update model config (#53)
This commit is contained in:
1 parent
2ab375111b
commit
c4048a5926
7 files changed
+107
-54
No files matched your search
@@ -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
@@ -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": {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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];
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user