commons-proxy 2.0.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/LICENSE +21 -0
- package/README.md +757 -0
- package/bin/cli.js +146 -0
- package/package.json +97 -0
- package/public/Complaint Details.pdf +0 -0
- package/public/Cyber Crime Portal.pdf +0 -0
- package/public/app.js +229 -0
- package/public/css/src/input.css +523 -0
- package/public/css/style.css +1 -0
- package/public/favicon.png +0 -0
- package/public/index.html +549 -0
- package/public/js/components/account-manager.js +356 -0
- package/public/js/components/add-account-modal.js +414 -0
- package/public/js/components/claude-config.js +420 -0
- package/public/js/components/dashboard/charts.js +605 -0
- package/public/js/components/dashboard/filters.js +362 -0
- package/public/js/components/dashboard/stats.js +110 -0
- package/public/js/components/dashboard.js +236 -0
- package/public/js/components/logs-viewer.js +100 -0
- package/public/js/components/models.js +36 -0
- package/public/js/components/server-config.js +349 -0
- package/public/js/config/constants.js +102 -0
- package/public/js/data-store.js +375 -0
- package/public/js/settings-store.js +58 -0
- package/public/js/store.js +99 -0
- package/public/js/translations/en.js +367 -0
- package/public/js/translations/id.js +412 -0
- package/public/js/translations/pt.js +308 -0
- package/public/js/translations/tr.js +358 -0
- package/public/js/translations/zh.js +373 -0
- package/public/js/utils/account-actions.js +189 -0
- package/public/js/utils/error-handler.js +96 -0
- package/public/js/utils/model-config.js +42 -0
- package/public/js/utils/ui-logger.js +143 -0
- package/public/js/utils/validators.js +77 -0
- package/public/js/utils.js +69 -0
- package/public/proxy-server-64.png +0 -0
- package/public/views/accounts.html +361 -0
- package/public/views/dashboard.html +484 -0
- package/public/views/logs.html +97 -0
- package/public/views/models.html +331 -0
- package/public/views/settings.html +1327 -0
- package/src/account-manager/credentials.js +378 -0
- package/src/account-manager/index.js +462 -0
- package/src/account-manager/onboarding.js +112 -0
- package/src/account-manager/rate-limits.js +369 -0
- package/src/account-manager/storage.js +160 -0
- package/src/account-manager/strategies/base-strategy.js +109 -0
- package/src/account-manager/strategies/hybrid-strategy.js +339 -0
- package/src/account-manager/strategies/index.js +79 -0
- package/src/account-manager/strategies/round-robin-strategy.js +76 -0
- package/src/account-manager/strategies/sticky-strategy.js +138 -0
- package/src/account-manager/strategies/trackers/health-tracker.js +162 -0
- package/src/account-manager/strategies/trackers/index.js +9 -0
- package/src/account-manager/strategies/trackers/quota-tracker.js +120 -0
- package/src/account-manager/strategies/trackers/token-bucket-tracker.js +155 -0
- package/src/auth/database.js +169 -0
- package/src/auth/oauth.js +548 -0
- package/src/auth/token-extractor.js +117 -0
- package/src/cli/accounts.js +648 -0
- package/src/cloudcode/index.js +29 -0
- package/src/cloudcode/message-handler.js +510 -0
- package/src/cloudcode/model-api.js +248 -0
- package/src/cloudcode/rate-limit-parser.js +235 -0
- package/src/cloudcode/request-builder.js +93 -0
- package/src/cloudcode/session-manager.js +47 -0
- package/src/cloudcode/sse-parser.js +121 -0
- package/src/cloudcode/sse-streamer.js +293 -0
- package/src/cloudcode/streaming-handler.js +615 -0
- package/src/config.js +125 -0
- package/src/constants.js +407 -0
- package/src/errors.js +242 -0
- package/src/fallback-config.js +29 -0
- package/src/format/content-converter.js +193 -0
- package/src/format/index.js +20 -0
- package/src/format/request-converter.js +255 -0
- package/src/format/response-converter.js +120 -0
- package/src/format/schema-sanitizer.js +673 -0
- package/src/format/signature-cache.js +88 -0
- package/src/format/thinking-utils.js +648 -0
- package/src/index.js +148 -0
- package/src/modules/usage-stats.js +205 -0
- package/src/providers/anthropic-provider.js +258 -0
- package/src/providers/base-provider.js +157 -0
- package/src/providers/cloudcode.js +94 -0
- package/src/providers/copilot.js +399 -0
- package/src/providers/github-provider.js +287 -0
- package/src/providers/google-provider.js +192 -0
- package/src/providers/index.js +211 -0
- package/src/providers/openai-compatible.js +265 -0
- package/src/providers/openai-provider.js +271 -0
- package/src/providers/openrouter-provider.js +325 -0
- package/src/providers/setup.js +83 -0
- package/src/server.js +870 -0
- package/src/utils/claude-config.js +245 -0
- package/src/utils/helpers.js +51 -0
- package/src/utils/logger.js +142 -0
- package/src/utils/native-module-helper.js +162 -0
- package/src/webui/index.js +1134 -0
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Add Account Modal Component
|
|
3
|
+
* Registers itself to window.Components for Alpine.js to consume
|
|
4
|
+
* Supports multi-provider account addition (Google OAuth, API keys, PAT, Device Auth)
|
|
5
|
+
*/
|
|
6
|
+
window.Components = window.Components || {};
|
|
7
|
+
|
|
8
|
+
window.Components.addAccountModal = () => ({
|
|
9
|
+
// Provider selection
|
|
10
|
+
providers: [],
|
|
11
|
+
selectedProvider: 'google',
|
|
12
|
+
|
|
13
|
+
// Form fields
|
|
14
|
+
email: '',
|
|
15
|
+
apiKey: '',
|
|
16
|
+
customEndpoint: '',
|
|
17
|
+
|
|
18
|
+
// OAuth state (Google)
|
|
19
|
+
manualMode: false,
|
|
20
|
+
authUrl: '',
|
|
21
|
+
authState: '',
|
|
22
|
+
callbackInput: '',
|
|
23
|
+
submitting: false,
|
|
24
|
+
|
|
25
|
+
// Copilot Device Auth state
|
|
26
|
+
copilotFlowId: null,
|
|
27
|
+
copilotUserCode: '',
|
|
28
|
+
copilotVerificationUri: '',
|
|
29
|
+
copilotPolling: false,
|
|
30
|
+
copilotPollTimer: null,
|
|
31
|
+
|
|
32
|
+
async init() {
|
|
33
|
+
// Fetch available providers on modal init
|
|
34
|
+
await this.loadProviders();
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
async loadProviders() {
|
|
38
|
+
try {
|
|
39
|
+
const store = Alpine.store('global');
|
|
40
|
+
const { response, newPassword } = await window.utils.request(
|
|
41
|
+
'/api/providers',
|
|
42
|
+
{},
|
|
43
|
+
store.webuiPassword
|
|
44
|
+
);
|
|
45
|
+
if (newPassword) store.webuiPassword = newPassword;
|
|
46
|
+
|
|
47
|
+
const data = await response.json();
|
|
48
|
+
if (data.status === 'ok' && Array.isArray(data.providers)) {
|
|
49
|
+
this.providers = data.providers.map(p => ({
|
|
50
|
+
id: p.id,
|
|
51
|
+
name: p.name,
|
|
52
|
+
authType: p.authType,
|
|
53
|
+
color: p.config?.color || '#4285f4'
|
|
54
|
+
}));
|
|
55
|
+
}
|
|
56
|
+
} catch (e) {
|
|
57
|
+
console.error('Failed to load providers:', e);
|
|
58
|
+
// Fallback to default providers if API fails
|
|
59
|
+
this.providers = [
|
|
60
|
+
{ id: 'google', name: 'Google Cloud Code', authType: 'oauth', color: '#4285f4' },
|
|
61
|
+
{ id: 'anthropic', name: 'Anthropic', authType: 'api-key', color: '#d97706' },
|
|
62
|
+
{ id: 'openai', name: 'OpenAI', authType: 'api-key', color: '#10b981' },
|
|
63
|
+
{ id: 'github', name: 'GitHub Models', authType: 'api-key', color: '#6366f1' },
|
|
64
|
+
{ id: 'copilot', name: 'GitHub Copilot', authType: 'device-auth', color: '#f97316' },
|
|
65
|
+
{ id: 'openrouter', name: 'OpenRouter', authType: 'api-key', color: '#6d28d9' }
|
|
66
|
+
];
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
get currentProvider() {
|
|
71
|
+
return this.providers.find(p => p.id === this.selectedProvider) || this.providers[0];
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
get isOAuthProvider() {
|
|
75
|
+
return this.currentProvider?.authType === 'oauth';
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
get requiresApiKey() {
|
|
79
|
+
return this.currentProvider?.authType === 'api-key' || this.currentProvider?.authType === 'pat';
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
get isDeviceAuthProvider() {
|
|
83
|
+
return this.currentProvider?.authType === 'device-auth';
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
get apiKeyLabel() {
|
|
87
|
+
if (this.currentProvider?.authType === 'pat') {
|
|
88
|
+
return 'Personal Access Token';
|
|
89
|
+
}
|
|
90
|
+
return 'API Key';
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
get apiKeyPlaceholder() {
|
|
94
|
+
const provider = this.currentProvider;
|
|
95
|
+
if (!provider) return 'Enter your API key';
|
|
96
|
+
|
|
97
|
+
if (provider.id === 'anthropic') {
|
|
98
|
+
return 'sk-ant-api03-...';
|
|
99
|
+
} else if (provider.id === 'openai') {
|
|
100
|
+
return 'sk-...';
|
|
101
|
+
} else if (provider.id === 'github') {
|
|
102
|
+
return 'github_pat_...';
|
|
103
|
+
} else if (provider.id === 'openrouter') {
|
|
104
|
+
return 'sk-or-v1-...';
|
|
105
|
+
}
|
|
106
|
+
return 'Enter your API key or token';
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
onProviderChange() {
|
|
110
|
+
// Reset form fields when provider changes
|
|
111
|
+
this.email = '';
|
|
112
|
+
this.apiKey = '';
|
|
113
|
+
this.customEndpoint = '';
|
|
114
|
+
this.authUrl = '';
|
|
115
|
+
this.callbackInput = '';
|
|
116
|
+
this.manualMode = false;
|
|
117
|
+
// Stop any active Copilot polling
|
|
118
|
+
this.stopCopilotPolling();
|
|
119
|
+
this.copilotFlowId = null;
|
|
120
|
+
this.copilotUserCode = '';
|
|
121
|
+
this.copilotVerificationUri = '';
|
|
122
|
+
},
|
|
123
|
+
|
|
124
|
+
// ==================== OAuth Methods (Google) ====================
|
|
125
|
+
|
|
126
|
+
async addAccountWeb() {
|
|
127
|
+
const store = Alpine.store('global');
|
|
128
|
+
const password = store.webuiPassword;
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
store.showOAuthProgress();
|
|
132
|
+
const { response, newPassword } = await window.utils.request('/api/auth/url', {}, password);
|
|
133
|
+
if (newPassword) store.webuiPassword = newPassword;
|
|
134
|
+
|
|
135
|
+
const data = await response.json();
|
|
136
|
+
if (data.status === 'ok') {
|
|
137
|
+
window.open(data.url, 'google_oauth', 'width=600,height=700,scrollbars=yes');
|
|
138
|
+
} else {
|
|
139
|
+
store.showToast(data.error || store.t('authUrlFailed'), 'error');
|
|
140
|
+
store.hideOAuthProgress();
|
|
141
|
+
}
|
|
142
|
+
} catch (e) {
|
|
143
|
+
store.showToast(store.t('authUrlFailed') + ': ' + e.message, 'error');
|
|
144
|
+
store.hideOAuthProgress();
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
|
|
148
|
+
async initManualAuth(event) {
|
|
149
|
+
if (!event.target.open || this.authUrl) return;
|
|
150
|
+
|
|
151
|
+
try {
|
|
152
|
+
const password = Alpine.store('global').webuiPassword;
|
|
153
|
+
const {
|
|
154
|
+
response,
|
|
155
|
+
newPassword
|
|
156
|
+
} = await window.utils.request('/api/auth/url', {}, password);
|
|
157
|
+
if (newPassword) Alpine.store('global').webuiPassword = newPassword;
|
|
158
|
+
const data = await response.json();
|
|
159
|
+
if (data.status === 'ok') {
|
|
160
|
+
this.authUrl = data.url;
|
|
161
|
+
this.authState = data.state;
|
|
162
|
+
}
|
|
163
|
+
} catch (e) {
|
|
164
|
+
Alpine.store('global').showToast(e.message, 'error');
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
|
|
168
|
+
async copyLink() {
|
|
169
|
+
if (!this.authUrl) return;
|
|
170
|
+
await navigator.clipboard.writeText(this.authUrl);
|
|
171
|
+
Alpine.store('global').showToast(Alpine.store('global').t('linkCopied'), 'success');
|
|
172
|
+
},
|
|
173
|
+
|
|
174
|
+
async completeManualAuth() {
|
|
175
|
+
if (!this.callbackInput || !this.authState) return;
|
|
176
|
+
this.submitting = true;
|
|
177
|
+
try {
|
|
178
|
+
const store = Alpine.store('global');
|
|
179
|
+
const {
|
|
180
|
+
response,
|
|
181
|
+
newPassword
|
|
182
|
+
} = await window.utils.request('/api/auth/complete', {
|
|
183
|
+
method: 'POST',
|
|
184
|
+
headers: {
|
|
185
|
+
'Content-Type': 'application/json'
|
|
186
|
+
},
|
|
187
|
+
body: JSON.stringify({
|
|
188
|
+
callbackInput: this.callbackInput,
|
|
189
|
+
state: this.authState
|
|
190
|
+
})
|
|
191
|
+
}, store.webuiPassword);
|
|
192
|
+
if (newPassword) store.webuiPassword = newPassword;
|
|
193
|
+
const data = await response.json();
|
|
194
|
+
if (data.status === 'ok') {
|
|
195
|
+
store.showToast(store.t('accountAddedSuccess'), 'success');
|
|
196
|
+
Alpine.store('data').fetchData();
|
|
197
|
+
document.getElementById('add_account_modal').close();
|
|
198
|
+
this.resetState();
|
|
199
|
+
} else {
|
|
200
|
+
store.showToast(data.error || store.t('authFailed'), 'error');
|
|
201
|
+
}
|
|
202
|
+
} catch (e) {
|
|
203
|
+
Alpine.store('global').showToast(e.message, 'error');
|
|
204
|
+
} finally {
|
|
205
|
+
this.submitting = false;
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
|
|
209
|
+
// ==================== Copilot Device Auth Methods ====================
|
|
210
|
+
|
|
211
|
+
async startCopilotDeviceAuth() {
|
|
212
|
+
const store = Alpine.store('global');
|
|
213
|
+
this.submitting = true;
|
|
214
|
+
|
|
215
|
+
try {
|
|
216
|
+
const { response, newPassword } = await window.utils.request(
|
|
217
|
+
'/api/copilot/device-auth',
|
|
218
|
+
{ method: 'POST', headers: { 'Content-Type': 'application/json' } },
|
|
219
|
+
store.webuiPassword
|
|
220
|
+
);
|
|
221
|
+
if (newPassword) store.webuiPassword = newPassword;
|
|
222
|
+
|
|
223
|
+
const data = await response.json();
|
|
224
|
+
if (data.status === 'ok') {
|
|
225
|
+
this.copilotFlowId = data.flowId;
|
|
226
|
+
this.copilotUserCode = data.userCode;
|
|
227
|
+
this.copilotVerificationUri = data.verificationUri;
|
|
228
|
+
|
|
229
|
+
// Open GitHub verification page
|
|
230
|
+
window.open(data.verificationUri, '_blank', 'width=600,height=700,scrollbars=yes');
|
|
231
|
+
|
|
232
|
+
store.showToast('Enter the code shown below on GitHub to authorize', 'info');
|
|
233
|
+
|
|
234
|
+
// Start polling for token
|
|
235
|
+
this.startCopilotPolling(data.interval || 5);
|
|
236
|
+
} else {
|
|
237
|
+
store.showToast(data.error || 'Failed to start device auth', 'error');
|
|
238
|
+
}
|
|
239
|
+
} catch (e) {
|
|
240
|
+
store.showToast('Device auth failed: ' + e.message, 'error');
|
|
241
|
+
} finally {
|
|
242
|
+
this.submitting = false;
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
|
|
246
|
+
startCopilotPolling(interval) {
|
|
247
|
+
this.copilotPolling = true;
|
|
248
|
+
const poll = async () => {
|
|
249
|
+
if (!this.copilotPolling || !this.copilotFlowId) return;
|
|
250
|
+
|
|
251
|
+
try {
|
|
252
|
+
const store = Alpine.store('global');
|
|
253
|
+
const { response, newPassword } = await window.utils.request(
|
|
254
|
+
'/api/copilot/poll-token',
|
|
255
|
+
{
|
|
256
|
+
method: 'POST',
|
|
257
|
+
headers: { 'Content-Type': 'application/json' },
|
|
258
|
+
body: JSON.stringify({ flowId: this.copilotFlowId })
|
|
259
|
+
},
|
|
260
|
+
store.webuiPassword
|
|
261
|
+
);
|
|
262
|
+
if (newPassword) store.webuiPassword = newPassword;
|
|
263
|
+
|
|
264
|
+
const data = await response.json();
|
|
265
|
+
|
|
266
|
+
if (data.completed) {
|
|
267
|
+
// Success!
|
|
268
|
+
this.stopCopilotPolling();
|
|
269
|
+
store.showToast(`Copilot account ${data.email} added successfully!`, 'success');
|
|
270
|
+
Alpine.store('data').fetchData();
|
|
271
|
+
document.getElementById('add_account_modal').close();
|
|
272
|
+
this.resetState();
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
if (data.status === 'error') {
|
|
277
|
+
this.stopCopilotPolling();
|
|
278
|
+
store.showToast(data.error || 'Device auth failed', 'error');
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Update interval if server says to slow down
|
|
283
|
+
if (data.interval) {
|
|
284
|
+
interval = data.interval;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// Continue polling
|
|
288
|
+
this.copilotPollTimer = setTimeout(poll, interval * 1000);
|
|
289
|
+
} catch (e) {
|
|
290
|
+
this.stopCopilotPolling();
|
|
291
|
+
Alpine.store('global').showToast('Polling error: ' + e.message, 'error');
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
this.copilotPollTimer = setTimeout(poll, interval * 1000);
|
|
296
|
+
},
|
|
297
|
+
|
|
298
|
+
stopCopilotPolling() {
|
|
299
|
+
this.copilotPolling = false;
|
|
300
|
+
if (this.copilotPollTimer) {
|
|
301
|
+
clearTimeout(this.copilotPollTimer);
|
|
302
|
+
this.copilotPollTimer = null;
|
|
303
|
+
}
|
|
304
|
+
},
|
|
305
|
+
|
|
306
|
+
async copyCopilotCode() {
|
|
307
|
+
if (!this.copilotUserCode) return;
|
|
308
|
+
await navigator.clipboard.writeText(this.copilotUserCode);
|
|
309
|
+
Alpine.store('global').showToast('Code copied to clipboard', 'success');
|
|
310
|
+
},
|
|
311
|
+
|
|
312
|
+
// ==================== API Key Methods (Anthropic, OpenAI, GitHub) ==
|
|
313
|
+
|
|
314
|
+
async addAccountWithProvider() {
|
|
315
|
+
return await window.ErrorHandler.withLoading(async () => {
|
|
316
|
+
const store = Alpine.store('global');
|
|
317
|
+
|
|
318
|
+
// Validate inputs
|
|
319
|
+
if (!this.email || !this.email.includes('@')) {
|
|
320
|
+
throw new Error(store.t('invalidEmail') || 'Invalid email address');
|
|
321
|
+
}
|
|
322
|
+
if (!this.apiKey) {
|
|
323
|
+
throw new Error(store.t('apiKeyRequired') || `${this.apiKeyLabel} is required`);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Validate credentials before adding
|
|
327
|
+
store.showToast(store.t('validatingCredentials') || 'Validating credentials...', 'info');
|
|
328
|
+
const validationResult = await this.validateCredentials();
|
|
329
|
+
if (!validationResult.valid) {
|
|
330
|
+
throw new Error(validationResult.error || 'Credential validation failed');
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Add account
|
|
334
|
+
const payload = {
|
|
335
|
+
provider: this.selectedProvider,
|
|
336
|
+
email: this.email,
|
|
337
|
+
apiKey: this.apiKey
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
if (this.customEndpoint && this.customEndpoint.trim()) {
|
|
341
|
+
payload.customApiEndpoint = this.customEndpoint.trim();
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
const { response, newPassword } = await window.utils.request(
|
|
345
|
+
'/api/accounts/add',
|
|
346
|
+
{
|
|
347
|
+
method: 'POST',
|
|
348
|
+
headers: { 'Content-Type': 'application/json' },
|
|
349
|
+
body: JSON.stringify(payload)
|
|
350
|
+
},
|
|
351
|
+
store.webuiPassword
|
|
352
|
+
);
|
|
353
|
+
if (newPassword) store.webuiPassword = newPassword;
|
|
354
|
+
|
|
355
|
+
const data = await response.json();
|
|
356
|
+
if (data.status === 'ok') {
|
|
357
|
+
store.showToast(store.t('accountAdded', { email: this.email }), 'success');
|
|
358
|
+
Alpine.store('data').fetchData();
|
|
359
|
+
document.getElementById('add_account_modal').close();
|
|
360
|
+
this.resetState();
|
|
361
|
+
} else {
|
|
362
|
+
throw new Error(data.error || store.t('addAccountFailed'));
|
|
363
|
+
}
|
|
364
|
+
}, this, 'submitting', { errorMessage: 'Failed to add account' });
|
|
365
|
+
},
|
|
366
|
+
|
|
367
|
+
async validateCredentials() {
|
|
368
|
+
const store = Alpine.store('global');
|
|
369
|
+
|
|
370
|
+
try {
|
|
371
|
+
const { response, newPassword } = await window.utils.request(
|
|
372
|
+
`/api/providers/${this.selectedProvider}/validate`,
|
|
373
|
+
{
|
|
374
|
+
method: 'POST',
|
|
375
|
+
headers: { 'Content-Type': 'application/json' },
|
|
376
|
+
body: JSON.stringify({
|
|
377
|
+
apiKey: this.apiKey,
|
|
378
|
+
customApiEndpoint: this.customEndpoint || undefined
|
|
379
|
+
})
|
|
380
|
+
},
|
|
381
|
+
store.webuiPassword
|
|
382
|
+
);
|
|
383
|
+
if (newPassword) store.webuiPassword = newPassword;
|
|
384
|
+
|
|
385
|
+
const data = await response.json();
|
|
386
|
+
return data; // { valid: boolean, error?: string }
|
|
387
|
+
} catch (e) {
|
|
388
|
+
return { valid: false, error: e.message };
|
|
389
|
+
}
|
|
390
|
+
},
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Reset all state to initial values
|
|
394
|
+
*/
|
|
395
|
+
resetState() {
|
|
396
|
+
this.selectedProvider = 'google';
|
|
397
|
+
this.email = '';
|
|
398
|
+
this.apiKey = '';
|
|
399
|
+
this.customEndpoint = '';
|
|
400
|
+
this.manualMode = false;
|
|
401
|
+
this.authUrl = '';
|
|
402
|
+
this.authState = '';
|
|
403
|
+
this.callbackInput = '';
|
|
404
|
+
this.submitting = false;
|
|
405
|
+
// Stop Copilot polling
|
|
406
|
+
this.stopCopilotPolling();
|
|
407
|
+
this.copilotFlowId = null;
|
|
408
|
+
this.copilotUserCode = '';
|
|
409
|
+
this.copilotVerificationUri = '';
|
|
410
|
+
// Close any open details elements
|
|
411
|
+
const details = document.querySelectorAll('#add_account_modal details[open]');
|
|
412
|
+
details.forEach(d => d.removeAttribute('open'));
|
|
413
|
+
}
|
|
414
|
+
});
|