From 07007b849f51e497cc58f3575b37d216c1f18694 Mon Sep 17 00:00:00 2001
From: Chrys Bader
Date: Thu, 12 Mar 2026 23:16:34 -0700
Subject: [PATCH 1/5] Add WhatsApp channel support and QR login flow parity.
Restore the WhatsApp provisioning and login behavior on top of current main, including plugin setup, route response parity, onboarding/watchdog wiring, and a resizable QR output UI. References #8.
---
lib/public/assets/icons/whatsapp.svg | 14 ++
.../agents-tab/create-channel-modal.js | 48 +++--
.../js/components/channel-login-modal.js | 78 +++++++
lib/public/js/components/channels.js | 63 +++++-
.../components/onboarding/welcome-config.js | 15 +-
.../onboarding/welcome-pairing-step.js | 8 +
lib/public/js/lib/api.js | 9 +
.../js/lib/channel-provider-availability.js | 2 +-
lib/server.js | 2 +-
lib/server/agents/channels.js | 195 +++++++++++++++++-
lib/server/agents/service.js | 1 +
lib/server/agents/shared.js | 52 +++--
lib/server/commands.js | 6 +-
lib/server/constants.js | 7 +
.../onboarding/import/secret-detector.js | 9 +
lib/server/onboarding/openclaw.js | 39 ++++
lib/server/onboarding/validation.js | 2 +-
lib/server/routes/agents.js | 22 ++
lib/server/routes/pairings.js | 4 +-
lib/server/watchdog-notify.js | 26 ++-
tests/server/agents-service.test.js | 149 +++++++++++++
tests/server/onboarding-validation.test.js | 40 ++++
tests/server/routes-agents.test.js | 58 ++++++
tests/server/watchdog-notify.test.js | 53 +++++
24 files changed, 848 insertions(+), 54 deletions(-)
create mode 100644 lib/public/assets/icons/whatsapp.svg
create mode 100644 lib/public/js/components/channel-login-modal.js
create mode 100644 tests/server/onboarding-validation.test.js
create mode 100644 tests/server/watchdog-notify.test.js
diff --git a/lib/public/assets/icons/whatsapp.svg b/lib/public/assets/icons/whatsapp.svg
new file mode 100644
index 0000000..70e0037
--- /dev/null
+++ b/lib/public/assets/icons/whatsapp.svg
@@ -0,0 +1,14 @@
+
+
+
+
+
diff --git a/lib/public/js/components/agents-tab/create-channel-modal.js b/lib/public/js/components/agents-tab/create-channel-modal.js
index 903bc70..dff1153 100644
--- a/lib/public/js/components/agents-tab/create-channel-modal.js
+++ b/lib/public/js/components/agents-tab/create-channel-modal.js
@@ -15,6 +15,7 @@ const kChannelEnvKeys = {
telegram: "TELEGRAM_BOT_TOKEN",
discord: "DISCORD_BOT_TOKEN",
slack: "SLACK_BOT_TOKEN",
+ whatsapp: "WHATSAPP_OWNER_NUMBER",
};
const kChannelExtraEnvKeys = {
@@ -152,10 +153,13 @@ export const CreateChannelModal = ({
}
setName(providerLabel);
}, [provider, providerHasAccounts, nameEditedManually, isEditMode]);
+ const normalizedProvider = String(provider || "").trim();
const isSingleAccountProvider =
- String(provider || "").trim() === "discord" ||
- String(provider || "").trim() === "slack";
- const needsAppToken = String(provider || "").trim() === "slack";
+ normalizedProvider === "discord" ||
+ normalizedProvider === "slack" ||
+ normalizedProvider === "whatsapp";
+ const needsAppToken = normalizedProvider === "slack";
+ const isWhatsApp = normalizedProvider === "whatsapp";
const accountId = useMemo(() => {
if (isEditMode) {
@@ -326,20 +330,34 @@ export const CreateChannelModal = ({
-
- ${needsAppToken ? "Bot Token" : "Token"}
+
+ ${isWhatsApp ? "Owner Number" : needsAppToken ? "Bot Token" : "Token"}
- <${SecretInput}
- value=${token}
- onInput=${(event) => setToken(event.target.value)}
- placeholder=${token ? "" : "Paste bot token"}
- loading=${loadingToken}
- isSecret=${true}
- inputClass="w-full bg-field border border-border rounded-lg px-3 py-2 text-sm font-mono text-body outline-none focus:border-fg-muted"
- />
+ ${isWhatsApp
+ ? html`
+ setToken(event.target.value)}
+ placeholder="+15551234567"
+ class="w-full bg-field border border-border rounded-lg px-3 py-2 text-sm font-mono text-body outline-none focus:border-fg-muted"
+ />
+ `
+ : html`
+ <${SecretInput}
+ value=${token}
+ onInput=${(event) => setToken(event.target.value)}
+ placeholder=${token ? "" : "Paste bot token"}
+ loading=${loadingToken}
+ isSecret=${true}
+ inputClass="w-full bg-field border border-border rounded-lg px-3 py-2 text-sm font-mono text-body outline-none focus:border-fg-muted"
+ />
+ `}
- Saved behind the scenes as
- ${envKey || "CHANNEL_TOKEN"}.
+ ${isWhatsApp
+ ? "E.164 format phone number used for allowlist pairing."
+ : html`Saved behind the scenes as
+ ${envKey || "CHANNEL_TOKEN"}.`}
diff --git a/lib/public/js/components/channel-login-modal.js b/lib/public/js/components/channel-login-modal.js
new file mode 100644
index 0000000..9bfcac9
--- /dev/null
+++ b/lib/public/js/components/channel-login-modal.js
@@ -0,0 +1,78 @@
+import { h } from "https://esm.sh/preact";
+import htm from "https://esm.sh/htm";
+import { ActionButton } from "./action-button.js";
+import { CloseIcon } from "./icons.js";
+import { ModalShell } from "./modal-shell.js";
+import { PageHeader } from "./page-header.js";
+
+const html = htm.bind(h);
+
+export const ChannelLoginModal = ({
+ visible = false,
+ loading = false,
+ title = "Link Channel",
+ output = "",
+ error = "",
+ onRun = async () => {},
+ onClose = () => {},
+}) => {
+ if (!visible) return null;
+ const hasOutput = !!String(output || "").trim();
+ const hasError = !!String(error || "").trim();
+ const displayOutput = hasOutput
+ ? String(output)
+ : hasError
+ ? String(error)
+ : "No output yet. Generate QR to start login.";
+ return html`
+ <${ModalShell}
+ visible=${visible}
+ onClose=${onClose}
+ panelClassName="bg-modal border border-border rounded-xl p-6 max-w-2xl w-full space-y-4"
+ >
+ <${PageHeader}
+ title=${title}
+ actions=${html`
+
+ <${CloseIcon} className="w-3.5 h-3.5 text-gray-300" />
+
+ `}
+ />
+
+
+ Click "Generate QR" to run channel login and capture terminal output.
+
+
+
+
+ <${ActionButton}
+ onClick=${onClose}
+ disabled=${loading}
+ loading=${false}
+ tone="secondary"
+ size="sm"
+ idleLabel="Close"
+ />
+ <${ActionButton}
+ onClick=${onRun}
+ disabled=${loading}
+ loading=${loading}
+ tone="primary"
+ size="sm"
+ idleLabel="Generate QR"
+ loadingLabel="Running..."
+ />
+
+ ${ModalShell}>
+ `;
+};
diff --git a/lib/public/js/components/channels.js b/lib/public/js/components/channels.js
index 1380c45..0af0213 100644
--- a/lib/public/js/components/channels.js
+++ b/lib/public/js/components/channels.js
@@ -8,11 +8,13 @@ import {
import htm from "htm";
import { AddChannelMenu } from "./add-channel-menu.js";
import { ChannelAccountStatusBadge } from "./channel-account-status-badge.js";
+import { ChannelLoginModal } from "./channel-login-modal.js";
import { ConfirmDialog } from "./confirm-dialog.js";
import { OverflowMenu, OverflowMenuItem } from "./overflow-menu.js";
import {
deleteChannelAccount,
fetchChannelAccounts,
+ runChannelAccountLogin,
updateChannelAccount,
} from "../lib/api.js";
import { useCachedFetch } from "../hooks/use-cached-fetch.js";
@@ -27,11 +29,12 @@ import { showToast } from "./toast.js";
const html = htm.bind(h);
-const ALL_CHANNELS = ["telegram", "discord", "slack"];
+const ALL_CHANNELS = ["telegram", "discord", "slack", "whatsapp"];
const kChannelMeta = {
telegram: { label: "Telegram", iconSrc: "/assets/icons/telegram.svg" },
discord: { label: "Discord", iconSrc: "/assets/icons/discord.svg" },
slack: { label: "Slack", iconSrc: "/assets/icons/slack.svg" },
+ whatsapp: { label: "WhatsApp", iconSrc: "/assets/icons/whatsapp.svg" },
};
const getChannelMeta = (channelId = "") => {
@@ -156,6 +159,10 @@ export const Channels = ({
const channelAccounts = Array.isArray(channelAccountsPayload?.channels)
? channelAccountsPayload.channels
: [];
+ const [loginAccount, setLoginAccount] = useState(null);
+ const [loginOutput, setLoginOutput] = useState("");
+ const [loginError, setLoginError] = useState("");
+ const [loginRunning, setLoginRunning] = useState(false);
const loadChannelAccounts = useCallback(async () => {
try {
@@ -163,7 +170,6 @@ export const Channels = ({
} catch {}
}, [refreshChannelAccounts]);
-
const configuredChannelMap = useMemo(
() =>
new Map(
@@ -259,6 +265,31 @@ export const Channels = ({
setSaving(false);
}
};
+ const handleRunChannelLogin = async () => {
+ if (!loginAccount) return;
+ setLoginRunning(true);
+ setLoginError("");
+ setLoginOutput("");
+ try {
+ const result = await runChannelAccountLogin({
+ provider: loginAccount.provider,
+ accountId: loginAccount.id,
+ });
+ const combinedOutput = [result?.stdout || "", result?.stderr || ""]
+ .filter(Boolean)
+ .join("\n\n")
+ .trim();
+ setLoginOutput(combinedOutput || "No terminal output captured.");
+ if (result?.completed) {
+ showToast("Channel linked", "success");
+ }
+ } catch (error) {
+ setLoginError(String(error?.message || "Could not start channel login"));
+ } finally {
+ setLoginRunning(false);
+ }
+ };
+
const openCreateChannelModal = (provider) => {
setMenuOpenId("");
setEditingAccount({
@@ -396,6 +427,20 @@ export const Channels = ({
>
Edit
${OverflowMenuItem}>
+ ${channelId === "whatsapp"
+ ? html`
+ <${OverflowMenuItem}
+ onClick=${() => {
+ setMenuOpenId("");
+ setLoginAccount(accountData);
+ setLoginOutput("");
+ setLoginError("");
+ }}
+ >
+ Link WhatsApp (QR)
+ ${OverflowMenuItem}>
+ `
+ : null}
<${OverflowMenuItem}
className="text-status-error hover:text-status-error"
onClick=${() => {
@@ -518,6 +563,20 @@ export const Channels = ({
setDeletingAccount(null);
}}
/>
+ <${ChannelLoginModal}
+ visible=${!!loginAccount}
+ loading=${loginRunning}
+ title=${`Link ${String(loginAccount?.name || "WhatsApp").trim()} via QR`}
+ output=${loginOutput}
+ error=${loginError}
+ onRun=${handleRunChannelLogin}
+ onClose=${() => {
+ if (loginRunning) return;
+ setLoginAccount(null);
+ setLoginOutput("");
+ setLoginError("");
+ }}
+ />
`;
};
diff --git a/lib/public/js/components/onboarding/welcome-config.js b/lib/public/js/components/onboarding/welcome-config.js
index 59ce6b1..8a7ff9d 100644
--- a/lib/public/js/components/onboarding/welcome-config.js
+++ b/lib/public/js/components/onboarding/welcome-config.js
@@ -151,8 +151,21 @@ export const kWelcomeGroups = [
>${" "}→ App-Level Tokens (needs${" "}connections:write${" "}scope)`,
placeholder: "xapp-...",
},
+ {
+ key: "WHATSAPP_OWNER_NUMBER",
+ label: "WhatsApp Owner Number",
+ hint: html`E.164 format phone number${" "}·${" "}full guide `,
+ placeholder: "+15551234567",
+ isText: true,
+ },
],
- validate: (vals) => !!(vals.TELEGRAM_BOT_TOKEN || vals.DISCORD_BOT_TOKEN || (vals.SLACK_BOT_TOKEN && vals.SLACK_APP_TOKEN)),
+ validate: (vals) => !!(vals.TELEGRAM_BOT_TOKEN || vals.DISCORD_BOT_TOKEN || (vals.SLACK_BOT_TOKEN && vals.SLACK_APP_TOKEN) || vals.WHATSAPP_OWNER_NUMBER),
},
{
id: "tools",
diff --git a/lib/public/js/components/onboarding/welcome-pairing-step.js b/lib/public/js/components/onboarding/welcome-pairing-step.js
index b7ee0ea..de0987d 100644
--- a/lib/public/js/components/onboarding/welcome-pairing-step.js
+++ b/lib/public/js/components/onboarding/welcome-pairing-step.js
@@ -14,6 +14,14 @@ const kChannelMeta = {
label: "Discord",
iconSrc: "/assets/icons/discord.svg",
},
+ slack: {
+ label: "Slack",
+ iconSrc: "/assets/icons/slack.svg",
+ },
+ whatsapp: {
+ label: "WhatsApp",
+ iconSrc: "/assets/icons/whatsapp.svg",
+ },
};
const PairingRow = ({ pairing, onApprove, onReject }) => {
diff --git a/lib/public/js/lib/api.js b/lib/public/js/lib/api.js
index f3cb4f9..b185aa0 100644
--- a/lib/public/js/lib/api.js
+++ b/lib/public/js/lib/api.js
@@ -993,6 +993,15 @@ export const deleteChannelAccount = async (payload) => {
return parseJsonOrThrow(res, "Could not delete channel account");
};
+export const runChannelAccountLogin = async (payload) => {
+ const res = await authFetch("/api/channels/accounts/login", {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify(payload || {}),
+ });
+ return parseJsonOrThrow(res, "Could not run channel login");
+};
+
export const fetchAgent = async (agentId) => {
const res = await authFetch(`/api/agents/${encodeURIComponent(String(agentId || ""))}`);
return parseJsonOrThrow(res, "Could not load agent");
diff --git a/lib/public/js/lib/channel-provider-availability.js b/lib/public/js/lib/channel-provider-availability.js
index 531975b..ba46437 100644
--- a/lib/public/js/lib/channel-provider-availability.js
+++ b/lib/public/js/lib/channel-provider-availability.js
@@ -1,4 +1,4 @@
-const kSingleAccountChannelProviders = new Set(["discord", "slack"]);
+const kSingleAccountChannelProviders = new Set(["discord", "slack", "whatsapp"]);
const hasConfiguredAccounts = ({ configuredChannelMap, provider }) => {
const channelEntry = configuredChannelMap instanceof Map
diff --git a/lib/server.js b/lib/server.js
index 082186d..4a4d3a0 100644
--- a/lib/server.js
+++ b/lib/server.js
@@ -216,7 +216,7 @@ const webhookMiddleware = createWebhookMiddleware({
const telegramApi = createTelegramApi(() => process.env.TELEGRAM_BOT_TOKEN);
const discordApi = createDiscordApi(() => process.env.DISCORD_BOT_TOKEN);
const slackApi = createSlackApi(() => process.env.SLACK_BOT_TOKEN);
-const watchdogNotifier = createWatchdogNotifier({ telegramApi, discordApi, slackApi });
+const watchdogNotifier = createWatchdogNotifier({ telegramApi, discordApi, slackApi, clawCmd });
const watchdog = createWatchdog({
clawCmd,
launchGatewayProcess,
diff --git a/lib/server/agents/channels.js b/lib/server/agents/channels.js
index 5833404..ea431e6 100644
--- a/lib/server/agents/channels.js
+++ b/lib/server/agents/channels.js
@@ -101,8 +101,6 @@ const createChannelsDomain = ({
const provider = normalizeChannelProvider(input.provider);
const name =
String(input.name || "").trim() || kChannelLabels[provider] || provider;
- const token = String(input.token || "").trim();
- if (!token) throw new Error("Channel token is required");
const cfg = withNormalizedAgentsConfig({
OPENCLAW_DIR,
@@ -144,7 +142,9 @@ const createChannelsDomain = ({
);
}
if (
- (provider === "discord" || provider === "slack") &&
+ (provider === "discord" ||
+ provider === "slack" ||
+ provider === "whatsapp") &&
Object.keys(existingAccounts).length > 0
) {
throw new Error(
@@ -152,6 +152,22 @@ const createChannelsDomain = ({
);
}
+ if (provider === "whatsapp") {
+ return await createWhatsAppChannelAccount({
+ input,
+ cfg,
+ agentId,
+ accountId,
+ name,
+ normalizedChannelConfig,
+ existingAccounts,
+ onProgress,
+ });
+ }
+
+ const token = String(input.token || "").trim();
+ if (!token) throw new Error("Channel token is required");
+
const envKey = deriveChannelEnvKey({ provider, accountId });
const extraEnvKeys = deriveChannelExtraEnvKeys({ provider, accountId });
const appToken = String(input.appToken || "").trim();
@@ -160,7 +176,9 @@ const createChannelsDomain = ({
}
const tokenField = kChannelTokenFields[provider];
const currentEnvVars = readEnvFile();
- const previousEnvVars = Array.isArray(currentEnvVars) ? currentEnvVars : [];
+ const previousEnvVars = Array.isArray(currentEnvVars)
+ ? currentEnvVars
+ : [];
const duplicateEnvEntry = previousEnvVars.find((entry) => {
const existingKey = String(entry?.key || "").trim();
const existingValue = String(entry?.value || "").trim();
@@ -583,7 +601,7 @@ const createChannelsDomain = ({
throw new Error(`Channel account "${provider}/${accountId}" not found`);
}
- if (provider === "discord") {
+ if (provider === "discord" || provider === "whatsapp") {
const nextCfg = withNormalizedAgentsConfig({
OPENCLAW_DIR,
cfg: loadConfig({ fsImpl, OPENCLAW_DIR }),
@@ -656,6 +674,9 @@ const createChannelsDomain = ({
}
cleanupChannelAccountPairingFiles({ provider, accountId });
+ if (provider === "whatsapp") {
+ await restartGateway();
+ }
return { ok: true };
}
@@ -766,11 +787,175 @@ const createChannelsDomain = ({
}));
};
+ const createWhatsAppChannelAccount = async ({
+ input,
+ cfg,
+ agentId,
+ accountId,
+ name,
+ normalizedChannelConfig,
+ existingAccounts,
+ onProgress,
+ }) => {
+ const ownerNumber = String(input.token || "").trim();
+ if (!ownerNumber) throw new Error("WhatsApp owner number is required");
+
+ const envKey = deriveChannelEnvKey({ provider: "whatsapp", accountId });
+ const currentEnvVars = readEnvFile();
+ const previousEnvVars = Array.isArray(currentEnvVars) ? currentEnvVars : [];
+ const previousConfig = cloneJson(cfg);
+
+ const nextEnvVars = previousEnvVars.filter(
+ (entry) => String(entry?.key || "").trim() !== envKey,
+ );
+ nextEnvVars.push({ key: envKey, value: ownerNumber });
+
+ try {
+ onProgress({ phase: "configuring", label: "Configuring..." });
+ writeEnvFile(nextEnvVars);
+ reloadEnv();
+
+ const nextCfg = withNormalizedAgentsConfig({
+ OPENCLAW_DIR,
+ cfg: loadConfig({ fsImpl, OPENCLAW_DIR }),
+ });
+ ensurePluginAllowed({ cfg: nextCfg, pluginKey: "whatsapp" });
+ saveConfig({ fsImpl, OPENCLAW_DIR, config: nextCfg });
+
+ onProgress({ phase: "configuring", label: "Adding channel..." });
+ const addArgs = [
+ "channels add",
+ "--channel whatsapp",
+ accountId !== "default" ? `--account ${shellEscapeArg(accountId)}` : "",
+ name ? `--name ${shellEscapeArg(name)}` : "",
+ `--token ${shellEscapeArg(ownerNumber)}`,
+ ].filter(Boolean);
+ const addResult = await clawCmd(addArgs.join(" "), {
+ quiet: true,
+ timeoutMs: 30000,
+ });
+ if (!addResult?.ok) {
+ throw new Error(
+ addResult?.stderr ||
+ addResult?.stdout ||
+ "Could not add WhatsApp channel account",
+ );
+ }
+
+ const refreshedCfg = withNormalizedAgentsConfig({
+ OPENCLAW_DIR,
+ cfg: loadConfig({ fsImpl, OPENCLAW_DIR }),
+ });
+
+ const nextAccounts = { ...existingAccounts };
+ nextAccounts[accountId] = {
+ ...(nextAccounts[accountId] &&
+ typeof nextAccounts[accountId] === "object"
+ ? nextAccounts[accountId]
+ : {}),
+ ...(name ? { name } : {}),
+ allowFrom: [`\${${envKey}}`],
+ groupAllowFrom: [`\${${envKey}}`],
+ dmPolicy: "allowlist",
+ groupPolicy: "allowlist",
+ selfChatMode: true,
+ };
+ normalizedChannelConfig.accounts = nextAccounts;
+ normalizedChannelConfig.enabled = true;
+ if (!String(normalizedChannelConfig.defaultAccount || "").trim()) {
+ normalizedChannelConfig.defaultAccount = "default";
+ }
+ refreshedCfg.channels =
+ refreshedCfg.channels && typeof refreshedCfg.channels === "object"
+ ? { ...refreshedCfg.channels }
+ : {};
+ refreshedCfg.channels.whatsapp = normalizedChannelConfig;
+
+ const bindSpec = buildBindingSpec({ provider: "whatsapp", accountId });
+ appendBindingToConfig({
+ cfg: refreshedCfg,
+ agentId,
+ match: normalizeBindingMatch({ channel: "whatsapp", accountId }),
+ });
+ saveConfig({ fsImpl, OPENCLAW_DIR, config: refreshedCfg });
+
+ onProgress({ phase: "restarting", label: "Rebooting..." });
+ await restartGateway();
+ } catch (error) {
+ try {
+ await clawCmd(
+ [
+ "channels remove",
+ "--channel whatsapp",
+ accountId !== "default" ? `--account ${shellEscapeArg(accountId)}` : "",
+ "--delete",
+ ]
+ .filter(Boolean)
+ .join(" "),
+ { quiet: true, timeoutMs: 30000 },
+ );
+ } catch {}
+ try {
+ writeEnvFile(previousEnvVars);
+ reloadEnv();
+ } catch {}
+ try {
+ saveConfig({ fsImpl, OPENCLAW_DIR, config: previousConfig });
+ } catch {}
+ throw error;
+ }
+
+ return {
+ channel: "whatsapp",
+ account: { id: accountId, name, envKey },
+ binding: {
+ agentId,
+ match: normalizeBindingMatch({ channel: "whatsapp", accountId }),
+ },
+ restartRequired: true,
+ };
+ };
+
+ const runChannelAccountLogin = async ({
+ provider: rawProvider,
+ accountId: rawAccountId,
+ } = {}) => {
+ const provider = normalizeChannelProvider(rawProvider);
+ if (provider !== "whatsapp") {
+ throw new Error("Channel login is currently only supported for WhatsApp");
+ }
+ const accountId = String(rawAccountId || "").trim() || "default";
+ const loginArgs = [
+ "channels login",
+ `--channel ${shellEscapeArg(provider)}`,
+ accountId !== "default" ? `--account ${shellEscapeArg(accountId)}` : "",
+ ].filter(Boolean);
+ const loginStartedAt = Date.now();
+ const result = await clawCmd(loginArgs.join(" "), {
+ quiet: true,
+ timeoutMs: 12000,
+ killSignal: "SIGKILL",
+ });
+ const elapsedMs = Date.now() - loginStartedAt;
+ console.log(
+ `[channels] login ${provider}/${accountId} finished ok=${!!result?.ok} code=${String(
+ result?.code ?? "",
+ )} elapsedMs=${elapsedMs}`,
+ );
+ return {
+ ok: !!result?.ok,
+ stdout: String(result?.stdout || ""),
+ stderr: String(result?.stderr || ""),
+ completed: !!result?.ok,
+ };
+ };
+
return {
getChannelAccountToken,
createChannelAccount,
updateChannelAccount,
deleteChannelAccount,
+ runChannelAccountLogin,
listConfiguredChannelAccountsWithMaskedTokens,
};
};
diff --git a/lib/server/agents/service.js b/lib/server/agents/service.js
index d09e213..69cf95a 100644
--- a/lib/server/agents/service.js
+++ b/lib/server/agents/service.js
@@ -41,6 +41,7 @@ const createAgentsService = ({
createChannelAccount: channelsDomain.createChannelAccount,
updateChannelAccount: channelsDomain.updateChannelAccount,
deleteChannelAccount: channelsDomain.deleteChannelAccount,
+ runChannelAccountLogin: channelsDomain.runChannelAccountLogin,
listConfiguredChannelAccounts:
channelsDomain.listConfiguredChannelAccountsWithMaskedTokens,
};
diff --git a/lib/server/agents/shared.js b/lib/server/agents/shared.js
index 0c80d1e..abbad1a 100644
--- a/lib/server/agents/shared.js
+++ b/lib/server/agents/shared.js
@@ -14,6 +14,7 @@ const kChannelEnvKeys = {
telegram: "TELEGRAM_BOT_TOKEN",
discord: "DISCORD_BOT_TOKEN",
slack: "SLACK_BOT_TOKEN",
+ whatsapp: "WHATSAPP_OWNER_NUMBER",
};
const kChannelExtraEnvKeys = {
slack: ["SLACK_APP_TOKEN"],
@@ -22,6 +23,7 @@ const kChannelTokenFields = {
telegram: "botToken",
discord: "token",
slack: "botToken",
+ // WhatsApp uses owner number, not a bot token field
};
const kChannelExtraTokenFields = {
slack: ["appToken"],
@@ -30,6 +32,13 @@ const kChannelLabels = {
telegram: "Telegram",
discord: "Discord",
slack: "Slack",
+ whatsapp: "WhatsApp",
+};
+const kChannelProviderAliases = {
+ wa: "whatsapp",
+ "whats-app": "whatsapp",
+ whats_app: "whatsapp",
+ "whats app": "whatsapp",
};
const kMaskedChannelToken = "********";
@@ -149,7 +158,7 @@ const normalizeChannelProvider = (value) => {
.trim()
.toLowerCase();
if (!provider || !kChannelEnvKeys[provider]) {
- throw new Error("Unsupported channel provider");
+ throw new Error(`Unsupported channel provider "${provider}"`);
}
return provider;
};
@@ -509,27 +518,26 @@ const listConfiguredChannelAccounts = ({ fsImpl, OPENCLAW_DIR, cfg }) => {
});
return {
channel: String(channelId || "").trim(),
- accounts: normalizedAccountIds
- .map((accountId) => {
- const accountConfig =
- accountId === "default" && accountIds.length === 0
- ? config
- : accountsConfig?.[accountId] || {};
- return {
- id: accountId,
- name: String(accountConfig?.name || "").trim(),
- envKey: deriveChannelEnvKey({ provider: channelId, accountId }),
- boundAgentId:
- boundAccountMap.get(
- `${String(channelId || "").trim()}:${accountId}`,
- ) || "",
- paired: Number(pairedCounts.get(accountId) || 0),
- status:
- Number(pairedCounts.get(accountId) || 0) > 0
- ? "paired"
- : "configured",
- };
- }),
+ accounts: normalizedAccountIds.map((accountId) => {
+ const accountConfig =
+ accountId === "default" && accountIds.length === 0
+ ? config
+ : accountsConfig?.[accountId] || {};
+ return {
+ id: accountId,
+ name: String(accountConfig?.name || "").trim(),
+ envKey: deriveChannelEnvKey({ provider: channelId, accountId }),
+ boundAgentId:
+ boundAccountMap.get(
+ `${String(channelId || "").trim()}:${accountId}`,
+ ) || "",
+ paired: Number(pairedCounts.get(accountId) || 0),
+ status:
+ Number(pairedCounts.get(accountId) || 0) > 0
+ ? "paired"
+ : "configured",
+ };
+ }),
};
})
.filter(Boolean);
diff --git a/lib/server/commands.js b/lib/server/commands.js
index 4b1e2af..2da1d76 100644
--- a/lib/server/commands.js
+++ b/lib/server/commands.js
@@ -32,7 +32,10 @@ const createCommands = ({ gatewayEnv }) => {
});
});
- const clawCmd = (cmd, { quiet = false, timeoutMs = 15000 } = {}) =>
+ const clawCmd = (
+ cmd,
+ { quiet = false, timeoutMs = 15000, killSignal = "SIGTERM" } = {},
+ ) =>
new Promise((resolve) => {
if (!quiet) console.log(`[alphaclaw] Running: openclaw ${cmd}`);
exec(
@@ -40,6 +43,7 @@ const createCommands = ({ gatewayEnv }) => {
{
env: gatewayEnv(),
timeout: timeoutMs,
+ killSignal,
},
(err, stdout, stderr) => {
const result = {
diff --git a/lib/server/constants.js b/lib/server/constants.js
index 4f674c4..638636d 100644
--- a/lib/server/constants.js
+++ b/lib/server/constants.js
@@ -249,6 +249,12 @@ const kKnownVars = [
group: "channels",
hint: "From Basic Information → App-Level Tokens (xapp-...)",
},
+ {
+ key: "WHATSAPP_OWNER_NUMBER",
+ label: "WhatsApp Owner Number",
+ group: "channels",
+ hint: "E.164 number, e.g. +15551234567",
+ },
{
key: "MISTRAL_API_KEY",
label: "Mistral API Key",
@@ -351,6 +357,7 @@ const kChannelDefs = {
telegram: { envKey: "TELEGRAM_BOT_TOKEN" },
discord: { envKey: "DISCORD_BOT_TOKEN" },
slack: { envKey: "SLACK_BOT_TOKEN", extraEnvKeys: ["SLACK_APP_TOKEN"] },
+ whatsapp: { envKey: "WHATSAPP_OWNER_NUMBER", sync: false },
};
const kProtectedBrowsePaths = new Set(
Array.isArray(kBrowseFilePolicies?.protectedPaths)
diff --git a/lib/server/onboarding/import/secret-detector.js b/lib/server/onboarding/import/secret-detector.js
index e092c58..4f49e9e 100644
--- a/lib/server/onboarding/import/secret-detector.js
+++ b/lib/server/onboarding/import/secret-detector.js
@@ -311,6 +311,15 @@ const extractPreFillValues = ({ fs, baseDir, configFiles = [] }) => {
if (channels.discord?.token && !isAlreadyEnvRef(channels.discord.token)) {
preFill.DISCORD_BOT_TOKEN = channels.discord.token;
}
+ const whatsAppAllowFrom = Array.isArray(channels.whatsapp?.allowFrom)
+ ? channels.whatsapp.allowFrom
+ : [];
+ const whatsAppOwner = whatsAppAllowFrom.find(
+ (v) => v && !isAlreadyEnvRef(String(v)),
+ );
+ if (whatsAppOwner) {
+ preFill.WHATSAPP_OWNER_NUMBER = String(whatsAppOwner);
+ }
const braveKey = cfg.tools?.web?.search?.apiKey;
if (braveKey && !isAlreadyEnvRef(braveKey)) {
diff --git a/lib/server/onboarding/openclaw.js b/lib/server/onboarding/openclaw.js
index 8bf9a7b..bc6973f 100644
--- a/lib/server/onboarding/openclaw.js
+++ b/lib/server/onboarding/openclaw.js
@@ -198,6 +198,19 @@ const applyFreshOnboardingChannels = ({ cfg, varMap }) => {
ensurePluginAllowed({ cfg, pluginKey: "slack" });
console.log("[onboard] Slack configured");
}
+ if (varMap.WHATSAPP_OWNER_NUMBER) {
+ cfg.channels.whatsapp = {
+ enabled: true,
+ allowFrom: [varMap.WHATSAPP_OWNER_NUMBER],
+ groupAllowFrom: [varMap.WHATSAPP_OWNER_NUMBER],
+ dmPolicy: "allowlist",
+ groupPolicy: "allowlist",
+ selfChatMode: true,
+ };
+ cfg.plugins.entries.whatsapp = { enabled: true };
+ ensurePluginAllowed({ cfg, pluginKey: "whatsapp" });
+ console.log("[onboard] WhatsApp configured");
+ }
ensureUsageTrackerPluginEntry(cfg);
};
@@ -280,6 +293,32 @@ const writeManagedImportOpenclawConfig = ({ fs, openclawDir, varMap }) => {
ensurePluginAllowed({ cfg, pluginKey: "slack" });
}
+ if (varMap.WHATSAPP_OWNER_NUMBER) {
+ const existingWhatsApp = cfg.channels.whatsapp || {};
+ const existingAllowFrom = Array.isArray(existingWhatsApp.allowFrom)
+ ? existingWhatsApp.allowFrom
+ : [];
+ const ownerRef = "${WHATSAPP_OWNER_NUMBER}";
+ cfg.channels.whatsapp = {
+ ...existingWhatsApp,
+ enabled: true,
+ allowFrom: existingAllowFrom.includes(ownerRef)
+ ? existingAllowFrom
+ : [...existingAllowFrom, ownerRef],
+ groupAllowFrom: existingAllowFrom.includes(ownerRef)
+ ? existingAllowFrom
+ : [...existingAllowFrom, ownerRef],
+ dmPolicy: "allowlist",
+ groupPolicy: "allowlist",
+ selfChatMode: true,
+ };
+ cfg.plugins.entries.whatsapp = {
+ ...(cfg.plugins.entries.whatsapp || {}),
+ enabled: true,
+ };
+ ensurePluginAllowed({ cfg, pluginKey: "whatsapp" });
+ }
+
fs.writeFileSync(configPath, JSON.stringify(cfg, null, 2));
};
diff --git a/lib/server/onboarding/validation.js b/lib/server/onboarding/validation.js
index 9b1ccbd..7301c64 100644
--- a/lib/server/onboarding/validation.js
+++ b/lib/server/onboarding/validation.js
@@ -89,7 +89,7 @@ const validateOnboardingInput = ({ vars, modelKey, resolveModelProvider, hasCode
? hasAiByProvider[selectedProvider]
: hasAnyAi;
const hasGithub = !!(githubToken && githubRepoInput);
- const hasChannel = !!(varMap.TELEGRAM_BOT_TOKEN || varMap.DISCORD_BOT_TOKEN || (varMap.SLACK_BOT_TOKEN && varMap.SLACK_APP_TOKEN));
+ const hasChannel = !!(varMap.TELEGRAM_BOT_TOKEN || varMap.DISCORD_BOT_TOKEN || (varMap.SLACK_BOT_TOKEN && varMap.SLACK_APP_TOKEN) || varMap.WHATSAPP_OWNER_NUMBER);
if (!hasAi) {
if (selectedProvider === "openai-codex") {
diff --git a/lib/server/routes/agents.js b/lib/server/routes/agents.js
index e0fce94..c1b9f4a 100644
--- a/lib/server/routes/agents.js
+++ b/lib/server/routes/agents.js
@@ -124,6 +124,28 @@ const registerAgentRoutes = ({
}
});
+ app.post("/api/channels/accounts/login", async (req, res) => {
+ try {
+ const body = req.body || {};
+ const result = await agentsService.runChannelAccountLogin({
+ provider: body.provider,
+ accountId: body.accountId,
+ });
+ return res.json({
+ ok: true,
+ completed: !!result?.ok,
+ stdout: String(result?.stdout || ""),
+ stderr: String(result?.stderr || ""),
+ code: result?.code ?? null,
+ });
+ } catch (error) {
+ const status = String(error.message || "").includes("only supported")
+ ? 400
+ : 500;
+ return res.status(status).json({ ok: false, error: error.message });
+ }
+ });
+
app.delete("/api/channels/accounts", async (req, res) => {
try {
const body = req.body || {};
diff --git a/lib/server/routes/pairings.js b/lib/server/routes/pairings.js
index 30fa6de..8778a31 100644
--- a/lib/server/routes/pairings.js
+++ b/lib/server/routes/pairings.js
@@ -5,7 +5,7 @@ const { buildManagedPaths } = require("../internal-files-migration");
const { parseJsonObjectFromNoisyOutput } = require("../utils/json");
const { quoteShellArg } = require("../utils/shell");
-const kAllowedPairingChannels = new Set(["telegram", "discord", "slack"]);
+const kAllowedPairingChannels = new Set(["telegram", "discord", "slack", "whatsapp"]);
const kSafePairingArgPattern = /^[\w\-:.]+$/;
const kDevicesListCliTimeoutMs = 5000;
const quoteCliArg = (value) => quoteShellArg(value, { strategy: "single" });
@@ -112,7 +112,7 @@ const registerPairingRoutes = ({ app, clawCmd, isOnboarded, fsModule = fs, openc
}
const pending = [];
- const channels = ["telegram", "discord", "slack"];
+ const channels = ["telegram", "discord", "slack", "whatsapp"];
for (const ch of channels) {
try {
diff --git a/lib/server/watchdog-notify.js b/lib/server/watchdog-notify.js
index 8cc1128..989817e 100644
--- a/lib/server/watchdog-notify.js
+++ b/lib/server/watchdog-notify.js
@@ -36,12 +36,13 @@ const getPairedIds = (channel) => {
const formatDiscordMessage = (message) =>
String(message || "").replace(/(? {
+const createWatchdogNotifier = ({ telegramApi, discordApi, slackApi, clawCmd }) => {
const notify = async (message) => {
const summary = {
telegram: { sent: 0, failed: 0, skipped: false, targets: 0 },
discord: { sent: 0, failed: 0, skipped: false, targets: 0 },
slack: { sent: 0, failed: 0, skipped: false, targets: 0 },
+ whatsapp: { sent: 0, failed: 0, skipped: false, targets: 0 },
};
const telegramTargets = getPairedIds("telegram");
summary.telegram.targets = telegramTargets.length;
@@ -94,8 +95,27 @@ const createWatchdogNotifier = ({ telegramApi, discordApi, slackApi }) => {
}
}
- const sent = summary.telegram.sent + summary.discord.sent + summary.slack.sent;
- const failed = summary.telegram.failed + summary.discord.failed + summary.slack.failed;
+ const whatsappTargets = getPairedIds("whatsapp");
+ summary.whatsapp.targets = whatsappTargets.length;
+ if (!clawCmd || !process.env.WHATSAPP_OWNER_NUMBER || whatsappTargets.length === 0) {
+ summary.whatsapp.skipped = true;
+ } else {
+ for (const target of whatsappTargets) {
+ try {
+ await clawCmd(
+ `message --channel whatsapp --target ${String(target || "").trim()} ${JSON.stringify(String(message || ""))}`,
+ { quiet: true, timeoutMs: 30000 },
+ );
+ summary.whatsapp.sent += 1;
+ } catch (err) {
+ summary.whatsapp.failed += 1;
+ console.error(`[watchdog] whatsapp notification failed for ${target}: ${err.message}`);
+ }
+ }
+ }
+
+ const sent = summary.telegram.sent + summary.discord.sent + summary.slack.sent + summary.whatsapp.sent;
+ const failed = summary.telegram.failed + summary.discord.failed + summary.slack.failed + summary.whatsapp.failed;
return {
ok: sent > 0,
sent,
diff --git a/tests/server/agents-service.test.js b/tests/server/agents-service.test.js
index cf1c6c7..e06d46c 100644
--- a/tests/server/agents-service.test.js
+++ b/tests/server/agents-service.test.js
@@ -1356,6 +1356,155 @@ describe("server/agents/service", () => {
).rejects.toThrow("Slack supports a single channel account");
});
+ it("creates a whatsapp channel account with allowlist defaults", async () => {
+ const fsMock = buildFsMock({
+ initialConfig: {
+ agents: {
+ list: [{ id: "main", default: true }],
+ },
+ },
+ });
+ const writeEnvFile = vi.fn();
+ const reloadEnv = vi.fn();
+ const restartGateway = vi.fn(async () => {});
+ const service = createAgentsService({
+ fs: fsMock,
+ OPENCLAW_DIR: "/test/.openclaw",
+ readEnvFile: vi.fn(() => []),
+ writeEnvFile,
+ reloadEnv,
+ restartGateway,
+ clawCmd: vi.fn(async () => ({ ok: true })),
+ });
+
+ const result = await service.createChannelAccount({
+ provider: "whatsapp",
+ name: "WhatsApp",
+ accountId: "default",
+ token: "+15551234567",
+ agentId: "main",
+ });
+
+ expect(result).toMatchObject({
+ channel: "whatsapp",
+ account: {
+ id: "default",
+ name: "WhatsApp",
+ envKey: "WHATSAPP_OWNER_NUMBER",
+ },
+ binding: {
+ agentId: "main",
+ match: { channel: "whatsapp", accountId: "default" },
+ },
+ });
+ expect(writeEnvFile).toHaveBeenCalledWith(
+ expect.arrayContaining([
+ { key: "WHATSAPP_OWNER_NUMBER", value: "+15551234567" },
+ ]),
+ );
+ expect(reloadEnv).toHaveBeenCalled();
+ expect(restartGateway).toHaveBeenCalled();
+ const savedConfig = fsMock.readConfig();
+ expect(savedConfig.channels?.whatsapp?.accounts?.default).toMatchObject({
+ name: "WhatsApp",
+ dmPolicy: "allowlist",
+ groupPolicy: "allowlist",
+ selfChatMode: true,
+ });
+ });
+
+ it("prevents creating multiple whatsapp channel accounts", async () => {
+ const fsMock = buildFsMock({
+ initialConfig: {
+ agents: {
+ list: [{ id: "main", default: true }],
+ },
+ channels: {
+ whatsapp: {
+ enabled: true,
+ defaultAccount: "default",
+ accounts: {
+ default: {
+ allowFrom: ["${WHATSAPP_OWNER_NUMBER}"],
+ },
+ },
+ },
+ },
+ },
+ });
+ const service = createAgentsService({
+ fs: fsMock,
+ OPENCLAW_DIR: "/test/.openclaw",
+ readEnvFile: vi.fn(() => [{ key: "WHATSAPP_OWNER_NUMBER", value: "+15551234567" }]),
+ writeEnvFile: vi.fn(),
+ reloadEnv: vi.fn(),
+ restartGateway: vi.fn(async () => {}),
+ clawCmd: vi.fn(async () => ({ ok: true })),
+ });
+
+ await expect(
+ service.createChannelAccount({
+ provider: "whatsapp",
+ name: "WhatsApp 2",
+ accountId: "alerts",
+ token: "+15557654321",
+ agentId: "main",
+ }),
+ ).rejects.toThrow("WhatsApp supports a single channel account");
+ });
+
+ it("runs channel account login for whatsapp", async () => {
+ const fsMock = buildFsMock({
+ initialConfig: {},
+ });
+ const clawCmd = vi.fn(async () => ({
+ ok: true,
+ stdout: "QR code displayed",
+ stderr: "",
+ }));
+ const service = createAgentsService({
+ fs: fsMock,
+ OPENCLAW_DIR: "/test/.openclaw",
+ readEnvFile: vi.fn(() => []),
+ writeEnvFile: vi.fn(),
+ reloadEnv: vi.fn(),
+ restartGateway: vi.fn(async () => {}),
+ clawCmd,
+ });
+
+ const result = await service.runChannelAccountLogin({
+ provider: "whatsapp",
+ accountId: "default",
+ });
+
+ expect(result.ok).toBe(true);
+ expect(result.completed).toBe(true);
+ expect(clawCmd).toHaveBeenCalledWith(
+ expect.stringContaining("channels login"),
+ expect.objectContaining({ quiet: true }),
+ );
+ });
+
+ it("rejects channel login for non-whatsapp providers", async () => {
+ const fsMock = buildFsMock({ initialConfig: {} });
+ const service = createAgentsService({
+ fs: fsMock,
+ OPENCLAW_DIR: "/test/.openclaw",
+ readEnvFile: vi.fn(() => []),
+ writeEnvFile: vi.fn(),
+ reloadEnv: vi.fn(),
+ restartGateway: vi.fn(async () => {}),
+ clawCmd: vi.fn(async () => ({ ok: true })),
+ });
+
+ await expect(
+ service.runChannelAccountLogin({
+ provider: "telegram",
+ accountId: "default",
+ }),
+ ).rejects.toThrow("Channel login is currently only supported for WhatsApp");
+ });
+
it("updates channel account name and bound agent", () => {
const fsMock = buildFsMock({
initialConfig: {
diff --git a/tests/server/onboarding-validation.test.js b/tests/server/onboarding-validation.test.js
new file mode 100644
index 0000000..27ba929
--- /dev/null
+++ b/tests/server/onboarding-validation.test.js
@@ -0,0 +1,40 @@
+const { validateOnboardingInput } = require("../../lib/server/onboarding/validation");
+
+const resolveModelProvider = (modelKey) => String(modelKey || "").split("/")[0];
+
+describe("server/onboarding/validation", () => {
+ it("accepts whatsapp owner number as the required channel credential", () => {
+ const result = validateOnboardingInput({
+ vars: [
+ { key: "OPENAI_API_KEY", value: "sk-test-123" },
+ { key: "GITHUB_TOKEN", value: "ghp_test_123" },
+ { key: "GITHUB_WORKSPACE_REPO", value: "owner/repo" },
+ { key: "WHATSAPP_OWNER_NUMBER", value: "+15551234567" },
+ ],
+ modelKey: "openai/gpt-5.1-codex",
+ resolveModelProvider,
+ hasCodexOauthProfile: () => false,
+ });
+
+ expect(result.ok).toBe(true);
+ });
+
+ it("rejects when no channel credentials are provided", () => {
+ const result = validateOnboardingInput({
+ vars: [
+ { key: "OPENAI_API_KEY", value: "sk-test-123" },
+ { key: "GITHUB_TOKEN", value: "ghp_test_123" },
+ { key: "GITHUB_WORKSPACE_REPO", value: "owner/repo" },
+ ],
+ modelKey: "openai/gpt-5.1-codex",
+ resolveModelProvider,
+ hasCodexOauthProfile: () => false,
+ });
+
+ expect(result).toEqual({
+ ok: false,
+ status: 400,
+ error: "At least one channel token is required",
+ });
+ });
+});
diff --git a/tests/server/routes-agents.test.js b/tests/server/routes-agents.test.js
index d67dc2b..57c9dbd 100644
--- a/tests/server/routes-agents.test.js
+++ b/tests/server/routes-agents.test.js
@@ -50,6 +50,12 @@ const createAgentsServiceMock = () => ({
token: "123:abc",
})),
deleteChannelAccount: vi.fn(() => ({ ok: true })),
+ runChannelAccountLogin: vi.fn(() => ({
+ ok: true,
+ stdout: "QR code displayed",
+ stderr: "",
+ completed: true,
+ })),
getAgent: vi.fn((id) =>
id === "main" ? { id: "main", name: "Main Agent", default: true } : null,
),
@@ -282,6 +288,58 @@ describe("server/routes/agents", () => {
expect(response.body.appToken).toBe("xapp-token");
});
+ it("runs channel login on POST /api/channels/accounts/login", async () => {
+ const agentsService = createAgentsServiceMock();
+ const app = createApp(agentsService);
+
+ const response = await request(app)
+ .post("/api/channels/accounts/login")
+ .send({ provider: "whatsapp", accountId: "default" });
+
+ expect(response.status).toBe(200);
+ expect(response.body.ok).toBe(true);
+ expect(response.body.completed).toBe(true);
+ expect(agentsService.runChannelAccountLogin).toHaveBeenCalledWith({
+ provider: "whatsapp",
+ accountId: "default",
+ });
+ });
+
+ it("returns login output with completed=false when CLI login is not complete", async () => {
+ const agentsService = createAgentsServiceMock();
+ agentsService.runChannelAccountLogin.mockReturnValue({
+ ok: false,
+ stdout: "Waiting for WhatsApp connection...",
+ stderr: "",
+ code: 1,
+ });
+ const app = createApp(agentsService);
+
+ const response = await request(app)
+ .post("/api/channels/accounts/login")
+ .send({ provider: "whatsapp", accountId: "default" });
+
+ expect(response.status).toBe(200);
+ expect(response.body.ok).toBe(true);
+ expect(response.body.completed).toBe(false);
+ expect(response.body.stdout).toContain("Waiting for WhatsApp connection");
+ });
+
+ it("returns 400 for unsupported channel login provider", async () => {
+ const agentsService = createAgentsServiceMock();
+ agentsService.runChannelAccountLogin.mockImplementation(() => {
+ throw new Error("Channel login is currently only supported for WhatsApp");
+ });
+ const app = createApp(agentsService);
+
+ const response = await request(app)
+ .post("/api/channels/accounts/login")
+ .send({ provider: "telegram", accountId: "default" });
+
+ expect(response.status).toBe(400);
+ expect(response.body.ok).toBe(false);
+ });
+
it("deletes a configured channel account on DELETE /api/channels/accounts", async () => {
const agentsService = createAgentsServiceMock();
const app = createApp(agentsService);
diff --git a/tests/server/watchdog-notify.test.js b/tests/server/watchdog-notify.test.js
new file mode 100644
index 0000000..18698d7
--- /dev/null
+++ b/tests/server/watchdog-notify.test.js
@@ -0,0 +1,53 @@
+const fs = require("fs");
+
+const originalExistsSync = fs.existsSync;
+const originalReaddirSync = fs.readdirSync;
+const originalReadFileSync = fs.readFileSync;
+const { createWatchdogNotifier } = require("../../lib/server/watchdog-notify");
+
+describe("server/watchdog-notify", () => {
+ const originalEnv = { ...process.env };
+
+ afterEach(() => {
+ fs.existsSync = originalExistsSync;
+ fs.readdirSync = originalReaddirSync;
+ fs.readFileSync = originalReadFileSync;
+ process.env = { ...originalEnv };
+ });
+
+ it("delivers whatsapp watchdog notices via clawCmd message action", async () => {
+ process.env.WHATSAPP_OWNER_NUMBER = "+15551234567";
+ fs.existsSync = vi.fn((targetPath) =>
+ String(targetPath || "").endsWith("/credentials"),
+ );
+ fs.readdirSync = vi.fn((targetPath) => {
+ if (String(targetPath || "").endsWith("/credentials")) {
+ return ["whatsapp-default-allowFrom.json"];
+ }
+ return [];
+ });
+ fs.readFileSync = vi.fn((targetPath) => {
+ if (
+ String(targetPath || "").endsWith(
+ "/credentials/whatsapp-default-allowFrom.json",
+ )
+ ) {
+ return JSON.stringify({ allowFrom: ["15551234567"] });
+ }
+ return "{}";
+ });
+
+ const clawCmd = vi.fn(async () => ({ ok: true, stdout: "sent", stderr: "" }));
+ const notifier = createWatchdogNotifier({ clawCmd });
+
+ const result = await notifier.notify("Gateway healthy again");
+
+ expect(result.ok).toBe(true);
+ expect(result.sent).toBe(1);
+ expect(result.channels.whatsapp.sent).toBe(1);
+ expect(clawCmd).toHaveBeenCalledWith(
+ expect.stringContaining("message --channel whatsapp"),
+ expect.objectContaining({ quiet: true }),
+ );
+ });
+});
From 99f4ca5547ee46c4013c42bf90c8acf3facb35b2 Mon Sep 17 00:00:00 2001
From: Chrys Bader
Date: Thu, 12 Mar 2026 23:27:42 -0700
Subject: [PATCH 2/5] Simplify onboarding by keeping WhatsApp post-setup.
Remove WhatsApp from onboarding channel inputs and pairing-step plumbing while keeping the post-setup channel flow intact, and fix completion copy spacing for dynamic channel names.
---
.../components/onboarding/welcome-config.js | 20 ++++++-------------
.../onboarding/welcome-pairing-step.js | 9 +++------
lib/public/js/components/welcome/index.js | 1 -
.../js/components/welcome/use-welcome.js | 2 +-
4 files changed, 10 insertions(+), 22 deletions(-)
diff --git a/lib/public/js/components/onboarding/welcome-config.js b/lib/public/js/components/onboarding/welcome-config.js
index 8a7ff9d..facce0f 100644
--- a/lib/public/js/components/onboarding/welcome-config.js
+++ b/lib/public/js/components/onboarding/welcome-config.js
@@ -151,21 +151,13 @@ export const kWelcomeGroups = [
>${" "}→ App-Level Tokens (needs${" "}connections:write${" "}scope)`,
placeholder: "xapp-...",
},
- {
- key: "WHATSAPP_OWNER_NUMBER",
- label: "WhatsApp Owner Number",
- hint: html`E.164 format phone number${" "}·${" "}full guide `,
- placeholder: "+15551234567",
- isText: true,
- },
],
- validate: (vals) => !!(vals.TELEGRAM_BOT_TOKEN || vals.DISCORD_BOT_TOKEN || (vals.SLACK_BOT_TOKEN && vals.SLACK_APP_TOKEN) || vals.WHATSAPP_OWNER_NUMBER),
+ validate: (vals) =>
+ !!(
+ vals.TELEGRAM_BOT_TOKEN ||
+ vals.DISCORD_BOT_TOKEN ||
+ (vals.SLACK_BOT_TOKEN && vals.SLACK_APP_TOKEN)
+ ),
},
{
id: "tools",
diff --git a/lib/public/js/components/onboarding/welcome-pairing-step.js b/lib/public/js/components/onboarding/welcome-pairing-step.js
index de0987d..3e3a4d0 100644
--- a/lib/public/js/components/onboarding/welcome-pairing-step.js
+++ b/lib/public/js/components/onboarding/welcome-pairing-step.js
@@ -87,7 +87,6 @@ const PairingRow = ({ pairing, onApprove, onReject }) => {
export const WelcomePairingStep = ({
channel,
pairings,
- channels,
loading,
error,
onApprove,
@@ -102,15 +101,13 @@ export const WelcomePairingStep = ({
: "Channel",
iconSrc: "",
};
- const channelInfo = channels?.[channel];
if (!channel) {
return html`
- Missing channel configuration. Go back and add a Telegram or Discord bot
- token.
+ Missing channel configuration. Go back and add a channel credential.
`;
}
@@ -124,8 +121,8 @@ export const WelcomePairingStep = ({
🎉 Setup complete
- Your ${channelMeta.label} channel is connected. You can switch
- to ${channelMeta.label} and start using your agent now.
+ Your ${channelMeta.label} channel is connected. You can switch to${" "}
+ ${channelMeta.label} and start using your agent now.
Continue to the dashboard to explore extras like Google Workspace
diff --git a/lib/public/js/components/welcome/index.js b/lib/public/js/components/welcome/index.js
index 8121f65..fd61edc 100644
--- a/lib/public/js/components/welcome/index.js
+++ b/lib/public/js/components/welcome/index.js
@@ -66,7 +66,6 @@ export const Welcome = ({ onComplete, acVersion }) => {
? html`<${WelcomePairingStep}
channel=${state.selectedPairingChannel}
pairings=${state.pairingRequestsPoll.data || []}
- channels=${state.pairingChannels}
loading=${!state.pairingStatusPoll.data}
error=${state.pairingError}
onApprove=${actions.handlePairingApprove}
diff --git a/lib/public/js/components/welcome/use-welcome.js b/lib/public/js/components/welcome/use-welcome.js
index bc6c724..3e7e612 100644
--- a/lib/public/js/components/welcome/use-welcome.js
+++ b/lib/public/js/components/welcome/use-welcome.js
@@ -271,7 +271,7 @@ export const useWelcome = ({ onComplete }) => {
const pairingChannel = getPreferredPairingChannel(normalizedVals);
if (!pairingChannel) {
throw new Error(
- "No Telegram or Discord bot token configured for pairing.",
+ "No channel credential configured for pairing.",
);
}
setVals((prev) => ({
From 0c91e3128fc1fee6a63e25b15a0dbf9962b80f8a Mon Sep 17 00:00:00 2001
From: Chrys Bader
Date: Sat, 21 Mar 2026 22:02:37 -0700
Subject: [PATCH 3/5] build: regenerate UI assets for whatsapp branch
---
lib/public/css/tailwind.generated.css | 2 +-
lib/public/dist/app.bundle.js | 2558 +++++++++++++------------
2 files changed, 1318 insertions(+), 1242 deletions(-)
diff --git a/lib/public/css/tailwind.generated.css b/lib/public/css/tailwind.generated.css
index 270c757..4c942ab 100644
--- a/lib/public/css/tailwind.generated.css
+++ b/lib/public/css/tailwind.generated.css
@@ -1 +1 @@
-*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:JetBrains Mono,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.\!visible{visibility:visible!important}.visible{visibility:visible}.invisible{visibility:hidden}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.inset-x-0{left:0;right:0}.bottom-0{bottom:0}.bottom-3{bottom:.75rem}.bottom-4{bottom:1rem}.left-0{left:0}.left-3{left:.75rem}.right-0{right:0}.right-2\.5{right:.625rem}.right-3{right:.75rem}.right-4{right:1rem}.right-5{right:1.25rem}.right-6{right:1.5rem}.top-0{top:0}.top-1\/2{top:50%}.top-4{top:1rem}.top-5{top:1.25rem}.top-6{top:1.5rem}.top-full{top:100%}.z-10{z-index:10}.z-20{z-index:20}.z-50{z-index:50}.z-\[60\]{z-index:60}.z-\[80\]{z-index:80}.-mx-2{margin-left:-.5rem;margin-right:-.5rem}.-mx-3{margin-left:-.75rem;margin-right:-.75rem}.mx-auto{margin-left:auto;margin-right:auto}.-ml-0\.5{margin-left:-.125rem}.mb-0\.5{margin-bottom:.125rem}.mb-1{margin-bottom:.25rem}.mb-12{margin-bottom:3rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.ml-1{margin-left:.25rem}.ml-3{margin-left:.75rem}.ml-auto{margin-left:auto}.mr-2\.5{margin-right:.625rem}.mt-0{margin-top:0}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-1\.5{margin-top:.375rem}.mt-10{margin-top:2.5rem}.mt-2{margin-top:.5rem}.mt-2\.5{margin-top:.625rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-8{margin-top:2rem}.line-clamp-1{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.contents{display:contents}.hidden{display:none}.h-0\.5{height:.125rem}.h-1{height:.25rem}.h-1\.5{height:.375rem}.h-10{height:2.5rem}.h-12{height:3rem}.h-2{height:.5rem}.h-2\.5{height:.625rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-40{height:10rem}.h-44{height:11rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-9{height:2.25rem}.h-\[22px\]{height:22px}.h-\[34px\]{height:34px}.h-full{height:100%}.h-px{height:1px}.max-h-80{max-height:20rem}.max-h-\[66vh\]{max-height:66vh}.max-h-\[92vh\]{max-height:92vh}.min-h-6{min-height:1.5rem}.min-h-\[200px\]{min-height:200px}.min-h-\[220px\]{min-height:220px}.min-h-\[26rem\]{min-height:26rem}.min-h-\[300px\]{min-height:300px}.min-h-\[320px\]{min-height:320px}.min-h-screen{min-height:100vh}.w-1\.5{width:.375rem}.w-10{width:2.5rem}.w-12{width:3rem}.w-2{width:.5rem}.w-2\.5{width:.625rem}.w-24{width:6rem}.w-28{width:7rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-32{width:8rem}.w-36{width:9rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-64{width:16rem}.w-7{width:1.75rem}.w-72{width:18rem}.w-8{width:2rem}.w-9{width:2.25rem}.w-auto{width:auto}.w-full{width:100%}.min-w-0{min-width:0}.min-w-\[88px\]{min-width:88px}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.max-w-64{max-width:16rem}.max-w-80{max-width:20rem}.max-w-full{max-width:100%}.max-w-lg{max-width:32rem}.max-w-md{max-width:28rem}.max-w-sm{max-width:24rem}.max-w-xl{max-width:36rem}.flex-1{flex:1 1 0%}.flex-shrink-0,.shrink-0{flex-shrink:0}.table-fixed{table-layout:fixed}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-y-1\/2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y:-50%}.-rotate-90{--tw-rotate:-90deg}.-rotate-90,.rotate-180{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-180{--tw-rotate:180deg}.rotate-90{--tw-rotate:90deg}.rotate-90,.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.cursor-default{cursor:default}.cursor-help{cursor:help}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize-y{resize:vertical}.resize{resize:both}.list-inside{list-style-position:inside}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.list-none{list-style-type:none}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-x-1\.5{-moz-column-gap:.375rem;column-gap:.375rem}.gap-x-3{-moz-column-gap:.75rem;column-gap:.75rem}.gap-y-1{row-gap:.25rem}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.125rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.125rem*var(--tw-space-y-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.375rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem*var(--tw-space-y-reverse))}.space-y-10>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(2.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2.5rem*var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-2\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.625rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.625rem*var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.25rem*var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-top-width:calc(1px*(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px*var(--tw-divide-y-reverse))}.divide-border>:not([hidden])~:not([hidden]){border-color:var(--border)}.justify-self-start{justify-self:start}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-visible{overflow:visible}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-normal{white-space:normal}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-line{white-space:pre-line}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-none{border-radius:0}.rounded-sm{border-radius:.125rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-0{border-width:0}.border-2{border-width:2px}.border-y{border-top-width:1px}.border-b,.border-y{border-bottom-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-blue-400\/30{border-color:rgba(96,165,250,.3)}.border-border{border-color:var(--border)}.border-cyan-400{--tw-border-opacity:1;border-color:rgb(34 211 238/var(--tw-border-opacity,1))}.border-cyan-400\/30{border-color:rgba(34,211,238,.3)}.border-cyan-500\/40{border-color:rgba(6,182,212,.4)}.border-fg-muted{border-color:var(--text-muted)}.border-gray-400\/30{border-color:rgba(156,163,175,.3)}.border-green-500\/30{border-color:rgba(34,197,94,.3)}.border-purple-400\/30{border-color:rgba(192,132,252,.3)}.border-red-500\/20{border-color:rgba(239,68,68,.2)}.border-status-error-border{border-color:var(--status-error-border)}.border-status-info-border{border-color:var(--status-info-border)}.border-status-success-border{border-color:var(--status-success-border)}.border-status-warning-border{border-color:var(--status-warning-border)}.border-transparent{border-color:transparent}.border-white\/10{border-color:hsla(0,0%,100%,.1)}.border-yellow-500\/30{border-color:rgba(234,179,8,.3)}.border-yellow-500\/35{border-color:rgba(234,179,8,.35)}.border-yellow-500\/40{border-color:rgba(234,179,8,.4)}.border-t-transparent{border-top-color:transparent}.bg-\[\#151922\]{--tw-bg-opacity:1;background-color:rgb(21 25 34/var(--tw-bg-opacity,1))}.bg-blue-400\/10{background-color:rgba(96,165,250,.1)}.bg-blue-500\/10{background-color:rgba(59,130,246,.1)}.bg-border{background-color:var(--border)}.bg-cyan-400{--tw-bg-opacity:1;background-color:rgb(34 211 238/var(--tw-bg-opacity,1))}.bg-cyan-400\/10{background-color:rgba(34,211,238,.1)}.bg-cyan-500\/10{background-color:rgba(6,182,212,.1)}.bg-field{background-color:var(--field-bg-contrast)}.bg-gray-400\/10{background-color:rgba(156,163,175,.1)}.bg-gray-500{--tw-bg-opacity:1;background-color:rgb(107 114 128/var(--tw-bg-opacity,1))}.bg-gray-500\/10{background-color:hsla(220,9%,46%,.1)}.bg-gray-500\/70{background-color:hsla(220,9%,46%,.7)}.bg-gray-600{--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity,1))}.bg-green-400{--tw-bg-opacity:1;background-color:rgb(74 222 128/var(--tw-bg-opacity,1))}.bg-green-500{--tw-bg-opacity:1;background-color:rgb(34 197 94/var(--tw-bg-opacity,1))}.bg-green-500\/10{background-color:rgba(34,197,94,.1)}.bg-green-500\/90{background-color:rgba(34,197,94,.9)}.bg-indigo-500\/10{background-color:rgba(99,102,241,.1)}.bg-overlay{background-color:var(--overlay)}.bg-purple-400\/10{background-color:rgba(192,132,252,.1)}.bg-purple-500\/10{background-color:rgba(168,85,247,.1)}.bg-red-400{--tw-bg-opacity:1;background-color:rgb(248 113 113/var(--tw-bg-opacity,1))}.bg-red-500{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.bg-red-500\/10{background-color:rgba(239,68,68,.1)}.bg-red-500\/90{background-color:rgba(239,68,68,.9)}.bg-status-error-bg{background-color:var(--status-error-bg)}.bg-status-info-bg{background-color:var(--status-info-bg)}.bg-status-success-bg{background-color:var(--status-success-bg)}.bg-status-warning-bg{background-color:var(--status-warning-bg)}.bg-surface{background-color:var(--bg-sidebar)}.bg-transparent{background-color:transparent}.bg-white\/15{background-color:hsla(0,0%,100%,.15)}.bg-white\/5{background-color:hsla(0,0%,100%,.05)}.bg-yellow-400{--tw-bg-opacity:1;background-color:rgb(250 204 21/var(--tw-bg-opacity,1))}.bg-yellow-400\/90{background-color:rgba(250,204,21,.9)}.bg-yellow-500{--tw-bg-opacity:1;background-color:rgb(234 179 8/var(--tw-bg-opacity,1))}.bg-yellow-500\/10{background-color:rgba(234,179,8,.1)}.p-0{padding:0}.p-0\.5{padding:.125rem}.p-2{padding:.5rem}.p-2\.5{padding:.625rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-10{padding-top:2.5rem;padding-bottom:2.5rem}.py-16{padding-top:4rem;padding-bottom:4rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pb-0\.5{padding-bottom:.125rem}.pb-2{padding-bottom:.5rem}.pb-20{padding-bottom:5rem}.pb-3{padding-bottom:.75rem}.pb-6{padding-bottom:1.5rem}.pb-8{padding-bottom:2rem}.pl-1{padding-left:.25rem}.pl-2{padding-left:.5rem}.pl-2\.5{padding-left:.625rem}.pl-3{padding-left:.75rem}.pl-3\.5{padding-left:.875rem}.pl-6{padding-left:1.5rem}.pr-1{padding-right:.25rem}.pr-10{padding-right:2.5rem}.pr-2{padding-right:.5rem}.pr-3{padding-right:.75rem}.pr-8{padding-right:2rem}.pr-9{padding-right:2.25rem}.pt-0{padding-top:0}.pt-1{padding-top:.25rem}.pt-1\.5{padding-top:.375rem}.pt-10{padding-top:2.5rem}.pt-12{padding-top:3rem}.pt-2{padding-top:.5rem}.pt-3{padding-top:.75rem}.pt-4{padding-top:1rem}.pt-6{padding-top:1.5rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-top{vertical-align:top}.align-middle{vertical-align:middle}.font-mono{font-family:JetBrains Mono,monospace}.font-sans{font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[12px\]{font-size:12px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.capitalize{text-transform:capitalize}.italic{font-style:italic}.leading-5{line-height:1.25rem}.leading-\[18px\]{line-height:18px}.leading-none{line-height:1}.leading-tight{line-height:1.25}.tracking-wide{letter-spacing:.025em}.text-\[var\(--text-muted\)\]{color:var(--text-muted)}.text-amber-300{--tw-text-opacity:1;color:rgb(252 211 77/var(--tw-text-opacity,1))}.text-blue-300{--tw-text-opacity:1;color:rgb(147 197 253/var(--tw-text-opacity,1))}.text-blue-400{--tw-text-opacity:1;color:rgb(96 165 250/var(--tw-text-opacity,1))}.text-body{color:var(--text)}.text-bright{color:var(--text-bright)}.text-cyan-400{--tw-text-opacity:1;color:rgb(34 211 238/var(--tw-text-opacity,1))}.text-fg-dim{color:var(--text-dim)}.text-fg-muted{color:var(--text-muted)}.text-indigo-300{--tw-text-opacity:1;color:rgb(165 180 252/var(--tw-text-opacity,1))}.text-purple-300{--tw-text-opacity:1;color:rgb(216 180 254/var(--tw-text-opacity,1))}.text-purple-400{--tw-text-opacity:1;color:rgb(192 132 252/var(--tw-text-opacity,1))}.text-status-error{color:var(--status-error)}.text-status-error-muted{color:var(--status-error-muted)}.text-status-info{color:var(--status-info)}.text-status-success{color:var(--status-success)}.text-status-success-muted{color:var(--status-success-muted)}.text-status-warning{color:var(--status-warning)}.text-status-warning-muted{color:var(--status-warning-muted)}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-white\/80{color:hsla(0,0%,100%,.8)}.underline{text-decoration-line:underline}.placeholder-fg-dim::-moz-placeholder{color:var(--text-dim)}.placeholder-fg-dim::placeholder{color:var(--text-dim)}.opacity-25{opacity:.25}.opacity-50{opacity:.5}.opacity-70{opacity:.7}.opacity-75{opacity:.75}.opacity-80{opacity:.8}.opacity-85{opacity:.85}.opacity-90{opacity:.9}.shadow-2xl{--tw-shadow:0 25px 50px -12px rgba(0,0,0,.25);--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_0_1px_rgba\(234\2c 179\2c 8\2c 0\.22\)\2c 0_0_18px_rgba\(234\2c 179\2c 8\2c 0\.12\)\]{--tw-shadow:0 0 0 1px rgba(234,179,8,.22),0 0 18px rgba(234,179,8,.12);--tw-shadow-colored:0 0 0 1px var(--tw-shadow-color),0 0 18px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_0_1px_rgba\(34\2c 211\2c 238\2c 0\.08\)\]{--tw-shadow:0 0 0 1px rgba(34,211,238,.08);--tw-shadow-colored:0 0 0 1px var(--tw-shadow-color)}.shadow-\[0_0_0_1px_rgba\(34\2c 211\2c 238\2c 0\.08\)\],.shadow-lg{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.outline-none{outline:2px solid transparent;outline-offset:2px}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-\[filter\]{transition-property:filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-150,.transition-transform{transition-duration:.15s}.duration-200{transition-duration:.2s}.first\:rounded-l-lg:first-child{border-top-left-radius:.5rem;border-bottom-left-radius:.5rem}.last\:rounded-r-lg:last-child{border-top-right-radius:.5rem;border-bottom-right-radius:.5rem}.last\:border-0:last-child{border-width:0}.last\:border-b-0:last-child{border-bottom-width:0}.focus-within\:border-fg-muted:focus-within{border-color:var(--text-muted)}.focus-within\:text-body:focus-within{color:var(--text)}.hover\:border-fg-muted:hover{border-color:var(--text-muted)}.hover\:border-red-500:hover{--tw-border-opacity:1;border-color:rgb(239 68 68/var(--tw-border-opacity,1))}.hover\:border-white\/20:hover{border-color:hsla(0,0%,100%,.2)}.hover\:border-yellow-400\/60:hover{border-color:rgba(250,204,21,.6)}.hover\:bg-field:hover{background-color:var(--field-bg-contrast)}.hover\:bg-surface:hover{background-color:var(--bg-sidebar)}.hover\:bg-yellow-500\/15:hover{background-color:rgba(234,179,8,.15)}.hover\:text-body:hover{color:var(--text)}.hover\:text-bright:hover{color:var(--text-bright)}.hover\:text-status-error:hover{color:var(--status-error)}.hover\:text-status-error-muted:hover{color:var(--status-error-muted)}.hover\:text-status-success:hover{color:var(--status-success)}.hover\:text-status-warning:hover{color:var(--status-warning)}.hover\:text-white:hover{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-90:hover{opacity:.9}.hover\:brightness-110:hover{--tw-brightness:brightness(1.1)}.hover\:brightness-110:hover,.hover\:brightness-125:hover{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.hover\:brightness-125:hover{--tw-brightness:brightness(1.25)}.focus\:border-fg-muted:focus{border-color:var(--text-muted)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-1:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-border:focus{--tw-ring-color:var(--border)}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:opacity-60:disabled{opacity:.6}.group[open] .group-open\:rotate-90{--tw-rotate:90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group[open] .group-open\:border-b{border-bottom-width:1px}.group[open] .group-open\:border-border{border-color:var(--border)}.group:hover .group-hover\:bg-surface{background-color:var(--bg-sidebar)}.group:hover .group-hover\:bg-white\/10{background-color:hsla(0,0%,100%,.1)}.group:hover .group-hover\:text-body{color:var(--text)}@media (min-width:640px){.sm\:flex{display:flex}.sm\:w-auto{width:auto}.sm\:min-w-0{min-width:0}.sm\:flex-1{flex:1 1 0%}.sm\:shrink-0{flex-shrink:0}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}.sm\:items-center{align-items:center}.sm\:justify-between{justify-content:space-between}.sm\:space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px*var(--tw-space-y-reverse))}}@media (min-width:768px){.md\:inline{display:inline}.md\:inline-flex{display:inline-flex}.md\:hidden{display:none}.md\:min-w-0{min-width:0}.md\:shrink-0{flex-shrink:0}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:flex-row{flex-direction:row}.md\:items-start{align-items:flex-start}.md\:justify-between{justify-content:space-between}.md\:gap-3{gap:.75rem}.md\:text-right{text-align:right}}
\ No newline at end of file
+*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:JetBrains Mono,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.\!visible{visibility:visible!important}.visible{visibility:visible}.invisible{visibility:hidden}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.inset-x-0{left:0;right:0}.bottom-0{bottom:0}.bottom-3{bottom:.75rem}.bottom-4{bottom:1rem}.left-0{left:0}.left-3{left:.75rem}.right-0{right:0}.right-2\.5{right:.625rem}.right-3{right:.75rem}.right-4{right:1rem}.right-5{right:1.25rem}.right-6{right:1.5rem}.top-0{top:0}.top-1\/2{top:50%}.top-4{top:1rem}.top-5{top:1.25rem}.top-6{top:1.5rem}.top-full{top:100%}.z-10{z-index:10}.z-20{z-index:20}.z-50{z-index:50}.z-\[60\]{z-index:60}.z-\[80\]{z-index:80}.-mx-2{margin-left:-.5rem;margin-right:-.5rem}.-mx-3{margin-left:-.75rem;margin-right:-.75rem}.mx-auto{margin-left:auto;margin-right:auto}.-ml-0\.5{margin-left:-.125rem}.mb-0\.5{margin-bottom:.125rem}.mb-1{margin-bottom:.25rem}.mb-12{margin-bottom:3rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.ml-1{margin-left:.25rem}.ml-3{margin-left:.75rem}.ml-auto{margin-left:auto}.mr-2\.5{margin-right:.625rem}.mt-0{margin-top:0}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-1\.5{margin-top:.375rem}.mt-10{margin-top:2.5rem}.mt-2{margin-top:.5rem}.mt-2\.5{margin-top:.625rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-8{margin-top:2rem}.line-clamp-1{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.contents{display:contents}.hidden{display:none}.h-0\.5{height:.125rem}.h-1{height:.25rem}.h-1\.5{height:.375rem}.h-10{height:2.5rem}.h-12{height:3rem}.h-2{height:.5rem}.h-2\.5{height:.625rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-40{height:10rem}.h-44{height:11rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-9{height:2.25rem}.h-\[22px\]{height:22px}.h-\[340px\]{height:340px}.h-\[34px\]{height:34px}.h-full{height:100%}.h-px{height:1px}.max-h-80{max-height:20rem}.max-h-\[66vh\]{max-height:66vh}.max-h-\[70vh\]{max-height:70vh}.max-h-\[92vh\]{max-height:92vh}.min-h-6{min-height:1.5rem}.min-h-\[200px\]{min-height:200px}.min-h-\[220px\]{min-height:220px}.min-h-\[26rem\]{min-height:26rem}.min-h-\[300px\]{min-height:300px}.min-h-\[320px\]{min-height:320px}.min-h-screen{min-height:100vh}.w-1\.5{width:.375rem}.w-10{width:2.5rem}.w-12{width:3rem}.w-2{width:.5rem}.w-2\.5{width:.625rem}.w-24{width:6rem}.w-28{width:7rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-32{width:8rem}.w-36{width:9rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-64{width:16rem}.w-7{width:1.75rem}.w-72{width:18rem}.w-8{width:2rem}.w-9{width:2.25rem}.w-auto{width:auto}.w-full{width:100%}.min-w-0{min-width:0}.min-w-\[88px\]{min-width:88px}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.max-w-64{max-width:16rem}.max-w-80{max-width:20rem}.max-w-full{max-width:100%}.max-w-lg{max-width:32rem}.max-w-md{max-width:28rem}.max-w-sm{max-width:24rem}.max-w-xl{max-width:36rem}.flex-1{flex:1 1 0%}.flex-shrink-0,.shrink-0{flex-shrink:0}.table-fixed{table-layout:fixed}.-translate-x-1\/2{--tw-translate-x:-50%}.-translate-x-1\/2,.-translate-y-1\/2{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y:-50%}.-rotate-90{--tw-rotate:-90deg}.-rotate-90,.rotate-180{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-180{--tw-rotate:180deg}.rotate-90{--tw-rotate:90deg}.rotate-90,.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.cursor-default{cursor:default}.cursor-help{cursor:help}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize-y{resize:vertical}.resize{resize:both}.list-inside{list-style-position:inside}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.list-none{list-style-type:none}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-x-1\.5{-moz-column-gap:.375rem;column-gap:.375rem}.gap-x-3{-moz-column-gap:.75rem;column-gap:.75rem}.gap-y-1{row-gap:.25rem}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.125rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.125rem*var(--tw-space-y-reverse))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.375rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem*var(--tw-space-y-reverse))}.space-y-10>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(2.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2.5rem*var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-2\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.625rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.625rem*var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.25rem*var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-top-width:calc(1px*(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px*var(--tw-divide-y-reverse))}.divide-border>:not([hidden])~:not([hidden]){border-color:var(--border)}.justify-self-start{justify-self:start}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-visible{overflow:visible}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-normal{white-space:normal}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-line{white-space:pre-line}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-none{border-radius:0}.rounded-sm{border-radius:.125rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-0{border-width:0}.border-2{border-width:2px}.border-y{border-top-width:1px}.border-b,.border-y{border-bottom-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-blue-400\/30{border-color:rgba(96,165,250,.3)}.border-border{border-color:var(--border)}.border-cyan-400{--tw-border-opacity:1;border-color:rgb(34 211 238/var(--tw-border-opacity,1))}.border-cyan-400\/30{border-color:rgba(34,211,238,.3)}.border-cyan-500\/40{border-color:rgba(6,182,212,.4)}.border-fg-muted{border-color:var(--text-muted)}.border-gray-400\/30{border-color:rgba(156,163,175,.3)}.border-green-500\/30{border-color:rgba(34,197,94,.3)}.border-purple-400\/30{border-color:rgba(192,132,252,.3)}.border-red-500\/20{border-color:rgba(239,68,68,.2)}.border-status-error-border{border-color:var(--status-error-border)}.border-status-info-border{border-color:var(--status-info-border)}.border-status-success-border{border-color:var(--status-success-border)}.border-status-warning-border{border-color:var(--status-warning-border)}.border-transparent{border-color:transparent}.border-white\/10{border-color:hsla(0,0%,100%,.1)}.border-yellow-500\/30{border-color:rgba(234,179,8,.3)}.border-yellow-500\/35{border-color:rgba(234,179,8,.35)}.border-yellow-500\/40{border-color:rgba(234,179,8,.4)}.border-t-transparent{border-top-color:transparent}.bg-\[\#151922\]{--tw-bg-opacity:1;background-color:rgb(21 25 34/var(--tw-bg-opacity,1))}.bg-black\/30{background-color:rgba(0,0,0,.3)}.bg-blue-400\/10{background-color:rgba(96,165,250,.1)}.bg-blue-500\/10{background-color:rgba(59,130,246,.1)}.bg-border{background-color:var(--border)}.bg-cyan-400{--tw-bg-opacity:1;background-color:rgb(34 211 238/var(--tw-bg-opacity,1))}.bg-cyan-400\/10{background-color:rgba(34,211,238,.1)}.bg-cyan-500\/10{background-color:rgba(6,182,212,.1)}.bg-field{background-color:var(--field-bg-contrast)}.bg-gray-400\/10{background-color:rgba(156,163,175,.1)}.bg-gray-500{--tw-bg-opacity:1;background-color:rgb(107 114 128/var(--tw-bg-opacity,1))}.bg-gray-500\/10{background-color:hsla(220,9%,46%,.1)}.bg-gray-500\/70{background-color:hsla(220,9%,46%,.7)}.bg-gray-600{--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity,1))}.bg-green-400{--tw-bg-opacity:1;background-color:rgb(74 222 128/var(--tw-bg-opacity,1))}.bg-green-500{--tw-bg-opacity:1;background-color:rgb(34 197 94/var(--tw-bg-opacity,1))}.bg-green-500\/10{background-color:rgba(34,197,94,.1)}.bg-green-500\/90{background-color:rgba(34,197,94,.9)}.bg-indigo-500\/10{background-color:rgba(99,102,241,.1)}.bg-overlay{background-color:var(--overlay)}.bg-purple-400\/10{background-color:rgba(192,132,252,.1)}.bg-purple-500\/10{background-color:rgba(168,85,247,.1)}.bg-red-400{--tw-bg-opacity:1;background-color:rgb(248 113 113/var(--tw-bg-opacity,1))}.bg-red-500{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.bg-red-500\/10{background-color:rgba(239,68,68,.1)}.bg-red-500\/90{background-color:rgba(239,68,68,.9)}.bg-status-error-bg{background-color:var(--status-error-bg)}.bg-status-info-bg{background-color:var(--status-info-bg)}.bg-status-success-bg{background-color:var(--status-success-bg)}.bg-status-warning-bg{background-color:var(--status-warning-bg)}.bg-surface{background-color:var(--bg-sidebar)}.bg-transparent{background-color:transparent}.bg-white\/15{background-color:hsla(0,0%,100%,.15)}.bg-white\/5{background-color:hsla(0,0%,100%,.05)}.bg-yellow-400{--tw-bg-opacity:1;background-color:rgb(250 204 21/var(--tw-bg-opacity,1))}.bg-yellow-400\/90{background-color:rgba(250,204,21,.9)}.bg-yellow-500{--tw-bg-opacity:1;background-color:rgb(234 179 8/var(--tw-bg-opacity,1))}.bg-yellow-500\/10{background-color:rgba(234,179,8,.1)}.p-0{padding:0}.p-0\.5{padding:.125rem}.p-2{padding:.5rem}.p-2\.5{padding:.625rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-10{padding-top:2.5rem;padding-bottom:2.5rem}.py-16{padding-top:4rem;padding-bottom:4rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pb-0\.5{padding-bottom:.125rem}.pb-2{padding-bottom:.5rem}.pb-20{padding-bottom:5rem}.pb-3{padding-bottom:.75rem}.pb-6{padding-bottom:1.5rem}.pb-8{padding-bottom:2rem}.pl-1{padding-left:.25rem}.pl-2{padding-left:.5rem}.pl-2\.5{padding-left:.625rem}.pl-3{padding-left:.75rem}.pl-3\.5{padding-left:.875rem}.pl-6{padding-left:1.5rem}.pr-1{padding-right:.25rem}.pr-10{padding-right:2.5rem}.pr-2{padding-right:.5rem}.pr-3{padding-right:.75rem}.pr-8{padding-right:2rem}.pr-9{padding-right:2.25rem}.pt-0{padding-top:0}.pt-1{padding-top:.25rem}.pt-1\.5{padding-top:.375rem}.pt-10{padding-top:2.5rem}.pt-12{padding-top:3rem}.pt-2{padding-top:.5rem}.pt-3{padding-top:.75rem}.pt-4{padding-top:1rem}.pt-6{padding-top:1.5rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-top{vertical-align:top}.align-middle{vertical-align:middle}.font-mono{font-family:JetBrains Mono,monospace}.font-sans{font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[12px\]{font-size:12px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.capitalize{text-transform:capitalize}.italic{font-style:italic}.leading-5{line-height:1.25rem}.leading-\[1\.1\]{line-height:1.1}.leading-\[18px\]{line-height:18px}.leading-none{line-height:1}.leading-tight{line-height:1.25}.tracking-wide{letter-spacing:.025em}.text-\[var\(--text-muted\)\]{color:var(--text-muted)}.text-amber-300{--tw-text-opacity:1;color:rgb(252 211 77/var(--tw-text-opacity,1))}.text-blue-300{--tw-text-opacity:1;color:rgb(147 197 253/var(--tw-text-opacity,1))}.text-blue-400{--tw-text-opacity:1;color:rgb(96 165 250/var(--tw-text-opacity,1))}.text-body{color:var(--text)}.text-bright{color:var(--text-bright)}.text-cyan-400{--tw-text-opacity:1;color:rgb(34 211 238/var(--tw-text-opacity,1))}.text-fg-dim{color:var(--text-dim)}.text-fg-muted{color:var(--text-muted)}.text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity,1))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.text-indigo-300{--tw-text-opacity:1;color:rgb(165 180 252/var(--tw-text-opacity,1))}.text-purple-300{--tw-text-opacity:1;color:rgb(216 180 254/var(--tw-text-opacity,1))}.text-purple-400{--tw-text-opacity:1;color:rgb(192 132 252/var(--tw-text-opacity,1))}.text-status-error{color:var(--status-error)}.text-status-error-muted{color:var(--status-error-muted)}.text-status-info{color:var(--status-info)}.text-status-success{color:var(--status-success)}.text-status-success-muted{color:var(--status-success-muted)}.text-status-warning{color:var(--status-warning)}.text-status-warning-muted{color:var(--status-warning-muted)}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-white\/80{color:hsla(0,0%,100%,.8)}.underline{text-decoration-line:underline}.placeholder-fg-dim::-moz-placeholder{color:var(--text-dim)}.placeholder-fg-dim::placeholder{color:var(--text-dim)}.opacity-25{opacity:.25}.opacity-50{opacity:.5}.opacity-70{opacity:.7}.opacity-75{opacity:.75}.opacity-80{opacity:.8}.opacity-85{opacity:.85}.opacity-90{opacity:.9}.shadow-2xl{--tw-shadow:0 25px 50px -12px rgba(0,0,0,.25);--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_0_1px_rgba\(234\2c 179\2c 8\2c 0\.22\)\2c 0_0_18px_rgba\(234\2c 179\2c 8\2c 0\.12\)\]{--tw-shadow:0 0 0 1px rgba(234,179,8,.22),0 0 18px rgba(234,179,8,.12);--tw-shadow-colored:0 0 0 1px var(--tw-shadow-color),0 0 18px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_0_1px_rgba\(34\2c 211\2c 238\2c 0\.08\)\]{--tw-shadow:0 0 0 1px rgba(34,211,238,.08);--tw-shadow-colored:0 0 0 1px var(--tw-shadow-color)}.shadow-\[0_0_0_1px_rgba\(34\2c 211\2c 238\2c 0\.08\)\],.shadow-lg{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.outline-none{outline:2px solid transparent;outline-offset:2px}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-\[filter\]{transition-property:filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-150,.transition-transform{transition-duration:.15s}.duration-200{transition-duration:.2s}.first\:rounded-l-lg:first-child{border-top-left-radius:.5rem;border-bottom-left-radius:.5rem}.last\:rounded-r-lg:last-child{border-top-right-radius:.5rem;border-bottom-right-radius:.5rem}.last\:border-0:last-child{border-width:0}.last\:border-b-0:last-child{border-bottom-width:0}.focus-within\:border-fg-muted:focus-within{border-color:var(--text-muted)}.focus-within\:text-body:focus-within{color:var(--text)}.hover\:border-fg-muted:hover{border-color:var(--text-muted)}.hover\:border-red-500:hover{--tw-border-opacity:1;border-color:rgb(239 68 68/var(--tw-border-opacity,1))}.hover\:border-white\/20:hover{border-color:hsla(0,0%,100%,.2)}.hover\:border-yellow-400\/60:hover{border-color:rgba(250,204,21,.6)}.hover\:bg-field:hover{background-color:var(--field-bg-contrast)}.hover\:bg-surface:hover{background-color:var(--bg-sidebar)}.hover\:bg-yellow-500\/15:hover{background-color:rgba(234,179,8,.15)}.hover\:text-body:hover{color:var(--text)}.hover\:text-bright:hover{color:var(--text-bright)}.hover\:text-status-error:hover{color:var(--status-error)}.hover\:text-status-error-muted:hover{color:var(--status-error-muted)}.hover\:text-status-success:hover{color:var(--status-success)}.hover\:text-status-warning:hover{color:var(--status-warning)}.hover\:text-white:hover{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-90:hover{opacity:.9}.hover\:brightness-110:hover{--tw-brightness:brightness(1.1)}.hover\:brightness-110:hover,.hover\:brightness-125:hover{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.hover\:brightness-125:hover{--tw-brightness:brightness(1.25)}.focus\:border-fg-muted:focus{border-color:var(--text-muted)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-1:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-border:focus{--tw-ring-color:var(--border)}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:opacity-60:disabled{opacity:.6}.group[open] .group-open\:rotate-90{--tw-rotate:90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group[open] .group-open\:border-b{border-bottom-width:1px}.group[open] .group-open\:border-border{border-color:var(--border)}.group:hover .group-hover\:bg-surface{background-color:var(--bg-sidebar)}.group:hover .group-hover\:bg-white\/10{background-color:hsla(0,0%,100%,.1)}.group:hover .group-hover\:text-body{color:var(--text)}@media (min-width:640px){.sm\:flex{display:flex}.sm\:w-auto{width:auto}.sm\:min-w-0{min-width:0}.sm\:flex-1{flex:1 1 0%}.sm\:shrink-0{flex-shrink:0}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}.sm\:items-center{align-items:center}.sm\:justify-between{justify-content:space-between}.sm\:space-y-0>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0px*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0px*var(--tw-space-y-reverse))}}@media (min-width:768px){.md\:inline{display:inline}.md\:inline-flex{display:inline-flex}.md\:hidden{display:none}.md\:min-w-0{min-width:0}.md\:shrink-0{flex-shrink:0}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:flex-row{flex-direction:row}.md\:items-start{align-items:flex-start}.md\:justify-between{justify-content:space-between}.md\:gap-3{gap:.75rem}.md\:text-right{text-align:right}}
\ No newline at end of file
diff --git a/lib/public/dist/app.bundle.js b/lib/public/dist/app.bundle.js
index 37237f1..c8edb8f 100644
--- a/lib/public/dist/app.bundle.js
+++ b/lib/public/dist/app.bundle.js
@@ -1,5 +1,5 @@
-import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa={},ra=[],Ck=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i,Rr=Array.isArray;function _n(t,e){for(var n in e)t[n]=e[n];return t}function Jc(t){t&&t.parentNode&&t.parentNode.removeChild(t)}function T(t,e,n){var s,o,r,i={};for(r in e)r=="key"?s=e[r]:r=="ref"?o=e[r]:i[r]=e[r];if(arguments.length>2&&(i.children=arguments.length>3?Tr.call(arguments,2):n),typeof t=="function"&&t.defaultProps!=null)for(r in t.defaultProps)i[r]===void 0&&(i[r]=t.defaultProps[r]);return Ar(t,i,s,o,null)}function Ar(t,e,n,s,o){var r={type:t,props:e,key:n,ref:s,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:o??++qf,__i:-1,__u:0};return o==null&&Se.vnode!=null&&Se.vnode(r),r}function ln(t){return t.children}function hn(t,e){this.props=t,this.context=e}function $o(t,e){if(e==null)return t.__?$o(t.__,t.__i+1):null;for(var n;ee&&hs.sort(Zf),t=hs.shift(),e=hs.length,_k(t)}finally{hs.length=ia.__r=0}}function eh(t,e,n,s,o,r,i,a,l,c,d){var u,p,f,g,m,h,b,x=s&&s.__k||ra,v=e.length;for(l=Mk(n,e,x,l,v),u=0;u0?i=t.__k[r]=Ar(i.type,i.props,i.key,i.ref?i.ref:null,i.__v):t.__k[r]=i,l=r+p,i.__=t,i.__b=t.__b+1,a=null,(c=i.__i=Ak(i,n,l,u))!=-1&&(u--,(a=n[c])&&(a.__u|=2)),a==null||a.__v==null?(c==-1&&(o>d?p--:ol?p--:p++,i.__u|=4))):t.__k[r]=null;if(u)for(r=0;r(d?1:0)){for(o=n-1,r=n+1;o>=0||r=0?o--:r++])!=null&&(2&c.__u)==0&&a==c.key&&l==c.type)return i}return-1}function Kf(t,e,n){e[0]=="-"?t.setProperty(e,n??""):t[e]=n==null?"":typeof n!="number"||Ck.test(e)?n:n+"px"}function sa(t,e,n,s,o){var r,i;e:if(e=="style")if(typeof n=="string")t.style.cssText=n;else{if(typeof s=="string"&&(t.style.cssText=s=""),s)for(e in s)n&&e in n||Kf(t.style,e,"");if(n)for(e in n)s&&n[e]==s[e]||Kf(t.style,e,n[e])}else if(e[0]=="o"&&e[1]=="n")r=e!=(e=e.replace(Yf,"$1")),i=e.toLowerCase(),e=i in t||e=="onFocusOut"||e=="onFocusIn"?i.slice(2):e.slice(2),t.l||(t.l={}),t.l[e+r]=n,n?s?n.u=s.u:(n.u=qc,t.addEventListener(e,r?Uc:zc,r)):t.removeEventListener(e,r?Uc:zc,r);else{if(o=="http://www.w3.org/2000/svg")e=e.replace(/xlink(H|:h)/,"h").replace(/sName$/,"s");else if(e!="width"&&e!="height"&&e!="href"&&e!="list"&&e!="form"&&e!="tabIndex"&&e!="download"&&e!="rowSpan"&&e!="colSpan"&&e!="role"&&e!="popover"&&e in t)try{t[e]=n??"";break e}catch{}typeof n=="function"||(n==null||n===!1&&e[4]!="-"?t.removeAttribute(e):t.setAttribute(e,e=="popover"&&n==1?"":n))}}function Gf(t){return function(e){if(this.l){var n=this.l[e.type+t];if(e.t==null)e.t=qc++;else if(e.t0?t:Rr(t)?t.map(sh):_n({},t)}function Tk(t,e,n,s,o,r,i,a,l){var c,d,u,p,f,g,m,h=n.props||oa,b=e.props,x=e.type;if(x=="svg"?o="http://www.w3.org/2000/svg":x=="math"?o="http://www.w3.org/1998/Math/MathML":o||(o="http://www.w3.org/1999/xhtml"),r!=null){for(c=0;c2&&(a.children=arguments.length>3?Tr.call(arguments,2):n),Ar(t.type,a,s||t.key,o||t.ref,null)}function ko(t){function e(n){var s,o;return this.getChildContext||(s=new Set,(o={})[e.__c]=this,this.getChildContext=function(){return o},this.componentWillUnmount=function(){s=null},this.shouldComponentUpdate=function(r){this.props.value!=r.value&&s.forEach(function(i){i.__e=!0,Kc(i)})},this.sub=function(r){s.add(r);var i=r.componentWillUnmount;r.componentWillUnmount=function(){s&&s.delete(r),i&&i.call(r)}}),n.children}return e.__c="__cC"+Xf++,e.__=t,e.Provider=e.__l=(e.Consumer=function(n,s){return n.children(s)}).contextType=e,e}Tr=ra.slice,Se={__e:function(t,e,n,s){for(var o,r,i;e=e.__;)if((o=e.__c)&&!o.__)try{if((r=o.constructor)&&r.getDerivedStateFromError!=null&&(o.setState(r.getDerivedStateFromError(t)),i=o.__d),o.componentDidCatch!=null&&(o.componentDidCatch(t,s||{}),i=o.__d),i)return o.__E=o}catch(a){t=a}throw t}},qf=0,Pr=function(t){return t!=null&&t.constructor===void 0},hn.prototype.setState=function(t,e){var n;n=this.__s!=null&&this.__s!=this.state?this.__s:this.__s=_n({},this.state),typeof t=="function"&&(t=t(_n({},n),this.props)),t&&_n(n,t),t!=null&&this.__v&&(e&&this._sb.push(e),Kc(this))},hn.prototype.forceUpdate=function(t){this.__v&&(this.__e=!0,t&&this.__h.push(t),Kc(this))},hn.prototype.render=ln,hs=[],Jf=typeof Promise=="function"?Promise.prototype.then.bind(Promise.resolve()):setTimeout,Zf=function(t,e){return t.__v.__b-e.__v.__b},ia.__r=0,Yf=/(PointerCapture)$|Capture$/i,qc=0,zc=Gf(!1),Uc=Gf(!0),Xf=0;var Ws,tt,Xc,rh,Ir=0,fh=[],ut=Se,ih=ut.__b,ah=ut.__r,lh=ut.diffed,ch=ut.__c,dh=ut.unmount,uh=ut.__;function Dr(t,e){ut.__h&&ut.__h(tt,t,Ir||e),Ir=0;var n=tt.__H||(tt.__H={__:[],__h:[]});return t>=n.__.length&&n.__.push({}),n.__[t]}function y(t){return Ir=1,hh(mh,t)}function hh(t,e,n){var s=Dr(Ws++,2);if(s.t=t,!s.__c&&(s.__=[n?n(e):mh(void 0,e),function(a){var l=s.__N?s.__N[0]:s.__[0],c=s.t(l,a);l!==c&&(s.__N=[c,s.__[1]],s.__c.setState({}))}],s.__c=tt,!tt.__f)){var o=function(a,l,c){if(!s.__c.__H)return!0;var d=s.__c.__H.__.filter(function(p){return p.__c});if(d.every(function(p){return!p.__N}))return!r||r.call(this,a,l,c);var u=s.__c.props!==a;return d.some(function(p){if(p.__N){var f=p.__[0];p.__=p.__N,p.__N=void 0,f!==p.__[0]&&(u=!0)}}),r&&r.call(this,a,l,c)||u};tt.__f=!0;var r=tt.shouldComponentUpdate,i=tt.componentWillUpdate;tt.componentWillUpdate=function(a,l,c){if(this.__e){var d=r;r=void 0,o(a,l,c),r=d}i&&i.call(this,a,l,c)},tt.shouldComponentUpdate=o}return s.__N||s.__}function L(t,e){var n=Dr(Ws++,3);!ut.__s&&ed(n.__H,e)&&(n.__=t,n.u=e,tt.__H.__h.push(n))}function Vs(t,e){var n=Dr(Ws++,4);!ut.__s&&ed(n.__H,e)&&(n.__=t,n.u=e,tt.__h.push(n))}function ee(t){return Ir=5,F(function(){return{current:t}},[])}function F(t,e){var n=Dr(Ws++,7);return ed(n.__H,e)&&(n.__=t(),n.__H=e,n.__h=t),n.__}function q(t,e){return Ir=8,F(function(){return t},e)}function Nr(t){var e=tt.context[t.__c],n=Dr(Ws++,9);return n.c=t,e?(n.__==null&&(n.__=!0,e.sub(tt)),e.props.value):t.__}function Rk(){for(var t;t=fh.shift();){var e=t.__H;if(t.__P&&e)try{e.__h.some(aa),e.__h.some(Qc),e.__h=[]}catch(n){e.__h=[],ut.__e(n,t.__v)}}}ut.__b=function(t){tt=null,ih&&ih(t)},ut.__=function(t,e){t&&e.__k&&e.__k.__m&&(t.__m=e.__k.__m),uh&&uh(t,e)},ut.__r=function(t){ah&&ah(t),Ws=0;var e=(tt=t.__c).__H;e&&(Xc===tt?(e.__h=[],tt.__h=[],e.__.some(function(n){n.__N&&(n.__=n.__N),n.u=n.__N=void 0})):(e.__h.some(aa),e.__h.some(Qc),e.__h=[],Ws=0)),Xc=tt},ut.diffed=function(t){lh&&lh(t);var e=t.__c;e&&e.__H&&(e.__H.__h.length&&(fh.push(e)!==1&&rh===ut.requestAnimationFrame||((rh=ut.requestAnimationFrame)||Lk)(Rk)),e.__H.__.some(function(n){n.u&&(n.__H=n.u),n.u=void 0})),Xc=tt=null},ut.__c=function(t,e){e.some(function(n){try{n.__h.some(aa),n.__h=n.__h.filter(function(s){return!s.__||Qc(s)})}catch(s){e.some(function(o){o.__h&&(o.__h=[])}),e=[],ut.__e(s,n.__v)}}),ch&&ch(t,e)},ut.unmount=function(t){dh&&dh(t);var e,n=t.__c;n&&n.__H&&(n.__H.__.some(function(s){try{aa(s)}catch(o){e=o}}),n.__H=void 0,e&&ut.__e(e,n.__v))};var ph=typeof requestAnimationFrame=="function";function Lk(t){var e,n=function(){clearTimeout(s),ph&&cancelAnimationFrame(e),setTimeout(t)},s=setTimeout(n,35);ph&&(e=requestAnimationFrame(n))}function aa(t){var e=tt,n=t.__c;typeof n=="function"&&(t.__c=void 0,n()),tt=e}function Qc(t){var e=tt;t.__c=t.__(),tt=e}function ed(t,e){return!t||t.length!==e.length||e.some(function(n,s){return n!==t[s]})}function mh(t,e){return typeof e=="function"?e(t):e}var bh=function(t,e,n,s){var o;e[0]=0;for(var r=1;r=5&&((i||!p&&r===5)&&(l.push(r,0,i,o),r=6),p&&(l.push(r,p,0,o),r=6)),i=""},d=0;d"?(r=1,i=""):i=s+i[0]:a?s===a?a="":i+=s:s==='"'||s==="'"?a=s:s===">"?(c(),r=1):r&&(s==="="?(r=5,o=i,i=""):s==="/"&&(r<5||n[d][u+1]===">")?(c(),r===3&&(l=l[0]),r=l,(l=l[0]).push(2,0,r),r=0):s===" "||s===" "||s===`
-`||s==="\r"?(c(),r=2):i+=s),r===3&&i==="!--"&&(r=4,l=l[0])}return c(),l})(t)),e),arguments,[])).length>1?e:e[0]}function xh(t,e){if(t instanceof RegExp)return{keys:!1,pattern:t};var n,s,o,r,i=[],a="",l=t.split("/");for(l[0]||l.shift();o=l.shift();)n=o[0],n==="*"?(i.push(n),a+=o[1]==="?"?"(?:/(.*))?":"/(.*)"):n===":"?(s=o.indexOf("?",1),r=o.indexOf(".",1),i.push(o.substring(1,~s?s:~r?r:o.length)),a+=~s&&!~r?"(?:/([^/]+?))?":"/([^/]+?)",~r&&(a+=(~s?"?":"")+"\\"+o.substring(r))):a+="/"+o;return{keys:i,pattern:new RegExp("^"+a+(e?"(?=$|/)":"/?$"),"i")}}var Ek=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";function td(t,e){return t===e&&(t!==0||1/t===1/e)||t!==t&&e!==e}function yh(t,e,n){n&&!Ek&&(e=n);let s=e(),[{_instance:o},r]=y({_instance:{_value:s,_getSnapshot:e}});return Vs(()=>{o._value=s,o._getSnapshot=e,td(o._value,e())||r({_instance:o})},[t,s,e]),L(()=>(td(o._value,o._getSnapshot())||r({_instance:o}),t(()=>{td(o._value,o._getSnapshot())||r({_instance:o})})),[t]),s}var nd=t=>{let e=ee([t,(...n)=>e[0](...n)]).current;return Vs(()=>{e[0]=t}),e[1]};var Ik="popstate",sd="pushState",od="replaceState",Dk="hashchange",vh=[Ik,sd,od,Dk],Nk=t=>{for(let e of vh)addEventListener(e,t);return()=>{for(let e of vh)removeEventListener(e,t)}},Sh=(t,e)=>yh(Nk,t,e),$h=()=>location.search,Ch=({ssrSearch:t}={})=>Sh($h,t!=null?()=>t:$h),wh=()=>location.pathname,Ok=({ssrPath:t}={})=>Sh(wh,t!=null?()=>t:wh);var Bk=(t,{replace:e=!1,state:n=null}={})=>history[e?od:sd](n,"",t),_h=(t={})=>[Ok(t),Bk],kh=Symbol.for("wouter_v3");if(typeof history<"u"&&typeof window[kh]>"u"){for(let t of[sd,od]){let e=history[t];history[t]=function(){let n=e.apply(this,arguments),s=new Event(t);return s.arguments=arguments,dispatchEvent(s),n}}Object.defineProperty(window,kh,{value:!0})}var Fk=(t,e)=>e.toLowerCase().indexOf(t.toLowerCase())?"~"+e:e.slice(t.length)||"/",Ah=(t="")=>t==="/"?"":t,Th=(t,e)=>t[0]==="~"?t.slice(1):Ah(e)+t,Ph=(t="",e)=>Fk(Mh(Ah(t)),Mh(e));var Mh=t=>{try{return decodeURI(t)}catch{return t}};var Lh={hook:_h,searchHook:Ch,parser:xh,base:"",ssrPath:void 0,ssrSearch:void 0,ssrContext:void 0,hrefs:t=>t,aroundNav:(t,e,n)=>t(e,n)},Eh=ko(Lh),Or=()=>Nr(Eh),Ih={},Dh=ko(Ih),Hk=()=>Nr(Dh),la=t=>{let[e,n]=t.hook(t);return[Ph(t.base,e),nd((s,o)=>t.aroundNav(n,Th(s,t.base),o))]},ca=()=>la(Or());var Nh=(t,e,n,s)=>{let{pattern:o,keys:r}=e instanceof RegExp?{keys:!1,pattern:e}:t(e||"*",s),i=o.exec(n)||[],[a,...l]=i;return a!==void 0?[!0,(()=>{let c=r!==!1?Object.fromEntries(r.map((u,p)=>[u,l[p]])):i.groups,d={...l};return c&&Object.assign(d,c),d})(),...s?[a]:[]]:[!1,null]};var da=({children:t,...e})=>{let n=Or(),s=e.hook?Lh:n,o=s,[r,i=e.ssrSearch??""]=e.ssrPath?.split("?")??[];r&&(e.ssrSearch=i,e.ssrPath=r),e.hrefs=e.hrefs??e.hook?.hrefs,e.searchHook=e.searchHook??e.hook?.searchHook;let a=ee({}),l=a.current,c=l;for(let d in s){let u=d==="base"?s[d]+(e[d]??""):e[d]??s[d];l===c&&u!==c[d]&&(a.current=c={...c}),c[d]=u,(u!==s[d]||u!==o[d])&&(o=c)}return T(Eh.Provider,{value:o,children:t})},Rh=({children:t,component:e},n)=>e?T(e,{params:n}):typeof t=="function"?t(n):t,Wk=t=>{let e=ee(Ih),n=e.current;return e.current=Object.keys(t).length!==Object.keys(n).length||Object.entries(t).some(([s,o])=>o!==n[s])?t:n};var rt=({path:t,nest:e,match:n,...s})=>{let o=Or(),[r]=la(o),[i,a,l]=n??Nh(o.parser,t,r,e),c=Wk({...Hk(),...a});if(!i)return null;let d=l?T(da,{base:l},Rh(s,c)):Rh(s,c);return T(Dh.Provider,{value:c,children:d})},l4=(t,e)=>{let n=Or(),[s,o]=la(n),{to:r="",href:i=r,onClick:a,asChild:l,children:c,className:d,replace:u,state:p,transition:f,...g}=t,m=nd(b=>{b.ctrlKey||b.metaKey||b.altKey||b.shiftKey||b.button!==0||(a?.(b),b.defaultPrevented||(b.preventDefault(),o(i,t)))}),h=n.hrefs(i[0]==="~"?i.slice(1):n.base+i,n);return l&&Pr(c)?Er(c,{onClick:m,href:h}):T("a",{...g,onClick:m,href:h,className:d?.call?d(s===i):d,children:c,ref:e})},Oh=t=>Array.isArray(t)?t.flatMap(e=>Oh(e&&e.type===ln?e.props.children:e)):[t],rd=({children:t,location:e})=>{let n=Or(),[s]=la(n);for(let o of Oh(t)){let r=0;if(Pr(o)&&(r=Nh(n.parser,o.props.path,e||s,o.props.nest))[0])return Er(o,{match:r})}return null};var id=t=>{if(typeof t!="string"||!t.trim())return{};try{return JSON.parse(t)}catch{return{}}},Bh=({url:t="",onMessage:e=()=>{},onError:n=()=>{}})=>{if(typeof window?.EventSource!="function")throw new Error("Server events are not supported in this browser");let s=new window.EventSource(String(t||""),{withCredentials:!0}),o=l=>{e({event:"phase",data:id(l?.data||"")})},r=l=>{e({event:"done",data:id(l?.data||"")})},i=l=>{e({event:"error",data:id(l?.data||"")})},a=l=>{n(l)};return s.addEventListener("phase",o),s.addEventListener("done",r),s.addEventListener("error",i),s.onerror=a,()=>{s.removeEventListener("phase",o),s.removeEventListener("done",r),s.removeEventListener("error",i),s.onerror=null,s.close()}};var Fh="x-client-timezone",Vk=()=>{try{return Intl?.DateTimeFormat?.().resolvedOptions?.().timeZone||""}catch{return""}},Y=async(t,e={})=>{let n={...e},s=new Headers(e?.headers||{});if(!s.has(Fh)){let r=Vk();r&&s.set(Fh,r)}n.headers=s;let o=await fetch(t,n);if(o.status===401){try{window.localStorage?.clear?.()}catch{}throw window.location.href="/setup",new Error("Unauthorized")}return o},Hh=({onMessage:t=()=>{},onOpen:e=()=>{},onError:n=()=>{}}={})=>{if(typeof window?.EventSource!="function")throw new Error("Server events are not supported in this browser");let s=new window.EventSource("/api/events/status",{withCredentials:!0}),o=r=>{let i={};try{i=r?.data?JSON.parse(r.data):{}}catch{}t(i||{})};return s.addEventListener("status",o),s.onopen=()=>e(),s.onerror=r=>n(r),()=>{s.removeEventListener("status",o),s.onopen=null,s.onerror=null,s.close()}};async function So(){return(await Y("/api/status")).json()}async function Co(){return(await Y("/api/pairings")).json()}async function _o(t,e,n=""){return(await Y(`/api/pairings/${t}/approve`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({channel:e,accountId:n})})).json()}async function Mo(t,e,n=""){let s=await Y(`/api/pairings/${t}/reject`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({channel:e,accountId:n})});return fe(s,"Could not reject pairing")}async function Wh(){return(await Y("/api/google/accounts")).json()}async function Vh({accountId:t="",client:e=""}={}){let n=new URLSearchParams;t&&n.set("accountId",String(t)),e&&n.set("client",String(e));let s=n.toString()?`?${n.toString()}`:"";return(await Y(`/api/google/credentials${s}`)).json()}async function jh(t=""){let e=new URLSearchParams;t&&e.set("accountId",String(t));let n=e.toString()?`?${e.toString()}`:"";return(await Y(`/api/google/check${n}`)).json()}async function zh({clientId:t,clientSecret:e,email:n,services:s=[],client:o="default",personal:r=!1,accountId:i=""}){return(await Y("/api/google/credentials",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({clientId:t,clientSecret:e,email:n,services:s,client:o,personal:r,accountId:i})})).json()}async function Uh({email:t,services:e=[],client:n="default",personal:s=!1,accountId:o=""}){return(await Y("/api/google/accounts",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:t,services:e,client:n,personal:s,accountId:o})})).json()}async function Kh(t=""){return(await Y("/api/google/disconnect",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({accountId:t})})).json()}var Gh=async()=>{let t=await Y("/api/gmail/config");return fe(t,"Could not load Gmail watch config")},qh=async({client:t="default",topicPath:e="",projectId:n="",regeneratePushToken:s=!1}={})=>{let o=await Y("/api/gmail/config",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({client:t,topicPath:e,projectId:n,regeneratePushToken:s})});return fe(o,"Could not save Gmail watch config")},Jh=async(t,{destination:e=null}={})=>{let n=await Y("/api/gmail/watch/start",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({accountId:String(t||""),...e?{destination:e}:{}})});return fe(n,"Could not start Gmail watch")},Zh=async t=>{let e=await Y("/api/gmail/watch/stop",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({accountId:String(t||"")})});return fe(e,"Could not stop Gmail watch")},Yh=async({accountId:t="",force:e=!0}={})=>{let n=await Y("/api/gmail/watch/renew",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({accountId:String(t||""),force:!!e})});return fe(n,"Could not renew Gmail watch")},Xh=async()=>{let t=await Y("/api/agent/sessions");return fe(t,"Could not load agent sessions")},ua=async()=>{let t=await Y("/api/doctor/status");return fe(t,"Could not load Doctor status")},Qh=async()=>{let t=await Y("/api/doctor/run",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({})});return fe(t,"Could not start Doctor run")};var em=async(t=10)=>{let e=new URLSearchParams({limit:String(t)}),n=await Y(`/api/doctor/runs?${e.toString()}`);return fe(n,"Could not load Doctor runs")},tm=async({runId:t="all"}={})=>{let e=new URLSearchParams;String(t||"").trim()&&e.set("runId",String(t||""));let n=e.toString()?`?${e.toString()}`:"",s=await Y(`/api/doctor/cards${n}`);return fe(s,"Could not load Doctor findings")};var pa=async({cardId:t,status:e})=>{let n=await Y(`/api/doctor/cards/${encodeURIComponent(String(t||""))}/status`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({status:String(e||"")})});return fe(n,"Could not update Doctor card status")},nm=async({cardId:t,sessionId:e="",replyChannel:n="",replyTo:s="",prompt:o=""}={})=>{let r=await Y(`/api/doctor/findings/${encodeURIComponent(String(t||""))}/fix`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sessionId:String(e||""),replyChannel:String(n||""),replyTo:String(s||""),prompt:String(o||"")})});return fe(r,"Could not send Doctor fix request")},fa=async({message:t="",sessionKey:e=""}={})=>{let n=await Y("/api/agent/message",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:String(t||""),sessionKey:String(e||"")})});return fe(n,"Could not send message to agent")};async function sm(){let t=await Y("/api/gateway/restart",{method:"POST"});return fe(t,"Could not restart gateway")}async function om(){let t=await Y("/api/restart-status");return fe(t,"Could not load restart status")}async function rm(){let t=await Y("/api/restart-status/dismiss",{method:"POST"});return fe(t,"Could not dismiss restart status")}async function im(){let t=await Y("/api/watchdog/status");return fe(t,"Could not load watchdog status")}async function am(t=30){let e=new URLSearchParams({days:String(t)}),n=await Y(`/api/usage/summary?${e.toString()}`);return fe(n,"Could not load usage summary")}async function lm(t=50){let e=new URLSearchParams({limit:String(t)}),n=await Y(`/api/usage/sessions?${e.toString()}`);return fe(n,"Could not load usage sessions")}async function cm(t){let e=await Y(`/api/usage/sessions/${encodeURIComponent(String(t||""))}`);return fe(e,"Could not load usage session detail")}async function dm(t=20){let e=await Y(`/api/watchdog/events?limit=${encodeURIComponent(String(t))}`);return fe(e,"Could not load watchdog events")}async function um(t=65536){let e=await Y(`/api/watchdog/logs?tail=${encodeURIComponent(String(t))}`);if(!e.ok)throw new Error("Could not load watchdog logs");return e.text()}async function ad(t){let e=await Y("/api/watchdog/terminal/close",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sessionId:String(t||"")})});return fe(e,"Could not close watchdog terminal")}async function ha(){let t=await Y("/api/watchdog/repair",{method:"POST"});return fe(t,"Could not trigger watchdog repair")}async function pm(){let t=await Y("/api/watchdog/resources");return fe(t,"Could not load system resources")}async function fm(){let t=await Y("/api/watchdog/settings");return fe(t,"Could not load watchdog settings")}async function ld(t){let e=await Y("/api/watchdog/settings",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(t||{})});return fe(e,"Could not update watchdog settings")}async function hm(){return(await Y("/api/gateway/dashboard")).json()}async function mm(t=!1){return(await Y(`/api/openclaw/version${t?"?refresh=1":""}`)).json()}async function ma(){return(await Y("/api/openclaw/update",{method:"POST"})).json()}async function gm(t=!1){return(await Y(`/api/alphaclaw/version${t?"?refresh=1":""}`)).json()}async function bm(t=""){let e=String(t||"").trim(),n=e?`?${new URLSearchParams({tag:e}).toString()}`:"";try{let s=await Y(`/api/alphaclaw/release-notes${n}`);return await fe(s,"Could not load release notes")}catch{let s=e?`https://api.github.com/repos/chrysb/alphaclaw/releases/tags/${encodeURIComponent(e)}`:"https://api.github.com/repos/chrysb/alphaclaw/releases/latest",o=await fetch(s,{headers:{Accept:"application/vnd.github+json"}}),r=await o.text(),i=null;try{i=r?JSON.parse(r):null}catch{throw new Error(r||"Could not load release notes")}if(!o.ok)throw new Error(i?.message||r||"Could not load release notes");return{ok:!0,tag:String(i?.tag_name||e||""),name:String(i?.name||""),body:String(i?.body||""),htmlUrl:String(i?.html_url||""),publishedAt:String(i?.published_at||"")}}}async function xm(){return(await Y("/api/alphaclaw/update",{method:"POST"})).json()}async function ym(t){let e=await Y("/api/sync-cron",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}),n=await e.text(),s;try{s=n?JSON.parse(n):{}}catch{throw new Error(n||"Could not parse sync cron response")}if(!e.ok)throw new Error(s.error||n||`HTTP ${e.status}`);return s}async function vm({sortBy:t="nextRunAtMs",sortDir:e="asc"}={}){let n=new URLSearchParams;t&&n.set("sortBy",String(t)),e&&n.set("sortDir",String(e));let s=n.toString()?`?${n.toString()}`:"",o=await Y(`/api/cron/jobs${s}`);return fe(o,"Could not load cron jobs")}async function $m(){let t=await Y("/api/cron/status");return fe(t,"Could not load cron status")}async function cd(t,{limit:e=20,offset:n=0,status:s="all",deliveryStatus:o="all",sortDir:r="desc",query:i=""}={}){let a=new URLSearchParams({limit:String(e),offset:String(n),status:String(s||"all"),deliveryStatus:String(o||"all"),sortDir:String(r||"desc")});String(i||"").trim()&&a.set("query",String(i).trim());let l=encodeURIComponent(String(t||"")),c=await Y(`/api/cron/jobs/${l}/runs?${a.toString()}`);return fe(c,"Could not load cron run history")}async function wm(t,{days:e=30}={}){let n=new URLSearchParams({days:String(e)}),s=encodeURIComponent(String(t||"")),o=await Y(`/api/cron/jobs/${s}/usage?${n.toString()}`);return fe(o,"Could not load cron job usage")}async function km(t,{range:e="7d"}={}){let n=new URLSearchParams({range:String(e||"7d")}),s=encodeURIComponent(String(t||"")),o=await Y(`/api/cron/jobs/${s}/trends?${n.toString()}`);return fe(o,"Could not load cron job trends")}async function Sm({days:t=30}={}){let e=new URLSearchParams({days:String(t)}),n=await Y(`/api/cron/usage/bulk?${e.toString()}`);return fe(n,"Could not load cron usage overview")}async function Cm({sinceMs:t=0,limitPerJob:e=20,status:n="all",deliveryStatus:s="all",sortDir:o="desc"}={}){let r=new URLSearchParams({sinceMs:String(t||0),limitPerJob:String(e||20),status:String(n||"all"),deliveryStatus:String(s||"all"),sortDir:String(o||"desc")}),i=await Y(`/api/cron/runs/bulk?${r.toString()}`);return fe(i,"Could not load cron run outcomes")}async function _m(t){let e=encodeURIComponent(String(t||"")),n=await Y(`/api/cron/jobs/${e}/run`,{method:"POST"});return fe(n,"Could not trigger cron job run")}async function Mm(t,e){let n=encodeURIComponent(String(t||"")),o=await Y(`/api/cron/jobs/${n}/${e?"enable":"disable"}`,{method:"POST"});return fe(o,"Could not update cron job state")}async function Am(t,e){let n=encodeURIComponent(String(t||"")),s=await Y(`/api/cron/jobs/${n}/prompt`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:String(e||"")})});return fe(s,"Could not update cron prompt")}async function Tm(t,{sessionTarget:e="",wakeMode:n="",deliveryMode:s="",deliveryChannel:o="",deliveryTo:r=""}={}){let i=encodeURIComponent(String(t||"")),a=await Y(`/api/cron/jobs/${i}/routing`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({sessionTarget:String(e||""),wakeMode:String(n||""),deliveryMode:String(s||""),deliveryChannel:String(o||""),deliveryTo:String(r||"")})});return fe(a,"Could not update cron routing")}async function ga(){return(await Y("/api/devices")).json()}async function ba(t){return(await Y(`/api/devices/${t}/approve`,{method:"POST"})).json()}async function xa(t){return(await Y(`/api/devices/${t}/reject`,{method:"POST"})).json()}var Pm=async()=>{let t=await Y("/api/nodes");return fe(t,"Could not load nodes")};var Rm=async t=>{let e=encodeURIComponent(String(t||"")),n=await Y(`/api/nodes/${e}`,{method:"DELETE"});return fe(n,"Could not remove node")},Lm=async t=>{let e=encodeURIComponent(String(t||"")),n=new AbortController,s=setTimeout(()=>n.abort(),2e4);try{let o=await Y(`/api/nodes/${e}/route`,{method:"POST",signal:n.signal});return fe(o,"Could not route execution to node")}catch(o){throw String(o?.name||"")==="AbortError"?new Error("Routing timed out. Gateway may be restarting or unavailable."):o}finally{clearTimeout(s)}},ya=async()=>{let t=await Y("/api/nodes/connect-info");return fe(t,"Could not load connect info")},Em=async(t,e="user")=>{let n=encodeURIComponent(String(t||"")),s=new URLSearchParams({profile:String(e||"user")}),o=await Y(`/api/nodes/${n}/browser-status?${s.toString()}`);return fe(o,"Could not load node browser status")};var Im=async()=>(await Y("/api/auth/status")).json(),Dm=async()=>(await Y("/api/auth/logout",{method:"POST"})).json();async function Nm(){return(await Y("/api/onboard/status")).json()}async function Om(t,e,{importMode:n=!1}={}){return(await Y("/api/onboard",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({vars:t,modelKey:e,importMode:n})})).json()}async function va(t,e,n="new"){return(await Y("/api/onboard/github/verify",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({repo:t,token:e,mode:n})})).json()}async function Bm(t){return(await Y("/api/onboard/import/scan",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({tempDir:t})})).json()}async function Fm({tempDir:t,approvedSecrets:e=[],skipSecretExtraction:n=!1,githubRepo:s="",githubToken:o=""}){return(await Y("/api/onboard/import/apply",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({tempDir:t,approvedSecrets:e,skipSecretExtraction:n,githubRepo:s,githubToken:o})})).json()}var Br=async()=>(await Y("/api/models")).json();var Hm=async({agentId:t}={})=>{let e=t?`?agentId=${encodeURIComponent(t)}`:"";return(await Y(`/api/models/config${e}`)).json()},Wm=async({primary:t,configuredModels:e,profiles:n,authOrder:s,agentId:o}={})=>{let r=o?`?agentId=${encodeURIComponent(o)}`:"";return(await Y(`/api/models/config${r}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({primary:t,configuredModels:e,profiles:n,authOrder:s})})).json()};var Ao=async()=>{let t=await Y("/api/agents");return fe(t,"Could not load agents")},To=async()=>{let t=await Y("/api/channels/accounts");return fe(t,"Could not load channel accounts")},Vm=async({provider:t="",accountId:e="default"}={})=>{let n=new URLSearchParams({provider:String(t||""),accountId:String(e||"default")}),s=await Y(`/api/channels/accounts/token?${n.toString()}`);return fe(s,"Could not load channel token")},jm=async t=>{let e=await Y("/api/channels/accounts",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t||{})});return fe(e,"Could not create channel account")},zm=async t=>{let e=await Y("/api/channels/accounts/jobs",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t||{})});return fe(e,"Could not start channel account operation")},Um=({operationId:t="",onMessage:e=()=>{},onError:n=()=>{}})=>Bh({url:`/api/operations/${encodeURIComponent(String(t||""))}/events`,onMessage:e,onError:n}),Fr=async t=>{let e=await Y("/api/channels/accounts",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(t||{})});return fe(e,"Could not update channel account")},$a=async t=>{let e=await Y("/api/channels/accounts",{method:"DELETE",headers:{"Content-Type":"application/json"},body:JSON.stringify(t||{})});return fe(e,"Could not delete channel account")};var Km=async t=>{let e=await Y(`/api/agents/${encodeURIComponent(String(t||""))}/workspace-size`);return fe(e,"Could not load workspace size")},Gm=async t=>{let e=await Y(`/api/agents/${encodeURIComponent(String(t||""))}/bindings`);return fe(e,"Could not load agent bindings")},qm=async t=>{let e=await Y("/api/agents",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t||{})});return fe(e,"Could not create agent")},Jm=async(t,e)=>{let n=await Y(`/api/agents/${encodeURIComponent(String(t||""))}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(e||{})});return fe(n,"Could not update agent")};var Zm=async(t,{keepWorkspace:e=!0}={})=>{let n=new URLSearchParams({keepWorkspace:e?"true":"false"}),s=await Y(`/api/agents/${encodeURIComponent(String(t||""))}?${n.toString()}`,{method:"DELETE"});return fe(s,"Could not delete agent")},Ym=async t=>{let e=await Y(`/api/agents/${encodeURIComponent(String(t||""))}/default`,{method:"POST"});return fe(e,"Could not set default agent")},Po=async()=>(await Y("/api/codex/status")).json(),Hr=async()=>(await Y("/api/codex/disconnect",{method:"POST"})).json(),Wr=async t=>(await Y("/api/codex/exchange",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({input:t})})).json();async function Vr(){return(await Y("/api/env")).json()}async function dd(t){let e=await Y("/api/env",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({vars:t})}),n=await e.text(),s;try{s=n?JSON.parse(n):{}}catch{throw new Error(n||"Could not parse env save response")}if(!e.ok)throw new Error(s.error||n||`HTTP ${e.status}`);return s}var fe=async(t,e)=>{let n=await t.text(),s;try{s=n?JSON.parse(n):{}}catch{throw new Error(n||e)}if(!t.ok||s?.ok===!1)throw new Error(s.error||n||`HTTP ${t.status}`);return s};async function Xm(){let t=await Y("/api/webhooks");return fe(t,"Could not load webhooks")}async function Qm(t){let e=await Y(`/api/webhooks/${encodeURIComponent(t)}`);return fe(e,"Could not load webhook detail")}async function eg(t,{destination:e=null,oauthCallback:n=!1}={}){let s=await Y("/api/webhooks",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:t,...e?{destination:e}:{},oauthCallback:!!n})});return fe(s,"Could not create webhook")}async function tg(t,{deleteTransformDir:e=!1}={}){let n=await Y(`/api/webhooks/${encodeURIComponent(t)}`,{method:"DELETE",headers:{"Content-Type":"application/json"},body:JSON.stringify({deleteTransformDir:!!e})});return fe(n,"Could not delete webhook")}async function ng(t,{destination:e=null}={}){let n=await Y(`/api/webhooks/${encodeURIComponent(t)}/destination`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({destination:e})});return fe(n,"Could not update webhook destination")}async function sg(t){let e=await Y(`/api/webhooks/${encodeURIComponent(t)}/oauth-callback/rotate`,{method:"POST"});return fe(e,"Could not rotate OAuth callback")}async function og(t,{limit:e=50,offset:n=0,status:s="all"}={}){let o=new URLSearchParams({limit:String(e),offset:String(n),status:String(s||"all")}),r=await Y(`/api/webhooks/${encodeURIComponent(t)}/requests?${o.toString()}`);return fe(r,"Could not load webhook requests")}async function rg(t,e){let n=await Y(`/api/webhooks/${encodeURIComponent(t)}/requests/${encodeURIComponent(String(e))}`);return fe(n,"Could not load webhook request")}var ig=async(t=10)=>{let e=new URLSearchParams({depth:String(t)}),n=await Y(`/api/browse/tree?${e.toString()}`);return fe(n,"Could not load file tree")},ud=async t=>{let e=new URLSearchParams({path:String(t||"")}),n=await Y(`/api/browse/read?${e.toString()}`);return fe(n,"Could not load file content")},ag=async(t,e)=>{let n=String(t||""),s=typeof e=="string"?e:String(e??""),o=await Y("/api/browse/write",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:n,content:s})});return fe(o,"Could not save file")},lg=async t=>{let e=await Y("/api/browse/create-file",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:String(t||"")})});return fe(e,"Could not create file")},cg=async t=>{let e=await Y("/api/browse/create-folder",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:String(t||"")})});return fe(e,"Could not create folder")},dg=async(t,e)=>{let n=await Y("/api/browse/move",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({from:String(t||""),to:String(e||"")})});return fe(n,"Could not move path")},wa=async t=>{let e=await Y("/api/browse/delete",{method:"DELETE",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:String(t||"")})});return fe(e,"Could not delete file")},ug=async t=>{let e=new URLSearchParams({path:String(t||"")}),n=await Y(`/api/browse/download?${e.toString()}`);if(!n.ok){let a=await n.text();throw new Error(a||"Could not download file")}let s=await n.blob(),o=window?.URL||URL;if(!o?.createObjectURL||!o?.revokeObjectURL)throw new Error("Download is not supported in this browser");let r=o.createObjectURL(s),i=String(t||"").split("/").filter(Boolean).pop()||"download";try{let a=document.createElement("a");a.href=r,a.download=i,document.body?.appendChild(a),a.click(),a.remove()}finally{o.revokeObjectURL(r)}return{ok:!0}},pg=async t=>{let e=await Y("/api/browse/restore",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:String(t||"")})});return fe(e,"Could not restore file")},pd=async()=>{let t=await Y("/api/browse/git-summary");return fe(t,"Could not load git summary")},fg=async t=>{let e=new URLSearchParams({path:String(t||"")}),n=await Y(`/api/browse/git-diff?${e.toString()}`);return fe(n,"Could not load file diff")},hg=async({filePath:t,table:e,limit:n=50,offset:s=0})=>{let o=new URLSearchParams({path:String(t||""),table:String(e||""),limit:String(n),offset:String(s)}),r=await Y(`/api/browse/sqlite-table?${o.toString()}`);return fe(r,"Could not load sqlite table data")},mg=async(t="")=>{let e=await Y("/api/browse/git-sync",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:String(t||"")})});return fe(e,"Could not sync changes")};var js=t=>String(t||"").split("/")[0]||"",Ro=t=>{let e=String(t||"").trim();return e==="openai-codex"?"openai":e==="volcengine-plan"?"volcengine":e==="byteplus-plan"?"byteplus":e},jk=[{label:"Opus 4.6",preferredKeys:["anthropic/claude-opus-4-6"]},{label:"Sonnet 4.6",preferredKeys:["anthropic/claude-sonnet-4-6"]},{label:"Codex 5.3",preferredKeys:["openai-codex/gpt-5.3-codex"]},{label:"GPT-5.4",preferredKeys:["openai-codex/gpt-5.4"]},{label:"Gemini 3.1 Pro",preferredKeys:["google/gemini-3.1-pro-preview"]}],Lo=t=>{let e=[],n=new Set;return jk.forEach(s=>{let o=s.preferredKeys.map(r=>t.find(i=>i.key===r)).find(Boolean);!o||n.has(o.key)||(e.push({...o,featuredLabel:s.label}),n.add(o.key))}),e},Mn={anthropic:[{key:"ANTHROPIC_API_KEY",label:"Anthropic API Key",url:"https://console.anthropic.com",linkText:"Get key",placeholder:"sk-ant-..."},{key:"ANTHROPIC_TOKEN",label:"Anthropic Setup Token",hint:"From claude setup-token (uses your Claude subscription)",linkText:"Get token",placeholder:"Token..."}],openai:[{key:"OPENAI_API_KEY",label:"OpenAI API Key",url:"https://platform.openai.com",linkText:"Get key",placeholder:"sk-..."}],google:[{key:"GEMINI_API_KEY",label:"Gemini API Key",url:"https://aistudio.google.com",linkText:"Get key",placeholder:"AI..."}],opencode:[{key:"OPENCODE_API_KEY",label:"OpenCode API Key",placeholder:"oc-..."}],openrouter:[{key:"OPENROUTER_API_KEY",label:"OpenRouter API Key",url:"https://openrouter.ai",linkText:"Get key",placeholder:"sk-or-..."}],zai:[{key:"ZAI_API_KEY",label:"Z.AI API Key",placeholder:"zai-..."}],"vercel-ai-gateway":[{key:"AI_GATEWAY_API_KEY",label:"AI Gateway API Key",placeholder:"aigw_..."}],kilocode:[{key:"KILOCODE_API_KEY",label:"KiloCode API Key",placeholder:"kilo_..."}],xai:[{key:"XAI_API_KEY",label:"xAI API Key",placeholder:"xai-..."}],mistral:[{key:"MISTRAL_API_KEY",label:"Mistral API Key",url:"https://console.mistral.ai",linkText:"Get key",placeholder:"sk-..."}],voyage:[{key:"VOYAGE_API_KEY",label:"Voyage API Key",url:"https://dash.voyageai.com",linkText:"Get key",placeholder:"pa-..."}],groq:[{key:"GROQ_API_KEY",label:"Groq API Key",url:"https://console.groq.com",linkText:"Get key",placeholder:"gsk_..."}],cerebras:[{key:"CEREBRAS_API_KEY",label:"Cerebras API Key",placeholder:"csk-..."}],moonshot:[{key:"MOONSHOT_API_KEY",label:"Moonshot API Key",placeholder:"sk-..."}],"kimi-coding":[{key:"KIMI_API_KEY",label:"Kimi API Key",placeholder:"sk-..."}],volcengine:[{key:"VOLCANO_ENGINE_API_KEY",label:"Volcano Engine API Key",placeholder:"ve-..."}],byteplus:[{key:"BYTEPLUS_API_KEY",label:"BytePlus API Key",placeholder:"bp-..."}],synthetic:[{key:"SYNTHETIC_API_KEY",label:"Synthetic API Key",placeholder:"syn-..."}],minimax:[{key:"MINIMAX_API_KEY",label:"MiniMax API Key",placeholder:"minimax-..."}],deepgram:[{key:"DEEPGRAM_API_KEY",label:"Deepgram API Key",url:"https://console.deepgram.com",linkText:"Get key",placeholder:"dg-..."}],vllm:[{key:"VLLM_API_KEY",label:"vLLM API Key",placeholder:"vllm-local"}]},zs={anthropic:"Anthropic",openai:"OpenAI",google:"Gemini",opencode:"OpenCode Zen",openrouter:"OpenRouter",zai:"Z.AI","vercel-ai-gateway":"Vercel AI Gateway",kilocode:"Kilo Gateway",xai:"xAI",mistral:"Mistral",cerebras:"Cerebras",moonshot:"Moonshot","kimi-coding":"Kimi Coding",volcengine:"Volcano Engine",byteplus:"BytePlus",synthetic:"Synthetic",minimax:"MiniMax",voyage:"Voyage",groq:"Groq",deepgram:"Deepgram",vllm:"vLLM"},jr=["anthropic","openai","google","zai","xai","openrouter","opencode","kilocode","vercel-ai-gateway","minimax","moonshot","kimi-coding","volcengine","byteplus","synthetic","mistral","cerebras","voyage","groq","deepgram","vllm"];var gg=[{id:"embeddings",label:"Memory Embeddings",tag:"Embeddings",providers:["openai","google","voyage","mistral"]},{id:"audio",label:"Audio Transcription",tag:"Audio",hasDefault:!0,providers:["openai","groq","deepgram","google","mistral"]}],bg=t=>{if(t==="openai-codex")return new Set;let e=Ro(t),n=Mn[e]||[];return new Set(n.map(s=>s.key))},xg=Object.values(Mn).flat().filter((t,e,n)=>n.findIndex(s=>s.key===t.key)===e);var Eo=P.bind(T),fd="new",hd="existing",An="fresh",Bt="import",Tn="create",qn="existing-empty",zk=t=>String(t||"").trim().replace(/^git@github\.com:/,"").replace(/^https:\/\/github\.com\//,"").replace(/\.git$/,""),zr=t=>{let e=zk(t);if(!e)return!1;let n=e.split("/").filter(Boolean);return n.length===2&&!n.some(s=>/\s/.test(s))},Ht=[{id:"github",title:"GitHub",description:"Auto-backup your config and workspace",fields:[{key:"_GITHUB_SOURCE_REPO",label:"Source Repo",placeholder:"username/existing-openclaw",isText:!0},{key:"GITHUB_WORKSPACE_REPO",label:"New Workspace Repo",placeholder:"username/my-agent",isText:!0},{key:"GITHUB_TOKEN",label:"Personal Access Token",hint:Eo`Create a${" "}2&&(i.children=arguments.length>3?Tr.call(arguments,2):n),typeof t=="function"&&t.defaultProps!=null)for(r in t.defaultProps)i[r]===void 0&&(i[r]=t.defaultProps[r]);return Mr(t,i,s,o,null)}function Mr(t,e,n,s,o){var r={type:t,props:e,key:n,ref:s,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:o??++qf,__i:-1,__u:0};return o==null&&Se.vnode!=null&&Se.vnode(r),r}function ln(t){return t.children}function hn(t,e){this.props=t,this.context=e}function $o(t,e){if(e==null)return t.__?$o(t.__,t.__i+1):null;for(var n;ee&&ms.sort(Zf),t=ms.shift(),e=ms.length,Tk(t)}finally{ms.length=ia.__r=0}}function eh(t,e,n,s,o,r,i,a,l,c,d){var u,p,f,g,m,h,b,x=s&&s.__k||ra,v=e.length;for(l=Pk(n,e,x,l,v),u=0;u0?i=t.__k[r]=Mr(i.type,i.props,i.key,i.ref?i.ref:null,i.__v):t.__k[r]=i,l=r+p,i.__=t,i.__b=t.__b+1,a=null,(c=i.__i=Rk(i,n,l,u))!=-1&&(u--,(a=n[c])&&(a.__u|=2)),a==null||a.__v==null?(c==-1&&(o>d?p--:ol?p--:p++,i.__u|=4))):t.__k[r]=null;if(u)for(r=0;r(d?1:0)){for(o=n-1,r=n+1;o>=0||r=0?o--:r++])!=null&&(2&c.__u)==0&&a==c.key&&l==c.type)return i}return-1}function Kf(t,e,n){e[0]=="-"?t.setProperty(e,n??""):t[e]=n==null?"":typeof n!="number"||Mk.test(e)?n:n+"px"}function sa(t,e,n,s,o){var r,i;e:if(e=="style")if(typeof n=="string")t.style.cssText=n;else{if(typeof s=="string"&&(t.style.cssText=s=""),s)for(e in s)n&&e in n||Kf(t.style,e,"");if(n)for(e in n)s&&n[e]==s[e]||Kf(t.style,e,n[e])}else if(e[0]=="o"&&e[1]=="n")r=e!=(e=e.replace(Yf,"$1")),i=e.toLowerCase(),e=i in t||e=="onFocusOut"||e=="onFocusIn"?i.slice(2):e.slice(2),t.l||(t.l={}),t.l[e+r]=n,n?s?n.u=s.u:(n.u=qc,t.addEventListener(e,r?Uc:zc,r)):t.removeEventListener(e,r?Uc:zc,r);else{if(o=="http://www.w3.org/2000/svg")e=e.replace(/xlink(H|:h)/,"h").replace(/sName$/,"s");else if(e!="width"&&e!="height"&&e!="href"&&e!="list"&&e!="form"&&e!="tabIndex"&&e!="download"&&e!="rowSpan"&&e!="colSpan"&&e!="role"&&e!="popover"&&e in t)try{t[e]=n??"";break e}catch{}typeof n=="function"||(n==null||n===!1&&e[4]!="-"?t.removeAttribute(e):t.setAttribute(e,e=="popover"&&n==1?"":n))}}function Gf(t){return function(e){if(this.l){var n=this.l[e.type+t];if(e.t==null)e.t=qc++;else if(e.t0?t:Rr(t)?t.map(sh):_n({},t)}function Lk(t,e,n,s,o,r,i,a,l){var c,d,u,p,f,g,m,h=n.props||oa,b=e.props,x=e.type;if(x=="svg"?o="http://www.w3.org/2000/svg":x=="math"?o="http://www.w3.org/1998/Math/MathML":o||(o="http://www.w3.org/1999/xhtml"),r!=null){for(c=0;c2&&(a.children=arguments.length>3?Tr.call(arguments,2):n),Mr(t.type,a,s||t.key,o||t.ref,null)}function ko(t){function e(n){var s,o;return this.getChildContext||(s=new Set,(o={})[e.__c]=this,this.getChildContext=function(){return o},this.componentWillUnmount=function(){s=null},this.shouldComponentUpdate=function(r){this.props.value!=r.value&&s.forEach(function(i){i.__e=!0,Kc(i)})},this.sub=function(r){s.add(r);var i=r.componentWillUnmount;r.componentWillUnmount=function(){s&&s.delete(r),i&&i.call(r)}}),n.children}return e.__c="__cC"+Xf++,e.__=t,e.Provider=e.__l=(e.Consumer=function(n,s){return n.children(s)}).contextType=e,e}Tr=ra.slice,Se={__e:function(t,e,n,s){for(var o,r,i;e=e.__;)if((o=e.__c)&&!o.__)try{if((r=o.constructor)&&r.getDerivedStateFromError!=null&&(o.setState(r.getDerivedStateFromError(t)),i=o.__d),o.componentDidCatch!=null&&(o.componentDidCatch(t,s||{}),i=o.__d),i)return o.__E=o}catch(a){t=a}throw t}},qf=0,Pr=function(t){return t!=null&&t.constructor===void 0},hn.prototype.setState=function(t,e){var n;n=this.__s!=null&&this.__s!=this.state?this.__s:this.__s=_n({},this.state),typeof t=="function"&&(t=t(_n({},n),this.props)),t&&_n(n,t),t!=null&&this.__v&&(e&&this._sb.push(e),Kc(this))},hn.prototype.forceUpdate=function(t){this.__v&&(this.__e=!0,t&&this.__h.push(t),Kc(this))},hn.prototype.render=ln,ms=[],Jf=typeof Promise=="function"?Promise.prototype.then.bind(Promise.resolve()):setTimeout,Zf=function(t,e){return t.__v.__b-e.__v.__b},ia.__r=0,Yf=/(PointerCapture)$|Capture$/i,qc=0,zc=Gf(!1),Uc=Gf(!0),Xf=0;var Vs,nt,Xc,rh,Ir=0,fh=[],ut=Se,ih=ut.__b,ah=ut.__r,lh=ut.diffed,ch=ut.__c,dh=ut.unmount,uh=ut.__;function Dr(t,e){ut.__h&&ut.__h(nt,t,Ir||e),Ir=0;var n=nt.__H||(nt.__H={__:[],__h:[]});return t>=n.__.length&&n.__.push({}),n.__[t]}function y(t){return Ir=1,hh(mh,t)}function hh(t,e,n){var s=Dr(Vs++,2);if(s.t=t,!s.__c&&(s.__=[n?n(e):mh(void 0,e),function(a){var l=s.__N?s.__N[0]:s.__[0],c=s.t(l,a);l!==c&&(s.__N=[c,s.__[1]],s.__c.setState({}))}],s.__c=nt,!nt.__f)){var o=function(a,l,c){if(!s.__c.__H)return!0;var d=s.__c.__H.__.filter(function(p){return p.__c});if(d.every(function(p){return!p.__N}))return!r||r.call(this,a,l,c);var u=s.__c.props!==a;return d.some(function(p){if(p.__N){var f=p.__[0];p.__=p.__N,p.__N=void 0,f!==p.__[0]&&(u=!0)}}),r&&r.call(this,a,l,c)||u};nt.__f=!0;var r=nt.shouldComponentUpdate,i=nt.componentWillUpdate;nt.componentWillUpdate=function(a,l,c){if(this.__e){var d=r;r=void 0,o(a,l,c),r=d}i&&i.call(this,a,l,c)},nt.shouldComponentUpdate=o}return s.__N||s.__}function L(t,e){var n=Dr(Vs++,3);!ut.__s&&ed(n.__H,e)&&(n.__=t,n.u=e,nt.__H.__h.push(n))}function js(t,e){var n=Dr(Vs++,4);!ut.__s&&ed(n.__H,e)&&(n.__=t,n.u=e,nt.__h.push(n))}function ee(t){return Ir=5,F(function(){return{current:t}},[])}function F(t,e){var n=Dr(Vs++,7);return ed(n.__H,e)&&(n.__=t(),n.__H=e,n.__h=t),n.__}function q(t,e){return Ir=8,F(function(){return t},e)}function Nr(t){var e=nt.context[t.__c],n=Dr(Vs++,9);return n.c=t,e?(n.__==null&&(n.__=!0,e.sub(nt)),e.props.value):t.__}function Ik(){for(var t;t=fh.shift();){var e=t.__H;if(t.__P&&e)try{e.__h.some(aa),e.__h.some(Qc),e.__h=[]}catch(n){e.__h=[],ut.__e(n,t.__v)}}}ut.__b=function(t){nt=null,ih&&ih(t)},ut.__=function(t,e){t&&e.__k&&e.__k.__m&&(t.__m=e.__k.__m),uh&&uh(t,e)},ut.__r=function(t){ah&&ah(t),Vs=0;var e=(nt=t.__c).__H;e&&(Xc===nt?(e.__h=[],nt.__h=[],e.__.some(function(n){n.__N&&(n.__=n.__N),n.u=n.__N=void 0})):(e.__h.some(aa),e.__h.some(Qc),e.__h=[],Vs=0)),Xc=nt},ut.diffed=function(t){lh&&lh(t);var e=t.__c;e&&e.__H&&(e.__H.__h.length&&(fh.push(e)!==1&&rh===ut.requestAnimationFrame||((rh=ut.requestAnimationFrame)||Dk)(Ik)),e.__H.__.some(function(n){n.u&&(n.__H=n.u),n.u=void 0})),Xc=nt=null},ut.__c=function(t,e){e.some(function(n){try{n.__h.some(aa),n.__h=n.__h.filter(function(s){return!s.__||Qc(s)})}catch(s){e.some(function(o){o.__h&&(o.__h=[])}),e=[],ut.__e(s,n.__v)}}),ch&&ch(t,e)},ut.unmount=function(t){dh&&dh(t);var e,n=t.__c;n&&n.__H&&(n.__H.__.some(function(s){try{aa(s)}catch(o){e=o}}),n.__H=void 0,e&&ut.__e(e,n.__v))};var ph=typeof requestAnimationFrame=="function";function Dk(t){var e,n=function(){clearTimeout(s),ph&&cancelAnimationFrame(e),setTimeout(t)},s=setTimeout(n,35);ph&&(e=requestAnimationFrame(n))}function aa(t){var e=nt,n=t.__c;typeof n=="function"&&(t.__c=void 0,n()),nt=e}function Qc(t){var e=nt;t.__c=t.__(),nt=e}function ed(t,e){return!t||t.length!==e.length||e.some(function(n,s){return n!==t[s]})}function mh(t,e){return typeof e=="function"?e(t):e}var bh=function(t,e,n,s){var o;e[0]=0;for(var r=1;r=5&&((i||!p&&r===5)&&(l.push(r,0,i,o),r=6),p&&(l.push(r,p,0,o),r=6)),i=""},d=0;d"?(r=1,i=""):i=s+i[0]:a?s===a?a="":i+=s:s==='"'||s==="'"?a=s:s===">"?(c(),r=1):r&&(s==="="?(r=5,o=i,i=""):s==="/"&&(r<5||n[d][u+1]===">")?(c(),r===3&&(l=l[0]),r=l,(l=l[0]).push(2,0,r),r=0):s===" "||s===" "||s===`
+`||s==="\r"?(c(),r=2):i+=s),r===3&&i==="!--"&&(r=4,l=l[0])}return c(),l})(t)),e),arguments,[])).length>1?e:e[0]}function xh(t,e){if(t instanceof RegExp)return{keys:!1,pattern:t};var n,s,o,r,i=[],a="",l=t.split("/");for(l[0]||l.shift();o=l.shift();)n=o[0],n==="*"?(i.push(n),a+=o[1]==="?"?"(?:/(.*))?":"/(.*)"):n===":"?(s=o.indexOf("?",1),r=o.indexOf(".",1),i.push(o.substring(1,~s?s:~r?r:o.length)),a+=~s&&!~r?"(?:/([^/]+?))?":"/([^/]+?)",~r&&(a+=(~s?"?":"")+"\\"+o.substring(r))):a+="/"+o;return{keys:i,pattern:new RegExp("^"+a+(e?"(?=$|/)":"/?$"),"i")}}var Nk=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";function td(t,e){return t===e&&(t!==0||1/t===1/e)||t!==t&&e!==e}function yh(t,e,n){n&&!Nk&&(e=n);let s=e(),[{_instance:o},r]=y({_instance:{_value:s,_getSnapshot:e}});return js(()=>{o._value=s,o._getSnapshot=e,td(o._value,e())||r({_instance:o})},[t,s,e]),L(()=>(td(o._value,o._getSnapshot())||r({_instance:o}),t(()=>{td(o._value,o._getSnapshot())||r({_instance:o})})),[t]),s}var nd=t=>{let e=ee([t,(...n)=>e[0](...n)]).current;return js(()=>{e[0]=t}),e[1]};var Ok="popstate",sd="pushState",od="replaceState",Bk="hashchange",vh=[Ok,sd,od,Bk],Fk=t=>{for(let e of vh)addEventListener(e,t);return()=>{for(let e of vh)removeEventListener(e,t)}},Sh=(t,e)=>yh(Fk,t,e),$h=()=>location.search,Ch=({ssrSearch:t}={})=>Sh($h,t!=null?()=>t:$h),wh=()=>location.pathname,Hk=({ssrPath:t}={})=>Sh(wh,t!=null?()=>t:wh);var Wk=(t,{replace:e=!1,state:n=null}={})=>history[e?od:sd](n,"",t),_h=(t={})=>[Hk(t),Wk],kh=Symbol.for("wouter_v3");if(typeof history<"u"&&typeof window[kh]>"u"){for(let t of[sd,od]){let e=history[t];history[t]=function(){let n=e.apply(this,arguments),s=new Event(t);return s.arguments=arguments,dispatchEvent(s),n}}Object.defineProperty(window,kh,{value:!0})}var Vk=(t,e)=>e.toLowerCase().indexOf(t.toLowerCase())?"~"+e:e.slice(t.length)||"/",Mh=(t="")=>t==="/"?"":t,Th=(t,e)=>t[0]==="~"?t.slice(1):Mh(e)+t,Ph=(t="",e)=>Vk(Ah(Mh(t)),Ah(e));var Ah=t=>{try{return decodeURI(t)}catch{return t}};var Lh={hook:_h,searchHook:Ch,parser:xh,base:"",ssrPath:void 0,ssrSearch:void 0,ssrContext:void 0,hrefs:t=>t,aroundNav:(t,e,n)=>t(e,n)},Eh=ko(Lh),Or=()=>Nr(Eh),Ih={},Dh=ko(Ih),jk=()=>Nr(Dh),la=t=>{let[e,n]=t.hook(t);return[Ph(t.base,e),nd((s,o)=>t.aroundNav(n,Th(s,t.base),o))]},ca=()=>la(Or());var Nh=(t,e,n,s)=>{let{pattern:o,keys:r}=e instanceof RegExp?{keys:!1,pattern:e}:t(e||"*",s),i=o.exec(n)||[],[a,...l]=i;return a!==void 0?[!0,(()=>{let c=r!==!1?Object.fromEntries(r.map((u,p)=>[u,l[p]])):i.groups,d={...l};return c&&Object.assign(d,c),d})(),...s?[a]:[]]:[!1,null]};var da=({children:t,...e})=>{let n=Or(),s=e.hook?Lh:n,o=s,[r,i=e.ssrSearch??""]=e.ssrPath?.split("?")??[];r&&(e.ssrSearch=i,e.ssrPath=r),e.hrefs=e.hrefs??e.hook?.hrefs,e.searchHook=e.searchHook??e.hook?.searchHook;let a=ee({}),l=a.current,c=l;for(let d in s){let u=d==="base"?s[d]+(e[d]??""):e[d]??s[d];l===c&&u!==c[d]&&(a.current=c={...c}),c[d]=u,(u!==s[d]||u!==o[d])&&(o=c)}return T(Eh.Provider,{value:o,children:t})},Rh=({children:t,component:e},n)=>e?T(e,{params:n}):typeof t=="function"?t(n):t,zk=t=>{let e=ee(Ih),n=e.current;return e.current=Object.keys(t).length!==Object.keys(n).length||Object.entries(t).some(([s,o])=>o!==n[s])?t:n};var rt=({path:t,nest:e,match:n,...s})=>{let o=Or(),[r]=la(o),[i,a,l]=n??Nh(o.parser,t,r,e),c=zk({...jk(),...a});if(!i)return null;let d=l?T(da,{base:l},Rh(s,c)):Rh(s,c);return T(Dh.Provider,{value:c,children:d})},f4=(t,e)=>{let n=Or(),[s,o]=la(n),{to:r="",href:i=r,onClick:a,asChild:l,children:c,className:d,replace:u,state:p,transition:f,...g}=t,m=nd(b=>{b.ctrlKey||b.metaKey||b.altKey||b.shiftKey||b.button!==0||(a?.(b),b.defaultPrevented||(b.preventDefault(),o(i,t)))}),h=n.hrefs(i[0]==="~"?i.slice(1):n.base+i,n);return l&&Pr(c)?Er(c,{onClick:m,href:h}):T("a",{...g,onClick:m,href:h,className:d?.call?d(s===i):d,children:c,ref:e})},Oh=t=>Array.isArray(t)?t.flatMap(e=>Oh(e&&e.type===ln?e.props.children:e)):[t],rd=({children:t,location:e})=>{let n=Or(),[s]=la(n);for(let o of Oh(t)){let r=0;if(Pr(o)&&(r=Nh(n.parser,o.props.path,e||s,o.props.nest))[0])return Er(o,{match:r})}return null};var id=t=>{if(typeof t!="string"||!t.trim())return{};try{return JSON.parse(t)}catch{return{}}},Bh=({url:t="",onMessage:e=()=>{},onError:n=()=>{}})=>{if(typeof window?.EventSource!="function")throw new Error("Server events are not supported in this browser");let s=new window.EventSource(String(t||""),{withCredentials:!0}),o=l=>{e({event:"phase",data:id(l?.data||"")})},r=l=>{e({event:"done",data:id(l?.data||"")})},i=l=>{e({event:"error",data:id(l?.data||"")})},a=l=>{n(l)};return s.addEventListener("phase",o),s.addEventListener("done",r),s.addEventListener("error",i),s.onerror=a,()=>{s.removeEventListener("phase",o),s.removeEventListener("done",r),s.removeEventListener("error",i),s.onerror=null,s.close()}};var Fh="x-client-timezone",Uk=()=>{try{return Intl?.DateTimeFormat?.().resolvedOptions?.().timeZone||""}catch{return""}},X=async(t,e={})=>{let n={...e},s=new Headers(e?.headers||{});if(!s.has(Fh)){let r=Uk();r&&s.set(Fh,r)}n.headers=s;let o=await fetch(t,n);if(o.status===401){try{window.localStorage?.clear?.()}catch{}throw window.location.href="/setup",new Error("Unauthorized")}return o},Hh=({onMessage:t=()=>{},onOpen:e=()=>{},onError:n=()=>{}}={})=>{if(typeof window?.EventSource!="function")throw new Error("Server events are not supported in this browser");let s=new window.EventSource("/api/events/status",{withCredentials:!0}),o=r=>{let i={};try{i=r?.data?JSON.parse(r.data):{}}catch{}t(i||{})};return s.addEventListener("status",o),s.onopen=()=>e(),s.onerror=r=>n(r),()=>{s.removeEventListener("status",o),s.onopen=null,s.onerror=null,s.close()}};async function So(){return(await X("/api/status")).json()}async function Co(){return(await X("/api/pairings")).json()}async function _o(t,e,n=""){return(await X(`/api/pairings/${t}/approve`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({channel:e,accountId:n})})).json()}async function Ao(t,e,n=""){let s=await X(`/api/pairings/${t}/reject`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({channel:e,accountId:n})});return he(s,"Could not reject pairing")}async function Wh(){return(await X("/api/google/accounts")).json()}async function Vh({accountId:t="",client:e=""}={}){let n=new URLSearchParams;t&&n.set("accountId",String(t)),e&&n.set("client",String(e));let s=n.toString()?`?${n.toString()}`:"";return(await X(`/api/google/credentials${s}`)).json()}async function jh(t=""){let e=new URLSearchParams;t&&e.set("accountId",String(t));let n=e.toString()?`?${e.toString()}`:"";return(await X(`/api/google/check${n}`)).json()}async function zh({clientId:t,clientSecret:e,email:n,services:s=[],client:o="default",personal:r=!1,accountId:i=""}){return(await X("/api/google/credentials",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({clientId:t,clientSecret:e,email:n,services:s,client:o,personal:r,accountId:i})})).json()}async function Uh({email:t,services:e=[],client:n="default",personal:s=!1,accountId:o=""}){return(await X("/api/google/accounts",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:t,services:e,client:n,personal:s,accountId:o})})).json()}async function Kh(t=""){return(await X("/api/google/disconnect",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({accountId:t})})).json()}var Gh=async()=>{let t=await X("/api/gmail/config");return he(t,"Could not load Gmail watch config")},qh=async({client:t="default",topicPath:e="",projectId:n="",regeneratePushToken:s=!1}={})=>{let o=await X("/api/gmail/config",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({client:t,topicPath:e,projectId:n,regeneratePushToken:s})});return he(o,"Could not save Gmail watch config")},Jh=async(t,{destination:e=null}={})=>{let n=await X("/api/gmail/watch/start",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({accountId:String(t||""),...e?{destination:e}:{}})});return he(n,"Could not start Gmail watch")},Zh=async t=>{let e=await X("/api/gmail/watch/stop",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({accountId:String(t||"")})});return he(e,"Could not stop Gmail watch")},Yh=async({accountId:t="",force:e=!0}={})=>{let n=await X("/api/gmail/watch/renew",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({accountId:String(t||""),force:!!e})});return he(n,"Could not renew Gmail watch")},Xh=async()=>{let t=await X("/api/agent/sessions");return he(t,"Could not load agent sessions")},ua=async()=>{let t=await X("/api/doctor/status");return he(t,"Could not load Doctor status")},Qh=async()=>{let t=await X("/api/doctor/run",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({})});return he(t,"Could not start Doctor run")};var em=async(t=10)=>{let e=new URLSearchParams({limit:String(t)}),n=await X(`/api/doctor/runs?${e.toString()}`);return he(n,"Could not load Doctor runs")},tm=async({runId:t="all"}={})=>{let e=new URLSearchParams;String(t||"").trim()&&e.set("runId",String(t||""));let n=e.toString()?`?${e.toString()}`:"",s=await X(`/api/doctor/cards${n}`);return he(s,"Could not load Doctor findings")};var pa=async({cardId:t,status:e})=>{let n=await X(`/api/doctor/cards/${encodeURIComponent(String(t||""))}/status`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({status:String(e||"")})});return he(n,"Could not update Doctor card status")},nm=async({cardId:t,sessionId:e="",replyChannel:n="",replyTo:s="",prompt:o=""}={})=>{let r=await X(`/api/doctor/findings/${encodeURIComponent(String(t||""))}/fix`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sessionId:String(e||""),replyChannel:String(n||""),replyTo:String(s||""),prompt:String(o||"")})});return he(r,"Could not send Doctor fix request")},fa=async({message:t="",sessionKey:e=""}={})=>{let n=await X("/api/agent/message",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:String(t||""),sessionKey:String(e||"")})});return he(n,"Could not send message to agent")};async function sm(){let t=await X("/api/gateway/restart",{method:"POST"});return he(t,"Could not restart gateway")}async function om(){let t=await X("/api/restart-status");return he(t,"Could not load restart status")}async function rm(){let t=await X("/api/restart-status/dismiss",{method:"POST"});return he(t,"Could not dismiss restart status")}async function im(){let t=await X("/api/watchdog/status");return he(t,"Could not load watchdog status")}async function am(t=30){let e=new URLSearchParams({days:String(t)}),n=await X(`/api/usage/summary?${e.toString()}`);return he(n,"Could not load usage summary")}async function lm(t=50){let e=new URLSearchParams({limit:String(t)}),n=await X(`/api/usage/sessions?${e.toString()}`);return he(n,"Could not load usage sessions")}async function cm(t){let e=await X(`/api/usage/sessions/${encodeURIComponent(String(t||""))}`);return he(e,"Could not load usage session detail")}async function dm(t=20){let e=await X(`/api/watchdog/events?limit=${encodeURIComponent(String(t))}`);return he(e,"Could not load watchdog events")}async function um(t=65536){let e=await X(`/api/watchdog/logs?tail=${encodeURIComponent(String(t))}`);if(!e.ok)throw new Error("Could not load watchdog logs");return e.text()}async function ad(t){let e=await X("/api/watchdog/terminal/close",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sessionId:String(t||"")})});return he(e,"Could not close watchdog terminal")}async function ha(){let t=await X("/api/watchdog/repair",{method:"POST"});return he(t,"Could not trigger watchdog repair")}async function pm(){let t=await X("/api/watchdog/resources");return he(t,"Could not load system resources")}async function fm(){let t=await X("/api/watchdog/settings");return he(t,"Could not load watchdog settings")}async function ld(t){let e=await X("/api/watchdog/settings",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(t||{})});return he(e,"Could not update watchdog settings")}async function hm(){return(await X("/api/gateway/dashboard")).json()}async function mm(t=!1){return(await X(`/api/openclaw/version${t?"?refresh=1":""}`)).json()}async function ma(){return(await X("/api/openclaw/update",{method:"POST"})).json()}async function gm(t=!1){return(await X(`/api/alphaclaw/version${t?"?refresh=1":""}`)).json()}async function bm(t=""){let e=String(t||"").trim(),n=e?`?${new URLSearchParams({tag:e}).toString()}`:"";try{let s=await X(`/api/alphaclaw/release-notes${n}`);return await he(s,"Could not load release notes")}catch{let s=e?`https://api.github.com/repos/chrysb/alphaclaw/releases/tags/${encodeURIComponent(e)}`:"https://api.github.com/repos/chrysb/alphaclaw/releases/latest",o=await fetch(s,{headers:{Accept:"application/vnd.github+json"}}),r=await o.text(),i=null;try{i=r?JSON.parse(r):null}catch{throw new Error(r||"Could not load release notes")}if(!o.ok)throw new Error(i?.message||r||"Could not load release notes");return{ok:!0,tag:String(i?.tag_name||e||""),name:String(i?.name||""),body:String(i?.body||""),htmlUrl:String(i?.html_url||""),publishedAt:String(i?.published_at||"")}}}async function xm(){return(await X("/api/alphaclaw/update",{method:"POST"})).json()}async function ym(t){let e=await X("/api/sync-cron",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}),n=await e.text(),s;try{s=n?JSON.parse(n):{}}catch{throw new Error(n||"Could not parse sync cron response")}if(!e.ok)throw new Error(s.error||n||`HTTP ${e.status}`);return s}async function vm({sortBy:t="nextRunAtMs",sortDir:e="asc"}={}){let n=new URLSearchParams;t&&n.set("sortBy",String(t)),e&&n.set("sortDir",String(e));let s=n.toString()?`?${n.toString()}`:"",o=await X(`/api/cron/jobs${s}`);return he(o,"Could not load cron jobs")}async function $m(){let t=await X("/api/cron/status");return he(t,"Could not load cron status")}async function cd(t,{limit:e=20,offset:n=0,status:s="all",deliveryStatus:o="all",sortDir:r="desc",query:i=""}={}){let a=new URLSearchParams({limit:String(e),offset:String(n),status:String(s||"all"),deliveryStatus:String(o||"all"),sortDir:String(r||"desc")});String(i||"").trim()&&a.set("query",String(i).trim());let l=encodeURIComponent(String(t||"")),c=await X(`/api/cron/jobs/${l}/runs?${a.toString()}`);return he(c,"Could not load cron run history")}async function wm(t,{days:e=30}={}){let n=new URLSearchParams({days:String(e)}),s=encodeURIComponent(String(t||"")),o=await X(`/api/cron/jobs/${s}/usage?${n.toString()}`);return he(o,"Could not load cron job usage")}async function km(t,{range:e="7d"}={}){let n=new URLSearchParams({range:String(e||"7d")}),s=encodeURIComponent(String(t||"")),o=await X(`/api/cron/jobs/${s}/trends?${n.toString()}`);return he(o,"Could not load cron job trends")}async function Sm({days:t=30}={}){let e=new URLSearchParams({days:String(t)}),n=await X(`/api/cron/usage/bulk?${e.toString()}`);return he(n,"Could not load cron usage overview")}async function Cm({sinceMs:t=0,limitPerJob:e=20,status:n="all",deliveryStatus:s="all",sortDir:o="desc"}={}){let r=new URLSearchParams({sinceMs:String(t||0),limitPerJob:String(e||20),status:String(n||"all"),deliveryStatus:String(s||"all"),sortDir:String(o||"desc")}),i=await X(`/api/cron/runs/bulk?${r.toString()}`);return he(i,"Could not load cron run outcomes")}async function _m(t){let e=encodeURIComponent(String(t||"")),n=await X(`/api/cron/jobs/${e}/run`,{method:"POST"});return he(n,"Could not trigger cron job run")}async function Am(t,e){let n=encodeURIComponent(String(t||"")),o=await X(`/api/cron/jobs/${n}/${e?"enable":"disable"}`,{method:"POST"});return he(o,"Could not update cron job state")}async function Mm(t,e){let n=encodeURIComponent(String(t||"")),s=await X(`/api/cron/jobs/${n}/prompt`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:String(e||"")})});return he(s,"Could not update cron prompt")}async function Tm(t,{sessionTarget:e="",wakeMode:n="",deliveryMode:s="",deliveryChannel:o="",deliveryTo:r=""}={}){let i=encodeURIComponent(String(t||"")),a=await X(`/api/cron/jobs/${i}/routing`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({sessionTarget:String(e||""),wakeMode:String(n||""),deliveryMode:String(s||""),deliveryChannel:String(o||""),deliveryTo:String(r||"")})});return he(a,"Could not update cron routing")}async function ga(){return(await X("/api/devices")).json()}async function ba(t){return(await X(`/api/devices/${t}/approve`,{method:"POST"})).json()}async function xa(t){return(await X(`/api/devices/${t}/reject`,{method:"POST"})).json()}var Pm=async()=>{let t=await X("/api/nodes");return he(t,"Could not load nodes")};var Rm=async t=>{let e=encodeURIComponent(String(t||"")),n=await X(`/api/nodes/${e}`,{method:"DELETE"});return he(n,"Could not remove node")},Lm=async t=>{let e=encodeURIComponent(String(t||"")),n=new AbortController,s=setTimeout(()=>n.abort(),2e4);try{let o=await X(`/api/nodes/${e}/route`,{method:"POST",signal:n.signal});return he(o,"Could not route execution to node")}catch(o){throw String(o?.name||"")==="AbortError"?new Error("Routing timed out. Gateway may be restarting or unavailable."):o}finally{clearTimeout(s)}},ya=async()=>{let t=await X("/api/nodes/connect-info");return he(t,"Could not load connect info")},Em=async(t,e="user")=>{let n=encodeURIComponent(String(t||"")),s=new URLSearchParams({profile:String(e||"user")}),o=await X(`/api/nodes/${n}/browser-status?${s.toString()}`);return he(o,"Could not load node browser status")};var Im=async()=>(await X("/api/auth/status")).json(),Dm=async()=>(await X("/api/auth/logout",{method:"POST"})).json();async function Nm(){return(await X("/api/onboard/status")).json()}async function Om(t,e,{importMode:n=!1}={}){return(await X("/api/onboard",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({vars:t,modelKey:e,importMode:n})})).json()}async function va(t,e,n="new"){return(await X("/api/onboard/github/verify",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({repo:t,token:e,mode:n})})).json()}async function Bm(t){return(await X("/api/onboard/import/scan",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({tempDir:t})})).json()}async function Fm({tempDir:t,approvedSecrets:e=[],skipSecretExtraction:n=!1,githubRepo:s="",githubToken:o=""}){return(await X("/api/onboard/import/apply",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({tempDir:t,approvedSecrets:e,skipSecretExtraction:n,githubRepo:s,githubToken:o})})).json()}var Br=async()=>(await X("/api/models")).json();var Hm=async({agentId:t}={})=>{let e=t?`?agentId=${encodeURIComponent(t)}`:"";return(await X(`/api/models/config${e}`)).json()},Wm=async({primary:t,configuredModels:e,profiles:n,authOrder:s,agentId:o}={})=>{let r=o?`?agentId=${encodeURIComponent(o)}`:"";return(await X(`/api/models/config${r}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({primary:t,configuredModels:e,profiles:n,authOrder:s})})).json()};var Mo=async()=>{let t=await X("/api/agents");return he(t,"Could not load agents")},To=async()=>{let t=await X("/api/channels/accounts");return he(t,"Could not load channel accounts")},Vm=async({provider:t="",accountId:e="default"}={})=>{let n=new URLSearchParams({provider:String(t||""),accountId:String(e||"default")}),s=await X(`/api/channels/accounts/token?${n.toString()}`);return he(s,"Could not load channel token")},jm=async t=>{let e=await X("/api/channels/accounts",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t||{})});return he(e,"Could not create channel account")},zm=async t=>{let e=await X("/api/channels/accounts/jobs",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t||{})});return he(e,"Could not start channel account operation")},Um=({operationId:t="",onMessage:e=()=>{},onError:n=()=>{}})=>Bh({url:`/api/operations/${encodeURIComponent(String(t||""))}/events`,onMessage:e,onError:n}),Fr=async t=>{let e=await X("/api/channels/accounts",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(t||{})});return he(e,"Could not update channel account")},$a=async t=>{let e=await X("/api/channels/accounts",{method:"DELETE",headers:{"Content-Type":"application/json"},body:JSON.stringify(t||{})});return he(e,"Could not delete channel account")},Km=async t=>{let e=await X("/api/channels/accounts/login",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t||{})});return he(e,"Could not run channel login")};var Gm=async t=>{let e=await X(`/api/agents/${encodeURIComponent(String(t||""))}/workspace-size`);return he(e,"Could not load workspace size")},qm=async t=>{let e=await X(`/api/agents/${encodeURIComponent(String(t||""))}/bindings`);return he(e,"Could not load agent bindings")},Jm=async t=>{let e=await X("/api/agents",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t||{})});return he(e,"Could not create agent")},Zm=async(t,e)=>{let n=await X(`/api/agents/${encodeURIComponent(String(t||""))}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(e||{})});return he(n,"Could not update agent")};var Ym=async(t,{keepWorkspace:e=!0}={})=>{let n=new URLSearchParams({keepWorkspace:e?"true":"false"}),s=await X(`/api/agents/${encodeURIComponent(String(t||""))}?${n.toString()}`,{method:"DELETE"});return he(s,"Could not delete agent")},Xm=async t=>{let e=await X(`/api/agents/${encodeURIComponent(String(t||""))}/default`,{method:"POST"});return he(e,"Could not set default agent")},Po=async()=>(await X("/api/codex/status")).json(),Hr=async()=>(await X("/api/codex/disconnect",{method:"POST"})).json(),Wr=async t=>(await X("/api/codex/exchange",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({input:t})})).json();async function Vr(){return(await X("/api/env")).json()}async function dd(t){let e=await X("/api/env",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({vars:t})}),n=await e.text(),s;try{s=n?JSON.parse(n):{}}catch{throw new Error(n||"Could not parse env save response")}if(!e.ok)throw new Error(s.error||n||`HTTP ${e.status}`);return s}var he=async(t,e)=>{let n=await t.text(),s;try{s=n?JSON.parse(n):{}}catch{throw new Error(n||e)}if(!t.ok||s?.ok===!1)throw new Error(s.error||n||`HTTP ${t.status}`);return s};async function Qm(){let t=await X("/api/webhooks");return he(t,"Could not load webhooks")}async function eg(t){let e=await X(`/api/webhooks/${encodeURIComponent(t)}`);return he(e,"Could not load webhook detail")}async function tg(t,{destination:e=null,oauthCallback:n=!1}={}){let s=await X("/api/webhooks",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:t,...e?{destination:e}:{},oauthCallback:!!n})});return he(s,"Could not create webhook")}async function ng(t,{deleteTransformDir:e=!1}={}){let n=await X(`/api/webhooks/${encodeURIComponent(t)}`,{method:"DELETE",headers:{"Content-Type":"application/json"},body:JSON.stringify({deleteTransformDir:!!e})});return he(n,"Could not delete webhook")}async function sg(t,{destination:e=null}={}){let n=await X(`/api/webhooks/${encodeURIComponent(t)}/destination`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({destination:e})});return he(n,"Could not update webhook destination")}async function og(t){let e=await X(`/api/webhooks/${encodeURIComponent(t)}/oauth-callback/rotate`,{method:"POST"});return he(e,"Could not rotate OAuth callback")}async function rg(t,{limit:e=50,offset:n=0,status:s="all"}={}){let o=new URLSearchParams({limit:String(e),offset:String(n),status:String(s||"all")}),r=await X(`/api/webhooks/${encodeURIComponent(t)}/requests?${o.toString()}`);return he(r,"Could not load webhook requests")}async function ig(t,e){let n=await X(`/api/webhooks/${encodeURIComponent(t)}/requests/${encodeURIComponent(String(e))}`);return he(n,"Could not load webhook request")}var ag=async(t=10)=>{let e=new URLSearchParams({depth:String(t)}),n=await X(`/api/browse/tree?${e.toString()}`);return he(n,"Could not load file tree")},ud=async t=>{let e=new URLSearchParams({path:String(t||"")}),n=await X(`/api/browse/read?${e.toString()}`);return he(n,"Could not load file content")},lg=async(t,e)=>{let n=String(t||""),s=typeof e=="string"?e:String(e??""),o=await X("/api/browse/write",{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:n,content:s})});return he(o,"Could not save file")},cg=async t=>{let e=await X("/api/browse/create-file",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:String(t||"")})});return he(e,"Could not create file")},dg=async t=>{let e=await X("/api/browse/create-folder",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:String(t||"")})});return he(e,"Could not create folder")},ug=async(t,e)=>{let n=await X("/api/browse/move",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({from:String(t||""),to:String(e||"")})});return he(n,"Could not move path")},wa=async t=>{let e=await X("/api/browse/delete",{method:"DELETE",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:String(t||"")})});return he(e,"Could not delete file")},pg=async t=>{let e=new URLSearchParams({path:String(t||"")}),n=await X(`/api/browse/download?${e.toString()}`);if(!n.ok){let a=await n.text();throw new Error(a||"Could not download file")}let s=await n.blob(),o=window?.URL||URL;if(!o?.createObjectURL||!o?.revokeObjectURL)throw new Error("Download is not supported in this browser");let r=o.createObjectURL(s),i=String(t||"").split("/").filter(Boolean).pop()||"download";try{let a=document.createElement("a");a.href=r,a.download=i,document.body?.appendChild(a),a.click(),a.remove()}finally{o.revokeObjectURL(r)}return{ok:!0}},fg=async t=>{let e=await X("/api/browse/restore",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:String(t||"")})});return he(e,"Could not restore file")},pd=async()=>{let t=await X("/api/browse/git-summary");return he(t,"Could not load git summary")},hg=async t=>{let e=new URLSearchParams({path:String(t||"")}),n=await X(`/api/browse/git-diff?${e.toString()}`);return he(n,"Could not load file diff")},mg=async({filePath:t,table:e,limit:n=50,offset:s=0})=>{let o=new URLSearchParams({path:String(t||""),table:String(e||""),limit:String(n),offset:String(s)}),r=await X(`/api/browse/sqlite-table?${o.toString()}`);return he(r,"Could not load sqlite table data")},gg=async(t="")=>{let e=await X("/api/browse/git-sync",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:String(t||"")})});return he(e,"Could not sync changes")};var zs=t=>String(t||"").split("/")[0]||"",Ro=t=>{let e=String(t||"").trim();return e==="openai-codex"?"openai":e==="volcengine-plan"?"volcengine":e==="byteplus-plan"?"byteplus":e},Kk=[{label:"Opus 4.6",preferredKeys:["anthropic/claude-opus-4-6"]},{label:"Sonnet 4.6",preferredKeys:["anthropic/claude-sonnet-4-6"]},{label:"Codex 5.3",preferredKeys:["openai-codex/gpt-5.3-codex"]},{label:"GPT-5.4",preferredKeys:["openai-codex/gpt-5.4"]},{label:"Gemini 3.1 Pro",preferredKeys:["google/gemini-3.1-pro-preview"]}],Lo=t=>{let e=[],n=new Set;return Kk.forEach(s=>{let o=s.preferredKeys.map(r=>t.find(i=>i.key===r)).find(Boolean);!o||n.has(o.key)||(e.push({...o,featuredLabel:s.label}),n.add(o.key))}),e},An={anthropic:[{key:"ANTHROPIC_API_KEY",label:"Anthropic API Key",url:"https://console.anthropic.com",linkText:"Get key",placeholder:"sk-ant-..."},{key:"ANTHROPIC_TOKEN",label:"Anthropic Setup Token",hint:"From claude setup-token (uses your Claude subscription)",linkText:"Get token",placeholder:"Token..."}],openai:[{key:"OPENAI_API_KEY",label:"OpenAI API Key",url:"https://platform.openai.com",linkText:"Get key",placeholder:"sk-..."}],google:[{key:"GEMINI_API_KEY",label:"Gemini API Key",url:"https://aistudio.google.com",linkText:"Get key",placeholder:"AI..."}],opencode:[{key:"OPENCODE_API_KEY",label:"OpenCode API Key",placeholder:"oc-..."}],openrouter:[{key:"OPENROUTER_API_KEY",label:"OpenRouter API Key",url:"https://openrouter.ai",linkText:"Get key",placeholder:"sk-or-..."}],zai:[{key:"ZAI_API_KEY",label:"Z.AI API Key",placeholder:"zai-..."}],"vercel-ai-gateway":[{key:"AI_GATEWAY_API_KEY",label:"AI Gateway API Key",placeholder:"aigw_..."}],kilocode:[{key:"KILOCODE_API_KEY",label:"KiloCode API Key",placeholder:"kilo_..."}],xai:[{key:"XAI_API_KEY",label:"xAI API Key",placeholder:"xai-..."}],mistral:[{key:"MISTRAL_API_KEY",label:"Mistral API Key",url:"https://console.mistral.ai",linkText:"Get key",placeholder:"sk-..."}],voyage:[{key:"VOYAGE_API_KEY",label:"Voyage API Key",url:"https://dash.voyageai.com",linkText:"Get key",placeholder:"pa-..."}],groq:[{key:"GROQ_API_KEY",label:"Groq API Key",url:"https://console.groq.com",linkText:"Get key",placeholder:"gsk_..."}],cerebras:[{key:"CEREBRAS_API_KEY",label:"Cerebras API Key",placeholder:"csk-..."}],moonshot:[{key:"MOONSHOT_API_KEY",label:"Moonshot API Key",placeholder:"sk-..."}],"kimi-coding":[{key:"KIMI_API_KEY",label:"Kimi API Key",placeholder:"sk-..."}],volcengine:[{key:"VOLCANO_ENGINE_API_KEY",label:"Volcano Engine API Key",placeholder:"ve-..."}],byteplus:[{key:"BYTEPLUS_API_KEY",label:"BytePlus API Key",placeholder:"bp-..."}],synthetic:[{key:"SYNTHETIC_API_KEY",label:"Synthetic API Key",placeholder:"syn-..."}],minimax:[{key:"MINIMAX_API_KEY",label:"MiniMax API Key",placeholder:"minimax-..."}],deepgram:[{key:"DEEPGRAM_API_KEY",label:"Deepgram API Key",url:"https://console.deepgram.com",linkText:"Get key",placeholder:"dg-..."}],vllm:[{key:"VLLM_API_KEY",label:"vLLM API Key",placeholder:"vllm-local"}]},Us={anthropic:"Anthropic",openai:"OpenAI",google:"Gemini",opencode:"OpenCode Zen",openrouter:"OpenRouter",zai:"Z.AI","vercel-ai-gateway":"Vercel AI Gateway",kilocode:"Kilo Gateway",xai:"xAI",mistral:"Mistral",cerebras:"Cerebras",moonshot:"Moonshot","kimi-coding":"Kimi Coding",volcengine:"Volcano Engine",byteplus:"BytePlus",synthetic:"Synthetic",minimax:"MiniMax",voyage:"Voyage",groq:"Groq",deepgram:"Deepgram",vllm:"vLLM"},jr=["anthropic","openai","google","zai","xai","openrouter","opencode","kilocode","vercel-ai-gateway","minimax","moonshot","kimi-coding","volcengine","byteplus","synthetic","mistral","cerebras","voyage","groq","deepgram","vllm"];var bg=[{id:"embeddings",label:"Memory Embeddings",tag:"Embeddings",providers:["openai","google","voyage","mistral"]},{id:"audio",label:"Audio Transcription",tag:"Audio",hasDefault:!0,providers:["openai","groq","deepgram","google","mistral"]}],xg=t=>{if(t==="openai-codex")return new Set;let e=Ro(t),n=An[e]||[];return new Set(n.map(s=>s.key))},yg=Object.values(An).flat().filter((t,e,n)=>n.findIndex(s=>s.key===t.key)===e);var Eo=P.bind(T),fd="new",hd="existing",Mn="fresh",Bt="import",Tn="create",Jn="existing-empty",Gk=t=>String(t||"").trim().replace(/^git@github\.com:/,"").replace(/^https:\/\/github\.com\//,"").replace(/\.git$/,""),zr=t=>{let e=Gk(t);if(!e)return!1;let n=e.split("/").filter(Boolean);return n.length===2&&!n.some(s=>/\s/.test(s))},Ht=[{id:"github",title:"GitHub",description:"Auto-backup your config and workspace",fields:[{key:"_GITHUB_SOURCE_REPO",label:"Source Repo",placeholder:"username/existing-openclaw",isText:!0},{key:"GITHUB_WORKSPACE_REPO",label:"New Workspace Repo",placeholder:"username/my-agent",isText:!0},{key:"GITHUB_TOKEN",label:"Personal Access Token",hint:Eo`Create a${" "}fine-grained token ${" "}with Contents + Metadata access`,placeholder:"ghp_... or github_pat_..."}],validate:t=>{let e=t._GITHUB_FLOW||An,n=zr(t.GITHUB_WORKSPACE_REPO),s=e!==Bt||zr(t._GITHUB_SOURCE_REPO);return!!(t.GITHUB_TOKEN&&n&&s)}},{id:"ai",title:"Primary Agent Model",description:"Choose your main model and authenticate its provider",fields:xg,validate:(t,e={})=>!!(t.MODEL_KEY&&e.hasAi)},{id:"channels",title:"Channels",description:"At least one is required to talk to your agent",fields:[{key:"TELEGRAM_BOT_TOKEN",label:"Telegram Bot Token",hint:Eo`From${" "}${" "}with Contents + Metadata access`,placeholder:"ghp_... or github_pat_..."}],validate:t=>{let e=t._GITHUB_FLOW||Mn,n=zr(t.GITHUB_WORKSPACE_REPO),s=e!==Bt||zr(t._GITHUB_SOURCE_REPO);return!!(t.GITHUB_TOKEN&&n&&s)}},{id:"ai",title:"Primary Agent Model",description:"Choose your main model and authenticate its provider",fields:yg,validate:(t,e={})=>!!(t.MODEL_KEY&&e.hasAi)},{id:"channels",title:"Channels",description:"At least one is required to talk to your agent",fields:[{key:"TELEGRAM_BOT_TOKEN",label:"Telegram Bot Token",hint:Eo`From${" "} brave.com/search/api ${" "}-${" "}free tier available`,placeholder:"BSA..."}],validate:()=>!0}];var Uk=P.bind(T),yg=({onSelectFlow:t})=>Uk`
+ >${" "}-${" "}free tier available`,placeholder:"BSA..."}],validate:()=>!0}];var qk=P.bind(T),vg=({onSelectFlow:t})=>qk`
t(An)}
+ onclick=${()=>t(Mn)}
class="w-full flex items-center gap-4 text-left p-4 rounded-xl ac-path-card"
>
- `;var Kk=P.bind(T),Ce=({className:t="h-4 w-4",ariaHidden:e=!0,style:n=""})=>Kk`
+ `;var Jk=P.bind(T),Ce=({className:t="h-4 w-4",ariaHidden:e=!0,style:n=""})=>Jk`
-`;var Io=P.bind(T),vg={primary:"ac-btn-cyan",secondary:"ac-btn-secondary",success:"ac-btn-green",danger:"ac-btn-danger",ghost:"ac-btn-ghost"},Gk=(t,e)=>t==="subtle"||t==="neutral"?e?"border border-border text-fg-muted hover:text-body hover:border-fg-muted":"border border-border text-fg-muted":t==="warning"?e?"border border-yellow-500/35 text-status-warning-muted bg-yellow-500/10 hover:border-yellow-400/60 hover:text-status-warning hover:bg-yellow-500/15":"border border-yellow-500/35 text-status-warning-muted bg-yellow-500/10":vg[t]||vg.primary,$g={sm:"h-7 text-xs leading-none px-2.5 py-1 rounded-lg",md:"h-9 text-sm font-medium leading-none px-4 rounded-xl",lg:"h-10 text-sm font-medium leading-none px-5 rounded-lg"},wg={sm:"h-7 w-7 p-0 rounded-lg",md:"h-9 w-9 p-0 rounded-xl",lg:"h-10 w-10 p-0 rounded-lg"},Z=({onClick:t,type:e="button",disabled:n=!1,loading:s=!1,tone:o="primary",size:r="sm",idleLabel:i="Action",loadingLabel:a="Working...",loadingMode:l="replace",className:c="",idleIcon:d=null,idleIconClassName:u="h-3 w-3",iconOnly:p=!1,title:f="",ariaLabel:g=""})=>{let m=n||s,b=Gk(o,!m),x=p?wg[r]||wg.sm:$g[r]||$g.sm,v=s?`cursor-not-allowed ${o==="warning"?"opacity-90 animate-pulse shadow-[0_0_0_1px_rgba(234,179,8,0.22),0_0_18px_rgba(234,179,8,0.12)]":"opacity-80"}`:"",w=r==="md"||r==="lg"?"h-4 w-4":"h-3 w-3",$=l==="inline",S=d,C=p&&S?Io`<${S} className=${u} />`:S?Io`
+`;var Io=P.bind(T),$g={primary:"ac-btn-cyan",secondary:"ac-btn-secondary",success:"ac-btn-green",danger:"ac-btn-danger",ghost:"ac-btn-ghost"},Zk=(t,e)=>t==="subtle"||t==="neutral"?e?"border border-border text-fg-muted hover:text-body hover:border-fg-muted":"border border-border text-fg-muted":t==="warning"?e?"border border-yellow-500/35 text-status-warning-muted bg-yellow-500/10 hover:border-yellow-400/60 hover:text-status-warning hover:bg-yellow-500/15":"border border-yellow-500/35 text-status-warning-muted bg-yellow-500/10":$g[t]||$g.primary,wg={sm:"h-7 text-xs leading-none px-2.5 py-1 rounded-lg",md:"h-9 text-sm font-medium leading-none px-4 rounded-xl",lg:"h-10 text-sm font-medium leading-none px-5 rounded-lg"},kg={sm:"h-7 w-7 p-0 rounded-lg",md:"h-9 w-9 p-0 rounded-xl",lg:"h-10 w-10 p-0 rounded-lg"},Y=({onClick:t,type:e="button",disabled:n=!1,loading:s=!1,tone:o="primary",size:r="sm",idleLabel:i="Action",loadingLabel:a="Working...",loadingMode:l="replace",className:c="",idleIcon:d=null,idleIconClassName:u="h-3 w-3",iconOnly:p=!1,title:f="",ariaLabel:g=""})=>{let m=n||s,b=Zk(o,!m),x=p?kg[r]||kg.sm:wg[r]||wg.sm,v=s?`cursor-not-allowed ${o==="warning"?"opacity-90 animate-pulse shadow-[0_0_0_1px_rgba(234,179,8,0.22),0_0_18px_rgba(234,179,8,0.12)]":"opacity-80"}`:"",w=r==="md"||r==="lg"?"h-4 w-4":"h-3 w-3",$=l==="inline",S=d,C=p&&S?Io`<${S} className=${u} />`:S?Io`
<${S} className=${u} />
${i}
@@ -194,7 +194,7 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
`:_}
- `};var ka=(t=[])=>(Array.isArray(t)?t:[]).filter(e=>e?.confidence==="high").map(e=>({...e,suggestedEnvVar:e?.suggestedEnvVar||""})),kg=(t=[])=>(Array.isArray(t)?t:[]).reduce((e,n)=>{let s=String(n?.suggestedEnvVar||"").trim(),o=String(n?.value||"");return!s||!o||(e[s]=o),e},{});var qt=P.bind(T),qk=[{key:"gatewayConfig",label:"Gateway Config",icon:"\u2699\uFE0F",description:"openclaw.json configuration",showFiles:!0},{key:"envFiles",label:"Environment Files",icon:"\u{1F510}",description:".env files with variables",showFiles:!0},{key:"workspaceFiles",label:"Workspace Files",icon:"\u{1F4C4}",description:"Prompt files (AGENTS.md, SOUL.md, etc.)",showFiles:!0},{key:"skills",label:"Skills",icon:"\u{1F6E0}",description:"Custom skill definitions",showFiles:!0},{key:"cronJobs",label:"Cron Jobs",icon:"\u23F0",description:"Scheduled tasks",showFiles:!0},{key:"webhooks",label:"Hooks",icon:"\u{1F517}",description:"Webhook mappings and internal hooks",showDirs:!0},{key:"memory",label:"Memory",icon:"\u{1F9E0}",description:"Agent memory and embeddings",showDirs:!0}],Jk=({category:t,data:e})=>{let[n,s]=y(!1);if(!e?.found)return null;let o=t.key==="webhooks",r=Array.isArray(e.transformWarnings)?e.transformWarnings:[],i=new Set(r.map(d=>String(d.actualPath||"").trim()).filter(Boolean).map(d=>d.split("/").slice(0,-2).join("/"))),a=[...e.jobNames||[],...e.hookNames||[],...e.files||[],...(e.dirs||[]).filter(d=>!i.has(d)),...e.extraMarkdown||[]],l=typeof e.jobCount=="number"&&e.jobCount>0?e.jobCount:typeof e.hookCount=="number"&&e.hookCount>0?e.hookCount:a.length,c=typeof e.warningCount=="number"?e.warningCount:r.length;return qt`
+ `};var ka=(t=[])=>(Array.isArray(t)?t:[]).filter(e=>e?.confidence==="high").map(e=>({...e,suggestedEnvVar:e?.suggestedEnvVar||""})),Sg=(t=[])=>(Array.isArray(t)?t:[]).reduce((e,n)=>{let s=String(n?.suggestedEnvVar||"").trim(),o=String(n?.value||"");return!s||!o||(e[s]=o),e},{});var qt=P.bind(T),Yk=[{key:"gatewayConfig",label:"Gateway Config",icon:"\u2699\uFE0F",description:"openclaw.json configuration",showFiles:!0},{key:"envFiles",label:"Environment Files",icon:"\u{1F510}",description:".env files with variables",showFiles:!0},{key:"workspaceFiles",label:"Workspace Files",icon:"\u{1F4C4}",description:"Prompt files (AGENTS.md, SOUL.md, etc.)",showFiles:!0},{key:"skills",label:"Skills",icon:"\u{1F6E0}",description:"Custom skill definitions",showFiles:!0},{key:"cronJobs",label:"Cron Jobs",icon:"\u23F0",description:"Scheduled tasks",showFiles:!0},{key:"webhooks",label:"Hooks",icon:"\u{1F517}",description:"Webhook mappings and internal hooks",showDirs:!0},{key:"memory",label:"Memory",icon:"\u{1F9E0}",description:"Agent memory and embeddings",showDirs:!0}],Xk=({category:t,data:e})=>{let[n,s]=y(!1);if(!e?.found)return null;let o=t.key==="webhooks",r=Array.isArray(e.transformWarnings)?e.transformWarnings:[],i=new Set(r.map(d=>String(d.actualPath||"").trim()).filter(Boolean).map(d=>d.split("/").slice(0,-2).join("/"))),a=[...e.jobNames||[],...e.hookNames||[],...e.files||[],...(e.dirs||[]).filter(d=>!i.has(d)),...e.extraMarkdown||[]],l=typeof e.jobCount=="number"&&e.jobCount>0?e.jobCount:typeof e.hookCount=="number"&&e.hookCount>0?e.hookCount:a.length,c=typeof e.warningCount=="number"?e.warningCount:r.length;return qt`
`}
- `},Sg=({scanResult:t,scanning:e,error:n,onApprove:s,onShowSecretReview:o,onBack:r})=>{if(e)return qt`
+ `},Cg=({scanResult:t,scanning:e,error:n,onApprove:s,onShowSecretReview:o,onBack:r})=>{if(e)return qt`
<${Ce} />
Scanning repository...
@@ -270,8 +270,8 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
- ${qk.map(l=>qt`
- <${Jk}
+ ${Yk.map(l=>qt`
+ <${Xk}
key=${l.key}
category=${l}
data=${t[l.key]}
@@ -332,7 +332,7 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
Review and extract to environment variables
- <${Z}
+ <${Y}
onClick=${o}
tone="primary"
size="sm"
@@ -343,14 +343,14 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
`}
- <${Z}
+ <${Y}
onClick=${r}
tone="secondary"
size="md"
idleLabel="Back"
className="w-full"
/>
- <${Z}
+ <${Y}
onClick=${()=>s(ka(t.secrets))}
loading=${e}
tone="primary"
@@ -383,7 +383,7 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
${l?"Hide":"Show"}
`:null}
- `};var gd=P.bind(T),Zk=t=>{let e=String(t||"").trim();return!!e&&e!=="placeholder"},Yk=({item:t,value:e,onInput:n})=>gd`
+ `};var gd=P.bind(T),Qk=t=>{let e=String(t||"").trim();return!!e&&e!=="placeholder"},eS=({item:t,value:e,onInput:n})=>gd`
@@ -402,7 +402,7 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
inputClass="w-full bg-field border border-border rounded-lg px-3 py-2 text-xs text-body outline-none focus:border-fg-muted font-mono"
/>
- `,Cg=({placeholderReview:t,vals:e,setValue:n,onContinue:s})=>{let o=Array.isArray(t?.vars)?t.vars:[],i=F(()=>o.filter(a=>!Zk(e[a.key])).map(a=>a.key),[o,e]).length;return o.length===0?null:gd`
+ `,_g=({placeholderReview:t,vals:e,setValue:n,onContinue:s})=>{let o=Array.isArray(t?.vars)?t.vars:[],i=F(()=>o.filter(a=>!Qk(e[a.key])).map(a=>a.key),[o,e]).length;return o.length===0?null:gd`
Add Missing Env Vars
@@ -410,7 +410,7 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
${o.map(a=>gd`
- <${Yk}
+ <${eS}
key=${a.key}
item=${a}
value=${String(e[a.key]||"")==="placeholder"?"":e[a.key]||""}
@@ -426,7 +426,7 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
- <${Z}
+ <${Y}
onClick=${s}
tone="primary"
size="md"
@@ -435,7 +435,7 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
/>
- `};var Pn=P.bind(T),Xk=({secret:t,selected:e,onToggle:n,envVarName:s,onEnvVarChange:o})=>Pn`
+ `};var Pn=P.bind(T),tS=({secret:t,selected:e,onToggle:n,envVarName:s,onEnvVarChange:o})=>Pn`
@@ -485,7 +485,7 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
`}
- `,_g=({secrets:t=[],onApprove:e,onBack:n,loading:s,error:o})=>{let[r,i]=y(()=>{let u={};for(let p of t)u[p.configPath]={selected:p.confidence==="high",envVarName:p.suggestedEnvVar||""};return u}),a=q(u=>{i(p=>({...p,[u]:{...p[u],selected:!p[u]?.selected}}))},[]),l=q((u,p)=>{i(f=>({...f,[u]:{...f[u],envVarName:p}}))},[]),c=Object.values(r).filter(u=>u.selected).length,d=()=>{let u=ka(t.map(p=>({...p,confidence:r[p.configPath]?.selected?"high":"medium",suggestedEnvVar:r[p.configPath]?.envVarName||p.suggestedEnvVar})));e(u)};return s?Pn`
+ `,Ag=({secrets:t=[],onApprove:e,onBack:n,loading:s,error:o})=>{let[r,i]=y(()=>{let u={};for(let p of t)u[p.configPath]={selected:p.confidence==="high",envVarName:p.suggestedEnvVar||""};return u}),a=q(u=>{i(p=>({...p,[u]:{...p[u],selected:!p[u]?.selected}}))},[]),l=q((u,p)=>{i(f=>({...f,[u]:{...f[u],envVarName:p}}))},[]),c=Object.values(r).filter(u=>u.selected).length,d=()=>{let u=ka(t.map(p=>({...p,confidence:r[p.configPath]?.selected?"high":"medium",suggestedEnvVar:r[p.configPath]?.envVarName||p.suggestedEnvVar})));e(u)};return s?Pn`
<${Ce} />
Applying import...
@@ -510,7 +510,7 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
${t.map(u=>Pn`
- <${Xk}
+ <${tS}
key=${u.configPath}
secret=${u}
selected=${r[u.configPath]?.selected||!1}
@@ -522,14 +522,14 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
- <${Z}
+ <${Y}
onClick=${n}
tone="secondary"
size="md"
idleLabel="Back"
className="w-full"
/>
- <${Z}
+ <${Y}
onClick=${d}
tone="primary"
size="md"
@@ -538,7 +538,7 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
/>
- `};var Mg=P.bind(T),Ag=({groups:t,step:e,isPreStep:n,isSetupStep:s,isPairingStep:o,stepNumber:r,activeStepLabel:i})=>{let a=[...t,{id:"setup",title:"Initializing"},{id:"pairing",title:"Pairing"}];return Mg`
+ `};var Mg=P.bind(T),Tg=({groups:t,step:e,isPreStep:n,isSetupStep:s,isPairingStep:o,stepNumber:r,activeStepLabel:i})=>{let a=[...t,{id:"setup",title:"Initializing"},{id:"pairing",title:"Pairing"}];return Mg`
`})}
- `};var Tg=P.bind(T),Pg=[{label:"\u{1F6E1}\uFE0F Safety tip",text:"Be careful what you give access to. Read access is always safer than write access."},{label:"\u{1F9E0} Best practice",text:"Trust but verify. Your agent may not always know what it's doing, so check the results."},{label:"\u{1F4A1} Idea",text:"Ask your agent to create a morning briefing for you."},{label:"\u{1F9E0} Best practice",text:"Ask your agent to review its own code and make sure it's doing what you want it to do."},{label:"\u{1F4A1} Idea",text:"Tell your agent to review the latest news and provide a summary."},{label:"\u{1F6E1}\uFE0F Safety tip",text:"Be incredibly careful installing skills from the internet - they may contain malicious code."}],Rg=({error:t,loading:e,onRetry:n,onBack:s})=>{let[o,r]=y(0);if(L(()=>{if(t||!e)return;let a=setInterval(()=>{r(l=>(l+1)%Pg.length)},5200);return()=>clearInterval(a)},[t,e]),t)return Tg`
+ `};var Pg=P.bind(T),Rg=[{label:"\u{1F6E1}\uFE0F Safety tip",text:"Be careful what you give access to. Read access is always safer than write access."},{label:"\u{1F9E0} Best practice",text:"Trust but verify. Your agent may not always know what it's doing, so check the results."},{label:"\u{1F4A1} Idea",text:"Ask your agent to create a morning briefing for you."},{label:"\u{1F9E0} Best practice",text:"Ask your agent to review its own code and make sure it's doing what you want it to do."},{label:"\u{1F4A1} Idea",text:"Tell your agent to review the latest news and provide a summary."},{label:"\u{1F6E1}\uFE0F Safety tip",text:"Be incredibly careful installing skills from the internet - they may contain malicious code."}],Lg=({error:t,loading:e,onRetry:n,onBack:s})=>{let[o,r]=y(0);if(L(()=>{if(t||!e)return;let a=setInterval(()=>{r(l=>(l+1)%Rg.length)},5200);return()=>clearInterval(a)},[t,e]),t)return Pg`
Setup failed
Fix the values and try again.
@@ -596,7 +596,7 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
${e?"Retrying...":"Retry"}
- `;let i=Pg[o];return Tg`
+ `;let i=Rg[o];return Pg`
- `};var Qk=P.bind(T),Lg={success:"bg-green-500/10 text-status-success-muted",warning:"bg-yellow-500/10 text-status-warning-muted",danger:"bg-red-500/10 text-status-error-muted",neutral:"bg-gray-500/10 text-fg-muted",info:"bg-blue-500/10 text-blue-400",accent:"bg-purple-500/10 text-purple-400",cyan:"bg-cyan-500/10 text-cyan-400",secondary:"bg-indigo-500/10 text-indigo-300"},ae=({tone:t="neutral",children:e})=>Qk`
-
+ `};var nS=P.bind(T),Eg={success:"bg-green-500/10 text-status-success-muted",warning:"bg-yellow-500/10 text-status-warning-muted",danger:"bg-red-500/10 text-status-error-muted",neutral:"bg-gray-500/10 text-fg-muted",info:"bg-blue-500/10 text-blue-400",accent:"bg-purple-500/10 text-purple-400",cyan:"bg-cyan-500/10 text-cyan-400",secondary:"bg-indigo-500/10 text-indigo-300"},le=({tone:t="neutral",children:e})=>nS`
+
${e}
-`;function tS(t,e){for(var n in e)t[n]=e[n];return t}function Eg(t,e){for(var n in t)if(n!=="__source"&&!(n in e))return!0;for(var s in e)if(s!=="__source"&&t[s]!==e[s])return!0;return!1}function Ig(t,e){this.props=t,this.context=e}(Ig.prototype=new hn).isPureReactComponent=!0,Ig.prototype.shouldComponentUpdate=function(t,e){return Eg(this.props,t)||Eg(this.state,e)};var Dg=Se.__b;Se.__b=function(t){t.type&&t.type.__f&&t.ref&&(t.props.ref=t.ref,t.ref=null),Dg&&Dg(t)};var xL=typeof Symbol<"u"&&Symbol.for&&Symbol.for("react.forward_ref")||3911;var nS=Se.__e;Se.__e=function(t,e,n,s){if(t.then){for(var o,r=e;r=r.__;)if((o=r.__c)&&o.__c)return e.__e==null&&(e.__e=n.__e,e.__k=n.__k),o.__c(t,e)}nS(t,e,n,s)};var Ng=Se.unmount;function Vg(t,e,n){return t&&(t.__c&&t.__c.__H&&(t.__c.__H.__.forEach(function(s){typeof s.__c=="function"&&s.__c()}),t.__c.__H=null),(t=tS({},t)).__c!=null&&(t.__c.__P===n&&(t.__c.__P=e),t.__c.__e=!0,t.__c=null),t.__k=t.__k&&t.__k.map(function(s){return Vg(s,e,n)})),t}function jg(t,e,n){return t&&n&&(t.__v=null,t.__k=t.__k&&t.__k.map(function(s){return jg(s,e,n)}),t.__c&&t.__c.__P===e&&(t.__e&&n.appendChild(t.__e),t.__c.__e=!0,t.__c.__P=n)),t}function bd(){this.__u=0,this.o=null,this.__b=null}function zg(t){var e=t.__&&t.__.__c;return e&&e.__a&&e.__a(t)}function Sa(){this.i=null,this.l=null}Se.unmount=function(t){var e=t.__c;e&&(e.__z=!0),e&&e.__R&&e.__R(),e&&32&t.__u&&(t.type=null),Ng&&Ng(t)},(bd.prototype=new hn).__c=function(t,e){var n=e.__c,s=this;s.o==null&&(s.o=[]),s.o.push(n);var o=zg(s.__v),r=!1,i=function(){r||s.__z||(r=!0,n.__R=null,o?o(l):l())};n.__R=i;var a=n.__P;n.__P=null;var l=function(){if(!--s.__u){if(s.state.__a){var c=s.state.__a;s.__v.__k[0]=jg(c,c.__c.__P,c.__c.__O)}var d;for(s.setState({__a:s.__b=null});d=s.o.pop();)d.__P=a,d.forceUpdate()}};s.__u++||32&e.__u||s.setState({__a:s.__b=s.__v.__k[0]}),t.then(i,i)},bd.prototype.componentWillUnmount=function(){this.o=[]},bd.prototype.render=function(t,e){if(this.__b){if(this.__v.__k){var n=document.createElement("div"),s=this.__v.__k[0].__c;this.__v.__k[0]=Vg(this.__b,n,s.__O=s.__P)}this.__b=null}var o=e.__a&&T(ln,null,t.fallback);return o&&(o.__u&=-33),[T(ln,null,e.__a?null:t.children),o]};var Og=function(t,e,n){if(++n[1]===n[0]&&t.l.delete(e),t.props.revealOrder&&(t.props.revealOrder[0]!=="t"||!t.l.size))for(n=t.i;n;){for(;n.length>3;)n.pop()();if(n[1]>>1,1),e.h.removeChild(o)}}}wo(T(sS,{context:e.context},t.__v),e.v)}function Do(t,e){var n=T(oS,{__v:t,h:e});return n.containerInfo=e,n}(Sa.prototype=new hn).__a=function(t){var e=this,n=zg(e.__v),s=e.l.get(t);return s[0]++,function(o){var r=function(){e.props.revealOrder?(s.push(o),Og(e,t,s)):o()};n?n(r):r()}},Sa.prototype.render=function(t){this.i=null,this.l=new Map;var e=Lr(t.children);t.revealOrder&&t.revealOrder[0]==="b"&&e.reverse();for(var n=e.length;n--;)this.l.set(e[n],this.i=[1,0,this.i]);return t.children},Sa.prototype.componentDidUpdate=Sa.prototype.componentDidMount=function(){var t=this;this.l.forEach(function(e,n){Og(t,n,e)})};var rS=typeof Symbol<"u"&&Symbol.for&&Symbol.for("react.element")||60103,iS=/^(?:accent|alignment|arabic|baseline|cap|clip(?!PathU)|color|dominant|fill|flood|font|glyph(?!R)|horiz|image(!S)|letter|lighting|marker(?!H|W|U)|overline|paint|pointer|shape|stop|strikethrough|stroke|text(?!L)|transform|underline|unicode|units|v|vector|vert|word|writing|x(?!C))[A-Z]/,aS=/^on(Ani|Tra|Tou|BeforeInp|Compo)/,lS=/[A-Z0-9]/g,cS=typeof document<"u",dS=function(t){return(typeof Symbol<"u"&&typeof Symbol()=="symbol"?/fil|che|rad/:/fil|che|ra/).test(t)};hn.prototype.isReactComponent=!0,["componentWillMount","componentWillReceiveProps","componentWillUpdate"].forEach(function(t){Object.defineProperty(hn.prototype,t,{configurable:!0,get:function(){return this["UNSAFE_"+t]},set:function(e){Object.defineProperty(this,t,{configurable:!0,writable:!0,value:e})}})});var Bg=Se.event;Se.event=function(t){return Bg&&(t=Bg(t)),t.persist=function(){},t.isPropagationStopped=function(){return this.cancelBubble},t.isDefaultPrevented=function(){return this.defaultPrevented},t.nativeEvent=t};var Ug,uS={configurable:!0,get:function(){return this.class}},Fg=Se.vnode;Se.vnode=function(t){typeof t.type=="string"&&(function(e){var n=e.props,s=e.type,o={},r=s.indexOf("-")==-1;for(var i in n){var a=n[i];if(!(i==="value"&&"defaultValue"in n&&a==null||cS&&i==="children"&&s==="noscript"||i==="class"||i==="className")){var l=i.toLowerCase();i==="defaultValue"&&"value"in n&&n.value==null?i="value":i==="download"&&a===!0?a="":l==="translate"&&a==="no"?a=!1:l[0]==="o"&&l[1]==="n"?l==="ondoubleclick"?i="ondblclick":l!=="onchange"||s!=="input"&&s!=="textarea"||dS(n.type)?l==="onfocus"?i="onfocusin":l==="onblur"?i="onfocusout":aS.test(i)&&(i=l):l=i="oninput":r&&iS.test(i)?i=i.replace(lS,"-$&").toLowerCase():a===null&&(a=void 0),l==="oninput"&&o[i=l]&&(i="oninputCapture"),o[i]=a}}s=="select"&&(o.multiple&&Array.isArray(o.value)&&(o.value=Lr(n.children).forEach(function(c){c.props.selected=o.value.indexOf(c.props.value)!=-1})),o.defaultValue!=null&&(o.value=Lr(n.children).forEach(function(c){c.props.selected=o.multiple?o.defaultValue.indexOf(c.props.value)!=-1:o.defaultValue==c.props.value}))),n.class&&!n.className?(o.class=n.class,Object.defineProperty(o,"className",uS)):n.className&&(o.class=o.className=n.className),e.props=o})(t),t.$$typeof=rS,Fg&&Fg(t)};var Hg=Se.__r;Se.__r=function(t){Hg&&Hg(t),Ug=t.__c};var Wg=Se.diffed;Se.diffed=function(t){Wg&&Wg(t);var e=t.props,n=t.__e;n!=null&&t.type==="textarea"&&"value"in e&&e.value!==n.value&&(n.value=e.value==null?"":e.value),Ug=null};var Kg=P.bind(T),Ur=8,xd=8,pS=400,Gg=0,qg=t=>{if(!t||typeof document>"u")return!1;let e=document.activeElement;return!e||!t.contains(e)?!1:typeof e.matches=="function"&&e.matches(":focus-visible")},fS=(t,e)=>{if(!t)return null;let n=t.getBoundingClientRect(),s=e?.getBoundingClientRect?.()||{width:0,height:0},o=Ur+s.width/2,r=window.innerWidth-Ur-s.width/2,i=n.left+n.width/2,a=s.width?Math.min(Math.max(i,o),r):i,l=n.bottom+xd,c=n.top-xd-s.height>=Ur;return l+s.height+Ur>window.innerHeight&&c&&(l=n.top-xd-s.height),{left:`${a}px`,top:`${Math.max(Ur,l)}px`}},yt=({text:t="",widthClass:e="w-64",tooltipClassName:n="",triggerClassName:s="",children:o=null,disabled:r=!1,delay:i=0})=>{let a=ee(null),l=ee(null),c=ee(null),d=ee(!1),[u,p]=y(!1),[f,g]=y(null);L(()=>{if(!u||r||!t)return;let b=()=>{let x=fS(a.current,l.current);x&&g(x)};return b(),window.addEventListener("resize",b),window.addEventListener("scroll",b,!0),()=>{window.removeEventListener("resize",b),window.removeEventListener("scroll",b,!0)}},[u,r,t]);let m=()=>{if(r||!t)return;let b=Date.now()-Gga.current?.matches?.(":hover")||qg(a.current);if(i>0&&!b)clearTimeout(c.current),c.current=setTimeout(()=>{x()&&p(!0)},i);else{if(!x())return;p(!0)}},h=()=>{clearTimeout(c.current),u&&(Gg=Date.now()),p(!1)};return Kg`
+`;function oS(t,e){for(var n in e)t[n]=e[n];return t}function Ig(t,e){for(var n in t)if(n!=="__source"&&!(n in e))return!0;for(var s in e)if(s!=="__source"&&t[s]!==e[s])return!0;return!1}function Dg(t,e){this.props=t,this.context=e}(Dg.prototype=new hn).isPureReactComponent=!0,Dg.prototype.shouldComponentUpdate=function(t,e){return Ig(this.props,t)||Ig(this.state,e)};var Ng=Se.__b;Se.__b=function(t){t.type&&t.type.__f&&t.ref&&(t.props.ref=t.ref,t.ref=null),Ng&&Ng(t)};var kL=typeof Symbol<"u"&&Symbol.for&&Symbol.for("react.forward_ref")||3911;var rS=Se.__e;Se.__e=function(t,e,n,s){if(t.then){for(var o,r=e;r=r.__;)if((o=r.__c)&&o.__c)return e.__e==null&&(e.__e=n.__e,e.__k=n.__k),o.__c(t,e)}rS(t,e,n,s)};var Og=Se.unmount;function jg(t,e,n){return t&&(t.__c&&t.__c.__H&&(t.__c.__H.__.forEach(function(s){typeof s.__c=="function"&&s.__c()}),t.__c.__H=null),(t=oS({},t)).__c!=null&&(t.__c.__P===n&&(t.__c.__P=e),t.__c.__e=!0,t.__c=null),t.__k=t.__k&&t.__k.map(function(s){return jg(s,e,n)})),t}function zg(t,e,n){return t&&n&&(t.__v=null,t.__k=t.__k&&t.__k.map(function(s){return zg(s,e,n)}),t.__c&&t.__c.__P===e&&(t.__e&&n.appendChild(t.__e),t.__c.__e=!0,t.__c.__P=n)),t}function bd(){this.__u=0,this.o=null,this.__b=null}function Ug(t){var e=t.__&&t.__.__c;return e&&e.__a&&e.__a(t)}function Sa(){this.i=null,this.l=null}Se.unmount=function(t){var e=t.__c;e&&(e.__z=!0),e&&e.__R&&e.__R(),e&&32&t.__u&&(t.type=null),Og&&Og(t)},(bd.prototype=new hn).__c=function(t,e){var n=e.__c,s=this;s.o==null&&(s.o=[]),s.o.push(n);var o=Ug(s.__v),r=!1,i=function(){r||s.__z||(r=!0,n.__R=null,o?o(l):l())};n.__R=i;var a=n.__P;n.__P=null;var l=function(){if(!--s.__u){if(s.state.__a){var c=s.state.__a;s.__v.__k[0]=zg(c,c.__c.__P,c.__c.__O)}var d;for(s.setState({__a:s.__b=null});d=s.o.pop();)d.__P=a,d.forceUpdate()}};s.__u++||32&e.__u||s.setState({__a:s.__b=s.__v.__k[0]}),t.then(i,i)},bd.prototype.componentWillUnmount=function(){this.o=[]},bd.prototype.render=function(t,e){if(this.__b){if(this.__v.__k){var n=document.createElement("div"),s=this.__v.__k[0].__c;this.__v.__k[0]=jg(this.__b,n,s.__O=s.__P)}this.__b=null}var o=e.__a&&T(ln,null,t.fallback);return o&&(o.__u&=-33),[T(ln,null,e.__a?null:t.children),o]};var Bg=function(t,e,n){if(++n[1]===n[0]&&t.l.delete(e),t.props.revealOrder&&(t.props.revealOrder[0]!=="t"||!t.l.size))for(n=t.i;n;){for(;n.length>3;)n.pop()();if(n[1]>>1,1),e.h.removeChild(o)}}}wo(T(iS,{context:e.context},t.__v),e.v)}function Do(t,e){var n=T(aS,{__v:t,h:e});return n.containerInfo=e,n}(Sa.prototype=new hn).__a=function(t){var e=this,n=Ug(e.__v),s=e.l.get(t);return s[0]++,function(o){var r=function(){e.props.revealOrder?(s.push(o),Bg(e,t,s)):o()};n?n(r):r()}},Sa.prototype.render=function(t){this.i=null,this.l=new Map;var e=Lr(t.children);t.revealOrder&&t.revealOrder[0]==="b"&&e.reverse();for(var n=e.length;n--;)this.l.set(e[n],this.i=[1,0,this.i]);return t.children},Sa.prototype.componentDidUpdate=Sa.prototype.componentDidMount=function(){var t=this;this.l.forEach(function(e,n){Bg(t,n,e)})};var lS=typeof Symbol<"u"&&Symbol.for&&Symbol.for("react.element")||60103,cS=/^(?:accent|alignment|arabic|baseline|cap|clip(?!PathU)|color|dominant|fill|flood|font|glyph(?!R)|horiz|image(!S)|letter|lighting|marker(?!H|W|U)|overline|paint|pointer|shape|stop|strikethrough|stroke|text(?!L)|transform|underline|unicode|units|v|vector|vert|word|writing|x(?!C))[A-Z]/,dS=/^on(Ani|Tra|Tou|BeforeInp|Compo)/,uS=/[A-Z0-9]/g,pS=typeof document<"u",fS=function(t){return(typeof Symbol<"u"&&typeof Symbol()=="symbol"?/fil|che|rad/:/fil|che|ra/).test(t)};hn.prototype.isReactComponent=!0,["componentWillMount","componentWillReceiveProps","componentWillUpdate"].forEach(function(t){Object.defineProperty(hn.prototype,t,{configurable:!0,get:function(){return this["UNSAFE_"+t]},set:function(e){Object.defineProperty(this,t,{configurable:!0,writable:!0,value:e})}})});var Fg=Se.event;Se.event=function(t){return Fg&&(t=Fg(t)),t.persist=function(){},t.isPropagationStopped=function(){return this.cancelBubble},t.isDefaultPrevented=function(){return this.defaultPrevented},t.nativeEvent=t};var Kg,hS={configurable:!0,get:function(){return this.class}},Hg=Se.vnode;Se.vnode=function(t){typeof t.type=="string"&&(function(e){var n=e.props,s=e.type,o={},r=s.indexOf("-")==-1;for(var i in n){var a=n[i];if(!(i==="value"&&"defaultValue"in n&&a==null||pS&&i==="children"&&s==="noscript"||i==="class"||i==="className")){var l=i.toLowerCase();i==="defaultValue"&&"value"in n&&n.value==null?i="value":i==="download"&&a===!0?a="":l==="translate"&&a==="no"?a=!1:l[0]==="o"&&l[1]==="n"?l==="ondoubleclick"?i="ondblclick":l!=="onchange"||s!=="input"&&s!=="textarea"||fS(n.type)?l==="onfocus"?i="onfocusin":l==="onblur"?i="onfocusout":dS.test(i)&&(i=l):l=i="oninput":r&&cS.test(i)?i=i.replace(uS,"-$&").toLowerCase():a===null&&(a=void 0),l==="oninput"&&o[i=l]&&(i="oninputCapture"),o[i]=a}}s=="select"&&(o.multiple&&Array.isArray(o.value)&&(o.value=Lr(n.children).forEach(function(c){c.props.selected=o.value.indexOf(c.props.value)!=-1})),o.defaultValue!=null&&(o.value=Lr(n.children).forEach(function(c){c.props.selected=o.multiple?o.defaultValue.indexOf(c.props.value)!=-1:o.defaultValue==c.props.value}))),n.class&&!n.className?(o.class=n.class,Object.defineProperty(o,"className",hS)):n.className&&(o.class=o.className=n.className),e.props=o})(t),t.$$typeof=lS,Hg&&Hg(t)};var Wg=Se.__r;Se.__r=function(t){Wg&&Wg(t),Kg=t.__c};var Vg=Se.diffed;Se.diffed=function(t){Vg&&Vg(t);var e=t.props,n=t.__e;n!=null&&t.type==="textarea"&&"value"in e&&e.value!==n.value&&(n.value=e.value==null?"":e.value),Kg=null};var Gg=P.bind(T),Ur=8,xd=8,mS=400,qg=0,Jg=t=>{if(!t||typeof document>"u")return!1;let e=document.activeElement;return!e||!t.contains(e)?!1:typeof e.matches=="function"&&e.matches(":focus-visible")},gS=(t,e)=>{if(!t)return null;let n=t.getBoundingClientRect(),s=e?.getBoundingClientRect?.()||{width:0,height:0},o=Ur+s.width/2,r=window.innerWidth-Ur-s.width/2,i=n.left+n.width/2,a=s.width?Math.min(Math.max(i,o),r):i,l=n.bottom+xd,c=n.top-xd-s.height>=Ur;return l+s.height+Ur>window.innerHeight&&c&&(l=n.top-xd-s.height),{left:`${a}px`,top:`${Math.max(Ur,l)}px`}},yt=({text:t="",widthClass:e="w-64",tooltipClassName:n="",triggerClassName:s="",children:o=null,disabled:r=!1,delay:i=0})=>{let a=ee(null),l=ee(null),c=ee(null),d=ee(!1),[u,p]=y(!1),[f,g]=y(null);L(()=>{if(!u||r||!t)return;let b=()=>{let x=gS(a.current,l.current);x&&g(x)};return b(),window.addEventListener("resize",b),window.addEventListener("scroll",b,!0),()=>{window.removeEventListener("resize",b),window.removeEventListener("scroll",b,!0)}},[u,r,t]);let m=()=>{if(r||!t)return;let b=Date.now()-qga.current?.matches?.(":hover")||Jg(a.current);if(i>0&&!b)clearTimeout(c.current),c.current=setTimeout(()=>{x()&&p(!0)},i);else{if(!x())return;p(!0)}},h=()=>{clearTimeout(c.current),u&&(qg=Date.now()),p(!1)};return Gg`
{d.current=!1}}
onMouseEnter=${m}
onMouseLeave=${h}
- onFocusIn=${()=>{d.current||qg(a.current)&&m()}}
+ onFocusIn=${()=>{d.current||Jg(a.current)&&m()}}
onFocusOut=${b=>{d.current=!1,!b.currentTarget.contains(b.relatedTarget)&&h()}}
>
${o}
- ${u&&!r&&t&&typeof document<"u"?Do(Kg`
+ ${u&&!r&&t&&typeof document<"u"?Do(Gg`
`,document.body):null}
- `};var yd=P.bind(T),Xe=({options:t=[],value:e,onChange:n=()=>{},className:s="",size:o="sm",fullWidth:r=!1})=>yd`
+ `};var yd=P.bind(T),Qe=({options:t=[],value:e,onChange:n=()=>{},className:s="",size:o="sm",fullWidth:r=!1})=>yd`
@@ -655,7 +655,7 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
`;return i.title?yd`<${yt} text=${i.title} delay=${1e3} widthClass="w-auto max-w-64 whitespace-normal">${a}${yt}>`:a})}
-`;var Me=P.bind(T),Ca=({className:t=""})=>Me`
+`;var Ae=P.bind(T),Ca=({className:t=""})=>Ae`
-`,nt=({className:t=""})=>Me`
+`,Ze=({className:t=""})=>Ae`
-`,No=({className:t=""})=>Me`
+`,No=({className:t=""})=>Ae`
-`;var Jg=({className:t=""})=>Me`
+`;var Zg=({className:t=""})=>Ae`
-`,Zg=({className:t=""})=>Me`
+`,Yg=({className:t=""})=>Ae`
-`,Yg=({className:t=""})=>Me`
+`,Xg=({className:t=""})=>Ae`
-`,Xg=({className:t=""})=>Me`
+`,Qg=({className:t=""})=>Ae`
-`,Qg=({className:t=""})=>Me`
+`,eb=({className:t=""})=>Ae`
-`,eb=({className:t=""})=>Me`
+`,tb=({className:t=""})=>Ae`
-`,tb=({className:t=""})=>Me`
+`,nb=({className:t=""})=>Ae`
-`,nb=({className:t=""})=>Me`
+`,sb=({className:t=""})=>Ae`
-`,_a=({className:t=""})=>Me`
+`,_a=({className:t=""})=>Ae`
-`,sb=({className:t=""})=>Me`
+`,ob=({className:t=""})=>Ae`
-`,ob=({className:t=""})=>Me`
+`,rb=({className:t=""})=>Ae`
-`,rb=({className:t=""})=>Me`
+`,ib=({className:t=""})=>Ae`
-`,ib=({className:t=""})=>Me`
+`,ab=({className:t=""})=>Ae`
-`,Ma=({className:t=""})=>Me`
+`,Aa=({className:t=""})=>Ae`
-`,ab=({className:t=""})=>Me`
+`,lb=({className:t=""})=>Ae`
-`,lb=({className:t=""})=>Me`
+`,cb=({className:t=""})=>Ae`
-`,cb=({className:t=""})=>Me`
+`,db=({className:t=""})=>Ae`
-`,db=({className:t=""})=>Me`
+`,ub=({className:t=""})=>Ae`
-`,ub=({className:t=""})=>Me`
+`,pb=({className:t=""})=>Ae`
-`,pb=({className:t=""})=>Me`
+`,fb=({className:t=""})=>Ae`
-`,vd=({className:t=""})=>Me`
+`,vd=({className:t=""})=>Ae`
-`,fb=({className:t=""})=>Me`
+`,hb=({className:t=""})=>Ae`
-`,Oo=({className:t=""})=>Me`
+`,Oo=({className:t=""})=>Ae`
-`,Aa=({className:t=""})=>Me`
+`,Ma=({className:t=""})=>Ae`
-`,Kr=({className:t=""})=>Me`
+`,Kr=({className:t=""})=>Ae`
-`,Gr=({className:t=""})=>Me`
+`,Gr=({className:t=""})=>Ae`
-`,hb=({className:t=""})=>Me`
+`,mb=({className:t=""})=>Ae`
-`,Us=({className:t=""})=>Me`
+`,Ks=({className:t=""})=>Ae`
-`,mb=({className:t=""})=>Me`
+`,gb=({className:t=""})=>Ae`
-`,gb=({className:t=""})=>Me`
+`,bb=({className:t=""})=>Ae`
-`,Ta=({className:t=""})=>Me`
+`,Ta=({className:t=""})=>Ae`
-`;var bb=({className:t=""})=>Me`
+`;var xb=({className:t=""})=>Ae`
-`,xb=({className:t=""})=>Me`
+`,yb=({className:t=""})=>Ae`
-`;var Pa=({className:t=""})=>Me`
+`;var Pa=({className:t=""})=>Ae`
-`;var Bo=P.bind(T),hS=({className:t=""})=>Bo`
+`;var Bo=P.bind(T),bS=({className:t=""})=>Bo`
@@ -1078,7 +1078,7 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
disabled=${a}
onclick=${u=>{u.stopPropagation(),e(u)}}
>
- <${hS} />
+ <${bS} />
`}
${t?Bo`
@@ -1087,7 +1087,7 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
`:null}
-`},We=({children:t=null,onClick:e=()=>{},className:n="",iconSrc:s="",disabled:o=!1})=>Bo`
+`},Oe=({children:t=null,onClick:e=()=>{},className:n="",iconSrc:s="",disabled:o=!1})=>Bo`
$d`
- <${Z}
+ <${Y}
onClick=${l}
disabled=${s}
loading=${!1}
@@ -1132,28 +1132,92 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
`}
>
${o.map(l=>{let c=r(l),d=!!i(l);return $d`
- <${We}
+ <${Oe}
key=${l}
iconSrc=${c.iconSrc}
disabled=${d}
onClick=${()=>a(l)}
>
${c.label}
- ${We}>
+ ${Oe}>
`})}
${pt}>
-`;var wd=P.bind(T),Ks=({status:t="configured",ownerAgentName:e="",showAgentBadge:n=!1,channelId:s="",pairedCount:o=0})=>String(t||"").trim()!=="paired"?wd`<${ae} tone="warning">Awaiting pairing${ae}>`:n&&e?wd`
- <${ae} tone="neutral">
+`;var wd=P.bind(T),Gs=({status:t="configured",ownerAgentName:e="",showAgentBadge:n=!1,channelId:s="",pairedCount:o=0})=>String(t||"").trim()!=="paired"?wd`<${le} tone="warning">Awaiting pairing${le}>`:n&&e?wd`
+ <${le} tone="neutral">
${e}
- ${ae}>
+ ${le}>
`:wd`
- <${ae} tone="success">
+ <${le} tone="success">
${s==="telegram"||Number(o)<=1?"Paired":`Paired (${Number(o)})`}
- ${ae}>
- `;var mS=P.bind(T),st=({visible:t=!1,title:e="Confirm action",message:n="Are you sure you want to continue?",details:s=null,confirmLabel:o="Confirm",confirmLoadingLabel:r="Working...",cancelLabel:i="Cancel",onConfirm:a,onCancel:l,confirmTone:c="primary",confirmLoading:d=!1,confirmDisabled:u=!1})=>(L(()=>{if(!t)return;let f=g=>{g.key==="Escape"&&l?.()};return window.addEventListener("keydown",f),()=>window.removeEventListener("keydown",f)},[t,l]),t?mS`
+ ${le}>
+ `;import{h as yS}from"https://esm.sh/preact";import vS from"https://esm.sh/htm";var xS=P.bind(T),Te=({visible:t=!1,onClose:e=()=>{},closeOnOverlayClick:n=!0,closeOnEscape:s=!0,panelClassName:o="bg-modal border border-border rounded-xl p-5 max-w-md w-full space-y-3",children:r=null})=>(L(()=>{if(!t||!s)return;let i=a=>{a.key==="Escape"&&e?.()};return window.addEventListener("keydown",i),()=>window.removeEventListener("keydown",i)},[t,s,e]),t?Do(xS`
+ {n&&i.target===i.currentTarget&&e?.()}}
+ >
+
${r}
+
+ `,document.body):null);var vb=P.bind(T),Pe=({title:t="",actions:e=null,leading:n=null})=>vb`
+
+
+ ${n||vb`
${t} `}
+
+
${e}
+
+`;var $b=vS.bind(yS),wb=({visible:t=!1,loading:e=!1,title:n="Link Channel",output:s="",error:o="",onRun:r=async()=>{},onClose:i=()=>{}})=>{if(!t)return null;let a=!!String(s||"").trim(),l=!!String(o||"").trim(),c=a?String(s):l?String(o):"No output yet. Generate QR to start login.";return $b`
+ <${Te}
+ visible=${t}
+ onClose=${i}
+ panelClassName="bg-modal border border-border rounded-xl p-6 max-w-2xl w-full space-y-4"
+ >
+ <${Pe}
+ title=${n}
+ actions=${$b`
+
+ <${Ze} className="w-3.5 h-3.5 text-gray-300" />
+
+ `}
+ />
+
+
+ Click "Generate QR" to run channel login and capture terminal output.
+
+
+
+
+ <${Y}
+ onClick=${i}
+ disabled=${e}
+ loading=${!1}
+ tone="secondary"
+ size="sm"
+ idleLabel="Close"
+ />
+ <${Y}
+ onClick=${r}
+ disabled=${e}
+ loading=${e}
+ tone="primary"
+ size="sm"
+ idleLabel="Generate QR"
+ loadingLabel="Running..."
+ />
+
+ ${Te}>
+ `};var $S=P.bind(T),st=({visible:t=!1,title:e="Confirm action",message:n="Are you sure you want to continue?",details:s=null,confirmLabel:o="Confirm",confirmLoadingLabel:r="Working...",cancelLabel:i="Cancel",onConfirm:a,onCancel:l,confirmTone:c="primary",confirmLoading:d=!1,confirmDisabled:u=!1})=>(L(()=>{if(!t)return;let f=g=>{g.key==="Escape"&&l?.()};return window.addEventListener("keydown",f),()=>window.removeEventListener("keydown",f)},[t,l]),t?$S`
{f.target===f.currentTarget&&l?.()}}
@@ -1163,7 +1227,7 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
${n}
${s}
- <${Z}
+ <${Y}
onClick=${l}
disabled=${d}
tone="secondary"
@@ -1171,7 +1235,7 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
idleLabel=${i}
className="px-4 py-2 rounded-lg text-sm"
/>
- <${Z}
+ <${Y}
onClick=${a}
disabled=${u}
loading=${d}
@@ -1184,36 +1248,22 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
- `:null);var kd=new Map,Gs=new Map,yb=()=>Date.now(),gS=(t,e)=>t?yb()-Number(t.fetchedAt||0){let e=String(t||"");return e?kd.get(e)?.data??null:null},La=(t="",e=null)=>{let n=String(t||"");return n&&kd.set(n,{data:e,fetchedAt:yb()}),e};var vb=async(t,e,{maxAgeMs:n=15e3,force:s=!1,staleWhileRevalidate:o=!0,onRevalidate:r=null}={})=>{let i=String(t||"");if(!i||typeof e!="function")return e();let a=kd.get(i);if(!s&&gS(a,n))return a.data;if(!s&&o&&a){if(!Gs.has(i)){let c=Promise.resolve().then(()=>e()).then(d=>(La(i,d),typeof r=="function"&&r(d),d)).finally(()=>{Gs.delete(i)});Gs.set(i,c)}return a.data}if(Gs.has(i))return Gs.get(i);let l=Promise.resolve().then(()=>e()).then(c=>(La(i,c),c)).finally(()=>{Gs.delete(i)});return Gs.set(i,l),l};var ct=(t,e,{enabled:n=!0,maxAgeMs:s=15e3,staleWhileRevalidate:o=!0}={})=>{let r=F(()=>String(t||""),[t]),i=F(()=>ms(r),[r]),[a,l]=y(i),[c,d]=y(i===null),[u,p]=y(null);L(()=>{l(ms(r))},[r]);let f=q(async({force:g=!1}={})=>{if(!n)return ms(r);ms(r)===null&&d(!0);try{let m=await vb(r,e,{maxAgeMs:s,force:g,staleWhileRevalidate:o,onRevalidate:h=>{l(h),p(null)}});return l(m),p(null),m}catch(m){throw p(m),m}finally{d(!1)}},[n,e,s,r,o]);return L(()=>{n&&f().catch(()=>{})},[n,f]),{data:a,error:u,loading:c,refresh:f}};var qs=({channelId:t,account:e={},providerLabel:n=""})=>{let s=t?t.charAt(0).toUpperCase()+t.slice(1):"Channel",o=String(n||"").trim()||s,r=String(e?.name||"").trim();if(r)return r;let i=String(e?.id||"").trim();return!i||i==="default"?o:`${o} ${i}`},gs=({accountId:t,boundAgentId:e})=>String(t||"").trim()==="default"&&!String(e||"").trim();var Ea=async({payload:t={},onPhase:e=()=>{}})=>{if(e("Loading..."),typeof window?.EventSource!="function")return jm(t);let n=await zm(t),s=String(n?.operationId||"").trim();if(!s)throw new Error("Could not start channel creation operation");return new Promise((o,r)=>{let i=!1,a="",l=0,c=null,d=null,u={restarting:1200},p=()=>{d&&(clearTimeout(d),d=null)},f=({phase:h="",label:b=""}={})=>{let x=String(h||"").trim(),v=String(b||"").trim();if(!v)return;let w=Number(u[a]||0),$=l>0?Date.now()-l:0;if(w>0&&x&&x!==a&&${d=null;let S=c;c=null,S&&f(S)},w-$);return}p(),c=null,e(v),a=x,l=Date.now()},g=()=>{p(),m()},m=Um({operationId:s,onMessage:h=>{let b=String(h?.event||"").trim();if(b==="phase"){f({phase:String(h?.data?.phase||"").trim(),label:String(h?.data?.label||"").trim()});return}if(b==="done"){if(i)return;i=!0,g(),o(h?.data||{});return}if(b==="error"){if(i)return;i=!0,g(),r(new Error(String(h?.data?.error||"Could not create channel")))}},onError:()=>{i||(i=!0,g(),r(new Error("Channel operation stream disconnected")))}})})};var bS=new Set(["discord","slack"]),xS=({configuredChannelMap:t,provider:e})=>{let n=t instanceof Map?t.get(String(e||"").trim()):null;return Array.isArray(n?.accounts)&&n.accounts.length>0},yS=(t="")=>bS.has(String(t||"").trim()),Ia=({configuredChannelMap:t=new Map,provider:e=""}={})=>yS(e)?xS({configuredChannelMap:t,provider:e}):!1;var vS=P.bind(T),De=({visible:t=!1,onClose:e=()=>{},closeOnOverlayClick:n=!0,closeOnEscape:s=!0,panelClassName:o="bg-modal border border-border rounded-xl p-5 max-w-md w-full space-y-3",children:r=null})=>(L(()=>{if(!t||!s)return;let i=a=>{a.key==="Escape"&&e?.()};return window.addEventListener("keydown",i),()=>window.removeEventListener("keydown",i)},[t,s,e]),t?Do(vS`
- {n&&i.target===i.currentTarget&&e?.()}}
- >
-
${r}
-
- `,document.body):null);var $b=P.bind(T),Ne=({title:t="",actions:e=null,leading:n=null})=>$b`
-
-
- ${n||$b`
${t} `}
-
-
${e}
-
-`;var Js=P.bind(T),$S={telegram:"TELEGRAM_BOT_TOKEN",discord:"DISCORD_BOT_TOKEN",slack:"SLACK_BOT_TOKEN"},wS={slack:"SLACK_APP_TOKEN"},kS=["app_mentions:read","channels:history","channels:read","chat:write","groups:history","im:history","im:read","im:write","mpim:history","reactions:read","reactions:write","users:read"],SS="https://docs.openclaw.ai/channels/slack",CS=t=>String(t||"").toLowerCase().trim().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,""),_S=({provider:t,accountId:e})=>{let n=$S[String(t||"").trim()]||"",s=String(e||"").trim();return n?!s||s==="default"?n:`${n}_${s.replace(/-/g,"_").toUpperCase()}`:""},MS=t=>/^\*+$/.test(String(t||"").trim()),qr=({visible:t=!1,loading:e=!1,createLoadingLabel:n="Creating...",agents:s=[],existingChannels:o=[],mode:r="create",account:i=null,initialAgentId:a="",initialProvider:l="",onClose:c=()=>{},onSubmit:d=async()=>{}})=>{let u=r==="edit",[p,f]=y("telegram"),[g,m]=y(""),[h,b]=y(""),[x,v]=y(""),[w,$]=y(""),[S,C]=y(""),[_,k]=y(""),[A,O]=y(!1),[D,z]=y(!1);L(()=>{if(!t)return;let K=u?String(i?.provider||"").trim()||"telegram":bs.includes(l)?l:bs[0]||"telegram",j=Lt(K).label||"Channel",X=o.find(xe=>String(xe?.channel||"").trim()===String(K||"").trim())||null,de=Array.isArray(X?.accounts)&&X.accounts.length>0,le=u?String(i?.name||"").trim()||j:de?"":j,ie=u?String(i?.ownerAgentId||"").trim()||String(a||"").trim()||String(s[0]?.id||"").trim():String(a||"").trim()||String(s[0]?.id||"").trim();f(K),m(le);let ne=u?(()=>{let xe=String(i?.token||"").trim();return MS(xe)?"":xe})():"";b(ne),v(ne),$(""),C(ie),k(""),O(u)},[t,a,l,s,o,u,i]);let E=F(()=>o.find(K=>String(K?.channel||"").trim()===String(p||"").trim())||null,[o,p]),M=F(()=>Array.isArray(E?.accounts)&&E.accounts.length>0,[E]);L(()=>{if(A)return;let K=Lt(p).label||"Channel";if(!u&&M){m("");return}m(K)},[p,M,A,u]);let R=String(p||"").trim()==="discord"||String(p||"").trim()==="slack",B=String(p||"").trim()==="slack",I=F(()=>u?String(i?.id||"").trim()||"default":R||!M?"default":CS(g),[g,M,u,i,R]),U=F(()=>_S({provider:p,accountId:I}),[p,I]),W=F(()=>Array.isArray(E?.accounts)&&E.accounts.some(K=>String(K?.id||"").trim()===String(I||"").trim()),[E,I]);L(()=>{if(!t||!u)return;let K=!1;return(async()=>{z(!0);try{let X=await Vm({provider:p,accountId:I});if(K)return;let de=String(X?.token||""),le=String(X?.appToken||"");b(de),v(de),$(le)}catch{}finally{K||z(!1)}})(),()=>{K=!0}},[t,u,p,I]);let G=!!String(p||"").trim()&&!!String(g||"").trim()&&!!String(I||"").trim()&&!!String(S||"").trim()&&(u||!!String(h||"").trim())&&(u||!B||!!String(w||"").trim())&&(u||!W)&&!D;if(!t)return null;let se=async()=>{if(!String(g||"").trim()){k("Name is required");return}if(!String(I||"").trim()){k("Channel id could not be derived from the name");return}if(!u&&!String(h||"").trim()){k("Token is required");return}if(!u&&B&&!String(w||"").trim()){k("App Token is required for Slack");return}if(!String(S||"").trim()){k("Agent is required");return}if(!u&&W){k("That channel id is already configured for this provider");return}k("");let K=String(h||"").trim(),j=K&&K!==String(x||"").trim(),X=String(w||"").trim();await d({provider:p,name:String(g||"").trim(),accountId:I,agentId:S,...j?{token:K}:{},...B&&X?{appToken:X}:{}})};return Js`
- <${De}
+ `:null);var kd=new Map,qs=new Map,kb=()=>Date.now(),wS=(t,e)=>t?kb()-Number(t.fetchedAt||0){let e=String(t||"");return e?kd.get(e)?.data??null:null},La=(t="",e=null)=>{let n=String(t||"");return n&&kd.set(n,{data:e,fetchedAt:kb()}),e};var Sb=async(t,e,{maxAgeMs:n=15e3,force:s=!1,staleWhileRevalidate:o=!0,onRevalidate:r=null}={})=>{let i=String(t||"");if(!i||typeof e!="function")return e();let a=kd.get(i);if(!s&&wS(a,n))return a.data;if(!s&&o&&a){if(!qs.has(i)){let c=Promise.resolve().then(()=>e()).then(d=>(La(i,d),typeof r=="function"&&r(d),d)).finally(()=>{qs.delete(i)});qs.set(i,c)}return a.data}if(qs.has(i))return qs.get(i);let l=Promise.resolve().then(()=>e()).then(c=>(La(i,c),c)).finally(()=>{qs.delete(i)});return qs.set(i,l),l};var ct=(t,e,{enabled:n=!0,maxAgeMs:s=15e3,staleWhileRevalidate:o=!0}={})=>{let r=F(()=>String(t||""),[t]),i=F(()=>gs(r),[r]),[a,l]=y(i),[c,d]=y(i===null),[u,p]=y(null);L(()=>{l(gs(r))},[r]);let f=q(async({force:g=!1}={})=>{if(!n)return gs(r);gs(r)===null&&d(!0);try{let m=await Sb(r,e,{maxAgeMs:s,force:g,staleWhileRevalidate:o,onRevalidate:h=>{l(h),p(null)}});return l(m),p(null),m}catch(m){throw p(m),m}finally{d(!1)}},[n,e,s,r,o]);return L(()=>{n&&f().catch(()=>{})},[n,f]),{data:a,error:u,loading:c,refresh:f}};var Js=({channelId:t,account:e={},providerLabel:n=""})=>{let s=t?t.charAt(0).toUpperCase()+t.slice(1):"Channel",o=String(n||"").trim()||s,r=String(e?.name||"").trim();if(r)return r;let i=String(e?.id||"").trim();return!i||i==="default"?o:`${o} ${i}`},bs=({accountId:t,boundAgentId:e})=>String(t||"").trim()==="default"&&!String(e||"").trim();var Ea=async({payload:t={},onPhase:e=()=>{}})=>{if(e("Loading..."),typeof window?.EventSource!="function")return jm(t);let n=await zm(t),s=String(n?.operationId||"").trim();if(!s)throw new Error("Could not start channel creation operation");return new Promise((o,r)=>{let i=!1,a="",l=0,c=null,d=null,u={restarting:1200},p=()=>{d&&(clearTimeout(d),d=null)},f=({phase:h="",label:b=""}={})=>{let x=String(h||"").trim(),v=String(b||"").trim();if(!v)return;let w=Number(u[a]||0),$=l>0?Date.now()-l:0;if(w>0&&x&&x!==a&&${d=null;let S=c;c=null,S&&f(S)},w-$);return}p(),c=null,e(v),a=x,l=Date.now()},g=()=>{p(),m()},m=Um({operationId:s,onMessage:h=>{let b=String(h?.event||"").trim();if(b==="phase"){f({phase:String(h?.data?.phase||"").trim(),label:String(h?.data?.label||"").trim()});return}if(b==="done"){if(i)return;i=!0,g(),o(h?.data||{});return}if(b==="error"){if(i)return;i=!0,g(),r(new Error(String(h?.data?.error||"Could not create channel")))}},onError:()=>{i||(i=!0,g(),r(new Error("Channel operation stream disconnected")))}})})};var kS=new Set(["discord","slack","whatsapp"]),SS=({configuredChannelMap:t,provider:e})=>{let n=t instanceof Map?t.get(String(e||"").trim()):null;return Array.isArray(n?.accounts)&&n.accounts.length>0},CS=(t="")=>kS.has(String(t||"").trim()),Ia=({configuredChannelMap:t=new Map,provider:e=""}={})=>CS(e)?SS({configuredChannelMap:t,provider:e}):!1;var Rn=P.bind(T),_S={telegram:"TELEGRAM_BOT_TOKEN",discord:"DISCORD_BOT_TOKEN",slack:"SLACK_BOT_TOKEN",whatsapp:"WHATSAPP_OWNER_NUMBER"},AS={slack:"SLACK_APP_TOKEN"},MS=["app_mentions:read","channels:history","channels:read","chat:write","groups:history","im:history","im:read","im:write","mpim:history","reactions:read","reactions:write","users:read"],TS="https://docs.openclaw.ai/channels/slack",PS=t=>String(t||"").toLowerCase().trim().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,""),RS=({provider:t,accountId:e})=>{let n=_S[String(t||"").trim()]||"",s=String(e||"").trim();return n?!s||s==="default"?n:`${n}_${s.replace(/-/g,"_").toUpperCase()}`:""},LS=t=>/^\*+$/.test(String(t||"").trim()),qr=({visible:t=!1,loading:e=!1,createLoadingLabel:n="Creating...",agents:s=[],existingChannels:o=[],mode:r="create",account:i=null,initialAgentId:a="",initialProvider:l="",onClose:c=()=>{},onSubmit:d=async()=>{}})=>{let u=r==="edit",[p,f]=y("telegram"),[g,m]=y(""),[h,b]=y(""),[x,v]=y(""),[w,$]=y(""),[S,C]=y(""),[_,k]=y(""),[A,D]=y(!1),[N,U]=y(!1);L(()=>{if(!t)return;let Z=u?String(i?.provider||"").trim()||"telegram":xs.includes(l)?l:xs[0]||"telegram",ue=Lt(Z).label||"Channel",re=o.find(ce=>String(ce?.channel||"").trim()===String(Z||"").trim())||null,oe=Array.isArray(re?.accounts)&&re.accounts.length>0,ne=u?String(i?.name||"").trim()||ue:oe?"":ue,me=u?String(i?.ownerAgentId||"").trim()||String(a||"").trim()||String(s[0]?.id||"").trim():String(a||"").trim()||String(s[0]?.id||"").trim();f(Z),m(ne);let pe=u?(()=>{let ce=String(i?.token||"").trim();return LS(ce)?"":ce})():"";b(pe),v(pe),$(""),C(me),k(""),D(u)},[t,a,l,s,o,u,i]);let O=F(()=>o.find(Z=>String(Z?.channel||"").trim()===String(p||"").trim())||null,[o,p]),M=F(()=>Array.isArray(O?.accounts)&&O.accounts.length>0,[O]);L(()=>{if(A)return;let Z=Lt(p).label||"Channel";if(!u&&M){m("");return}m(Z)},[p,M,A,u]);let R=String(p||"").trim(),B=R==="discord"||R==="slack"||R==="whatsapp",E=R==="slack",G=R==="whatsapp",H=F(()=>u?String(i?.id||"").trim()||"default":B||!M?"default":PS(g),[g,M,u,i,B]),z=F(()=>RS({provider:p,accountId:H}),[p,H]),te=F(()=>Array.isArray(O?.accounts)&&O.accounts.some(Z=>String(Z?.id||"").trim()===String(H||"").trim()),[O,H]);L(()=>{if(!t||!u)return;let Z=!1;return(async()=>{U(!0);try{let re=await Vm({provider:p,accountId:H});if(Z)return;let oe=String(re?.token||""),ne=String(re?.appToken||"");b(oe),v(oe),$(ne)}catch{}finally{Z||U(!1)}})(),()=>{Z=!0}},[t,u,p,H]);let K=!!String(p||"").trim()&&!!String(g||"").trim()&&!!String(H||"").trim()&&!!String(S||"").trim()&&(u||!!String(h||"").trim())&&(u||!E||!!String(w||"").trim())&&(u||!te)&&!N;if(!t)return null;let V=async()=>{if(!String(g||"").trim()){k("Name is required");return}if(!String(H||"").trim()){k("Channel id could not be derived from the name");return}if(!u&&!String(h||"").trim()){k("Token is required");return}if(!u&&E&&!String(w||"").trim()){k("App Token is required for Slack");return}if(!String(S||"").trim()){k("Agent is required");return}if(!u&&te){k("That channel id is already configured for this provider");return}k("");let Z=String(h||"").trim(),ue=Z&&Z!==String(x||"").trim(),re=String(w||"").trim();await d({provider:p,name:String(g||"").trim(),accountId:H,agentId:S,...ue?{token:Z}:{},...E&&re?{appToken:re}:{}})};return Rn`
+ <${Te}
visible=${t}
onClose=${c}
panelClassName="bg-modal border border-border rounded-xl p-6 max-w-lg w-full space-y-4"
>
- <${Ne}
+ <${Pe}
title=${u?"Edit Channel":`Add ${Lt(p).label||"Channel"} Channel`}
- actions=${Js`
+ actions=${Rn`
- <${nt} className="w-3.5 h-3.5 text-body" />
+ <${Ze} className="w-3.5 h-3.5 text-body" />
`}
/>
@@ -1224,7 +1274,7 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
{O(!0),m(K.target.value)}}
+ onInput=${Z=>{D(!0),m(Z.target.value)}}
placeholder=${Lt(p).label||"Channel"}
class="w-full bg-field border border-border rounded-lg px-3 py-2 text-sm text-body outline-none focus:border-fg-muted"
/>
@@ -1234,41 +1284,51 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
Id
- ${u?"Channel id is fixed after creation.":R?`${Lt(p).label} supports one channel account and uses the default id.`:M?"Derived from the channel name.":"First account uses the default id for this provider."}
+ ${u?"Channel id is fixed after creation.":B?`${Lt(p).label} supports one channel account and uses the default id.`:M?"Derived from the channel name.":"First account uses the default id for this provider."}
-
- ${B?"Bot Token":"Token"}
+
+ ${G?"Owner Number":E?"Bot Token":"Token"}
- <${Rt}
- value=${h}
- onInput=${K=>b(K.target.value)}
- placeholder=${h?"":"Paste bot token"}
- loading=${D}
- isSecret=${!0}
- inputClass="w-full bg-field border border-border rounded-lg px-3 py-2 text-sm font-mono text-body outline-none focus:border-fg-muted"
- />
+ ${G?Rn`
+ b(Z.target.value)}
+ placeholder="+15551234567"
+ class="w-full bg-field border border-border rounded-lg px-3 py-2 text-sm font-mono text-body outline-none focus:border-fg-muted"
+ />
+ `:Rn`
+ <${Rt}
+ value=${h}
+ onInput=${Z=>b(Z.target.value)}
+ placeholder=${h?"":"Paste bot token"}
+ loading=${N}
+ isSecret=${!0}
+ inputClass="w-full bg-field border border-border rounded-lg px-3 py-2 text-sm font-mono text-body outline-none focus:border-fg-muted"
+ />
+ `}
- Saved behind the scenes as
- ${U||"CHANNEL_TOKEN"}.
+ ${G?"E.164 format phone number used for allowlist pairing.":Rn`Saved behind the scenes as
+ ${z||"CHANNEL_TOKEN"}.`}
- ${B?Js`
+ ${E?Rn`
App Token (Socket Mode)
<${Rt}
value=${w}
- onInput=${K=>$(K.target.value)}
+ onInput=${Z=>$(Z.target.value)}
placeholder="xapp-..."
isSecret=${!0}
inputClass="w-full bg-field border border-border rounded-lg px-3 py-2 text-sm font-mono text-body outline-none focus:border-fg-muted"
@@ -1276,13 +1336,13 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
Saved behind the scenes as
- ${wS.slack}
+ ${AS.slack}
.
`:null}
- ${B?Js`
+ ${E?Rn`
Slack-specific instructions (step-by-step)
@@ -1315,7 +1375,7 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
Create a Bot Token (xoxb-...)
with scopes:
- ${kS.join(", ")}
+ ${MS.join(", ")}
@@ -1328,7 +1388,7 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
Agent
C(K.target.value)}
+ onInput=${Z=>C(Z.target.value)}
class="w-full bg-field border border-border rounded-lg px-3 py-2 text-sm text-body outline-none focus:border-fg-muted"
>
- ${s.map(K=>Js`
-
- ${K.name||K.id}
+ ${s.map(Z=>Rn`
+
+ ${Z.name||Z.id}
`)}
- ${!u&&W?Js`
+ ${!u&&te?Rn`
- ${R?`${Lt(p).label} already has a configured channel account.`:`A ${Lt(p).label} account with this id already exists.`}
+ ${B?`${Lt(p).label} already has a configured channel account.`:`A ${Lt(p).label} account with this id already exists.`}
`:null}
- ${_?Js`${_}
`:null}
+ ${_?Rn`${_}
`:null}
- <${Z}
+ <${Y}
onClick=${c}
disabled=${e}
loading=${!1}
@@ -1371,9 +1431,9 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
size="md"
idleLabel="Cancel"
/>
- <${Z}
- onClick=${se}
- disabled=${e||!G}
+ <${Y}
+ onClick=${V}
+ disabled=${e||!K}
loading=${e}
tone="primary"
size="md"
@@ -1381,21 +1441,21 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
loadingLabel=${u?"Saving...":n}
/>
- ${De}>
- `};var wb=P.bind(T),AS=0,Da=null,TS={success:"success",error:"error",warning:"warning",info:"info",green:"success",red:"error",yellow:"warning",blue:"info"},PS={success:"bg-status-success-bg border border-status-success-border text-status-success",error:"bg-status-error-bg border border-status-error-border text-status-error",warning:"bg-status-warning-bg border border-status-warning-border text-status-warning",info:"bg-status-info-bg border border-status-info-border text-status-info"},kb=t=>{let e=String(t||"").trim().toLowerCase();return TS[e]||"info"};function N(t,e="info"){Da&&Da({id:++AS,text:t,type:kb(e)})}function Na({className:t="fixed bottom-4 right-4 z-50 space-y-2"}){let[e,n]=y([]);return L(()=>(Da=s=>{n(o=>[...o,s]),setTimeout(()=>n(o=>o.filter(r=>r.id!==s.id)),4e3)},()=>{Da=null}),[]),e.length===0?null:Do(wb`
- ${e.map(s=>wb`
-
+ ${Te}>
+ `};var Cb=P.bind(T),ES=0,Da=null,IS={success:"success",error:"error",warning:"warning",info:"info",green:"success",red:"error",yellow:"warning",blue:"info"},DS={success:"bg-status-success-bg border border-status-success-border text-status-success",error:"bg-status-error-bg border border-status-error-border text-status-error",warning:"bg-status-warning-bg border border-status-warning-border text-status-warning",info:"bg-status-info-bg border border-status-info-border text-status-info"},_b=t=>{let e=String(t||"").trim().toLowerCase();return IS[e]||"info"};function I(t,e="info"){Da&&Da({id:++ES,text:t,type:_b(e)})}function Na({className:t="fixed bottom-4 right-4 z-50 space-y-2"}){let[e,n]=y([]);return L(()=>(Da=s=>{n(o=>[...o,s]),setTimeout(()=>n(o=>o.filter(r=>r.id!==s.id)),4e3)},()=>{Da=null}),[]),e.length===0?null:Do(Cb`
+ ${e.map(s=>Cb`
+
${s.text}
`)}
-
`,document.body)}var en=P.bind(T),bs=["telegram","discord","slack"],RS={telegram:{label:"Telegram",iconSrc:"/assets/icons/telegram.svg"},discord:{label:"Discord",iconSrc:"/assets/icons/discord.svg"},slack:{label:"Slack",iconSrc:"/assets/icons/slack.svg"}},Lt=(t="")=>{let e=String(t||"").trim();return RS[e]||{label:e?e.charAt(0).toUpperCase()+e.slice(1):"Channel",iconSrc:""}},Sb=()=>window.dispatchEvent(new CustomEvent("alphaclaw:restart-required")),Oa=({title:t="Channels",items:e=[],loadingLabel:n="Loading...",actions:s=null,renderItem:o=null})=>en`
+
`,document.body)}var Jt=P.bind(T),xs=["telegram","discord","slack","whatsapp"],NS={telegram:{label:"Telegram",iconSrc:"/assets/icons/telegram.svg"},discord:{label:"Discord",iconSrc:"/assets/icons/discord.svg"},slack:{label:"Slack",iconSrc:"/assets/icons/slack.svg"},whatsapp:{label:"WhatsApp",iconSrc:"/assets/icons/whatsapp.svg"}},Lt=(t="")=>{let e=String(t||"").trim();return NS[e]||{label:e?e.charAt(0).toUpperCase()+e.slice(1):"Channel",iconSrc:""}},Ab=()=>window.dispatchEvent(new CustomEvent("alphaclaw:restart-required")),Oa=({title:t="Channels",items:e=[],loadingLabel:n="Loading...",actions:s=null,renderItem:o=null})=>Jt`
${t}
- ${s?en`
${s}
`:null}
+ ${s?Jt`
${s}
`:null}
- ${e.length>0?e.map(r=>{let i=Lt(r.channel||r.id),a=!!r.clickable,l=o?o({item:r,channelMeta:i,clickable:a}):null;return l||en`
+ ${e.length>0?e.map(r=>{let i=Lt(r.channel||r.id),a=!!r.clickable,l=o?o({item:r,channelMeta:i,clickable:a}):null;return l||Jt`
- ${i.iconSrc?en`
+ ${i.iconSrc?Jt`
${r.label||i.label}
- ${r.detailText?en`
+ ${r.detailText?Jt`
${r.detailText}
`:null}
- ${r.detailChevron?en`
+ ${r.detailChevron?Jt`
- `}):en`
-`,Cb=({channels:t=null,agents:e=[],onNavigate:n=()=>{},onRefreshStatuses:s=()=>{}})=>{let[o,r]=y(!1),[i,a]=y("Creating..."),[l,c]=y(""),[d,u]=y(null),[p,f]=y(null),{data:g,loading:m,refresh:h}=ct("/api/channels/accounts",To,{maxAgeMs:3e4}),b=Array.isArray(g?.channels)?g.channels:[],x=q(async()=>{try{await h({force:!0})}catch{}},[h]),v=F(()=>new Map(b.map(D=>[String(D?.channel||"").trim(),D])),[b]),w=F(()=>new Map(e.map(D=>[String(D?.id||"").trim(),String(D?.name||"").trim()||String(D?.id||"").trim()])),[e]),$=F(()=>String(e.find(D=>D?.default)?.id||"").trim(),[e]),S=e.length>0,C=async D=>{r(!0);try{let z=await Fr(D);u(null),N("Channel updated","success"),z?.restartRequired&&Sb(),await Promise.all([x(),Promise.resolve(s?.())])}catch(z){N(z.message||"Could not update channel","error")}finally{r(!1)}},_=async D=>{r(!0),a("Creating...");try{let z=await Ea({payload:D,onPhase:E=>{a(String(E||"").trim()||"Creating...")}});u(null),N("Channel configured","success"),z?.restartRequired&&Sb(),await Promise.all([x(),Promise.resolve(s?.())])}catch(z){N(z.message||"Could not configure channel","error")}finally{r(!1),a("Creating...")}},k=async()=>{if(p){r(!0);try{await $a({provider:p.provider,accountId:p.id}),f(null),N("Channel deleted","success"),await Promise.all([x(),Promise.resolve(s?.())])}catch(D){N(D.message||"Could not delete channel","error")}finally{r(!1)}}},A=D=>{c(""),u({id:"default",provider:D,name:Lt(D).label,ownerAgentId:$,mode:"create"})},O=F(()=>{if(m||!t)return[];let D=new Map(b.map((E,M)=>[String(E?.channel||"").trim(),M])),z=new Map(b.flatMap(E=>(Array.isArray(E?.accounts)?E.accounts:[]).map((M,R)=>[`${String(E?.channel||"").trim()}:${String(M?.id||"").trim()||"default"}`,R])));return Array.from(new Set([...b.map(E=>String(E?.channel||"").trim())])).filter(Boolean).flatMap(E=>{let M=t[E],R=v.get(E),B=Array.isArray(R?.accounts)?R.accounts:[];return R?B.map(I=>{let U=String(I?.id||"").trim()||"default",W=M?.accounts?.[U]||M||null,G=String(W?.status||I?.status||"configured").trim(),se=Number(W?.paired??I?.paired??M?.paired??0),K=E==="telegram"&&G==="paired"&&n,j=String(I?.boundAgentId||"").trim(),X=j||(gs({accountId:U,boundAgentId:j})?$:""),de=w.get(X)||X||"",le={id:U,provider:E,name:qs({channelId:E,account:I,providerLabel:Lt(E).label||"Channel"}),ownerAgentId:X,envKey:String(I?.envKey||"").trim(),token:String(I?.token||"").trim()},ie=en`
+`,Mb=({channels:t=null,agents:e=[],onNavigate:n=()=>{},onRefreshStatuses:s=()=>{}})=>{let[o,r]=y(!1),[i,a]=y("Creating..."),[l,c]=y(""),[d,u]=y(null),[p,f]=y(null),{data:g,loading:m,refresh:h}=ct("/api/channels/accounts",To,{maxAgeMs:3e4}),b=Array.isArray(g?.channels)?g.channels:[],[x,v]=y(null),[w,$]=y(""),[S,C]=y(""),[_,k]=y(!1),A=q(async()=>{try{await h({force:!0})}catch{}},[h]),D=F(()=>new Map(b.map(z=>[String(z?.channel||"").trim(),z])),[b]),N=F(()=>new Map(e.map(z=>[String(z?.id||"").trim(),String(z?.name||"").trim()||String(z?.id||"").trim()])),[e]),U=F(()=>String(e.find(z=>z?.default)?.id||"").trim(),[e]),O=e.length>0,M=async z=>{r(!0);try{let te=await Fr(z);u(null),I("Channel updated","success"),te?.restartRequired&&Ab(),await Promise.all([A(),Promise.resolve(s?.())])}catch(te){I(te.message||"Could not update channel","error")}finally{r(!1)}},R=async z=>{r(!0),a("Creating...");try{let te=await Ea({payload:z,onPhase:K=>{a(String(K||"").trim()||"Creating...")}});u(null),I("Channel configured","success"),te?.restartRequired&&Ab(),await Promise.all([A(),Promise.resolve(s?.())])}catch(te){I(te.message||"Could not configure channel","error")}finally{r(!1),a("Creating...")}},B=async()=>{if(p){r(!0);try{await $a({provider:p.provider,accountId:p.id}),f(null),I("Channel deleted","success"),await Promise.all([A(),Promise.resolve(s?.())])}catch(z){I(z.message||"Could not delete channel","error")}finally{r(!1)}}},E=async()=>{if(x){k(!0),C(""),$("");try{let z=await Km({provider:x.provider,accountId:x.id}),te=[z?.stdout||"",z?.stderr||""].filter(Boolean).join(`
+
+`).trim();$(te||"No terminal output captured."),z?.completed&&I("Channel linked","success")}catch(z){C(String(z?.message||"Could not start channel login"))}finally{k(!1)}}},G=z=>{c(""),u({id:"default",provider:z,name:Lt(z).label,ownerAgentId:U,mode:"create"})},H=F(()=>{if(m||!t)return[];let z=new Map(b.map((K,V)=>[String(K?.channel||"").trim(),V])),te=new Map(b.flatMap(K=>(Array.isArray(K?.accounts)?K.accounts:[]).map((V,Z)=>[`${String(K?.channel||"").trim()}:${String(V?.id||"").trim()||"default"}`,Z])));return Array.from(new Set([...b.map(K=>String(K?.channel||"").trim())])).filter(Boolean).flatMap(K=>{let V=t[K],Z=D.get(K),ue=Array.isArray(Z?.accounts)?Z.accounts:[];return Z?ue.map(re=>{let oe=String(re?.id||"").trim()||"default",ne=V?.accounts?.[oe]||V||null,me=String(ne?.status||re?.status||"configured").trim(),pe=Number(ne?.paired??re?.paired??V?.paired??0),ce=K==="telegram"&&me==="paired"&&n,ge=String(re?.boundAgentId||"").trim(),j=ge||(bs({accountId:oe,boundAgentId:ge})?U:""),J=N.get(j)||j||"",ie={id:oe,provider:K,name:Js({channelId:K,account:re,providerLabel:Lt(K).label||"Channel"}),ownerAgentId:j,envKey:String(re?.envKey||"").trim(),token:String(re?.token||"").trim()},de=Jt`
- ${S&&de&&G==="paired"?en`<${Ks}
- status=${G}
- ownerAgentName=${de}
- showAgentBadge=${S}
- channelId=${E}
- pairedCount=${se}
+ ${O&&J&&me==="paired"?Jt`<${Gs}
+ status=${me}
+ ownerAgentName=${J}
+ showAgentBadge=${O}
+ channelId=${K}
+ pairedCount=${pe}
/>`:null}
- ${G==="paired"?S&&de?null:en`<${Ks}
- status=${G}
+ ${me==="paired"?O&&J?null:Jt`<${Gs}
+ status=${me}
ownerAgentName=""
showAgentBadge=${!1}
- channelId=${E}
- pairedCount=${se}
- />`:en`<${Ks}
- status=${G}
+ channelId=${K}
+ pairedCount=${pe}
+ />`:Jt`<${Gs}
+ status=${me}
ownerAgentName=""
showAgentBadge=${!1}
- channelId=${E}
- pairedCount=${se}
+ channelId=${K}
+ pairedCount=${pe}
/>`}
<${pt}
- open=${l===`${E}:${U}`}
+ open=${l===`${K}:${oe}`}
ariaLabel="Open channel actions"
title="Open channel actions"
onClose=${()=>c("")}
- onToggle=${()=>c(ne=>ne===`${E}:${U}`?"":`${E}:${U}`)}
+ onToggle=${()=>c(be=>be===`${K}:${oe}`?"":`${K}:${oe}`)}
>
- <${We}
- onClick=${()=>{c(""),u(le)}}
+ <${Oe}
+ onClick=${()=>{c(""),u(ie)}}
>
Edit
- ${We}>
- <${We}
+ ${Oe}>
+ ${K==="whatsapp"?Jt`
+ <${Oe}
+ onClick=${()=>{c(""),v(ie),$(""),C("")}}
+ >
+ Link WhatsApp (QR)
+ ${Oe}>
+ `:null}
+ <${Oe}
className="text-status-error hover:text-status-error"
- onClick=${()=>{c(""),f(le)}}
+ onClick=${()=>{c(""),f(ie)}}
>
Delete
- ${We}>
+ ${Oe}>
${pt}>
- `;return{id:`${E}:${U}`,channel:E,channelOrder:Number(D.get(E)??9999),accountOrder:Number(z.get(`${E}:${U}`)??9999),label:qs({channelId:E,account:I,providerLabel:Lt(E).label||"Channel"}),isAwaitingPairing:G!=="paired",detailText:K?"Workspace":"",detailChevron:K,clickable:K,onClick:K?()=>n(`telegram/${encodeURIComponent(U)}`):void 0,trailing:ie}}):[]}).sort((E,M)=>{let R=+!!E?.isAwaitingPairing-+!!M?.isAwaitingPairing;if(R!==0)return R;let B=Number(E?.channelOrder??9999)-Number(M?.channelOrder??9999);if(B!==0)return B;let I=Number(E?.accountOrder??9999)-Number(M?.accountOrder??9999);return I!==0?I:String(E?.label||"").localeCompare(String(M?.label||""))})},[w,e.length,b,t,v,$,m,l,n,S]);return en`
+ `;return{id:`${K}:${oe}`,channel:K,channelOrder:Number(z.get(K)??9999),accountOrder:Number(te.get(`${K}:${oe}`)??9999),label:Js({channelId:K,account:re,providerLabel:Lt(K).label||"Channel"}),isAwaitingPairing:me!=="paired",detailText:ce?"Workspace":"",detailChevron:ce,clickable:ce,onClick:ce?()=>n(`telegram/${encodeURIComponent(oe)}`):void 0,trailing:de}}):[]}).sort((K,V)=>{let Z=+!!K?.isAwaitingPairing-+!!V?.isAwaitingPairing;if(Z!==0)return Z;let ue=Number(K?.channelOrder??9999)-Number(V?.channelOrder??9999);if(ue!==0)return ue;let re=Number(K?.accountOrder??9999)-Number(V?.accountOrder??9999);return re!==0?re:String(K?.label||"").localeCompare(String(V?.label||""))})},[N,e.length,b,t,D,U,m,l,n,O]);return Jt`
<${Oa}
title="Channels"
- items=${O}
+ items=${H}
loadingLabel=${m?"Loading...":"No channels configured"}
- actions=${en`
+ actions=${Jt`
<${Ra}
open=${l==="__create_channel"}
onClose=${()=>c("")}
- onToggle=${()=>c(D=>D==="__create_channel"?"":"__create_channel")}
+ onToggle=${()=>c(z=>z==="__create_channel"?"":"__create_channel")}
triggerDisabled=${o||m}
- channelIds=${bs}
+ channelIds=${xs}
getChannelMeta=${Lt}
- isChannelDisabled=${D=>Ia({configuredChannelMap:v,provider:D})}
- onSelectChannel=${A}
+ isChannelDisabled=${z=>Ia({configuredChannelMap:D,provider:z})}
+ onSelectChannel=${G}
/>
`}
/>
@@ -1520,7 +1589,7 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
initialAgentId=${String(d?.ownerAgentId||"").trim()}
initialProvider=${String(d?.provider||"").trim()}
onClose=${()=>u(null)}
- onSubmit=${d?.mode==="create"?_:C}
+ onSubmit=${d?.mode==="create"?R:M}
/>
<${st}
visible=${!!p}
@@ -1530,89 +1599,98 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
confirmLoadingLabel="Deleting..."
confirmTone="warning"
confirmLoading=${o}
- onConfirm=${k}
+ onConfirm=${B}
onCancel=${()=>{o||f(null)}}
/>
+ <${wb}
+ visible=${!!x}
+ loading=${_}
+ title=${`Link ${String(x?.name||"WhatsApp").trim()} via QR`}
+ output=${w}
+ error=${S}
+ onRun=${E}
+ onClose=${()=>{_||(v(null),$(""),C(""))}}
+ />
- `};var Pe=P.bind(T),LS=[{id:"telegram",title:"Telegram",fieldKeys:["TELEGRAM_BOT_TOKEN"]},{id:"discord",title:"Discord",fieldKeys:["DISCORD_BOT_TOKEN"]},{id:"slack",title:"Slack",fieldKeys:["SLACK_BOT_TOKEN","SLACK_APP_TOKEN"]}],_b=({activeGroup:t,vals:e,hasAi:n,setValue:s,modelOptions:o,modelsLoading:r,modelsError:i,canToggleFullCatalog:a,showAllModels:l,setShowAllModels:c,selectedProvider:d,codexLoading:u,codexStatus:p,startCodexAuth:f,handleCodexDisconnect:g,codexAuthStarted:m,codexAuthWaiting:h,codexManualInput:b,setCodexManualInput:x,completeCodexAuth:v,codexExchanging:w,visibleAiFieldKeys:$,error:S,step:C,totalGroups:_,currentGroupValid:k,goBack:A,goNext:O,loading:D,githubStepLoading:z,allValid:E,handleSubmit:M})=>{let[R,B]=y(!1),[I,U]=y(!1),[W,G]=y(()=>new Set(["telegram"])),se=e._GITHUB_FLOW||An,K=se===Bt?Tn:e._GITHUB_TARGET_REPO_MODE||Tn,j=se===Bt||K===qn?"ghp_... or github_pat_...":"ghp_...";L(()=>{t.id},[t.id]),L(()=>{C===_-1&&(B(!e.OPENAI_API_KEY),U(!e.GEMINI_API_KEY))},[C===_-1]),L(()=>{t.id==="channels"&&G(ne=>ne.size>0?ne:new Set(["telegram"]))},[t.id]);let X=ne=>Pe`
+ `};var Le=P.bind(T),OS=[{id:"telegram",title:"Telegram",fieldKeys:["TELEGRAM_BOT_TOKEN"]},{id:"discord",title:"Discord",fieldKeys:["DISCORD_BOT_TOKEN"]},{id:"slack",title:"Slack",fieldKeys:["SLACK_BOT_TOKEN","SLACK_APP_TOKEN"]}],Tb=({activeGroup:t,vals:e,hasAi:n,setValue:s,modelOptions:o,modelsLoading:r,modelsError:i,canToggleFullCatalog:a,showAllModels:l,setShowAllModels:c,selectedProvider:d,codexLoading:u,codexStatus:p,startCodexAuth:f,handleCodexDisconnect:g,codexAuthStarted:m,codexAuthWaiting:h,codexManualInput:b,setCodexManualInput:x,completeCodexAuth:v,codexExchanging:w,visibleAiFieldKeys:$,error:S,step:C,totalGroups:_,currentGroupValid:k,goBack:A,goNext:D,loading:N,githubStepLoading:U,allValid:O,handleSubmit:M})=>{let[R,B]=y(!1),[E,G]=y(!1),[H,z]=y(()=>new Set(["telegram"])),te=e._GITHUB_FLOW||Mn,K=te===Bt?Tn:e._GITHUB_TARGET_REPO_MODE||Tn,V=te===Bt||K===Jn?"ghp_... or github_pat_...":"ghp_...";L(()=>{t.id},[t.id]),L(()=>{C===_-1&&(B(!e.OPENAI_API_KEY),G(!e.GEMINI_API_KEY))},[C===_-1]),L(()=>{t.id==="channels"&&z(ne=>ne.size>0?ne:new Set(["telegram"]))},[t.id]);let Z=ne=>Le`
${ne.label}
<${Rt}
key=${ne.key}
value=${e[ne.key]||""}
- onInput=${xe=>s(ne.key,xe.target.value)}
- placeholder=${t.id==="github"&&ne.key==="GITHUB_TOKEN"?j:ne.placeholder||""}
+ onInput=${me=>s(ne.key,me.target.value)}
+ placeholder=${t.id==="github"&&ne.key==="GITHUB_TOKEN"?V:ne.placeholder||""}
isSecret=${!ne.isText}
inputClass="flex-1 bg-field border border-border rounded-lg px-3 py-2 text-sm text-body outline-none focus:border-fg-muted font-mono"
/>
- ${t.id==="github"&&ne.key==="GITHUB_WORKSPACE_REPO"?se===Bt?"Your new project will live here":K===qn?"Enter the owner/repo of an existing empty repository":"A new private repo will be created for you":t.id==="github"&&ne.key==="_GITHUB_SOURCE_REPO"?"The repo to import from":t.id==="github"&&ne.key==="GITHUB_TOKEN"?se===Bt?K===Tn?Pe`Use a classic PAT with${" "}repo${" "}scope to create the target repo. Fine-grained
works if the target already exists and can access both
- repos.`:Pe`Use a classic PAT with${" "}repo${" "}scope, or a fine-grained token with Contents +
Metadata access to both the source repo and target
- repo`:K===qn?Pe`Use a classic PAT with${" "}repo${" "}scope, or a fine-grained token with Contents +
- Metadata access to this repo`:Pe`Use a classic PAT with${" "}repo${" "}scope to create a new private repository`:ne.hint}
- `,de=new Map((t.fields||[]).map(ne=>[ne.key,ne])),le=ne=>G(xe=>{let he=new Set(xe);return he.has(ne)?he.delete(ne):he.add(ne),he}),ie=()=>Pe`
- ${LS.map(ne=>{let xe=W.has(ne.id),he=ne.fieldKeys.map(V=>de.get(V)).filter(Boolean),ue=Lt(ne.id),me=ne.fieldKeys.some(V=>String(e[V]||"").trim());return Pe`
+ `,ue=new Map((t.fields||[]).map(ne=>[ne.key,ne])),re=ne=>z(me=>{let pe=new Set(me);return pe.has(ne)?pe.delete(ne):pe.add(ne),pe}),oe=()=>Le`
+ ${OS.map(ne=>{let me=H.has(ne.id),pe=ne.fieldKeys.map(j=>ue.get(j)).filter(Boolean),ce=Lt(ne.id),ge=ne.fieldKeys.some(j=>String(e[j]||"").trim());return Le`
le(ne.id)}
+ onclick=${()=>re(ne.id)}
class="w-full flex items-center justify-between gap-2 px-3 py-2 text-left hover:bg-surface"
>
- ${ue.iconSrc?Pe` `:null}
${ne.title}
- ${me?Pe`<${ae} tone="success">Configured${ae}>`:null}
+ ${ge?Le`<${le} tone="success">Configured${le}>`:null}
▸
- ${xe?Pe`
+ ${me?Le`
- ${he.map(V=>X(V))}
+ ${pe.map(j=>Z(j))}
`:null}
`})}
-
`;return Pe`
+
`;return Le`
${t.title}
${t.description}
- ${t.validate(e,{hasAi:n})?Pe`
✓ `:t.id!=="tools"?Pe`
`:t.id!=="tools"?Le`Required `:null}
- ${t.id==="ai"&&Pe`
+ ${t.id==="ai"&&Le`
Model
Select a model
- ${o.map(ne=>Pe`
+ ${o.map(ne=>Le`
${ne.label||ne.key}
`)}
${r?"Loading model catalog...":i||""}
- ${a&&Pe`
+ ${a&&Le`
c(ne=>!ne)}
@@ -1639,22 +1717,22 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
`}
`}
- ${t.id==="ai"&&d==="openai-codex"&&Pe`
+ ${t.id==="ai"&&d==="openai-codex"&&Le`
Codex OAuth
- ${u?Pe`Checking... `:p.connected?Pe`<${ae} tone="success">Connected${ae}>`:Pe`<${ae} tone="warning">Not connected${ae}>`}
+ ${u?Le`Checking... `:p.connected?Le`<${le} tone="success">Connected${le}>`:Le`<${le} tone="warning">Not connected${le}>`}
- <${Z}
+ <${Y}
onClick=${f}
tone=${p.connected||m?"neutral":"primary"}
size="sm"
idleLabel=${p.connected?"Reconnect Codex":"Connect Codex OAuth"}
className="font-medium"
/>
- ${p.connected&&Pe`
- <${Z}
+ ${p.connected&&Le`
+ <${Y}
onClick=${g}
tone="ghost"
size="sm"
@@ -1663,7 +1741,7 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
/>
`}
- ${!p.connected&&m&&Pe`
+ ${!p.connected&&m&&Le`
${h?"Complete login in the popup, then paste the full redirect URL from the address bar (starts with ":"Paste the full redirect URL from the address bar (starts with "}
@@ -1678,7 +1756,7 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
placeholder="http://localhost:1455/auth/callback?code=...&state=..."
class="w-full bg-field border border-border rounded-lg px-3 py-2 text-xs text-body outline-none focus:border-fg-muted"
/>
- <${Z}
+ <${Y}
onClick=${v}
disabled=${!b.trim()||w}
loading=${w}
@@ -1692,12 +1770,12 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
`}
`}
- ${t.id==="github"&&Pe`
+ ${t.id==="github"&&Le`
- ${se===An?Pe`
+ ${te===Mn?Le`
- <${Xe}
- options=${[{label:"Create new repo",value:Tn},{label:"Use existing empty repo",value:qn}]}
+ <${Qe}
+ options=${[{label:"Create new repo",value:Tn},{label:"Use existing empty repo",value:Jn}]}
value=${K}
onChange=${ne=>s("_GITHUB_TARGET_REPO_MODE",ne)}
fullWidth=${!0}
@@ -1706,14 +1784,14 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
`:null}
`}
- ${t.id==="channels"?ie():(t.id==="ai"?t.fields.filter(ne=>$.has(ne.key)):t.id==="github"?t.fields.filter(ne=>se===Bt?!0:ne.key!=="_GITHUB_SOURCE_REPO"):t.fields).map(ne=>X(ne))}
- ${S?Pe`
$.has(ne.key)):t.id==="github"?t.fields.filter(ne=>te===Bt?!0:ne.key!=="_GITHUB_SOURCE_REPO"):t.fields).map(ne=>Z(ne))}
+ ${S?Le`
${S}
`:null}
- ${C===_-1&&(R||I)?Pe`
- ${R?Pe`
+ ${C===_-1&&(R||E)?Le`
+ ${R?Le`
OpenAI API Key
@@ -1735,7 +1813,7 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
>
`:null}
- ${I?Pe`
+ ${E?Le`
Gemini API Key
@@ -1760,36 +1838,36 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
`:null}
- ${C<_-1?Pe`
- ${C>=0?Pe`<${Z}
+ ${C<_-1?Le`
+ ${C>=0?Le`<${Y}
onClick=${A}
tone="secondary"
size="md"
idleLabel="Back"
className="w-full"
- />`:Pe`
`}
- <${Z}
- onClick=${O}
+ />`:Le`
`}
+ <${Y}
+ onClick=${D}
disabled=${!k}
- loading=${t.id==="github"&&z}
+ loading=${t.id==="github"&&U}
tone="primary"
size="md"
- idleLabel=${t.id==="github"&&se===Bt?"Check compatibility":"Next"}
+ idleLabel=${t.id==="github"&&te===Bt?"Check compatibility":"Next"}
loadingLabel="Checking..."
className="w-full"
/>
- `:Pe`
- ${C>=0?Pe`<${Z}
+ `:Le`
+ ${C>=0?Le`<${Y}
onClick=${A}
tone="secondary"
size="md"
idleLabel="Back"
className="w-full"
- />`:Pe`
`}
- <${Z}
+ />`:Le`
`}
+ <${Y}
onClick=${M}
- disabled=${!E}
- loading=${D}
+ disabled=${!O}
+ loading=${N}
tone="primary"
size="md"
idleLabel="Next"
@@ -1798,7 +1876,7 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
/>
`}
- `};var Rn=P.bind(T),ES={telegram:{label:"Telegram",iconSrc:"/assets/icons/telegram.svg"},discord:{label:"Discord",iconSrc:"/assets/icons/discord.svg"}},IS=({pairing:t,onApprove:e,onReject:n})=>{let[s,o]=y(""),r=async()=>{o("approve");try{await e(t.id,t.channel,t.accountId||"")}finally{o("")}},i=async()=>{o("reject");try{await n(t.id,t.channel,t.accountId||"")}finally{o("")}};return Rn`
+ `};var Ln=P.bind(T),BS={telegram:{label:"Telegram",iconSrc:"/assets/icons/telegram.svg"},discord:{label:"Discord",iconSrc:"/assets/icons/discord.svg"},slack:{label:"Slack",iconSrc:"/assets/icons/slack.svg"},whatsapp:{label:"WhatsApp",iconSrc:"/assets/icons/whatsapp.svg"}},FS=({pairing:t,onApprove:e,onReject:n})=>{let[s,o]=y(""),r=async()=>{o("approve");try{await e(t.id,t.channel,t.accountId||"")}finally{o("")}},i=async()=>{o("reject");try{await n(t.id,t.channel,t.accountId||"")}finally{o("")}};return Ln`
@@ -1830,7 +1908,7 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
- `},Mb=({channel:t,pairings:e,channels:n,loading:s,error:o,onApprove:r,onReject:i,canFinish:a,onContinue:l,onSkip:c})=>{let d=ES[t]||{label:t?t.charAt(0).toUpperCase()+t.slice(1):"Channel",iconSrc:""},u=n?.[t];return t?a?Rn`
+ `},Pb=({channel:t,pairings:e,loading:n,error:s,onApprove:o,onReject:r,canFinish:i,onContinue:a,onSkip:l})=>{let c=BS[t]||{label:t?t.charAt(0).toUpperCase()+t.slice(1):"Channel",iconSrc:""};return t?i?Ln`
@@ -1838,8 +1916,8 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
🎉 Setup complete
- Your ${d.label} channel is connected. You can switch
- to ${d.label} and start using your agent now.
+ Your ${c.label} channel is connected. You can switch to${" "}
+ ${c.label} and start using your agent now.
Continue to the dashboard to explore extras like Google Workspace
@@ -1848,40 +1926,40 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
Continue to dashboard
- `:Rn`
+ `:Ln`
- <${ae} tone="warning"
- >${s?"Checking...":e.length>0?"Pairing request detected":"Awaiting pairing"}${ae}
+ <${le} tone="warning"
+ >${n?"Checking...":e.length>0?"Pairing request detected":"Awaiting pairing"}${le}
>
- ${e.length>0?Rn`
+ ${e.length>0?Ln`
- ${e.map(p=>Rn`<${IS}
- key=${p.id}
- pairing=${p}
- onApprove=${r}
- onReject=${i}
+ ${e.map(d=>Ln`<${FS}
+ key=${d.id}
+ pairing=${d}
+ onApprove=${o}
+ onReject=${r}
/>`)}
-
`:Rn`
`:Ln`
- ${d.iconSrc?Rn`
`:null}
- Send a message to your ${d.label} bot
+ Send a message to your ${c.label} bot
The pairing request will appear here in 5-10 seconds
@@ -1889,31 +1967,30 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
`}
- ${o?Rn`
- ${o}
+ ${s}
`:null}
- ${e.length===0?Rn`
+ ${e.length===0?Ln`
Skip pairing for now
`:null}
- `:Rn`
+ `:Ln`
- Missing channel configuration. Go back and add a Telegram or Discord bot
- token.
+ Missing channel configuration. Go back and add a channel credential.
- `};var Sd=(t={})=>t.TELEGRAM_BOT_TOKEN?"telegram":t.DISCORD_BOT_TOKEN?"discord":t.SLACK_BOT_TOKEN&&t.SLACK_APP_TOKEN?"slack":"",Ab=(t={},e="")=>{if(!e)return!1;let n=t?.[e];return n?n.status==="paired"&&Number(n.paired||0)>0:!1};var Cd="alphaclaw.ui.settings",Jr="alphaclaw.browse.viewerMode",Ba="alphaclaw.browse.editorSelection",_d="alphaclaw.browse.expandedFolders",Fa="alphaclaw.browse.draft.",Md="alphaclaw.browse.draftIndex",Zr="alphaclaw.onboarding.state",Ha="alphaclaw.telegram.workspaceState",Wa="alphaclaw.telegram.workspaceCache",Ad="alphaclaw.agent.sessionsCache",Td="alphaclaw.agent.lastSessionKey";var Tb="_step",Pd="_pairingChannel",Pb="_lastSetupError",DS=()=>{try{return JSON.parse(localStorage.getItem(Zr)||"{}")}catch{return{}}},Rb=({kSetupStepIndex:t,kPairingStepIndex:e}={})=>{let[n]=y(DS),[s,o]=y(()=>({...n})),[r,i]=y(null),l=!!String(n?.[Pb]||"").trim(),[c,d]=y(()=>{let p=Number.parseInt(String(n?.[Tb]||""),10);if(!Number.isFinite(p))return-1;let f=Math.max(-1,Math.min(e,p));return f===t&&l?0:f});return L(()=>{localStorage.setItem(Zr,JSON.stringify({...s,[Tb]:c,...r?{[Pb]:r}:{}}))},[s,c,r]),{vals:s,setVals:o,setValue:(p,f)=>o(g=>({...g,[p]:f})),step:c,setStep:d,setupError:r,setSetupError:i}};var Lb=({setFormError:t}={})=>{let[e,n]=y({connected:!1}),[s,o]=y(!0),[r,i]=y(""),[a,l]=y(!1),[c,d]=y(!1),[u,p]=y(!1),f=ee(null),g=async()=>{try{let x=await Po();n(x),x?.connected&&(d(!1),p(!1))}catch{n({connected:!1})}finally{o(!1)}};return L(()=>{g()},[]),L(()=>{let x=async v=>{v.data?.codex==="success"&&await g(),v.data?.codex==="error"&&t(`Codex auth failed: ${v.data.message||"unknown error"}`)};return window.addEventListener("message",x),()=>window.removeEventListener("message",x)},[t]),L(()=>()=>{f.current&&(clearInterval(f.current),f.current=null)},[]),{codexStatus:e,codexLoading:s,codexManualInput:r,setCodexManualInput:i,codexExchanging:a,codexAuthStarted:c,codexAuthWaiting:u,startCodexAuth:()=>{if(e.connected)return;d(!0),p(!0);let x="/auth/codex/start",v=window.open(x,"codex-auth","popup=yes,width=640,height=780");if(!v||v.closed){p(!1),window.location.href=x;return}f.current&&clearInterval(f.current),f.current=setInterval(()=>{v.closed&&(clearInterval(f.current),f.current=null,p(!1))},500)},completeCodexAuth:async()=>{if(!(!r.trim()||a)){l(!0),t(null);try{let x=await Wr(r.trim());if(!x.ok)throw new Error(x.error||"Codex OAuth exchange failed");i(""),d(!1),p(!1),await g()}catch(x){t(x.message||"Codex OAuth exchange failed")}finally{l(!1)}}},handleCodexDisconnect:async()=>{let x=await Hr();if(!x.ok){t(x.error||"Failed to disconnect Codex");return}d(!1),p(!1),i(""),await g()}}};var Re=(t,e,{enabled:n=!0,pauseWhenHidden:s=!0,cacheKey:o=""}={})=>{let r=String(o||""),[i,a]=y(()=>r?ms(r):null),[l,c]=y(null),d=ee(t);d.current=t;let u=q(async()=>{try{let p=await d.current();return r&&La(r,p),a(p),c(null),p}catch(p){return c(p),null}},[r]);return L(()=>{if(!r)return;let p=ms(r);p!==null&&a(p)},[r]),L(()=>{if(!n||s&&typeof document<"u"&&document.hidden)return;u();let p=setInterval(u,e);return()=>clearInterval(p)},[n,e,s,u]),L(()=>{if(!n||!s||typeof document>"u")return;let p=()=>{document.hidden||u()};return document.addEventListener("visibilitychange",p),()=>document.removeEventListener("visibilitychange",p)},[n,s,u]),{data:i,error:l,refresh:u}};var Eb=({isPairingStep:t=!1,selectedPairingChannel:e=""}={})=>{let[n,s]=y(null),[o,r]=y(!1),i=Re(So,3e3,{enabled:t}),a=Re(async()=>((await Co()).pending||[]).filter(m=>m.channel===e),1e3,{enabled:t&&!!e}),l=i.data?.channels||{},c=Ab(l,e);return L(()=>{t&&c&&r(!0)},[t,c]),{pairingStatusPoll:i,pairingRequestsPoll:a,pairingChannels:l,canFinishPairing:c,pairingError:n,pairingComplete:o,handlePairingApprove:async(f,g,m="")=>{try{s(null);let h=await _o(f,g,m);if(!h.ok)throw new Error(h.error||"Could not approve pairing");r(!0),a.refresh(),i.refresh()}catch(h){s(h.message||"Could not approve pairing")}},handlePairingReject:async(f,g,m="")=>{try{s(null);let h=await Mo(f,g,m);if(!h.ok)throw new Error(h.error||"Could not reject pairing");a.refresh()}catch(h){s(h.message||"Could not reject pairing")}},resetPairingState:()=>{s(null),r(!1)}}};var Ib=64,NS=128,Db=4096,Rd="import",Nb="secret-review",Va="placeholder-review",Ob="_IMPORT_SUBSTEP",Ld="_IMPORT_PLACEHOLDER_REVIEW",Bb="_IMPORT_PLACEHOLDER_SKIP_CONFIRMED",Fb=(t={})=>{let e=!1,n=Object.entries(t).map(([s,o])=>{let r=typeof o=="string"?o.trim():o;return r!==o&&(e=!0),[s,r]});return{normalizedVals:e?Object.fromEntries(n):t,didChange:e}},Hb=t=>!t||!Array.isArray(t.vars)||t.vars.length===0?{found:!1,count:0,vars:[]}:{found:!0,count:typeof t.count=="number"?t.count:t.vars.length,vars:t.vars.map(e=>({key:String(e?.key||"").trim(),status:String(e?.status||"missing").trim()||"missing"})).filter(e=>e.key)},Wb=({onComplete:t})=>{let e=Ht.length,n=e+1,{vals:s,setVals:o,setValue:r,step:i,setStep:a,setupError:l,setSetupError:c}=Rb({kSetupStepIndex:e,kPairingStepIndex:n}),[d,u]=y([]),[p,f]=y(!0),[g,m]=y(null),[h,b]=y(!1),[x,v]=y(!1),[w,$]=y(!1),[S,C]=y(null),{codexStatus:_,codexLoading:k,codexManualInput:A,setCodexManualInput:O,codexExchanging:D,codexAuthStarted:z,codexAuthWaiting:E,startCodexAuth:M,completeCodexAuth:R,handleCodexDisconnect:B}=Lb({setFormError:C}),[I,U]=y(()=>{let ge=String(s[Ob]||"").trim();return ge===Va?ge:null}),[W,G]=y(null),[se,K]=y(null),[j,X]=y(!1),[de,le]=y(null),ie=ge=>{U(ge),o(bt=>({...bt,[Ob]:ge===Va?ge:""}))},ne=()=>{o(ge=>({...ge,[Ld]:null,[Bb]:!1}))};L(()=>{Br().then(ge=>{let bt=Array.isArray(ge.models)?ge.models:[],Pt=Lo(bt);if(u(bt),!s.MODEL_KEY&&bt.length>0){let xt=Pt[0]||bt[0];o(fn=>({...fn,MODEL_KEY:xt.key}))}}).catch(()=>m("Failed to load models")).finally(()=>f(!1))},[]);let xe=js(s.MODEL_KEY),he=Hb(s[Ld]),ue=Lo(d),me=h?d:ue.length>0?ue:d,V=d.find(ge=>ge.key===s.MODEL_KEY),J=V&&!me.some(ge=>ge.key===V.key)?[...me,V]:me,oe=ue.length>0&&d.length>ue.length,ce=bg(xe),be=Ro(xe),Ve=Mn[be]||[],et=xe==="openai-codex"?!!_.connected:Ve.some(ge=>!!String(s[ge.key]||"").trim()),kt=Ht.every(ge=>ge.validate(s,{hasAi:et})),Ot=i===-1,Q=i===e,pe=i===n,te=i>=0&&i
{let{normalizedVals:ge,didChange:bt}=Fb(s);if(bt&&o(ge),!Ht.every(Ke=>Ke.validate(ge,{hasAi:et}))||x)return;let Pt=Object.entries(ge).filter(([Ke])=>Ke!=="MODEL_KEY"&&!String(Ke||"").startsWith("_")).filter(([,Ke])=>Ke).map(([Ke,St])=>({key:Ke,value:St})),xt=(()=>{if(!ge.MODEL_KEY||!String(ge.MODEL_KEY).includes("/"))return"A model selection is required";if(Pt.length>Ib)return`Too many environment variables (max ${Ib})`;for(let Ke of Pt){let St=String(Ke?.key||""),Gt=String(Ke?.value||"");if(!St)return"Each variable must include a key";if(St.length>NS)return`Variable key is too long: ${St.slice(0,32)}...`;if(Gt.length>Db)return`Value too long for ${St} (max ${Db} chars)`}return!ge.GITHUB_TOKEN||!zr(ge.GITHUB_WORKSPACE_REPO)?'Target repo must be in "owner/repo" format.':(ge._GITHUB_FLOW||An)===Bt&&!zr(ge._GITHUB_SOURCE_REPO)?'Source repo must be in "owner/repo" format.':""})();if(xt){C(xt),c(null),a(Math.max(0,Ht.findIndex(Ke=>Ke.id==="github")));return}a(e),v(!0),C(null),c(null),ea();let fn=(ge._GITHUB_FLOW||An)===Bt;try{let Ke=await Om(Pt,ge.MODEL_KEY,{importMode:fn});if(!Ke.ok)throw new Error(Ke.error||"Onboarding failed");let St=Sd(ge);if(!St)throw new Error("No Telegram or Discord bot token configured for pairing.");o(Gt=>({...Gt,[Pd]:St})),v(!1),a(n),ea(),c(null)}catch(Ke){console.error("Onboard error:",Ke),c(Ke.message||"Onboarding failed"),v(!1)}},Cr=()=>{localStorage.removeItem(Zr),t()},jc=()=>{Q||(C(null),a(ge=>Math.max(-1,ge-1)))},ta=()=>{v(!1),c(null),a(Ht.length-1)},Kt=async()=>{let{normalizedVals:ge,didChange:bt}=Fb(s);if(bt&&o(ge),!(!te||!te.validate(ge,{hasAi:et}))){if(C(null),te.id==="github"){let Pt=ge._GITHUB_FLOW||An,xt=Pt===Bt?Tn:ge._GITHUB_TARGET_REPO_MODE||Tn,fn=xt===qn?hd:fd,Ke=Pt===Bt?ge._GITHUB_SOURCE_REPO:ge.GITHUB_WORKSPACE_REPO;$(!0),ne();try{if(Pt===Bt){let Gt=await va(Ke,ge.GITHUB_TOKEN,hd);if(!Gt?.ok){C(Gt?.error||"GitHub source verification failed");return}if(Gt.repoIsEmpty){C("That source repository is empty. Use Start fresh if you want AlphaClaw to bootstrap a new setup there.");return}let vo=await va(ge.GITHUB_WORKSPACE_REPO,ge.GITHUB_TOKEN,fd);if(!vo?.ok){C(vo?.error||"GitHub target verification failed");return}if(xt===Tn&&vo.repoExists){C("That target repository already exists. Choose Use existing empty repo or pick a new target repo name.");return}if(xt===qn&&!vo.repoExists){C("That target repository does not exist yet. Choose Create new repo or enter an existing empty target repo.");return}if(Gt.tempDir&&!Gt.repoIsEmpty){G(Gt.tempDir),ie(Rd),X(!0),le(null);try{let Hs=await Bm(Gt.tempDir);if(!Hs?.ok){le(Hs?.error||"Import scan failed"),X(!1);return}K(Hs)}catch(Hs){le(Hs?.message||"Import scan failed")}finally{X(!1)}return}}let St=await va(ge.GITHUB_WORKSPACE_REPO,ge.GITHUB_TOKEN,fn);if(!St?.ok){C(St?.error||"GitHub verification failed");return}if(xt===Tn&&St.repoExists){C("That target repository already exists. Choose Use existing empty repo or pick a new target repo name.");return}if(xt===qn&&!St.repoExists){C("That target repository does not exist yet. Choose Create new repo or enter an existing empty target repo.");return}}catch(St){C(St?.message||"GitHub verification failed");return}finally{$(!1)}}a(Pt=>Math.min(Ht.length-1,Pt+1))}},Vf=async(ge=[])=>{X(!0),le(null);try{let bt=ge.length===0,Pt=kg(ge),xt=await Fm({tempDir:W,approvedSecrets:ge,skipSecretExtraction:bt,githubRepo:s.GITHUB_WORKSPACE_REPO,githubToken:s.GITHUB_TOKEN});if(!xt?.ok){le(xt?.error||"Import failed"),X(!1);return}let fn=Hb(xt.placeholderReview);if(o(Ke=>({...Ke,...Pt,...xt.preFill||{},[Ld]:fn,[Bb]:!1})),fn.found){ie(Va);return}ne(),ie(null),a(Ke=>Math.min(Ht.length-1,Ke+1))}catch(bt){le(bt?.message||"Import failed")}finally{X(!1)}},go=()=>{ie(Nb)},bo=()=>{ie(Rd)},_r=()=>{ie(null),G(null),K(null),le(null),ne()},na=()=>{ne(),ie(null),a(ge=>Math.min(Ht.length-1,ge+1))},ps=ge=>{r("_GITHUB_FLOW",ge),a(0)},xo=I===Rd,Fs=I===Nb,fs=I===Va,Gn=Ot?"Getting Started":xo?"Import":Fs?"Review Secrets":fs?"Review Env Vars":Q?"Initializing":pe?"Pairing":te?.title||"Setup",yo=Ot?0:xo||Fs||fs?i+1:Q?Ht.length+1:pe?Ht.length+2:i+1;return{state:{vals:s,step:i,setupError:l,modelsLoading:p,modelsError:g,showAllModels:h,loading:x,githubStepLoading:w,formError:S,importScanResult:se,importScanning:j,importError:de,selectedProvider:xe,modelOptions:J,canToggleFullCatalog:oe,visibleAiFieldKeys:ce,hasAi:et,allValid:kt,isPreStep:Ot,isSetupStep:Q,isPairingStep:pe,activeGroup:te,currentGroupValid:Ee,selectedPairingChannel:ke,placeholderReview:he,isImportStep:xo,isSecretReviewStep:Fs,isPlaceholderReviewStep:fs,activeStepLabel:Gn,stepNumber:yo,codexStatus:_,codexLoading:k,codexManualInput:A,codexExchanging:D,codexAuthStarted:z,codexAuthWaiting:E,pairingStatusPoll:H,pairingRequestsPoll:re,pairingChannels:ye,canFinishPairing:ve,pairingError:Ie,pairingComplete:gt},actions:{setVals:o,setValue:r,setShowAllModels:b,setCodexManualInput:O,startCodexAuth:M,completeCodexAuth:R,handleCodexDisconnect:B,handleSubmit:Vc,finishOnboarding:Cr,goBack:jc,goBackFromSetupError:ta,goNext:Kt,handleSelectFlow:ps,handleImportApprove:Vf,handleShowSecretReview:go,handleSecretReviewBack:bo,handleImportBack:_r,handlePlaceholderReviewContinue:na,handlePairingApprove:Hc,handlePairingReject:Wc}}};var Jn=P.bind(T),Vb=({onComplete:t,acVersion:e})=>{let{state:n,actions:s}=Wb({onComplete:t});return Jn`
+ `};var Sd=(t={})=>t.TELEGRAM_BOT_TOKEN?"telegram":t.DISCORD_BOT_TOKEN?"discord":t.SLACK_BOT_TOKEN&&t.SLACK_APP_TOKEN?"slack":"",Rb=(t={},e="")=>{if(!e)return!1;let n=t?.[e];return n?n.status==="paired"&&Number(n.paired||0)>0:!1};var Cd="alphaclaw.ui.settings",Jr="alphaclaw.browse.viewerMode",Ba="alphaclaw.browse.editorSelection",_d="alphaclaw.browse.expandedFolders",Fa="alphaclaw.browse.draft.",Ad="alphaclaw.browse.draftIndex",Zr="alphaclaw.onboarding.state",Ha="alphaclaw.telegram.workspaceState",Wa="alphaclaw.telegram.workspaceCache",Md="alphaclaw.agent.sessionsCache",Td="alphaclaw.agent.lastSessionKey";var Lb="_step",Pd="_pairingChannel",Eb="_lastSetupError",HS=()=>{try{return JSON.parse(localStorage.getItem(Zr)||"{}")}catch{return{}}},Ib=({kSetupStepIndex:t,kPairingStepIndex:e}={})=>{let[n]=y(HS),[s,o]=y(()=>({...n})),[r,i]=y(null),l=!!String(n?.[Eb]||"").trim(),[c,d]=y(()=>{let p=Number.parseInt(String(n?.[Lb]||""),10);if(!Number.isFinite(p))return-1;let f=Math.max(-1,Math.min(e,p));return f===t&&l?0:f});return L(()=>{localStorage.setItem(Zr,JSON.stringify({...s,[Lb]:c,...r?{[Eb]:r}:{}}))},[s,c,r]),{vals:s,setVals:o,setValue:(p,f)=>o(g=>({...g,[p]:f})),step:c,setStep:d,setupError:r,setSetupError:i}};var Db=({setFormError:t}={})=>{let[e,n]=y({connected:!1}),[s,o]=y(!0),[r,i]=y(""),[a,l]=y(!1),[c,d]=y(!1),[u,p]=y(!1),f=ee(null),g=async()=>{try{let x=await Po();n(x),x?.connected&&(d(!1),p(!1))}catch{n({connected:!1})}finally{o(!1)}};return L(()=>{g()},[]),L(()=>{let x=async v=>{v.data?.codex==="success"&&await g(),v.data?.codex==="error"&&t(`Codex auth failed: ${v.data.message||"unknown error"}`)};return window.addEventListener("message",x),()=>window.removeEventListener("message",x)},[t]),L(()=>()=>{f.current&&(clearInterval(f.current),f.current=null)},[]),{codexStatus:e,codexLoading:s,codexManualInput:r,setCodexManualInput:i,codexExchanging:a,codexAuthStarted:c,codexAuthWaiting:u,startCodexAuth:()=>{if(e.connected)return;d(!0),p(!0);let x="/auth/codex/start",v=window.open(x,"codex-auth","popup=yes,width=640,height=780");if(!v||v.closed){p(!1),window.location.href=x;return}f.current&&clearInterval(f.current),f.current=setInterval(()=>{v.closed&&(clearInterval(f.current),f.current=null,p(!1))},500)},completeCodexAuth:async()=>{if(!(!r.trim()||a)){l(!0),t(null);try{let x=await Wr(r.trim());if(!x.ok)throw new Error(x.error||"Codex OAuth exchange failed");i(""),d(!1),p(!1),await g()}catch(x){t(x.message||"Codex OAuth exchange failed")}finally{l(!1)}}},handleCodexDisconnect:async()=>{let x=await Hr();if(!x.ok){t(x.error||"Failed to disconnect Codex");return}d(!1),p(!1),i(""),await g()}}};var Ee=(t,e,{enabled:n=!0,pauseWhenHidden:s=!0,cacheKey:o=""}={})=>{let r=String(o||""),[i,a]=y(()=>r?gs(r):null),[l,c]=y(null),d=ee(t);d.current=t;let u=q(async()=>{try{let p=await d.current();return r&&La(r,p),a(p),c(null),p}catch(p){return c(p),null}},[r]);return L(()=>{if(!r)return;let p=gs(r);p!==null&&a(p)},[r]),L(()=>{if(!n||s&&typeof document<"u"&&document.hidden)return;u();let p=setInterval(u,e);return()=>clearInterval(p)},[n,e,s,u]),L(()=>{if(!n||!s||typeof document>"u")return;let p=()=>{document.hidden||u()};return document.addEventListener("visibilitychange",p),()=>document.removeEventListener("visibilitychange",p)},[n,s,u]),{data:i,error:l,refresh:u}};var Nb=({isPairingStep:t=!1,selectedPairingChannel:e=""}={})=>{let[n,s]=y(null),[o,r]=y(!1),i=Ee(So,3e3,{enabled:t}),a=Ee(async()=>((await Co()).pending||[]).filter(m=>m.channel===e),1e3,{enabled:t&&!!e}),l=i.data?.channels||{},c=Rb(l,e);return L(()=>{t&&c&&r(!0)},[t,c]),{pairingStatusPoll:i,pairingRequestsPoll:a,pairingChannels:l,canFinishPairing:c,pairingError:n,pairingComplete:o,handlePairingApprove:async(f,g,m="")=>{try{s(null);let h=await _o(f,g,m);if(!h.ok)throw new Error(h.error||"Could not approve pairing");r(!0),a.refresh(),i.refresh()}catch(h){s(h.message||"Could not approve pairing")}},handlePairingReject:async(f,g,m="")=>{try{s(null);let h=await Ao(f,g,m);if(!h.ok)throw new Error(h.error||"Could not reject pairing");a.refresh()}catch(h){s(h.message||"Could not reject pairing")}},resetPairingState:()=>{s(null),r(!1)}}};var Ob=64,WS=128,Bb=4096,Rd="import",Fb="secret-review",Va="placeholder-review",Hb="_IMPORT_SUBSTEP",Ld="_IMPORT_PLACEHOLDER_REVIEW",Wb="_IMPORT_PLACEHOLDER_SKIP_CONFIRMED",Vb=(t={})=>{let e=!1,n=Object.entries(t).map(([s,o])=>{let r=typeof o=="string"?o.trim():o;return r!==o&&(e=!0),[s,r]});return{normalizedVals:e?Object.fromEntries(n):t,didChange:e}},jb=t=>!t||!Array.isArray(t.vars)||t.vars.length===0?{found:!1,count:0,vars:[]}:{found:!0,count:typeof t.count=="number"?t.count:t.vars.length,vars:t.vars.map(e=>({key:String(e?.key||"").trim(),status:String(e?.status||"missing").trim()||"missing"})).filter(e=>e.key)},zb=({onComplete:t})=>{let e=Ht.length,n=e+1,{vals:s,setVals:o,setValue:r,step:i,setStep:a,setupError:l,setSetupError:c}=Ib({kSetupStepIndex:e,kPairingStepIndex:n}),[d,u]=y([]),[p,f]=y(!0),[g,m]=y(null),[h,b]=y(!1),[x,v]=y(!1),[w,$]=y(!1),[S,C]=y(null),{codexStatus:_,codexLoading:k,codexManualInput:A,setCodexManualInput:D,codexExchanging:N,codexAuthStarted:U,codexAuthWaiting:O,startCodexAuth:M,completeCodexAuth:R,handleCodexDisconnect:B}=Db({setFormError:C}),[E,G]=y(()=>{let xe=String(s[Hb]||"").trim();return xe===Va?xe:null}),[H,z]=y(null),[te,K]=y(null),[V,Z]=y(!1),[ue,re]=y(null),oe=xe=>{G(xe),o(bt=>({...bt,[Hb]:xe===Va?xe:""}))},ne=()=>{o(xe=>({...xe,[Ld]:null,[Wb]:!1}))};L(()=>{Br().then(xe=>{let bt=Array.isArray(xe.models)?xe.models:[],Pt=Lo(bt);if(u(bt),!s.MODEL_KEY&&bt.length>0){let xt=Pt[0]||bt[0];o(fn=>({...fn,MODEL_KEY:xt.key}))}}).catch(()=>m("Failed to load models")).finally(()=>f(!1))},[]);let me=zs(s.MODEL_KEY),pe=jb(s[Ld]),ce=Lo(d),ge=h?d:ce.length>0?ce:d,j=d.find(xe=>xe.key===s.MODEL_KEY),J=j&&!ge.some(xe=>xe.key===j.key)?[...ge,j]:ge,ie=ce.length>0&&d.length>ce.length,de=xg(me),be=Ro(me),Ve=An[be]||[],tt=me==="openai-codex"?!!_.connected:Ve.some(xe=>!!String(s[xe.key]||"").trim()),kt=Ht.every(xe=>xe.validate(s,{hasAi:tt})),Ot=i===-1,Q=i===e,fe=i===n,se=i>=0&&i{let{normalizedVals:xe,didChange:bt}=Vb(s);if(bt&&o(xe),!Ht.every(Ke=>Ke.validate(xe,{hasAi:tt}))||x)return;let Pt=Object.entries(xe).filter(([Ke])=>Ke!=="MODEL_KEY"&&!String(Ke||"").startsWith("_")).filter(([,Ke])=>Ke).map(([Ke,St])=>({key:Ke,value:St})),xt=(()=>{if(!xe.MODEL_KEY||!String(xe.MODEL_KEY).includes("/"))return"A model selection is required";if(Pt.length>Ob)return`Too many environment variables (max ${Ob})`;for(let Ke of Pt){let St=String(Ke?.key||""),Gt=String(Ke?.value||"");if(!St)return"Each variable must include a key";if(St.length>WS)return`Variable key is too long: ${St.slice(0,32)}...`;if(Gt.length>Bb)return`Value too long for ${St} (max ${Bb} chars)`}return!xe.GITHUB_TOKEN||!zr(xe.GITHUB_WORKSPACE_REPO)?'Target repo must be in "owner/repo" format.':(xe._GITHUB_FLOW||Mn)===Bt&&!zr(xe._GITHUB_SOURCE_REPO)?'Source repo must be in "owner/repo" format.':""})();if(xt){C(xt),c(null),a(Math.max(0,Ht.findIndex(Ke=>Ke.id==="github")));return}a(e),v(!0),C(null),c(null),ea();let fn=(xe._GITHUB_FLOW||Mn)===Bt;try{let Ke=await Om(Pt,xe.MODEL_KEY,{importMode:fn});if(!Ke.ok)throw new Error(Ke.error||"Onboarding failed");let St=Sd(xe);if(!St)throw new Error("No channel credential configured for pairing.");o(Gt=>({...Gt,[Pd]:St})),v(!1),a(n),ea(),c(null)}catch(Ke){console.error("Onboard error:",Ke),c(Ke.message||"Onboarding failed"),v(!1)}},Cr=()=>{localStorage.removeItem(Zr),t()},jc=()=>{Q||(C(null),a(xe=>Math.max(-1,xe-1)))},ta=()=>{v(!1),c(null),a(Ht.length-1)},Kt=async()=>{let{normalizedVals:xe,didChange:bt}=Vb(s);if(bt&&o(xe),!(!se||!se.validate(xe,{hasAi:tt}))){if(C(null),se.id==="github"){let Pt=xe._GITHUB_FLOW||Mn,xt=Pt===Bt?Tn:xe._GITHUB_TARGET_REPO_MODE||Tn,fn=xt===Jn?hd:fd,Ke=Pt===Bt?xe._GITHUB_SOURCE_REPO:xe.GITHUB_WORKSPACE_REPO;$(!0),ne();try{if(Pt===Bt){let Gt=await va(Ke,xe.GITHUB_TOKEN,hd);if(!Gt?.ok){C(Gt?.error||"GitHub source verification failed");return}if(Gt.repoIsEmpty){C("That source repository is empty. Use Start fresh if you want AlphaClaw to bootstrap a new setup there.");return}let vo=await va(xe.GITHUB_WORKSPACE_REPO,xe.GITHUB_TOKEN,fd);if(!vo?.ok){C(vo?.error||"GitHub target verification failed");return}if(xt===Tn&&vo.repoExists){C("That target repository already exists. Choose Use existing empty repo or pick a new target repo name.");return}if(xt===Jn&&!vo.repoExists){C("That target repository does not exist yet. Choose Create new repo or enter an existing empty target repo.");return}if(Gt.tempDir&&!Gt.repoIsEmpty){z(Gt.tempDir),oe(Rd),Z(!0),re(null);try{let Ws=await Bm(Gt.tempDir);if(!Ws?.ok){re(Ws?.error||"Import scan failed"),Z(!1);return}K(Ws)}catch(Ws){re(Ws?.message||"Import scan failed")}finally{Z(!1)}return}}let St=await va(xe.GITHUB_WORKSPACE_REPO,xe.GITHUB_TOKEN,fn);if(!St?.ok){C(St?.error||"GitHub verification failed");return}if(xt===Tn&&St.repoExists){C("That target repository already exists. Choose Use existing empty repo or pick a new target repo name.");return}if(xt===Jn&&!St.repoExists){C("That target repository does not exist yet. Choose Create new repo or enter an existing empty target repo.");return}}catch(St){C(St?.message||"GitHub verification failed");return}finally{$(!1)}}a(Pt=>Math.min(Ht.length-1,Pt+1))}},Vf=async(xe=[])=>{Z(!0),re(null);try{let bt=xe.length===0,Pt=Sg(xe),xt=await Fm({tempDir:H,approvedSecrets:xe,skipSecretExtraction:bt,githubRepo:s.GITHUB_WORKSPACE_REPO,githubToken:s.GITHUB_TOKEN});if(!xt?.ok){re(xt?.error||"Import failed"),Z(!1);return}let fn=jb(xt.placeholderReview);if(o(Ke=>({...Ke,...Pt,...xt.preFill||{},[Ld]:fn,[Wb]:!1})),fn.found){oe(Va);return}ne(),oe(null),a(Ke=>Math.min(Ht.length-1,Ke+1))}catch(bt){re(bt?.message||"Import failed")}finally{Z(!1)}},go=()=>{oe(Fb)},bo=()=>{oe(Rd)},_r=()=>{oe(null),z(null),K(null),re(null),ne()},na=()=>{ne(),oe(null),a(xe=>Math.min(Ht.length-1,xe+1))},fs=xe=>{r("_GITHUB_FLOW",xe),a(0)},xo=E===Rd,Hs=E===Fb,hs=E===Va,qn=Ot?"Getting Started":xo?"Import":Hs?"Review Secrets":hs?"Review Env Vars":Q?"Initializing":fe?"Pairing":se?.title||"Setup",yo=Ot?0:xo||Hs||hs?i+1:Q?Ht.length+1:fe?Ht.length+2:i+1;return{state:{vals:s,step:i,setupError:l,modelsLoading:p,modelsError:g,showAllModels:h,loading:x,githubStepLoading:w,formError:S,importScanResult:te,importScanning:V,importError:ue,selectedProvider:me,modelOptions:J,canToggleFullCatalog:ie,visibleAiFieldKeys:de,hasAi:tt,allValid:kt,isPreStep:Ot,isSetupStep:Q,isPairingStep:fe,activeGroup:se,currentGroupValid:De,selectedPairingChannel:ke,placeholderReview:pe,isImportStep:xo,isSecretReviewStep:Hs,isPlaceholderReviewStep:hs,activeStepLabel:qn,stepNumber:yo,codexStatus:_,codexLoading:k,codexManualInput:A,codexExchanging:N,codexAuthStarted:U,codexAuthWaiting:O,pairingStatusPoll:W,pairingRequestsPoll:ae,pairingChannels:ye,canFinishPairing:ve,pairingError:Ne,pairingComplete:gt},actions:{setVals:o,setValue:r,setShowAllModels:b,setCodexManualInput:D,startCodexAuth:M,completeCodexAuth:R,handleCodexDisconnect:B,handleSubmit:Vc,finishOnboarding:Cr,goBack:jc,goBackFromSetupError:ta,goNext:Kt,handleSelectFlow:fs,handleImportApprove:Vf,handleShowSecretReview:go,handleSecretReviewBack:bo,handleImportBack:_r,handlePlaceholderReviewContinue:na,handlePairingApprove:Hc,handlePairingReject:Wc}}};var Zn=P.bind(T),Ub=({onComplete:t,acVersion:e})=>{let{state:n,actions:s}=zb({onComplete:t});return Zn`
- <${Ag}
+ <${Tg}
groups=${Ht}
step=${n.step}
isPreStep=${n.isPreStep}
@@ -1924,33 +2001,32 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
/>
- ${n.isPreStep?Jn`<${yg} onSelectFlow=${s.handleSelectFlow} />`:n.isImportStep?Jn`<${Sg}
+ ${n.isPreStep?Zn`<${vg} onSelectFlow=${s.handleSelectFlow} />`:n.isImportStep?Zn`<${Cg}
scanResult=${n.importScanResult}
scanning=${n.importScanning}
error=${n.importError}
onApprove=${s.handleImportApprove}
onShowSecretReview=${s.handleShowSecretReview}
onBack=${s.handleImportBack}
- />`:n.isSecretReviewStep?Jn`<${_g}
+ />`:n.isSecretReviewStep?Zn`<${Ag}
secrets=${n.importScanResult?.secrets||[]}
onApprove=${s.handleImportApprove}
onBack=${s.handleSecretReviewBack}
loading=${n.importScanning}
error=${n.importError}
- />`:n.isPlaceholderReviewStep?Jn`<${Cg}
+ />`:n.isPlaceholderReviewStep?Zn`<${_g}
placeholderReview=${n.placeholderReview}
vals=${n.vals}
setValue=${s.setValue}
onContinue=${s.handlePlaceholderReviewContinue}
- />`:n.isSetupStep?Jn`<${Rg}
+ />`:n.isSetupStep?Zn`<${Lg}
error=${n.setupError}
loading=${n.loading}
onRetry=${s.handleSubmit}
onBack=${s.goBackFromSetupError}
- />`:n.isPairingStep?Jn`<${Mb}
+ />`:n.isPairingStep?Zn`<${Pb}
channel=${n.selectedPairingChannel}
pairings=${n.pairingRequestsPoll.data||[]}
- channels=${n.pairingChannels}
loading=${!n.pairingStatusPoll.data}
error=${n.pairingError}
onApprove=${s.handlePairingApprove}
@@ -1958,8 +2034,8 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
canFinish=${n.pairingComplete||n.canFinishPairing}
onContinue=${s.finishOnboarding}
onSkip=${s.finishOnboarding}
- />`:Jn`
- <${_b}
+ />`:Zn`
+ <${Tb}
activeGroup=${n.activeGroup}
vals=${n.vals}
hasAi=${n.hasAi}
@@ -1995,14 +2071,14 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
/>
`}
- ${e?Jn`
+ ${e?Zn`
v${e}
`:null}
- `};var OS=P.bind(T),tn=({onClick:t,disabled:e=!1,loading:n=!1,warning:s=!1,idleLabel:o="Check updates",loadingLabel:r="Checking...",className:i=""})=>OS`
- <${Z}
+ `};var VS=P.bind(T),tn=({onClick:t,disabled:e=!1,loading:n=!1,warning:s=!1,idleLabel:o="Check updates",loadingLabel:r="Checking...",className:i=""})=>VS`
+ <${Y}
onClick=${t}
disabled=${e}
loading=${n}
@@ -2012,7 +2088,7 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
loadingLabel=${r}
className=${i}
/>
-`;var BS=P.bind(T),jb=({visible:t=!1,restarting:e=!1,onRestart:n,onDismiss:s=()=>{}})=>t?BS`
+`;var jS=P.bind(T),Kb=({visible:t=!1,restarting:e=!1,onRestart:n,onDismiss:s=()=>{}})=>t?jS`
@@ -2035,12 +2111,12 @@ import"./chunks/chunk-72ZECFVW.js";var Tr,Se,qf,Pr,hs,Uf,Jf,Zf,Yf,qc,zc,Uc,Xf,oa
aria-label="Dismiss restart banner"
title="Dismiss"
>
- <${nt} className="h-3.5 w-3.5" />
+ <${Ze} className="h-3.5 w-3.5" />
- `:null;var ja="alphaclaw:browse-draft-index-changed",Fo=t=>t||window.localStorage,Ed=t=>`${Fa}${String(t||"").trim()}`,zb=(t,e)=>{try{if(!t)return"";let s=Fo(e).getItem(Ed(t));return typeof s=="string"?s:""}catch{return""}},za=(t,e,n)=>{try{if(!t)return;Fo(n).setItem(Ed(t),String(e||""))}catch{}},xs=(t,e)=>{try{if(!t)return;Fo(e).removeItem(Ed(t))}catch{}},Ub=t=>{try{let n=Fo(t).getItem(Md);if(!n)return new Set;let s=JSON.parse(n);return Array.isArray(s)?new Set(s.map(o=>String(o||"").trim()).filter(Boolean)):new Set}catch{return new Set}},Kb=(t,e={})=>{let{storage:n,dispatchEvent:s}=e;try{let o=Fo(n),r=Array.from(t).sort((i,a)=>i.localeCompare(a));o.setItem(Md,JSON.stringify(r)),s&&s(new CustomEvent(ja,{detail:{paths:r}}))}catch{}},mn=(t,e,n={})=>{let{storage:s,dispatchEvent:o}=n;if(!t)return;let r=String(t||"").trim();if(!r)return;let i=Ub(s);e?i.add(r):i.delete(r),Kb(i,{storage:s,dispatchEvent:o})},Id=t=>{try{let e=Fo(t),n=Ub(e);if(n.size>0)return n;let s=new Set;for(let o=0;o
0&&Kb(s,{storage:e}),s}catch{return new Set}};var FS=new URL("../../shared/browse-file-policies.json",import.meta.url),Yr={protectedPaths:[],lockedPaths:[]};try{let t=await fetch(FS);if(t.ok){let e=await t.json();e&&typeof e=="object"&&(Yr=e)}}catch{}var Ua=new Set(Array.isArray(Yr?.protectedPaths)?Yr.protectedPaths:[]),Zs=new Set(Array.isArray(Yr?.lockedPaths)?Yr.lockedPaths:[]),Ys=t=>String(t||"").replaceAll("\\","/").replace(/^\.\/+/,"").replace(/^\/+/,"").trim().toLowerCase(),Zn=(t,e)=>{let n=String(e||"").trim();if(!n)return!1;for(let s of t)if(n===s||n.endsWith(`/${s}`)||n.startsWith(`${s}/`)||n.includes(`/${s}/`))return!0;return!1};var Gb=t=>{let e=String(t||"").split("/").map(s=>s.trim()).filter(Boolean);if(e.length<=1)return[];let n=[];for(let s=0;s{let e=String(t||"");if(!e)return!1;try{if(navigator?.clipboard?.writeText)return await navigator.clipboard.writeText(e),!0}catch{}let n=null,s=!1;try{return!document?.createElement||!document?.body?.appendChild||!document?.body?.removeChild||typeof document.execCommand!="function"?!1:(n=document.createElement("textarea"),n.value=e,n.setAttribute("readonly",""),n.style.position="fixed",n.style.opacity="0",document.body.appendChild(n),s=!0,n.select(),document.execCommand("copy"))}catch{return!1}finally{n&&s&&document.body.removeChild(n)}};var Ge=P.bind(T),Dd=9,HS=10,qb=14,WS=5e3,VS=()=>{try{let t=window.localStorage.getItem(_d);if(!t)return null;let e=JSON.parse(t);return Array.isArray(e)?new Set(e.map(n=>String(n))):null}catch{return null}},Jb=(t,e)=>{!t||t.type!=="folder"||(t.path&&e.add(t.path),(t.children||[]).forEach(n=>Jb(n,e)))},Nd=(t,e)=>{if(t){if(t.type==="file"){t.path&&e.push(t.path);return}(t.children||[]).forEach(n=>Nd(n,e))}},Od=(t,e)=>{if(!t)return null;let n=String(e||"").trim();if(!n)return t;if(String(t.path||"").trim()===n)return null;if(t.type!=="folder")return t;let o=(t.children||[]).map(r=>Od(r,n)).filter(Boolean);return o.length===(t.children||[]).length?t:{...t,children:o}},Zb=(t,e)=>{if(!t)return null;let n=String(e||"").trim().toLowerCase();if(!n)return t;let s=String(t.name||"").toLowerCase(),o=String(t.path||"").toLowerCase(),r=s.includes(n)||o.includes(n);if(t.type==="file")return r?t:null;let i=(t.children||[]).map(a=>Zb(a,n)).filter(Boolean);return!r&&i.length===0?null:{...t,children:i}},jS=t=>{let n=String(t||"").toLowerCase().replace(/(\.bak)+$/i,"");return n.endsWith(".md")?{icon:Xg,className:"file-icon file-icon-md"}:n.endsWith(".js")||n.endsWith(".mjs")?{icon:eb,className:"file-icon file-icon-js"}:n.endsWith(".json")||n.endsWith(".jsonl")?{icon:Ma,className:"file-icon file-icon-json"}:n.endsWith(".css")||n.endsWith(".scss")?{icon:cb,className:"file-icon file-icon-css"}:/\.(html?)$/i.test(n)?{icon:ab,className:"file-icon file-icon-html"}:/\.(png|jpe?g|gif|webp|svg|bmp|ico|avif)$/i.test(n)?{icon:tb,className:"file-icon file-icon-image"}:/\.(mp3|wav|ogg|oga|m4a|aac|flac|opus|weba)$/i.test(n)?{icon:rb,className:"file-icon file-icon-audio"}:/\.(sh|bash|zsh|command)$/i.test(n)||[".bashrc",".zshrc",".profile",".bash_profile",".zprofile",".zshenv"].includes(n)?{icon:ib,className:"file-icon file-icon-shell"}:/\.(db|sqlite|sqlite3|db3|sdb|sqlitedb|duckdb|mdb|accdb)$/i.test(n)?{icon:lb,className:"file-icon file-icon-db"}:{icon:Qg,className:"file-icon file-icon-generic"}},zS=({x:t,y:e,targetPath:n,targetType:s,isLocked:o,onNewFile:r,onNewFolder:i,onCopyPath:a,onDownload:l,onDelete:c,onClose:d})=>{let u=ee(null);L(()=>{let w=C=>{u.current&&!u.current.contains(C.target)&&d()},$=C=>{C.key==="Escape"&&d()},S=()=>d();return window.addEventListener("mousedown",w),window.addEventListener("keydown",$),window.addEventListener("scroll",S,!0),()=>{window.removeEventListener("mousedown",w),window.removeEventListener("keydown",$),window.removeEventListener("scroll",S,!0)}},[d]);let p=s==="folder",f=s==="file",g=s==="root",m=p?n:"",h=!o&&(p||g),b=!!((p||f)&&n),x=f&&n,v=!o&&(p||f)&&n;return Ge`
+ `:null;var ja="alphaclaw:browse-draft-index-changed",Fo=t=>t||window.localStorage,Ed=t=>`${Fa}${String(t||"").trim()}`,Gb=(t,e)=>{try{if(!t)return"";let s=Fo(e).getItem(Ed(t));return typeof s=="string"?s:""}catch{return""}},za=(t,e,n)=>{try{if(!t)return;Fo(n).setItem(Ed(t),String(e||""))}catch{}},ys=(t,e)=>{try{if(!t)return;Fo(e).removeItem(Ed(t))}catch{}},qb=t=>{try{let n=Fo(t).getItem(Ad);if(!n)return new Set;let s=JSON.parse(n);return Array.isArray(s)?new Set(s.map(o=>String(o||"").trim()).filter(Boolean)):new Set}catch{return new Set}},Jb=(t,e={})=>{let{storage:n,dispatchEvent:s}=e;try{let o=Fo(n),r=Array.from(t).sort((i,a)=>i.localeCompare(a));o.setItem(Ad,JSON.stringify(r)),s&&s(new CustomEvent(ja,{detail:{paths:r}}))}catch{}},mn=(t,e,n={})=>{let{storage:s,dispatchEvent:o}=n;if(!t)return;let r=String(t||"").trim();if(!r)return;let i=qb(s);e?i.add(r):i.delete(r),Jb(i,{storage:s,dispatchEvent:o})},Id=t=>{try{let e=Fo(t),n=qb(e);if(n.size>0)return n;let s=new Set;for(let o=0;o0&&Jb(s,{storage:e}),s}catch{return new Set}};var zS=new URL("../../shared/browse-file-policies.json",import.meta.url),Yr={protectedPaths:[],lockedPaths:[]};try{let t=await fetch(zS);if(t.ok){let e=await t.json();e&&typeof e=="object"&&(Yr=e)}}catch{}var Ua=new Set(Array.isArray(Yr?.protectedPaths)?Yr.protectedPaths:[]),Zs=new Set(Array.isArray(Yr?.lockedPaths)?Yr.lockedPaths:[]),Ys=t=>String(t||"").replaceAll("\\","/").replace(/^\.\/+/,"").replace(/^\/+/,"").trim().toLowerCase(),Yn=(t,e)=>{let n=String(e||"").trim();if(!n)return!1;for(let s of t)if(n===s||n.endsWith(`/${s}`)||n.startsWith(`${s}/`)||n.includes(`/${s}/`))return!0;return!1};var Zb=t=>{let e=String(t||"").split("/").map(s=>s.trim()).filter(Boolean);if(e.length<=1)return[];let n=[];for(let s=0;s{let e=String(t||"");if(!e)return!1;try{if(navigator?.clipboard?.writeText)return await navigator.clipboard.writeText(e),!0}catch{}let n=null,s=!1;try{return!document?.createElement||!document?.body?.appendChild||!document?.body?.removeChild||typeof document.execCommand!="function"?!1:(n=document.createElement("textarea"),n.value=e,n.setAttribute("readonly",""),n.style.position="fixed",n.style.opacity="0",document.body.appendChild(n),s=!0,n.select(),document.execCommand("copy"))}catch{return!1}finally{n&&s&&document.body.removeChild(n)}};var Ge=P.bind(T),Dd=9,US=10,Yb=14,KS=5e3,GS=()=>{try{let t=window.localStorage.getItem(_d);if(!t)return null;let e=JSON.parse(t);return Array.isArray(e)?new Set(e.map(n=>String(n))):null}catch{return null}},Xb=(t,e)=>{!t||t.type!=="folder"||(t.path&&e.add(t.path),(t.children||[]).forEach(n=>Xb(n,e)))},Nd=(t,e)=>{if(t){if(t.type==="file"){t.path&&e.push(t.path);return}(t.children||[]).forEach(n=>Nd(n,e))}},Od=(t,e)=>{if(!t)return null;let n=String(e||"").trim();if(!n)return t;if(String(t.path||"").trim()===n)return null;if(t.type!=="folder")return t;let o=(t.children||[]).map(r=>Od(r,n)).filter(Boolean);return o.length===(t.children||[]).length?t:{...t,children:o}},Qb=(t,e)=>{if(!t)return null;let n=String(e||"").trim().toLowerCase();if(!n)return t;let s=String(t.name||"").toLowerCase(),o=String(t.path||"").toLowerCase(),r=s.includes(n)||o.includes(n);if(t.type==="file")return r?t:null;let i=(t.children||[]).map(a=>Qb(a,n)).filter(Boolean);return!r&&i.length===0?null:{...t,children:i}},qS=t=>{let n=String(t||"").toLowerCase().replace(/(\.bak)+$/i,"");return n.endsWith(".md")?{icon:Qg,className:"file-icon file-icon-md"}:n.endsWith(".js")||n.endsWith(".mjs")?{icon:tb,className:"file-icon file-icon-js"}:n.endsWith(".json")||n.endsWith(".jsonl")?{icon:Aa,className:"file-icon file-icon-json"}:n.endsWith(".css")||n.endsWith(".scss")?{icon:db,className:"file-icon file-icon-css"}:/\.(html?)$/i.test(n)?{icon:lb,className:"file-icon file-icon-html"}:/\.(png|jpe?g|gif|webp|svg|bmp|ico|avif)$/i.test(n)?{icon:nb,className:"file-icon file-icon-image"}:/\.(mp3|wav|ogg|oga|m4a|aac|flac|opus|weba)$/i.test(n)?{icon:ib,className:"file-icon file-icon-audio"}:/\.(sh|bash|zsh|command)$/i.test(n)||[".bashrc",".zshrc",".profile",".bash_profile",".zprofile",".zshenv"].includes(n)?{icon:ab,className:"file-icon file-icon-shell"}:/\.(db|sqlite|sqlite3|db3|sdb|sqlitedb|duckdb|mdb|accdb)$/i.test(n)?{icon:cb,className:"file-icon file-icon-db"}:{icon:eb,className:"file-icon file-icon-generic"}},JS=({x:t,y:e,targetPath:n,targetType:s,isLocked:o,onNewFile:r,onNewFolder:i,onCopyPath:a,onDownload:l,onDelete:c,onClose:d})=>{let u=ee(null);L(()=>{let w=C=>{u.current&&!u.current.contains(C.target)&&d()},$=C=>{C.key==="Escape"&&d()},S=()=>d();return window.addEventListener("mousedown",w),window.addEventListener("keydown",$),window.addEventListener("scroll",S,!0),()=>{window.removeEventListener("mousedown",w),window.removeEventListener("keydown",$),window.removeEventListener("scroll",S,!0)}},[d]);let p=s==="folder",f=s==="file",g=s==="root",m=p?n:"",h=!o&&(p||g),b=!!((p||f)&&n),x=f&&n,v=!o&&(p||f)&&n;return Ge`