unbound-claude-code
Version:
Claude Code with Unbound integration - Drop-in replacement for Claude Code with multi-provider routing and cost optimization
167 lines • 5.88 kB
JavaScript
;
/**
* Unbound API Authentication and Verification
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.UnboundAuth = void 0;
const storage_1 = require("./storage");
const global_1 = require("./global");
class UnboundAuth {
constructor(baseUrl = `${global_1.UNBOUND_BASE_URL}/v1`) {
this.baseUrl = baseUrl;
this.storage = new storage_1.UnboundStorage();
}
/**
* Verify API key by calling the /models endpoint
*/
async verifyApiKey(apiKey) {
if (apiKey.length === 0) {
console.log("API key is empty");
return false;
}
try {
const response = await fetch(`${this.baseUrl}/models`, {
method: "GET",
headers: {
"Authorization": `Bearer ${apiKey}`,
"Content-Type": "application/json",
}
});
const data = await response.json();
if (response.ok) {
// Handle different response formats
if (data && Array.isArray(data.data) && data.data.length > 0) {
return true;
}
else if (data && Array.isArray(data) && data.length > 0) {
return true;
}
else if (data && typeof data === 'object') {
return true;
}
return false;
}
console.log("API key verification failed...", data.error.message);
return false;
}
catch (error) {
console.log("API key verification failed...", error);
return false;
}
}
/**
* Get available models from Unbound API
*/
async getModels(apiKey) {
try {
const response = await fetch(`${this.baseUrl}/models`, {
method: "GET",
headers: {
"Authorization": `Bearer ${apiKey}`,
"Content-Type": "application/json",
}
});
if (response.ok) {
const data = await response.json();
if (data && Array.isArray(data.data)) {
return data;
}
else if (data && Array.isArray(data)) {
return { object: "list", data: data };
}
else {
console.warn("Unexpected models response format:", data);
return null;
}
}
else {
console.warn(`Failed to fetch models: ${response.status} ${response.statusText}`);
}
return null;
}
catch (error) {
console.error("Failed to get models:", error);
return null;
}
}
/**
* Prompt user for API key interactively
*/
async promptForApiKey() {
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
return new Promise((resolve, reject) => {
const askForKey = async () => {
rl.question('Enter your Unbound API key: ', async (apiKey) => {
const trimmedKey = apiKey ? apiKey.trim() : '';
if (!trimmedKey || trimmedKey.length === 0) {
console.log('API key cannot be empty. Please try again.');
askForKey(); // Ask again
return;
}
// Validate the API key
const isValid = await this.verifyApiKey(trimmedKey);
if (!isValid) {
console.log('❌ Invalid API key. Please check your key and try again.');
askForKey(); // Ask again
return;
}
rl.close();
resolve(trimmedKey);
});
};
askForKey();
});
}
/**
* Get Unbound API key from environment or prompt user
*/
async getApiKey() {
// First try environment variable
const envApiKey = process.env.UNBOUND_API_KEY;
if (envApiKey && envApiKey.trim().length > 0) {
console.log('Using Unbound API key from UNBOUND_API_KEY environment variable');
return envApiKey.trim();
}
// If not found in environment, prompt user
console.log('UNBOUND_API_KEY environment variable not found.');
return await this.promptForApiKey();
}
/**
* Get API key without verification
*/
async getApiKeyOnly() {
// First try environment variable
const envApiKey = process.env.UNBOUND_API_KEY;
if (envApiKey && envApiKey.trim().length > 0) {
return envApiKey.trim();
}
// Then try stored API key
const storedApiKey = await this.storage.getApiKey();
if (storedApiKey) {
return storedApiKey;
}
// If not found anywhere, prompt user
console.log('No stored API key found.');
const apiKey = await this.promptForApiKey();
return apiKey;
}
/**
* Complete authentication flow: get API key and verify it
*/
async authenticate() {
const apiKey = await this.getApiKey();
console.log('Verifying API key...');
const isValid = await this.verifyApiKey(apiKey);
if (!isValid) {
throw new Error('Invalid API key. Please check your Unbound API key and try again.');
}
console.log('✓ API key verified successfully');
return apiKey;
}
}
exports.UnboundAuth = UnboundAuth;
//# sourceMappingURL=auth.js.map