antri_cli 1.57.51 → 1.57.52
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/shortcuts.d.ts.map +1 -1
- package/dist/cli/shortcuts.js +39 -7
- package/dist/cli/shortcuts.js.map +1 -1
- package/dist/core/config.d.ts +5 -1
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +64 -2
- package/dist/core/config.js.map +1 -1
- package/dist/core/updater.d.ts +1 -1
- package/dist/core/updater.js +1 -1
- package/dist/desktop/public/app.js +246 -0
- package/dist/desktop/public/index.html +76 -1
- package/dist/desktop/server.d.ts.map +1 -1
- package/dist/desktop/server.js +73 -0
- package/dist/desktop/server.js.map +1 -1
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -1
- package/dist/providers/gemini.d.ts +6 -0
- package/dist/providers/gemini.d.ts.map +1 -1
- package/dist/providers/gemini.js +37 -2
- package/dist/providers/gemini.js.map +1 -1
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +14 -0
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/openai.d.ts +3 -0
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +18 -1
- package/dist/providers/openai.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -2899,3 +2899,249 @@ async function respondGlobalPermission(requestId, allowed, alwaysAllow) {
|
|
|
2899
2899
|
console.error('Failed to send permission response:', err);
|
|
2900
2900
|
}
|
|
2901
2901
|
}
|
|
2902
|
+
|
|
2903
|
+
// -------------------------------------------------------------
|
|
2904
|
+
// AUTH & ACCOUNT MODAL MANAGEMENT
|
|
2905
|
+
// -------------------------------------------------------------
|
|
2906
|
+
function openAuthModal() {
|
|
2907
|
+
const modal = document.getElementById('auth-modal');
|
|
2908
|
+
if (modal) modal.style.display = 'flex';
|
|
2909
|
+
}
|
|
2910
|
+
|
|
2911
|
+
function closeAuthModal() {
|
|
2912
|
+
const modal = document.getElementById('auth-modal');
|
|
2913
|
+
if (modal) modal.style.display = 'none';
|
|
2914
|
+
}
|
|
2915
|
+
|
|
2916
|
+
async function checkAuthStatus() {
|
|
2917
|
+
try {
|
|
2918
|
+
const res = await fetch('/api/status');
|
|
2919
|
+
const data = await res.json();
|
|
2920
|
+
const user = data.user;
|
|
2921
|
+
const dot = document.getElementById('auth-status-dot');
|
|
2922
|
+
const text = document.getElementById('auth-status-text');
|
|
2923
|
+
const formView = document.getElementById('auth-form-view');
|
|
2924
|
+
const loggedView = document.getElementById('auth-logged-view');
|
|
2925
|
+
const loggedEmail = document.getElementById('logged-user-email');
|
|
2926
|
+
const loggedId = document.getElementById('logged-user-id');
|
|
2927
|
+
|
|
2928
|
+
if (user && user.email) {
|
|
2929
|
+
if (dot) dot.className = 'status-dot online';
|
|
2930
|
+
if (text) text.textContent = user.email.split('@')[0];
|
|
2931
|
+
if (formView) formView.style.display = 'none';
|
|
2932
|
+
if (loggedView) loggedView.style.display = 'block';
|
|
2933
|
+
if (loggedEmail) loggedEmail.textContent = user.email;
|
|
2934
|
+
if (loggedId) loggedId.textContent = `Partition: ${user.userId || user.email}`;
|
|
2935
|
+
} else {
|
|
2936
|
+
if (dot) dot.className = 'status-dot';
|
|
2937
|
+
if (text) text.textContent = 'Login';
|
|
2938
|
+
if (formView) formView.style.display = 'block';
|
|
2939
|
+
if (loggedView) loggedView.style.display = 'none';
|
|
2940
|
+
}
|
|
2941
|
+
|
|
2942
|
+
loadSettingsState(data.config);
|
|
2943
|
+
} catch (_) {}
|
|
2944
|
+
}
|
|
2945
|
+
|
|
2946
|
+
async function submitDesktopLogin() {
|
|
2947
|
+
const email = (document.getElementById('modal-email-input')?.value || '').trim();
|
|
2948
|
+
const password = (document.getElementById('modal-pass-input')?.value || '').trim();
|
|
2949
|
+
const backendUrl = (document.getElementById('modal-backend-url-input')?.value || '').trim();
|
|
2950
|
+
|
|
2951
|
+
if (!email) {
|
|
2952
|
+
showToast('Please enter an email address.', true);
|
|
2953
|
+
return;
|
|
2954
|
+
}
|
|
2955
|
+
|
|
2956
|
+
showToast('Authenticating with Google Cloud Firestore...');
|
|
2957
|
+
try {
|
|
2958
|
+
const res = await fetch('/api/auth/login', {
|
|
2959
|
+
method: 'POST',
|
|
2960
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2961
|
+
body: JSON.stringify({ email, password, backendUrl }),
|
|
2962
|
+
});
|
|
2963
|
+
const data = await res.json();
|
|
2964
|
+
if (data.success) {
|
|
2965
|
+
closeAuthModal();
|
|
2966
|
+
showToast(`Signed in as ${data.user?.email || email}. Profiles synced!`);
|
|
2967
|
+
await checkAuthStatus();
|
|
2968
|
+
await loadProfiles();
|
|
2969
|
+
await loadStatus();
|
|
2970
|
+
} else {
|
|
2971
|
+
showToast(data.message || 'Login failed', true);
|
|
2972
|
+
}
|
|
2973
|
+
} catch (err) {
|
|
2974
|
+
showToast(`Auth error: ${err.message}`, true);
|
|
2975
|
+
}
|
|
2976
|
+
}
|
|
2977
|
+
|
|
2978
|
+
async function submitDesktopLogout() {
|
|
2979
|
+
await fetch('/api/auth/logout', { method: 'POST' });
|
|
2980
|
+
closeAuthModal();
|
|
2981
|
+
showToast('Logged out. Switched to guest mode.');
|
|
2982
|
+
await checkAuthStatus();
|
|
2983
|
+
await loadProfiles();
|
|
2984
|
+
await loadStatus();
|
|
2985
|
+
}
|
|
2986
|
+
|
|
2987
|
+
// -------------------------------------------------------------
|
|
2988
|
+
// SETTINGS: GOOGLE CLOUD RUN & MULTI-KEY POOL MANAGEMENT
|
|
2989
|
+
// -------------------------------------------------------------
|
|
2990
|
+
function loadSettingsState(cfg) {
|
|
2991
|
+
if (!cfg) return;
|
|
2992
|
+
const backendInput = document.getElementById('settings-backend-url');
|
|
2993
|
+
const badge = document.getElementById('cloud-status-badge');
|
|
2994
|
+
|
|
2995
|
+
if (backendInput && cfg.backendUrl) {
|
|
2996
|
+
backendInput.value = cfg.backendUrl;
|
|
2997
|
+
}
|
|
2998
|
+
|
|
2999
|
+
if (badge) {
|
|
3000
|
+
if (cfg.backendUrl) {
|
|
3001
|
+
badge.className = 'badge badge-running';
|
|
3002
|
+
badge.textContent = 'Cloud Run Active';
|
|
3003
|
+
} else {
|
|
3004
|
+
badge.className = 'badge badge-idle';
|
|
3005
|
+
badge.textContent = 'Local Node';
|
|
3006
|
+
}
|
|
3007
|
+
}
|
|
3008
|
+
|
|
3009
|
+
onSettingsProviderChange();
|
|
3010
|
+
}
|
|
3011
|
+
|
|
3012
|
+
function onSettingsProviderChange() {
|
|
3013
|
+
const provider = document.getElementById('settings-key-provider')?.value || 'gemini';
|
|
3014
|
+
const textarea = document.getElementById('settings-keys-textarea');
|
|
3015
|
+
const poolBadge = document.getElementById('keys-pool-count');
|
|
3016
|
+
|
|
3017
|
+
if (!currentConfig) return;
|
|
3018
|
+
|
|
3019
|
+
const formatted = provider.replace(/-/g, '_');
|
|
3020
|
+
const pool = currentConfig.apiKeyPools?.[formatted];
|
|
3021
|
+
const single = currentConfig.apiKeys?.[formatted];
|
|
3022
|
+
|
|
3023
|
+
if (textarea) {
|
|
3024
|
+
if (pool && pool.length > 0) {
|
|
3025
|
+
textarea.value = pool.join('\n');
|
|
3026
|
+
} else if (single) {
|
|
3027
|
+
textarea.value = single;
|
|
3028
|
+
} else {
|
|
3029
|
+
textarea.value = '';
|
|
3030
|
+
}
|
|
3031
|
+
}
|
|
3032
|
+
|
|
3033
|
+
if (poolBadge) {
|
|
3034
|
+
const count = (pool && pool.length > 0) ? pool.length : (single ? 1 : 0);
|
|
3035
|
+
poolBadge.textContent = `${count} Key(s) in Pool`;
|
|
3036
|
+
}
|
|
3037
|
+
}
|
|
3038
|
+
|
|
3039
|
+
async function saveCloudBackendUrl() {
|
|
3040
|
+
const input = document.getElementById('settings-backend-url');
|
|
3041
|
+
const url = (input?.value || '').trim();
|
|
3042
|
+
const out = document.getElementById('cloud-health-output');
|
|
3043
|
+
|
|
3044
|
+
showToast('Connecting to Cloud Run backend...');
|
|
3045
|
+
try {
|
|
3046
|
+
const res = await fetch('/api/config/backend', {
|
|
3047
|
+
method: 'POST',
|
|
3048
|
+
headers: { 'Content-Type': 'application/json' },
|
|
3049
|
+
body: JSON.stringify({ url }),
|
|
3050
|
+
});
|
|
3051
|
+
const data = await res.json();
|
|
3052
|
+
if (data.success) {
|
|
3053
|
+
if (out) {
|
|
3054
|
+
out.style.display = 'block';
|
|
3055
|
+
if (data.healthOk) {
|
|
3056
|
+
out.style.color = '#4ade80';
|
|
3057
|
+
out.textContent = `✓ Connected to Cloud Run Backend! Service: ${data.health.service || 'Online'} · Model: ${data.health.model || 'gemini-3.7-flash'}`;
|
|
3058
|
+
} else {
|
|
3059
|
+
out.style.color = '#f59e0b';
|
|
3060
|
+
out.textContent = `ℹ Endpoint saved (${url}). Health ping returned status check.`;
|
|
3061
|
+
}
|
|
3062
|
+
}
|
|
3063
|
+
showToast('Google Cloud Run backend endpoint saved.');
|
|
3064
|
+
await loadStatus();
|
|
3065
|
+
}
|
|
3066
|
+
} catch (err) {
|
|
3067
|
+
showToast(`Failed: ${err.message}`, true);
|
|
3068
|
+
}
|
|
3069
|
+
}
|
|
3070
|
+
|
|
3071
|
+
async function testCloudBackendHealth() {
|
|
3072
|
+
const input = document.getElementById('settings-backend-url');
|
|
3073
|
+
const url = (input?.value || '').trim();
|
|
3074
|
+
const out = document.getElementById('cloud-health-output');
|
|
3075
|
+
if (!url) {
|
|
3076
|
+
showToast('Please enter a Cloud Run URL first.', true);
|
|
3077
|
+
return;
|
|
3078
|
+
}
|
|
3079
|
+
|
|
3080
|
+
if (out) {
|
|
3081
|
+
out.style.display = 'block';
|
|
3082
|
+
out.style.color = '#38bdf8';
|
|
3083
|
+
out.textContent = 'Pinging Cloud Run health probe...';
|
|
3084
|
+
}
|
|
3085
|
+
|
|
3086
|
+
try {
|
|
3087
|
+
const resp = await fetch(`${url.replace(/\/$/, '')}/api/health`);
|
|
3088
|
+
if (resp.ok) {
|
|
3089
|
+
const data = await resp.json();
|
|
3090
|
+
if (out) {
|
|
3091
|
+
out.style.color = '#4ade80';
|
|
3092
|
+
out.textContent = `✓ 200 OK — ${data.service} (${data.googleCloud?.platform || 'Google Cloud Run'}) · Gemini Suite Active`;
|
|
3093
|
+
}
|
|
3094
|
+
showToast('✓ Cloud Run Health Check Passed (100% Online)');
|
|
3095
|
+
} else {
|
|
3096
|
+
if (out) {
|
|
3097
|
+
out.style.color = '#ef4444';
|
|
3098
|
+
out.textContent = `✕ Health check failed with HTTP ${resp.status}`;
|
|
3099
|
+
}
|
|
3100
|
+
showToast(`Health check returned HTTP ${resp.status}`, true);
|
|
3101
|
+
}
|
|
3102
|
+
} catch (err) {
|
|
3103
|
+
if (out) {
|
|
3104
|
+
out.style.color = '#ef4444';
|
|
3105
|
+
out.textContent = `✕ Error reaching endpoint: ${err.message}`;
|
|
3106
|
+
}
|
|
3107
|
+
showToast(`Health check failed: ${err.message}`, true);
|
|
3108
|
+
}
|
|
3109
|
+
}
|
|
3110
|
+
|
|
3111
|
+
async function saveApiKeyPool() {
|
|
3112
|
+
const provider = document.getElementById('settings-key-provider')?.value || 'gemini';
|
|
3113
|
+
const rawKeys = document.getElementById('settings-keys-textarea')?.value || '';
|
|
3114
|
+
|
|
3115
|
+
try {
|
|
3116
|
+
const res = await fetch('/api/config/keys', {
|
|
3117
|
+
method: 'POST',
|
|
3118
|
+
headers: { 'Content-Type': 'application/json' },
|
|
3119
|
+
body: JSON.stringify({ provider, keys: rawKeys }),
|
|
3120
|
+
});
|
|
3121
|
+
const data = await res.json();
|
|
3122
|
+
if (data.success) {
|
|
3123
|
+
showToast(`Saved ${data.keysCount} API key(s) in auto-rotation pool for ${provider}.`);
|
|
3124
|
+
await loadStatus();
|
|
3125
|
+
}
|
|
3126
|
+
} catch (err) {
|
|
3127
|
+
showToast(`Failed to save key pool: ${err.message}`, true);
|
|
3128
|
+
}
|
|
3129
|
+
}
|
|
3130
|
+
|
|
3131
|
+
async function rotateKeyPoolManually() {
|
|
3132
|
+
const provider = document.getElementById('settings-key-provider')?.value || 'gemini';
|
|
3133
|
+
try {
|
|
3134
|
+
const res = await fetch('/api/config/key-rotate', {
|
|
3135
|
+
method: 'POST',
|
|
3136
|
+
headers: { 'Content-Type': 'application/json' },
|
|
3137
|
+
body: JSON.stringify({ provider }),
|
|
3138
|
+
});
|
|
3139
|
+
const data = await res.json();
|
|
3140
|
+
if (data.success) {
|
|
3141
|
+
showToast(`Rotated to next key in pool (${data.totalKeys} keys total).`);
|
|
3142
|
+
await loadStatus();
|
|
3143
|
+
}
|
|
3144
|
+
} catch (err) {
|
|
3145
|
+
showToast(`Rotate failed: ${err.message}`, true);
|
|
3146
|
+
}
|
|
3147
|
+
}
|
|
@@ -106,6 +106,9 @@
|
|
|
106
106
|
<button class="nav-item" onclick="showTab('suggestions')">
|
|
107
107
|
<span class="nav-label">💡 Suggestions & Ideas</span>
|
|
108
108
|
</button>
|
|
109
|
+
<button class="nav-item" onclick="showTab('settings')">
|
|
110
|
+
<span class="nav-label">⚙️ Settings & Cloud Run</span>
|
|
111
|
+
</button>
|
|
109
112
|
|
|
110
113
|
<div class="sidebar-footer">
|
|
111
114
|
<div class="sync-status">
|
|
@@ -890,6 +893,73 @@
|
|
|
890
893
|
</div>
|
|
891
894
|
</section>
|
|
892
895
|
|
|
896
|
+
<!-- TAB: SETTINGS & GOOGLE CLOUD RUN -->
|
|
897
|
+
<section id="tab-settings" class="tab-panel">
|
|
898
|
+
<div class="panel-header">
|
|
899
|
+
<div>
|
|
900
|
+
<h2>⚙️ Cloud Run & Multi-Key Settings</h2>
|
|
901
|
+
<p class="subtitle">Configure Google Cloud Run backend endpoints, multi-API key auto-rotation pools, and platform sync.</p>
|
|
902
|
+
</div>
|
|
903
|
+
</div>
|
|
904
|
+
|
|
905
|
+
<div style="display:grid;grid-template-columns:repeat(auto-fit, minmax(400px, 1fr));gap:20px;margin-top:16px;">
|
|
906
|
+
<!-- CARD 1: Google Cloud Run Backend Endpoint -->
|
|
907
|
+
<div class="card" style="background:var(--bg-surface);border:1px solid var(--border);border-radius:12px;padding:20px;">
|
|
908
|
+
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:12px;">
|
|
909
|
+
<h3 style="margin:0;font-size:16px;color:var(--text);display:flex;align-items:center;gap:8px;">
|
|
910
|
+
<span>☁️</span> Google Cloud Run Backend (.run.app)
|
|
911
|
+
</h3>
|
|
912
|
+
<span id="cloud-status-badge" class="badge badge-idle" style="padding:4px 8px;font-size:11px;">Local Node</span>
|
|
913
|
+
</div>
|
|
914
|
+
<p style="font-size:13px;color:var(--text-muted);margin-bottom:16px;">
|
|
915
|
+
Connect ANTRI Desktop & CLI to your Google Cloud Run container. Automatically inherits Gemini 3.7 / 3.5 models and tools.
|
|
916
|
+
</p>
|
|
917
|
+
<div style="margin-bottom:12px;">
|
|
918
|
+
<label style="display:block;font-size:12px;font-weight:600;margin-bottom:6px;">Cloud Run URL</label>
|
|
919
|
+
<input type="text" id="settings-backend-url" class="modal-input" placeholder="https://antri-backend-xxxxx-uc.a.run.app" />
|
|
920
|
+
</div>
|
|
921
|
+
<div style="display:flex;gap:8px;">
|
|
922
|
+
<button class="action-btn" onclick="saveCloudBackendUrl()" style="flex:1;">⚡ Connect Cloud Run</button>
|
|
923
|
+
<button class="action-btn-secondary" onclick="testCloudBackendHealth()">🔍 Test Health</button>
|
|
924
|
+
</div>
|
|
925
|
+
<div id="cloud-health-output" style="margin-top:12px;font-size:12px;display:none;padding:8px 12px;border-radius:6px;background:rgba(255,255,255,0.03);border:1px solid var(--border);"></div>
|
|
926
|
+
</div>
|
|
927
|
+
|
|
928
|
+
<!-- CARD 2: Multi-API Key Auto-Rotation Pool -->
|
|
929
|
+
<div class="card" style="background:var(--bg-surface);border:1px solid var(--border);border-radius:12px;padding:20px;">
|
|
930
|
+
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:12px;">
|
|
931
|
+
<h3 style="margin:0;font-size:16px;color:var(--text);display:flex;align-items:center;gap:8px;">
|
|
932
|
+
<span>🔑</span> Multi-API Key Auto-Rotation Pool
|
|
933
|
+
</h3>
|
|
934
|
+
<span id="keys-pool-count" class="badge" style="background:#7c3aed;color:#fff;padding:4px 8px;font-size:11px;">1 Key Active</span>
|
|
935
|
+
</div>
|
|
936
|
+
<p style="font-size:13px;color:var(--text-muted);margin-bottom:16px;">
|
|
937
|
+
Provide 3-4 API keys. When one key reaches rate limits (429) or runs out of credits, ANTRI seamlessly spins up the next key with zero downtime.
|
|
938
|
+
</p>
|
|
939
|
+
<div style="margin-bottom:12px;">
|
|
940
|
+
<label style="display:block;font-size:12px;font-weight:600;margin-bottom:6px;">Select Provider</label>
|
|
941
|
+
<select id="settings-key-provider" class="modal-input" onchange="onSettingsProviderChange()">
|
|
942
|
+
<option value="gemini">Google Gemini (Recommended)</option>
|
|
943
|
+
<option value="openai">OpenAI</option>
|
|
944
|
+
<option value="anthropic">Anthropic</option>
|
|
945
|
+
<option value="cerebras">Cerebras</option>
|
|
946
|
+
<option value="cohere">Cohere</option>
|
|
947
|
+
<option value="deepseek">DeepSeek</option>
|
|
948
|
+
<option value="nvidia_nim">NVIDIA NIM</option>
|
|
949
|
+
</select>
|
|
950
|
+
</div>
|
|
951
|
+
<div style="margin-bottom:12px;">
|
|
952
|
+
<label style="display:block;font-size:12px;font-weight:600;margin-bottom:6px;">API Key Pool (Paste 1-4 keys, comma or newline separated)</label>
|
|
953
|
+
<textarea id="settings-keys-textarea" class="modal-input" rows="3" placeholder="AIzaSyKey1..., AIzaSyKey2..., AIzaSyKey3..."></textarea>
|
|
954
|
+
</div>
|
|
955
|
+
<div style="display:flex;gap:8px;">
|
|
956
|
+
<button class="action-btn" onclick="saveApiKeyPool()" style="flex:1;">💾 Save Key Pool</button>
|
|
957
|
+
<button class="action-btn-secondary" onclick="rotateKeyPoolManually()">🔄 Rotate Key</button>
|
|
958
|
+
</div>
|
|
959
|
+
</div>
|
|
960
|
+
</div>
|
|
961
|
+
</section>
|
|
962
|
+
|
|
893
963
|
</main>
|
|
894
964
|
</div>
|
|
895
965
|
|
|
@@ -929,10 +999,15 @@
|
|
|
929
999
|
<label style="display:block;font-size:12px;font-weight:600;margin-bottom:6px;">Email Address</label>
|
|
930
1000
|
<input type="email" id="modal-email-input" class="modal-input" placeholder="user@gmail.com" />
|
|
931
1001
|
</div>
|
|
932
|
-
<div style="margin-bottom:
|
|
1002
|
+
<div style="margin-bottom:12px;">
|
|
933
1003
|
<label style="display:block;font-size:12px;font-weight:600;margin-bottom:6px;">Password</label>
|
|
934
1004
|
<input type="password" id="modal-pass-input" class="modal-input" placeholder="••••••••" />
|
|
935
1005
|
</div>
|
|
1006
|
+
<div style="margin-bottom:16px;">
|
|
1007
|
+
<label style="display:block;font-size:12px;font-weight:600;margin-bottom:6px;">Google Cloud Run Backend URL (Optional)</label>
|
|
1008
|
+
<input type="text" id="modal-backend-url-input" class="modal-input" placeholder="https://antri-backend-xxxxx-uc.a.run.app" />
|
|
1009
|
+
<span style="font-size:11px;color:var(--text-muted);display:block;margin-top:4px;">When set, automatically auto-configures API & LLM models via your Cloud Run container.</span>
|
|
1010
|
+
</div>
|
|
936
1011
|
<button class="action-btn" style="width:100%;margin-bottom:8px;" onclick="submitDesktopLogin()">Sign In / Register</button>
|
|
937
1012
|
</div>
|
|
938
1013
|
<div id="auth-logged-view" style="display:none;text-align:center;padding:12px 0;">
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/desktop/server.ts"],"names":[],"mappings":"AAuCA;;;GAGG;AACH,qBAAa,uBAAuB;IAClC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAiD;IAC1E,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAiD;WAEpE,cAAc,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,IAAI,GAAG,MAAM,IAAI;WAOtE,gBAAgB,IAAI,OAAO;WAI3B,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAE,KAAK,GAAG,SAAiB,GAAG,OAAO,CAAC,OAAO,CAAC;WAyB/G,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,OAAO,GAAG,OAAO;CAiBrG;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,IAAI,CAA4C;IACxD,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,gBAAgB,CAAqD;;IAO7E,OAAO,CAAC,sBAAsB;IAUjB,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAkGxB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAUpB,SAAS;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/desktop/server.ts"],"names":[],"mappings":"AAuCA;;;GAGG;AACH,qBAAa,uBAAuB;IAClC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAiD;IAC1E,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAiD;WAEpE,cAAc,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,IAAI,GAAG,MAAM,IAAI;WAOtE,gBAAgB,IAAI,OAAO;WAI3B,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAE,KAAK,GAAG,SAAiB,GAAG,OAAO,CAAC,OAAO,CAAC;WAyB/G,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,OAAO,GAAG,OAAO;CAiBrG;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,IAAI,CAA4C;IACxD,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,gBAAgB,CAAqD;;IAO7E,OAAO,CAAC,sBAAsB;IAUjB,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAkGxB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAUpB,SAAS;WAu8BH,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;CAyBnD"}
|
package/dist/desktop/server.js
CHANGED
|
@@ -990,6 +990,79 @@ export class DesktopServer {
|
|
|
990
990
|
res.end(JSON.stringify({ output: result }));
|
|
991
991
|
return;
|
|
992
992
|
}
|
|
993
|
+
// POST /api/config/backend (Configure Cloud Run endpoint and auto-configure)
|
|
994
|
+
if (pathname === '/api/config/backend' && req.method === 'POST') {
|
|
995
|
+
const url = (payload.url || '').trim();
|
|
996
|
+
configManager.setBackendUrl(url);
|
|
997
|
+
this.activeAgent.updateConfig(configManager.get());
|
|
998
|
+
let healthData = null;
|
|
999
|
+
let healthOk = false;
|
|
1000
|
+
if (url) {
|
|
1001
|
+
try {
|
|
1002
|
+
const resp = await fetch(`${url.replace(/\/$/, '')}/api/health`);
|
|
1003
|
+
if (resp.ok) {
|
|
1004
|
+
healthData = await resp.json();
|
|
1005
|
+
healthOk = true;
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
catch (_) { }
|
|
1009
|
+
}
|
|
1010
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
1011
|
+
res.end(JSON.stringify({ success: true, backendUrl: url, healthOk, health: healthData }));
|
|
1012
|
+
return;
|
|
1013
|
+
}
|
|
1014
|
+
// POST /api/config/keys (Save Multi-Key API Key Pool with auto-rotation)
|
|
1015
|
+
if (pathname === '/api/config/keys' && req.method === 'POST') {
|
|
1016
|
+
const provider = payload.provider || config.provider;
|
|
1017
|
+
const rawKeys = payload.keys || '';
|
|
1018
|
+
configManager.setApiKey(provider, rawKeys);
|
|
1019
|
+
this.activeAgent.updateConfig(configManager.get());
|
|
1020
|
+
const keysList = configManager.getApiKeysList(provider);
|
|
1021
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
1022
|
+
res.end(JSON.stringify({ success: true, provider, keysCount: keysList.length, activeKey: keysList[0] || '' }));
|
|
1023
|
+
return;
|
|
1024
|
+
}
|
|
1025
|
+
// POST /api/config/key-rotate (Rotate to next key in pool)
|
|
1026
|
+
if (pathname === '/api/config/key-rotate' && req.method === 'POST') {
|
|
1027
|
+
const provider = payload.provider || config.provider;
|
|
1028
|
+
const nextKey = configManager.rotateApiKey(provider);
|
|
1029
|
+
this.activeAgent.updateConfig(configManager.get());
|
|
1030
|
+
const keysList = configManager.getApiKeysList(provider);
|
|
1031
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
1032
|
+
res.end(JSON.stringify({ success: true, provider, activeKey: nextKey, totalKeys: keysList.length }));
|
|
1033
|
+
return;
|
|
1034
|
+
}
|
|
1035
|
+
// POST /api/auth/login (Desktop Login & optional Cloud Run auto-config)
|
|
1036
|
+
if (pathname === '/api/auth/login' && req.method === 'POST') {
|
|
1037
|
+
const { AuthManager } = await import('../cloud/auth.js');
|
|
1038
|
+
const email = payload.email || '';
|
|
1039
|
+
const password = payload.password || 'password123';
|
|
1040
|
+
const backendUrl = (payload.backendUrl || '').trim();
|
|
1041
|
+
if (backendUrl) {
|
|
1042
|
+
configManager.setBackendUrl(backendUrl);
|
|
1043
|
+
}
|
|
1044
|
+
let authRes = await AuthManager.login(email, password);
|
|
1045
|
+
if (!authRes.success) {
|
|
1046
|
+
authRes = await AuthManager.register(email, password);
|
|
1047
|
+
}
|
|
1048
|
+
if (authRes.success) {
|
|
1049
|
+
configManager.reloadForUser();
|
|
1050
|
+
this.activeAgent.updateConfig(configManager.get());
|
|
1051
|
+
}
|
|
1052
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
1053
|
+
res.end(JSON.stringify(authRes));
|
|
1054
|
+
return;
|
|
1055
|
+
}
|
|
1056
|
+
// POST /api/auth/logout (Desktop Logout)
|
|
1057
|
+
if (pathname === '/api/auth/logout' && req.method === 'POST') {
|
|
1058
|
+
const { AuthManager } = await import('../cloud/auth.js');
|
|
1059
|
+
AuthManager.logout();
|
|
1060
|
+
configManager.reloadForUser('default_user');
|
|
1061
|
+
this.activeAgent.updateConfig(configManager.get());
|
|
1062
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
1063
|
+
res.end(JSON.stringify({ success: true }));
|
|
1064
|
+
return;
|
|
1065
|
+
}
|
|
993
1066
|
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
994
1067
|
res.end(JSON.stringify({ error: 'Endpoint not found' }));
|
|
995
1068
|
}
|