@chrysb/alphaclaw 0.5.6 → 0.6.0-beta.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/alphaclaw.js +6 -1
- package/lib/public/css/agents.css +92 -0
- package/lib/public/css/explorer.css +101 -0
- package/lib/public/css/shell.css +15 -4
- package/lib/public/js/app.js +69 -3
- package/lib/public/js/components/action-button.js +5 -0
- package/lib/public/js/components/agents-tab/agent-bindings-section/helpers.js +76 -0
- package/lib/public/js/components/agents-tab/agent-bindings-section/index.js +490 -0
- package/lib/public/js/components/agents-tab/agent-bindings-section/use-agent-bindings.js +256 -0
- package/lib/public/js/components/agents-tab/agent-detail-panel.js +74 -0
- package/lib/public/js/components/agents-tab/agent-identity-section.js +175 -0
- package/lib/public/js/components/agents-tab/agent-overview/index.js +53 -0
- package/lib/public/js/components/agents-tab/agent-overview/manage-card.js +44 -0
- package/lib/public/js/components/agents-tab/agent-overview/model-card.js +158 -0
- package/lib/public/js/components/agents-tab/agent-overview/use-model-card.js +169 -0
- package/lib/public/js/components/agents-tab/agent-overview/use-workspace-card.js +45 -0
- package/lib/public/js/components/agents-tab/agent-overview/workspace-card.js +47 -0
- package/lib/public/js/components/agents-tab/agent-pairing-section.js +265 -0
- package/lib/public/js/components/agents-tab/create-agent-modal.js +189 -0
- package/lib/public/js/components/agents-tab/create-channel-modal.js +323 -0
- package/lib/public/js/components/agents-tab/delete-agent-dialog.js +50 -0
- package/lib/public/js/components/agents-tab/edit-agent-modal.js +109 -0
- package/lib/public/js/components/agents-tab/index.js +148 -0
- package/lib/public/js/components/agents-tab/use-agents.js +89 -0
- package/lib/public/js/components/channel-account-status-badge.js +35 -0
- package/lib/public/js/components/channel-operations-panel.js +33 -0
- package/lib/public/js/components/channels.js +545 -60
- package/lib/public/js/components/envars.js +25 -4
- package/lib/public/js/components/general/index.js +21 -11
- package/lib/public/js/components/general/use-general-tab.js +78 -16
- package/lib/public/js/components/google/gmail-setup-wizard.js +1 -3
- package/lib/public/js/components/google/index.js +28 -30
- package/lib/public/js/components/icons.js +37 -0
- package/lib/public/js/components/models-tab/index.js +58 -224
- package/lib/public/js/components/models-tab/model-picker.js +212 -0
- package/lib/public/js/components/models-tab/use-models.js +17 -14
- package/lib/public/js/components/onboarding/use-welcome-pairing.js +4 -4
- package/lib/public/js/components/onboarding/welcome-pairing-step.js +2 -2
- package/lib/public/js/components/overflow-menu.js +122 -0
- package/lib/public/js/components/pairings.js +36 -8
- package/lib/public/js/components/routes/agents-route.js +27 -0
- package/lib/public/js/components/routes/general-route.js +2 -0
- package/lib/public/js/components/routes/index.js +1 -0
- package/lib/public/js/components/routes/telegram-route.js +2 -2
- package/lib/public/js/components/secret-input.js +8 -1
- package/lib/public/js/components/sidebar.js +64 -26
- package/lib/public/js/components/telegram-workspace/index.js +175 -74
- package/lib/public/js/components/telegram-workspace/manage.js +83 -10
- package/lib/public/js/components/telegram-workspace/onboarding.js +9 -8
- package/lib/public/js/components/webhooks.js +43 -18
- package/lib/public/js/hooks/use-app-shell-controller.js +7 -0
- package/lib/public/js/hooks/use-browse-navigation.js +8 -5
- package/lib/public/js/hooks/use-destination-session-selection.js +8 -1
- package/lib/public/js/lib/api.js +163 -9
- package/lib/public/js/lib/app-navigation.js +2 -1
- package/lib/public/js/lib/channel-create-operation.js +102 -0
- package/lib/public/js/lib/format.js +14 -0
- package/lib/public/js/lib/sse.js +51 -0
- package/lib/public/js/lib/telegram-api.js +38 -18
- package/lib/public/setup.html +1 -0
- package/lib/public/shared/browse-file-policies.json +0 -1
- package/lib/server/agents/service.js +1478 -0
- package/lib/server/constants.js +2 -2
- package/lib/server/env.js +3 -1
- package/lib/server/gateway.js +104 -20
- package/lib/server/gmail-watch.js +29 -2
- package/lib/server/onboarding/import/import-applier.js +0 -1
- package/lib/server/onboarding/index.js +0 -6
- package/lib/server/onboarding/workspace.js +73 -38
- package/lib/server/openclaw-config.js +23 -0
- package/lib/server/operation-events.js +141 -0
- package/lib/server/routes/agents.js +266 -0
- package/lib/server/routes/pairings.js +135 -25
- package/lib/server/routes/system.js +90 -10
- package/lib/server/routes/telegram.js +247 -51
- package/lib/server/telegram-workspace.js +61 -10
- package/lib/server/topic-registry.js +66 -7
- package/lib/server/watchdog.js +39 -1
- package/lib/server/webhooks.js +60 -12
- package/lib/server.js +21 -7
- package/lib/setup/core-prompts/AGENTS.md +6 -5
- package/lib/setup/core-prompts/TOOLS.md +1 -8
- package/package.json +1 -1
- package/lib/setup/skills/control-ui/SKILL.md +0 -62
|
@@ -45,6 +45,7 @@ const kFeatureIconByName = {
|
|
|
45
45
|
},
|
|
46
46
|
};
|
|
47
47
|
const normalizeEnvVarKey = (raw) => raw.trim().toUpperCase().replace(/[^A-Z0-9_]/g, "_");
|
|
48
|
+
const kManagedChannelTokenPattern = /^(TELEGRAM|DISCORD)_BOT_TOKEN(?:_[A-Z0-9_]+)?$/;
|
|
48
49
|
const stripSurroundingQuotes = (raw) => {
|
|
49
50
|
const value = String(raw || "").trim();
|
|
50
51
|
if (value.length < 2) return value;
|
|
@@ -56,6 +57,8 @@ const stripSurroundingQuotes = (raw) => {
|
|
|
56
57
|
if (startsWithSingle && endsWithSingle) return value.slice(1, -1);
|
|
57
58
|
return value;
|
|
58
59
|
};
|
|
60
|
+
const isManagedChannelTokenKey = (key = "") =>
|
|
61
|
+
kManagedChannelTokenPattern.test(String(key || "").trim().toUpperCase());
|
|
59
62
|
const getVarsSignature = (items) =>
|
|
60
63
|
JSON.stringify(
|
|
61
64
|
(items || [])
|
|
@@ -234,7 +237,7 @@ export const Envars = ({ onRestartRequired = () => {} }) => {
|
|
|
234
237
|
setSaving(true);
|
|
235
238
|
try {
|
|
236
239
|
const toSave = vars
|
|
237
|
-
.filter((v) => v.editable)
|
|
240
|
+
.filter((v) => v.editable && !isManagedChannelTokenKey(v?.key))
|
|
238
241
|
.map((v) => ({ key: v.key, value: v.value }));
|
|
239
242
|
const result = await saveEnvVars(toSave);
|
|
240
243
|
const needsRestart = !!result?.restartRequired;
|
|
@@ -281,12 +284,17 @@ export const Envars = ({ onRestartRequired = () => {} }) => {
|
|
|
281
284
|
const addVars = (pairs) => {
|
|
282
285
|
let added = 0;
|
|
283
286
|
const blocked = [];
|
|
287
|
+
const managedChannelKeys = [];
|
|
284
288
|
const addedCustomKeys = [];
|
|
285
289
|
setVars((prev) => {
|
|
286
290
|
const next = [...prev];
|
|
287
291
|
for (const { key: rawKey, value } of pairs) {
|
|
288
292
|
const key = normalizeEnvVarKey(rawKey);
|
|
289
293
|
if (!key) continue;
|
|
294
|
+
if (isManagedChannelTokenKey(key)) {
|
|
295
|
+
managedChannelKeys.push(key);
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
290
298
|
if (reservedKeys.has(key)) {
|
|
291
299
|
blocked.push(key);
|
|
292
300
|
continue;
|
|
@@ -313,7 +321,7 @@ export const Envars = ({ onRestartRequired = () => {} }) => {
|
|
|
313
321
|
if (addedCustomKeys.length) {
|
|
314
322
|
setPendingCustomKeys((prev) => [...prev, ...addedCustomKeys]);
|
|
315
323
|
}
|
|
316
|
-
return { added, blocked };
|
|
324
|
+
return { added, blocked, managedChannelKeys };
|
|
317
325
|
};
|
|
318
326
|
|
|
319
327
|
const handlePaste = (e, fallbackField) => {
|
|
@@ -321,7 +329,7 @@ export const Envars = ({ onRestartRequired = () => {} }) => {
|
|
|
321
329
|
const pairs = parsePaste(text);
|
|
322
330
|
if (pairs.length > 1) {
|
|
323
331
|
e.preventDefault();
|
|
324
|
-
const { added, blocked } = addVars(pairs);
|
|
332
|
+
const { added, blocked, managedChannelKeys } = addVars(pairs);
|
|
325
333
|
setNewKey("");
|
|
326
334
|
setNewVal("");
|
|
327
335
|
if (blocked.length) {
|
|
@@ -331,6 +339,13 @@ export const Envars = ({ onRestartRequired = () => {} }) => {
|
|
|
331
339
|
"error",
|
|
332
340
|
);
|
|
333
341
|
}
|
|
342
|
+
if (managedChannelKeys.length) {
|
|
343
|
+
const uniqueManagedKeys = Array.from(new Set(managedChannelKeys));
|
|
344
|
+
showToast(
|
|
345
|
+
`Channel bot tokens are managed from Channels: ${uniqueManagedKeys.join(", ")}`,
|
|
346
|
+
"error",
|
|
347
|
+
);
|
|
348
|
+
}
|
|
334
349
|
if (added) {
|
|
335
350
|
showToast(`Added ${added} variable${added !== 1 ? "s" : ""}`, "success");
|
|
336
351
|
}
|
|
@@ -367,6 +382,10 @@ export const Envars = ({ onRestartRequired = () => {} }) => {
|
|
|
367
382
|
const handleAddVar = () => {
|
|
368
383
|
const key = normalizeEnvVarKey(newKey);
|
|
369
384
|
if (!key) return;
|
|
385
|
+
if (isManagedChannelTokenKey(key)) {
|
|
386
|
+
showToast(`Channel bot tokens are managed from Channels: ${key}`, "error");
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
370
389
|
if (reservedKeys.has(key)) {
|
|
371
390
|
showToast(`Reserved var can't be added: ${key}`, "error");
|
|
372
391
|
return;
|
|
@@ -376,9 +395,11 @@ export const Envars = ({ onRestartRequired = () => {} }) => {
|
|
|
376
395
|
setNewVal("");
|
|
377
396
|
};
|
|
378
397
|
|
|
398
|
+
const visibleVars = vars.filter((v) => !isManagedChannelTokenKey(v?.key));
|
|
399
|
+
|
|
379
400
|
// Group vars
|
|
380
401
|
const grouped = {};
|
|
381
|
-
for (const v of
|
|
402
|
+
for (const v of visibleVars) {
|
|
382
403
|
const g = v.group || "custom";
|
|
383
404
|
if (!grouped[g]) grouped[g] = [];
|
|
384
405
|
grouped[g].push(v);
|
|
@@ -2,6 +2,7 @@ import { h } from "https://esm.sh/preact";
|
|
|
2
2
|
import htm from "https://esm.sh/htm";
|
|
3
3
|
import { Gateway } from "../gateway.js";
|
|
4
4
|
import { Channels } from "../channels.js";
|
|
5
|
+
import { ChannelOperationsPanel } from "../channel-operations-panel.js";
|
|
5
6
|
import { Pairings } from "../pairings.js";
|
|
6
7
|
import { DevicePairings } from "../device-pairings.js";
|
|
7
8
|
import { Google } from "../google/index.js";
|
|
@@ -17,6 +18,7 @@ export const GeneralTab = ({
|
|
|
17
18
|
statusData = null,
|
|
18
19
|
watchdogData = null,
|
|
19
20
|
doctorStatusData = null,
|
|
21
|
+
agents = [],
|
|
20
22
|
doctorWarningDismissedUntilMs = 0,
|
|
21
23
|
onRefreshStatuses = () => {},
|
|
22
24
|
onSwitchTab = () => {},
|
|
@@ -62,17 +64,25 @@ export const GeneralTab = ({
|
|
|
62
64
|
onOpenDoctor=${() => onSwitchTab("doctor")}
|
|
63
65
|
onDismiss=${onDismissDoctorWarning}
|
|
64
66
|
/>
|
|
65
|
-
<${
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
67
|
+
<${ChannelOperationsPanel}
|
|
68
|
+
channelsSection=${html`
|
|
69
|
+
<${Channels}
|
|
70
|
+
channels=${state.channels}
|
|
71
|
+
agents=${agents}
|
|
72
|
+
onNavigate=${onNavigate}
|
|
73
|
+
onRefreshStatuses=${onRefreshStatuses}
|
|
74
|
+
/>
|
|
75
|
+
`}
|
|
76
|
+
pairingsSection=${html`
|
|
77
|
+
<${Pairings}
|
|
78
|
+
pending=${state.pending}
|
|
79
|
+
channels=${state.channels}
|
|
80
|
+
visible=${state.hasUnpaired}
|
|
81
|
+
statusRefreshing=${state.pairingStatusRefreshing}
|
|
82
|
+
onApprove=${actions.handleApprove}
|
|
83
|
+
onReject=${actions.handleReject}
|
|
84
|
+
/>
|
|
85
|
+
`}
|
|
76
86
|
/>
|
|
77
87
|
<${Features} onSwitchTab=${onSwitchTab} />
|
|
78
88
|
<${Google}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect, useState } from "https://esm.sh/preact/hooks";
|
|
1
|
+
import { useEffect, useRef, useState } from "https://esm.sh/preact/hooks";
|
|
2
2
|
import {
|
|
3
3
|
approveDevice,
|
|
4
4
|
approvePairing,
|
|
@@ -30,6 +30,10 @@ export const useGeneralTab = ({
|
|
|
30
30
|
const [syncCronSchedule, setSyncCronSchedule] = useState(kDefaultSyncCronSchedule);
|
|
31
31
|
const [savingSyncCron, setSavingSyncCron] = useState(false);
|
|
32
32
|
const [syncCronChoice, setSyncCronChoice] = useState(kDefaultSyncCronSchedule);
|
|
33
|
+
const [pairingStatusRefreshing, setPairingStatusRefreshing] = useState(false);
|
|
34
|
+
const [devicePollingEnabled, setDevicePollingEnabled] = useState(false);
|
|
35
|
+
const [cliAutoApproveComplete, setCliAutoApproveComplete] = useState(false);
|
|
36
|
+
const pairingRefreshTimerRef = useRef(null);
|
|
33
37
|
|
|
34
38
|
const status = statusData;
|
|
35
39
|
const watchdogStatus = watchdogData;
|
|
@@ -42,7 +46,15 @@ export const useGeneralTab = ({
|
|
|
42
46
|
|
|
43
47
|
const hasUnpaired = ALL_CHANNELS.some((channel) => {
|
|
44
48
|
const info = channels?.[channel];
|
|
45
|
-
|
|
49
|
+
if (!info) return false;
|
|
50
|
+
const accounts =
|
|
51
|
+
info.accounts && typeof info.accounts === "object" ? info.accounts : {};
|
|
52
|
+
if (Object.keys(accounts).length > 0) {
|
|
53
|
+
return Object.values(accounts).some(
|
|
54
|
+
(acc) => acc && acc.status !== "paired",
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
return info.status !== "paired";
|
|
46
58
|
});
|
|
47
59
|
|
|
48
60
|
const pairingsPoll = usePolling(
|
|
@@ -54,14 +66,17 @@ export const useGeneralTab = ({
|
|
|
54
66
|
{ enabled: hasUnpaired && gatewayStatus === "running" },
|
|
55
67
|
);
|
|
56
68
|
const pending = pairingsPoll.data || [];
|
|
69
|
+
const shouldPollDevices =
|
|
70
|
+
gatewayStatus === "running" && (devicePollingEnabled || !cliAutoApproveComplete);
|
|
57
71
|
|
|
58
72
|
const devicePoll = usePolling(
|
|
59
73
|
async () => {
|
|
60
74
|
const data = await fetchDevicePairings();
|
|
75
|
+
setCliAutoApproveComplete(data?.cliAutoApproveComplete === true);
|
|
61
76
|
return data.pending || [];
|
|
62
77
|
},
|
|
63
78
|
2000,
|
|
64
|
-
{ enabled:
|
|
79
|
+
{ enabled: shouldPollDevices },
|
|
65
80
|
);
|
|
66
81
|
const devicePending = devicePoll.data || [];
|
|
67
82
|
|
|
@@ -69,23 +84,38 @@ export const useGeneralTab = ({
|
|
|
69
84
|
if (!isActive) return;
|
|
70
85
|
onRefreshStatuses();
|
|
71
86
|
pairingsPoll.refresh();
|
|
72
|
-
|
|
73
|
-
|
|
87
|
+
if (shouldPollDevices) {
|
|
88
|
+
devicePoll.refresh();
|
|
89
|
+
}
|
|
90
|
+
}, [
|
|
91
|
+
devicePoll.refresh,
|
|
92
|
+
isActive,
|
|
93
|
+
onRefreshStatuses,
|
|
94
|
+
pairingsPoll.refresh,
|
|
95
|
+
devicePollingEnabled,
|
|
96
|
+
shouldPollDevices,
|
|
97
|
+
]);
|
|
74
98
|
|
|
75
99
|
useEffect(() => {
|
|
76
100
|
if (!restartSignal || !isActive) return;
|
|
77
101
|
onRefreshStatuses();
|
|
78
102
|
pairingsPoll.refresh();
|
|
79
|
-
|
|
103
|
+
if (shouldPollDevices) {
|
|
104
|
+
devicePoll.refresh();
|
|
105
|
+
}
|
|
80
106
|
const t1 = setTimeout(() => {
|
|
81
107
|
onRefreshStatuses();
|
|
82
108
|
pairingsPoll.refresh();
|
|
83
|
-
|
|
109
|
+
if (shouldPollDevices) {
|
|
110
|
+
devicePoll.refresh();
|
|
111
|
+
}
|
|
84
112
|
}, 1200);
|
|
85
113
|
const t2 = setTimeout(() => {
|
|
86
114
|
onRefreshStatuses();
|
|
87
115
|
pairingsPoll.refresh();
|
|
88
|
-
|
|
116
|
+
if (shouldPollDevices) {
|
|
117
|
+
devicePoll.refresh();
|
|
118
|
+
}
|
|
89
119
|
}, 3500);
|
|
90
120
|
return () => {
|
|
91
121
|
clearTimeout(t1);
|
|
@@ -97,6 +127,8 @@ export const useGeneralTab = ({
|
|
|
97
127
|
onRefreshStatuses,
|
|
98
128
|
pairingsPoll.refresh,
|
|
99
129
|
restartSignal,
|
|
130
|
+
devicePollingEnabled,
|
|
131
|
+
shouldPollDevices,
|
|
100
132
|
]);
|
|
101
133
|
|
|
102
134
|
useEffect(() => {
|
|
@@ -108,10 +140,34 @@ export const useGeneralTab = ({
|
|
|
108
140
|
);
|
|
109
141
|
}, [syncCron?.enabled, syncCron?.schedule]);
|
|
110
142
|
|
|
143
|
+
useEffect(
|
|
144
|
+
() => () => {
|
|
145
|
+
if (pairingRefreshTimerRef.current) {
|
|
146
|
+
clearTimeout(pairingRefreshTimerRef.current);
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
[],
|
|
150
|
+
);
|
|
151
|
+
|
|
111
152
|
const refreshAfterPairingAction = () => {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
153
|
+
setPairingStatusRefreshing(true);
|
|
154
|
+
if (pairingRefreshTimerRef.current) {
|
|
155
|
+
clearTimeout(pairingRefreshTimerRef.current);
|
|
156
|
+
}
|
|
157
|
+
pairingRefreshTimerRef.current = setTimeout(() => {
|
|
158
|
+
setPairingStatusRefreshing(false);
|
|
159
|
+
pairingRefreshTimerRef.current = null;
|
|
160
|
+
}, 2800);
|
|
161
|
+
onRefreshStatuses();
|
|
162
|
+
pairingsPoll.refresh();
|
|
163
|
+
setTimeout(() => {
|
|
164
|
+
onRefreshStatuses();
|
|
165
|
+
pairingsPoll.refresh();
|
|
166
|
+
}, 700);
|
|
167
|
+
setTimeout(() => {
|
|
168
|
+
onRefreshStatuses();
|
|
169
|
+
pairingsPoll.refresh();
|
|
170
|
+
}, 1800);
|
|
115
171
|
};
|
|
116
172
|
|
|
117
173
|
const saveSyncCronSettings = async ({
|
|
@@ -146,14 +202,18 @@ export const useGeneralTab = ({
|
|
|
146
202
|
});
|
|
147
203
|
};
|
|
148
204
|
|
|
149
|
-
const handleApprove = async (id, channel) => {
|
|
150
|
-
await approvePairing(id, channel);
|
|
205
|
+
const handleApprove = async (id, channel, accountId = "") => {
|
|
206
|
+
await approvePairing(id, channel, accountId);
|
|
151
207
|
refreshAfterPairingAction();
|
|
152
208
|
};
|
|
153
209
|
|
|
154
|
-
const handleReject = async (id, channel) => {
|
|
155
|
-
|
|
156
|
-
|
|
210
|
+
const handleReject = async (id, channel, accountId = "") => {
|
|
211
|
+
try {
|
|
212
|
+
await rejectPairing(id, channel, accountId);
|
|
213
|
+
refreshAfterPairingAction();
|
|
214
|
+
} catch (err) {
|
|
215
|
+
showToast(err.message || "Could not reject pairing", "error");
|
|
216
|
+
}
|
|
157
217
|
};
|
|
158
218
|
|
|
159
219
|
const handleDeviceApprove = async (id) => {
|
|
@@ -187,6 +247,7 @@ export const useGeneralTab = ({
|
|
|
187
247
|
|
|
188
248
|
const handleOpenDashboard = async () => {
|
|
189
249
|
if (dashboardLoading) return;
|
|
250
|
+
setDevicePollingEnabled(true);
|
|
190
251
|
setDashboardLoading(true);
|
|
191
252
|
try {
|
|
192
253
|
const data = await fetchDashboardUrl();
|
|
@@ -210,6 +271,7 @@ export const useGeneralTab = ({
|
|
|
210
271
|
hasUnpaired,
|
|
211
272
|
openclawVersion,
|
|
212
273
|
pending,
|
|
274
|
+
pairingStatusRefreshing,
|
|
213
275
|
repairingWatchdog,
|
|
214
276
|
repo,
|
|
215
277
|
savingSyncCron,
|
|
@@ -135,9 +135,7 @@ export const GmailSetupWizard = ({
|
|
|
135
135
|
String(projectIdInput || "").trim() ||
|
|
136
136
|
String(clientConfig?.projectId || "").trim() ||
|
|
137
137
|
"<project-id>";
|
|
138
|
-
const hasExistingWebhookSetup = Boolean(
|
|
139
|
-
clientConfig?.configured && clientConfig?.transformExists,
|
|
140
|
-
);
|
|
138
|
+
const hasExistingWebhookSetup = Boolean(clientConfig?.webhookExists);
|
|
141
139
|
const client =
|
|
142
140
|
String(account?.client || clientConfig?.client || "default").trim() ||
|
|
143
141
|
"default";
|
|
@@ -17,6 +17,7 @@ import { CredentialsModal } from "../credentials-modal.js";
|
|
|
17
17
|
import { ConfirmDialog } from "../confirm-dialog.js";
|
|
18
18
|
import { showToast } from "../toast.js";
|
|
19
19
|
import { ActionButton } from "../action-button.js";
|
|
20
|
+
import { OverflowMenu, OverflowMenuItem } from "../overflow-menu.js";
|
|
20
21
|
import { GoogleAccountRow } from "./account-row.js";
|
|
21
22
|
import { AddGoogleAccountModal } from "./add-account-modal.js";
|
|
22
23
|
import { useGoogleAccounts } from "./use-google-accounts.js";
|
|
@@ -455,37 +456,34 @@ export const Google = ({
|
|
|
455
456
|
${accounts.length
|
|
456
457
|
? html`
|
|
457
458
|
<div class="relative">
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
459
|
+
<${OverflowMenu}
|
|
460
|
+
open=${addMenuOpen}
|
|
461
|
+
ariaLabel="Add Google account"
|
|
462
|
+
title="Add Google account"
|
|
463
|
+
onClose=${() => setAddMenuOpen(false)}
|
|
464
|
+
onToggle=${() => setAddMenuOpen((prev) => !prev)}
|
|
465
|
+
renderTrigger=${({ onToggle, ariaLabel, title }) => html`
|
|
466
|
+
<${ActionButton}
|
|
467
|
+
onClick=${onToggle}
|
|
468
|
+
tone="subtle"
|
|
469
|
+
size="sm"
|
|
470
|
+
idleLabel="+ Add Account"
|
|
471
|
+
ariaLabel=${ariaLabel}
|
|
472
|
+
title=${title}
|
|
473
|
+
/>
|
|
474
|
+
`}
|
|
462
475
|
>
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
>
|
|
475
|
-
Company account
|
|
476
|
-
</button>
|
|
477
|
-
${!hasPersonalAccount
|
|
478
|
-
? html`<button
|
|
479
|
-
type="button"
|
|
480
|
-
onclick=${handleAddPersonalClick}
|
|
481
|
-
class="w-full text-left px-2.5 py-1.5 text-xs rounded-md hover:bg-black/30"
|
|
482
|
-
>
|
|
483
|
-
Personal account
|
|
484
|
-
</button>`
|
|
485
|
-
: null}
|
|
486
|
-
</div>
|
|
487
|
-
`
|
|
488
|
-
: null}
|
|
476
|
+
<${OverflowMenuItem} onClick=${handleAddCompanyClick}>
|
|
477
|
+
Company account
|
|
478
|
+
</${OverflowMenuItem}>
|
|
479
|
+
${!hasPersonalAccount
|
|
480
|
+
? html`
|
|
481
|
+
<${OverflowMenuItem} onClick=${handleAddPersonalClick}>
|
|
482
|
+
Personal account
|
|
483
|
+
</${OverflowMenuItem}>
|
|
484
|
+
`
|
|
485
|
+
: null}
|
|
486
|
+
</${OverflowMenu}>
|
|
489
487
|
</div>
|
|
490
488
|
`
|
|
491
489
|
: null}
|
|
@@ -41,6 +41,30 @@ export const CloseIcon = ({ className = "" }) => html`
|
|
|
41
41
|
</svg>
|
|
42
42
|
`;
|
|
43
43
|
|
|
44
|
+
export const AddLineIcon = ({ className = "" }) => html`
|
|
45
|
+
<svg
|
|
46
|
+
class=${className}
|
|
47
|
+
viewBox="0 0 24 24"
|
|
48
|
+
fill="currentColor"
|
|
49
|
+
aria-hidden="true"
|
|
50
|
+
>
|
|
51
|
+
<path d="M11 11V5H13V11H19V13H13V19H11V13H5V11H11Z" />
|
|
52
|
+
</svg>
|
|
53
|
+
`;
|
|
54
|
+
|
|
55
|
+
export const More2FillIcon = ({ className = "" }) => html`
|
|
56
|
+
<svg
|
|
57
|
+
class=${className}
|
|
58
|
+
viewBox="0 0 24 24"
|
|
59
|
+
fill="currentColor"
|
|
60
|
+
aria-hidden="true"
|
|
61
|
+
>
|
|
62
|
+
<path
|
|
63
|
+
d="M5 10C3.89543 10 3 10.8954 3 12C3 13.1046 3.89543 14 5 14C6.10457 14 7 13.1046 7 12C7 10.8954 6.10457 10 5 10ZM12 10C10.8954 10 10 10.8954 10 12C10 13.1046 10.8954 14 12 14C13.1046 14 14 13.1046 14 12C14 10.8954 13.1046 10 12 10ZM19 10C17.8954 10 17 10.8954 17 12C17 13.1046 17.8954 14 19 14C20.1046 14 21 13.1046 21 12C21 10.8954 20.1046 10 19 10Z"
|
|
64
|
+
/>
|
|
65
|
+
</svg>
|
|
66
|
+
`;
|
|
67
|
+
|
|
44
68
|
export const HomeLineIcon = ({ className = "" }) => html`
|
|
45
69
|
<svg
|
|
46
70
|
class=${className}
|
|
@@ -67,6 +91,19 @@ export const FolderLineIcon = ({ className = "" }) => html`
|
|
|
67
91
|
</svg>
|
|
68
92
|
`;
|
|
69
93
|
|
|
94
|
+
export const RobotLineIcon = ({ className = "" }) => html`
|
|
95
|
+
<svg
|
|
96
|
+
class=${className}
|
|
97
|
+
viewBox="0 0 24 24"
|
|
98
|
+
fill="currentColor"
|
|
99
|
+
aria-hidden="true"
|
|
100
|
+
>
|
|
101
|
+
<path
|
|
102
|
+
d="M13.5 2C13.5 2.44425 13.3069 2.84339 13 3.11805V5H18C19.6569 5 21 6.34315 21 8V18C21 19.6569 19.6569 21 18 21H6C4.34315 21 3 19.6569 3 18V8C3 6.34315 4.34315 5 6 5H11V3.11805C10.6931 2.84339 10.5 2.44425 10.5 2C10.5 1.17157 11.1716 0.5 12 0.5C12.8284 0.5 13.5 1.17157 13.5 2ZM6 7C5.44772 7 5 7.44772 5 8V18C5 18.5523 5.44772 19 6 19H18C18.5523 19 19 18.5523 19 18V8C19 7.44772 18.5523 7 18 7H13H11H6ZM2 10H0V16H2V10ZM22 10H24V16H22V10ZM9 14.5C9.82843 14.5 10.5 13.8284 10.5 13C10.5 12.1716 9.82843 11.5 9 11.5C8.17157 11.5 7.5 12.1716 7.5 13C7.5 13.8284 8.17157 14.5 9 14.5ZM15 14.5C15.8284 14.5 16.5 13.8284 16.5 13C16.5 12.1716 15.8284 11.5 15 11.5C14.1716 11.5 13.5 12.1716 13.5 13C13.5 13.8284 14.1716 14.5 15 14.5Z"
|
|
103
|
+
/>
|
|
104
|
+
</svg>
|
|
105
|
+
`;
|
|
106
|
+
|
|
70
107
|
export const MarkdownFillIcon = ({ className = "" }) => html`
|
|
71
108
|
<svg
|
|
72
109
|
class=${className}
|