venice-dev-tools
Version:
unOfficial SDK for the Venice AI API
261 lines (225 loc) • 10.1 kB
text/typescript
// CLI entry point
import { Command } from 'commander';
import colors from 'ansi-colors';
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
import * as packageJson from '../../package.json';
import { VeniceNode } from '../venice-node';
import { registerChatCommands } from './chat';
import { registerModelsCommands } from './commands/models';
import { registerKeysCommands } from './commands/keys';
import { registerImagesCommands } from './commands/images';
import { registerVisionCommands } from './commands/vision';
import { registerCharactersCommands } from './commands/characters';
import { registerWeb3KeysCommands } from './commands/web3-keys';
// Create the CLI instance
const program = new Command();
// Create the Venice SDK instance with quiet mode by default
// Only enable logging if --verbose flag is passed
const isVerboseMode = process.argv.includes('--verbose');
// Create the client with quiet mode by default
const venice = new VeniceNode({
logLevel: isVerboseMode ? undefined : 4 // LogLevel.NONE = 4 (quiet by default)
});
// Setup CLI basic info
program
.name('venice')
.description('Venice AI SDK Command Line Interface')
.version(packageJson.version);
// Load API key from config file or environment variable
function loadApiKey(): string | undefined {
// First try environment variable
if (process.env.VENICE_API_KEY) {
return process.env.VENICE_API_KEY;
}
// Then try config file in home directory
const configPath = path.join(os.homedir(), '.venice', 'config.json');
try {
if (fs.existsSync(configPath)) {
const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
return config.apiKey;
}
} catch (error) {
// Silently ignore errors reading config
}
return undefined;
}
// Configure API key
const apiKey = loadApiKey();
if (apiKey) {
venice.setApiKey(apiKey);
}
// Register commands
registerChatCommands(program, venice);
registerModelsCommands(program, venice);
registerKeysCommands(program, venice);
registerImagesCommands(program, venice);
registerVisionCommands(program, venice);
registerCharactersCommands(program, venice);
registerWeb3KeysCommands(program, venice);
// Add set-key command
program
.command('set-key')
.description('Set your Venice AI API key')
.argument('<apiKey>', 'Your Venice API key')
.action((apiKey, options) => {
try {
// Set the API key in memory
venice.setApiKey(apiKey);
// Save the API key to config file
const configDir = path.join(os.homedir(), '.venice');
const configPath = path.join(configDir, 'config.json');
// Create directory if it doesn't exist
if (!fs.existsSync(configDir)) {
fs.mkdirSync(configDir, { recursive: true });
}
// Read existing config if it exists
let config = {};
if (fs.existsSync(configPath)) {
try {
config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
} catch (error) {
// Ignore errors reading config
}
}
// Update config with new API key
config = { ...config, apiKey };
// Write config file
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
console.log(colors.green('API key saved successfully!'));
} catch (error) {
console.error(colors.red(`Error: ${(error as Error).message}`));
process.exit(1);
}
});
// Add global options
program.option('-k, --api-key <key>', 'Venice API key', process.env.VENICE_API_KEY);
program.option('--json', 'Output response as JSON (useful for programmatic use)');
program.option('--raw', 'Output raw text without formatting (useful for piping to other commands)');
program.option('--stream', 'Stream the response when supported');
program.option('--verbose', 'Show detailed logs and output (default: quiet)');
// Add help command with extended help
program
.command('help')
.description('Display help information')
.action(() => {
console.log(colors.bold('\nChat Commands:'));
console.log(' Create chat completions with various models');
console.log(' Support for streaming responses and interactive mode');
console.log(' Character integration via --character option');
console.log(' Web search capabilities via --web-search option');
console.log('\nExamples:');
console.log(' venice chat completion --prompt "Hello" --model llama-3.3-70b');
console.log(' venice chat interactive --stream --character "assistant-name"');
console.log(colors.bold('\nMultimodal Features:'));
console.log(' Attach files to your messages using the --attach option');
console.log(' Supported file types: Images (PNG, JPEG, etc.), PDFs, and text files');
console.log('\nExamples:');
console.log(' venice chat completion --prompt "Describe this image" --attach image.jpg');
console.log(' venice chat completion --prompt "Compare these images" --attach "image1.jpg,image2.png"');
console.log('\nIn interactive mode:');
console.log(' venice chat interactive');
console.log(' venice chat interactive --stream # Enable streaming responses');
console.log(' > /attach document.pdf');
console.log(colors.bold('\nVision Commands:'));
console.log(' Use vision models to analyze images without message history issues');
console.log(' Supports both positional arguments and option flags for image paths');
console.log('\nExamples:');
console.log(' venice vision analyze sunset.png');
console.log(' venice vision analyze --prompt "Describe this image" --image sunset.png');
console.log(' venice vision interactive sunset.png');
console.log(' venice vision i sunset.png # Using alias');
console.log(colors.bold('\nImage Generation:'));
console.log(' Generate images with AI models');
console.log(' Upscale existing images');
console.log(' List available image styles');
console.log('\nExamples:');
console.log(' venice images generate "A sunset over mountains"');
console.log(' venice images generate --prompt "A sunset over mountains" --model fluently-xl');
console.log(' venice images upscale image.jpg --scale 4');
console.log(' venice images styles');
console.log(colors.bold('\nModels:'));
console.log(' List available models and their capabilities');
console.log(' Get model traits and compatibility information');
console.log('\nExamples:');
console.log(' venice models list');
console.log(' venice models list --type text');
console.log(' venice models traits # Shows all model traits by default');
console.log(' venice models traits --type text # Filter to show only text model traits');
console.log(' venice models traits --json # Output as JSON');
console.log(' venice models compatibility');
console.log(colors.bold('\nAPI Keys:'));
console.log(' Manage Venice AI API keys');
console.log(' List, create, and delete API keys');
console.log(' Get rate limits and usage information');
console.log('\nExamples:');
console.log(' venice keys list');
console.log(' venice keys create --description "My API Key" --type INFERENCE');
console.log(' venice keys rate-limits');
console.log(' venice keys delete <key-id>');
console.log(colors.bold('\nCharacters:'));
console.log(' List and use characters in chat completions');
console.log(' Characters provide specialized personalities and capabilities');
console.log('\nExamples:');
console.log(' venice characters list');
console.log(' venice characters list --json');
console.log(' venice chat completion --prompt "Hello" --character "assistant-name"');
console.log(colors.bold('\nCrypto/Web3 Features:'));
console.log(' API key management with web3 authentication');
console.log(' Generate tokens for wallet signing');
console.log(' Create API keys with wallet authentication');
console.log('\nExamples:');
console.log(' venice web3-keys generate-token');
console.log(' venice web3-keys create --address <wallet> --signature <sig> --token <token>');
program.help();
});
// Handle global options
program.hook('preAction', (thisCommand, actionCommand) => {
// Get options from both the parent command and the action command
const parentOptions = thisCommand.opts();
const options = actionCommand.opts();
// Check if API key is provided via command line
if (parentOptions.apiKey) {
venice.setApiKey(parentOptions.apiKey);
} else if (options.apiKey) {
venice.setApiKey(options.apiKey);
}
// Pass global output format options to the command
if (parentOptions.json && !options.json) {
actionCommand.setOptionValue('json', true);
}
if (parentOptions.raw && !options.raw) {
actionCommand.setOptionValue('raw', true);
}
if (parentOptions.stream && !options.stream) {
actionCommand.setOptionValue('stream', true);
}
if (parentOptions.verbose && !options.verbose) {
actionCommand.setOptionValue('verbose', true);
}
// Set log level based on verbose flag
if (parentOptions.verbose || options.verbose) {
venice.setLogLevel(1); // LogLevel.INFO = 1
}
// Verify API key is set
if (actionCommand.name() !== 'set-key' && actionCommand.name() !== 'help') {
try {
// This will throw an error if no API key is set
venice.getApiKey();
} catch (error) {
console.error(colors.red('Error: API key not found or invalid.'));
console.error(colors.yellow('Please provide an API key using one of these methods:'));
console.error(colors.yellow('1. Use the --api-key or -k option: venice -k YOUR_API_KEY ...'));
console.error(colors.yellow('2. Set the VENICE_API_KEY environment variable'));
console.error(colors.yellow('3. Save your API key using: venice set-key YOUR_API_KEY'));
process.exit(1);
}
}
});
// Parse arguments
program.parse(process.argv);
// Show help if no arguments provided
if (process.argv.length === 2) {
program.help();
}