antigravity-proxy 0.1.1

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.
Files changed (46) hide show
  1. package/.dockerignore +10 -0
  2. package/.env.example +2 -0
  3. package/Dockerfile +20 -0
  4. package/README.md +132 -0
  5. package/bun.lock +51 -0
  6. package/docker-compose.yml +11 -0
  7. package/package.json +22 -0
  8. package/reset-accounts.ts +17 -0
  9. package/screenshots/screenshot.png +0 -0
  10. package/src/api/quota.ts +187 -0
  11. package/src/auth/manager.ts +326 -0
  12. package/src/auth/oauth.ts +95 -0
  13. package/src/auth/storage.ts +39 -0
  14. package/src/auth/types.ts +73 -0
  15. package/src/config/manager.ts +141 -0
  16. package/src/config/types.ts +73 -0
  17. package/src/frontend/components/config-modal.html +109 -0
  18. package/src/frontend/components/header.html +55 -0
  19. package/src/frontend/components/main.html +64 -0
  20. package/src/frontend/css/styles.css +53 -0
  21. package/src/frontend/index.html +48 -0
  22. package/src/frontend/js/app.js +883 -0
  23. package/src/frontend/js/tailwind-config.js +40 -0
  24. package/src/scripts/check_quota_api.ts +70 -0
  25. package/src/scripts/check_sandbox_quota.ts +42 -0
  26. package/src/scripts/debug-accounts.ts +25 -0
  27. package/src/scripts/debug-quota-raw.ts +47 -0
  28. package/src/scripts/diagnose_claude_quota.ts +97 -0
  29. package/src/scripts/reset-accounts.ts +24 -0
  30. package/src/scripts/test-claude-cli.ts +55 -0
  31. package/src/scripts/test-request.ts +138 -0
  32. package/src/scripts/test-routing-logic.ts +40 -0
  33. package/src/scripts/test_claude_forced.ts +53 -0
  34. package/src/scripts/test_placeholder_model.ts +85 -0
  35. package/src/scripts/verify-claude.ts +51 -0
  36. package/src/server.ts +679 -0
  37. package/src/utils/cache.ts +18 -0
  38. package/src/utils/errors.ts +93 -0
  39. package/src/utils/headers.ts +172 -0
  40. package/src/utils/schema.ts +100 -0
  41. package/src/utils/transform.ts +532 -0
  42. package/tests/functional/gemini-functional.test.ts +122 -0
  43. package/tests/functional/models.test.ts +100 -0
  44. package/tests/unit/manager.test.ts +13 -0
  45. package/tests/unit/transform.test.ts +135 -0
  46. package/tsconfig.json +20 -0
@@ -0,0 +1,73 @@
1
+ export interface ProxyConfig {
2
+ rotation: RotationConfig;
3
+ scoring: ScoringConfig;
4
+ models: ModelsConfig;
5
+ retry: RetryConfig;
6
+ tokens: TokensConfig;
7
+ quota: QuotaConfig;
8
+ endpoints: EndpointsConfig;
9
+ logging: LoggingConfig;
10
+ }
11
+
12
+ export interface RotationConfig {
13
+ strategy: 'hybrid' | 'sticky' | 'round-robin' | 'random' | 'least-used';
14
+ cooldown: {
15
+ defaultDurationMs: number;
16
+ maxDurationMs: number;
17
+ };
18
+ }
19
+
20
+ export interface ScoringConfig {
21
+ healthRange: {
22
+ min: number;
23
+ max: number;
24
+ initial: number;
25
+ };
26
+ penalties: {
27
+ apiError: number;
28
+ refreshError: number;
29
+ fatalError: number;
30
+ systemicError: number;
31
+ };
32
+ rewards: {
33
+ success: number;
34
+ };
35
+ weights: {
36
+ health: number;
37
+ lru: number;
38
+ };
39
+ }
40
+
41
+ export interface ModelsConfig {
42
+ blacklist: string[];
43
+ routing: {
44
+ sandboxKeywords: string[];
45
+ cliKeywords: string[];
46
+ forceToSandbox: string[];
47
+ };
48
+ timeouts: Record<string, number>;
49
+ }
50
+
51
+ export interface RetryConfig {
52
+ maxAttempts: number;
53
+ transientRetryThresholdSeconds: number;
54
+ }
55
+
56
+ export interface TokensConfig {
57
+ expiryBufferMs: number;
58
+ }
59
+
60
+ export interface QuotaConfig {
61
+ refreshIntervalMs: number;
62
+ initialDelayMs: number;
63
+ }
64
+
65
+ export interface EndpointsConfig {
66
+ sandbox: string[];
67
+ cli: string | string[];
68
+ }
69
+
70
+ export interface LoggingConfig {
71
+ maxBufferSize: number;
72
+ enableConsoleCapture: boolean;
73
+ }
@@ -0,0 +1,109 @@
1
+ <div id="config-modal" class="hidden fixed inset-0 bg-black/50 dark:bg-black/80 backdrop-blur-sm z-50 flex items-center justify-center p-4 transition-colors">
2
+ <div class="bg-white dark:bg-[#050505] rounded shadow-2xl max-w-4xl w-full max-h-[90vh] overflow-y-auto border border-zinc-200 dark:border-zinc-800 transition-colors">
3
+ <div class="sticky top-0 bg-white dark:bg-[#050505] border-b border-zinc-200 dark:border-zinc-800 px-6 py-4 flex items-center justify-between z-10 transition-colors">
4
+ <h2 class="text-lg font-bold text-zinc-900 dark:text-white uppercase tracking-wider transition-colors">Configuration</h2>
5
+ <button onclick="closeConfigModal()" class="text-zinc-500 hover:text-zinc-900 dark:hover:text-white transition-colors">
6
+ <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/></svg>
7
+ </button>
8
+ </div>
9
+
10
+ <div class="p-6 space-y-8 font-mono">
11
+ <div>
12
+ <h3 class="text-xs font-bold text-zinc-500 dark:text-zinc-400 uppercase tracking-widest mb-4 flex items-center gap-2 transition-colors">
13
+ <svg class="w-4 h-4 text-zinc-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"/></svg>
14
+ Rotation Strategy
15
+ </h3>
16
+ <div class="grid grid-cols-2 gap-4">
17
+ <div>
18
+ <label class="block text-[10px] text-zinc-500 mb-1.5 uppercase tracking-wide">Cooldown Default (ms)</label>
19
+ <input type="number" id="cfg-cooldown-default" class="w-full px-3 py-2 text-sm border border-zinc-200 dark:border-zinc-800 rounded bg-zinc-50 dark:bg-zinc-900/50 text-zinc-900 dark:text-white focus:border-zinc-400 dark:focus:border-zinc-600 focus:outline-none transition-colors" />
20
+ </div>
21
+ <div>
22
+ <label class="block text-[10px] text-zinc-500 mb-1.5 uppercase tracking-wide">Cooldown Max (ms)</label>
23
+ <input type="number" id="cfg-cooldown-max" class="w-full px-3 py-2 text-sm border border-zinc-200 dark:border-zinc-800 rounded bg-zinc-50 dark:bg-zinc-900/50 text-zinc-900 dark:text-white focus:border-zinc-400 dark:focus:border-zinc-600 focus:outline-none transition-colors" />
24
+ </div>
25
+ </div>
26
+ </div>
27
+
28
+ <div>
29
+ <h3 class="text-xs font-bold text-zinc-500 dark:text-zinc-400 uppercase tracking-widest mb-4 flex items-center gap-2 transition-colors">
30
+ <svg class="w-4 h-4 text-emerald-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"/></svg>
31
+ Health Scoring
32
+ </h3>
33
+ <div class="grid grid-cols-3 gap-4 mb-4">
34
+ <div>
35
+ <label class="block text-[10px] text-zinc-500 mb-1.5 uppercase tracking-wide">Min Health</label>
36
+ <input type="number" id="cfg-health-min" class="w-full px-3 py-2 text-sm border border-zinc-200 dark:border-zinc-800 rounded bg-zinc-50 dark:bg-zinc-900/50 text-zinc-900 dark:text-white focus:border-zinc-400 dark:focus:border-zinc-600 focus:outline-none transition-colors" />
37
+ </div>
38
+ <div>
39
+ <label class="block text-[10px] text-zinc-500 mb-1.5 uppercase tracking-wide">Max Health</label>
40
+ <input type="number" id="cfg-health-max" class="w-full px-3 py-2 text-sm border border-zinc-200 dark:border-zinc-800 rounded bg-zinc-50 dark:bg-zinc-900/50 text-zinc-900 dark:text-white focus:border-zinc-400 dark:focus:border-zinc-600 focus:outline-none transition-colors" />
41
+ </div>
42
+ <div>
43
+ <label class="block text-[10px] text-zinc-500 mb-1.5 uppercase tracking-wide">Initial Health</label>
44
+ <input type="number" id="cfg-health-initial" class="w-full px-3 py-2 text-sm border border-zinc-200 dark:border-zinc-800 rounded bg-zinc-50 dark:bg-zinc-900/50 text-zinc-900 dark:text-white focus:border-zinc-400 dark:focus:border-zinc-600 focus:outline-none transition-colors" />
45
+ </div>
46
+ </div>
47
+ <div class="grid grid-cols-2 gap-4 mb-4">
48
+ <div>
49
+ <label class="block text-[10px] text-zinc-500 mb-1.5 uppercase tracking-wide">API Error Penalty</label>
50
+ <input type="number" id="cfg-penalty-api" class="w-full px-3 py-2 text-sm border border-zinc-200 dark:border-zinc-800 rounded bg-zinc-50 dark:bg-zinc-900/50 text-zinc-900 dark:text-white focus:border-zinc-400 dark:focus:border-zinc-600 focus:outline-none transition-colors" />
51
+ </div>
52
+ <div>
53
+ <label class="block text-[10px] text-zinc-500 mb-1.5 uppercase tracking-wide">Refresh Error Penalty</label>
54
+ <input type="number" id="cfg-penalty-refresh" class="w-full px-3 py-2 text-sm border border-zinc-200 dark:border-zinc-800 rounded bg-zinc-50 dark:bg-zinc-900/50 text-zinc-900 dark:text-white focus:border-zinc-400 dark:focus:border-zinc-600 focus:outline-none transition-colors" />
55
+ </div>
56
+ </div>
57
+ <div class="grid grid-cols-3 gap-4">
58
+ <div>
59
+ <label class="block text-[10px] text-zinc-500 mb-1.5 uppercase tracking-wide">Success Reward</label>
60
+ <input type="number" id="cfg-reward-success" class="w-full px-3 py-2 text-sm border border-zinc-200 dark:border-zinc-800 rounded bg-zinc-50 dark:bg-zinc-900/50 text-zinc-900 dark:text-white focus:border-zinc-400 dark:focus:border-zinc-600 focus:outline-none transition-colors" />
61
+ </div>
62
+ <div>
63
+ <label class="block text-[10px] text-zinc-500 mb-1.5 uppercase tracking-wide">Health Weight</label>
64
+ <input type="number" step="0.1" id="cfg-weight-health" class="w-full px-3 py-2 text-sm border border-zinc-200 dark:border-zinc-800 rounded bg-zinc-50 dark:bg-zinc-900/50 text-zinc-900 dark:text-white focus:border-zinc-400 dark:focus:border-zinc-600 focus:outline-none transition-colors" />
65
+ </div>
66
+ <div>
67
+ <label class="block text-[10px] text-zinc-500 mb-1.5 uppercase tracking-wide">LRU Weight</label>
68
+ <input type="number" step="0.01" id="cfg-weight-lru" class="w-full px-3 py-2 text-sm border border-zinc-200 dark:border-zinc-800 rounded bg-zinc-50 dark:bg-zinc-900/50 text-zinc-900 dark:text-white focus:border-zinc-400 dark:focus:border-zinc-600 focus:outline-none transition-colors" />
69
+ </div>
70
+ </div>
71
+ </div>
72
+
73
+ <div>
74
+ <h3 class="text-xs font-bold text-zinc-500 dark:text-zinc-400 uppercase tracking-widest mb-4 flex items-center gap-2 transition-colors">
75
+ <svg class="w-4 h-4 text-rose-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M18.364 18.364A9 9 0 005.636 5.636m12.728 12.728A9 9 0 015.636 5.636m12.728 12.728L5.636 5.636"/></svg>
76
+ Model Blacklist
77
+ </h3>
78
+ <textarea id="cfg-blacklist" rows="3" class="w-full px-3 py-2 text-sm border border-zinc-200 dark:border-zinc-800 rounded bg-zinc-50 dark:bg-zinc-900/50 text-zinc-900 dark:text-white focus:border-zinc-400 dark:focus:border-zinc-600 focus:outline-none transition-colors font-mono" placeholder="One model per line"></textarea>
79
+ <p class="text-[10px] text-zinc-600 dark:text-zinc-600 mt-1 uppercase tracking-wide">Enter model names to block, one per line</p>
80
+ </div>
81
+
82
+ <div>
83
+ <h3 class="text-xs font-bold text-zinc-500 dark:text-zinc-400 uppercase tracking-widest mb-4 flex items-center gap-2 transition-colors">
84
+ <svg class="w-4 h-4 text-amber-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"/></svg>
85
+ Retry Configuration
86
+ </h3>
87
+ <div class="grid grid-cols-2 gap-4">
88
+ <div>
89
+ <label class="block text-[10px] text-zinc-500 mb-1.5 uppercase tracking-wide">Max Attempts</label>
90
+ <input type="number" id="cfg-retry-max" class="w-full px-3 py-2 text-sm border border-zinc-200 dark:border-zinc-800 rounded bg-zinc-50 dark:bg-zinc-900/50 text-zinc-900 dark:text-white focus:border-zinc-400 dark:focus:border-zinc-600 focus:outline-none transition-colors" />
91
+ </div>
92
+ <div>
93
+ <label class="block text-[10px] text-zinc-500 mb-1.5 uppercase tracking-wide">Transient Retry Threshold (s)</label>
94
+ <input type="number" id="cfg-retry-threshold" class="w-full px-3 py-2 text-sm border border-zinc-200 dark:border-zinc-800 rounded bg-zinc-50 dark:bg-zinc-900/50 text-zinc-900 dark:text-white focus:border-zinc-400 dark:focus:border-zinc-600 focus:outline-none transition-colors" />
95
+ </div>
96
+ </div>
97
+ </div>
98
+ </div>
99
+
100
+ <div class="sticky bottom-0 bg-white dark:bg-[#050505] border-t border-zinc-200 dark:border-zinc-800 px-6 py-4 flex justify-end gap-3 z-10 transition-colors">
101
+ <button onclick="closeConfigModal()" class="px-4 py-2 text-xs font-bold text-zinc-500 dark:text-zinc-400 hover:text-zinc-900 dark:hover:text-white uppercase tracking-wider transition-colors">
102
+ Cancel
103
+ </button>
104
+ <button onclick="saveConfig()" class="px-4 py-2 text-xs font-bold text-white dark:text-black bg-zinc-900 dark:bg-white hover:bg-zinc-700 dark:hover:bg-zinc-200 rounded transition-colors uppercase tracking-wider">
105
+ Save Changes
106
+ </button>
107
+ </div>
108
+ </div>
109
+ </div>
@@ -0,0 +1,55 @@
1
+ <header class="sticky top-0 z-50 bg-white dark:bg-black h-14 shrink-0 border-b border-zinc-200 dark:border-zinc-800 transition-colors">
2
+ <div class="h-full px-4 sm:px-6 flex items-center justify-between">
3
+ <div class="flex items-center gap-4">
4
+ <div class="flex items-center justify-center w-8 h-8 rounded border border-zinc-200 dark:border-zinc-800 bg-zinc-50 dark:bg-zinc-900 text-zinc-900 dark:text-white font-bold text-lg transition-colors">
5
+ A
6
+ </div>
7
+ <div class="hidden sm:block">
8
+ <h1 class="font-bold text-sm tracking-tight text-zinc-900 dark:text-white transition-colors">Antigravity Proxy</h1>
9
+ </div>
10
+ <div class="hidden sm:flex items-center px-2 py-0.5 rounded text-[10px] font-medium bg-zinc-50 dark:bg-zinc-900 text-zinc-500 dark:text-zinc-400 border border-zinc-200 dark:border-zinc-800 transition-colors">
11
+ v0.1.0
12
+ </div>
13
+ </div>
14
+
15
+ <div class="flex items-center gap-2 sm:gap-6">
16
+ <div class="hidden md:flex items-center gap-3 px-3 py-1.5">
17
+ <span class="relative flex h-2 w-2">
18
+ <span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75"></span>
19
+ <span class="relative inline-flex rounded-full h-2 w-2 bg-emerald-500"></span>
20
+ </span>
21
+ <span class="text-xs font-medium text-zinc-500 dark:text-zinc-400 transition-colors"><span id="stat-total-accounts" class="text-zinc-900 dark:text-white transition-colors">0</span> <span class="text-zinc-400 dark:text-zinc-500 transition-colors">active</span></span>
22
+ </div>
23
+
24
+ <div class="h-4 w-px bg-zinc-200 dark:bg-zinc-800 hidden sm:block transition-colors"></div>
25
+
26
+ <div class="relative group">
27
+ <select id="strategy-selector" onchange="updateStrategy()" class="appearance-none bg-transparent hover:text-zinc-900 dark:hover:text-white text-xs font-medium pr-6 outline-none transition-colors cursor-pointer text-zinc-500 dark:text-zinc-400 focus:text-zinc-900 dark:focus:text-white">
28
+ <option value="hybrid" class="bg-white dark:bg-zinc-900 text-zinc-700 dark:text-zinc-300">STRATEGY: HYBRID</option>
29
+ <option value="sticky" class="bg-white dark:bg-zinc-900 text-zinc-700 dark:text-zinc-300">STRATEGY: STICKY</option>
30
+ <option value="round-robin" class="bg-white dark:bg-zinc-900 text-zinc-700 dark:text-zinc-300">STRATEGY: ROUND ROBIN</option>
31
+ <option value="random" class="bg-white dark:bg-zinc-900 text-zinc-700 dark:text-zinc-300">STRATEGY: RANDOM</option>
32
+ <option value="least-used" class="bg-white dark:bg-zinc-900 text-zinc-700 dark:text-zinc-300">STRATEGY: LEAST USED</option>
33
+ </select>
34
+ <svg class="w-3 h-3 absolute right-0 top-1/2 -translate-y-1/2 text-zinc-400 dark:text-zinc-600 pointer-events-none group-hover:text-zinc-600 dark:group-hover:text-zinc-400 transition-colors" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
35
+ </div>
36
+
37
+ <div class="flex items-center gap-2">
38
+ <button onclick="cycleTheme()" class="p-1.5 rounded text-zinc-500 hover:text-zinc-900 dark:hover:text-white transition-colors relative w-7 h-7 flex items-center justify-center" title="Toggle Theme">
39
+ <svg id="icon-sun" class="w-4 h-4 hidden absolute" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"></path></svg>
40
+ <svg id="icon-moon" class="w-4 h-4 hidden absolute" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"></path></svg>
41
+ <svg id="icon-system" class="w-4 h-4 hidden absolute" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"></path></svg>
42
+ </button>
43
+
44
+ <button onclick="openConfigModal()" class="p-1.5 rounded text-zinc-500 hover:text-zinc-900 dark:hover:text-white transition-colors" title="Settings">
45
+ <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/></svg>
46
+ </button>
47
+
48
+ <a href="/oauth/start" class="ml-2 hidden sm:inline-flex items-center px-3 py-1.5 border border-zinc-200 dark:border-zinc-800 text-xs font-medium rounded text-zinc-600 dark:text-zinc-300 bg-zinc-50 dark:bg-zinc-900 hover:bg-white dark:hover:bg-zinc-800 hover:text-zinc-900 dark:hover:text-white transition-all">
49
+ <svg class="w-3.5 h-3.5 mr-2 text-emerald-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"/></svg>
50
+ ADD ACCOUNT
51
+ </a>
52
+ </div>
53
+ </div>
54
+ </div>
55
+ </header>
@@ -0,0 +1,64 @@
1
+ <div class="shrink-0 p-4 border-b border-zinc-200 dark:border-zinc-800 bg-white dark:bg-black z-10 transition-colors">
2
+ <div class="max-w-7xl mx-auto mb-3 flex items-center justify-end">
3
+ <button onclick="toggleAllFamilies()" class="group flex items-center gap-2 px-2 py-1 bg-transparent hover:text-zinc-900 dark:hover:text-white rounded text-[10px] font-medium text-zinc-500 transition-all uppercase tracking-wide" id="btn-toggle-all">
4
+ <svg class="w-3 h-3 text-emerald-500 group-hover:scale-110 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16m-7 6h7"/></svg>
5
+ <span>Expand Metrics</span>
6
+ </button>
7
+ </div>
8
+ <div class="grid grid-cols-2 lg:grid-cols-4 gap-4 max-w-7xl mx-auto" id="family-grid">
9
+ <div class="col-span-full h-24 flex items-center justify-center text-xs text-zinc-500 dark:text-zinc-600 border border-dashed border-zinc-300 dark:border-zinc-800 rounded bg-zinc-50 dark:bg-zinc-900/20 transition-colors">
10
+ // Scanning for model families...
11
+ </div>
12
+ </div>
13
+ </div>
14
+
15
+ <div class="flex-grow overflow-y-auto bg-zinc-50 dark:bg-black scrollbar-hide transition-colors">
16
+ <div class="max-w-7xl mx-auto p-4 sm:p-6">
17
+ <div class="flex items-center justify-between mb-6 border-b border-zinc-200 dark:border-zinc-800 pb-2 transition-colors">
18
+ <div class="flex items-center gap-4">
19
+ <h2 class="text-sm font-bold text-zinc-900 dark:text-white uppercase tracking-wider transition-colors">Active Accounts <span class="text-zinc-500 dark:text-zinc-600 text-xs normal-case ml-2 font-normal transition-colors">// Details</span></h2>
20
+ </div>
21
+ <div class="flex items-center gap-4">
22
+ <button onclick="resetAllAccounts()" class="opacity-0 hover:opacity-100 group-hover:opacity-100 transition-opacity inline-flex items-center text-[10px] font-bold text-rose-500 hover:text-rose-600 dark:hover:text-rose-400 uppercase tracking-widest" title="System Reset">
23
+ <svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"/></svg>
24
+ Flush
25
+ </button>
26
+ <div class="flex items-center gap-2">
27
+ <div class="w-1.5 h-1.5 rounded-full bg-emerald-500 animate-pulse"></div>
28
+ <span class="text-[10px] text-zinc-500 font-medium" id="last-updated">--:--:--</span>
29
+ </div>
30
+ </div>
31
+ </div>
32
+
33
+ <div class="border border-zinc-200 dark:border-zinc-800 rounded bg-white dark:bg-[#0a0a0a] transition-colors shadow-sm dark:shadow-none">
34
+ <table class="w-full text-left border-collapse">
35
+ <thead class="bg-zinc-50 dark:bg-zinc-900/50 border-b border-zinc-200 dark:border-zinc-800 transition-colors">
36
+ <tr>
37
+ <th class="px-4 py-3 text-[10px] font-medium text-zinc-500 uppercase tracking-wider w-1/2">Identity</th>
38
+ <th class="px-4 py-3 text-[10px] font-medium text-zinc-500 uppercase tracking-wider w-1/4">Health</th>
39
+ <th class="px-4 py-3 text-[10px] font-medium text-zinc-500 uppercase tracking-wider w-1/4">Last Active</th>
40
+ <th class="px-4 py-3 text-[10px] font-medium text-zinc-500 uppercase tracking-wider text-right">Action</th>
41
+ </tr>
42
+ </thead>
43
+ <tbody id="accounts-table-body" class="divide-y divide-zinc-200 dark:divide-zinc-800 text-sm transition-colors">
44
+ </tbody>
45
+ </table>
46
+ </div>
47
+ </div>
48
+ </div>
49
+
50
+ <div class="shrink-0 bg-white dark:bg-[#050505] border-t border-zinc-200 dark:border-zinc-800 h-48 sm:h-64 flex flex-col transition-[height,colors] duration-200 relative group" id="logs-panel">
51
+ <div id="logs-resizer" class="absolute top-[-3px] left-0 right-0 h-[6px] cursor-ns-resize hover:bg-emerald-500/50 transition-colors z-50"></div>
52
+ <div class="flex items-center justify-between px-4 py-2 bg-zinc-50 dark:bg-zinc-900/30 border-b border-zinc-200 dark:border-zinc-800 shrink-0 select-none transition-colors">
53
+ <div class="flex items-center gap-2">
54
+ <svg class="w-3.5 h-3.5 text-emerald-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/></svg>
55
+ <h3 class="text-[10px] font-bold text-zinc-500 uppercase tracking-widest">Console Output</h3>
56
+ </div>
57
+ <button onclick="toggleLogs()" class="text-zinc-500 dark:text-zinc-600 hover:text-zinc-900 dark:hover:text-zinc-300 p-1 rounded hover:bg-zinc-100 dark:hover:bg-zinc-800 transition-colors">
58
+ <svg id="logs-chevron" class="w-3.5 h-3.5 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg>
59
+ </button>
60
+ </div>
61
+ <div id="logs-content" class="flex-grow overflow-y-auto p-4 font-mono text-[11px] leading-relaxed text-zinc-600 dark:text-zinc-400 space-y-1 selection:bg-emerald-500/30 selection:text-emerald-900 dark:selection:text-white transition-colors">
62
+ <div class="text-zinc-400 dark:text-zinc-600 italic">// Initializing console connection...</div>
63
+ </div>
64
+ </div>
@@ -0,0 +1,53 @@
1
+ ::-webkit-scrollbar {
2
+ width: 6px;
3
+ height: 6px;
4
+ }
5
+
6
+ ::-webkit-scrollbar-track {
7
+ background: transparent;
8
+ }
9
+
10
+ ::-webkit-scrollbar-thumb {
11
+ background: #27272a;
12
+ border-radius: 0;
13
+ }
14
+
15
+ ::-webkit-scrollbar-thumb:hover {
16
+ background: #3f3f46;
17
+ }
18
+
19
+ .scrollbar-hide::-webkit-scrollbar {
20
+ display: none;
21
+ }
22
+
23
+ .scrollbar-hide {
24
+ -ms-overflow-style: none;
25
+ scrollbar-width: none;
26
+ }
27
+
28
+ .font-mono-dense {
29
+ font-family: 'JetBrains Mono', monospace;
30
+ letter-spacing: -0.02em;
31
+ }
32
+
33
+ tr.flash-active td {
34
+ animation: flashRow 1s ease-out;
35
+ }
36
+
37
+ tr.flash-error td {
38
+ animation: flashRowError 1s ease-out;
39
+ }
40
+
41
+ @keyframes flashRow {
42
+ 0% { background-color: rgba(16, 185, 129, 0.1); }
43
+ 100% { background-color: transparent; }
44
+ }
45
+
46
+ @keyframes flashRowError {
47
+ 0% { background-color: rgba(244, 63, 94, 0.1); }
48
+ 100% { background-color: transparent; }
49
+ }
50
+
51
+ tr td {
52
+ position: relative;
53
+ }
@@ -0,0 +1,48 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en" class="h-full antialiased">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Antigravity Console</title>
7
+
8
+ <link rel="preconnect" href="https://fonts.googleapis.com">
9
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10
+ <link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet">
11
+
12
+ <script src="https://cdn.tailwindcss.com"></script>
13
+ <script src="js/tailwind-config.js"></script>
14
+ <link rel="stylesheet" href="css/styles.css">
15
+ </head>
16
+ <body class="bg-zinc-50 dark:bg-black text-zinc-900 dark:text-zinc-200 h-full flex flex-col transition-colors duration-300 overflow-hidden font-mono selection:bg-emerald-500/30 selection:text-emerald-700 dark:selection:text-emerald-200">
17
+
18
+ <div id="header-container"></div>
19
+ <main id="main-container" class="flex-grow flex flex-col h-[calc(100vh-4rem)] overflow-hidden"></main>
20
+ <div id="modal-container"></div>
21
+
22
+ <script src="js/app.js"></script>
23
+ <script>
24
+ async function loadComponent(id, url) {
25
+ try {
26
+ const res = await fetch(url);
27
+ if (!res.ok) throw new Error(`Failed to load ${url}`);
28
+ document.getElementById(id).innerHTML = await res.text();
29
+ } catch (e) {
30
+ console.error(e);
31
+ document.getElementById(id).innerHTML = `<div class="p-4 text-rose-500">Error loading component: ${e.message}</div>`;
32
+ }
33
+ }
34
+
35
+ (async () => {
36
+ await Promise.all([
37
+ loadComponent('header-container', 'components/header.html'),
38
+ loadComponent('main-container', 'components/main.html'),
39
+ loadComponent('modal-container', 'components/config-modal.html')
40
+ ]);
41
+
42
+ if (window.initializeApp) {
43
+ window.initializeApp();
44
+ }
45
+ })();
46
+ </script>
47
+ </body>
48
+ </html>