update model config (#53)

This commit is contained in:
Ismail Pelaseyed authored and GitHub committed 2025-07-28 22:12:06 +02:00
1 parent 2ab375111b
commit c4048a5926
7 files changed
+107 -54

No files matched your search

+20 -2
View File
@@ -118,8 +118,9 @@ This mode is particularly useful for:
### Model Selection
You can specify which AI model to use with the `--model` parameter:
You can specify which AI model to use with the `--model` parameter or `GROK_MODEL` environment variable:
**Method 1: Command Line Flag**
```bash
# Use Grok models
grok --model grok-4-latest
@@ -131,6 +132,23 @@ grok --model gemini-2.5-pro --base-url https://api-endpoint.com/v1
grok --model claude-sonnet-4-20250514 --base-url https://api-endpoint.com/v1
```
**Method 2: Environment Variable**
```bash
export GROK_MODEL=grok-4-latest
grok
```
**Method 3: User Settings File**
Add to `~/.grok/user-settings.json`:
```json
{
"apiKey": "your_api_key_here",
"model": "grok-4-latest"
}
```
Priority order: `--model` flag > `GROK_MODEL` environment variable > user settings > default (grok-4-latest)
### Command Line Options
```bash
@@ -141,7 +159,7 @@ Options:
-d, --directory <dir> set working directory
-k, --api-key <key> Grok API key (or set GROK_API_KEY env var)
-u, --base-url <url> Grok API base URL (or set GROK_BASE_URL env var)
-m, --model <model> AI model to use (e.g., grok-4-latest, grok-3-latest)
-m, --model <model> AI model to use (e.g., grok-4-latest, grok-3-latest) (or set GROK_MODEL env var)
-p, --prompt <prompt> process a single prompt and exit (headless mode)
-h, --help display help for command
```
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@vibe-kit/grok-cli",
"version": "0.0.14",
"version": "0.0.15",
"description": "An open-source AI agent that brings the power of Grok directly into your terminal.",
"main": "dist/index.js",
"bin": {
+1 -2
View File
@@ -54,8 +54,7 @@ export class GrokAgent extends EventEmitter {
constructor(apiKey: string, baseURL?: string, model?: string) {
super();
// Use saved model if no model is explicitly provided
const savedModel = getSetting("selectedModel");
const savedModel = getSetting("model");
const modelToUse = model || savedModel || "grok-4-latest";
this.grokClient = new GrokClient(apiKey, modelToUse, baseURL);
this.textEditor = new TextEditorTool();
+2 -2
View File
@@ -150,7 +150,7 @@ Examples:
if (modelNames.includes(modelArg)) {
agent.setModel(modelArg);
updateSetting("selectedModel", modelArg);
updateSetting("model", modelArg);
const confirmEntry: ChatEntry = {
type: "assistant",
content: `✓ Switched to model: ${modelArg}`,
@@ -663,7 +663,7 @@ Respond with ONLY the commit message, no additional text.`;
if (key.tab || key.return) {
const selectedModel = availableModels[selectedModelIndex];
agent.setModel(selectedModel.model);
updateSetting("selectedModel", selectedModel.model);
updateSetting("model", selectedModel.model);
const confirmEntry: ChatEntry = {
type: "assistant",
content: `✓ Switched to model: ${selectedModel.model}`,
+62 -29
View File
@@ -6,6 +6,7 @@ import { program } from "commander";
import * as dotenv from "dotenv";
import { GrokAgent } from "./agent/grok-agent";
import ChatInterface from "./ui/components/chat-interface";
import { getSetting, loadSettings } from "./utils/settings";
import * as fs from "fs";
import * as path from "path";
import * as os from "os";
@@ -16,32 +17,32 @@ import { createMCPCommand } from "./commands/mcp";
dotenv.config();
// Add proper signal handling for terminal cleanup
process.on('SIGINT', () => {
process.on("SIGINT", () => {
// Restore terminal to normal mode before exit
if (process.stdin.isTTY) {
process.stdin.setRawMode(false);
}
console.log('\nGracefully shutting down...');
console.log("\nGracefully shutting down...");
process.exit(0);
});
process.on('SIGTERM', () => {
process.on("SIGTERM", () => {
// Restore terminal to normal mode before exit
if (process.stdin.isTTY) {
process.stdin.setRawMode(false);
}
console.log('\nGracefully shutting down...');
console.log("\nGracefully shutting down...");
process.exit(0);
});
// Handle uncaught exceptions to prevent hanging
process.on('uncaughtException', (error) => {
console.error('Uncaught exception:', error);
process.on("uncaughtException", (error) => {
console.error("Uncaught exception:", error);
process.exit(1);
});
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled rejection at:', promise, 'reason:', reason);
process.on("unhandledRejection", (reason, promise) => {
console.error("Unhandled rejection at:", promise, "reason:", reason);
process.exit(1);
});
@@ -62,7 +63,7 @@ function ensureUserSettingsDirectory(): void {
const defaultSettings = {
apiKey: "",
baseURL: "",
defaultModel: "grok-4-latest"
defaultModel: "grok-4-latest",
};
fs.writeFileSync(settingsFile, JSON.stringify(defaultSettings, null, 2));
}
@@ -119,6 +120,24 @@ function loadBaseURL(): string | undefined {
return baseURL;
}
// Load model from user settings if not in environment
function loadModel(): string | undefined {
// First check environment variables
let model = process.env.GROK_MODEL;
if (!model) {
// Try to load from local settings file
try {
const settings = loadSettings();
model = settings.model;
} catch (error) {
// Ignore errors, model will remain undefined
}
}
return model;
}
// Handle commit-and-push command in headless mode
async function handleCommitAndPushHeadless(
apiKey: string,
@@ -136,8 +155,10 @@ async function handleCommitAndPushHeadless(
console.log("> /commit-and-push\n");
// First check if there are any changes at all
const initialStatusResult = await agent.executeBashCommand("git status --porcelain");
const initialStatusResult = await agent.executeBashCommand(
"git status --porcelain"
);
if (!initialStatusResult.success || !initialStatusResult.output?.trim()) {
console.log("❌ No changes to commit. Working directory is clean.");
process.exit(1);
@@ -147,9 +168,11 @@ async function handleCommitAndPushHeadless(
// Add all changes
const addResult = await agent.executeBashCommand("git add .");
if (!addResult.success) {
console.log(`❌ git add: ${addResult.error || 'Failed to stage changes'}`);
console.log(
`❌ git add: ${addResult.error || "Failed to stage changes"}`
);
process.exit(1);
}
@@ -171,10 +194,10 @@ Follow conventional commit format (feat:, fix:, docs:, etc.) and keep it under 7
Respond with ONLY the commit message, no additional text.`;
console.log("🤖 Generating commit message...");
const commitMessageEntries = await agent.processUserMessage(commitPrompt);
let commitMessage = "";
// Extract the commit message from the AI response
for (const entry of commitMessageEntries) {
if (entry.type === "assistant" && entry.content.trim()) {
@@ -189,7 +212,7 @@ Respond with ONLY the commit message, no additional text.`;
}
// Clean the commit message
const cleanCommitMessage = commitMessage.replace(/^["']|["']$/g, '');
const cleanCommitMessage = commitMessage.replace(/^["']|["']$/g, "");
console.log(`✅ Generated commit message: "${cleanCommitMessage}"`);
// Execute the commit
@@ -197,28 +220,38 @@ Respond with ONLY the commit message, no additional text.`;
const commitResult = await agent.executeBashCommand(commitCommand);
if (commitResult.success) {
console.log(`✅ git commit: ${commitResult.output?.split('\n')[0] || 'Commit successful'}`);
console.log(
`✅ git commit: ${
commitResult.output?.split("\n")[0] || "Commit successful"
}`
);
// If commit was successful, push to remote
// First try regular push, if it fails try with upstream setup
let pushResult = await agent.executeBashCommand("git push");
if (!pushResult.success && pushResult.error?.includes("no upstream branch")) {
if (
!pushResult.success &&
pushResult.error?.includes("no upstream branch")
) {
console.log("🔄 Setting upstream and pushing...");
pushResult = await agent.executeBashCommand("git push -u origin HEAD");
}
if (pushResult.success) {
console.log(`✅ git push: ${pushResult.output?.split('\n')[0] || 'Push successful'}`);
console.log(
`✅ git push: ${
pushResult.output?.split("\n")[0] || "Push successful"
}`
);
} else {
console.log(`❌ git push: ${pushResult.error || 'Push failed'}`);
console.log(`❌ git push: ${pushResult.error || "Push failed"}`);
process.exit(1);
}
} else {
console.log(`❌ git commit: ${commitResult.error || 'Commit failed'}`);
console.log(`❌ git commit: ${commitResult.error || "Commit failed"}`);
process.exit(1);
}
} catch (error: any) {
console.error("❌ Error during commit and push:", error.message);
process.exit(1);
@@ -306,7 +339,7 @@ program
)
.option(
"-m, --model <model>",
"AI model to use (e.g., gemini-2.5-pro, grok-4-latest)"
"AI model to use (e.g., gemini-2.5-pro, grok-4-latest) (or set GROK_MODEL env var)"
)
.option(
"-p, --prompt <prompt>",
@@ -329,7 +362,7 @@ program
// Get API key from options, environment, or user settings
const apiKey = options.apiKey || loadApiKey();
const baseURL = options.baseUrl || loadBaseURL();
const model = options.model;
const model = options.model || loadModel();
if (!apiKey) {
console.error(
@@ -370,7 +403,7 @@ gitCommand
)
.option(
"-m, --model <model>",
"AI model to use (e.g., gemini-2.5-pro, grok-4-latest)"
"AI model to use (e.g., gemini-2.5-pro, grok-4-latest) (or set GROK_MODEL env var)"
)
.action(async (options) => {
if (options.directory) {
@@ -389,7 +422,7 @@ gitCommand
// Get API key from options, environment, or user settings
const apiKey = options.apiKey || loadApiKey();
const baseURL = options.baseUrl || loadBaseURL();
const model = options.model;
const model = options.model || loadModel();
if (!apiKey) {
console.error(
+4 -4
View File
@@ -7,7 +7,7 @@ const CONFIG_DIR = path.join(process.cwd(), ".grok");
const SETTINGS_FILE = path.join(CONFIG_DIR, "settings.json");
export interface Settings {
selectedModel?: string;
model?: string;
mcpServers?: Record<string, MCPServerConfig>;
}
@@ -52,12 +52,12 @@ export function loadMCPConfig(): MCPConfig {
export function saveMCPConfig(config: MCPConfig): void {
const settings = loadSettings();
settings.mcpServers = {};
// Convert servers array to object keyed by name
for (const server of config.servers) {
settings.mcpServers[server.name] = server;
}
saveSettings(settings);
}
@@ -66,7 +66,7 @@ export function addMCPServer(config: MCPServerConfig): void {
if (!settings.mcpServers) {
settings.mcpServers = {};
}
settings.mcpServers[config.name] = config;
saveSettings(settings);
}
+17 -14
View File
@@ -1,13 +1,13 @@
import fs from 'fs';
import path from 'path';
import fs from "fs";
import path from "path";
interface Settings {
selectedModel?: string;
model?: string;
[key: string]: any;
}
const SETTINGS_DIR = '.grok';
const SETTINGS_FILE = 'settings.json';
const SETTINGS_DIR = ".grok";
const SETTINGS_FILE = "settings.json";
function getSettingsPath(): string {
return path.join(process.cwd(), SETTINGS_DIR, SETTINGS_FILE);
@@ -21,23 +21,23 @@ function ensureSettingsDirectory(): void {
}
const DEFAULT_SETTINGS: Settings = {
selectedModel: 'grok-4-latest'
model: "grok-4-latest",
};
export function loadSettings(): Settings {
try {
ensureSettingsDirectory();
const settingsPath = getSettingsPath();
if (!fs.existsSync(settingsPath)) {
saveSettings(DEFAULT_SETTINGS);
return DEFAULT_SETTINGS;
}
const settingsContent = fs.readFileSync(settingsPath, 'utf-8');
const settingsContent = fs.readFileSync(settingsPath, "utf-8");
return JSON.parse(settingsContent);
} catch (error) {
console.warn('Failed to load settings:', error);
console.warn("Failed to load settings:", error);
return {};
}
}
@@ -46,14 +46,17 @@ export function saveSettings(settings: Settings): void {
try {
ensureSettingsDirectory();
const settingsPath = getSettingsPath();
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
} catch (error) {
console.error('Failed to save settings:', error);
console.error("Failed to save settings:", error);
}
}
export function updateSetting<K extends keyof Settings>(key: K, value: Settings[K]): void {
export function updateSetting<K extends keyof Settings>(
key: K,
value: Settings[K]
): void {
const currentSettings = loadSettings();
currentSettings[key] = value;
saveSettings(currentSettings);
@@ -62,4 +65,4 @@ export function updateSetting<K extends keyof Settings>(key: K, value: Settings[
export function getSetting<K extends keyof Settings>(key: K): Settings[K] {
const settings = loadSettings();
return settings[key];
}
}