@chrysb/alphaclaw 0.1.16 → 0.1.18
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/lib/public/css/theme.css +66 -1
- package/lib/public/js/app.js +101 -30
- package/lib/public/js/components/credentials-modal.js +2 -2
- package/lib/public/js/components/envars.js +2 -6
- package/lib/public/js/components/google.js +2 -5
- package/lib/public/js/components/models.js +3 -5
- package/lib/public/js/components/onboarding/welcome-form-step.js +2 -5
- package/lib/public/js/components/scope-picker.js +2 -2
- package/lib/public/js/components/welcome.js +3 -1
- package/lib/server/routes/google.js +1 -2
- package/package.json +1 -1
package/lib/public/css/theme.css
CHANGED
|
@@ -47,4 +47,69 @@ body::before {
|
|
|
47
47
|
/* Google scope picker toggle buttons */
|
|
48
48
|
.scope-btn { background: rgba(255,255,255,0.03); color: var(--text-muted); border: 1px solid var(--border); transition: all 0.15s; }
|
|
49
49
|
.scope-btn:hover { border-color: var(--text-dim); color: var(--text); }
|
|
50
|
-
.scope-btn.active {
|
|
50
|
+
.scope-btn-read.active {
|
|
51
|
+
background: rgba(255, 255, 255, 0.12);
|
|
52
|
+
color: #f3f4f6;
|
|
53
|
+
border-color: rgba(255, 255, 255, 0.35);
|
|
54
|
+
}
|
|
55
|
+
.scope-btn-write.active {
|
|
56
|
+
background: rgba(255, 255, 255, 0.12);
|
|
57
|
+
color: #f3f4f6;
|
|
58
|
+
border-color: rgba(255, 255, 255, 0.35);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/* Reusable cyan action buttons */
|
|
62
|
+
.ac-btn-cyan {
|
|
63
|
+
border: 1px solid var(--accent-dim);
|
|
64
|
+
background: linear-gradient(
|
|
65
|
+
180deg,
|
|
66
|
+
rgba(99, 235, 255, 0.14) 0%,
|
|
67
|
+
rgba(99, 235, 255, 0.08) 100%
|
|
68
|
+
);
|
|
69
|
+
color: var(--accent);
|
|
70
|
+
box-shadow: inset 0 0 0 1px rgba(99, 235, 255, 0.12);
|
|
71
|
+
transition:
|
|
72
|
+
border-color 0.15s ease,
|
|
73
|
+
background 0.15s ease,
|
|
74
|
+
color 0.15s ease,
|
|
75
|
+
box-shadow 0.15s ease,
|
|
76
|
+
transform 0.15s ease;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.ac-btn-cyan:hover:not(:disabled) {
|
|
80
|
+
border-color: rgba(99, 235, 255, 0.7);
|
|
81
|
+
background: linear-gradient(
|
|
82
|
+
180deg,
|
|
83
|
+
rgba(99, 235, 255, 0.24) 0%,
|
|
84
|
+
rgba(99, 235, 255, 0.12) 100%
|
|
85
|
+
);
|
|
86
|
+
color: #b9f8ff;
|
|
87
|
+
box-shadow:
|
|
88
|
+
inset 0 0 0 1px rgba(99, 235, 255, 0.2),
|
|
89
|
+
0 0 12px rgba(99, 235, 255, 0.14);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.ac-btn-cyan:active:not(:disabled) {
|
|
93
|
+
transform: translateY(1px);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.ac-btn-cyan:disabled {
|
|
97
|
+
opacity: 0.5;
|
|
98
|
+
cursor: not-allowed;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.ac-btn-cyan-ghost {
|
|
102
|
+
border: 1px solid var(--accent-dim);
|
|
103
|
+
color: rgba(99, 235, 255, 0.75);
|
|
104
|
+
background: rgba(99, 235, 255, 0.04);
|
|
105
|
+
transition:
|
|
106
|
+
border-color 0.15s ease,
|
|
107
|
+
color 0.15s ease,
|
|
108
|
+
background 0.15s ease;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.ac-btn-cyan-ghost:hover {
|
|
112
|
+
border-color: rgba(99, 235, 255, 0.5);
|
|
113
|
+
color: #a4f3ff;
|
|
114
|
+
background: rgba(99, 235, 255, 0.08);
|
|
115
|
+
}
|
package/lib/public/js/app.js
CHANGED
|
@@ -27,6 +27,9 @@ import { Envars } from "./components/envars.js";
|
|
|
27
27
|
import { ToastContainer, showToast } from "./components/toast.js";
|
|
28
28
|
import { ChevronDownIcon } from "./components/icons.js";
|
|
29
29
|
const html = htm.bind(h);
|
|
30
|
+
const kUiTabStorageKey = "alphaclaw_ui_tab";
|
|
31
|
+
const kUiTabs = ["general", "models", "envars"];
|
|
32
|
+
const kDefaultUiTab = "general";
|
|
30
33
|
|
|
31
34
|
const GeneralTab = ({ onSwitchTab }) => {
|
|
32
35
|
const [googleKey, setGoogleKey] = useState(0);
|
|
@@ -116,15 +119,23 @@ const GeneralTab = ({ onSwitchTab }) => {
|
|
|
116
119
|
if (!syncCron) return;
|
|
117
120
|
setSyncCronEnabled(syncCron.enabled !== false);
|
|
118
121
|
setSyncCronSchedule(syncCron.schedule || "0 * * * *");
|
|
119
|
-
setSyncCronChoice(
|
|
122
|
+
setSyncCronChoice(
|
|
123
|
+
syncCron.enabled === false
|
|
124
|
+
? "disabled"
|
|
125
|
+
: syncCron.schedule || "0 * * * *",
|
|
126
|
+
);
|
|
120
127
|
}, [syncCron?.enabled, syncCron?.schedule]);
|
|
121
128
|
|
|
122
|
-
const saveSyncCronSettings = async ({
|
|
129
|
+
const saveSyncCronSettings = async ({
|
|
130
|
+
enabled = syncCronEnabled,
|
|
131
|
+
schedule = syncCronSchedule,
|
|
132
|
+
}) => {
|
|
123
133
|
if (savingSyncCron) return;
|
|
124
134
|
setSavingSyncCron(true);
|
|
125
135
|
try {
|
|
126
136
|
const data = await updateSyncCron({ enabled, schedule });
|
|
127
|
-
if (!data.ok)
|
|
137
|
+
if (!data.ok)
|
|
138
|
+
throw new Error(data.error || "Could not save sync settings");
|
|
128
139
|
showToast("Sync schedule updated", "success");
|
|
129
140
|
statusPoll.refresh();
|
|
130
141
|
} catch (err) {
|
|
@@ -148,12 +159,26 @@ const GeneralTab = ({ onSwitchTab }) => {
|
|
|
148
159
|
/>
|
|
149
160
|
<${Google} key=${googleKey} gatewayStatus=${gatewayStatus} />
|
|
150
161
|
|
|
151
|
-
${repo &&
|
|
162
|
+
${repo &&
|
|
163
|
+
html`
|
|
152
164
|
<div class="bg-surface border border-border rounded-xl p-4">
|
|
153
165
|
<div class="flex items-center justify-between gap-3">
|
|
154
166
|
<div class="flex items-center gap-2 min-w-0">
|
|
155
|
-
<svg
|
|
156
|
-
|
|
167
|
+
<svg
|
|
168
|
+
class="w-4 h-4 text-gray-400"
|
|
169
|
+
viewBox="0 0 16 16"
|
|
170
|
+
fill="currentColor"
|
|
171
|
+
>
|
|
172
|
+
<path
|
|
173
|
+
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"
|
|
174
|
+
/>
|
|
175
|
+
</svg>
|
|
176
|
+
<a
|
|
177
|
+
href="https://github.com/${repo}"
|
|
178
|
+
target="_blank"
|
|
179
|
+
class="text-sm text-gray-400 hover:text-gray-200 transition-colors truncate"
|
|
180
|
+
>${repo}</a
|
|
181
|
+
>
|
|
157
182
|
</div>
|
|
158
183
|
<div class="flex items-center gap-2 shrink-0">
|
|
159
184
|
<span class="text-xs text-gray-400">Auto-sync</span>
|
|
@@ -164,7 +189,9 @@ const GeneralTab = ({ onSwitchTab }) => {
|
|
|
164
189
|
const nextChoice = e.target.value;
|
|
165
190
|
setSyncCronChoice(nextChoice);
|
|
166
191
|
const nextEnabled = nextChoice !== "disabled";
|
|
167
|
-
const nextSchedule = nextEnabled
|
|
192
|
+
const nextSchedule = nextEnabled
|
|
193
|
+
? nextChoice
|
|
194
|
+
: syncCronSchedule;
|
|
168
195
|
setSyncCronEnabled(nextEnabled);
|
|
169
196
|
setSyncCronSchedule(nextSchedule);
|
|
170
197
|
saveSyncCronSettings({
|
|
@@ -176,7 +203,9 @@ const GeneralTab = ({ onSwitchTab }) => {
|
|
|
176
203
|
class="appearance-none bg-black/30 border border-border rounded-lg pl-2.5 pr-9 py-1.5 text-xs text-gray-300 ${savingSyncCron
|
|
177
204
|
? "opacity-50 cursor-not-allowed"
|
|
178
205
|
: ""}"
|
|
179
|
-
title=${syncCron?.installed === false
|
|
206
|
+
title=${syncCron?.installed === false
|
|
207
|
+
? "Not Installed Yet"
|
|
208
|
+
: syncCronStatusText}
|
|
180
209
|
>
|
|
181
210
|
<option value="disabled">Disabled</option>
|
|
182
211
|
<option value="*/30 * * * *">Every 30 min</option>
|
|
@@ -195,7 +224,7 @@ const GeneralTab = ({ onSwitchTab }) => {
|
|
|
195
224
|
<div class="bg-surface border border-border rounded-xl p-4">
|
|
196
225
|
<div class="flex items-center justify-between">
|
|
197
226
|
<div>
|
|
198
|
-
<h2 class="font-semibold text-sm">Gateway Dashboard</h2>
|
|
227
|
+
<h2 class="font-semibold text-sm">OpenClaw Gateway Dashboard</h2>
|
|
199
228
|
</div>
|
|
200
229
|
<button
|
|
201
230
|
onclick=${async () => {
|
|
@@ -203,18 +232,20 @@ const GeneralTab = ({ onSwitchTab }) => {
|
|
|
203
232
|
setDashboardLoading(true);
|
|
204
233
|
try {
|
|
205
234
|
const data = await fetchDashboardUrl();
|
|
206
|
-
console.log(
|
|
207
|
-
window.open(data.url ||
|
|
235
|
+
console.log("[dashboard] response:", JSON.stringify(data));
|
|
236
|
+
window.open(data.url || "/openclaw", "_blank");
|
|
208
237
|
} catch (err) {
|
|
209
|
-
console.error(
|
|
210
|
-
window.open(
|
|
238
|
+
console.error("[dashboard] error:", err);
|
|
239
|
+
window.open("/openclaw", "_blank");
|
|
211
240
|
}
|
|
212
241
|
setDashboardLoading(false);
|
|
213
242
|
}}
|
|
214
243
|
disabled=${dashboardLoading}
|
|
215
|
-
class="text-xs px-2.5 py-1 rounded-lg border border-border text-gray-500 hover:text-gray-300 hover:border-gray-500 transition-colors ${dashboardLoading
|
|
244
|
+
class="text-xs px-2.5 py-1 rounded-lg border border-border text-gray-500 hover:text-gray-300 hover:border-gray-500 transition-colors ${dashboardLoading
|
|
245
|
+
? "opacity-50 cursor-not-allowed"
|
|
246
|
+
: ""}"
|
|
216
247
|
>
|
|
217
|
-
${dashboardLoading ?
|
|
248
|
+
${dashboardLoading ? "Opening..." : "Open"}
|
|
218
249
|
</button>
|
|
219
250
|
</div>
|
|
220
251
|
<${DevicePairings}
|
|
@@ -241,7 +272,14 @@ const GeneralTab = ({ onSwitchTab }) => {
|
|
|
241
272
|
|
|
242
273
|
function App() {
|
|
243
274
|
const [onboarded, setOnboarded] = useState(null);
|
|
244
|
-
const [tab, setTab] = useState(
|
|
275
|
+
const [tab, setTab] = useState(() => {
|
|
276
|
+
try {
|
|
277
|
+
const savedTab = localStorage.getItem(kUiTabStorageKey);
|
|
278
|
+
return kUiTabs.includes(savedTab) ? savedTab : kDefaultUiTab;
|
|
279
|
+
} catch {
|
|
280
|
+
return kDefaultUiTab;
|
|
281
|
+
}
|
|
282
|
+
});
|
|
245
283
|
const [acVersion, setAcVersion] = useState(null);
|
|
246
284
|
const [acLatest, setAcLatest] = useState(null);
|
|
247
285
|
const [acHasUpdate, setAcHasUpdate] = useState(false);
|
|
@@ -254,6 +292,12 @@ function App() {
|
|
|
254
292
|
.catch(() => setOnboarded(false));
|
|
255
293
|
}, []);
|
|
256
294
|
|
|
295
|
+
useEffect(() => {
|
|
296
|
+
try {
|
|
297
|
+
localStorage.setItem(kUiTabStorageKey, tab);
|
|
298
|
+
} catch {}
|
|
299
|
+
}, [tab]);
|
|
300
|
+
|
|
257
301
|
useEffect(() => {
|
|
258
302
|
if (!onboarded) return;
|
|
259
303
|
let active = true;
|
|
@@ -268,7 +312,10 @@ function App() {
|
|
|
268
312
|
};
|
|
269
313
|
check(true);
|
|
270
314
|
const id = setInterval(() => check(false), 5 * 60 * 1000);
|
|
271
|
-
return () => {
|
|
315
|
+
return () => {
|
|
316
|
+
active = false;
|
|
317
|
+
clearInterval(id);
|
|
318
|
+
};
|
|
272
319
|
}, [onboarded]);
|
|
273
320
|
|
|
274
321
|
const handleAcUpdate = async () => {
|
|
@@ -292,7 +339,10 @@ function App() {
|
|
|
292
339
|
// Still loading onboard status
|
|
293
340
|
if (onboarded === null) {
|
|
294
341
|
return html`
|
|
295
|
-
<div
|
|
342
|
+
<div
|
|
343
|
+
class="min-h-screen flex items-center justify-center"
|
|
344
|
+
style="position: relative; z-index: 1"
|
|
345
|
+
>
|
|
296
346
|
<svg
|
|
297
347
|
class="animate-spin h-6 w-6"
|
|
298
348
|
style="color: var(--text-muted)"
|
|
@@ -320,7 +370,10 @@ function App() {
|
|
|
320
370
|
|
|
321
371
|
if (!onboarded) {
|
|
322
372
|
return html`
|
|
323
|
-
<div
|
|
373
|
+
<div
|
|
374
|
+
class="min-h-screen flex justify-center pt-12 pb-8 px-4"
|
|
375
|
+
style="position: relative; z-index: 1"
|
|
376
|
+
>
|
|
324
377
|
<${Welcome} onComplete=${() => setOnboarded(true)} />
|
|
325
378
|
</div>
|
|
326
379
|
<${ToastContainer} />
|
|
@@ -354,13 +407,17 @@ function App() {
|
|
|
354
407
|
)}
|
|
355
408
|
</nav>
|
|
356
409
|
<div class="sidebar-footer">
|
|
357
|
-
${acHasUpdate && acLatest && !acDismissed
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
410
|
+
${acHasUpdate && acLatest && !acDismissed
|
|
411
|
+
? html`
|
|
412
|
+
<button
|
|
413
|
+
onclick=${handleAcUpdate}
|
|
414
|
+
disabled=${acUpdating}
|
|
415
|
+
class="sidebar-update-btn"
|
|
416
|
+
>
|
|
417
|
+
${acUpdating ? "Updating..." : `Update to v${acLatest}`}
|
|
418
|
+
</button>
|
|
419
|
+
`
|
|
420
|
+
: null}
|
|
364
421
|
</div>
|
|
365
422
|
</div>
|
|
366
423
|
|
|
@@ -380,12 +437,26 @@ function App() {
|
|
|
380
437
|
|
|
381
438
|
<div class="app-statusbar">
|
|
382
439
|
<div class="statusbar-left">
|
|
383
|
-
${acVersion
|
|
440
|
+
${acVersion
|
|
441
|
+
? html`<span style="color: var(--text-muted)">v${acVersion}</span>`
|
|
442
|
+
: null}
|
|
384
443
|
</div>
|
|
385
444
|
<div class="statusbar-right">
|
|
386
|
-
<a href="https://docs.openclaw.ai" target="_blank" rel="noreferrer"
|
|
387
|
-
|
|
388
|
-
|
|
445
|
+
<a href="https://docs.openclaw.ai" target="_blank" rel="noreferrer"
|
|
446
|
+
>docs</a
|
|
447
|
+
>
|
|
448
|
+
<a
|
|
449
|
+
href="https://discord.com/invite/clawd"
|
|
450
|
+
target="_blank"
|
|
451
|
+
rel="noreferrer"
|
|
452
|
+
>discord</a
|
|
453
|
+
>
|
|
454
|
+
<a
|
|
455
|
+
href="https://github.com/openclaw/openclaw"
|
|
456
|
+
target="_blank"
|
|
457
|
+
rel="noreferrer"
|
|
458
|
+
>github</a
|
|
459
|
+
>
|
|
389
460
|
</div>
|
|
390
461
|
</div>
|
|
391
462
|
</div>
|
|
@@ -322,13 +322,13 @@ export const CredentialsModal = ({ visible, onClose, onSaved }) => {
|
|
|
322
322
|
<button
|
|
323
323
|
onclick=${submit}
|
|
324
324
|
disabled=${saving}
|
|
325
|
-
class="flex-1
|
|
325
|
+
class="flex-1 font-medium py-2 rounded-lg text-sm ac-btn-cyan"
|
|
326
326
|
>
|
|
327
327
|
${saving ? "Saving..." : "Connect Google"}
|
|
328
328
|
</button>
|
|
329
329
|
<button
|
|
330
330
|
onclick=${onClose}
|
|
331
|
-
class="px-4
|
|
331
|
+
class="px-4 py-2 rounded-lg text-sm ac-btn-cyan-ghost"
|
|
332
332
|
>
|
|
333
333
|
Cancel
|
|
334
334
|
</button>
|
|
@@ -332,11 +332,7 @@ export const Envars = () => {
|
|
|
332
332
|
<button
|
|
333
333
|
onclick=${handleSave}
|
|
334
334
|
disabled=${!dirty || saving || restartingGateway}
|
|
335
|
-
class="w-full text-sm font-medium px-4 py-2.5 rounded-xl transition-all
|
|
336
|
-
!saving &&
|
|
337
|
-
!restartingGateway
|
|
338
|
-
? "bg-white text-black hover:opacity-85"
|
|
339
|
-
: "bg-gray-800 text-gray-500 cursor-not-allowed"}"
|
|
335
|
+
class="w-full text-sm font-medium px-4 py-2.5 rounded-xl transition-all ac-btn-cyan"
|
|
340
336
|
>
|
|
341
337
|
${saving
|
|
342
338
|
? html`<span class="flex items-center justify-center gap-2">
|
|
@@ -357,7 +353,7 @@ export const Envars = () => {
|
|
|
357
353
|
</svg>
|
|
358
354
|
Saving...
|
|
359
355
|
</span>`
|
|
360
|
-
: "Save
|
|
356
|
+
: "Save changes"}
|
|
361
357
|
</button>
|
|
362
358
|
</div>
|
|
363
359
|
`;
|
|
@@ -175,10 +175,7 @@ export function Google({ gatewayStatus }) {
|
|
|
175
175
|
<button
|
|
176
176
|
onclick=${() => startAuth(email)}
|
|
177
177
|
disabled=${isAuthed && !scopesChanged}
|
|
178
|
-
class="text-xs font-medium px-3 py-1.5 rounded-lg
|
|
179
|
-
!scopesChanged
|
|
180
|
-
? "bg-gray-600 text-gray-400 cursor-not-allowed"
|
|
181
|
-
: "bg-white text-black hover:opacity-85"}"
|
|
178
|
+
class="text-xs font-medium px-3 py-1.5 rounded-lg ac-btn-cyan"
|
|
182
179
|
>
|
|
183
180
|
${isAuthed ? "Update Permissions" : "Sign in with Google"}
|
|
184
181
|
</button>
|
|
@@ -207,7 +204,7 @@ export function Google({ gatewayStatus }) {
|
|
|
207
204
|
</p>
|
|
208
205
|
<button
|
|
209
206
|
onclick=${() => setModalOpen(true)}
|
|
210
|
-
class="
|
|
207
|
+
class="text-sm font-medium px-4 py-2 rounded-lg ac-btn-cyan"
|
|
211
208
|
>
|
|
212
209
|
Set up Google
|
|
213
210
|
</button>
|
|
@@ -320,7 +320,7 @@ export const Models = () => {
|
|
|
320
320
|
? html`
|
|
321
321
|
<button
|
|
322
322
|
onclick=${startCodexAuth}
|
|
323
|
-
class="text-xs font-medium px-3 py-1.5 rounded-lg
|
|
323
|
+
class="text-xs font-medium px-3 py-1.5 rounded-lg ac-btn-cyan"
|
|
324
324
|
>
|
|
325
325
|
Connect Codex OAuth
|
|
326
326
|
</button>
|
|
@@ -357,7 +357,7 @@ export const Models = () => {
|
|
|
357
357
|
<button
|
|
358
358
|
onclick=${completeCodexAuth}
|
|
359
359
|
disabled=${!codexManualInput.trim() || codexExchanging}
|
|
360
|
-
class="text-xs font-medium px-3 py-1.5 rounded-lg
|
|
360
|
+
class="text-xs font-medium px-3 py-1.5 rounded-lg ac-btn-cyan"
|
|
361
361
|
>
|
|
362
362
|
${codexExchanging ? "Completing..." : "Complete Codex OAuth"}
|
|
363
363
|
</button>
|
|
@@ -442,9 +442,7 @@ export const Models = () => {
|
|
|
442
442
|
<button
|
|
443
443
|
onclick=${saveChanges}
|
|
444
444
|
disabled=${!canSaveChanges}
|
|
445
|
-
class="w-full text-sm font-medium px-4 py-2.5 rounded-xl transition-all
|
|
446
|
-
? "bg-white text-black hover:opacity-85"
|
|
447
|
-
: "bg-gray-800 text-gray-500 cursor-not-allowed"}"
|
|
445
|
+
class="w-full text-sm font-medium px-4 py-2.5 rounded-xl transition-all ac-btn-cyan"
|
|
448
446
|
>
|
|
449
447
|
${savingChanges ? "Saving..." : "Save changes"}
|
|
450
448
|
</button>
|
|
@@ -110,7 +110,7 @@ export const WelcomeFormStep = ({
|
|
|
110
110
|
onclick=${startCodexAuth}
|
|
111
111
|
class="text-xs font-medium px-3 py-1.5 rounded-lg ${codexStatus.connected
|
|
112
112
|
? "border border-border text-gray-300 hover:border-gray-500"
|
|
113
|
-
: "
|
|
113
|
+
: "ac-btn-cyan"}"
|
|
114
114
|
>
|
|
115
115
|
${codexStatus.connected ? "Reconnect Codex" : "Connect Codex OAuth"}
|
|
116
116
|
</button>
|
|
@@ -148,10 +148,7 @@ export const WelcomeFormStep = ({
|
|
|
148
148
|
type="button"
|
|
149
149
|
onclick=${completeCodexAuth}
|
|
150
150
|
disabled=${!codexManualInput.trim() || codexExchanging}
|
|
151
|
-
class="text-xs font-medium px-3 py-1.5 rounded-lg
|
|
152
|
-
codexExchanging
|
|
153
|
-
? "bg-gray-700 text-gray-400 cursor-not-allowed"
|
|
154
|
-
: "bg-white text-black hover:opacity-85"}"
|
|
151
|
+
class="text-xs font-medium px-3 py-1.5 rounded-lg ac-btn-cyan"
|
|
155
152
|
>
|
|
156
153
|
${codexExchanging ? "Completing..." : "Complete Codex OAuth"}
|
|
157
154
|
</button>
|
|
@@ -59,8 +59,8 @@ export function ScopePicker({ scopes, onToggle, apiStatus, loading }) {
|
|
|
59
59
|
<span class="text-sm">${s.icon} ${s.label}</span>
|
|
60
60
|
<div class="flex items-center gap-2">
|
|
61
61
|
${apiIndicator}
|
|
62
|
-
<button onclick=${() => onToggle(`${s.key}:read`)} class="scope-btn ${readOn ? 'active' : ''} text-xs px-2 py-0.5 rounded">Read</button>
|
|
63
|
-
<button onclick=${() => onToggle(`${s.key}:write`)} class="scope-btn ${writeOn ? 'active' : ''} text-xs px-2 py-0.5 rounded">Write</button>
|
|
62
|
+
<button onclick=${() => onToggle(`${s.key}:read`)} class="scope-btn scope-btn-read ${readOn ? 'active' : ''} text-xs px-2 py-0.5 rounded">Read</button>
|
|
63
|
+
<button onclick=${() => onToggle(`${s.key}:write`)} class="scope-btn scope-btn-write ${writeOn ? 'active' : ''} text-xs px-2 py-0.5 rounded">Write</button>
|
|
64
64
|
</div>
|
|
65
65
|
</div>`;
|
|
66
66
|
})}
|
|
@@ -224,7 +224,9 @@ export const Welcome = ({ onComplete }) => {
|
|
|
224
224
|
|
|
225
225
|
try {
|
|
226
226
|
const vars = Object.entries(vals)
|
|
227
|
-
.filter(
|
|
227
|
+
.filter(
|
|
228
|
+
([key]) => key !== "MODEL_KEY" && !String(key || "").startsWith("_"),
|
|
229
|
+
)
|
|
228
230
|
.filter(([, v]) => v)
|
|
229
231
|
.map(([key, value]) => ({ key, value }));
|
|
230
232
|
const result = await runOnboard(vars, vals.MODEL_KEY);
|
|
@@ -91,7 +91,6 @@ const registerGoogleRoutes = ({
|
|
|
91
91
|
|
|
92
92
|
const services = req.body.services || [
|
|
93
93
|
"gmail:read",
|
|
94
|
-
"gmail:write",
|
|
95
94
|
"calendar:read",
|
|
96
95
|
"calendar:write",
|
|
97
96
|
"drive:read",
|
|
@@ -208,7 +207,7 @@ const registerGoogleRoutes = ({
|
|
|
208
207
|
const email = req.query.email || "";
|
|
209
208
|
const services = (
|
|
210
209
|
req.query.services ||
|
|
211
|
-
"gmail:read,
|
|
210
|
+
"gmail:read,calendar:read,calendar:write,drive:read,sheets:read,docs:read"
|
|
212
211
|
)
|
|
213
212
|
.split(",")
|
|
214
213
|
.filter(Boolean);
|