Skip to content

Commit

Permalink
feat: Enhance configuration with advanced model and base URL support
Browse files Browse the repository at this point in the history
- Add support for custom base URL and model selection in setup
- Implement flexible configuration management with new config options
- Update README with new configuration details and commands
- Add `config` command to view current configuration
- Extend config interface to support base URL and model selection
  • Loading branch information
aindong committed Jan 30, 2025
1 parent 6a73a77 commit 039ad2b
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 26 deletions.
22 changes: 20 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
## AI-Powered Code Review CLI 🛠️
![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)
[![Publish Package](https://github.com/aindong/deepreview/actions/workflows/publish.yml/badge.svg)](https://github.com/aindong/deepreview/actions/workflows/publish.yml)
[![npm version](https://img.shields.io/npm/v/deepreview)](https://www.npmjs.com/package/deepreview)

A intelligent CLI tool that leverages AI for code analysis, pull request generation, and interactive code reviews.

## Features ✨
Expand All @@ -22,13 +24,29 @@ After installation, run:
deepreview setup
```

You'll be prompted to enter your OpenAI/DeepSeek API key. This will be stored securely in your home directory at `~/.deepreview/.env`.
To update your API key later, just run again:
```bash
deepreview setup
```

## Configuration ⚙️

Customize your CLI behavior with:

To update your API key later:
```bash
deepreview setup
```

Available settings:
- API Key (required)
- Base URL (default: OpenAI's endpoint)
- Default Model (gpt-4o, gpt-4, gpt-3.5-turbo, deepseek-chat, deepseek-reasoner)

View current config:
```bash
deepreview config
```

## Usage 🚀

### Analyze Code Quality
Expand Down
30 changes: 18 additions & 12 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ const CONFIG_DIR = path.join(homedir(), '.config', 'deepreview');
const CONFIG_PATH = path.join(CONFIG_DIR, 'config.json');

interface Config {
apiKey?: string;
apiKey: string;
baseUrl?: string;
model?: string;
}

export async function getApiKey(): Promise<string> {
Expand All @@ -28,24 +30,19 @@ export async function getApiKey(): Promise<string> {

async function readConfig(): Promise<Config> {
if (!existsSync(CONFIG_PATH)) {
return {};
return { apiKey: '' };
}

const content = await readFile(CONFIG_PATH, 'utf-8');
return JSON.parse(content);
}

export async function writeConfig(apiKey: string): Promise<void> {
// Store in system keychain
await keytar.setPassword(SERVICE_NAME, 'apiKey', apiKey);
export async function writeConfig(config: Config): Promise<void> {
await keytar.setPassword(SERVICE_NAME, 'apiKey', config.apiKey);

// Write empty config file for metadata
if (!existsSync(CONFIG_DIR)) {
mkdirSync(CONFIG_DIR, { recursive: true });
chmodSync(CONFIG_DIR, 0o700);
}
await writeFile(CONFIG_PATH, JSON.stringify({}, null, 2));
chmodSync(CONFIG_PATH, 0o600);
// Store other config in JSON
const { apiKey: _, ...restConfig } = config;
await writeFile(CONFIG_PATH, JSON.stringify(restConfig, null, 2));
}

export async function deleteConfig(): Promise<void> {
Expand All @@ -55,4 +52,13 @@ export async function deleteConfig(): Promise<void> {
} catch (error) {
console.error('Cleanup error:', error instanceof Error ? error.message : 'Unknown error');
}
}

export async function getConfig(): Promise<Config> {
const apiKey = await getApiKey();
const fileConfig = await readConfig();
return {
...fileConfig,
apiKey
};
}
17 changes: 12 additions & 5 deletions src/deepseek.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
import OpenAI from 'openai';
import { CodeReviewComments } from './interfaces';
import { parseAiResponse } from './parser';
import { getApiKey } from './config';
import { getApiKey, getConfig } from './config';

let client: OpenAI | null = null;
let defaultModel = 'gpt-4o';

async function getClient(): Promise<OpenAI> {
if (!client) {
const { apiKey, baseUrl, model } = await getConfig();
defaultModel = model || 'gpt-4o';

client = new OpenAI({
apiKey: await getApiKey(),
// baseURL: 'https://api.deepseek.com' // Uncomment if using DeepSeek
apiKey,
baseURL: baseUrl,
defaultHeaders: {
'User-Agent': 'DeepReview-CLI/1.0'
}
});
}
return client;
Expand All @@ -21,7 +28,7 @@ export async function queryLLM(prompt: string, code: string): Promise<string> {
try {
const openai = await getClient();
const completion = await openai.chat.completions.create({
model: "gpt-4o",
model: defaultModel,
messages: [
{
role: "system",
Expand Down Expand Up @@ -59,7 +66,7 @@ export async function streamAiResponse(
const openapi = await getClient();
const content = code ? `${prompt}\n\nCode:\n\`\`\`\n${code}\n\`\`\`` : prompt;
const stream = await openapi.chat.completions.create({
model: "gpt-4o",
model: defaultModel,
messages: [
{
role: "system",
Expand Down
16 changes: 16 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { readFile } from 'fs/promises';
import { generatePRDescription } from './pr-generator';
import { streamAiResponse } from './deepseek';
import { setupCommand } from './setup';
import { getConfig } from './config';

const program = new Command();

Expand Down Expand Up @@ -87,6 +88,21 @@ program
}
});

program
.command('config')
.description('View current configuration')
.action(async () => {
try {
const config = await getConfig();
console.log('Current configuration:');
console.log(`- API Key: ${config.apiKey ? '*****' + config.apiKey.slice(-4) : 'Not set'}`);
console.log(`- Base URL: ${config.baseUrl || 'Default'}`);
console.log(`- Model: ${config.model || 'gpt-4o'}`);
} catch (error) {
console.error('Error:', error instanceof Error ? error.message : 'Unknown error');
}
});

async function getDiffContent(diffInput: string): Promise<string> {
if (diffInput === '-') {
return new Promise((resolve, reject) => {
Expand Down
39 changes: 32 additions & 7 deletions src/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,40 @@ export async function setupCommand() {
}

// Get API key from user
const { apiKey } = await inquirer.prompt([{
type: 'password',
name: 'apiKey',
message: 'Enter your OpenAI/DeepSeek API key:',
validate: input => !!input.trim() || 'API key is required'
}]);
const { apiKey, baseUrl, model } = await inquirer.prompt([
{
type: 'password',
name: 'apiKey',
message: 'Enter your OpenAI/DeepSeek API key:',
validate: input => !!input.trim() || 'API key is required'
},
{
type: 'input',
name: 'baseUrl',
message: 'API base URL (leave blank for default):',
default: 'https://api.openai.com/v1'
},
{
type: 'list',
name: 'model',
message: 'Select default model:',
choices: [
{ name: 'GPT-4o', value: 'gpt-4o' },
{ name: 'GPT-4', value: 'gpt-4' },
{ name: 'GPT-3.5 Turbo', value: 'gpt-3.5-turbo' },
{ name: 'DeepSeek', value: 'deepseek-chat' },
{ name: 'DeepSeek Reasoner (R1)', value: 'deepseek-reasoner' },
],
default: 'gpt-4o'
}
]);

// Write to system keychain
await writeConfig(apiKey);
await writeConfig({
apiKey,
baseUrl: baseUrl || undefined,
model: model || 'gpt-4o'
});
console.log('\n✅ Configuration saved successfully!');

} catch (error) {
Expand Down

0 comments on commit 039ad2b

Please sign in to comment.