cline-sdk
Version:
Comprehensive SDK for Cline - AI-powered development assistant with database integration, execution modes, and custom functions
467 lines • 19.3 kB
JavaScript
;
/**
* Cline SDK Configuration System
* Handles API keys, settings, and tool configurations
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.ClineConfigManager = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const os = __importStar(require("os"));
class ClineConfigManager {
constructor(configDir) {
const defaultConfigDir = configDir || path.join(os.homedir(), ".cline-sdk");
this.configPath = path.join(defaultConfigDir, "config.json");
// Ensure config directory exists
if (!fs.existsSync(defaultConfigDir)) {
fs.mkdirSync(defaultConfigDir, { recursive: true });
}
// Load or create default config
this.config = this.loadConfig();
}
loadConfig() {
try {
if (fs.existsSync(this.configPath)) {
const configData = fs.readFileSync(this.configPath, "utf8");
const loadedConfig = JSON.parse(configData);
return { ...this.getDefaultConfig(), ...loadedConfig };
}
}
catch (error) {
console.warn("Failed to load config, using defaults:", error);
}
return this.getDefaultConfig();
}
getDefaultConfig() {
return {
apiProvider: "anthropic",
apiKey: process.env.ANTHROPIC_API_KEY || process.env.CLINE_API_KEY,
model: "claude-3-sonnet-20240229",
enabledTools: ["Write", "Read", "Bash"],
enableCustomFunctions: true,
enableDatabase: false,
maxRequestsPerTask: 50,
timeout: 30000,
executionMode: "act",
storageType: "local",
workingDirectory: process.cwd(),
alwaysAllowReadOnly: false,
supabase: process.env.SUPABASE_URL && process.env.SUPABASE_ANON_KEY
? {
url: process.env.SUPABASE_URL,
anonKey: process.env.SUPABASE_ANON_KEY,
serviceKey: process.env.SUPABASE_SERVICE_KEY, // Optional admin key
bucketName: process.env.SUPABASE_BUCKET || "cline-files",
projectPath: process.env.SUPABASE_PROJECT_PATH,
}
: undefined,
database: process.env.DATABASE_URL ||
(process.env.DB_HOST && process.env.DB_NAME && process.env.DB_USER && process.env.DB_PASSWORD)
? {
host: process.env.DB_HOST || "localhost",
port: parseInt(process.env.DB_PORT || "5432", 10),
database: process.env.DB_NAME || process.env.DB_DATABASE || "postgres",
username: process.env.DB_USER || process.env.DB_USERNAME || "postgres",
password: process.env.DB_PASSWORD || "",
ssl: process.env.DB_SSL === "true" || process.env.DATABASE_SSL === "true",
maxConnections: parseInt(process.env.DB_MAX_CONNECTIONS || "20", 10),
idleTimeoutMillis: parseInt(process.env.DB_IDLE_TIMEOUT || "30000", 10),
connectionTimeoutMillis: parseInt(process.env.DB_CONNECTION_TIMEOUT || "10000", 10),
permissions: {
allowRead: process.env.DB_ALLOW_READ !== "false",
allowWrite: process.env.DB_ALLOW_WRITE === "true",
allowDelete: process.env.DB_ALLOW_DELETE === "true",
allowSchemaChanges: process.env.DB_ALLOW_SCHEMA_CHANGES === "true",
allowRLSManagement: process.env.DB_ALLOW_RLS === "true",
restrictedTables: process.env.DB_RESTRICTED_TABLES
? process.env.DB_RESTRICTED_TABLES.split(",")
: [],
allowedTables: process.env.DB_ALLOWED_TABLES ? process.env.DB_ALLOWED_TABLES.split(",") : [],
},
}
: undefined,
temperature: 0.7,
maxTokens: 4000,
useCache: true,
anthropicVersion: "2023-06-01",
streaming: false,
reasoning: false,
imageSupport: false,
functionCalling: true,
requestTimeout: 30000,
rateLimiting: {
enabled: false,
requestsPerMinute: 60,
requestsPerHour: 1000
},
costLimits: {
maxCostPerTask: 1.0,
maxCostPerDay: 10.0,
alertThreshold: 5.0
},
retry: {
enabled: true,
maxAttempts: 3,
waitTimeMs: 6000, // 6 seconds as requested
exponentialBackoff: false,
retryOnErrors: ["llm_error", "api_error", "timeout_error"]
},
};
}
getConfig() {
return { ...this.config };
}
updateConfig(updates) {
this.config = { ...this.config, ...updates };
this.saveConfig();
}
setApiKey(apiKey) {
this.config.apiKey = apiKey;
this.saveConfig();
}
setWorkingDirectory(directory) {
if (fs.existsSync(directory)) {
this.config.workingDirectory = path.resolve(directory);
this.saveConfig();
}
else {
throw new Error(`Directory does not exist: ${directory}`);
}
}
enableTool(toolName) {
if (!this.config.enabledTools.includes(toolName)) {
this.config.enabledTools.push(toolName);
this.saveConfig();
}
}
disableTool(toolName) {
this.config.enabledTools = this.config.enabledTools.filter((tool) => tool !== toolName);
this.saveConfig();
}
saveConfig() {
try {
fs.writeFileSync(this.configPath, JSON.stringify(this.config, null, 2), "utf8");
}
catch (error) {
console.error("Failed to save config:", error);
}
}
getConfigPath() {
return this.configPath;
}
// Model validation helper
validateModel() {
const errors = [];
if (!this.config.model) {
errors.push("Model is required");
return { valid: false, errors };
}
// Basic model validation based on provider
const modelValidation = this.getModelValidation();
if (!modelValidation.valid) {
errors.push(...modelValidation.errors);
}
return {
valid: errors.length === 0,
errors,
};
}
getModelValidation() {
const errors = [];
const model = this.config.model;
const provider = this.config.apiProvider;
// Skip validation for custom models (allow any string)
if (typeof model === "string" && model.includes("custom")) {
return { valid: true, errors: [] };
}
// Provider-specific model validation
switch (provider) {
case "anthropic":
const anthropicModels = [
"claude-3-sonnet-20240229",
"claude-3-haiku-20240307",
"claude-3-opus-20240229",
"claude-3-5-sonnet-20241022",
"claude-3-5-haiku-20241022"
];
if (model && !anthropicModels.includes(model)) {
errors.push(`Invalid Anthropic model: ${model}. Supported models: ${anthropicModels.join(", ")}`);
}
break;
case "openai":
const openaiModels = [
"gpt-4", "gpt-4-turbo", "gpt-4o", "gpt-4o-mini", "gpt-3.5-turbo"
];
if (model && !openaiModels.includes(model)) {
errors.push(`Invalid OpenAI model: ${model}. Supported models: ${openaiModels.join(", ")}`);
}
break;
case "ollama":
const ollamaModels = [
"llama3", "llama3.1", "llama3.2", "codellama", "mistral", "gemma", "qwen", "deepseek-coder"
];
if (model && !ollamaModels.includes(model)) {
errors.push(`Invalid Ollama model: ${model}. Supported models: ${ollamaModels.join(", ")}`);
}
break;
case "bedrock":
const bedrockModels = [
"anthropic.claude-3-sonnet-20240229-v1:0",
"anthropic.claude-3-haiku-20240307-v1:0",
"anthropic.claude-3-opus-20240229-v1:0",
"anthropic.claude-3-5-sonnet-20241022-v2:0"
];
if (model && !bedrockModels.includes(model)) {
errors.push(`Invalid Bedrock model: ${model}. Supported models: ${bedrockModels.join(", ")}`);
}
break;
case "vertex":
const vertexModels = [
"gemini-1.5-pro", "gemini-1.5-flash", "gemini-1.0-pro"
];
if (model && !vertexModels.includes(model)) {
errors.push(`Invalid Vertex model: ${model}. Supported models: ${vertexModels.join(", ")}`);
}
break;
}
return {
valid: errors.length === 0,
errors,
};
}
// Enhanced validation methods
validateConfig() {
const errors = [];
if (!this.config.apiKey) {
errors.push("API key is required");
}
if (!fs.existsSync(this.config.workingDirectory)) {
errors.push(`Working directory does not exist: ${this.config.workingDirectory}`);
}
if (this.config.maxRequestsPerTask < 1) {
errors.push("maxRequestsPerTask must be at least 1");
}
if (this.config.timeout < 1000) {
errors.push("timeout must be at least 1000ms");
}
// Validate execution mode
if (this.config.executionMode && !["ask", "plan", "act"].includes(this.config.executionMode)) {
errors.push(`Invalid execution mode: ${this.config.executionMode}. Must be 'ask', 'plan', or 'act'`);
}
// Validate temperature
if (this.config.temperature !== undefined && (this.config.temperature < 0 || this.config.temperature > 2)) {
errors.push("temperature must be between 0 and 2");
}
// Validate maxTokens
if (this.config.maxTokens !== undefined && this.config.maxTokens < 1) {
errors.push("maxTokens must be at least 1");
}
// Validate model
const modelValidation = this.validateModel();
if (!modelValidation.valid) {
errors.push(...modelValidation.errors);
}
return {
valid: errors.length === 0,
errors,
};
}
// Environment-based configuration
static fromEnvironment() {
const config = new ClineConfigManager();
// Override with environment variables
const envConfig = {};
if (process.env.ANTHROPIC_API_KEY) {
envConfig.apiKey = process.env.ANTHROPIC_API_KEY;
envConfig.apiProvider = "anthropic";
}
if (process.env.OPENAI_API_KEY) {
envConfig.apiKey = process.env.OPENAI_API_KEY;
envConfig.apiProvider = "openai";
}
if (process.env.OPENROUTER_API_KEY) {
envConfig.apiKey = process.env.OPENROUTER_API_KEY;
envConfig.apiProvider = "openrouter";
}
// Provider-specific configurations
if (process.env.AWS_REGION || process.env.AWS_ACCESS_KEY_ID) {
envConfig.providerConfig = {
...envConfig.providerConfig,
bedrock: {
region: process.env.AWS_REGION || "us-east-1",
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
modelId: process.env.BEDROCK_MODEL_ID
}
};
}
if (process.env.GOOGLE_PROJECT_ID) {
envConfig.providerConfig = {
...envConfig.providerConfig,
vertex: {
projectId: process.env.GOOGLE_PROJECT_ID,
location: process.env.GOOGLE_LOCATION || "us-central1"
}
};
}
if (process.env.OLLAMA_HOST) {
envConfig.providerConfig = {
...envConfig.providerConfig,
ollama: {
host: process.env.OLLAMA_HOST,
port: process.env.OLLAMA_PORT ? parseInt(process.env.OLLAMA_PORT, 10) : 11434
}
};
}
if (process.env.CLINE_WORKING_DIR) {
envConfig.workingDirectory = process.env.CLINE_WORKING_DIR;
}
if (process.env.CLINE_MODEL) {
envConfig.model = process.env.CLINE_MODEL;
}
if (process.env.CLINE_MAX_REQUESTS) {
envConfig.maxRequestsPerTask = parseInt(process.env.CLINE_MAX_REQUESTS, 10);
}
if (process.env.CLINE_EXECUTION_MODE) {
const mode = process.env.CLINE_EXECUTION_MODE.toLowerCase();
if (mode === "ask" || mode === "plan" || mode === "act") {
envConfig.executionMode = mode;
}
}
// Retry configuration from environment variables
if (process.env.RETRY_ENABLED !== undefined) {
envConfig.retry = {
...(envConfig.retry || { enabled: false }),
enabled: process.env.RETRY_ENABLED === "true"
};
}
if (process.env.RETRY_MAX_ATTEMPTS) {
envConfig.retry = {
...(envConfig.retry || { enabled: false }),
maxAttempts: parseInt(process.env.RETRY_MAX_ATTEMPTS, 10)
};
}
if (process.env.RETRY_WAIT_TIME_MS) {
envConfig.retry = {
...(envConfig.retry || { enabled: false }),
waitTimeMs: parseInt(process.env.RETRY_WAIT_TIME_MS, 10)
};
}
if (process.env.RETRY_EXPONENTIAL_BACKOFF !== undefined) {
envConfig.retry = {
...(envConfig.retry || { enabled: false }),
exponentialBackoff: process.env.RETRY_EXPONENTIAL_BACKOFF === "true"
};
}
if (process.env.RETRY_ON_ERRORS) {
envConfig.retry = {
...(envConfig.retry || { enabled: false }),
retryOnErrors: process.env.RETRY_ON_ERRORS.split(",").map(e => e.trim())
};
}
// Advanced API settings from environment variables
if (process.env.CLINE_TEMPERATURE) {
envConfig.temperature = parseFloat(process.env.CLINE_TEMPERATURE);
}
if (process.env.CLINE_MAX_TOKENS) {
envConfig.maxTokens = parseInt(process.env.CLINE_MAX_TOKENS, 10);
}
if (process.env.CLINE_USE_CACHE !== undefined) {
envConfig.useCache = process.env.CLINE_USE_CACHE === "true";
}
if (process.env.ANTHROPIC_VERSION) {
envConfig.anthropicVersion = process.env.ANTHROPIC_VERSION;
}
// Advanced API features from environment variables
if (process.env.CLINE_STREAMING !== undefined) {
envConfig.streaming = process.env.CLINE_STREAMING === "true";
}
if (process.env.CLINE_REASONING !== undefined) {
envConfig.reasoning = process.env.CLINE_REASONING === "true";
}
if (process.env.CLINE_IMAGE_SUPPORT !== undefined) {
envConfig.imageSupport = process.env.CLINE_IMAGE_SUPPORT === "true";
}
if (process.env.CLINE_FUNCTION_CALLING !== undefined) {
envConfig.functionCalling = process.env.CLINE_FUNCTION_CALLING === "true";
}
if (process.env.CLINE_REQUEST_TIMEOUT) {
envConfig.requestTimeout = parseInt(process.env.CLINE_REQUEST_TIMEOUT, 10);
}
// Rate limiting configuration
if (process.env.CLINE_RATE_LIMITING_ENABLED !== undefined) {
envConfig.rateLimiting = {
...(envConfig.rateLimiting || { enabled: false }),
enabled: process.env.CLINE_RATE_LIMITING_ENABLED === "true"
};
}
if (process.env.CLINE_REQUESTS_PER_MINUTE) {
envConfig.rateLimiting = {
...(envConfig.rateLimiting || { enabled: false }),
requestsPerMinute: parseInt(process.env.CLINE_REQUESTS_PER_MINUTE, 10)
};
}
if (process.env.CLINE_REQUESTS_PER_HOUR) {
envConfig.rateLimiting = {
...(envConfig.rateLimiting || { enabled: false }),
requestsPerHour: parseInt(process.env.CLINE_REQUESTS_PER_HOUR, 10)
};
}
// Cost limits configuration
if (process.env.CLINE_MAX_COST_PER_TASK) {
envConfig.costLimits = {
...(envConfig.costLimits || {}),
maxCostPerTask: parseFloat(process.env.CLINE_MAX_COST_PER_TASK)
};
}
if (process.env.CLINE_MAX_COST_PER_DAY) {
envConfig.costLimits = {
...(envConfig.costLimits || {}),
maxCostPerDay: parseFloat(process.env.CLINE_MAX_COST_PER_DAY)
};
}
if (process.env.CLINE_COST_ALERT_THRESHOLD) {
envConfig.costLimits = {
...(envConfig.costLimits || {}),
alertThreshold: parseFloat(process.env.CLINE_COST_ALERT_THRESHOLD)
};
}
config.updateConfig(envConfig);
return config;
}
}
exports.ClineConfigManager = ClineConfigManager;
//# sourceMappingURL=cline-config.js.map