390 lines
23 KiB
PHP
Executable File
390 lines
23 KiB
PHP
Executable File
<?php
|
|
require_once("/opt/wevads/config/credentials.php");
|
|
/**
|
|
* IA Provider Factory v2 — Multi-Account + Persona + Token Rotation
|
|
* - Multi-account per provider (persona-based)
|
|
* - Auto key rotation on rate limit
|
|
* - Token budget tracking
|
|
* - Account creation workflow
|
|
* - Key health monitoring + renewal
|
|
*/
|
|
header('Content-Type: application/json');
|
|
header('Access-Control-Allow-Origin: *');
|
|
|
|
$db = pg_connect("host=localhost dbname=adx_system user=admin password=".WEVADS_DB_PASS);
|
|
if(!$db){echo json_encode(['status'=>'error','message'=>'DB fail']);exit;}
|
|
pg_query($db,"SET search_path TO admin");
|
|
|
|
$action = $_GET['action'] ?? $_POST['action'] ?? json_decode(file_get_contents('php://input'),true)['action'] ?? 'dashboard';
|
|
|
|
// ═══ PROVIDER CATALOG ═══
|
|
$PROVIDERS = [
|
|
'Cerebras'=>['url'=>'https://api.cerebras.ai/v1/chat/completions','model'=>'llama-3.3-70b','type'=>'free','daily_tokens'=>1000000,'daily_reqs'=>1000,'signup'=>'https://cloud.cerebras.ai/','format'=>'openai'],
|
|
'Groq'=>['url'=>'https://api.groq.com/openai/v1/chat/completions','model'=>'llama-3.3-70b-versatile','type'=>'free','daily_tokens'=>500000,'daily_reqs'=>500,'signup'=>'https://console.groq.com/','format'=>'openai'],
|
|
'DeepSeek'=>['url'=>'https://api.deepseek.com/v1/chat/completions','model'=>'deepseek-chat','type'=>'paid','daily_tokens'=>2000000,'daily_reqs'=>1000,'signup'=>'https://platform.deepseek.com/','format'=>'openai'],
|
|
'Gemini'=>['url'=>'https://generativelanguage.googleapis.com/v1beta/models','model'=>'gemini-2.0-flash','type'=>'free','daily_tokens'=>1500000,'daily_reqs'=>1500,'signup'=>'https://aistudio.google.com/','format'=>'gemini'],
|
|
'SambaNova'=>['url'=>'https://api.sambanova.ai/v1/chat/completions','model'=>'Meta-Llama-3.3-70B-Instruct','type'=>'free','daily_tokens'=>500000,'daily_reqs'=>500,'signup'=>'https://cloud.sambanova.ai/','format'=>'openai'],
|
|
'Hyperbolic'=>['url'=>'https://api.hyperbolic.xyz/v1/chat/completions','model'=>'meta-llama/Llama-3.3-70B-Instruct','type'=>'free','daily_tokens'=>500000,'daily_reqs'=>500,'signup'=>'https://app.hyperbolic.xyz/','format'=>'openai'],
|
|
'Mistral'=>['url'=>'https://api.mistral.ai/v1/chat/completions','model'=>'mistral-large-latest','type'=>'free','daily_tokens'=>500000,'daily_reqs'=>500,'signup'=>'https://console.mistral.ai/','format'=>'openai'],
|
|
'Cohere'=>['url'=>'https://api.cohere.ai/v1/chat','model'=>'command-r-plus','type'=>'free','daily_tokens'=>1000000,'daily_reqs'=>1000,'signup'=>'https://dashboard.cohere.com/','format'=>'cohere'],
|
|
'OpenRouter'=>['url'=>'https://openrouter.ai/api/v1/chat/completions','model'=>'meta-llama/llama-3.1-70b-instruct','type'=>'free','daily_tokens'=>1000000,'daily_reqs'=>1000,'signup'=>'https://openrouter.ai/','format'=>'openai'],
|
|
'Together'=>['url'=>'https://api.together.xyz/v1/chat/completions','model'=>'meta-llama/Llama-3.3-70B-Instruct-Turbo','type'=>'free','daily_tokens'=>500000,'daily_reqs'=>500,'signup'=>'https://api.together.xyz/','format'=>'openai'],
|
|
'Lepton'=>['url'=>'https://llama3-70b.lepton.run/api/v1/chat/completions','model'=>'llama3-70b','type'=>'free','daily_tokens'=>1000000,'daily_reqs'=>1000,'signup'=>'https://www.lepton.ai/','format'=>'openai'],
|
|
'Novita'=>['url'=>'https://api.novita.ai/v3/openai/chat/completions','model'=>'meta-llama/llama-3.1-70b','type'=>'free','daily_tokens'=>500000,'daily_reqs'=>500,'signup'=>'https://novita.ai/','format'=>'openai'],
|
|
];
|
|
|
|
switch($action) {
|
|
|
|
// ═══════════════════════════════════════════════════
|
|
// DASHBOARD: Full overview of all accounts + tokens
|
|
// ═══════════════════════════════════════════════════
|
|
case 'dashboard':
|
|
$accounts = [];
|
|
$r = pg_query($db, "SELECT ipa.*, p.first_name, p.last_name, p.email as persona_email
|
|
FROM ia_provider_accounts ipa
|
|
LEFT JOIN personas p ON ipa.persona_id=p.id
|
|
ORDER BY ipa.provider_name, ipa.priority");
|
|
while($row=pg_fetch_assoc($r)) $accounts[] = $row;
|
|
|
|
// Aggregate by provider
|
|
$byProvider = [];
|
|
foreach($accounts as $a) {
|
|
$pn = $a['provider_name'];
|
|
if(!isset($byProvider[$pn])) $byProvider[$pn] = ['accounts'=>0,'active'=>0,'keys'=>0,'tokens_used'=>0,'tokens_limit'=>0,'requests_today'=>0];
|
|
$byProvider[$pn]['accounts']++;
|
|
if($a['status']=='active') $byProvider[$pn]['active']++;
|
|
if($a['api_key'] && strlen($a['api_key'])>5) $byProvider[$pn]['keys']++;
|
|
$byProvider[$pn]['tokens_used'] += (int)$a['tokens_used_today'];
|
|
$byProvider[$pn]['tokens_limit'] += (int)$a['tokens_limit_daily'];
|
|
$byProvider[$pn]['requests_today'] += (int)$a['requests_today'];
|
|
}
|
|
|
|
// Token budget
|
|
$totalTokensAvail = 0; $totalTokensUsed = 0;
|
|
foreach($byProvider as $p=>$d) {
|
|
$totalTokensAvail += $d['tokens_limit'];
|
|
$totalTokensUsed += $d['tokens_used'];
|
|
}
|
|
|
|
// Alerts
|
|
$alerts = [];
|
|
foreach($PROVIDERS as $pn=>$cfg) {
|
|
$pa = $byProvider[$pn] ?? null;
|
|
if(!$pa || $pa['keys']==0) $alerts[] = ['level'=>'critical','msg'=>"$pn: 0 API keys — add accounts via personas"];
|
|
elseif($pa['accounts']<2) $alerts[] = ['level'=>'warning','msg'=>"$pn: only {$pa['accounts']} account — add more personas for token boost"];
|
|
if($pa && $pa['tokens_limit']>0 && $pa['tokens_used']/$pa['tokens_limit']>0.8)
|
|
$alerts[] = ['level'=>'warning','msg'=>"$pn: ".round($pa['tokens_used']/$pa['tokens_limit']*100)."% token budget used — rotate keys"];
|
|
}
|
|
|
|
// Persona coverage
|
|
$pr = pg_query($db,"SELECT COUNT(*) as total, COUNT(DISTINCT persona_id) FILTER(WHERE persona_id IS NOT NULL) as with_persona FROM ia_provider_accounts");
|
|
$pcov = pg_fetch_assoc($pr);
|
|
|
|
echo json_encode([
|
|
'status'=>'success',
|
|
'total_accounts'=>count($accounts),
|
|
'active_accounts'=>count(array_filter($accounts,fn($a)=>$a['status']=='active')),
|
|
'total_keys'=>count(array_filter($accounts,fn($a)=>$a['api_key']&&strlen($a['api_key'])>5)),
|
|
'providers'=>$byProvider,
|
|
'token_budget'=>[
|
|
'total_daily_limit'=>$totalTokensAvail,
|
|
'used_today'=>$totalTokensUsed,
|
|
'remaining'=>$totalTokensAvail-$totalTokensUsed,
|
|
'usage_pct'=>$totalTokensAvail>0?round($totalTokensUsed/$totalTokensAvail*100,1):0
|
|
],
|
|
'persona_coverage'=>$pcov,
|
|
'alerts'=>$alerts,
|
|
'accounts'=>$accounts,
|
|
'catalog'=>array_map(fn($c)=>['type'=>$c['type'],'signup'=>$c['signup'],'model'=>$c['model'],'daily_tokens'=>$c['daily_tokens']],$PROVIDERS)
|
|
]);
|
|
break;
|
|
|
|
// ═══════════════════════════════════════════════════
|
|
// GET_BEST_KEY: Smart rotation — get best available key
|
|
// ═══════════════════════════════════════════════════
|
|
case 'get_best_key':
|
|
$provider = $_GET['provider'] ?? $_POST['provider'] ?? null;
|
|
$where = $provider ? "AND ipa.provider_name='".pg_escape_string($db,$provider)."'" : "";
|
|
|
|
$r = pg_query($db, "SELECT ipa.id, ipa.provider_name, ipa.api_key, ipa.model, ipa.api_url,
|
|
ipa.tokens_used_today, ipa.tokens_limit_daily, ipa.requests_today, ipa.requests_limit_daily,
|
|
ipa.latency_ms, ipa.success_rate, ipa.priority
|
|
FROM ia_provider_accounts ipa
|
|
WHERE ipa.status='active' AND ipa.api_key IS NOT NULL AND LENGTH(ipa.api_key)>5
|
|
AND (ipa.cooldown_until IS NULL OR ipa.cooldown_until < NOW())
|
|
AND ipa.requests_today < ipa.requests_limit_daily
|
|
$where
|
|
ORDER BY
|
|
ipa.priority ASC,
|
|
(ipa.tokens_used_today::float / NULLIF(ipa.tokens_limit_daily,0)) ASC,
|
|
ipa.success_rate DESC,
|
|
ipa.latency_ms ASC
|
|
LIMIT 1");
|
|
|
|
$best = pg_fetch_assoc($r);
|
|
if(!$best) {
|
|
echo json_encode(['status'=>'error','message'=>'No available key — all rate limited or no keys','action'=>'add_more_accounts']);
|
|
break;
|
|
}
|
|
|
|
// Update usage
|
|
pg_query($db, "UPDATE ia_provider_accounts SET requests_today=requests_today+1, last_used=NOW() WHERE id={$best['id']}");
|
|
|
|
echo json_encode([
|
|
'status'=>'success',
|
|
'account_id'=>$best['id'],
|
|
'provider'=>$best['provider_name'],
|
|
'api_key'=>$best['api_key'],
|
|
'model'=>$best['model'],
|
|
'api_url'=>$best['api_url'],
|
|
'budget_remaining_pct'=>$best['tokens_limit_daily']>0 ? round((1-$best['tokens_used_today']/$best['tokens_limit_daily'])*100,1) : 100
|
|
]);
|
|
break;
|
|
|
|
// ═══════════════════════════════════════════════════
|
|
// LOG_USAGE: Track token consumption per call
|
|
// ═══════════════════════════════════════════════════
|
|
case 'log_usage':
|
|
$data = json_decode(file_get_contents('php://input'),true);
|
|
$accId = (int)($data['account_id'] ?? 0);
|
|
$tokIn = (int)($data['tokens_input'] ?? 0);
|
|
$tokOut = (int)($data['tokens_output'] ?? 0);
|
|
$tokTotal = $tokIn + $tokOut;
|
|
$latency = (int)($data['latency_ms'] ?? 0);
|
|
$success = ($data['success'] ?? true) ? 'true' : 'false';
|
|
$error = pg_escape_string($db, $data['error'] ?? '');
|
|
|
|
// Update account
|
|
pg_query($db, "UPDATE ia_provider_accounts SET
|
|
tokens_used_today=tokens_used_today+$tokTotal,
|
|
tokens_used_total=tokens_used_total+$tokTotal,
|
|
requests_total=requests_total+1,
|
|
latency_ms=$latency,
|
|
last_used=NOW(),
|
|
success_rate = CASE WHEN $success THEN LEAST(100, success_rate+0.1) ELSE GREATEST(0, success_rate-5) END
|
|
".($success=='false'?",error_count=error_count+1,last_error='$error'":"")."
|
|
WHERE id=$accId");
|
|
|
|
// Check if rate limited
|
|
$acc = pg_fetch_assoc(pg_query($db,"SELECT tokens_used_today,tokens_limit_daily,requests_today,requests_limit_daily FROM ia_provider_accounts WHERE id=$accId"));
|
|
$rateLimited = false;
|
|
if($acc && ($acc['tokens_used_today']>=$acc['tokens_limit_daily']*0.95 || $acc['requests_today']>=$acc['requests_limit_daily']*0.95)) {
|
|
pg_query($db,"UPDATE ia_provider_accounts SET status='rate_limited',cooldown_until=NOW()+interval '1 hour' WHERE id=$accId");
|
|
$rateLimited = true;
|
|
// Log rotation
|
|
pg_query($db,"INSERT INTO ia_key_rotation_log(old_account_id,provider_name,reason) SELECT $accId,provider_name,'rate_limited' FROM ia_provider_accounts WHERE id=$accId");
|
|
}
|
|
|
|
// Log
|
|
pg_query($db,"INSERT INTO ia_token_usage_log(account_id,provider_name,tokens_input,tokens_output,tokens_total,model,latency_ms,success,error_message)
|
|
SELECT $accId,provider_name,$tokIn,$tokOut,$tokTotal,model,$latency,$success,'$error' FROM ia_provider_accounts WHERE id=$accId");
|
|
|
|
echo json_encode(['status'=>'success','tokens_logged'=>$tokTotal,'rate_limited'=>$rateLimited]);
|
|
break;
|
|
|
|
// ═══════════════════════════════════════════════════
|
|
// CREATE_ACCOUNT: Link persona → provider account
|
|
// ═══════════════════════════════════════════════════
|
|
case 'create_account':
|
|
$data = json_decode(file_get_contents('php://input'),true) ?: $_POST;
|
|
$provider = pg_escape_string($db, $data['provider'] ?? '');
|
|
$apiKey = pg_escape_string($db, $data['api_key'] ?? '');
|
|
$personaId = (int)($data['persona_id'] ?? 0);
|
|
$email = pg_escape_string($db, $data['email'] ?? '');
|
|
|
|
if(!$provider){echo json_encode(['status'=>'error','message'=>'provider required']);break;}
|
|
|
|
$cat = $PROVIDERS[$provider] ?? null;
|
|
$model = pg_escape_string($db, $data['model'] ?? ($cat['model']??''));
|
|
$apiUrl = pg_escape_string($db, $data['api_url'] ?? ($cat['url']??''));
|
|
$tokLimit = $cat['daily_tokens'] ?? 500000;
|
|
$reqLimit = $cat['daily_reqs'] ?? 500;
|
|
|
|
// Check persona
|
|
$personaClause = $personaId>0 ? $personaId : 'NULL';
|
|
|
|
$r = pg_query($db, "INSERT INTO ia_provider_accounts(provider_name,persona_id,account_email,api_key,model,api_url,tokens_limit_daily,requests_limit_daily,status,signup_method)
|
|
VALUES('$provider',$personaClause,'$email','$apiKey','$model','$apiUrl',$tokLimit,$reqLimit,
|
|
".($apiKey?"'active'":"'pending'").",'manual') RETURNING id");
|
|
$new = pg_fetch_assoc($r);
|
|
|
|
echo json_encode(['status'=>'success','account_id'=>$new['id'],'message'=>"Account created for $provider"]);
|
|
break;
|
|
|
|
// ═══════════════════════════════════════════════════
|
|
// BATCH_CREATE: Auto-assign personas to providers
|
|
// ═══════════════════════════════════════════════════
|
|
case 'batch_create':
|
|
$data = json_decode(file_get_contents('php://input'),true) ?: $_POST;
|
|
$targetPerProvider = (int)($data['target_per_provider'] ?? 3);
|
|
|
|
// Get available personas without accounts
|
|
$personas = [];
|
|
$r = pg_query($db, "SELECT p.id, p.first_name, p.last_name, p.email
|
|
FROM personas p WHERE p.is_active=true
|
|
AND p.id NOT IN (SELECT persona_id FROM ia_provider_accounts WHERE persona_id IS NOT NULL)
|
|
ORDER BY random() LIMIT 100");
|
|
while($row=pg_fetch_assoc($r)) $personas[] = $row;
|
|
|
|
$created = [];
|
|
$pIdx = 0;
|
|
foreach($PROVIDERS as $pn=>$cfg) {
|
|
if($cfg['type']=='paid') continue; // Skip paid providers for auto-create
|
|
|
|
// Count existing accounts
|
|
$existing = pg_fetch_assoc(pg_query($db, "SELECT COUNT(*) as c FROM ia_provider_accounts WHERE provider_name='$pn'"));
|
|
$need = max(0, $targetPerProvider - (int)$existing['c']);
|
|
|
|
for($i=0; $i<$need && $pIdx<count($personas); $i++) {
|
|
$p = $personas[$pIdx++];
|
|
$email = strtolower($p['first_name'].'.'.$p['last_name'].rand(10,99).'@gmail.com');
|
|
pg_query($db, "INSERT INTO ia_provider_accounts(provider_name,persona_id,account_email,model,api_url,tokens_limit_daily,requests_limit_daily,status,signup_method,signup_url)
|
|
VALUES('$pn',{$p['id']},'$email','{$cfg['model']}','{$cfg['url']}',{$cfg['daily_tokens']},{$cfg['daily_reqs']},'pending','automated','{$cfg['signup']}')");
|
|
$created[] = ['provider'=>$pn,'persona'=>$p['first_name'].' '.$p['last_name'],'email'=>$email,'status'=>'pending'];
|
|
}
|
|
}
|
|
|
|
echo json_encode(['status'=>'success','created'=>count($created),'accounts'=>$created,
|
|
'message'=>count($created).' persona accounts created. Set API keys to activate.',
|
|
'next_step'=>'For each pending account: signup at provider URL, get API key, call update_key']);
|
|
break;
|
|
|
|
// ═══════════════════════════════════════════════════
|
|
// UPDATE_KEY: Add/update API key for account
|
|
// ═══════════════════════════════════════════════════
|
|
case 'update_key':
|
|
$data = json_decode(file_get_contents('php://input'),true) ?: $_POST;
|
|
$accId = (int)($data['account_id'] ?? 0);
|
|
$apiKey = pg_escape_string($db, $data['api_key'] ?? '');
|
|
if(!$accId||!$apiKey){echo json_encode(['status'=>'error','message'=>'account_id + api_key required']);break;}
|
|
|
|
pg_query($db, "UPDATE ia_provider_accounts SET api_key='$apiKey', status='active', key_created_at=NOW(), updated_at=NOW() WHERE id=$accId");
|
|
echo json_encode(['status'=>'success','message'=>'Key updated, account activated']);
|
|
break;
|
|
|
|
// ═══════════════════════════════════════════════════
|
|
// TEST_ALL: Test every active key
|
|
// ═══════════════════════════════════════════════════
|
|
case 'test_all':
|
|
case 'scan':
|
|
$accounts = [];
|
|
$r = pg_query($db, "SELECT id,provider_name,api_key,model,api_url FROM ia_provider_accounts WHERE api_key IS NOT NULL AND LENGTH(api_key)>5 ORDER BY provider_name");
|
|
$results = [];
|
|
while($acc=pg_fetch_assoc($r)) {
|
|
$res = testKey($acc['provider_name'],$acc['api_key'],$acc['model'],$acc['api_url']);
|
|
$status = $res['http_code']==200 ? 'active' : ($res['http_code']==429 ? 'rate_limited' : 'error');
|
|
pg_query($db, "UPDATE ia_provider_accounts SET status='$status', last_tested=NOW(), last_test_result='$status', latency_ms={$res['latency_ms']} WHERE id={$acc['id']}");
|
|
$results[] = ['id'=>$acc['id'],'provider'=>$acc['provider_name'],'status'=>$status,'latency'=>$res['latency_ms'].'ms','http'=>$res['http_code']];
|
|
}
|
|
echo json_encode(['status'=>'success','tested'=>count($results),'results'=>$results]);
|
|
break;
|
|
|
|
// ═══════════════════════════════════════════════════
|
|
// ROTATE: Reset daily counters + unblock rate_limited
|
|
// ═══════════════════════════════════════════════════
|
|
case 'rotate':
|
|
case 'reset_daily':
|
|
pg_query($db, "UPDATE ia_provider_accounts SET tokens_used_today=0, requests_today=0, status='active' WHERE status='rate_limited' AND cooldown_until<NOW()");
|
|
pg_query($db, "UPDATE ia_provider_accounts SET tokens_used_today=0, requests_today=0 WHERE tokens_used_today>0");
|
|
$r = pg_fetch_assoc(pg_query($db, "SELECT COUNT(*) as reset FROM ia_provider_accounts WHERE tokens_used_today=0"));
|
|
echo json_encode(['status'=>'success','message'=>'Daily counters reset','accounts_reset'=>$r['reset']]);
|
|
break;
|
|
|
|
// ═══════════════════════════════════════════════════
|
|
// TOKEN_REPORT: Detailed token usage analytics
|
|
// ═══════════════════════════════════════════════════
|
|
case 'token_report':
|
|
$days = (int)($_GET['days'] ?? 7);
|
|
$r = pg_query($db, "SELECT provider_name,
|
|
SUM(tokens_total) as total_tokens,
|
|
COUNT(*) as total_requests,
|
|
AVG(latency_ms) as avg_latency,
|
|
SUM(CASE WHEN success THEN 1 ELSE 0 END)*100.0/COUNT(*) as success_pct
|
|
FROM ia_token_usage_log
|
|
WHERE logged_at > NOW()-interval '$days days'
|
|
GROUP BY provider_name ORDER BY total_tokens DESC");
|
|
$report = [];
|
|
while($row=pg_fetch_assoc($r)) $report[] = $row;
|
|
|
|
echo json_encode(['status'=>'success','period_days'=>$days,'usage'=>$report]);
|
|
break;
|
|
|
|
// ═══════════════════════════════════════════════════
|
|
// PENDING: Show accounts needing API keys
|
|
// ═══════════════════════════════════════════════════
|
|
case 'pending':
|
|
$r = pg_query($db, "SELECT ipa.id, ipa.provider_name, ipa.account_email, ipa.signup_url,
|
|
p.first_name, p.last_name
|
|
FROM ia_provider_accounts ipa
|
|
LEFT JOIN personas p ON ipa.persona_id=p.id
|
|
WHERE ipa.status='pending' ORDER BY ipa.provider_name");
|
|
$pending = [];
|
|
while($row=pg_fetch_assoc($r)) $pending[] = $row;
|
|
echo json_encode(['status'=>'success','pending_count'=>count($pending),'accounts'=>$pending]);
|
|
break;
|
|
|
|
// ═══════════════════════════════════════════════════
|
|
// STATUS: Quick health check
|
|
// ═══════════════════════════════════════════════════
|
|
case 'status':
|
|
default:
|
|
$stats = pg_fetch_assoc(pg_query($db, "SELECT
|
|
COUNT(*) as total,
|
|
SUM(CASE WHEN status='active' THEN 1 ELSE 0 END) as active,
|
|
SUM(CASE WHEN status='pending' THEN 1 ELSE 0 END) as pending,
|
|
SUM(CASE WHEN status='rate_limited' THEN 1 ELSE 0 END) as rate_limited,
|
|
SUM(CASE WHEN api_key IS NOT NULL AND LENGTH(api_key)>5 THEN 1 ELSE 0 END) as with_keys,
|
|
COUNT(DISTINCT provider_name) as providers,
|
|
COUNT(DISTINCT persona_id) FILTER(WHERE persona_id IS NOT NULL) as personas_linked,
|
|
SUM(tokens_limit_daily) as total_daily_tokens,
|
|
SUM(tokens_used_today) as tokens_used_today
|
|
FROM ia_provider_accounts"));
|
|
|
|
$health = 'EXCELLENT';
|
|
if((int)$stats['with_keys']<5) $health = 'NEEDS_MORE_KEYS';
|
|
if((int)$stats['active']<3) $health = 'CRITICAL';
|
|
if((int)$stats['total']>10 && (int)$stats['personas_linked']<5) $health = 'NEEDS_PERSONA_LINKS';
|
|
|
|
echo json_encode([
|
|
'status'=>'success',
|
|
'health'=>$health,
|
|
'stats'=>$stats,
|
|
'token_budget'=>[
|
|
'daily_limit'=>(int)$stats['total_daily_tokens'],
|
|
'used_today'=>(int)$stats['tokens_used_today'],
|
|
'remaining'=>(int)$stats['total_daily_tokens']-(int)$stats['tokens_used_today']
|
|
]
|
|
]);
|
|
break;
|
|
}
|
|
|
|
// ═══ TEST KEY FUNCTION ═══
|
|
function testKey($provider,$key,$model,$apiUrl) {
|
|
$start = microtime(true);
|
|
$ch = curl_init();
|
|
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER=>true, CURLOPT_TIMEOUT=>10, CURLOPT_SSL_VERIFYPEER=>false]);
|
|
|
|
if(stripos($provider,'gemini')!==false) {
|
|
curl_setopt($ch, CURLOPT_URL, "$apiUrl/$model:generateContent?key=$key");
|
|
curl_setopt($ch, CURLOPT_POST, true);
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['contents'=>[['parts'=>[['text'=>'OK']]]]]));
|
|
} elseif(stripos($provider,'cohere')!==false) {
|
|
curl_setopt($ch, CURLOPT_URL, $apiUrl);
|
|
curl_setopt($ch, CURLOPT_POST, true);
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json',"Authorization: Bearer $key"]);
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['model'=>$model,'message'=>'OK']));
|
|
} else {
|
|
curl_setopt($ch, CURLOPT_URL, $apiUrl);
|
|
curl_setopt($ch, CURLOPT_POST, true);
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json',"Authorization: Bearer $key"]);
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['model'=>$model,'messages'=>[['role'=>'user','content'=>'Say OK']],'max_tokens'=>10]));
|
|
}
|
|
|
|
curl_exec($ch);
|
|
$http = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
$lat = round((microtime(true)-$start)*1000);
|
|
curl_close($ch);
|
|
return ['http_code'=>$http,'latency_ms'=>$lat];
|
|
}
|
|
?>
|