antigravity-claude-proxy 3.0.0 → 3.1.0
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/bin/cli.js +4 -11
- package/package.json +1 -1
- package/public/app.js +7 -4
- package/public/css/src/input.css +379 -216
- package/public/css/style.css +1 -1
- package/public/favicon.svg +4 -8
- package/public/index.html +78 -72
- package/public/js/components/claude-config.js +0 -8
- package/public/js/components/dashboard/charts.js +25 -51
- package/public/js/components/dashboard/stats.js +1 -1
- package/public/js/components/dashboard.js +16 -21
- package/public/js/components/logs-viewer.js +1 -1
- package/public/js/components/models.js +12 -12
- package/public/js/components/server-config.js +1 -9
- package/public/js/data-store.js +2 -2
- package/public/js/store.js +1 -1
- package/public/js/translations/en.js +37 -39
- package/public/js/translations/id.js +36 -37
- package/public/js/translations/pt.js +37 -38
- package/public/js/translations/tr.js +37 -39
- package/public/js/translations/zh.js +0 -2
- package/public/js/utils/error-handler.js +0 -2
- package/public/js/utils/ui-logger.js +4 -3
- package/public/views/accounts.html +34 -38
- package/public/views/dashboard.html +86 -99
- package/public/views/logs.html +4 -4
- package/public/views/models.html +32 -36
- package/public/views/settings.html +50 -50
- package/src/account-manager/index.js +0 -4
- package/src/account-manager/rate-limits.js +0 -5
- package/src/account-manager/strategies/base-strategy.js +4 -4
- package/src/account-manager/strategies/hybrid-strategy.js +3 -3
- package/src/auth/database.js +1 -0
- package/src/auth/oauth.js +43 -41
- package/src/auth/token-extractor.js +1 -1
- package/src/cli/accounts.js +2 -1
- package/src/cloudcode/model-registry.js +0 -3
- package/src/cloudcode/rate-limit-state.js +1 -7
- package/src/config.js +1 -1
- package/src/constants.js +0 -2
- package/src/format/content-converter.js +0 -4
- package/src/format/request-converter.js +1 -6
- package/src/format/response-converter.js +0 -3
- package/src/format/schema-sanitizer.js +3 -22
- package/src/format/thinking-utils.js +1 -13
- package/src/index.js +1 -6
- package/src/modules/usage-stats.js +1 -1
- package/src/server.js +1 -28
- package/src/utils/claude-config.js +2 -6
- package/src/utils/native-module-helper.js +0 -4
- package/src/utils/proxy.js +1 -10
- package/src/utils/version-detector.js +14 -5
- package/src/webui/index.js +1 -37
package/public/favicon.svg
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
</linearGradient>
|
|
7
|
-
</defs>
|
|
8
|
-
<rect width="32" height="32" rx="6" fill="url(#favicon_grad)" />
|
|
9
|
-
<text x="50%" y="50%" dominant-baseline="central" text-anchor="middle" fill="white" font-family="Inter, system-ui, sans-serif" font-weight="800" font-size="14">AG</text>
|
|
2
|
+
<rect width="32" height="32" rx="7" fill="#111214" />
|
|
3
|
+
<ellipse cx="16" cy="16" rx="12" ry="5.75" transform="rotate(-28 16 16)" stroke="#87857f" stroke-width="1.5" />
|
|
4
|
+
<circle cx="16" cy="16" r="4.5" fill="#eceae4" />
|
|
5
|
+
<circle cx="26" cy="10.4" r="2.6" fill="#d45bc2" />
|
|
10
6
|
</svg>
|
package/public/index.html
CHANGED
|
@@ -12,12 +12,18 @@
|
|
|
12
12
|
<!-- Alpine.js must be deferred so stores register their listeners first -->
|
|
13
13
|
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
|
|
14
14
|
|
|
15
|
+
<!-- Fonts -->
|
|
16
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
17
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
18
|
+
<link rel="stylesheet"
|
|
19
|
+
href="https://fonts.googleapis.com/css2?family=B612:wght@400;700&family=B612+Mono:wght@400;700&family=IBM+Plex+Sans:wght@400;500;600&display=swap">
|
|
20
|
+
|
|
15
21
|
<!-- Compiled Tailwind CSS (includes DaisyUI) -->
|
|
16
22
|
<link rel="stylesheet" href="css/style.css">
|
|
17
23
|
</head>
|
|
18
24
|
|
|
19
25
|
<body
|
|
20
|
-
class="bg-space-950 text-gray-300 font-sans antialiased min-h-screen overflow-hidden
|
|
26
|
+
class="bg-space-950 text-gray-300 font-sans antialiased min-h-screen overflow-hidden "
|
|
21
27
|
x-cloak x-data="app" x-init="if(window.UILogger) window.UILogger.debug('App initialized')">
|
|
22
28
|
|
|
23
29
|
<!-- Toast Notification -->
|
|
@@ -29,10 +35,10 @@
|
|
|
29
35
|
x-transition:leave="transition ease-in duration-200"
|
|
30
36
|
x-transition:leave-start="opacity-100 translate-x-0 scale-100"
|
|
31
37
|
x-transition:leave-end="opacity-0 translate-x-4 scale-95"
|
|
32
|
-
class="alert
|
|
33
|
-
'
|
|
34
|
-
'
|
|
35
|
-
'
|
|
38
|
+
class="alert rounded-lg border bg-space-850 pointer-events-auto min-w-[300px] shadow-[0_8px_24px_-8px_rgba(0,0,0,0.6)]" :class="{
|
|
39
|
+
'border-neon-cyan/30 text-gray-200 [&_svg]:text-neon-cyan': $store.global.toast.type === 'info',
|
|
40
|
+
'border-neon-green/30 text-gray-200 [&_svg]:text-neon-green': $store.global.toast.type === 'success',
|
|
41
|
+
'border-neon-red/30 text-gray-200 [&_svg]:text-neon-red': $store.global.toast.type === 'error'
|
|
36
42
|
}">
|
|
37
43
|
<div class="flex items-center gap-3">
|
|
38
44
|
<!-- Icons based on type -->
|
|
@@ -54,7 +60,7 @@
|
|
|
54
60
|
d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
|
55
61
|
</svg>
|
|
56
62
|
</template>
|
|
57
|
-
<span x-text="$store.global.toast.message" class="
|
|
63
|
+
<span x-text="$store.global.toast.message" class="text-sm"></span>
|
|
58
64
|
</div>
|
|
59
65
|
</div>
|
|
60
66
|
</template>
|
|
@@ -62,47 +68,47 @@
|
|
|
62
68
|
|
|
63
69
|
<!-- Navbar -->
|
|
64
70
|
<div
|
|
65
|
-
class="h-14
|
|
71
|
+
class="app-topbar h-14 flex items-center px-3 lg:px-4 justify-between z-50 relative">
|
|
66
72
|
<div class="flex items-center gap-3">
|
|
67
73
|
<!-- Mobile Menu Button -->
|
|
68
|
-
<button @click="toggleSidebar()" class="text-gray-
|
|
69
|
-
<svg class="w-
|
|
70
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="
|
|
74
|
+
<button @click="toggleSidebar()" class="text-gray-500 hover:text-white rounded-md p-1.5 hover:bg-space-800 transition-colors" aria-label="Toggle navigation">
|
|
75
|
+
<svg class="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
76
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.75" d="M4 7h16M4 12h16M4 17h10" />
|
|
71
77
|
</svg>
|
|
72
78
|
</button>
|
|
73
79
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
<
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
80
|
+
<!-- Brand: a body held in orbit -->
|
|
81
|
+
<svg class="w-7 h-7 shrink-0" viewBox="0 0 28 28" fill="none" aria-hidden="true">
|
|
82
|
+
<ellipse cx="14" cy="14" rx="11.5" ry="5.5" transform="rotate(-28 14 14)" stroke="#87857f" stroke-width="1.25"/>
|
|
83
|
+
<circle cx="14" cy="14" r="4" fill="#eceae4"/>
|
|
84
|
+
<circle cx="23.6" cy="8.6" r="2.2" fill="#d45bc2"/>
|
|
85
|
+
</svg>
|
|
86
|
+
<div class="flex items-baseline gap-2.5">
|
|
87
|
+
<span class="font-display text-[15px] font-bold text-white"
|
|
88
|
+
x-text="$store.global.t('systemName')">Antigravity</span>
|
|
89
|
+
<span class="hidden sm:inline text-xs text-gray-500"
|
|
90
|
+
x-text="$store.global.t('systemDesc')">Claude proxy</span>
|
|
91
|
+
<span class="hidden sm:inline text-xs text-gray-600 font-mono"
|
|
92
|
+
x-text="'v' + $store.global.version">v1.0.0</span>
|
|
86
93
|
</div>
|
|
87
94
|
</div>
|
|
88
95
|
|
|
89
|
-
<div class="flex items-center gap-
|
|
96
|
+
<div class="flex items-center gap-3">
|
|
90
97
|
<!-- Connection Pill -->
|
|
91
|
-
<div class="flex items-center gap-2 px-
|
|
98
|
+
<div class="flex items-center gap-2 px-2.5 py-1 rounded-full text-xs font-medium border border-space-border transition-colors duration-300"
|
|
92
99
|
:class="connectionStatus === 'connected'
|
|
93
|
-
? '
|
|
94
|
-
: (connectionStatus === 'connecting' ? '
|
|
100
|
+
? 'text-gray-300'
|
|
101
|
+
: (connectionStatus === 'connecting' ? 'text-neon-yellow' : 'text-neon-red border-neon-red/30')">
|
|
95
102
|
<div class="w-1.5 h-1.5 rounded-full"
|
|
96
|
-
:class="connectionStatus === 'connected' ? 'bg-neon-green
|
|
103
|
+
:class="connectionStatus === 'connected' ? 'bg-neon-green' : (connectionStatus === 'connecting' ? 'bg-neon-yellow animate-pulse' : 'bg-neon-red')">
|
|
97
104
|
</div>
|
|
98
105
|
<span
|
|
99
106
|
x-text="connectionStatus === 'connected' ? $store.global.t('online') : (connectionStatus === 'disconnected' ? $store.global.t('offline') : $store.global.t('connecting'))"></span>
|
|
100
107
|
</div>
|
|
101
108
|
|
|
102
|
-
|
|
103
|
-
|
|
109
|
+
|
|
104
110
|
<!-- Refresh Button -->
|
|
105
|
-
<button type="button" class="btn btn-ghost btn-
|
|
111
|
+
<button type="button" class="btn btn-ghost btn-sm btn-square text-gray-500 hover:text-white hover:bg-space-800"
|
|
106
112
|
@click="fetchData" :disabled="loading" :title="$store.global.t('refreshData')" aria-label="Refresh data">
|
|
107
113
|
<svg class="w-4 h-4" :class="{'animate-spin': loading}" fill="none" stroke="currentColor"
|
|
108
114
|
viewBox="0 0 24 24">
|
|
@@ -129,7 +135,7 @@
|
|
|
129
135
|
style="display: none;"></div>
|
|
130
136
|
|
|
131
137
|
<!-- Sidebar -->
|
|
132
|
-
<div class="fixed top-14 bottom-0 left-0 z-40
|
|
138
|
+
<div class="app-sidebar fixed top-14 bottom-0 left-0 z-40 border-r border-space-border transition-all duration-300 shadow-2xl overflow-hidden lg:static lg:h-auto lg:shadow-none lg:flex-shrink-0"
|
|
133
139
|
:class="{
|
|
134
140
|
'translate-x-0': sidebarOpen,
|
|
135
141
|
'-translate-x-full': !sidebarOpen,
|
|
@@ -140,7 +146,7 @@
|
|
|
140
146
|
}">
|
|
141
147
|
|
|
142
148
|
<!-- Inner Sidebar Content (Fixed Width to prevent squashing) -->
|
|
143
|
-
<div class="w-64 flex flex-col h-full pt-
|
|
149
|
+
<div class="w-64 flex flex-col h-full pt-5 pb-4 flex-shrink-0">
|
|
144
150
|
<!-- Mobile Menu Header -->
|
|
145
151
|
<div class="flex items-center justify-between px-4 mb-6 lg:hidden">
|
|
146
152
|
<span class="text-sm font-bold text-white" x-text="$store.global.t('menu')">Menu</span>
|
|
@@ -152,60 +158,60 @@
|
|
|
152
158
|
</div>
|
|
153
159
|
|
|
154
160
|
<!-- Desktop Header (Main) -->
|
|
155
|
-
<div class="
|
|
161
|
+
<div class="nav-section-label hidden lg:block"
|
|
156
162
|
x-text="$store.global.t('main')">Main</div>
|
|
157
163
|
|
|
158
|
-
<nav class="flex flex-col gap-
|
|
164
|
+
<nav class="flex flex-col gap-0.5">
|
|
159
165
|
<button
|
|
160
|
-
class="nav-item flex items-center gap-3 px-
|
|
166
|
+
class="nav-item flex items-center gap-3 px-3 py-2 text-sm font-medium text-gray-400 hover:text-white hover:bg-space-850"
|
|
161
167
|
:class="{'active': $store.global.activeTab === 'dashboard'}"
|
|
162
168
|
@click="$store.global.activeTab = 'dashboard'">
|
|
163
|
-
<svg class="w-
|
|
164
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="
|
|
169
|
+
<svg class="w-[18px] h-[18px]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
170
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.75"
|
|
165
171
|
d="M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z" />
|
|
166
172
|
</svg>
|
|
167
173
|
<span x-text="$store.global.t('dashboard')">Dashboard</span>
|
|
168
174
|
</button>
|
|
169
175
|
<button
|
|
170
|
-
class="nav-item flex items-center gap-3 px-
|
|
176
|
+
class="nav-item flex items-center gap-3 px-3 py-2 text-sm font-medium text-gray-400 hover:text-white hover:bg-space-850"
|
|
171
177
|
:class="{'active': $store.global.activeTab === 'models'}"
|
|
172
178
|
@click="$store.global.activeTab = 'models'">
|
|
173
|
-
<svg class="w-
|
|
174
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="
|
|
179
|
+
<svg class="w-[18px] h-[18px]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
180
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.75"
|
|
175
181
|
d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4" />
|
|
176
182
|
</svg>
|
|
177
183
|
<span x-text="$store.global.t('models')">Models</span>
|
|
178
184
|
</button>
|
|
179
185
|
<button
|
|
180
|
-
class="nav-item flex items-center gap-3 px-
|
|
186
|
+
class="nav-item flex items-center gap-3 px-3 py-2 text-sm font-medium text-gray-400 hover:text-white hover:bg-space-850"
|
|
181
187
|
:class="{'active': $store.global.activeTab === 'accounts'}"
|
|
182
188
|
@click="$store.global.activeTab = 'accounts'">
|
|
183
|
-
<svg class="w-
|
|
184
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="
|
|
189
|
+
<svg class="w-[18px] h-[18px]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
190
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.75"
|
|
185
191
|
d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z" />
|
|
186
192
|
</svg>
|
|
187
193
|
<span x-text="$store.global.t('accounts')">Accounts</span>
|
|
188
194
|
</button>
|
|
189
195
|
</nav>
|
|
190
196
|
|
|
191
|
-
<div class="
|
|
197
|
+
<div class="nav-section-label mt-7"
|
|
192
198
|
x-text="$store.global.t('system')">System</div>
|
|
193
|
-
<nav class="flex flex-col gap-
|
|
199
|
+
<nav class="flex flex-col gap-0.5">
|
|
194
200
|
<button
|
|
195
|
-
class="nav-item flex items-center gap-3 px-
|
|
201
|
+
class="nav-item flex items-center gap-3 px-3 py-2 text-sm font-medium text-gray-400 hover:text-white hover:bg-space-850"
|
|
196
202
|
:class="{'active': $store.global.activeTab === 'logs'}" @click="$store.global.activeTab = 'logs'">
|
|
197
|
-
<svg class="w-
|
|
198
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="
|
|
203
|
+
<svg class="w-[18px] h-[18px]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
204
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.75"
|
|
199
205
|
d="M8 9l3 3-3 3m5 0h3M5 20h14a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
|
|
200
206
|
</svg>
|
|
201
207
|
<span x-text="$store.global.t('logs')">Logs</span>
|
|
202
208
|
</button>
|
|
203
209
|
<button
|
|
204
|
-
class="nav-item flex items-center gap-3 px-
|
|
210
|
+
class="nav-item flex items-center gap-3 px-3 py-2 text-sm font-medium text-gray-400 hover:text-white hover:bg-space-850"
|
|
205
211
|
:class="{'active': $store.global.activeTab === 'settings'}"
|
|
206
212
|
@click="$store.global.activeTab = 'settings'">
|
|
207
|
-
<svg class="w-
|
|
208
|
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="
|
|
213
|
+
<svg class="w-[18px] h-[18px]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
214
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.75"
|
|
209
215
|
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" />
|
|
210
216
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
|
211
217
|
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
|
|
@@ -215,10 +221,10 @@
|
|
|
215
221
|
</nav>
|
|
216
222
|
|
|
217
223
|
<!-- Footer Info -->
|
|
218
|
-
<div class="mt-auto px-6 text-xs text-gray-
|
|
219
|
-
<div class="flex
|
|
224
|
+
<div class="mt-auto px-6 text-xs text-gray-500">
|
|
225
|
+
<div class="flex">
|
|
220
226
|
<a href="https://github.com/badri-s2001/antigravity-claude-proxy" target="_blank" rel="noopener noreferrer"
|
|
221
|
-
class="flex items-center gap-1.5 hover:text-
|
|
227
|
+
class="flex items-center gap-1.5 hover:text-gray-200 transition-colors">
|
|
222
228
|
<svg class="w-4 h-4" fill="currentColor" viewBox="0 0 24 24">
|
|
223
229
|
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
|
|
224
230
|
</svg>
|
|
@@ -260,9 +266,9 @@
|
|
|
260
266
|
</div>
|
|
261
267
|
|
|
262
268
|
<!-- Add Account Modal -->
|
|
263
|
-
<dialog id="add_account_modal" class="modal
|
|
264
|
-
<div class="modal-box max-w-lg w-full bg-space-900 border border-space-border text-gray-300
|
|
265
|
-
<h3 class="font-
|
|
269
|
+
<dialog id="add_account_modal" class="modal" x-data="addAccountModal">
|
|
270
|
+
<div class="modal-box max-w-lg w-full bg-space-900 border border-space-border text-gray-300 p-6">
|
|
271
|
+
<h3 class="font-semibold text-lg text-white mb-3" x-text="$store.global.t('addAccount')">Add New Account</h3>
|
|
266
272
|
|
|
267
273
|
<div class="flex flex-col gap-4">
|
|
268
274
|
<p class="text-sm text-gray-400 leading-relaxed" x-text="$store.global.t('connectGoogleDesc')">Connect a Google
|
|
@@ -288,23 +294,23 @@
|
|
|
288
294
|
</button>
|
|
289
295
|
|
|
290
296
|
<div class="text-center mt-2">
|
|
291
|
-
<p class="text-xs text-gray-500 mb-2" x-text="$store.global.t('or')">
|
|
297
|
+
<p class="text-xs text-gray-500 mb-2" x-text="$store.global.t('or')">or</p>
|
|
292
298
|
|
|
293
299
|
<!-- Manual Mode (collapsible) -->
|
|
294
300
|
<details class="group mb-2" @toggle="initManualAuth($event)">
|
|
295
|
-
<summary class="text-xs text-gray-400 hover:text-
|
|
301
|
+
<summary class="text-xs text-gray-400 hover:text-white cursor-pointer transition-colors inline-flex items-center gap-1">
|
|
296
302
|
<svg class="w-3 h-3 transition-transform group-open:rotate-90" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
297
303
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
|
|
298
304
|
</svg>
|
|
299
305
|
<span x-text="$store.global.t('manualMode')">Manual Mode</span>
|
|
300
306
|
</summary>
|
|
301
|
-
<div class="mt-3 p-3 bg-
|
|
307
|
+
<div class="mt-3 p-3 bg-space-950 rounded-md border border-space-border text-xs">
|
|
302
308
|
<template x-if="authUrl">
|
|
303
309
|
<div>
|
|
304
310
|
<div class="flex items-center gap-2 mb-2">
|
|
305
311
|
<input type="text" readonly :value="authUrl"
|
|
306
|
-
class="input input-xs input-bordered flex-1 bg-space-
|
|
307
|
-
<button class="btn btn-xs btn-ghost text-
|
|
312
|
+
class="input input-xs input-bordered flex-1 bg-space-850 border-space-border text-gray-300 font-mono">
|
|
313
|
+
<button class="btn btn-xs btn-ghost text-gray-400 hover:text-white" @click="copyLink" aria-label="Copy link" :title="$store.global.t('linkCopied')">
|
|
308
314
|
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
309
315
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"/>
|
|
310
316
|
</svg>
|
|
@@ -313,7 +319,7 @@
|
|
|
313
319
|
<div class="flex items-center gap-2">
|
|
314
320
|
<input type="text" x-model="callbackInput"
|
|
315
321
|
:placeholder="$store.global.t('pasteCallbackPlaceholder')"
|
|
316
|
-
class="input input-xs input-bordered flex-1 bg-space-
|
|
322
|
+
class="input input-xs input-bordered flex-1 bg-space-850 border-space-border text-gray-300 font-mono">
|
|
317
323
|
<button class="btn btn-xs btn-success"
|
|
318
324
|
@click="completeManualAuth"
|
|
319
325
|
:disabled="!callbackInput || submitting"
|
|
@@ -331,13 +337,13 @@
|
|
|
331
337
|
|
|
332
338
|
<!-- CLI Command -->
|
|
333
339
|
<details class="group">
|
|
334
|
-
<summary class="text-xs text-gray-400 hover:text-
|
|
340
|
+
<summary class="text-xs text-gray-400 hover:text-white cursor-pointer transition-colors inline-flex items-center gap-1">
|
|
335
341
|
<svg class="w-3 h-3 transition-transform group-open:rotate-90" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
336
342
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
|
|
337
343
|
</svg>
|
|
338
344
|
<span x-text="$store.global.t('useCliCommand')">Use CLI Command</span>
|
|
339
345
|
</summary>
|
|
340
|
-
<div class="mt-3 p-3 bg-
|
|
346
|
+
<div class="mt-3 p-3 bg-space-950 rounded-md border border-space-border font-mono text-xs text-gray-300">
|
|
341
347
|
<div class="flex items-center gap-2">
|
|
342
348
|
<span class="text-gray-600">$</span>
|
|
343
349
|
<code>npm run accounts:add</code>
|
|
@@ -349,7 +355,7 @@
|
|
|
349
355
|
|
|
350
356
|
<div class="modal-action mt-6">
|
|
351
357
|
<form method="dialog">
|
|
352
|
-
<button type="submit" class="btn btn-ghost hover:bg-
|
|
358
|
+
<button type="submit" class="btn btn-ghost btn-sm text-gray-400 hover:text-white hover:bg-space-800" @click="resetState()" x-text="$store.global.t('close')">Close</button>
|
|
353
359
|
</form>
|
|
354
360
|
</div>
|
|
355
361
|
</div>
|
|
@@ -360,9 +366,9 @@
|
|
|
360
366
|
|
|
361
367
|
<!-- OAuth Progress Modal -->
|
|
362
368
|
<dialog id="oauth_progress_modal" class="modal" :class="{ 'modal-open': $store.global.oauthProgress.active }">
|
|
363
|
-
<div class="modal-box bg-space-900 border border-
|
|
364
|
-
<h3 class="font-
|
|
365
|
-
<svg class="w-
|
|
369
|
+
<div class="modal-box bg-space-900 border border-space-border">
|
|
370
|
+
<h3 class="font-semibold text-lg text-white flex items-center gap-2">
|
|
371
|
+
<svg class="w-5 h-5 text-neon-purple animate-spin" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
366
372
|
<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" />
|
|
367
373
|
</svg>
|
|
368
374
|
<span x-text="$store.global.t('oauthWaiting')">Waiting for OAuth...</span>
|
|
@@ -372,14 +378,14 @@
|
|
|
372
378
|
</p>
|
|
373
379
|
|
|
374
380
|
<!-- Progress Bar -->
|
|
375
|
-
<div class="w-full bg-space-800 rounded-full h-
|
|
376
|
-
<div class="bg-neon-purple h-
|
|
381
|
+
<div class="w-full bg-space-800 rounded-full h-1.5 mb-3 overflow-hidden">
|
|
382
|
+
<div class="bg-neon-purple h-1.5 rounded-full transition-all duration-500"
|
|
377
383
|
:style="`width: ${($store.global.oauthProgress.current / $store.global.oauthProgress.max) * 100}%`">
|
|
378
384
|
</div>
|
|
379
385
|
</div>
|
|
380
386
|
|
|
381
387
|
<!-- Progress Text -->
|
|
382
|
-
<div class="flex justify-between text-xs text-gray-
|
|
388
|
+
<div class="flex justify-between text-xs text-gray-500 font-mono mb-4">
|
|
383
389
|
<span x-text="`${$store.global.oauthProgress.current} / ${$store.global.oauthProgress.max}s`"></span>
|
|
384
390
|
<span x-text="`${Math.round(($store.global.oauthProgress.current / $store.global.oauthProgress.max) * 100)}%`"></span>
|
|
385
391
|
</div>
|
|
@@ -203,10 +203,6 @@ window.Components.claudeConfig = () => ({
|
|
|
203
203
|
}
|
|
204
204
|
},
|
|
205
205
|
|
|
206
|
-
// ==========================================
|
|
207
|
-
// Presets Management
|
|
208
|
-
// ==========================================
|
|
209
|
-
|
|
210
206
|
/**
|
|
211
207
|
* Fetch all saved presets from the server
|
|
212
208
|
*/
|
|
@@ -438,10 +434,6 @@ window.Components.claudeConfig = () => ({
|
|
|
438
434
|
}
|
|
439
435
|
},
|
|
440
436
|
|
|
441
|
-
// ==========================================
|
|
442
|
-
// Mode Toggle (Proxy/Paid)
|
|
443
|
-
// ==========================================
|
|
444
|
-
|
|
445
437
|
/**
|
|
446
438
|
* Fetch current mode from server
|
|
447
439
|
*/
|
|
@@ -26,13 +26,13 @@ const getThemeColor = (name) => window.utils.getThemeColor(name);
|
|
|
26
26
|
// Color palette for different families and models
|
|
27
27
|
const FAMILY_COLORS = {
|
|
28
28
|
get claude() {
|
|
29
|
-
return getThemeColor("--color-
|
|
29
|
+
return getThemeColor("--color-family-claude");
|
|
30
30
|
},
|
|
31
31
|
get gemini() {
|
|
32
|
-
return getThemeColor("--color-
|
|
32
|
+
return getThemeColor("--color-family-gemini");
|
|
33
33
|
},
|
|
34
34
|
get other() {
|
|
35
|
-
return getThemeColor("--color-
|
|
35
|
+
return getThemeColor("--color-family-other");
|
|
36
36
|
},
|
|
37
37
|
};
|
|
38
38
|
|
|
@@ -75,57 +75,31 @@ function isCanvasReady(canvas) {
|
|
|
75
75
|
try {
|
|
76
76
|
const ctx = canvas.getContext("2d");
|
|
77
77
|
return !!ctx;
|
|
78
|
-
} catch
|
|
78
|
+
} catch {
|
|
79
79
|
return false;
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
/**
|
|
84
|
-
* Create a Chart.js dataset
|
|
84
|
+
* Create a Chart.js dataset drawn as a plain instrument trace (no area fill)
|
|
85
85
|
* @param {string} label - Dataset label
|
|
86
86
|
* @param {Array} data - Data points
|
|
87
87
|
* @param {string} color - Line color
|
|
88
|
-
* @param {HTMLCanvasElement} canvas - Canvas element
|
|
89
88
|
* @returns {object} Chart.js dataset configuration
|
|
90
89
|
*/
|
|
91
|
-
window.DashboardCharts.createDataset = function (label, data, color
|
|
92
|
-
let gradient;
|
|
93
|
-
|
|
94
|
-
try {
|
|
95
|
-
// Safely create gradient with fallback
|
|
96
|
-
if (canvas && canvas.getContext) {
|
|
97
|
-
const ctx = canvas.getContext("2d");
|
|
98
|
-
if (ctx && ctx.createLinearGradient) {
|
|
99
|
-
gradient = ctx.createLinearGradient(0, 0, 0, 200);
|
|
100
|
-
gradient.addColorStop(0, window.DashboardCharts.hexToRgba(color, 0.12));
|
|
101
|
-
gradient.addColorStop(
|
|
102
|
-
0.6,
|
|
103
|
-
window.DashboardCharts.hexToRgba(color, 0.05)
|
|
104
|
-
);
|
|
105
|
-
gradient.addColorStop(1, "rgba(0, 0, 0, 0)");
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
} catch (e) {
|
|
109
|
-
if (window.UILogger) window.UILogger.debug("Gradient fallback:", e.message);
|
|
110
|
-
gradient = null;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Fallback to solid color if gradient creation failed
|
|
114
|
-
const backgroundColor =
|
|
115
|
-
gradient || window.DashboardCharts.hexToRgba(color, 0.08);
|
|
116
|
-
|
|
90
|
+
window.DashboardCharts.createDataset = function (label, data, color) {
|
|
117
91
|
return {
|
|
118
92
|
label,
|
|
119
93
|
data,
|
|
120
94
|
borderColor: color,
|
|
121
|
-
backgroundColor:
|
|
122
|
-
borderWidth: 2
|
|
123
|
-
tension: 0.
|
|
124
|
-
fill:
|
|
125
|
-
pointRadius: 2
|
|
126
|
-
pointHoverRadius:
|
|
95
|
+
backgroundColor: color,
|
|
96
|
+
borderWidth: 2,
|
|
97
|
+
tension: 0.25,
|
|
98
|
+
fill: false,
|
|
99
|
+
pointRadius: 2,
|
|
100
|
+
pointHoverRadius: 5,
|
|
127
101
|
pointBackgroundColor: color,
|
|
128
|
-
pointBorderColor: "
|
|
102
|
+
pointBorderColor: getThemeColor("--color-space-900") || "#111214",
|
|
129
103
|
pointBorderWidth: 1.5,
|
|
130
104
|
};
|
|
131
105
|
};
|
|
@@ -139,14 +113,14 @@ window.DashboardCharts.updateCharts = function (component) {
|
|
|
139
113
|
|
|
140
114
|
// Safety checks
|
|
141
115
|
if (!canvas) {
|
|
142
|
-
|
|
116
|
+
window.UILogger?.debug("quotaChart canvas not found");
|
|
143
117
|
return;
|
|
144
118
|
}
|
|
145
119
|
|
|
146
120
|
// FORCE DESTROY: Check for existing chart on the canvas element property
|
|
147
121
|
// This handles cases where Component state is lost but DOM persists
|
|
148
122
|
if (canvas._chartInstance) {
|
|
149
|
-
|
|
123
|
+
window.UILogger?.debug("Destroying existing quota chart from canvas property");
|
|
150
124
|
try {
|
|
151
125
|
canvas._chartInstance.destroy();
|
|
152
126
|
} catch(e) { if (window.UILogger) window.UILogger.debug(e); }
|
|
@@ -157,7 +131,7 @@ window.DashboardCharts.updateCharts = function (component) {
|
|
|
157
131
|
if (component.charts.quotaDistribution) {
|
|
158
132
|
try {
|
|
159
133
|
component.charts.quotaDistribution.destroy();
|
|
160
|
-
} catch(e) { }
|
|
134
|
+
} catch (e) { window.UILogger?.debug("quotaDistribution destroy failed", e); }
|
|
161
135
|
component.charts.quotaDistribution = null;
|
|
162
136
|
}
|
|
163
137
|
|
|
@@ -165,7 +139,7 @@ window.DashboardCharts.updateCharts = function (component) {
|
|
|
165
139
|
if (typeof Chart !== "undefined" && Chart.getChart) {
|
|
166
140
|
const regChart = Chart.getChart(canvas);
|
|
167
141
|
if (regChart) {
|
|
168
|
-
try { regChart.destroy(); } catch(e) {}
|
|
142
|
+
try { regChart.destroy(); } catch (e) { window.UILogger?.debug("Registry chart destroy failed", e); }
|
|
169
143
|
}
|
|
170
144
|
}
|
|
171
145
|
|
|
@@ -214,9 +188,9 @@ window.DashboardCharts.updateCharts = function (component) {
|
|
|
214
188
|
: 0;
|
|
215
189
|
|
|
216
190
|
const familyColors = {
|
|
217
|
-
claude: getThemeColor("--color-
|
|
218
|
-
gemini: getThemeColor("--color-
|
|
219
|
-
unknown: getThemeColor("--color-
|
|
191
|
+
claude: getThemeColor("--color-family-claude") || "#4cc9d6",
|
|
192
|
+
gemini: getThemeColor("--color-family-gemini") || "#d9c39a",
|
|
193
|
+
unknown: getThemeColor("--color-family-other") || "#9aa7b0",
|
|
220
194
|
};
|
|
221
195
|
|
|
222
196
|
const data = [];
|
|
@@ -332,7 +306,7 @@ window.DashboardCharts.updateTrendChart = function (component) {
|
|
|
332
306
|
// FORCE DESTROY: Check for existing chart on the canvas element property
|
|
333
307
|
if (canvas) {
|
|
334
308
|
if (canvas._chartInstance) {
|
|
335
|
-
|
|
309
|
+
window.UILogger?.debug("Destroying existing trend chart from canvas property");
|
|
336
310
|
try {
|
|
337
311
|
canvas._chartInstance.stop();
|
|
338
312
|
canvas._chartInstance.destroy();
|
|
@@ -344,7 +318,7 @@ window.DashboardCharts.updateTrendChart = function (component) {
|
|
|
344
318
|
if (typeof Chart !== "undefined" && Chart.getChart) {
|
|
345
319
|
const regChart = Chart.getChart(canvas);
|
|
346
320
|
if (regChart) {
|
|
347
|
-
try { regChart.stop(); regChart.destroy(); } catch(e) {}
|
|
321
|
+
try { regChart.stop(); regChart.destroy(); } catch (e) { window.UILogger?.debug("Registry chart destroy failed", e); }
|
|
348
322
|
}
|
|
349
323
|
}
|
|
350
324
|
}
|
|
@@ -354,7 +328,7 @@ window.DashboardCharts.updateTrendChart = function (component) {
|
|
|
354
328
|
try {
|
|
355
329
|
component.charts.usageTrend.stop();
|
|
356
330
|
component.charts.usageTrend.destroy();
|
|
357
|
-
} catch (e) { }
|
|
331
|
+
} catch (e) { window.UILogger?.debug("usageTrend destroy failed", e); }
|
|
358
332
|
component.charts.usageTrend = null;
|
|
359
333
|
}
|
|
360
334
|
|
|
@@ -588,7 +562,7 @@ window.DashboardCharts.updateTrendChart = function (component) {
|
|
|
588
562
|
grid: { display: false },
|
|
589
563
|
ticks: {
|
|
590
564
|
color: getThemeColor("--color-text-muted"),
|
|
591
|
-
font: { size: 10 },
|
|
565
|
+
font: { size: 10, family: '"B612 Mono", ui-monospace, monospace' },
|
|
592
566
|
},
|
|
593
567
|
},
|
|
594
568
|
y: {
|
|
@@ -602,7 +576,7 @@ window.DashboardCharts.updateTrendChart = function (component) {
|
|
|
602
576
|
},
|
|
603
577
|
ticks: {
|
|
604
578
|
color: getThemeColor("--color-text-muted"),
|
|
605
|
-
font: { size: 10 },
|
|
579
|
+
font: { size: 10, family: '"B612 Mono", ui-monospace, monospace' },
|
|
606
580
|
},
|
|
607
581
|
},
|
|
608
582
|
},
|
|
@@ -81,7 +81,7 @@ window.DashboardStats.updateStats = function(component) {
|
|
|
81
81
|
|
|
82
82
|
enabledAccounts.forEach(acc => {
|
|
83
83
|
const limits = Object.entries(acc.limits || {});
|
|
84
|
-
limits.forEach(([
|
|
84
|
+
limits.forEach(([_id, l]) => {
|
|
85
85
|
totalTrackedModels++;
|
|
86
86
|
if (!l || l.remainingFraction == null || l.remainingFraction <= 0.05) {
|
|
87
87
|
totalLimitedModels++;
|
|
@@ -49,6 +49,8 @@ window.Components.dashboard = () => ({
|
|
|
49
49
|
this.$nextTick(() => {
|
|
50
50
|
this.updateStats();
|
|
51
51
|
this.updateCharts();
|
|
52
|
+
// History that arrived while another tab was active was skipped by the watcher below
|
|
53
|
+
this.syncHistory(this.$store.data.usageHistory);
|
|
52
54
|
this.updateTrendChart();
|
|
53
55
|
this.checkClaudeConfigStatus();
|
|
54
56
|
});
|
|
@@ -71,15 +73,8 @@ window.Components.dashboard = () => ({
|
|
|
71
73
|
|
|
72
74
|
// Watch for history updates from data-store (automatically loaded with account data)
|
|
73
75
|
this.$watch('$store.data.usageHistory', (newHistory) => {
|
|
74
|
-
if (this.$store.global.activeTab === 'dashboard'
|
|
75
|
-
|
|
76
|
-
if (this.historyData && JSON.stringify(newHistory) === JSON.stringify(this.historyData)) {
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
this.historyData = newHistory;
|
|
81
|
-
this.processHistory(newHistory);
|
|
82
|
-
this.stats.hasTrendData = true;
|
|
76
|
+
if (this.$store.global.activeTab === 'dashboard') {
|
|
77
|
+
this.syncHistory(newHistory);
|
|
83
78
|
}
|
|
84
79
|
});
|
|
85
80
|
|
|
@@ -89,22 +84,22 @@ window.Components.dashboard = () => ({
|
|
|
89
84
|
this.$nextTick(() => {
|
|
90
85
|
this.updateStats();
|
|
91
86
|
this.updateCharts();
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
// The usageHistory watcher above will handle updates if data changes
|
|
95
|
-
const history = Alpine.store('data').usageHistory;
|
|
96
|
-
if (history && Object.keys(history).length > 0) {
|
|
97
|
-
// Check if we already have this data to avoid redundant chart update
|
|
98
|
-
if (!this.historyData || JSON.stringify(history) !== JSON.stringify(this.historyData)) {
|
|
99
|
-
this.historyData = history;
|
|
100
|
-
this.processHistory(history);
|
|
101
|
-
this.stats.hasTrendData = true;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
87
|
+
// The store may already hold history loaded before this component initialised
|
|
88
|
+
this.syncHistory(Alpine.store('data').usageHistory);
|
|
104
89
|
});
|
|
105
90
|
}
|
|
106
91
|
},
|
|
107
92
|
|
|
93
|
+
// Process usage history unless it is empty or identical to what is already rendered
|
|
94
|
+
syncHistory(history) {
|
|
95
|
+
if (!history || Object.keys(history).length === 0) return;
|
|
96
|
+
if (JSON.stringify(history) === JSON.stringify(this.historyData)) return;
|
|
97
|
+
|
|
98
|
+
this.historyData = history;
|
|
99
|
+
this.processHistory(history);
|
|
100
|
+
this.stats.hasTrendData = true;
|
|
101
|
+
},
|
|
102
|
+
|
|
108
103
|
processHistory(history) {
|
|
109
104
|
// Build model tree from hierarchical data
|
|
110
105
|
const tree = {};
|