From ff42a48b54681f3b647617d4f7153e47e0fdc7b4 Mon Sep 17 00:00:00 2001 From: Yi Wang Date: Mon, 26 Jan 2026 21:59:38 -0500 Subject: [PATCH 001/129] Skip cooldowned providers during model failover (#2143) * feat(agents): skip cooldowned providers during failover When all auth profiles for a provider are in cooldown, the failover mechanism now skips that provider immediately rather than attempting and waiting for the cooldown error. This prevents long delays when multiple OAuth providers fail in sequence. * fix(agents): correct imports and API usage for cooldown check --- src/agents/model-fallback.ts | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/agents/model-fallback.ts b/src/agents/model-fallback.ts index ea338ae60..60827ea00 100644 --- a/src/agents/model-fallback.ts +++ b/src/agents/model-fallback.ts @@ -14,6 +14,9 @@ import { resolveModelRefFromString, } from "./model-selection.js"; import type { FailoverReason } from "./pi-embedded-helpers.js"; +import { isProfileInCooldown } from "./auth-profiles/usage.js"; +import { loadAuthProfileStore } from "./auth-profiles/store.js"; +import { resolveAuthProfileOrder } from "./auth-profiles/order.js"; type ModelCandidate = { provider: string; @@ -211,11 +214,36 @@ export async function runWithModelFallback(params: { model: params.model, fallbacksOverride: params.fallbacksOverride, }); + + const authStore = params.cfg ? loadAuthProfileStore() : null; + const attempts: FallbackAttempt[] = []; let lastError: unknown; for (let i = 0; i < candidates.length; i += 1) { const candidate = candidates[i] as ModelCandidate; + + // Skip candidates that are in cooldown + if (authStore) { + const profileIds = resolveAuthProfileOrder({ + cfg: params.cfg, + store: authStore, + provider: candidate.provider, + }); + const isAnyProfileAvailable = profileIds.some((id) => !isProfileInCooldown(authStore, id)); + + if (profileIds.length > 0 && !isAnyProfileAvailable) { + // All profiles for this provider are in cooldown; skip without attempting + attempts.push({ + provider: candidate.provider, + model: candidate.model, + error: `Provider ${candidate.provider} is in cooldown (all profiles unavailable)`, + reason: "auth", // Best effort classification + }); + continue; + } + } + try { const result = await params.run(candidate.provider, candidate.model); return { From 959ddae6124c93f0f7bb308a4b4e1902981d9069 Mon Sep 17 00:00:00 2001 From: Gustavo Madeira Santana Date: Mon, 26 Jan 2026 22:05:31 -0500 Subject: [PATCH 002/129] Agents: finish cooldowned provider skip (#2534) * Agents: skip cooldowned providers in fallback * fix: skip cooldowned providers during model failover (#2143) (thanks @YiWang24) --- CHANGELOG.md | 1 + src/agents/model-fallback.test.ts | 123 ++++++++++++++++++ src/agents/model-fallback.ts | 20 +-- .../reply/agent-runner-execution.ts | 1 + src/auto-reply/reply/agent-runner-memory.ts | 1 + src/auto-reply/reply/followup-runner.ts | 1 + src/commands/agent.ts | 1 + src/cron/isolated-agent/run.ts | 3 + 8 files changed, 141 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 17bb4477c..0770e0062 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -66,6 +66,7 @@ Status: unreleased. - CLI: avoid loading config for global help/version while registering plugin commands. (#2212) Thanks @dial481. - Agents: include memory.md when bootstrapping memory context. (#2318) Thanks @czekaj. - Agents: release session locks on process termination and cover more signals. (#2483) Thanks @janeexai. +- Agents: skip cooldowned providers during model failover. (#2143) Thanks @YiWang24. - Telegram: harden polling + retry behavior for transient network errors and Node 22 transport issues. (#2420) Thanks @techboss. - Telegram: wrap reasoning italics per line to avoid raw underscores. (#2181) Thanks @YuriNachos. - Telegram: centralize API error logging for delivery and bot calls. (#2492) Thanks @altryne. diff --git a/src/agents/model-fallback.test.ts b/src/agents/model-fallback.test.ts index 8662b0101..73008202d 100644 --- a/src/agents/model-fallback.test.ts +++ b/src/agents/model-fallback.test.ts @@ -1,6 +1,13 @@ +import crypto from "node:crypto"; +import fs from "node:fs/promises"; +import os from "node:os"; +import path from "node:path"; import { describe, expect, it, vi } from "vitest"; import type { ClawdbotConfig } from "../config/config.js"; +import type { AuthProfileStore } from "./auth-profiles.js"; +import { saveAuthProfileStore } from "./auth-profiles.js"; +import { AUTH_STORE_VERSION } from "./auth-profiles/constants.js"; import { runWithModelFallback } from "./model-fallback.js"; function makeCfg(overrides: Partial = {}): ClawdbotConfig { @@ -117,6 +124,122 @@ describe("runWithModelFallback", () => { expect(run.mock.calls[1]?.[1]).toBe("claude-haiku-3-5"); }); + it("skips providers when all profiles are in cooldown", async () => { + const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-auth-")); + const provider = `cooldown-test-${crypto.randomUUID()}`; + const profileId = `${provider}:default`; + + const store: AuthProfileStore = { + version: AUTH_STORE_VERSION, + profiles: { + [profileId]: { + type: "api_key", + provider, + key: "test-key", + }, + }, + usageStats: { + [profileId]: { + cooldownUntil: Date.now() + 60_000, + }, + }, + }; + + saveAuthProfileStore(store, tempDir); + + const cfg = makeCfg({ + agents: { + defaults: { + model: { + primary: `${provider}/m1`, + fallbacks: ["fallback/ok-model"], + }, + }, + }, + }); + const run = vi.fn().mockImplementation(async (providerId, modelId) => { + if (providerId === "fallback") return "ok"; + throw new Error(`unexpected provider: ${providerId}/${modelId}`); + }); + + try { + const result = await runWithModelFallback({ + cfg, + provider, + model: "m1", + agentDir: tempDir, + run, + }); + + expect(result.result).toBe("ok"); + expect(run.mock.calls).toEqual([["fallback", "ok-model"]]); + expect(result.attempts[0]?.reason).toBe("rate_limit"); + } finally { + await fs.rm(tempDir, { recursive: true, force: true }); + } + }); + + it("does not skip when any profile is available", async () => { + const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-auth-")); + const provider = `cooldown-mixed-${crypto.randomUUID()}`; + const profileA = `${provider}:a`; + const profileB = `${provider}:b`; + + const store: AuthProfileStore = { + version: AUTH_STORE_VERSION, + profiles: { + [profileA]: { + type: "api_key", + provider, + key: "key-a", + }, + [profileB]: { + type: "api_key", + provider, + key: "key-b", + }, + }, + usageStats: { + [profileA]: { + cooldownUntil: Date.now() + 60_000, + }, + }, + }; + + saveAuthProfileStore(store, tempDir); + + const cfg = makeCfg({ + agents: { + defaults: { + model: { + primary: `${provider}/m1`, + fallbacks: ["fallback/ok-model"], + }, + }, + }, + }); + const run = vi.fn().mockImplementation(async (providerId) => { + if (providerId === provider) return "ok"; + return "unexpected"; + }); + + try { + const result = await runWithModelFallback({ + cfg, + provider, + model: "m1", + agentDir: tempDir, + run, + }); + + expect(result.result).toBe("ok"); + expect(run.mock.calls).toEqual([[provider, "m1"]]); + expect(result.attempts).toEqual([]); + } finally { + await fs.rm(tempDir, { recursive: true, force: true }); + } + }); + it("does not append configured primary when fallbacksOverride is set", async () => { const cfg = makeCfg({ agents: { diff --git a/src/agents/model-fallback.ts b/src/agents/model-fallback.ts index 60827ea00..074f7df59 100644 --- a/src/agents/model-fallback.ts +++ b/src/agents/model-fallback.ts @@ -14,9 +14,11 @@ import { resolveModelRefFromString, } from "./model-selection.js"; import type { FailoverReason } from "./pi-embedded-helpers.js"; -import { isProfileInCooldown } from "./auth-profiles/usage.js"; -import { loadAuthProfileStore } from "./auth-profiles/store.js"; -import { resolveAuthProfileOrder } from "./auth-profiles/order.js"; +import { + ensureAuthProfileStore, + isProfileInCooldown, + resolveAuthProfileOrder, +} from "./auth-profiles.js"; type ModelCandidate = { provider: string; @@ -192,6 +194,7 @@ export async function runWithModelFallback(params: { cfg: ClawdbotConfig | undefined; provider: string; model: string; + agentDir?: string; /** Optional explicit fallbacks list; when provided (even empty), replaces agents.defaults.model.fallbacks. */ fallbacksOverride?: string[]; run: (provider: string, model: string) => Promise; @@ -214,16 +217,14 @@ export async function runWithModelFallback(params: { model: params.model, fallbacksOverride: params.fallbacksOverride, }); - - const authStore = params.cfg ? loadAuthProfileStore() : null; - + const authStore = params.cfg + ? ensureAuthProfileStore(params.agentDir, { allowKeychainPrompt: false }) + : null; const attempts: FallbackAttempt[] = []; let lastError: unknown; for (let i = 0; i < candidates.length; i += 1) { const candidate = candidates[i] as ModelCandidate; - - // Skip candidates that are in cooldown if (authStore) { const profileIds = resolveAuthProfileOrder({ cfg: params.cfg, @@ -238,12 +239,11 @@ export async function runWithModelFallback(params: { provider: candidate.provider, model: candidate.model, error: `Provider ${candidate.provider} is in cooldown (all profiles unavailable)`, - reason: "auth", // Best effort classification + reason: "rate_limit", }); continue; } } - try { const result = await params.run(candidate.provider, candidate.model); return { diff --git a/src/auto-reply/reply/agent-runner-execution.ts b/src/auto-reply/reply/agent-runner-execution.ts index 3537972e4..7aae24e6a 100644 --- a/src/auto-reply/reply/agent-runner-execution.ts +++ b/src/auto-reply/reply/agent-runner-execution.ts @@ -138,6 +138,7 @@ export async function runAgentTurnWithFallback(params: { cfg: params.followupRun.run.config, provider: params.followupRun.run.provider, model: params.followupRun.run.model, + agentDir: params.followupRun.run.agentDir, fallbacksOverride: resolveAgentModelFallbacksOverride( params.followupRun.run.config, resolveAgentIdFromSessionKey(params.followupRun.run.sessionKey), diff --git a/src/auto-reply/reply/agent-runner-memory.ts b/src/auto-reply/reply/agent-runner-memory.ts index a7d590750..2b2e26b0c 100644 --- a/src/auto-reply/reply/agent-runner-memory.ts +++ b/src/auto-reply/reply/agent-runner-memory.ts @@ -92,6 +92,7 @@ export async function runMemoryFlushIfNeeded(params: { cfg: params.followupRun.run.config, provider: params.followupRun.run.provider, model: params.followupRun.run.model, + agentDir: params.followupRun.run.agentDir, fallbacksOverride: resolveAgentModelFallbacksOverride( params.followupRun.run.config, resolveAgentIdFromSessionKey(params.followupRun.run.sessionKey), diff --git a/src/auto-reply/reply/followup-runner.ts b/src/auto-reply/reply/followup-runner.ts index febbc6e6a..7f5bdde21 100644 --- a/src/auto-reply/reply/followup-runner.ts +++ b/src/auto-reply/reply/followup-runner.ts @@ -129,6 +129,7 @@ export function createFollowupRunner(params: { cfg: queued.run.config, provider: queued.run.provider, model: queued.run.model, + agentDir: queued.run.agentDir, fallbacksOverride: resolveAgentModelFallbacksOverride( queued.run.config, resolveAgentIdFromSessionKey(queued.run.sessionKey), diff --git a/src/commands/agent.ts b/src/commands/agent.ts index ef9718833..d3ee7e783 100644 --- a/src/commands/agent.ts +++ b/src/commands/agent.ts @@ -382,6 +382,7 @@ export async function agentCommand( cfg, provider, model, + agentDir, fallbacksOverride: resolveAgentModelFallbacksOverride(cfg, sessionAgentId), run: (providerOverride, modelOverride) => { if (isCliProvider(providerOverride, cfg)) { diff --git a/src/cron/isolated-agent/run.ts b/src/cron/isolated-agent/run.ts index 2840cb50f..a267c7deb 100644 --- a/src/cron/isolated-agent/run.ts +++ b/src/cron/isolated-agent/run.ts @@ -1,5 +1,6 @@ import { resolveAgentConfig, + resolveAgentDir, resolveAgentModelFallbacksOverride, resolveAgentWorkspaceDir, resolveDefaultAgentId, @@ -128,6 +129,7 @@ export async function runCronIsolatedAgentTurn(params: { }); const workspaceDirRaw = resolveAgentWorkspaceDir(params.cfg, agentId); + const agentDir = resolveAgentDir(params.cfg, agentId); const workspace = await ensureAgentWorkspace({ dir: workspaceDirRaw, ensureBootstrapFiles: !agentCfg?.skipBootstrap, @@ -330,6 +332,7 @@ export async function runCronIsolatedAgentTurn(params: { cfg: cfgWithAgentDefaults, provider, model, + agentDir, fallbacksOverride: resolveAgentModelFallbacksOverride(params.cfg, agentId), run: (providerOverride, modelOverride) => { if (isCliProvider(providerOverride, cfgWithAgentDefaults)) { From b151b8d196c094315d423e4c507c0371e3fa1657 Mon Sep 17 00:00:00 2001 From: Vignesh Date: Mon, 26 Jan 2026 19:20:54 -0800 Subject: [PATCH 003/129] test: stabilize CLI hint assertions under CLAWDBOT_PROFILE (#2507) --- src/agents/clawdbot-gateway-tool.test.ts | 4 +++- src/agents/session-write-lock.test.ts | 2 +- src/cli/gateway-cli.coverage.test.ts | 2 +- .../channels.adds-non-default-telegram-account.test.ts | 2 +- src/commands/daemon-install-helpers.test.ts | 4 +++- src/commands/onboard-hooks.test.ts | 2 +- src/commands/sandbox.test.ts | 2 +- src/commands/status.test.ts | 8 +++++++- src/pairing/pairing-messages.test.ts | 5 ++++- 9 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/agents/clawdbot-gateway-tool.test.ts b/src/agents/clawdbot-gateway-tool.test.ts index b377a53ac..b452e9379 100644 --- a/src/agents/clawdbot-gateway-tool.test.ts +++ b/src/agents/clawdbot-gateway-tool.test.ts @@ -47,7 +47,9 @@ describe("gateway tool", () => { payload?: { kind?: string; doctorHint?: string | null }; }; expect(parsed.payload?.kind).toBe("restart"); - expect(parsed.payload?.doctorHint).toBe("Run: clawdbot doctor --non-interactive"); + expect(parsed.payload?.doctorHint).toBe( + "Run: clawdbot --profile isolated doctor --non-interactive", + ); expect(kill).not.toHaveBeenCalled(); await vi.runAllTimersAsync(); diff --git a/src/agents/session-write-lock.test.ts b/src/agents/session-write-lock.test.ts index 072eca364..524945e19 100644 --- a/src/agents/session-write-lock.test.ts +++ b/src/agents/session-write-lock.test.ts @@ -104,7 +104,7 @@ describe("acquireSessionWriteLock", () => { }); it("cleans up locks on SIGINT without removing other handlers", async () => { const root = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-lock-")); - const originalKill = process.kill.bind(process); + const originalKill = process.kill.bind(process) as typeof process.kill; const killCalls: Array = []; let otherHandlerCalled = false; diff --git a/src/cli/gateway-cli.coverage.test.ts b/src/cli/gateway-cli.coverage.test.ts index 002743170..783a9c86a 100644 --- a/src/cli/gateway-cli.coverage.test.ts +++ b/src/cli/gateway-cli.coverage.test.ts @@ -314,7 +314,7 @@ describe("gateway-cli coverage", () => { expect(startGatewayServer).toHaveBeenCalled(); expect(runtimeErrors.join("\n")).toContain("Gateway failed to start:"); - expect(runtimeErrors.join("\n")).toContain("clawdbot gateway stop"); + expect(runtimeErrors.join("\n")).toContain("gateway stop"); }); it("uses env/config port when --port is omitted", async () => { diff --git a/src/commands/channels.adds-non-default-telegram-account.test.ts b/src/commands/channels.adds-non-default-telegram-account.test.ts index 3b1204c3b..d5241a2fd 100644 --- a/src/commands/channels.adds-non-default-telegram-account.test.ts +++ b/src/commands/channels.adds-non-default-telegram-account.test.ts @@ -370,7 +370,7 @@ describe("channels command", () => { }); expect(lines.join("\n")).toMatch(/Warnings:/); expect(lines.join("\n")).toMatch(/Message Content Intent is disabled/i); - expect(lines.join("\n")).toMatch(/Run: clawdbot doctor/); + expect(lines.join("\n")).toMatch(/Run: clawdbot( --profile isolated)? doctor/); }); it("surfaces Discord permission audit issues in channels status output", () => { diff --git a/src/commands/daemon-install-helpers.test.ts b/src/commands/daemon-install-helpers.test.ts index 8cd819185..e3b873737 100644 --- a/src/commands/daemon-install-helpers.test.ts +++ b/src/commands/daemon-install-helpers.test.ts @@ -234,6 +234,8 @@ describe("buildGatewayInstallPlan", () => { describe("gatewayInstallErrorHint", () => { it("returns platform-specific hints", () => { expect(gatewayInstallErrorHint("win32")).toContain("Run as administrator"); - expect(gatewayInstallErrorHint("linux")).toContain("clawdbot gateway install"); + expect(gatewayInstallErrorHint("linux")).toMatch( + /clawdbot( --profile isolated)? gateway install/, + ); }); }); diff --git a/src/commands/onboard-hooks.test.ts b/src/commands/onboard-hooks.test.ts index c40eeb46b..10c99140a 100644 --- a/src/commands/onboard-hooks.test.ts +++ b/src/commands/onboard-hooks.test.ts @@ -239,7 +239,7 @@ describe("onboard-hooks", () => { // Second note should confirm configuration expect(noteCalls[1][0]).toContain("Enabled 1 hook: session-memory"); - expect(noteCalls[1][0]).toContain("clawdbot hooks list"); + expect(noteCalls[1][0]).toMatch(/clawdbot( --profile isolated)? hooks list/); }); }); }); diff --git a/src/commands/sandbox.test.ts b/src/commands/sandbox.test.ts index 0cb94407e..2b2ada9c3 100644 --- a/src/commands/sandbox.test.ts +++ b/src/commands/sandbox.test.ts @@ -130,7 +130,7 @@ describe("sandboxListCommand", () => { expectLogContains(runtime, "⚠️"); expectLogContains(runtime, "image mismatch"); - expectLogContains(runtime, "clawdbot sandbox recreate --all"); + expectLogContains(runtime, "sandbox recreate --all"); }); it("should display message when no containers found", async () => { diff --git a/src/commands/status.test.ts b/src/commands/status.test.ts index 01babf1cb..2cba37b49 100644 --- a/src/commands/status.test.ts +++ b/src/commands/status.test.ts @@ -312,7 +312,13 @@ describe("statusCommand", () => { expect(logs.some((l) => l.includes("FAQ:"))).toBe(true); expect(logs.some((l) => l.includes("Troubleshooting:"))).toBe(true); expect(logs.some((l) => l.includes("Next steps:"))).toBe(true); - expect(logs.some((l) => l.includes("clawdbot status --all"))).toBe(true); + expect( + logs.some( + (l) => + l.includes("clawdbot status --all") || + l.includes("clawdbot --profile isolated status --all"), + ), + ).toBe(true); }); it("shows gateway auth when reachable", async () => { diff --git a/src/pairing/pairing-messages.test.ts b/src/pairing/pairing-messages.test.ts index 34b620ed0..581d405d3 100644 --- a/src/pairing/pairing-messages.test.ts +++ b/src/pairing/pairing-messages.test.ts @@ -36,7 +36,10 @@ describe("buildPairingReply", () => { const text = buildPairingReply(testCase); expect(text).toContain(testCase.idLine); expect(text).toContain(`Pairing code: ${testCase.code}`); - expect(text).toContain(`clawdbot pairing approve ${testCase.channel} `); + // CLI commands should respect CLAWDBOT_PROFILE when set (most tests run with isolated profile) + expect(text).toContain( + `clawdbot --profile isolated pairing approve ${testCase.channel} `, + ); }); } }); From e7fdccce3905ac592277b1a76fe43040fba25a7e Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Tue, 27 Jan 2026 03:23:42 +0000 Subject: [PATCH 004/129] refactor: route browser control via gateway/node --- CHANGELOG.md | 6 +- README.md | 1 - assets/chrome-extension/options.html | 3 +- docs/cli/browser.md | 22 +- docs/cli/index.md | 3 +- docs/gateway/configuration.md | 7 +- docs/gateway/index.md | 4 +- docs/gateway/multiple-gateways.md | 6 +- docs/gateway/remote.md | 2 +- docs/gateway/security.md | 34 +-- docs/gateway/tailscale.md | 32 +-- docs/help/faq.md | 7 +- docs/tools/browser.md | 161 ++--------- docs/tools/chrome-extension.md | 47 +--- docs/tools/index.md | 9 +- src/agents/clawdbot-tools.ts | 10 +- ...ed-runner.buildembeddedsandboxinfo.test.ts | 4 +- src/agents/pi-embedded-runner/sandbox-info.ts | 5 +- src/agents/pi-embedded-runner/types.ts | 5 +- ...e-aliases-schemas-without-dropping.test.ts | 1 - src/agents/pi-tools.ts | 5 +- src/agents/sandbox/browser.ts | 6 +- src/agents/sandbox/config.ts | 17 -- src/agents/sandbox/context.ts | 3 - src/agents/sandbox/types.ts | 8 +- src/agents/system-prompt.ts | 18 +- src/agents/tools/browser-tool.schema.ts | 3 +- src/agents/tools/browser-tool.test.ts | 36 +-- src/agents/tools/browser-tool.ts | 121 ++------ src/browser/bridge-server.ts | 7 +- src/browser/client-actions-core.ts | 40 ++- src/browser/client-actions-observe.ts | 38 +-- src/browser/client-actions-state.ts | 137 +++++----- src/browser/client-fetch.ts | 147 +++++----- src/browser/client.test.ts | 42 +-- src/browser/client.ts | 107 ++++---- src/browser/config.test.ts | 55 ++-- src/browser/config.ts | 43 +-- src/browser/constants.ts | 1 - src/browser/control-service.ts | 80 ++++++ src/browser/profiles-service.test.ts | 10 +- src/browser/routes/agent.act.ts | 8 +- src/browser/routes/agent.debug.ts | 8 +- src/browser/routes/agent.shared.ts | 13 +- src/browser/routes/agent.snapshot.ts | 8 +- src/browser/routes/agent.storage.ts | 8 +- src/browser/routes/agent.ts | 5 +- src/browser/routes/basic.ts | 6 +- src/browser/routes/dispatcher.ts | 122 +++++++++ src/browser/routes/index.ts | 5 +- src/browser/routes/tabs.ts | 5 +- src/browser/routes/types.ts | 21 ++ src/browser/routes/utils.ts | 7 +- ...-tab-available.prefers-last-target.test.ts | 6 - .../server-context.remote-tab-ops.test.ts | 2 - src/browser/server-context.types.ts | 2 +- ...-contract-form-layout-act-commands.test.ts | 9 +- ....agent-contract-snapshot-endpoints.test.ts | 9 +- ...overs-additional-endpoint-branches.test.ts | 9 +- ...s-open-profile-unknown-returns-404.test.ts | 9 +- ...es-status-starts-browser-requested.test.ts | 9 +- ...fault-maxchars-explicitly-set-zero.test.ts | 11 +- src/browser/server.ts | 22 +- .../register.element.ts | 88 +++--- .../register.files-downloads.ts | 110 +++++--- .../register.form-wait-eval.ts | 43 +-- .../register.navigation.ts | 44 +-- src/cli/browser-cli-actions-input/shared.ts | 25 +- src/cli/browser-cli-actions-observe.ts | 67 +++-- src/cli/browser-cli-debug.ts | 122 ++++++--- src/cli/browser-cli-inspect.ts | 50 ++-- src/cli/browser-cli-manage.ts | 258 +++++++++++++----- src/cli/browser-cli-serve.ts | 121 -------- src/cli/browser-cli-shared.ts | 57 +++- src/cli/browser-cli-state.cookies-storage.ts | 124 +++++---- src/cli/browser-cli-state.ts | 198 +++++++++----- src/cli/browser-cli.ts | 6 +- src/config/schema.ts | 1 - src/config/types.browser.ts | 11 +- src/config/types.sandbox.ts | 15 - src/config/zod-schema.agent-runtime.ts | 3 - src/config/zod-schema.ts | 2 - src/gateway/server-browser.ts | 18 +- src/gateway/server-methods-list.ts | 1 + src/gateway/server-methods.ts | 3 + src/gateway/server-methods/browser.ts | 253 +++++++++++++++++ src/gateway/server.reload.e2e.test.ts | 2 +- src/node-host/runner.ts | 123 +++++---- src/security/audit-extra.ts | 33 +-- src/security/audit.test.ts | 73 +---- src/security/audit.ts | 69 +---- 91 files changed, 1909 insertions(+), 1608 deletions(-) create mode 100644 src/browser/control-service.ts create mode 100644 src/browser/routes/dispatcher.ts create mode 100644 src/browser/routes/types.ts delete mode 100644 src/cli/browser-cli-serve.ts create mode 100644 src/gateway/server-methods/browser.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 0770e0062..e37880ccd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,8 @@ Status: unreleased. - CI: increase Node heap size for macOS checks. (#1890) Thanks @realZachi. - macOS: avoid crash when rendering code blocks by bumping Textual to 0.3.1. (#2033) Thanks @garricn. - Browser: fall back to URL matching for extension relay target resolution. (#1999) Thanks @jonit-dev. +- Browser: route browser control via gateway/node; remove standalone browser control command and control URL config. +- Browser: route `browser.request` via node proxies when available; honor proxy timeouts; derive browser ports from `gateway.port`. - Update: ignore dist/control-ui for dirty checks and restore after ui builds. (#1976) Thanks @Glucksberg. - Telegram: allow caption param for media sends. (#1888) Thanks @mguellsegarra. - Telegram: support plugin sendPayload channelData (media/buttons) and validate plugin commands. (#1917) Thanks @JoshuaLelon. @@ -705,7 +707,7 @@ Thanks @AlexMikhalev, @CoreyH, @John-Rood, @KrauseFx, @MaudeBot, @Nachx639, @Nic ### Highlights - Web search: `web_search`/`web_fetch` tools (Brave API) + first-time setup in onboarding/configure. -- Browser control: Chrome extension relay takeover mode + remote browser control via `clawdbot browser serve`. +- Browser control: Chrome extension relay takeover mode + remote browser control support. - Plugins: channel plugins (gateway HTTP hooks) + Zalo plugin + onboarding install flow. (#854) — thanks @longmaba. - Security: expanded `clawdbot security audit` (+ `--fix`), detect-secrets CI scan, and a `SECURITY.md` reporting policy. @@ -723,7 +725,7 @@ Thanks @AlexMikhalev, @CoreyH, @John-Rood, @KrauseFx, @MaudeBot, @Nachx639, @Nic - Security: add detect-secrets CI scan and baseline guidance. (#227) — thanks @Hyaxia. - Tools: add `web_search`/`web_fetch` (Brave API), auto-enable `web_fetch` for sandboxed sessions, and remove the `brave-search` skill. - CLI/Docs: add a web tools configure section for storing Brave API keys and update onboarding tips. -- Browser: add Chrome extension relay takeover mode (toolbar button), plus `clawdbot browser extension install/path` and remote browser control via `clawdbot browser serve` + `browser.controlToken`. +- Browser: add Chrome extension relay takeover mode (toolbar button), plus `clawdbot browser extension install/path` and remote browser control (standalone server + token auth). ### Fixes - Sessions: refactor session store updates to lock + mutate per-entry, add chat.inject, and harden subagent cleanup flow. (#944) — thanks @tyler6204. diff --git a/README.md b/README.md index db80c6cd0..a3f0b11d1 100644 --- a/README.md +++ b/README.md @@ -384,7 +384,6 @@ Browser control (optional): { browser: { enabled: true, - controlUrl: "http://127.0.0.1:18791", color: "#FF4500" } } diff --git a/assets/chrome-extension/options.html b/assets/chrome-extension/options.html index 4e701826d..f66608f43 100644 --- a/assets/chrome-extension/options.html +++ b/assets/chrome-extension/options.html @@ -168,8 +168,7 @@

Getting started

If you see a red ! badge on the extension icon, the relay server is not reachable. - Start Clawdbot’s browser relay on this machine (Gateway or clawdbot browser serve), - then click the toolbar button again. + Start Clawdbot’s browser relay on this machine (Gateway or node host), then click the toolbar button again.

Full guide (install, remote Gateway, security): docs.clawd.bot/tools/chrome-extension diff --git a/docs/cli/browser.md b/docs/cli/browser.md index 8ba2bc237..6d54b8a10 100644 --- a/docs/cli/browser.md +++ b/docs/cli/browser.md @@ -1,8 +1,8 @@ --- -summary: "CLI reference for `clawdbot browser` (profiles, tabs, actions, extension relay, remote serve)" +summary: "CLI reference for `clawdbot browser` (profiles, tabs, actions, extension relay)" read_when: - You use `clawdbot browser` and want examples for common tasks - - You want to control a remote browser via `browser.controlUrl` + - You want to control a browser running on another machine via a node host - You want to use the Chrome extension relay (attach/detach via toolbar button) --- @@ -16,8 +16,10 @@ Related: ## Common flags -- `--url `: override `browser.controlUrl` for this command invocation. -- `--browser-profile `: choose a browser profile (default comes from config). +- `--url `: Gateway WebSocket URL (defaults to config). +- `--token `: Gateway token (if required). +- `--timeout `: request timeout (ms). +- `--browser-profile `: choose a browser profile (default from config). - `--json`: machine-readable output (where supported). ## Quick start (local) @@ -93,14 +95,10 @@ Then Chrome → `chrome://extensions` → enable “Developer mode” → “Loa Full guide: [Chrome extension](/tools/chrome-extension) -## Remote browser control (`clawdbot browser serve`) +## Remote browser control (node host proxy) -If the Gateway runs on a different machine than the browser, run a standalone browser control server on the machine that runs Chrome: +If the Gateway runs on a different machine than the browser, run a **node host** on the machine that has Chrome/Brave/Edge/Chromium. The Gateway will proxy browser actions to that node (no separate browser control server required). -```bash -clawdbot browser serve --bind 127.0.0.1 --port 18791 --token -``` +Use `gateway.nodes.browser.mode` to control auto-routing and `gateway.nodes.browser.node` to pin a specific node if multiple are connected. -Then point the Gateway at it using `browser.controlUrl` + `browser.controlToken` (or `CLAWDBOT_BROWSER_CONTROL_TOKEN`). - -Security + TLS best-practices: [Browser tool](/tools/browser), [Tailscale](/gateway/tailscale), [Security](/gateway/security) +Security + remote setup: [Browser tool](/tools/browser), [Remote access](/gateway/remote), [Tailscale](/gateway/tailscale), [Security](/gateway/security) diff --git a/docs/cli/index.md b/docs/cli/index.md index c49677cbf..9d809bde5 100644 --- a/docs/cli/index.md +++ b/docs/cli/index.md @@ -859,9 +859,8 @@ Location: Browser control CLI (dedicated Chrome/Brave/Edge/Chromium). See [`clawdbot browser`](/cli/browser) and the [Browser tool](/tools/browser). Common options: -- `--url ` +- `--url`, `--token`, `--timeout`, `--json` - `--browser-profile ` -- `--json` Manage: - `browser status` diff --git a/docs/gateway/configuration.md b/docs/gateway/configuration.md index 9c850e070..3473c1ade 100644 --- a/docs/gateway/configuration.md +++ b/docs/gateway/configuration.md @@ -2759,7 +2759,7 @@ Example: ### `browser` (clawd-managed browser) -Clawdbot can start a **dedicated, isolated** Chrome/Brave/Edge/Chromium instance for clawd and expose a small loopback control server. +Clawdbot can start a **dedicated, isolated** Chrome/Brave/Edge/Chromium instance for clawd and expose a small loopback control service. Profiles can point at a **remote** Chromium-based browser via `profiles..cdpUrl`. Remote profiles are attach-only (start/stop/reset are disabled). @@ -2768,8 +2768,8 @@ scheme/host for profiles that only set `cdpPort`. Defaults: - enabled: `true` -- control URL: `http://127.0.0.1:18791` (CDP uses `18792`) -- CDP URL: `http://127.0.0.1:18792` (control URL + 1, legacy single-profile) +- control service: loopback only (port derived from `gateway.port`, default `18791`) +- CDP URL: `http://127.0.0.1:18792` (control service + 1, legacy single-profile) - profile color: `#FF4500` (lobster-orange) - Note: the control server is started by the running gateway (Clawdbot.app menubar, or `clawdbot gateway`). - Auto-detect order: default browser if Chromium-based; otherwise Chrome → Brave → Edge → Chromium → Chrome Canary. @@ -2778,7 +2778,6 @@ Defaults: { browser: { enabled: true, - controlUrl: "http://127.0.0.1:18791", // cdpUrl: "http://127.0.0.1:18792", // legacy single-profile override defaultProfile: "chrome", profiles: { diff --git a/docs/gateway/index.md b/docs/gateway/index.md index 824984bde..b357d80f2 100644 --- a/docs/gateway/index.md +++ b/docs/gateway/index.md @@ -83,13 +83,13 @@ Defaults (can be overridden via env/flags/config): - `CLAWDBOT_STATE_DIR=~/.clawdbot-dev` - `CLAWDBOT_CONFIG_PATH=~/.clawdbot-dev/clawdbot.json` - `CLAWDBOT_GATEWAY_PORT=19001` (Gateway WS + HTTP) -- `browser.controlUrl=http://127.0.0.1:19003` (derived: `gateway.port+2`) +- browser control service port = `19003` (derived: `gateway.port+2`, loopback only) - `canvasHost.port=19005` (derived: `gateway.port+4`) - `agents.defaults.workspace` default becomes `~/clawd-dev` when you run `setup`/`onboard` under `--dev`. Derived ports (rules of thumb): - Base port = `gateway.port` (or `CLAWDBOT_GATEWAY_PORT` / `--port`) -- `browser.controlUrl port = base + 2` (or `CLAWDBOT_BROWSER_CONTROL_URL` / config override) +- browser control service port = base + 2 (loopback only) - `canvasHost.port = base + 4` (or `CLAWDBOT_CANVAS_HOST_PORT` / config override) - Browser profile CDP ports auto-allocate from `browser.controlPort + 9 .. + 108` (persisted per profile). diff --git a/docs/gateway/multiple-gateways.md b/docs/gateway/multiple-gateways.md index b444290f6..9b5193621 100644 --- a/docs/gateway/multiple-gateways.md +++ b/docs/gateway/multiple-gateways.md @@ -73,7 +73,7 @@ clawdbot --profile rescue gateway install Base port = `gateway.port` (or `CLAWDBOT_GATEWAY_PORT` / `--port`). -- `browser.controlUrl port = base + 2` +- browser control service port = base + 2 (loopback only) - `canvasHost.port = base + 4` - Browser profile CDP ports auto-allocate from `browser.controlPort + 9 .. + 108` @@ -81,8 +81,8 @@ If you override any of these in config or env, you must keep them unique per ins ## Browser/CDP notes (common footgun) -- Do **not** pin `browser.controlUrl` or `browser.cdpUrl` to the same values on multiple instances. -- Each instance needs its own browser control port and CDP range. +- Do **not** pin `browser.cdpUrl` to the same values on multiple instances. +- Each instance needs its own browser control port and CDP range (derived from its gateway port). - If you need explicit CDP ports, set `browser.profiles..cdpPort` per instance. - Remote Chrome: use `browser.profiles..cdpUrl` (per profile, per instance). diff --git a/docs/gateway/remote.md b/docs/gateway/remote.md index aa3fff7f7..13c514845 100644 --- a/docs/gateway/remote.md +++ b/docs/gateway/remote.md @@ -117,6 +117,6 @@ Short version: **keep the Gateway loopback-only** unless you’re sure you need - `gateway.remote.tlsFingerprint` pins the remote TLS cert when using `wss://`. - **Tailscale Serve** can authenticate via identity headers when `gateway.auth.allowTailscale: true`. Set it to `false` if you want tokens/passwords instead. -- Treat `browser.controlUrl` like an admin API: tailnet-only + token auth. +- Treat browser control like operator access: tailnet-only + deliberate node pairing. Deep dive: [Security](/gateway/security). diff --git a/docs/gateway/security.md b/docs/gateway/security.md index 52671d864..ca532aae0 100644 --- a/docs/gateway/security.md +++ b/docs/gateway/security.md @@ -36,7 +36,7 @@ Start with the smallest access that still works, then widen it as you gain confi - **Inbound access** (DM policies, group policies, allowlists): can strangers trigger the bot? - **Tool blast radius** (elevated tools + open rooms): could prompt injection turn into shell/file/network actions? - **Network exposure** (Gateway bind/auth, Tailscale Serve/Funnel). -- **Browser control exposure** (remote controlUrl without token, HTTP, token reuse). +- **Browser control exposure** (remote nodes, relay ports, remote CDP endpoints). - **Local disk hygiene** (permissions, symlinks, config includes, “synced folder” paths). - **Plugins** (extensions exist without an explicit allowlist). - **Model hygiene** (warn when configured models look legacy; not a hard block). @@ -61,7 +61,7 @@ When the audit prints findings, treat this as a priority order: 1. **Anything “open” + tools enabled**: lock down DMs/groups first (pairing/allowlists), then tighten tool policy/sandboxing. 2. **Public network exposure** (LAN bind, Funnel, missing auth): fix immediately. -3. **Browser control remote exposure**: treat it like a remote admin API (token required; HTTPS/tailnet-only). +3. **Browser control remote exposure**: treat it like operator access (tailnet-only, pair nodes deliberately, avoid public exposure). 4. **Permissions**: make sure state/config/credentials/auth are not group/world-readable. 5. **Plugins/extensions**: only load what you explicitly trust. 6. **Model choice**: prefer modern, instruction-hardened models for any bot with tools. @@ -277,7 +277,7 @@ Assume “compromised” means: someone got into a room that can trigger the bot - Lock down inbound surfaces (DM policy, group allowlists, mention gating). 2. **Rotate secrets** - Rotate `gateway.auth` token/password. - - Rotate `browser.controlToken` and `hooks.token` (if used). + - Rotate `hooks.token` (if used) and revoke any suspicious node pairings. - Revoke/rotate model provider credentials (API keys / OAuth). 3. **Review artifacts** - Check Gateway logs and recent sessions/transcripts for unexpected tool calls. @@ -430,26 +430,19 @@ Trusted proxies: See [Tailscale](/gateway/tailscale) and [Web overview](/web). -### 0.6.1) Browser control server over Tailscale (recommended) +### 0.6.1) Browser control via node host (recommended) -If your Gateway is remote but the browser runs on another machine, you’ll often run a **separate browser control server** -on the browser machine (see [Browser tool](/tools/browser)). Treat this like an admin API. +If your Gateway is remote but the browser runs on another machine, run a **node host** +on the browser machine and let the Gateway proxy browser actions (see [Browser tool](/tools/browser)). +Treat node pairing like admin access. Recommended pattern: - -```bash -# on the machine that runs Chrome -clawdbot browser serve --bind 127.0.0.1 --port 18791 --token -tailscale serve https / http://127.0.0.1:18791 -``` - -Then on the Gateway, set: -- `browser.controlUrl` to the `https://…` Serve URL (MagicDNS/ts.net) -- and authenticate with the same token (`CLAWDBOT_BROWSER_CONTROL_TOKEN` env preferred) +- Keep the Gateway and node host on the same tailnet (Tailscale). +- Pair the node intentionally; disable browser proxy routing if you don’t need it. Avoid: -- `--bind 0.0.0.0` (LAN-visible surface) -- Tailscale Funnel for browser control endpoints (public exposure) +- Exposing relay/control ports over LAN or public Internet. +- Tailscale Funnel for browser control endpoints (public exposure). ### 0.7) Secrets on disk (what’s sensitive) @@ -581,9 +574,8 @@ access those accounts and data. Treat browser profiles as **sensitive state**: - Treat browser downloads as untrusted input; prefer an isolated downloads directory. - Disable browser sync/password managers in the agent profile if possible (reduces blast radius). - For remote gateways, assume “browser control” is equivalent to “operator access” to whatever that profile can reach. -- Treat `browser.controlUrl` endpoints as an admin API: tailnet-only + token auth. Prefer Tailscale Serve over LAN binds. -- Keep `browser.controlToken` separate from `gateway.auth.token` (you can reuse it, but that increases blast radius). -- Prefer env vars for the token (`CLAWDBOT_BROWSER_CONTROL_TOKEN`) instead of storing it in config on disk. +- Keep the Gateway and node hosts tailnet-only; avoid exposing relay/control ports to LAN or public Internet. +- Disable browser proxy routing when you don’t need it (`gateway.nodes.browser.mode="off"`). - Chrome extension relay mode is **not** “safer”; it can take over your existing Chrome tabs. Assume it can act as you in whatever that tab/profile can reach. ## Per-agent access profiles (multi-agent) diff --git a/docs/gateway/tailscale.md b/docs/gateway/tailscale.md index e6477fbfc..6b68c0c61 100644 --- a/docs/gateway/tailscale.md +++ b/docs/gateway/tailscale.md @@ -100,35 +100,13 @@ clawdbot gateway --tailscale funnel --auth password - Serve/Funnel only expose the **Gateway control UI + WS**. Nodes connect over the same Gateway WS endpoint, so Serve can work for node access. -## Browser control server (remote Gateway + local browser) +## Browser control (remote Gateway + local browser) -If you run the Gateway on one machine but want to drive a browser on another machine, use a **separate browser control server** -and publish it through Tailscale **Serve** (tailnet-only): +If you run the Gateway on one machine but want to drive a browser on another machine, +run a **node host** on the browser machine and keep both on the same tailnet. +The Gateway will proxy browser actions to the node; no separate control server or Serve URL needed. -```bash -# on the machine that runs Chrome -clawdbot browser serve --bind 127.0.0.1 --port 18791 --token -tailscale serve https / http://127.0.0.1:18791 -``` - -Then point the Gateway config at the HTTPS URL: - -```json5 -{ - browser: { - enabled: true, - controlUrl: "https:///" - } -} -``` - -And authenticate from the Gateway with the same token (prefer env): - -```bash -export CLAWDBOT_BROWSER_CONTROL_TOKEN="" -``` - -Avoid Funnel for browser control endpoints unless you explicitly want public exposure. +Avoid Funnel for browser control; treat node pairing like operator access. ## Tailscale prerequisites + limits diff --git a/docs/help/faq.md b/docs/help/faq.md index 336b324c9..554597165 100644 --- a/docs/help/faq.md +++ b/docs/help/faq.md @@ -1093,9 +1093,10 @@ clawdbot browser extension path Then Chrome → `chrome://extensions` → enable “Developer mode” → “Load unpacked” → pick that folder. -Full guide (including remote Gateway via Tailscale + security notes): [Chrome extension](/tools/chrome-extension) +Full guide (including remote Gateway + security notes): [Chrome extension](/tools/chrome-extension) -If the Gateway runs on the same machine as Chrome (default setup), you usually **do not** need `clawdbot browser serve`. +If the Gateway runs on the same machine as Chrome (default setup), you usually **do not** need anything extra. +If the Gateway runs elsewhere, run a node host on the browser machine so the Gateway can proxy browser actions. You still need to click the extension button on the tab you want to control (it doesn’t auto-attach). ## Sandboxing and memory @@ -1479,7 +1480,7 @@ setup is an always‑on host plus your laptop as a node. - **Safer execution controls.** `system.run` is gated by node allowlists/approvals on that laptop. - **More device tools.** Nodes expose `canvas`, `camera`, and `screen` in addition to `system.run`. - **Local browser automation.** Keep the Gateway on a VPS, but run Chrome locally and relay control - with the Chrome extension + `clawdbot browser serve`. + with the Chrome extension + a node host on the laptop. SSH is fine for ad‑hoc shell access, but nodes are simpler for ongoing agent workflows and device automation. diff --git a/docs/tools/browser.md b/docs/tools/browser.md index 3bf597e33..4b8b7eb00 100644 --- a/docs/tools/browser.md +++ b/docs/tools/browser.md @@ -1,5 +1,5 @@ --- -summary: "Integrated browser control server + action commands" +summary: "Integrated browser control service + action commands" read_when: - Adding agent-controlled browser automation - Debugging why clawd is interfering with your own Chrome @@ -10,7 +10,7 @@ read_when: Clawdbot can run a **dedicated Chrome/Brave/Edge/Chromium profile** that the agent controls. It is isolated from your personal browser and is managed through a small local -control server. +control service inside the Gateway (loopback only). Beginner view: - Think of it as a **separate, agent-only browser**. @@ -57,8 +57,7 @@ Browser settings live in `~/.clawdbot/clawdbot.json`. { browser: { enabled: true, // default: true - controlUrl: "http://127.0.0.1:18791", - cdpUrl: "http://127.0.0.1:18792", // defaults to controlUrl + 1 + // cdpUrl: "http://127.0.0.1:18792", // legacy single-profile override remoteCdpTimeoutMs: 1500, // remote CDP HTTP timeout (ms) remoteCdpHandshakeTimeoutMs: 3000, // remote CDP WebSocket handshake timeout (ms) defaultProfile: "chrome", @@ -77,10 +76,11 @@ Browser settings live in `~/.clawdbot/clawdbot.json`. ``` Notes: -- `controlUrl` defaults to `http://127.0.0.1:18791`. +- The browser control service binds to loopback on a port derived from `gateway.port` + (default: `18791`, which is gateway + 2). The relay uses the next port (`18792`). - If you override the Gateway port (`gateway.port` or `CLAWDBOT_GATEWAY_PORT`), - the default browser ports shift to stay in the same “family” (control = gateway + 2). -- `cdpUrl` defaults to `controlUrl + 1` when unset. + the derived browser ports shift to stay in the same “family”. +- `cdpUrl` defaults to the relay port when unset. - `remoteCdpTimeoutMs` applies to remote (non-loopback) CDP reachability checks. - `remoteCdpHandshakeTimeoutMs` applies to remote CDP WebSocket reachability checks. - `attachOnly: true` means “never launch a local browser; only attach if it is already running.” @@ -126,38 +126,11 @@ clawdbot config set browser.executablePath "/usr/bin/google-chrome" ## Local vs remote control -- **Local control (default):** `controlUrl` is loopback (`127.0.0.1`/`localhost`). - The Gateway starts the control server and can launch a local browser. -- **Remote control:** `controlUrl` is non-loopback. The Gateway **does not** start - a local server; it assumes you are pointing at an existing server elsewhere. +- **Local control (default):** the Gateway starts the loopback control service and can launch a local browser. +- **Remote control (node host):** run a node host on the machine that has the browser; the Gateway proxies browser actions to it. - **Remote CDP:** set `browser.profiles..cdpUrl` (or `browser.cdpUrl`) to attach to a remote Chromium-based browser. In this case, Clawdbot will not launch a local browser. -## Remote browser (control server) - -You can run the **browser control server** on another machine and point your -Gateway at it with a remote `controlUrl`. This lets the agent drive a browser -outside the host (lab box, VM, remote desktop, etc.). - -Key points: -- The **control server** speaks to Chromium-based browsers (Chrome/Brave/Edge/Chromium) via **CDP**. -- The **Gateway** only needs the HTTP control URL. -- Profiles are resolved on the **control server** side. - -Example: -```json5 -{ - browser: { - enabled: true, - controlUrl: "http://10.0.0.42:18791", - defaultProfile: "work" - } -} -``` - -Use `profiles..cdpUrl` for **remote CDP** if you want the Gateway to talk -directly to a Chromium-based browser instance without a remote control server. - Remote CDP URLs can include auth: - Query tokens (e.g., `https://provider.example?token=`) - HTTP Basic auth (e.g., `https://user:pass@provider.example`) @@ -166,11 +139,11 @@ Clawdbot preserves the auth when calling `/json/*` endpoints and when connecting to the CDP WebSocket. Prefer environment variables or secrets managers for tokens instead of committing them to config files. -### Node browser proxy (zero-config default) +## Node browser proxy (zero-config default) If you run a **node host** on the machine that has your browser, Clawdbot can -auto-route browser tool calls to that node without any custom `controlUrl` -setup. This is the default path for remote gateways. +auto-route browser tool calls to that node without any extra browser config. +This is the default path for remote gateways. Notes: - The node host exposes its local browser control server via a **proxy command**. @@ -179,7 +152,7 @@ Notes: - On the node: `nodeHost.browserProxy.enabled=false` - On the gateway: `gateway.nodes.browser.mode="off"` -### Browserless (hosted remote CDP) +## Browserless (hosted remote CDP) [Browserless](https://browserless.io) is a hosted Chromium service that exposes CDP endpoints over HTTPS. You can point a Clawdbot browser profile at a @@ -207,94 +180,16 @@ Notes: - Replace `` with your real Browserless token. - Choose the region endpoint that matches your Browserless account (see their docs). -### Running the control server on the browser machine - -Run a standalone browser control server (recommended when your Gateway is remote): - -```bash -# on the machine that runs Chrome/Brave/Edge -clawdbot browser serve --bind --port 18791 --token -``` - -Then point your Gateway at it: - -```json5 -{ - browser: { - enabled: true, - controlUrl: "http://:18791", - - // Option A (recommended): keep token in env on the Gateway - // (avoid writing secrets into config files) - // controlToken: "" - } -} -``` - -And set the auth token in the Gateway environment: - -```bash -export CLAWDBOT_BROWSER_CONTROL_TOKEN="" -``` - -Option B: store the token in the Gateway config instead (same shared token): - -```json5 -{ - browser: { - enabled: true, - controlUrl: "http://:18791", - controlToken: "" - } -} -``` - ## Security -This section covers the **browser control server** (`browser.controlUrl`) used for agent browser automation. - Key ideas: -- Treat the browser control server like an admin API: **private network only**. -- Use **token auth** always when the server is reachable off-machine. -- Prefer **Tailnet-only** connectivity over LAN exposure. +- Browser control is loopback-only; access flows through the Gateway’s auth or node pairing. +- Keep the Gateway and any node hosts on a private network (Tailscale); avoid public exposure. +- Treat remote CDP URLs/tokens as secrets; prefer env vars or a secrets manager. -### Tokens (what is shared with what?) - -- `browser.controlToken` / `CLAWDBOT_BROWSER_CONTROL_TOKEN` is **only** for authenticating browser control HTTP requests to `browser.controlUrl`. -- It is **not** the Gateway token (`gateway.auth.token`) and **not** a node pairing token. -- You *can* reuse the same string value, but it’s better to keep them separate to reduce blast radius. - -### Binding (don’t expose to your LAN by accident) - -Recommended: -- Keep `clawdbot browser serve` bound to loopback (`127.0.0.1`) and publish it via Tailscale. -- Or bind to a Tailnet IP only (never `0.0.0.0`) and require a token. - -Avoid: -- `--bind 0.0.0.0` (LAN-visible). Even with token auth, traffic is plain HTTP unless you also add TLS. - -### TLS / HTTPS (recommended approach: terminate in front) - -Best practice here: keep `clawdbot browser serve` on HTTP and terminate TLS in front. - -If you’re already using Tailscale, you have two good options: - -1) **Tailnet-only, still HTTP** (transport is encrypted by Tailscale): -- Keep `controlUrl` as `http://…` but ensure it’s only reachable over your tailnet. - -2) **Serve HTTPS via Tailscale** (nice UX: `https://…` URL): - -```bash -# on the browser machine -clawdbot browser serve --bind 127.0.0.1 --port 18791 --token -tailscale serve https / http://127.0.0.1:18791 -``` - -Then set your Gateway config `browser.controlUrl` to the HTTPS URL (MagicDNS/ts.net) and keep using the same token. - -Notes: -- Do **not** use Tailscale Funnel for this unless you explicitly want to make the endpoint public. -- For Tailnet setup/background, see [Gateway web surfaces](/web/index) and the [Gateway CLI](/cli/gateway). +Remote CDP tips: +- Prefer HTTPS endpoints and short-lived tokens where possible. +- Avoid embedding long-lived tokens directly in config files. ## Profiles (multi-browser) @@ -318,13 +213,12 @@ Clawdbot can also drive **your existing Chrome tabs** (no separate “clawd” C Full guide: [Chrome extension](/tools/chrome-extension) Flow: -- You run a **browser control server** (Gateway on the same machine, or `clawdbot browser serve`). +- The Gateway runs locally (same machine) or a node host runs on the browser machine. - A local **relay server** listens at a loopback `cdpUrl` (default: `http://127.0.0.1:18792`). - You click the **Clawdbot Browser Relay** extension icon on a tab to attach (it does not auto-attach). - The agent controls that tab via the normal `browser` tool, by selecting the right profile. -If the Gateway runs on the same machine as Chrome (default setup), you usually **do not** need `clawdbot browser serve`. -Use `browser serve` only when the Gateway runs elsewhere (remote mode). +If the Gateway runs elsewhere, run a node host on the browser machine so the Gateway can proxy browser actions. ### Sandboxed sessions @@ -387,8 +281,7 @@ Platforms: ## Control API (optional) -If you want to integrate directly, the browser control server exposes a small -HTTP API: +For local integrations only, the Gateway exposes a small loopback HTTP API: - Status/start/stop: `GET /`, `POST /start`, `POST /stop` - Tabs: `GET /tabs`, `POST /tabs/open`, `POST /tabs/focus`, `DELETE /tabs/:targetId` @@ -613,7 +506,7 @@ These are useful for “make the site behave like X” workflows: - The clawd browser profile may contain logged-in sessions; treat it as sensitive. - For logins and anti-bot notes (X/Twitter, etc.), see [Browser login + X/Twitter posting](/tools/browser-login). -- Keep control URLs loopback-only unless you intentionally expose the server. +- Keep the Gateway/node host private (loopback or tailnet-only). - Remote CDP endpoints are powerful; tunnel and protect them. ## Troubleshooting @@ -631,12 +524,10 @@ How it maps: - `browser act` uses the snapshot `ref` IDs to click/type/drag/select. - `browser screenshot` captures pixels (full page or element). - `browser` accepts: - - `profile` to choose a named browser profile (host or remote control server). - - `target` (`sandbox` | `host` | `custom`) to select where the browser lives. - - `controlUrl` sets `target: "custom"` implicitly (remote control server). + - `profile` to choose a named browser profile (clawd, chrome, or remote CDP). + - `target` (`sandbox` | `host` | `node`) to select where the browser lives. - In sandboxed sessions, `target: "host"` requires `agents.defaults.sandbox.browser.allowHostControl=true`. - If `target` is omitted: sandboxed sessions default to `sandbox`, non-sandbox sessions default to `host`. - - Sandbox allowlists can restrict `target: "custom"` to specific URLs/hosts/ports. - - Defaults: allowlists unset (no restriction), and sandbox host control is disabled. + - If a browser-capable node is connected, the tool may auto-route to it unless you pin `target="host"` or `target="node"`. This keeps the agent deterministic and avoids brittle selectors. diff --git a/docs/tools/chrome-extension.md b/docs/tools/chrome-extension.md index 1b1d0e9e0..afb70856b 100644 --- a/docs/tools/chrome-extension.md +++ b/docs/tools/chrome-extension.md @@ -15,7 +15,7 @@ Attach/detach happens via a **single Chrome toolbar button**. ## What it is (concept) There are three parts: -- **Browser control server** (HTTP): the API the agent/tool calls (`browser.controlUrl`) +- **Browser control service** (Gateway or node): the API the agent/tool calls (via the Gateway) - **Local relay server** (loopback CDP): bridges between the control server and the extension (`http://127.0.0.1:18792` by default) - **Chrome MV3 extension**: attaches to the active tab using `chrome.debugger` and pipes CDP messages to the relay @@ -87,23 +87,22 @@ clawdbot browser create-profile \ - `!`: relay not reachable (most common: browser relay server isn’t running on this machine). If you see `!`: -- Make sure the Gateway is running locally (default setup), or run `clawdbot browser serve` on this machine (remote gateway setup). +- Make sure the Gateway is running locally (default setup), or run a node host on this machine if the Gateway runs elsewhere. - Open the extension Options page; it shows whether the relay is reachable. -## Do I need `clawdbot browser serve`? +## Remote Gateway (use a node host) -### Local Gateway (same machine as Chrome) — usually **no** +### Local Gateway (same machine as Chrome) — usually **no extra steps** -If the Gateway is running on the same machine as Chrome and your `browser.controlUrl` is loopback (default), -you typically **do not** need `clawdbot browser serve`. +If the Gateway runs on the same machine as Chrome, it starts the browser control service on loopback +and auto-starts the relay server. The extension talks to the local relay; the CLI/tool calls go to the Gateway. -The Gateway’s built-in browser control server will start on `http://127.0.0.1:18791/` and Clawdbot will -auto-start the local relay server on `http://127.0.0.1:18792/`. +### Remote Gateway (Gateway runs elsewhere) — **run a node host** -### Remote Gateway (Gateway runs elsewhere) — **yes** +If your Gateway runs on another machine, start a node host on the machine that runs Chrome. +The Gateway will proxy browser actions to that node; the extension + relay stay local to the browser machine. -If your Gateway runs on another machine, run `clawdbot browser serve` on the machine that runs Chrome -(and publish it via Tailscale Serve / TLS). See the section below. +If multiple nodes are connected, pin one with `gateway.nodes.browser.node` or set `gateway.nodes.browser.mode`. ## Sandboxing (tool containers) @@ -134,26 +133,10 @@ Then ensure the tool isn’t denied by tool policy, and (if needed) call `browse Debugging: `clawdbot sandbox explain` -## Remote Gateway (recommended: Tailscale Serve) +## Remote access tips -Goal: Gateway runs on one machine, but Chrome runs somewhere else. - -On the **browser machine**: - -```bash -clawdbot browser serve --bind 127.0.0.1 --port 18791 --token -tailscale serve https / http://127.0.0.1:18791 -``` - -On the **Gateway machine**: -- Set `browser.controlUrl` to the HTTPS Serve URL (MagicDNS/ts.net). -- Provide the token (prefer env): - -```bash -export CLAWDBOT_BROWSER_CONTROL_TOKEN="" -``` - -Then the agent can drive the browser by calling the remote `browser.controlUrl` API, while the extension + relay stay local on the browser machine. +- Keep the Gateway and node host on the same tailnet; avoid exposing relay ports to LAN or public Internet. +- Pair nodes intentionally; disable browser proxy routing if you don’t want remote control (`gateway.nodes.browser.mode="off"`). ## How “extension path” works @@ -176,8 +159,8 @@ This is powerful and risky. Treat it like giving the model “hands on your brow Recommendations: - Prefer a dedicated Chrome profile (separate from your personal browsing) for extension relay usage. -- Keep the browser control server tailnet-only (Tailscale) and require a token. -- Avoid exposing browser control over LAN (`0.0.0.0`) and avoid Funnel (public). +- Keep the Gateway and any node hosts tailnet-only; rely on Gateway auth + node pairing. +- Avoid exposing relay ports over LAN (`0.0.0.0`) and avoid Funnel (public). Related: - Browser tool overview: [Browser](/tools/browser) diff --git a/docs/tools/index.md b/docs/tools/index.md index 7d9b3f581..3ada44edd 100644 --- a/docs/tools/index.md +++ b/docs/tools/index.md @@ -249,16 +249,17 @@ Profile management: - `reset-profile` — kill orphan process on profile's port (local only) Common parameters: -- `controlUrl` (defaults from config) - `profile` (optional; defaults to `browser.defaultProfile`) +- `target` (`sandbox` | `host` | `node`) +- `node` (optional; picks a specific node id/name) Notes: - Requires `browser.enabled=true` (default is `true`; set `false` to disable). -- Uses `browser.controlUrl` unless `controlUrl` is passed explicitly. - All actions accept optional `profile` parameter for multi-instance support. - When `profile` is omitted, uses `browser.defaultProfile` (defaults to "chrome"). - Profile names: lowercase alphanumeric + hyphens only (max 64 chars). - Port range: 18800-18899 (~100 profiles max). - Remote profiles are attach-only (no start/stop/reset). +- If a browser-capable node is connected, the tool may auto-route to it (unless you pin `target`). - `snapshot` defaults to `ai` when Playwright is installed; use `aria` for the accessibility tree. - `snapshot` also supports role-snapshot options (`interactive`, `compact`, `depth`, `selector`) which return refs like `e12`. - `act` requires `ref` from `snapshot` (numeric `12` from AI snapshots, or `e12` from role snapshots); use `evaluate` for rare CSS selector needs. @@ -410,7 +411,9 @@ Gateway-backed tools (`canvas`, `nodes`, `cron`): - `timeoutMs` Browser tool: -- `controlUrl` (defaults from config) +- `profile` (optional; defaults to `browser.defaultProfile`) +- `target` (`sandbox` | `host` | `node`) +- `node` (optional; pin a specific node id/name) ## Recommended agent flows diff --git a/src/agents/clawdbot-tools.ts b/src/agents/clawdbot-tools.ts index b420cad6f..995925cfe 100644 --- a/src/agents/clawdbot-tools.ts +++ b/src/agents/clawdbot-tools.ts @@ -20,11 +20,8 @@ import { createWebFetchTool, createWebSearchTool } from "./tools/web-tools.js"; import { createTtsTool } from "./tools/tts-tool.js"; export function createClawdbotTools(options?: { - browserControlUrl?: string; + sandboxBrowserBridgeUrl?: string; allowHostBrowserControl?: boolean; - allowedControlUrls?: string[]; - allowedControlHosts?: string[]; - allowedControlPorts?: number[]; agentSessionKey?: string; agentChannel?: GatewayMessageChannel; agentAccountId?: string; @@ -75,11 +72,8 @@ export function createClawdbotTools(options?: { }); const tools: AnyAgentTool[] = [ createBrowserTool({ - defaultControlUrl: options?.browserControlUrl, + sandboxBridgeUrl: options?.sandboxBrowserBridgeUrl, allowHostControl: options?.allowHostBrowserControl, - allowedControlUrls: options?.allowedControlUrls, - allowedControlHosts: options?.allowedControlHosts, - allowedControlPorts: options?.allowedControlPorts, }), createCanvasTool(), createNodesTool({ diff --git a/src/agents/pi-embedded-runner.buildembeddedsandboxinfo.test.ts b/src/agents/pi-embedded-runner.buildembeddedsandboxinfo.test.ts index 6602a8c20..325fef691 100644 --- a/src/agents/pi-embedded-runner.buildembeddedsandboxinfo.test.ts +++ b/src/agents/pi-embedded-runner.buildembeddedsandboxinfo.test.ts @@ -127,7 +127,7 @@ describe("buildEmbeddedSandboxInfo", () => { }, browserAllowHostControl: true, browser: { - controlUrl: "http://localhost:9222", + bridgeUrl: "http://localhost:9222", noVncUrl: "http://localhost:6080", containerName: "clawdbot-sbx-browser-test", }, @@ -138,7 +138,7 @@ describe("buildEmbeddedSandboxInfo", () => { workspaceDir: "/tmp/clawdbot-sandbox", workspaceAccess: "none", agentWorkspaceMount: undefined, - browserControlUrl: "http://localhost:9222", + browserBridgeUrl: "http://localhost:9222", browserNoVncUrl: "http://localhost:6080", hostBrowserAllowed: true, }); diff --git a/src/agents/pi-embedded-runner/sandbox-info.ts b/src/agents/pi-embedded-runner/sandbox-info.ts index 1ffc76f0c..a72797c9c 100644 --- a/src/agents/pi-embedded-runner/sandbox-info.ts +++ b/src/agents/pi-embedded-runner/sandbox-info.ts @@ -13,12 +13,9 @@ export function buildEmbeddedSandboxInfo( workspaceDir: sandbox.workspaceDir, workspaceAccess: sandbox.workspaceAccess, agentWorkspaceMount: sandbox.workspaceAccess === "ro" ? "/agent" : undefined, - browserControlUrl: sandbox.browser?.controlUrl, + browserBridgeUrl: sandbox.browser?.bridgeUrl, browserNoVncUrl: sandbox.browser?.noVncUrl, hostBrowserAllowed: sandbox.browserAllowHostControl, - allowedControlUrls: sandbox.browserAllowedControlUrls, - allowedControlHosts: sandbox.browserAllowedControlHosts, - allowedControlPorts: sandbox.browserAllowedControlPorts, ...(elevatedAllowed ? { elevated: { diff --git a/src/agents/pi-embedded-runner/types.ts b/src/agents/pi-embedded-runner/types.ts index 6a1ee1128..4be395bce 100644 --- a/src/agents/pi-embedded-runner/types.ts +++ b/src/agents/pi-embedded-runner/types.ts @@ -69,12 +69,9 @@ export type EmbeddedSandboxInfo = { workspaceDir?: string; workspaceAccess?: "none" | "ro" | "rw"; agentWorkspaceMount?: string; - browserControlUrl?: string; + browserBridgeUrl?: string; browserNoVncUrl?: string; hostBrowserAllowed?: boolean; - allowedControlUrls?: string[]; - allowedControlHosts?: string[]; - allowedControlPorts?: number[]; elevated?: { allowed: boolean; defaultLevel: "on" | "off" | "ask" | "full"; diff --git a/src/agents/pi-tools.create-clawdbot-coding-tools.adds-claude-style-aliases-schemas-without-dropping.test.ts b/src/agents/pi-tools.create-clawdbot-coding-tools.adds-claude-style-aliases-schemas-without-dropping.test.ts index 221222338..329f58c72 100644 --- a/src/agents/pi-tools.create-clawdbot-coding-tools.adds-claude-style-aliases-schemas-without-dropping.test.ts +++ b/src/agents/pi-tools.create-clawdbot-coding-tools.adds-claude-style-aliases-schemas-without-dropping.test.ts @@ -96,7 +96,6 @@ describe("createClawdbotCodingTools", () => { }; expect(parameters.properties?.action).toBeDefined(); expect(parameters.properties?.target).toBeDefined(); - expect(parameters.properties?.controlUrl).toBeDefined(); expect(parameters.properties?.targetUrl).toBeDefined(); expect(parameters.properties?.request).toBeDefined(); expect(parameters.required ?? []).toContain("action"); diff --git a/src/agents/pi-tools.ts b/src/agents/pi-tools.ts index 4a0bebed0..87dd0919d 100644 --- a/src/agents/pi-tools.ts +++ b/src/agents/pi-tools.ts @@ -294,11 +294,8 @@ export function createClawdbotCodingTools(options?: { // Channel docking: include channel-defined agent tools (login, etc.). ...listChannelAgentTools({ cfg: options?.config }), ...createClawdbotTools({ - browserControlUrl: sandbox?.browser?.controlUrl, + sandboxBrowserBridgeUrl: sandbox?.browser?.bridgeUrl, allowHostBrowserControl: sandbox ? sandbox.browserAllowHostControl : true, - allowedControlUrls: sandbox?.browserAllowedControlUrls, - allowedControlHosts: sandbox?.browserAllowedControlHosts, - allowedControlPorts: sandbox?.browserAllowedControlPorts, agentSessionKey: options?.sessionKey, agentChannel: resolveGatewayMessageChannel(options?.messageProvider), agentAccountId: options?.agentAccountId, diff --git a/src/agents/sandbox/browser.ts b/src/agents/sandbox/browser.ts index dcfde8975..cf552e157 100644 --- a/src/agents/sandbox/browser.ts +++ b/src/agents/sandbox/browser.ts @@ -40,13 +40,9 @@ function buildSandboxBrowserResolvedConfig(params: { cdpPort: number; headless: boolean; }): ResolvedBrowserConfig { - const controlHost = "127.0.0.1"; - const controlUrl = `http://${controlHost}:${params.controlPort}`; const cdpHost = "127.0.0.1"; return { enabled: true, - controlUrl, - controlHost, controlPort: params.controlPort, cdpProtocol: "http", cdpHost, @@ -204,7 +200,7 @@ export async function ensureSandboxBrowser(params: { : undefined; return { - controlUrl: resolvedBridge.baseUrl, + bridgeUrl: resolvedBridge.baseUrl, noVncUrl, containerName, }; diff --git a/src/agents/sandbox/config.ts b/src/agents/sandbox/config.ts index a633a0fd9..cabf907bc 100644 --- a/src/agents/sandbox/config.ts +++ b/src/agents/sandbox/config.ts @@ -86,11 +86,6 @@ export function resolveSandboxBrowserConfig(params: { }): SandboxBrowserConfig { const agentBrowser = params.scope === "shared" ? undefined : params.agentBrowser; const globalBrowser = params.globalBrowser; - const allowedControlUrls = agentBrowser?.allowedControlUrls ?? globalBrowser?.allowedControlUrls; - const allowedControlHosts = - agentBrowser?.allowedControlHosts ?? globalBrowser?.allowedControlHosts; - const allowedControlPorts = - agentBrowser?.allowedControlPorts ?? globalBrowser?.allowedControlPorts; return { enabled: agentBrowser?.enabled ?? globalBrowser?.enabled ?? false, image: agentBrowser?.image ?? globalBrowser?.image ?? DEFAULT_SANDBOX_BROWSER_IMAGE, @@ -105,18 +100,6 @@ export function resolveSandboxBrowserConfig(params: { headless: agentBrowser?.headless ?? globalBrowser?.headless ?? false, enableNoVnc: agentBrowser?.enableNoVnc ?? globalBrowser?.enableNoVnc ?? true, allowHostControl: agentBrowser?.allowHostControl ?? globalBrowser?.allowHostControl ?? false, - allowedControlUrls: - Array.isArray(allowedControlUrls) && allowedControlUrls.length > 0 - ? allowedControlUrls - : undefined, - allowedControlHosts: - Array.isArray(allowedControlHosts) && allowedControlHosts.length > 0 - ? allowedControlHosts - : undefined, - allowedControlPorts: - Array.isArray(allowedControlPorts) && allowedControlPorts.length > 0 - ? allowedControlPorts - : undefined, autoStart: agentBrowser?.autoStart ?? globalBrowser?.autoStart ?? true, autoStartTimeoutMs: agentBrowser?.autoStartTimeoutMs ?? diff --git a/src/agents/sandbox/context.ts b/src/agents/sandbox/context.ts index ff6372e69..8e0c004b5 100644 --- a/src/agents/sandbox/context.ts +++ b/src/agents/sandbox/context.ts @@ -87,9 +87,6 @@ export async function resolveSandboxContext(params: { docker: cfg.docker, tools: cfg.tools, browserAllowHostControl: cfg.browser.allowHostControl, - browserAllowedControlUrls: cfg.browser.allowedControlUrls, - browserAllowedControlHosts: cfg.browser.allowedControlHosts, - browserAllowedControlPorts: cfg.browser.allowedControlPorts, browser: browser ?? undefined, }; } diff --git a/src/agents/sandbox/types.ts b/src/agents/sandbox/types.ts index 03b7713ce..f27dfd715 100644 --- a/src/agents/sandbox/types.ts +++ b/src/agents/sandbox/types.ts @@ -37,9 +37,6 @@ export type SandboxBrowserConfig = { headless: boolean; enableNoVnc: boolean; allowHostControl: boolean; - allowedControlUrls?: string[]; - allowedControlHosts?: string[]; - allowedControlPorts?: number[]; autoStart: boolean; autoStartTimeoutMs: number; }; @@ -63,7 +60,7 @@ export type SandboxConfig = { }; export type SandboxBrowserContext = { - controlUrl: string; + bridgeUrl: string; noVncUrl?: string; containerName: string; }; @@ -79,9 +76,6 @@ export type SandboxContext = { docker: SandboxDockerConfig; tools: SandboxToolPolicy; browserAllowHostControl: boolean; - browserAllowedControlUrls?: string[]; - browserAllowedControlHosts?: string[]; - browserAllowedControlPorts?: number[]; browser?: SandboxBrowserContext; }; diff --git a/src/agents/system-prompt.ts b/src/agents/system-prompt.ts index 41ec9a7d5..1d1a6a5eb 100644 --- a/src/agents/system-prompt.ts +++ b/src/agents/system-prompt.ts @@ -165,12 +165,9 @@ export function buildAgentSystemPrompt(params: { workspaceDir?: string; workspaceAccess?: "none" | "ro" | "rw"; agentWorkspaceMount?: string; - browserControlUrl?: string; + browserBridgeUrl?: string; browserNoVncUrl?: string; hostBrowserAllowed?: boolean; - allowedControlUrls?: string[]; - allowedControlHosts?: string[]; - allowedControlPorts?: number[]; elevated?: { allowed: boolean; defaultLevel: "on" | "off" | "ask" | "full"; @@ -419,9 +416,7 @@ export function buildAgentSystemPrompt(params: { : "" }` : "", - params.sandboxInfo.browserControlUrl - ? `Sandbox browser control URL: ${params.sandboxInfo.browserControlUrl}` - : "", + params.sandboxInfo.browserBridgeUrl ? "Sandbox browser: enabled." : "", params.sandboxInfo.browserNoVncUrl ? `Sandbox browser observer (noVNC): ${params.sandboxInfo.browserNoVncUrl}` : "", @@ -430,15 +425,6 @@ export function buildAgentSystemPrompt(params: { : params.sandboxInfo.hostBrowserAllowed === false ? "Host browser control: blocked." : "", - params.sandboxInfo.allowedControlUrls?.length - ? `Browser control URL allowlist: ${params.sandboxInfo.allowedControlUrls.join(", ")}` - : "", - params.sandboxInfo.allowedControlHosts?.length - ? `Browser control host allowlist: ${params.sandboxInfo.allowedControlHosts.join(", ")}` - : "", - params.sandboxInfo.allowedControlPorts?.length - ? `Browser control port allowlist: ${params.sandboxInfo.allowedControlPorts.join(", ")}` - : "", params.sandboxInfo.elevated?.allowed ? "Elevated exec is available for this session." : "", diff --git a/src/agents/tools/browser-tool.schema.ts b/src/agents/tools/browser-tool.schema.ts index 5861f7de4..30cf3cc0f 100644 --- a/src/agents/tools/browser-tool.schema.ts +++ b/src/agents/tools/browser-tool.schema.ts @@ -35,7 +35,7 @@ const BROWSER_TOOL_ACTIONS = [ "act", ] as const; -const BROWSER_TARGETS = ["sandbox", "host", "custom", "node"] as const; +const BROWSER_TARGETS = ["sandbox", "host", "node"] as const; const BROWSER_SNAPSHOT_FORMATS = ["aria", "ai"] as const; const BROWSER_SNAPSHOT_MODES = ["efficient"] as const; @@ -86,7 +86,6 @@ export const BrowserToolSchema = Type.Object({ target: optionalStringEnum(BROWSER_TARGETS), node: Type.Optional(Type.String()), profile: Type.Optional(Type.String()), - controlUrl: Type.Optional(Type.String()), targetUrl: Type.Optional(Type.String()), targetId: Type.Optional(Type.String()), limit: Type.Optional(Type.Number()), diff --git a/src/agents/tools/browser-tool.test.ts b/src/agents/tools/browser-tool.test.ts index e50082d66..7248a7a2f 100644 --- a/src/agents/tools/browser-tool.test.ts +++ b/src/agents/tools/browser-tool.test.ts @@ -28,23 +28,7 @@ vi.mock("../../browser/client.js", () => browserClientMocks); const browserConfigMocks = vi.hoisted(() => ({ resolveBrowserConfig: vi.fn(() => ({ enabled: true, - controlUrl: "http://127.0.0.1:18791", - controlHost: "127.0.0.1", controlPort: 18791, - cdpProtocol: "http", - cdpHost: "127.0.0.1", - cdpIsLoopback: true, - color: "#FF0000", - headless: true, - noSandbox: false, - attachOnly: false, - defaultProfile: "clawd", - profiles: { - clawd: { - cdpPort: 18792, - color: "#FF0000", - }, - }, })), })); vi.mock("../../browser/config.js", () => browserConfigMocks); @@ -99,7 +83,7 @@ describe("browser tool snapshot maxChars", () => { await tool.execute?.(null, { action: "snapshot", snapshotFormat: "ai" }); expect(browserClientMocks.browserSnapshot).toHaveBeenCalledWith( - "http://127.0.0.1:18791", + undefined, expect.objectContaining({ format: "ai", maxChars: DEFAULT_AI_SNAPSHOT_MAX_CHARS, @@ -117,7 +101,7 @@ describe("browser tool snapshot maxChars", () => { }); expect(browserClientMocks.browserSnapshot).toHaveBeenCalledWith( - "http://127.0.0.1:18791", + undefined, expect.objectContaining({ maxChars: override, }), @@ -141,7 +125,7 @@ describe("browser tool snapshot maxChars", () => { const tool = createBrowserTool(); await tool.execute?.(null, { action: "profiles" }); - expect(browserClientMocks.browserProfiles).toHaveBeenCalledWith("http://127.0.0.1:18791"); + expect(browserClientMocks.browserProfiles).toHaveBeenCalledWith(undefined); }); it("passes refs mode through to browser snapshot", async () => { @@ -149,7 +133,7 @@ describe("browser tool snapshot maxChars", () => { await tool.execute?.(null, { action: "snapshot", snapshotFormat: "ai", refs: "aria" }); expect(browserClientMocks.browserSnapshot).toHaveBeenCalledWith( - "http://127.0.0.1:18791", + undefined, expect.objectContaining({ format: "ai", refs: "aria", @@ -165,7 +149,7 @@ describe("browser tool snapshot maxChars", () => { await tool.execute?.(null, { action: "snapshot", snapshotFormat: "ai" }); expect(browserClientMocks.browserSnapshot).toHaveBeenCalledWith( - "http://127.0.0.1:18791", + undefined, expect.objectContaining({ mode: "efficient", }), @@ -185,11 +169,11 @@ describe("browser tool snapshot maxChars", () => { }); it("defaults to host when using profile=chrome (even in sandboxed sessions)", async () => { - const tool = createBrowserTool({ defaultControlUrl: "http://127.0.0.1:9999" }); + const tool = createBrowserTool({ sandboxBridgeUrl: "http://127.0.0.1:9999" }); await tool.execute?.(null, { action: "snapshot", profile: "chrome", snapshotFormat: "ai" }); expect(browserClientMocks.browserSnapshot).toHaveBeenCalledWith( - "http://127.0.0.1:18791", + undefined, expect.objectContaining({ profile: "chrome", }), @@ -220,7 +204,7 @@ describe("browser tool snapshot maxChars", () => { expect(browserClientMocks.browserStatus).not.toHaveBeenCalled(); }); - it("keeps sandbox control url when node proxy is available", async () => { + it("keeps sandbox bridge url when node proxy is available", async () => { nodesUtilsMocks.listNodes.mockResolvedValue([ { nodeId: "node-1", @@ -230,7 +214,7 @@ describe("browser tool snapshot maxChars", () => { commands: ["browser.proxy"], }, ]); - const tool = createBrowserTool({ defaultControlUrl: "http://127.0.0.1:9999" }); + const tool = createBrowserTool({ sandboxBridgeUrl: "http://127.0.0.1:9999" }); await tool.execute?.(null, { action: "status" }); expect(browserClientMocks.browserStatus).toHaveBeenCalledWith( @@ -254,7 +238,7 @@ describe("browser tool snapshot maxChars", () => { await tool.execute?.(null, { action: "status", profile: "chrome" }); expect(browserClientMocks.browserStatus).toHaveBeenCalledWith( - "http://127.0.0.1:18791", + undefined, expect.objectContaining({ profile: "chrome" }), ); expect(gatewayMocks.callGatewayTool).not.toHaveBeenCalled(); diff --git a/src/agents/tools/browser-tool.ts b/src/agents/tools/browser-tool.ts index 998059b54..1f063bdea 100644 --- a/src/agents/tools/browser-tool.ts +++ b/src/agents/tools/browser-tool.ts @@ -55,9 +55,8 @@ function isBrowserNode(node: NodeListNode) { async function resolveBrowserNodeTarget(params: { requestedNode?: string; - target?: "sandbox" | "host" | "custom" | "node"; - controlUrl?: string; - defaultControlUrl?: string; + target?: "sandbox" | "host" | "node"; + sandboxBridgeUrl?: string; }): Promise { const cfg = loadConfig(); const policy = cfg.gateway?.nodes?.browser; @@ -68,10 +67,9 @@ async function resolveBrowserNodeTarget(params: { } return null; } - if (params.defaultControlUrl?.trim() && params.target !== "node" && !params.requestedNode) { + if (params.sandboxBridgeUrl?.trim() && params.target !== "node" && !params.requestedNode) { return null; } - if (params.controlUrl?.trim()) return null; if (params.target && params.target !== "node") return null; if (mode === "manual" && params.target !== "node" && !params.requestedNode) { return null; @@ -187,70 +185,22 @@ function applyProxyPaths(result: unknown, mapping: Map) { } function resolveBrowserBaseUrl(params: { - target?: "sandbox" | "host" | "custom"; - controlUrl?: string; - defaultControlUrl?: string; + target?: "sandbox" | "host"; + sandboxBridgeUrl?: string; allowHostControl?: boolean; - allowedControlUrls?: string[]; - allowedControlHosts?: string[]; - allowedControlPorts?: number[]; -}) { +}): string | undefined { const cfg = loadConfig(); - const resolved = resolveBrowserConfig(cfg.browser); - const normalizedControlUrl = params.controlUrl?.trim() ?? ""; - const normalizedDefault = params.defaultControlUrl?.trim() ?? ""; - const target = - params.target ?? (normalizedControlUrl ? "custom" : normalizedDefault ? "sandbox" : "host"); - - const assertAllowedControlUrl = (url: string) => { - const allowedUrls = params.allowedControlUrls?.map((entry) => entry.trim().replace(/\/$/, "")); - const allowedHosts = params.allowedControlHosts?.map((entry) => entry.trim().toLowerCase()); - const allowedPorts = params.allowedControlPorts; - if (!allowedUrls?.length && !allowedHosts?.length && !allowedPorts?.length) { - return; - } - let parsed: URL; - try { - parsed = new URL(url); - } catch { - throw new Error(`Invalid browser controlUrl: ${url}`); - } - const normalizedUrl = parsed.toString().replace(/\/$/, ""); - if (allowedUrls?.length && !allowedUrls.includes(normalizedUrl)) { - throw new Error("Browser controlUrl is not in the allowed URL list."); - } - if (allowedHosts?.length && !allowedHosts.includes(parsed.hostname)) { - throw new Error("Browser controlUrl hostname is not in the allowed host list."); - } - if (allowedPorts?.length) { - const port = - parsed.port?.trim() !== "" ? Number(parsed.port) : parsed.protocol === "https:" ? 443 : 80; - if (!Number.isFinite(port) || !allowedPorts.includes(port)) { - throw new Error("Browser controlUrl port is not in the allowed port list."); - } - } - }; - - if (target !== "custom" && params.target && normalizedControlUrl) { - throw new Error('controlUrl is only supported with target="custom".'); - } - - if (target === "custom") { - if (!normalizedControlUrl) { - throw new Error("Custom browser target requires controlUrl."); - } - const normalized = normalizedControlUrl.replace(/\/$/, ""); - assertAllowedControlUrl(normalized); - return normalized; - } + const resolved = resolveBrowserConfig(cfg.browser, cfg); + const normalizedSandbox = params.sandboxBridgeUrl?.trim() ?? ""; + const target = params.target ?? (normalizedSandbox ? "sandbox" : "host"); if (target === "sandbox") { - if (!normalizedDefault) { + if (!normalizedSandbox) { throw new Error( 'Sandbox browser is unavailable. Enable agents.defaults.sandbox.browser.enabled or use target="host" if allowed.', ); } - return normalizedDefault.replace(/\/$/, ""); + return normalizedSandbox.replace(/\/$/, ""); } if (params.allowHostControl === false) { @@ -261,27 +211,16 @@ function resolveBrowserBaseUrl(params: { "Browser control is disabled. Set browser.enabled=true in ~/.clawdbot/clawdbot.json.", ); } - const normalized = resolved.controlUrl.replace(/\/$/, ""); - assertAllowedControlUrl(normalized); - return normalized; + return undefined; } export function createBrowserTool(opts?: { - defaultControlUrl?: string; + sandboxBridgeUrl?: string; allowHostControl?: boolean; - allowedControlUrls?: string[]; - allowedControlHosts?: string[]; - allowedControlPorts?: number[]; }): AnyAgentTool { - const targetDefault = opts?.defaultControlUrl ? "sandbox" : "host"; + const targetDefault = opts?.sandboxBridgeUrl ? "sandbox" : "host"; const hostHint = opts?.allowHostControl === false ? "Host target blocked by policy." : "Host target allowed."; - const allowlistHint = - opts?.allowedControlUrls?.length || - opts?.allowedControlHosts?.length || - opts?.allowedControlPorts?.length - ? "Custom targets are restricted by sandbox allowlists." - : "Custom targets are unrestricted."; return { label: "Browser", name: "browser", @@ -294,33 +233,22 @@ export function createBrowserTool(opts?: { "When using refs from snapshot (e.g. e12), keep the same tab: prefer passing targetId from the snapshot response into subsequent actions (act/click/type/etc).", 'For stable, self-resolving refs across calls, use snapshot with refs="aria" (Playwright aria-ref ids). Default refs="role" are role+name-based.', "Use snapshot+act for UI automation. Avoid act:wait by default; use only in exceptional cases when no reliable UI state exists.", - `target selects browser location (sandbox|host|custom|node). Default: ${targetDefault}.`, - "controlUrl implies target=custom (remote control server).", + `target selects browser location (sandbox|host|node). Default: ${targetDefault}.`, hostHint, - allowlistHint, ].join(" "), parameters: BrowserToolSchema, execute: async (_toolCallId, args) => { const params = args as Record; const action = readStringParam(params, "action", { required: true }); - const controlUrl = readStringParam(params, "controlUrl"); const profile = readStringParam(params, "profile"); const requestedNode = readStringParam(params, "node"); - let target = readStringParam(params, "target") as - | "sandbox" - | "host" - | "custom" - | "node" - | undefined; + let target = readStringParam(params, "target") as "sandbox" | "host" | "node" | undefined; - if (controlUrl?.trim() && (target === "node" || requestedNode)) { - throw new Error('controlUrl is not supported with target="node".'); - } - if (target === "custom" && requestedNode) { - throw new Error('node is not supported with target="custom".'); + if (requestedNode && target && target !== "node") { + throw new Error('node is only supported with target="node".'); } - if (!target && !controlUrl?.trim() && !requestedNode && profile === "chrome") { + if (!target && !requestedNode && profile === "chrome") { // Chrome extension relay takeover is a host Chrome feature; prefer host unless explicitly targeting a node. target = "host"; } @@ -328,21 +256,16 @@ export function createBrowserTool(opts?: { const nodeTarget = await resolveBrowserNodeTarget({ requestedNode: requestedNode ?? undefined, target, - controlUrl, - defaultControlUrl: opts?.defaultControlUrl, + sandboxBridgeUrl: opts?.sandboxBridgeUrl, }); const resolvedTarget = target === "node" ? undefined : target; const baseUrl = nodeTarget - ? "" + ? undefined : resolveBrowserBaseUrl({ target: resolvedTarget, - controlUrl, - defaultControlUrl: opts?.defaultControlUrl, + sandboxBridgeUrl: opts?.sandboxBridgeUrl, allowHostControl: opts?.allowHostControl, - allowedControlUrls: opts?.allowedControlUrls, - allowedControlHosts: opts?.allowedControlHosts, - allowedControlPorts: opts?.allowedControlPorts, }); const proxyRequest = nodeTarget diff --git a/src/browser/bridge-server.ts b/src/browser/bridge-server.ts index 6bfe190a5..eaab062cc 100644 --- a/src/browser/bridge-server.ts +++ b/src/browser/bridge-server.ts @@ -4,6 +4,7 @@ import express from "express"; import type { ResolvedBrowserConfig } from "./config.js"; import { registerBrowserRoutes } from "./routes/index.js"; +import type { BrowserRouteRegistrar } from "./routes/types.js"; import { type BrowserServerState, createBrowserRouteContext, @@ -50,7 +51,7 @@ export async function startBrowserBridgeServer(params: { getState: () => state, onEnsureAttachTarget: params.onEnsureAttachTarget, }); - registerBrowserRoutes(app, ctx); + registerBrowserRoutes(app as unknown as BrowserRouteRegistrar, ctx); const server = await new Promise((resolve, reject) => { const s = app.listen(port, host, () => resolve(s)); @@ -61,11 +62,9 @@ export async function startBrowserBridgeServer(params: { const resolvedPort = address?.port ?? port; state.server = server; state.port = resolvedPort; - state.resolved.controlHost = host; state.resolved.controlPort = resolvedPort; - state.resolved.controlUrl = `http://${host}:${resolvedPort}`; - const baseUrl = state.resolved.controlUrl; + const baseUrl = `http://${host}:${resolvedPort}`; return { server, port: resolvedPort, baseUrl, state }; } diff --git a/src/browser/client-actions-core.ts b/src/browser/client-actions-core.ts index 667600ef3..96688f701 100644 --- a/src/browser/client-actions-core.ts +++ b/src/browser/client-actions-core.ts @@ -9,6 +9,12 @@ function buildProfileQuery(profile?: string): string { return profile ? `?profile=${encodeURIComponent(profile)}` : ""; } +function withBaseUrl(baseUrl: string | undefined, path: string): string { + const trimmed = baseUrl?.trim(); + if (!trimmed) return path; + return `${trimmed.replace(/\/$/, "")}${path}`; +} + export type BrowserFormField = { ref: string; type: string; @@ -92,11 +98,15 @@ export type BrowserDownloadPayload = { }; export async function browserNavigate( - baseUrl: string, - opts: { url: string; targetId?: string; profile?: string }, + baseUrl: string | undefined, + opts: { + url: string; + targetId?: string; + profile?: string; + }, ): Promise { const q = buildProfileQuery(opts.profile); - return await fetchBrowserJson(`${baseUrl}/navigate${q}`, { + return await fetchBrowserJson(withBaseUrl(baseUrl, `/navigate${q}`), { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ url: opts.url, targetId: opts.targetId }), @@ -105,7 +115,7 @@ export async function browserNavigate( } export async function browserArmDialog( - baseUrl: string, + baseUrl: string | undefined, opts: { accept: boolean; promptText?: string; @@ -115,7 +125,7 @@ export async function browserArmDialog( }, ): Promise { const q = buildProfileQuery(opts.profile); - return await fetchBrowserJson(`${baseUrl}/hooks/dialog${q}`, { + return await fetchBrowserJson(withBaseUrl(baseUrl, `/hooks/dialog${q}`), { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ @@ -129,7 +139,7 @@ export async function browserArmDialog( } export async function browserArmFileChooser( - baseUrl: string, + baseUrl: string | undefined, opts: { paths: string[]; ref?: string; @@ -141,7 +151,7 @@ export async function browserArmFileChooser( }, ): Promise { const q = buildProfileQuery(opts.profile); - return await fetchBrowserJson(`${baseUrl}/hooks/file-chooser${q}`, { + return await fetchBrowserJson(withBaseUrl(baseUrl, `/hooks/file-chooser${q}`), { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ @@ -157,7 +167,7 @@ export async function browserArmFileChooser( } export async function browserWaitForDownload( - baseUrl: string, + baseUrl: string | undefined, opts: { path?: string; targetId?: string; @@ -170,7 +180,7 @@ export async function browserWaitForDownload( ok: true; targetId: string; download: BrowserDownloadPayload; - }>(`${baseUrl}/wait/download${q}`, { + }>(withBaseUrl(baseUrl, `/wait/download${q}`), { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ @@ -183,7 +193,7 @@ export async function browserWaitForDownload( } export async function browserDownload( - baseUrl: string, + baseUrl: string | undefined, opts: { ref: string; path: string; @@ -197,7 +207,7 @@ export async function browserDownload( ok: true; targetId: string; download: BrowserDownloadPayload; - }>(`${baseUrl}/download${q}`, { + }>(withBaseUrl(baseUrl, `/download${q}`), { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ @@ -211,12 +221,12 @@ export async function browserDownload( } export async function browserAct( - baseUrl: string, + baseUrl: string | undefined, req: BrowserActRequest, opts?: { profile?: string }, ): Promise { const q = buildProfileQuery(opts?.profile); - return await fetchBrowserJson(`${baseUrl}/act${q}`, { + return await fetchBrowserJson(withBaseUrl(baseUrl, `/act${q}`), { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(req), @@ -225,7 +235,7 @@ export async function browserAct( } export async function browserScreenshotAction( - baseUrl: string, + baseUrl: string | undefined, opts: { targetId?: string; fullPage?: boolean; @@ -236,7 +246,7 @@ export async function browserScreenshotAction( }, ): Promise { const q = buildProfileQuery(opts.profile); - return await fetchBrowserJson(`${baseUrl}/screenshot${q}`, { + return await fetchBrowserJson(withBaseUrl(baseUrl, `/screenshot${q}`), { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ diff --git a/src/browser/client-actions-observe.ts b/src/browser/client-actions-observe.ts index 4002d48c5..4b042d9b0 100644 --- a/src/browser/client-actions-observe.ts +++ b/src/browser/client-actions-observe.ts @@ -10,8 +10,14 @@ function buildProfileQuery(profile?: string): string { return profile ? `?profile=${encodeURIComponent(profile)}` : ""; } +function withBaseUrl(baseUrl: string | undefined, path: string): string { + const trimmed = baseUrl?.trim(); + if (!trimmed) return path; + return `${trimmed.replace(/\/$/, "")}${path}`; +} + export async function browserConsoleMessages( - baseUrl: string, + baseUrl: string | undefined, opts: { level?: string; targetId?: string; profile?: string } = {}, ): Promise<{ ok: true; messages: BrowserConsoleMessage[]; targetId: string }> { const q = new URLSearchParams(); @@ -23,15 +29,15 @@ export async function browserConsoleMessages( ok: true; messages: BrowserConsoleMessage[]; targetId: string; - }>(`${baseUrl}/console${suffix}`, { timeoutMs: 20000 }); + }>(withBaseUrl(baseUrl, `/console${suffix}`), { timeoutMs: 20000 }); } export async function browserPdfSave( - baseUrl: string, + baseUrl: string | undefined, opts: { targetId?: string; profile?: string } = {}, ): Promise { const q = buildProfileQuery(opts.profile); - return await fetchBrowserJson(`${baseUrl}/pdf${q}`, { + return await fetchBrowserJson(withBaseUrl(baseUrl, `/pdf${q}`), { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ targetId: opts.targetId }), @@ -40,7 +46,7 @@ export async function browserPdfSave( } export async function browserPageErrors( - baseUrl: string, + baseUrl: string | undefined, opts: { targetId?: string; clear?: boolean; profile?: string } = {}, ): Promise<{ ok: true; targetId: string; errors: BrowserPageError[] }> { const q = new URLSearchParams(); @@ -52,11 +58,11 @@ export async function browserPageErrors( ok: true; targetId: string; errors: BrowserPageError[]; - }>(`${baseUrl}/errors${suffix}`, { timeoutMs: 20000 }); + }>(withBaseUrl(baseUrl, `/errors${suffix}`), { timeoutMs: 20000 }); } export async function browserRequests( - baseUrl: string, + baseUrl: string | undefined, opts: { targetId?: string; filter?: string; @@ -74,11 +80,11 @@ export async function browserRequests( ok: true; targetId: string; requests: BrowserNetworkRequest[]; - }>(`${baseUrl}/requests${suffix}`, { timeoutMs: 20000 }); + }>(withBaseUrl(baseUrl, `/requests${suffix}`), { timeoutMs: 20000 }); } export async function browserTraceStart( - baseUrl: string, + baseUrl: string | undefined, opts: { targetId?: string; screenshots?: boolean; @@ -88,7 +94,7 @@ export async function browserTraceStart( } = {}, ): Promise { const q = buildProfileQuery(opts.profile); - return await fetchBrowserJson(`${baseUrl}/trace/start${q}`, { + return await fetchBrowserJson(withBaseUrl(baseUrl, `/trace/start${q}`), { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ @@ -102,11 +108,11 @@ export async function browserTraceStart( } export async function browserTraceStop( - baseUrl: string, + baseUrl: string | undefined, opts: { targetId?: string; path?: string; profile?: string } = {}, ): Promise { const q = buildProfileQuery(opts.profile); - return await fetchBrowserJson(`${baseUrl}/trace/stop${q}`, { + return await fetchBrowserJson(withBaseUrl(baseUrl, `/trace/stop${q}`), { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ targetId: opts.targetId, path: opts.path }), @@ -115,11 +121,11 @@ export async function browserTraceStop( } export async function browserHighlight( - baseUrl: string, + baseUrl: string | undefined, opts: { ref: string; targetId?: string; profile?: string }, ): Promise { const q = buildProfileQuery(opts.profile); - return await fetchBrowserJson(`${baseUrl}/highlight${q}`, { + return await fetchBrowserJson(withBaseUrl(baseUrl, `/highlight${q}`), { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ targetId: opts.targetId, ref: opts.ref }), @@ -128,7 +134,7 @@ export async function browserHighlight( } export async function browserResponseBody( - baseUrl: string, + baseUrl: string | undefined, opts: { url: string; targetId?: string; @@ -158,7 +164,7 @@ export async function browserResponseBody( body: string; truncated?: boolean; }; - }>(`${baseUrl}/response/body${q}`, { + }>(withBaseUrl(baseUrl, `/response/body${q}`), { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ diff --git a/src/browser/client-actions-state.ts b/src/browser/client-actions-state.ts index 192cad997..751634a9e 100644 --- a/src/browser/client-actions-state.ts +++ b/src/browser/client-actions-state.ts @@ -5,8 +5,14 @@ function buildProfileQuery(profile?: string): string { return profile ? `?profile=${encodeURIComponent(profile)}` : ""; } +function withBaseUrl(baseUrl: string | undefined, path: string): string { + const trimmed = baseUrl?.trim(); + if (!trimmed) return path; + return `${trimmed.replace(/\/$/, "")}${path}`; +} + export async function browserCookies( - baseUrl: string, + baseUrl: string | undefined, opts: { targetId?: string; profile?: string } = {}, ): Promise<{ ok: true; targetId: string; cookies: unknown[] }> { const q = new URLSearchParams(); @@ -17,11 +23,11 @@ export async function browserCookies( ok: true; targetId: string; cookies: unknown[]; - }>(`${baseUrl}/cookies${suffix}`, { timeoutMs: 20000 }); + }>(withBaseUrl(baseUrl, `/cookies${suffix}`), { timeoutMs: 20000 }); } export async function browserCookiesSet( - baseUrl: string, + baseUrl: string | undefined, opts: { cookie: Record; targetId?: string; @@ -29,7 +35,7 @@ export async function browserCookiesSet( }, ): Promise { const q = buildProfileQuery(opts.profile); - return await fetchBrowserJson(`${baseUrl}/cookies/set${q}`, { + return await fetchBrowserJson(withBaseUrl(baseUrl, `/cookies/set${q}`), { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ targetId: opts.targetId, cookie: opts.cookie }), @@ -38,11 +44,11 @@ export async function browserCookiesSet( } export async function browserCookiesClear( - baseUrl: string, + baseUrl: string | undefined, opts: { targetId?: string; profile?: string } = {}, ): Promise { const q = buildProfileQuery(opts.profile); - return await fetchBrowserJson(`${baseUrl}/cookies/clear${q}`, { + return await fetchBrowserJson(withBaseUrl(baseUrl, `/cookies/clear${q}`), { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ targetId: opts.targetId }), @@ -51,7 +57,7 @@ export async function browserCookiesClear( } export async function browserStorageGet( - baseUrl: string, + baseUrl: string | undefined, opts: { kind: "local" | "session"; key?: string; @@ -68,11 +74,11 @@ export async function browserStorageGet( ok: true; targetId: string; values: Record; - }>(`${baseUrl}/storage/${opts.kind}${suffix}`, { timeoutMs: 20000 }); + }>(withBaseUrl(baseUrl, `/storage/${opts.kind}${suffix}`), { timeoutMs: 20000 }); } export async function browserStorageSet( - baseUrl: string, + baseUrl: string | undefined, opts: { kind: "local" | "session"; key: string; @@ -82,25 +88,28 @@ export async function browserStorageSet( }, ): Promise { const q = buildProfileQuery(opts.profile); - return await fetchBrowserJson(`${baseUrl}/storage/${opts.kind}/set${q}`, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ - targetId: opts.targetId, - key: opts.key, - value: opts.value, - }), - timeoutMs: 20000, - }); + return await fetchBrowserJson( + withBaseUrl(baseUrl, `/storage/${opts.kind}/set${q}`), + { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + targetId: opts.targetId, + key: opts.key, + value: opts.value, + }), + timeoutMs: 20000, + }, + ); } export async function browserStorageClear( - baseUrl: string, + baseUrl: string | undefined, opts: { kind: "local" | "session"; targetId?: string; profile?: string }, ): Promise { const q = buildProfileQuery(opts.profile); return await fetchBrowserJson( - `${baseUrl}/storage/${opts.kind}/clear${q}`, + withBaseUrl(baseUrl, `/storage/${opts.kind}/clear${q}`), { method: "POST", headers: { "Content-Type": "application/json" }, @@ -111,11 +120,11 @@ export async function browserStorageClear( } export async function browserSetOffline( - baseUrl: string, + baseUrl: string | undefined, opts: { offline: boolean; targetId?: string; profile?: string }, ): Promise { const q = buildProfileQuery(opts.profile); - return await fetchBrowserJson(`${baseUrl}/set/offline${q}`, { + return await fetchBrowserJson(withBaseUrl(baseUrl, `/set/offline${q}`), { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ targetId: opts.targetId, offline: opts.offline }), @@ -124,7 +133,7 @@ export async function browserSetOffline( } export async function browserSetHeaders( - baseUrl: string, + baseUrl: string | undefined, opts: { headers: Record; targetId?: string; @@ -132,7 +141,7 @@ export async function browserSetHeaders( }, ): Promise { const q = buildProfileQuery(opts.profile); - return await fetchBrowserJson(`${baseUrl}/set/headers${q}`, { + return await fetchBrowserJson(withBaseUrl(baseUrl, `/set/headers${q}`), { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ targetId: opts.targetId, headers: opts.headers }), @@ -141,7 +150,7 @@ export async function browserSetHeaders( } export async function browserSetHttpCredentials( - baseUrl: string, + baseUrl: string | undefined, opts: { username?: string; password?: string; @@ -151,21 +160,24 @@ export async function browserSetHttpCredentials( } = {}, ): Promise { const q = buildProfileQuery(opts.profile); - return await fetchBrowserJson(`${baseUrl}/set/credentials${q}`, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ - targetId: opts.targetId, - username: opts.username, - password: opts.password, - clear: opts.clear, - }), - timeoutMs: 20000, - }); + return await fetchBrowserJson( + withBaseUrl(baseUrl, `/set/credentials${q}`), + { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + targetId: opts.targetId, + username: opts.username, + password: opts.password, + clear: opts.clear, + }), + timeoutMs: 20000, + }, + ); } export async function browserSetGeolocation( - baseUrl: string, + baseUrl: string | undefined, opts: { latitude?: number; longitude?: number; @@ -177,23 +189,26 @@ export async function browserSetGeolocation( } = {}, ): Promise { const q = buildProfileQuery(opts.profile); - return await fetchBrowserJson(`${baseUrl}/set/geolocation${q}`, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ - targetId: opts.targetId, - latitude: opts.latitude, - longitude: opts.longitude, - accuracy: opts.accuracy, - origin: opts.origin, - clear: opts.clear, - }), - timeoutMs: 20000, - }); + return await fetchBrowserJson( + withBaseUrl(baseUrl, `/set/geolocation${q}`), + { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + targetId: opts.targetId, + latitude: opts.latitude, + longitude: opts.longitude, + accuracy: opts.accuracy, + origin: opts.origin, + clear: opts.clear, + }), + timeoutMs: 20000, + }, + ); } export async function browserSetMedia( - baseUrl: string, + baseUrl: string | undefined, opts: { colorScheme: "dark" | "light" | "no-preference" | "none"; targetId?: string; @@ -201,7 +216,7 @@ export async function browserSetMedia( }, ): Promise { const q = buildProfileQuery(opts.profile); - return await fetchBrowserJson(`${baseUrl}/set/media${q}`, { + return await fetchBrowserJson(withBaseUrl(baseUrl, `/set/media${q}`), { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ @@ -213,11 +228,11 @@ export async function browserSetMedia( } export async function browserSetTimezone( - baseUrl: string, + baseUrl: string | undefined, opts: { timezoneId: string; targetId?: string; profile?: string }, ): Promise { const q = buildProfileQuery(opts.profile); - return await fetchBrowserJson(`${baseUrl}/set/timezone${q}`, { + return await fetchBrowserJson(withBaseUrl(baseUrl, `/set/timezone${q}`), { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ @@ -229,11 +244,11 @@ export async function browserSetTimezone( } export async function browserSetLocale( - baseUrl: string, + baseUrl: string | undefined, opts: { locale: string; targetId?: string; profile?: string }, ): Promise { const q = buildProfileQuery(opts.profile); - return await fetchBrowserJson(`${baseUrl}/set/locale${q}`, { + return await fetchBrowserJson(withBaseUrl(baseUrl, `/set/locale${q}`), { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ targetId: opts.targetId, locale: opts.locale }), @@ -242,11 +257,11 @@ export async function browserSetLocale( } export async function browserSetDevice( - baseUrl: string, + baseUrl: string | undefined, opts: { name: string; targetId?: string; profile?: string }, ): Promise { const q = buildProfileQuery(opts.profile); - return await fetchBrowserJson(`${baseUrl}/set/device${q}`, { + return await fetchBrowserJson(withBaseUrl(baseUrl, `/set/device${q}`), { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ targetId: opts.targetId, name: opts.name }), @@ -255,11 +270,11 @@ export async function browserSetDevice( } export async function browserClearPermissions( - baseUrl: string, + baseUrl: string | undefined, opts: { targetId?: string; profile?: string } = {}, ): Promise { const q = buildProfileQuery(opts.profile); - return await fetchBrowserJson(`${baseUrl}/set/geolocation${q}`, { + return await fetchBrowserJson(withBaseUrl(baseUrl, `/set/geolocation${q}`), { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ targetId: opts.targetId, clear: true }), diff --git a/src/browser/client-fetch.ts b/src/browser/client-fetch.ts index e815f45c4..43bc7c07b 100644 --- a/src/browser/client-fetch.ts +++ b/src/browser/client-fetch.ts @@ -1,57 +1,44 @@ -import { extractErrorCode, formatErrorMessage } from "../infra/errors.js"; -import { loadConfig } from "../config/config.js"; import { formatCliCommand } from "../cli/command-format.js"; -import { resolveBrowserConfig } from "./config.js"; +import { + createBrowserControlContext, + startBrowserControlServiceFromConfig, +} from "./control-service.js"; +import { createBrowserRouteDispatcher } from "./routes/dispatcher.js"; -let cachedConfigToken: string | null | undefined = undefined; - -function getBrowserControlToken(): string | null { - const env = process.env.CLAWDBOT_BROWSER_CONTROL_TOKEN?.trim(); - if (env) return env; - - if (cachedConfigToken !== undefined) return cachedConfigToken; - try { - const cfg = loadConfig(); - const resolved = resolveBrowserConfig(cfg.browser); - const token = resolved.controlToken?.trim() || ""; - cachedConfigToken = token ? token : null; - } catch { - cachedConfigToken = null; - } - return cachedConfigToken; -} - -function unwrapCause(err: unknown): unknown { - if (!err || typeof err !== "object") return null; - const cause = (err as { cause?: unknown }).cause; - return cause ?? null; +function isAbsoluteHttp(url: string): boolean { + return /^https?:\/\//i.test(url.trim()); } function enhanceBrowserFetchError(url: string, err: unknown, timeoutMs: number): Error { - const cause = unwrapCause(err); - const code = extractErrorCode(cause) ?? extractErrorCode(err) ?? ""; - - const hint = `Start (or restart) the Clawdbot gateway (Clawdbot.app menubar, or \`${formatCliCommand("clawdbot gateway")}\`) and try again.`; - - if (code === "ECONNREFUSED") { + const hint = isAbsoluteHttp(url) + ? "If this is a sandboxed session, ensure the sandbox browser is running and try again." + : `Start (or restart) the Clawdbot gateway (Clawdbot.app menubar, or \`${formatCliCommand("clawdbot gateway")}\`) and try again.`; + const msg = String(err); + if (msg.toLowerCase().includes("timed out") || msg.toLowerCase().includes("timeout")) { return new Error( - `Can't reach the clawd browser control server at ${url} (connection refused). ${hint}`, - ); - } - if (code === "ETIMEDOUT" || code === "UND_ERR_CONNECT_TIMEOUT") { - return new Error( - `Can't reach the clawd browser control server at ${url} (timed out after ${timeoutMs}ms). ${hint}`, + `Can't reach the clawd browser control service (timed out after ${timeoutMs}ms). ${hint}`, ); } + return new Error(`Can't reach the clawd browser control service. ${hint} (${msg})`); +} - const msg = formatErrorMessage(err); - if (msg.toLowerCase().includes("abort")) { - return new Error( - `Can't reach the clawd browser control server at ${url} (timed out after ${timeoutMs}ms). ${hint}`, - ); +async function fetchHttpJson( + url: string, + init: RequestInit & { timeoutMs?: number }, +): Promise { + const timeoutMs = init.timeoutMs ?? 5000; + const ctrl = new AbortController(); + const t = setTimeout(() => ctrl.abort(), timeoutMs); + try { + const res = await fetch(url, { ...init, signal: ctrl.signal }); + if (!res.ok) { + const text = await res.text().catch(() => ""); + throw new Error(text || `HTTP ${res.status}`); + } + return (await res.json()) as T; + } finally { + clearTimeout(t); } - - return new Error(`Can't reach the clawd browser control server at ${url}. ${hint} (${msg})`); } export async function fetchBrowserJson( @@ -59,32 +46,58 @@ export async function fetchBrowserJson( init?: RequestInit & { timeoutMs?: number }, ): Promise { const timeoutMs = init?.timeoutMs ?? 5000; - const ctrl = new AbortController(); - const t = setTimeout(() => ctrl.abort(), timeoutMs); - let res: Response; try { - const token = getBrowserControlToken(); - const mergedHeaders = (() => { - if (!token) return init?.headers; - const h = new Headers(init?.headers ?? {}); - if (!h.has("Authorization")) { - h.set("Authorization", `Bearer ${token}`); + if (isAbsoluteHttp(url)) { + return await fetchHttpJson(url, { ...(init ?? {}), timeoutMs }); + } + const started = await startBrowserControlServiceFromConfig(); + if (!started) { + throw new Error("browser control disabled"); + } + const dispatcher = createBrowserRouteDispatcher(createBrowserControlContext()); + const parsed = new URL(url, "http://localhost"); + const query: Record = {}; + for (const [key, value] of parsed.searchParams.entries()) { + query[key] = value; + } + let body = init?.body; + if (typeof body === "string") { + try { + body = JSON.parse(body); + } catch { + // keep as string } - return h; - })(); - res = await fetch(url, { - ...init, - ...(mergedHeaders ? { headers: mergedHeaders } : {}), - signal: ctrl.signal, - } as RequestInit); + } + const dispatchPromise = dispatcher.dispatch({ + method: + init?.method?.toUpperCase() === "DELETE" + ? "DELETE" + : init?.method?.toUpperCase() === "POST" + ? "POST" + : "GET", + path: parsed.pathname, + query, + body, + }); + + const result = await (timeoutMs + ? Promise.race([ + dispatchPromise, + new Promise((_, reject) => + setTimeout(() => reject(new Error("timed out")), timeoutMs), + ), + ]) + : dispatchPromise); + + if (result.status >= 400) { + const message = + result.body && typeof result.body === "object" && "error" in result.body + ? String((result.body as { error?: unknown }).error) + : `HTTP ${result.status}`; + throw new Error(message); + } + return result.body as T; } catch (err) { throw enhanceBrowserFetchError(url, err, timeoutMs); - } finally { - clearTimeout(t); } - if (!res.ok) { - const text = await res.text().catch(() => ""); - throw new Error(text ? `${res.status}: ${text}` : `HTTP ${res.status}`); - } - return (await res.json()) as T; } diff --git a/src/browser/client.test.ts b/src/browser/client.test.ts index 7721828f8..848c53d18 100644 --- a/src/browser/client.test.ts +++ b/src/browser/client.test.ts @@ -16,7 +16,7 @@ describe("browser client", () => { vi.unstubAllGlobals(); }); - it("wraps connection failures with a gateway hint", async () => { + it("wraps connection failures with a sandbox hint", async () => { const refused = Object.assign(new Error("connect ECONNREFUSED 127.0.0.1"), { code: "ECONNREFUSED", }); @@ -26,7 +26,7 @@ describe("browser client", () => { vi.stubGlobal("fetch", vi.fn().mockRejectedValue(fetchFailed)); - await expect(browserStatus("http://127.0.0.1:18791")).rejects.toThrow(/Start .*gateway/i); + await expect(browserStatus("http://127.0.0.1:18791")).rejects.toThrow(/sandboxed session/i); }); it("adds useful timeout messaging for abort-like failures", async () => { @@ -34,41 +34,6 @@ describe("browser client", () => { await expect(browserStatus("http://127.0.0.1:18791")).rejects.toThrow(/timed out/i); }); - it("adds Authorization when CLAWDBOT_BROWSER_CONTROL_TOKEN is set", async () => { - const prev = process.env.CLAWDBOT_BROWSER_CONTROL_TOKEN; - process.env.CLAWDBOT_BROWSER_CONTROL_TOKEN = "t1"; - - const calls: Array<{ url: string; init?: RequestInit }> = []; - vi.stubGlobal( - "fetch", - vi.fn(async (url: string, init?: RequestInit) => { - calls.push({ url, init }); - return { - ok: true, - json: async () => ({ - enabled: true, - controlUrl: "http://127.0.0.1:18791", - running: false, - pid: null, - cdpPort: 18792, - chosenBrowser: null, - userDataDir: null, - color: "#FF0000", - headless: true, - attachOnly: false, - }), - } as unknown as Response; - }), - ); - - await browserStatus("http://127.0.0.1:18791"); - const init = calls[0]?.init; - const auth = new Headers(init?.headers ?? {}).get("Authorization"); - expect(auth).toBe("Bearer t1"); - - process.env.CLAWDBOT_BROWSER_CONTROL_TOKEN = prev; - }); - it("surfaces non-2xx responses with body text", async () => { vi.stubGlobal( "fetch", @@ -81,7 +46,7 @@ describe("browser client", () => { await expect( browserSnapshot("http://127.0.0.1:18791", { format: "aria", limit: 1 }), - ).rejects.toThrow(/409: conflict/i); + ).rejects.toThrow(/conflict/i); }); it("adds labels + efficient mode query params to snapshots", async () => { @@ -255,7 +220,6 @@ describe("browser client", () => { ok: true, json: async () => ({ enabled: true, - controlUrl: "http://127.0.0.1:18791", running: true, pid: 1, cdpPort: 18792, diff --git a/src/browser/client.ts b/src/browser/client.ts index eb98e8138..fa8cf2d69 100644 --- a/src/browser/client.ts +++ b/src/browser/client.ts @@ -1,10 +1,7 @@ -import { loadConfig } from "../config/config.js"; import { fetchBrowserJson } from "./client-fetch.js"; -import { resolveBrowserConfig } from "./config.js"; export type BrowserStatus = { enabled: boolean; - controlUrl: string; profile?: string; running: boolean; cdpReady?: boolean; @@ -89,59 +86,64 @@ export type SnapshotResult = imageType?: "png" | "jpeg"; }; -export function resolveBrowserControlUrl(overrideUrl?: string) { - const cfg = loadConfig(); - const resolved = resolveBrowserConfig(cfg.browser); - const url = overrideUrl?.trim() ? overrideUrl.trim() : resolved.controlUrl; - return url.replace(/\/$/, ""); -} - function buildProfileQuery(profile?: string): string { return profile ? `?profile=${encodeURIComponent(profile)}` : ""; } +function withBaseUrl(baseUrl: string | undefined, path: string): string { + const trimmed = baseUrl?.trim(); + if (!trimmed) return path; + return `${trimmed.replace(/\/$/, "")}${path}`; +} + export async function browserStatus( - baseUrl: string, + baseUrl?: string, opts?: { profile?: string }, ): Promise { const q = buildProfileQuery(opts?.profile); - return await fetchBrowserJson(`${baseUrl}/${q}`, { + return await fetchBrowserJson(withBaseUrl(baseUrl, `/${q}`), { timeoutMs: 1500, }); } -export async function browserProfiles(baseUrl: string): Promise { - const res = await fetchBrowserJson<{ profiles: ProfileStatus[] }>(`${baseUrl}/profiles`, { - timeoutMs: 3000, - }); +export async function browserProfiles(baseUrl?: string): Promise { + const res = await fetchBrowserJson<{ profiles: ProfileStatus[] }>( + withBaseUrl(baseUrl, `/profiles`), + { + timeoutMs: 3000, + }, + ); return res.profiles ?? []; } -export async function browserStart(baseUrl: string, opts?: { profile?: string }): Promise { +export async function browserStart(baseUrl?: string, opts?: { profile?: string }): Promise { const q = buildProfileQuery(opts?.profile); - await fetchBrowserJson(`${baseUrl}/start${q}`, { + await fetchBrowserJson(withBaseUrl(baseUrl, `/start${q}`), { method: "POST", timeoutMs: 15000, }); } -export async function browserStop(baseUrl: string, opts?: { profile?: string }): Promise { +export async function browserStop(baseUrl?: string, opts?: { profile?: string }): Promise { const q = buildProfileQuery(opts?.profile); - await fetchBrowserJson(`${baseUrl}/stop${q}`, { + await fetchBrowserJson(withBaseUrl(baseUrl, `/stop${q}`), { method: "POST", timeoutMs: 15000, }); } export async function browserResetProfile( - baseUrl: string, + baseUrl?: string, opts?: { profile?: string }, ): Promise { const q = buildProfileQuery(opts?.profile); - return await fetchBrowserJson(`${baseUrl}/reset-profile${q}`, { - method: "POST", - timeoutMs: 20000, - }); + return await fetchBrowserJson( + withBaseUrl(baseUrl, `/reset-profile${q}`), + { + method: "POST", + timeoutMs: 20000, + }, + ); } export type BrowserCreateProfileResult = { @@ -154,7 +156,7 @@ export type BrowserCreateProfileResult = { }; export async function browserCreateProfile( - baseUrl: string, + baseUrl: string | undefined, opts: { name: string; color?: string; @@ -162,17 +164,20 @@ export async function browserCreateProfile( driver?: "clawd" | "extension"; }, ): Promise { - return await fetchBrowserJson(`${baseUrl}/profiles/create`, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ - name: opts.name, - color: opts.color, - cdpUrl: opts.cdpUrl, - driver: opts.driver, - }), - timeoutMs: 10000, - }); + return await fetchBrowserJson( + withBaseUrl(baseUrl, `/profiles/create`), + { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + name: opts.name, + color: opts.color, + cdpUrl: opts.cdpUrl, + driver: opts.driver, + }), + timeoutMs: 10000, + }, + ); } export type BrowserDeleteProfileResult = { @@ -182,11 +187,11 @@ export type BrowserDeleteProfileResult = { }; export async function browserDeleteProfile( - baseUrl: string, + baseUrl: string | undefined, profile: string, ): Promise { return await fetchBrowserJson( - `${baseUrl}/profiles/${encodeURIComponent(profile)}`, + withBaseUrl(baseUrl, `/profiles/${encodeURIComponent(profile)}`), { method: "DELETE", timeoutMs: 20000, @@ -195,24 +200,24 @@ export async function browserDeleteProfile( } export async function browserTabs( - baseUrl: string, + baseUrl?: string, opts?: { profile?: string }, ): Promise { const q = buildProfileQuery(opts?.profile); const res = await fetchBrowserJson<{ running: boolean; tabs: BrowserTab[] }>( - `${baseUrl}/tabs${q}`, + withBaseUrl(baseUrl, `/tabs${q}`), { timeoutMs: 3000 }, ); return res.tabs ?? []; } export async function browserOpenTab( - baseUrl: string, + baseUrl: string | undefined, url: string, opts?: { profile?: string }, ): Promise { const q = buildProfileQuery(opts?.profile); - return await fetchBrowserJson(`${baseUrl}/tabs/open${q}`, { + return await fetchBrowserJson(withBaseUrl(baseUrl, `/tabs/open${q}`), { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ url }), @@ -221,12 +226,12 @@ export async function browserOpenTab( } export async function browserFocusTab( - baseUrl: string, + baseUrl: string | undefined, targetId: string, opts?: { profile?: string }, ): Promise { const q = buildProfileQuery(opts?.profile); - await fetchBrowserJson(`${baseUrl}/tabs/focus${q}`, { + await fetchBrowserJson(withBaseUrl(baseUrl, `/tabs/focus${q}`), { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ targetId }), @@ -235,19 +240,19 @@ export async function browserFocusTab( } export async function browserCloseTab( - baseUrl: string, + baseUrl: string | undefined, targetId: string, opts?: { profile?: string }, ): Promise { const q = buildProfileQuery(opts?.profile); - await fetchBrowserJson(`${baseUrl}/tabs/${encodeURIComponent(targetId)}${q}`, { + await fetchBrowserJson(withBaseUrl(baseUrl, `/tabs/${encodeURIComponent(targetId)}${q}`), { method: "DELETE", timeoutMs: 5000, }); } export async function browserTabAction( - baseUrl: string, + baseUrl: string | undefined, opts: { action: "list" | "new" | "close" | "select"; index?: number; @@ -255,7 +260,7 @@ export async function browserTabAction( }, ): Promise { const q = buildProfileQuery(opts.profile); - return await fetchBrowserJson(`${baseUrl}/tabs/action${q}`, { + return await fetchBrowserJson(withBaseUrl(baseUrl, `/tabs/action${q}`), { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ @@ -267,7 +272,7 @@ export async function browserTabAction( } export async function browserSnapshot( - baseUrl: string, + baseUrl: string | undefined, opts: { format: "aria" | "ai"; targetId?: string; @@ -301,7 +306,7 @@ export async function browserSnapshot( if (opts.labels === true) q.set("labels", "1"); if (opts.mode) q.set("mode", opts.mode); if (opts.profile) q.set("profile", opts.profile); - return await fetchBrowserJson(`${baseUrl}/snapshot?${q.toString()}`, { + return await fetchBrowserJson(withBaseUrl(baseUrl, `/snapshot?${q.toString()}`), { timeoutMs: 20000, }); } diff --git a/src/browser/config.test.ts b/src/browser/config.test.ts index 0304896dc..136846059 100644 --- a/src/browser/config.test.ts +++ b/src/browser/config.test.ts @@ -2,13 +2,14 @@ import { describe, expect, it } from "vitest"; import { resolveBrowserConfig, resolveProfile, shouldStartLocalBrowserServer } from "./config.js"; describe("browser config", () => { - it("defaults to enabled with loopback control url and lobster-orange color", () => { + it("defaults to enabled with loopback defaults and lobster-orange color", () => { const resolved = resolveBrowserConfig(undefined); expect(resolved.enabled).toBe(true); expect(resolved.controlPort).toBe(18791); - expect(resolved.controlHost).toBe("127.0.0.1"); expect(resolved.color).toBe("#FF4500"); expect(shouldStartLocalBrowserServer(resolved)).toBe(true); + expect(resolved.cdpHost).toBe("127.0.0.1"); + expect(resolved.cdpProtocol).toBe("http"); const profile = resolveProfile(resolved, resolved.defaultProfile); expect(profile?.name).toBe("chrome"); expect(profile?.driver).toBe("extension"); @@ -46,9 +47,31 @@ describe("browser config", () => { } }); + it("derives default ports from gateway.port when env is unset", () => { + const prev = process.env.CLAWDBOT_GATEWAY_PORT; + delete process.env.CLAWDBOT_GATEWAY_PORT; + try { + const resolved = resolveBrowserConfig(undefined, { gateway: { port: 19011 } }); + expect(resolved.controlPort).toBe(19013); + const chrome = resolveProfile(resolved, "chrome"); + expect(chrome?.driver).toBe("extension"); + expect(chrome?.cdpPort).toBe(19014); + expect(chrome?.cdpUrl).toBe("http://127.0.0.1:19014"); + + const clawd = resolveProfile(resolved, "clawd"); + expect(clawd?.cdpPort).toBe(19022); + expect(clawd?.cdpUrl).toBe("http://127.0.0.1:19022"); + } finally { + if (prev === undefined) { + delete process.env.CLAWDBOT_GATEWAY_PORT; + } else { + process.env.CLAWDBOT_GATEWAY_PORT = prev; + } + } + }); + it("normalizes hex colors", () => { const resolved = resolveBrowserConfig({ - controlUrl: "http://localhost:18791", color: "ff4500", }); expect(resolved.color).toBe("#FF4500"); @@ -56,7 +79,6 @@ describe("browser config", () => { it("supports custom remote CDP timeouts", () => { const resolved = resolveBrowserConfig({ - controlUrl: "http://127.0.0.1:18791", remoteCdpTimeoutMs: 2200, remoteCdpHandshakeTimeoutMs: 5000, }); @@ -66,31 +88,21 @@ describe("browser config", () => { it("falls back to default color for invalid hex", () => { const resolved = resolveBrowserConfig({ - controlUrl: "http://localhost:18791", color: "#GGGGGG", }); expect(resolved.color).toBe("#FF4500"); }); - it("treats non-loopback control urls as remote", () => { + it("treats non-loopback cdpUrl as remote", () => { const resolved = resolveBrowserConfig({ - controlUrl: "http://example.com:18791", + cdpUrl: "http://example.com:9222", }); - expect(shouldStartLocalBrowserServer(resolved)).toBe(false); - }); - - it("derives CDP host/protocol from control url when cdpUrl is unset", () => { - const resolved = resolveBrowserConfig({ - controlUrl: "http://127.0.0.1:19000", - }); - expect(resolved.controlPort).toBe(19000); - expect(resolved.cdpHost).toBe("127.0.0.1"); - expect(resolved.cdpProtocol).toBe("http"); + const profile = resolveProfile(resolved, "clawd"); + expect(profile?.cdpIsLoopback).toBe(false); }); it("supports explicit CDP URLs for the default profile", () => { const resolved = resolveBrowserConfig({ - controlUrl: "http://127.0.0.1:18791", cdpUrl: "http://example.com:9222", }); const profile = resolveProfile(resolved, "clawd"); @@ -101,7 +113,6 @@ describe("browser config", () => { it("uses profile cdpUrl when provided", () => { const resolved = resolveBrowserConfig({ - controlUrl: "http://127.0.0.1:18791", profiles: { remote: { cdpUrl: "http://10.0.0.42:9222", color: "#0066CC" }, }, @@ -115,7 +126,6 @@ describe("browser config", () => { it("uses base protocol for profiles with only cdpPort", () => { const resolved = resolveBrowserConfig({ - controlUrl: "http://127.0.0.1:18791", cdpUrl: "https://example.com:9443", profiles: { work: { cdpPort: 18801, color: "#0066CC" }, @@ -127,14 +137,11 @@ describe("browser config", () => { }); it("rejects unsupported protocols", () => { - expect(() => resolveBrowserConfig({ controlUrl: "ws://127.0.0.1:18791" })).toThrow( - /must be http/i, - ); + expect(() => resolveBrowserConfig({ cdpUrl: "ws://127.0.0.1:18791" })).toThrow(/must be http/i); }); it("does not add the built-in chrome extension profile if the derived relay port is already used", () => { const resolved = resolveBrowserConfig({ - controlUrl: "http://127.0.0.1:18791", profiles: { clawd: { cdpPort: 18792, color: "#FF4500" }, }, diff --git a/src/browser/config.ts b/src/browser/config.ts index e8e1bb128..4f862db51 100644 --- a/src/browser/config.ts +++ b/src/browser/config.ts @@ -1,11 +1,12 @@ -import type { BrowserConfig, BrowserProfileConfig } from "../config/config.js"; +import type { BrowserConfig, BrowserProfileConfig, ClawdbotConfig } from "../config/config.js"; import { deriveDefaultBrowserCdpPortRange, deriveDefaultBrowserControlPort, + DEFAULT_BROWSER_CONTROL_PORT, } from "../config/port-defaults.js"; +import { resolveGatewayPort } from "../config/paths.js"; import { DEFAULT_CLAWD_BROWSER_COLOR, - DEFAULT_CLAWD_BROWSER_CONTROL_URL, DEFAULT_CLAWD_BROWSER_ENABLED, DEFAULT_BROWSER_DEFAULT_PROFILE_NAME, DEFAULT_CLAWD_BROWSER_PROFILE_NAME, @@ -14,10 +15,7 @@ import { CDP_PORT_RANGE_START, getUsedPorts } from "./profiles.js"; export type ResolvedBrowserConfig = { enabled: boolean; - controlUrl: string; - controlHost: string; controlPort: number; - controlToken?: string; cdpProtocol: "http" | "https"; cdpHost: string; cdpIsLoopback: boolean; @@ -137,24 +135,13 @@ function ensureDefaultChromeExtensionProfile( }; return result; } -export function resolveBrowserConfig(cfg: BrowserConfig | undefined): ResolvedBrowserConfig { +export function resolveBrowserConfig( + cfg: BrowserConfig | undefined, + rootConfig?: ClawdbotConfig, +): ResolvedBrowserConfig { const enabled = cfg?.enabled ?? DEFAULT_CLAWD_BROWSER_ENABLED; - const envControlUrl = process.env.CLAWDBOT_BROWSER_CONTROL_URL?.trim(); - const controlToken = cfg?.controlToken?.trim() || undefined; - const derivedControlPort = (() => { - const raw = process.env.CLAWDBOT_GATEWAY_PORT?.trim(); - if (!raw) return null; - const gatewayPort = Number.parseInt(raw, 10); - if (!Number.isFinite(gatewayPort) || gatewayPort <= 0) return null; - return deriveDefaultBrowserControlPort(gatewayPort); - })(); - const derivedControlUrl = derivedControlPort ? `http://127.0.0.1:${derivedControlPort}` : null; - - const controlInfo = parseHttpUrl( - cfg?.controlUrl ?? envControlUrl ?? derivedControlUrl ?? DEFAULT_CLAWD_BROWSER_CONTROL_URL, - "browser.controlUrl", - ); - const controlPort = controlInfo.port; + const gatewayPort = resolveGatewayPort(rootConfig); + const controlPort = deriveDefaultBrowserControlPort(gatewayPort ?? DEFAULT_BROWSER_CONTROL_PORT); const defaultColor = normalizeHexColor(cfg?.color); const remoteCdpTimeoutMs = normalizeTimeoutMs(cfg?.remoteCdpTimeoutMs, 1500); const remoteCdpHandshakeTimeoutMs = normalizeTimeoutMs( @@ -178,11 +165,10 @@ export function resolveBrowserConfig(cfg: BrowserConfig | undefined): ResolvedBr const derivedPort = controlPort + 1; if (derivedPort > 65535) { throw new Error( - `browser.controlUrl port (${controlPort}) is too high; cannot derive CDP port (${derivedPort})`, + `Derived CDP port (${derivedPort}) is too high; check gateway port configuration.`, ); } - const derived = new URL(controlInfo.normalized); - derived.port = String(derivedPort); + const derived = new URL(`http://127.0.0.1:${derivedPort}`); cdpInfo = { parsed: derived, port: derivedPort, @@ -211,10 +197,7 @@ export function resolveBrowserConfig(cfg: BrowserConfig | undefined): ResolvedBr return { enabled, - controlUrl: controlInfo.normalized, - controlHost: controlInfo.parsed.hostname, controlPort, - ...(controlToken ? { controlToken } : {}), cdpProtocol, cdpHost: cdpInfo.parsed.hostname, cdpIsLoopback: isLoopbackHost(cdpInfo.parsed.hostname), @@ -269,6 +252,6 @@ export function resolveProfile( }; } -export function shouldStartLocalBrowserServer(resolved: ResolvedBrowserConfig) { - return isLoopbackHost(resolved.controlHost); +export function shouldStartLocalBrowserServer(_resolved: ResolvedBrowserConfig) { + return true; } diff --git a/src/browser/constants.ts b/src/browser/constants.ts index 3e8cb60d2..88642a6c5 100644 --- a/src/browser/constants.ts +++ b/src/browser/constants.ts @@ -1,5 +1,4 @@ export const DEFAULT_CLAWD_BROWSER_ENABLED = true; -export const DEFAULT_CLAWD_BROWSER_CONTROL_URL = "http://127.0.0.1:18791"; export const DEFAULT_CLAWD_BROWSER_COLOR = "#FF4500"; export const DEFAULT_CLAWD_BROWSER_PROFILE_NAME = "clawd"; export const DEFAULT_BROWSER_DEFAULT_PROFILE_NAME = "chrome"; diff --git a/src/browser/control-service.ts b/src/browser/control-service.ts new file mode 100644 index 000000000..6c8f3cef2 --- /dev/null +++ b/src/browser/control-service.ts @@ -0,0 +1,80 @@ +import { loadConfig } from "../config/config.js"; +import { createSubsystemLogger } from "../logging/subsystem.js"; +import { resolveBrowserConfig, resolveProfile } from "./config.js"; +import { ensureChromeExtensionRelayServer } from "./extension-relay.js"; +import { type BrowserServerState, createBrowserRouteContext } from "./server-context.js"; + +let state: BrowserServerState | null = null; +const log = createSubsystemLogger("browser"); +const logService = log.child("service"); + +export function getBrowserControlState(): BrowserServerState | null { + return state; +} + +export function createBrowserControlContext() { + return createBrowserRouteContext({ + getState: () => state, + }); +} + +export async function startBrowserControlServiceFromConfig(): Promise { + if (state) return state; + + const cfg = loadConfig(); + const resolved = resolveBrowserConfig(cfg.browser, cfg); + if (!resolved.enabled) return null; + + state = { + server: null, + port: resolved.controlPort, + resolved, + profiles: new Map(), + }; + + // If any profile uses the Chrome extension relay, start the local relay server eagerly + // so the extension can connect before the first browser action. + for (const name of Object.keys(resolved.profiles)) { + const profile = resolveProfile(resolved, name); + if (!profile || profile.driver !== "extension") continue; + await ensureChromeExtensionRelayServer({ cdpUrl: profile.cdpUrl }).catch((err) => { + logService.warn(`Chrome extension relay init failed for profile "${name}": ${String(err)}`); + }); + } + + logService.info( + `Browser control service ready (profiles=${Object.keys(resolved.profiles).length})`, + ); + return state; +} + +export async function stopBrowserControlService(): Promise { + const current = state; + if (!current) return; + + const ctx = createBrowserRouteContext({ + getState: () => state, + }); + + try { + for (const name of Object.keys(current.resolved.profiles)) { + try { + await ctx.forProfile(name).stopRunningBrowser(); + } catch { + // ignore + } + } + } catch (err) { + logService.warn(`clawd browser stop failed: ${String(err)}`); + } + + state = null; + + // Optional: Playwright is not always available (e.g. embedded gateway builds). + try { + const mod = await import("./pw-ai.js"); + await mod.closePlaywrightBrowserConnection(); + } catch { + // ignore + } +} diff --git a/src/browser/profiles-service.test.ts b/src/browser/profiles-service.test.ts index 4092cf655..1daeec2de 100644 --- a/src/browser/profiles-service.test.ts +++ b/src/browser/profiles-service.test.ts @@ -49,9 +49,7 @@ function createCtx(resolved: BrowserServerState["resolved"]) { describe("BrowserProfilesService", () => { it("allocates next local port for new profiles", async () => { - const resolved = resolveBrowserConfig({ - controlUrl: "http://127.0.0.1:18791", - }); + const resolved = resolveBrowserConfig({}); const { ctx, state } = createCtx(resolved); vi.mocked(loadConfig).mockReturnValue({ browser: { profiles: {} } }); @@ -66,9 +64,7 @@ describe("BrowserProfilesService", () => { }); it("accepts per-profile cdpUrl for remote Chrome", async () => { - const resolved = resolveBrowserConfig({ - controlUrl: "http://127.0.0.1:18791", - }); + const resolved = resolveBrowserConfig({}); const { ctx } = createCtx(resolved); vi.mocked(loadConfig).mockReturnValue({ browser: { profiles: {} } }); @@ -97,7 +93,6 @@ describe("BrowserProfilesService", () => { it("deletes remote profiles without stopping or removing local data", async () => { const resolved = resolveBrowserConfig({ - controlUrl: "http://127.0.0.1:18791", profiles: { remote: { cdpUrl: "http://10.0.0.42:9222", color: "#0066CC" }, }, @@ -124,7 +119,6 @@ describe("BrowserProfilesService", () => { it("deletes local profiles and moves data to Trash", async () => { const resolved = resolveBrowserConfig({ - controlUrl: "http://127.0.0.1:18791", profiles: { work: { cdpPort: 18801, color: "#0066CC" }, }, diff --git a/src/browser/routes/agent.act.ts b/src/browser/routes/agent.act.ts index ea681bd25..ae8d274b7 100644 --- a/src/browser/routes/agent.act.ts +++ b/src/browser/routes/agent.act.ts @@ -1,5 +1,3 @@ -import type express from "express"; - import type { BrowserFormField } from "../client-actions-core.js"; import type { BrowserRouteContext } from "../server-context.js"; import { @@ -16,8 +14,12 @@ import { SELECTOR_UNSUPPORTED_MESSAGE, } from "./agent.shared.js"; import { jsonError, toBoolean, toNumber, toStringArray, toStringOrEmpty } from "./utils.js"; +import type { BrowserRouteRegistrar } from "./types.js"; -export function registerBrowserAgentActRoutes(app: express.Express, ctx: BrowserRouteContext) { +export function registerBrowserAgentActRoutes( + app: BrowserRouteRegistrar, + ctx: BrowserRouteContext, +) { app.post("/act", async (req, res) => { const profileCtx = resolveProfileContext(req, res, ctx); if (!profileCtx) return; diff --git a/src/browser/routes/agent.debug.ts b/src/browser/routes/agent.debug.ts index c71bd7b47..2533474f7 100644 --- a/src/browser/routes/agent.debug.ts +++ b/src/browser/routes/agent.debug.ts @@ -2,13 +2,15 @@ import crypto from "node:crypto"; import fs from "node:fs/promises"; import path from "node:path"; -import type express from "express"; - import type { BrowserRouteContext } from "../server-context.js"; import { handleRouteError, readBody, requirePwAi, resolveProfileContext } from "./agent.shared.js"; import { toBoolean, toStringOrEmpty } from "./utils.js"; +import type { BrowserRouteRegistrar } from "./types.js"; -export function registerBrowserAgentDebugRoutes(app: express.Express, ctx: BrowserRouteContext) { +export function registerBrowserAgentDebugRoutes( + app: BrowserRouteRegistrar, + ctx: BrowserRouteContext, +) { app.get("/console", async (req, res) => { const profileCtx = resolveProfileContext(req, res, ctx); if (!profileCtx) return; diff --git a/src/browser/routes/agent.shared.ts b/src/browser/routes/agent.shared.ts index da8c608e3..08b010149 100644 --- a/src/browser/routes/agent.shared.ts +++ b/src/browser/routes/agent.shared.ts @@ -1,9 +1,8 @@ -import type express from "express"; - import type { BrowserRouteContext, ProfileContext } from "../server-context.js"; import type { PwAiModule } from "../pw-ai-module.js"; import { getPwAiModule as getPwAiModuleBase } from "../pw-ai-module.js"; import { getProfileContext, jsonError } from "./utils.js"; +import type { BrowserRequest, BrowserResponse } from "./types.js"; export const SELECTOR_UNSUPPORTED_MESSAGE = [ "Error: 'selector' is not supported. Use 'ref' from snapshot instead.", @@ -15,21 +14,21 @@ export const SELECTOR_UNSUPPORTED_MESSAGE = [ "This is more reliable for modern SPAs.", ].join("\n"); -export function readBody(req: express.Request): Record { +export function readBody(req: BrowserRequest): Record { const body = req.body as Record | undefined; if (!body || typeof body !== "object" || Array.isArray(body)) return {}; return body; } -export function handleRouteError(ctx: BrowserRouteContext, res: express.Response, err: unknown) { +export function handleRouteError(ctx: BrowserRouteContext, res: BrowserResponse, err: unknown) { const mapped = ctx.mapTabError(err); if (mapped) return jsonError(res, mapped.status, mapped.message); jsonError(res, 500, String(err)); } export function resolveProfileContext( - req: express.Request, - res: express.Response, + req: BrowserRequest, + res: BrowserResponse, ctx: BrowserRouteContext, ): ProfileContext | null { const profileCtx = getProfileContext(req, ctx); @@ -45,7 +44,7 @@ export async function getPwAiModule(): Promise { } export async function requirePwAi( - res: express.Response, + res: BrowserResponse, feature: string, ): Promise { const mod = await getPwAiModule(); diff --git a/src/browser/routes/agent.snapshot.ts b/src/browser/routes/agent.snapshot.ts index fdeb7f69e..41ade72ff 100644 --- a/src/browser/routes/agent.snapshot.ts +++ b/src/browser/routes/agent.snapshot.ts @@ -1,7 +1,5 @@ import path from "node:path"; -import type express from "express"; - import { ensureMediaDir, saveMediaBuffer } from "../../media/store.js"; import { captureScreenshot, snapshotAria } from "../cdp.js"; import { @@ -23,8 +21,12 @@ import { resolveProfileContext, } from "./agent.shared.js"; import { jsonError, toBoolean, toNumber, toStringOrEmpty } from "./utils.js"; +import type { BrowserRouteRegistrar } from "./types.js"; -export function registerBrowserAgentSnapshotRoutes(app: express.Express, ctx: BrowserRouteContext) { +export function registerBrowserAgentSnapshotRoutes( + app: BrowserRouteRegistrar, + ctx: BrowserRouteContext, +) { app.post("/navigate", async (req, res) => { const profileCtx = resolveProfileContext(req, res, ctx); if (!profileCtx) return; diff --git a/src/browser/routes/agent.storage.ts b/src/browser/routes/agent.storage.ts index 1f5c137b6..2f1905c22 100644 --- a/src/browser/routes/agent.storage.ts +++ b/src/browser/routes/agent.storage.ts @@ -1,10 +1,12 @@ -import type express from "express"; - import type { BrowserRouteContext } from "../server-context.js"; import { handleRouteError, readBody, requirePwAi, resolveProfileContext } from "./agent.shared.js"; import { jsonError, toBoolean, toNumber, toStringOrEmpty } from "./utils.js"; +import type { BrowserRouteRegistrar } from "./types.js"; -export function registerBrowserAgentStorageRoutes(app: express.Express, ctx: BrowserRouteContext) { +export function registerBrowserAgentStorageRoutes( + app: BrowserRouteRegistrar, + ctx: BrowserRouteContext, +) { app.get("/cookies", async (req, res) => { const profileCtx = resolveProfileContext(req, res, ctx); if (!profileCtx) return; diff --git a/src/browser/routes/agent.ts b/src/browser/routes/agent.ts index b2cf4950c..dc5e65433 100644 --- a/src/browser/routes/agent.ts +++ b/src/browser/routes/agent.ts @@ -1,12 +1,11 @@ -import type express from "express"; - import type { BrowserRouteContext } from "../server-context.js"; import { registerBrowserAgentActRoutes } from "./agent.act.js"; import { registerBrowserAgentDebugRoutes } from "./agent.debug.js"; import { registerBrowserAgentSnapshotRoutes } from "./agent.snapshot.js"; import { registerBrowserAgentStorageRoutes } from "./agent.storage.js"; +import type { BrowserRouteRegistrar } from "./types.js"; -export function registerBrowserAgentRoutes(app: express.Express, ctx: BrowserRouteContext) { +export function registerBrowserAgentRoutes(app: BrowserRouteRegistrar, ctx: BrowserRouteContext) { registerBrowserAgentSnapshotRoutes(app, ctx); registerBrowserAgentActRoutes(app, ctx); registerBrowserAgentDebugRoutes(app, ctx); diff --git a/src/browser/routes/basic.ts b/src/browser/routes/basic.ts index 4b1fcab5c..32be15704 100644 --- a/src/browser/routes/basic.ts +++ b/src/browser/routes/basic.ts @@ -1,11 +1,10 @@ -import type express from "express"; - import { resolveBrowserExecutableForPlatform } from "../chrome.executables.js"; import { createBrowserProfilesService } from "../profiles-service.js"; import type { BrowserRouteContext } from "../server-context.js"; import { getProfileContext, jsonError, toStringOrEmpty } from "./utils.js"; +import type { BrowserRouteRegistrar } from "./types.js"; -export function registerBrowserBasicRoutes(app: express.Express, ctx: BrowserRouteContext) { +export function registerBrowserBasicRoutes(app: BrowserRouteRegistrar, ctx: BrowserRouteContext) { // List all profiles with their status app.get("/profiles", async (_req, res) => { try { @@ -53,7 +52,6 @@ export function registerBrowserBasicRoutes(app: express.Express, ctx: BrowserRou res.json({ enabled: current.resolved.enabled, - controlUrl: current.resolved.controlUrl, profile: profileCtx.profile.name, running: cdpReady, cdpReady, diff --git a/src/browser/routes/dispatcher.ts b/src/browser/routes/dispatcher.ts new file mode 100644 index 000000000..d5a26598d --- /dev/null +++ b/src/browser/routes/dispatcher.ts @@ -0,0 +1,122 @@ +import type { BrowserRouteContext } from "../server-context.js"; +import { registerBrowserRoutes } from "./index.js"; +import type { BrowserRequest, BrowserResponse, BrowserRouteRegistrar } from "./types.js"; + +type BrowserDispatchRequest = { + method: "GET" | "POST" | "DELETE"; + path: string; + query?: Record; + body?: unknown; +}; + +type BrowserDispatchResponse = { + status: number; + body: unknown; +}; + +type RouteEntry = { + method: BrowserDispatchRequest["method"]; + path: string; + regex: RegExp; + paramNames: string[]; + handler: (req: BrowserRequest, res: BrowserResponse) => void | Promise; +}; + +function escapeRegex(value: string) { + return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); +} + +function compileRoute(path: string): { regex: RegExp; paramNames: string[] } { + const paramNames: string[] = []; + const parts = path.split("/").map((part) => { + if (part.startsWith(":")) { + const name = part.slice(1); + paramNames.push(name); + return "([^/]+)"; + } + return escapeRegex(part); + }); + return { regex: new RegExp(`^${parts.join("/")}$`), paramNames }; +} + +function createRegistry() { + const routes: RouteEntry[] = []; + const register = + (method: RouteEntry["method"]) => (path: string, handler: RouteEntry["handler"]) => { + const { regex, paramNames } = compileRoute(path); + routes.push({ method, path, regex, paramNames, handler }); + }; + const router: BrowserRouteRegistrar = { + get: register("GET"), + post: register("POST"), + delete: register("DELETE"), + }; + return { routes, router }; +} + +function normalizePath(path: string) { + if (!path) return "/"; + return path.startsWith("/") ? path : `/${path}`; +} + +export function createBrowserRouteDispatcher(ctx: BrowserRouteContext) { + const registry = createRegistry(); + registerBrowserRoutes(registry.router, ctx); + + return { + dispatch: async (req: BrowserDispatchRequest): Promise => { + const method = req.method; + const path = normalizePath(req.path); + const query = req.query ?? {}; + const body = req.body; + + const match = registry.routes.find((route) => { + if (route.method !== method) return false; + return route.regex.test(path); + }); + if (!match) { + return { status: 404, body: { error: "Not Found" } }; + } + + const exec = match.regex.exec(path); + const params: Record = {}; + if (exec) { + for (const [idx, name] of match.paramNames.entries()) { + const value = exec[idx + 1]; + if (typeof value === "string") { + params[name] = decodeURIComponent(value); + } + } + } + + let status = 200; + let payload: unknown = undefined; + const res: BrowserResponse = { + status(code) { + status = code; + return res; + }, + json(bodyValue) { + payload = bodyValue; + }, + }; + + try { + await match.handler( + { + params, + query, + body, + }, + res, + ); + } catch (err) { + return { status: 500, body: { error: String(err) } }; + } + + return { status, body: payload }; + }, + }; +} + +export type { BrowserDispatchRequest, BrowserDispatchResponse }; diff --git a/src/browser/routes/index.ts b/src/browser/routes/index.ts index df435ffb8..3c20ef1c6 100644 --- a/src/browser/routes/index.ts +++ b/src/browser/routes/index.ts @@ -1,11 +1,10 @@ -import type express from "express"; - import type { BrowserRouteContext } from "../server-context.js"; import { registerBrowserAgentRoutes } from "./agent.js"; import { registerBrowserBasicRoutes } from "./basic.js"; import { registerBrowserTabRoutes } from "./tabs.js"; +import type { BrowserRouteRegistrar } from "./types.js"; -export function registerBrowserRoutes(app: express.Express, ctx: BrowserRouteContext) { +export function registerBrowserRoutes(app: BrowserRouteRegistrar, ctx: BrowserRouteContext) { registerBrowserBasicRoutes(app, ctx); registerBrowserTabRoutes(app, ctx); registerBrowserAgentRoutes(app, ctx); diff --git a/src/browser/routes/tabs.ts b/src/browser/routes/tabs.ts index 44596be85..e510dd521 100644 --- a/src/browser/routes/tabs.ts +++ b/src/browser/routes/tabs.ts @@ -1,9 +1,8 @@ -import type express from "express"; - import type { BrowserRouteContext } from "../server-context.js"; import { getProfileContext, jsonError, toNumber, toStringOrEmpty } from "./utils.js"; +import type { BrowserRouteRegistrar } from "./types.js"; -export function registerBrowserTabRoutes(app: express.Express, ctx: BrowserRouteContext) { +export function registerBrowserTabRoutes(app: BrowserRouteRegistrar, ctx: BrowserRouteContext) { app.get("/tabs", async (req, res) => { const profileCtx = getProfileContext(req, ctx); if ("error" in profileCtx) return jsonError(res, profileCtx.status, profileCtx.error); diff --git a/src/browser/routes/types.ts b/src/browser/routes/types.ts new file mode 100644 index 000000000..76e6051c9 --- /dev/null +++ b/src/browser/routes/types.ts @@ -0,0 +1,21 @@ +export type BrowserRequest = { + params: Record; + query: Record; + body?: unknown; +}; + +export type BrowserResponse = { + status: (code: number) => BrowserResponse; + json: (body: unknown) => void; +}; + +export type BrowserRouteHandler = ( + req: BrowserRequest, + res: BrowserResponse, +) => void | Promise; + +export type BrowserRouteRegistrar = { + get: (path: string, handler: BrowserRouteHandler) => void; + post: (path: string, handler: BrowserRouteHandler) => void; + delete: (path: string, handler: BrowserRouteHandler) => void; +}; diff --git a/src/browser/routes/utils.ts b/src/browser/routes/utils.ts index 1c6e37fc5..ad510da4b 100644 --- a/src/browser/routes/utils.ts +++ b/src/browser/routes/utils.ts @@ -1,14 +1,13 @@ -import type express from "express"; - import type { BrowserRouteContext, ProfileContext } from "../server-context.js"; import { parseBooleanValue } from "../../utils/boolean.js"; +import type { BrowserRequest, BrowserResponse } from "./types.js"; /** * Extract profile name from query string or body and get profile context. * Query string takes precedence over body for consistency with GET routes. */ export function getProfileContext( - req: express.Request, + req: BrowserRequest, ctx: BrowserRouteContext, ): ProfileContext | { error: string; status: number } { let profileName: string | undefined; @@ -33,7 +32,7 @@ export function getProfileContext( } } -export function jsonError(res: express.Response, status: number, message: string) { +export function jsonError(res: BrowserResponse, status: number, message: string) { res.status(status).json({ error: message }); } diff --git a/src/browser/server-context.ensure-tab-available.prefers-last-target.test.ts b/src/browser/server-context.ensure-tab-available.prefers-last-target.test.ts index 4863cc1fe..5d9555387 100644 --- a/src/browser/server-context.ensure-tab-available.prefers-last-target.test.ts +++ b/src/browser/server-context.ensure-tab-available.prefers-last-target.test.ts @@ -62,8 +62,6 @@ describe("browser server-context ensureTabAvailable", () => { port: 0, resolved: { enabled: true, - controlUrl: "http://127.0.0.1:18791", - controlHost: "127.0.0.1", controlPort: 18791, cdpProtocol: "http", cdpHost: "127.0.0.1", @@ -121,8 +119,6 @@ describe("browser server-context ensureTabAvailable", () => { port: 0, resolved: { enabled: true, - controlUrl: "http://127.0.0.1:18791", - controlHost: "127.0.0.1", controlPort: 18791, cdpProtocol: "http", cdpHost: "127.0.0.1", @@ -170,8 +166,6 @@ describe("browser server-context ensureTabAvailable", () => { port: 0, resolved: { enabled: true, - controlUrl: "http://127.0.0.1:18791", - controlHost: "127.0.0.1", controlPort: 18791, cdpProtocol: "http", cdpHost: "127.0.0.1", diff --git a/src/browser/server-context.remote-tab-ops.test.ts b/src/browser/server-context.remote-tab-ops.test.ts index 379394497..b3cdb38f9 100644 --- a/src/browser/server-context.remote-tab-ops.test.ts +++ b/src/browser/server-context.remote-tab-ops.test.ts @@ -21,8 +21,6 @@ function makeState( port: 0, resolved: { enabled: true, - controlUrl: "http://127.0.0.1:18791", - controlHost: "127.0.0.1", controlPort: 18791, cdpProtocol: profile === "remote" ? "https" : "http", cdpHost: profile === "remote" ? "browserless.example" : "127.0.0.1", diff --git a/src/browser/server-context.types.ts b/src/browser/server-context.types.ts index 6532010e9..7fa6d273a 100644 --- a/src/browser/server-context.types.ts +++ b/src/browser/server-context.types.ts @@ -17,7 +17,7 @@ export type ProfileRuntimeState = { }; export type BrowserServerState = { - server: Server; + server?: Server | null; port: number; resolved: ResolvedBrowserConfig; profiles: Map; diff --git a/src/browser/server.agent-contract-form-layout-act-commands.test.ts b/src/browser/server.agent-contract-form-layout-act-commands.test.ts index cbff6dca5..87293a9a3 100644 --- a/src/browser/server.agent-contract-form-layout-act-commands.test.ts +++ b/src/browser/server.agent-contract-form-layout-act-commands.test.ts @@ -8,6 +8,7 @@ let cdpBaseUrl = ""; let reachable = false; let cfgAttachOnly = false; let createTargetId: string | null = null; +let prevGatewayPort: string | undefined; const cdpMocks = vi.hoisted(() => ({ createTargetViaCdp: vi.fn(async () => { @@ -88,7 +89,6 @@ vi.mock("../config/config.js", async (importOriginal) => { loadConfig: () => ({ browser: { enabled: true, - controlUrl: `http://127.0.0.1:${testPort}`, color: "#FF4500", attachOnly: cfgAttachOnly, headless: true, @@ -197,6 +197,8 @@ describe("browser control server", () => { testPort = await getFreePort(); cdpBaseUrl = `http://127.0.0.1:${testPort + 1}`; + prevGatewayPort = process.env.CLAWDBOT_GATEWAY_PORT; + process.env.CLAWDBOT_GATEWAY_PORT = String(testPort - 2); // Minimal CDP JSON endpoints used by the server. let putNewCalls = 0; @@ -248,6 +250,11 @@ describe("browser control server", () => { afterEach(async () => { vi.unstubAllGlobals(); vi.restoreAllMocks(); + if (prevGatewayPort === undefined) { + delete process.env.CLAWDBOT_GATEWAY_PORT; + } else { + process.env.CLAWDBOT_GATEWAY_PORT = prevGatewayPort; + } const { stopBrowserControlServer } = await import("./server.js"); await stopBrowserControlServer(); }); diff --git a/src/browser/server.agent-contract-snapshot-endpoints.test.ts b/src/browser/server.agent-contract-snapshot-endpoints.test.ts index 65a86facb..494d64657 100644 --- a/src/browser/server.agent-contract-snapshot-endpoints.test.ts +++ b/src/browser/server.agent-contract-snapshot-endpoints.test.ts @@ -9,6 +9,7 @@ let cdpBaseUrl = ""; let reachable = false; let cfgAttachOnly = false; let createTargetId: string | null = null; +let prevGatewayPort: string | undefined; const cdpMocks = vi.hoisted(() => ({ createTargetViaCdp: vi.fn(async () => { @@ -89,7 +90,6 @@ vi.mock("../config/config.js", async (importOriginal) => { loadConfig: () => ({ browser: { enabled: true, - controlUrl: `http://127.0.0.1:${testPort}`, color: "#FF4500", attachOnly: cfgAttachOnly, headless: true, @@ -198,6 +198,8 @@ describe("browser control server", () => { testPort = await getFreePort(); cdpBaseUrl = `http://127.0.0.1:${testPort + 1}`; + prevGatewayPort = process.env.CLAWDBOT_GATEWAY_PORT; + process.env.CLAWDBOT_GATEWAY_PORT = String(testPort - 2); // Minimal CDP JSON endpoints used by the server. let putNewCalls = 0; @@ -249,6 +251,11 @@ describe("browser control server", () => { afterEach(async () => { vi.unstubAllGlobals(); vi.restoreAllMocks(); + if (prevGatewayPort === undefined) { + delete process.env.CLAWDBOT_GATEWAY_PORT; + } else { + process.env.CLAWDBOT_GATEWAY_PORT = prevGatewayPort; + } const { stopBrowserControlServer } = await import("./server.js"); await stopBrowserControlServer(); }); diff --git a/src/browser/server.covers-additional-endpoint-branches.test.ts b/src/browser/server.covers-additional-endpoint-branches.test.ts index bc16040cf..ee5463ab5 100644 --- a/src/browser/server.covers-additional-endpoint-branches.test.ts +++ b/src/browser/server.covers-additional-endpoint-branches.test.ts @@ -8,6 +8,7 @@ let _cdpBaseUrl = ""; let reachable = false; let cfgAttachOnly = false; let createTargetId: string | null = null; +let prevGatewayPort: string | undefined; const cdpMocks = vi.hoisted(() => ({ createTargetViaCdp: vi.fn(async () => { @@ -88,7 +89,6 @@ vi.mock("../config/config.js", async (importOriginal) => { loadConfig: () => ({ browser: { enabled: true, - controlUrl: `http://127.0.0.1:${testPort}`, color: "#FF4500", attachOnly: cfgAttachOnly, headless: true, @@ -197,6 +197,8 @@ describe("browser control server", () => { testPort = await getFreePort(); _cdpBaseUrl = `http://127.0.0.1:${testPort + 1}`; + prevGatewayPort = process.env.CLAWDBOT_GATEWAY_PORT; + process.env.CLAWDBOT_GATEWAY_PORT = String(testPort - 2); // Minimal CDP JSON endpoints used by the server. let putNewCalls = 0; @@ -248,6 +250,11 @@ describe("browser control server", () => { afterEach(async () => { vi.unstubAllGlobals(); vi.restoreAllMocks(); + if (prevGatewayPort === undefined) { + delete process.env.CLAWDBOT_GATEWAY_PORT; + } else { + process.env.CLAWDBOT_GATEWAY_PORT = prevGatewayPort; + } const { stopBrowserControlServer } = await import("./server.js"); await stopBrowserControlServer(); }); diff --git a/src/browser/server.post-tabs-open-profile-unknown-returns-404.test.ts b/src/browser/server.post-tabs-open-profile-unknown-returns-404.test.ts index 4908a536c..f178858a7 100644 --- a/src/browser/server.post-tabs-open-profile-unknown-returns-404.test.ts +++ b/src/browser/server.post-tabs-open-profile-unknown-returns-404.test.ts @@ -8,6 +8,7 @@ let _cdpBaseUrl = ""; let reachable = false; let cfgAttachOnly = false; let createTargetId: string | null = null; +let prevGatewayPort: string | undefined; const cdpMocks = vi.hoisted(() => ({ createTargetViaCdp: vi.fn(async () => { @@ -88,7 +89,6 @@ vi.mock("../config/config.js", async (importOriginal) => { loadConfig: () => ({ browser: { enabled: true, - controlUrl: `http://127.0.0.1:${testPort}`, color: "#FF4500", attachOnly: cfgAttachOnly, headless: true, @@ -197,6 +197,8 @@ describe("browser control server", () => { testPort = await getFreePort(); _cdpBaseUrl = `http://127.0.0.1:${testPort + 1}`; + prevGatewayPort = process.env.CLAWDBOT_GATEWAY_PORT; + process.env.CLAWDBOT_GATEWAY_PORT = String(testPort - 2); // Minimal CDP JSON endpoints used by the server. let putNewCalls = 0; @@ -248,6 +250,11 @@ describe("browser control server", () => { afterEach(async () => { vi.unstubAllGlobals(); vi.restoreAllMocks(); + if (prevGatewayPort === undefined) { + delete process.env.CLAWDBOT_GATEWAY_PORT; + } else { + process.env.CLAWDBOT_GATEWAY_PORT = prevGatewayPort; + } const { stopBrowserControlServer } = await import("./server.js"); await stopBrowserControlServer(); }); diff --git a/src/browser/server.serves-status-starts-browser-requested.test.ts b/src/browser/server.serves-status-starts-browser-requested.test.ts index 8cfcca40e..41ea6ab47 100644 --- a/src/browser/server.serves-status-starts-browser-requested.test.ts +++ b/src/browser/server.serves-status-starts-browser-requested.test.ts @@ -8,6 +8,7 @@ let _cdpBaseUrl = ""; let reachable = false; let cfgAttachOnly = false; let createTargetId: string | null = null; +let prevGatewayPort: string | undefined; const cdpMocks = vi.hoisted(() => ({ createTargetViaCdp: vi.fn(async () => { @@ -88,7 +89,6 @@ vi.mock("../config/config.js", async (importOriginal) => { loadConfig: () => ({ browser: { enabled: true, - controlUrl: `http://127.0.0.1:${testPort}`, color: "#FF4500", attachOnly: cfgAttachOnly, headless: true, @@ -197,6 +197,8 @@ describe("browser control server", () => { testPort = await getFreePort(); _cdpBaseUrl = `http://127.0.0.1:${testPort + 1}`; + prevGatewayPort = process.env.CLAWDBOT_GATEWAY_PORT; + process.env.CLAWDBOT_GATEWAY_PORT = String(testPort - 2); // Minimal CDP JSON endpoints used by the server. let putNewCalls = 0; @@ -248,6 +250,11 @@ describe("browser control server", () => { afterEach(async () => { vi.unstubAllGlobals(); vi.restoreAllMocks(); + if (prevGatewayPort === undefined) { + delete process.env.CLAWDBOT_GATEWAY_PORT; + } else { + process.env.CLAWDBOT_GATEWAY_PORT = prevGatewayPort; + } const { stopBrowserControlServer } = await import("./server.js"); await stopBrowserControlServer(); }); diff --git a/src/browser/server.skips-default-maxchars-explicitly-set-zero.test.ts b/src/browser/server.skips-default-maxchars-explicitly-set-zero.test.ts index d50313413..ed4d4f9f5 100644 --- a/src/browser/server.skips-default-maxchars-explicitly-set-zero.test.ts +++ b/src/browser/server.skips-default-maxchars-explicitly-set-zero.test.ts @@ -8,6 +8,7 @@ let cdpBaseUrl = ""; let reachable = false; let cfgAttachOnly = false; let createTargetId: string | null = null; +let prevGatewayPort: string | undefined; const cdpMocks = vi.hoisted(() => ({ createTargetViaCdp: vi.fn(async () => { @@ -88,7 +89,6 @@ vi.mock("../config/config.js", async (importOriginal) => { loadConfig: () => ({ browser: { enabled: true, - controlUrl: `http://127.0.0.1:${testPort}`, color: "#FF4500", attachOnly: cfgAttachOnly, headless: true, @@ -197,6 +197,8 @@ describe("browser control server", () => { testPort = await getFreePort(); cdpBaseUrl = `http://127.0.0.1:${testPort + 1}`; + prevGatewayPort = process.env.CLAWDBOT_GATEWAY_PORT; + process.env.CLAWDBOT_GATEWAY_PORT = String(testPort - 2); // Minimal CDP JSON endpoints used by the server. let putNewCalls = 0; @@ -248,6 +250,11 @@ describe("browser control server", () => { afterEach(async () => { vi.unstubAllGlobals(); vi.restoreAllMocks(); + if (prevGatewayPort === undefined) { + delete process.env.CLAWDBOT_GATEWAY_PORT; + } else { + process.env.CLAWDBOT_GATEWAY_PORT = prevGatewayPort; + } const { stopBrowserControlServer } = await import("./server.js"); await stopBrowserControlServer(); }); @@ -394,8 +401,6 @@ describe("browser control server", () => { const bridge = await startBrowserBridgeServer({ resolved: { enabled: true, - controlUrl: "http://127.0.0.1:0", - controlHost: "127.0.0.1", controlPort: 0, cdpProtocol: "http", cdpHost: "127.0.0.1", diff --git a/src/browser/server.ts b/src/browser/server.ts index 9fb9a5f81..8eda99508 100644 --- a/src/browser/server.ts +++ b/src/browser/server.ts @@ -3,9 +3,10 @@ import express from "express"; import { loadConfig } from "../config/config.js"; import { createSubsystemLogger } from "../logging/subsystem.js"; -import { resolveBrowserConfig, resolveProfile, shouldStartLocalBrowserServer } from "./config.js"; +import { resolveBrowserConfig, resolveProfile } from "./config.js"; import { ensureChromeExtensionRelayServer } from "./extension-relay.js"; import { registerBrowserRoutes } from "./routes/index.js"; +import type { BrowserRouteRegistrar } from "./routes/types.js"; import { type BrowserServerState, createBrowserRouteContext } from "./server-context.js"; let state: BrowserServerState | null = null; @@ -16,23 +17,16 @@ export async function startBrowserControlServerFromConfig(): Promise state, }); - registerBrowserRoutes(app, ctx); + registerBrowserRoutes(app as unknown as BrowserRouteRegistrar, ctx); const port = resolved.controlPort; const server = await new Promise((resolve, reject) => { @@ -89,9 +83,11 @@ export async function stopBrowserControlServer(): Promise { logServer.warn(`clawd browser stop failed: ${String(err)}`); } - await new Promise((resolve) => { - current.server.close(() => resolve()); - }); + if (current.server) { + await new Promise((resolve) => { + current.server?.close(() => resolve()); + }); + } state = null; // Optional: Playwright is not always available (e.g. embedded gateway builds). diff --git a/src/cli/browser-cli-actions-input/register.element.ts b/src/cli/browser-cli-actions-input/register.element.ts index da313cf24..c018e7e24 100644 --- a/src/cli/browser-cli-actions-input/register.element.ts +++ b/src/cli/browser-cli-actions-input/register.element.ts @@ -1,9 +1,8 @@ import type { Command } from "commander"; -import { browserAct } from "../../browser/client-actions.js"; import { danger } from "../../globals.js"; import { defaultRuntime } from "../../runtime.js"; import type { BrowserParentOpts } from "../browser-cli-shared.js"; -import { requireRef, resolveBrowserActionContext } from "./shared.js"; +import { callBrowserAct, requireRef, resolveBrowserActionContext } from "./shared.js"; export function registerBrowserElementCommands( browser: Command, @@ -18,7 +17,7 @@ export function registerBrowserElementCommands( .option("--button ", "Mouse button to use") .option("--modifiers ", "Comma-separated modifiers (Shift,Alt,Meta)") .action(async (ref: string | undefined, opts, cmd) => { - const { parent, baseUrl, profile } = resolveBrowserActionContext(cmd, parentOpts); + const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts); const refValue = requireRef(ref); if (!refValue) return; const modifiers = opts.modifiers @@ -28,9 +27,10 @@ export function registerBrowserElementCommands( .filter(Boolean) : undefined; try { - const result = await browserAct( - baseUrl, - { + const result = await callBrowserAct({ + parent, + profile, + body: { kind: "click", ref: refValue, targetId: opts.targetId?.trim() || undefined, @@ -38,8 +38,7 @@ export function registerBrowserElementCommands( button: opts.button?.trim() || undefined, modifiers, }, - { profile }, - ); + }); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -61,13 +60,14 @@ export function registerBrowserElementCommands( .option("--slowly", "Type slowly (human-like)", false) .option("--target-id ", "CDP target id (or unique prefix)") .action(async (ref: string | undefined, text: string, opts, cmd) => { - const { parent, baseUrl, profile } = resolveBrowserActionContext(cmd, parentOpts); + const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts); const refValue = requireRef(ref); if (!refValue) return; try { - const result = await browserAct( - baseUrl, - { + const result = await callBrowserAct({ + parent, + profile, + body: { kind: "type", ref: refValue, text, @@ -75,8 +75,7 @@ export function registerBrowserElementCommands( slowly: Boolean(opts.slowly), targetId: opts.targetId?.trim() || undefined, }, - { profile }, - ); + }); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -94,13 +93,13 @@ export function registerBrowserElementCommands( .argument("", "Key to press (e.g. Enter)") .option("--target-id ", "CDP target id (or unique prefix)") .action(async (key: string, opts, cmd) => { - const { parent, baseUrl, profile } = resolveBrowserActionContext(cmd, parentOpts); + const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts); try { - const result = await browserAct( - baseUrl, - { kind: "press", key, targetId: opts.targetId?.trim() || undefined }, - { profile }, - ); + const result = await callBrowserAct({ + parent, + profile, + body: { kind: "press", key, targetId: opts.targetId?.trim() || undefined }, + }); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -118,13 +117,13 @@ export function registerBrowserElementCommands( .argument("", "Ref id from snapshot") .option("--target-id ", "CDP target id (or unique prefix)") .action(async (ref: string, opts, cmd) => { - const { parent, baseUrl, profile } = resolveBrowserActionContext(cmd, parentOpts); + const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts); try { - const result = await browserAct( - baseUrl, - { kind: "hover", ref, targetId: opts.targetId?.trim() || undefined }, - { profile }, - ); + const result = await callBrowserAct({ + parent, + profile, + body: { kind: "hover", ref, targetId: opts.targetId?.trim() || undefined }, + }); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -145,20 +144,21 @@ export function registerBrowserElementCommands( Number(v), ) .action(async (ref: string | undefined, opts, cmd) => { - const { parent, baseUrl, profile } = resolveBrowserActionContext(cmd, parentOpts); + const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts); const refValue = requireRef(ref); if (!refValue) return; try { - const result = await browserAct( - baseUrl, - { + const result = await callBrowserAct({ + parent, + profile, + body: { kind: "scrollIntoView", ref: refValue, targetId: opts.targetId?.trim() || undefined, timeoutMs: Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : undefined, }, - { profile }, - ); + timeoutMs: Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : undefined, + }); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -177,18 +177,18 @@ export function registerBrowserElementCommands( .argument("", "End ref id") .option("--target-id ", "CDP target id (or unique prefix)") .action(async (startRef: string, endRef: string, opts, cmd) => { - const { parent, baseUrl, profile } = resolveBrowserActionContext(cmd, parentOpts); + const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts); try { - const result = await browserAct( - baseUrl, - { + const result = await callBrowserAct({ + parent, + profile, + body: { kind: "drag", startRef, endRef, targetId: opts.targetId?.trim() || undefined, }, - { profile }, - ); + }); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -207,18 +207,18 @@ export function registerBrowserElementCommands( .argument("", "Option values to select") .option("--target-id ", "CDP target id (or unique prefix)") .action(async (ref: string, values: string[], opts, cmd) => { - const { parent, baseUrl, profile } = resolveBrowserActionContext(cmd, parentOpts); + const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts); try { - const result = await browserAct( - baseUrl, - { + const result = await callBrowserAct({ + parent, + profile, + body: { kind: "select", ref, values, targetId: opts.targetId?.trim() || undefined, }, - { profile }, - ); + }); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; diff --git a/src/cli/browser-cli-actions-input/register.files-downloads.ts b/src/cli/browser-cli-actions-input/register.files-downloads.ts index ffad3faa9..baa3c71a1 100644 --- a/src/cli/browser-cli-actions-input/register.files-downloads.ts +++ b/src/cli/browser-cli-actions-input/register.files-downloads.ts @@ -1,13 +1,7 @@ import type { Command } from "commander"; -import { - browserArmDialog, - browserArmFileChooser, - browserDownload, - browserWaitForDownload, -} from "../../browser/client-actions.js"; import { danger } from "../../globals.js"; import { defaultRuntime } from "../../runtime.js"; -import type { BrowserParentOpts } from "../browser-cli-shared.js"; +import { callBrowserRequest, type BrowserParentOpts } from "../browser-cli-shared.js"; import { resolveBrowserActionContext } from "./shared.js"; import { shortenHomePath } from "../../utils.js"; @@ -29,17 +23,26 @@ export function registerBrowserFilesAndDownloadsCommands( (v: string) => Number(v), ) .action(async (paths: string[], opts, cmd) => { - const { parent, baseUrl, profile } = resolveBrowserActionContext(cmd, parentOpts); + const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts); try { - const result = await browserArmFileChooser(baseUrl, { - paths, - ref: opts.ref?.trim() || undefined, - inputRef: opts.inputRef?.trim() || undefined, - element: opts.element?.trim() || undefined, - targetId: opts.targetId?.trim() || undefined, - timeoutMs: Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : undefined, - profile, - }); + const timeoutMs = Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : undefined; + const result = await callBrowserRequest( + parent, + { + method: "POST", + path: "/hooks/file-chooser", + query: profile ? { profile } : undefined, + body: { + paths, + ref: opts.ref?.trim() || undefined, + inputRef: opts.inputRef?.trim() || undefined, + element: opts.element?.trim() || undefined, + targetId: opts.targetId?.trim() || undefined, + timeoutMs, + }, + }, + { timeoutMs: timeoutMs ?? 20000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -62,14 +65,23 @@ export function registerBrowserFilesAndDownloadsCommands( (v: string) => Number(v), ) .action(async (outPath: string | undefined, opts, cmd) => { - const { parent, baseUrl, profile } = resolveBrowserActionContext(cmd, parentOpts); + const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts); try { - const result = await browserWaitForDownload(baseUrl, { - path: outPath?.trim() || undefined, - targetId: opts.targetId?.trim() || undefined, - timeoutMs: Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : undefined, - profile, - }); + const timeoutMs = Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : undefined; + const result = await callBrowserRequest( + parent, + { + method: "POST", + path: "/wait/download", + query: profile ? { profile } : undefined, + body: { + path: outPath?.trim() || undefined, + targetId: opts.targetId?.trim() || undefined, + timeoutMs, + }, + }, + { timeoutMs: timeoutMs ?? 20000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -93,15 +105,24 @@ export function registerBrowserFilesAndDownloadsCommands( (v: string) => Number(v), ) .action(async (ref: string, outPath: string, opts, cmd) => { - const { parent, baseUrl, profile } = resolveBrowserActionContext(cmd, parentOpts); + const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts); try { - const result = await browserDownload(baseUrl, { - ref, - path: outPath, - targetId: opts.targetId?.trim() || undefined, - timeoutMs: Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : undefined, - profile, - }); + const timeoutMs = Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : undefined; + const result = await callBrowserRequest( + parent, + { + method: "POST", + path: "/download", + query: profile ? { profile } : undefined, + body: { + ref, + path: outPath, + targetId: opts.targetId?.trim() || undefined, + timeoutMs, + }, + }, + { timeoutMs: timeoutMs ?? 20000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -126,7 +147,7 @@ export function registerBrowserFilesAndDownloadsCommands( (v: string) => Number(v), ) .action(async (opts, cmd) => { - const { parent, baseUrl, profile } = resolveBrowserActionContext(cmd, parentOpts); + const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts); const accept = opts.accept ? true : opts.dismiss ? false : undefined; if (accept === undefined) { defaultRuntime.error(danger("Specify --accept or --dismiss")); @@ -134,13 +155,22 @@ export function registerBrowserFilesAndDownloadsCommands( return; } try { - const result = await browserArmDialog(baseUrl, { - accept, - promptText: opts.prompt?.trim() || undefined, - targetId: opts.targetId?.trim() || undefined, - timeoutMs: Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : undefined, - profile, - }); + const timeoutMs = Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : undefined; + const result = await callBrowserRequest( + parent, + { + method: "POST", + path: "/hooks/dialog", + query: profile ? { profile } : undefined, + body: { + accept, + promptText: opts.prompt?.trim() || undefined, + targetId: opts.targetId?.trim() || undefined, + timeoutMs, + }, + }, + { timeoutMs: timeoutMs ?? 20000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; diff --git a/src/cli/browser-cli-actions-input/register.form-wait-eval.ts b/src/cli/browser-cli-actions-input/register.form-wait-eval.ts index 0a72423dc..f71662700 100644 --- a/src/cli/browser-cli-actions-input/register.form-wait-eval.ts +++ b/src/cli/browser-cli-actions-input/register.form-wait-eval.ts @@ -1,9 +1,8 @@ import type { Command } from "commander"; -import { browserAct } from "../../browser/client-actions.js"; import { danger } from "../../globals.js"; import { defaultRuntime } from "../../runtime.js"; import type { BrowserParentOpts } from "../browser-cli-shared.js"; -import { readFields, resolveBrowserActionContext } from "./shared.js"; +import { callBrowserAct, readFields, resolveBrowserActionContext } from "./shared.js"; export function registerBrowserFormWaitEvalCommands( browser: Command, @@ -16,21 +15,21 @@ export function registerBrowserFormWaitEvalCommands( .option("--fields-file ", "Read JSON array from a file") .option("--target-id ", "CDP target id (or unique prefix)") .action(async (opts, cmd) => { - const { parent, baseUrl, profile } = resolveBrowserActionContext(cmd, parentOpts); + const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts); try { const fields = await readFields({ fields: opts.fields, fieldsFile: opts.fieldsFile, }); - const result = await browserAct( - baseUrl, - { + const result = await callBrowserAct({ + parent, + profile, + body: { kind: "fill", fields, targetId: opts.targetId?.trim() || undefined, }, - { profile }, - ); + }); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -59,16 +58,18 @@ export function registerBrowserFormWaitEvalCommands( ) .option("--target-id ", "CDP target id (or unique prefix)") .action(async (selector: string | undefined, opts, cmd) => { - const { parent, baseUrl, profile } = resolveBrowserActionContext(cmd, parentOpts); + const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts); try { const sel = selector?.trim() || undefined; const load = opts.load === "load" || opts.load === "domcontentloaded" || opts.load === "networkidle" ? (opts.load as "load" | "domcontentloaded" | "networkidle") : undefined; - const result = await browserAct( - baseUrl, - { + const timeoutMs = Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : undefined; + const result = await callBrowserAct({ + parent, + profile, + body: { kind: "wait", timeMs: Number.isFinite(opts.time) ? opts.time : undefined, text: opts.text?.trim() || undefined, @@ -78,10 +79,10 @@ export function registerBrowserFormWaitEvalCommands( loadState: load, fn: opts.fn?.trim() || undefined, targetId: opts.targetId?.trim() || undefined, - timeoutMs: Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : undefined, + timeoutMs, }, - { profile }, - ); + timeoutMs, + }); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -100,23 +101,23 @@ export function registerBrowserFormWaitEvalCommands( .option("--ref ", "Ref from snapshot") .option("--target-id ", "CDP target id (or unique prefix)") .action(async (opts, cmd) => { - const { parent, baseUrl, profile } = resolveBrowserActionContext(cmd, parentOpts); + const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts); if (!opts.fn) { defaultRuntime.error(danger("Missing --fn")); defaultRuntime.exit(1); return; } try { - const result = await browserAct( - baseUrl, - { + const result = await callBrowserAct({ + parent, + profile, + body: { kind: "evaluate", fn: opts.fn, ref: opts.ref?.trim() || undefined, targetId: opts.targetId?.trim() || undefined, }, - { profile }, - ); + }); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; diff --git a/src/cli/browser-cli-actions-input/register.navigation.ts b/src/cli/browser-cli-actions-input/register.navigation.ts index af7b76cd8..5ab7247c3 100644 --- a/src/cli/browser-cli-actions-input/register.navigation.ts +++ b/src/cli/browser-cli-actions-input/register.navigation.ts @@ -1,8 +1,7 @@ import type { Command } from "commander"; -import { browserAct, browserNavigate } from "../../browser/client-actions.js"; import { danger } from "../../globals.js"; import { defaultRuntime } from "../../runtime.js"; -import type { BrowserParentOpts } from "../browser-cli-shared.js"; +import { callBrowserRequest, type BrowserParentOpts } from "../browser-cli-shared.js"; import { requireRef, resolveBrowserActionContext } from "./shared.js"; export function registerBrowserNavigationCommands( @@ -15,13 +14,21 @@ export function registerBrowserNavigationCommands( .argument("", "URL to navigate to") .option("--target-id ", "CDP target id (or unique prefix)") .action(async (url: string, opts, cmd) => { - const { parent, baseUrl, profile } = resolveBrowserActionContext(cmd, parentOpts); + const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts); try { - const result = await browserNavigate(baseUrl, { - url, - targetId: opts.targetId?.trim() || undefined, - profile, - }); + const result = await callBrowserRequest<{ url?: string }>( + parent, + { + method: "POST", + path: "/navigate", + query: profile ? { profile } : undefined, + body: { + url, + targetId: opts.targetId?.trim() || undefined, + }, + }, + { timeoutMs: 20000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -40,22 +47,27 @@ export function registerBrowserNavigationCommands( .argument("", "Viewport height", (v: string) => Number(v)) .option("--target-id ", "CDP target id (or unique prefix)") .action(async (width: number, height: number, opts, cmd) => { - const { parent, baseUrl, profile } = resolveBrowserActionContext(cmd, parentOpts); + const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts); if (!Number.isFinite(width) || !Number.isFinite(height)) { defaultRuntime.error(danger("width and height must be numbers")); defaultRuntime.exit(1); return; } try { - const result = await browserAct( - baseUrl, + const result = await callBrowserRequest( + parent, { - kind: "resize", - width, - height, - targetId: opts.targetId?.trim() || undefined, + method: "POST", + path: "/act", + query: profile ? { profile } : undefined, + body: { + kind: "resize", + width, + height, + targetId: opts.targetId?.trim() || undefined, + }, }, - { profile }, + { timeoutMs: 20000 }, ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); diff --git a/src/cli/browser-cli-actions-input/shared.ts b/src/cli/browser-cli-actions-input/shared.ts index 7bed18736..a04449d54 100644 --- a/src/cli/browser-cli-actions-input/shared.ts +++ b/src/cli/browser-cli-actions-input/shared.ts @@ -1,13 +1,11 @@ import type { Command } from "commander"; -import { resolveBrowserControlUrl } from "../../browser/client.js"; import type { BrowserFormField } from "../../browser/client-actions-core.js"; import { danger } from "../../globals.js"; import { defaultRuntime } from "../../runtime.js"; -import type { BrowserParentOpts } from "../browser-cli-shared.js"; +import { callBrowserRequest, type BrowserParentOpts } from "../browser-cli-shared.js"; export type BrowserActionContext = { parent: BrowserParentOpts; - baseUrl: string; profile: string | undefined; }; @@ -16,9 +14,26 @@ export function resolveBrowserActionContext( parentOpts: (cmd: Command) => BrowserParentOpts, ): BrowserActionContext { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; - return { parent, baseUrl, profile }; + return { parent, profile }; +} + +export async function callBrowserAct(params: { + parent: BrowserParentOpts; + profile?: string; + body: Record; + timeoutMs?: number; +}): Promise { + return await callBrowserRequest( + params.parent, + { + method: "POST", + path: "/act", + query: params.profile ? { profile: params.profile } : undefined, + body: params.body, + }, + { timeoutMs: params.timeoutMs ?? 20000 }, + ); } export function requireRef(ref: string | undefined) { diff --git a/src/cli/browser-cli-actions-observe.ts b/src/cli/browser-cli-actions-observe.ts index 66202e357..63abd357d 100644 --- a/src/cli/browser-cli-actions-observe.ts +++ b/src/cli/browser-cli-actions-observe.ts @@ -1,13 +1,7 @@ import type { Command } from "commander"; -import { resolveBrowserControlUrl } from "../browser/client.js"; -import { - browserConsoleMessages, - browserPdfSave, - browserResponseBody, -} from "../browser/client-actions.js"; import { danger } from "../globals.js"; import { defaultRuntime } from "../runtime.js"; -import type { BrowserParentOpts } from "./browser-cli-shared.js"; +import { callBrowserRequest, type BrowserParentOpts } from "./browser-cli-shared.js"; import { runCommandWithRuntime } from "./cli-utils.js"; import { shortenHomePath } from "../utils.js"; @@ -29,14 +23,21 @@ export function registerBrowserActionObserveCommands( .option("--target-id ", "CDP target id (or unique prefix)") .action(async (opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; await runBrowserObserve(async () => { - const result = await browserConsoleMessages(baseUrl, { - level: opts.level?.trim() || undefined, - targetId: opts.targetId?.trim() || undefined, - profile, - }); + const result = await callBrowserRequest<{ messages: unknown[] }>( + parent, + { + method: "GET", + path: "/console", + query: { + level: opts.level?.trim() || undefined, + targetId: opts.targetId?.trim() || undefined, + profile, + }, + }, + { timeoutMs: 20000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -51,13 +52,18 @@ export function registerBrowserActionObserveCommands( .option("--target-id ", "CDP target id (or unique prefix)") .action(async (opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; await runBrowserObserve(async () => { - const result = await browserPdfSave(baseUrl, { - targetId: opts.targetId?.trim() || undefined, - profile, - }); + const result = await callBrowserRequest<{ path: string }>( + parent, + { + method: "POST", + path: "/pdf", + query: profile ? { profile } : undefined, + body: { targetId: opts.targetId?.trim() || undefined }, + }, + { timeoutMs: 20000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -81,16 +87,25 @@ export function registerBrowserActionObserveCommands( ) .action(async (url: string, opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; await runBrowserObserve(async () => { - const result = await browserResponseBody(baseUrl, { - url, - targetId: opts.targetId?.trim() || undefined, - timeoutMs: Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : undefined, - maxChars: Number.isFinite(opts.maxChars) ? opts.maxChars : undefined, - profile, - }); + const timeoutMs = Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : undefined; + const maxChars = Number.isFinite(opts.maxChars) ? opts.maxChars : undefined; + const result = await callBrowserRequest<{ response: { body: string } }>( + parent, + { + method: "POST", + path: "/response/body", + query: profile ? { profile } : undefined, + body: { + url, + targetId: opts.targetId?.trim() || undefined, + timeoutMs, + maxChars, + }, + }, + { timeoutMs: timeoutMs ?? 20000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; diff --git a/src/cli/browser-cli-debug.ts b/src/cli/browser-cli-debug.ts index daa5ba284..25ebab5a4 100644 --- a/src/cli/browser-cli-debug.ts +++ b/src/cli/browser-cli-debug.ts @@ -1,16 +1,8 @@ import type { Command } from "commander"; -import { resolveBrowserControlUrl } from "../browser/client.js"; -import { - browserHighlight, - browserPageErrors, - browserRequests, - browserTraceStart, - browserTraceStop, -} from "../browser/client-actions.js"; import { danger } from "../globals.js"; import { defaultRuntime } from "../runtime.js"; -import type { BrowserParentOpts } from "./browser-cli-shared.js"; +import { callBrowserRequest, type BrowserParentOpts } from "./browser-cli-shared.js"; import { runCommandWithRuntime } from "./cli-utils.js"; import { shortenHomePath } from "../utils.js"; @@ -32,14 +24,21 @@ export function registerBrowserDebugCommands( .option("--target-id ", "CDP target id (or unique prefix)") .action(async (ref: string, opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; await runBrowserDebug(async () => { - const result = await browserHighlight(baseUrl, { - ref: ref.trim(), - targetId: opts.targetId?.trim() || undefined, - profile, - }); + const result = await callBrowserRequest( + parent, + { + method: "POST", + path: "/highlight", + query: profile ? { profile } : undefined, + body: { + ref: ref.trim(), + targetId: opts.targetId?.trim() || undefined, + }, + }, + { timeoutMs: 20000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -55,14 +54,23 @@ export function registerBrowserDebugCommands( .option("--target-id ", "CDP target id (or unique prefix)") .action(async (opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; await runBrowserDebug(async () => { - const result = await browserPageErrors(baseUrl, { - targetId: opts.targetId?.trim() || undefined, - clear: Boolean(opts.clear), - profile, - }); + const result = await callBrowserRequest<{ + errors: Array<{ timestamp: string; name?: string; message: string }>; + }>( + parent, + { + method: "GET", + path: "/errors", + query: { + targetId: opts.targetId?.trim() || undefined, + clear: Boolean(opts.clear), + profile, + }, + }, + { timeoutMs: 20000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -87,15 +95,31 @@ export function registerBrowserDebugCommands( .option("--target-id ", "CDP target id (or unique prefix)") .action(async (opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; await runBrowserDebug(async () => { - const result = await browserRequests(baseUrl, { - targetId: opts.targetId?.trim() || undefined, - filter: opts.filter?.trim() || undefined, - clear: Boolean(opts.clear), - profile, - }); + const result = await callBrowserRequest<{ + requests: Array<{ + timestamp: string; + method: string; + status?: number; + ok?: boolean; + url: string; + failureText?: string; + }>; + }>( + parent, + { + method: "GET", + path: "/requests", + query: { + targetId: opts.targetId?.trim() || undefined, + filter: opts.filter?.trim() || undefined, + clear: Boolean(opts.clear), + profile, + }, + }, + { timeoutMs: 20000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -128,16 +152,23 @@ export function registerBrowserDebugCommands( .option("--sources", "Include sources (bigger traces)", false) .action(async (opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; await runBrowserDebug(async () => { - const result = await browserTraceStart(baseUrl, { - targetId: opts.targetId?.trim() || undefined, - screenshots: Boolean(opts.screenshots), - snapshots: Boolean(opts.snapshots), - sources: Boolean(opts.sources), - profile, - }); + const result = await callBrowserRequest( + parent, + { + method: "POST", + path: "/trace/start", + query: profile ? { profile } : undefined, + body: { + targetId: opts.targetId?.trim() || undefined, + screenshots: Boolean(opts.screenshots), + snapshots: Boolean(opts.snapshots), + sources: Boolean(opts.sources), + }, + }, + { timeoutMs: 20000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -153,14 +184,21 @@ export function registerBrowserDebugCommands( .option("--target-id ", "CDP target id (or unique prefix)") .action(async (opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; await runBrowserDebug(async () => { - const result = await browserTraceStop(baseUrl, { - targetId: opts.targetId?.trim() || undefined, - path: opts.out?.trim() || undefined, - profile, - }); + const result = await callBrowserRequest<{ path: string }>( + parent, + { + method: "POST", + path: "/trace/stop", + query: profile ? { profile } : undefined, + body: { + targetId: opts.targetId?.trim() || undefined, + path: opts.out?.trim() || undefined, + }, + }, + { timeoutMs: 20000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; diff --git a/src/cli/browser-cli-inspect.ts b/src/cli/browser-cli-inspect.ts index 000d33be9..e36b5c797 100644 --- a/src/cli/browser-cli-inspect.ts +++ b/src/cli/browser-cli-inspect.ts @@ -1,12 +1,11 @@ import type { Command } from "commander"; -import { browserSnapshot, resolveBrowserControlUrl } from "../browser/client.js"; -import { browserScreenshotAction } from "../browser/client-actions.js"; +import type { SnapshotResult } from "../browser/client.js"; import { loadConfig } from "../config/config.js"; import { danger } from "../globals.js"; import { defaultRuntime } from "../runtime.js"; import { shortenHomePath } from "../utils.js"; -import type { BrowserParentOpts } from "./browser-cli-shared.js"; +import { callBrowserRequest, type BrowserParentOpts } from "./browser-cli-shared.js"; export function registerBrowserInspectCommands( browser: Command, @@ -22,17 +21,24 @@ export function registerBrowserInspectCommands( .option("--type ", "Output type (default: png)", "png") .action(async (targetId: string | undefined, opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; try { - const result = await browserScreenshotAction(baseUrl, { - targetId: targetId?.trim() || undefined, - fullPage: Boolean(opts.fullPage), - ref: opts.ref?.trim() || undefined, - element: opts.element?.trim() || undefined, - type: opts.type === "jpeg" ? "jpeg" : "png", - profile, - }); + const result = await callBrowserRequest<{ path: string }>( + parent, + { + method: "POST", + path: "/screenshot", + query: profile ? { profile } : undefined, + body: { + targetId: targetId?.trim() || undefined, + fullPage: Boolean(opts.fullPage), + ref: opts.ref?.trim() || undefined, + element: opts.element?.trim() || undefined, + type: opts.type === "jpeg" ? "jpeg" : "png", + }, + }, + { timeoutMs: 20000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -61,7 +67,6 @@ export function registerBrowserInspectCommands( .option("--out ", "Write snapshot to a file") .action(async (opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; const format = opts.format === "aria" ? "aria" : "ai"; const configMode = @@ -70,19 +75,28 @@ export function registerBrowserInspectCommands( : undefined; const mode = opts.efficient === true || opts.mode === "efficient" ? "efficient" : configMode; try { - const result = await browserSnapshot(baseUrl, { + const query: Record = { format, targetId: opts.targetId?.trim() || undefined, limit: Number.isFinite(opts.limit) ? opts.limit : undefined, - interactive: Boolean(opts.interactive) || undefined, - compact: Boolean(opts.compact) || undefined, + interactive: opts.interactive ? true : undefined, + compact: opts.compact ? true : undefined, depth: Number.isFinite(opts.depth) ? opts.depth : undefined, selector: opts.selector?.trim() || undefined, frame: opts.frame?.trim() || undefined, - labels: Boolean(opts.labels) || undefined, + labels: opts.labels ? true : undefined, mode, profile, - }); + }; + const result = await callBrowserRequest( + parent, + { + method: "GET", + path: "/snapshot", + query, + }, + { timeoutMs: 20000 }, + ); if (opts.out) { const fs = await import("node:fs/promises"); diff --git a/src/cli/browser-cli-manage.ts b/src/cli/browser-cli-manage.ts index 612653616..44ff3836e 100644 --- a/src/cli/browser-cli-manage.ts +++ b/src/cli/browser-cli-manage.ts @@ -1,25 +1,16 @@ import type { Command } from "commander"; -import type { BrowserTab } from "../browser/client.js"; -import { - browserCloseTab, - browserCreateProfile, - browserDeleteProfile, - browserFocusTab, - browserOpenTab, - browserProfiles, - browserResetProfile, - browserStart, - browserStatus, - browserStop, - browserTabAction, - browserTabs, - resolveBrowserControlUrl, +import type { + BrowserCreateProfileResult, + BrowserDeleteProfileResult, + BrowserResetProfileResult, + BrowserStatus, + BrowserTab, + ProfileStatus, } from "../browser/client.js"; -import { browserAct } from "../browser/client-actions-core.js"; import { danger, info } from "../globals.js"; import { defaultRuntime } from "../runtime.js"; import { shortenHomePath } from "../utils.js"; -import type { BrowserParentOpts } from "./browser-cli-shared.js"; +import { callBrowserRequest, type BrowserParentOpts } from "./browser-cli-shared.js"; import { runCommandWithRuntime } from "./cli-utils.js"; function runBrowserCommand(action: () => Promise) { @@ -38,11 +29,18 @@ export function registerBrowserManageCommands( .description("Show browser status") .action(async (_opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); await runBrowserCommand(async () => { - const status = await browserStatus(baseUrl, { - profile: parent?.browserProfile, - }); + const status = await callBrowserRequest( + parent, + { + method: "GET", + path: "/", + query: parent?.browserProfile ? { profile: parent.browserProfile } : undefined, + }, + { + timeoutMs: 1500, + }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(status, null, 2)); return; @@ -54,7 +52,6 @@ export function registerBrowserManageCommands( `profile: ${status.profile ?? "clawd"}`, `enabled: ${status.enabled}`, `running: ${status.running}`, - `controlUrl: ${status.controlUrl}`, `cdpPort: ${status.cdpPort}`, `cdpUrl: ${status.cdpUrl ?? `http://127.0.0.1:${status.cdpPort}`}`, `browser: ${status.chosenBrowser ?? "unknown"}`, @@ -72,11 +69,26 @@ export function registerBrowserManageCommands( .description("Start the browser (no-op if already running)") .action(async (_opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; await runBrowserCommand(async () => { - await browserStart(baseUrl, { profile }); - const status = await browserStatus(baseUrl, { profile }); + await callBrowserRequest( + parent, + { + method: "POST", + path: "/start", + query: profile ? { profile } : undefined, + }, + { timeoutMs: 15000 }, + ); + const status = await callBrowserRequest( + parent, + { + method: "GET", + path: "/", + query: profile ? { profile } : undefined, + }, + { timeoutMs: 1500 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(status, null, 2)); return; @@ -91,11 +103,26 @@ export function registerBrowserManageCommands( .description("Stop the browser (best-effort)") .action(async (_opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; await runBrowserCommand(async () => { - await browserStop(baseUrl, { profile }); - const status = await browserStatus(baseUrl, { profile }); + await callBrowserRequest( + parent, + { + method: "POST", + path: "/stop", + query: profile ? { profile } : undefined, + }, + { timeoutMs: 15000 }, + ); + const status = await callBrowserRequest( + parent, + { + method: "GET", + path: "/", + query: profile ? { profile } : undefined, + }, + { timeoutMs: 1500 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(status, null, 2)); return; @@ -110,10 +137,17 @@ export function registerBrowserManageCommands( .description("Reset browser profile (moves it to Trash)") .action(async (_opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; await runBrowserCommand(async () => { - const result = await browserResetProfile(baseUrl, { profile }); + const result = await callBrowserRequest( + parent, + { + method: "POST", + path: "/reset-profile", + query: profile ? { profile } : undefined, + }, + { timeoutMs: 20000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -132,10 +166,18 @@ export function registerBrowserManageCommands( .description("List open tabs") .action(async (_opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; await runBrowserCommand(async () => { - const tabs = await browserTabs(baseUrl, { profile }); + const result = await callBrowserRequest<{ running: boolean; tabs: BrowserTab[] }>( + parent, + { + method: "GET", + path: "/tabs", + query: profile ? { profile } : undefined, + }, + { timeoutMs: 3000 }, + ); + const tabs = result.tabs ?? []; if (parent?.json) { defaultRuntime.log(JSON.stringify({ tabs }, null, 2)); return; @@ -159,13 +201,20 @@ export function registerBrowserManageCommands( .description("Tab shortcuts (index-based)") .action(async (_opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; await runBrowserCommand(async () => { - const result = (await browserTabAction(baseUrl, { - action: "list", - profile, - })) as { ok: true; tabs: BrowserTab[] }; + const result = await callBrowserRequest<{ ok: true; tabs: BrowserTab[] }>( + parent, + { + method: "POST", + path: "/tabs/action", + query: profile ? { profile } : undefined, + body: { + action: "list", + }, + }, + { timeoutMs: 10_000 }, + ); const tabs = result.tabs ?? []; if (parent?.json) { defaultRuntime.log(JSON.stringify({ tabs }, null, 2)); @@ -190,13 +239,18 @@ export function registerBrowserManageCommands( .description("Open a new tab (about:blank)") .action(async (_opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; await runBrowserCommand(async () => { - const result = await browserTabAction(baseUrl, { - action: "new", - profile, - }); + const result = await callBrowserRequest( + parent, + { + method: "POST", + path: "/tabs/action", + query: profile ? { profile } : undefined, + body: { action: "new" }, + }, + { timeoutMs: 10_000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -211,7 +265,6 @@ export function registerBrowserManageCommands( .argument("", "Tab index (1-based)", (v: string) => Number(v)) .action(async (index: number, _opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; if (!Number.isFinite(index) || index < 1) { defaultRuntime.error(danger("index must be a positive number")); @@ -219,11 +272,16 @@ export function registerBrowserManageCommands( return; } await runBrowserCommand(async () => { - const result = await browserTabAction(baseUrl, { - action: "select", - index: Math.floor(index) - 1, - profile, - }); + const result = await callBrowserRequest( + parent, + { + method: "POST", + path: "/tabs/action", + query: profile ? { profile } : undefined, + body: { action: "select", index: Math.floor(index) - 1 }, + }, + { timeoutMs: 10_000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -238,7 +296,6 @@ export function registerBrowserManageCommands( .argument("[index]", "Tab index (1-based)", (v: string) => Number(v)) .action(async (index: number | undefined, _opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; const idx = typeof index === "number" && Number.isFinite(index) ? Math.floor(index) - 1 : undefined; @@ -248,11 +305,16 @@ export function registerBrowserManageCommands( return; } await runBrowserCommand(async () => { - const result = await browserTabAction(baseUrl, { - action: "close", - index: idx, - profile, - }); + const result = await callBrowserRequest( + parent, + { + method: "POST", + path: "/tabs/action", + query: profile ? { profile } : undefined, + body: { action: "close", index: idx }, + }, + { timeoutMs: 10_000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -267,10 +329,18 @@ export function registerBrowserManageCommands( .argument("", "URL to open") .action(async (url: string, _opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; await runBrowserCommand(async () => { - const tab = await browserOpenTab(baseUrl, url, { profile }); + const tab = await callBrowserRequest( + parent, + { + method: "POST", + path: "/tabs/open", + query: profile ? { profile } : undefined, + body: { url }, + }, + { timeoutMs: 15000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(tab, null, 2)); return; @@ -285,10 +355,18 @@ export function registerBrowserManageCommands( .argument("", "Target id or unique prefix") .action(async (targetId: string, _opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; await runBrowserCommand(async () => { - await browserFocusTab(baseUrl, targetId, { profile }); + await callBrowserRequest( + parent, + { + method: "POST", + path: "/tabs/focus", + query: profile ? { profile } : undefined, + body: { targetId }, + }, + { timeoutMs: 5000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify({ ok: true }, null, 2)); return; @@ -303,13 +381,29 @@ export function registerBrowserManageCommands( .argument("[targetId]", "Target id or unique prefix (optional)") .action(async (targetId: string | undefined, _opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; await runBrowserCommand(async () => { if (targetId?.trim()) { - await browserCloseTab(baseUrl, targetId.trim(), { profile }); + await callBrowserRequest( + parent, + { + method: "DELETE", + path: `/tabs/${encodeURIComponent(targetId.trim())}`, + query: profile ? { profile } : undefined, + }, + { timeoutMs: 5000 }, + ); } else { - await browserAct(baseUrl, { kind: "close" }, { profile }); + await callBrowserRequest( + parent, + { + method: "POST", + path: "/act", + query: profile ? { profile } : undefined, + body: { kind: "close" }, + }, + { timeoutMs: 20000 }, + ); } if (parent?.json) { defaultRuntime.log(JSON.stringify({ ok: true }, null, 2)); @@ -325,9 +419,16 @@ export function registerBrowserManageCommands( .description("List all browser profiles") .action(async (_opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); await runBrowserCommand(async () => { - const profiles = await browserProfiles(baseUrl); + const result = await callBrowserRequest<{ profiles: ProfileStatus[] }>( + parent, + { + method: "GET", + path: "/profiles", + }, + { timeoutMs: 3000 }, + ); + const profiles = result.profiles ?? []; if (parent?.json) { defaultRuntime.log(JSON.stringify({ profiles }, null, 2)); return; @@ -361,14 +462,21 @@ export function registerBrowserManageCommands( .action( async (opts: { name: string; color?: string; cdpUrl?: string; driver?: string }, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); await runBrowserCommand(async () => { - const result = await browserCreateProfile(baseUrl, { - name: opts.name, - color: opts.color, - cdpUrl: opts.cdpUrl, - driver: opts.driver === "extension" ? "extension" : undefined, - }); + const result = await callBrowserRequest( + parent, + { + method: "POST", + path: "/profiles/create", + body: { + name: opts.name, + color: opts.color, + cdpUrl: opts.cdpUrl, + driver: opts.driver === "extension" ? "extension" : undefined, + }, + }, + { timeoutMs: 10_000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -391,9 +499,15 @@ export function registerBrowserManageCommands( .requiredOption("--name ", "Profile name to delete") .action(async (opts: { name: string }, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); await runBrowserCommand(async () => { - const result = await browserDeleteProfile(baseUrl, opts.name); + const result = await callBrowserRequest( + parent, + { + method: "DELETE", + path: `/profiles/${encodeURIComponent(opts.name)}`, + }, + { timeoutMs: 20_000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; diff --git a/src/cli/browser-cli-serve.ts b/src/cli/browser-cli-serve.ts deleted file mode 100644 index 179424ed1..000000000 --- a/src/cli/browser-cli-serve.ts +++ /dev/null @@ -1,121 +0,0 @@ -import type { Command } from "commander"; - -import { loadConfig } from "../config/config.js"; -import { danger, info } from "../globals.js"; -import { defaultRuntime } from "../runtime.js"; -import { resolveBrowserConfig, resolveProfile } from "../browser/config.js"; -import { startBrowserBridgeServer, stopBrowserBridgeServer } from "../browser/bridge-server.js"; -import { ensureChromeExtensionRelayServer } from "../browser/extension-relay.js"; - -function isLoopbackBindHost(host: string) { - const h = host.trim().toLowerCase(); - return h === "localhost" || h === "127.0.0.1" || h === "::1" || h === "[::1]"; -} - -function parsePort(raw: unknown): number | null { - const v = typeof raw === "string" ? raw.trim() : ""; - if (!v) return null; - const n = Number.parseInt(v, 10); - if (!Number.isFinite(n) || n < 0 || n > 65535) return null; - return n; -} - -export function registerBrowserServeCommands( - browser: Command, - _parentOpts: (cmd: Command) => unknown, -) { - browser - .command("serve") - .description("Run a standalone browser control server (for remote gateways)") - .option("--bind ", "Bind host (default: 127.0.0.1)") - .option("--port ", "Bind port (default: from browser.controlUrl)") - .option( - "--token ", - "Require Authorization: Bearer (required when binding non-loopback)", - ) - .action(async (opts: { bind?: string; port?: string; token?: string }) => { - const cfg = loadConfig(); - const resolved = resolveBrowserConfig(cfg.browser); - if (!resolved.enabled) { - defaultRuntime.error( - danger("Browser control is disabled. Set browser.enabled=true and try again."), - ); - defaultRuntime.exit(1); - } - - const host = (opts.bind ?? "127.0.0.1").trim(); - const port = parsePort(opts.port) ?? resolved.controlPort; - - const envToken = process.env.CLAWDBOT_BROWSER_CONTROL_TOKEN?.trim(); - const authToken = (opts.token ?? envToken ?? resolved.controlToken)?.trim(); - if (!isLoopbackBindHost(host) && !authToken) { - defaultRuntime.error( - danger( - `Refusing to bind browser control on ${host} without --token (or CLAWDBOT_BROWSER_CONTROL_TOKEN, or browser.controlToken).`, - ), - ); - defaultRuntime.exit(1); - } - - const bridge = await startBrowserBridgeServer({ - resolved, - host, - port, - ...(authToken ? { authToken } : {}), - }); - - // If any profile uses the Chrome extension relay, start the local relay server eagerly - // so the extension can connect before the first browser action. - for (const name of Object.keys(resolved.profiles)) { - const profile = resolveProfile(resolved, name); - if (!profile || profile.driver !== "extension") continue; - await ensureChromeExtensionRelayServer({ cdpUrl: profile.cdpUrl }).catch((err) => { - defaultRuntime.error( - danger(`Chrome extension relay init failed for profile "${name}": ${String(err)}`), - ); - }); - } - - defaultRuntime.log( - info( - [ - `🦞 Browser control listening on ${bridge.baseUrl}/`, - authToken ? "Auth: Bearer token required." : "Auth: off (loopback only).", - "", - "Paste on the Gateway (clawdbot.json):", - JSON.stringify( - { - browser: { - enabled: true, - controlUrl: bridge.baseUrl, - ...(authToken ? { controlToken: authToken } : {}), - }, - }, - null, - 2, - ), - ...(authToken - ? [ - "", - "Or use env on the Gateway (instead of controlToken in config):", - `export CLAWDBOT_BROWSER_CONTROL_TOKEN=${JSON.stringify(authToken)}`, - ] - : []), - ].join("\n"), - ), - ); - - let shuttingDown = false; - const shutdown = async (signal: string) => { - if (shuttingDown) return; - shuttingDown = true; - defaultRuntime.log(info(`Shutting down (${signal})...`)); - await stopBrowserBridgeServer(bridge.server).catch(() => {}); - process.exit(0); - }; - process.once("SIGINT", () => void shutdown("SIGINT")); - process.once("SIGTERM", () => void shutdown("SIGTERM")); - - await new Promise(() => {}); - }); -} diff --git a/src/cli/browser-cli-shared.ts b/src/cli/browser-cli-shared.ts index 2e110f186..aa78eff27 100644 --- a/src/cli/browser-cli-shared.ts +++ b/src/cli/browser-cli-shared.ts @@ -1,5 +1,58 @@ -export type BrowserParentOpts = { - url?: string; +import type { GatewayRpcOpts } from "./gateway-rpc.js"; +import { callGatewayFromCli } from "./gateway-rpc.js"; + +export type BrowserParentOpts = GatewayRpcOpts & { json?: boolean; browserProfile?: string; }; + +type BrowserRequestParams = { + method: "GET" | "POST" | "DELETE"; + path: string; + query?: Record; + body?: unknown; +}; + +function normalizeQuery(query: BrowserRequestParams["query"]): Record | undefined { + if (!query) return undefined; + const out: Record = {}; + for (const [key, value] of Object.entries(query)) { + if (value === undefined) continue; + out[key] = String(value); + } + return Object.keys(out).length ? out : undefined; +} + +export async function callBrowserRequest( + opts: BrowserParentOpts, + params: BrowserRequestParams, + extra?: { timeoutMs?: number; progress?: boolean }, +): Promise { + const resolvedTimeoutMs = + typeof extra?.timeoutMs === "number" && Number.isFinite(extra.timeoutMs) + ? Math.max(1, Math.floor(extra.timeoutMs)) + : typeof opts.timeout === "string" + ? Number.parseInt(opts.timeout, 10) + : undefined; + const resolvedTimeout = + typeof resolvedTimeoutMs === "number" && Number.isFinite(resolvedTimeoutMs) + ? resolvedTimeoutMs + : undefined; + const timeout = typeof resolvedTimeout === "number" ? String(resolvedTimeout) : opts.timeout; + const payload = await callGatewayFromCli( + "browser.request", + { ...opts, timeout }, + { + method: params.method, + path: params.path, + query: normalizeQuery(params.query), + body: params.body, + timeoutMs: resolvedTimeout, + }, + { progress: extra?.progress }, + ); + if (payload === undefined) { + throw new Error("Unexpected browser.request response"); + } + return payload as T; +} diff --git a/src/cli/browser-cli-state.cookies-storage.ts b/src/cli/browser-cli-state.cookies-storage.ts index 2cabdec37..a9db259cf 100644 --- a/src/cli/browser-cli-state.cookies-storage.ts +++ b/src/cli/browser-cli-state.cookies-storage.ts @@ -1,17 +1,8 @@ import type { Command } from "commander"; -import { resolveBrowserControlUrl } from "../browser/client.js"; -import { - browserCookies, - browserCookiesClear, - browserCookiesSet, - browserStorageClear, - browserStorageGet, - browserStorageSet, -} from "../browser/client-actions.js"; import { danger } from "../globals.js"; import { defaultRuntime } from "../runtime.js"; -import type { BrowserParentOpts } from "./browser-cli-shared.js"; +import { callBrowserRequest, type BrowserParentOpts } from "./browser-cli-shared.js"; export function registerBrowserCookiesAndStorageCommands( browser: Command, @@ -23,13 +14,20 @@ export function registerBrowserCookiesAndStorageCommands( .option("--target-id ", "CDP target id (or unique prefix)") .action(async (opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; try { - const result = await browserCookies(baseUrl, { - targetId: opts.targetId?.trim() || undefined, - profile, - }); + const result = await callBrowserRequest<{ cookies?: unknown[] }>( + parent, + { + method: "GET", + path: "/cookies", + query: { + targetId: opts.targetId?.trim() || undefined, + profile, + }, + }, + { timeoutMs: 20000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -50,14 +48,21 @@ export function registerBrowserCookiesAndStorageCommands( .option("--target-id ", "CDP target id (or unique prefix)") .action(async (name: string, value: string, opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; try { - const result = await browserCookiesSet(baseUrl, { - targetId: opts.targetId?.trim() || undefined, - cookie: { name, value, url: opts.url }, - profile, - }); + const result = await callBrowserRequest( + parent, + { + method: "POST", + path: "/cookies/set", + query: profile ? { profile } : undefined, + body: { + targetId: opts.targetId?.trim() || undefined, + cookie: { name, value, url: opts.url }, + }, + }, + { timeoutMs: 20000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -75,13 +80,20 @@ export function registerBrowserCookiesAndStorageCommands( .option("--target-id ", "CDP target id (or unique prefix)") .action(async (opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; try { - const result = await browserCookiesClear(baseUrl, { - targetId: opts.targetId?.trim() || undefined, - profile, - }); + const result = await callBrowserRequest( + parent, + { + method: "POST", + path: "/cookies/clear", + query: profile ? { profile } : undefined, + body: { + targetId: opts.targetId?.trim() || undefined, + }, + }, + { timeoutMs: 20000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -105,15 +117,21 @@ export function registerBrowserCookiesAndStorageCommands( .option("--target-id ", "CDP target id (or unique prefix)") .action(async (key: string | undefined, opts, cmd2) => { const parent = parentOpts(cmd2); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; try { - const result = await browserStorageGet(baseUrl, { - kind, - key: key?.trim() || undefined, - targetId: opts.targetId?.trim() || undefined, - profile, - }); + const result = await callBrowserRequest<{ values?: Record }>( + parent, + { + method: "GET", + path: `/storage/${kind}`, + query: { + key: key?.trim() || undefined, + targetId: opts.targetId?.trim() || undefined, + profile, + }, + }, + { timeoutMs: 20000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -133,16 +151,22 @@ export function registerBrowserCookiesAndStorageCommands( .option("--target-id ", "CDP target id (or unique prefix)") .action(async (key: string, value: string, opts, cmd2) => { const parent = parentOpts(cmd2); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; try { - const result = await browserStorageSet(baseUrl, { - kind, - key, - value, - targetId: opts.targetId?.trim() || undefined, - profile, - }); + const result = await callBrowserRequest( + parent, + { + method: "POST", + path: `/storage/${kind}/set`, + query: profile ? { profile } : undefined, + body: { + key, + value, + targetId: opts.targetId?.trim() || undefined, + }, + }, + { timeoutMs: 20000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -160,14 +184,20 @@ export function registerBrowserCookiesAndStorageCommands( .option("--target-id ", "CDP target id (or unique prefix)") .action(async (opts, cmd2) => { const parent = parentOpts(cmd2); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; try { - const result = await browserStorageClear(baseUrl, { - kind, - targetId: opts.targetId?.trim() || undefined, - profile, - }); + const result = await callBrowserRequest( + parent, + { + method: "POST", + path: `/storage/${kind}/clear`, + query: profile ? { profile } : undefined, + body: { + targetId: opts.targetId?.trim() || undefined, + }, + }, + { timeoutMs: 20000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; diff --git a/src/cli/browser-cli-state.ts b/src/cli/browser-cli-state.ts index ea98901e1..335f9547a 100644 --- a/src/cli/browser-cli-state.ts +++ b/src/cli/browser-cli-state.ts @@ -1,21 +1,9 @@ import type { Command } from "commander"; -import { resolveBrowserControlUrl } from "../browser/client.js"; -import { - browserSetDevice, - browserSetGeolocation, - browserSetHeaders, - browserSetHttpCredentials, - browserSetLocale, - browserSetMedia, - browserSetOffline, - browserSetTimezone, -} from "../browser/client-actions.js"; -import { browserAct } from "../browser/client-actions-core.js"; import { danger } from "../globals.js"; import { defaultRuntime } from "../runtime.js"; import { parseBooleanValue } from "../utils/boolean.js"; -import type { BrowserParentOpts } from "./browser-cli-shared.js"; +import { callBrowserRequest, type BrowserParentOpts } from "./browser-cli-shared.js"; import { registerBrowserCookiesAndStorageCommands } from "./browser-cli-state.cookies-storage.js"; import { runCommandWithRuntime } from "./cli-utils.js"; @@ -47,7 +35,6 @@ export function registerBrowserStateCommands( .option("--target-id ", "CDP target id (or unique prefix)") .action(async (width: number, height: number, opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; if (!Number.isFinite(width) || !Number.isFinite(height)) { defaultRuntime.error(danger("width and height must be numbers")); @@ -55,15 +42,20 @@ export function registerBrowserStateCommands( return; } await runBrowserCommand(async () => { - const result = await browserAct( - baseUrl, + const result = await callBrowserRequest( + parent, { - kind: "resize", - width, - height, - targetId: opts.targetId?.trim() || undefined, + method: "POST", + path: "/act", + query: profile ? { profile } : undefined, + body: { + kind: "resize", + width, + height, + targetId: opts.targetId?.trim() || undefined, + }, }, - { profile }, + { timeoutMs: 20000 }, ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); @@ -80,7 +72,6 @@ export function registerBrowserStateCommands( .option("--target-id ", "CDP target id (or unique prefix)") .action(async (value: string, opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; const offline = parseOnOff(value); if (offline === null) { @@ -89,11 +80,19 @@ export function registerBrowserStateCommands( return; } await runBrowserCommand(async () => { - const result = await browserSetOffline(baseUrl, { - offline, - targetId: opts.targetId?.trim() || undefined, - profile, - }); + const result = await callBrowserRequest( + parent, + { + method: "POST", + path: "/set/offline", + query: profile ? { profile } : undefined, + body: { + offline, + targetId: opts.targetId?.trim() || undefined, + }, + }, + { timeoutMs: 20000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -109,7 +108,6 @@ export function registerBrowserStateCommands( .option("--target-id ", "CDP target id (or unique prefix)") .action(async (opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; await runBrowserCommand(async () => { const parsed = JSON.parse(String(opts.json)) as unknown; @@ -120,11 +118,19 @@ export function registerBrowserStateCommands( for (const [k, v] of Object.entries(parsed as Record)) { if (typeof v === "string") headers[k] = v; } - const result = await browserSetHeaders(baseUrl, { - headers, - targetId: opts.targetId?.trim() || undefined, - profile, - }); + const result = await callBrowserRequest( + parent, + { + method: "POST", + path: "/set/headers", + query: profile ? { profile } : undefined, + body: { + headers, + targetId: opts.targetId?.trim() || undefined, + }, + }, + { timeoutMs: 20000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -142,16 +148,23 @@ export function registerBrowserStateCommands( .option("--target-id ", "CDP target id (or unique prefix)") .action(async (username: string | undefined, password: string | undefined, opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; await runBrowserCommand(async () => { - const result = await browserSetHttpCredentials(baseUrl, { - username: username?.trim() || undefined, - password, - clear: Boolean(opts.clear), - targetId: opts.targetId?.trim() || undefined, - profile, - }); + const result = await callBrowserRequest( + parent, + { + method: "POST", + path: "/set/credentials", + query: profile ? { profile } : undefined, + body: { + username: username?.trim() || undefined, + password, + clear: Boolean(opts.clear), + targetId: opts.targetId?.trim() || undefined, + }, + }, + { timeoutMs: 20000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -171,18 +184,25 @@ export function registerBrowserStateCommands( .option("--target-id ", "CDP target id (or unique prefix)") .action(async (latitude: number | undefined, longitude: number | undefined, opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; await runBrowserCommand(async () => { - const result = await browserSetGeolocation(baseUrl, { - latitude: Number.isFinite(latitude) ? latitude : undefined, - longitude: Number.isFinite(longitude) ? longitude : undefined, - accuracy: Number.isFinite(opts.accuracy) ? opts.accuracy : undefined, - origin: opts.origin?.trim() || undefined, - clear: Boolean(opts.clear), - targetId: opts.targetId?.trim() || undefined, - profile, - }); + const result = await callBrowserRequest( + parent, + { + method: "POST", + path: "/set/geolocation", + query: profile ? { profile } : undefined, + body: { + latitude: Number.isFinite(latitude) ? latitude : undefined, + longitude: Number.isFinite(longitude) ? longitude : undefined, + accuracy: Number.isFinite(opts.accuracy) ? opts.accuracy : undefined, + origin: opts.origin?.trim() || undefined, + clear: Boolean(opts.clear), + targetId: opts.targetId?.trim() || undefined, + }, + }, + { timeoutMs: 20000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -198,7 +218,6 @@ export function registerBrowserStateCommands( .option("--target-id ", "CDP target id (or unique prefix)") .action(async (value: string, opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; const v = value.trim().toLowerCase(); const colorScheme = @@ -209,11 +228,19 @@ export function registerBrowserStateCommands( return; } await runBrowserCommand(async () => { - const result = await browserSetMedia(baseUrl, { - colorScheme, - targetId: opts.targetId?.trim() || undefined, - profile, - }); + const result = await callBrowserRequest( + parent, + { + method: "POST", + path: "/set/media", + query: profile ? { profile } : undefined, + body: { + colorScheme, + targetId: opts.targetId?.trim() || undefined, + }, + }, + { timeoutMs: 20000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -229,14 +256,21 @@ export function registerBrowserStateCommands( .option("--target-id ", "CDP target id (or unique prefix)") .action(async (timezoneId: string, opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; await runBrowserCommand(async () => { - const result = await browserSetTimezone(baseUrl, { - timezoneId, - targetId: opts.targetId?.trim() || undefined, - profile, - }); + const result = await callBrowserRequest( + parent, + { + method: "POST", + path: "/set/timezone", + query: profile ? { profile } : undefined, + body: { + timezoneId, + targetId: opts.targetId?.trim() || undefined, + }, + }, + { timeoutMs: 20000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -252,14 +286,21 @@ export function registerBrowserStateCommands( .option("--target-id ", "CDP target id (or unique prefix)") .action(async (locale: string, opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; await runBrowserCommand(async () => { - const result = await browserSetLocale(baseUrl, { - locale, - targetId: opts.targetId?.trim() || undefined, - profile, - }); + const result = await callBrowserRequest( + parent, + { + method: "POST", + path: "/set/locale", + query: profile ? { profile } : undefined, + body: { + locale, + targetId: opts.targetId?.trim() || undefined, + }, + }, + { timeoutMs: 20000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; @@ -275,14 +316,21 @@ export function registerBrowserStateCommands( .option("--target-id ", "CDP target id (or unique prefix)") .action(async (name: string, opts, cmd) => { const parent = parentOpts(cmd); - const baseUrl = resolveBrowserControlUrl(parent?.url); const profile = parent?.browserProfile; await runBrowserCommand(async () => { - const result = await browserSetDevice(baseUrl, { - name, - targetId: opts.targetId?.trim() || undefined, - profile, - }); + const result = await callBrowserRequest( + parent, + { + method: "POST", + path: "/set/device", + query: profile ? { profile } : undefined, + body: { + name, + targetId: opts.targetId?.trim() || undefined, + }, + }, + { timeoutMs: 20000 }, + ); if (parent?.json) { defaultRuntime.log(JSON.stringify(result, null, 2)); return; diff --git a/src/cli/browser-cli.ts b/src/cli/browser-cli.ts index b3b456dea..50c71ef01 100644 --- a/src/cli/browser-cli.ts +++ b/src/cli/browser-cli.ts @@ -13,15 +13,14 @@ import { browserActionExamples, browserCoreExamples } from "./browser-cli-exampl import { registerBrowserExtensionCommands } from "./browser-cli-extension.js"; import { registerBrowserInspectCommands } from "./browser-cli-inspect.js"; import { registerBrowserManageCommands } from "./browser-cli-manage.js"; -import { registerBrowserServeCommands } from "./browser-cli-serve.js"; import type { BrowserParentOpts } from "./browser-cli-shared.js"; import { registerBrowserStateCommands } from "./browser-cli-state.js"; +import { addGatewayClientOptions } from "./gateway-rpc.js"; export function registerBrowserCli(program: Command) { const browser = program .command("browser") .description("Manage clawd's dedicated browser (Chrome/Chromium)") - .option("--url ", "Override browser control URL (default from ~/.clawdbot/clawdbot.json)") .option("--browser-profile ", "Browser profile name (default from config)") .option("--json", "Output machine-readable JSON", false) .addHelpText( @@ -43,11 +42,12 @@ export function registerBrowserCli(program: Command) { defaultRuntime.exit(1); }); + addGatewayClientOptions(browser); + const parentOpts = (cmd: Command) => cmd.parent?.opts?.() as BrowserParentOpts; registerBrowserManageCommands(browser, parentOpts); registerBrowserExtensionCommands(browser, parentOpts); - registerBrowserServeCommands(browser, parentOpts); registerBrowserInspectCommands(browser, parentOpts); registerBrowserActionInputCommands(browser, parentOpts); registerBrowserActionObserveCommands(browser, parentOpts); diff --git a/src/config/schema.ts b/src/config/schema.ts index 3261b5170..f05ac277c 100644 --- a/src/config/schema.ts +++ b/src/config/schema.ts @@ -279,7 +279,6 @@ const FIELD_LABELS: Record = { "ui.seamColor": "Accent Color", "ui.assistant.name": "Assistant Name", "ui.assistant.avatar": "Assistant Avatar", - "browser.controlUrl": "Browser Control URL", "browser.snapshotDefaults": "Browser Snapshot Defaults", "browser.snapshotDefaults.mode": "Browser Snapshot Mode", "browser.remoteCdpTimeoutMs": "Remote CDP Timeout (ms)", diff --git a/src/config/types.browser.ts b/src/config/types.browser.ts index 1c39c050a..cbd006589 100644 --- a/src/config/types.browser.ts +++ b/src/config/types.browser.ts @@ -14,16 +14,7 @@ export type BrowserSnapshotDefaults = { }; export type BrowserConfig = { enabled?: boolean; - /** Base URL of the clawd browser control server. Default: http://127.0.0.1:18791 */ - controlUrl?: string; - /** - * Shared token for the browser control server. - * If set, clients must send `Authorization: Bearer `. - * - * Prefer `CLAWDBOT_BROWSER_CONTROL_TOKEN` env for ephemeral setups; use this for "works after reboot". - */ - controlToken?: string; - /** Base URL of the CDP endpoint. Default: controlUrl with port + 1. */ + /** Base URL of the CDP endpoint (for remote browsers). Default: loopback CDP on the derived port. */ cdpUrl?: string; /** Remote CDP HTTP timeout (ms). Default: 1500. */ remoteCdpTimeoutMs?: number; diff --git a/src/config/types.sandbox.ts b/src/config/types.sandbox.ts index c7566260f..4f5f83810 100644 --- a/src/config/types.sandbox.ts +++ b/src/config/types.sandbox.ts @@ -58,21 +58,6 @@ export type SandboxBrowserSettings = { * Default: false. */ allowHostControl?: boolean; - /** - * Allowlist of exact control URLs for target="custom". - * When set, any custom controlUrl must match this list. - */ - allowedControlUrls?: string[]; - /** - * Allowlist of hostnames for control URLs (hostname only, no ports). - * When set, controlUrl hostname must match. - */ - allowedControlHosts?: string[]; - /** - * Allowlist of ports for control URLs. - * When set, controlUrl port must match (defaults: http=80, https=443). - */ - allowedControlPorts?: number[]; /** * When true (default), sandboxed browser control will try to start/reattach to * the sandbox browser container when a tool call needs it. diff --git a/src/config/zod-schema.agent-runtime.ts b/src/config/zod-schema.agent-runtime.ts index b5a03a3ea..7a63e307d 100644 --- a/src/config/zod-schema.agent-runtime.ts +++ b/src/config/zod-schema.agent-runtime.ts @@ -130,9 +130,6 @@ export const SandboxBrowserSchema = z headless: z.boolean().optional(), enableNoVnc: z.boolean().optional(), allowHostControl: z.boolean().optional(), - allowedControlUrls: z.array(z.string()).optional(), - allowedControlHosts: z.array(z.string()).optional(), - allowedControlPorts: z.array(z.number().int().positive()).optional(), autoStart: z.boolean().optional(), autoStartTimeoutMs: z.number().int().positive().optional(), }) diff --git a/src/config/zod-schema.ts b/src/config/zod-schema.ts index f39b001fa..75f438c1e 100644 --- a/src/config/zod-schema.ts +++ b/src/config/zod-schema.ts @@ -134,8 +134,6 @@ export const ClawdbotSchema = z browser: z .object({ enabled: z.boolean().optional(), - controlUrl: z.string().optional(), - controlToken: z.string().optional(), cdpUrl: z.string().optional(), remoteCdpTimeoutMs: z.number().int().nonnegative().optional(), remoteCdpHandshakeTimeoutMs: z.number().int().nonnegative().optional(), diff --git a/src/gateway/server-browser.ts b/src/gateway/server-browser.ts index 35cf02af1..f525348bb 100644 --- a/src/gateway/server-browser.ts +++ b/src/gateway/server-browser.ts @@ -9,7 +9,19 @@ export async function startBrowserControlServerIfEnabled(): Promise Promise }) + .startBrowserControlServiceFromConfig + : (mod as { startBrowserControlServerFromConfig?: () => Promise }) + .startBrowserControlServerFromConfig; + const stop = + typeof (mod as { stopBrowserControlService?: unknown }).stopBrowserControlService === "function" + ? (mod as { stopBrowserControlService: () => Promise }).stopBrowserControlService + : (mod as { stopBrowserControlServer?: () => Promise }).stopBrowserControlServer; + if (!start) return null; + await start(); + return { stop: stop ?? (async () => {}) }; } diff --git a/src/gateway/server-methods-list.ts b/src/gateway/server-methods-list.ts index 28ee5be54..098384d44 100644 --- a/src/gateway/server-methods-list.ts +++ b/src/gateway/server-methods-list.ts @@ -77,6 +77,7 @@ const BASE_METHODS = [ "agent", "agent.identity.get", "agent.wait", + "browser.request", // WebChat WebSocket-native chat methods "chat.history", "chat.abort", diff --git a/src/gateway/server-methods.ts b/src/gateway/server-methods.ts index 48bf32b59..66492b976 100644 --- a/src/gateway/server-methods.ts +++ b/src/gateway/server-methods.ts @@ -1,6 +1,7 @@ import { ErrorCodes, errorShape } from "./protocol/index.js"; import { agentHandlers } from "./server-methods/agent.js"; import { agentsHandlers } from "./server-methods/agents.js"; +import { browserHandlers } from "./server-methods/browser.js"; import { channelsHandlers } from "./server-methods/channels.js"; import { chatHandlers } from "./server-methods/chat.js"; import { configHandlers } from "./server-methods/config.js"; @@ -86,6 +87,7 @@ const WRITE_METHODS = new Set([ "node.invoke", "chat.send", "chat.abort", + "browser.request", ]); function authorizeGatewayMethod(method: string, client: GatewayRequestOptions["client"]) { @@ -168,6 +170,7 @@ export const coreGatewayHandlers: GatewayRequestHandlers = { ...usageHandlers, ...agentHandlers, ...agentsHandlers, + ...browserHandlers, }; export async function handleGatewayRequest( diff --git a/src/gateway/server-methods/browser.ts b/src/gateway/server-methods/browser.ts new file mode 100644 index 000000000..16811fbcf --- /dev/null +++ b/src/gateway/server-methods/browser.ts @@ -0,0 +1,253 @@ +import crypto from "node:crypto"; +import { + createBrowserControlContext, + startBrowserControlServiceFromConfig, +} from "../../browser/control-service.js"; +import { createBrowserRouteDispatcher } from "../../browser/routes/dispatcher.js"; +import { loadConfig } from "../../config/config.js"; +import { saveMediaBuffer } from "../../media/store.js"; +import { isNodeCommandAllowed, resolveNodeCommandAllowlist } from "../node-command-policy.js"; +import type { NodeSession } from "../node-registry.js"; +import { ErrorCodes, errorShape } from "../protocol/index.js"; +import { safeParseJson } from "./nodes.helpers.js"; +import type { GatewayRequestHandlers } from "./types.js"; + +type BrowserRequestParams = { + method?: string; + path?: string; + query?: Record; + body?: unknown; + timeoutMs?: number; +}; + +type BrowserProxyFile = { + path: string; + base64: string; + mimeType?: string; +}; + +type BrowserProxyResult = { + result: unknown; + files?: BrowserProxyFile[]; +}; + +function isBrowserNode(node: NodeSession) { + const caps = Array.isArray(node.caps) ? node.caps : []; + const commands = Array.isArray(node.commands) ? node.commands : []; + return caps.includes("browser") || commands.includes("browser.proxy"); +} + +function normalizeNodeKey(value: string) { + return value + .trim() + .toLowerCase() + .replace(/[^a-z0-9]+/g, ""); +} + +function resolveBrowserNode(nodes: NodeSession[], query: string): NodeSession | null { + const q = query.trim(); + if (!q) return null; + const qNorm = normalizeNodeKey(q); + const matches = nodes.filter((node) => { + if (node.nodeId === q) return true; + if (typeof node.remoteIp === "string" && node.remoteIp === q) return true; + const name = typeof node.displayName === "string" ? node.displayName : ""; + if (name && normalizeNodeKey(name) === qNorm) return true; + if (q.length >= 6 && node.nodeId.startsWith(q)) return true; + return false; + }); + if (matches.length === 1) return matches[0] ?? null; + if (matches.length === 0) return null; + throw new Error( + `ambiguous node: ${q} (matches: ${matches + .map((node) => node.displayName || node.remoteIp || node.nodeId) + .join(", ")})`, + ); +} + +function resolveBrowserNodeTarget(params: { + cfg: ReturnType; + nodes: NodeSession[]; +}): NodeSession | null { + const policy = params.cfg.gateway?.nodes?.browser; + const mode = policy?.mode ?? "auto"; + if (mode === "off") return null; + const browserNodes = params.nodes.filter((node) => isBrowserNode(node)); + if (browserNodes.length === 0) { + if (policy?.node?.trim()) { + throw new Error("No connected browser-capable nodes."); + } + return null; + } + const requested = policy?.node?.trim() || ""; + if (requested) { + const resolved = resolveBrowserNode(browserNodes, requested); + if (!resolved) { + throw new Error(`Configured browser node not connected: ${requested}`); + } + return resolved; + } + if (mode === "manual") return null; + if (browserNodes.length === 1) return browserNodes[0] ?? null; + return null; +} + +async function persistProxyFiles(files: BrowserProxyFile[] | undefined) { + if (!files || files.length === 0) return new Map(); + const mapping = new Map(); + for (const file of files) { + const buffer = Buffer.from(file.base64, "base64"); + const saved = await saveMediaBuffer(buffer, file.mimeType, "browser", buffer.byteLength); + mapping.set(file.path, saved.path); + } + return mapping; +} + +function applyProxyPaths(result: unknown, mapping: Map) { + if (!result || typeof result !== "object") return; + const obj = result as Record; + if (typeof obj.path === "string" && mapping.has(obj.path)) { + obj.path = mapping.get(obj.path); + } + if (typeof obj.imagePath === "string" && mapping.has(obj.imagePath)) { + obj.imagePath = mapping.get(obj.imagePath); + } + const download = obj.download; + if (download && typeof download === "object") { + const d = download as Record; + if (typeof d.path === "string" && mapping.has(d.path)) { + d.path = mapping.get(d.path); + } + } +} + +export const browserHandlers: GatewayRequestHandlers = { + "browser.request": async ({ params, respond, context }) => { + const typed = params as BrowserRequestParams; + const methodRaw = typeof typed.method === "string" ? typed.method.trim().toUpperCase() : ""; + const path = typeof typed.path === "string" ? typed.path.trim() : ""; + const query = typed.query && typeof typed.query === "object" ? typed.query : undefined; + const body = typed.body; + const timeoutMs = + typeof typed.timeoutMs === "number" && Number.isFinite(typed.timeoutMs) + ? Math.max(1, Math.floor(typed.timeoutMs)) + : undefined; + + if (!methodRaw || !path) { + respond( + false, + undefined, + errorShape(ErrorCodes.INVALID_REQUEST, "method and path are required"), + ); + return; + } + if (methodRaw !== "GET" && methodRaw !== "POST" && methodRaw !== "DELETE") { + respond( + false, + undefined, + errorShape(ErrorCodes.INVALID_REQUEST, "method must be GET, POST, or DELETE"), + ); + return; + } + + const cfg = loadConfig(); + let nodeTarget: NodeSession | null = null; + try { + nodeTarget = resolveBrowserNodeTarget({ + cfg, + nodes: context.nodeRegistry.listConnected(), + }); + } catch (err) { + respond(false, undefined, errorShape(ErrorCodes.UNAVAILABLE, String(err))); + return; + } + + if (nodeTarget) { + const allowlist = resolveNodeCommandAllowlist(cfg, nodeTarget); + const allowed = isNodeCommandAllowed({ + command: "browser.proxy", + declaredCommands: nodeTarget.commands, + allowlist, + }); + if (!allowed.ok) { + respond( + false, + undefined, + errorShape(ErrorCodes.INVALID_REQUEST, "node command not allowed", { + details: { reason: allowed.reason, command: "browser.proxy" }, + }), + ); + return; + } + + const proxyParams = { + method: methodRaw, + path, + query, + body, + timeoutMs, + profile: typeof query?.profile === "string" ? query.profile : undefined, + }; + const res = await context.nodeRegistry.invoke({ + nodeId: nodeTarget.nodeId, + command: "browser.proxy", + params: proxyParams, + timeoutMs, + idempotencyKey: crypto.randomUUID(), + }); + if (!res.ok) { + respond( + false, + undefined, + errorShape(ErrorCodes.UNAVAILABLE, res.error?.message ?? "node invoke failed", { + details: { nodeError: res.error ?? null }, + }), + ); + return; + } + const payload = res.payloadJSON ? safeParseJson(res.payloadJSON) : res.payload; + const proxy = payload && typeof payload === "object" ? (payload as BrowserProxyResult) : null; + if (!proxy || !("result" in proxy)) { + respond(false, undefined, errorShape(ErrorCodes.UNAVAILABLE, "browser proxy failed")); + return; + } + const mapping = await persistProxyFiles(proxy.files); + applyProxyPaths(proxy.result, mapping); + respond(true, proxy.result); + return; + } + + const ready = await startBrowserControlServiceFromConfig(); + if (!ready) { + respond(false, undefined, errorShape(ErrorCodes.UNAVAILABLE, "browser control is disabled")); + return; + } + + let dispatcher; + try { + dispatcher = createBrowserRouteDispatcher(createBrowserControlContext()); + } catch (err) { + respond(false, undefined, errorShape(ErrorCodes.UNAVAILABLE, String(err))); + return; + } + + const result = await dispatcher.dispatch({ + method: methodRaw, + path, + query, + body, + }); + + if (result.status >= 400) { + const message = + result.body && typeof result.body === "object" && "error" in result.body + ? String((result.body as { error?: unknown }).error) + : `browser request failed (${result.status})`; + const code = result.status >= 500 ? ErrorCodes.UNAVAILABLE : ErrorCodes.INVALID_REQUEST; + respond(false, undefined, errorShape(code, message, { details: result.body })); + return; + } + + respond(true, result.body); + }, +}; diff --git a/src/gateway/server.reload.e2e.test.ts b/src/gateway/server.reload.e2e.test.ts index 8fe8eece1..b9fc76d98 100644 --- a/src/gateway/server.reload.e2e.test.ts +++ b/src/gateway/server.reload.e2e.test.ts @@ -206,7 +206,7 @@ describe("gateway hot reload", () => { }, cron: { enabled: true, store: "/tmp/cron.json" }, agents: { defaults: { heartbeat: { every: "1m" }, maxConcurrent: 2 } }, - browser: { enabled: true, controlUrl: "http://127.0.0.1:18791" }, + browser: { enabled: true }, web: { enabled: true }, channels: { telegram: { botToken: "token" }, diff --git a/src/node-host/runner.ts b/src/node-host/runner.ts index f76065883..278244a78 100644 --- a/src/node-host/runner.ts +++ b/src/node-host/runner.ts @@ -33,7 +33,12 @@ import { import { getMachineDisplayName } from "../infra/machine-name.js"; import { loadOrCreateDeviceIdentity } from "../infra/device-identity.js"; import { loadConfig } from "../config/config.js"; -import { resolveBrowserConfig, shouldStartLocalBrowserServer } from "../browser/config.js"; +import { resolveBrowserConfig } from "../browser/config.js"; +import { + createBrowserControlContext, + startBrowserControlServiceFromConfig, +} from "../browser/control-service.js"; +import { createBrowserRouteDispatcher } from "../browser/routes/dispatcher.js"; import { detectMime } from "../media/mime.js"; import { resolveAgentConfig } from "../agents/agent-scope.js"; import { ensureClawdbotCliOnPath } from "../infra/path-env.js"; @@ -235,23 +240,39 @@ function resolveBrowserProxyConfig() { let browserControlReady: Promise | null = null; -async function ensureBrowserControlServer(): Promise { +async function ensureBrowserControlService(): Promise { if (browserControlReady) return browserControlReady; browserControlReady = (async () => { const cfg = loadConfig(); - const resolved = resolveBrowserConfig(cfg.browser); + const resolved = resolveBrowserConfig(cfg.browser, cfg); if (!resolved.enabled) { throw new Error("browser control disabled"); } - if (!shouldStartLocalBrowserServer(resolved)) { - throw new Error("browser control URL is non-loopback"); - } - const mod = await import("../browser/server.js"); - await mod.startBrowserControlServerFromConfig(); + const started = await startBrowserControlServiceFromConfig(); + if (!started) throw new Error("browser control disabled"); })(); return browserControlReady; } +async function withTimeout(promise: Promise, timeoutMs?: number, label?: string): Promise { + const resolved = + typeof timeoutMs === "number" && Number.isFinite(timeoutMs) + ? Math.max(1, Math.floor(timeoutMs)) + : undefined; + if (!resolved) return await promise; + let timer: ReturnType | undefined; + const timeoutPromise = new Promise((_, reject) => { + timer = setTimeout(() => { + reject(new Error(`${label ?? "request"} timed out`)); + }, resolved); + }); + try { + return await Promise.race([promise, timeoutPromise]); + } finally { + if (timer) clearTimeout(timer); + } +} + function isProfileAllowed(params: { allowProfiles: string[]; profile?: string | null }) { const { allowProfiles, profile } = params; if (!allowProfiles.length) return true; @@ -488,11 +509,8 @@ export async function runNodeHost(opts: NodeHostRunOptions): Promise { const cfg = loadConfig(); const browserProxy = resolveBrowserProxyConfig(); - const resolvedBrowser = resolveBrowserConfig(cfg.browser); - const browserProxyEnabled = - browserProxy.enabled && - resolvedBrowser.enabled && - shouldStartLocalBrowserServer(resolvedBrowser); + const resolvedBrowser = resolveBrowserConfig(cfg.browser, cfg); + const browserProxyEnabled = browserProxy.enabled && resolvedBrowser.enabled; const isRemoteMode = cfg.gateway?.mode === "remote"; const token = process.env.CLAWDBOT_GATEWAY_TOKEN?.trim() || @@ -584,9 +602,11 @@ async function handleInvoke( payloadJSON: JSON.stringify(payload), }); } catch (err) { + const message = String(err); + const code = message.toLowerCase().includes("timed out") ? "TIMEOUT" : "INVALID_REQUEST"; await sendInvokeResult(client, frame, { ok: false, - error: { code: "INVALID_REQUEST", message: String(err) }, + error: { code, message }, }); } return; @@ -667,8 +687,9 @@ async function handleInvoke( if (!proxyConfig.enabled) { throw new Error("UNAVAILABLE: node browser proxy disabled"); } - await ensureBrowserControlServer(); - const resolved = resolveBrowserConfig(loadConfig().browser); + await ensureBrowserControlService(); + const cfg = loadConfig(); + const resolved = resolveBrowserConfig(cfg.browser, cfg); const requestedProfile = typeof params.profile === "string" ? params.profile.trim() : ""; const allowedProfiles = proxyConfig.allowProfiles; if (allowedProfiles.length > 0) { @@ -684,54 +705,38 @@ async function handleInvoke( } } - const url = new URL( - pathValue.startsWith("/") ? pathValue : `/${pathValue}`, - resolved.controlUrl, - ); - if (requestedProfile) { - url.searchParams.set("profile", requestedProfile); - } - const query = params.query ?? {}; - for (const [key, value] of Object.entries(query)) { - if (value === undefined || value === null) continue; - url.searchParams.set(key, String(value)); - } const method = typeof params.method === "string" ? params.method.toUpperCase() : "GET"; + const path = pathValue.startsWith("/") ? pathValue : `/${pathValue}`; const body = params.body; - const ctrl = new AbortController(); - const timeoutMs = - typeof params.timeoutMs === "number" && Number.isFinite(params.timeoutMs) - ? Math.max(1, Math.floor(params.timeoutMs)) - : 20_000; - const timer = setTimeout(() => ctrl.abort(), timeoutMs); - const headers = new Headers(); - let bodyJson: string | undefined; - if (body !== undefined) { - headers.set("Content-Type", "application/json"); - bodyJson = JSON.stringify(body); + const query: Record = {}; + if (requestedProfile) { + query.profile = requestedProfile; } - const token = - process.env.CLAWDBOT_BROWSER_CONTROL_TOKEN?.trim() || resolved.controlToken?.trim(); - if (token) { - headers.set("Authorization", `Bearer ${token}`); + const rawQuery = params.query ?? {}; + for (const [key, value] of Object.entries(rawQuery)) { + if (value === undefined || value === null) continue; + query[key] = typeof value === "string" ? value : String(value); } - let res: Response; - try { - res = await fetch(url.toString(), { - method, - headers, - body: bodyJson, - signal: ctrl.signal, - }); - } finally { - clearTimeout(timer); + const dispatcher = createBrowserRouteDispatcher(createBrowserControlContext()); + const response = await withTimeout( + dispatcher.dispatch({ + method: method === "DELETE" ? "DELETE" : method === "POST" ? "POST" : "GET", + path, + query, + body, + }), + params.timeoutMs, + "browser proxy request", + ); + if (response.status >= 400) { + const message = + response.body && typeof response.body === "object" && "error" in response.body + ? String((response.body as { error?: unknown }).error) + : `HTTP ${response.status}`; + throw new Error(message); } - if (!res.ok) { - const text = await res.text().catch(() => ""); - throw new Error(text ? `${res.status}: ${text}` : `HTTP ${res.status}`); - } - const result = (await res.json()) as unknown; - if (allowedProfiles.length > 0 && url.pathname === "/profiles") { + const result = response.body as unknown; + if (allowedProfiles.length > 0 && path === "/profiles") { const obj = typeof result === "object" && result !== null ? (result as Record) : {}; const profiles = Array.isArray(obj.profiles) ? obj.profiles : []; diff --git a/src/security/audit-extra.ts b/src/security/audit-extra.ts index 9aabb9721..89b1f3e63 100644 --- a/src/security/audit-extra.ts +++ b/src/security/audit-extra.ts @@ -73,7 +73,7 @@ export function collectAttackSurfaceSummaryFindings(cfg: ClawdbotConfig): Securi const group = summarizeGroupPolicy(cfg); const elevated = cfg.tools?.elevated?.enabled !== false; const hooksEnabled = cfg.hooks?.enabled === true; - const browserEnabled = Boolean(cfg.browser?.enabled ?? cfg.browser?.controlUrl); + const browserEnabled = cfg.browser?.enabled ?? true; const detail = `groups: open=${group.open}, allowlist=${group.allowlist}` + @@ -143,20 +143,6 @@ export function collectSecretsInConfigFindings(cfg: ClawdbotConfig): SecurityAud }); } - const browserToken = - typeof cfg.browser?.controlToken === "string" ? cfg.browser.controlToken.trim() : ""; - if (browserToken && !looksLikeEnvRef(browserToken)) { - findings.push({ - checkId: "config.secrets.browser_control_token_in_config", - severity: "warn", - title: "Browser control token is stored in config", - detail: - "browser.controlToken is set in the config file; prefer environment variables for secrets when possible.", - remediation: - "Prefer CLAWDBOT_BROWSER_CONTROL_TOKEN (env) and remove browser.controlToken from disk.", - }); - } - const hooksToken = typeof cfg.hooks?.token === "string" ? cfg.hooks.token.trim() : ""; if (cfg.hooks?.enabled === true && hooksToken && !looksLikeEnvRef(hooksToken)) { findings.push({ @@ -206,21 +192,6 @@ export function collectHooksHardeningFindings(cfg: ClawdbotConfig): SecurityAudi }); } - const browserToken = - typeof cfg.browser?.controlToken === "string" && cfg.browser.controlToken.trim() - ? cfg.browser.controlToken.trim() - : process.env.CLAWDBOT_BROWSER_CONTROL_TOKEN?.trim() || null; - if (token && browserToken && token === browserToken) { - findings.push({ - checkId: "hooks.token_reuse_browser_token", - severity: "warn", - title: "Hooks token reuses the browser control token", - detail: - "hooks.token matches browser control token; compromise of hooks may enable browser control endpoints.", - remediation: "Use a separate hooks.token dedicated to hook ingress.", - }); - } - const rawPath = typeof cfg.hooks?.path === "string" ? cfg.hooks.path.trim() : ""; if (rawPath === "/") { findings.push({ @@ -457,7 +428,7 @@ function isWebFetchEnabled(cfg: ClawdbotConfig): boolean { function isBrowserEnabled(cfg: ClawdbotConfig): boolean { try { - return resolveBrowserConfig(cfg.browser).enabled; + return resolveBrowserConfig(cfg.browser, cfg).enabled; } catch { return true; } diff --git a/src/security/audit.test.ts b/src/security/audit.test.ts index 3a43ff4cc..ade919d5a 100644 --- a/src/security/audit.test.ts +++ b/src/security/audit.test.ts @@ -274,41 +274,13 @@ describe("security audit", () => { ); }); - it("flags remote browser control without token as critical", async () => { - const prev = process.env.CLAWDBOT_BROWSER_CONTROL_TOKEN; - delete process.env.CLAWDBOT_BROWSER_CONTROL_TOKEN; - try { - const cfg: ClawdbotConfig = { - browser: { - controlUrl: "http://example.com:18791", - }, - }; - - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, - }); - - expect(res.findings).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - checkId: "browser.control_remote_no_token", - severity: "critical", - }), - ]), - ); - } finally { - if (prev === undefined) delete process.env.CLAWDBOT_BROWSER_CONTROL_TOKEN; - else process.env.CLAWDBOT_BROWSER_CONTROL_TOKEN = prev; - } - }); - - it("warns when browser control token matches gateway auth token", async () => { - const token = "0123456789abcdef0123456789abcdef"; + it("warns when remote CDP uses HTTP", async () => { const cfg: ClawdbotConfig = { - gateway: { auth: { token } }, - browser: { controlUrl: "https://browser.example.com", controlToken: token }, + browser: { + profiles: { + remote: { cdpUrl: "http://example.com:9222", color: "#0066CC" }, + }, + }, }; const res = await runSecurityAudit({ @@ -319,42 +291,11 @@ describe("security audit", () => { expect(res.findings).toEqual( expect.arrayContaining([ - expect.objectContaining({ - checkId: "browser.control_token_reuse_gateway_token", - severity: "warn", - }), + expect.objectContaining({ checkId: "browser.remote_cdp_http", severity: "warn" }), ]), ); }); - it("warns when remote browser control uses HTTP", async () => { - const prev = process.env.CLAWDBOT_BROWSER_CONTROL_TOKEN; - delete process.env.CLAWDBOT_BROWSER_CONTROL_TOKEN; - try { - const cfg: ClawdbotConfig = { - browser: { - controlUrl: "http://example.com:18791", - controlToken: "0123456789abcdef01234567", - }, - }; - - const res = await runSecurityAudit({ - config: cfg, - includeFilesystem: false, - includeChannelSecurity: false, - }); - - expect(res.findings).toEqual( - expect.arrayContaining([ - expect.objectContaining({ checkId: "browser.control_remote_http", severity: "warn" }), - ]), - ); - } finally { - if (prev === undefined) delete process.env.CLAWDBOT_BROWSER_CONTROL_TOKEN; - else process.env.CLAWDBOT_BROWSER_CONTROL_TOKEN = prev; - } - }); - it("warns when control UI allows insecure auth", async () => { const cfg: ClawdbotConfig = { gateway: { diff --git a/src/security/audit.ts b/src/security/audit.ts index 6cac2c37c..a96213134 100644 --- a/src/security/audit.ts +++ b/src/security/audit.ts @@ -356,82 +356,41 @@ function collectGatewayConfigFindings( return findings; } -function isLoopbackClientHost(hostname: string): boolean { - const h = hostname.trim().toLowerCase(); - return h === "localhost" || h === "127.0.0.1" || h === "::1"; -} - function collectBrowserControlFindings(cfg: ClawdbotConfig): SecurityAuditFinding[] { const findings: SecurityAuditFinding[] = []; let resolved: ReturnType; try { - resolved = resolveBrowserConfig(cfg.browser); + resolved = resolveBrowserConfig(cfg.browser, cfg); } catch (err) { findings.push({ checkId: "browser.control_invalid_config", severity: "warn", title: "Browser control config looks invalid", detail: String(err), - remediation: `Fix browser.controlUrl/browser.cdpUrl in ${resolveConfigPath()} and re-run "${formatCliCommand("clawdbot security audit --deep")}".`, + remediation: `Fix browser.cdpUrl in ${resolveConfigPath()} and re-run "${formatCliCommand("clawdbot security audit --deep")}".`, }); return findings; } if (!resolved.enabled) return findings; - const url = new URL(resolved.controlUrl); - const isLoopback = isLoopbackClientHost(url.hostname); - const envToken = process.env.CLAWDBOT_BROWSER_CONTROL_TOKEN?.trim(); - const controlToken = (envToken || resolved.controlToken)?.trim() || null; - - if (!isLoopback) { - if (!controlToken) { - findings.push({ - checkId: "browser.control_remote_no_token", - severity: "critical", - title: "Remote browser control is missing an auth token", - detail: `browser.controlUrl is non-loopback (${resolved.controlUrl}) but no browser.controlToken (or CLAWDBOT_BROWSER_CONTROL_TOKEN) is configured.`, - remediation: - "Set browser.controlToken (or export CLAWDBOT_BROWSER_CONTROL_TOKEN) and prefer serving over Tailscale Serve or HTTPS reverse proxy.", - }); + for (const name of Object.keys(resolved.profiles)) { + const profile = resolveProfile(resolved, name); + if (!profile || profile.cdpIsLoopback) continue; + let url: URL; + try { + url = new URL(profile.cdpUrl); + } catch { + continue; } - if (url.protocol === "http:") { findings.push({ - checkId: "browser.control_remote_http", + checkId: "browser.remote_cdp_http", severity: "warn", - title: "Remote browser control uses HTTP", - detail: `browser.controlUrl=${resolved.controlUrl} is http; this is OK only if it's tailnet-only (Tailscale) or behind another encrypted tunnel.`, - remediation: `Prefer HTTPS termination (Tailscale Serve) and keep the endpoint tailnet-only.`, - }); - } - - if (controlToken && controlToken.length < 24) { - findings.push({ - checkId: "browser.control_token_too_short", - severity: "warn", - title: "Browser control token looks short", - detail: `browser control token is ${controlToken.length} chars; prefer a long random token.`, - }); - } - - const tailscaleMode = cfg.gateway?.tailscale?.mode ?? "off"; - const gatewayAuth = resolveGatewayAuth({ authConfig: cfg.gateway?.auth, tailscaleMode }); - const gatewayToken = - gatewayAuth.mode === "token" && - typeof gatewayAuth.token === "string" && - gatewayAuth.token.trim() - ? gatewayAuth.token.trim() - : null; - - if (controlToken && gatewayToken && controlToken === gatewayToken) { - findings.push({ - checkId: "browser.control_token_reuse_gateway_token", - severity: "warn", - title: "Browser control token reuses the Gateway token", - detail: `browser.controlToken matches gateway.auth token; compromise of browser control expands blast radius to the Gateway API.`, - remediation: `Use a separate browser.controlToken dedicated to browser control.`, + title: "Remote CDP uses HTTP", + detail: `browser profile "${name}" uses http CDP (${profile.cdpUrl}); this is OK only if it's tailnet-only or behind an encrypted tunnel.`, + remediation: `Prefer HTTPS/TLS or a tailnet-only endpoint for remote CDP.`, }); } } From 8b56f0e68d977b9141bb5e24622b47707d3eb8de Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Tue, 27 Jan 2026 03:30:26 +0000 Subject: [PATCH 005/129] docs: warn against public web binding --- SECURITY.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/SECURITY.md b/SECURITY.md index 11aa0b781..5bc9c9112 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -13,6 +13,10 @@ For threat model + hardening guidance (including `clawdbot security audit --deep - `https://docs.clawd.bot/gateway/security` +### Web Interface Safety + +Clawdbot's web interface is intended for local use only. Do **not** bind it to the public internet; it is not hardened for public exposure. + ## Runtime Requirements ### Node.js Version From 5eee991913bc8410775168b647aab9f87e45a1d3 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 26 Jan 2026 20:05:03 +0000 Subject: [PATCH 006/129] fix: harden file serving --- src/canvas-host/server.ts | 50 ++++++++++-------- src/infra/fs-safe.ts | 103 ++++++++++++++++++++++++++++++++++++++ src/media/server.test.ts | 36 +++++++++++-- src/media/server.ts | 52 +++++++++++++------ src/media/store.ts | 22 ++++---- 5 files changed, 213 insertions(+), 50 deletions(-) create mode 100644 src/infra/fs-safe.ts diff --git a/src/canvas-host/server.ts b/src/canvas-host/server.ts index b04d0d5ff..7cde546b8 100644 --- a/src/canvas-host/server.ts +++ b/src/canvas-host/server.ts @@ -8,6 +8,7 @@ import type { Duplex } from "node:stream"; import chokidar from "chokidar"; import { type WebSocket, WebSocketServer } from "ws"; import { isTruthyEnvValue } from "../infra/env.js"; +import { SafeOpenError, openFileWithinRoot } from "../infra/fs-safe.js"; import { detectMime } from "../media/mime.js"; import type { RuntimeEnv } from "../runtime.js"; import { ensureDir, resolveUserPath } from "../utils.js"; @@ -145,30 +146,31 @@ async function resolveFilePath(rootReal: string, urlPath: string) { const rel = normalized.replace(/^\/+/, ""); if (rel.split("/").some((p) => p === "..")) return null; - let candidate = path.join(rootReal, rel); + const tryOpen = async (relative: string) => { + try { + return await openFileWithinRoot({ rootDir: rootReal, relativePath: relative }); + } catch (err) { + if (err instanceof SafeOpenError) return null; + throw err; + } + }; + if (normalized.endsWith("/")) { - candidate = path.join(candidate, "index.html"); + return await tryOpen(path.posix.join(rel, "index.html")); } + const candidate = path.join(rootReal, rel); try { - const st = await fs.stat(candidate); + const st = await fs.lstat(candidate); + if (st.isSymbolicLink()) return null; if (st.isDirectory()) { - candidate = path.join(candidate, "index.html"); + return await tryOpen(path.posix.join(rel, "index.html")); } } catch { // ignore } - const rootPrefix = rootReal.endsWith(path.sep) ? rootReal : `${rootReal}${path.sep}`; - try { - const lstat = await fs.lstat(candidate); - if (lstat.isSymbolicLink()) return null; - const real = await fs.realpath(candidate); - if (!real.startsWith(rootPrefix)) return null; - return real; - } catch { - return null; - } + return await tryOpen(rel); } function isDisabledByEnv() { @@ -311,8 +313,8 @@ export async function createCanvasHostHandler( return true; } - const filePath = await resolveFilePath(rootReal, urlPath); - if (!filePath) { + const opened = await resolveFilePath(rootReal, urlPath); + if (!opened) { if (urlPath === "/" || urlPath.endsWith("/")) { res.statusCode = 404; res.setHeader("Content-Type", "text/html; charset=utf-8"); @@ -327,22 +329,30 @@ export async function createCanvasHostHandler( return true; } - const lower = filePath.toLowerCase(); + const { handle, realPath } = opened; + let data: Buffer; + try { + data = await handle.readFile(); + } finally { + await handle.close().catch(() => {}); + } + + const lower = realPath.toLowerCase(); const mime = lower.endsWith(".html") || lower.endsWith(".htm") ? "text/html" - : ((await detectMime({ filePath })) ?? "application/octet-stream"); + : ((await detectMime({ filePath: realPath })) ?? "application/octet-stream"); res.setHeader("Cache-Control", "no-store"); if (mime === "text/html") { - const html = await fs.readFile(filePath, "utf8"); + const html = data.toString("utf8"); res.setHeader("Content-Type", "text/html; charset=utf-8"); res.end(liveReload ? injectCanvasLiveReload(html) : html); return true; } res.setHeader("Content-Type", mime); - res.end(await fs.readFile(filePath)); + res.end(data); return true; } catch (err) { opts.runtime.error(`canvasHost request failed: ${String(err)}`); diff --git a/src/infra/fs-safe.ts b/src/infra/fs-safe.ts new file mode 100644 index 000000000..52a94b46f --- /dev/null +++ b/src/infra/fs-safe.ts @@ -0,0 +1,103 @@ +import { constants as fsConstants } from "node:fs"; +import type { Stats } from "node:fs"; +import type { FileHandle } from "node:fs/promises"; +import fs from "node:fs/promises"; +import path from "node:path"; + +export type SafeOpenErrorCode = "invalid-path" | "not-found"; + +export class SafeOpenError extends Error { + code: SafeOpenErrorCode; + + constructor(code: SafeOpenErrorCode, message: string) { + super(message); + this.code = code; + this.name = "SafeOpenError"; + } +} + +export type SafeOpenResult = { + handle: FileHandle; + realPath: string; + stat: Stats; +}; + +const NOT_FOUND_CODES = new Set(["ENOENT", "ENOTDIR"]); + +const ensureTrailingSep = (value: string) => (value.endsWith(path.sep) ? value : value + path.sep); + +const isNodeError = (err: unknown): err is NodeJS.ErrnoException => + Boolean(err && typeof err === "object" && "code" in (err as Record)); + +const isNotFoundError = (err: unknown) => + isNodeError(err) && typeof err.code === "string" && NOT_FOUND_CODES.has(err.code); + +const isSymlinkOpenError = (err: unknown) => + isNodeError(err) && (err.code === "ELOOP" || err.code === "EINVAL" || err.code === "ENOTSUP"); + +export async function openFileWithinRoot(params: { + rootDir: string; + relativePath: string; +}): Promise { + let rootReal: string; + try { + rootReal = await fs.realpath(params.rootDir); + } catch (err) { + if (isNotFoundError(err)) { + throw new SafeOpenError("not-found", "root dir not found"); + } + throw err; + } + const rootWithSep = ensureTrailingSep(rootReal); + const resolved = path.resolve(rootWithSep, params.relativePath); + if (!resolved.startsWith(rootWithSep)) { + throw new SafeOpenError("invalid-path", "path escapes root"); + } + + const supportsNoFollow = process.platform !== "win32" && "O_NOFOLLOW" in fsConstants; + const flags = fsConstants.O_RDONLY | (supportsNoFollow ? (fsConstants.O_NOFOLLOW as number) : 0); + + let handle: FileHandle; + try { + handle = await fs.open(resolved, flags); + } catch (err) { + if (isNotFoundError(err)) { + throw new SafeOpenError("not-found", "file not found"); + } + if (isSymlinkOpenError(err)) { + throw new SafeOpenError("invalid-path", "symlink open blocked"); + } + throw err; + } + + try { + const lstat = await fs.lstat(resolved).catch(() => null); + if (lstat?.isSymbolicLink()) { + throw new SafeOpenError("invalid-path", "symlink not allowed"); + } + + const realPath = await fs.realpath(resolved); + if (!realPath.startsWith(rootWithSep)) { + throw new SafeOpenError("invalid-path", "path escapes root"); + } + + const stat = await handle.stat(); + if (!stat.isFile()) { + throw new SafeOpenError("invalid-path", "not a file"); + } + + const realStat = await fs.stat(realPath); + if (stat.ino !== realStat.ino || stat.dev !== realStat.dev) { + throw new SafeOpenError("invalid-path", "path mismatch"); + } + + return { handle, realPath, stat }; + } catch (err) { + await handle.close().catch(() => {}); + if (err instanceof SafeOpenError) throw err; + if (isNotFoundError(err)) { + throw new SafeOpenError("not-found", "file not found"); + } + throw err; + } +} diff --git a/src/media/server.test.ts b/src/media/server.test.ts index 693ba5940..34182c5f2 100644 --- a/src/media/server.test.ts +++ b/src/media/server.test.ts @@ -7,12 +7,17 @@ import { afterAll, beforeAll, describe, expect, it, vi } from "vitest"; const MEDIA_DIR = path.join(process.cwd(), "tmp-media-test"); const cleanOldMedia = vi.fn().mockResolvedValue(undefined); -vi.mock("./store.js", () => ({ - getMediaDir: () => MEDIA_DIR, - cleanOldMedia, -})); +vi.mock("./store.js", async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + getMediaDir: () => MEDIA_DIR, + cleanOldMedia, + }; +}); const { startMediaServer } = await import("./server.js"); +const { MEDIA_MAX_BYTES } = await import("./store.js"); const waitForFileRemoval = async (file: string, timeoutMs = 200) => { const start = Date.now(); @@ -84,4 +89,27 @@ describe("media server", () => { expect(await res.text()).toBe("invalid path"); await new Promise((r) => server.close(r)); }); + + it("rejects invalid media ids", async () => { + const file = path.join(MEDIA_DIR, "file2"); + await fs.writeFile(file, "hello"); + const server = await startMediaServer(0, 5_000); + const port = (server.address() as AddressInfo).port; + const res = await fetch(`http://localhost:${port}/media/invalid%20id`); + expect(res.status).toBe(400); + expect(await res.text()).toBe("invalid path"); + await new Promise((r) => server.close(r)); + }); + + it("rejects oversized media files", async () => { + const file = path.join(MEDIA_DIR, "big"); + await fs.writeFile(file, ""); + await fs.truncate(file, MEDIA_MAX_BYTES + 1); + const server = await startMediaServer(0, 5_000); + const port = (server.address() as AddressInfo).port; + const res = await fetch(`http://localhost:${port}/media/big`); + expect(res.status).toBe(413); + expect(await res.text()).toBe("too large"); + await new Promise((r) => server.close(r)); + }); }); diff --git a/src/media/server.ts b/src/media/server.ts index e0af8b908..4791352d8 100644 --- a/src/media/server.ts +++ b/src/media/server.ts @@ -1,13 +1,23 @@ import fs from "node:fs/promises"; import type { Server } from "node:http"; -import path from "node:path"; import express, { type Express } from "express"; import { danger } from "../globals.js"; import { defaultRuntime, type RuntimeEnv } from "../runtime.js"; +import { SafeOpenError, openFileWithinRoot } from "../infra/fs-safe.js"; import { detectMime } from "./mime.js"; -import { cleanOldMedia, getMediaDir } from "./store.js"; +import { cleanOldMedia, getMediaDir, MEDIA_MAX_BYTES } from "./store.js"; const DEFAULT_TTL_MS = 2 * 60 * 1000; +const MAX_MEDIA_ID_CHARS = 200; +const MEDIA_ID_PATTERN = /^[\p{L}\p{N}._-]+$/u; +const MAX_MEDIA_BYTES = MEDIA_MAX_BYTES; + +const isValidMediaId = (id: string) => { + if (!id) return false; + if (id.length > MAX_MEDIA_ID_CHARS) return false; + if (id === "." || id === "..") return false; + return MEDIA_ID_PATTERN.test(id); +}; export function attachMediaRoutes( app: Express, @@ -18,26 +28,28 @@ export function attachMediaRoutes( app.get("/media/:id", async (req, res) => { const id = req.params.id; - const mediaRoot = (await fs.realpath(mediaDir)) + path.sep; - const file = path.resolve(mediaRoot, id); + if (!isValidMediaId(id)) { + res.status(400).send("invalid path"); + return; + } try { - const lstat = await fs.lstat(file); - if (lstat.isSymbolicLink()) { - res.status(400).send("invalid path"); + const { handle, realPath, stat } = await openFileWithinRoot({ + rootDir: mediaDir, + relativePath: id, + }); + if (stat.size > MAX_MEDIA_BYTES) { + await handle.close().catch(() => {}); + res.status(413).send("too large"); return; } - const realPath = await fs.realpath(file); - if (!realPath.startsWith(mediaRoot)) { - res.status(400).send("invalid path"); - return; - } - const stat = await fs.stat(realPath); if (Date.now() - stat.mtimeMs > ttlMs) { + await handle.close().catch(() => {}); await fs.rm(realPath).catch(() => {}); res.status(410).send("expired"); return; } - const data = await fs.readFile(realPath); + const data = await handle.readFile(); + await handle.close().catch(() => {}); const mime = await detectMime({ buffer: data, filePath: realPath }); if (mime) res.type(mime); res.send(data); @@ -47,7 +59,17 @@ export function attachMediaRoutes( fs.rm(realPath).catch(() => {}); }, 50); }); - } catch { + } catch (err) { + if (err instanceof SafeOpenError) { + if (err.code === "invalid-path") { + res.status(400).send("invalid path"); + return; + } + if (err.code === "not-found") { + res.status(404).send("not found"); + return; + } + } res.status(404).send("not found"); } }); diff --git a/src/media/store.ts b/src/media/store.ts index c24614016..268937084 100644 --- a/src/media/store.ts +++ b/src/media/store.ts @@ -10,7 +10,8 @@ import { resolvePinnedHostname } from "../infra/net/ssrf.js"; import { detectMime, extensionForMime } from "./mime.js"; const resolveMediaDir = () => path.join(resolveConfigDir(), "media"); -const MAX_BYTES = 5 * 1024 * 1024; // 5MB default +export const MEDIA_MAX_BYTES = 5 * 1024 * 1024; // 5MB default +const MAX_BYTES = MEDIA_MAX_BYTES; const DEFAULT_TTL_MS = 2 * 60 * 1000; // 2 minutes /** @@ -19,10 +20,9 @@ const DEFAULT_TTL_MS = 2 * 60 * 1000; // 2 minutes * Keeps: alphanumeric, dots, hyphens, underscores, Unicode letters/numbers. */ function sanitizeFilename(name: string): string { - // Remove: < > : " / \ | ? * and control chars (U+0000-U+001F) - // oxlint-disable-next-line no-control-regex -- Intentionally matching control chars - const unsafe = /[<>:"/\\|?*\x00-\x1f]/g; - const sanitized = name.trim().replace(unsafe, "_").replace(/\s+/g, "_"); // Replace whitespace runs with underscore + const trimmed = name.trim(); + if (!trimmed) return ""; + const sanitized = trimmed.replace(/[^\p{L}\p{N}._-]+/gu, "_"); // Collapse multiple underscores, trim leading/trailing, limit length return sanitized.replace(/_+/g, "_").replace(/^_|_$/g, "").slice(0, 60); } @@ -56,7 +56,7 @@ export function getMediaDir() { export async function ensureMediaDir() { const mediaDir = resolveMediaDir(); - await fs.mkdir(mediaDir, { recursive: true }); + await fs.mkdir(mediaDir, { recursive: true, mode: 0o700 }); return mediaDir; } @@ -123,7 +123,7 @@ async function downloadToFile( let total = 0; const sniffChunks: Buffer[] = []; let sniffLen = 0; - const out = createWriteStream(dest); + const out = createWriteStream(dest, { mode: 0o600 }); res.on("data", (chunk) => { total += chunk.length; if (sniffLen < 16384) { @@ -168,7 +168,7 @@ export async function saveMediaSource( ): Promise { const baseDir = resolveMediaDir(); const dir = subdir ? path.join(baseDir, subdir) : baseDir; - await fs.mkdir(dir, { recursive: true }); + await fs.mkdir(dir, { recursive: true, mode: 0o700 }); await cleanOldMedia(); const baseId = crypto.randomUUID(); if (looksLikeUrl(source)) { @@ -198,7 +198,7 @@ export async function saveMediaSource( const ext = extensionForMime(mime) ?? path.extname(source); const id = ext ? `${baseId}${ext}` : baseId; const dest = path.join(dir, id); - await fs.writeFile(dest, buffer); + await fs.writeFile(dest, buffer, { mode: 0o600 }); return { id, path: dest, size: stat.size, contentType: mime }; } @@ -213,7 +213,7 @@ export async function saveMediaBuffer( throw new Error(`Media exceeds ${(maxBytes / (1024 * 1024)).toFixed(0)}MB limit`); } const dir = path.join(resolveMediaDir(), subdir); - await fs.mkdir(dir, { recursive: true }); + await fs.mkdir(dir, { recursive: true, mode: 0o700 }); const uuid = crypto.randomUUID(); const headerExt = extensionForMime(contentType?.split(";")[0]?.trim() ?? undefined); const mime = await detectMime({ buffer, headerMime: contentType }); @@ -231,6 +231,6 @@ export async function saveMediaBuffer( } const dest = path.join(dir, id); - await fs.writeFile(dest, buffer); + await fs.writeFile(dest, buffer, { mode: 0o600 }); return { id, path: dest, size: buffer.byteLength, contentType: mime }; } From 71196fb15080b7c8848e86d5658f06f322b34f79 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 26 Jan 2026 20:27:24 +0000 Subject: [PATCH 007/129] style: format fs-safe From 83de980d6c92a0cd12d92a5c563a91e0f65e1c4d Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 26 Jan 2026 20:28:46 +0000 Subject: [PATCH 008/129] style: wrap fs-safe From 771f23d36b95ec2204cc9a0054045f5d8439ea75 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Tue, 27 Jan 2026 03:33:09 +0000 Subject: [PATCH 009/129] fix(exec): prevent PATH injection in docker sandbox --- docs/tools/exec.md | 3 ++- src/agents/bash-tools.shared.ts | 9 ++++++++- src/agents/bash-tools.test.ts | 25 +++++++++++++++++++++++-- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/docs/tools/exec.md b/docs/tools/exec.md index 2524c3665..30771cf38 100644 --- a/docs/tools/exec.md +++ b/docs/tools/exec.md @@ -67,7 +67,8 @@ Example: - macOS: `/opt/homebrew/bin`, `/usr/local/bin`, `/usr/bin`, `/bin` - Linux: `/usr/local/bin`, `/usr/bin`, `/bin` - `host=sandbox`: runs `sh -lc` (login shell) inside the container, so `/etc/profile` may reset `PATH`. - Clawdbot prepends `env.PATH` after profile sourcing; `tools.exec.pathPrepend` applies here too. + Clawdbot prepends `env.PATH` after profile sourcing via an internal env var (no shell interpolation); + `tools.exec.pathPrepend` applies here too. - `host=node`: only env overrides you pass are sent to the node. `tools.exec.pathPrepend` only applies if the exec call already sets `env.PATH`. Headless node hosts accept `PATH` only when it prepends the node host PATH (no replacement). macOS nodes drop `PATH` overrides entirely. diff --git a/src/agents/bash-tools.shared.ts b/src/agents/bash-tools.shared.ts index bd09a18ff..aa4e5d000 100644 --- a/src/agents/bash-tools.shared.ts +++ b/src/agents/bash-tools.shared.ts @@ -60,11 +60,18 @@ export function buildDockerExecArgs(params: { for (const [key, value] of Object.entries(params.env)) { args.push("-e", `${key}=${value}`); } + const hasCustomPath = typeof params.env.PATH === "string" && params.env.PATH.length > 0; + if (hasCustomPath) { + // Avoid interpolating PATH into the shell command; pass it via env instead. + args.push("-e", `CLAWDBOT_PREPEND_PATH=${params.env.PATH}`); + } // Login shell (-l) sources /etc/profile which resets PATH to a minimal set, // overriding both Docker ENV and -e PATH=... environment variables. // Prepend custom PATH after profile sourcing to ensure custom tools are accessible // while preserving system paths that /etc/profile may have added. - const pathExport = params.env.PATH ? `export PATH="${params.env.PATH}:$PATH"; ` : ""; + const pathExport = hasCustomPath + ? 'export PATH="${CLAWDBOT_PREPEND_PATH}:$PATH"; unset CLAWDBOT_PREPEND_PATH; ' + : ""; args.push(params.containerName, "sh", "-lc", `${pathExport}${params.command}`); return args; } diff --git a/src/agents/bash-tools.test.ts b/src/agents/bash-tools.test.ts index 500b95f30..e5a008ca2 100644 --- a/src/agents/bash-tools.test.ts +++ b/src/agents/bash-tools.test.ts @@ -318,9 +318,30 @@ describe("buildDockerExecArgs", () => { }); const commandArg = args[args.length - 1]; - expect(commandArg).toContain('export PATH="/custom/bin:/usr/local/bin:/usr/bin:$PATH"'); + expect(args).toContain("CLAWDBOT_PREPEND_PATH=/custom/bin:/usr/local/bin:/usr/bin"); + expect(commandArg).toContain('export PATH="${CLAWDBOT_PREPEND_PATH}:$PATH"'); expect(commandArg).toContain("echo hello"); - expect(commandArg).toBe('export PATH="/custom/bin:/usr/local/bin:/usr/bin:$PATH"; echo hello'); + expect(commandArg).toBe( + 'export PATH="${CLAWDBOT_PREPEND_PATH}:$PATH"; unset CLAWDBOT_PREPEND_PATH; echo hello', + ); + }); + + it("does not interpolate PATH into the shell command", () => { + const injectedPath = "$(touch /tmp/clawdbot-path-injection)"; + const args = buildDockerExecArgs({ + containerName: "test-container", + command: "echo hello", + env: { + PATH: injectedPath, + HOME: "/home/user", + }, + tty: false, + }); + + const commandArg = args[args.length - 1]; + expect(args).toContain(`CLAWDBOT_PREPEND_PATH=${injectedPath}`); + expect(commandArg).not.toContain(injectedPath); + expect(commandArg).toContain("CLAWDBOT_PREPEND_PATH"); }); it("does not add PATH export when PATH is not in env", () => { From 407498172c8bd723c68909c17e101c4914732645 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Tue, 27 Jan 2026 03:33:54 +0000 Subject: [PATCH 010/129] test(exec): normalize PATH injection quoting From 912c869ed18f544e8d7ef51335dfff704c30be37 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Tue, 27 Jan 2026 03:34:30 +0000 Subject: [PATCH 011/129] test(exec): quote PATH injection string From 1cca0e50729f517791472dcae180e51821ae0279 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Tue, 27 Jan 2026 03:46:52 +0000 Subject: [PATCH 012/129] chore: warn on weak uuid fallback --- ui/src/ui/uuid.test.ts | 12 +++++++++--- ui/src/ui/uuid.ts | 9 +++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/ui/src/ui/uuid.test.ts b/ui/src/ui/uuid.test.ts index 9f7ccbf81..2d5421bdd 100644 --- a/ui/src/ui/uuid.test.ts +++ b/ui/src/ui/uuid.test.ts @@ -1,4 +1,4 @@ -import { describe, expect, it } from "vitest"; +import { describe, expect, it, vi } from "vitest"; import { generateUUID } from "./uuid"; @@ -26,7 +26,13 @@ describe("generateUUID", () => { }); it("still returns a v4 UUID when crypto is missing", () => { - const id = generateUUID(null); - expect(id).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/); + const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {}); + try { + const id = generateUUID(null); + expect(id).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/); + expect(warnSpy).toHaveBeenCalled(); + } finally { + warnSpy.mockRestore(); + } }); }); diff --git a/ui/src/ui/uuid.ts b/ui/src/ui/uuid.ts index f231d0f7f..7c927cda1 100644 --- a/ui/src/ui/uuid.ts +++ b/ui/src/ui/uuid.ts @@ -3,6 +3,8 @@ export type CryptoLike = { getRandomValues?: ((array: Uint8Array) => Uint8Array) | undefined; }; +let warnedWeakCrypto = false; + function uuidFromBytes(bytes: Uint8Array): string { bytes[6] = (bytes[6] & 0x0f) | 0x40; // version 4 bytes[8] = (bytes[8] & 0x3f) | 0x80; // variant 1 @@ -29,6 +31,12 @@ function weakRandomBytes(): Uint8Array { return bytes; } +function warnWeakCryptoOnce() { + if (warnedWeakCrypto) return; + warnedWeakCrypto = true; + console.warn("[uuid] crypto API missing; falling back to weak randomness"); +} + export function generateUUID(cryptoLike: CryptoLike | null = globalThis.crypto): string { if (cryptoLike && typeof cryptoLike.randomUUID === "function") return cryptoLike.randomUUID(); @@ -38,5 +46,6 @@ export function generateUUID(cryptoLike: CryptoLike | null = globalThis.crypto): return uuidFromBytes(bytes); } + warnWeakCryptoOnce(); return uuidFromBytes(weakRandomBytes()); } From 615ccf6411dcfaf25509df2da63f3428fd9165e8 Mon Sep 17 00:00:00 2001 From: 0oAstro <79555780+0oAstro@users.noreply.github.com> Date: Mon, 26 Jan 2026 09:27:20 +0530 Subject: [PATCH 013/129] git: stop tracking bundled build artifacts These files are generated at build time and shouldn't be committed: - dist/control-ui assets (JS/CSS bundles) - src/canvas-host/a2ui bundle files This removes ~100MB+ of bloat from git history by no longer tracking repeatedly regenerated bundle files. Add to .gitignore to prevent accidental re-addition. Co-Authored-By: Claude --- .gitignore | 3 + dist/control-ui/assets/index-08nzABV3.css | 1 - dist/control-ui/assets/index-DQcOTEYz.js | 3119 --- dist/control-ui/assets/index-DQcOTEYz.js.map | 1 - dist/control-ui/index.html | 15 - src/canvas-host/a2ui/a2ui.bundle.js | 17768 ----------------- src/canvas-host/a2ui/index.html | 307 - 7 files changed, 3 insertions(+), 21211 deletions(-) delete mode 100644 dist/control-ui/assets/index-08nzABV3.css delete mode 100644 dist/control-ui/assets/index-DQcOTEYz.js delete mode 100644 dist/control-ui/assets/index-DQcOTEYz.js.map delete mode 100644 dist/control-ui/index.html delete mode 100644 src/canvas-host/a2ui/a2ui.bundle.js delete mode 100644 src/canvas-host/a2ui/index.html diff --git a/.gitignore b/.gitignore index b2c1de9a2..e513b071b 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,9 @@ apps/ios/*.xcfilelist # Vendor build artifacts vendor/a2ui/renderers/lit/dist/ +src/canvas-host/a2ui/*.bundle.js +src/canvas-host/a2ui/*.map +src/canvas-host/a2ui/index.html .bundle.hash # fastlane (iOS) diff --git a/dist/control-ui/assets/index-08nzABV3.css b/dist/control-ui/assets/index-08nzABV3.css deleted file mode 100644 index 58e39560c..000000000 --- a/dist/control-ui/assets/index-08nzABV3.css +++ /dev/null @@ -1 +0,0 @@ -@import"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500&display=swap";:root{--bg: #0c0d12;--bg-accent: #0d0e14;--bg-elevated: #181a21;--bg-hover: #252830;--bg-muted: #252830;--card: #13151c;--card-foreground: #f8fafc;--card-highlight: rgba(255, 255, 255, .04);--popover: #13151c;--popover-foreground: #f8fafc;--panel: #0c0d12;--panel-strong: #181a21;--panel-hover: #252830;--chrome: rgba(12, 13, 18, .95);--chrome-strong: rgba(12, 13, 18, .98);--text: #f8fafc;--text-strong: #ffffff;--chat-text: #f8fafc;--muted: #94a3b8;--muted-strong: #64748b;--muted-foreground: #94a3b8;--border: #333842;--border-strong: #454d5c;--border-hover: #5a6373;--input: #333842;--ring: #ff4d4d;--accent: #ff4d4d;--accent-hover: #ff6666;--accent-muted: #ff4d4d;--accent-subtle: rgba(255, 77, 77, .12);--accent-foreground: #f8fafc;--primary: #ff4d4d;--primary-foreground: #ffffff;--secondary: #252830;--secondary-foreground: #f8fafc;--accent-2: #3b82f6;--accent-2-muted: rgba(59, 130, 246, .7);--ok: #22c55e;--ok-muted: rgba(34, 197, 94, .7);--ok-subtle: rgba(34, 197, 94, .1);--destructive: #ef4444;--destructive-foreground: #fafafa;--warn: #eab308;--warn-muted: rgba(234, 179, 8, .7);--warn-subtle: rgba(234, 179, 8, .1);--danger: #ef4444;--danger-muted: rgba(239, 68, 68, .7);--danger-subtle: rgba(239, 68, 68, .1);--info: #3b82f6;--focus: rgba(255, 77, 77, .2);--focus-ring: 0 0 0 2px var(--bg), 0 0 0 4px var(--ring);--grid-line: rgba(255, 255, 255, .03);--theme-switch-x: 50%;--theme-switch-y: 50%;--mono: "JetBrains Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas, monospace;--font-body: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;--font-display: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;--shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, .05);--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, .1), 0 2px 4px -2px rgba(0, 0, 0, .1);--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, .1), 0 4px 6px -4px rgba(0, 0, 0, .1);--shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, .1), 0 8px 10px -6px rgba(0, 0, 0, .1);--radius-sm: 4px;--radius-md: 6px;--radius-lg: 8px;--radius-xl: 12px;--radius-full: 9999px;--radius: 6px;--ease-out: cubic-bezier(.16, 1, .3, 1);--ease-in-out: cubic-bezier(.4, 0, .2, 1);--duration-fast: .15s;--duration-normal: .2s;--duration-slow: .3s;color-scheme:dark}:root[data-theme=light]{--bg: #f8f8f7;--bg-accent: #f3f2f0;--bg-elevated: #ffffff;--bg-hover: #eae8e6;--bg-muted: #eae8e6;--bg-content: #f0efed;--card: #ffffff;--card-foreground: #1c1917;--card-highlight: rgba(0, 0, 0, .04);--popover: #ffffff;--popover-foreground: #1c1917;--panel: #f8f8f7;--panel-strong: #f0efed;--panel-hover: #e5e3e1;--chrome: rgba(248, 248, 247, .95);--chrome-strong: rgba(248, 248, 247, .98);--text: #44403c;--text-strong: #292524;--chat-text: #44403c;--muted: #5c5856;--muted-strong: #44403c;--muted-foreground: #5c5856;--border: #e0dedc;--border-strong: #d6d3d1;--border-hover: #a8a5a0;--input: #e0dedc;--accent: #b91c1c;--accent-hover: #dc2626;--accent-muted: #b91c1c;--accent-subtle: rgba(185, 28, 28, .18);--accent-foreground: #ffffff;--primary: #b91c1c;--primary-foreground: #ffffff;--secondary: #eae8e6;--secondary-foreground: #44403c;--ok: #15803d;--ok-muted: rgba(21, 128, 61, .75);--ok-subtle: rgba(21, 128, 61, .12);--destructive: #b91c1c;--destructive-foreground: #fafafa;--warn: #a16207;--warn-muted: rgba(161, 98, 7, .75);--warn-subtle: rgba(161, 98, 7, .12);--danger: #b91c1c;--danger-muted: rgba(185, 28, 28, .75);--danger-subtle: rgba(185, 28, 28, .12);--info: #1d4ed8;--focus: rgba(185, 28, 28, .25);--grid-line: rgba(0, 0, 0, .06);color-scheme:light}*{box-sizing:border-box}html,body{height:100%}body{margin:0;font:400 14px/1.5 var(--font-body);letter-spacing:-.011em;background:var(--bg);color:var(--text);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@keyframes theme-circle-transition{0%{clip-path:circle(0% at var(--theme-switch-x, 50%) var(--theme-switch-y, 50%))}to{clip-path:circle(150% at var(--theme-switch-x, 50%) var(--theme-switch-y, 50%))}}html.theme-transition{view-transition-name:theme}html.theme-transition::view-transition-old(theme){mix-blend-mode:normal;animation:none;z-index:1}html.theme-transition::view-transition-new(theme){mix-blend-mode:normal;z-index:2;animation:theme-circle-transition .4s var(--ease-out) forwards}@media(prefers-reduced-motion:reduce){html.theme-transition::view-transition-old(theme),html.theme-transition::view-transition-new(theme){animation:none!important}}clawdbot-app{display:block;position:relative;z-index:1;min-height:100vh}a{color:var(--accent);text-decoration:none}a:hover{text-decoration:underline}button,input,textarea,select{font:inherit;color:inherit}::selection{background:var(--accent-subtle);color:var(--text-strong)}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--border);border-radius:var(--radius-full)}::-webkit-scrollbar-thumb:hover{background:var(--border-strong)}@keyframes rise{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}@keyframes scale-in{0%{opacity:0;transform:scale(.96)}to{opacity:1;transform:scale(1)}}@keyframes dashboard-enter{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}@keyframes shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}:focus-visible{outline:none;box-shadow:var(--focus-ring)}.shell{--shell-pad: 16px;--shell-gap: 16px;--shell-nav-width: 220px;--shell-topbar-height: 56px;--shell-focus-duration: .2s;--shell-focus-ease: var(--ease-out);height:100vh;display:grid;grid-template-columns:var(--shell-nav-width) minmax(0,1fr);grid-template-rows:var(--shell-topbar-height) 1fr;grid-template-areas:"topbar topbar" "nav content";gap:0;animation:dashboard-enter .4s var(--ease-out);transition:grid-template-columns var(--shell-focus-duration) var(--shell-focus-ease);overflow:hidden}@supports (height: 100dvh){.shell{height:100dvh}}.shell--chat{min-height:100vh;height:100vh;overflow:hidden}@supports (height: 100dvh){.shell--chat{height:100dvh}}.shell--nav-collapsed,.shell--chat-focus{grid-template-columns:0px minmax(0,1fr)}.shell--onboarding{grid-template-rows:0 1fr}.shell--onboarding .topbar{display:none}.shell--onboarding .content{padding-top:0}.shell--chat-focus .content{padding-top:0;gap:0}.topbar{grid-area:topbar;position:sticky;top:0;z-index:40;display:flex;justify-content:space-between;align-items:center;gap:16px;padding:0 20px;height:var(--shell-topbar-height);border-bottom:1px solid var(--border);background:var(--bg)}.topbar-left{display:flex;align-items:center;gap:12px}.topbar .nav-collapse-toggle{width:36px;height:36px;margin-bottom:0}.topbar .nav-collapse-toggle__icon{width:20px;height:20px}.topbar .nav-collapse-toggle__icon svg{width:20px;height:20px}.brand{display:flex;align-items:center;gap:10px}.brand-logo{width:28px;height:28px;flex-shrink:0}.brand-logo img{width:100%;height:100%;object-fit:contain}.brand-text{display:flex;flex-direction:column;gap:1px}.brand-title{font-size:15px;font-weight:600;letter-spacing:-.02em;line-height:1.1;color:var(--text-strong)}.brand-sub{font-size:11px;font-weight:500;color:var(--muted);letter-spacing:.02em;line-height:1}.topbar-status{display:flex;align-items:center;gap:8px}.topbar-status .pill{padding:6px 10px;gap:6px;font-size:12px;font-weight:500;height:32px;box-sizing:border-box}.topbar-status .pill .mono{display:flex;align-items:center;line-height:1;margin-top:0}.topbar-status .statusDot{width:6px;height:6px}.topbar-status .theme-toggle{--theme-item: 24px;--theme-gap: 2px;--theme-pad: 3px}.topbar-status .theme-icon{width:12px;height:12px}.nav{grid-area:nav;overflow-y:auto;overflow-x:hidden;padding:16px 12px;border-right:1px solid var(--border);background:var(--bg);transition:width var(--shell-focus-duration) var(--shell-focus-ease),padding var(--shell-focus-duration) var(--shell-focus-ease),opacity var(--shell-focus-duration) var(--shell-focus-ease);min-height:0}.shell--chat-focus .nav{width:0;padding:0;border-width:0;overflow:hidden;pointer-events:none;opacity:0}.nav--collapsed{width:0;min-width:0;padding:0;overflow:hidden;border:none;opacity:0;pointer-events:none}.nav-collapse-toggle{width:32px;height:32px;display:flex;align-items:center;justify-content:center;background:transparent;border:1px solid transparent;border-radius:var(--radius-md);cursor:pointer;transition:background var(--duration-fast) ease,border-color var(--duration-fast) ease;margin-bottom:16px}.nav-collapse-toggle:hover{background:var(--bg-hover);border-color:var(--border)}.nav-collapse-toggle__icon{display:flex;align-items:center;justify-content:center;width:18px;height:18px;color:var(--muted);transition:color var(--duration-fast) ease}.nav-collapse-toggle__icon svg{width:18px;height:18px;stroke:currentColor;fill:none;stroke-width:1.5px;stroke-linecap:round;stroke-linejoin:round}.nav-collapse-toggle:hover .nav-collapse-toggle__icon{color:var(--text)}.nav-group{margin-bottom:20px;display:grid;gap:2px}.nav-group:last-child{margin-bottom:0}.nav-group__items{display:grid;gap:1px}.nav-group--collapsed .nav-group__items{display:none}.nav-label{display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;padding:6px 10px;font-size:11px;font-weight:500;color:var(--muted);margin-bottom:4px;background:transparent;border:none;cursor:pointer;text-align:left;border-radius:var(--radius-sm);transition:color var(--duration-fast) ease,background var(--duration-fast) ease}.nav-label:hover{color:var(--text);background:var(--bg-hover)}.nav-label--static{cursor:default}.nav-label--static:hover{color:var(--muted);background:transparent}.nav-label__text{flex:1}.nav-label__chevron{font-size:10px;opacity:.5;transition:transform var(--duration-fast) ease}.nav-group--collapsed .nav-label__chevron{transform:rotate(-90deg)}.nav-item{position:relative;display:flex;align-items:center;justify-content:flex-start;gap:10px;padding:8px 10px;border-radius:var(--radius-md);border:1px solid transparent;background:transparent;color:var(--muted);cursor:pointer;text-decoration:none;transition:border-color var(--duration-fast) ease,background var(--duration-fast) ease,color var(--duration-fast) ease}.nav-item__icon{width:16px;height:16px;display:flex;align-items:center;justify-content:center;flex-shrink:0;opacity:.7;transition:opacity var(--duration-fast) ease}.nav-item__icon svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:1.5px;stroke-linecap:round;stroke-linejoin:round}.nav-item__text{font-size:13px;font-weight:500;white-space:nowrap}.nav-item:hover{color:var(--text);background:var(--bg-hover);text-decoration:none}.nav-item:hover .nav-item__icon{opacity:1}.nav-item.active{color:var(--text-strong);background:var(--accent-subtle)}.nav-item.active .nav-item__icon{opacity:1;color:var(--accent)}.content{grid-area:content;padding:8px 8px 24px;display:flex;flex-direction:column;gap:20px;min-height:0;overflow-y:auto;overflow-x:hidden}:root[data-theme=light] .content{background:var(--bg-content)}.content--chat{overflow:hidden;padding-bottom:0}.content-header{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;padding:4px 8px;overflow:hidden;transform-origin:top center;transition:opacity var(--shell-focus-duration) var(--shell-focus-ease),transform var(--shell-focus-duration) var(--shell-focus-ease),max-height var(--shell-focus-duration) var(--shell-focus-ease),padding var(--shell-focus-duration) var(--shell-focus-ease);max-height:80px}.shell--chat-focus .content-header{opacity:0;transform:translateY(-8px);max-height:0px;padding:0;pointer-events:none}.page-title{font-size:24px;font-weight:600;letter-spacing:-.02em;line-height:1.2;color:var(--text-strong)}.page-sub{color:var(--muted);font-size:13px;font-weight:400;margin-top:4px}.page-meta{display:flex;gap:8px}.content--chat .content-header{flex-direction:row;align-items:center;justify-content:space-between;gap:16px}.content--chat .content-header>div:first-child{text-align:left}.content--chat .page-meta{justify-content:flex-start}.content--chat .chat-controls{flex-shrink:0}.grid{display:grid;gap:16px}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.stat-grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(140px,1fr))}.note-grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(200px,1fr))}.row{display:flex;gap:10px;align-items:center}.stack{display:grid;gap:12px}.filters{display:flex;flex-wrap:wrap;gap:8px;align-items:center}@media(max-width:1100px){.shell{--shell-pad: 12px;--shell-gap: 12px;grid-template-columns:1fr;grid-template-rows:auto auto 1fr;grid-template-areas:"topbar" "nav" "content"}.nav{position:static;max-height:none;display:flex;gap:6px;overflow-x:auto;border-right:none;border-bottom:1px solid var(--border);padding:10px 14px;background:var(--bg)}.nav-group{grid-auto-flow:column;grid-template-columns:repeat(auto-fit,minmax(100px,1fr));margin-bottom:0}.grid-cols-2,.grid-cols-3{grid-template-columns:1fr}.topbar{position:static;padding:12px 14px;gap:10px}.topbar-status{flex-wrap:wrap}.table-head,.table-row,.list-item{grid-template-columns:1fr}}@media(max-width:1100px){.nav{display:flex;flex-direction:row;flex-wrap:nowrap;gap:4px;padding:10px 14px;overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none}.nav::-webkit-scrollbar{display:none}.nav-group,.nav-group__items{display:contents}.nav-label{display:none}.nav-group--collapsed .nav-group__items{display:contents}.nav-item{padding:8px 14px;font-size:13px;border-radius:var(--radius-md);white-space:nowrap;flex-shrink:0}}@media(max-width:600px){.shell{--shell-pad: 8px;--shell-gap: 8px}.topbar{padding:10px 12px;gap:8px;flex-direction:row;flex-wrap:wrap;justify-content:space-between;align-items:center}.brand{flex:1;min-width:0}.brand-title{font-size:14px}.brand-sub{display:none}.topbar-status{gap:6px;width:auto;flex-wrap:nowrap}.topbar-status .pill{padding:4px 8px;font-size:11px;gap:4px}.topbar-status .pill .mono{display:none}.topbar-status .pill span:nth-child(2){display:none}.nav{padding:8px 10px;gap:4px;-webkit-overflow-scrolling:touch;scrollbar-width:none}.nav::-webkit-scrollbar{display:none}.nav-group{display:contents}.nav-label{display:none}.nav-item{padding:6px 10px;font-size:12px;border-radius:var(--radius-md);white-space:nowrap;flex-shrink:0}.content-header{display:none}.content{padding:4px 4px 16px;gap:12px}.card{padding:12px;border-radius:var(--radius-md)}.card-title{font-size:13px}.stat-grid{gap:8px;grid-template-columns:repeat(2,1fr)}.stat{padding:10px;border-radius:var(--radius-md)}.stat-label{font-size:11px}.stat-value{font-size:18px}.note-grid{grid-template-columns:1fr;gap:8px}.form-grid{grid-template-columns:1fr;gap:10px}.field input,.field textarea,.field select{padding:8px 10px;border-radius:var(--radius-md);font-size:14px}.btn{padding:8px 12px;font-size:12px}.pill{padding:4px 10px;font-size:12px}.chat-header{flex-direction:column;align-items:stretch;gap:8px}.chat-header__left{flex-direction:column;align-items:stretch}.chat-header__right{justify-content:space-between}.chat-session{min-width:unset;width:100%}.chat-thread{margin-top:8px;padding:12px 8px}.chat-msg{max-width:90%}.chat-bubble{padding:8px 12px;border-radius:var(--radius-md)}.chat-compose{gap:8px}.chat-compose__field textarea{min-height:60px;padding:8px 10px;border-radius:var(--radius-md);font-size:14px}.log-stream{border-radius:var(--radius-md);max-height:380px}.log-row{grid-template-columns:1fr;gap:4px;padding:8px}.log-time{font-size:10px}.log-level{font-size:9px}.log-subsystem{font-size:11px}.log-message{font-size:12px}.list-item{padding:10px;border-radius:var(--radius-md)}.list-title{font-size:13px}.list-sub{font-size:11px}.code-block{padding:8px;border-radius:var(--radius-md);font-size:11px}.theme-toggle{--theme-item: 24px;--theme-gap: 2px;--theme-pad: 3px}.theme-icon{width:12px;height:12px}}@media(max-width:400px){.shell{--shell-pad: 4px}.topbar{padding:8px 10px}.brand-title{font-size:13px}.nav{padding:6px 8px}.nav-item{padding:6px 8px;font-size:11px}.content{padding:4px 4px 12px;gap:10px}.card{padding:10px}.stat{padding:8px}.stat-value{font-size:16px}.chat-bubble{padding:8px 10px}.chat-compose__field textarea{min-height:52px;padding:8px 10px;font-size:13px}.btn{padding:6px 10px;font-size:11px}.topbar-status .pill{padding:3px 6px;font-size:10px}.theme-toggle{--theme-item: 22px;--theme-gap: 2px;--theme-pad: 2px}.theme-icon{width:11px;height:11px}}.chat{position:relative;display:flex;flex-direction:column;flex:1 1 0;height:100%;min-height:0;overflow:hidden;background:transparent!important;border:none!important;box-shadow:none!important}.chat-header{display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:nowrap;flex-shrink:0;padding-bottom:12px;margin-bottom:12px;background:transparent}.chat-header__left{display:flex;align-items:center;gap:12px;flex-wrap:wrap;min-width:0}.chat-session{min-width:180px}.chat-thread{flex:1 1 0;overflow-y:auto;overflow-x:hidden;padding:12px 4px;margin:0 -4px;min-height:0;border-radius:12px;background:transparent}.chat-focus-exit{position:absolute;top:12px;right:12px;z-index:100;width:32px;height:32px;border-radius:50%;border:1px solid var(--border);background:var(--panel);color:var(--muted);font-size:20px;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:background .15s ease-out,color .15s ease-out,border-color .15s ease-out;box-shadow:0 4px 12px #0003}.chat-focus-exit:hover{background:var(--panel-strong);color:var(--text);border-color:var(--accent)}.chat-focus-exit svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:2px;stroke-linecap:round;stroke-linejoin:round}.chat-compose{position:sticky;bottom:0;flex-shrink:0;display:flex;align-items:stretch;gap:12px;margin-top:auto;padding:12px 4px 4px;background:linear-gradient(to bottom,transparent,var(--bg) 20%);z-index:10}:root[data-theme=light] .chat-compose{background:linear-gradient(to bottom,transparent,var(--bg-content) 20%)}.chat-compose__field{flex:1 1 auto;min-width:0;display:flex;align-items:stretch}.chat-compose__field>span{display:none}.chat-compose .chat-compose__field textarea{width:100%;height:40px;min-height:40px;max-height:150px;padding:9px 12px;border-radius:8px;resize:vertical;white-space:pre-wrap;font-family:var(--font-body);font-size:14px;line-height:1.45}.chat-compose__field textarea:disabled{opacity:.7;cursor:not-allowed}.chat-compose__actions{flex-shrink:0;display:flex;align-items:stretch;gap:8px}.chat-compose .chat-compose__actions .btn{padding:0 16px;font-size:13px;height:40px;min-height:40px;max-height:40px;line-height:1;white-space:nowrap;box-sizing:border-box}.chat-controls{display:flex;align-items:center;justify-content:flex-start;gap:12px;flex-wrap:wrap}.chat-controls__session{min-width:140px}.chat-controls__thinking{display:flex;align-items:center;gap:6px;font-size:13px}.btn--icon{padding:8px!important;min-width:36px;height:36px;display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--border);background:#ffffff0f}.chat-controls__separator{color:#fff6;font-size:18px;margin:0 8px;font-weight:300}:root[data-theme=light] .chat-controls__separator{color:#1018284d}.btn--icon:hover{background:#ffffff1f;border-color:#fff3}:root[data-theme=light] .btn--icon{background:#fff;border-color:var(--border);box-shadow:0 1px 2px #1018280d;color:var(--muted)}:root[data-theme=light] .btn--icon:hover{background:#fff;border-color:var(--border-strong);color:var(--text)}.btn--icon svg{display:block;width:18px;height:18px;stroke:currentColor;fill:none;stroke-width:1.5px;stroke-linecap:round;stroke-linejoin:round}.chat-controls__session select{padding:6px 10px;font-size:13px}.chat-controls__thinking{display:flex;align-items:center;gap:4px;font-size:12px;padding:4px 10px;background:#ffffff0a;border-radius:6px;border:1px solid var(--border)}:root[data-theme=light] .chat-controls__thinking{background:#ffffffe6;border-color:#10182826}@media(max-width:640px){.chat-session{min-width:140px}.chat-compose{grid-template-columns:1fr}.chat-controls{flex-wrap:wrap;gap:8px}.chat-controls__session{min-width:120px}}.chat-thinking{margin-bottom:10px;padding:10px 12px;border-radius:10px;border:1px dashed rgba(255,255,255,.18);background:#ffffff0a;color:var(--muted);font-size:12px;line-height:1.4}:root[data-theme=light] .chat-thinking{border-color:#10182840;background:#1018280a}.chat-text{font-size:14px;line-height:1.5;word-wrap:break-word;overflow-wrap:break-word}.chat-text :where(p+p,p+ul,p+ol,p+pre,p+blockquote){margin-top:.75em}.chat-text :where(ul,ol){padding-left:1.5em}.chat-text :where(a){color:var(--accent);text-decoration:underline;text-underline-offset:2px}.chat-text :where(a:hover){opacity:.8}.chat-text :where(:not(pre)>code){background:#00000026;padding:.15em .4em;border-radius:4px}.chat-text :where(pre){background:#00000026;border-radius:6px;padding:10px 12px;overflow-x:auto}.chat-text :where(pre code){background:none;padding:0}.chat-text :where(blockquote){border-left:3px solid var(--border-strong);margin-left:0;color:var(--muted);background:#ffffff05;padding:8px 12px;border-radius:0 var(--radius-sm) var(--radius-sm) 0}.chat-text :where(blockquote blockquote){margin-top:8px;border-left-color:var(--border-hover);background:#ffffff08}.chat-text :where(blockquote blockquote blockquote){border-left-color:var(--muted-strong);background:#ffffff0a}:root[data-theme=light] .chat-text :where(blockquote){background:#00000008}:root[data-theme=light] .chat-text :where(blockquote blockquote){background:#0000000d}:root[data-theme=light] .chat-text :where(blockquote blockquote blockquote){background:#0000000a}:root[data-theme=light] .chat-text :where(:not(pre)>code){background:#00000014;border:1px solid rgba(0,0,0,.1)}:root[data-theme=light] .chat-text :where(pre){background:#0000000d;border:1px solid rgba(0,0,0,.1)}.chat-text :where(hr){border:none;border-top:1px solid var(--border);margin:1em 0}.chat-group{display:flex;gap:12px;align-items:flex-start;margin-bottom:16px;margin-left:4px;margin-right:16px}.chat-group.user{flex-direction:row-reverse;justify-content:flex-start}.chat-group-messages{display:flex;flex-direction:column;gap:2px;max-width:min(900px,calc(100% - 60px))}.chat-group.user .chat-group-messages{align-items:flex-end}.chat-group.user .chat-group-footer{justify-content:flex-end}.chat-group-footer{display:flex;gap:8px;align-items:baseline;margin-top:6px}.chat-sender-name{font-weight:500;font-size:12px;color:var(--muted)}.chat-group-timestamp{font-size:11px;color:var(--muted);opacity:.7}.chat-avatar{width:40px;height:40px;border-radius:8px;background:var(--panel-strong);display:grid;place-items:center;font-weight:600;font-size:14px;flex-shrink:0;align-self:flex-end;margin-bottom:4px}.chat-avatar.user{background:var(--accent-subtle);color:var(--accent)}.chat-avatar.assistant,.chat-avatar.other,.chat-avatar.tool{background:var(--secondary);color:var(--muted)}img.chat-avatar{display:block;object-fit:cover;object-position:center}.chat-bubble{position:relative;display:inline-block;border:1px solid transparent;background:var(--card);border-radius:var(--radius-lg);padding:10px 14px;box-shadow:none;transition:background .15s ease-out,border-color .15s ease-out;max-width:100%;word-wrap:break-word}.chat-bubble.has-copy{padding-right:36px}.chat-copy-btn{position:absolute;top:6px;right:8px;border:1px solid var(--border);background:var(--bg);color:var(--muted);border-radius:var(--radius-md);padding:4px 6px;font-size:14px;line-height:1;cursor:pointer;opacity:0;pointer-events:none;transition:opacity .12s ease-out,background .12s ease-out}.chat-copy-btn__icon{display:inline-flex;width:14px;height:14px;position:relative}.chat-copy-btn__icon svg{width:14px;height:14px;stroke:currentColor;fill:none;stroke-width:1.5px;stroke-linecap:round;stroke-linejoin:round}.chat-copy-btn__icon-copy,.chat-copy-btn__icon-check{position:absolute;top:0;left:0;transition:opacity .15s ease}.chat-copy-btn__icon-check,.chat-copy-btn[data-copied="1"] .chat-copy-btn__icon-copy{opacity:0}.chat-copy-btn[data-copied="1"] .chat-copy-btn__icon-check{opacity:1}.chat-bubble:hover .chat-copy-btn{opacity:1;pointer-events:auto}.chat-copy-btn:hover{background:var(--bg-hover)}.chat-copy-btn[data-copying="1"]{opacity:0;pointer-events:none}.chat-copy-btn[data-error="1"]{opacity:1;pointer-events:auto;border-color:var(--danger-subtle);background:var(--danger-subtle);color:var(--danger)}.chat-copy-btn[data-copied="1"]{opacity:1;pointer-events:auto;border-color:var(--ok-subtle);background:var(--ok-subtle);color:var(--ok)}.chat-copy-btn:focus-visible{opacity:1;pointer-events:auto;outline:2px solid var(--accent);outline-offset:2px}@media(hover:none){.chat-copy-btn{opacity:1;pointer-events:auto}}:root[data-theme=light] .chat-bubble{border-color:var(--border);box-shadow:inset 0 1px 0 var(--card-highlight)}.chat-bubble:hover{background:var(--bg-hover)}.chat-group.user .chat-bubble{background:var(--accent-subtle);border-color:transparent}:root[data-theme=light] .chat-group.user .chat-bubble{border-color:#ea580c33;background:#fb923c1f}.chat-group.user .chat-bubble:hover{background:#ff4d4d26}.chat-bubble.streaming{animation:pulsing-border 1.5s ease-out infinite}@keyframes pulsing-border{0%,to{border-color:var(--border)}50%{border-color:var(--accent)}}.chat-bubble.fade-in{animation:fade-in .2s ease-out}@keyframes fade-in{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}.chat-tool-card{border:1px solid var(--border);border-radius:8px;padding:12px;margin-top:8px;background:var(--card);box-shadow:inset 0 1px 0 var(--card-highlight);transition:border-color .15s ease-out,background .15s ease-out;max-height:120px;overflow:hidden}.chat-tool-card:hover{border-color:var(--border-strong);background:var(--bg-hover)}.chat-tool-card:first-child{margin-top:0}.chat-tool-card--clickable{cursor:pointer}.chat-tool-card--clickable:focus{outline:2px solid var(--accent);outline-offset:2px}.chat-tool-card__header{display:flex;justify-content:space-between;align-items:center;gap:8px}.chat-tool-card__title{display:inline-flex;align-items:center;gap:6px;font-weight:600;font-size:13px;line-height:1.2}.chat-tool-card__icon{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;flex-shrink:0}.chat-tool-card__icon svg{width:14px;height:14px;stroke:currentColor;fill:none;stroke-width:1.5px;stroke-linecap:round;stroke-linejoin:round}.chat-tool-card__action{display:inline-flex;align-items:center;gap:4px;font-size:12px;color:var(--accent);opacity:.8;transition:opacity .15s ease-out}.chat-tool-card__action svg{width:12px;height:12px;stroke:currentColor;fill:none;stroke-width:1.5px;stroke-linecap:round;stroke-linejoin:round}.chat-tool-card--clickable:hover .chat-tool-card__action{opacity:1}.chat-tool-card__status{display:inline-flex;align-items:center;color:var(--ok)}.chat-tool-card__status svg{width:14px;height:14px;stroke:currentColor;fill:none;stroke-width:2px;stroke-linecap:round;stroke-linejoin:round}.chat-tool-card__status-text{font-size:11px;margin-top:4px}.chat-tool-card__detail{font-size:12px;color:var(--muted);margin-top:4px}.chat-tool-card__preview{font-size:11px;color:var(--muted);margin-top:8px;padding:8px 10px;background:var(--secondary);border-radius:var(--radius-md);white-space:pre-wrap;overflow:hidden;max-height:44px;line-height:1.4;border:1px solid var(--border)}.chat-tool-card--clickable:hover .chat-tool-card__preview{background:var(--bg-hover);border-color:var(--border-strong)}.chat-tool-card__inline{font-size:11px;color:var(--text);margin-top:6px;padding:6px 8px;background:var(--secondary);border-radius:var(--radius-sm);white-space:pre-wrap;word-break:break-word}.chat-reading-indicator{background:transparent;border:1px solid var(--border);padding:12px;display:inline-flex}.chat-reading-indicator__dots{display:flex;gap:6px;align-items:center}.chat-reading-indicator__dots span{width:6px;height:6px;border-radius:50%;background:var(--muted);animation:reading-pulse 1.4s ease-in-out infinite}.chat-reading-indicator__dots span:nth-child(1){animation-delay:0s}.chat-reading-indicator__dots span:nth-child(2){animation-delay:.2s}.chat-reading-indicator__dots span:nth-child(3){animation-delay:.4s}@keyframes reading-pulse{0%,60%,to{opacity:.3;transform:scale(.8)}30%{opacity:1;transform:scale(1)}}.chat-split-container{display:flex;gap:0;flex:1;min-height:0;height:100%}.chat-main{min-width:400px;display:flex;flex-direction:column;overflow:hidden;transition:flex .25s ease-out}.chat-sidebar{flex:1;min-width:300px;border-left:1px solid var(--border);display:flex;flex-direction:column;overflow:hidden;animation:slide-in .2s ease-out}@keyframes slide-in{0%{opacity:0;transform:translate(20px)}to{opacity:1;transform:translate(0)}}.sidebar-panel{display:flex;flex-direction:column;height:100%;background:var(--panel)}.sidebar-header{display:flex;justify-content:space-between;align-items:center;padding:12px 16px;border-bottom:1px solid var(--border);flex-shrink:0;position:sticky;top:0;z-index:10;background:var(--panel)}.sidebar-header .btn{padding:4px 8px;font-size:14px;min-width:auto;line-height:1}.sidebar-title{font-weight:600;font-size:14px}.sidebar-content{flex:1;overflow:auto;padding:16px}.sidebar-markdown{font-size:14px;line-height:1.5}.sidebar-markdown pre{background:#0000001f;border-radius:4px;padding:12px;overflow-x:auto}.sidebar-markdown code{font-family:var(--mono);font-size:13px}@media(max-width:768px){.chat-split-container--open{position:fixed;inset:0;z-index:1000}.chat-split-container--open .chat-main{display:none}.chat-split-container--open .chat-sidebar{width:100%;min-width:0;border-left:none}}.card{border:1px solid var(--border);background:var(--card);border-radius:var(--radius-lg);padding:16px;animation:rise .3s var(--ease-out);transition:border-color var(--duration-fast) ease;box-shadow:inset 0 1px 0 var(--card-highlight)}.card:hover{border-color:var(--border-strong)}.card-title{font-size:14px;font-weight:600;color:var(--text-strong)}.card-sub{color:var(--muted);font-size:13px;margin-top:4px}.stat{background:var(--card);border-radius:var(--radius-md);padding:12px 14px;border:1px solid var(--border);transition:border-color var(--duration-fast) ease;box-shadow:inset 0 1px 0 var(--card-highlight)}.stat:hover{border-color:var(--border-strong)}.stat-label{color:var(--muted);font-size:12px;font-weight:500}.stat-value{font-size:20px;font-weight:600;margin-top:4px;letter-spacing:-.02em}.stat-value.ok{color:var(--ok)}.stat-value.warn{color:var(--warn)}.stat-card{display:grid;gap:4px}.note-title{font-weight:600}.status-list{display:grid;gap:8px}.status-list div{display:flex;justify-content:space-between;gap:12px;padding:8px 0;border-bottom:1px solid var(--border)}.status-list div:last-child{border-bottom:none}.account-count{margin-top:10px;font-size:12px;font-weight:500;color:var(--muted)}.account-card-list{margin-top:16px;display:grid;gap:12px}.account-card{border:1px solid var(--border);border-radius:var(--radius-md);padding:12px;background:var(--bg-elevated);transition:border-color var(--duration-fast) ease}.account-card:hover{border-color:var(--border-strong)}.account-card-header{display:flex;justify-content:space-between;align-items:baseline;gap:12px}.account-card-title{font-weight:500}.account-card-id{font-family:var(--mono);font-size:12px;color:var(--muted)}.account-card-status{margin-top:10px;font-size:13px}.account-card-status div{padding:4px 0}.account-card-error{margin-top:8px;color:var(--danger);font-size:12px}.label{color:var(--muted);font-size:12px;font-weight:500}.pill{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--border);padding:6px 12px;border-radius:var(--radius-full);background:var(--secondary);font-size:13px;font-weight:500;transition:border-color var(--duration-fast) ease}.pill:hover{border-color:var(--border-strong)}.pill.danger{border-color:var(--danger-subtle);background:var(--danger-subtle);color:var(--danger)}.theme-toggle{--theme-item: 28px;--theme-gap: 2px;--theme-pad: 4px;position:relative}.theme-toggle__track{position:relative;display:grid;grid-template-columns:repeat(3,var(--theme-item));gap:var(--theme-gap);padding:var(--theme-pad);border-radius:var(--radius-full);border:1px solid var(--border);background:var(--secondary)}.theme-toggle__indicator{position:absolute;top:50%;left:var(--theme-pad);width:var(--theme-item);height:var(--theme-item);border-radius:var(--radius-full);transform:translateY(-50%) translate(calc(var(--theme-index, 0) * (var(--theme-item) + var(--theme-gap))));background:var(--accent);transition:transform var(--duration-normal) var(--ease-out);z-index:0}.theme-toggle__button{height:var(--theme-item);width:var(--theme-item);display:grid;place-items:center;border:0;border-radius:var(--radius-full);background:transparent;color:var(--muted);cursor:pointer;position:relative;z-index:1;transition:color var(--duration-fast) ease}.theme-toggle__button:hover{color:var(--text)}.theme-toggle__button.active{color:var(--accent-foreground)}.theme-toggle__button.active .theme-icon{stroke:var(--accent-foreground)}.theme-icon{width:14px;height:14px;stroke:currentColor;fill:none;stroke-width:1.5px;stroke-linecap:round;stroke-linejoin:round}.statusDot{width:8px;height:8px;border-radius:var(--radius-full);background:var(--danger)}.statusDot.ok{background:var(--ok)}.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;border:1px solid var(--border);background:var(--bg-elevated);padding:8px 14px;border-radius:var(--radius-md);font-size:13px;font-weight:500;cursor:pointer;transition:border-color var(--duration-fast) ease,background var(--duration-fast) ease}.btn:hover{background:var(--bg-hover);border-color:var(--border-strong)}.btn:active{background:var(--secondary)}.btn svg{width:16px;height:16px;stroke:currentColor;fill:none;stroke-width:1.5px;stroke-linecap:round;stroke-linejoin:round;flex-shrink:0}.btn.primary{border-color:var(--accent);background:var(--accent);color:var(--primary-foreground)}.btn.primary:hover{background:var(--accent-hover);border-color:var(--accent-hover)}.btn-kbd{display:inline-flex;align-items:center;justify-content:center;margin-left:6px;padding:2px 5px;font-family:var(--mono);font-size:11px;font-weight:500;line-height:1;border-radius:4px;background:#ffffff26;color:inherit;opacity:.8}.btn.primary .btn-kbd{background:#fff3}:root[data-theme=light] .btn-kbd{background:#00000014}:root[data-theme=light] .btn.primary .btn-kbd{background:#ffffff40}.btn.active{border-color:var(--accent);background:var(--accent-subtle);color:var(--accent)}.btn.danger{border-color:transparent;background:var(--danger-subtle);color:var(--danger)}.btn.danger:hover{background:#ef444426}.btn--sm{padding:6px 10px;font-size:12px}.btn:disabled{opacity:.5;cursor:not-allowed}.field{display:grid;gap:6px}.field.full{grid-column:1 / -1}.field span{color:var(--muted);font-size:13px;font-weight:500}.field input,.field textarea,.field select{border:1px solid var(--input);background:var(--card);border-radius:var(--radius-md);padding:8px 12px;outline:none;box-shadow:inset 0 1px 0 var(--card-highlight);transition:border-color var(--duration-fast) ease,box-shadow var(--duration-fast) ease}.field input:focus,.field textarea:focus,.field select:focus{border-color:var(--ring);box-shadow:var(--focus-ring)}.field select{appearance:none;padding-right:36px;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23a1a1aa' stroke-width='2'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 10px center;cursor:pointer}.field textarea{font-family:var(--mono);min-height:160px;resize:vertical;white-space:pre;line-height:1.5}.field.checkbox{grid-template-columns:auto 1fr;align-items:center}.config-form .field.checkbox{grid-template-columns:18px minmax(0,1fr);column-gap:10px}.config-form .field.checkbox input[type=checkbox]{margin:0;width:16px;height:16px;accent-color:var(--accent)}.form-grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(200px,1fr))}:root[data-theme=light] .field input,:root[data-theme=light] .field textarea,:root[data-theme=light] .field select{background:var(--card);border-color:var(--input)}:root[data-theme=light] .btn{background:var(--bg);border-color:var(--input)}:root[data-theme=light] .btn:hover{background:var(--bg-hover)}:root[data-theme=light] .btn.primary{background:var(--accent);border-color:var(--accent)}.muted{color:var(--muted)}.mono{font-family:var(--mono)}.callout{padding:12px 14px;border-radius:var(--radius-md);background:var(--secondary);border:1px solid var(--border);font-size:13px}.callout.danger{border-color:var(--danger-subtle);background:var(--danger-subtle);color:var(--danger)}.callout.info{border-color:#3b82f633;background:#3b82f61a;color:var(--info)}.callout.success{border-color:var(--ok-subtle);background:var(--ok-subtle);color:var(--ok)}.compaction-indicator{font-size:13px;padding:10px 12px;margin-bottom:8px;animation:fade-in .2s var(--ease-out)}.compaction-indicator--active{animation:compaction-pulse 1.5s ease-in-out infinite}.compaction-indicator--complete{animation:fade-in .2s var(--ease-out)}@keyframes compaction-pulse{0%,to{opacity:.7}50%{opacity:1}}.code-block{font-family:var(--mono);font-size:13px;line-height:1.5;background:var(--secondary);padding:12px;border-radius:var(--radius-md);border:1px solid var(--border);max-height:360px;overflow:auto}:root[data-theme=light] .code-block,:root[data-theme=light] .list-item,:root[data-theme=light] .table-row,:root[data-theme=light] .chip{background:var(--bg)}.list{display:grid;gap:8px;container-type:inline-size}.list-item{display:grid;grid-template-columns:minmax(0,1fr) minmax(200px,260px);gap:16px;align-items:start;border:1px solid var(--border);border-radius:var(--radius-md);padding:12px;background:var(--card);transition:border-color var(--duration-fast) ease}.list-item-clickable{cursor:pointer}.list-item-clickable:hover{border-color:var(--border-strong)}.list-item-selected{border-color:var(--accent);box-shadow:var(--focus-ring)}.list-main{display:grid;gap:4px;min-width:0}.list-title{font-weight:500}.list-sub{color:var(--muted);font-size:12px}.list-meta{text-align:right;color:var(--muted);font-size:12px;display:grid;gap:4px;min-width:200px}.list-meta .btn{padding:6px 10px}.list-meta .field input,.list-meta .field textarea,.list-meta .field select{width:100%}@container (max-width: 560px){.list-item{grid-template-columns:1fr}.list-meta{min-width:0;text-align:left}}.chip-row{display:flex;flex-wrap:wrap;gap:6px}.chip{font-size:12px;font-weight:500;border:1px solid var(--border);border-radius:var(--radius-full);padding:4px 10px;color:var(--muted);background:var(--secondary);transition:border-color var(--duration-fast) ease}.chip input{margin-right:6px}.chip-ok{color:var(--ok);border-color:var(--ok-subtle)}.chip-warn{color:var(--warn);border-color:var(--warn-subtle)}.table{display:grid;gap:6px}.table-head,.table-row{display:grid;grid-template-columns:1.4fr 1fr .8fr .7fr .8fr .8fr .8fr .8fr .6fr;gap:12px;align-items:center}.table-head{font-size:12px;font-weight:500;color:var(--muted);padding:0 12px}.table-row{border:1px solid var(--border);padding:10px 12px;border-radius:var(--radius-md);background:var(--card);transition:border-color var(--duration-fast) ease}.table-row:hover{border-color:var(--border-strong)}.session-link{text-decoration:none;color:var(--accent);font-weight:500}.session-link:hover{text-decoration:underline}.log-stream{border:1px solid var(--border);border-radius:var(--radius-md);background:var(--card);max-height:500px;overflow:auto;container-type:inline-size}.log-row{display:grid;grid-template-columns:90px 70px minmax(140px,200px) minmax(0,1fr);gap:12px;align-items:start;padding:8px 12px;border-bottom:1px solid var(--border);font-size:12px;transition:background var(--duration-fast) ease}.log-row:hover{background:var(--bg-hover)}.log-row:last-child{border-bottom:none}.log-time{color:var(--muted);font-family:var(--mono)}.log-level{font-size:11px;font-weight:500;border:1px solid var(--border);border-radius:var(--radius-sm);padding:2px 6px;width:fit-content}.log-level.trace,.log-level.debug{color:var(--muted)}.log-level.info{color:var(--info);border-color:#3b82f64d}.log-level.warn{color:var(--warn);border-color:var(--warn-subtle)}.log-level.error,.log-level.fatal{color:var(--danger);border-color:var(--danger-subtle)}.log-chip.trace,.log-chip.debug{color:var(--muted)}.log-chip.info{color:var(--info);border-color:#3b82f64d}.log-chip.warn{color:var(--warn);border-color:var(--warn-subtle)}.log-chip.error,.log-chip.fatal{color:var(--danger);border-color:var(--danger-subtle)}.log-subsystem{color:var(--muted);font-family:var(--mono)}.log-message{white-space:pre-wrap;word-break:break-word;font-family:var(--mono)}@container (max-width: 620px){.log-row{grid-template-columns:70px 60px minmax(0,1fr)}.log-subsystem{display:none}}.chat{display:flex;flex-direction:column;min-height:0}.shell--chat .chat{flex:1}.chat-header{display:flex;justify-content:space-between;align-items:flex-end;gap:16px;flex-wrap:wrap}.chat-header__left{display:flex;align-items:flex-end;gap:12px;flex-wrap:wrap;min-width:0}.chat-header__right{display:flex;align-items:center;gap:8px}.chat-session{min-width:240px}.chat-thread{margin-top:16px;display:flex;flex-direction:column;gap:12px;flex:1;min-height:0;overflow-y:auto;overflow-x:hidden;padding:16px 12px;min-width:0;border-radius:0;border:none;background:transparent}.chat-queue{margin-top:12px;padding:12px;border-radius:var(--radius-lg);border:1px solid var(--border);background:var(--card);display:grid;gap:8px}.chat-queue__title{font-family:var(--mono);font-size:12px;font-weight:500;color:var(--muted)}.chat-queue__list{display:grid;gap:8px}.chat-queue__item{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:start;gap:12px;padding:10px 12px;border-radius:var(--radius-md);border:1px dashed var(--border-strong);background:var(--secondary)}.chat-queue__text{color:var(--chat-text);font-size:13px;line-height:1.45;white-space:pre-wrap;overflow:hidden;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical}.chat-queue__remove{align-self:start;padding:4px 10px;font-size:12px;line-height:1}.chat-line{display:flex}.chat-line.user{justify-content:flex-end}.chat-line.assistant,.chat-line.other{justify-content:flex-start}.chat-msg{display:grid;gap:6px;max-width:min(700px,82%)}.chat-line.user .chat-msg{justify-items:end}.chat-bubble{border:1px solid transparent;background:var(--card);border-radius:var(--radius-lg);padding:10px 14px;min-width:0}:root[data-theme=light] .chat-bubble{border-color:var(--border);background:var(--bg)}.chat-line.user .chat-bubble{border-color:transparent;background:var(--accent-subtle)}:root[data-theme=light] .chat-line.user .chat-bubble{border-color:#ea580c33;background:#fb923c1f}.chat-line.assistant .chat-bubble{border-color:transparent;background:var(--secondary)}:root[data-theme=light] .chat-line.assistant .chat-bubble{border-color:var(--border);background:var(--bg-muted)}@keyframes chatStreamPulse{0%,to{border-color:var(--border)}50%{border-color:var(--accent)}}.chat-bubble.streaming{animation:chatStreamPulse 1.5s ease-in-out infinite}@media(prefers-reduced-motion:reduce){.chat-bubble.streaming{animation:none;border-color:var(--accent)}}.chat-bubble.chat-reading-indicator{width:fit-content;padding:10px 16px}.chat-reading-indicator__dots{display:inline-flex;align-items:center;gap:4px;height:12px}.chat-reading-indicator__dots>span{display:inline-block;width:6px;height:6px;border-radius:var(--radius-full);background:var(--muted);opacity:.6;transform:translateY(0);animation:chatReadingDot 1.2s ease-in-out infinite;will-change:transform,opacity}.chat-reading-indicator__dots>span:nth-child(2){animation-delay:.15s}.chat-reading-indicator__dots>span:nth-child(3){animation-delay:.3s}@keyframes chatReadingDot{0%,80%,to{opacity:.4;transform:translateY(0)}40%{opacity:1;transform:translateY(-3px)}}@media(prefers-reduced-motion:reduce){.chat-reading-indicator__dots>span{animation:none;opacity:.6}}.chat-text{overflow-wrap:anywhere;word-break:break-word;color:var(--chat-text);line-height:1.5}.chat-text :where(p,ul,ol,pre,blockquote,table){margin:0}.chat-text :where(p+p,p+ul,p+ol,p+pre,p+blockquote,p+table){margin-top:.75em}.chat-text :where(ul,ol){padding-left:1.2em}.chat-text :where(li+li){margin-top:.25em}.chat-text :where(a){color:var(--accent)}.chat-text :where(a:hover){text-decoration:underline}.chat-text :where(blockquote){border-left:2px solid var(--border-strong);padding-left:12px;color:var(--muted)}.chat-text :where(hr){border:0;border-top:1px solid var(--border);margin:1em 0}.chat-text :where(code){font-family:var(--mono);font-size:.9em}.chat-text :where(:not(pre)>code){padding:.15em .35em;border-radius:var(--radius-sm);border:1px solid var(--border);background:var(--secondary)}:root[data-theme=light] .chat-text :where(:not(pre)>code){background:var(--bg-muted)}.chat-text :where(pre){margin-top:.75em;padding:10px 12px;border-radius:var(--radius-md);border:1px solid var(--border);background:var(--secondary);overflow:auto}:root[data-theme=light] .chat-text :where(pre){background:var(--bg-muted)}.chat-text :where(pre code){font-size:12px;white-space:pre}.chat-text :where(table){margin-top:.75em;border-collapse:collapse;width:100%;font-size:13px}.chat-text :where(th,td){border:1px solid var(--border);padding:6px 10px;vertical-align:top}.chat-text :where(th){font-family:var(--mono);font-weight:500;color:var(--muted);background:var(--secondary)}.chat-tool-card{margin-top:8px;padding:10px 12px;border-radius:var(--radius-md);border:1px solid var(--border);background:var(--secondary);display:grid;gap:4px}:root[data-theme=light] .chat-tool-card{background:var(--bg-muted)}.chat-tool-card__title{font-family:var(--mono);font-size:12px;font-weight:500;color:var(--text)}.chat-tool-card__detail{font-family:var(--mono);font-size:11px;color:var(--muted)}.chat-tool-card__details{margin-top:6px}.chat-tool-card__summary{font-family:var(--mono);font-size:11px;color:var(--muted);cursor:pointer;list-style:none;display:inline-flex;align-items:center;gap:6px}.chat-tool-card__summary::-webkit-details-marker{display:none}.chat-tool-card__summary-meta{color:var(--muted);opacity:.7}.chat-tool-card__details[open] .chat-tool-card__summary{color:var(--text)}.chat-tool-card__output{margin-top:8px;font-family:var(--mono);font-size:11px;line-height:1.5;white-space:pre-wrap;color:var(--chat-text);padding:8px 10px;border-radius:var(--radius-md);border:1px solid var(--border);background:var(--card)}:root[data-theme=light] .chat-tool-card__output{background:var(--bg)}.chat-stamp{font-size:11px;color:var(--muted)}.chat-line.user .chat-stamp{text-align:right}.chat-compose{margin-top:12px;display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:end;gap:10px}.shell--chat .chat-compose{position:sticky;bottom:0;z-index:5;margin-top:0;padding-top:12px;background:linear-gradient(180deg,transparent 0%,var(--bg) 40%)}.shell--chat-focus .chat-compose{bottom:calc(var(--shell-pad) + 8px);padding-bottom:calc(12px + env(safe-area-inset-bottom,0px));border-bottom-left-radius:var(--radius-lg);border-bottom-right-radius:var(--radius-lg)}.chat-compose__field{gap:4px}.chat-compose__field textarea{min-height:72px;padding:10px 14px;border-radius:var(--radius-lg);resize:vertical;white-space:pre-wrap;font-family:var(--font-body);line-height:1.5;border:1px solid var(--input);background:var(--card);box-shadow:inset 0 1px 0 var(--card-highlight);transition:border-color var(--duration-fast) ease,box-shadow var(--duration-fast) ease}.chat-compose__field textarea:focus{border-color:var(--ring);box-shadow:var(--focus-ring)}.chat-compose__field textarea:disabled{opacity:.5;cursor:not-allowed}.chat-compose__actions{justify-content:flex-end;align-self:end}@media(max-width:900px){.chat-session{min-width:180px}.chat-compose{grid-template-columns:1fr}}.qr-wrap{margin-top:16px;border-radius:var(--radius-md);background:var(--card);border:1px dashed var(--border-strong);padding:16px;display:inline-flex}.qr-wrap img{width:160px;height:160px;border-radius:var(--radius-sm);image-rendering:pixelated}.exec-approval-overlay{position:fixed;inset:0;background:#000c;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;padding:24px;z-index:200}.exec-approval-card{width:min(540px,100%);background:var(--card);border:1px solid var(--border);border-radius:var(--radius-lg);padding:20px;animation:scale-in .2s var(--ease-out)}.exec-approval-header{display:flex;align-items:center;justify-content:space-between;gap:16px}.exec-approval-title{font-size:14px;font-weight:600}.exec-approval-sub{color:var(--muted);font-size:13px;margin-top:4px}.exec-approval-queue{font-size:11px;font-weight:500;color:var(--muted);border:1px solid var(--border);border-radius:var(--radius-full);padding:4px 10px}.exec-approval-command{margin-top:12px;padding:10px 12px;background:var(--secondary);border:1px solid var(--border);border-radius:var(--radius-md);word-break:break-word;white-space:pre-wrap;font-family:var(--mono);font-size:13px}.exec-approval-meta{margin-top:12px;display:grid;gap:6px;font-size:13px;color:var(--muted)}.exec-approval-meta-row{display:flex;justify-content:space-between;gap:12px}.exec-approval-meta-row span:last-child{color:var(--text);font-family:var(--mono)}.exec-approval-error{margin-top:10px;font-size:13px;color:var(--danger)}.exec-approval-actions{margin-top:16px;display:flex;flex-wrap:wrap;gap:8px}.config-layout{display:grid;grid-template-columns:260px minmax(0,1fr);gap:0;min-height:calc(100vh - 160px);margin:-16px;border-radius:var(--radius-xl);overflow:hidden;border:1px solid var(--border);background:var(--panel)}.config-sidebar{display:flex;flex-direction:column;background:var(--bg-accent);border-right:1px solid var(--border)}:root[data-theme=light] .config-sidebar{background:var(--bg-hover)}.config-sidebar__header{display:flex;align-items:center;justify-content:space-between;padding:18px;border-bottom:1px solid var(--border)}.config-sidebar__title{font-weight:600;font-size:14px;letter-spacing:-.01em}.config-sidebar__footer{margin-top:auto;padding:14px;border-top:1px solid var(--border)}.config-search{position:relative;padding:14px;border-bottom:1px solid var(--border)}.config-search__icon{position:absolute;left:28px;top:50%;transform:translateY(-50%);width:16px;height:16px;color:var(--muted);pointer-events:none}.config-search__input{width:100%;padding:11px 36px 11px 42px;border:1px solid var(--border);border-radius:var(--radius-md);background:var(--bg-elevated);font-size:13px;outline:none;transition:border-color var(--duration-fast) ease,box-shadow var(--duration-fast) ease,background var(--duration-fast) ease}.config-search__input::placeholder{color:var(--muted)}.config-search__input:focus{border-color:var(--accent);box-shadow:var(--focus-ring);background:var(--bg-hover)}:root[data-theme=light] .config-search__input{background:#fff}:root[data-theme=light] .config-search__input:focus{background:#fff}.config-search__clear{position:absolute;right:22px;top:50%;transform:translateY(-50%);width:22px;height:22px;border:none;border-radius:var(--radius-full);background:var(--bg-hover);color:var(--muted);font-size:14px;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:background var(--duration-fast) ease,color var(--duration-fast) ease}.config-search__clear:hover{background:var(--border-strong);color:var(--text)}.config-nav{flex:1;overflow-y:auto;padding:10px}.config-nav__item{display:flex;align-items:center;gap:12px;width:100%;padding:11px 14px;border:none;border-radius:var(--radius-md);background:transparent;color:var(--muted);font-size:13px;font-weight:500;text-align:left;cursor:pointer;transition:background var(--duration-fast) ease,color var(--duration-fast) ease}.config-nav__item:hover{background:var(--bg-hover);color:var(--text)}:root[data-theme=light] .config-nav__item:hover{background:#0000000a}.config-nav__item.active{background:var(--accent-subtle);color:var(--accent)}.config-nav__icon{width:20px;height:20px;display:flex;align-items:center;justify-content:center;font-size:15px;opacity:.7}.config-nav__item:hover .config-nav__icon,.config-nav__item.active .config-nav__icon{opacity:1}.config-nav__icon svg{width:18px;height:18px;stroke:currentColor;fill:none}.config-nav__label{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.config-mode-toggle{display:flex;padding:4px;background:var(--bg-elevated);border-radius:var(--radius-md);border:1px solid var(--border)}:root[data-theme=light] .config-mode-toggle{background:#fff}.config-mode-toggle__btn{flex:1;padding:9px 14px;border:none;border-radius:var(--radius-sm);background:transparent;color:var(--muted);font-size:12px;font-weight:600;cursor:pointer;transition:background var(--duration-fast) ease,color var(--duration-fast) ease,box-shadow var(--duration-fast) ease}.config-mode-toggle__btn:hover{color:var(--text)}.config-mode-toggle__btn.active{background:var(--accent);color:#fff;box-shadow:var(--shadow-sm)}.config-main{display:flex;flex-direction:column;min-width:0;background:var(--panel)}.config-actions{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:14px 22px;background:var(--bg-accent);border-bottom:1px solid var(--border)}:root[data-theme=light] .config-actions{background:var(--bg-hover)}.config-actions__left,.config-actions__right{display:flex;align-items:center;gap:10px}.config-changes-badge{padding:6px 14px;border-radius:var(--radius-full);background:var(--accent-subtle);border:1px solid rgba(255,77,77,.3);color:var(--accent);font-size:12px;font-weight:600}.config-status{font-size:13px;color:var(--muted)}.config-diff{margin:18px 22px 0;border:1px solid rgba(255,77,77,.25);border-radius:var(--radius-lg);background:var(--accent-subtle);overflow:hidden}.config-diff__summary{display:flex;align-items:center;justify-content:space-between;padding:14px 18px;cursor:pointer;font-size:13px;font-weight:600;color:var(--accent);list-style:none}.config-diff__summary::-webkit-details-marker{display:none}.config-diff__chevron{width:16px;height:16px;transition:transform var(--duration-normal) var(--ease-out)}.config-diff__chevron svg{width:100%;height:100%}.config-diff[open] .config-diff__chevron{transform:rotate(180deg)}.config-diff__content{padding:0 18px 18px;display:grid;gap:10px}.config-diff__item{display:flex;align-items:baseline;gap:14px;padding:10px 14px;border-radius:var(--radius-md);background:var(--bg-elevated);font-size:12px;font-family:var(--mono)}:root[data-theme=light] .config-diff__item{background:#fff}.config-diff__path{font-weight:600;color:var(--text);flex-shrink:0}.config-diff__values{display:flex;align-items:baseline;gap:10px;min-width:0;flex-wrap:wrap}.config-diff__from{color:var(--danger);opacity:.85}.config-diff__arrow{color:var(--muted)}.config-diff__to{color:var(--ok)}.config-section-hero{display:flex;align-items:center;gap:16px;padding:16px 22px;border-bottom:1px solid var(--border);background:var(--bg-accent)}:root[data-theme=light] .config-section-hero{background:var(--bg-hover)}.config-section-hero__icon{width:30px;height:30px;color:var(--accent);display:flex;align-items:center;justify-content:center}.config-section-hero__icon svg{width:100%;height:100%;stroke:currentColor;fill:none}.config-section-hero__text{display:grid;gap:3px;min-width:0}.config-section-hero__title{font-size:16px;font-weight:600;letter-spacing:-.01em}.config-section-hero__desc{font-size:13px;color:var(--muted)}.config-subnav{display:flex;gap:8px;padding:12px 22px 14px;border-bottom:1px solid var(--border);background:var(--bg-accent);overflow-x:auto}:root[data-theme=light] .config-subnav{background:var(--bg-hover)}.config-subnav__item{border:1px solid transparent;border-radius:var(--radius-full);padding:7px 14px;font-size:12px;font-weight:600;color:var(--muted);background:var(--bg-elevated);cursor:pointer;transition:background var(--duration-fast) ease,color var(--duration-fast) ease,border-color var(--duration-fast) ease;white-space:nowrap}:root[data-theme=light] .config-subnav__item{background:#fff}.config-subnav__item:hover{color:var(--text);border-color:var(--border)}.config-subnav__item.active{color:var(--accent);border-color:#ff4d4d66;background:var(--accent-subtle)}.config-content{flex:1;overflow-y:auto;padding:22px}.config-raw-field textarea{min-height:500px;font-family:var(--mono);font-size:13px;line-height:1.55}.config-loading{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:18px;padding:80px 24px;color:var(--muted)}.config-loading__spinner{width:40px;height:40px;border:3px solid var(--border);border-top-color:var(--accent);border-radius:var(--radius-full);animation:spin .75s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.config-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:18px;padding:80px 24px;text-align:center}.config-empty__icon{font-size:56px;opacity:.35}.config-empty__text{color:var(--muted);font-size:15px}.config-form--modern{display:grid;gap:26px}.config-section-card{border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--bg-elevated);overflow:hidden;transition:border-color var(--duration-fast) ease}.config-section-card:hover{border-color:var(--border-strong)}:root[data-theme=light] .config-section-card{background:#fff}.config-section-card__header{display:flex;align-items:flex-start;gap:16px;padding:20px 22px;background:var(--bg-accent);border-bottom:1px solid var(--border)}:root[data-theme=light] .config-section-card__header{background:var(--bg-hover)}.config-section-card__icon{width:34px;height:34px;color:var(--accent);flex-shrink:0}.config-section-card__icon svg{width:100%;height:100%}.config-section-card__titles{flex:1;min-width:0}.config-section-card__title{margin:0;font-size:17px;font-weight:600;letter-spacing:-.01em}.config-section-card__desc{margin:5px 0 0;font-size:13px;color:var(--muted);line-height:1.45}.config-section-card__content{padding:22px}.cfg-fields{display:grid;gap:22px}.cfg-field{display:grid;gap:8px}.cfg-field--error{padding:14px;border-radius:var(--radius-md);background:var(--danger-subtle);border:1px solid rgba(239,68,68,.3)}.cfg-field__label{font-size:13px;font-weight:600;color:var(--text)}.cfg-field__help{font-size:12px;color:var(--muted);line-height:1.45}.cfg-field__error{font-size:12px;color:var(--danger)}.cfg-input-wrap{display:flex;gap:10px}.cfg-input{flex:1;padding:11px 14px;border:1px solid var(--border-strong);border-radius:var(--radius-md);background:var(--bg-accent);font-size:14px;outline:none;transition:border-color var(--duration-fast) ease,box-shadow var(--duration-fast) ease,background var(--duration-fast) ease}.cfg-input::placeholder{color:var(--muted);opacity:.7}.cfg-input:focus{border-color:var(--accent);box-shadow:var(--focus-ring);background:var(--bg-hover)}:root[data-theme=light] .cfg-input{background:#fff}:root[data-theme=light] .cfg-input:focus{background:#fff}.cfg-input--sm{padding:9px 12px;font-size:13px}.cfg-input__reset{padding:10px 14px;border:1px solid var(--border);border-radius:var(--radius-md);background:var(--bg-elevated);color:var(--muted);font-size:14px;cursor:pointer;transition:background var(--duration-fast) ease,color var(--duration-fast) ease}.cfg-input__reset:hover:not(:disabled){background:var(--bg-hover);color:var(--text)}.cfg-input__reset:disabled{opacity:.5;cursor:not-allowed}.cfg-textarea{width:100%;padding:12px 14px;border:1px solid var(--border-strong);border-radius:var(--radius-md);background:var(--bg-accent);font-family:var(--mono);font-size:13px;line-height:1.55;resize:vertical;outline:none;transition:border-color var(--duration-fast) ease,box-shadow var(--duration-fast) ease}.cfg-textarea:focus{border-color:var(--accent);box-shadow:var(--focus-ring)}:root[data-theme=light] .cfg-textarea{background:#fff}.cfg-textarea--sm{padding:10px 12px;font-size:12px}.cfg-number{display:inline-flex;border:1px solid var(--border-strong);border-radius:var(--radius-md);overflow:hidden;background:var(--bg-accent)}:root[data-theme=light] .cfg-number{background:#fff}.cfg-number__btn{width:44px;border:none;background:var(--bg-elevated);color:var(--text);font-size:18px;font-weight:300;cursor:pointer;transition:background var(--duration-fast) ease}.cfg-number__btn:hover:not(:disabled){background:var(--bg-hover)}.cfg-number__btn:disabled{opacity:.4;cursor:not-allowed}:root[data-theme=light] .cfg-number__btn{background:var(--bg-hover)}:root[data-theme=light] .cfg-number__btn:hover:not(:disabled){background:var(--border)}.cfg-number__input{width:85px;padding:11px;border:none;border-left:1px solid var(--border);border-right:1px solid var(--border);background:transparent;font-size:14px;text-align:center;outline:none;-moz-appearance:textfield}.cfg-number__input::-webkit-outer-spin-button,.cfg-number__input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.cfg-select{padding:11px 40px 11px 14px;border:1px solid var(--border-strong);border-radius:var(--radius-md);background-color:var(--bg-accent);background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23888' stroke-width='2'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 12px center;font-size:14px;cursor:pointer;outline:none;appearance:none;transition:border-color var(--duration-fast) ease,box-shadow var(--duration-fast) ease}.cfg-select:focus{border-color:var(--accent);box-shadow:var(--focus-ring)}:root[data-theme=light] .cfg-select{background-color:#fff}.cfg-segmented{display:inline-flex;padding:4px;border:1px solid var(--border);border-radius:var(--radius-md);background:var(--bg-accent)}:root[data-theme=light] .cfg-segmented{background:var(--bg-hover)}.cfg-segmented__btn{padding:9px 18px;border:none;border-radius:var(--radius-sm);background:transparent;color:var(--muted);font-size:13px;font-weight:500;cursor:pointer;transition:background var(--duration-fast) ease,color var(--duration-fast) ease,box-shadow var(--duration-fast) ease}.cfg-segmented__btn:hover:not(:disabled):not(.active){color:var(--text)}.cfg-segmented__btn.active{background:var(--accent);color:#fff;box-shadow:var(--shadow-sm)}.cfg-segmented__btn:disabled{opacity:.5;cursor:not-allowed}.cfg-toggle-row{display:flex;align-items:center;justify-content:space-between;gap:18px;padding:16px 18px;border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--bg-accent);cursor:pointer;transition:background var(--duration-fast) ease,border-color var(--duration-fast) ease}.cfg-toggle-row:hover:not(.disabled){background:var(--bg-hover);border-color:var(--border-strong)}.cfg-toggle-row.disabled{opacity:.55;cursor:not-allowed}:root[data-theme=light] .cfg-toggle-row{background:#fff}:root[data-theme=light] .cfg-toggle-row:hover:not(.disabled){background:var(--bg-hover)}.cfg-toggle-row__content{flex:1;min-width:0}.cfg-toggle-row__label{display:block;font-size:14px;font-weight:500;color:var(--text)}.cfg-toggle-row__help{display:block;margin-top:3px;font-size:12px;color:var(--muted);line-height:1.45}.cfg-toggle{position:relative;flex-shrink:0}.cfg-toggle input{position:absolute;opacity:0;width:0;height:0}.cfg-toggle__track{display:block;width:50px;height:28px;background:var(--bg-elevated);border:1px solid var(--border-strong);border-radius:var(--radius-full);position:relative;transition:background var(--duration-normal) ease,border-color var(--duration-normal) ease}:root[data-theme=light] .cfg-toggle__track{background:var(--border)}.cfg-toggle__track:after{content:"";position:absolute;top:3px;left:3px;width:20px;height:20px;background:var(--text);border-radius:var(--radius-full);box-shadow:var(--shadow-sm);transition:transform var(--duration-normal) var(--ease-out),background var(--duration-normal) ease}.cfg-toggle input:checked+.cfg-toggle__track{background:var(--ok-subtle);border-color:#22c55e66}.cfg-toggle input:checked+.cfg-toggle__track:after{transform:translate(22px);background:var(--ok)}.cfg-toggle input:focus+.cfg-toggle__track{box-shadow:var(--focus-ring)}.cfg-object{border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--bg-accent);overflow:hidden}:root[data-theme=light] .cfg-object{background:#fff}.cfg-object__header{display:flex;align-items:center;justify-content:space-between;padding:14px 18px;cursor:pointer;list-style:none;transition:background var(--duration-fast) ease}.cfg-object__header:hover{background:var(--bg-hover)}.cfg-object__header::-webkit-details-marker{display:none}.cfg-object__title{font-size:14px;font-weight:600;color:var(--text)}.cfg-object__chevron{width:18px;height:18px;color:var(--muted);transition:transform var(--duration-normal) var(--ease-out)}.cfg-object__chevron svg{width:100%;height:100%}.cfg-object[open] .cfg-object__chevron{transform:rotate(180deg)}.cfg-object__help{padding:0 18px 14px;font-size:12px;color:var(--muted);border-bottom:1px solid var(--border)}.cfg-object__content{padding:18px;display:grid;gap:18px}.cfg-array{border:1px solid var(--border);border-radius:var(--radius-lg);overflow:hidden}.cfg-array__header{display:flex;align-items:center;gap:14px;padding:14px 18px;background:var(--bg-accent);border-bottom:1px solid var(--border)}:root[data-theme=light] .cfg-array__header{background:var(--bg-hover)}.cfg-array__label{flex:1;font-size:14px;font-weight:600;color:var(--text)}.cfg-array__count{font-size:12px;color:var(--muted);padding:4px 10px;background:var(--bg-elevated);border-radius:var(--radius-full)}:root[data-theme=light] .cfg-array__count{background:#fff}.cfg-array__add{display:inline-flex;align-items:center;gap:6px;padding:7px 14px;border:1px solid var(--border);border-radius:var(--radius-md);background:var(--bg-elevated);color:var(--text);font-size:12px;font-weight:500;cursor:pointer;transition:background var(--duration-fast) ease}.cfg-array__add:hover:not(:disabled){background:var(--bg-hover)}.cfg-array__add:disabled{opacity:.5;cursor:not-allowed}.cfg-array__add-icon{width:14px;height:14px}.cfg-array__add-icon svg{width:100%;height:100%}.cfg-array__help{padding:12px 18px;font-size:12px;color:var(--muted);border-bottom:1px solid var(--border)}.cfg-array__empty{padding:36px 18px;text-align:center;color:var(--muted);font-size:13px}.cfg-array__items{display:grid;gap:1px;background:var(--border)}.cfg-array__item{background:var(--panel)}.cfg-array__item-header{display:flex;align-items:center;justify-content:space-between;padding:12px 18px;background:var(--bg-accent);border-bottom:1px solid var(--border)}:root[data-theme=light] .cfg-array__item-header{background:var(--bg-hover)}.cfg-array__item-index{font-size:11px;font-weight:600;color:var(--muted);text-transform:uppercase;letter-spacing:.05em}.cfg-array__item-remove{width:30px;height:30px;display:flex;align-items:center;justify-content:center;border:none;border-radius:var(--radius-md);background:transparent;color:var(--muted);cursor:pointer;transition:background var(--duration-fast) ease,color var(--duration-fast) ease}.cfg-array__item-remove svg{width:16px;height:16px}.cfg-array__item-remove:hover:not(:disabled){background:var(--danger-subtle);color:var(--danger)}.cfg-array__item-remove:disabled{opacity:.4;cursor:not-allowed}.cfg-array__item-content{padding:18px}.cfg-map{border:1px solid var(--border);border-radius:var(--radius-lg);overflow:hidden}.cfg-map__header{display:flex;align-items:center;justify-content:space-between;gap:14px;padding:14px 18px;background:var(--bg-accent);border-bottom:1px solid var(--border)}:root[data-theme=light] .cfg-map__header{background:var(--bg-hover)}.cfg-map__label{font-size:13px;font-weight:600;color:var(--muted)}.cfg-map__add{display:inline-flex;align-items:center;gap:6px;padding:7px 14px;border:1px solid var(--border);border-radius:var(--radius-md);background:var(--bg-elevated);color:var(--text);font-size:12px;font-weight:500;cursor:pointer;transition:background var(--duration-fast) ease}.cfg-map__add:hover:not(:disabled){background:var(--bg-hover)}.cfg-map__add-icon{width:14px;height:14px}.cfg-map__add-icon svg{width:100%;height:100%}.cfg-map__empty{padding:28px 18px;text-align:center;color:var(--muted);font-size:13px}.cfg-map__items{display:grid;gap:10px;padding:14px}.cfg-map__item{display:grid;grid-template-columns:150px 1fr auto;gap:10px;align-items:start}.cfg-map__item-key,.cfg-map__item-value{min-width:0}.cfg-map__item-remove{width:34px;height:34px;display:flex;align-items:center;justify-content:center;border:none;border-radius:var(--radius-md);background:transparent;color:var(--muted);cursor:pointer;transition:background var(--duration-fast) ease,color var(--duration-fast) ease}.cfg-map__item-remove svg{width:16px;height:16px}.cfg-map__item-remove:hover:not(:disabled){background:var(--danger-subtle);color:var(--danger)}.pill--sm{padding:5px 12px;font-size:11px}.pill--ok{border-color:#22c55e59;color:var(--ok)}.pill--danger{border-color:#ef444459;color:var(--danger)}@media(max-width:768px){.config-layout{grid-template-columns:1fr}.config-sidebar{border-right:none;border-bottom:1px solid var(--border)}.config-sidebar__header{padding:14px 16px}.config-nav{display:flex;flex-wrap:nowrap;gap:6px;padding:10px 14px;overflow-x:auto;-webkit-overflow-scrolling:touch}.config-nav__item{flex:0 0 auto;padding:9px 14px;white-space:nowrap}.config-nav__label{display:inline}.config-sidebar__footer{display:none}.config-actions{flex-wrap:wrap;padding:14px 16px}.config-actions__left,.config-actions__right{width:100%;justify-content:center}.config-section-hero{padding:14px 16px}.config-subnav{padding:10px 16px 12px}.config-content{padding:18px}.config-section-card__header{padding:16px 18px}.config-section-card__content{padding:18px}.cfg-toggle-row{padding:14px 16px}.cfg-map__item{grid-template-columns:1fr;gap:10px}.cfg-map__item-remove{justify-self:end}}@media(max-width:480px){.config-nav__icon{width:26px;height:26px;font-size:17px}.config-nav__label{display:none}.config-section-card__icon{width:30px;height:30px}.config-section-card__title{font-size:16px}.cfg-segmented{flex-wrap:wrap}.cfg-segmented__btn{flex:1 0 auto;min-width:70px}} diff --git a/dist/control-ui/assets/index-DQcOTEYz.js b/dist/control-ui/assets/index-DQcOTEYz.js deleted file mode 100644 index e897319f1..000000000 --- a/dist/control-ui/assets/index-DQcOTEYz.js +++ /dev/null @@ -1,3119 +0,0 @@ -(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const i of document.querySelectorAll('link[rel="modulepreload"]'))s(i);new MutationObserver(i=>{for(const a of i)if(a.type==="childList")for(const o of a.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&s(o)}).observe(document,{childList:!0,subtree:!0});function n(i){const a={};return i.integrity&&(a.integrity=i.integrity),i.referrerPolicy&&(a.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?a.credentials="include":i.crossOrigin==="anonymous"?a.credentials="omit":a.credentials="same-origin",a}function s(i){if(i.ep)return;i.ep=!0;const a=n(i);fetch(i.href,a)}})();const qt=globalThis,Ts=qt.ShadowRoot&&(qt.ShadyCSS===void 0||qt.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,Cs=Symbol(),Pi=new WeakMap;let qa=class{constructor(t,n,s){if(this._$cssResult$=!0,s!==Cs)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=n}get styleSheet(){let t=this.o;const n=this.t;if(Ts&&t===void 0){const s=n!==void 0&&n.length===1;s&&(t=Pi.get(n)),t===void 0&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),s&&Pi.set(n,t))}return t}toString(){return this.cssText}};const Or=e=>new qa(typeof e=="string"?e:e+"",void 0,Cs),Dr=(e,...t)=>{const n=e.length===1?e[0]:t.reduce((s,i,a)=>s+(o=>{if(o._$cssResult$===!0)return o.cssText;if(typeof o=="number")return o;throw Error("Value passed to 'css' function must be a 'css' function result: "+o+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(i)+e[a+1],e[0]);return new qa(n,e,Cs)},Br=(e,t)=>{if(Ts)e.adoptedStyleSheets=t.map(n=>n instanceof CSSStyleSheet?n:n.styleSheet);else for(const n of t){const s=document.createElement("style"),i=qt.litNonce;i!==void 0&&s.setAttribute("nonce",i),s.textContent=n.cssText,e.appendChild(s)}},Ni=Ts?e=>e:e=>e instanceof CSSStyleSheet?(t=>{let n="";for(const s of t.cssRules)n+=s.cssText;return Or(n)})(e):e;const{is:Fr,defineProperty:Ur,getOwnPropertyDescriptor:Kr,getOwnPropertyNames:Hr,getOwnPropertySymbols:zr,getPrototypeOf:jr}=Object,nn=globalThis,Oi=nn.trustedTypes,qr=Oi?Oi.emptyScript:"",Vr=nn.reactiveElementPolyfillSupport,bt=(e,t)=>e,Gt={toAttribute(e,t){switch(t){case Boolean:e=e?qr:null;break;case Object:case Array:e=e==null?e:JSON.stringify(e)}return e},fromAttribute(e,t){let n=e;switch(t){case Boolean:n=e!==null;break;case Number:n=e===null?null:Number(e);break;case Object:case Array:try{n=JSON.parse(e)}catch{n=null}}return n}},Es=(e,t)=>!Fr(e,t),Di={attribute:!0,type:String,converter:Gt,reflect:!1,useDefault:!1,hasChanged:Es};Symbol.metadata??=Symbol("metadata"),nn.litPropertyMetadata??=new WeakMap;let Ye=class extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??=[]).push(t)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,n=Di){if(n.state&&(n.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(t)&&((n=Object.create(n)).wrapped=!0),this.elementProperties.set(t,n),!n.noAccessor){const s=Symbol(),i=this.getPropertyDescriptor(t,s,n);i!==void 0&&Ur(this.prototype,t,i)}}static getPropertyDescriptor(t,n,s){const{get:i,set:a}=Kr(this.prototype,t)??{get(){return this[n]},set(o){this[n]=o}};return{get:i,set(o){const c=i?.call(this);a?.call(this,o),this.requestUpdate(t,c,s)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??Di}static _$Ei(){if(this.hasOwnProperty(bt("elementProperties")))return;const t=jr(this);t.finalize(),t.l!==void 0&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(bt("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(bt("properties"))){const n=this.properties,s=[...Hr(n),...zr(n)];for(const i of s)this.createProperty(i,n[i])}const t=this[Symbol.metadata];if(t!==null){const n=litPropertyMetadata.get(t);if(n!==void 0)for(const[s,i]of n)this.elementProperties.set(s,i)}this._$Eh=new Map;for(const[n,s]of this.elementProperties){const i=this._$Eu(n,s);i!==void 0&&this._$Eh.set(i,n)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(t){const n=[];if(Array.isArray(t)){const s=new Set(t.flat(1/0).reverse());for(const i of s)n.unshift(Ni(i))}else t!==void 0&&n.push(Ni(t));return n}static _$Eu(t,n){const s=n.attribute;return s===!1?void 0:typeof s=="string"?s:typeof t=="string"?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(t=>t(this))}addController(t){(this._$EO??=new Set).add(t),this.renderRoot!==void 0&&this.isConnected&&t.hostConnected?.()}removeController(t){this._$EO?.delete(t)}_$E_(){const t=new Map,n=this.constructor.elementProperties;for(const s of n.keys())this.hasOwnProperty(s)&&(t.set(s,this[s]),delete this[s]);t.size>0&&(this._$Ep=t)}createRenderRoot(){const t=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return Br(t,this.constructor.elementStyles),t}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(t=>t.hostConnected?.())}enableUpdating(t){}disconnectedCallback(){this._$EO?.forEach(t=>t.hostDisconnected?.())}attributeChangedCallback(t,n,s){this._$AK(t,s)}_$ET(t,n){const s=this.constructor.elementProperties.get(t),i=this.constructor._$Eu(t,s);if(i!==void 0&&s.reflect===!0){const a=(s.converter?.toAttribute!==void 0?s.converter:Gt).toAttribute(n,s.type);this._$Em=t,a==null?this.removeAttribute(i):this.setAttribute(i,a),this._$Em=null}}_$AK(t,n){const s=this.constructor,i=s._$Eh.get(t);if(i!==void 0&&this._$Em!==i){const a=s.getPropertyOptions(i),o=typeof a.converter=="function"?{fromAttribute:a.converter}:a.converter?.fromAttribute!==void 0?a.converter:Gt;this._$Em=i;const c=o.fromAttribute(n,a.type);this[i]=c??this._$Ej?.get(i)??c,this._$Em=null}}requestUpdate(t,n,s,i=!1,a){if(t!==void 0){const o=this.constructor;if(i===!1&&(a=this[t]),s??=o.getPropertyOptions(t),!((s.hasChanged??Es)(a,n)||s.useDefault&&s.reflect&&a===this._$Ej?.get(t)&&!this.hasAttribute(o._$Eu(t,s))))return;this.C(t,n,s)}this.isUpdatePending===!1&&(this._$ES=this._$EP())}C(t,n,{useDefault:s,reflect:i,wrapped:a},o){s&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,o??n??this[t]),a!==!0||o!==void 0)||(this._$AL.has(t)||(this.hasUpdated||s||(n=void 0),this._$AL.set(t,n)),i===!0&&this._$Em!==t&&(this._$Eq??=new Set).add(t))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(n){Promise.reject(n)}const t=this.scheduleUpdate();return t!=null&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[i,a]of this._$Ep)this[i]=a;this._$Ep=void 0}const s=this.constructor.elementProperties;if(s.size>0)for(const[i,a]of s){const{wrapped:o}=a,c=this[i];o!==!0||this._$AL.has(i)||c===void 0||this.C(i,void 0,a,c)}}let t=!1;const n=this._$AL;try{t=this.shouldUpdate(n),t?(this.willUpdate(n),this._$EO?.forEach(s=>s.hostUpdate?.()),this.update(n)):this._$EM()}catch(s){throw t=!1,this._$EM(),s}t&&this._$AE(n)}willUpdate(t){}_$AE(t){this._$EO?.forEach(n=>n.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return!0}update(t){this._$Eq&&=this._$Eq.forEach(n=>this._$ET(n,this[n])),this._$EM()}updated(t){}firstUpdated(t){}};Ye.elementStyles=[],Ye.shadowRootOptions={mode:"open"},Ye[bt("elementProperties")]=new Map,Ye[bt("finalized")]=new Map,Vr?.({ReactiveElement:Ye}),(nn.reactiveElementVersions??=[]).push("2.1.2");const Ls=globalThis,Bi=e=>e,Yt=Ls.trustedTypes,Fi=Yt?Yt.createPolicy("lit-html",{createHTML:e=>e}):void 0,Va="$lit$",xe=`lit$${Math.random().toFixed(9).slice(2)}$`,Wa="?"+xe,Wr=`<${Wa}>`,Oe=document,$t=()=>Oe.createComment(""),xt=e=>e===null||typeof e!="object"&&typeof e!="function",Ms=Array.isArray,Gr=e=>Ms(e)||typeof e?.[Symbol.iterator]=="function",On=`[ -\f\r]`,rt=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,Ui=/-->/g,Ki=/>/g,Le=RegExp(`>|${On}(?:([^\\s"'>=/]+)(${On}*=${On}*(?:[^ -\f\r"'\`<>=]|("|')|))|$)`,"g"),Hi=/'/g,zi=/"/g,Ga=/^(?:script|style|textarea|title)$/i,Yr=e=>(t,...n)=>({_$litType$:e,strings:t,values:n}),r=Yr(1),Se=Symbol.for("lit-noChange"),g=Symbol.for("lit-nothing"),ji=new WeakMap,Pe=Oe.createTreeWalker(Oe,129);function Ya(e,t){if(!Ms(e)||!e.hasOwnProperty("raw"))throw Error("invalid template strings array");return Fi!==void 0?Fi.createHTML(t):t}const Qr=(e,t)=>{const n=e.length-1,s=[];let i,a=t===2?"":t===3?"":"",o=rt;for(let c=0;c"?(o=i??rt,u=-1):d[1]===void 0?u=-2:(u=o.lastIndex-d[2].length,p=d[1],o=d[3]===void 0?Le:d[3]==='"'?zi:Hi):o===zi||o===Hi?o=Le:o===Ui||o===Ki?o=rt:(o=Le,i=void 0);const v=o===Le&&e[c+1].startsWith("/>")?" ":"";a+=o===rt?l+Wr:u>=0?(s.push(p),l.slice(0,u)+Va+l.slice(u)+xe+v):l+xe+(u===-2?c:v)}return[Ya(e,a+(e[n]||"")+(t===2?"":t===3?"":"")),s]};let ts=class Qa{constructor({strings:t,_$litType$:n},s){let i;this.parts=[];let a=0,o=0;const c=t.length-1,l=this.parts,[p,d]=Qr(t,n);if(this.el=Qa.createElement(p,s),Pe.currentNode=this.el.content,n===2||n===3){const u=this.el.content.firstChild;u.replaceWith(...u.childNodes)}for(;(i=Pe.nextNode())!==null&&l.length0){i.textContent=Yt?Yt.emptyScript:"";for(let v=0;v2||s[0]!==""||s[1]!==""?(this._$AH=Array(s.length-1).fill(new String),this.strings=s):this._$AH=g}_$AI(t,n=this,s,i){const a=this.strings;let o=!1;if(a===void 0)t=Je(this,t,n,0),o=!xt(t)||t!==this._$AH&&t!==Se,o&&(this._$AH=t);else{const c=t;let l,p;for(t=a[0],l=0;l{const s=n?.renderBefore??t;let i=s._$litPart$;if(i===void 0){const a=n?.renderBefore??null;s._$litPart$=i=new sn(t.insertBefore($t(),a),a,void 0,n??{})}return i._$AI(e),i};const Is=globalThis;let Ze=class extends Ye{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){const t=super.createRenderRoot();return this.renderOptions.renderBefore??=t.firstChild,t}update(t){const n=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=il(n,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return Se}};Ze._$litElement$=!0,Ze.finalized=!0,Is.litElementHydrateSupport?.({LitElement:Ze});const al=Is.litElementPolyfillSupport;al?.({LitElement:Ze});(Is.litElementVersions??=[]).push("4.2.2");const Ja=e=>(t,n)=>{n!==void 0?n.addInitializer(()=>{customElements.define(e,t)}):customElements.define(e,t)};const ol={attribute:!0,type:String,converter:Gt,reflect:!1,hasChanged:Es},rl=(e=ol,t,n)=>{const{kind:s,metadata:i}=n;let a=globalThis.litPropertyMetadata.get(i);if(a===void 0&&globalThis.litPropertyMetadata.set(i,a=new Map),s==="setter"&&((e=Object.create(e)).wrapped=!0),a.set(n.name,e),s==="accessor"){const{name:o}=n;return{set(c){const l=t.get.call(this);t.set.call(this,c),this.requestUpdate(o,l,e,!0,c)},init(c){return c!==void 0&&this.C(o,void 0,e,c),c}}}if(s==="setter"){const{name:o}=n;return function(c){const l=this[o];t.call(this,c),this.requestUpdate(o,l,e,!0,c)}}throw Error("Unsupported decorator location: "+s)};function on(e){return(t,n)=>typeof n=="object"?rl(e,t,n):((s,i,a)=>{const o=i.hasOwnProperty(a);return i.constructor.createProperty(a,s),o?Object.getOwnPropertyDescriptor(i,a):void 0})(e,t,n)}function y(e){return on({...e,state:!0,attribute:!1})}const ll=50,cl=200,dl="Assistant";function qi(e,t){if(typeof e!="string")return;const n=e.trim();if(n)return n.length<=t?n:n.slice(0,t)}function ns(e){const t=qi(e?.name,ll)??dl,n=qi(e?.avatar??void 0,cl)??null;return{agentId:typeof e?.agentId=="string"&&e.agentId.trim()?e.agentId.trim():null,name:t,avatar:n}}function ul(){return ns(typeof window>"u"?{}:{name:window.__CLAWDBOT_ASSISTANT_NAME__,avatar:window.__CLAWDBOT_ASSISTANT_AVATAR__})}const Xa="clawdbot.control.settings.v1";function pl(){const t={gatewayUrl:`${location.protocol==="https:"?"wss":"ws"}://${location.host}`,token:"",sessionKey:"main",lastActiveSessionKey:"main",theme:"system",chatFocusMode:!1,chatShowThinking:!0,splitRatio:.6,navCollapsed:!1,navGroupsCollapsed:{}};try{const n=localStorage.getItem(Xa);if(!n)return t;const s=JSON.parse(n);return{gatewayUrl:typeof s.gatewayUrl=="string"&&s.gatewayUrl.trim()?s.gatewayUrl.trim():t.gatewayUrl,token:typeof s.token=="string"?s.token:t.token,sessionKey:typeof s.sessionKey=="string"&&s.sessionKey.trim()?s.sessionKey.trim():t.sessionKey,lastActiveSessionKey:typeof s.lastActiveSessionKey=="string"&&s.lastActiveSessionKey.trim()?s.lastActiveSessionKey.trim():typeof s.sessionKey=="string"&&s.sessionKey.trim()||t.lastActiveSessionKey,theme:s.theme==="light"||s.theme==="dark"||s.theme==="system"?s.theme:t.theme,chatFocusMode:typeof s.chatFocusMode=="boolean"?s.chatFocusMode:t.chatFocusMode,chatShowThinking:typeof s.chatShowThinking=="boolean"?s.chatShowThinking:t.chatShowThinking,splitRatio:typeof s.splitRatio=="number"&&s.splitRatio>=.4&&s.splitRatio<=.7?s.splitRatio:t.splitRatio,navCollapsed:typeof s.navCollapsed=="boolean"?s.navCollapsed:t.navCollapsed,navGroupsCollapsed:typeof s.navGroupsCollapsed=="object"&&s.navGroupsCollapsed!==null?s.navGroupsCollapsed:t.navGroupsCollapsed}}catch{return t}}function fl(e){localStorage.setItem(Xa,JSON.stringify(e))}function eo(e){const t=(e??"").trim();if(!t)return null;const n=t.split(":").filter(Boolean);if(n.length<3||n[0]!=="agent")return null;const s=n[1]?.trim(),i=n.slice(2).join(":");return!s||!i?null:{agentId:s,rest:i}}const hl=[{label:"Chat",tabs:["chat"]},{label:"Control",tabs:["overview","channels","instances","sessions","cron"]},{label:"Agent",tabs:["skills","nodes"]},{label:"Settings",tabs:["config","debug","logs"]}],to={overview:"/overview",channels:"/channels",instances:"/instances",sessions:"/sessions",cron:"/cron",skills:"/skills",nodes:"/nodes",chat:"/chat",config:"/config",debug:"/debug",logs:"/logs"},no=new Map(Object.entries(to).map(([e,t])=>[t,e]));function rn(e){if(!e)return"";let t=e.trim();return t.startsWith("/")||(t=`/${t}`),t==="/"?"":(t.endsWith("/")&&(t=t.slice(0,-1)),t)}function kt(e){if(!e)return"/";let t=e.trim();return t.startsWith("/")||(t=`/${t}`),t.length>1&&t.endsWith("/")&&(t=t.slice(0,-1)),t}function Rs(e,t=""){const n=rn(t),s=to[e];return n?`${n}${s}`:s}function so(e,t=""){const n=rn(t);let s=e||"/";n&&(s===n?s="/":s.startsWith(`${n}/`)&&(s=s.slice(n.length)));let i=kt(s).toLowerCase();return i.endsWith("/index.html")&&(i="/"),i==="/"?"chat":no.get(i)??null}function gl(e){let t=kt(e);if(t.endsWith("/index.html")&&(t=kt(t.slice(0,-11))),t==="/")return"";const n=t.split("/").filter(Boolean);if(n.length===0)return"";for(let s=0;s`,barChart:r``,link:r``,radio:r``,fileText:r``,zap:r``,monitor:r``,settings:r``,bug:r``,scrollText:r``,folder:r``,menu:r``,x:r``,check:r``,copy:r``,search:r``,brain:r``,book:r``,loader:r``,wrench:r``,fileCode:r``,edit:r``,penLine:r``,paperclip:r``,globe:r``,image:r``,smartphone:r``,plug:r``,circle:r``,puzzle:r``},bl=/<\s*\/?\s*(?:think(?:ing)?|thought|antthinking|final)\b/i,Dt=/<\s*\/?\s*final\b[^>]*>/gi,Vi=/<\s*(\/?)\s*(?:think(?:ing)?|thought|antthinking)\b[^>]*>/gi;function yl(e,t){return e.trimStart()}function wl(e,t){if(!e||!bl.test(e))return e;let n=e;Dt.test(n)?(Dt.lastIndex=0,n=n.replace(Dt,"")):Dt.lastIndex=0,Vi.lastIndex=0;let s="",i=0,a=!1;for(const o of n.matchAll(Vi)){const c=o.index??0,l=o[1]==="/";a?l&&(a=!1):(s+=n.slice(i,c),l||(a=!0)),i=c+o[0].length}return s+=n.slice(i),yl(s)}function At(e){return!e&&e!==0?"n/a":new Date(e).toLocaleString()}function O(e){if(!e&&e!==0)return"n/a";const t=Date.now()-e;if(t<0)return"just now";const n=Math.round(t/1e3);if(n<60)return`${n}s ago`;const s=Math.round(n/60);if(s<60)return`${s}m ago`;const i=Math.round(s/60);return i<48?`${i}h ago`:`${Math.round(i/24)}d ago`}function io(e){if(!e&&e!==0)return"n/a";if(e<1e3)return`${e}ms`;const t=Math.round(e/1e3);if(t<60)return`${t}s`;const n=Math.round(t/60);if(n<60)return`${n}m`;const s=Math.round(n/60);return s<48?`${s}h`:`${Math.round(s/24)}d`}function is(e){return!e||e.length===0?"none":e.filter(t=>!!(t&&t.trim())).join(", ")}function as(e,t=120){return e.length<=t?e:`${e.slice(0,Math.max(0,t-1))}…`}function ao(e,t){return e.length<=t?{text:e,truncated:!1,total:e.length}:{text:e.slice(0,Math.max(0,t)),truncated:!0,total:e.length}}function Qt(e,t){const n=Number(e);return Number.isFinite(n)?n:t}function Dn(e){return wl(e)}const $l=/^\[([^\]]+)\]\s*/,xl=["WebChat","WhatsApp","Telegram","Signal","Slack","Discord","iMessage","Teams","Matrix","Zalo","Zalo Personal","BlueBubbles"],Bn=new WeakMap,Fn=new WeakMap;function kl(e){return/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}Z\b/.test(e)||/\d{4}-\d{2}-\d{2} \d{2}:\d{2}\b/.test(e)?!0:xl.some(t=>e.startsWith(`${t} `))}function Un(e){const t=e.match($l);if(!t)return e;const n=t[1]??"";return kl(n)?e.slice(t[0].length):e}function os(e){const t=e,n=typeof t.role=="string"?t.role:"",s=t.content;if(typeof s=="string")return n==="assistant"?Dn(s):Un(s);if(Array.isArray(s)){const i=s.map(a=>{const o=a;return o.type==="text"&&typeof o.text=="string"?o.text:null}).filter(a=>typeof a=="string");if(i.length>0){const a=i.join(` -`);return n==="assistant"?Dn(a):Un(a)}}return typeof t.text=="string"?n==="assistant"?Dn(t.text):Un(t.text):null}function oo(e){if(!e||typeof e!="object")return os(e);const t=e;if(Bn.has(t))return Bn.get(t)??null;const n=os(e);return Bn.set(t,n),n}function Wi(e){const n=e.content,s=[];if(Array.isArray(n))for(const c of n){const l=c;if(l.type==="thinking"&&typeof l.thinking=="string"){const p=l.thinking.trim();p&&s.push(p)}}if(s.length>0)return s.join(` -`);const i=Sl(e);if(!i)return null;const o=[...i.matchAll(/<\s*think(?:ing)?\s*>([\s\S]*?)<\s*\/\s*think(?:ing)?\s*>/gi)].map(c=>(c[1]??"").trim()).filter(Boolean);return o.length>0?o.join(` -`):null}function Al(e){if(!e||typeof e!="object")return Wi(e);const t=e;if(Fn.has(t))return Fn.get(t)??null;const n=Wi(e);return Fn.set(t,n),n}function Sl(e){const t=e,n=t.content;if(typeof n=="string")return n;if(Array.isArray(n)){const s=n.map(i=>{const a=i;return a.type==="text"&&typeof a.text=="string"?a.text:null}).filter(i=>typeof i=="string");if(s.length>0)return s.join(` -`)}return typeof t.text=="string"?t.text:null}function _l(e){const t=e.trim();if(!t)return"";const n=t.split(/\r?\n/).map(s=>s.trim()).filter(Boolean).map(s=>`_${s}_`);return n.length?["_Reasoning:_",...n].join(` -`):""}function Gi(e){e[6]=e[6]&15|64,e[8]=e[8]&63|128;let t="";for(let n=0;n>>8&255,e[2]^=t>>>16&255,e[3]^=t>>>24&255,e}function Ps(e=globalThis.crypto){if(e&&typeof e.randomUUID=="function")return e.randomUUID();if(e&&typeof e.getRandomValues=="function"){const t=new Uint8Array(16);return e.getRandomValues(t),Gi(t)}return Gi(Tl())}async function Xe(e){if(!(!e.client||!e.connected)){e.chatLoading=!0,e.lastError=null;try{const t=await e.client.request("chat.history",{sessionKey:e.sessionKey,limit:200});e.chatMessages=Array.isArray(t.messages)?t.messages:[],e.chatThinkingLevel=t.thinkingLevel??null}catch(t){e.lastError=String(t)}finally{e.chatLoading=!1}}}async function Cl(e,t){if(!e.client||!e.connected)return!1;const n=t.trim();if(!n)return!1;const s=Date.now();e.chatMessages=[...e.chatMessages,{role:"user",content:[{type:"text",text:n}],timestamp:s}],e.chatSending=!0,e.lastError=null;const i=Ps();e.chatRunId=i,e.chatStream="",e.chatStreamStartedAt=s;try{return await e.client.request("chat.send",{sessionKey:e.sessionKey,message:n,deliver:!1,idempotencyKey:i}),!0}catch(a){const o=String(a);return e.chatRunId=null,e.chatStream=null,e.chatStreamStartedAt=null,e.lastError=o,e.chatMessages=[...e.chatMessages,{role:"assistant",content:[{type:"text",text:"Error: "+o}],timestamp:Date.now()}],!1}finally{e.chatSending=!1}}async function El(e){if(!e.client||!e.connected)return!1;const t=e.chatRunId;try{return await e.client.request("chat.abort",t?{sessionKey:e.sessionKey,runId:t}:{sessionKey:e.sessionKey}),!0}catch(n){return e.lastError=String(n),!1}}function Ll(e,t){if(!t||t.sessionKey!==e.sessionKey||t.runId&&e.chatRunId&&t.runId!==e.chatRunId)return null;if(t.state==="delta"){const n=os(t.message);if(typeof n=="string"){const s=e.chatStream??"";(!s||n.length>=s.length)&&(e.chatStream=n)}}else t.state==="final"||t.state==="aborted"?(e.chatStream=null,e.chatRunId=null,e.chatStreamStartedAt=null):t.state==="error"&&(e.chatStream=null,e.chatRunId=null,e.chatStreamStartedAt=null,e.lastError=t.errorMessage??"chat error");return t.state}async function st(e){if(!(!e.client||!e.connected)&&!e.sessionsLoading){e.sessionsLoading=!0,e.sessionsError=null;try{const t={includeGlobal:e.sessionsIncludeGlobal,includeUnknown:e.sessionsIncludeUnknown},n=Qt(e.sessionsFilterActive,0),s=Qt(e.sessionsFilterLimit,0);n>0&&(t.activeMinutes=n),s>0&&(t.limit=s);const i=await e.client.request("sessions.list",t);i&&(e.sessionsResult=i)}catch(t){e.sessionsError=String(t)}finally{e.sessionsLoading=!1}}}async function Ml(e,t,n){if(!e.client||!e.connected)return;const s={key:t};"label"in n&&(s.label=n.label),"thinkingLevel"in n&&(s.thinkingLevel=n.thinkingLevel),"verboseLevel"in n&&(s.verboseLevel=n.verboseLevel),"reasoningLevel"in n&&(s.reasoningLevel=n.reasoningLevel);try{await e.client.request("sessions.patch",s),await st(e)}catch(i){e.sessionsError=String(i)}}async function Il(e,t){if(!(!e.client||!e.connected||e.sessionsLoading||!window.confirm(`Delete session "${t}"? - -Deletes the session entry and archives its transcript.`))){e.sessionsLoading=!0,e.sessionsError=null;try{await e.client.request("sessions.delete",{key:t,deleteTranscript:!0}),await st(e)}catch(s){e.sessionsError=String(s)}finally{e.sessionsLoading=!1}}}const Yi=50,Rl=80,Pl=12e4;function Nl(e){if(!e||typeof e!="object")return null;const t=e;if(typeof t.text=="string")return t.text;const n=t.content;if(!Array.isArray(n))return null;const s=n.map(i=>{if(!i||typeof i!="object")return null;const a=i;return a.type==="text"&&typeof a.text=="string"?a.text:null}).filter(i=>!!i);return s.length===0?null:s.join(` -`)}function Qi(e){if(e==null)return null;if(typeof e=="number"||typeof e=="boolean")return String(e);const t=Nl(e);let n;if(typeof e=="string")n=e;else if(t)n=t;else try{n=JSON.stringify(e,null,2)}catch{n=String(e)}const s=ao(n,Pl);return s.truncated?`${s.text} - -… truncated (${s.total} chars, showing first ${s.text.length}).`:s.text}function Ol(e){const t=[];return t.push({type:"toolcall",name:e.name,arguments:e.args??{}}),e.output&&t.push({type:"toolresult",name:e.name,text:e.output}),{role:"assistant",toolCallId:e.toolCallId,runId:e.runId,content:t,timestamp:e.startedAt}}function Dl(e){if(e.toolStreamOrder.length<=Yi)return;const t=e.toolStreamOrder.length-Yi,n=e.toolStreamOrder.splice(0,t);for(const s of n)e.toolStreamById.delete(s)}function Bl(e){e.chatToolMessages=e.toolStreamOrder.map(t=>e.toolStreamById.get(t)?.message).filter(t=>!!t)}function rs(e){e.toolStreamSyncTimer!=null&&(clearTimeout(e.toolStreamSyncTimer),e.toolStreamSyncTimer=null),Bl(e)}function Fl(e,t=!1){if(t){rs(e);return}e.toolStreamSyncTimer==null&&(e.toolStreamSyncTimer=window.setTimeout(()=>rs(e),Rl))}function Ns(e){e.toolStreamById.clear(),e.toolStreamOrder=[],e.chatToolMessages=[],rs(e)}const Ul=5e3;function Kl(e,t){const n=t.data??{},s=typeof n.phase=="string"?n.phase:"";e.compactionClearTimer!=null&&(window.clearTimeout(e.compactionClearTimer),e.compactionClearTimer=null),s==="start"?e.compactionStatus={active:!0,startedAt:Date.now(),completedAt:null}:s==="end"&&(e.compactionStatus={active:!1,startedAt:e.compactionStatus?.startedAt??null,completedAt:Date.now()},e.compactionClearTimer=window.setTimeout(()=>{e.compactionStatus=null,e.compactionClearTimer=null},Ul))}function Hl(e,t){if(!t)return;if(t.stream==="compaction"){Kl(e,t);return}if(t.stream!=="tool")return;const n=typeof t.sessionKey=="string"?t.sessionKey:void 0;if(n&&n!==e.sessionKey||!n&&e.chatRunId&&t.runId!==e.chatRunId||e.chatRunId&&t.runId!==e.chatRunId||!e.chatRunId)return;const s=t.data??{},i=typeof s.toolCallId=="string"?s.toolCallId:"";if(!i)return;const a=typeof s.name=="string"?s.name:"tool",o=typeof s.phase=="string"?s.phase:"",c=o==="start"?s.args:void 0,l=o==="update"?Qi(s.partialResult):o==="result"?Qi(s.result):void 0,p=Date.now();let d=e.toolStreamById.get(i);d?(d.name=a,c!==void 0&&(d.args=c),l!==void 0&&(d.output=l),d.updatedAt=p):(d={toolCallId:i,runId:t.runId,sessionKey:n,name:a,args:c,output:l,startedAt:typeof t.ts=="number"?t.ts:p,updatedAt:p,message:{}},e.toolStreamById.set(i,d),e.toolStreamOrder.push(i)),d.message=Ol(d),Dl(e),Fl(e,o==="result")}function ln(e,t=!1){e.chatScrollFrame&&cancelAnimationFrame(e.chatScrollFrame),e.chatScrollTimeout!=null&&(clearTimeout(e.chatScrollTimeout),e.chatScrollTimeout=null);const n=()=>{const s=e.querySelector(".chat-thread");if(s){const i=getComputedStyle(s).overflowY;if(i==="auto"||i==="scroll"||s.scrollHeight-s.clientHeight>1)return s}return document.scrollingElement??document.documentElement};e.updateComplete.then(()=>{e.chatScrollFrame=requestAnimationFrame(()=>{e.chatScrollFrame=null;const s=n();if(!s)return;const i=s.scrollHeight-s.scrollTop-s.clientHeight;if(!(t||e.chatUserNearBottom||i<200))return;t&&(e.chatHasAutoScrolled=!0),s.scrollTop=s.scrollHeight,e.chatUserNearBottom=!0;const o=t?150:120;e.chatScrollTimeout=window.setTimeout(()=>{e.chatScrollTimeout=null;const c=n();if(!c)return;const l=c.scrollHeight-c.scrollTop-c.clientHeight;(t||e.chatUserNearBottom||l<200)&&(c.scrollTop=c.scrollHeight,e.chatUserNearBottom=!0)},o)})})}function ro(e,t=!1){e.logsScrollFrame&&cancelAnimationFrame(e.logsScrollFrame),e.updateComplete.then(()=>{e.logsScrollFrame=requestAnimationFrame(()=>{e.logsScrollFrame=null;const n=e.querySelector(".log-stream");if(!n)return;const s=n.scrollHeight-n.scrollTop-n.clientHeight;(t||s<80)&&(n.scrollTop=n.scrollHeight)})})}function zl(e,t){const n=t.currentTarget;if(!n)return;const s=n.scrollHeight-n.scrollTop-n.clientHeight;e.chatUserNearBottom=s<200}function jl(e,t){const n=t.currentTarget;if(!n)return;const s=n.scrollHeight-n.scrollTop-n.clientHeight;e.logsAtBottom=s<80}function ql(e){e.chatHasAutoScrolled=!1,e.chatUserNearBottom=!0}function Vl(e,t){if(e.length===0)return;const n=new Blob([`${e.join(` -`)} -`],{type:"text/plain"}),s=URL.createObjectURL(n),i=document.createElement("a"),a=new Date().toISOString().slice(0,19).replace(/[:T]/g,"-");i.href=s,i.download=`clawdbot-logs-${t}-${a}.log`,i.click(),URL.revokeObjectURL(s)}function Wl(e){if(typeof ResizeObserver>"u")return;const t=e.querySelector(".topbar");if(!t)return;const n=()=>{const{height:s}=t.getBoundingClientRect();e.style.setProperty("--topbar-height",`${s}px`)};n(),e.topbarObserver=new ResizeObserver(()=>n()),e.topbarObserver.observe(t)}function De(e){return typeof structuredClone=="function"?structuredClone(e):JSON.parse(JSON.stringify(e))}function et(e){return`${JSON.stringify(e,null,2).trimEnd()} -`}function lo(e,t,n){if(t.length===0)return;let s=e;for(let a=0;a0&&(n.timeoutSeconds=s),n}async function ec(e){if(!(!e.client||!e.connected||e.cronBusy)){e.cronBusy=!0,e.cronError=null;try{const t=Jl(e.cronForm),n=Xl(e.cronForm),s=e.cronForm.agentId.trim(),i={name:e.cronForm.name.trim(),description:e.cronForm.description.trim()||void 0,agentId:s||void 0,enabled:e.cronForm.enabled,schedule:t,sessionTarget:e.cronForm.sessionTarget,wakeMode:e.cronForm.wakeMode,payload:n,isolation:e.cronForm.postToMainPrefix.trim()&&e.cronForm.sessionTarget==="isolated"?{postToMainPrefix:e.cronForm.postToMainPrefix.trim()}:void 0};if(!i.name)throw new Error("Name required.");await e.client.request("cron.add",i),e.cronForm={...e.cronForm,name:"",description:"",payloadText:""},await cn(e),await Tt(e)}catch(t){e.cronError=String(t)}finally{e.cronBusy=!1}}}async function tc(e,t,n){if(!(!e.client||!e.connected||e.cronBusy)){e.cronBusy=!0,e.cronError=null;try{await e.client.request("cron.update",{id:t.id,patch:{enabled:n}}),await cn(e),await Tt(e)}catch(s){e.cronError=String(s)}finally{e.cronBusy=!1}}}async function nc(e,t){if(!(!e.client||!e.connected||e.cronBusy)){e.cronBusy=!0,e.cronError=null;try{await e.client.request("cron.run",{id:t.id,mode:"force"}),await po(e,t.id)}catch(n){e.cronError=String(n)}finally{e.cronBusy=!1}}}async function sc(e,t){if(!(!e.client||!e.connected||e.cronBusy)){e.cronBusy=!0,e.cronError=null;try{await e.client.request("cron.remove",{id:t.id}),e.cronRunsJobId===t.id&&(e.cronRunsJobId=null,e.cronRuns=[]),await cn(e),await Tt(e)}catch(n){e.cronError=String(n)}finally{e.cronBusy=!1}}}async function po(e,t){if(!(!e.client||!e.connected))try{const n=await e.client.request("cron.runs",{id:t,limit:50});e.cronRunsJobId=t,e.cronRuns=Array.isArray(n.entries)?n.entries:[]}catch(n){e.cronError=String(n)}}async function oe(e,t){if(!(!e.client||!e.connected)&&!e.channelsLoading){e.channelsLoading=!0,e.channelsError=null;try{const n=await e.client.request("channels.status",{probe:t,timeoutMs:8e3});e.channelsSnapshot=n,e.channelsLastSuccess=Date.now()}catch(n){e.channelsError=String(n)}finally{e.channelsLoading=!1}}}async function ic(e,t){if(!(!e.client||!e.connected||e.whatsappBusy)){e.whatsappBusy=!0;try{const n=await e.client.request("web.login.start",{force:t,timeoutMs:3e4});e.whatsappLoginMessage=n.message??null,e.whatsappLoginQrDataUrl=n.qrDataUrl??null,e.whatsappLoginConnected=null}catch(n){e.whatsappLoginMessage=String(n),e.whatsappLoginQrDataUrl=null,e.whatsappLoginConnected=null}finally{e.whatsappBusy=!1}}}async function ac(e){if(!(!e.client||!e.connected||e.whatsappBusy)){e.whatsappBusy=!0;try{const t=await e.client.request("web.login.wait",{timeoutMs:12e4});e.whatsappLoginMessage=t.message??null,e.whatsappLoginConnected=t.connected??null,t.connected&&(e.whatsappLoginQrDataUrl=null)}catch(t){e.whatsappLoginMessage=String(t),e.whatsappLoginConnected=null}finally{e.whatsappBusy=!1}}}async function oc(e){if(!(!e.client||!e.connected||e.whatsappBusy)){e.whatsappBusy=!0;try{await e.client.request("channels.logout",{channel:"whatsapp"}),e.whatsappLoginMessage="Logged out.",e.whatsappLoginQrDataUrl=null,e.whatsappLoginConnected=null}catch(t){e.whatsappLoginMessage=String(t)}finally{e.whatsappBusy=!1}}}async function dn(e){if(!(!e.client||!e.connected)&&!e.debugLoading){e.debugLoading=!0;try{const[t,n,s,i]=await Promise.all([e.client.request("status",{}),e.client.request("health",{}),e.client.request("models.list",{}),e.client.request("last-heartbeat",{})]);e.debugStatus=t,e.debugHealth=n;const a=s;e.debugModels=Array.isArray(a?.models)?a?.models:[],e.debugHeartbeat=i}catch(t){e.debugCallError=String(t)}finally{e.debugLoading=!1}}}async function rc(e){if(!(!e.client||!e.connected)){e.debugCallError=null,e.debugCallResult=null;try{const t=e.debugCallParams.trim()?JSON.parse(e.debugCallParams):{},n=await e.client.request(e.debugCallMethod.trim(),t);e.debugCallResult=JSON.stringify(n,null,2)}catch(t){e.debugCallError=String(t)}}}const lc=2e3,cc=new Set(["trace","debug","info","warn","error","fatal"]);function dc(e){if(typeof e!="string")return null;const t=e.trim();if(!t.startsWith("{")||!t.endsWith("}"))return null;try{const n=JSON.parse(t);return!n||typeof n!="object"?null:n}catch{return null}}function uc(e){if(typeof e!="string")return null;const t=e.toLowerCase();return cc.has(t)?t:null}function pc(e){if(!e.trim())return{raw:e,message:e};try{const t=JSON.parse(e),n=t&&typeof t._meta=="object"&&t._meta!==null?t._meta:null,s=typeof t.time=="string"?t.time:typeof n?.date=="string"?n?.date:null,i=uc(n?.logLevelName??n?.level),a=typeof t[0]=="string"?t[0]:typeof n?.name=="string"?n?.name:null,o=dc(a);let c=null;o&&(typeof o.subsystem=="string"?c=o.subsystem:typeof o.module=="string"&&(c=o.module)),!c&&a&&a.length<120&&(c=a);let l=null;return typeof t[1]=="string"?l=t[1]:!o&&typeof t[0]=="string"?l=t[0]:typeof t.message=="string"&&(l=t.message),{raw:e,time:s,level:i,subsystem:c,message:l??e,meta:n??void 0}}catch{return{raw:e,message:e}}}async function Os(e,t){if(!(!e.client||!e.connected)&&!(e.logsLoading&&!t?.quiet)){t?.quiet||(e.logsLoading=!0),e.logsError=null;try{const s=await e.client.request("logs.tail",{cursor:t?.reset?void 0:e.logsCursor??void 0,limit:e.logsLimit,maxBytes:e.logsMaxBytes}),a=(Array.isArray(s.lines)?s.lines.filter(c=>typeof c=="string"):[]).map(pc),o=!!(t?.reset||s.reset||e.logsCursor==null);e.logsEntries=o?a:[...e.logsEntries,...a].slice(-lc),typeof s.cursor=="number"&&(e.logsCursor=s.cursor),typeof s.file=="string"&&(e.logsFile=s.file),e.logsTruncated=!!s.truncated,e.logsLastFetchAt=Date.now()}catch(n){e.logsError=String(n)}finally{t?.quiet||(e.logsLoading=!1)}}}const fo={p:0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffedn,n:0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3edn,h:8n,a:0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffecn,d:0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3n,Gx:0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51an,Gy:0x6666666666666666666666666666666666666666666666666666666666666658n},{p:V,n:Vt,Gx:Ji,Gy:Xi,a:Kn,d:Hn,h:fc}=fo,Be=32,Ds=64,hc=(...e)=>{"captureStackTrace"in Error&&typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(...e)},H=(e="")=>{const t=new Error(e);throw hc(t,H),t},gc=e=>typeof e=="bigint",vc=e=>typeof e=="string",mc=e=>e instanceof Uint8Array||ArrayBuffer.isView(e)&&e.constructor.name==="Uint8Array",_e=(e,t,n="")=>{const s=mc(e),i=e?.length,a=t!==void 0;if(!s||a&&i!==t){const o=n&&`"${n}" `,c=a?` of length ${t}`:"",l=s?`length=${i}`:`type=${typeof e}`;H(o+"expected Uint8Array"+c+", got "+l)}return e},un=e=>new Uint8Array(e),ho=e=>Uint8Array.from(e),go=(e,t)=>e.toString(16).padStart(t,"0"),vo=e=>Array.from(_e(e)).map(t=>go(t,2)).join(""),ve={_0:48,_9:57,A:65,F:70,a:97,f:102},ea=e=>{if(e>=ve._0&&e<=ve._9)return e-ve._0;if(e>=ve.A&&e<=ve.F)return e-(ve.A-10);if(e>=ve.a&&e<=ve.f)return e-(ve.a-10)},mo=e=>{const t="hex invalid";if(!vc(e))return H(t);const n=e.length,s=n/2;if(n%2)return H(t);const i=un(s);for(let a=0,o=0;aglobalThis?.crypto,bc=()=>bo()?.subtle??H("crypto.subtle must be defined, consider polyfill"),St=(...e)=>{const t=un(e.reduce((s,i)=>s+_e(i).length,0));let n=0;return e.forEach(s=>{t.set(s,n),n+=s.length}),t},yc=(e=Be)=>bo().getRandomValues(un(e)),Zt=BigInt,Re=(e,t,n,s="bad number: out of range")=>gc(e)&&t<=e&&e{const n=e%t;return n>=0n?n:t+n},yo=e=>A(e,Vt),wc=(e,t)=>{(e===0n||t<=0n)&&H("no inverse n="+e+" mod="+t);let n=A(e,t),s=t,i=0n,a=1n;for(;n!==0n;){const o=s/n,c=s%n,l=i-a*o;s=n,n=c,i=a,a=l}return s===1n?A(i,t):H("no inverse")},$c=e=>{const t=ko[e];return typeof t!="function"&&H("hashes."+e+" not set"),t},zn=e=>e instanceof ee?e:H("Point expected"),cs=2n**256n;class ee{static BASE;static ZERO;X;Y;Z;T;constructor(t,n,s,i){const a=cs;this.X=Re(t,0n,a),this.Y=Re(n,0n,a),this.Z=Re(s,1n,a),this.T=Re(i,0n,a),Object.freeze(this)}static CURVE(){return fo}static fromAffine(t){return new ee(t.x,t.y,1n,A(t.x*t.y))}static fromBytes(t,n=!1){const s=Hn,i=ho(_e(t,Be)),a=t[31];i[31]=a&-129;const o=$o(i);Re(o,0n,n?cs:V);const l=A(o*o),p=A(l-1n),d=A(s*l+1n);let{isValid:u,value:h}=kc(p,d);u||H("bad point: y not sqrt");const v=(h&1n)===1n,w=(a&128)!==0;return!n&&h===0n&&w&&H("bad point: x==0, isLastByteOdd"),w!==v&&(h=A(-h)),new ee(h,o,1n,A(h*o))}static fromHex(t,n){return ee.fromBytes(mo(t),n)}get x(){return this.toAffine().x}get y(){return this.toAffine().y}assertValidity(){const t=Kn,n=Hn,s=this;if(s.is0())return H("bad point: ZERO");const{X:i,Y:a,Z:o,T:c}=s,l=A(i*i),p=A(a*a),d=A(o*o),u=A(d*d),h=A(l*t),v=A(d*A(h+p)),w=A(u+A(n*A(l*p)));if(v!==w)return H("bad point: equation left != right (1)");const $=A(i*a),k=A(o*c);return $!==k?H("bad point: equation left != right (2)"):this}equals(t){const{X:n,Y:s,Z:i}=this,{X:a,Y:o,Z:c}=zn(t),l=A(n*c),p=A(a*i),d=A(s*c),u=A(o*i);return l===p&&d===u}is0(){return this.equals(Qe)}negate(){return new ee(A(-this.X),this.Y,this.Z,A(-this.T))}double(){const{X:t,Y:n,Z:s}=this,i=Kn,a=A(t*t),o=A(n*n),c=A(2n*A(s*s)),l=A(i*a),p=t+n,d=A(A(p*p)-a-o),u=l+o,h=u-c,v=l-o,w=A(d*h),$=A(u*v),k=A(d*v),T=A(h*u);return new ee(w,$,T,k)}add(t){const{X:n,Y:s,Z:i,T:a}=this,{X:o,Y:c,Z:l,T:p}=zn(t),d=Kn,u=Hn,h=A(n*o),v=A(s*c),w=A(a*u*p),$=A(i*l),k=A((n+s)*(o+c)-h-v),T=A($-w),M=A($+w),P=A(v-d*h),L=A(k*T),C=A(M*P),E=A(k*P),pe=A(T*M);return new ee(L,C,pe,E)}subtract(t){return this.add(zn(t).negate())}multiply(t,n=!0){if(!n&&(t===0n||this.is0()))return Qe;if(Re(t,1n,Vt),t===1n)return this;if(this.equals(Fe))return Pc(t).p;let s=Qe,i=Fe;for(let a=this;t>0n;a=a.double(),t>>=1n)t&1n?s=s.add(a):n&&(i=i.add(a));return s}multiplyUnsafe(t){return this.multiply(t,!1)}toAffine(){const{X:t,Y:n,Z:s}=this;if(this.equals(Qe))return{x:0n,y:1n};const i=wc(s,V);A(s*i)!==1n&&H("invalid inverse");const a=A(t*i),o=A(n*i);return{x:a,y:o}}toBytes(){const{x:t,y:n}=this.assertValidity().toAffine(),s=wo(n);return s[31]|=t&1n?128:0,s}toHex(){return vo(this.toBytes())}clearCofactor(){return this.multiply(Zt(fc),!1)}isSmallOrder(){return this.clearCofactor().is0()}isTorsionFree(){let t=this.multiply(Vt/2n,!1).double();return Vt%2n&&(t=t.add(this)),t.is0()}}const Fe=new ee(Ji,Xi,1n,A(Ji*Xi)),Qe=new ee(0n,1n,1n,0n);ee.BASE=Fe;ee.ZERO=Qe;const wo=e=>mo(go(Re(e,0n,cs),Ds)).reverse(),$o=e=>Zt("0x"+vo(ho(_e(e)).reverse())),ce=(e,t)=>{let n=e;for(;t-- >0n;)n*=n,n%=V;return n},xc=e=>{const n=e*e%V*e%V,s=ce(n,2n)*n%V,i=ce(s,1n)*e%V,a=ce(i,5n)*i%V,o=ce(a,10n)*a%V,c=ce(o,20n)*o%V,l=ce(c,40n)*c%V,p=ce(l,80n)*l%V,d=ce(p,80n)*l%V,u=ce(d,10n)*a%V;return{pow_p_5_8:ce(u,2n)*e%V,b2:n}},ta=0x2b8324804fc1df0b2b4d00993dfbd7a72f431806ad2fe478c4ee1b274a0ea0b0n,kc=(e,t)=>{const n=A(t*t*t),s=A(n*n*t),i=xc(e*s).pow_p_5_8;let a=A(e*n*i);const o=A(t*a*a),c=a,l=A(a*ta),p=o===e,d=o===A(-e),u=o===A(-e*ta);return p&&(a=c),(d||u)&&(a=l),(A(a)&1n)===1n&&(a=A(-a)),{isValid:p||d,value:a}},ds=e=>yo($o(e)),Bs=(...e)=>ko.sha512Async(St(...e)),Ac=(...e)=>$c("sha512")(St(...e)),xo=e=>{const t=e.slice(0,Be);t[0]&=248,t[31]&=127,t[31]|=64;const n=e.slice(Be,Ds),s=ds(t),i=Fe.multiply(s),a=i.toBytes();return{head:t,prefix:n,scalar:s,point:i,pointBytes:a}},Fs=e=>Bs(_e(e,Be)).then(xo),Sc=e=>xo(Ac(_e(e,Be))),_c=e=>Fs(e).then(t=>t.pointBytes),Tc=e=>Bs(e.hashable).then(e.finish),Cc=(e,t,n)=>{const{pointBytes:s,scalar:i}=e,a=ds(t),o=Fe.multiply(a).toBytes();return{hashable:St(o,s,n),finish:p=>{const d=yo(a+ds(p)*i);return _e(St(o,wo(d)),Ds)}}},Ec=async(e,t)=>{const n=_e(e),s=await Fs(t),i=await Bs(s.prefix,n);return Tc(Cc(s,i,n))},ko={sha512Async:async e=>{const t=bc(),n=St(e);return un(await t.digest("SHA-512",n.buffer))},sha512:void 0},Lc=(e=yc(Be))=>e,Mc={getExtendedPublicKeyAsync:Fs,getExtendedPublicKey:Sc,randomSecretKey:Lc},Jt=8,Ic=256,Ao=Math.ceil(Ic/Jt)+1,us=2**(Jt-1),Rc=()=>{const e=[];let t=Fe,n=t;for(let s=0;s{const n=t.negate();return e?n:t},Pc=e=>{const t=na||(na=Rc());let n=Qe,s=Fe;const i=2**Jt,a=i,o=Zt(i-1),c=Zt(Jt);for(let l=0;l>=c,p>us&&(p-=a,e+=1n);const d=l*us,u=d,h=d+Math.abs(p)-1,v=l%2!==0,w=p<0;p===0?s=s.add(sa(v,t[u])):n=n.add(sa(w,t[h]))}return e!==0n&&H("invalid wnaf"),{p:n,f:s}},jn="clawdbot-device-identity-v1";function ps(e){let t="";for(const n of e)t+=String.fromCharCode(n);return btoa(t).replaceAll("+","-").replaceAll("/","_").replace(/=+$/g,"")}function So(e){const t=e.replaceAll("-","+").replaceAll("_","/"),n=t+"=".repeat((4-t.length%4)%4),s=atob(n),i=new Uint8Array(s.length);for(let a=0;at.toString(16).padStart(2,"0")).join("")}async function _o(e){const t=await crypto.subtle.digest("SHA-256",e);return Nc(new Uint8Array(t))}async function Oc(){const e=Mc.randomSecretKey(),t=await _c(e);return{deviceId:await _o(t),publicKey:ps(t),privateKey:ps(e)}}async function Us(){try{const n=localStorage.getItem(jn);if(n){const s=JSON.parse(n);if(s?.version===1&&typeof s.deviceId=="string"&&typeof s.publicKey=="string"&&typeof s.privateKey=="string"){const i=await _o(So(s.publicKey));if(i!==s.deviceId){const a={...s,deviceId:i};return localStorage.setItem(jn,JSON.stringify(a)),{deviceId:i,publicKey:s.publicKey,privateKey:s.privateKey}}return{deviceId:s.deviceId,publicKey:s.publicKey,privateKey:s.privateKey}}}}catch{}const e=await Oc(),t={version:1,deviceId:e.deviceId,publicKey:e.publicKey,privateKey:e.privateKey,createdAtMs:Date.now()};return localStorage.setItem(jn,JSON.stringify(t)),e}async function Dc(e,t){const n=So(e),s=new TextEncoder().encode(t),i=await Ec(s,n);return ps(i)}const To="clawdbot.device.auth.v1";function Ks(e){return e.trim()}function Bc(e){if(!Array.isArray(e))return[];const t=new Set;for(const n of e){const s=n.trim();s&&t.add(s)}return[...t].sort()}function Hs(){try{const e=window.localStorage.getItem(To);if(!e)return null;const t=JSON.parse(e);return!t||t.version!==1||!t.deviceId||typeof t.deviceId!="string"||!t.tokens||typeof t.tokens!="object"?null:t}catch{return null}}function Co(e){try{window.localStorage.setItem(To,JSON.stringify(e))}catch{}}function Fc(e){const t=Hs();if(!t||t.deviceId!==e.deviceId)return null;const n=Ks(e.role),s=t.tokens[n];return!s||typeof s.token!="string"?null:s}function Eo(e){const t=Ks(e.role),n={version:1,deviceId:e.deviceId,tokens:{}},s=Hs();s&&s.deviceId===e.deviceId&&(n.tokens={...s.tokens});const i={token:e.token,role:t,scopes:Bc(e.scopes),updatedAtMs:Date.now()};return n.tokens[t]=i,Co(n),i}function Lo(e){const t=Hs();if(!t||t.deviceId!==e.deviceId)return;const n=Ks(e.role);if(!t.tokens[n])return;const s={...t,tokens:{...t.tokens}};delete s.tokens[n],Co(s)}async function Te(e,t){if(!(!e.client||!e.connected)&&!e.devicesLoading){e.devicesLoading=!0,t?.quiet||(e.devicesError=null);try{const n=await e.client.request("device.pair.list",{});e.devicesList={pending:Array.isArray(n?.pending)?n.pending:[],paired:Array.isArray(n?.paired)?n.paired:[]}}catch(n){t?.quiet||(e.devicesError=String(n))}finally{e.devicesLoading=!1}}}async function Uc(e,t){if(!(!e.client||!e.connected))try{await e.client.request("device.pair.approve",{requestId:t}),await Te(e)}catch(n){e.devicesError=String(n)}}async function Kc(e,t){if(!(!e.client||!e.connected||!window.confirm("Reject this device pairing request?")))try{await e.client.request("device.pair.reject",{requestId:t}),await Te(e)}catch(s){e.devicesError=String(s)}}async function Hc(e,t){if(!(!e.client||!e.connected))try{const n=await e.client.request("device.token.rotate",t);if(n?.token){const s=await Us(),i=n.role??t.role;(n.deviceId===s.deviceId||t.deviceId===s.deviceId)&&Eo({deviceId:s.deviceId,role:i,token:n.token,scopes:n.scopes??t.scopes??[]}),window.prompt("New device token (copy and store securely):",n.token)}await Te(e)}catch(n){e.devicesError=String(n)}}async function zc(e,t){if(!(!e.client||!e.connected||!window.confirm(`Revoke token for ${t.deviceId} (${t.role})?`)))try{await e.client.request("device.token.revoke",t);const s=await Us();t.deviceId===s.deviceId&&Lo({deviceId:s.deviceId,role:t.role}),await Te(e)}catch(s){e.devicesError=String(s)}}async function pn(e,t){if(!(!e.client||!e.connected)&&!e.nodesLoading){e.nodesLoading=!0,t?.quiet||(e.lastError=null);try{const n=await e.client.request("node.list",{});e.nodes=Array.isArray(n.nodes)?n.nodes:[]}catch(n){t?.quiet||(e.lastError=String(n))}finally{e.nodesLoading=!1}}}function jc(e){if(!e||e.kind==="gateway")return{method:"exec.approvals.get",params:{}};const t=e.nodeId.trim();return t?{method:"exec.approvals.node.get",params:{nodeId:t}}:null}function qc(e,t){if(!e||e.kind==="gateway")return{method:"exec.approvals.set",params:t};const n=e.nodeId.trim();return n?{method:"exec.approvals.node.set",params:{...t,nodeId:n}}:null}async function zs(e,t){if(!(!e.client||!e.connected)&&!e.execApprovalsLoading){e.execApprovalsLoading=!0,e.lastError=null;try{const n=jc(t);if(!n){e.lastError="Select a node before loading exec approvals.";return}const s=await e.client.request(n.method,n.params);Vc(e,s)}catch(n){e.lastError=String(n)}finally{e.execApprovalsLoading=!1}}}function Vc(e,t){e.execApprovalsSnapshot=t,e.execApprovalsDirty||(e.execApprovalsForm=De(t.file??{}))}async function Wc(e,t){if(!(!e.client||!e.connected)){e.execApprovalsSaving=!0,e.lastError=null;try{const n=e.execApprovalsSnapshot?.hash;if(!n){e.lastError="Exec approvals hash missing; reload and retry.";return}const s=e.execApprovalsForm??e.execApprovalsSnapshot?.file??{},i=qc(t,{file:s,baseHash:n});if(!i){e.lastError="Select a node before saving exec approvals.";return}await e.client.request(i.method,i.params),e.execApprovalsDirty=!1,await zs(e,t)}catch(n){e.lastError=String(n)}finally{e.execApprovalsSaving=!1}}}function Gc(e,t,n){const s=De(e.execApprovalsForm??e.execApprovalsSnapshot?.file??{});lo(s,t,n),e.execApprovalsForm=s,e.execApprovalsDirty=!0}function Yc(e,t){const n=De(e.execApprovalsForm??e.execApprovalsSnapshot?.file??{});co(n,t),e.execApprovalsForm=n,e.execApprovalsDirty=!0}async function js(e){if(!(!e.client||!e.connected)&&!e.presenceLoading){e.presenceLoading=!0,e.presenceError=null,e.presenceStatus=null;try{const t=await e.client.request("system-presence",{});Array.isArray(t)?(e.presenceEntries=t,e.presenceStatus=t.length===0?"No instances yet.":null):(e.presenceEntries=[],e.presenceStatus="No presence payload.")}catch(t){e.presenceError=String(t)}finally{e.presenceLoading=!1}}}function tt(e,t,n){if(!t.trim())return;const s={...e.skillMessages};n?s[t]=n:delete s[t],e.skillMessages=s}function fn(e){return e instanceof Error?e.message:String(e)}async function Ct(e,t){if(t?.clearMessages&&Object.keys(e.skillMessages).length>0&&(e.skillMessages={}),!(!e.client||!e.connected)&&!e.skillsLoading){e.skillsLoading=!0,e.skillsError=null;try{const n=await e.client.request("skills.status",{});n&&(e.skillsReport=n)}catch(n){e.skillsError=fn(n)}finally{e.skillsLoading=!1}}}function Qc(e,t,n){e.skillEdits={...e.skillEdits,[t]:n}}async function Zc(e,t,n){if(!(!e.client||!e.connected)){e.skillsBusyKey=t,e.skillsError=null;try{await e.client.request("skills.update",{skillKey:t,enabled:n}),await Ct(e),tt(e,t,{kind:"success",message:n?"Skill enabled":"Skill disabled"})}catch(s){const i=fn(s);e.skillsError=i,tt(e,t,{kind:"error",message:i})}finally{e.skillsBusyKey=null}}}async function Jc(e,t){if(!(!e.client||!e.connected)){e.skillsBusyKey=t,e.skillsError=null;try{const n=e.skillEdits[t]??"";await e.client.request("skills.update",{skillKey:t,apiKey:n}),await Ct(e),tt(e,t,{kind:"success",message:"API key saved"})}catch(n){const s=fn(n);e.skillsError=s,tt(e,t,{kind:"error",message:s})}finally{e.skillsBusyKey=null}}}async function Xc(e,t,n,s){if(!(!e.client||!e.connected)){e.skillsBusyKey=t,e.skillsError=null;try{const i=await e.client.request("skills.install",{name:n,installId:s,timeoutMs:12e4});await Ct(e),tt(e,t,{kind:"success",message:i?.message??"Installed"})}catch(i){const a=fn(i);e.skillsError=a,tt(e,t,{kind:"error",message:a})}finally{e.skillsBusyKey=null}}}function ed(){return typeof window>"u"||typeof window.matchMedia!="function"||window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}function qs(e){return e==="system"?ed():e}const Ft=e=>Number.isNaN(e)?.5:e<=0?0:e>=1?1:e,td=()=>typeof window>"u"||typeof window.matchMedia!="function"?!1:window.matchMedia("(prefers-reduced-motion: reduce)").matches??!1,Ut=e=>{e.classList.remove("theme-transition"),e.style.removeProperty("--theme-switch-x"),e.style.removeProperty("--theme-switch-y")},nd=({nextTheme:e,applyTheme:t,context:n,currentTheme:s})=>{if(s===e)return;const i=globalThis.document??null;if(!i){t();return}const a=i.documentElement,o=i,c=td();if(!!o.startViewTransition&&!c){let p=.5,d=.5;if(n?.pointerClientX!==void 0&&n?.pointerClientY!==void 0&&typeof window<"u")p=Ft(n.pointerClientX/window.innerWidth),d=Ft(n.pointerClientY/window.innerHeight);else if(n?.element){const u=n.element.getBoundingClientRect();u.width>0&&u.height>0&&typeof window<"u"&&(p=Ft((u.left+u.width/2)/window.innerWidth),d=Ft((u.top+u.height/2)/window.innerHeight))}a.style.setProperty("--theme-switch-x",`${p*100}%`),a.style.setProperty("--theme-switch-y",`${d*100}%`),a.classList.add("theme-transition");try{const u=o.startViewTransition?.(()=>{t()});u?.finished?u.finished.finally(()=>Ut(a)):Ut(a)}catch{Ut(a),t()}return}t(),Ut(a)};function sd(e){e.nodesPollInterval==null&&(e.nodesPollInterval=window.setInterval(()=>{pn(e,{quiet:!0})},5e3))}function id(e){e.nodesPollInterval!=null&&(clearInterval(e.nodesPollInterval),e.nodesPollInterval=null)}function Vs(e){e.logsPollInterval==null&&(e.logsPollInterval=window.setInterval(()=>{e.tab==="logs"&&Os(e,{quiet:!0})},2e3))}function Ws(e){e.logsPollInterval!=null&&(clearInterval(e.logsPollInterval),e.logsPollInterval=null)}function Gs(e){e.debugPollInterval==null&&(e.debugPollInterval=window.setInterval(()=>{e.tab==="debug"&&dn(e)},3e3))}function Ys(e){e.debugPollInterval!=null&&(clearInterval(e.debugPollInterval),e.debugPollInterval=null)}function ke(e,t){const n={...t,lastActiveSessionKey:t.lastActiveSessionKey?.trim()||t.sessionKey.trim()||"main"};e.settings=n,fl(n),t.theme!==e.theme&&(e.theme=t.theme,hn(e,qs(t.theme))),e.applySessionKey=e.settings.lastActiveSessionKey}function Mo(e,t){const n=t.trim();n&&e.settings.lastActiveSessionKey!==n&&ke(e,{...e.settings,lastActiveSessionKey:n})}function ad(e){if(!window.location.search)return;const t=new URLSearchParams(window.location.search),n=t.get("token"),s=t.get("password"),i=t.get("session"),a=t.get("gatewayUrl");let o=!1;if(n!=null){const l=n.trim();l&&l!==e.settings.token&&ke(e,{...e.settings,token:l}),t.delete("token"),o=!0}if(s!=null){const l=s.trim();l&&(e.password=l),t.delete("password"),o=!0}if(i!=null){const l=i.trim();l&&(e.sessionKey=l,ke(e,{...e.settings,sessionKey:l,lastActiveSessionKey:l}))}if(a!=null){const l=a.trim();l&&l!==e.settings.gatewayUrl&&ke(e,{...e.settings,gatewayUrl:l}),t.delete("gatewayUrl"),o=!0}if(!o)return;const c=new URL(window.location.href);c.search=t.toString(),window.history.replaceState({},"",c.toString())}function od(e,t){e.tab!==t&&(e.tab=t),t==="chat"&&(e.chatHasAutoScrolled=!1),t==="logs"?Vs(e):Ws(e),t==="debug"?Gs(e):Ys(e),Qs(e),Ro(e,t,!1)}function rd(e,t,n){nd({nextTheme:t,applyTheme:()=>{e.theme=t,ke(e,{...e.settings,theme:t}),hn(e,qs(t))},context:n,currentTheme:e.theme})}async function Qs(e){e.tab==="overview"&&await Po(e),e.tab==="channels"&&await gd(e),e.tab==="instances"&&await js(e),e.tab==="sessions"&&await st(e),e.tab==="cron"&&await Zs(e),e.tab==="skills"&&await Ct(e),e.tab==="nodes"&&(await pn(e),await Te(e),await be(e),await zs(e)),e.tab==="chat"&&(await wd(e),ln(e,!e.chatHasAutoScrolled)),e.tab==="config"&&(await uo(e),await be(e)),e.tab==="debug"&&(await dn(e),e.eventLog=e.eventLogBuffer),e.tab==="logs"&&(e.logsAtBottom=!0,await Os(e,{reset:!0}),ro(e,!0))}function ld(){if(typeof window>"u")return"";const e=window.__CLAWDBOT_CONTROL_UI_BASE_PATH__;return typeof e=="string"&&e.trim()?rn(e):gl(window.location.pathname)}function cd(e){e.theme=e.settings.theme??"system",hn(e,qs(e.theme))}function hn(e,t){if(e.themeResolved=t,typeof document>"u")return;const n=document.documentElement;n.dataset.theme=t,n.style.colorScheme=t}function dd(e){if(typeof window>"u"||typeof window.matchMedia!="function")return;if(e.themeMedia=window.matchMedia("(prefers-color-scheme: dark)"),e.themeMediaHandler=n=>{e.theme==="system"&&hn(e,n.matches?"dark":"light")},typeof e.themeMedia.addEventListener=="function"){e.themeMedia.addEventListener("change",e.themeMediaHandler);return}e.themeMedia.addListener(e.themeMediaHandler)}function ud(e){if(!e.themeMedia||!e.themeMediaHandler)return;if(typeof e.themeMedia.removeEventListener=="function"){e.themeMedia.removeEventListener("change",e.themeMediaHandler);return}e.themeMedia.removeListener(e.themeMediaHandler),e.themeMedia=null,e.themeMediaHandler=null}function pd(e,t){if(typeof window>"u")return;const n=so(window.location.pathname,e.basePath)??"chat";Io(e,n),Ro(e,n,t)}function fd(e){if(typeof window>"u")return;const t=so(window.location.pathname,e.basePath);if(!t)return;const s=new URL(window.location.href).searchParams.get("session")?.trim();s&&(e.sessionKey=s,ke(e,{...e.settings,sessionKey:s,lastActiveSessionKey:s})),Io(e,t)}function Io(e,t){e.tab!==t&&(e.tab=t),t==="chat"&&(e.chatHasAutoScrolled=!1),t==="logs"?Vs(e):Ws(e),t==="debug"?Gs(e):Ys(e),e.connected&&Qs(e)}function Ro(e,t,n){if(typeof window>"u")return;const s=kt(Rs(t,e.basePath)),i=kt(window.location.pathname),a=new URL(window.location.href);t==="chat"&&e.sessionKey?a.searchParams.set("session",e.sessionKey):a.searchParams.delete("session"),i!==s&&(a.pathname=s),n?window.history.replaceState({},"",a.toString()):window.history.pushState({},"",a.toString())}function hd(e,t,n){if(typeof window>"u")return;const s=new URL(window.location.href);s.searchParams.set("session",t),window.history.replaceState({},"",s.toString())}async function Po(e){await Promise.all([oe(e,!1),js(e),st(e),Tt(e),dn(e)])}async function gd(e){await Promise.all([oe(e,!0),uo(e),be(e)])}async function Zs(e){await Promise.all([oe(e,!1),Tt(e),cn(e)])}function No(e){return e.chatSending||!!e.chatRunId}function vd(e){const t=e.trim();if(!t)return!1;const n=t.toLowerCase();return n==="/stop"?!0:n==="stop"||n==="esc"||n==="abort"||n==="wait"||n==="exit"}async function Oo(e){e.connected&&(e.chatMessage="",await El(e))}function md(e,t){const n=t.trim();n&&(e.chatQueue=[...e.chatQueue,{id:Ps(),text:n,createdAt:Date.now()}])}async function Do(e,t,n){Ns(e);const s=await Cl(e,t);return!s&&n?.previousDraft!=null&&(e.chatMessage=n.previousDraft),s&&Mo(e,e.sessionKey),s&&n?.restoreDraft&&n.previousDraft?.trim()&&(e.chatMessage=n.previousDraft),ln(e),s&&!e.chatRunId&&Bo(e),s}async function Bo(e){if(!e.connected||No(e))return;const[t,...n]=e.chatQueue;if(!t)return;e.chatQueue=n,await Do(e,t.text)||(e.chatQueue=[t,...e.chatQueue])}function bd(e,t){e.chatQueue=e.chatQueue.filter(n=>n.id!==t)}async function yd(e,t,n){if(!e.connected)return;const s=e.chatMessage,i=(t??e.chatMessage).trim();if(i){if(vd(i)){await Oo(e);return}if(t==null&&(e.chatMessage=""),No(e)){md(e,i);return}await Do(e,i,{previousDraft:t==null?s:void 0,restoreDraft:!!(t&&n?.restoreDraft)})}}async function wd(e){await Promise.all([Xe(e),st(e),fs(e)]),ln(e,!0)}const $d=Bo;function xd(e){const t=eo(e.sessionKey);return t?.agentId?t.agentId:e.hello?.snapshot?.sessionDefaults?.defaultAgentId?.trim()||"main"}function kd(e,t){const n=rn(e),s=encodeURIComponent(t);return n?`${n}/avatar/${s}?meta=1`:`/avatar/${s}?meta=1`}async function fs(e){if(!e.connected){e.chatAvatarUrl=null;return}const t=xd(e);if(!t){e.chatAvatarUrl=null;return}e.chatAvatarUrl=null;const n=kd(e.basePath,t);try{const s=await fetch(n,{method:"GET"});if(!s.ok){e.chatAvatarUrl=null;return}const i=await s.json(),a=typeof i.avatarUrl=="string"?i.avatarUrl.trim():"";e.chatAvatarUrl=a||null}catch{e.chatAvatarUrl=null}}const Fo={CHILD:2},Uo=e=>(...t)=>({_$litDirective$:e,values:t});let Ko=class{constructor(t){}get _$AU(){return this._$AM._$AU}_$AT(t,n,s){this._$Ct=t,this._$AM=n,this._$Ci=s}_$AS(t,n){return this.update(t,n)}update(t,n){return this.render(...n)}};const{I:Ad}=nl,ia=e=>e,aa=()=>document.createComment(""),lt=(e,t,n)=>{const s=e._$AA.parentNode,i=t===void 0?e._$AB:t._$AA;if(n===void 0){const a=s.insertBefore(aa(),i),o=s.insertBefore(aa(),i);n=new Ad(a,o,e,e.options)}else{const a=n._$AB.nextSibling,o=n._$AM,c=o!==e;if(c){let l;n._$AQ?.(e),n._$AM=e,n._$AP!==void 0&&(l=e._$AU)!==o._$AU&&n._$AP(l)}if(a!==i||c){let l=n._$AA;for(;l!==a;){const p=ia(l).nextSibling;ia(s).insertBefore(l,i),l=p}}}return n},Me=(e,t,n=e)=>(e._$AI(t,n),e),Sd={},_d=(e,t=Sd)=>e._$AH=t,Td=e=>e._$AH,qn=e=>{e._$AR(),e._$AA.remove()};const oa=(e,t,n)=>{const s=new Map;for(let i=t;i<=n;i++)s.set(e[i],i);return s},Ho=Uo(class extends Ko{constructor(e){if(super(e),e.type!==Fo.CHILD)throw Error("repeat() can only be used in text expressions")}dt(e,t,n){let s;n===void 0?n=t:t!==void 0&&(s=t);const i=[],a=[];let o=0;for(const c of e)i[o]=s?s(c,o):o,a[o]=n(c,o),o++;return{values:a,keys:i}}render(e,t,n){return this.dt(e,t,n).values}update(e,[t,n,s]){const i=Td(e),{values:a,keys:o}=this.dt(t,n,s);if(!Array.isArray(i))return this.ut=o,a;const c=this.ut??=[],l=[];let p,d,u=0,h=i.length-1,v=0,w=a.length-1;for(;u<=h&&v<=w;)if(i[u]===null)u++;else if(i[h]===null)h--;else if(c[u]===o[v])l[v]=Me(i[u],a[v]),u++,v++;else if(c[h]===o[w])l[w]=Me(i[h],a[w]),h--,w--;else if(c[u]===o[w])l[w]=Me(i[u],a[w]),lt(e,l[w+1],i[u]),u++,w--;else if(c[h]===o[v])l[v]=Me(i[h],a[v]),lt(e,i[u],i[h]),h--,v++;else if(p===void 0&&(p=oa(o,v,w),d=oa(c,u,h)),p.has(c[u]))if(p.has(c[h])){const $=d.get(o[v]),k=$!==void 0?i[$]:null;if(k===null){const T=lt(e,i[u]);Me(T,a[v]),l[v]=T}else l[v]=Me(k,a[v]),lt(e,i[u],k),i[$]=null;v++}else qn(i[h]),h--;else qn(i[u]),u++;for(;v<=w;){const $=lt(e,l[w+1]);Me($,a[v]),l[v++]=$}for(;u<=h;){const $=i[u++];$!==null&&qn($)}return this.ut=o,_d(e,l),Se}});function zo(e){const t=e;let n=typeof t.role=="string"?t.role:"unknown";const s=typeof t.toolCallId=="string"||typeof t.tool_call_id=="string",i=t.content,a=Array.isArray(i)?i:null,o=Array.isArray(a)&&a.some(u=>{const v=String(u.type??"").toLowerCase();return v==="toolresult"||v==="tool_result"}),c=typeof t.toolName=="string"||typeof t.tool_name=="string";(s||o||c)&&(n="toolResult");let l=[];typeof t.content=="string"?l=[{type:"text",text:t.content}]:Array.isArray(t.content)?l=t.content.map(u=>({type:u.type||"text",text:u.text,name:u.name,args:u.args||u.arguments})):typeof t.text=="string"&&(l=[{type:"text",text:t.text}]);const p=typeof t.timestamp=="number"?t.timestamp:Date.now(),d=typeof t.id=="string"?t.id:void 0;return{role:n,content:l,timestamp:p,id:d}}function Js(e){const t=e.toLowerCase();return e==="user"||e==="User"?e:e==="assistant"?"assistant":e==="system"?"system":t==="toolresult"||t==="tool_result"||t==="tool"||t==="function"?"tool":e}function jo(e){const t=e,n=typeof t.role=="string"?t.role.toLowerCase():"";return n==="toolresult"||n==="tool_result"}class hs extends Ko{constructor(t){if(super(t),this.it=g,t.type!==Fo.CHILD)throw Error(this.constructor.directiveName+"() can only be used in child bindings")}render(t){if(t===g||t==null)return this._t=void 0,this.it=t;if(t===Se)return t;if(typeof t!="string")throw Error(this.constructor.directiveName+"() called with a non-string value");if(t===this.it)return this._t;this.it=t;const n=[t];return n.raw=n,this._t={_$litType$:this.constructor.resultType,strings:n,values:[]}}}hs.directiveName="unsafeHTML",hs.resultType=1;const gs=Uo(hs);const{entries:qo,setPrototypeOf:ra,isFrozen:Cd,getPrototypeOf:Ed,getOwnPropertyDescriptor:Ld}=Object;let{freeze:Z,seal:ne,create:vs}=Object,{apply:ms,construct:bs}=typeof Reflect<"u"&&Reflect;Z||(Z=function(t){return t});ne||(ne=function(t){return t});ms||(ms=function(t,n){for(var s=arguments.length,i=new Array(s>2?s-2:0),a=2;a1?n-1:0),i=1;i1?n-1:0),i=1;i2&&arguments[2]!==void 0?arguments[2]:Wt;ra&&ra(e,null);let s=t.length;for(;s--;){let i=t[s];if(typeof i=="string"){const a=n(i);a!==i&&(Cd(t)||(t[s]=a),i=a)}e[i]=!0}return e}function Od(e){for(let t=0;t/gm),Kd=ne(/\$\{[\w\W]*/gm),Hd=ne(/^data-[\-\w.\u00B7-\uFFFF]+$/),zd=ne(/^aria-[\-\w]+$/),Vo=ne(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),jd=ne(/^(?:\w+script|data):/i),qd=ne(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),Wo=ne(/^html$/i),Vd=ne(/^[a-z][.\w]*(-[.\w]+)+$/i);var fa=Object.freeze({__proto__:null,ARIA_ATTR:zd,ATTR_WHITESPACE:qd,CUSTOM_ELEMENT:Vd,DATA_ATTR:Hd,DOCTYPE_NAME:Wo,ERB_EXPR:Ud,IS_ALLOWED_URI:Vo,IS_SCRIPT_OR_DATA:jd,MUSTACHE_EXPR:Fd,TMPLIT_EXPR:Kd});const ft={element:1,text:3,progressingInstruction:7,comment:8,document:9},Wd=function(){return typeof window>"u"?null:window},Gd=function(t,n){if(typeof t!="object"||typeof t.createPolicy!="function")return null;let s=null;const i="data-tt-policy-suffix";n&&n.hasAttribute(i)&&(s=n.getAttribute(i));const a="dompurify"+(s?"#"+s:"");try{return t.createPolicy(a,{createHTML(o){return o},createScriptURL(o){return o}})}catch{return console.warn("TrustedTypes policy "+a+" could not be created."),null}},ha=function(){return{afterSanitizeAttributes:[],afterSanitizeElements:[],afterSanitizeShadowDOM:[],beforeSanitizeAttributes:[],beforeSanitizeElements:[],beforeSanitizeShadowDOM:[],uponSanitizeAttribute:[],uponSanitizeElement:[],uponSanitizeShadowNode:[]}};function Go(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:Wd();const t=_=>Go(_);if(t.version="3.3.1",t.removed=[],!e||!e.document||e.document.nodeType!==ft.document||!e.Element)return t.isSupported=!1,t;let{document:n}=e;const s=n,i=s.currentScript,{DocumentFragment:a,HTMLTemplateElement:o,Node:c,Element:l,NodeFilter:p,NamedNodeMap:d=e.NamedNodeMap||e.MozNamedAttrMap,HTMLFormElement:u,DOMParser:h,trustedTypes:v}=e,w=l.prototype,$=pt(w,"cloneNode"),k=pt(w,"remove"),T=pt(w,"nextSibling"),M=pt(w,"childNodes"),P=pt(w,"parentNode");if(typeof o=="function"){const _=n.createElement("template");_.content&&_.content.ownerDocument&&(n=_.content.ownerDocument)}let L,C="";const{implementation:E,createNodeIterator:pe,createDocumentFragment:yn,getElementsByTagName:wn}=n,{importNode:kr}=s;let W=ha();t.isSupported=typeof qo=="function"&&typeof P=="function"&&E&&E.createHTMLDocument!==void 0;const{MUSTACHE_EXPR:$n,ERB_EXPR:xn,TMPLIT_EXPR:kn,DATA_ATTR:Ar,ARIA_ATTR:Sr,IS_SCRIPT_OR_DATA:_r,ATTR_WHITESPACE:di,CUSTOM_ELEMENT:Tr}=fa;let{IS_ALLOWED_URI:ui}=fa,K=null;const pi=I({},[...ca,...Gn,...Yn,...Qn,...da]);let z=null;const fi=I({},[...ua,...Zn,...pa,...Ht]);let B=Object.seal(vs(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),it=null,An=null;const He=Object.seal(vs(null,{tagCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeCheck:{writable:!0,configurable:!1,enumerable:!0,value:null}}));let hi=!0,Sn=!0,gi=!1,vi=!0,ze=!1,Lt=!0,Ce=!1,_n=!1,Tn=!1,je=!1,Mt=!1,It=!1,mi=!0,bi=!1;const Cr="user-content-";let Cn=!0,at=!1,qe={},re=null;const En=I({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","style","svg","template","thead","title","video","xmp"]);let yi=null;const wi=I({},["audio","video","img","source","image","track"]);let Ln=null;const $i=I({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),Rt="http://www.w3.org/1998/Math/MathML",Pt="http://www.w3.org/2000/svg",fe="http://www.w3.org/1999/xhtml";let Ve=fe,Mn=!1,In=null;const Er=I({},[Rt,Pt,fe],Vn);let Nt=I({},["mi","mo","mn","ms","mtext"]),Ot=I({},["annotation-xml"]);const Lr=I({},["title","style","font","a","script"]);let ot=null;const Mr=["application/xhtml+xml","text/html"],Ir="text/html";let U=null,We=null;const Rr=n.createElement("form"),xi=function(f){return f instanceof RegExp||f instanceof Function},Rn=function(){let f=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};if(!(We&&We===f)){if((!f||typeof f!="object")&&(f={}),f=de(f),ot=Mr.indexOf(f.PARSER_MEDIA_TYPE)===-1?Ir:f.PARSER_MEDIA_TYPE,U=ot==="application/xhtml+xml"?Vn:Wt,K=se(f,"ALLOWED_TAGS")?I({},f.ALLOWED_TAGS,U):pi,z=se(f,"ALLOWED_ATTR")?I({},f.ALLOWED_ATTR,U):fi,In=se(f,"ALLOWED_NAMESPACES")?I({},f.ALLOWED_NAMESPACES,Vn):Er,Ln=se(f,"ADD_URI_SAFE_ATTR")?I(de($i),f.ADD_URI_SAFE_ATTR,U):$i,yi=se(f,"ADD_DATA_URI_TAGS")?I(de(wi),f.ADD_DATA_URI_TAGS,U):wi,re=se(f,"FORBID_CONTENTS")?I({},f.FORBID_CONTENTS,U):En,it=se(f,"FORBID_TAGS")?I({},f.FORBID_TAGS,U):de({}),An=se(f,"FORBID_ATTR")?I({},f.FORBID_ATTR,U):de({}),qe=se(f,"USE_PROFILES")?f.USE_PROFILES:!1,hi=f.ALLOW_ARIA_ATTR!==!1,Sn=f.ALLOW_DATA_ATTR!==!1,gi=f.ALLOW_UNKNOWN_PROTOCOLS||!1,vi=f.ALLOW_SELF_CLOSE_IN_ATTR!==!1,ze=f.SAFE_FOR_TEMPLATES||!1,Lt=f.SAFE_FOR_XML!==!1,Ce=f.WHOLE_DOCUMENT||!1,je=f.RETURN_DOM||!1,Mt=f.RETURN_DOM_FRAGMENT||!1,It=f.RETURN_TRUSTED_TYPE||!1,Tn=f.FORCE_BODY||!1,mi=f.SANITIZE_DOM!==!1,bi=f.SANITIZE_NAMED_PROPS||!1,Cn=f.KEEP_CONTENT!==!1,at=f.IN_PLACE||!1,ui=f.ALLOWED_URI_REGEXP||Vo,Ve=f.NAMESPACE||fe,Nt=f.MATHML_TEXT_INTEGRATION_POINTS||Nt,Ot=f.HTML_INTEGRATION_POINTS||Ot,B=f.CUSTOM_ELEMENT_HANDLING||{},f.CUSTOM_ELEMENT_HANDLING&&xi(f.CUSTOM_ELEMENT_HANDLING.tagNameCheck)&&(B.tagNameCheck=f.CUSTOM_ELEMENT_HANDLING.tagNameCheck),f.CUSTOM_ELEMENT_HANDLING&&xi(f.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)&&(B.attributeNameCheck=f.CUSTOM_ELEMENT_HANDLING.attributeNameCheck),f.CUSTOM_ELEMENT_HANDLING&&typeof f.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements=="boolean"&&(B.allowCustomizedBuiltInElements=f.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements),ze&&(Sn=!1),Mt&&(je=!0),qe&&(K=I({},da),z=[],qe.html===!0&&(I(K,ca),I(z,ua)),qe.svg===!0&&(I(K,Gn),I(z,Zn),I(z,Ht)),qe.svgFilters===!0&&(I(K,Yn),I(z,Zn),I(z,Ht)),qe.mathMl===!0&&(I(K,Qn),I(z,pa),I(z,Ht))),f.ADD_TAGS&&(typeof f.ADD_TAGS=="function"?He.tagCheck=f.ADD_TAGS:(K===pi&&(K=de(K)),I(K,f.ADD_TAGS,U))),f.ADD_ATTR&&(typeof f.ADD_ATTR=="function"?He.attributeCheck=f.ADD_ATTR:(z===fi&&(z=de(z)),I(z,f.ADD_ATTR,U))),f.ADD_URI_SAFE_ATTR&&I(Ln,f.ADD_URI_SAFE_ATTR,U),f.FORBID_CONTENTS&&(re===En&&(re=de(re)),I(re,f.FORBID_CONTENTS,U)),f.ADD_FORBID_CONTENTS&&(re===En&&(re=de(re)),I(re,f.ADD_FORBID_CONTENTS,U)),Cn&&(K["#text"]=!0),Ce&&I(K,["html","head","body"]),K.table&&(I(K,["tbody"]),delete it.tbody),f.TRUSTED_TYPES_POLICY){if(typeof f.TRUSTED_TYPES_POLICY.createHTML!="function")throw ut('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');if(typeof f.TRUSTED_TYPES_POLICY.createScriptURL!="function")throw ut('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');L=f.TRUSTED_TYPES_POLICY,C=L.createHTML("")}else L===void 0&&(L=Gd(v,i)),L!==null&&typeof C=="string"&&(C=L.createHTML(""));Z&&Z(f),We=f}},ki=I({},[...Gn,...Yn,...Dd]),Ai=I({},[...Qn,...Bd]),Pr=function(f){let x=P(f);(!x||!x.tagName)&&(x={namespaceURI:Ve,tagName:"template"});const S=Wt(f.tagName),D=Wt(x.tagName);return In[f.namespaceURI]?f.namespaceURI===Pt?x.namespaceURI===fe?S==="svg":x.namespaceURI===Rt?S==="svg"&&(D==="annotation-xml"||Nt[D]):!!ki[S]:f.namespaceURI===Rt?x.namespaceURI===fe?S==="math":x.namespaceURI===Pt?S==="math"&&Ot[D]:!!Ai[S]:f.namespaceURI===fe?x.namespaceURI===Pt&&!Ot[D]||x.namespaceURI===Rt&&!Nt[D]?!1:!Ai[S]&&(Lr[S]||!ki[S]):!!(ot==="application/xhtml+xml"&&In[f.namespaceURI]):!1},le=function(f){ct(t.removed,{element:f});try{P(f).removeChild(f)}catch{k(f)}},Ee=function(f,x){try{ct(t.removed,{attribute:x.getAttributeNode(f),from:x})}catch{ct(t.removed,{attribute:null,from:x})}if(x.removeAttribute(f),f==="is")if(je||Mt)try{le(x)}catch{}else try{x.setAttribute(f,"")}catch{}},Si=function(f){let x=null,S=null;if(Tn)f=""+f;else{const F=Wn(f,/^[\r\n\t ]+/);S=F&&F[0]}ot==="application/xhtml+xml"&&Ve===fe&&(f=''+f+"");const D=L?L.createHTML(f):f;if(Ve===fe)try{x=new h().parseFromString(D,ot)}catch{}if(!x||!x.documentElement){x=E.createDocument(Ve,"template",null);try{x.documentElement.innerHTML=Mn?C:D}catch{}}const q=x.body||x.documentElement;return f&&S&&q.insertBefore(n.createTextNode(S),q.childNodes[0]||null),Ve===fe?wn.call(x,Ce?"html":"body")[0]:Ce?x.documentElement:q},_i=function(f){return pe.call(f.ownerDocument||f,f,p.SHOW_ELEMENT|p.SHOW_COMMENT|p.SHOW_TEXT|p.SHOW_PROCESSING_INSTRUCTION|p.SHOW_CDATA_SECTION,null)},Pn=function(f){return f instanceof u&&(typeof f.nodeName!="string"||typeof f.textContent!="string"||typeof f.removeChild!="function"||!(f.attributes instanceof d)||typeof f.removeAttribute!="function"||typeof f.setAttribute!="function"||typeof f.namespaceURI!="string"||typeof f.insertBefore!="function"||typeof f.hasChildNodes!="function")},Ti=function(f){return typeof c=="function"&&f instanceof c};function he(_,f,x){Kt(_,S=>{S.call(t,f,x,We)})}const Ci=function(f){let x=null;if(he(W.beforeSanitizeElements,f,null),Pn(f))return le(f),!0;const S=U(f.nodeName);if(he(W.uponSanitizeElement,f,{tagName:S,allowedTags:K}),Lt&&f.hasChildNodes()&&!Ti(f.firstElementChild)&&G(/<[/\w!]/g,f.innerHTML)&&G(/<[/\w!]/g,f.textContent)||f.nodeType===ft.progressingInstruction||Lt&&f.nodeType===ft.comment&&G(/<[/\w]/g,f.data))return le(f),!0;if(!(He.tagCheck instanceof Function&&He.tagCheck(S))&&(!K[S]||it[S])){if(!it[S]&&Li(S)&&(B.tagNameCheck instanceof RegExp&&G(B.tagNameCheck,S)||B.tagNameCheck instanceof Function&&B.tagNameCheck(S)))return!1;if(Cn&&!re[S]){const D=P(f)||f.parentNode,q=M(f)||f.childNodes;if(q&&D){const F=q.length;for(let X=F-1;X>=0;--X){const ge=$(q[X],!0);ge.__removalCount=(f.__removalCount||0)+1,D.insertBefore(ge,T(f))}}}return le(f),!0}return f instanceof l&&!Pr(f)||(S==="noscript"||S==="noembed"||S==="noframes")&&G(/<\/no(script|embed|frames)/i,f.innerHTML)?(le(f),!0):(ze&&f.nodeType===ft.text&&(x=f.textContent,Kt([$n,xn,kn],D=>{x=dt(x,D," ")}),f.textContent!==x&&(ct(t.removed,{element:f.cloneNode()}),f.textContent=x)),he(W.afterSanitizeElements,f,null),!1)},Ei=function(f,x,S){if(mi&&(x==="id"||x==="name")&&(S in n||S in Rr))return!1;if(!(Sn&&!An[x]&&G(Ar,x))){if(!(hi&&G(Sr,x))){if(!(He.attributeCheck instanceof Function&&He.attributeCheck(x,f))){if(!z[x]||An[x]){if(!(Li(f)&&(B.tagNameCheck instanceof RegExp&&G(B.tagNameCheck,f)||B.tagNameCheck instanceof Function&&B.tagNameCheck(f))&&(B.attributeNameCheck instanceof RegExp&&G(B.attributeNameCheck,x)||B.attributeNameCheck instanceof Function&&B.attributeNameCheck(x,f))||x==="is"&&B.allowCustomizedBuiltInElements&&(B.tagNameCheck instanceof RegExp&&G(B.tagNameCheck,S)||B.tagNameCheck instanceof Function&&B.tagNameCheck(S))))return!1}else if(!Ln[x]){if(!G(ui,dt(S,di,""))){if(!((x==="src"||x==="xlink:href"||x==="href")&&f!=="script"&&Rd(S,"data:")===0&&yi[f])){if(!(gi&&!G(_r,dt(S,di,"")))){if(S)return!1}}}}}}}return!0},Li=function(f){return f!=="annotation-xml"&&Wn(f,Tr)},Mi=function(f){he(W.beforeSanitizeAttributes,f,null);const{attributes:x}=f;if(!x||Pn(f))return;const S={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:z,forceKeepAttr:void 0};let D=x.length;for(;D--;){const q=x[D],{name:F,namespaceURI:X,value:ge}=q,Ge=U(F),Nn=ge;let j=F==="value"?Nn:Pd(Nn);if(S.attrName=Ge,S.attrValue=j,S.keepAttr=!0,S.forceKeepAttr=void 0,he(W.uponSanitizeAttribute,f,S),j=S.attrValue,bi&&(Ge==="id"||Ge==="name")&&(Ee(F,f),j=Cr+j),Lt&&G(/((--!?|])>)|<\/(style|title|textarea)/i,j)){Ee(F,f);continue}if(Ge==="attributename"&&Wn(j,"href")){Ee(F,f);continue}if(S.forceKeepAttr)continue;if(!S.keepAttr){Ee(F,f);continue}if(!vi&&G(/\/>/i,j)){Ee(F,f);continue}ze&&Kt([$n,xn,kn],Ri=>{j=dt(j,Ri," ")});const Ii=U(f.nodeName);if(!Ei(Ii,Ge,j)){Ee(F,f);continue}if(L&&typeof v=="object"&&typeof v.getAttributeType=="function"&&!X)switch(v.getAttributeType(Ii,Ge)){case"TrustedHTML":{j=L.createHTML(j);break}case"TrustedScriptURL":{j=L.createScriptURL(j);break}}if(j!==Nn)try{X?f.setAttributeNS(X,F,j):f.setAttribute(F,j),Pn(f)?le(f):la(t.removed)}catch{Ee(F,f)}}he(W.afterSanitizeAttributes,f,null)},Nr=function _(f){let x=null;const S=_i(f);for(he(W.beforeSanitizeShadowDOM,f,null);x=S.nextNode();)he(W.uponSanitizeShadowNode,x,null),Ci(x),Mi(x),x.content instanceof a&&_(x.content);he(W.afterSanitizeShadowDOM,f,null)};return t.sanitize=function(_){let f=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},x=null,S=null,D=null,q=null;if(Mn=!_,Mn&&(_=""),typeof _!="string"&&!Ti(_))if(typeof _.toString=="function"){if(_=_.toString(),typeof _!="string")throw ut("dirty is not a string, aborting")}else throw ut("toString is not a function");if(!t.isSupported)return _;if(_n||Rn(f),t.removed=[],typeof _=="string"&&(at=!1),at){if(_.nodeName){const ge=U(_.nodeName);if(!K[ge]||it[ge])throw ut("root node is forbidden and cannot be sanitized in-place")}}else if(_ instanceof c)x=Si(""),S=x.ownerDocument.importNode(_,!0),S.nodeType===ft.element&&S.nodeName==="BODY"||S.nodeName==="HTML"?x=S:x.appendChild(S);else{if(!je&&!ze&&!Ce&&_.indexOf("<")===-1)return L&&It?L.createHTML(_):_;if(x=Si(_),!x)return je?null:It?C:""}x&&Tn&&le(x.firstChild);const F=_i(at?_:x);for(;D=F.nextNode();)Ci(D),Mi(D),D.content instanceof a&&Nr(D.content);if(at)return _;if(je){if(Mt)for(q=yn.call(x.ownerDocument);x.firstChild;)q.appendChild(x.firstChild);else q=x;return(z.shadowroot||z.shadowrootmode)&&(q=kr.call(s,q,!0)),q}let X=Ce?x.outerHTML:x.innerHTML;return Ce&&K["!doctype"]&&x.ownerDocument&&x.ownerDocument.doctype&&x.ownerDocument.doctype.name&&G(Wo,x.ownerDocument.doctype.name)&&(X=" -`+X),ze&&Kt([$n,xn,kn],ge=>{X=dt(X,ge," ")}),L&&It?L.createHTML(X):X},t.setConfig=function(){let _=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};Rn(_),_n=!0},t.clearConfig=function(){We=null,_n=!1},t.isValidAttribute=function(_,f,x){We||Rn({});const S=U(_),D=U(f);return Ei(S,D,x)},t.addHook=function(_,f){typeof f=="function"&&ct(W[_],f)},t.removeHook=function(_,f){if(f!==void 0){const x=Md(W[_],f);return x===-1?void 0:Id(W[_],x,1)[0]}return la(W[_])},t.removeHooks=function(_){W[_]=[]},t.removeAllHooks=function(){W=ha()},t}var ys=Go();function Xs(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}var Ke=Xs();function Yo(e){Ke=e}var yt={exec:()=>null};function R(e,t=""){let n=typeof e=="string"?e:e.source,s={replace:(i,a)=>{let o=typeof a=="string"?a:a.source;return o=o.replace(Y.caret,"$1"),n=n.replace(i,o),s},getRegex:()=>new RegExp(n,t)};return s}var Yd=(()=>{try{return!!new RegExp("(?<=1)(?/,blockquoteSetextReplace:/\n {0,3}((?:=+|-+) *)(?=\n|$)/g,blockquoteSetextReplace2:/^ {0,3}>[ \t]?/gm,listReplaceTabs:/^\t+/,listReplaceNesting:/^ {1,4}(?=( {4})*[^ ])/g,listIsTask:/^\[[ xX]\] +\S/,listReplaceTask:/^\[[ xX]\] +/,listTaskCheckbox:/\[[ xX]\]/,anyLine:/\n.*\n/,hrefBrackets:/^<(.*)>$/,tableDelimiter:/[:|]/,tableAlignChars:/^\||\| *$/g,tableRowBlankLine:/\n[ \t]*$/,tableAlignRight:/^ *-+: *$/,tableAlignCenter:/^ *:-+: *$/,tableAlignLeft:/^ *:-+ *$/,startATag:/^/i,startPreScriptTag:/^<(pre|code|kbd|script)(\s|>)/i,endPreScriptTag:/^<\/(pre|code|kbd|script)(\s|>)/i,startAngleBracket:/^$/,pedanticHrefTitle:/^([^'"]*[^\s])\s+(['"])(.*)\2/,unicodeAlphaNumeric:/[\p{L}\p{N}]/u,escapeTest:/[&<>"']/,escapeReplace:/[&<>"']/g,escapeTestNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,escapeReplaceNoEncode:/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g,unescapeTest:/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig,caret:/(^|[^\[])\^/g,percentDecode:/%25/g,findPipe:/\|/g,splitPipe:/ \|/,slashPipe:/\\\|/g,carriageReturn:/\r\n|\r/g,spaceLine:/^ +$/gm,notSpaceStart:/^\S*/,endingNewline:/\n$/,listItemRegex:e=>new RegExp(`^( {0,3}${e})((?:[ ][^\\n]*)?(?:\\n|$))`),nextBulletRegex:e=>new RegExp(`^ {0,${Math.min(3,e-1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ ][^\\n]*)?(?:\\n|$))`),hrRegex:e=>new RegExp(`^ {0,${Math.min(3,e-1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`),fencesBeginRegex:e=>new RegExp(`^ {0,${Math.min(3,e-1)}}(?:\`\`\`|~~~)`),headingBeginRegex:e=>new RegExp(`^ {0,${Math.min(3,e-1)}}#`),htmlBeginRegex:e=>new RegExp(`^ {0,${Math.min(3,e-1)}}<(?:[a-z].*>|!--)`,"i")},Qd=/^(?:[ \t]*(?:\n|$))+/,Zd=/^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/,Jd=/^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,Et=/^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,Xd=/^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,ei=/(?:[*+-]|\d{1,9}[.)])/,Qo=/^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/,Zo=R(Qo).replace(/bull/g,ei).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/\|table/g,"").getRegex(),eu=R(Qo).replace(/bull/g,ei).replace(/blockCode/g,/(?: {4}| {0,3}\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).replace(/table/g,/ {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex(),ti=/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,tu=/^[^\n]+/,ni=/(?!\s*\])(?:\\[\s\S]|[^\[\]\\])+/,nu=R(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label",ni).replace("title",/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex(),su=R(/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g,ei).getRegex(),gn="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",si=/|$))/,iu=R("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|\\n*|$)|\\n*|$)|)[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$)|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ ]*)+\\n|$))","i").replace("comment",si).replace("tag",gn).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),Jo=R(ti).replace("hr",Et).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("|table","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",gn).getRegex(),au=R(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph",Jo).getRegex(),ii={blockquote:au,code:Zd,def:nu,fences:Jd,heading:Xd,hr:Et,html:iu,lheading:Zo,list:su,newline:Qd,paragraph:Jo,table:yt,text:tu},ga=R("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr",Et).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("blockquote"," {0,3}>").replace("code","(?: {4}| {0,3} )[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",gn).getRegex(),ou={...ii,lheading:eu,table:ga,paragraph:R(ti).replace("hr",Et).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("table",ga).replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",gn).getRegex()},ru={...ii,html:R(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment",si).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^(#{1,6})(.*)(?:\n+|$)/,fences:yt,lheading:/^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,paragraph:R(ti).replace("hr",Et).replace("heading",` *#{1,6} *[^ -]`).replace("lheading",Zo).replace("|table","").replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").replace("|tag","").getRegex()},lu=/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,cu=/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,Xo=/^( {2,}|\\)\n(?!\s*$)/,du=/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\`+)[^`]+\k(?!`))*?\]\((?:\\[\s\S]|[^\\\(\)]|\((?:\\[\s\S]|[^\\\(\)])*\))*\)/).replace("precode-",Yd?"(?`+)[^`]+\k(?!`)/).replace("html",/<(?! )[^<>]*?>/).getRegex(),nr=/^(?:\*+(?:((?!\*)punct)|[^\s*]))|^_+(?:((?!_)punct)|([^\s_]))/,gu=R(nr,"u").replace(/punct/g,vn).getRegex(),vu=R(nr,"u").replace(/punct/g,tr).getRegex(),sr="^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)",mu=R(sr,"gu").replace(/notPunctSpace/g,er).replace(/punctSpace/g,ai).replace(/punct/g,vn).getRegex(),bu=R(sr,"gu").replace(/notPunctSpace/g,fu).replace(/punctSpace/g,pu).replace(/punct/g,tr).getRegex(),yu=R("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)","gu").replace(/notPunctSpace/g,er).replace(/punctSpace/g,ai).replace(/punct/g,vn).getRegex(),wu=R(/\\(punct)/,"gu").replace(/punct/g,vn).getRegex(),$u=R(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme",/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email",/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(),xu=R(si).replace("(?:-->|$)","-->").getRegex(),ku=R("^comment|^|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^").replace("comment",xu).replace("attribute",/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex(),Xt=/(?:\[(?:\\[\s\S]|[^\[\]\\])*\]|\\[\s\S]|`+[^`]*?`+(?!`)|[^\[\]\\`])*?/,Au=R(/^!?\[(label)\]\(\s*(href)(?:(?:[ \t]*(?:\n[ \t]*)?)(title))?\s*\)/).replace("label",Xt).replace("href",/<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]*/).replace("title",/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex(),ir=R(/^!?\[(label)\]\[(ref)\]/).replace("label",Xt).replace("ref",ni).getRegex(),ar=R(/^!?\[(ref)\](?:\[\])?/).replace("ref",ni).getRegex(),Su=R("reflink|nolink(?!\\()","g").replace("reflink",ir).replace("nolink",ar).getRegex(),va=/[hH][tT][tT][pP][sS]?|[fF][tT][pP]/,oi={_backpedal:yt,anyPunctuation:wu,autolink:$u,blockSkip:hu,br:Xo,code:cu,del:yt,emStrongLDelim:gu,emStrongRDelimAst:mu,emStrongRDelimUnd:yu,escape:lu,link:Au,nolink:ar,punctuation:uu,reflink:ir,reflinkSearch:Su,tag:ku,text:du,url:yt},_u={...oi,link:R(/^!?\[(label)\]\((.*?)\)/).replace("label",Xt).getRegex(),reflink:R(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",Xt).getRegex()},ws={...oi,emStrongRDelimAst:bu,emStrongLDelim:vu,url:R(/^((?:protocol):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/).replace("protocol",va).replace("email",/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(),_backpedal:/(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/,del:/^(~~?)(?=[^\s~])((?:\\[\s\S]|[^\\])*?(?:\\[\s\S]|[^\s~\\]))\1(?=[^~]|$)/,text:R(/^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\":">",'"':""","'":"'"},ma=e=>Cu[e];function me(e,t){if(t){if(Y.escapeTest.test(e))return e.replace(Y.escapeReplace,ma)}else if(Y.escapeTestNoEncode.test(e))return e.replace(Y.escapeReplaceNoEncode,ma);return e}function ba(e){try{e=encodeURI(e).replace(Y.percentDecode,"%")}catch{return null}return e}function ya(e,t){let n=e.replace(Y.findPipe,(a,o,c)=>{let l=!1,p=o;for(;--p>=0&&c[p]==="\\";)l=!l;return l?"|":" |"}),s=n.split(Y.splitPipe),i=0;if(s[0].trim()||s.shift(),s.length>0&&!s.at(-1)?.trim()&&s.pop(),t)if(s.length>t)s.splice(t);else for(;s.length0?-2:-1}function wa(e,t,n,s,i){let a=t.href,o=t.title||null,c=e[1].replace(i.other.outputLinkReplace,"$1");s.state.inLink=!0;let l={type:e[0].charAt(0)==="!"?"image":"link",raw:n,href:a,title:o,text:c,tokens:s.inlineTokens(c)};return s.state.inLink=!1,l}function Lu(e,t,n){let s=e.match(n.other.indentCodeCompensation);if(s===null)return t;let i=s[1];return t.split(` -`).map(a=>{let o=a.match(n.other.beginningSpace);if(o===null)return a;let[c]=o;return c.length>=i.length?a.slice(i.length):a}).join(` -`)}var en=class{options;rules;lexer;constructor(e){this.options=e||Ke}space(e){let t=this.rules.block.newline.exec(e);if(t&&t[0].length>0)return{type:"space",raw:t[0]}}code(e){let t=this.rules.block.code.exec(e);if(t){let n=t[0].replace(this.rules.other.codeRemoveIndent,"");return{type:"code",raw:t[0],codeBlockStyle:"indented",text:this.options.pedantic?n:gt(n,` -`)}}}fences(e){let t=this.rules.block.fences.exec(e);if(t){let n=t[0],s=Lu(n,t[3]||"",this.rules);return{type:"code",raw:n,lang:t[2]?t[2].trim().replace(this.rules.inline.anyPunctuation,"$1"):t[2],text:s}}}heading(e){let t=this.rules.block.heading.exec(e);if(t){let n=t[2].trim();if(this.rules.other.endingHash.test(n)){let s=gt(n,"#");(this.options.pedantic||!s||this.rules.other.endingSpaceChar.test(s))&&(n=s.trim())}return{type:"heading",raw:t[0],depth:t[1].length,text:n,tokens:this.lexer.inline(n)}}}hr(e){let t=this.rules.block.hr.exec(e);if(t)return{type:"hr",raw:gt(t[0],` -`)}}blockquote(e){let t=this.rules.block.blockquote.exec(e);if(t){let n=gt(t[0],` -`).split(` -`),s="",i="",a=[];for(;n.length>0;){let o=!1,c=[],l;for(l=0;l1,i={type:"list",raw:"",ordered:s,start:s?+n.slice(0,-1):"",loose:!1,items:[]};n=s?`\\d{1,9}\\${n.slice(-1)}`:`\\${n}`,this.options.pedantic&&(n=s?n:"[*+-]");let a=this.rules.other.listItemRegex(n),o=!1;for(;e;){let l=!1,p="",d="";if(!(t=a.exec(e))||this.rules.block.hr.test(e))break;p=t[0],e=e.substring(p.length);let u=t[2].split(` -`,1)[0].replace(this.rules.other.listReplaceTabs,$=>" ".repeat(3*$.length)),h=e.split(` -`,1)[0],v=!u.trim(),w=0;if(this.options.pedantic?(w=2,d=u.trimStart()):v?w=t[1].length+1:(w=t[2].search(this.rules.other.nonSpaceChar),w=w>4?1:w,d=u.slice(w),w+=t[1].length),v&&this.rules.other.blankLine.test(h)&&(p+=h+` -`,e=e.substring(h.length+1),l=!0),!l){let $=this.rules.other.nextBulletRegex(w),k=this.rules.other.hrRegex(w),T=this.rules.other.fencesBeginRegex(w),M=this.rules.other.headingBeginRegex(w),P=this.rules.other.htmlBeginRegex(w);for(;e;){let L=e.split(` -`,1)[0],C;if(h=L,this.options.pedantic?(h=h.replace(this.rules.other.listReplaceNesting," "),C=h):C=h.replace(this.rules.other.tabCharGlobal," "),T.test(h)||M.test(h)||P.test(h)||$.test(h)||k.test(h))break;if(C.search(this.rules.other.nonSpaceChar)>=w||!h.trim())d+=` -`+C.slice(w);else{if(v||u.replace(this.rules.other.tabCharGlobal," ").search(this.rules.other.nonSpaceChar)>=4||T.test(u)||M.test(u)||k.test(u))break;d+=` -`+h}!v&&!h.trim()&&(v=!0),p+=L+` -`,e=e.substring(L.length+1),u=C.slice(w)}}i.loose||(o?i.loose=!0:this.rules.other.doubleBlankLine.test(p)&&(o=!0)),i.items.push({type:"list_item",raw:p,task:!!this.options.gfm&&this.rules.other.listIsTask.test(d),loose:!1,text:d,tokens:[]}),i.raw+=p}let c=i.items.at(-1);if(c)c.raw=c.raw.trimEnd(),c.text=c.text.trimEnd();else return;i.raw=i.raw.trimEnd();for(let l of i.items){if(this.lexer.state.top=!1,l.tokens=this.lexer.blockTokens(l.text,[]),l.task){if(l.text=l.text.replace(this.rules.other.listReplaceTask,""),l.tokens[0]?.type==="text"||l.tokens[0]?.type==="paragraph"){l.tokens[0].raw=l.tokens[0].raw.replace(this.rules.other.listReplaceTask,""),l.tokens[0].text=l.tokens[0].text.replace(this.rules.other.listReplaceTask,"");for(let d=this.lexer.inlineQueue.length-1;d>=0;d--)if(this.rules.other.listIsTask.test(this.lexer.inlineQueue[d].src)){this.lexer.inlineQueue[d].src=this.lexer.inlineQueue[d].src.replace(this.rules.other.listReplaceTask,"");break}}let p=this.rules.other.listTaskCheckbox.exec(l.raw);if(p){let d={type:"checkbox",raw:p[0]+" ",checked:p[0]!=="[ ]"};l.checked=d.checked,i.loose?l.tokens[0]&&["paragraph","text"].includes(l.tokens[0].type)&&"tokens"in l.tokens[0]&&l.tokens[0].tokens?(l.tokens[0].raw=d.raw+l.tokens[0].raw,l.tokens[0].text=d.raw+l.tokens[0].text,l.tokens[0].tokens.unshift(d)):l.tokens.unshift({type:"paragraph",raw:d.raw,text:d.raw,tokens:[d]}):l.tokens.unshift(d)}}if(!i.loose){let p=l.tokens.filter(u=>u.type==="space"),d=p.length>0&&p.some(u=>this.rules.other.anyLine.test(u.raw));i.loose=d}}if(i.loose)for(let l of i.items){l.loose=!0;for(let p of l.tokens)p.type==="text"&&(p.type="paragraph")}return i}}html(e){let t=this.rules.block.html.exec(e);if(t)return{type:"html",block:!0,raw:t[0],pre:t[1]==="pre"||t[1]==="script"||t[1]==="style",text:t[0]}}def(e){let t=this.rules.block.def.exec(e);if(t){let n=t[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal," "),s=t[2]?t[2].replace(this.rules.other.hrefBrackets,"$1").replace(this.rules.inline.anyPunctuation,"$1"):"",i=t[3]?t[3].substring(1,t[3].length-1).replace(this.rules.inline.anyPunctuation,"$1"):t[3];return{type:"def",tag:n,raw:t[0],href:s,title:i}}}table(e){let t=this.rules.block.table.exec(e);if(!t||!this.rules.other.tableDelimiter.test(t[2]))return;let n=ya(t[1]),s=t[2].replace(this.rules.other.tableAlignChars,"").split("|"),i=t[3]?.trim()?t[3].replace(this.rules.other.tableRowBlankLine,"").split(` -`):[],a={type:"table",raw:t[0],header:[],align:[],rows:[]};if(n.length===s.length){for(let o of s)this.rules.other.tableAlignRight.test(o)?a.align.push("right"):this.rules.other.tableAlignCenter.test(o)?a.align.push("center"):this.rules.other.tableAlignLeft.test(o)?a.align.push("left"):a.align.push(null);for(let o=0;o({text:c,tokens:this.lexer.inline(c),header:!1,align:a.align[l]})));return a}}lheading(e){let t=this.rules.block.lheading.exec(e);if(t)return{type:"heading",raw:t[0],depth:t[2].charAt(0)==="="?1:2,text:t[1],tokens:this.lexer.inline(t[1])}}paragraph(e){let t=this.rules.block.paragraph.exec(e);if(t){let n=t[1].charAt(t[1].length-1)===` -`?t[1].slice(0,-1):t[1];return{type:"paragraph",raw:t[0],text:n,tokens:this.lexer.inline(n)}}}text(e){let t=this.rules.block.text.exec(e);if(t)return{type:"text",raw:t[0],text:t[0],tokens:this.lexer.inline(t[0])}}escape(e){let t=this.rules.inline.escape.exec(e);if(t)return{type:"escape",raw:t[0],text:t[1]}}tag(e){let t=this.rules.inline.tag.exec(e);if(t)return!this.lexer.state.inLink&&this.rules.other.startATag.test(t[0])?this.lexer.state.inLink=!0:this.lexer.state.inLink&&this.rules.other.endATag.test(t[0])&&(this.lexer.state.inLink=!1),!this.lexer.state.inRawBlock&&this.rules.other.startPreScriptTag.test(t[0])?this.lexer.state.inRawBlock=!0:this.lexer.state.inRawBlock&&this.rules.other.endPreScriptTag.test(t[0])&&(this.lexer.state.inRawBlock=!1),{type:"html",raw:t[0],inLink:this.lexer.state.inLink,inRawBlock:this.lexer.state.inRawBlock,block:!1,text:t[0]}}link(e){let t=this.rules.inline.link.exec(e);if(t){let n=t[2].trim();if(!this.options.pedantic&&this.rules.other.startAngleBracket.test(n)){if(!this.rules.other.endAngleBracket.test(n))return;let a=gt(n.slice(0,-1),"\\");if((n.length-a.length)%2===0)return}else{let a=Eu(t[2],"()");if(a===-2)return;if(a>-1){let o=(t[0].indexOf("!")===0?5:4)+t[1].length+a;t[2]=t[2].substring(0,a),t[0]=t[0].substring(0,o).trim(),t[3]=""}}let s=t[2],i="";if(this.options.pedantic){let a=this.rules.other.pedanticHrefTitle.exec(s);a&&(s=a[1],i=a[3])}else i=t[3]?t[3].slice(1,-1):"";return s=s.trim(),this.rules.other.startAngleBracket.test(s)&&(this.options.pedantic&&!this.rules.other.endAngleBracket.test(n)?s=s.slice(1):s=s.slice(1,-1)),wa(t,{href:s&&s.replace(this.rules.inline.anyPunctuation,"$1"),title:i&&i.replace(this.rules.inline.anyPunctuation,"$1")},t[0],this.lexer,this.rules)}}reflink(e,t){let n;if((n=this.rules.inline.reflink.exec(e))||(n=this.rules.inline.nolink.exec(e))){let s=(n[2]||n[1]).replace(this.rules.other.multipleSpaceGlobal," "),i=t[s.toLowerCase()];if(!i){let a=n[0].charAt(0);return{type:"text",raw:a,text:a}}return wa(n,i,n[0],this.lexer,this.rules)}}emStrong(e,t,n=""){let s=this.rules.inline.emStrongLDelim.exec(e);if(!(!s||s[3]&&n.match(this.rules.other.unicodeAlphaNumeric))&&(!(s[1]||s[2])||!n||this.rules.inline.punctuation.exec(n))){let i=[...s[0]].length-1,a,o,c=i,l=0,p=s[0][0]==="*"?this.rules.inline.emStrongRDelimAst:this.rules.inline.emStrongRDelimUnd;for(p.lastIndex=0,t=t.slice(-1*e.length+i);(s=p.exec(t))!=null;){if(a=s[1]||s[2]||s[3]||s[4]||s[5]||s[6],!a)continue;if(o=[...a].length,s[3]||s[4]){c+=o;continue}else if((s[5]||s[6])&&i%3&&!((i+o)%3)){l+=o;continue}if(c-=o,c>0)continue;o=Math.min(o,o+c+l);let d=[...s[0]][0].length,u=e.slice(0,i+s.index+d+o);if(Math.min(i,o)%2){let v=u.slice(1,-1);return{type:"em",raw:u,text:v,tokens:this.lexer.inlineTokens(v)}}let h=u.slice(2,-2);return{type:"strong",raw:u,text:h,tokens:this.lexer.inlineTokens(h)}}}}codespan(e){let t=this.rules.inline.code.exec(e);if(t){let n=t[2].replace(this.rules.other.newLineCharGlobal," "),s=this.rules.other.nonSpaceChar.test(n),i=this.rules.other.startingSpaceChar.test(n)&&this.rules.other.endingSpaceChar.test(n);return s&&i&&(n=n.substring(1,n.length-1)),{type:"codespan",raw:t[0],text:n}}}br(e){let t=this.rules.inline.br.exec(e);if(t)return{type:"br",raw:t[0]}}del(e){let t=this.rules.inline.del.exec(e);if(t)return{type:"del",raw:t[0],text:t[2],tokens:this.lexer.inlineTokens(t[2])}}autolink(e){let t=this.rules.inline.autolink.exec(e);if(t){let n,s;return t[2]==="@"?(n=t[1],s="mailto:"+n):(n=t[1],s=n),{type:"link",raw:t[0],text:n,href:s,tokens:[{type:"text",raw:n,text:n}]}}}url(e){let t;if(t=this.rules.inline.url.exec(e)){let n,s;if(t[2]==="@")n=t[0],s="mailto:"+n;else{let i;do i=t[0],t[0]=this.rules.inline._backpedal.exec(t[0])?.[0]??"";while(i!==t[0]);n=t[0],t[1]==="www."?s="http://"+t[0]:s=t[0]}return{type:"link",raw:t[0],text:n,href:s,tokens:[{type:"text",raw:n,text:n}]}}}inlineText(e){let t=this.rules.inline.text.exec(e);if(t){let n=this.lexer.state.inRawBlock;return{type:"text",raw:t[0],text:t[0],escaped:n}}}},ie=class $s{tokens;options;state;inlineQueue;tokenizer;constructor(t){this.tokens=[],this.tokens.links=Object.create(null),this.options=t||Ke,this.options.tokenizer=this.options.tokenizer||new en,this.tokenizer=this.options.tokenizer,this.tokenizer.options=this.options,this.tokenizer.lexer=this,this.inlineQueue=[],this.state={inLink:!1,inRawBlock:!1,top:!0};let n={other:Y,block:zt.normal,inline:ht.normal};this.options.pedantic?(n.block=zt.pedantic,n.inline=ht.pedantic):this.options.gfm&&(n.block=zt.gfm,this.options.breaks?n.inline=ht.breaks:n.inline=ht.gfm),this.tokenizer.rules=n}static get rules(){return{block:zt,inline:ht}}static lex(t,n){return new $s(n).lex(t)}static lexInline(t,n){return new $s(n).inlineTokens(t)}lex(t){t=t.replace(Y.carriageReturn,` -`),this.blockTokens(t,this.tokens);for(let n=0;n(i=o.call({lexer:this},t,n))?(t=t.substring(i.raw.length),n.push(i),!0):!1))continue;if(i=this.tokenizer.space(t)){t=t.substring(i.raw.length);let o=n.at(-1);i.raw.length===1&&o!==void 0?o.raw+=` -`:n.push(i);continue}if(i=this.tokenizer.code(t)){t=t.substring(i.raw.length);let o=n.at(-1);o?.type==="paragraph"||o?.type==="text"?(o.raw+=(o.raw.endsWith(` -`)?"":` -`)+i.raw,o.text+=` -`+i.text,this.inlineQueue.at(-1).src=o.text):n.push(i);continue}if(i=this.tokenizer.fences(t)){t=t.substring(i.raw.length),n.push(i);continue}if(i=this.tokenizer.heading(t)){t=t.substring(i.raw.length),n.push(i);continue}if(i=this.tokenizer.hr(t)){t=t.substring(i.raw.length),n.push(i);continue}if(i=this.tokenizer.blockquote(t)){t=t.substring(i.raw.length),n.push(i);continue}if(i=this.tokenizer.list(t)){t=t.substring(i.raw.length),n.push(i);continue}if(i=this.tokenizer.html(t)){t=t.substring(i.raw.length),n.push(i);continue}if(i=this.tokenizer.def(t)){t=t.substring(i.raw.length);let o=n.at(-1);o?.type==="paragraph"||o?.type==="text"?(o.raw+=(o.raw.endsWith(` -`)?"":` -`)+i.raw,o.text+=` -`+i.raw,this.inlineQueue.at(-1).src=o.text):this.tokens.links[i.tag]||(this.tokens.links[i.tag]={href:i.href,title:i.title},n.push(i));continue}if(i=this.tokenizer.table(t)){t=t.substring(i.raw.length),n.push(i);continue}if(i=this.tokenizer.lheading(t)){t=t.substring(i.raw.length),n.push(i);continue}let a=t;if(this.options.extensions?.startBlock){let o=1/0,c=t.slice(1),l;this.options.extensions.startBlock.forEach(p=>{l=p.call({lexer:this},c),typeof l=="number"&&l>=0&&(o=Math.min(o,l))}),o<1/0&&o>=0&&(a=t.substring(0,o+1))}if(this.state.top&&(i=this.tokenizer.paragraph(a))){let o=n.at(-1);s&&o?.type==="paragraph"?(o.raw+=(o.raw.endsWith(` -`)?"":` -`)+i.raw,o.text+=` -`+i.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=o.text):n.push(i),s=a.length!==t.length,t=t.substring(i.raw.length);continue}if(i=this.tokenizer.text(t)){t=t.substring(i.raw.length);let o=n.at(-1);o?.type==="text"?(o.raw+=(o.raw.endsWith(` -`)?"":` -`)+i.raw,o.text+=` -`+i.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=o.text):n.push(i);continue}if(t){let o="Infinite loop on byte: "+t.charCodeAt(0);if(this.options.silent){console.error(o);break}else throw new Error(o)}}return this.state.top=!0,n}inline(t,n=[]){return this.inlineQueue.push({src:t,tokens:n}),n}inlineTokens(t,n=[]){let s=t,i=null;if(this.tokens.links){let l=Object.keys(this.tokens.links);if(l.length>0)for(;(i=this.tokenizer.rules.inline.reflinkSearch.exec(s))!=null;)l.includes(i[0].slice(i[0].lastIndexOf("[")+1,-1))&&(s=s.slice(0,i.index)+"["+"a".repeat(i[0].length-2)+"]"+s.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex))}for(;(i=this.tokenizer.rules.inline.anyPunctuation.exec(s))!=null;)s=s.slice(0,i.index)+"++"+s.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);let a;for(;(i=this.tokenizer.rules.inline.blockSkip.exec(s))!=null;)a=i[2]?i[2].length:0,s=s.slice(0,i.index+a)+"["+"a".repeat(i[0].length-a-2)+"]"+s.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);s=this.options.hooks?.emStrongMask?.call({lexer:this},s)??s;let o=!1,c="";for(;t;){o||(c=""),o=!1;let l;if(this.options.extensions?.inline?.some(d=>(l=d.call({lexer:this},t,n))?(t=t.substring(l.raw.length),n.push(l),!0):!1))continue;if(l=this.tokenizer.escape(t)){t=t.substring(l.raw.length),n.push(l);continue}if(l=this.tokenizer.tag(t)){t=t.substring(l.raw.length),n.push(l);continue}if(l=this.tokenizer.link(t)){t=t.substring(l.raw.length),n.push(l);continue}if(l=this.tokenizer.reflink(t,this.tokens.links)){t=t.substring(l.raw.length);let d=n.at(-1);l.type==="text"&&d?.type==="text"?(d.raw+=l.raw,d.text+=l.text):n.push(l);continue}if(l=this.tokenizer.emStrong(t,s,c)){t=t.substring(l.raw.length),n.push(l);continue}if(l=this.tokenizer.codespan(t)){t=t.substring(l.raw.length),n.push(l);continue}if(l=this.tokenizer.br(t)){t=t.substring(l.raw.length),n.push(l);continue}if(l=this.tokenizer.del(t)){t=t.substring(l.raw.length),n.push(l);continue}if(l=this.tokenizer.autolink(t)){t=t.substring(l.raw.length),n.push(l);continue}if(!this.state.inLink&&(l=this.tokenizer.url(t))){t=t.substring(l.raw.length),n.push(l);continue}let p=t;if(this.options.extensions?.startInline){let d=1/0,u=t.slice(1),h;this.options.extensions.startInline.forEach(v=>{h=v.call({lexer:this},u),typeof h=="number"&&h>=0&&(d=Math.min(d,h))}),d<1/0&&d>=0&&(p=t.substring(0,d+1))}if(l=this.tokenizer.inlineText(p)){t=t.substring(l.raw.length),l.raw.slice(-1)!=="_"&&(c=l.raw.slice(-1)),o=!0;let d=n.at(-1);d?.type==="text"?(d.raw+=l.raw,d.text+=l.text):n.push(l);continue}if(t){let d="Infinite loop on byte: "+t.charCodeAt(0);if(this.options.silent){console.error(d);break}else throw new Error(d)}}return n}},tn=class{options;parser;constructor(e){this.options=e||Ke}space(e){return""}code({text:e,lang:t,escaped:n}){let s=(t||"").match(Y.notSpaceStart)?.[0],i=e.replace(Y.endingNewline,"")+` -`;return s?'

'+(n?i:me(i,!0))+`
-`:"
"+(n?i:me(i,!0))+`
-`}blockquote({tokens:e}){return`
-${this.parser.parse(e)}
-`}html({text:e}){return e}def(e){return""}heading({tokens:e,depth:t}){return`${this.parser.parseInline(e)} -`}hr(e){return`
-`}list(e){let t=e.ordered,n=e.start,s="";for(let o=0;o -`+s+" -`}listitem(e){return`
  • ${this.parser.parse(e.tokens)}
  • -`}checkbox({checked:e}){return" '}paragraph({tokens:e}){return`

    ${this.parser.parseInline(e)}

    -`}table(e){let t="",n="";for(let i=0;i${s}`),` - -`+t+` -`+s+`
    -`}tablerow({text:e}){return` -${e} -`}tablecell(e){let t=this.parser.parseInline(e.tokens),n=e.header?"th":"td";return(e.align?`<${n} align="${e.align}">`:`<${n}>`)+t+` -`}strong({tokens:e}){return`${this.parser.parseInline(e)}`}em({tokens:e}){return`${this.parser.parseInline(e)}`}codespan({text:e}){return`${me(e,!0)}`}br(e){return"
    "}del({tokens:e}){return`${this.parser.parseInline(e)}`}link({href:e,title:t,tokens:n}){let s=this.parser.parseInline(n),i=ba(e);if(i===null)return s;e=i;let a='
    ",a}image({href:e,title:t,text:n,tokens:s}){s&&(n=this.parser.parseInline(s,this.parser.textRenderer));let i=ba(e);if(i===null)return me(n);e=i;let a=`${n}{let o=i[a].flat(1/0);n=n.concat(this.walkTokens(o,t))}):i.tokens&&(n=n.concat(this.walkTokens(i.tokens,t)))}}return n}use(...e){let t=this.defaults.extensions||{renderers:{},childTokens:{}};return e.forEach(n=>{let s={...n};if(s.async=this.defaults.async||s.async||!1,n.extensions&&(n.extensions.forEach(i=>{if(!i.name)throw new Error("extension name required");if("renderer"in i){let a=t.renderers[i.name];a?t.renderers[i.name]=function(...o){let c=i.renderer.apply(this,o);return c===!1&&(c=a.apply(this,o)),c}:t.renderers[i.name]=i.renderer}if("tokenizer"in i){if(!i.level||i.level!=="block"&&i.level!=="inline")throw new Error("extension level must be 'block' or 'inline'");let a=t[i.level];a?a.unshift(i.tokenizer):t[i.level]=[i.tokenizer],i.start&&(i.level==="block"?t.startBlock?t.startBlock.push(i.start):t.startBlock=[i.start]:i.level==="inline"&&(t.startInline?t.startInline.push(i.start):t.startInline=[i.start]))}"childTokens"in i&&i.childTokens&&(t.childTokens[i.name]=i.childTokens)}),s.extensions=t),n.renderer){let i=this.defaults.renderer||new tn(this.defaults);for(let a in n.renderer){if(!(a in i))throw new Error(`renderer '${a}' does not exist`);if(["options","parser"].includes(a))continue;let o=a,c=n.renderer[o],l=i[o];i[o]=(...p)=>{let d=c.apply(i,p);return d===!1&&(d=l.apply(i,p)),d||""}}s.renderer=i}if(n.tokenizer){let i=this.defaults.tokenizer||new en(this.defaults);for(let a in n.tokenizer){if(!(a in i))throw new Error(`tokenizer '${a}' does not exist`);if(["options","rules","lexer"].includes(a))continue;let o=a,c=n.tokenizer[o],l=i[o];i[o]=(...p)=>{let d=c.apply(i,p);return d===!1&&(d=l.apply(i,p)),d}}s.tokenizer=i}if(n.hooks){let i=this.defaults.hooks||new vt;for(let a in n.hooks){if(!(a in i))throw new Error(`hook '${a}' does not exist`);if(["options","block"].includes(a))continue;let o=a,c=n.hooks[o],l=i[o];vt.passThroughHooks.has(a)?i[o]=p=>{if(this.defaults.async&&vt.passThroughHooksRespectAsync.has(a))return(async()=>{let u=await c.call(i,p);return l.call(i,u)})();let d=c.call(i,p);return l.call(i,d)}:i[o]=(...p)=>{if(this.defaults.async)return(async()=>{let u=await c.apply(i,p);return u===!1&&(u=await l.apply(i,p)),u})();let d=c.apply(i,p);return d===!1&&(d=l.apply(i,p)),d}}s.hooks=i}if(n.walkTokens){let i=this.defaults.walkTokens,a=n.walkTokens;s.walkTokens=function(o){let c=[];return c.push(a.call(this,o)),i&&(c=c.concat(i.call(this,o))),c}}this.defaults={...this.defaults,...s}}),this}setOptions(e){return this.defaults={...this.defaults,...e},this}lexer(e,t){return ie.lex(e,t??this.defaults)}parser(e,t){return ae.parse(e,t??this.defaults)}parseMarkdown(e){return(t,n)=>{let s={...n},i={...this.defaults,...s},a=this.onError(!!i.silent,!!i.async);if(this.defaults.async===!0&&s.async===!1)return a(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise."));if(typeof t>"u"||t===null)return a(new Error("marked(): input parameter is undefined or null"));if(typeof t!="string")return a(new Error("marked(): input parameter is of type "+Object.prototype.toString.call(t)+", string expected"));if(i.hooks&&(i.hooks.options=i,i.hooks.block=e),i.async)return(async()=>{let o=i.hooks?await i.hooks.preprocess(t):t,c=await(i.hooks?await i.hooks.provideLexer():e?ie.lex:ie.lexInline)(o,i),l=i.hooks?await i.hooks.processAllTokens(c):c;i.walkTokens&&await Promise.all(this.walkTokens(l,i.walkTokens));let p=await(i.hooks?await i.hooks.provideParser():e?ae.parse:ae.parseInline)(l,i);return i.hooks?await i.hooks.postprocess(p):p})().catch(a);try{i.hooks&&(t=i.hooks.preprocess(t));let o=(i.hooks?i.hooks.provideLexer():e?ie.lex:ie.lexInline)(t,i);i.hooks&&(o=i.hooks.processAllTokens(o)),i.walkTokens&&this.walkTokens(o,i.walkTokens);let c=(i.hooks?i.hooks.provideParser():e?ae.parse:ae.parseInline)(o,i);return i.hooks&&(c=i.hooks.postprocess(c)),c}catch(o){return a(o)}}}onError(e,t){return n=>{if(n.message+=` -Please report this to https://github.com/markedjs/marked.`,e){let s="

    An error occurred:

    "+me(n.message+"",!0)+"
    ";return t?Promise.resolve(s):s}if(t)return Promise.reject(n);throw n}}},Ue=new Mu;function N(e,t){return Ue.parse(e,t)}N.options=N.setOptions=function(e){return Ue.setOptions(e),N.defaults=Ue.defaults,Yo(N.defaults),N};N.getDefaults=Xs;N.defaults=Ke;N.use=function(...e){return Ue.use(...e),N.defaults=Ue.defaults,Yo(N.defaults),N};N.walkTokens=function(e,t){return Ue.walkTokens(e,t)};N.parseInline=Ue.parseInline;N.Parser=ae;N.parser=ae.parse;N.Renderer=tn;N.TextRenderer=ri;N.Lexer=ie;N.lexer=ie.lex;N.Tokenizer=en;N.Hooks=vt;N.parse=N;N.options;N.setOptions;N.use;N.walkTokens;N.parseInline;ae.parse;ie.lex;N.setOptions({gfm:!0,breaks:!0,mangle:!1});const $a=["a","b","blockquote","br","code","del","em","h1","h2","h3","h4","hr","i","li","ol","p","pre","strong","table","tbody","td","th","thead","tr","ul"],xa=["class","href","rel","target","title","start"];let ka=!1;const Iu=14e4,Ru=4e4,Pu=200,Jn=5e4,Ne=new Map;function Nu(e){const t=Ne.get(e);return t===void 0?null:(Ne.delete(e),Ne.set(e,t),t)}function Aa(e,t){if(Ne.set(e,t),Ne.size<=Pu)return;const n=Ne.keys().next().value;n&&Ne.delete(n)}function Ou(){ka||(ka=!0,ys.addHook("afterSanitizeAttributes",e=>{!(e instanceof HTMLAnchorElement)||!e.getAttribute("href")||(e.setAttribute("rel","noreferrer noopener"),e.setAttribute("target","_blank"))}))}function ks(e){const t=e.trim();if(!t)return"";if(Ou(),t.length<=Jn){const o=Nu(t);if(o!==null)return o}const n=ao(t,Iu),s=n.truncated?` - -… truncated (${n.total} chars, showing first ${n.text.length}).`:"";if(n.text.length>Ru){const c=`
    ${Du(`${n.text}${s}`)}
    `,l=ys.sanitize(c,{ALLOWED_TAGS:$a,ALLOWED_ATTR:xa});return t.length<=Jn&&Aa(t,l),l}const i=N.parse(`${n.text}${s}`),a=ys.sanitize(i,{ALLOWED_TAGS:$a,ALLOWED_ATTR:xa});return t.length<=Jn&&Aa(t,a),a}function Du(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}const Bu=1500,Fu=2e3,or="Copy as markdown",Uu="Copied",Ku="Copy failed";async function Hu(e){if(!e)return!1;try{return await navigator.clipboard.writeText(e),!0}catch{return!1}}function jt(e,t){e.title=t,e.setAttribute("aria-label",t)}function zu(e){const t=e.label??or;return r` - - `}function ju(e){return zu({text:()=>e,label:or})}const qu={icon:"puzzle",detailKeys:["command","path","url","targetUrl","targetId","ref","element","node","nodeId","id","requestId","to","channelId","guildId","userId","name","query","pattern","messageId"]},Vu={bash:{icon:"wrench",title:"Bash",detailKeys:["command"]},process:{icon:"wrench",title:"Process",detailKeys:["sessionId"]},read:{icon:"fileText",title:"Read",detailKeys:["path"]},write:{icon:"edit",title:"Write",detailKeys:["path"]},edit:{icon:"penLine",title:"Edit",detailKeys:["path"]},attach:{icon:"paperclip",title:"Attach",detailKeys:["path","url","fileName"]},browser:{icon:"globe",title:"Browser",actions:{status:{label:"status"},start:{label:"start"},stop:{label:"stop"},tabs:{label:"tabs"},open:{label:"open",detailKeys:["targetUrl"]},focus:{label:"focus",detailKeys:["targetId"]},close:{label:"close",detailKeys:["targetId"]},snapshot:{label:"snapshot",detailKeys:["targetUrl","targetId","ref","element","format"]},screenshot:{label:"screenshot",detailKeys:["targetUrl","targetId","ref","element"]},navigate:{label:"navigate",detailKeys:["targetUrl","targetId"]},console:{label:"console",detailKeys:["level","targetId"]},pdf:{label:"pdf",detailKeys:["targetId"]},upload:{label:"upload",detailKeys:["paths","ref","inputRef","element","targetId"]},dialog:{label:"dialog",detailKeys:["accept","promptText","targetId"]},act:{label:"act",detailKeys:["request.kind","request.ref","request.selector","request.text","request.value"]}}},canvas:{icon:"image",title:"Canvas",actions:{present:{label:"present",detailKeys:["target","node","nodeId"]},hide:{label:"hide",detailKeys:["node","nodeId"]},navigate:{label:"navigate",detailKeys:["url","node","nodeId"]},eval:{label:"eval",detailKeys:["javaScript","node","nodeId"]},snapshot:{label:"snapshot",detailKeys:["format","node","nodeId"]},a2ui_push:{label:"A2UI push",detailKeys:["jsonlPath","node","nodeId"]},a2ui_reset:{label:"A2UI reset",detailKeys:["node","nodeId"]}}},nodes:{icon:"smartphone",title:"Nodes",actions:{status:{label:"status"},describe:{label:"describe",detailKeys:["node","nodeId"]},pending:{label:"pending"},approve:{label:"approve",detailKeys:["requestId"]},reject:{label:"reject",detailKeys:["requestId"]},notify:{label:"notify",detailKeys:["node","nodeId","title","body"]},camera_snap:{label:"camera snap",detailKeys:["node","nodeId","facing","deviceId"]},camera_list:{label:"camera list",detailKeys:["node","nodeId"]},camera_clip:{label:"camera clip",detailKeys:["node","nodeId","facing","duration","durationMs"]},screen_record:{label:"screen record",detailKeys:["node","nodeId","duration","durationMs","fps","screenIndex"]}}},cron:{icon:"loader",title:"Cron",actions:{status:{label:"status"},list:{label:"list"},add:{label:"add",detailKeys:["job.name","job.id","job.schedule","job.cron"]},update:{label:"update",detailKeys:["id"]},remove:{label:"remove",detailKeys:["id"]},run:{label:"run",detailKeys:["id"]},runs:{label:"runs",detailKeys:["id"]},wake:{label:"wake",detailKeys:["text","mode"]}}},gateway:{icon:"plug",title:"Gateway",actions:{restart:{label:"restart",detailKeys:["reason","delayMs"]},"config.get":{label:"config get"},"config.schema":{label:"config schema"},"config.apply":{label:"config apply",detailKeys:["restartDelayMs"]},"update.run":{label:"update run",detailKeys:["restartDelayMs"]}}},whatsapp_login:{icon:"circle",title:"WhatsApp Login",actions:{start:{label:"start"},wait:{label:"wait"}}},discord:{icon:"messageSquare",title:"Discord",actions:{react:{label:"react",detailKeys:["channelId","messageId","emoji"]},reactions:{label:"reactions",detailKeys:["channelId","messageId"]},sticker:{label:"sticker",detailKeys:["to","stickerIds"]},poll:{label:"poll",detailKeys:["question","to"]},permissions:{label:"permissions",detailKeys:["channelId"]},readMessages:{label:"read messages",detailKeys:["channelId","limit"]},sendMessage:{label:"send",detailKeys:["to","content"]},editMessage:{label:"edit",detailKeys:["channelId","messageId"]},deleteMessage:{label:"delete",detailKeys:["channelId","messageId"]},threadCreate:{label:"thread create",detailKeys:["channelId","name"]},threadList:{label:"thread list",detailKeys:["guildId","channelId"]},threadReply:{label:"thread reply",detailKeys:["channelId","content"]},pinMessage:{label:"pin",detailKeys:["channelId","messageId"]},unpinMessage:{label:"unpin",detailKeys:["channelId","messageId"]},listPins:{label:"list pins",detailKeys:["channelId"]},searchMessages:{label:"search",detailKeys:["guildId","content"]},memberInfo:{label:"member",detailKeys:["guildId","userId"]},roleInfo:{label:"roles",detailKeys:["guildId"]},emojiList:{label:"emoji list",detailKeys:["guildId"]},roleAdd:{label:"role add",detailKeys:["guildId","userId","roleId"]},roleRemove:{label:"role remove",detailKeys:["guildId","userId","roleId"]},channelInfo:{label:"channel",detailKeys:["channelId"]},channelList:{label:"channels",detailKeys:["guildId"]},voiceStatus:{label:"voice",detailKeys:["guildId","userId"]},eventList:{label:"events",detailKeys:["guildId"]},eventCreate:{label:"event create",detailKeys:["guildId","name"]},timeout:{label:"timeout",detailKeys:["guildId","userId"]},kick:{label:"kick",detailKeys:["guildId","userId"]},ban:{label:"ban",detailKeys:["guildId","userId"]}}},slack:{icon:"messageSquare",title:"Slack",actions:{react:{label:"react",detailKeys:["channelId","messageId","emoji"]},reactions:{label:"reactions",detailKeys:["channelId","messageId"]},sendMessage:{label:"send",detailKeys:["to","content"]},editMessage:{label:"edit",detailKeys:["channelId","messageId"]},deleteMessage:{label:"delete",detailKeys:["channelId","messageId"]},readMessages:{label:"read messages",detailKeys:["channelId","limit"]},pinMessage:{label:"pin",detailKeys:["channelId","messageId"]},unpinMessage:{label:"unpin",detailKeys:["channelId","messageId"]},listPins:{label:"list pins",detailKeys:["channelId"]},memberInfo:{label:"member",detailKeys:["userId"]},emojiList:{label:"emoji list"}}}},Wu={fallback:qu,tools:Vu},rr=Wu,Sa=rr.fallback??{icon:"puzzle"},Gu=rr.tools??{};function Yu(e){return(e??"tool").trim()}function Qu(e){const t=e.replace(/_/g," ").trim();return t?t.split(/\s+/).map(n=>n.length<=2&&n.toUpperCase()===n?n:`${n.at(0)?.toUpperCase()??""}${n.slice(1)}`).join(" "):"Tool"}function Zu(e){const t=e?.trim();if(t)return t.replace(/_/g," ")}function lr(e){if(e!=null){if(typeof e=="string"){const t=e.trim();if(!t)return;const n=t.split(/\r?\n/)[0]?.trim()??"";return n?n.length>160?`${n.slice(0,157)}…`:n:void 0}if(typeof e=="number"||typeof e=="boolean")return String(e);if(Array.isArray(e)){const t=e.map(s=>lr(s)).filter(s=>!!s);if(t.length===0)return;const n=t.slice(0,3).join(", ");return t.length>3?`${n}…`:n}}}function Ju(e,t){if(!e||typeof e!="object")return;let n=e;for(const s of t.split(".")){if(!s||!n||typeof n!="object")return;n=n[s]}return n}function Xu(e,t){for(const n of t){const s=Ju(e,n),i=lr(s);if(i)return i}}function ep(e){if(!e||typeof e!="object")return;const t=e,n=typeof t.path=="string"?t.path:void 0;if(!n)return;const s=typeof t.offset=="number"?t.offset:void 0,i=typeof t.limit=="number"?t.limit:void 0;return s!==void 0&&i!==void 0?`${n}:${s}-${s+i}`:n}function tp(e){if(!e||typeof e!="object")return;const t=e;return typeof t.path=="string"?t.path:void 0}function np(e,t){if(!(!e||!t))return e.actions?.[t]??void 0}function sp(e){const t=Yu(e.name),n=t.toLowerCase(),s=Gu[n],i=s?.icon??Sa.icon??"puzzle",a=s?.title??Qu(t),o=s?.label??t,c=e.args&&typeof e.args=="object"?e.args.action:void 0,l=typeof c=="string"?c.trim():void 0,p=np(s,l),d=Zu(p?.label??l);let u;n==="read"&&(u=ep(e.args)),!u&&(n==="write"||n==="edit"||n==="attach")&&(u=tp(e.args));const h=p?.detailKeys??s?.detailKeys??Sa.detailKeys??[];return!u&&h.length>0&&(u=Xu(e.args,h)),!u&&e.meta&&(u=e.meta),u&&(u=ap(u)),{name:t,icon:i,title:a,label:o,verb:d,detail:u}}function ip(e){const t=[];if(e.verb&&t.push(e.verb),e.detail&&t.push(e.detail),t.length!==0)return t.join(" · ")}function ap(e){return e&&e.replace(/\/Users\/[^/]+/g,"~").replace(/\/home\/[^/]+/g,"~")}const op=80,rp=2,_a=100;function lp(e){const t=e.trim();if(t.startsWith("{")||t.startsWith("["))try{const n=JSON.parse(t);return"```json\n"+JSON.stringify(n,null,2)+"\n```"}catch{}return e}function cp(e){const t=e.split(` -`),n=t.slice(0,rp),s=n.join(` -`);return s.length>_a?s.slice(0,_a)+"…":n.lengthi.kind==="result")){const i=typeof t.toolName=="string"&&t.toolName||typeof t.tool_name=="string"&&t.tool_name||"tool",a=oo(e)??void 0;s.push({kind:"result",name:i,text:a})}return s}function Ta(e,t){const n=sp({name:e.name,args:e.args}),s=ip(n),i=!!e.text?.trim(),a=!!t,o=a?()=>{if(i){t(lp(e.text));return}const u=`## ${n.label} - -${s?`**Command:** \`${s}\` - -`:""}*No output — tool completed successfully.*`;t(u)}:void 0,c=i&&(e.text?.length??0)<=op,l=i&&!c,p=i&&c,d=!i;return r` -
    {u.key!=="Enter"&&u.key!==" "||(u.preventDefault(),o?.())}:g} - > -
    -
    - ${Q[n.icon]} - ${n.label} -
    - ${a?r`${i?"View":""} ${Q.check}`:g} - ${d&&!a?r`${Q.check}`:g} -
    - ${s?r`
    ${s}
    `:g} - ${d?r`
    Completed
    `:g} - ${l?r`
    ${cp(e.text)}
    `:g} - ${p?r`
    ${e.text}
    `:g} -
    - `}function up(e){return Array.isArray(e)?e.filter(Boolean):[]}function pp(e){if(typeof e!="string")return e;const t=e.trim();if(!t||!t.startsWith("{")&&!t.startsWith("["))return e;try{return JSON.parse(t)}catch{return e}}function fp(e){if(typeof e.text=="string")return e.text;if(typeof e.content=="string")return e.content}function hp(e){return r` -
    - ${li("assistant",e)} -
    - -
    -
    - `}function gp(e,t,n,s){const i=new Date(t).toLocaleTimeString([],{hour:"numeric",minute:"2-digit"}),a=s?.name??"Assistant";return r` -
    - ${li("assistant",s)} -
    - ${cr({role:"assistant",content:[{type:"text",text:e}],timestamp:t},{isStreaming:!0,showReasoning:!1},n)} - -
    -
    - `}function vp(e,t){const n=Js(e.role),s=t.assistantName??"Assistant",i=n==="user"?"You":n==="assistant"?s:n,a=n==="user"?"user":n==="assistant"?"assistant":"other",o=new Date(e.timestamp).toLocaleTimeString([],{hour:"numeric",minute:"2-digit"});return r` -
    - ${li(e.role,{name:s,avatar:t.assistantAvatar??null})} -
    - ${e.messages.map((c,l)=>cr(c.message,{isStreaming:e.isStreaming&&l===e.messages.length-1,showReasoning:t.showReasoning},t.onOpenSidebar))} - -
    -
    - `}function li(e,t){const n=Js(e),s=t?.name?.trim()||"Assistant",i=t?.avatar?.trim()||"",a=n==="user"?"U":n==="assistant"?s.charAt(0).toUpperCase()||"A":n==="tool"?"⚙":"?",o=n==="user"?"user":n==="assistant"?"assistant":n==="tool"?"tool":"other";return i&&n==="assistant"?mp(i)?r`${s}`:r`
    ${i}
    `:r`
    ${a}
    `}function mp(e){return/^https?:\/\//i.test(e)||/^data:image\//i.test(e)||/^\//.test(e)}function cr(e,t,n){const s=e,i=typeof s.role=="string"?s.role:"unknown",a=jo(e)||i.toLowerCase()==="toolresult"||i.toLowerCase()==="tool_result"||typeof s.toolCallId=="string"||typeof s.tool_call_id=="string",o=dp(e),c=o.length>0,l=oo(e),p=t.showReasoning&&i==="assistant"?Al(e):null,d=l?.trim()?l:null,u=p?_l(p):null,h=d,v=i==="assistant"&&!!h?.trim(),w=["chat-bubble",v?"has-copy":"",t.isStreaming?"streaming":"","fade-in"].filter(Boolean).join(" ");return!h&&c&&a?r`${o.map($=>Ta($,n))}`:!h&&!c?g:r` -
    - ${v?ju(h):g} - ${u?r`
    ${gs(ks(u))}
    `:g} - ${h?r`
    ${gs(ks(h))}
    `:g} - ${o.map($=>Ta($,n))} -
    - `}function bp(e){return r` - - `}var yp=Object.defineProperty,wp=Object.getOwnPropertyDescriptor,mn=(e,t,n,s)=>{for(var i=s>1?void 0:s?wp(t,n):t,a=e.length-1,o;a>=0;a--)(o=e[a])&&(i=(s?o(t,n,i):o(i))||i);return s&&i&&yp(t,n,i),i};let nt=class extends Ze{constructor(){super(...arguments),this.splitRatio=.6,this.minRatio=.4,this.maxRatio=.7,this.isDragging=!1,this.startX=0,this.startRatio=0,this.handleMouseDown=e=>{this.isDragging=!0,this.startX=e.clientX,this.startRatio=this.splitRatio,this.classList.add("dragging"),document.addEventListener("mousemove",this.handleMouseMove),document.addEventListener("mouseup",this.handleMouseUp),e.preventDefault()},this.handleMouseMove=e=>{if(!this.isDragging)return;const t=this.parentElement;if(!t)return;const n=t.getBoundingClientRect().width,i=(e.clientX-this.startX)/n;let a=this.startRatio+i;a=Math.max(this.minRatio,Math.min(this.maxRatio,a)),this.dispatchEvent(new CustomEvent("resize",{detail:{splitRatio:a},bubbles:!0,composed:!0}))},this.handleMouseUp=()=>{this.isDragging=!1,this.classList.remove("dragging"),document.removeEventListener("mousemove",this.handleMouseMove),document.removeEventListener("mouseup",this.handleMouseUp)}}render(){return r``}connectedCallback(){super.connectedCallback(),this.addEventListener("mousedown",this.handleMouseDown)}disconnectedCallback(){super.disconnectedCallback(),this.removeEventListener("mousedown",this.handleMouseDown),document.removeEventListener("mousemove",this.handleMouseMove),document.removeEventListener("mouseup",this.handleMouseUp)}};nt.styles=Dr` - :host { - width: 4px; - cursor: col-resize; - background: var(--border, #333); - transition: background 150ms ease-out; - flex-shrink: 0; - position: relative; - } - - :host::before { - content: ""; - position: absolute; - top: 0; - left: -4px; - right: -4px; - bottom: 0; - } - - :host(:hover) { - background: var(--accent, #007bff); - } - - :host(.dragging) { - background: var(--accent, #007bff); - } - `;mn([on({type:Number})],nt.prototype,"splitRatio",2);mn([on({type:Number})],nt.prototype,"minRatio",2);mn([on({type:Number})],nt.prototype,"maxRatio",2);nt=mn([Ja("resizable-divider")],nt);const $p=5e3;function xp(e){return e?e.active?r` -
    - ${Q.loader} Compacting context... -
    - `:e.completedAt&&Date.now()-e.completedAt<$p?r` -
    - ${Q.check} Context compacted -
    - `:g:g}function kp(e){const t=e.connected,n=e.sending||e.stream!==null,s=!!(e.canAbort&&e.onAbort),a=e.sessions?.sessions?.find(h=>h.key===e.sessionKey)?.reasoningLevel??"off",o=e.showThinking&&a!=="off",c={name:e.assistantName,avatar:e.assistantAvatar??e.assistantAvatarUrl??null},l=e.connected?"Message (↩ to send, Shift+↩ for line breaks)":"Connect to the gateway to start chatting…",p=e.splitRatio??.6,d=!!(e.sidebarOpen&&e.onCloseSidebar),u=r` -
    - ${e.loading?r`
    Loading chat…
    `:g} - ${Ho(Sp(e),h=>h.key,h=>h.kind==="reading-indicator"?hp(c):h.kind==="stream"?gp(h.text,h.startedAt,e.onOpenSidebar,c):h.kind==="group"?vp(h,{onOpenSidebar:e.onOpenSidebar,showReasoning:o,assistantName:e.assistantName,assistantAvatar:c.avatar}):g)} -
    - `;return r` -
    - ${e.disabledReason?r`
    ${e.disabledReason}
    `:g} - - ${e.error?r`
    ${e.error}
    `:g} - - ${xp(e.compactionStatus)} - - ${e.focusMode?r` - - `:g} - -
    -
    - ${u} -
    - - ${d?r` - e.onSplitRatioChange?.(h.detail.splitRatio)} - > -
    - ${bp({content:e.sidebarContent??null,error:e.sidebarError??null,onClose:e.onCloseSidebar,onViewRawText:()=>{!e.sidebarContent||!e.onOpenSidebar||e.onOpenSidebar(`\`\`\` -${e.sidebarContent} -\`\`\``)}})} -
    - `:g} -
    - - ${e.queue.length?r` -
    -
    Queued (${e.queue.length})
    -
    - ${e.queue.map(h=>r` -
    -
    ${h.text}
    - -
    - `)} -
    -
    - `:g} - -
    - -
    - - -
    -
    -
    - `}const Ca=200;function Ap(e){const t=[];let n=null;for(const s of e){if(s.kind!=="message"){n&&(t.push(n),n=null),t.push(s);continue}const i=zo(s.message),a=Js(i.role),o=i.timestamp||Date.now();!n||n.role!==a?(n&&t.push(n),n={kind:"group",key:`group:${a}:${s.key}`,role:a,messages:[{message:s.message,key:s.key}],timestamp:o,isStreaming:!1}):n.messages.push({message:s.message,key:s.key})}return n&&t.push(n),t}function Sp(e){const t=[],n=Array.isArray(e.messages)?e.messages:[],s=Array.isArray(e.toolMessages)?e.toolMessages:[],i=Math.max(0,n.length-Ca);i>0&&t.push({kind:"message",key:"chat:history:notice",message:{role:"system",content:`Showing last ${Ca} messages (${i} hidden).`,timestamp:Date.now()}});for(let a=i;a0?t.push({kind:"stream",key:a,text:e.stream,startedAt:e.streamStartedAt??Date.now()}):t.push({kind:"reading-indicator",key:a})}return Ap(t)}function Ea(e,t){const n=e,s=typeof n.toolCallId=="string"?n.toolCallId:"";if(s)return`tool:${s}`;const i=typeof n.id=="string"?n.id:"";if(i)return`msg:${i}`;const a=typeof n.messageId=="string"?n.messageId:"";if(a)return`msg:${a}`;const o=typeof n.timestamp=="number"?n.timestamp:null,c=typeof n.role=="string"?n.role:"unknown";return o!=null?`msg:${c}:${o}:${t}`:`msg:${c}:${t}`}function ue(e){if(e)return Array.isArray(e.type)?e.type.filter(n=>n!=="null")[0]??e.type[0]:e.type}function dr(e){if(!e)return"";if(e.default!==void 0)return e.default;switch(ue(e)){case"object":return{};case"array":return[];case"boolean":return!1;case"number":case"integer":return 0;case"string":return"";default:return""}}function bn(e){return e.filter(t=>typeof t=="string").join(".")}function te(e,t){const n=bn(e),s=t[n];if(s)return s;const i=n.split(".");for(const[a,o]of Object.entries(t)){if(!a.includes("*"))continue;const c=a.split(".");if(c.length!==i.length)continue;let l=!0;for(let p=0;pt.toUpperCase())}function _p(e){const t=bn(e).toLowerCase();return t.includes("token")||t.includes("password")||t.includes("secret")||t.includes("apikey")||t.endsWith("key")}const Tp=new Set(["title","description","default","nullable"]);function Cp(e){return Object.keys(e??{}).filter(n=>!Tp.has(n)).length===0}function Ep(e){if(e===void 0)return"";try{return JSON.stringify(e,null,2)??""}catch{return""}}const _t={chevronDown:r``,plus:r``,minus:r``,trash:r``,edit:r``};function ye(e){const{schema:t,value:n,path:s,hints:i,unsupported:a,disabled:o,onPatch:c}=e,l=e.showLabel??!0,p=ue(t),d=te(s,i),u=d?.label??t.title??we(String(s.at(-1))),h=d?.help??t.description,v=bn(s);if(a.has(v))return r`
    -
    ${u}
    -
    Unsupported schema node. Use Raw mode.
    -
    `;if(t.anyOf||t.oneOf){const $=(t.anyOf??t.oneOf??[]).filter(C=>!(C.type==="null"||Array.isArray(C.type)&&C.type.includes("null")));if($.length===1)return ye({...e,schema:$[0]});const k=C=>{if(C.const!==void 0)return C.const;if(C.enum&&C.enum.length===1)return C.enum[0]},T=$.map(k),M=T.every(C=>C!==void 0);if(M&&T.length>0&&T.length<=5){const C=n??t.default;return r` -
    - ${l?r``:g} - ${h?r`
    ${h}
    `:g} -
    - ${T.map((E,pe)=>r` - - `)} -
    -
    - `}if(M&&T.length>5)return Ma({...e,options:T,value:n??t.default});const P=new Set($.map(C=>ue(C)).filter(Boolean)),L=new Set([...P].map(C=>C==="integer"?"number":C));if([...L].every(C=>["string","number","boolean"].includes(C))){const C=L.has("string"),E=L.has("number");if(L.has("boolean")&&L.size===1)return ye({...e,schema:{...t,type:"boolean",anyOf:void 0,oneOf:void 0}});if(C||E)return La({...e,inputType:E&&!C?"number":"text"})}}if(t.enum){const w=t.enum;if(w.length<=5){const $=n??t.default;return r` -
    - ${l?r``:g} - ${h?r`
    ${h}
    `:g} -
    - ${w.map(k=>r` - - `)} -
    -
    - `}return Ma({...e,options:w,value:n??t.default})}if(p==="object")return Mp(e);if(p==="array")return Ip(e);if(p==="boolean"){const w=typeof n=="boolean"?n:typeof t.default=="boolean"?t.default:!1;return r` - - `}return p==="number"||p==="integer"?Lp(e):p==="string"?La({...e,inputType:"text"}):r` -
    -
    ${u}
    -
    Unsupported type: ${p}. Use Raw mode.
    -
    - `}function La(e){const{schema:t,value:n,path:s,hints:i,disabled:a,onPatch:o,inputType:c}=e,l=e.showLabel??!0,p=te(s,i),d=p?.label??t.title??we(String(s.at(-1))),u=p?.help??t.description,h=p?.sensitive??_p(s),v=p?.placeholder??(h?"••••":t.default!==void 0?`Default: ${t.default}`:""),w=n??"";return r` -
    - ${l?r``:g} - ${u?r`
    ${u}
    `:g} -
    - {const k=$.target.value;if(c==="number"){if(k.trim()===""){o(s,void 0);return}const T=Number(k);o(s,Number.isNaN(T)?k:T);return}o(s,k)}} - /> - ${t.default!==void 0?r` - - `:g} -
    -
    - `}function Lp(e){const{schema:t,value:n,path:s,hints:i,disabled:a,onPatch:o}=e,c=e.showLabel??!0,l=te(s,i),p=l?.label??t.title??we(String(s.at(-1))),d=l?.help??t.description,u=n??t.default??"",h=typeof u=="number"?u:0;return r` -
    - ${c?r``:g} - ${d?r`
    ${d}
    `:g} -
    - - {const w=v.target.value,$=w===""?void 0:Number(w);o(s,$)}} - /> - -
    -
    - `}function Ma(e){const{schema:t,value:n,path:s,hints:i,disabled:a,options:o,onPatch:c}=e,l=e.showLabel??!0,p=te(s,i),d=p?.label??t.title??we(String(s.at(-1))),u=p?.help??t.description,h=n??t.default,v=o.findIndex($=>$===h||String($)===String(h)),w="__unset__";return r` -
    - ${l?r``:g} - ${u?r`
    ${u}
    `:g} - -
    - `}function Mp(e){const{schema:t,value:n,path:s,hints:i,unsupported:a,disabled:o,onPatch:c}=e;e.showLabel;const l=te(s,i),p=l?.label??t.title??we(String(s.at(-1))),d=l?.help??t.description,u=n??t.default,h=u&&typeof u=="object"&&!Array.isArray(u)?u:{},v=t.properties??{},$=Object.entries(v).sort((P,L)=>{const C=te([...s,P[0]],i)?.order??0,E=te([...s,L[0]],i)?.order??0;return C!==E?C-E:P[0].localeCompare(L[0])}),k=new Set(Object.keys(v)),T=t.additionalProperties,M=!!T&&typeof T=="object";return s.length===1?r` -
    - ${$.map(([P,L])=>ye({schema:L,value:h[P],path:[...s,P],hints:i,unsupported:a,disabled:o,onPatch:c}))} - ${M?Ia({schema:T,value:h,path:s,hints:i,unsupported:a,disabled:o,reservedKeys:k,onPatch:c}):g} -
    - `:r` -
    - - ${p} - ${_t.chevronDown} - - ${d?r`
    ${d}
    `:g} -
    - ${$.map(([P,L])=>ye({schema:L,value:h[P],path:[...s,P],hints:i,unsupported:a,disabled:o,onPatch:c}))} - ${M?Ia({schema:T,value:h,path:s,hints:i,unsupported:a,disabled:o,reservedKeys:k,onPatch:c}):g} -
    -
    - `}function Ip(e){const{schema:t,value:n,path:s,hints:i,unsupported:a,disabled:o,onPatch:c}=e,l=e.showLabel??!0,p=te(s,i),d=p?.label??t.title??we(String(s.at(-1))),u=p?.help??t.description,h=Array.isArray(t.items)?t.items[0]:t.items;if(!h)return r` -
    -
    ${d}
    -
    Unsupported array schema. Use Raw mode.
    -
    - `;const v=Array.isArray(n)?n:Array.isArray(t.default)?t.default:[];return r` -
    -
    - ${l?r`${d}`:g} - ${v.length} item${v.length!==1?"s":""} - -
    - ${u?r`
    ${u}
    `:g} - - ${v.length===0?r` -
    - No items yet. Click "Add" to create one. -
    - `:r` -
    - ${v.map((w,$)=>r` -
    -
    - #${$+1} - -
    -
    - ${ye({schema:h,value:w,path:[...s,$],hints:i,unsupported:a,disabled:o,showLabel:!1,onPatch:c})} -
    -
    - `)} -
    - `} -
    - `}function Ia(e){const{schema:t,value:n,path:s,hints:i,unsupported:a,disabled:o,reservedKeys:c,onPatch:l}=e,p=Cp(t),d=Object.entries(n??{}).filter(([u])=>!c.has(u));return r` -
    -
    - Custom entries - -
    - - ${d.length===0?r` -
    No custom entries.
    - `:r` -
    - ${d.map(([u,h])=>{const v=[...s,u],w=Ep(h);return r` -
    -
    - {const k=$.target.value.trim();if(!k||k===u)return;const T={...n??{}};k in T||(T[k]=T[u],delete T[u],l(s,T))}} - /> -
    -
    - ${p?r` - - `:ye({schema:t,value:h,path:v,hints:i,unsupported:a,disabled:o,showLabel:!1,onPatch:l})} -
    - -
    - `})} -
    - `} -
    - `}const Ra={env:r``,update:r``,agents:r``,auth:r``,channels:r``,messages:r``,commands:r``,hooks:r``,skills:r``,tools:r``,gateway:r``,wizard:r``,meta:r``,logging:r``,browser:r``,ui:r``,models:r``,bindings:r``,broadcast:r``,audio:r``,session:r``,cron:r``,web:r``,discovery:r``,canvasHost:r``,talk:r``,plugins:r``,default:r``},ci={env:{label:"Environment Variables",description:"Environment variables passed to the gateway process"},update:{label:"Updates",description:"Auto-update settings and release channel"},agents:{label:"Agents",description:"Agent configurations, models, and identities"},auth:{label:"Authentication",description:"API keys and authentication profiles"},channels:{label:"Channels",description:"Messaging channels (Telegram, Discord, Slack, etc.)"},messages:{label:"Messages",description:"Message handling and routing settings"},commands:{label:"Commands",description:"Custom slash commands"},hooks:{label:"Hooks",description:"Webhooks and event hooks"},skills:{label:"Skills",description:"Skill packs and capabilities"},tools:{label:"Tools",description:"Tool configurations (browser, search, etc.)"},gateway:{label:"Gateway",description:"Gateway server settings (port, auth, binding)"},wizard:{label:"Setup Wizard",description:"Setup wizard state and history"},meta:{label:"Metadata",description:"Gateway metadata and version information"},logging:{label:"Logging",description:"Log levels and output configuration"},browser:{label:"Browser",description:"Browser automation settings"},ui:{label:"UI",description:"User interface preferences"},models:{label:"Models",description:"AI model configurations and providers"},bindings:{label:"Bindings",description:"Key bindings and shortcuts"},broadcast:{label:"Broadcast",description:"Broadcast and notification settings"},audio:{label:"Audio",description:"Audio input/output settings"},session:{label:"Session",description:"Session management and persistence"},cron:{label:"Cron",description:"Scheduled tasks and automation"},web:{label:"Web",description:"Web server and API settings"},discovery:{label:"Discovery",description:"Service discovery and networking"},canvasHost:{label:"Canvas Host",description:"Canvas rendering and display"},talk:{label:"Talk",description:"Voice and speech settings"},plugins:{label:"Plugins",description:"Plugin management and extensions"}};function Pa(e){return Ra[e]??Ra.default}function Rp(e,t,n){if(!n)return!0;const s=n.toLowerCase(),i=ci[e];return e.toLowerCase().includes(s)||i&&(i.label.toLowerCase().includes(s)||i.description.toLowerCase().includes(s))?!0:mt(t,s)}function mt(e,t){if(e.title?.toLowerCase().includes(t)||e.description?.toLowerCase().includes(t)||e.enum?.some(s=>String(s).toLowerCase().includes(t)))return!0;if(e.properties){for(const[s,i]of Object.entries(e.properties))if(s.toLowerCase().includes(t)||mt(i,t))return!0}if(e.items){const s=Array.isArray(e.items)?e.items:[e.items];for(const i of s)if(i&&mt(i,t))return!0}if(e.additionalProperties&&typeof e.additionalProperties=="object"&&mt(e.additionalProperties,t))return!0;const n=e.anyOf??e.oneOf??e.allOf;if(n){for(const s of n)if(s&&mt(s,t))return!0}return!1}function Pp(e){if(!e.schema)return r`
    Schema unavailable.
    `;const t=e.schema,n=e.value??{};if(ue(t)!=="object"||!t.properties)return r`
    Unsupported schema. Use Raw.
    `;const s=new Set(e.unsupportedPaths??[]),i=t.properties,a=e.searchQuery??"",o=e.activeSection,c=e.activeSubsection??null,p=Object.entries(i).sort((u,h)=>{const v=te([u[0]],e.uiHints)?.order??50,w=te([h[0]],e.uiHints)?.order??50;return v!==w?v-w:u[0].localeCompare(h[0])}).filter(([u,h])=>!(o&&u!==o||a&&!Rp(u,h,a)));let d=null;if(o&&c&&p.length===1){const u=p[0]?.[1];u&&ue(u)==="object"&&u.properties&&u.properties[c]&&(d={sectionKey:o,subsectionKey:c,schema:u.properties[c]})}return p.length===0?r` -
    -
    ${Q.search}
    -
    - ${a?`No settings match "${a}"`:"No settings in this section"} -
    -
    - `:r` -
    - ${d?(()=>{const{sectionKey:u,subsectionKey:h,schema:v}=d,w=te([u,h],e.uiHints),$=w?.label??v.title??we(h),k=w?.help??v.description??"",T=n[u],M=T&&typeof T=="object"?T[h]:void 0,P=`config-section-${u}-${h}`;return r` -
    -
    - ${Pa(u)} -
    -

    ${$}

    - ${k?r`

    ${k}

    `:g} -
    -
    -
    - ${ye({schema:v,value:M,path:[u,h],hints:e.uiHints,unsupported:s,disabled:e.disabled??!1,showLabel:!1,onPatch:e.onPatch})} -
    -
    - `})():p.map(([u,h])=>{const v=ci[u]??{label:u.charAt(0).toUpperCase()+u.slice(1),description:h.description??""};return r` -
    -
    - ${Pa(u)} -
    -

    ${v.label}

    - ${v.description?r`

    ${v.description}

    `:g} -
    -
    -
    - ${ye({schema:h,value:n[u],path:[u],hints:e.uiHints,unsupported:s,disabled:e.disabled??!1,showLabel:!1,onPatch:e.onPatch})} -
    -
    - `})} -
    - `}const Np=new Set(["title","description","default","nullable"]);function Op(e){return Object.keys(e??{}).filter(n=>!Np.has(n)).length===0}function ur(e){const t=e.filter(i=>i!=null),n=t.length!==e.length,s=[];for(const i of t)s.some(a=>Object.is(a,i))||s.push(i);return{enumValues:s,nullable:n}}function pr(e){return!e||typeof e!="object"?{schema:null,unsupportedPaths:[""]}:wt(e,[])}function wt(e,t){const n=new Set,s={...e},i=bn(t)||"";if(e.anyOf||e.oneOf||e.allOf){const c=Dp(e,t);return c||{schema:e,unsupportedPaths:[i]}}const a=Array.isArray(e.type)&&e.type.includes("null"),o=ue(e)??(e.properties||e.additionalProperties?"object":void 0);if(s.type=o??e.type,s.nullable=a||e.nullable,s.enum){const{enumValues:c,nullable:l}=ur(s.enum);s.enum=c,l&&(s.nullable=!0),c.length===0&&n.add(i)}if(o==="object"){const c=e.properties??{},l={};for(const[p,d]of Object.entries(c)){const u=wt(d,[...t,p]);u.schema&&(l[p]=u.schema);for(const h of u.unsupportedPaths)n.add(h)}if(s.properties=l,e.additionalProperties===!0)n.add(i);else if(e.additionalProperties===!1)s.additionalProperties=!1;else if(e.additionalProperties&&typeof e.additionalProperties=="object"&&!Op(e.additionalProperties)){const p=wt(e.additionalProperties,[...t,"*"]);s.additionalProperties=p.schema??e.additionalProperties,p.unsupportedPaths.length>0&&n.add(i)}}else if(o==="array"){const c=Array.isArray(e.items)?e.items[0]:e.items;if(!c)n.add(i);else{const l=wt(c,[...t,"*"]);s.items=l.schema??c,l.unsupportedPaths.length>0&&n.add(i)}}else o!=="string"&&o!=="number"&&o!=="integer"&&o!=="boolean"&&!s.enum&&n.add(i);return{schema:s,unsupportedPaths:Array.from(n)}}function Dp(e,t){if(e.allOf)return null;const n=e.anyOf??e.oneOf;if(!n)return null;const s=[],i=[];let a=!1;for(const c of n){if(!c||typeof c!="object")return null;if(Array.isArray(c.enum)){const{enumValues:l,nullable:p}=ur(c.enum);s.push(...l),p&&(a=!0);continue}if("const"in c){if(c.const==null){a=!0;continue}s.push(c.const);continue}if(ue(c)==="null"){a=!0;continue}i.push(c)}if(s.length>0&&i.length===0){const c=[];for(const l of s)c.some(p=>Object.is(p,l))||c.push(l);return{schema:{...e,enum:c,nullable:a,anyOf:void 0,oneOf:void 0,allOf:void 0},unsupportedPaths:[]}}if(i.length===1){const c=wt(i[0],t);return c.schema&&(c.schema.nullable=a||c.schema.nullable),c}const o=["string","number","integer","boolean"];return i.length>0&&s.length===0&&i.every(c=>c.type&&o.includes(String(c.type)))?{schema:{...e,nullable:a},unsupportedPaths:[]}:null}const As={all:r``,env:r``,update:r``,agents:r``,auth:r``,channels:r``,messages:r``,commands:r``,hooks:r``,skills:r``,tools:r``,gateway:r``,wizard:r``,meta:r``,logging:r``,browser:r``,ui:r``,models:r``,bindings:r``,broadcast:r``,audio:r``,session:r``,cron:r``,web:r``,discovery:r``,canvasHost:r``,talk:r``,plugins:r``,default:r``},Na=[{key:"env",label:"Environment"},{key:"update",label:"Updates"},{key:"agents",label:"Agents"},{key:"auth",label:"Authentication"},{key:"channels",label:"Channels"},{key:"messages",label:"Messages"},{key:"commands",label:"Commands"},{key:"hooks",label:"Hooks"},{key:"skills",label:"Skills"},{key:"tools",label:"Tools"},{key:"gateway",label:"Gateway"},{key:"wizard",label:"Setup Wizard"}],Oa="__all__";function Da(e){return As[e]??As.default}function Bp(e,t){const n=ci[e];return n||{label:t?.title??we(e),description:t?.description??""}}function Fp(e){const{key:t,schema:n,uiHints:s}=e;if(!n||ue(n)!=="object"||!n.properties)return[];const i=Object.entries(n.properties).map(([a,o])=>{const c=te([t,a],s),l=c?.label??o.title??we(a),p=c?.help??o.description??"",d=c?.order??50;return{key:a,label:l,description:p,order:d}});return i.sort((a,o)=>a.order!==o.order?a.order-o.order:a.key.localeCompare(o.key)),i}function Up(e,t){if(!e||!t)return[];const n=[];function s(i,a,o){if(i===a)return;if(typeof i!=typeof a){n.push({path:o,from:i,to:a});return}if(typeof i!="object"||i===null||a===null){i!==a&&n.push({path:o,from:i,to:a});return}if(Array.isArray(i)&&Array.isArray(a)){JSON.stringify(i)!==JSON.stringify(a)&&n.push({path:o,from:i,to:a});return}const c=i,l=a,p=new Set([...Object.keys(c),...Object.keys(l)]);for(const d of p)s(c[d],l[d],o?`${o}.${d}`:d)}return s(e,t,""),n}function Ba(e,t=40){let n;try{n=JSON.stringify(e)??String(e)}catch{n=String(e)}return n.length<=t?n:n.slice(0,t-3)+"..."}function Kp(e){const t=e.valid==null?"unknown":e.valid?"valid":"invalid",n=pr(e.schema),s=n.schema?n.unsupportedPaths.length>0:!1,i=n.schema?.properties??{},a=Na.filter(E=>E.key in i),o=new Set(Na.map(E=>E.key)),c=Object.keys(i).filter(E=>!o.has(E)).map(E=>({key:E,label:E.charAt(0).toUpperCase()+E.slice(1)})),l=[...a,...c],p=e.activeSection&&n.schema&&ue(n.schema)==="object"?n.schema.properties?.[e.activeSection]:void 0,d=e.activeSection?Bp(e.activeSection,p):null,u=e.activeSection?Fp({key:e.activeSection,schema:p,uiHints:e.uiHints}):[],h=e.formMode==="form"&&!!e.activeSection&&u.length>0,v=e.activeSubsection===Oa,w=e.searchQuery||v?null:e.activeSubsection??u[0]?.key??null,$=e.formMode==="form"?Up(e.originalValue,e.formValue):[],k=e.formMode==="raw"&&e.raw!==e.originalRaw,T=e.formMode==="form"?$.length>0:k,M=!!e.formValue&&!e.loading&&!!n.schema,P=e.connected&&!e.saving&&T&&(e.formMode==="raw"?!0:M),L=e.connected&&!e.applying&&!e.updating&&T&&(e.formMode==="raw"?!0:M),C=e.connected&&!e.applying&&!e.updating;return r` -
    - - - - -
    - -
    -
    - ${T?r` - ${e.formMode==="raw"?"Unsaved changes":`${$.length} unsaved change${$.length!==1?"s":""}`} - `:r` - No changes - `} -
    -
    - - - - -
    -
    - - - ${T&&e.formMode==="form"?r` -
    - - View ${$.length} pending change${$.length!==1?"s":""} - - - - -
    - ${$.map(E=>r` -
    -
    ${E.path}
    -
    - ${Ba(E.from)} - - ${Ba(E.to)} -
    -
    - `)} -
    -
    - `:g} - - ${d&&e.formMode==="form"?r` -
    -
    ${Da(e.activeSection??"")}
    -
    -
    ${d.label}
    - ${d.description?r`
    ${d.description}
    `:g} -
    -
    - `:g} - - ${h?r` -
    - - ${u.map(E=>r` - - `)} -
    - `:g} - - -
    - ${e.formMode==="form"?r` - ${e.schemaLoading?r`
    -
    - Loading schema… -
    `:Pp({schema:n.schema,uiHints:e.uiHints,value:e.formValue,disabled:e.loading||!e.formValue,unsupportedPaths:n.unsupportedPaths,onPatch:e.onFormPatch,searchQuery:e.searchQuery,activeSection:e.activeSection,activeSubsection:w})} - ${s?r`
    - Form view can't safely edit some fields. - Use Raw to avoid losing config entries. -
    `:g} - `:r` - - `} -
    - - ${e.issues.length>0?r`
    -
    ${JSON.stringify(e.issues,null,2)}
    -
    `:g} -
    -
    - `}function Hp(e){if(!e&&e!==0)return"n/a";const t=Math.round(e/1e3);if(t<60)return`${t}s`;const n=Math.round(t/60);return n<60?`${n}m`:`${Math.round(n/60)}h`}function zp(e,t){const n=t.snapshot,s=n?.channels;if(!n||!s)return!1;const i=s[e],a=typeof i?.configured=="boolean"&&i.configured,o=typeof i?.running=="boolean"&&i.running,c=typeof i?.connected=="boolean"&&i.connected,p=(n.channelAccounts?.[e]??[]).some(d=>d.configured||d.running||d.connected);return a||o||c||p}function jp(e,t){return t?.[e]?.length??0}function fr(e,t){const n=jp(e,t);return n<2?g:r``}function qp(e,t){let n=e;for(const s of t){if(!n)return null;const i=ue(n);if(i==="object"){const a=n.properties??{};if(typeof s=="string"&&a[s]){n=a[s];continue}const o=n.additionalProperties;if(typeof s=="string"&&o&&typeof o=="object"){n=o;continue}return null}if(i==="array"){if(typeof s!="number")return null;n=(Array.isArray(n.items)?n.items[0]:n.items)??null;continue}return null}return n}function Vp(e,t){const s=(e.channels??{})[t],i=e[t];return(s&&typeof s=="object"?s:null)??(i&&typeof i=="object"?i:null)??{}}function Wp(e){const t=pr(e.schema),n=t.schema;if(!n)return r`
    Schema unavailable. Use Raw.
    `;const s=qp(n,["channels",e.channelId]);if(!s)return r`
    Channel config schema unavailable.
    `;const i=e.configValue??{},a=Vp(i,e.channelId);return r` -
    - ${ye({schema:s,value:a,path:["channels",e.channelId],hints:e.uiHints,unsupported:new Set(t.unsupportedPaths),disabled:e.disabled,showLabel:!1,onPatch:e.onPatch})} -
    - `}function $e(e){const{channelId:t,props:n}=e,s=n.configSaving||n.configSchemaLoading;return r` -
    - ${n.configSchemaLoading?r`
    Loading config schema…
    `:Wp({channelId:t,configValue:n.configForm,schema:n.configSchema,uiHints:n.configUiHints,disabled:s,onPatch:n.onConfigPatch})} -
    - - -
    -
    - `}function Gp(e){const{props:t,discord:n,accountCountLabel:s}=e;return r` -
    -
    Discord
    -
    Bot status and channel configuration.
    - ${s} - -
    -
    - Configured - ${n?.configured?"Yes":"No"} -
    -
    - Running - ${n?.running?"Yes":"No"} -
    -
    - Last start - ${n?.lastStartAt?O(n.lastStartAt):"n/a"} -
    -
    - Last probe - ${n?.lastProbeAt?O(n.lastProbeAt):"n/a"} -
    -
    - - ${n?.lastError?r`
    - ${n.lastError} -
    `:g} - - ${n?.probe?r`
    - Probe ${n.probe.ok?"ok":"failed"} · - ${n.probe.status??""} ${n.probe.error??""} -
    `:g} - - ${$e({channelId:"discord",props:t})} - -
    - -
    -
    - `}function Yp(e){const{props:t,googleChat:n,accountCountLabel:s}=e;return r` -
    -
    Google Chat
    -
    Chat API webhook status and channel configuration.
    - ${s} - -
    -
    - Configured - ${n?n.configured?"Yes":"No":"n/a"} -
    -
    - Running - ${n?n.running?"Yes":"No":"n/a"} -
    -
    - Credential - ${n?.credentialSource??"n/a"} -
    -
    - Audience - - ${n?.audienceType?`${n.audienceType}${n.audience?` · ${n.audience}`:""}`:"n/a"} - -
    -
    - Last start - ${n?.lastStartAt?O(n.lastStartAt):"n/a"} -
    -
    - Last probe - ${n?.lastProbeAt?O(n.lastProbeAt):"n/a"} -
    -
    - - ${n?.lastError?r`
    - ${n.lastError} -
    `:g} - - ${n?.probe?r`
    - Probe ${n.probe.ok?"ok":"failed"} · - ${n.probe.status??""} ${n.probe.error??""} -
    `:g} - - ${$e({channelId:"googlechat",props:t})} - -
    - -
    -
    - `}function Qp(e){const{props:t,imessage:n,accountCountLabel:s}=e;return r` -
    -
    iMessage
    -
    macOS bridge status and channel configuration.
    - ${s} - -
    -
    - Configured - ${n?.configured?"Yes":"No"} -
    -
    - Running - ${n?.running?"Yes":"No"} -
    -
    - Last start - ${n?.lastStartAt?O(n.lastStartAt):"n/a"} -
    -
    - Last probe - ${n?.lastProbeAt?O(n.lastProbeAt):"n/a"} -
    -
    - - ${n?.lastError?r`
    - ${n.lastError} -
    `:g} - - ${n?.probe?r`
    - Probe ${n.probe.ok?"ok":"failed"} · - ${n.probe.error??""} -
    `:g} - - ${$e({channelId:"imessage",props:t})} - -
    - -
    -
    - `}function Zp(e){const{values:t,original:n}=e;return t.name!==n.name||t.displayName!==n.displayName||t.about!==n.about||t.picture!==n.picture||t.banner!==n.banner||t.website!==n.website||t.nip05!==n.nip05||t.lud16!==n.lud16}function Jp(e){const{state:t,callbacks:n,accountId:s}=e,i=Zp(t),a=(c,l,p={})=>{const{type:d="text",placeholder:u,maxLength:h,help:v}=p,w=t.values[c]??"",$=t.fieldErrors[c],k=`nostr-profile-${c}`;return d==="textarea"?r` -
    - - - ${v?r`
    ${v}
    `:g} - ${$?r`
    ${$}
    `:g} -
    - `:r` -
    - - {const M=T.target;n.onFieldChange(c,M.value)}} - ?disabled=${t.saving} - /> - ${v?r`
    ${v}
    `:g} - ${$?r`
    ${$}
    `:g} -
    - `},o=()=>{const c=t.values.picture;return c?r` -
    - Profile picture preview{const p=l.target;p.style.display="none"}} - @load=${l=>{const p=l.target;p.style.display="block"}} - /> -
    - `:g};return r` -
    -
    -
    Edit Profile
    -
    Account: ${s}
    -
    - - ${t.error?r`
    ${t.error}
    `:g} - - ${t.success?r`
    ${t.success}
    `:g} - - ${o()} - - ${a("name","Username",{placeholder:"satoshi",maxLength:256,help:"Short username (e.g., satoshi)"})} - - ${a("displayName","Display Name",{placeholder:"Satoshi Nakamoto",maxLength:256,help:"Your full display name"})} - - ${a("about","Bio",{type:"textarea",placeholder:"Tell people about yourself...",maxLength:2e3,help:"A brief bio or description"})} - - ${a("picture","Avatar URL",{type:"url",placeholder:"https://example.com/avatar.jpg",help:"HTTPS URL to your profile picture"})} - - ${t.showAdvanced?r` -
    -
    Advanced
    - - ${a("banner","Banner URL",{type:"url",placeholder:"https://example.com/banner.jpg",help:"HTTPS URL to a banner image"})} - - ${a("website","Website",{type:"url",placeholder:"https://example.com",help:"Your personal website"})} - - ${a("nip05","NIP-05 Identifier",{placeholder:"you@example.com",help:"Verifiable identifier (e.g., you@domain.com)"})} - - ${a("lud16","Lightning Address",{placeholder:"you@getalby.com",help:"Lightning address for tips (LUD-16)"})} -
    - `:g} - -
    - - - - - - - -
    - - ${i?r`
    - You have unsaved changes -
    `:g} -
    - `}function Xp(e){const t={name:e?.name??"",displayName:e?.displayName??"",about:e?.about??"",picture:e?.picture??"",banner:e?.banner??"",website:e?.website??"",nip05:e?.nip05??"",lud16:e?.lud16??""};return{values:t,original:{...t},saving:!1,importing:!1,error:null,success:null,fieldErrors:{},showAdvanced:!!(e?.banner||e?.website||e?.nip05||e?.lud16)}}function Fa(e){return e?e.length<=20?e:`${e.slice(0,8)}...${e.slice(-8)}`:"n/a"}function ef(e){const{props:t,nostr:n,nostrAccounts:s,accountCountLabel:i,profileFormState:a,profileFormCallbacks:o,onEditProfile:c}=e,l=s[0],p=n?.configured??l?.configured??!1,d=n?.running??l?.running??!1,u=n?.publicKey??l?.publicKey,h=n?.lastStartAt??l?.lastStartAt??null,v=n?.lastError??l?.lastError??null,w=s.length>1,$=a!=null,k=M=>{const P=M.publicKey,L=M.profile,C=L?.displayName??L?.name??M.name??M.accountId;return r` - - `},T=()=>{if($&&o)return Jp({state:a,callbacks:o,accountId:s[0]?.accountId??"default"});const M=l?.profile??n?.profile,{name:P,displayName:L,about:C,picture:E,nip05:pe}=M??{},yn=P||L||C||E||pe;return r` -
    -
    -
    Profile
    - ${p?r` - - `:g} -
    - ${yn?r` -
    - ${E?r` -
    - Profile picture{wn.target.style.display="none"}} - /> -
    - `:g} - ${P?r`
    Name${P}
    `:g} - ${L?r`
    Display Name${L}
    `:g} - ${C?r`
    About${C}
    `:g} - ${pe?r`
    NIP-05${pe}
    `:g} -
    - `:r` -
    - No profile set. Click "Edit Profile" to add your name, bio, and avatar. -
    - `} -
    - `};return r` -
    -
    Nostr
    -
    Decentralized DMs via Nostr relays (NIP-04).
    - ${i} - - ${w?r` - - `:r` -
    -
    - Configured - ${p?"Yes":"No"} -
    -
    - Running - ${d?"Yes":"No"} -
    -
    - Public Key - ${Fa(u)} -
    -
    - Last start - ${h?O(h):"n/a"} -
    -
    - `} - - ${v?r`
    ${v}
    `:g} - - ${T()} - - ${$e({channelId:"nostr",props:t})} - -
    - -
    -
    - `}function tf(e){const{props:t,signal:n,accountCountLabel:s}=e;return r` -
    -
    Signal
    -
    signal-cli status and channel configuration.
    - ${s} - -
    -
    - Configured - ${n?.configured?"Yes":"No"} -
    -
    - Running - ${n?.running?"Yes":"No"} -
    -
    - Base URL - ${n?.baseUrl??"n/a"} -
    -
    - Last start - ${n?.lastStartAt?O(n.lastStartAt):"n/a"} -
    -
    - Last probe - ${n?.lastProbeAt?O(n.lastProbeAt):"n/a"} -
    -
    - - ${n?.lastError?r`
    - ${n.lastError} -
    `:g} - - ${n?.probe?r`
    - Probe ${n.probe.ok?"ok":"failed"} · - ${n.probe.status??""} ${n.probe.error??""} -
    `:g} - - ${$e({channelId:"signal",props:t})} - -
    - -
    -
    - `}function nf(e){const{props:t,slack:n,accountCountLabel:s}=e;return r` -
    -
    Slack
    -
    Socket mode status and channel configuration.
    - ${s} - -
    -
    - Configured - ${n?.configured?"Yes":"No"} -
    -
    - Running - ${n?.running?"Yes":"No"} -
    -
    - Last start - ${n?.lastStartAt?O(n.lastStartAt):"n/a"} -
    -
    - Last probe - ${n?.lastProbeAt?O(n.lastProbeAt):"n/a"} -
    -
    - - ${n?.lastError?r`
    - ${n.lastError} -
    `:g} - - ${n?.probe?r`
    - Probe ${n.probe.ok?"ok":"failed"} · - ${n.probe.status??""} ${n.probe.error??""} -
    `:g} - - ${$e({channelId:"slack",props:t})} - -
    - -
    -
    - `}function sf(e){const{props:t,telegram:n,telegramAccounts:s,accountCountLabel:i}=e,a=s.length>1,o=c=>{const p=c.probe?.bot?.username,d=c.name||c.accountId;return r` - - `};return r` -
    -
    Telegram
    -
    Bot status and channel configuration.
    - ${i} - - ${a?r` - - `:r` -
    -
    - Configured - ${n?.configured?"Yes":"No"} -
    -
    - Running - ${n?.running?"Yes":"No"} -
    -
    - Mode - ${n?.mode??"n/a"} -
    -
    - Last start - ${n?.lastStartAt?O(n.lastStartAt):"n/a"} -
    -
    - Last probe - ${n?.lastProbeAt?O(n.lastProbeAt):"n/a"} -
    -
    - `} - - ${n?.lastError?r`
    - ${n.lastError} -
    `:g} - - ${n?.probe?r`
    - Probe ${n.probe.ok?"ok":"failed"} · - ${n.probe.status??""} ${n.probe.error??""} -
    `:g} - - ${$e({channelId:"telegram",props:t})} - -
    - -
    -
    - `}function af(e){const{props:t,whatsapp:n,accountCountLabel:s}=e;return r` -
    -
    WhatsApp
    -
    Link WhatsApp Web and monitor connection health.
    - ${s} - -
    -
    - Configured - ${n?.configured?"Yes":"No"} -
    -
    - Linked - ${n?.linked?"Yes":"No"} -
    -
    - Running - ${n?.running?"Yes":"No"} -
    -
    - Connected - ${n?.connected?"Yes":"No"} -
    -
    - Last connect - - ${n?.lastConnectedAt?O(n.lastConnectedAt):"n/a"} - -
    -
    - Last message - - ${n?.lastMessageAt?O(n.lastMessageAt):"n/a"} - -
    -
    - Auth age - - ${n?.authAgeMs!=null?Hp(n.authAgeMs):"n/a"} - -
    -
    - - ${n?.lastError?r`
    - ${n.lastError} -
    `:g} - - ${t.whatsappMessage?r`
    - ${t.whatsappMessage} -
    `:g} - - ${t.whatsappQrDataUrl?r`
    - WhatsApp QR -
    `:g} - -
    - - - - - -
    - - ${$e({channelId:"whatsapp",props:t})} -
    - `}function of(e){const t=e.snapshot?.channels,n=t?.whatsapp??void 0,s=t?.telegram??void 0,i=t?.discord??null;t?.googlechat;const a=t?.slack??null,o=t?.signal??null,c=t?.imessage??null,l=t?.nostr??null,d=rf(e.snapshot).map((u,h)=>({key:u,enabled:zp(u,e),order:h})).sort((u,h)=>u.enabled!==h.enabled?u.enabled?-1:1:u.order-h.order);return r` -
    - ${d.map(u=>lf(u.key,e,{whatsapp:n,telegram:s,discord:i,slack:a,signal:o,imessage:c,nostr:l,channelAccounts:e.snapshot?.channelAccounts??null}))} -
    - -
    -
    -
    -
    Channel health
    -
    Channel status snapshots from the gateway.
    -
    -
    ${e.lastSuccessAt?O(e.lastSuccessAt):"n/a"}
    -
    - ${e.lastError?r`
    - ${e.lastError} -
    `:g} -
    -${e.snapshot?JSON.stringify(e.snapshot,null,2):"No snapshot yet."}
    -      
    -
    - `}function rf(e){return e?.channelMeta?.length?e.channelMeta.map(t=>t.id):e?.channelOrder?.length?e.channelOrder:["whatsapp","telegram","discord","googlechat","slack","signal","imessage","nostr"]}function lf(e,t,n){const s=fr(e,n.channelAccounts);switch(e){case"whatsapp":return af({props:t,whatsapp:n.whatsapp,accountCountLabel:s});case"telegram":return sf({props:t,telegram:n.telegram,telegramAccounts:n.channelAccounts?.telegram??[],accountCountLabel:s});case"discord":return Gp({props:t,discord:n.discord,accountCountLabel:s});case"googlechat":return Yp({props:t,accountCountLabel:s});case"slack":return nf({props:t,slack:n.slack,accountCountLabel:s});case"signal":return tf({props:t,signal:n.signal,accountCountLabel:s});case"imessage":return Qp({props:t,imessage:n.imessage,accountCountLabel:s});case"nostr":{const i=n.channelAccounts?.nostr??[],a=i[0],o=a?.accountId??"default",c=a?.profile??null,l=t.nostrProfileAccountId===o?t.nostrProfileFormState:null,p=l?{onFieldChange:t.onNostrProfileFieldChange,onSave:t.onNostrProfileSave,onImport:t.onNostrProfileImport,onCancel:t.onNostrProfileCancel,onToggleAdvanced:t.onNostrProfileToggleAdvanced}:null;return ef({props:t,nostr:n.nostr,nostrAccounts:i,accountCountLabel:s,profileFormState:l,profileFormCallbacks:p,onEditProfile:()=>t.onNostrProfileEdit(o,c)})}default:return cf(e,t,n.channelAccounts??{})}}function cf(e,t,n){const s=uf(t.snapshot,e),i=t.snapshot?.channels?.[e],a=typeof i?.configured=="boolean"?i.configured:void 0,o=typeof i?.running=="boolean"?i.running:void 0,c=typeof i?.connected=="boolean"?i.connected:void 0,l=typeof i?.lastError=="string"?i.lastError:void 0,p=n[e]??[],d=fr(e,n);return r` -
    -
    ${s}
    -
    Channel status and configuration.
    - ${d} - - ${p.length>0?r` - - `:r` -
    -
    - Configured - ${a==null?"n/a":a?"Yes":"No"} -
    -
    - Running - ${o==null?"n/a":o?"Yes":"No"} -
    -
    - Connected - ${c==null?"n/a":c?"Yes":"No"} -
    -
    - `} - - ${l?r`
    - ${l} -
    `:g} - - ${$e({channelId:e,props:t})} -
    - `}function df(e){return e?.channelMeta?.length?Object.fromEntries(e.channelMeta.map(t=>[t.id,t])):{}}function uf(e,t){return df(e)[t]?.label??e?.channelLabels?.[t]??t}const pf=600*1e3;function hr(e){return e.lastInboundAt?Date.now()-e.lastInboundAt
    - `:r` -
    - Auth failed. Re-copy a tokenized URL with - clawdbot dashboard --no-open, or update the token, - then click Connect. - -
    - `})(),a=(()=>{if(e.connected||!e.lastError||(typeof window<"u"?window.isSecureContext:!0)!==!1)return null;const c=e.lastError.toLowerCase();return!c.includes("secure context")&&!c.includes("device identity required")?null:r` -
    - This page is HTTP, so the browser blocks device identity. Use HTTPS (Tailscale Serve) or - open http://127.0.0.1:18789 on the gateway host. -
    - If you must stay on HTTP, set - gateway.controlUi.allowInsecureAuth: true (token-only). -
    - -
    - `})();return r` -
    -
    -
    Gateway Access
    -
    Where the dashboard connects and how it authenticates.
    -
    - - - - -
    -
    - - - Click Connect to apply connection changes. -
    -
    - -
    -
    Snapshot
    -
    Latest gateway handshake information.
    -
    -
    -
    Status
    -
    - ${e.connected?"Connected":"Disconnected"} -
    -
    -
    -
    Uptime
    -
    ${n}
    -
    -
    -
    Tick Interval
    -
    ${s}
    -
    -
    -
    Last Channels Refresh
    -
    - ${e.lastChannelsRefresh?O(e.lastChannelsRefresh):"n/a"} -
    -
    -
    - ${e.lastError?r`
    -
    ${e.lastError}
    - ${i??""} - ${a??""} -
    `:r`
    - Use Channels to link WhatsApp, Telegram, Discord, Signal, or iMessage. -
    `} -
    -
    - -
    -
    -
    Instances
    -
    ${e.presenceCount}
    -
    Presence beacons in the last 5 minutes.
    -
    -
    -
    Sessions
    -
    ${e.sessionsCount??"n/a"}
    -
    Recent session keys tracked by the gateway.
    -
    -
    -
    Cron
    -
    - ${e.cronEnabled==null?"n/a":e.cronEnabled?"Enabled":"Disabled"} -
    -
    Next wake ${gr(e.cronNext)}
    -
    -
    - -
    -
    Notes
    -
    Quick reminders for remote control setups.
    -
    -
    -
    Tailscale serve
    -
    - Prefer serve mode to keep the gateway on loopback with tailnet auth. -
    -
    -
    -
    Session hygiene
    -
    Use /new or sessions.patch to reset context.
    -
    -
    -
    Cron reminders
    -
    Use isolated sessions for recurring runs.
    -
    -
    -
    - `}const rh=["","off","minimal","low","medium","high"],lh=["","off","on"],ch=[{value:"",label:"inherit"},{value:"off",label:"off (explicit)"},{value:"on",label:"on"}],dh=["","off","on","stream"];function uh(e){if(!e)return"";const t=e.trim().toLowerCase();return t==="z.ai"||t==="z-ai"?"zai":t}function vr(e){return uh(e)==="zai"}function ph(e){return vr(e)?lh:rh}function fh(e,t){return!t||!e||e==="off"?e:"on"}function hh(e,t){return e?t&&e==="on"?"low":e:null}function gh(e){const t=e.result?.sessions??[];return r` -
    -
    -
    -
    Sessions
    -
    Active session keys and per-session overrides.
    -
    - -
    - -
    - - - - -
    - - ${e.error?r`
    ${e.error}
    `:g} - -
    - ${e.result?`Store: ${e.result.path}`:""} -
    - -
    -
    -
    Key
    -
    Label
    -
    Kind
    -
    Updated
    -
    Tokens
    -
    Thinking
    -
    Verbose
    -
    Reasoning
    -
    Actions
    -
    - ${t.length===0?r`
    No sessions found.
    `:t.map(n=>vh(n,e.basePath,e.onPatch,e.onDelete,e.loading))} -
    -
    - `}function vh(e,t,n,s,i){const a=e.updatedAt?O(e.updatedAt):"n/a",o=e.thinkingLevel??"",c=vr(e.modelProvider),l=fh(o,c),p=ph(e.modelProvider),d=e.verboseLevel??"",u=e.reasoningLevel??"",h=e.displayName??e.key,v=e.kind!=="global",w=v?`${Rs("chat",t)}?session=${encodeURIComponent(e.key)}`:null;return r` -
    -
    ${v?r`${h}`:h}
    -
    - {const k=$.target.value.trim();n(e.key,{label:k||null})}} - /> -
    -
    ${e.kind}
    -
    ${a}
    -
    ${bf(e)}
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - `}function mh(e){const t=Math.max(0,e),n=Math.floor(t/1e3);if(n<60)return`${n}s`;const s=Math.floor(n/60);return s<60?`${s}m`:`${Math.floor(s/60)}h`}function Ie(e,t){return t?r`
    ${e}${t}
    `:g}function bh(e){const t=e.execApprovalQueue[0];if(!t)return g;const n=t.request,s=t.expiresAtMs-Date.now(),i=s>0?`expires in ${mh(s)}`:"expired",a=e.execApprovalQueue.length;return r` - - `}function yh(e){const t=e.report?.skills??[],n=e.filter.trim().toLowerCase(),s=n?t.filter(i=>[i.name,i.description,i.source].join(" ").toLowerCase().includes(n)):t;return r` -
    -
    -
    -
    Skills
    -
    Bundled, managed, and workspace skills.
    -
    - -
    - -
    - -
    ${s.length} shown
    -
    - - ${e.error?r`
    ${e.error}
    `:g} - - ${s.length===0?r`
    No skills found.
    `:r` -
    - ${s.map(i=>wh(i,e))} -
    - `} -
    - `}function wh(e,t){const n=t.busyKey===e.skillKey,s=t.edits[e.skillKey]??"",i=t.messages[e.skillKey]??null,a=e.install.length>0&&e.missing.bins.length>0,o=[...e.missing.bins.map(l=>`bin:${l}`),...e.missing.env.map(l=>`env:${l}`),...e.missing.config.map(l=>`config:${l}`),...e.missing.os.map(l=>`os:${l}`)],c=[];return e.disabled&&c.push("disabled"),e.blockedByAllowlist&&c.push("blocked by allowlist"),r` -
    -
    -
    - ${e.emoji?`${e.emoji} `:""}${e.name} -
    -
    ${as(e.description,140)}
    -
    - ${e.source} - - ${e.eligible?"eligible":"blocked"} - - ${e.disabled?r`disabled`:g} -
    - ${o.length>0?r` -
    - Missing: ${o.join(", ")} -
    - `:g} - ${c.length>0?r` -
    - Reason: ${c.join(", ")} -
    - `:g} -
    -
    -
    - - ${a?r``:g} -
    - ${i?r`
    - ${i.message} -
    `:g} - ${e.primaryEnv?r` -
    - API key - t.onEdit(e.skillKey,l.target.value)} - /> -
    - - `:g} -
    -
    - `}function $h(e,t){const n=Rs(t,e.basePath);return r` - {s.defaultPrevented||s.button!==0||s.metaKey||s.ctrlKey||s.shiftKey||s.altKey||(s.preventDefault(),e.setTab(t))}} - title=${ss(t)} - > - - ${ss(t)} - - `}function xh(e){const t=kh(e.sessionKey,e.sessionsResult),n=e.onboarding,s=e.onboarding,i=e.onboarding?!1:e.settings.chatShowThinking,a=e.onboarding?!0:e.settings.chatFocusMode,o=r``,c=r``;return r` -
    - - - | - - -
    - `}function kh(e,t){const n=new Set,s=[],i=t?.sessions?.find(a=>a.key===e);if(n.add(e),s.push({key:e,displayName:i?.displayName}),t?.sessions)for(const a of t.sessions)n.has(a.key)||(n.add(a.key),s.push({key:a.key,displayName:a.displayName}));return s}const Ah=["system","light","dark"];function Sh(e){const t=Math.max(0,Ah.indexOf(e.theme)),n=s=>i=>{const o={element:i.currentTarget};(i.clientX||i.clientY)&&(o.pointerClientX=i.clientX,o.pointerClientY=i.clientY),e.setTheme(s,o)};return r` -
    -
    - - - - -
    -
    - `}function _h(){return r` - - `}function Th(){return r` - - `}function Ch(){return r` - - `}const Eh=/^data:/i,Lh=/^https?:\/\//i;function Mh(e){const t=e.agentsList?.agents??[],s=eo(e.sessionKey)?.agentId??e.agentsList?.defaultId??"main",a=t.find(c=>c.id===s)?.identity,o=a?.avatarUrl??a?.avatar;if(o)return Eh.test(o)||Lh.test(o)?o:a?.avatarUrl}function Ih(e){const t=e.presenceEntries.length,n=e.sessionsResult?.count??null,s=e.cronStatus?.nextWakeAtMs??null,i=e.connected?null:"Disconnected from gateway.",a=e.tab==="chat",o=a&&(e.settings.chatFocusMode||e.onboarding),c=e.onboarding?!1:e.settings.chatShowThinking,l=Mh(e),p=e.chatAvatarUrl??l??null;return r` -
    -
    -
    - -
    - -
    -
    CLAWDBOT
    -
    Gateway Dashboard
    -
    -
    -
    -
    -
    - - Health - ${e.connected?"OK":"Offline"} -
    - ${Sh(e)} -
    -
    - -
    -
    -
    -
    ${ss(e.tab)}
    -
    ${ml(e.tab)}
    -
    -
    - ${e.lastError?r`
    ${e.lastError}
    `:g} - ${a?xh(e):g} -
    -
    - - ${e.tab==="overview"?oh({connected:e.connected,hello:e.hello,settings:e.settings,password:e.password,lastError:e.lastError,presenceCount:t,sessionsCount:n,cronEnabled:e.cronStatus?.enabled??null,cronNext:s,lastChannelsRefresh:e.channelsLastSuccess,onSettingsChange:d=>e.applySettings(d),onPasswordChange:d=>e.password=d,onSessionKeyChange:d=>{e.sessionKey=d,e.chatMessage="",e.resetToolStream(),e.applySettings({...e.settings,sessionKey:d,lastActiveSessionKey:d}),e.loadAssistantIdentity()},onConnect:()=>e.connect(),onRefresh:()=>e.loadOverview()}):g} - - ${e.tab==="channels"?of({connected:e.connected,loading:e.channelsLoading,snapshot:e.channelsSnapshot,lastError:e.channelsError,lastSuccessAt:e.channelsLastSuccess,whatsappMessage:e.whatsappLoginMessage,whatsappQrDataUrl:e.whatsappLoginQrDataUrl,whatsappConnected:e.whatsappLoginConnected,whatsappBusy:e.whatsappBusy,configSchema:e.configSchema,configSchemaLoading:e.configSchemaLoading,configForm:e.configForm,configUiHints:e.configUiHints,configSaving:e.configSaving,configFormDirty:e.configFormDirty,nostrProfileFormState:e.nostrProfileFormState,nostrProfileAccountId:e.nostrProfileAccountId,onRefresh:d=>oe(e,d),onWhatsAppStart:d=>e.handleWhatsAppStart(d),onWhatsAppWait:()=>e.handleWhatsAppWait(),onWhatsAppLogout:()=>e.handleWhatsAppLogout(),onConfigPatch:(d,u)=>Bt(e,d,u),onConfigSave:()=>e.handleChannelConfigSave(),onConfigReload:()=>e.handleChannelConfigReload(),onNostrProfileEdit:(d,u)=>e.handleNostrProfileEdit(d,u),onNostrProfileCancel:()=>e.handleNostrProfileCancel(),onNostrProfileFieldChange:(d,u)=>e.handleNostrProfileFieldChange(d,u),onNostrProfileSave:()=>e.handleNostrProfileSave(),onNostrProfileImport:()=>e.handleNostrProfileImport(),onNostrProfileToggleAdvanced:()=>e.handleNostrProfileToggleAdvanced()}):g} - - ${e.tab==="instances"?Lf({loading:e.presenceLoading,entries:e.presenceEntries,lastError:e.presenceError,statusMessage:e.presenceStatus,onRefresh:()=>js(e)}):g} - - ${e.tab==="sessions"?gh({loading:e.sessionsLoading,result:e.sessionsResult,error:e.sessionsError,activeMinutes:e.sessionsFilterActive,limit:e.sessionsFilterLimit,includeGlobal:e.sessionsIncludeGlobal,includeUnknown:e.sessionsIncludeUnknown,basePath:e.basePath,onFiltersChange:d=>{e.sessionsFilterActive=d.activeMinutes,e.sessionsFilterLimit=d.limit,e.sessionsIncludeGlobal=d.includeGlobal,e.sessionsIncludeUnknown=d.includeUnknown},onRefresh:()=>st(e),onPatch:(d,u)=>Ml(e,d,u),onDelete:d=>Il(e,d)}):g} - - ${e.tab==="cron"?Sf({loading:e.cronLoading,status:e.cronStatus,jobs:e.cronJobs,error:e.cronError,busy:e.cronBusy,form:e.cronForm,channels:e.channelsSnapshot?.channelMeta?.length?e.channelsSnapshot.channelMeta.map(d=>d.id):e.channelsSnapshot?.channelOrder??[],channelLabels:e.channelsSnapshot?.channelLabels??{},channelMeta:e.channelsSnapshot?.channelMeta??[],runsJobId:e.cronRunsJobId,runs:e.cronRuns,onFormChange:d=>e.cronForm={...e.cronForm,...d},onRefresh:()=>e.loadCron(),onAdd:()=>ec(e),onToggle:(d,u)=>tc(e,d,u),onRun:d=>nc(e,d),onRemove:d=>sc(e,d),onLoadRuns:d=>po(e,d)}):g} - - ${e.tab==="skills"?yh({loading:e.skillsLoading,report:e.skillsReport,error:e.skillsError,filter:e.skillsFilter,edits:e.skillEdits,messages:e.skillMessages,busyKey:e.skillsBusyKey,onFilterChange:d=>e.skillsFilter=d,onRefresh:()=>Ct(e,{clearMessages:!0}),onToggle:(d,u)=>Zc(e,d,u),onEdit:(d,u)=>Qc(e,d,u),onSaveKey:d=>Jc(e,d),onInstall:(d,u,h)=>Xc(e,d,u,h)}):g} - - ${e.tab==="nodes"?Nf({loading:e.nodesLoading,nodes:e.nodes,devicesLoading:e.devicesLoading,devicesError:e.devicesError,devicesList:e.devicesList,configForm:e.configForm??e.configSnapshot?.config,configLoading:e.configLoading,configSaving:e.configSaving,configDirty:e.configFormDirty,configFormMode:e.configFormMode,execApprovalsLoading:e.execApprovalsLoading,execApprovalsSaving:e.execApprovalsSaving,execApprovalsDirty:e.execApprovalsDirty,execApprovalsSnapshot:e.execApprovalsSnapshot,execApprovalsForm:e.execApprovalsForm,execApprovalsSelectedAgent:e.execApprovalsSelectedAgent,execApprovalsTarget:e.execApprovalsTarget,execApprovalsTargetNodeId:e.execApprovalsTargetNodeId,onRefresh:()=>pn(e),onDevicesRefresh:()=>Te(e),onDeviceApprove:d=>Uc(e,d),onDeviceReject:d=>Kc(e,d),onDeviceRotate:(d,u,h)=>Hc(e,{deviceId:d,role:u,scopes:h}),onDeviceRevoke:(d,u)=>zc(e,{deviceId:d,role:u}),onLoadConfig:()=>be(e),onLoadExecApprovals:()=>{const d=e.execApprovalsTarget==="node"&&e.execApprovalsTargetNodeId?{kind:"node",nodeId:e.execApprovalsTargetNodeId}:{kind:"gateway"};return zs(e,d)},onBindDefault:d=>{d?Bt(e,["tools","exec","node"],d):Zi(e,["tools","exec","node"])},onBindAgent:(d,u)=>{const h=["agents","list",d,"tools","exec","node"];u?Bt(e,h,u):Zi(e,h)},onSaveBindings:()=>ls(e),onExecApprovalsTargetChange:(d,u)=>{e.execApprovalsTarget=d,e.execApprovalsTargetNodeId=u,e.execApprovalsSnapshot=null,e.execApprovalsForm=null,e.execApprovalsDirty=!1,e.execApprovalsSelectedAgent=null},onExecApprovalsSelectAgent:d=>{e.execApprovalsSelectedAgent=d},onExecApprovalsPatch:(d,u)=>Gc(e,d,u),onExecApprovalsRemove:d=>Yc(e,d),onSaveExecApprovals:()=>{const d=e.execApprovalsTarget==="node"&&e.execApprovalsTargetNodeId?{kind:"node",nodeId:e.execApprovalsTargetNodeId}:{kind:"gateway"};return Wc(e,d)}}):g} - - ${e.tab==="chat"?kp({sessionKey:e.sessionKey,onSessionKeyChange:d=>{e.sessionKey=d,e.chatMessage="",e.chatStream=null,e.chatStreamStartedAt=null,e.chatRunId=null,e.chatQueue=[],e.resetToolStream(),e.resetChatScroll(),e.applySettings({...e.settings,sessionKey:d,lastActiveSessionKey:d}),e.loadAssistantIdentity(),Xe(e),fs(e)},thinkingLevel:e.chatThinkingLevel,showThinking:c,loading:e.chatLoading,sending:e.chatSending,compactionStatus:e.compactionStatus,assistantAvatarUrl:p,messages:e.chatMessages,toolMessages:e.chatToolMessages,stream:e.chatStream,streamStartedAt:e.chatStreamStartedAt,draft:e.chatMessage,queue:e.chatQueue,connected:e.connected,canSend:e.connected,disabledReason:i,error:e.lastError,sessions:e.sessionsResult,focusMode:o,onRefresh:()=>(e.resetToolStream(),Promise.all([Xe(e),fs(e)])),onToggleFocusMode:()=>{e.onboarding||e.applySettings({...e.settings,chatFocusMode:!e.settings.chatFocusMode})},onChatScroll:d=>e.handleChatScroll(d),onDraftChange:d=>e.chatMessage=d,onSend:()=>e.handleSendChat(),canAbort:!!e.chatRunId,onAbort:()=>{e.handleAbortChat()},onQueueRemove:d=>e.removeQueuedMessage(d),onNewSession:()=>e.handleSendChat("/new",{restoreDraft:!0}),sidebarOpen:e.sidebarOpen,sidebarContent:e.sidebarContent,sidebarError:e.sidebarError,splitRatio:e.splitRatio,onOpenSidebar:d=>e.handleOpenSidebar(d),onCloseSidebar:()=>e.handleCloseSidebar(),onSplitRatioChange:d=>e.handleSplitRatioChange(d),assistantName:e.assistantName,assistantAvatar:e.assistantAvatar}):g} - - ${e.tab==="config"?Kp({raw:e.configRaw,originalRaw:e.configRawOriginal,valid:e.configValid,issues:e.configIssues,loading:e.configLoading,saving:e.configSaving,applying:e.configApplying,updating:e.updateRunning,connected:e.connected,schema:e.configSchema,schemaLoading:e.configSchemaLoading,uiHints:e.configUiHints,formMode:e.configFormMode,formValue:e.configForm,originalValue:e.configFormOriginal,searchQuery:e.configSearchQuery,activeSection:e.configActiveSection,activeSubsection:e.configActiveSubsection,onRawChange:d=>{e.configRaw=d},onFormModeChange:d=>e.configFormMode=d,onFormPatch:(d,u)=>Bt(e,d,u),onSearchChange:d=>e.configSearchQuery=d,onSectionChange:d=>{e.configActiveSection=d,e.configActiveSubsection=null},onSubsectionChange:d=>e.configActiveSubsection=d,onReload:()=>be(e),onSave:()=>ls(e),onApply:()=>Ql(e),onUpdate:()=>Zl(e)}):g} - - ${e.tab==="debug"?Ef({loading:e.debugLoading,status:e.debugStatus,health:e.debugHealth,models:e.debugModels,heartbeat:e.debugHeartbeat,eventLog:e.eventLog,callMethod:e.debugCallMethod,callParams:e.debugCallParams,callResult:e.debugCallResult,callError:e.debugCallError,onCallMethodChange:d=>e.debugCallMethod=d,onCallParamsChange:d=>e.debugCallParams=d,onRefresh:()=>dn(e),onCall:()=>rc(e)}):g} - - ${e.tab==="logs"?Pf({loading:e.logsLoading,error:e.logsError,file:e.logsFile,entries:e.logsEntries,filterText:e.logsFilterText,levelFilters:e.logsLevelFilters,autoFollow:e.logsAutoFollow,truncated:e.logsTruncated,onFilterTextChange:d=>e.logsFilterText=d,onLevelToggle:(d,u)=>{e.logsLevelFilters={...e.logsLevelFilters,[d]:u}},onToggleAutoFollow:d=>e.logsAutoFollow=d,onRefresh:()=>Os(e,{reset:!0}),onExport:(d,u)=>e.exportLogs(d,u),onScroll:d=>e.handleLogsScroll(d)}):g} -
    - ${bh(e)} -
    - `}const Rh={trace:!0,debug:!0,info:!0,warn:!0,error:!0,fatal:!0},Ph={name:"",description:"",agentId:"",enabled:!0,scheduleKind:"every",scheduleAt:"",everyAmount:"30",everyUnit:"minutes",cronExpr:"0 7 * * *",cronTz:"",sessionTarget:"main",wakeMode:"next-heartbeat",payloadKind:"systemEvent",payloadText:"",deliver:!1,channel:"last",to:"",timeoutSeconds:"",postToMainPrefix:""};async function Nh(e){if(!(!e.client||!e.connected)&&!e.agentsLoading){e.agentsLoading=!0,e.agentsError=null;try{const t=await e.client.request("agents.list",{});t&&(e.agentsList=t)}catch(t){e.agentsError=String(t)}finally{e.agentsLoading=!1}}}const mr={WEBCHAT_UI:"webchat-ui",CONTROL_UI:"clawdbot-control-ui",WEBCHAT:"webchat",CLI:"cli",GATEWAY_CLIENT:"gateway-client",MACOS_APP:"clawdbot-macos",IOS_APP:"clawdbot-ios",ANDROID_APP:"clawdbot-android",NODE_HOST:"node-host",TEST:"test",FINGERPRINT:"fingerprint",PROBE:"clawdbot-probe"},za=mr,Ss={WEBCHAT:"webchat",CLI:"cli",UI:"ui",BACKEND:"backend",NODE:"node",PROBE:"probe",TEST:"test"};new Set(Object.values(mr));new Set(Object.values(Ss));function Oh(e){const t=e.version??(e.nonce?"v2":"v1"),n=e.scopes.join(","),s=e.token??"",i=[t,e.deviceId,e.clientId,e.clientMode,e.role,n,String(e.signedAtMs),s];return t==="v2"&&i.push(e.nonce??""),i.join("|")}const Dh=4008;class Bh{constructor(t){this.opts=t,this.ws=null,this.pending=new Map,this.closed=!1,this.lastSeq=null,this.connectNonce=null,this.connectSent=!1,this.connectTimer=null,this.backoffMs=800}start(){this.closed=!1,this.connect()}stop(){this.closed=!0,this.ws?.close(),this.ws=null,this.flushPending(new Error("gateway client stopped"))}get connected(){return this.ws?.readyState===WebSocket.OPEN}connect(){this.closed||(this.ws=new WebSocket(this.opts.url),this.ws.onopen=()=>this.queueConnect(),this.ws.onmessage=t=>this.handleMessage(String(t.data??"")),this.ws.onclose=t=>{const n=String(t.reason??"");this.ws=null,this.flushPending(new Error(`gateway closed (${t.code}): ${n}`)),this.opts.onClose?.({code:t.code,reason:n}),this.scheduleReconnect()},this.ws.onerror=()=>{})}scheduleReconnect(){if(this.closed)return;const t=this.backoffMs;this.backoffMs=Math.min(this.backoffMs*1.7,15e3),window.setTimeout(()=>this.connect(),t)}flushPending(t){for(const[,n]of this.pending)n.reject(t);this.pending.clear()}async sendConnect(){if(this.connectSent)return;this.connectSent=!0,this.connectTimer!==null&&(window.clearTimeout(this.connectTimer),this.connectTimer=null);const t=typeof crypto<"u"&&!!crypto.subtle,n=["operator.admin","operator.approvals","operator.pairing"],s="operator";let i=null,a=!1,o=this.opts.token;if(t){i=await Us();const d=Fc({deviceId:i.deviceId,role:s})?.token;o=d??this.opts.token,a=!!(d&&this.opts.token)}const c=o||this.opts.password?{token:o,password:this.opts.password}:void 0;let l;if(t&&i){const d=Date.now(),u=this.connectNonce??void 0,h=Oh({deviceId:i.deviceId,clientId:this.opts.clientName??za.CONTROL_UI,clientMode:this.opts.mode??Ss.WEBCHAT,role:s,scopes:n,signedAtMs:d,token:o??null,nonce:u}),v=await Dc(i.privateKey,h);l={id:i.deviceId,publicKey:i.publicKey,signature:v,signedAt:d,nonce:u}}const p={minProtocol:3,maxProtocol:3,client:{id:this.opts.clientName??za.CONTROL_UI,version:this.opts.clientVersion??"dev",platform:this.opts.platform??navigator.platform??"web",mode:this.opts.mode??Ss.WEBCHAT,instanceId:this.opts.instanceId},role:s,scopes:n,device:l,caps:[],auth:c,userAgent:navigator.userAgent,locale:navigator.language};this.request("connect",p).then(d=>{d?.auth?.deviceToken&&i&&Eo({deviceId:i.deviceId,role:d.auth.role??s,token:d.auth.deviceToken,scopes:d.auth.scopes??[]}),this.backoffMs=800,this.opts.onHello?.(d)}).catch(()=>{a&&i&&Lo({deviceId:i.deviceId,role:s}),this.ws?.close(Dh,"connect failed")})}handleMessage(t){let n;try{n=JSON.parse(t)}catch{return}const s=n;if(s.type==="event"){const i=n;if(i.event==="connect.challenge"){const o=i.payload,c=o&&typeof o.nonce=="string"?o.nonce:null;c&&(this.connectNonce=c,this.sendConnect());return}const a=typeof i.seq=="number"?i.seq:null;a!==null&&(this.lastSeq!==null&&a>this.lastSeq+1&&this.opts.onGap?.({expected:this.lastSeq+1,received:a}),this.lastSeq=a);try{this.opts.onEvent?.(i)}catch(o){console.error("[gateway] event handler error:",o)}return}if(s.type==="res"){const i=n,a=this.pending.get(i.id);if(!a)return;this.pending.delete(i.id),i.ok?a.resolve(i.payload):a.reject(new Error(i.error?.message??"request failed"));return}}request(t,n){if(!this.ws||this.ws.readyState!==WebSocket.OPEN)return Promise.reject(new Error("gateway not connected"));const s=Ps(),i={type:"req",id:s,method:t,params:n},a=new Promise((o,c)=>{this.pending.set(s,{resolve:l=>o(l),reject:c})});return this.ws.send(JSON.stringify(i)),a}queueConnect(){this.connectNonce=null,this.connectSent=!1,this.connectTimer!==null&&window.clearTimeout(this.connectTimer),this.connectTimer=window.setTimeout(()=>{this.sendConnect()},750)}}function _s(e){return typeof e=="object"&&e!==null}function Fh(e){if(!_s(e))return null;const t=typeof e.id=="string"?e.id.trim():"",n=e.request;if(!t||!_s(n))return null;const s=typeof n.command=="string"?n.command.trim():"";if(!s)return null;const i=typeof e.createdAtMs=="number"?e.createdAtMs:0,a=typeof e.expiresAtMs=="number"?e.expiresAtMs:0;return!i||!a?null:{id:t,request:{command:s,cwd:typeof n.cwd=="string"?n.cwd:null,host:typeof n.host=="string"?n.host:null,security:typeof n.security=="string"?n.security:null,ask:typeof n.ask=="string"?n.ask:null,agentId:typeof n.agentId=="string"?n.agentId:null,resolvedPath:typeof n.resolvedPath=="string"?n.resolvedPath:null,sessionKey:typeof n.sessionKey=="string"?n.sessionKey:null},createdAtMs:i,expiresAtMs:a}}function Uh(e){if(!_s(e))return null;const t=typeof e.id=="string"?e.id.trim():"";return t?{id:t,decision:typeof e.decision=="string"?e.decision:null,resolvedBy:typeof e.resolvedBy=="string"?e.resolvedBy:null,ts:typeof e.ts=="number"?e.ts:null}:null}function br(e){const t=Date.now();return e.filter(n=>n.expiresAtMs>t)}function Kh(e,t){const n=br(e).filter(s=>s.id!==t.id);return n.push(t),n}function ja(e,t){return br(e).filter(n=>n.id!==t)}async function yr(e,t){if(!e.client||!e.connected)return;const n=e.sessionKey.trim(),s=n?{sessionKey:n}:{};try{const i=await e.client.request("agent.identity.get",s);if(!i)return;const a=ns(i);e.assistantName=a.name,e.assistantAvatar=a.avatar,e.assistantAgentId=a.agentId??null}catch{}}function Xn(e,t){const n=(e??"").trim(),s=t.mainSessionKey?.trim();if(!s)return n;if(!n)return s;const i=t.mainKey?.trim()||"main",a=t.defaultAgentId?.trim();return n==="main"||n===i||a&&(n===`agent:${a}:main`||n===`agent:${a}:${i}`)?s:n}function Hh(e,t){if(!t?.mainSessionKey)return;const n=Xn(e.sessionKey,t),s=Xn(e.settings.sessionKey,t),i=Xn(e.settings.lastActiveSessionKey,t),a=n||s||e.sessionKey,o={...e.settings,sessionKey:s||a,lastActiveSessionKey:i||a},c=o.sessionKey!==e.settings.sessionKey||o.lastActiveSessionKey!==e.settings.lastActiveSessionKey;a!==e.sessionKey&&(e.sessionKey=a),c&&ke(e,o)}function wr(e){e.lastError=null,e.hello=null,e.connected=!1,e.execApprovalQueue=[],e.execApprovalError=null,e.client?.stop(),e.client=new Bh({url:e.settings.gatewayUrl,token:e.settings.token.trim()?e.settings.token:void 0,password:e.password.trim()?e.password:void 0,clientName:"clawdbot-control-ui",mode:"webchat",onHello:t=>{e.connected=!0,e.lastError=null,e.hello=t,qh(e,t),yr(e),Nh(e),pn(e,{quiet:!0}),Te(e,{quiet:!0}),Qs(e)},onClose:({code:t,reason:n})=>{e.connected=!1,t!==1012&&(e.lastError=`disconnected (${t}): ${n||"no reason"}`)},onEvent:t=>zh(e,t),onGap:({expected:t,received:n})=>{e.lastError=`event gap detected (expected seq ${t}, got ${n}); refresh recommended`}}),e.client.start()}function zh(e,t){try{jh(e,t)}catch(n){console.error("[gateway] handleGatewayEvent error:",t.event,n)}}function jh(e,t){if(e.eventLogBuffer=[{ts:Date.now(),event:t.event,payload:t.payload},...e.eventLogBuffer].slice(0,250),e.tab==="debug"&&(e.eventLog=e.eventLogBuffer),t.event==="agent"){if(e.onboarding)return;Hl(e,t.payload);return}if(t.event==="chat"){const n=t.payload;n?.sessionKey&&Mo(e,n.sessionKey);const s=Ll(e,n);(s==="final"||s==="error"||s==="aborted")&&(Ns(e),$d(e)),s==="final"&&Xe(e);return}if(t.event==="presence"){const n=t.payload;n?.presence&&Array.isArray(n.presence)&&(e.presenceEntries=n.presence,e.presenceError=null,e.presenceStatus=null);return}if(t.event==="cron"&&e.tab==="cron"&&Zs(e),(t.event==="device.pair.requested"||t.event==="device.pair.resolved")&&Te(e,{quiet:!0}),t.event==="exec.approval.requested"){const n=Fh(t.payload);if(n){e.execApprovalQueue=Kh(e.execApprovalQueue,n),e.execApprovalError=null;const s=Math.max(0,n.expiresAtMs-Date.now()+500);window.setTimeout(()=>{e.execApprovalQueue=ja(e.execApprovalQueue,n.id)},s)}return}if(t.event==="exec.approval.resolved"){const n=Uh(t.payload);n&&(e.execApprovalQueue=ja(e.execApprovalQueue,n.id))}}function qh(e,t){const n=t.snapshot;n?.presence&&Array.isArray(n.presence)&&(e.presenceEntries=n.presence),n?.health&&(e.debugHealth=n.health),n?.sessionDefaults&&Hh(e,n.sessionDefaults)}function Vh(e){e.basePath=ld(),pd(e,!0),cd(e),dd(e),window.addEventListener("popstate",e.popStateHandler),ad(e),wr(e),sd(e),e.tab==="logs"&&Vs(e),e.tab==="debug"&&Gs(e)}function Wh(e){Wl(e)}function Gh(e){window.removeEventListener("popstate",e.popStateHandler),id(e),Ws(e),Ys(e),ud(e),e.topbarObserver?.disconnect(),e.topbarObserver=null}function Yh(e,t){if(e.tab==="chat"&&(t.has("chatMessages")||t.has("chatToolMessages")||t.has("chatStream")||t.has("chatLoading")||t.has("tab"))){const n=t.has("tab"),s=t.has("chatLoading")&&t.get("chatLoading")===!0&&e.chatLoading===!1;ln(e,n||s||!e.chatHasAutoScrolled)}e.tab==="logs"&&(t.has("logsEntries")||t.has("logsAutoFollow")||t.has("tab"))&&e.logsAutoFollow&&e.logsAtBottom&&ro(e,t.has("tab")||t.has("logsAutoFollow"))}async function Qh(e,t){await ic(e,t),await oe(e,!0)}async function Zh(e){await ac(e),await oe(e,!0)}async function Jh(e){await oc(e),await oe(e,!0)}async function Xh(e){await ls(e),await be(e),await oe(e,!0)}async function eg(e){await be(e),await oe(e,!0)}function tg(e){if(!Array.isArray(e))return{};const t={};for(const n of e){if(typeof n!="string")continue;const[s,...i]=n.split(":");if(!s||i.length===0)continue;const a=s.trim(),o=i.join(":").trim();a&&o&&(t[a]=o)}return t}function $r(e){return(e.channelsSnapshot?.channelAccounts?.nostr??[])[0]?.accountId??e.nostrProfileAccountId??"default"}function xr(e,t=""){return`/api/channels/nostr/${encodeURIComponent(e)}/profile${t}`}function ng(e,t,n){e.nostrProfileAccountId=t,e.nostrProfileFormState=Xp(n??void 0)}function sg(e){e.nostrProfileFormState=null,e.nostrProfileAccountId=null}function ig(e,t,n){const s=e.nostrProfileFormState;s&&(e.nostrProfileFormState={...s,values:{...s.values,[t]:n},fieldErrors:{...s.fieldErrors,[t]:""}})}function ag(e){const t=e.nostrProfileFormState;t&&(e.nostrProfileFormState={...t,showAdvanced:!t.showAdvanced})}async function og(e){const t=e.nostrProfileFormState;if(!t||t.saving)return;const n=$r(e);e.nostrProfileFormState={...t,saving:!0,error:null,success:null,fieldErrors:{}};try{const s=await fetch(xr(n),{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(t.values)}),i=await s.json().catch(()=>null);if(!s.ok||i?.ok===!1||!i){const a=i?.error??`Profile update failed (${s.status})`;e.nostrProfileFormState={...t,saving:!1,error:a,success:null,fieldErrors:tg(i?.details)};return}if(!i.persisted){e.nostrProfileFormState={...t,saving:!1,error:"Profile publish failed on all relays.",success:null};return}e.nostrProfileFormState={...t,saving:!1,error:null,success:"Profile published to relays.",fieldErrors:{},original:{...t.values}},await oe(e,!0)}catch(s){e.nostrProfileFormState={...t,saving:!1,error:`Profile update failed: ${String(s)}`,success:null}}}async function rg(e){const t=e.nostrProfileFormState;if(!t||t.importing)return;const n=$r(e);e.nostrProfileFormState={...t,importing:!0,error:null,success:null};try{const s=await fetch(xr(n,"/import"),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({autoMerge:!0})}),i=await s.json().catch(()=>null);if(!s.ok||i?.ok===!1||!i){const l=i?.error??`Profile import failed (${s.status})`;e.nostrProfileFormState={...t,importing:!1,error:l,success:null};return}const a=i.merged??i.imported??null,o=a?{...t.values,...a}:t.values,c=!!(o.banner||o.website||o.nip05||o.lud16);e.nostrProfileFormState={...t,importing:!1,values:o,error:null,success:i.saved?"Profile imported from relays. Review and publish.":"Profile imported. Review and publish.",showAdvanced:c},i.saved&&await oe(e,!0)}catch(s){e.nostrProfileFormState={...t,importing:!1,error:`Profile import failed: ${String(s)}`,success:null}}}var lg=Object.defineProperty,cg=Object.getOwnPropertyDescriptor,b=(e,t,n,s)=>{for(var i=s>1?void 0:s?cg(t,n):t,a=e.length-1,o;a>=0;a--)(o=e[a])&&(i=(s?o(t,n,i):o(i))||i);return s&&i&&lg(t,n,i),i};const es=ul();function dg(){if(!window.location.search)return!1;const t=new URLSearchParams(window.location.search).get("onboarding");if(!t)return!1;const n=t.trim().toLowerCase();return n==="1"||n==="true"||n==="yes"||n==="on"}let m=class extends Ze{constructor(){super(...arguments),this.settings=pl(),this.password="",this.tab="chat",this.onboarding=dg(),this.connected=!1,this.theme=this.settings.theme??"system",this.themeResolved="dark",this.hello=null,this.lastError=null,this.eventLog=[],this.eventLogBuffer=[],this.toolStreamSyncTimer=null,this.sidebarCloseTimer=null,this.assistantName=es.name,this.assistantAvatar=es.avatar,this.assistantAgentId=es.agentId??null,this.sessionKey=this.settings.sessionKey,this.chatLoading=!1,this.chatSending=!1,this.chatMessage="",this.chatMessages=[],this.chatToolMessages=[],this.chatStream=null,this.chatStreamStartedAt=null,this.chatRunId=null,this.compactionStatus=null,this.chatAvatarUrl=null,this.chatThinkingLevel=null,this.chatQueue=[],this.sidebarOpen=!1,this.sidebarContent=null,this.sidebarError=null,this.splitRatio=this.settings.splitRatio,this.nodesLoading=!1,this.nodes=[],this.devicesLoading=!1,this.devicesError=null,this.devicesList=null,this.execApprovalsLoading=!1,this.execApprovalsSaving=!1,this.execApprovalsDirty=!1,this.execApprovalsSnapshot=null,this.execApprovalsForm=null,this.execApprovalsSelectedAgent=null,this.execApprovalsTarget="gateway",this.execApprovalsTargetNodeId=null,this.execApprovalQueue=[],this.execApprovalBusy=!1,this.execApprovalError=null,this.configLoading=!1,this.configRaw=`{ -} -`,this.configRawOriginal="",this.configValid=null,this.configIssues=[],this.configSaving=!1,this.configApplying=!1,this.updateRunning=!1,this.applySessionKey=this.settings.lastActiveSessionKey,this.configSnapshot=null,this.configSchema=null,this.configSchemaVersion=null,this.configSchemaLoading=!1,this.configUiHints={},this.configForm=null,this.configFormOriginal=null,this.configFormDirty=!1,this.configFormMode="form",this.configSearchQuery="",this.configActiveSection=null,this.configActiveSubsection=null,this.channelsLoading=!1,this.channelsSnapshot=null,this.channelsError=null,this.channelsLastSuccess=null,this.whatsappLoginMessage=null,this.whatsappLoginQrDataUrl=null,this.whatsappLoginConnected=null,this.whatsappBusy=!1,this.nostrProfileFormState=null,this.nostrProfileAccountId=null,this.presenceLoading=!1,this.presenceEntries=[],this.presenceError=null,this.presenceStatus=null,this.agentsLoading=!1,this.agentsList=null,this.agentsError=null,this.sessionsLoading=!1,this.sessionsResult=null,this.sessionsError=null,this.sessionsFilterActive="",this.sessionsFilterLimit="120",this.sessionsIncludeGlobal=!0,this.sessionsIncludeUnknown=!1,this.cronLoading=!1,this.cronJobs=[],this.cronStatus=null,this.cronError=null,this.cronForm={...Ph},this.cronRunsJobId=null,this.cronRuns=[],this.cronBusy=!1,this.skillsLoading=!1,this.skillsReport=null,this.skillsError=null,this.skillsFilter="",this.skillEdits={},this.skillsBusyKey=null,this.skillMessages={},this.debugLoading=!1,this.debugStatus=null,this.debugHealth=null,this.debugModels=[],this.debugHeartbeat=null,this.debugCallMethod="",this.debugCallParams="{}",this.debugCallResult=null,this.debugCallError=null,this.logsLoading=!1,this.logsError=null,this.logsFile=null,this.logsEntries=[],this.logsFilterText="",this.logsLevelFilters={...Rh},this.logsAutoFollow=!0,this.logsTruncated=!1,this.logsCursor=null,this.logsLastFetchAt=null,this.logsLimit=500,this.logsMaxBytes=25e4,this.logsAtBottom=!0,this.client=null,this.chatScrollFrame=null,this.chatScrollTimeout=null,this.chatHasAutoScrolled=!1,this.chatUserNearBottom=!0,this.nodesPollInterval=null,this.logsPollInterval=null,this.debugPollInterval=null,this.logsScrollFrame=null,this.toolStreamById=new Map,this.toolStreamOrder=[],this.basePath="",this.popStateHandler=()=>fd(this),this.themeMedia=null,this.themeMediaHandler=null,this.topbarObserver=null}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),Vh(this)}firstUpdated(){Wh(this)}disconnectedCallback(){Gh(this),super.disconnectedCallback()}updated(e){Yh(this,e)}connect(){wr(this)}handleChatScroll(e){zl(this,e)}handleLogsScroll(e){jl(this,e)}exportLogs(e,t){Vl(e,t)}resetToolStream(){Ns(this)}resetChatScroll(){ql(this)}async loadAssistantIdentity(){await yr(this)}applySettings(e){ke(this,e)}setTab(e){od(this,e)}setTheme(e,t){rd(this,e,t)}async loadOverview(){await Po(this)}async loadCron(){await Zs(this)}async handleAbortChat(){await Oo(this)}removeQueuedMessage(e){bd(this,e)}async handleSendChat(e,t){await yd(this,e,t)}async handleWhatsAppStart(e){await Qh(this,e)}async handleWhatsAppWait(){await Zh(this)}async handleWhatsAppLogout(){await Jh(this)}async handleChannelConfigSave(){await Xh(this)}async handleChannelConfigReload(){await eg(this)}handleNostrProfileEdit(e,t){ng(this,e,t)}handleNostrProfileCancel(){sg(this)}handleNostrProfileFieldChange(e,t){ig(this,e,t)}async handleNostrProfileSave(){await og(this)}async handleNostrProfileImport(){await rg(this)}handleNostrProfileToggleAdvanced(){ag(this)}async handleExecApprovalDecision(e){const t=this.execApprovalQueue[0];if(!(!t||!this.client||this.execApprovalBusy)){this.execApprovalBusy=!0,this.execApprovalError=null;try{await this.client.request("exec.approval.resolve",{id:t.id,decision:e}),this.execApprovalQueue=this.execApprovalQueue.filter(n=>n.id!==t.id)}catch(n){this.execApprovalError=`Exec approval failed: ${String(n)}`}finally{this.execApprovalBusy=!1}}}handleOpenSidebar(e){this.sidebarCloseTimer!=null&&(window.clearTimeout(this.sidebarCloseTimer),this.sidebarCloseTimer=null),this.sidebarContent=e,this.sidebarError=null,this.sidebarOpen=!0}handleCloseSidebar(){this.sidebarOpen=!1,this.sidebarCloseTimer!=null&&window.clearTimeout(this.sidebarCloseTimer),this.sidebarCloseTimer=window.setTimeout(()=>{this.sidebarOpen||(this.sidebarContent=null,this.sidebarError=null,this.sidebarCloseTimer=null)},200)}handleSplitRatioChange(e){const t=Math.max(.4,Math.min(.7,e));this.splitRatio=t,this.applySettings({...this.settings,splitRatio:t})}render(){return Ih(this)}};b([y()],m.prototype,"settings",2);b([y()],m.prototype,"password",2);b([y()],m.prototype,"tab",2);b([y()],m.prototype,"onboarding",2);b([y()],m.prototype,"connected",2);b([y()],m.prototype,"theme",2);b([y()],m.prototype,"themeResolved",2);b([y()],m.prototype,"hello",2);b([y()],m.prototype,"lastError",2);b([y()],m.prototype,"eventLog",2);b([y()],m.prototype,"assistantName",2);b([y()],m.prototype,"assistantAvatar",2);b([y()],m.prototype,"assistantAgentId",2);b([y()],m.prototype,"sessionKey",2);b([y()],m.prototype,"chatLoading",2);b([y()],m.prototype,"chatSending",2);b([y()],m.prototype,"chatMessage",2);b([y()],m.prototype,"chatMessages",2);b([y()],m.prototype,"chatToolMessages",2);b([y()],m.prototype,"chatStream",2);b([y()],m.prototype,"chatStreamStartedAt",2);b([y()],m.prototype,"chatRunId",2);b([y()],m.prototype,"compactionStatus",2);b([y()],m.prototype,"chatAvatarUrl",2);b([y()],m.prototype,"chatThinkingLevel",2);b([y()],m.prototype,"chatQueue",2);b([y()],m.prototype,"sidebarOpen",2);b([y()],m.prototype,"sidebarContent",2);b([y()],m.prototype,"sidebarError",2);b([y()],m.prototype,"splitRatio",2);b([y()],m.prototype,"nodesLoading",2);b([y()],m.prototype,"nodes",2);b([y()],m.prototype,"devicesLoading",2);b([y()],m.prototype,"devicesError",2);b([y()],m.prototype,"devicesList",2);b([y()],m.prototype,"execApprovalsLoading",2);b([y()],m.prototype,"execApprovalsSaving",2);b([y()],m.prototype,"execApprovalsDirty",2);b([y()],m.prototype,"execApprovalsSnapshot",2);b([y()],m.prototype,"execApprovalsForm",2);b([y()],m.prototype,"execApprovalsSelectedAgent",2);b([y()],m.prototype,"execApprovalsTarget",2);b([y()],m.prototype,"execApprovalsTargetNodeId",2);b([y()],m.prototype,"execApprovalQueue",2);b([y()],m.prototype,"execApprovalBusy",2);b([y()],m.prototype,"execApprovalError",2);b([y()],m.prototype,"configLoading",2);b([y()],m.prototype,"configRaw",2);b([y()],m.prototype,"configRawOriginal",2);b([y()],m.prototype,"configValid",2);b([y()],m.prototype,"configIssues",2);b([y()],m.prototype,"configSaving",2);b([y()],m.prototype,"configApplying",2);b([y()],m.prototype,"updateRunning",2);b([y()],m.prototype,"applySessionKey",2);b([y()],m.prototype,"configSnapshot",2);b([y()],m.prototype,"configSchema",2);b([y()],m.prototype,"configSchemaVersion",2);b([y()],m.prototype,"configSchemaLoading",2);b([y()],m.prototype,"configUiHints",2);b([y()],m.prototype,"configForm",2);b([y()],m.prototype,"configFormOriginal",2);b([y()],m.prototype,"configFormDirty",2);b([y()],m.prototype,"configFormMode",2);b([y()],m.prototype,"configSearchQuery",2);b([y()],m.prototype,"configActiveSection",2);b([y()],m.prototype,"configActiveSubsection",2);b([y()],m.prototype,"channelsLoading",2);b([y()],m.prototype,"channelsSnapshot",2);b([y()],m.prototype,"channelsError",2);b([y()],m.prototype,"channelsLastSuccess",2);b([y()],m.prototype,"whatsappLoginMessage",2);b([y()],m.prototype,"whatsappLoginQrDataUrl",2);b([y()],m.prototype,"whatsappLoginConnected",2);b([y()],m.prototype,"whatsappBusy",2);b([y()],m.prototype,"nostrProfileFormState",2);b([y()],m.prototype,"nostrProfileAccountId",2);b([y()],m.prototype,"presenceLoading",2);b([y()],m.prototype,"presenceEntries",2);b([y()],m.prototype,"presenceError",2);b([y()],m.prototype,"presenceStatus",2);b([y()],m.prototype,"agentsLoading",2);b([y()],m.prototype,"agentsList",2);b([y()],m.prototype,"agentsError",2);b([y()],m.prototype,"sessionsLoading",2);b([y()],m.prototype,"sessionsResult",2);b([y()],m.prototype,"sessionsError",2);b([y()],m.prototype,"sessionsFilterActive",2);b([y()],m.prototype,"sessionsFilterLimit",2);b([y()],m.prototype,"sessionsIncludeGlobal",2);b([y()],m.prototype,"sessionsIncludeUnknown",2);b([y()],m.prototype,"cronLoading",2);b([y()],m.prototype,"cronJobs",2);b([y()],m.prototype,"cronStatus",2);b([y()],m.prototype,"cronError",2);b([y()],m.prototype,"cronForm",2);b([y()],m.prototype,"cronRunsJobId",2);b([y()],m.prototype,"cronRuns",2);b([y()],m.prototype,"cronBusy",2);b([y()],m.prototype,"skillsLoading",2);b([y()],m.prototype,"skillsReport",2);b([y()],m.prototype,"skillsError",2);b([y()],m.prototype,"skillsFilter",2);b([y()],m.prototype,"skillEdits",2);b([y()],m.prototype,"skillsBusyKey",2);b([y()],m.prototype,"skillMessages",2);b([y()],m.prototype,"debugLoading",2);b([y()],m.prototype,"debugStatus",2);b([y()],m.prototype,"debugHealth",2);b([y()],m.prototype,"debugModels",2);b([y()],m.prototype,"debugHeartbeat",2);b([y()],m.prototype,"debugCallMethod",2);b([y()],m.prototype,"debugCallParams",2);b([y()],m.prototype,"debugCallResult",2);b([y()],m.prototype,"debugCallError",2);b([y()],m.prototype,"logsLoading",2);b([y()],m.prototype,"logsError",2);b([y()],m.prototype,"logsFile",2);b([y()],m.prototype,"logsEntries",2);b([y()],m.prototype,"logsFilterText",2);b([y()],m.prototype,"logsLevelFilters",2);b([y()],m.prototype,"logsAutoFollow",2);b([y()],m.prototype,"logsTruncated",2);b([y()],m.prototype,"logsCursor",2);b([y()],m.prototype,"logsLastFetchAt",2);b([y()],m.prototype,"logsLimit",2);b([y()],m.prototype,"logsMaxBytes",2);b([y()],m.prototype,"logsAtBottom",2);m=b([Ja("clawdbot-app")],m); -//# sourceMappingURL=index-DQcOTEYz.js.map diff --git a/dist/control-ui/assets/index-DQcOTEYz.js.map b/dist/control-ui/assets/index-DQcOTEYz.js.map deleted file mode 100644 index d48222472..000000000 --- a/dist/control-ui/assets/index-DQcOTEYz.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index-DQcOTEYz.js","sources":["../../../node_modules/.pnpm/@lit+reactive-element@2.1.2/node_modules/@lit/reactive-element/css-tag.js","../../../node_modules/.pnpm/@lit+reactive-element@2.1.2/node_modules/@lit/reactive-element/reactive-element.js","../../../node_modules/.pnpm/lit-html@3.3.2/node_modules/lit-html/lit-html.js","../../../node_modules/.pnpm/lit-element@4.2.2/node_modules/lit-element/lit-element.js","../../../node_modules/.pnpm/@lit+reactive-element@2.1.2/node_modules/@lit/reactive-element/decorators/custom-element.js","../../../node_modules/.pnpm/@lit+reactive-element@2.1.2/node_modules/@lit/reactive-element/decorators/property.js","../../../node_modules/.pnpm/@lit+reactive-element@2.1.2/node_modules/@lit/reactive-element/decorators/state.js","../../../ui/src/ui/assistant-identity.ts","../../../ui/src/ui/storage.ts","../../../src/sessions/session-key-utils.ts","../../../ui/src/ui/navigation.ts","../../../ui/src/ui/icons.ts","../../../src/shared/text/reasoning-tags.ts","../../../ui/src/ui/format.ts","../../../ui/src/ui/chat/message-extract.ts","../../../ui/src/ui/uuid.ts","../../../ui/src/ui/controllers/chat.ts","../../../ui/src/ui/controllers/sessions.ts","../../../ui/src/ui/app-tool-stream.ts","../../../ui/src/ui/app-scroll.ts","../../../ui/src/ui/controllers/config/form-utils.ts","../../../ui/src/ui/controllers/config.ts","../../../ui/src/ui/controllers/cron.ts","../../../ui/src/ui/controllers/channels.ts","../../../ui/src/ui/controllers/debug.ts","../../../ui/src/ui/controllers/logs.ts","../../../node_modules/.pnpm/@noble+ed25519@3.0.0/node_modules/@noble/ed25519/index.js","../../../ui/src/ui/device-identity.ts","../../../ui/src/ui/device-auth.ts","../../../ui/src/ui/controllers/devices.ts","../../../ui/src/ui/controllers/nodes.ts","../../../ui/src/ui/controllers/exec-approvals.ts","../../../ui/src/ui/controllers/presence.ts","../../../ui/src/ui/controllers/skills.ts","../../../ui/src/ui/theme.ts","../../../ui/src/ui/theme-transition.ts","../../../ui/src/ui/app-polling.ts","../../../ui/src/ui/app-settings.ts","../../../ui/src/ui/app-chat.ts","../../../node_modules/.pnpm/lit-html@3.3.2/node_modules/lit-html/directive.js","../../../node_modules/.pnpm/lit-html@3.3.2/node_modules/lit-html/directive-helpers.js","../../../node_modules/.pnpm/lit-html@3.3.2/node_modules/lit-html/directives/repeat.js","../../../ui/src/ui/chat/message-normalizer.ts","../../../node_modules/.pnpm/lit-html@3.3.2/node_modules/lit-html/directives/unsafe-html.js","../../../node_modules/.pnpm/dompurify@3.3.1/node_modules/dompurify/dist/purify.es.mjs","../../../node_modules/.pnpm/marked@17.0.1/node_modules/marked/lib/marked.esm.js","../../../ui/src/ui/markdown.ts","../../../ui/src/ui/chat/copy-as-markdown.ts","../../../ui/src/ui/tool-display.ts","../../../ui/src/ui/chat/constants.ts","../../../ui/src/ui/chat/tool-helpers.ts","../../../ui/src/ui/chat/tool-cards.ts","../../../ui/src/ui/chat/grouped-render.ts","../../../ui/src/ui/views/markdown-sidebar.ts","../../../ui/src/ui/components/resizable-divider.ts","../../../ui/src/ui/views/chat.ts","../../../ui/src/ui/views/config-form.shared.ts","../../../ui/src/ui/views/config-form.node.ts","../../../ui/src/ui/views/config-form.render.ts","../../../ui/src/ui/views/config-form.analyze.ts","../../../ui/src/ui/views/config.ts","../../../ui/src/ui/views/channels.shared.ts","../../../ui/src/ui/views/channels.config.ts","../../../ui/src/ui/views/channels.discord.ts","../../../ui/src/ui/views/channels.googlechat.ts","../../../ui/src/ui/views/channels.imessage.ts","../../../ui/src/ui/views/channels.nostr-profile-form.ts","../../../ui/src/ui/views/channels.nostr.ts","../../../ui/src/ui/views/channels.signal.ts","../../../ui/src/ui/views/channels.slack.ts","../../../ui/src/ui/views/channels.telegram.ts","../../../ui/src/ui/views/channels.whatsapp.ts","../../../ui/src/ui/views/channels.ts","../../../ui/src/ui/presenter.ts","../../../ui/src/ui/views/cron.ts","../../../ui/src/ui/views/debug.ts","../../../ui/src/ui/views/instances.ts","../../../ui/src/ui/views/logs.ts","../../../ui/src/ui/views/nodes.ts","../../../ui/src/ui/views/overview.ts","../../../ui/src/ui/views/sessions.ts","../../../ui/src/ui/views/exec-approval.ts","../../../ui/src/ui/views/skills.ts","../../../ui/src/ui/app-render.helpers.ts","../../../ui/src/ui/app-render.ts","../../../ui/src/ui/app-defaults.ts","../../../ui/src/ui/controllers/agents.ts","../../../src/gateway/protocol/client-info.ts","../../../src/gateway/device-auth.ts","../../../ui/src/ui/gateway.ts","../../../ui/src/ui/controllers/exec-approval.ts","../../../ui/src/ui/controllers/assistant-identity.ts","../../../ui/src/ui/app-gateway.ts","../../../ui/src/ui/app-lifecycle.ts","../../../ui/src/ui/app-channels.ts","../../../ui/src/ui/app.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2019 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\nconst t=globalThis,e=t.ShadowRoot&&(void 0===t.ShadyCSS||t.ShadyCSS.nativeShadow)&&\"adoptedStyleSheets\"in Document.prototype&&\"replace\"in CSSStyleSheet.prototype,s=Symbol(),o=new WeakMap;class n{constructor(t,e,o){if(this._$cssResult$=!0,o!==s)throw Error(\"CSSResult is not constructable. Use `unsafeCSS` or `css` instead.\");this.cssText=t,this.t=e}get styleSheet(){let t=this.o;const s=this.t;if(e&&void 0===t){const e=void 0!==s&&1===s.length;e&&(t=o.get(s)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),e&&o.set(s,t))}return t}toString(){return this.cssText}}const r=t=>new n(\"string\"==typeof t?t:t+\"\",void 0,s),i=(t,...e)=>{const o=1===t.length?t[0]:e.reduce((e,s,o)=>e+(t=>{if(!0===t._$cssResult$)return t.cssText;if(\"number\"==typeof t)return t;throw Error(\"Value passed to 'css' function must be a 'css' function result: \"+t+\". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.\")})(s)+t[o+1],t[0]);return new n(o,t,s)},S=(s,o)=>{if(e)s.adoptedStyleSheets=o.map(t=>t instanceof CSSStyleSheet?t:t.styleSheet);else for(const e of o){const o=document.createElement(\"style\"),n=t.litNonce;void 0!==n&&o.setAttribute(\"nonce\",n),o.textContent=e.cssText,s.appendChild(o)}},c=e?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e=\"\";for(const s of t.cssRules)e+=s.cssText;return r(e)})(t):t;export{n as CSSResult,S as adoptStyles,i as css,c as getCompatibleStyle,e as supportsAdoptingStyleSheets,r as unsafeCSS};\n//# sourceMappingURL=css-tag.js.map\n","import{getCompatibleStyle as t,adoptStyles as s}from\"./css-tag.js\";export{CSSResult,css,supportsAdoptingStyleSheets,unsafeCSS}from\"./css-tag.js\";\n/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */const{is:i,defineProperty:e,getOwnPropertyDescriptor:h,getOwnPropertyNames:r,getOwnPropertySymbols:o,getPrototypeOf:n}=Object,a=globalThis,c=a.trustedTypes,l=c?c.emptyScript:\"\",p=a.reactiveElementPolyfillSupport,d=(t,s)=>t,u={toAttribute(t,s){switch(s){case Boolean:t=t?l:null;break;case Object:case Array:t=null==t?t:JSON.stringify(t)}return t},fromAttribute(t,s){let i=t;switch(s){case Boolean:i=null!==t;break;case Number:i=null===t?null:Number(t);break;case Object:case Array:try{i=JSON.parse(t)}catch(t){i=null}}return i}},f=(t,s)=>!i(t,s),b={attribute:!0,type:String,converter:u,reflect:!1,useDefault:!1,hasChanged:f};Symbol.metadata??=Symbol(\"metadata\"),a.litPropertyMetadata??=new WeakMap;class y extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??=[]).push(t)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,s=b){if(s.state&&(s.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(t)&&((s=Object.create(s)).wrapped=!0),this.elementProperties.set(t,s),!s.noAccessor){const i=Symbol(),h=this.getPropertyDescriptor(t,i,s);void 0!==h&&e(this.prototype,t,h)}}static getPropertyDescriptor(t,s,i){const{get:e,set:r}=h(this.prototype,t)??{get(){return this[s]},set(t){this[s]=t}};return{get:e,set(s){const h=e?.call(this);r?.call(this,s),this.requestUpdate(t,h,i)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??b}static _$Ei(){if(this.hasOwnProperty(d(\"elementProperties\")))return;const t=n(this);t.finalize(),void 0!==t.l&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(d(\"finalized\")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(d(\"properties\"))){const t=this.properties,s=[...r(t),...o(t)];for(const i of s)this.createProperty(i,t[i])}const t=this[Symbol.metadata];if(null!==t){const s=litPropertyMetadata.get(t);if(void 0!==s)for(const[t,i]of s)this.elementProperties.set(t,i)}this._$Eh=new Map;for(const[t,s]of this.elementProperties){const i=this._$Eu(t,s);void 0!==i&&this._$Eh.set(i,t)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(s){const i=[];if(Array.isArray(s)){const e=new Set(s.flat(1/0).reverse());for(const s of e)i.unshift(t(s))}else void 0!==s&&i.push(t(s));return i}static _$Eu(t,s){const i=s.attribute;return!1===i?void 0:\"string\"==typeof i?i:\"string\"==typeof t?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(t=>t(this))}addController(t){(this._$EO??=new Set).add(t),void 0!==this.renderRoot&&this.isConnected&&t.hostConnected?.()}removeController(t){this._$EO?.delete(t)}_$E_(){const t=new Map,s=this.constructor.elementProperties;for(const i of s.keys())this.hasOwnProperty(i)&&(t.set(i,this[i]),delete this[i]);t.size>0&&(this._$Ep=t)}createRenderRoot(){const t=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return s(t,this.constructor.elementStyles),t}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(t=>t.hostConnected?.())}enableUpdating(t){}disconnectedCallback(){this._$EO?.forEach(t=>t.hostDisconnected?.())}attributeChangedCallback(t,s,i){this._$AK(t,i)}_$ET(t,s){const i=this.constructor.elementProperties.get(t),e=this.constructor._$Eu(t,i);if(void 0!==e&&!0===i.reflect){const h=(void 0!==i.converter?.toAttribute?i.converter:u).toAttribute(s,i.type);this._$Em=t,null==h?this.removeAttribute(e):this.setAttribute(e,h),this._$Em=null}}_$AK(t,s){const i=this.constructor,e=i._$Eh.get(t);if(void 0!==e&&this._$Em!==e){const t=i.getPropertyOptions(e),h=\"function\"==typeof t.converter?{fromAttribute:t.converter}:void 0!==t.converter?.fromAttribute?t.converter:u;this._$Em=e;const r=h.fromAttribute(s,t.type);this[e]=r??this._$Ej?.get(e)??r,this._$Em=null}}requestUpdate(t,s,i,e=!1,h){if(void 0!==t){const r=this.constructor;if(!1===e&&(h=this[t]),i??=r.getPropertyOptions(t),!((i.hasChanged??f)(h,s)||i.useDefault&&i.reflect&&h===this._$Ej?.get(t)&&!this.hasAttribute(r._$Eu(t,i))))return;this.C(t,s,i)}!1===this.isUpdatePending&&(this._$ES=this._$EP())}C(t,s,{useDefault:i,reflect:e,wrapped:h},r){i&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,r??s??this[t]),!0!==h||void 0!==r)||(this._$AL.has(t)||(this.hasUpdated||i||(s=void 0),this._$AL.set(t,s)),!0===e&&this._$Em!==t&&(this._$Eq??=new Set).add(t))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(t){Promise.reject(t)}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[t,s]of this._$Ep)this[t]=s;this._$Ep=void 0}const t=this.constructor.elementProperties;if(t.size>0)for(const[s,i]of t){const{wrapped:t}=i,e=this[s];!0!==t||this._$AL.has(s)||void 0===e||this.C(s,void 0,i,e)}}let t=!1;const s=this._$AL;try{t=this.shouldUpdate(s),t?(this.willUpdate(s),this._$EO?.forEach(t=>t.hostUpdate?.()),this.update(s)):this._$EM()}catch(s){throw t=!1,this._$EM(),s}t&&this._$AE(s)}willUpdate(t){}_$AE(t){this._$EO?.forEach(t=>t.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return!0}update(t){this._$Eq&&=this._$Eq.forEach(t=>this._$ET(t,this[t])),this._$EM()}updated(t){}firstUpdated(t){}}y.elementStyles=[],y.shadowRootOptions={mode:\"open\"},y[d(\"elementProperties\")]=new Map,y[d(\"finalized\")]=new Map,p?.({ReactiveElement:y}),(a.reactiveElementVersions??=[]).push(\"2.1.2\");export{y as ReactiveElement,s as adoptStyles,u as defaultConverter,t as getCompatibleStyle,f as notEqual};\n//# sourceMappingURL=reactive-element.js.map\n","/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\nconst t=globalThis,i=t=>t,s=t.trustedTypes,e=s?s.createPolicy(\"lit-html\",{createHTML:t=>t}):void 0,h=\"$lit$\",o=`lit$${Math.random().toFixed(9).slice(2)}$`,n=\"?\"+o,r=`<${n}>`,l=document,c=()=>l.createComment(\"\"),a=t=>null===t||\"object\"!=typeof t&&\"function\"!=typeof t,u=Array.isArray,d=t=>u(t)||\"function\"==typeof t?.[Symbol.iterator],f=\"[ \\t\\n\\f\\r]\",v=/<(?:(!--|\\/[^a-zA-Z])|(\\/?[a-zA-Z][^>\\s]*)|(\\/?$))/g,_=/-->/g,m=/>/g,p=RegExp(`>|${f}(?:([^\\\\s\"'>=/]+)(${f}*=${f}*(?:[^ \\t\\n\\f\\r\"'\\`<>=]|(\"|')|))|$)`,\"g\"),g=/'/g,$=/\"/g,y=/^(?:script|style|textarea|title)$/i,x=t=>(i,...s)=>({_$litType$:t,strings:i,values:s}),b=x(1),w=x(2),T=x(3),E=Symbol.for(\"lit-noChange\"),A=Symbol.for(\"lit-nothing\"),C=new WeakMap,P=l.createTreeWalker(l,129);function V(t,i){if(!u(t)||!t.hasOwnProperty(\"raw\"))throw Error(\"invalid template strings array\");return void 0!==e?e.createHTML(i):i}const N=(t,i)=>{const s=t.length-1,e=[];let n,l=2===i?\"\":3===i?\"\":\"\",c=v;for(let i=0;i\"===u[0]?(c=n??v,d=-1):void 0===u[1]?d=-2:(d=c.lastIndex-u[2].length,a=u[1],c=void 0===u[3]?p:'\"'===u[3]?$:g):c===$||c===g?c=p:c===_||c===m?c=v:(c=p,n=void 0);const x=c===p&&t[i+1].startsWith(\"/>\")?\" \":\"\";l+=c===v?s+r:d>=0?(e.push(a),s.slice(0,d)+h+s.slice(d)+o+x):s+o+(-2===d?i:x)}return[V(t,l+(t[s]||\"\")+(2===i?\"\":3===i?\"\":\"\")),e]};class S{constructor({strings:t,_$litType$:i},e){let r;this.parts=[];let l=0,a=0;const u=t.length-1,d=this.parts,[f,v]=N(t,i);if(this.el=S.createElement(f,e),P.currentNode=this.el.content,2===i||3===i){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes)}for(;null!==(r=P.nextNode())&&d.length0){r.textContent=s?s.emptyScript:\"\";for(let s=0;s2||\"\"!==s[0]||\"\"!==s[1]?(this._$AH=Array(s.length-1).fill(new String),this.strings=s):this._$AH=A}_$AI(t,i=this,s,e){const h=this.strings;let o=!1;if(void 0===h)t=M(this,t,i,0),o=!a(t)||t!==this._$AH&&t!==E,o&&(this._$AH=t);else{const e=t;let n,r;for(t=h[0],n=0;n{const e=s?.renderBefore??i;let h=e._$litPart$;if(void 0===h){const t=s?.renderBefore??null;e._$litPart$=h=new k(i.insertBefore(c(),t),t,void 0,s??{})}return h._$AI(t),h};export{j as _$LH,b as html,T as mathml,E as noChange,A as nothing,D as render,w as svg};\n//# sourceMappingURL=lit-html.js.map\n","import{ReactiveElement as t}from\"@lit/reactive-element\";export*from\"@lit/reactive-element\";import{render as e,noChange as r}from\"lit-html\";export*from\"lit-html\";\n/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */const s=globalThis;class i extends t{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){const t=super.createRenderRoot();return this.renderOptions.renderBefore??=t.firstChild,t}update(t){const r=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=e(r,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return r}}i._$litElement$=!0,i[\"finalized\"]=!0,s.litElementHydrateSupport?.({LitElement:i});const o=s.litElementPolyfillSupport;o?.({LitElement:i});const n={_$AK:(t,e,r)=>{t._$AK(e,r)},_$AL:t=>t._$AL};(s.litElementVersions??=[]).push(\"4.2.2\");export{i as LitElement,n as _$LE};\n//# sourceMappingURL=lit-element.js.map\n","/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\nconst t=t=>(e,o)=>{void 0!==o?o.addInitializer(()=>{customElements.define(t,e)}):customElements.define(t,e)};export{t as customElement};\n//# sourceMappingURL=custom-element.js.map\n","import{notEqual as t,defaultConverter as e}from\"../reactive-element.js\";\n/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */const o={attribute:!0,type:String,converter:e,reflect:!1,hasChanged:t},r=(t=o,e,r)=>{const{kind:n,metadata:i}=r;let s=globalThis.litPropertyMetadata.get(i);if(void 0===s&&globalThis.litPropertyMetadata.set(i,s=new Map),\"setter\"===n&&((t=Object.create(t)).wrapped=!0),s.set(r.name,t),\"accessor\"===n){const{name:o}=r;return{set(r){const n=e.get.call(this);e.set.call(this,r),this.requestUpdate(o,n,t,!0,r)},init(e){return void 0!==e&&this.C(o,void 0,t,e),e}}}if(\"setter\"===n){const{name:o}=r;return function(r){const n=this[o];e.call(this,r),this.requestUpdate(o,n,t,!0,r)}}throw Error(\"Unsupported decorator location: \"+n)};function n(t){return(e,o)=>\"object\"==typeof o?r(t,e,o):((t,e,o)=>{const r=e.hasOwnProperty(o);return e.constructor.createProperty(o,t),r?Object.getOwnPropertyDescriptor(e,o):void 0})(t,e,o)}export{n as property,r as standardProperty};\n//# sourceMappingURL=property.js.map\n","import{property as t}from\"./property.js\";\n/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */function r(r){return t({...r,state:!0,attribute:!1})}export{r as state};\n//# sourceMappingURL=state.js.map\n","const MAX_ASSISTANT_NAME = 50;\nconst MAX_ASSISTANT_AVATAR = 200;\n\nexport const DEFAULT_ASSISTANT_NAME = \"Assistant\";\nexport const DEFAULT_ASSISTANT_AVATAR = \"A\";\n\nexport type AssistantIdentity = {\n agentId?: string | null;\n name: string;\n avatar: string | null;\n};\n\ndeclare global {\n interface Window {\n __CLAWDBOT_ASSISTANT_NAME__?: string;\n __CLAWDBOT_ASSISTANT_AVATAR__?: string;\n }\n}\n\nfunction coerceIdentityValue(value: string | undefined, maxLength: number): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n if (!trimmed) return undefined;\n if (trimmed.length <= maxLength) return trimmed;\n return trimmed.slice(0, maxLength);\n}\n\nexport function normalizeAssistantIdentity(\n input?: Partial | null,\n): AssistantIdentity {\n const name =\n coerceIdentityValue(input?.name, MAX_ASSISTANT_NAME) ?? DEFAULT_ASSISTANT_NAME;\n const avatar = coerceIdentityValue(input?.avatar ?? undefined, MAX_ASSISTANT_AVATAR) ?? null;\n const agentId =\n typeof input?.agentId === \"string\" && input.agentId.trim()\n ? input.agentId.trim()\n : null;\n return { agentId, name, avatar };\n}\n\nexport function resolveInjectedAssistantIdentity(): AssistantIdentity {\n if (typeof window === \"undefined\") {\n return normalizeAssistantIdentity({});\n }\n return normalizeAssistantIdentity({\n name: window.__CLAWDBOT_ASSISTANT_NAME__,\n avatar: window.__CLAWDBOT_ASSISTANT_AVATAR__,\n });\n}\n","const KEY = \"clawdbot.control.settings.v1\";\n\nimport type { ThemeMode } from \"./theme\";\n\nexport type UiSettings = {\n gatewayUrl: string;\n token: string;\n sessionKey: string;\n lastActiveSessionKey: string;\n theme: ThemeMode;\n chatFocusMode: boolean;\n chatShowThinking: boolean;\n splitRatio: number; // Sidebar split ratio (0.4 to 0.7, default 0.6)\n navCollapsed: boolean; // Collapsible sidebar state\n navGroupsCollapsed: Record; // Which nav groups are collapsed\n};\n\nexport function loadSettings(): UiSettings {\n const defaultUrl = (() => {\n const proto = location.protocol === \"https:\" ? \"wss\" : \"ws\";\n return `${proto}://${location.host}`;\n })();\n\n const defaults: UiSettings = {\n gatewayUrl: defaultUrl,\n token: \"\",\n sessionKey: \"main\",\n lastActiveSessionKey: \"main\",\n theme: \"system\",\n chatFocusMode: false,\n chatShowThinking: true,\n splitRatio: 0.6,\n navCollapsed: false,\n navGroupsCollapsed: {},\n };\n\n try {\n const raw = localStorage.getItem(KEY);\n if (!raw) return defaults;\n const parsed = JSON.parse(raw) as Partial;\n return {\n gatewayUrl:\n typeof parsed.gatewayUrl === \"string\" && parsed.gatewayUrl.trim()\n ? parsed.gatewayUrl.trim()\n : defaults.gatewayUrl,\n token: typeof parsed.token === \"string\" ? parsed.token : defaults.token,\n sessionKey:\n typeof parsed.sessionKey === \"string\" && parsed.sessionKey.trim()\n ? parsed.sessionKey.trim()\n : defaults.sessionKey,\n lastActiveSessionKey:\n typeof parsed.lastActiveSessionKey === \"string\" &&\n parsed.lastActiveSessionKey.trim()\n ? parsed.lastActiveSessionKey.trim()\n : (typeof parsed.sessionKey === \"string\" &&\n parsed.sessionKey.trim()) ||\n defaults.lastActiveSessionKey,\n theme:\n parsed.theme === \"light\" ||\n parsed.theme === \"dark\" ||\n parsed.theme === \"system\"\n ? parsed.theme\n : defaults.theme,\n chatFocusMode:\n typeof parsed.chatFocusMode === \"boolean\"\n ? parsed.chatFocusMode\n : defaults.chatFocusMode,\n chatShowThinking:\n typeof parsed.chatShowThinking === \"boolean\"\n ? parsed.chatShowThinking\n : defaults.chatShowThinking,\n splitRatio:\n typeof parsed.splitRatio === \"number\" &&\n parsed.splitRatio >= 0.4 &&\n parsed.splitRatio <= 0.7\n ? parsed.splitRatio\n : defaults.splitRatio,\n navCollapsed:\n typeof parsed.navCollapsed === \"boolean\"\n ? parsed.navCollapsed\n : defaults.navCollapsed,\n navGroupsCollapsed:\n typeof parsed.navGroupsCollapsed === \"object\" &&\n parsed.navGroupsCollapsed !== null\n ? parsed.navGroupsCollapsed\n : defaults.navGroupsCollapsed,\n };\n } catch {\n return defaults;\n }\n}\n\nexport function saveSettings(next: UiSettings) {\n localStorage.setItem(KEY, JSON.stringify(next));\n}\n","export type ParsedAgentSessionKey = {\n agentId: string;\n rest: string;\n};\n\nexport function parseAgentSessionKey(\n sessionKey: string | undefined | null,\n): ParsedAgentSessionKey | null {\n const raw = (sessionKey ?? \"\").trim();\n if (!raw) return null;\n const parts = raw.split(\":\").filter(Boolean);\n if (parts.length < 3) return null;\n if (parts[0] !== \"agent\") return null;\n const agentId = parts[1]?.trim();\n const rest = parts.slice(2).join(\":\");\n if (!agentId || !rest) return null;\n return { agentId, rest };\n}\n\nexport function isSubagentSessionKey(sessionKey: string | undefined | null): boolean {\n const raw = (sessionKey ?? \"\").trim();\n if (!raw) return false;\n if (raw.toLowerCase().startsWith(\"subagent:\")) return true;\n const parsed = parseAgentSessionKey(raw);\n return Boolean((parsed?.rest ?? \"\").toLowerCase().startsWith(\"subagent:\"));\n}\n\nexport function isAcpSessionKey(sessionKey: string | undefined | null): boolean {\n const raw = (sessionKey ?? \"\").trim();\n if (!raw) return false;\n const normalized = raw.toLowerCase();\n if (normalized.startsWith(\"acp:\")) return true;\n const parsed = parseAgentSessionKey(raw);\n return Boolean((parsed?.rest ?? \"\").toLowerCase().startsWith(\"acp:\"));\n}\n\nconst THREAD_SESSION_MARKERS = [\":thread:\", \":topic:\"];\n\nexport function resolveThreadParentSessionKey(\n sessionKey: string | undefined | null,\n): string | null {\n const raw = (sessionKey ?? \"\").trim();\n if (!raw) return null;\n const normalized = raw.toLowerCase();\n let idx = -1;\n for (const marker of THREAD_SESSION_MARKERS) {\n const candidate = normalized.lastIndexOf(marker);\n if (candidate > idx) idx = candidate;\n }\n if (idx <= 0) return null;\n const parent = raw.slice(0, idx).trim();\n return parent ? parent : null;\n}\n","import type { IconName } from \"./icons.js\";\n\nexport const TAB_GROUPS = [\n { label: \"Chat\", tabs: [\"chat\"] },\n {\n label: \"Control\",\n tabs: [\"overview\", \"channels\", \"instances\", \"sessions\", \"cron\"],\n },\n { label: \"Agent\", tabs: [\"skills\", \"nodes\"] },\n { label: \"Settings\", tabs: [\"config\", \"debug\", \"logs\"] },\n] as const;\n\nexport type Tab =\n | \"overview\"\n | \"channels\"\n | \"instances\"\n | \"sessions\"\n | \"cron\"\n | \"skills\"\n | \"nodes\"\n | \"chat\"\n | \"config\"\n | \"debug\"\n | \"logs\";\n\nconst TAB_PATHS: Record = {\n overview: \"/overview\",\n channels: \"/channels\",\n instances: \"/instances\",\n sessions: \"/sessions\",\n cron: \"/cron\",\n skills: \"/skills\",\n nodes: \"/nodes\",\n chat: \"/chat\",\n config: \"/config\",\n debug: \"/debug\",\n logs: \"/logs\",\n};\n\nconst PATH_TO_TAB = new Map(\n Object.entries(TAB_PATHS).map(([tab, path]) => [path, tab as Tab]),\n);\n\nexport function normalizeBasePath(basePath: string): string {\n if (!basePath) return \"\";\n let base = basePath.trim();\n if (!base.startsWith(\"/\")) base = `/${base}`;\n if (base === \"/\") return \"\";\n if (base.endsWith(\"/\")) base = base.slice(0, -1);\n return base;\n}\n\nexport function normalizePath(path: string): string {\n if (!path) return \"/\";\n let normalized = path.trim();\n if (!normalized.startsWith(\"/\")) normalized = `/${normalized}`;\n if (normalized.length > 1 && normalized.endsWith(\"/\")) {\n normalized = normalized.slice(0, -1);\n }\n return normalized;\n}\n\nexport function pathForTab(tab: Tab, basePath = \"\"): string {\n const base = normalizeBasePath(basePath);\n const path = TAB_PATHS[tab];\n return base ? `${base}${path}` : path;\n}\n\nexport function tabFromPath(pathname: string, basePath = \"\"): Tab | null {\n const base = normalizeBasePath(basePath);\n let path = pathname || \"/\";\n if (base) {\n if (path === base) {\n path = \"/\";\n } else if (path.startsWith(`${base}/`)) {\n path = path.slice(base.length);\n }\n }\n let normalized = normalizePath(path).toLowerCase();\n if (normalized.endsWith(\"/index.html\")) normalized = \"/\";\n if (normalized === \"/\") return \"chat\";\n return PATH_TO_TAB.get(normalized) ?? null;\n}\n\nexport function inferBasePathFromPathname(pathname: string): string {\n let normalized = normalizePath(pathname);\n if (normalized.endsWith(\"/index.html\")) {\n normalized = normalizePath(normalized.slice(0, -\"/index.html\".length));\n }\n if (normalized === \"/\") return \"\";\n const segments = normalized.split(\"/\").filter(Boolean);\n if (segments.length === 0) return \"\";\n for (let i = 0; i < segments.length; i++) {\n const candidate = `/${segments.slice(i).join(\"/\")}`.toLowerCase();\n if (PATH_TO_TAB.has(candidate)) {\n const prefix = segments.slice(0, i);\n return prefix.length ? `/${prefix.join(\"/\")}` : \"\";\n }\n }\n return `/${segments.join(\"/\")}`;\n}\n\nexport function iconForTab(tab: Tab): IconName {\n switch (tab) {\n case \"chat\":\n return \"messageSquare\";\n case \"overview\":\n return \"barChart\";\n case \"channels\":\n return \"link\";\n case \"instances\":\n return \"radio\";\n case \"sessions\":\n return \"fileText\";\n case \"cron\":\n return \"loader\";\n case \"skills\":\n return \"zap\";\n case \"nodes\":\n return \"monitor\";\n case \"config\":\n return \"settings\";\n case \"debug\":\n return \"bug\";\n case \"logs\":\n return \"scrollText\";\n default:\n return \"folder\";\n }\n}\n\nexport function titleForTab(tab: Tab) {\n switch (tab) {\n case \"overview\":\n return \"Overview\";\n case \"channels\":\n return \"Channels\";\n case \"instances\":\n return \"Instances\";\n case \"sessions\":\n return \"Sessions\";\n case \"cron\":\n return \"Cron Jobs\";\n case \"skills\":\n return \"Skills\";\n case \"nodes\":\n return \"Nodes\";\n case \"chat\":\n return \"Chat\";\n case \"config\":\n return \"Config\";\n case \"debug\":\n return \"Debug\";\n case \"logs\":\n return \"Logs\";\n default:\n return \"Control\";\n }\n}\n\nexport function subtitleForTab(tab: Tab) {\n switch (tab) {\n case \"overview\":\n return \"Gateway status, entry points, and a fast health read.\";\n case \"channels\":\n return \"Manage channels and settings.\";\n case \"instances\":\n return \"Presence beacons from connected clients and nodes.\";\n case \"sessions\":\n return \"Inspect active sessions and adjust per-session defaults.\";\n case \"cron\":\n return \"Schedule wakeups and recurring agent runs.\";\n case \"skills\":\n return \"Manage skill availability and API key injection.\";\n case \"nodes\":\n return \"Paired devices, capabilities, and command exposure.\";\n case \"chat\":\n return \"Direct gateway chat session for quick interventions.\";\n case \"config\":\n return \"Edit ~/.clawdbot/clawdbot.json safely.\";\n case \"debug\":\n return \"Gateway snapshots, events, and manual RPC calls.\";\n case \"logs\":\n return \"Live tail of the gateway file logs.\";\n default:\n return \"\";\n }\n}\n","import { html, type TemplateResult } from \"lit\";\n\n// Lucide-style SVG icons\n// All icons use currentColor for stroke\n\nexport const icons = {\n // Navigation icons\n messageSquare: html``,\n barChart: html``,\n link: html``,\n radio: html``,\n fileText: html``,\n zap: html``,\n monitor: html``,\n settings: html``,\n bug: html``,\n scrollText: html``,\n folder: html``,\n\n // UI icons\n menu: html``,\n x: html``,\n check: html``,\n copy: html``,\n search: html``,\n brain: html``,\n book: html``,\n loader: html``,\n\n // Tool icons\n wrench: html``,\n fileCode: html``,\n edit: html``,\n penLine: html``,\n paperclip: html``,\n globe: html``,\n image: html``,\n smartphone: html``,\n plug: html``,\n circle: html``,\n puzzle: html``,\n} as const;\n\nexport type IconName = keyof typeof icons;\n\nexport function icon(name: IconName): TemplateResult {\n return icons[name];\n}\n\nexport function renderIcon(name: IconName, className = \"nav-item__icon\"): TemplateResult {\n return html`${icons[name]}`;\n}\n\n// Legacy function for compatibility\nexport function renderEmojiIcon(iconContent: string | TemplateResult, className: string): TemplateResult {\n return html`${iconContent}`;\n}\n\nexport function setEmojiIcon(target: HTMLElement | null, icon: string): void {\n if (!target) return;\n target.textContent = icon;\n}\n","export type ReasoningTagMode = \"strict\" | \"preserve\";\nexport type ReasoningTagTrim = \"none\" | \"start\" | \"both\";\n\nconst QUICK_TAG_RE = /<\\s*\\/?\\s*(?:think(?:ing)?|thought|antthinking|final)\\b/i;\nconst FINAL_TAG_RE = /<\\s*\\/?\\s*final\\b[^>]*>/gi;\nconst THINKING_TAG_RE = /<\\s*(\\/?)\\s*(?:think(?:ing)?|thought|antthinking)\\b[^>]*>/gi;\n\nfunction applyTrim(value: string, mode: ReasoningTagTrim): string {\n if (mode === \"none\") return value;\n if (mode === \"start\") return value.trimStart();\n return value.trim();\n}\n\nexport function stripReasoningTagsFromText(\n text: string,\n options?: {\n mode?: ReasoningTagMode;\n trim?: ReasoningTagTrim;\n },\n): string {\n if (!text) return text;\n if (!QUICK_TAG_RE.test(text)) return text;\n\n const mode = options?.mode ?? \"strict\";\n const trimMode = options?.trim ?? \"both\";\n\n let cleaned = text;\n if (FINAL_TAG_RE.test(cleaned)) {\n FINAL_TAG_RE.lastIndex = 0;\n cleaned = cleaned.replace(FINAL_TAG_RE, \"\");\n } else {\n FINAL_TAG_RE.lastIndex = 0;\n }\n\n THINKING_TAG_RE.lastIndex = 0;\n let result = \"\";\n let lastIndex = 0;\n let inThinking = false;\n\n for (const match of cleaned.matchAll(THINKING_TAG_RE)) {\n const idx = match.index ?? 0;\n const isClose = match[1] === \"/\";\n\n if (!inThinking) {\n result += cleaned.slice(lastIndex, idx);\n if (!isClose) {\n inThinking = true;\n }\n } else if (isClose) {\n inThinking = false;\n }\n\n lastIndex = idx + match[0].length;\n }\n\n if (!inThinking || mode === \"preserve\") {\n result += cleaned.slice(lastIndex);\n }\n\n return applyTrim(result, trimMode);\n}\n","import { stripReasoningTagsFromText } from \"../../../src/shared/text/reasoning-tags.js\";\n\nexport function formatMs(ms?: number | null): string {\n if (!ms && ms !== 0) return \"n/a\";\n return new Date(ms).toLocaleString();\n}\n\nexport function formatAgo(ms?: number | null): string {\n if (!ms && ms !== 0) return \"n/a\";\n const diff = Date.now() - ms;\n if (diff < 0) return \"just now\";\n const sec = Math.round(diff / 1000);\n if (sec < 60) return `${sec}s ago`;\n const min = Math.round(sec / 60);\n if (min < 60) return `${min}m ago`;\n const hr = Math.round(min / 60);\n if (hr < 48) return `${hr}h ago`;\n const day = Math.round(hr / 24);\n return `${day}d ago`;\n}\n\nexport function formatDurationMs(ms?: number | null): string {\n if (!ms && ms !== 0) return \"n/a\";\n if (ms < 1000) return `${ms}ms`;\n const sec = Math.round(ms / 1000);\n if (sec < 60) return `${sec}s`;\n const min = Math.round(sec / 60);\n if (min < 60) return `${min}m`;\n const hr = Math.round(min / 60);\n if (hr < 48) return `${hr}h`;\n const day = Math.round(hr / 24);\n return `${day}d`;\n}\n\nexport function formatList(values?: Array): string {\n if (!values || values.length === 0) return \"none\";\n return values.filter((v): v is string => Boolean(v && v.trim())).join(\", \");\n}\n\nexport function clampText(value: string, max = 120): string {\n if (value.length <= max) return value;\n return `${value.slice(0, Math.max(0, max - 1))}…`;\n}\n\nexport function truncateText(value: string, max: number): {\n text: string;\n truncated: boolean;\n total: number;\n} {\n if (value.length <= max) {\n return { text: value, truncated: false, total: value.length };\n }\n return {\n text: value.slice(0, Math.max(0, max)),\n truncated: true,\n total: value.length,\n };\n}\n\nexport function toNumber(value: string, fallback: number): number {\n const n = Number(value);\n return Number.isFinite(n) ? n : fallback;\n}\n\nexport function parseList(input: string): string[] {\n return input\n .split(/[,\\n]/)\n .map((v) => v.trim())\n .filter((v) => v.length > 0);\n}\n\nexport function stripThinkingTags(value: string): string {\n return stripReasoningTagsFromText(value, { mode: \"preserve\", trim: \"start\" });\n}\n","import { stripThinkingTags } from \"../format\";\n\nconst ENVELOPE_PREFIX = /^\\[([^\\]]+)\\]\\s*/;\nconst ENVELOPE_CHANNELS = [\n \"WebChat\",\n \"WhatsApp\",\n \"Telegram\",\n \"Signal\",\n \"Slack\",\n \"Discord\",\n \"iMessage\",\n \"Teams\",\n \"Matrix\",\n \"Zalo\",\n \"Zalo Personal\",\n \"BlueBubbles\",\n];\n\nconst textCache = new WeakMap();\nconst thinkingCache = new WeakMap();\n\nfunction looksLikeEnvelopeHeader(header: string): boolean {\n if (/\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}Z\\b/.test(header)) return true;\n if (/\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}\\b/.test(header)) return true;\n return ENVELOPE_CHANNELS.some((label) => header.startsWith(`${label} `));\n}\n\nexport function stripEnvelope(text: string): string {\n const match = text.match(ENVELOPE_PREFIX);\n if (!match) return text;\n const header = match[1] ?? \"\";\n if (!looksLikeEnvelopeHeader(header)) return text;\n return text.slice(match[0].length);\n}\n\nexport function extractText(message: unknown): string | null {\n const m = message as Record;\n const role = typeof m.role === \"string\" ? m.role : \"\";\n const content = m.content;\n if (typeof content === \"string\") {\n const processed = role === \"assistant\" ? stripThinkingTags(content) : stripEnvelope(content);\n return processed;\n }\n if (Array.isArray(content)) {\n const parts = content\n .map((p) => {\n const item = p as Record;\n if (item.type === \"text\" && typeof item.text === \"string\") return item.text;\n return null;\n })\n .filter((v): v is string => typeof v === \"string\");\n if (parts.length > 0) {\n const joined = parts.join(\"\\n\");\n const processed = role === \"assistant\" ? stripThinkingTags(joined) : stripEnvelope(joined);\n return processed;\n }\n }\n if (typeof m.text === \"string\") {\n const processed = role === \"assistant\" ? stripThinkingTags(m.text) : stripEnvelope(m.text);\n return processed;\n }\n return null;\n}\n\nexport function extractTextCached(message: unknown): string | null {\n if (!message || typeof message !== \"object\") return extractText(message);\n const obj = message as object;\n if (textCache.has(obj)) return textCache.get(obj) ?? null;\n const value = extractText(message);\n textCache.set(obj, value);\n return value;\n}\n\nexport function extractThinking(message: unknown): string | null {\n const m = message as Record;\n const content = m.content;\n const parts: string[] = [];\n if (Array.isArray(content)) {\n for (const p of content) {\n const item = p as Record;\n if (item.type === \"thinking\" && typeof item.thinking === \"string\") {\n const cleaned = item.thinking.trim();\n if (cleaned) parts.push(cleaned);\n }\n }\n }\n if (parts.length > 0) return parts.join(\"\\n\");\n\n // Back-compat: older logs may still have tags inside text blocks.\n const rawText = extractRawText(message);\n if (!rawText) return null;\n const matches = [\n ...rawText.matchAll(\n /<\\s*think(?:ing)?\\s*>([\\s\\S]*?)<\\s*\\/\\s*think(?:ing)?\\s*>/gi,\n ),\n ];\n const extracted = matches\n .map((m) => (m[1] ?? \"\").trim())\n .filter(Boolean);\n return extracted.length > 0 ? extracted.join(\"\\n\") : null;\n}\n\nexport function extractThinkingCached(message: unknown): string | null {\n if (!message || typeof message !== \"object\") return extractThinking(message);\n const obj = message as object;\n if (thinkingCache.has(obj)) return thinkingCache.get(obj) ?? null;\n const value = extractThinking(message);\n thinkingCache.set(obj, value);\n return value;\n}\n\nexport function extractRawText(message: unknown): string | null {\n const m = message as Record;\n const content = m.content;\n if (typeof content === \"string\") return content;\n if (Array.isArray(content)) {\n const parts = content\n .map((p) => {\n const item = p as Record;\n if (item.type === \"text\" && typeof item.text === \"string\") return item.text;\n return null;\n })\n .filter((v): v is string => typeof v === \"string\");\n if (parts.length > 0) return parts.join(\"\\n\");\n }\n if (typeof m.text === \"string\") return m.text;\n return null;\n}\n\nexport function formatReasoningMarkdown(text: string): string {\n const trimmed = text.trim();\n if (!trimmed) return \"\";\n const lines = trimmed\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .filter(Boolean)\n .map((line) => `_${line}_`);\n return lines.length ? [\"_Reasoning:_\", ...lines].join(\"\\n\") : \"\";\n}\n","export type CryptoLike = {\n randomUUID?: (() => string) | undefined;\n getRandomValues?: ((array: Uint8Array) => Uint8Array) | undefined;\n};\n\nfunction uuidFromBytes(bytes: Uint8Array): string {\n bytes[6] = (bytes[6] & 0x0f) | 0x40; // version 4\n bytes[8] = (bytes[8] & 0x3f) | 0x80; // variant 1\n\n let hex = \"\";\n for (let i = 0; i < bytes.length; i++) {\n hex += bytes[i]!.toString(16).padStart(2, \"0\");\n }\n\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(\n 16,\n 20,\n )}-${hex.slice(20)}`;\n}\n\nfunction weakRandomBytes(): Uint8Array {\n const bytes = new Uint8Array(16);\n const now = Date.now();\n for (let i = 0; i < bytes.length; i++) bytes[i] = Math.floor(Math.random() * 256);\n bytes[0] ^= now & 0xff;\n bytes[1] ^= (now >>> 8) & 0xff;\n bytes[2] ^= (now >>> 16) & 0xff;\n bytes[3] ^= (now >>> 24) & 0xff;\n return bytes;\n}\n\nexport function generateUUID(cryptoLike: CryptoLike | null = globalThis.crypto): string {\n if (cryptoLike && typeof cryptoLike.randomUUID === \"function\") return cryptoLike.randomUUID();\n\n if (cryptoLike && typeof cryptoLike.getRandomValues === \"function\") {\n const bytes = new Uint8Array(16);\n cryptoLike.getRandomValues(bytes);\n return uuidFromBytes(bytes);\n }\n\n return uuidFromBytes(weakRandomBytes());\n}\n\n","import type { GatewayBrowserClient } from \"../gateway\";\nimport { extractText } from \"../chat/message-extract\";\nimport { generateUUID } from \"../uuid\";\n\nexport type ChatState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n sessionKey: string;\n chatLoading: boolean;\n chatMessages: unknown[];\n chatThinkingLevel: string | null;\n chatSending: boolean;\n chatMessage: string;\n chatRunId: string | null;\n chatStream: string | null;\n chatStreamStartedAt: number | null;\n lastError: string | null;\n};\n\nexport type ChatEventPayload = {\n runId: string;\n sessionKey: string;\n state: \"delta\" | \"final\" | \"aborted\" | \"error\";\n message?: unknown;\n errorMessage?: string;\n};\n\nexport async function loadChatHistory(state: ChatState) {\n if (!state.client || !state.connected) return;\n state.chatLoading = true;\n state.lastError = null;\n try {\n const res = (await state.client.request(\"chat.history\", {\n sessionKey: state.sessionKey,\n limit: 200,\n })) as { messages?: unknown[]; thinkingLevel?: string | null };\n state.chatMessages = Array.isArray(res.messages) ? res.messages : [];\n state.chatThinkingLevel = res.thinkingLevel ?? null;\n } catch (err) {\n state.lastError = String(err);\n } finally {\n state.chatLoading = false;\n }\n}\n\nexport async function sendChatMessage(state: ChatState, message: string): Promise {\n if (!state.client || !state.connected) return false;\n const msg = message.trim();\n if (!msg) return false;\n\n const now = Date.now();\n state.chatMessages = [\n ...state.chatMessages,\n {\n role: \"user\",\n content: [{ type: \"text\", text: msg }],\n timestamp: now,\n },\n ];\n\n state.chatSending = true;\n state.lastError = null;\n const runId = generateUUID();\n state.chatRunId = runId;\n state.chatStream = \"\";\n state.chatStreamStartedAt = now;\n try {\n await state.client.request(\"chat.send\", {\n sessionKey: state.sessionKey,\n message: msg,\n deliver: false,\n idempotencyKey: runId,\n });\n return true;\n } catch (err) {\n const error = String(err);\n state.chatRunId = null;\n state.chatStream = null;\n state.chatStreamStartedAt = null;\n state.lastError = error;\n state.chatMessages = [\n ...state.chatMessages,\n {\n role: \"assistant\",\n content: [{ type: \"text\", text: \"Error: \" + error }],\n timestamp: Date.now(),\n },\n ];\n return false;\n } finally {\n state.chatSending = false;\n }\n}\n\nexport async function abortChatRun(state: ChatState): Promise {\n if (!state.client || !state.connected) return false;\n const runId = state.chatRunId;\n try {\n await state.client.request(\n \"chat.abort\",\n runId\n ? { sessionKey: state.sessionKey, runId }\n : { sessionKey: state.sessionKey },\n );\n return true;\n } catch (err) {\n state.lastError = String(err);\n return false;\n }\n}\n\nexport function handleChatEvent(\n state: ChatState,\n payload?: ChatEventPayload,\n) {\n if (!payload) return null;\n if (payload.sessionKey !== state.sessionKey) return null;\n if (payload.runId && state.chatRunId && payload.runId !== state.chatRunId)\n return null;\n\n if (payload.state === \"delta\") {\n const next = extractText(payload.message);\n if (typeof next === \"string\") {\n const current = state.chatStream ?? \"\";\n if (!current || next.length >= current.length) {\n state.chatStream = next;\n }\n }\n } else if (payload.state === \"final\") {\n state.chatStream = null;\n state.chatRunId = null;\n state.chatStreamStartedAt = null;\n } else if (payload.state === \"aborted\") {\n state.chatStream = null;\n state.chatRunId = null;\n state.chatStreamStartedAt = null;\n } else if (payload.state === \"error\") {\n state.chatStream = null;\n state.chatRunId = null;\n state.chatStreamStartedAt = null;\n state.lastError = payload.errorMessage ?? \"chat error\";\n }\n return payload.state;\n}\n","import type { GatewayBrowserClient } from \"../gateway\";\nimport { toNumber } from \"../format\";\nimport type { SessionsListResult } from \"../types\";\n\nexport type SessionsState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n sessionsLoading: boolean;\n sessionsResult: SessionsListResult | null;\n sessionsError: string | null;\n sessionsFilterActive: string;\n sessionsFilterLimit: string;\n sessionsIncludeGlobal: boolean;\n sessionsIncludeUnknown: boolean;\n};\n\nexport async function loadSessions(state: SessionsState) {\n if (!state.client || !state.connected) return;\n if (state.sessionsLoading) return;\n state.sessionsLoading = true;\n state.sessionsError = null;\n try {\n const params: Record = {\n includeGlobal: state.sessionsIncludeGlobal,\n includeUnknown: state.sessionsIncludeUnknown,\n };\n const activeMinutes = toNumber(state.sessionsFilterActive, 0);\n const limit = toNumber(state.sessionsFilterLimit, 0);\n if (activeMinutes > 0) params.activeMinutes = activeMinutes;\n if (limit > 0) params.limit = limit;\n const res = (await state.client.request(\"sessions.list\", params)) as\n | SessionsListResult\n | undefined;\n if (res) state.sessionsResult = res;\n } catch (err) {\n state.sessionsError = String(err);\n } finally {\n state.sessionsLoading = false;\n }\n}\n\nexport async function patchSession(\n state: SessionsState,\n key: string,\n patch: {\n label?: string | null;\n thinkingLevel?: string | null;\n verboseLevel?: string | null;\n reasoningLevel?: string | null;\n },\n) {\n if (!state.client || !state.connected) return;\n const params: Record = { key };\n if (\"label\" in patch) params.label = patch.label;\n if (\"thinkingLevel\" in patch) params.thinkingLevel = patch.thinkingLevel;\n if (\"verboseLevel\" in patch) params.verboseLevel = patch.verboseLevel;\n if (\"reasoningLevel\" in patch) params.reasoningLevel = patch.reasoningLevel;\n try {\n await state.client.request(\"sessions.patch\", params);\n await loadSessions(state);\n } catch (err) {\n state.sessionsError = String(err);\n }\n}\n\nexport async function deleteSession(state: SessionsState, key: string) {\n if (!state.client || !state.connected) return;\n if (state.sessionsLoading) return;\n const confirmed = window.confirm(\n `Delete session \"${key}\"?\\n\\nDeletes the session entry and archives its transcript.`,\n );\n if (!confirmed) return;\n state.sessionsLoading = true;\n state.sessionsError = null;\n try {\n await state.client.request(\"sessions.delete\", { key, deleteTranscript: true });\n await loadSessions(state);\n } catch (err) {\n state.sessionsError = String(err);\n } finally {\n state.sessionsLoading = false;\n }\n}\n","import { truncateText } from \"./format\";\n\nconst TOOL_STREAM_LIMIT = 50;\nconst TOOL_STREAM_THROTTLE_MS = 80;\nconst TOOL_OUTPUT_CHAR_LIMIT = 120_000;\n\nexport type AgentEventPayload = {\n runId: string;\n seq: number;\n stream: string;\n ts: number;\n sessionKey?: string;\n data: Record;\n};\n\nexport type ToolStreamEntry = {\n toolCallId: string;\n runId: string;\n sessionKey?: string;\n name: string;\n args?: unknown;\n output?: string;\n startedAt: number;\n updatedAt: number;\n message: Record;\n};\n\ntype ToolStreamHost = {\n sessionKey: string;\n chatRunId: string | null;\n toolStreamById: Map;\n toolStreamOrder: string[];\n chatToolMessages: Record[];\n toolStreamSyncTimer: number | null;\n};\n\nfunction extractToolOutputText(value: unknown): string | null {\n if (!value || typeof value !== \"object\") return null;\n const record = value as Record;\n if (typeof record.text === \"string\") return record.text;\n const content = record.content;\n if (!Array.isArray(content)) return null;\n const parts = content\n .map((item) => {\n if (!item || typeof item !== \"object\") return null;\n const entry = item as Record;\n if (entry.type === \"text\" && typeof entry.text === \"string\") return entry.text;\n return null;\n })\n .filter((part): part is string => Boolean(part));\n if (parts.length === 0) return null;\n return parts.join(\"\\n\");\n}\n\nfunction formatToolOutput(value: unknown): string | null {\n if (value === null || value === undefined) return null;\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n const contentText = extractToolOutputText(value);\n let text: string;\n if (typeof value === \"string\") {\n text = value;\n } else if (contentText) {\n text = contentText;\n } else {\n try {\n text = JSON.stringify(value, null, 2);\n } catch {\n text = String(value);\n }\n }\n const truncated = truncateText(text, TOOL_OUTPUT_CHAR_LIMIT);\n if (!truncated.truncated) return truncated.text;\n return `${truncated.text}\\n\\n… truncated (${truncated.total} chars, showing first ${truncated.text.length}).`;\n}\n\nfunction buildToolStreamMessage(entry: ToolStreamEntry): Record {\n const content: Array> = [];\n content.push({\n type: \"toolcall\",\n name: entry.name,\n arguments: entry.args ?? {},\n });\n if (entry.output) {\n content.push({\n type: \"toolresult\",\n name: entry.name,\n text: entry.output,\n });\n }\n return {\n role: \"assistant\",\n toolCallId: entry.toolCallId,\n runId: entry.runId,\n content,\n timestamp: entry.startedAt,\n };\n}\n\nfunction trimToolStream(host: ToolStreamHost) {\n if (host.toolStreamOrder.length <= TOOL_STREAM_LIMIT) return;\n const overflow = host.toolStreamOrder.length - TOOL_STREAM_LIMIT;\n const removed = host.toolStreamOrder.splice(0, overflow);\n for (const id of removed) host.toolStreamById.delete(id);\n}\n\nfunction syncToolStreamMessages(host: ToolStreamHost) {\n host.chatToolMessages = host.toolStreamOrder\n .map((id) => host.toolStreamById.get(id)?.message)\n .filter((msg): msg is Record => Boolean(msg));\n}\n\nexport function flushToolStreamSync(host: ToolStreamHost) {\n if (host.toolStreamSyncTimer != null) {\n clearTimeout(host.toolStreamSyncTimer);\n host.toolStreamSyncTimer = null;\n }\n syncToolStreamMessages(host);\n}\n\nexport function scheduleToolStreamSync(host: ToolStreamHost, force = false) {\n if (force) {\n flushToolStreamSync(host);\n return;\n }\n if (host.toolStreamSyncTimer != null) return;\n host.toolStreamSyncTimer = window.setTimeout(\n () => flushToolStreamSync(host),\n TOOL_STREAM_THROTTLE_MS,\n );\n}\n\nexport function resetToolStream(host: ToolStreamHost) {\n host.toolStreamById.clear();\n host.toolStreamOrder = [];\n host.chatToolMessages = [];\n flushToolStreamSync(host);\n}\n\nexport type CompactionStatus = {\n active: boolean;\n startedAt: number | null;\n completedAt: number | null;\n};\n\ntype CompactionHost = ToolStreamHost & {\n compactionStatus?: CompactionStatus | null;\n compactionClearTimer?: number | null;\n};\n\nconst COMPACTION_TOAST_DURATION_MS = 5000;\n\nexport function handleCompactionEvent(host: CompactionHost, payload: AgentEventPayload) {\n const data = payload.data ?? {};\n const phase = typeof data.phase === \"string\" ? data.phase : \"\";\n \n // Clear any existing timer\n if (host.compactionClearTimer != null) {\n window.clearTimeout(host.compactionClearTimer);\n host.compactionClearTimer = null;\n }\n \n if (phase === \"start\") {\n host.compactionStatus = {\n active: true,\n startedAt: Date.now(),\n completedAt: null,\n };\n } else if (phase === \"end\") {\n host.compactionStatus = {\n active: false,\n startedAt: host.compactionStatus?.startedAt ?? null,\n completedAt: Date.now(),\n };\n // Auto-clear the toast after duration\n host.compactionClearTimer = window.setTimeout(() => {\n host.compactionStatus = null;\n host.compactionClearTimer = null;\n }, COMPACTION_TOAST_DURATION_MS);\n }\n}\n\nexport function handleAgentEvent(host: ToolStreamHost, payload?: AgentEventPayload) {\n if (!payload) return;\n \n // Handle compaction events\n if (payload.stream === \"compaction\") {\n handleCompactionEvent(host as CompactionHost, payload);\n return;\n }\n \n if (payload.stream !== \"tool\") return;\n const sessionKey =\n typeof payload.sessionKey === \"string\" ? payload.sessionKey : undefined;\n if (sessionKey && sessionKey !== host.sessionKey) return;\n // Fallback: only accept session-less events for the active run.\n if (!sessionKey && host.chatRunId && payload.runId !== host.chatRunId) return;\n if (host.chatRunId && payload.runId !== host.chatRunId) return;\n if (!host.chatRunId) return;\n\n const data = payload.data ?? {};\n const toolCallId = typeof data.toolCallId === \"string\" ? data.toolCallId : \"\";\n if (!toolCallId) return;\n const name = typeof data.name === \"string\" ? data.name : \"tool\";\n const phase = typeof data.phase === \"string\" ? data.phase : \"\";\n const args = phase === \"start\" ? data.args : undefined;\n const output =\n phase === \"update\"\n ? formatToolOutput(data.partialResult)\n : phase === \"result\"\n ? formatToolOutput(data.result)\n : undefined;\n\n const now = Date.now();\n let entry = host.toolStreamById.get(toolCallId);\n if (!entry) {\n entry = {\n toolCallId,\n runId: payload.runId,\n sessionKey,\n name,\n args,\n output,\n startedAt: typeof payload.ts === \"number\" ? payload.ts : now,\n updatedAt: now,\n message: {},\n };\n host.toolStreamById.set(toolCallId, entry);\n host.toolStreamOrder.push(toolCallId);\n } else {\n entry.name = name;\n if (args !== undefined) entry.args = args;\n if (output !== undefined) entry.output = output;\n entry.updatedAt = now;\n }\n\n entry.message = buildToolStreamMessage(entry);\n trimToolStream(host);\n scheduleToolStreamSync(host, phase === \"result\");\n}\n","type ScrollHost = {\n updateComplete: Promise;\n querySelector: (selectors: string) => Element | null;\n style: CSSStyleDeclaration;\n chatScrollFrame: number | null;\n chatScrollTimeout: number | null;\n chatHasAutoScrolled: boolean;\n chatUserNearBottom: boolean;\n logsScrollFrame: number | null;\n logsAtBottom: boolean;\n topbarObserver: ResizeObserver | null;\n};\n\nexport function scheduleChatScroll(host: ScrollHost, force = false) {\n if (host.chatScrollFrame) cancelAnimationFrame(host.chatScrollFrame);\n if (host.chatScrollTimeout != null) {\n clearTimeout(host.chatScrollTimeout);\n host.chatScrollTimeout = null;\n }\n const pickScrollTarget = () => {\n const container = host.querySelector(\".chat-thread\") as HTMLElement | null;\n if (container) {\n const overflowY = getComputedStyle(container).overflowY;\n const canScroll =\n overflowY === \"auto\" ||\n overflowY === \"scroll\" ||\n container.scrollHeight - container.clientHeight > 1;\n if (canScroll) return container;\n }\n return (document.scrollingElement ?? document.documentElement) as HTMLElement | null;\n };\n // Wait for Lit render to complete, then scroll\n void host.updateComplete.then(() => {\n host.chatScrollFrame = requestAnimationFrame(() => {\n host.chatScrollFrame = null;\n const target = pickScrollTarget();\n if (!target) return;\n const distanceFromBottom =\n target.scrollHeight - target.scrollTop - target.clientHeight;\n const shouldStick = force || host.chatUserNearBottom || distanceFromBottom < 200;\n if (!shouldStick) return;\n if (force) host.chatHasAutoScrolled = true;\n target.scrollTop = target.scrollHeight;\n host.chatUserNearBottom = true;\n const retryDelay = force ? 150 : 120;\n host.chatScrollTimeout = window.setTimeout(() => {\n host.chatScrollTimeout = null;\n const latest = pickScrollTarget();\n if (!latest) return;\n const latestDistanceFromBottom =\n latest.scrollHeight - latest.scrollTop - latest.clientHeight;\n const shouldStickRetry =\n force || host.chatUserNearBottom || latestDistanceFromBottom < 200;\n if (!shouldStickRetry) return;\n latest.scrollTop = latest.scrollHeight;\n host.chatUserNearBottom = true;\n }, retryDelay);\n });\n });\n}\n\nexport function scheduleLogsScroll(host: ScrollHost, force = false) {\n if (host.logsScrollFrame) cancelAnimationFrame(host.logsScrollFrame);\n void host.updateComplete.then(() => {\n host.logsScrollFrame = requestAnimationFrame(() => {\n host.logsScrollFrame = null;\n const container = host.querySelector(\".log-stream\") as HTMLElement | null;\n if (!container) return;\n const distanceFromBottom =\n container.scrollHeight - container.scrollTop - container.clientHeight;\n const shouldStick = force || distanceFromBottom < 80;\n if (!shouldStick) return;\n container.scrollTop = container.scrollHeight;\n });\n });\n}\n\nexport function handleChatScroll(host: ScrollHost, event: Event) {\n const container = event.currentTarget as HTMLElement | null;\n if (!container) return;\n const distanceFromBottom =\n container.scrollHeight - container.scrollTop - container.clientHeight;\n host.chatUserNearBottom = distanceFromBottom < 200;\n}\n\nexport function handleLogsScroll(host: ScrollHost, event: Event) {\n const container = event.currentTarget as HTMLElement | null;\n if (!container) return;\n const distanceFromBottom =\n container.scrollHeight - container.scrollTop - container.clientHeight;\n host.logsAtBottom = distanceFromBottom < 80;\n}\n\nexport function resetChatScroll(host: ScrollHost) {\n host.chatHasAutoScrolled = false;\n host.chatUserNearBottom = true;\n}\n\nexport function exportLogs(lines: string[], label: string) {\n if (lines.length === 0) return;\n const blob = new Blob([`${lines.join(\"\\n\")}\\n`], { type: \"text/plain\" });\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement(\"a\");\n const stamp = new Date().toISOString().slice(0, 19).replace(/[:T]/g, \"-\");\n anchor.href = url;\n anchor.download = `clawdbot-logs-${label}-${stamp}.log`;\n anchor.click();\n URL.revokeObjectURL(url);\n}\n\nexport function observeTopbar(host: ScrollHost) {\n if (typeof ResizeObserver === \"undefined\") return;\n const topbar = host.querySelector(\".topbar\");\n if (!topbar) return;\n const update = () => {\n const { height } = topbar.getBoundingClientRect();\n host.style.setProperty(\"--topbar-height\", `${height}px`);\n };\n update();\n host.topbarObserver = new ResizeObserver(() => update());\n host.topbarObserver.observe(topbar);\n}\n","export function cloneConfigObject(value: T): T {\n if (typeof structuredClone === \"function\") {\n return structuredClone(value);\n }\n return JSON.parse(JSON.stringify(value)) as T;\n}\n\nexport function serializeConfigForm(form: Record): string {\n return `${JSON.stringify(form, null, 2).trimEnd()}\\n`;\n}\n\nexport function setPathValue(\n obj: Record | unknown[],\n path: Array,\n value: unknown,\n) {\n if (path.length === 0) return;\n let current: Record | unknown[] = obj;\n for (let i = 0; i < path.length - 1; i += 1) {\n const key = path[i];\n const nextKey = path[i + 1];\n if (typeof key === \"number\") {\n if (!Array.isArray(current)) return;\n if (current[key] == null) {\n current[key] =\n typeof nextKey === \"number\" ? [] : ({} as Record);\n }\n current = current[key] as Record | unknown[];\n } else {\n if (typeof current !== \"object\" || current == null) return;\n const record = current as Record;\n if (record[key] == null) {\n record[key] =\n typeof nextKey === \"number\" ? [] : ({} as Record);\n }\n current = record[key] as Record | unknown[];\n }\n }\n const lastKey = path[path.length - 1];\n if (typeof lastKey === \"number\") {\n if (Array.isArray(current)) current[lastKey] = value;\n return;\n }\n if (typeof current === \"object\" && current != null) {\n (current as Record)[lastKey] = value;\n }\n}\n\nexport function removePathValue(\n obj: Record | unknown[],\n path: Array,\n) {\n if (path.length === 0) return;\n let current: Record | unknown[] = obj;\n for (let i = 0; i < path.length - 1; i += 1) {\n const key = path[i];\n if (typeof key === \"number\") {\n if (!Array.isArray(current)) return;\n current = current[key] as Record | unknown[];\n } else {\n if (typeof current !== \"object\" || current == null) return;\n current = (current as Record)[key] as\n | Record\n | unknown[];\n }\n if (current == null) return;\n }\n const lastKey = path[path.length - 1];\n if (typeof lastKey === \"number\") {\n if (Array.isArray(current)) current.splice(lastKey, 1);\n return;\n }\n if (typeof current === \"object\" && current != null) {\n delete (current as Record)[lastKey];\n }\n}\n\n","import type { GatewayBrowserClient } from \"../gateway\";\nimport type {\n ConfigSchemaResponse,\n ConfigSnapshot,\n ConfigUiHints,\n} from \"../types\";\nimport {\n cloneConfigObject,\n removePathValue,\n serializeConfigForm,\n setPathValue,\n} from \"./config/form-utils\";\n\nexport type ConfigState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n applySessionKey: string;\n configLoading: boolean;\n configRaw: string;\n configRawOriginal: string;\n configValid: boolean | null;\n configIssues: unknown[];\n configSaving: boolean;\n configApplying: boolean;\n updateRunning: boolean;\n configSnapshot: ConfigSnapshot | null;\n configSchema: unknown | null;\n configSchemaVersion: string | null;\n configSchemaLoading: boolean;\n configUiHints: ConfigUiHints;\n configForm: Record | null;\n configFormOriginal: Record | null;\n configFormDirty: boolean;\n configFormMode: \"form\" | \"raw\";\n configSearchQuery: string;\n configActiveSection: string | null;\n configActiveSubsection: string | null;\n lastError: string | null;\n};\n\nexport async function loadConfig(state: ConfigState) {\n if (!state.client || !state.connected) return;\n state.configLoading = true;\n state.lastError = null;\n try {\n const res = (await state.client.request(\"config.get\", {})) as ConfigSnapshot;\n applyConfigSnapshot(state, res);\n } catch (err) {\n state.lastError = String(err);\n } finally {\n state.configLoading = false;\n }\n}\n\nexport async function loadConfigSchema(state: ConfigState) {\n if (!state.client || !state.connected) return;\n if (state.configSchemaLoading) return;\n state.configSchemaLoading = true;\n try {\n const res = (await state.client.request(\n \"config.schema\",\n {},\n )) as ConfigSchemaResponse;\n applyConfigSchema(state, res);\n } catch (err) {\n state.lastError = String(err);\n } finally {\n state.configSchemaLoading = false;\n }\n}\n\nexport function applyConfigSchema(\n state: ConfigState,\n res: ConfigSchemaResponse,\n) {\n state.configSchema = res.schema ?? null;\n state.configUiHints = res.uiHints ?? {};\n state.configSchemaVersion = res.version ?? null;\n}\n\nexport function applyConfigSnapshot(state: ConfigState, snapshot: ConfigSnapshot) {\n state.configSnapshot = snapshot;\n const rawFromSnapshot =\n typeof snapshot.raw === \"string\"\n ? snapshot.raw\n : snapshot.config && typeof snapshot.config === \"object\"\n ? serializeConfigForm(snapshot.config as Record)\n : state.configRaw;\n if (!state.configFormDirty || state.configFormMode === \"raw\") {\n state.configRaw = rawFromSnapshot;\n } else if (state.configForm) {\n state.configRaw = serializeConfigForm(state.configForm);\n } else {\n state.configRaw = rawFromSnapshot;\n }\n state.configValid = typeof snapshot.valid === \"boolean\" ? snapshot.valid : null;\n state.configIssues = Array.isArray(snapshot.issues) ? snapshot.issues : [];\n\n if (!state.configFormDirty) {\n state.configForm = cloneConfigObject(snapshot.config ?? {});\n state.configFormOriginal = cloneConfigObject(snapshot.config ?? {});\n state.configRawOriginal = rawFromSnapshot;\n }\n}\n\nexport async function saveConfig(state: ConfigState) {\n if (!state.client || !state.connected) return;\n state.configSaving = true;\n state.lastError = null;\n try {\n const raw =\n state.configFormMode === \"form\" && state.configForm\n ? serializeConfigForm(state.configForm)\n : state.configRaw;\n const baseHash = state.configSnapshot?.hash;\n if (!baseHash) {\n state.lastError = \"Config hash missing; reload and retry.\";\n return;\n }\n await state.client.request(\"config.set\", { raw, baseHash });\n state.configFormDirty = false;\n await loadConfig(state);\n } catch (err) {\n state.lastError = String(err);\n } finally {\n state.configSaving = false;\n }\n}\n\nexport async function applyConfig(state: ConfigState) {\n if (!state.client || !state.connected) return;\n state.configApplying = true;\n state.lastError = null;\n try {\n const raw =\n state.configFormMode === \"form\" && state.configForm\n ? serializeConfigForm(state.configForm)\n : state.configRaw;\n const baseHash = state.configSnapshot?.hash;\n if (!baseHash) {\n state.lastError = \"Config hash missing; reload and retry.\";\n return;\n }\n await state.client.request(\"config.apply\", {\n raw,\n baseHash,\n sessionKey: state.applySessionKey,\n });\n state.configFormDirty = false;\n await loadConfig(state);\n } catch (err) {\n state.lastError = String(err);\n } finally {\n state.configApplying = false;\n }\n}\n\nexport async function runUpdate(state: ConfigState) {\n if (!state.client || !state.connected) return;\n state.updateRunning = true;\n state.lastError = null;\n try {\n await state.client.request(\"update.run\", {\n sessionKey: state.applySessionKey,\n });\n } catch (err) {\n state.lastError = String(err);\n } finally {\n state.updateRunning = false;\n }\n}\n\nexport function updateConfigFormValue(\n state: ConfigState,\n path: Array,\n value: unknown,\n) {\n const base = cloneConfigObject(\n state.configForm ?? state.configSnapshot?.config ?? {},\n );\n setPathValue(base, path, value);\n state.configForm = base;\n state.configFormDirty = true;\n if (state.configFormMode === \"form\") {\n state.configRaw = serializeConfigForm(base);\n }\n}\n\nexport function removeConfigFormValue(\n state: ConfigState,\n path: Array,\n) {\n const base = cloneConfigObject(\n state.configForm ?? state.configSnapshot?.config ?? {},\n );\n removePathValue(base, path);\n state.configForm = base;\n state.configFormDirty = true;\n if (state.configFormMode === \"form\") {\n state.configRaw = serializeConfigForm(base);\n }\n}\n","import { toNumber } from \"../format\";\nimport type { GatewayBrowserClient } from \"../gateway\";\nimport type { CronJob, CronRunLogEntry, CronStatus } from \"../types\";\nimport type { CronFormState } from \"../ui-types\";\n\nexport type CronState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n cronLoading: boolean;\n cronJobs: CronJob[];\n cronStatus: CronStatus | null;\n cronError: string | null;\n cronForm: CronFormState;\n cronRunsJobId: string | null;\n cronRuns: CronRunLogEntry[];\n cronBusy: boolean;\n};\n\nexport async function loadCronStatus(state: CronState) {\n if (!state.client || !state.connected) return;\n try {\n const res = (await state.client.request(\"cron.status\", {})) as CronStatus;\n state.cronStatus = res;\n } catch (err) {\n state.cronError = String(err);\n }\n}\n\nexport async function loadCronJobs(state: CronState) {\n if (!state.client || !state.connected) return;\n if (state.cronLoading) return;\n state.cronLoading = true;\n state.cronError = null;\n try {\n const res = (await state.client.request(\"cron.list\", {\n includeDisabled: true,\n })) as { jobs?: CronJob[] };\n state.cronJobs = Array.isArray(res.jobs) ? res.jobs : [];\n } catch (err) {\n state.cronError = String(err);\n } finally {\n state.cronLoading = false;\n }\n}\n\nexport function buildCronSchedule(form: CronFormState) {\n if (form.scheduleKind === \"at\") {\n const ms = Date.parse(form.scheduleAt);\n if (!Number.isFinite(ms)) throw new Error(\"Invalid run time.\");\n return { kind: \"at\" as const, atMs: ms };\n }\n if (form.scheduleKind === \"every\") {\n const amount = toNumber(form.everyAmount, 0);\n if (amount <= 0) throw new Error(\"Invalid interval amount.\");\n const unit = form.everyUnit;\n const mult = unit === \"minutes\" ? 60_000 : unit === \"hours\" ? 3_600_000 : 86_400_000;\n return { kind: \"every\" as const, everyMs: amount * mult };\n }\n const expr = form.cronExpr.trim();\n if (!expr) throw new Error(\"Cron expression required.\");\n return { kind: \"cron\" as const, expr, tz: form.cronTz.trim() || undefined };\n}\n\nexport function buildCronPayload(form: CronFormState) {\n if (form.payloadKind === \"systemEvent\") {\n const text = form.payloadText.trim();\n if (!text) throw new Error(\"System event text required.\");\n return { kind: \"systemEvent\" as const, text };\n }\n const message = form.payloadText.trim();\n if (!message) throw new Error(\"Agent message required.\");\n const payload: {\n kind: \"agentTurn\";\n message: string;\n deliver?: boolean;\n channel?: string;\n to?: string;\n timeoutSeconds?: number;\n } = { kind: \"agentTurn\", message };\n if (form.deliver) payload.deliver = true;\n if (form.channel) payload.channel = form.channel;\n if (form.to.trim()) payload.to = form.to.trim();\n const timeoutSeconds = toNumber(form.timeoutSeconds, 0);\n if (timeoutSeconds > 0) payload.timeoutSeconds = timeoutSeconds;\n return payload;\n}\n\nexport async function addCronJob(state: CronState) {\n if (!state.client || !state.connected || state.cronBusy) return;\n state.cronBusy = true;\n state.cronError = null;\n try {\n const schedule = buildCronSchedule(state.cronForm);\n const payload = buildCronPayload(state.cronForm);\n const agentId = state.cronForm.agentId.trim();\n const job = {\n name: state.cronForm.name.trim(),\n description: state.cronForm.description.trim() || undefined,\n agentId: agentId || undefined,\n enabled: state.cronForm.enabled,\n schedule,\n sessionTarget: state.cronForm.sessionTarget,\n wakeMode: state.cronForm.wakeMode,\n payload,\n isolation:\n state.cronForm.postToMainPrefix.trim() &&\n state.cronForm.sessionTarget === \"isolated\"\n ? { postToMainPrefix: state.cronForm.postToMainPrefix.trim() }\n : undefined,\n };\n if (!job.name) throw new Error(\"Name required.\");\n await state.client.request(\"cron.add\", job);\n state.cronForm = {\n ...state.cronForm,\n name: \"\",\n description: \"\",\n payloadText: \"\",\n };\n await loadCronJobs(state);\n await loadCronStatus(state);\n } catch (err) {\n state.cronError = String(err);\n } finally {\n state.cronBusy = false;\n }\n}\n\nexport async function toggleCronJob(\n state: CronState,\n job: CronJob,\n enabled: boolean,\n) {\n if (!state.client || !state.connected || state.cronBusy) return;\n state.cronBusy = true;\n state.cronError = null;\n try {\n await state.client.request(\"cron.update\", { id: job.id, patch: { enabled } });\n await loadCronJobs(state);\n await loadCronStatus(state);\n } catch (err) {\n state.cronError = String(err);\n } finally {\n state.cronBusy = false;\n }\n}\n\nexport async function runCronJob(state: CronState, job: CronJob) {\n if (!state.client || !state.connected || state.cronBusy) return;\n state.cronBusy = true;\n state.cronError = null;\n try {\n await state.client.request(\"cron.run\", { id: job.id, mode: \"force\" });\n await loadCronRuns(state, job.id);\n } catch (err) {\n state.cronError = String(err);\n } finally {\n state.cronBusy = false;\n }\n}\n\nexport async function removeCronJob(state: CronState, job: CronJob) {\n if (!state.client || !state.connected || state.cronBusy) return;\n state.cronBusy = true;\n state.cronError = null;\n try {\n await state.client.request(\"cron.remove\", { id: job.id });\n if (state.cronRunsJobId === job.id) {\n state.cronRunsJobId = null;\n state.cronRuns = [];\n }\n await loadCronJobs(state);\n await loadCronStatus(state);\n } catch (err) {\n state.cronError = String(err);\n } finally {\n state.cronBusy = false;\n }\n}\n\nexport async function loadCronRuns(state: CronState, jobId: string) {\n if (!state.client || !state.connected) return;\n try {\n const res = (await state.client.request(\"cron.runs\", {\n id: jobId,\n limit: 50,\n })) as { entries?: CronRunLogEntry[] };\n state.cronRunsJobId = jobId;\n state.cronRuns = Array.isArray(res.entries) ? res.entries : [];\n } catch (err) {\n state.cronError = String(err);\n }\n}\n","import type { ChannelsStatusSnapshot } from \"../types\";\nimport type { ChannelsState } from \"./channels.types\";\n\nexport type { ChannelsState };\n\nexport async function loadChannels(state: ChannelsState, probe: boolean) {\n if (!state.client || !state.connected) return;\n if (state.channelsLoading) return;\n state.channelsLoading = true;\n state.channelsError = null;\n try {\n const res = (await state.client.request(\"channels.status\", {\n probe,\n timeoutMs: 8000,\n })) as ChannelsStatusSnapshot;\n state.channelsSnapshot = res;\n state.channelsLastSuccess = Date.now();\n } catch (err) {\n state.channelsError = String(err);\n } finally {\n state.channelsLoading = false;\n }\n}\n\nexport async function startWhatsAppLogin(state: ChannelsState, force: boolean) {\n if (!state.client || !state.connected || state.whatsappBusy) return;\n state.whatsappBusy = true;\n try {\n const res = (await state.client.request(\"web.login.start\", {\n force,\n timeoutMs: 30000,\n })) as { message?: string; qrDataUrl?: string };\n state.whatsappLoginMessage = res.message ?? null;\n state.whatsappLoginQrDataUrl = res.qrDataUrl ?? null;\n state.whatsappLoginConnected = null;\n } catch (err) {\n state.whatsappLoginMessage = String(err);\n state.whatsappLoginQrDataUrl = null;\n state.whatsappLoginConnected = null;\n } finally {\n state.whatsappBusy = false;\n }\n}\n\nexport async function waitWhatsAppLogin(state: ChannelsState) {\n if (!state.client || !state.connected || state.whatsappBusy) return;\n state.whatsappBusy = true;\n try {\n const res = (await state.client.request(\"web.login.wait\", {\n timeoutMs: 120000,\n })) as { connected?: boolean; message?: string };\n state.whatsappLoginMessage = res.message ?? null;\n state.whatsappLoginConnected = res.connected ?? null;\n if (res.connected) state.whatsappLoginQrDataUrl = null;\n } catch (err) {\n state.whatsappLoginMessage = String(err);\n state.whatsappLoginConnected = null;\n } finally {\n state.whatsappBusy = false;\n }\n}\n\nexport async function logoutWhatsApp(state: ChannelsState) {\n if (!state.client || !state.connected || state.whatsappBusy) return;\n state.whatsappBusy = true;\n try {\n await state.client.request(\"channels.logout\", { channel: \"whatsapp\" });\n state.whatsappLoginMessage = \"Logged out.\";\n state.whatsappLoginQrDataUrl = null;\n state.whatsappLoginConnected = null;\n } catch (err) {\n state.whatsappLoginMessage = String(err);\n } finally {\n state.whatsappBusy = false;\n }\n}\n","import type { GatewayBrowserClient } from \"../gateway\";\nimport type { HealthSnapshot, StatusSummary } from \"../types\";\n\nexport type DebugState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n debugLoading: boolean;\n debugStatus: StatusSummary | null;\n debugHealth: HealthSnapshot | null;\n debugModels: unknown[];\n debugHeartbeat: unknown | null;\n debugCallMethod: string;\n debugCallParams: string;\n debugCallResult: string | null;\n debugCallError: string | null;\n};\n\nexport async function loadDebug(state: DebugState) {\n if (!state.client || !state.connected) return;\n if (state.debugLoading) return;\n state.debugLoading = true;\n try {\n const [status, health, models, heartbeat] = await Promise.all([\n state.client.request(\"status\", {}),\n state.client.request(\"health\", {}),\n state.client.request(\"models.list\", {}),\n state.client.request(\"last-heartbeat\", {}),\n ]);\n state.debugStatus = status as StatusSummary;\n state.debugHealth = health as HealthSnapshot;\n const modelPayload = models as { models?: unknown[] } | undefined;\n state.debugModels = Array.isArray(modelPayload?.models)\n ? modelPayload?.models\n : [];\n state.debugHeartbeat = heartbeat as unknown;\n } catch (err) {\n state.debugCallError = String(err);\n } finally {\n state.debugLoading = false;\n }\n}\n\nexport async function callDebugMethod(state: DebugState) {\n if (!state.client || !state.connected) return;\n state.debugCallError = null;\n state.debugCallResult = null;\n try {\n const params = state.debugCallParams.trim()\n ? (JSON.parse(state.debugCallParams) as unknown)\n : {};\n const res = await state.client.request(state.debugCallMethod.trim(), params);\n state.debugCallResult = JSON.stringify(res, null, 2);\n } catch (err) {\n state.debugCallError = String(err);\n }\n}\n\n","import type { GatewayBrowserClient } from \"../gateway\";\nimport type { LogEntry, LogLevel } from \"../types\";\n\nexport type LogsState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n logsLoading: boolean;\n logsError: string | null;\n logsCursor: number | null;\n logsFile: string | null;\n logsEntries: LogEntry[];\n logsTruncated: boolean;\n logsLastFetchAt: number | null;\n logsLimit: number;\n logsMaxBytes: number;\n};\n\nconst LOG_BUFFER_LIMIT = 2000;\nconst LEVELS = new Set([\n \"trace\",\n \"debug\",\n \"info\",\n \"warn\",\n \"error\",\n \"fatal\",\n]);\n\nfunction parseMaybeJsonString(value: unknown) {\n if (typeof value !== \"string\") return null;\n const trimmed = value.trim();\n if (!trimmed.startsWith(\"{\") || !trimmed.endsWith(\"}\")) return null;\n try {\n const parsed = JSON.parse(trimmed) as unknown;\n if (!parsed || typeof parsed !== \"object\") return null;\n return parsed as Record;\n } catch {\n return null;\n }\n}\n\nfunction normalizeLevel(value: unknown): LogLevel | null {\n if (typeof value !== \"string\") return null;\n const lowered = value.toLowerCase() as LogLevel;\n return LEVELS.has(lowered) ? lowered : null;\n}\n\nexport function parseLogLine(line: string): LogEntry {\n if (!line.trim()) return { raw: line, message: line };\n try {\n const obj = JSON.parse(line) as Record;\n const meta =\n obj && typeof obj._meta === \"object\" && obj._meta !== null\n ? (obj._meta as Record)\n : null;\n const time =\n typeof obj.time === \"string\"\n ? obj.time\n : typeof meta?.date === \"string\"\n ? meta?.date\n : null;\n const level = normalizeLevel(meta?.logLevelName ?? meta?.level);\n\n const contextCandidate =\n typeof obj[\"0\"] === \"string\"\n ? (obj[\"0\"] as string)\n : typeof meta?.name === \"string\"\n ? (meta?.name as string)\n : null;\n const contextObj = parseMaybeJsonString(contextCandidate);\n let subsystem: string | null = null;\n if (contextObj) {\n if (typeof contextObj.subsystem === \"string\") subsystem = contextObj.subsystem;\n else if (typeof contextObj.module === \"string\") subsystem = contextObj.module;\n }\n if (!subsystem && contextCandidate && contextCandidate.length < 120) {\n subsystem = contextCandidate;\n }\n\n let message: string | null = null;\n if (typeof obj[\"1\"] === \"string\") message = obj[\"1\"] as string;\n else if (!contextObj && typeof obj[\"0\"] === \"string\") message = obj[\"0\"] as string;\n else if (typeof obj.message === \"string\") message = obj.message as string;\n\n return {\n raw: line,\n time,\n level,\n subsystem,\n message: message ?? line,\n meta: meta ?? undefined,\n };\n } catch {\n return { raw: line, message: line };\n }\n}\n\nexport async function loadLogs(\n state: LogsState,\n opts?: { reset?: boolean; quiet?: boolean },\n) {\n if (!state.client || !state.connected) return;\n if (state.logsLoading && !opts?.quiet) return;\n if (!opts?.quiet) state.logsLoading = true;\n state.logsError = null;\n try {\n const res = await state.client.request(\"logs.tail\", {\n cursor: opts?.reset ? undefined : state.logsCursor ?? undefined,\n limit: state.logsLimit,\n maxBytes: state.logsMaxBytes,\n });\n const payload = res as {\n file?: string;\n cursor?: number;\n size?: number;\n lines?: unknown;\n truncated?: boolean;\n reset?: boolean;\n };\n const lines = Array.isArray(payload.lines)\n ? (payload.lines.filter((line) => typeof line === \"string\") as string[])\n : [];\n const entries = lines.map(parseLogLine);\n const shouldReset = Boolean(opts?.reset || payload.reset || state.logsCursor == null);\n state.logsEntries = shouldReset\n ? entries\n : [...state.logsEntries, ...entries].slice(-LOG_BUFFER_LIMIT);\n if (typeof payload.cursor === \"number\") state.logsCursor = payload.cursor;\n if (typeof payload.file === \"string\") state.logsFile = payload.file;\n state.logsTruncated = Boolean(payload.truncated);\n state.logsLastFetchAt = Date.now();\n } catch (err) {\n state.logsError = String(err);\n } finally {\n if (!opts?.quiet) state.logsLoading = false;\n }\n}\n","/*! noble-ed25519 - MIT License (c) 2019 Paul Miller (paulmillr.com) */\n/**\n * 5KB JS implementation of ed25519 EdDSA signatures.\n * Compliant with RFC8032, FIPS 186-5 & ZIP215.\n * @module\n * @example\n * ```js\nimport * as ed from '@noble/ed25519';\n(async () => {\n const secretKey = ed.utils.randomSecretKey();\n const message = Uint8Array.from([0xab, 0xbc, 0xcd, 0xde]);\n const pubKey = await ed.getPublicKeyAsync(secretKey); // Sync methods are also present\n const signature = await ed.signAsync(message, secretKey);\n const isValid = await ed.verifyAsync(signature, message, pubKey);\n})();\n```\n */\n/**\n * Curve params. ed25519 is twisted edwards curve. Equation is −x² + y² = -a + dx²y².\n * * P = `2n**255n - 19n` // field over which calculations are done\n * * N = `2n**252n + 27742317777372353535851937790883648493n` // group order, amount of curve points\n * * h = 8 // cofactor\n * * a = `Fp.create(BigInt(-1))` // equation param\n * * d = -121665/121666 a.k.a. `Fp.neg(121665 * Fp.inv(121666))` // equation param\n * * Gx, Gy are coordinates of Generator / base point\n */\nconst ed25519_CURVE = {\n p: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffedn,\n n: 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3edn,\n h: 8n,\n a: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffecn,\n d: 0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3n,\n Gx: 0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51an,\n Gy: 0x6666666666666666666666666666666666666666666666666666666666666658n,\n};\nconst { p: P, n: N, Gx, Gy, a: _a, d: _d, h } = ed25519_CURVE;\nconst L = 32; // field / group byte length\nconst L2 = 64;\n// Helpers and Precomputes sections are reused between libraries\n// ## Helpers\n// ----------\nconst captureTrace = (...args) => {\n if ('captureStackTrace' in Error && typeof Error.captureStackTrace === 'function') {\n Error.captureStackTrace(...args);\n }\n};\nconst err = (message = '') => {\n const e = new Error(message);\n captureTrace(e, err);\n throw e;\n};\nconst isBig = (n) => typeof n === 'bigint'; // is big integer\nconst isStr = (s) => typeof s === 'string'; // is string\nconst isBytes = (a) => a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array');\n/** Asserts something is Uint8Array. */\nconst abytes = (value, length, title = '') => {\n const bytes = isBytes(value);\n const len = value?.length;\n const needsLen = length !== undefined;\n if (!bytes || (needsLen && len !== length)) {\n const prefix = title && `\"${title}\" `;\n const ofLen = needsLen ? ` of length ${length}` : '';\n const got = bytes ? `length=${len}` : `type=${typeof value}`;\n err(prefix + 'expected Uint8Array' + ofLen + ', got ' + got);\n }\n return value;\n};\n/** create Uint8Array */\nconst u8n = (len) => new Uint8Array(len);\nconst u8fr = (buf) => Uint8Array.from(buf);\nconst padh = (n, pad) => n.toString(16).padStart(pad, '0');\nconst bytesToHex = (b) => Array.from(abytes(b))\n .map((e) => padh(e, 2))\n .join('');\nconst C = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 }; // ASCII characters\nconst _ch = (ch) => {\n if (ch >= C._0 && ch <= C._9)\n return ch - C._0; // '2' => 50-48\n if (ch >= C.A && ch <= C.F)\n return ch - (C.A - 10); // 'B' => 66-(65-10)\n if (ch >= C.a && ch <= C.f)\n return ch - (C.a - 10); // 'b' => 98-(97-10)\n return;\n};\nconst hexToBytes = (hex) => {\n const e = 'hex invalid';\n if (!isStr(hex))\n return err(e);\n const hl = hex.length;\n const al = hl / 2;\n if (hl % 2)\n return err(e);\n const array = u8n(al);\n for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {\n // treat each char as ASCII\n const n1 = _ch(hex.charCodeAt(hi)); // parse first char, multiply it by 16\n const n2 = _ch(hex.charCodeAt(hi + 1)); // parse second char\n if (n1 === undefined || n2 === undefined)\n return err(e);\n array[ai] = n1 * 16 + n2; // example: 'A9' => 10*16 + 9\n }\n return array;\n};\nconst cr = () => globalThis?.crypto; // WebCrypto is available in all modern environments\nconst subtle = () => cr()?.subtle ?? err('crypto.subtle must be defined, consider polyfill');\n// prettier-ignore\nconst concatBytes = (...arrs) => {\n const r = u8n(arrs.reduce((sum, a) => sum + abytes(a).length, 0)); // create u8a of summed length\n let pad = 0; // walk through each array,\n arrs.forEach(a => { r.set(a, pad); pad += a.length; }); // ensure they have proper type\n return r;\n};\n/** WebCrypto OS-level CSPRNG (random number generator). Will throw when not available. */\nconst randomBytes = (len = L) => {\n const c = cr();\n return c.getRandomValues(u8n(len));\n};\nconst big = BigInt;\nconst assertRange = (n, min, max, msg = 'bad number: out of range') => (isBig(n) && min <= n && n < max ? n : err(msg));\n/** modular division */\nconst M = (a, b = P) => {\n const r = a % b;\n return r >= 0n ? r : b + r;\n};\nconst modN = (a) => M(a, N);\n/** Modular inversion using euclidean GCD (non-CT). No negative exponent for now. */\n// prettier-ignore\nconst invert = (num, md) => {\n if (num === 0n || md <= 0n)\n err('no inverse n=' + num + ' mod=' + md);\n let a = M(num, md), b = md, x = 0n, y = 1n, u = 1n, v = 0n;\n while (a !== 0n) {\n const q = b / a, r = b % a;\n const m = x - u * q, n = y - v * q;\n b = a, a = r, x = u, y = v, u = m, v = n;\n }\n return b === 1n ? M(x, md) : err('no inverse'); // b is gcd at this point\n};\nconst callHash = (name) => {\n // @ts-ignore\n const fn = hashes[name];\n if (typeof fn !== 'function')\n err('hashes.' + name + ' not set');\n return fn;\n};\nconst hash = (msg) => callHash('sha512')(msg);\nconst apoint = (p) => (p instanceof Point ? p : err('Point expected'));\n// ## End of Helpers\n// -----------------\nconst B256 = 2n ** 256n;\n/** Point in XYZT extended coordinates. */\nclass Point {\n static BASE;\n static ZERO;\n X;\n Y;\n Z;\n T;\n constructor(X, Y, Z, T) {\n const max = B256;\n this.X = assertRange(X, 0n, max);\n this.Y = assertRange(Y, 0n, max);\n this.Z = assertRange(Z, 1n, max);\n this.T = assertRange(T, 0n, max);\n Object.freeze(this);\n }\n static CURVE() {\n return ed25519_CURVE;\n }\n static fromAffine(p) {\n return new Point(p.x, p.y, 1n, M(p.x * p.y));\n }\n /** RFC8032 5.1.3: Uint8Array to Point. */\n static fromBytes(hex, zip215 = false) {\n const d = _d;\n // Copy array to not mess it up.\n const normed = u8fr(abytes(hex, L));\n // adjust first LE byte = last BE byte\n const lastByte = hex[31];\n normed[31] = lastByte & ~0x80;\n const y = bytesToNumLE(normed);\n // zip215=true: 0 <= y < 2^256\n // zip215=false, RFC8032: 0 <= y < 2^255-19\n const max = zip215 ? B256 : P;\n assertRange(y, 0n, max);\n const y2 = M(y * y); // y²\n const u = M(y2 - 1n); // u=y²-1\n const v = M(d * y2 + 1n); // v=dy²+1\n let { isValid, value: x } = uvRatio(u, v); // (uv³)(uv⁷)^(p-5)/8; square root\n if (!isValid)\n err('bad point: y not sqrt'); // not square root: bad point\n const isXOdd = (x & 1n) === 1n; // adjust sign of x coordinate\n const isLastByteOdd = (lastByte & 0x80) !== 0; // x_0, last bit\n if (!zip215 && x === 0n && isLastByteOdd)\n err('bad point: x==0, isLastByteOdd'); // x=0, x_0=1\n if (isLastByteOdd !== isXOdd)\n x = M(-x);\n return new Point(x, y, 1n, M(x * y)); // Z=1, T=xy\n }\n static fromHex(hex, zip215) {\n return Point.fromBytes(hexToBytes(hex), zip215);\n }\n get x() {\n return this.toAffine().x;\n }\n get y() {\n return this.toAffine().y;\n }\n /** Checks if the point is valid and on-curve. */\n assertValidity() {\n const a = _a;\n const d = _d;\n const p = this;\n if (p.is0())\n return err('bad point: ZERO'); // TODO: optimize, with vars below?\n // Equation in affine coordinates: ax² + y² = 1 + dx²y²\n // Equation in projective coordinates (X/Z, Y/Z, Z): (aX² + Y²)Z² = Z⁴ + dX²Y²\n const { X, Y, Z, T } = p;\n const X2 = M(X * X); // X²\n const Y2 = M(Y * Y); // Y²\n const Z2 = M(Z * Z); // Z²\n const Z4 = M(Z2 * Z2); // Z⁴\n const aX2 = M(X2 * a); // aX²\n const left = M(Z2 * M(aX2 + Y2)); // (aX² + Y²)Z²\n const right = M(Z4 + M(d * M(X2 * Y2))); // Z⁴ + dX²Y²\n if (left !== right)\n return err('bad point: equation left != right (1)');\n // In Extended coordinates we also have T, which is x*y=T/Z: check X*Y == Z*T\n const XY = M(X * Y);\n const ZT = M(Z * T);\n if (XY !== ZT)\n return err('bad point: equation left != right (2)');\n return this;\n }\n /** Equality check: compare points P&Q. */\n equals(other) {\n const { X: X1, Y: Y1, Z: Z1 } = this;\n const { X: X2, Y: Y2, Z: Z2 } = apoint(other); // checks class equality\n const X1Z2 = M(X1 * Z2);\n const X2Z1 = M(X2 * Z1);\n const Y1Z2 = M(Y1 * Z2);\n const Y2Z1 = M(Y2 * Z1);\n return X1Z2 === X2Z1 && Y1Z2 === Y2Z1;\n }\n is0() {\n return this.equals(I);\n }\n /** Flip point over y coordinate. */\n negate() {\n return new Point(M(-this.X), this.Y, this.Z, M(-this.T));\n }\n /** Point doubling. Complete formula. Cost: `4M + 4S + 1*a + 6add + 1*2`. */\n double() {\n const { X: X1, Y: Y1, Z: Z1 } = this;\n const a = _a;\n // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd\n const A = M(X1 * X1);\n const B = M(Y1 * Y1);\n const C = M(2n * M(Z1 * Z1));\n const D = M(a * A);\n const x1y1 = X1 + Y1;\n const E = M(M(x1y1 * x1y1) - A - B);\n const G = D + B;\n const F = G - C;\n const H = D - B;\n const X3 = M(E * F);\n const Y3 = M(G * H);\n const T3 = M(E * H);\n const Z3 = M(F * G);\n return new Point(X3, Y3, Z3, T3);\n }\n /** Point addition. Complete formula. Cost: `8M + 1*k + 8add + 1*2`. */\n add(other) {\n const { X: X1, Y: Y1, Z: Z1, T: T1 } = this;\n const { X: X2, Y: Y2, Z: Z2, T: T2 } = apoint(other); // doesn't check if other on-curve\n const a = _a;\n const d = _d;\n // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#addition-add-2008-hwcd-3\n const A = M(X1 * X2);\n const B = M(Y1 * Y2);\n const C = M(T1 * d * T2);\n const D = M(Z1 * Z2);\n const E = M((X1 + Y1) * (X2 + Y2) - A - B);\n const F = M(D - C);\n const G = M(D + C);\n const H = M(B - a * A);\n const X3 = M(E * F);\n const Y3 = M(G * H);\n const T3 = M(E * H);\n const Z3 = M(F * G);\n return new Point(X3, Y3, Z3, T3);\n }\n subtract(other) {\n return this.add(apoint(other).negate());\n }\n /**\n * Point-by-scalar multiplication. Scalar must be in range 1 <= n < CURVE.n.\n * Uses {@link wNAF} for base point.\n * Uses fake point to mitigate side-channel leakage.\n * @param n scalar by which point is multiplied\n * @param safe safe mode guards against timing attacks; unsafe mode is faster\n */\n multiply(n, safe = true) {\n if (!safe && (n === 0n || this.is0()))\n return I;\n assertRange(n, 1n, N);\n if (n === 1n)\n return this;\n if (this.equals(G))\n return wNAF(n).p;\n // init result point & fake point\n let p = I;\n let f = G;\n for (let d = this; n > 0n; d = d.double(), n >>= 1n) {\n // if bit is present, add to point\n // if not present, add to fake, for timing safety\n if (n & 1n)\n p = p.add(d);\n else if (safe)\n f = f.add(d);\n }\n return p;\n }\n multiplyUnsafe(scalar) {\n return this.multiply(scalar, false);\n }\n /** Convert point to 2d xy affine point. (X, Y, Z) ∋ (x=X/Z, y=Y/Z) */\n toAffine() {\n const { X, Y, Z } = this;\n // fast-paths for ZERO point OR Z=1\n if (this.equals(I))\n return { x: 0n, y: 1n };\n const iz = invert(Z, P);\n // (Z * Z^-1) must be 1, otherwise bad math\n if (M(Z * iz) !== 1n)\n err('invalid inverse');\n // x = X*Z^-1; y = Y*Z^-1\n const x = M(X * iz);\n const y = M(Y * iz);\n return { x, y };\n }\n toBytes() {\n const { x, y } = this.assertValidity().toAffine();\n const b = numTo32bLE(y);\n // store sign in first LE byte\n b[31] |= x & 1n ? 0x80 : 0;\n return b;\n }\n toHex() {\n return bytesToHex(this.toBytes());\n }\n clearCofactor() {\n return this.multiply(big(h), false);\n }\n isSmallOrder() {\n return this.clearCofactor().is0();\n }\n isTorsionFree() {\n // Multiply by big number N. We can't `mul(N)` because of checks. Instead, we `mul(N/2)*2+1`\n let p = this.multiply(N / 2n, false).double();\n if (N % 2n)\n p = p.add(this);\n return p.is0();\n }\n}\n/** Generator / base point */\nconst G = new Point(Gx, Gy, 1n, M(Gx * Gy));\n/** Identity / zero point */\nconst I = new Point(0n, 1n, 1n, 0n);\n// Static aliases\nPoint.BASE = G;\nPoint.ZERO = I;\nconst numTo32bLE = (num) => hexToBytes(padh(assertRange(num, 0n, B256), L2)).reverse();\nconst bytesToNumLE = (b) => big('0x' + bytesToHex(u8fr(abytes(b)).reverse()));\nconst pow2 = (x, power) => {\n // pow2(x, 4) == x^(2^4)\n let r = x;\n while (power-- > 0n) {\n r *= r;\n r %= P;\n }\n return r;\n};\n// prettier-ignore\nconst pow_2_252_3 = (x) => {\n const x2 = (x * x) % P; // x^2, bits 1\n const b2 = (x2 * x) % P; // x^3, bits 11\n const b4 = (pow2(b2, 2n) * b2) % P; // x^(2^4-1), bits 1111\n const b5 = (pow2(b4, 1n) * x) % P; // x^(2^5-1), bits 11111\n const b10 = (pow2(b5, 5n) * b5) % P; // x^(2^10)\n const b20 = (pow2(b10, 10n) * b10) % P; // x^(2^20)\n const b40 = (pow2(b20, 20n) * b20) % P; // x^(2^40)\n const b80 = (pow2(b40, 40n) * b40) % P; // x^(2^80)\n const b160 = (pow2(b80, 80n) * b80) % P; // x^(2^160)\n const b240 = (pow2(b160, 80n) * b80) % P; // x^(2^240)\n const b250 = (pow2(b240, 10n) * b10) % P; // x^(2^250)\n const pow_p_5_8 = (pow2(b250, 2n) * x) % P; // < To pow to (p+3)/8, multiply it by x.\n return { pow_p_5_8, b2 };\n};\nconst RM1 = 0x2b8324804fc1df0b2b4d00993dfbd7a72f431806ad2fe478c4ee1b274a0ea0b0n; // √-1\n// for sqrt comp\n// prettier-ignore\nconst uvRatio = (u, v) => {\n const v3 = M(v * v * v); // v³\n const v7 = M(v3 * v3 * v); // v⁷\n const pow = pow_2_252_3(u * v7).pow_p_5_8; // (uv⁷)^(p-5)/8\n let x = M(u * v3 * pow); // (uv³)(uv⁷)^(p-5)/8\n const vx2 = M(v * x * x); // vx²\n const root1 = x; // First root candidate\n const root2 = M(x * RM1); // Second root candidate; RM1 is √-1\n const useRoot1 = vx2 === u; // If vx² = u (mod p), x is a square root\n const useRoot2 = vx2 === M(-u); // If vx² = -u, set x <-- x * 2^((p-1)/4)\n const noRoot = vx2 === M(-u * RM1); // There is no valid root, vx² = -u√-1\n if (useRoot1)\n x = root1;\n if (useRoot2 || noRoot)\n x = root2; // We return root2 anyway, for const-time\n if ((M(x) & 1n) === 1n)\n x = M(-x); // edIsNegative\n return { isValid: useRoot1 || useRoot2, value: x };\n};\n// N == L, just weird naming\nconst modL_LE = (hash) => modN(bytesToNumLE(hash)); // modulo L; but little-endian\n/** hashes.sha512 should conform to the interface. */\n// TODO: rename\nconst sha512a = (...m) => hashes.sha512Async(concatBytes(...m)); // Async SHA512\nconst sha512s = (...m) => callHash('sha512')(concatBytes(...m));\n// RFC8032 5.1.5\nconst hash2extK = (hashed) => {\n // slice creates a copy, unlike subarray\n const head = hashed.slice(0, L);\n head[0] &= 248; // Clamp bits: 0b1111_1000\n head[31] &= 127; // 0b0111_1111\n head[31] |= 64; // 0b0100_0000\n const prefix = hashed.slice(L, L2); // secret key \"prefix\"\n const scalar = modL_LE(head); // modular division over curve order\n const point = G.multiply(scalar); // public key point\n const pointBytes = point.toBytes(); // point serialized to Uint8Array\n return { head, prefix, scalar, point, pointBytes };\n};\n// RFC8032 5.1.5; getPublicKey async, sync. Hash priv key and extract point.\nconst getExtendedPublicKeyAsync = (secretKey) => sha512a(abytes(secretKey, L)).then(hash2extK);\nconst getExtendedPublicKey = (secretKey) => hash2extK(sha512s(abytes(secretKey, L)));\n/** Creates 32-byte ed25519 public key from 32-byte secret key. Async. */\nconst getPublicKeyAsync = (secretKey) => getExtendedPublicKeyAsync(secretKey).then((p) => p.pointBytes);\n/** Creates 32-byte ed25519 public key from 32-byte secret key. To use, set `hashes.sha512` first. */\nconst getPublicKey = (priv) => getExtendedPublicKey(priv).pointBytes;\nconst hashFinishA = (res) => sha512a(res.hashable).then(res.finish);\nconst hashFinishS = (res) => res.finish(sha512s(res.hashable));\n// Code, shared between sync & async sign\nconst _sign = (e, rBytes, msg) => {\n const { pointBytes: P, scalar: s } = e;\n const r = modL_LE(rBytes); // r was created outside, reduce it modulo L\n const R = G.multiply(r).toBytes(); // R = [r]B\n const hashable = concatBytes(R, P, msg); // dom2(F, C) || R || A || PH(M)\n const finish = (hashed) => {\n // k = SHA512(dom2(F, C) || R || A || PH(M))\n const S = modN(r + modL_LE(hashed) * s); // S = (r + k * s) mod L; 0 <= s < l\n return abytes(concatBytes(R, numTo32bLE(S)), L2); // 64-byte sig: 32b R.x + 32b LE(S)\n };\n return { hashable, finish };\n};\n/**\n * Signs message using secret key. Async.\n * Follows RFC8032 5.1.6.\n */\nconst signAsync = async (message, secretKey) => {\n const m = abytes(message);\n const e = await getExtendedPublicKeyAsync(secretKey);\n const rBytes = await sha512a(e.prefix, m); // r = SHA512(dom2(F, C) || prefix || PH(M))\n return hashFinishA(_sign(e, rBytes, m)); // gen R, k, S, then 64-byte signature\n};\n/**\n * Signs message using secret key. To use, set `hashes.sha512` first.\n * Follows RFC8032 5.1.6.\n */\nconst sign = (message, secretKey) => {\n const m = abytes(message);\n const e = getExtendedPublicKey(secretKey);\n const rBytes = sha512s(e.prefix, m); // r = SHA512(dom2(F, C) || prefix || PH(M))\n return hashFinishS(_sign(e, rBytes, m)); // gen R, k, S, then 64-byte signature\n};\nconst defaultVerifyOpts = { zip215: true };\nconst _verify = (sig, msg, pub, opts = defaultVerifyOpts) => {\n sig = abytes(sig, L2); // Signature hex str/Bytes, must be 64 bytes\n msg = abytes(msg); // Message hex str/Bytes\n pub = abytes(pub, L);\n const { zip215 } = opts; // switch between zip215 and rfc8032 verif\n let A;\n let R;\n let s;\n let SB;\n let hashable = Uint8Array.of();\n try {\n A = Point.fromBytes(pub, zip215); // public key A decoded\n R = Point.fromBytes(sig.slice(0, L), zip215); // 0 <= R < 2^256: ZIP215 R can be >= P\n s = bytesToNumLE(sig.slice(L, L2)); // Decode second half as an integer S\n SB = G.multiply(s, false); // in the range 0 <= s < L\n hashable = concatBytes(R.toBytes(), A.toBytes(), msg); // dom2(F, C) || R || A || PH(M)\n }\n catch (error) { }\n const finish = (hashed) => {\n // k = SHA512(dom2(F, C) || R || A || PH(M))\n if (SB == null)\n return false; // false if try-catch catched an error\n if (!zip215 && A.isSmallOrder())\n return false; // false for SBS: Strongly Binding Signature\n const k = modL_LE(hashed); // decode in little-endian, modulo L\n const RkA = R.add(A.multiply(k, false)); // [8]R + [8][k]A'\n return RkA.add(SB.negate()).clearCofactor().is0(); // [8][S]B = [8]R + [8][k]A'\n };\n return { hashable, finish };\n};\n/** Verifies signature on message and public key. Async. Follows RFC8032 5.1.7. */\nconst verifyAsync = async (signature, message, publicKey, opts = defaultVerifyOpts) => hashFinishA(_verify(signature, message, publicKey, opts));\n/** Verifies signature on message and public key. To use, set `hashes.sha512` first. Follows RFC8032 5.1.7. */\nconst verify = (signature, message, publicKey, opts = defaultVerifyOpts) => hashFinishS(_verify(signature, message, publicKey, opts));\n/** Math, hex, byte helpers. Not in `utils` because utils share API with noble-curves. */\nconst etc = {\n bytesToHex: bytesToHex,\n hexToBytes: hexToBytes,\n concatBytes: concatBytes,\n mod: M,\n invert: invert,\n randomBytes: randomBytes,\n};\nconst hashes = {\n sha512Async: async (message) => {\n const s = subtle();\n const m = concatBytes(message);\n return u8n(await s.digest('SHA-512', m.buffer));\n },\n sha512: undefined,\n};\n// FIPS 186 B.4.1 compliant key generation produces private keys\n// with modulo bias being neglible. takes >N+16 bytes, returns (hash mod n-1)+1\nconst randomSecretKey = (seed = randomBytes(L)) => seed;\nconst keygen = (seed) => {\n const secretKey = randomSecretKey(seed);\n const publicKey = getPublicKey(secretKey);\n return { secretKey, publicKey };\n};\nconst keygenAsync = async (seed) => {\n const secretKey = randomSecretKey(seed);\n const publicKey = await getPublicKeyAsync(secretKey);\n return { secretKey, publicKey };\n};\n/** ed25519-specific key utilities. */\nconst utils = {\n getExtendedPublicKeyAsync: getExtendedPublicKeyAsync,\n getExtendedPublicKey: getExtendedPublicKey,\n randomSecretKey: randomSecretKey,\n};\n// ## Precomputes\n// --------------\nconst W = 8; // W is window size\nconst scalarBits = 256;\nconst pwindows = Math.ceil(scalarBits / W) + 1; // 33 for W=8, NOT 32 - see wNAF loop\nconst pwindowSize = 2 ** (W - 1); // 128 for W=8\nconst precompute = () => {\n const points = [];\n let p = G;\n let b = p;\n for (let w = 0; w < pwindows; w++) {\n b = p;\n points.push(b);\n for (let i = 1; i < pwindowSize; i++) {\n b = b.add(p);\n points.push(b);\n } // i=1, bc we skip 0\n p = b.double();\n }\n return points;\n};\nlet Gpows = undefined; // precomputes for base point G\n// const-time negate\nconst ctneg = (cnd, p) => {\n const n = p.negate();\n return cnd ? n : p;\n};\n/**\n * Precomputes give 12x faster getPublicKey(), 10x sign(), 2x verify() by\n * caching multiples of G (base point). Cache is stored in 32MB of RAM.\n * Any time `G.multiply` is done, precomputes are used.\n * Not used for getSharedSecret, which instead multiplies random pubkey `P.multiply`.\n *\n * w-ary non-adjacent form (wNAF) precomputation method is 10% slower than windowed method,\n * but takes 2x less RAM. RAM reduction is possible by utilizing `.subtract`.\n *\n * !! Precomputes can be disabled by commenting-out call of the wNAF() inside Point#multiply().\n */\nconst wNAF = (n) => {\n const comp = Gpows || (Gpows = precompute());\n let p = I;\n let f = G; // f must be G, or could become I in the end\n const pow_2_w = 2 ** W; // 256 for W=8\n const maxNum = pow_2_w; // 256 for W=8\n const mask = big(pow_2_w - 1); // 255 for W=8 == mask 0b11111111\n const shiftBy = big(W); // 8 for W=8\n for (let w = 0; w < pwindows; w++) {\n let wbits = Number(n & mask); // extract W bits.\n n >>= shiftBy; // shift number by W bits.\n // We use negative indexes to reduce size of precomputed table by 2x.\n // Instead of needing precomputes 0..256, we only calculate them for 0..128.\n // If an index > 128 is found, we do (256-index) - where 256 is next window.\n // Naive: index +127 => 127, +224 => 224\n // Optimized: index +127 => 127, +224 => 256-32\n if (wbits > pwindowSize) {\n wbits -= maxNum;\n n += 1n;\n }\n const off = w * pwindowSize;\n const offF = off; // offsets, evaluate both\n const offP = off + Math.abs(wbits) - 1;\n const isEven = w % 2 !== 0; // conditions, evaluate both\n const isNeg = wbits < 0;\n if (wbits === 0) {\n // off == I: can't add it. Adding random offF instead.\n f = f.add(ctneg(isEven, comp[offF])); // bits are 0: add garbage to fake point\n }\n else {\n p = p.add(ctneg(isNeg, comp[offP])); // bits are 1: add to result point\n }\n }\n if (n !== 0n)\n err('invalid wnaf');\n return { p, f }; // return both real and fake points for JIT\n};\n// !! Remove the export to easily use in REPL / browser console\nexport { etc, getPublicKey, getPublicKeyAsync, hash, hashes, keygen, keygenAsync, Point, sign, signAsync, utils, verify, verifyAsync, };\n","import { getPublicKeyAsync, signAsync, utils } from \"@noble/ed25519\";\n\ntype StoredIdentity = {\n version: 1;\n deviceId: string;\n publicKey: string;\n privateKey: string;\n createdAtMs: number;\n};\n\nexport type DeviceIdentity = {\n deviceId: string;\n publicKey: string;\n privateKey: string;\n};\n\nconst STORAGE_KEY = \"clawdbot-device-identity-v1\";\n\nfunction base64UrlEncode(bytes: Uint8Array): string {\n let binary = \"\";\n for (const byte of bytes) binary += String.fromCharCode(byte);\n return btoa(binary).replaceAll(\"+\", \"-\").replaceAll(\"/\", \"_\").replace(/=+$/g, \"\");\n}\n\nfunction base64UrlDecode(input: string): Uint8Array {\n const normalized = input.replaceAll(\"-\", \"+\").replaceAll(\"_\", \"/\");\n const padded = normalized + \"=\".repeat((4 - (normalized.length % 4)) % 4);\n const binary = atob(padded);\n const out = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i += 1) out[i] = binary.charCodeAt(i);\n return out;\n}\n\nfunction bytesToHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\nasync function fingerprintPublicKey(publicKey: Uint8Array): Promise {\n const hash = await crypto.subtle.digest(\"SHA-256\", publicKey);\n return bytesToHex(new Uint8Array(hash));\n}\n\nasync function generateIdentity(): Promise {\n const privateKey = utils.randomSecretKey();\n const publicKey = await getPublicKeyAsync(privateKey);\n const deviceId = await fingerprintPublicKey(publicKey);\n return {\n deviceId,\n publicKey: base64UrlEncode(publicKey),\n privateKey: base64UrlEncode(privateKey),\n };\n}\n\nexport async function loadOrCreateDeviceIdentity(): Promise {\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (raw) {\n const parsed = JSON.parse(raw) as StoredIdentity;\n if (\n parsed?.version === 1 &&\n typeof parsed.deviceId === \"string\" &&\n typeof parsed.publicKey === \"string\" &&\n typeof parsed.privateKey === \"string\"\n ) {\n const derivedId = await fingerprintPublicKey(base64UrlDecode(parsed.publicKey));\n if (derivedId !== parsed.deviceId) {\n const updated: StoredIdentity = {\n ...parsed,\n deviceId: derivedId,\n };\n localStorage.setItem(STORAGE_KEY, JSON.stringify(updated));\n return {\n deviceId: derivedId,\n publicKey: parsed.publicKey,\n privateKey: parsed.privateKey,\n };\n }\n return {\n deviceId: parsed.deviceId,\n publicKey: parsed.publicKey,\n privateKey: parsed.privateKey,\n };\n }\n }\n } catch {\n // fall through to regenerate\n }\n\n const identity = await generateIdentity();\n const stored: StoredIdentity = {\n version: 1,\n deviceId: identity.deviceId,\n publicKey: identity.publicKey,\n privateKey: identity.privateKey,\n createdAtMs: Date.now(),\n };\n localStorage.setItem(STORAGE_KEY, JSON.stringify(stored));\n return identity;\n}\n\nexport async function signDevicePayload(privateKeyBase64Url: string, payload: string) {\n const key = base64UrlDecode(privateKeyBase64Url);\n const data = new TextEncoder().encode(payload);\n const sig = await signAsync(data, key);\n return base64UrlEncode(sig);\n}\n","export type DeviceAuthEntry = {\n token: string;\n role: string;\n scopes: string[];\n updatedAtMs: number;\n};\n\ntype DeviceAuthStore = {\n version: 1;\n deviceId: string;\n tokens: Record;\n};\n\nconst STORAGE_KEY = \"clawdbot.device.auth.v1\";\n\nfunction normalizeRole(role: string): string {\n return role.trim();\n}\n\nfunction normalizeScopes(scopes: string[] | undefined): string[] {\n if (!Array.isArray(scopes)) return [];\n const out = new Set();\n for (const scope of scopes) {\n const trimmed = scope.trim();\n if (trimmed) out.add(trimmed);\n }\n return [...out].sort();\n}\n\nfunction readStore(): DeviceAuthStore | null {\n try {\n const raw = window.localStorage.getItem(STORAGE_KEY);\n if (!raw) return null;\n const parsed = JSON.parse(raw) as DeviceAuthStore;\n if (!parsed || parsed.version !== 1) return null;\n if (!parsed.deviceId || typeof parsed.deviceId !== \"string\") return null;\n if (!parsed.tokens || typeof parsed.tokens !== \"object\") return null;\n return parsed;\n } catch {\n return null;\n }\n}\n\nfunction writeStore(store: DeviceAuthStore) {\n try {\n window.localStorage.setItem(STORAGE_KEY, JSON.stringify(store));\n } catch {\n // best-effort\n }\n}\n\nexport function loadDeviceAuthToken(params: {\n deviceId: string;\n role: string;\n}): DeviceAuthEntry | null {\n const store = readStore();\n if (!store || store.deviceId !== params.deviceId) return null;\n const role = normalizeRole(params.role);\n const entry = store.tokens[role];\n if (!entry || typeof entry.token !== \"string\") return null;\n return entry;\n}\n\nexport function storeDeviceAuthToken(params: {\n deviceId: string;\n role: string;\n token: string;\n scopes?: string[];\n}): DeviceAuthEntry {\n const role = normalizeRole(params.role);\n const next: DeviceAuthStore = {\n version: 1,\n deviceId: params.deviceId,\n tokens: {},\n };\n const existing = readStore();\n if (existing && existing.deviceId === params.deviceId) {\n next.tokens = { ...existing.tokens };\n }\n const entry: DeviceAuthEntry = {\n token: params.token,\n role,\n scopes: normalizeScopes(params.scopes),\n updatedAtMs: Date.now(),\n };\n next.tokens[role] = entry;\n writeStore(next);\n return entry;\n}\n\nexport function clearDeviceAuthToken(params: { deviceId: string; role: string }) {\n const store = readStore();\n if (!store || store.deviceId !== params.deviceId) return;\n const role = normalizeRole(params.role);\n if (!store.tokens[role]) return;\n const next = { ...store, tokens: { ...store.tokens } };\n delete next.tokens[role];\n writeStore(next);\n}\n","import type { GatewayBrowserClient } from \"../gateway\";\nimport { loadOrCreateDeviceIdentity } from \"../device-identity\";\nimport { clearDeviceAuthToken, storeDeviceAuthToken } from \"../device-auth\";\n\nexport type DeviceTokenSummary = {\n role: string;\n scopes?: string[];\n createdAtMs?: number;\n rotatedAtMs?: number;\n revokedAtMs?: number;\n lastUsedAtMs?: number;\n};\n\nexport type PendingDevice = {\n requestId: string;\n deviceId: string;\n displayName?: string;\n role?: string;\n remoteIp?: string;\n isRepair?: boolean;\n ts?: number;\n};\n\nexport type PairedDevice = {\n deviceId: string;\n displayName?: string;\n roles?: string[];\n scopes?: string[];\n remoteIp?: string;\n tokens?: DeviceTokenSummary[];\n createdAtMs?: number;\n approvedAtMs?: number;\n};\n\nexport type DevicePairingList = {\n pending: PendingDevice[];\n paired: PairedDevice[];\n};\n\nexport type DevicesState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n devicesLoading: boolean;\n devicesError: string | null;\n devicesList: DevicePairingList | null;\n};\n\nexport async function loadDevices(state: DevicesState, opts?: { quiet?: boolean }) {\n if (!state.client || !state.connected) return;\n if (state.devicesLoading) return;\n state.devicesLoading = true;\n if (!opts?.quiet) state.devicesError = null;\n try {\n const res = (await state.client.request(\"device.pair.list\", {})) as DevicePairingList | null;\n state.devicesList = {\n pending: Array.isArray(res?.pending) ? res!.pending : [],\n paired: Array.isArray(res?.paired) ? res!.paired : [],\n };\n } catch (err) {\n if (!opts?.quiet) state.devicesError = String(err);\n } finally {\n state.devicesLoading = false;\n }\n}\n\nexport async function approveDevicePairing(state: DevicesState, requestId: string) {\n if (!state.client || !state.connected) return;\n try {\n await state.client.request(\"device.pair.approve\", { requestId });\n await loadDevices(state);\n } catch (err) {\n state.devicesError = String(err);\n }\n}\n\nexport async function rejectDevicePairing(state: DevicesState, requestId: string) {\n if (!state.client || !state.connected) return;\n const confirmed = window.confirm(\"Reject this device pairing request?\");\n if (!confirmed) return;\n try {\n await state.client.request(\"device.pair.reject\", { requestId });\n await loadDevices(state);\n } catch (err) {\n state.devicesError = String(err);\n }\n}\n\nexport async function rotateDeviceToken(\n state: DevicesState,\n params: { deviceId: string; role: string; scopes?: string[] },\n) {\n if (!state.client || !state.connected) return;\n try {\n const res = (await state.client.request(\"device.token.rotate\", params)) as\n | { token?: string; role?: string; deviceId?: string; scopes?: string[] }\n | undefined;\n if (res?.token) {\n const identity = await loadOrCreateDeviceIdentity();\n const role = res.role ?? params.role;\n if (res.deviceId === identity.deviceId || params.deviceId === identity.deviceId) {\n storeDeviceAuthToken({\n deviceId: identity.deviceId,\n role,\n token: res.token,\n scopes: res.scopes ?? params.scopes ?? [],\n });\n }\n window.prompt(\"New device token (copy and store securely):\", res.token);\n }\n await loadDevices(state);\n } catch (err) {\n state.devicesError = String(err);\n }\n}\n\nexport async function revokeDeviceToken(\n state: DevicesState,\n params: { deviceId: string; role: string },\n) {\n if (!state.client || !state.connected) return;\n const confirmed = window.confirm(\n `Revoke token for ${params.deviceId} (${params.role})?`,\n );\n if (!confirmed) return;\n try {\n await state.client.request(\"device.token.revoke\", params);\n const identity = await loadOrCreateDeviceIdentity();\n if (params.deviceId === identity.deviceId) {\n clearDeviceAuthToken({ deviceId: identity.deviceId, role: params.role });\n }\n await loadDevices(state);\n } catch (err) {\n state.devicesError = String(err);\n }\n}\n","import type { GatewayBrowserClient } from \"../gateway\";\n\nexport type NodesState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n nodesLoading: boolean;\n nodes: Array>;\n lastError: string | null;\n};\n\nexport async function loadNodes(\n state: NodesState,\n opts?: { quiet?: boolean },\n) {\n if (!state.client || !state.connected) return;\n if (state.nodesLoading) return;\n state.nodesLoading = true;\n if (!opts?.quiet) state.lastError = null;\n try {\n const res = (await state.client.request(\"node.list\", {})) as {\n nodes?: Array>;\n };\n state.nodes = Array.isArray(res.nodes) ? res.nodes : [];\n } catch (err) {\n if (!opts?.quiet) state.lastError = String(err);\n } finally {\n state.nodesLoading = false;\n }\n}\n","import type { GatewayBrowserClient } from \"../gateway\";\nimport { cloneConfigObject, removePathValue, setPathValue } from \"./config/form-utils\";\n\nexport type ExecApprovalsDefaults = {\n security?: string;\n ask?: string;\n askFallback?: string;\n autoAllowSkills?: boolean;\n};\n\nexport type ExecApprovalsAllowlistEntry = {\n id?: string;\n pattern: string;\n lastUsedAt?: number;\n lastUsedCommand?: string;\n lastResolvedPath?: string;\n};\n\nexport type ExecApprovalsAgent = ExecApprovalsDefaults & {\n allowlist?: ExecApprovalsAllowlistEntry[];\n};\n\nexport type ExecApprovalsFile = {\n version?: number;\n socket?: { path?: string };\n defaults?: ExecApprovalsDefaults;\n agents?: Record;\n};\n\nexport type ExecApprovalsSnapshot = {\n path: string;\n exists: boolean;\n hash: string;\n file: ExecApprovalsFile;\n};\n\nexport type ExecApprovalsTarget =\n | { kind: \"gateway\" }\n | { kind: \"node\"; nodeId: string };\n\nexport type ExecApprovalsState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n execApprovalsLoading: boolean;\n execApprovalsSaving: boolean;\n execApprovalsDirty: boolean;\n execApprovalsSnapshot: ExecApprovalsSnapshot | null;\n execApprovalsForm: ExecApprovalsFile | null;\n execApprovalsSelectedAgent: string | null;\n lastError: string | null;\n};\n\nfunction resolveExecApprovalsRpc(target?: ExecApprovalsTarget | null): {\n method: string;\n params: Record;\n} | null {\n if (!target || target.kind === \"gateway\") {\n return { method: \"exec.approvals.get\", params: {} };\n }\n const nodeId = target.nodeId.trim();\n if (!nodeId) return null;\n return { method: \"exec.approvals.node.get\", params: { nodeId } };\n}\n\nfunction resolveExecApprovalsSaveRpc(\n target: ExecApprovalsTarget | null | undefined,\n params: { file: ExecApprovalsFile; baseHash: string },\n): { method: string; params: Record } | null {\n if (!target || target.kind === \"gateway\") {\n return { method: \"exec.approvals.set\", params };\n }\n const nodeId = target.nodeId.trim();\n if (!nodeId) return null;\n return { method: \"exec.approvals.node.set\", params: { ...params, nodeId } };\n}\n\nexport async function loadExecApprovals(\n state: ExecApprovalsState,\n target?: ExecApprovalsTarget | null,\n) {\n if (!state.client || !state.connected) return;\n if (state.execApprovalsLoading) return;\n state.execApprovalsLoading = true;\n state.lastError = null;\n try {\n const rpc = resolveExecApprovalsRpc(target);\n if (!rpc) {\n state.lastError = \"Select a node before loading exec approvals.\";\n return;\n }\n const res = (await state.client.request(rpc.method, rpc.params)) as ExecApprovalsSnapshot;\n applyExecApprovalsSnapshot(state, res);\n } catch (err) {\n state.lastError = String(err);\n } finally {\n state.execApprovalsLoading = false;\n }\n}\n\nexport function applyExecApprovalsSnapshot(\n state: ExecApprovalsState,\n snapshot: ExecApprovalsSnapshot,\n) {\n state.execApprovalsSnapshot = snapshot;\n if (!state.execApprovalsDirty) {\n state.execApprovalsForm = cloneConfigObject(snapshot.file ?? {});\n }\n}\n\nexport async function saveExecApprovals(\n state: ExecApprovalsState,\n target?: ExecApprovalsTarget | null,\n) {\n if (!state.client || !state.connected) return;\n state.execApprovalsSaving = true;\n state.lastError = null;\n try {\n const baseHash = state.execApprovalsSnapshot?.hash;\n if (!baseHash) {\n state.lastError = \"Exec approvals hash missing; reload and retry.\";\n return;\n }\n const file =\n state.execApprovalsForm ??\n state.execApprovalsSnapshot?.file ??\n {};\n const rpc = resolveExecApprovalsSaveRpc(target, { file, baseHash });\n if (!rpc) {\n state.lastError = \"Select a node before saving exec approvals.\";\n return;\n }\n await state.client.request(rpc.method, rpc.params);\n state.execApprovalsDirty = false;\n await loadExecApprovals(state, target);\n } catch (err) {\n state.lastError = String(err);\n } finally {\n state.execApprovalsSaving = false;\n }\n}\n\nexport function updateExecApprovalsFormValue(\n state: ExecApprovalsState,\n path: Array,\n value: unknown,\n) {\n const base = cloneConfigObject(\n state.execApprovalsForm ?? state.execApprovalsSnapshot?.file ?? {},\n );\n setPathValue(base, path, value);\n state.execApprovalsForm = base;\n state.execApprovalsDirty = true;\n}\n\nexport function removeExecApprovalsFormValue(\n state: ExecApprovalsState,\n path: Array,\n) {\n const base = cloneConfigObject(\n state.execApprovalsForm ?? state.execApprovalsSnapshot?.file ?? {},\n );\n removePathValue(base, path);\n state.execApprovalsForm = base;\n state.execApprovalsDirty = true;\n}\n","import type { GatewayBrowserClient } from \"../gateway\";\nimport type { PresenceEntry } from \"../types\";\n\nexport type PresenceState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n presenceLoading: boolean;\n presenceEntries: PresenceEntry[];\n presenceError: string | null;\n presenceStatus: string | null;\n};\n\nexport async function loadPresence(state: PresenceState) {\n if (!state.client || !state.connected) return;\n if (state.presenceLoading) return;\n state.presenceLoading = true;\n state.presenceError = null;\n state.presenceStatus = null;\n try {\n const res = (await state.client.request(\"system-presence\", {})) as\n | PresenceEntry[]\n | undefined;\n if (Array.isArray(res)) {\n state.presenceEntries = res;\n state.presenceStatus = res.length === 0 ? \"No instances yet.\" : null;\n } else {\n state.presenceEntries = [];\n state.presenceStatus = \"No presence payload.\";\n }\n } catch (err) {\n state.presenceError = String(err);\n } finally {\n state.presenceLoading = false;\n }\n}\n\n","import type { GatewayBrowserClient } from \"../gateway\";\nimport type { SkillStatusReport } from \"../types\";\n\nexport type SkillsState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n skillsLoading: boolean;\n skillsReport: SkillStatusReport | null;\n skillsError: string | null;\n skillsBusyKey: string | null;\n skillEdits: Record;\n skillMessages: SkillMessageMap;\n};\n\nexport type SkillMessage = {\n kind: \"success\" | \"error\";\n message: string;\n};\n\nexport type SkillMessageMap = Record;\n\ntype LoadSkillsOptions = {\n clearMessages?: boolean;\n};\n\nfunction setSkillMessage(state: SkillsState, key: string, message?: SkillMessage) {\n if (!key.trim()) return;\n const next = { ...state.skillMessages };\n if (message) next[key] = message;\n else delete next[key];\n state.skillMessages = next;\n}\n\nfunction getErrorMessage(err: unknown) {\n if (err instanceof Error) return err.message;\n return String(err);\n}\n\nexport async function loadSkills(state: SkillsState, options?: LoadSkillsOptions) {\n if (options?.clearMessages && Object.keys(state.skillMessages).length > 0) {\n state.skillMessages = {};\n }\n if (!state.client || !state.connected) return;\n if (state.skillsLoading) return;\n state.skillsLoading = true;\n state.skillsError = null;\n try {\n const res = (await state.client.request(\"skills.status\", {})) as\n | SkillStatusReport\n | undefined;\n if (res) state.skillsReport = res;\n } catch (err) {\n state.skillsError = getErrorMessage(err);\n } finally {\n state.skillsLoading = false;\n }\n}\n\nexport function updateSkillEdit(\n state: SkillsState,\n skillKey: string,\n value: string,\n) {\n state.skillEdits = { ...state.skillEdits, [skillKey]: value };\n}\n\nexport async function updateSkillEnabled(\n state: SkillsState,\n skillKey: string,\n enabled: boolean,\n) {\n if (!state.client || !state.connected) return;\n state.skillsBusyKey = skillKey;\n state.skillsError = null;\n try {\n await state.client.request(\"skills.update\", { skillKey, enabled });\n await loadSkills(state);\n setSkillMessage(state, skillKey, {\n kind: \"success\",\n message: enabled ? \"Skill enabled\" : \"Skill disabled\",\n });\n } catch (err) {\n const message = getErrorMessage(err);\n state.skillsError = message;\n setSkillMessage(state, skillKey, {\n kind: \"error\",\n message,\n });\n } finally {\n state.skillsBusyKey = null;\n }\n}\n\nexport async function saveSkillApiKey(state: SkillsState, skillKey: string) {\n if (!state.client || !state.connected) return;\n state.skillsBusyKey = skillKey;\n state.skillsError = null;\n try {\n const apiKey = state.skillEdits[skillKey] ?? \"\";\n await state.client.request(\"skills.update\", { skillKey, apiKey });\n await loadSkills(state);\n setSkillMessage(state, skillKey, {\n kind: \"success\",\n message: \"API key saved\",\n });\n } catch (err) {\n const message = getErrorMessage(err);\n state.skillsError = message;\n setSkillMessage(state, skillKey, {\n kind: \"error\",\n message,\n });\n } finally {\n state.skillsBusyKey = null;\n }\n}\n\nexport async function installSkill(\n state: SkillsState,\n skillKey: string,\n name: string,\n installId: string,\n) {\n if (!state.client || !state.connected) return;\n state.skillsBusyKey = skillKey;\n state.skillsError = null;\n try {\n const result = (await state.client.request(\"skills.install\", {\n name,\n installId,\n timeoutMs: 120000,\n })) as { ok?: boolean; message?: string };\n await loadSkills(state);\n setSkillMessage(state, skillKey, {\n kind: \"success\",\n message: result?.message ?? \"Installed\",\n });\n } catch (err) {\n const message = getErrorMessage(err);\n state.skillsError = message;\n setSkillMessage(state, skillKey, {\n kind: \"error\",\n message,\n });\n } finally {\n state.skillsBusyKey = null;\n }\n}\n","export type ThemeMode = \"system\" | \"light\" | \"dark\";\nexport type ResolvedTheme = \"light\" | \"dark\";\n\nexport function getSystemTheme(): ResolvedTheme {\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") {\n return \"dark\";\n }\n return window.matchMedia(\"(prefers-color-scheme: dark)\").matches\n ? \"dark\"\n : \"light\";\n}\n\nexport function resolveTheme(mode: ThemeMode): ResolvedTheme {\n if (mode === \"system\") return getSystemTheme();\n return mode;\n}\n","import type { ThemeMode } from \"./theme\";\n\nexport type ThemeTransitionContext = {\n element?: HTMLElement | null;\n pointerClientX?: number;\n pointerClientY?: number;\n};\n\nexport type ThemeTransitionOptions = {\n nextTheme: ThemeMode;\n applyTheme: () => void;\n context?: ThemeTransitionContext;\n currentTheme?: ThemeMode | null;\n};\n\ntype DocumentWithViewTransition = Document & {\n startViewTransition?: (callback: () => void) => { finished: Promise };\n};\n\nconst clamp01 = (value: number) => {\n if (Number.isNaN(value)) return 0.5;\n if (value <= 0) return 0;\n if (value >= 1) return 1;\n return value;\n};\n\nconst hasReducedMotionPreference = () => {\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") {\n return false;\n }\n return window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches ?? false;\n};\n\nconst cleanupThemeTransition = (root: HTMLElement) => {\n root.classList.remove(\"theme-transition\");\n root.style.removeProperty(\"--theme-switch-x\");\n root.style.removeProperty(\"--theme-switch-y\");\n};\n\nexport const startThemeTransition = ({\n nextTheme,\n applyTheme,\n context,\n currentTheme,\n}: ThemeTransitionOptions) => {\n if (currentTheme === nextTheme) return;\n\n const documentReference = globalThis.document ?? null;\n if (!documentReference) {\n applyTheme();\n return;\n }\n\n const root = documentReference.documentElement;\n const document_ = documentReference as DocumentWithViewTransition;\n const prefersReducedMotion = hasReducedMotionPreference();\n\n const canUseViewTransition =\n Boolean(document_.startViewTransition) && !prefersReducedMotion;\n\n if (canUseViewTransition) {\n let xPercent = 0.5;\n let yPercent = 0.5;\n\n if (\n context?.pointerClientX !== undefined &&\n context?.pointerClientY !== undefined &&\n typeof window !== \"undefined\"\n ) {\n xPercent = clamp01(context.pointerClientX / window.innerWidth);\n yPercent = clamp01(context.pointerClientY / window.innerHeight);\n } else if (context?.element) {\n const rect = context.element.getBoundingClientRect();\n if (\n rect.width > 0 &&\n rect.height > 0 &&\n typeof window !== \"undefined\"\n ) {\n xPercent = clamp01((rect.left + rect.width / 2) / window.innerWidth);\n yPercent = clamp01((rect.top + rect.height / 2) / window.innerHeight);\n }\n }\n\n root.style.setProperty(\"--theme-switch-x\", `${xPercent * 100}%`);\n root.style.setProperty(\"--theme-switch-y\", `${yPercent * 100}%`);\n root.classList.add(\"theme-transition\");\n\n try {\n const transition = document_.startViewTransition?.(() => {\n applyTheme();\n });\n if (transition?.finished) {\n void transition.finished.finally(() => cleanupThemeTransition(root));\n } else {\n cleanupThemeTransition(root);\n }\n } catch {\n cleanupThemeTransition(root);\n applyTheme();\n }\n return;\n }\n\n applyTheme();\n cleanupThemeTransition(root);\n};\n","import { loadLogs } from \"./controllers/logs\";\nimport { loadNodes } from \"./controllers/nodes\";\nimport { loadDebug } from \"./controllers/debug\";\nimport type { ClawdbotApp } from \"./app\";\n\ntype PollingHost = {\n nodesPollInterval: number | null;\n logsPollInterval: number | null;\n debugPollInterval: number | null;\n tab: string;\n};\n\nexport function startNodesPolling(host: PollingHost) {\n if (host.nodesPollInterval != null) return;\n host.nodesPollInterval = window.setInterval(\n () => void loadNodes(host as unknown as ClawdbotApp, { quiet: true }),\n 5000,\n );\n}\n\nexport function stopNodesPolling(host: PollingHost) {\n if (host.nodesPollInterval == null) return;\n clearInterval(host.nodesPollInterval);\n host.nodesPollInterval = null;\n}\n\nexport function startLogsPolling(host: PollingHost) {\n if (host.logsPollInterval != null) return;\n host.logsPollInterval = window.setInterval(() => {\n if (host.tab !== \"logs\") return;\n void loadLogs(host as unknown as ClawdbotApp, { quiet: true });\n }, 2000);\n}\n\nexport function stopLogsPolling(host: PollingHost) {\n if (host.logsPollInterval == null) return;\n clearInterval(host.logsPollInterval);\n host.logsPollInterval = null;\n}\n\nexport function startDebugPolling(host: PollingHost) {\n if (host.debugPollInterval != null) return;\n host.debugPollInterval = window.setInterval(() => {\n if (host.tab !== \"debug\") return;\n void loadDebug(host as unknown as ClawdbotApp);\n }, 3000);\n}\n\nexport function stopDebugPolling(host: PollingHost) {\n if (host.debugPollInterval == null) return;\n clearInterval(host.debugPollInterval);\n host.debugPollInterval = null;\n}\n","import { loadConfig, loadConfigSchema } from \"./controllers/config\";\nimport { loadCronJobs, loadCronStatus } from \"./controllers/cron\";\nimport { loadChannels } from \"./controllers/channels\";\nimport { loadDebug } from \"./controllers/debug\";\nimport { loadLogs } from \"./controllers/logs\";\nimport { loadDevices } from \"./controllers/devices\";\nimport { loadNodes } from \"./controllers/nodes\";\nimport { loadExecApprovals } from \"./controllers/exec-approvals\";\nimport { loadPresence } from \"./controllers/presence\";\nimport { loadSessions } from \"./controllers/sessions\";\nimport { loadSkills } from \"./controllers/skills\";\nimport { inferBasePathFromPathname, normalizeBasePath, normalizePath, pathForTab, tabFromPath, type Tab } from \"./navigation\";\nimport { saveSettings, type UiSettings } from \"./storage\";\nimport { resolveTheme, type ResolvedTheme, type ThemeMode } from \"./theme\";\nimport { startThemeTransition, type ThemeTransitionContext } from \"./theme-transition\";\nimport { scheduleChatScroll, scheduleLogsScroll } from \"./app-scroll\";\nimport { startLogsPolling, stopLogsPolling, startDebugPolling, stopDebugPolling } from \"./app-polling\";\nimport { refreshChat } from \"./app-chat\";\nimport type { ClawdbotApp } from \"./app\";\n\ntype SettingsHost = {\n settings: UiSettings;\n theme: ThemeMode;\n themeResolved: ResolvedTheme;\n applySessionKey: string;\n sessionKey: string;\n tab: Tab;\n connected: boolean;\n chatHasAutoScrolled: boolean;\n logsAtBottom: boolean;\n eventLog: unknown[];\n eventLogBuffer: unknown[];\n basePath: string;\n themeMedia: MediaQueryList | null;\n themeMediaHandler: ((event: MediaQueryListEvent) => void) | null;\n};\n\nexport function applySettings(host: SettingsHost, next: UiSettings) {\n const normalized = {\n ...next,\n lastActiveSessionKey: next.lastActiveSessionKey?.trim() || next.sessionKey.trim() || \"main\",\n };\n host.settings = normalized;\n saveSettings(normalized);\n if (next.theme !== host.theme) {\n host.theme = next.theme;\n applyResolvedTheme(host, resolveTheme(next.theme));\n }\n host.applySessionKey = host.settings.lastActiveSessionKey;\n}\n\nexport function setLastActiveSessionKey(host: SettingsHost, next: string) {\n const trimmed = next.trim();\n if (!trimmed) return;\n if (host.settings.lastActiveSessionKey === trimmed) return;\n applySettings(host, { ...host.settings, lastActiveSessionKey: trimmed });\n}\n\nexport function applySettingsFromUrl(host: SettingsHost) {\n if (!window.location.search) return;\n const params = new URLSearchParams(window.location.search);\n const tokenRaw = params.get(\"token\");\n const passwordRaw = params.get(\"password\");\n const sessionRaw = params.get(\"session\");\n const gatewayUrlRaw = params.get(\"gatewayUrl\");\n let shouldCleanUrl = false;\n\n if (tokenRaw != null) {\n const token = tokenRaw.trim();\n if (token && token !== host.settings.token) {\n applySettings(host, { ...host.settings, token });\n }\n params.delete(\"token\");\n shouldCleanUrl = true;\n }\n\n if (passwordRaw != null) {\n const password = passwordRaw.trim();\n if (password) {\n (host as { password: string }).password = password;\n }\n params.delete(\"password\");\n shouldCleanUrl = true;\n }\n\n if (sessionRaw != null) {\n const session = sessionRaw.trim();\n if (session) {\n host.sessionKey = session;\n applySettings(host, {\n ...host.settings,\n sessionKey: session,\n lastActiveSessionKey: session,\n });\n }\n }\n\n if (gatewayUrlRaw != null) {\n const gatewayUrl = gatewayUrlRaw.trim();\n if (gatewayUrl && gatewayUrl !== host.settings.gatewayUrl) {\n applySettings(host, { ...host.settings, gatewayUrl });\n }\n params.delete(\"gatewayUrl\");\n shouldCleanUrl = true;\n }\n\n if (!shouldCleanUrl) return;\n const url = new URL(window.location.href);\n url.search = params.toString();\n window.history.replaceState({}, \"\", url.toString());\n}\n\nexport function setTab(host: SettingsHost, next: Tab) {\n if (host.tab !== next) host.tab = next;\n if (next === \"chat\") host.chatHasAutoScrolled = false;\n if (next === \"logs\")\n startLogsPolling(host as unknown as Parameters[0]);\n else stopLogsPolling(host as unknown as Parameters[0]);\n if (next === \"debug\")\n startDebugPolling(host as unknown as Parameters[0]);\n else stopDebugPolling(host as unknown as Parameters[0]);\n void refreshActiveTab(host);\n syncUrlWithTab(host, next, false);\n}\n\nexport function setTheme(\n host: SettingsHost,\n next: ThemeMode,\n context?: ThemeTransitionContext,\n) {\n const applyTheme = () => {\n host.theme = next;\n applySettings(host, { ...host.settings, theme: next });\n applyResolvedTheme(host, resolveTheme(next));\n };\n startThemeTransition({\n nextTheme: next,\n applyTheme,\n context,\n currentTheme: host.theme,\n });\n}\n\nexport async function refreshActiveTab(host: SettingsHost) {\n if (host.tab === \"overview\") await loadOverview(host);\n if (host.tab === \"channels\") await loadChannelsTab(host);\n if (host.tab === \"instances\") await loadPresence(host as unknown as ClawdbotApp);\n if (host.tab === \"sessions\") await loadSessions(host as unknown as ClawdbotApp);\n if (host.tab === \"cron\") await loadCron(host);\n if (host.tab === \"skills\") await loadSkills(host as unknown as ClawdbotApp);\n if (host.tab === \"nodes\") {\n await loadNodes(host as unknown as ClawdbotApp);\n await loadDevices(host as unknown as ClawdbotApp);\n await loadConfig(host as unknown as ClawdbotApp);\n await loadExecApprovals(host as unknown as ClawdbotApp);\n }\n if (host.tab === \"chat\") {\n await refreshChat(host as unknown as Parameters[0]);\n scheduleChatScroll(\n host as unknown as Parameters[0],\n !host.chatHasAutoScrolled,\n );\n }\n if (host.tab === \"config\") {\n await loadConfigSchema(host as unknown as ClawdbotApp);\n await loadConfig(host as unknown as ClawdbotApp);\n }\n if (host.tab === \"debug\") {\n await loadDebug(host as unknown as ClawdbotApp);\n host.eventLog = host.eventLogBuffer;\n }\n if (host.tab === \"logs\") {\n host.logsAtBottom = true;\n await loadLogs(host as unknown as ClawdbotApp, { reset: true });\n scheduleLogsScroll(\n host as unknown as Parameters[0],\n true,\n );\n }\n}\n\nexport function inferBasePath() {\n if (typeof window === \"undefined\") return \"\";\n const configured = window.__CLAWDBOT_CONTROL_UI_BASE_PATH__;\n if (typeof configured === \"string\" && configured.trim()) {\n return normalizeBasePath(configured);\n }\n return inferBasePathFromPathname(window.location.pathname);\n}\n\nexport function syncThemeWithSettings(host: SettingsHost) {\n host.theme = host.settings.theme ?? \"system\";\n applyResolvedTheme(host, resolveTheme(host.theme));\n}\n\nexport function applyResolvedTheme(host: SettingsHost, resolved: ResolvedTheme) {\n host.themeResolved = resolved;\n if (typeof document === \"undefined\") return;\n const root = document.documentElement;\n root.dataset.theme = resolved;\n root.style.colorScheme = resolved;\n}\n\nexport function attachThemeListener(host: SettingsHost) {\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") return;\n host.themeMedia = window.matchMedia(\"(prefers-color-scheme: dark)\");\n host.themeMediaHandler = (event) => {\n if (host.theme !== \"system\") return;\n applyResolvedTheme(host, event.matches ? \"dark\" : \"light\");\n };\n if (typeof host.themeMedia.addEventListener === \"function\") {\n host.themeMedia.addEventListener(\"change\", host.themeMediaHandler);\n return;\n }\n const legacy = host.themeMedia as MediaQueryList & {\n addListener: (cb: (event: MediaQueryListEvent) => void) => void;\n };\n legacy.addListener(host.themeMediaHandler);\n}\n\nexport function detachThemeListener(host: SettingsHost) {\n if (!host.themeMedia || !host.themeMediaHandler) return;\n if (typeof host.themeMedia.removeEventListener === \"function\") {\n host.themeMedia.removeEventListener(\"change\", host.themeMediaHandler);\n return;\n }\n const legacy = host.themeMedia as MediaQueryList & {\n removeListener: (cb: (event: MediaQueryListEvent) => void) => void;\n };\n legacy.removeListener(host.themeMediaHandler);\n host.themeMedia = null;\n host.themeMediaHandler = null;\n}\n\nexport function syncTabWithLocation(host: SettingsHost, replace: boolean) {\n if (typeof window === \"undefined\") return;\n const resolved = tabFromPath(window.location.pathname, host.basePath) ?? \"chat\";\n setTabFromRoute(host, resolved);\n syncUrlWithTab(host, resolved, replace);\n}\n\nexport function onPopState(host: SettingsHost) {\n if (typeof window === \"undefined\") return;\n const resolved = tabFromPath(window.location.pathname, host.basePath);\n if (!resolved) return;\n\n const url = new URL(window.location.href);\n const session = url.searchParams.get(\"session\")?.trim();\n if (session) {\n host.sessionKey = session;\n applySettings(host, {\n ...host.settings,\n sessionKey: session,\n lastActiveSessionKey: session,\n });\n }\n\n setTabFromRoute(host, resolved);\n}\n\nexport function setTabFromRoute(host: SettingsHost, next: Tab) {\n if (host.tab !== next) host.tab = next;\n if (next === \"chat\") host.chatHasAutoScrolled = false;\n if (next === \"logs\")\n startLogsPolling(host as unknown as Parameters[0]);\n else stopLogsPolling(host as unknown as Parameters[0]);\n if (next === \"debug\")\n startDebugPolling(host as unknown as Parameters[0]);\n else stopDebugPolling(host as unknown as Parameters[0]);\n if (host.connected) void refreshActiveTab(host);\n}\n\nexport function syncUrlWithTab(host: SettingsHost, tab: Tab, replace: boolean) {\n if (typeof window === \"undefined\") return;\n const targetPath = normalizePath(pathForTab(tab, host.basePath));\n const currentPath = normalizePath(window.location.pathname);\n const url = new URL(window.location.href);\n\n if (tab === \"chat\" && host.sessionKey) {\n url.searchParams.set(\"session\", host.sessionKey);\n } else {\n url.searchParams.delete(\"session\");\n }\n\n if (currentPath !== targetPath) {\n url.pathname = targetPath;\n }\n\n if (replace) {\n window.history.replaceState({}, \"\", url.toString());\n } else {\n window.history.pushState({}, \"\", url.toString());\n }\n}\n\nexport function syncUrlWithSessionKey(\n host: SettingsHost,\n sessionKey: string,\n replace: boolean,\n) {\n if (typeof window === \"undefined\") return;\n const url = new URL(window.location.href);\n url.searchParams.set(\"session\", sessionKey);\n if (replace) window.history.replaceState({}, \"\", url.toString());\n else window.history.pushState({}, \"\", url.toString());\n}\n\nexport async function loadOverview(host: SettingsHost) {\n await Promise.all([\n loadChannels(host as unknown as ClawdbotApp, false),\n loadPresence(host as unknown as ClawdbotApp),\n loadSessions(host as unknown as ClawdbotApp),\n loadCronStatus(host as unknown as ClawdbotApp),\n loadDebug(host as unknown as ClawdbotApp),\n ]);\n}\n\nexport async function loadChannelsTab(host: SettingsHost) {\n await Promise.all([\n loadChannels(host as unknown as ClawdbotApp, true),\n loadConfigSchema(host as unknown as ClawdbotApp),\n loadConfig(host as unknown as ClawdbotApp),\n ]);\n}\n\nexport async function loadCron(host: SettingsHost) {\n await Promise.all([\n loadChannels(host as unknown as ClawdbotApp, false),\n loadCronStatus(host as unknown as ClawdbotApp),\n loadCronJobs(host as unknown as ClawdbotApp),\n ]);\n}\n","import { abortChatRun, loadChatHistory, sendChatMessage } from \"./controllers/chat\";\nimport { loadSessions } from \"./controllers/sessions\";\nimport { generateUUID } from \"./uuid\";\nimport { resetToolStream } from \"./app-tool-stream\";\nimport { scheduleChatScroll } from \"./app-scroll\";\nimport { setLastActiveSessionKey } from \"./app-settings\";\nimport { normalizeBasePath } from \"./navigation\";\nimport type { GatewayHelloOk } from \"./gateway\";\nimport { parseAgentSessionKey } from \"../../../src/sessions/session-key-utils.js\";\nimport type { ClawdbotApp } from \"./app\";\n\ntype ChatHost = {\n connected: boolean;\n chatMessage: string;\n chatQueue: Array<{ id: string; text: string; createdAt: number }>;\n chatRunId: string | null;\n chatSending: boolean;\n sessionKey: string;\n basePath: string;\n hello: GatewayHelloOk | null;\n chatAvatarUrl: string | null;\n};\n\nexport function isChatBusy(host: ChatHost) {\n return host.chatSending || Boolean(host.chatRunId);\n}\n\nexport function isChatStopCommand(text: string) {\n const trimmed = text.trim();\n if (!trimmed) return false;\n const normalized = trimmed.toLowerCase();\n if (normalized === \"/stop\") return true;\n return (\n normalized === \"stop\" ||\n normalized === \"esc\" ||\n normalized === \"abort\" ||\n normalized === \"wait\" ||\n normalized === \"exit\"\n );\n}\n\nexport async function handleAbortChat(host: ChatHost) {\n if (!host.connected) return;\n host.chatMessage = \"\";\n await abortChatRun(host as unknown as ClawdbotApp);\n}\n\nfunction enqueueChatMessage(host: ChatHost, text: string) {\n const trimmed = text.trim();\n if (!trimmed) return;\n host.chatQueue = [\n ...host.chatQueue,\n {\n id: generateUUID(),\n text: trimmed,\n createdAt: Date.now(),\n },\n ];\n}\n\nasync function sendChatMessageNow(\n host: ChatHost,\n message: string,\n opts?: { previousDraft?: string; restoreDraft?: boolean },\n) {\n resetToolStream(host as unknown as Parameters[0]);\n const ok = await sendChatMessage(host as unknown as ClawdbotApp, message);\n if (!ok && opts?.previousDraft != null) {\n host.chatMessage = opts.previousDraft;\n }\n if (ok) {\n setLastActiveSessionKey(host as unknown as Parameters[0], host.sessionKey);\n }\n if (ok && opts?.restoreDraft && opts.previousDraft?.trim()) {\n host.chatMessage = opts.previousDraft;\n }\n scheduleChatScroll(host as unknown as Parameters[0]);\n if (ok && !host.chatRunId) {\n void flushChatQueue(host);\n }\n return ok;\n}\n\nasync function flushChatQueue(host: ChatHost) {\n if (!host.connected || isChatBusy(host)) return;\n const [next, ...rest] = host.chatQueue;\n if (!next) return;\n host.chatQueue = rest;\n const ok = await sendChatMessageNow(host, next.text);\n if (!ok) {\n host.chatQueue = [next, ...host.chatQueue];\n }\n}\n\nexport function removeQueuedMessage(host: ChatHost, id: string) {\n host.chatQueue = host.chatQueue.filter((item) => item.id !== id);\n}\n\nexport async function handleSendChat(\n host: ChatHost,\n messageOverride?: string,\n opts?: { restoreDraft?: boolean },\n) {\n if (!host.connected) return;\n const previousDraft = host.chatMessage;\n const message = (messageOverride ?? host.chatMessage).trim();\n if (!message) return;\n\n if (isChatStopCommand(message)) {\n await handleAbortChat(host);\n return;\n }\n\n if (messageOverride == null) {\n host.chatMessage = \"\";\n }\n\n if (isChatBusy(host)) {\n enqueueChatMessage(host, message);\n return;\n }\n\n await sendChatMessageNow(host, message, {\n previousDraft: messageOverride == null ? previousDraft : undefined,\n restoreDraft: Boolean(messageOverride && opts?.restoreDraft),\n });\n}\n\nexport async function refreshChat(host: ChatHost) {\n await Promise.all([\n loadChatHistory(host as unknown as ClawdbotApp),\n loadSessions(host as unknown as ClawdbotApp),\n refreshChatAvatar(host),\n ]);\n scheduleChatScroll(host as unknown as Parameters[0], true);\n}\n\nexport const flushChatQueueForEvent = flushChatQueue;\n\ntype SessionDefaultsSnapshot = {\n defaultAgentId?: string;\n};\n\nfunction resolveAgentIdForSession(host: ChatHost): string | null {\n const parsed = parseAgentSessionKey(host.sessionKey);\n if (parsed?.agentId) return parsed.agentId;\n const snapshot = host.hello?.snapshot as { sessionDefaults?: SessionDefaultsSnapshot } | undefined;\n const fallback = snapshot?.sessionDefaults?.defaultAgentId?.trim();\n return fallback || \"main\";\n}\n\nfunction buildAvatarMetaUrl(basePath: string, agentId: string): string {\n const base = normalizeBasePath(basePath);\n const encoded = encodeURIComponent(agentId);\n return base ? `${base}/avatar/${encoded}?meta=1` : `/avatar/${encoded}?meta=1`;\n}\n\nexport async function refreshChatAvatar(host: ChatHost) {\n if (!host.connected) {\n host.chatAvatarUrl = null;\n return;\n }\n const agentId = resolveAgentIdForSession(host);\n if (!agentId) {\n host.chatAvatarUrl = null;\n return;\n }\n host.chatAvatarUrl = null;\n const url = buildAvatarMetaUrl(host.basePath, agentId);\n try {\n const res = await fetch(url, { method: \"GET\" });\n if (!res.ok) {\n host.chatAvatarUrl = null;\n return;\n }\n const data = (await res.json()) as { avatarUrl?: unknown };\n const avatarUrl = typeof data.avatarUrl === \"string\" ? data.avatarUrl.trim() : \"\";\n host.chatAvatarUrl = avatarUrl || null;\n } catch {\n host.chatAvatarUrl = null;\n }\n}\n","/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\nconst t={ATTRIBUTE:1,CHILD:2,PROPERTY:3,BOOLEAN_ATTRIBUTE:4,EVENT:5,ELEMENT:6},e=t=>(...e)=>({_$litDirective$:t,values:e});class i{constructor(t){}get _$AU(){return this._$AM._$AU}_$AT(t,e,i){this._$Ct=t,this._$AM=e,this._$Ci=i}_$AS(t,e){return this.update(t,e)}update(t,e){return this.render(...e)}}export{i as Directive,t as PartType,e as directive};\n//# sourceMappingURL=directive.js.map\n","import{_$LH as o}from\"./lit-html.js\";\n/**\n * @license\n * Copyright 2020 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */const{I:t}=o,i=o=>o,n=o=>null===o||\"object\"!=typeof o&&\"function\"!=typeof o,e={HTML:1,SVG:2,MATHML:3},l=(o,t)=>void 0===t?void 0!==o?._$litType$:o?._$litType$===t,d=o=>null!=o?._$litType$?.h,c=o=>void 0!==o?._$litDirective$,f=o=>o?._$litDirective$,r=o=>void 0===o.strings,s=()=>document.createComment(\"\"),v=(o,n,e)=>{const l=o._$AA.parentNode,d=void 0===n?o._$AB:n._$AA;if(void 0===e){const i=l.insertBefore(s(),d),n=l.insertBefore(s(),d);e=new t(i,n,o,o.options)}else{const t=e._$AB.nextSibling,n=e._$AM,c=n!==o;if(c){let t;e._$AQ?.(o),e._$AM=o,void 0!==e._$AP&&(t=o._$AU)!==n._$AU&&e._$AP(t)}if(t!==d||c){let o=e._$AA;for(;o!==t;){const t=i(o).nextSibling;i(l).insertBefore(o,d),o=t}}}return e},u=(o,t,i=o)=>(o._$AI(t,i),o),m={},p=(o,t=m)=>o._$AH=t,M=o=>o._$AH,h=o=>{o._$AR(),o._$AA.remove()},j=o=>{o._$AR()};export{e as TemplateResultType,j as clearPart,M as getCommittedValue,f as getDirectiveClass,v as insertPart,d as isCompiledTemplateResult,c as isDirectiveResult,n as isPrimitive,r as isSingleExpression,l as isTemplateResult,h as removePart,u as setChildPartValue,p as setCommittedValue};\n//# sourceMappingURL=directive-helpers.js.map\n","import{noChange as e}from\"../lit-html.js\";import{directive as s,Directive as t,PartType as r}from\"../directive.js\";import{getCommittedValue as l,setChildPartValue as o,insertPart as i,removePart as n,setCommittedValue as f}from\"../directive-helpers.js\";\n/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\nconst u=(e,s,t)=>{const r=new Map;for(let l=s;l<=t;l++)r.set(e[l],l);return r},c=s(class extends t{constructor(e){if(super(e),e.type!==r.CHILD)throw Error(\"repeat() can only be used in text expressions\")}dt(e,s,t){let r;void 0===t?t=s:void 0!==s&&(r=s);const l=[],o=[];let i=0;for(const s of e)l[i]=r?r(s,i):i,o[i]=t(s,i),i++;return{values:o,keys:l}}render(e,s,t){return this.dt(e,s,t).values}update(s,[t,r,c]){const d=l(s),{values:p,keys:a}=this.dt(t,r,c);if(!Array.isArray(d))return this.ut=a,p;const h=this.ut??=[],v=[];let m,y,x=0,j=d.length-1,k=0,w=p.length-1;for(;x<=j&&k<=w;)if(null===d[x])x++;else if(null===d[j])j--;else if(h[x]===a[k])v[k]=o(d[x],p[k]),x++,k++;else if(h[j]===a[w])v[w]=o(d[j],p[w]),j--,w--;else if(h[x]===a[w])v[w]=o(d[x],p[w]),i(s,v[w+1],d[x]),x++,w--;else if(h[j]===a[k])v[k]=o(d[j],p[k]),i(s,d[x],d[j]),j--,k++;else if(void 0===m&&(m=u(a,k,w),y=u(h,x,j)),m.has(h[x]))if(m.has(h[j])){const e=y.get(a[k]),t=void 0!==e?d[e]:null;if(null===t){const e=i(s,d[x]);o(e,p[k]),v[k]=e}else v[k]=o(t,p[k]),i(s,d[x],t),d[e]=null;k++}else n(d[j]),j--;else n(d[x]),x++;for(;k<=w;){const e=i(s,v[w+1]);o(e,p[k]),v[k++]=e}for(;x<=j;){const e=d[x++];null!==e&&n(e)}return this.ut=a,f(s,v),e}});export{c as repeat};\n//# sourceMappingURL=repeat.js.map\n","/**\n * Message normalization utilities for chat rendering.\n */\n\nimport type {\n NormalizedMessage,\n MessageContentItem,\n} from \"../types/chat-types\";\n\n/**\n * Normalize a raw message object into a consistent structure.\n */\nexport function normalizeMessage(message: unknown): NormalizedMessage {\n const m = message as Record;\n let role = typeof m.role === \"string\" ? m.role : \"unknown\";\n\n // Detect tool messages by common gateway shapes.\n // Some tool events come through as assistant role with tool_* items in the content array.\n const hasToolId =\n typeof m.toolCallId === \"string\" || typeof m.tool_call_id === \"string\";\n\n const contentRaw = m.content;\n const contentItems = Array.isArray(contentRaw) ? contentRaw : null;\n const hasToolContent =\n Array.isArray(contentItems) &&\n contentItems.some((item) => {\n const x = item as Record;\n const t = String(x.type ?? \"\").toLowerCase();\n return t === \"toolresult\" || t === \"tool_result\";\n });\n\n const hasToolName =\n typeof (m as Record).toolName === \"string\" ||\n typeof (m as Record).tool_name === \"string\";\n\n if (hasToolId || hasToolContent || hasToolName) {\n role = \"toolResult\";\n }\n\n // Extract content\n let content: MessageContentItem[] = [];\n\n if (typeof m.content === \"string\") {\n content = [{ type: \"text\", text: m.content }];\n } else if (Array.isArray(m.content)) {\n content = m.content.map((item: Record) => ({\n type: (item.type as MessageContentItem[\"type\"]) || \"text\",\n text: item.text as string | undefined,\n name: item.name as string | undefined,\n args: item.args || item.arguments,\n }));\n } else if (typeof m.text === \"string\") {\n content = [{ type: \"text\", text: m.text }];\n }\n\n const timestamp = typeof m.timestamp === \"number\" ? m.timestamp : Date.now();\n const id = typeof m.id === \"string\" ? m.id : undefined;\n\n return { role, content, timestamp, id };\n}\n\n/**\n * Normalize role for grouping purposes.\n */\nexport function normalizeRoleForGrouping(role: string): string {\n const lower = role.toLowerCase();\n // Preserve original casing when it's already a core role.\n if (role === \"user\" || role === \"User\") return role;\n if (role === \"assistant\") return \"assistant\";\n if (role === \"system\") return \"system\";\n // Keep tool-related roles distinct so the UI can style/toggle them.\n if (\n lower === \"toolresult\" ||\n lower === \"tool_result\" ||\n lower === \"tool\" ||\n lower === \"function\"\n ) {\n return \"tool\";\n }\n return role;\n}\n\n/**\n * Check if a message is a tool result message based on its role.\n */\nexport function isToolResultMessage(message: unknown): boolean {\n const m = message as Record;\n const role = typeof m.role === \"string\" ? m.role.toLowerCase() : \"\";\n return role === \"toolresult\" || role === \"tool_result\";\n}\n","import{nothing as t,noChange as i}from\"../lit-html.js\";import{directive as r,Directive as s,PartType as n}from\"../directive.js\";\n/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */class e extends s{constructor(i){if(super(i),this.it=t,i.type!==n.CHILD)throw Error(this.constructor.directiveName+\"() can only be used in child bindings\")}render(r){if(r===t||null==r)return this._t=void 0,this.it=r;if(r===i)return r;if(\"string\"!=typeof r)throw Error(this.constructor.directiveName+\"() called with a non-string value\");if(r===this.it)return this._t;this.it=r;const s=[r];return s.raw=s,this._t={_$litType$:this.constructor.resultType,strings:s,values:[]}}}e.directiveName=\"unsafeHTML\",e.resultType=1;const o=r(e);export{e as UnsafeHTMLDirective,o as unsafeHTML};\n//# sourceMappingURL=unsafe-html.js.map\n","/*! @license DOMPurify 3.3.1 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.3.1/LICENSE */\n\nconst {\n entries,\n setPrototypeOf,\n isFrozen,\n getPrototypeOf,\n getOwnPropertyDescriptor\n} = Object;\nlet {\n freeze,\n seal,\n create\n} = Object; // eslint-disable-line import/no-mutable-exports\nlet {\n apply,\n construct\n} = typeof Reflect !== 'undefined' && Reflect;\nif (!freeze) {\n freeze = function freeze(x) {\n return x;\n };\n}\nif (!seal) {\n seal = function seal(x) {\n return x;\n };\n}\nif (!apply) {\n apply = function apply(func, thisArg) {\n for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {\n args[_key - 2] = arguments[_key];\n }\n return func.apply(thisArg, args);\n };\n}\nif (!construct) {\n construct = function construct(Func) {\n for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n args[_key2 - 1] = arguments[_key2];\n }\n return new Func(...args);\n };\n}\nconst arrayForEach = unapply(Array.prototype.forEach);\nconst arrayLastIndexOf = unapply(Array.prototype.lastIndexOf);\nconst arrayPop = unapply(Array.prototype.pop);\nconst arrayPush = unapply(Array.prototype.push);\nconst arraySplice = unapply(Array.prototype.splice);\nconst stringToLowerCase = unapply(String.prototype.toLowerCase);\nconst stringToString = unapply(String.prototype.toString);\nconst stringMatch = unapply(String.prototype.match);\nconst stringReplace = unapply(String.prototype.replace);\nconst stringIndexOf = unapply(String.prototype.indexOf);\nconst stringTrim = unapply(String.prototype.trim);\nconst objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);\nconst regExpTest = unapply(RegExp.prototype.test);\nconst typeErrorCreate = unconstruct(TypeError);\n/**\n * Creates a new function that calls the given function with a specified thisArg and arguments.\n *\n * @param func - The function to be wrapped and called.\n * @returns A new function that calls the given function with a specified thisArg and arguments.\n */\nfunction unapply(func) {\n return function (thisArg) {\n if (thisArg instanceof RegExp) {\n thisArg.lastIndex = 0;\n }\n for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {\n args[_key3 - 1] = arguments[_key3];\n }\n return apply(func, thisArg, args);\n };\n}\n/**\n * Creates a new function that constructs an instance of the given constructor function with the provided arguments.\n *\n * @param func - The constructor function to be wrapped and called.\n * @returns A new function that constructs an instance of the given constructor function with the provided arguments.\n */\nfunction unconstruct(Func) {\n return function () {\n for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {\n args[_key4] = arguments[_key4];\n }\n return construct(Func, args);\n };\n}\n/**\n * Add properties to a lookup table\n *\n * @param set - The set to which elements will be added.\n * @param array - The array containing elements to be added to the set.\n * @param transformCaseFunc - An optional function to transform the case of each element before adding to the set.\n * @returns The modified set with added elements.\n */\nfunction addToSet(set, array) {\n let transformCaseFunc = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : stringToLowerCase;\n if (setPrototypeOf) {\n // Make 'in' and truthy checks like Boolean(set.constructor)\n // independent of any properties defined on Object.prototype.\n // Prevent prototype setters from intercepting set as a this value.\n setPrototypeOf(set, null);\n }\n let l = array.length;\n while (l--) {\n let element = array[l];\n if (typeof element === 'string') {\n const lcElement = transformCaseFunc(element);\n if (lcElement !== element) {\n // Config presets (e.g. tags.js, attrs.js) are immutable.\n if (!isFrozen(array)) {\n array[l] = lcElement;\n }\n element = lcElement;\n }\n }\n set[element] = true;\n }\n return set;\n}\n/**\n * Clean up an array to harden against CSPP\n *\n * @param array - The array to be cleaned.\n * @returns The cleaned version of the array\n */\nfunction cleanArray(array) {\n for (let index = 0; index < array.length; index++) {\n const isPropertyExist = objectHasOwnProperty(array, index);\n if (!isPropertyExist) {\n array[index] = null;\n }\n }\n return array;\n}\n/**\n * Shallow clone an object\n *\n * @param object - The object to be cloned.\n * @returns A new object that copies the original.\n */\nfunction clone(object) {\n const newObject = create(null);\n for (const [property, value] of entries(object)) {\n const isPropertyExist = objectHasOwnProperty(object, property);\n if (isPropertyExist) {\n if (Array.isArray(value)) {\n newObject[property] = cleanArray(value);\n } else if (value && typeof value === 'object' && value.constructor === Object) {\n newObject[property] = clone(value);\n } else {\n newObject[property] = value;\n }\n }\n }\n return newObject;\n}\n/**\n * This method automatically checks if the prop is function or getter and behaves accordingly.\n *\n * @param object - The object to look up the getter function in its prototype chain.\n * @param prop - The property name for which to find the getter function.\n * @returns The getter function found in the prototype chain or a fallback function.\n */\nfunction lookupGetter(object, prop) {\n while (object !== null) {\n const desc = getOwnPropertyDescriptor(object, prop);\n if (desc) {\n if (desc.get) {\n return unapply(desc.get);\n }\n if (typeof desc.value === 'function') {\n return unapply(desc.value);\n }\n }\n object = getPrototypeOf(object);\n }\n function fallbackValue() {\n return null;\n }\n return fallbackValue;\n}\n\nconst html$1 = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'search', 'section', 'select', 'shadow', 'slot', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);\nconst svg$1 = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'enterkeyhint', 'exportparts', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'inputmode', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'part', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'view', 'vkern']);\nconst svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feDropShadow', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);\n// List of SVG elements that are disallowed by default.\n// We still need to know them so that we can do namespace\n// checks properly in case one wants to add them to\n// allow-list.\nconst svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'foreignobject', 'hatch', 'hatchpath', 'mesh', 'meshgradient', 'meshpatch', 'meshrow', 'missing-glyph', 'script', 'set', 'solidcolor', 'unknown', 'use']);\nconst mathMl$1 = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover', 'mprescripts']);\n// Similarly to SVG, we want to know all MathML elements,\n// even those that we disallow by default.\nconst mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);\nconst text = freeze(['#text']);\n\nconst html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'exportparts', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inert', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'nonce', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'part', 'pattern', 'placeholder', 'playsinline', 'popover', 'popovertarget', 'popovertargetaction', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'slot', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'wrap', 'xmlns', 'slot']);\nconst svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'amplitude', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'exponent', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'intercept', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'mask-type', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'slope', 'specularconstant', 'specularexponent', 'spreadmethod', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'tablevalues', 'targetx', 'targety', 'transform', 'transform-origin', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);\nconst mathMl = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);\nconst xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);\n\n// eslint-disable-next-line unicorn/better-regex\nconst MUSTACHE_EXPR = seal(/\\{\\{[\\w\\W]*|[\\w\\W]*\\}\\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode\nconst ERB_EXPR = seal(/<%[\\w\\W]*|[\\w\\W]*%>/gm);\nconst TMPLIT_EXPR = seal(/\\$\\{[\\w\\W]*/gm); // eslint-disable-line unicorn/better-regex\nconst DATA_ATTR = seal(/^data-[\\-\\w.\\u00B7-\\uFFFF]+$/); // eslint-disable-line no-useless-escape\nconst ARIA_ATTR = seal(/^aria-[\\-\\w]+$/); // eslint-disable-line no-useless-escape\nconst IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\\-]+(?:[^a-z+.\\-:]|$))/i // eslint-disable-line no-useless-escape\n);\nconst IS_SCRIPT_OR_DATA = seal(/^(?:\\w+script|data):/i);\nconst ATTR_WHITESPACE = seal(/[\\u0000-\\u0020\\u00A0\\u1680\\u180E\\u2000-\\u2029\\u205F\\u3000]/g // eslint-disable-line no-control-regex\n);\nconst DOCTYPE_NAME = seal(/^html$/i);\nconst CUSTOM_ELEMENT = seal(/^[a-z][.\\w]*(-[.\\w]+)+$/i);\n\nvar EXPRESSIONS = /*#__PURE__*/Object.freeze({\n __proto__: null,\n ARIA_ATTR: ARIA_ATTR,\n ATTR_WHITESPACE: ATTR_WHITESPACE,\n CUSTOM_ELEMENT: CUSTOM_ELEMENT,\n DATA_ATTR: DATA_ATTR,\n DOCTYPE_NAME: DOCTYPE_NAME,\n ERB_EXPR: ERB_EXPR,\n IS_ALLOWED_URI: IS_ALLOWED_URI,\n IS_SCRIPT_OR_DATA: IS_SCRIPT_OR_DATA,\n MUSTACHE_EXPR: MUSTACHE_EXPR,\n TMPLIT_EXPR: TMPLIT_EXPR\n});\n\n/* eslint-disable @typescript-eslint/indent */\n// https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType\nconst NODE_TYPE = {\n element: 1,\n attribute: 2,\n text: 3,\n cdataSection: 4,\n entityReference: 5,\n // Deprecated\n entityNode: 6,\n // Deprecated\n progressingInstruction: 7,\n comment: 8,\n document: 9,\n documentType: 10,\n documentFragment: 11,\n notation: 12 // Deprecated\n};\nconst getGlobal = function getGlobal() {\n return typeof window === 'undefined' ? null : window;\n};\n/**\n * Creates a no-op policy for internal use only.\n * Don't export this function outside this module!\n * @param trustedTypes The policy factory.\n * @param purifyHostElement The Script element used to load DOMPurify (to determine policy name suffix).\n * @return The policy created (or null, if Trusted Types\n * are not supported or creating the policy failed).\n */\nconst _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, purifyHostElement) {\n if (typeof trustedTypes !== 'object' || typeof trustedTypes.createPolicy !== 'function') {\n return null;\n }\n // Allow the callers to control the unique policy name\n // by adding a data-tt-policy-suffix to the script element with the DOMPurify.\n // Policy creation with duplicate names throws in Trusted Types.\n let suffix = null;\n const ATTR_NAME = 'data-tt-policy-suffix';\n if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) {\n suffix = purifyHostElement.getAttribute(ATTR_NAME);\n }\n const policyName = 'dompurify' + (suffix ? '#' + suffix : '');\n try {\n return trustedTypes.createPolicy(policyName, {\n createHTML(html) {\n return html;\n },\n createScriptURL(scriptUrl) {\n return scriptUrl;\n }\n });\n } catch (_) {\n // Policy creation failed (most likely another DOMPurify script has\n // already run). Skip creating the policy, as this will only cause errors\n // if TT are enforced.\n console.warn('TrustedTypes policy ' + policyName + ' could not be created.');\n return null;\n }\n};\nconst _createHooksMap = function _createHooksMap() {\n return {\n afterSanitizeAttributes: [],\n afterSanitizeElements: [],\n afterSanitizeShadowDOM: [],\n beforeSanitizeAttributes: [],\n beforeSanitizeElements: [],\n beforeSanitizeShadowDOM: [],\n uponSanitizeAttribute: [],\n uponSanitizeElement: [],\n uponSanitizeShadowNode: []\n };\n};\nfunction createDOMPurify() {\n let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();\n const DOMPurify = root => createDOMPurify(root);\n DOMPurify.version = '3.3.1';\n DOMPurify.removed = [];\n if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) {\n // Not running in a browser, provide a factory function\n // so that you can pass your own Window\n DOMPurify.isSupported = false;\n return DOMPurify;\n }\n let {\n document\n } = window;\n const originalDocument = document;\n const currentScript = originalDocument.currentScript;\n const {\n DocumentFragment,\n HTMLTemplateElement,\n Node,\n Element,\n NodeFilter,\n NamedNodeMap = window.NamedNodeMap || window.MozNamedAttrMap,\n HTMLFormElement,\n DOMParser,\n trustedTypes\n } = window;\n const ElementPrototype = Element.prototype;\n const cloneNode = lookupGetter(ElementPrototype, 'cloneNode');\n const remove = lookupGetter(ElementPrototype, 'remove');\n const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');\n const getChildNodes = lookupGetter(ElementPrototype, 'childNodes');\n const getParentNode = lookupGetter(ElementPrototype, 'parentNode');\n // As per issue #47, the web-components registry is inherited by a\n // new document created via createHTMLDocument. As per the spec\n // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)\n // a new empty registry is used when creating a template contents owner\n // document, so we use that as our parent document to ensure nothing\n // is inherited.\n if (typeof HTMLTemplateElement === 'function') {\n const template = document.createElement('template');\n if (template.content && template.content.ownerDocument) {\n document = template.content.ownerDocument;\n }\n }\n let trustedTypesPolicy;\n let emptyHTML = '';\n const {\n implementation,\n createNodeIterator,\n createDocumentFragment,\n getElementsByTagName\n } = document;\n const {\n importNode\n } = originalDocument;\n let hooks = _createHooksMap();\n /**\n * Expose whether this browser supports running the full DOMPurify.\n */\n DOMPurify.isSupported = typeof entries === 'function' && typeof getParentNode === 'function' && implementation && implementation.createHTMLDocument !== undefined;\n const {\n MUSTACHE_EXPR,\n ERB_EXPR,\n TMPLIT_EXPR,\n DATA_ATTR,\n ARIA_ATTR,\n IS_SCRIPT_OR_DATA,\n ATTR_WHITESPACE,\n CUSTOM_ELEMENT\n } = EXPRESSIONS;\n let {\n IS_ALLOWED_URI: IS_ALLOWED_URI$1\n } = EXPRESSIONS;\n /**\n * We consider the elements and attributes below to be safe. Ideally\n * don't add any new ones but feel free to remove unwanted ones.\n */\n /* allowed element names */\n let ALLOWED_TAGS = null;\n const DEFAULT_ALLOWED_TAGS = addToSet({}, [...html$1, ...svg$1, ...svgFilters, ...mathMl$1, ...text]);\n /* Allowed attribute names */\n let ALLOWED_ATTR = null;\n const DEFAULT_ALLOWED_ATTR = addToSet({}, [...html, ...svg, ...mathMl, ...xml]);\n /*\n * Configure how DOMPurify should handle custom elements and their attributes as well as customized built-in elements.\n * @property {RegExp|Function|null} tagNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any custom elements)\n * @property {RegExp|Function|null} attributeNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any attributes not on the allow list)\n * @property {boolean} allowCustomizedBuiltInElements allow custom elements derived from built-ins if they pass CUSTOM_ELEMENT_HANDLING.tagNameCheck. Default: `false`.\n */\n let CUSTOM_ELEMENT_HANDLING = Object.seal(create(null, {\n tagNameCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null\n },\n attributeNameCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null\n },\n allowCustomizedBuiltInElements: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: false\n }\n }));\n /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */\n let FORBID_TAGS = null;\n /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */\n let FORBID_ATTR = null;\n /* Config object to store ADD_TAGS/ADD_ATTR functions (when used as functions) */\n const EXTRA_ELEMENT_HANDLING = Object.seal(create(null, {\n tagCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null\n },\n attributeCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null\n }\n }));\n /* Decide if ARIA attributes are okay */\n let ALLOW_ARIA_ATTR = true;\n /* Decide if custom data attributes are okay */\n let ALLOW_DATA_ATTR = true;\n /* Decide if unknown protocols are okay */\n let ALLOW_UNKNOWN_PROTOCOLS = false;\n /* Decide if self-closing tags in attributes are allowed.\n * Usually removed due to a mXSS issue in jQuery 3.0 */\n let ALLOW_SELF_CLOSE_IN_ATTR = true;\n /* Output should be safe for common template engines.\n * This means, DOMPurify removes data attributes, mustaches and ERB\n */\n let SAFE_FOR_TEMPLATES = false;\n /* Output should be safe even for XML used within HTML and alike.\n * This means, DOMPurify removes comments when containing risky content.\n */\n let SAFE_FOR_XML = true;\n /* Decide if document with ... should be returned */\n let WHOLE_DOCUMENT = false;\n /* Track whether config is already set on this instance of DOMPurify. */\n let SET_CONFIG = false;\n /* Decide if all elements (e.g. style, script) must be children of\n * document.body. By default, browsers might move them to document.head */\n let FORCE_BODY = false;\n /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html\n * string (or a TrustedHTML object if Trusted Types are supported).\n * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead\n */\n let RETURN_DOM = false;\n /* Decide if a DOM `DocumentFragment` should be returned, instead of a html\n * string (or a TrustedHTML object if Trusted Types are supported) */\n let RETURN_DOM_FRAGMENT = false;\n /* Try to return a Trusted Type object instead of a string, return a string in\n * case Trusted Types are not supported */\n let RETURN_TRUSTED_TYPE = false;\n /* Output should be free from DOM clobbering attacks?\n * This sanitizes markups named with colliding, clobberable built-in DOM APIs.\n */\n let SANITIZE_DOM = true;\n /* Achieve full DOM Clobbering protection by isolating the namespace of named\n * properties and JS variables, mitigating attacks that abuse the HTML/DOM spec rules.\n *\n * HTML/DOM spec rules that enable DOM Clobbering:\n * - Named Access on Window (§7.3.3)\n * - DOM Tree Accessors (§3.1.5)\n * - Form Element Parent-Child Relations (§4.10.3)\n * - Iframe srcdoc / Nested WindowProxies (§4.8.5)\n * - HTMLCollection (§4.2.10.2)\n *\n * Namespace isolation is implemented by prefixing `id` and `name` attributes\n * with a constant string, i.e., `user-content-`\n */\n let SANITIZE_NAMED_PROPS = false;\n const SANITIZE_NAMED_PROPS_PREFIX = 'user-content-';\n /* Keep element content when removing element? */\n let KEEP_CONTENT = true;\n /* If a `Node` is passed to sanitize(), then performs sanitization in-place instead\n * of importing it into a new Document and returning a sanitized copy */\n let IN_PLACE = false;\n /* Allow usage of profiles like html, svg and mathMl */\n let USE_PROFILES = {};\n /* Tags to ignore content of when KEEP_CONTENT is true */\n let FORBID_CONTENTS = null;\n const DEFAULT_FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'noscript', 'plaintext', 'script', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']);\n /* Tags that are safe for data: URIs */\n let DATA_URI_TAGS = null;\n const DEFAULT_DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image', 'track']);\n /* Attributes safe for values like \"javascript:\" */\n let URI_SAFE_ATTRIBUTES = null;\n const DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'role', 'summary', 'title', 'value', 'style', 'xmlns']);\n const MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';\n const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';\n const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';\n /* Document namespace */\n let NAMESPACE = HTML_NAMESPACE;\n let IS_EMPTY_INPUT = false;\n /* Allowed XHTML+XML namespaces */\n let ALLOWED_NAMESPACES = null;\n const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString);\n let MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ['mi', 'mo', 'mn', 'ms', 'mtext']);\n let HTML_INTEGRATION_POINTS = addToSet({}, ['annotation-xml']);\n // Certain elements are allowed in both SVG and HTML\n // namespace. We need to specify them explicitly\n // so that they don't get erroneously deleted from\n // HTML namespace.\n const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ['title', 'style', 'font', 'a', 'script']);\n /* Parsing of strict XHTML documents */\n let PARSER_MEDIA_TYPE = null;\n const SUPPORTED_PARSER_MEDIA_TYPES = ['application/xhtml+xml', 'text/html'];\n const DEFAULT_PARSER_MEDIA_TYPE = 'text/html';\n let transformCaseFunc = null;\n /* Keep a reference to config to pass to hooks */\n let CONFIG = null;\n /* Ideally, do not touch anything below this line */\n /* ______________________________________________ */\n const formElement = document.createElement('form');\n const isRegexOrFunction = function isRegexOrFunction(testValue) {\n return testValue instanceof RegExp || testValue instanceof Function;\n };\n /**\n * _parseConfig\n *\n * @param cfg optional config literal\n */\n // eslint-disable-next-line complexity\n const _parseConfig = function _parseConfig() {\n let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n if (CONFIG && CONFIG === cfg) {\n return;\n }\n /* Shield configuration object from tampering */\n if (!cfg || typeof cfg !== 'object') {\n cfg = {};\n }\n /* Shield configuration object from prototype pollution */\n cfg = clone(cfg);\n PARSER_MEDIA_TYPE =\n // eslint-disable-next-line unicorn/prefer-includes\n SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? DEFAULT_PARSER_MEDIA_TYPE : cfg.PARSER_MEDIA_TYPE;\n // HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.\n transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? stringToString : stringToLowerCase;\n /* Set configuration parameters */\n ALLOWED_TAGS = objectHasOwnProperty(cfg, 'ALLOWED_TAGS') ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;\n ALLOWED_ATTR = objectHasOwnProperty(cfg, 'ALLOWED_ATTR') ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;\n ALLOWED_NAMESPACES = objectHasOwnProperty(cfg, 'ALLOWED_NAMESPACES') ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;\n URI_SAFE_ATTRIBUTES = objectHasOwnProperty(cfg, 'ADD_URI_SAFE_ATTR') ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR, transformCaseFunc) : DEFAULT_URI_SAFE_ATTRIBUTES;\n DATA_URI_TAGS = objectHasOwnProperty(cfg, 'ADD_DATA_URI_TAGS') ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS, transformCaseFunc) : DEFAULT_DATA_URI_TAGS;\n FORBID_CONTENTS = objectHasOwnProperty(cfg, 'FORBID_CONTENTS') ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;\n FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS') ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : clone({});\n FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR') ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : clone({});\n USE_PROFILES = objectHasOwnProperty(cfg, 'USE_PROFILES') ? cfg.USE_PROFILES : false;\n ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true\n ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true\n ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false\n ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false; // Default true\n SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false\n SAFE_FOR_XML = cfg.SAFE_FOR_XML !== false; // Default true\n WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false\n RETURN_DOM = cfg.RETURN_DOM || false; // Default false\n RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false\n RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; // Default false\n FORCE_BODY = cfg.FORCE_BODY || false; // Default false\n SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true\n SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; // Default false\n KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true\n IN_PLACE = cfg.IN_PLACE || false; // Default false\n IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI;\n NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;\n MATHML_TEXT_INTEGRATION_POINTS = cfg.MATHML_TEXT_INTEGRATION_POINTS || MATHML_TEXT_INTEGRATION_POINTS;\n HTML_INTEGRATION_POINTS = cfg.HTML_INTEGRATION_POINTS || HTML_INTEGRATION_POINTS;\n CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || {};\n if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {\n CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;\n }\n if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)) {\n CUSTOM_ELEMENT_HANDLING.attributeNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.attributeNameCheck;\n }\n if (cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements === 'boolean') {\n CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = cfg.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements;\n }\n if (SAFE_FOR_TEMPLATES) {\n ALLOW_DATA_ATTR = false;\n }\n if (RETURN_DOM_FRAGMENT) {\n RETURN_DOM = true;\n }\n /* Parse profile info */\n if (USE_PROFILES) {\n ALLOWED_TAGS = addToSet({}, text);\n ALLOWED_ATTR = [];\n if (USE_PROFILES.html === true) {\n addToSet(ALLOWED_TAGS, html$1);\n addToSet(ALLOWED_ATTR, html);\n }\n if (USE_PROFILES.svg === true) {\n addToSet(ALLOWED_TAGS, svg$1);\n addToSet(ALLOWED_ATTR, svg);\n addToSet(ALLOWED_ATTR, xml);\n }\n if (USE_PROFILES.svgFilters === true) {\n addToSet(ALLOWED_TAGS, svgFilters);\n addToSet(ALLOWED_ATTR, svg);\n addToSet(ALLOWED_ATTR, xml);\n }\n if (USE_PROFILES.mathMl === true) {\n addToSet(ALLOWED_TAGS, mathMl$1);\n addToSet(ALLOWED_ATTR, mathMl);\n addToSet(ALLOWED_ATTR, xml);\n }\n }\n /* Merge configuration parameters */\n if (cfg.ADD_TAGS) {\n if (typeof cfg.ADD_TAGS === 'function') {\n EXTRA_ELEMENT_HANDLING.tagCheck = cfg.ADD_TAGS;\n } else {\n if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {\n ALLOWED_TAGS = clone(ALLOWED_TAGS);\n }\n addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);\n }\n }\n if (cfg.ADD_ATTR) {\n if (typeof cfg.ADD_ATTR === 'function') {\n EXTRA_ELEMENT_HANDLING.attributeCheck = cfg.ADD_ATTR;\n } else {\n if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {\n ALLOWED_ATTR = clone(ALLOWED_ATTR);\n }\n addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);\n }\n }\n if (cfg.ADD_URI_SAFE_ATTR) {\n addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);\n }\n if (cfg.FORBID_CONTENTS) {\n if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {\n FORBID_CONTENTS = clone(FORBID_CONTENTS);\n }\n addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);\n }\n if (cfg.ADD_FORBID_CONTENTS) {\n if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {\n FORBID_CONTENTS = clone(FORBID_CONTENTS);\n }\n addToSet(FORBID_CONTENTS, cfg.ADD_FORBID_CONTENTS, transformCaseFunc);\n }\n /* Add #text in case KEEP_CONTENT is set to true */\n if (KEEP_CONTENT) {\n ALLOWED_TAGS['#text'] = true;\n }\n /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */\n if (WHOLE_DOCUMENT) {\n addToSet(ALLOWED_TAGS, ['html', 'head', 'body']);\n }\n /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286, #365 */\n if (ALLOWED_TAGS.table) {\n addToSet(ALLOWED_TAGS, ['tbody']);\n delete FORBID_TAGS.tbody;\n }\n if (cfg.TRUSTED_TYPES_POLICY) {\n if (typeof cfg.TRUSTED_TYPES_POLICY.createHTML !== 'function') {\n throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a \"createHTML\" hook.');\n }\n if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== 'function') {\n throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a \"createScriptURL\" hook.');\n }\n // Overwrite existing TrustedTypes policy.\n trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY;\n // Sign local variables required by `sanitize`.\n emptyHTML = trustedTypesPolicy.createHTML('');\n } else {\n // Uninitialized policy, attempt to initialize the internal dompurify policy.\n if (trustedTypesPolicy === undefined) {\n trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript);\n }\n // If creating the internal policy succeeded sign internal variables.\n if (trustedTypesPolicy !== null && typeof emptyHTML === 'string') {\n emptyHTML = trustedTypesPolicy.createHTML('');\n }\n }\n // Prevent further manipulation of configuration.\n // Not available in IE8, Safari 5, etc.\n if (freeze) {\n freeze(cfg);\n }\n CONFIG = cfg;\n };\n /* Keep track of all possible SVG and MathML tags\n * so that we can perform the namespace checks\n * correctly. */\n const ALL_SVG_TAGS = addToSet({}, [...svg$1, ...svgFilters, ...svgDisallowed]);\n const ALL_MATHML_TAGS = addToSet({}, [...mathMl$1, ...mathMlDisallowed]);\n /**\n * @param element a DOM element whose namespace is being checked\n * @returns Return false if the element has a\n * namespace that a spec-compliant parser would never\n * return. Return true otherwise.\n */\n const _checkValidNamespace = function _checkValidNamespace(element) {\n let parent = getParentNode(element);\n // In JSDOM, if we're inside shadow DOM, then parentNode\n // can be null. We just simulate parent in this case.\n if (!parent || !parent.tagName) {\n parent = {\n namespaceURI: NAMESPACE,\n tagName: 'template'\n };\n }\n const tagName = stringToLowerCase(element.tagName);\n const parentTagName = stringToLowerCase(parent.tagName);\n if (!ALLOWED_NAMESPACES[element.namespaceURI]) {\n return false;\n }\n if (element.namespaceURI === SVG_NAMESPACE) {\n // The only way to switch from HTML namespace to SVG\n // is via . If it happens via any other tag, then\n // it should be killed.\n if (parent.namespaceURI === HTML_NAMESPACE) {\n return tagName === 'svg';\n }\n // The only way to switch from MathML to SVG is via`\n // svg if parent is either or MathML\n // text integration points.\n if (parent.namespaceURI === MATHML_NAMESPACE) {\n return tagName === 'svg' && (parentTagName === 'annotation-xml' || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);\n }\n // We only allow elements that are defined in SVG\n // spec. All others are disallowed in SVG namespace.\n return Boolean(ALL_SVG_TAGS[tagName]);\n }\n if (element.namespaceURI === MATHML_NAMESPACE) {\n // The only way to switch from HTML namespace to MathML\n // is via . If it happens via any other tag, then\n // it should be killed.\n if (parent.namespaceURI === HTML_NAMESPACE) {\n return tagName === 'math';\n }\n // The only way to switch from SVG to MathML is via\n // and HTML integration points\n if (parent.namespaceURI === SVG_NAMESPACE) {\n return tagName === 'math' && HTML_INTEGRATION_POINTS[parentTagName];\n }\n // We only allow elements that are defined in MathML\n // spec. All others are disallowed in MathML namespace.\n return Boolean(ALL_MATHML_TAGS[tagName]);\n }\n if (element.namespaceURI === HTML_NAMESPACE) {\n // The only way to switch from SVG to HTML is via\n // HTML integration points, and from MathML to HTML\n // is via MathML text integration points\n if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {\n return false;\n }\n if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {\n return false;\n }\n // We disallow tags that are specific for MathML\n // or SVG and should never appear in HTML namespace\n return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);\n }\n // For XHTML and XML documents that support custom namespaces\n if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && ALLOWED_NAMESPACES[element.namespaceURI]) {\n return true;\n }\n // The code should never reach this place (this means\n // that the element somehow got namespace that is not\n // HTML, SVG, MathML or allowed via ALLOWED_NAMESPACES).\n // Return false just in case.\n return false;\n };\n /**\n * _forceRemove\n *\n * @param node a DOM node\n */\n const _forceRemove = function _forceRemove(node) {\n arrayPush(DOMPurify.removed, {\n element: node\n });\n try {\n // eslint-disable-next-line unicorn/prefer-dom-node-remove\n getParentNode(node).removeChild(node);\n } catch (_) {\n remove(node);\n }\n };\n /**\n * _removeAttribute\n *\n * @param name an Attribute name\n * @param element a DOM node\n */\n const _removeAttribute = function _removeAttribute(name, element) {\n try {\n arrayPush(DOMPurify.removed, {\n attribute: element.getAttributeNode(name),\n from: element\n });\n } catch (_) {\n arrayPush(DOMPurify.removed, {\n attribute: null,\n from: element\n });\n }\n element.removeAttribute(name);\n // We void attribute values for unremovable \"is\" attributes\n if (name === 'is') {\n if (RETURN_DOM || RETURN_DOM_FRAGMENT) {\n try {\n _forceRemove(element);\n } catch (_) {}\n } else {\n try {\n element.setAttribute(name, '');\n } catch (_) {}\n }\n }\n };\n /**\n * _initDocument\n *\n * @param dirty - a string of dirty markup\n * @return a DOM, filled with the dirty markup\n */\n const _initDocument = function _initDocument(dirty) {\n /* Create a HTML document */\n let doc = null;\n let leadingWhitespace = null;\n if (FORCE_BODY) {\n dirty = '' + dirty;\n } else {\n /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */\n const matches = stringMatch(dirty, /^[\\r\\n\\t ]+/);\n leadingWhitespace = matches && matches[0];\n }\n if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && NAMESPACE === HTML_NAMESPACE) {\n // Root of XHTML doc must contain xmlns declaration (see https://www.w3.org/TR/xhtml1/normative.html#strict)\n dirty = '' + dirty + '';\n }\n const dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;\n /*\n * Use the DOMParser API by default, fallback later if needs be\n * DOMParser not work for svg when has multiple root element.\n */\n if (NAMESPACE === HTML_NAMESPACE) {\n try {\n doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);\n } catch (_) {}\n }\n /* Use createHTMLDocument in case DOMParser is not available */\n if (!doc || !doc.documentElement) {\n doc = implementation.createDocument(NAMESPACE, 'template', null);\n try {\n doc.documentElement.innerHTML = IS_EMPTY_INPUT ? emptyHTML : dirtyPayload;\n } catch (_) {\n // Syntax error if dirtyPayload is invalid xml\n }\n }\n const body = doc.body || doc.documentElement;\n if (dirty && leadingWhitespace) {\n body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);\n }\n /* Work on whole document or just its body */\n if (NAMESPACE === HTML_NAMESPACE) {\n return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];\n }\n return WHOLE_DOCUMENT ? doc.documentElement : body;\n };\n /**\n * Creates a NodeIterator object that you can use to traverse filtered lists of nodes or elements in a document.\n *\n * @param root The root element or node to start traversing on.\n * @return The created NodeIterator\n */\n const _createNodeIterator = function _createNodeIterator(root) {\n return createNodeIterator.call(root.ownerDocument || root, root,\n // eslint-disable-next-line no-bitwise\n NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION | NodeFilter.SHOW_CDATA_SECTION, null);\n };\n /**\n * _isClobbered\n *\n * @param element element to check for clobbering attacks\n * @return true if clobbered, false if safe\n */\n const _isClobbered = function _isClobbered(element) {\n return element instanceof HTMLFormElement && (typeof element.nodeName !== 'string' || typeof element.textContent !== 'string' || typeof element.removeChild !== 'function' || !(element.attributes instanceof NamedNodeMap) || typeof element.removeAttribute !== 'function' || typeof element.setAttribute !== 'function' || typeof element.namespaceURI !== 'string' || typeof element.insertBefore !== 'function' || typeof element.hasChildNodes !== 'function');\n };\n /**\n * Checks whether the given object is a DOM node.\n *\n * @param value object to check whether it's a DOM node\n * @return true is object is a DOM node\n */\n const _isNode = function _isNode(value) {\n return typeof Node === 'function' && value instanceof Node;\n };\n function _executeHooks(hooks, currentNode, data) {\n arrayForEach(hooks, hook => {\n hook.call(DOMPurify, currentNode, data, CONFIG);\n });\n }\n /**\n * _sanitizeElements\n *\n * @protect nodeName\n * @protect textContent\n * @protect removeChild\n * @param currentNode to check for permission to exist\n * @return true if node was killed, false if left alive\n */\n const _sanitizeElements = function _sanitizeElements(currentNode) {\n let content = null;\n /* Execute a hook if present */\n _executeHooks(hooks.beforeSanitizeElements, currentNode, null);\n /* Check if element is clobbered or can clobber */\n if (_isClobbered(currentNode)) {\n _forceRemove(currentNode);\n return true;\n }\n /* Now let's check the element's type and name */\n const tagName = transformCaseFunc(currentNode.nodeName);\n /* Execute a hook if present */\n _executeHooks(hooks.uponSanitizeElement, currentNode, {\n tagName,\n allowedTags: ALLOWED_TAGS\n });\n /* Detect mXSS attempts abusing namespace confusion */\n if (SAFE_FOR_XML && currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(/<[/\\w!]/g, currentNode.innerHTML) && regExpTest(/<[/\\w!]/g, currentNode.textContent)) {\n _forceRemove(currentNode);\n return true;\n }\n /* Remove any occurrence of processing instructions */\n if (currentNode.nodeType === NODE_TYPE.progressingInstruction) {\n _forceRemove(currentNode);\n return true;\n }\n /* Remove any kind of possibly harmful comments */\n if (SAFE_FOR_XML && currentNode.nodeType === NODE_TYPE.comment && regExpTest(/<[/\\w]/g, currentNode.data)) {\n _forceRemove(currentNode);\n return true;\n }\n /* Remove element if anything forbids its presence */\n if (!(EXTRA_ELEMENT_HANDLING.tagCheck instanceof Function && EXTRA_ELEMENT_HANDLING.tagCheck(tagName)) && (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName])) {\n /* Check if we have a custom element to handle */\n if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {\n if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {\n return false;\n }\n if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) {\n return false;\n }\n }\n /* Keep content except for bad-listed elements */\n if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {\n const parentNode = getParentNode(currentNode) || currentNode.parentNode;\n const childNodes = getChildNodes(currentNode) || currentNode.childNodes;\n if (childNodes && parentNode) {\n const childCount = childNodes.length;\n for (let i = childCount - 1; i >= 0; --i) {\n const childClone = cloneNode(childNodes[i], true);\n childClone.__removalCount = (currentNode.__removalCount || 0) + 1;\n parentNode.insertBefore(childClone, getNextSibling(currentNode));\n }\n }\n }\n _forceRemove(currentNode);\n return true;\n }\n /* Check whether element has a valid namespace */\n if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {\n _forceRemove(currentNode);\n return true;\n }\n /* Make sure that older browsers don't get fallback-tag mXSS */\n if ((tagName === 'noscript' || tagName === 'noembed' || tagName === 'noframes') && regExpTest(/<\\/no(script|embed|frames)/i, currentNode.innerHTML)) {\n _forceRemove(currentNode);\n return true;\n }\n /* Sanitize element content to be template-safe */\n if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) {\n /* Get the element's text content */\n content = currentNode.textContent;\n arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {\n content = stringReplace(content, expr, ' ');\n });\n if (currentNode.textContent !== content) {\n arrayPush(DOMPurify.removed, {\n element: currentNode.cloneNode()\n });\n currentNode.textContent = content;\n }\n }\n /* Execute a hook if present */\n _executeHooks(hooks.afterSanitizeElements, currentNode, null);\n return false;\n };\n /**\n * _isValidAttribute\n *\n * @param lcTag Lowercase tag name of containing element.\n * @param lcName Lowercase attribute name.\n * @param value Attribute value.\n * @return Returns true if `value` is valid, otherwise false.\n */\n // eslint-disable-next-line complexity\n const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {\n /* Make sure attribute cannot clobber */\n if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {\n return false;\n }\n /* Allow valid data-* attributes: At least one character after \"-\"\n (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)\n XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)\n We don't need to check the value; it's always URI safe. */\n if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR, lcName)) ; else if (EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function && EXTRA_ELEMENT_HANDLING.attributeCheck(lcName, lcTag)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {\n if (\n // First condition does a very basic check if a) it's basically a valid custom element tagname AND\n // b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck\n // and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck\n _isBasicCustomElement(lcTag) && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) && (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName, lcTag)) ||\n // Alternative, second condition checks if it's an `is`-attribute, AND\n // the value passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck\n lcName === 'is' && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(value))) ; else {\n return false;\n }\n /* Check value is safe. First, is attr inert? If so, is safe */\n } else if (URI_SAFE_ATTRIBUTES[lcName]) ; else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE, ''))) ; else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) ; else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA, stringReplace(value, ATTR_WHITESPACE, ''))) ; else if (value) {\n return false;\n } else ;\n return true;\n };\n /**\n * _isBasicCustomElement\n * checks if at least one dash is included in tagName, and it's not the first char\n * for more sophisticated checking see https://github.com/sindresorhus/validate-element-name\n *\n * @param tagName name of the tag of the node to sanitize\n * @returns Returns true if the tag name meets the basic criteria for a custom element, otherwise false.\n */\n const _isBasicCustomElement = function _isBasicCustomElement(tagName) {\n return tagName !== 'annotation-xml' && stringMatch(tagName, CUSTOM_ELEMENT);\n };\n /**\n * _sanitizeAttributes\n *\n * @protect attributes\n * @protect nodeName\n * @protect removeAttribute\n * @protect setAttribute\n *\n * @param currentNode to sanitize\n */\n const _sanitizeAttributes = function _sanitizeAttributes(currentNode) {\n /* Execute a hook if present */\n _executeHooks(hooks.beforeSanitizeAttributes, currentNode, null);\n const {\n attributes\n } = currentNode;\n /* Check if we have attributes; if not we might have a text node */\n if (!attributes || _isClobbered(currentNode)) {\n return;\n }\n const hookEvent = {\n attrName: '',\n attrValue: '',\n keepAttr: true,\n allowedAttributes: ALLOWED_ATTR,\n forceKeepAttr: undefined\n };\n let l = attributes.length;\n /* Go backwards over all attributes; safely remove bad ones */\n while (l--) {\n const attr = attributes[l];\n const {\n name,\n namespaceURI,\n value: attrValue\n } = attr;\n const lcName = transformCaseFunc(name);\n const initValue = attrValue;\n let value = name === 'value' ? initValue : stringTrim(initValue);\n /* Execute a hook if present */\n hookEvent.attrName = lcName;\n hookEvent.attrValue = value;\n hookEvent.keepAttr = true;\n hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set\n _executeHooks(hooks.uponSanitizeAttribute, currentNode, hookEvent);\n value = hookEvent.attrValue;\n /* Full DOM Clobbering protection via namespace isolation,\n * Prefix id and name attributes with `user-content-`\n */\n if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name')) {\n // Remove the attribute with this value\n _removeAttribute(name, currentNode);\n // Prefix the value and later re-create the attribute with the sanitized value\n value = SANITIZE_NAMED_PROPS_PREFIX + value;\n }\n /* Work around a security issue with comments inside attributes */\n if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\\/(style|title|textarea)/i, value)) {\n _removeAttribute(name, currentNode);\n continue;\n }\n /* Make sure we cannot easily use animated hrefs, even if animations are allowed */\n if (lcName === 'attributename' && stringMatch(value, 'href')) {\n _removeAttribute(name, currentNode);\n continue;\n }\n /* Did the hooks approve of the attribute? */\n if (hookEvent.forceKeepAttr) {\n continue;\n }\n /* Did the hooks approve of the attribute? */\n if (!hookEvent.keepAttr) {\n _removeAttribute(name, currentNode);\n continue;\n }\n /* Work around a security issue in jQuery 3.0 */\n if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(/\\/>/i, value)) {\n _removeAttribute(name, currentNode);\n continue;\n }\n /* Sanitize attribute content to be template-safe */\n if (SAFE_FOR_TEMPLATES) {\n arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {\n value = stringReplace(value, expr, ' ');\n });\n }\n /* Is `value` valid for this attribute? */\n const lcTag = transformCaseFunc(currentNode.nodeName);\n if (!_isValidAttribute(lcTag, lcName, value)) {\n _removeAttribute(name, currentNode);\n continue;\n }\n /* Handle attributes that require Trusted Types */\n if (trustedTypesPolicy && typeof trustedTypes === 'object' && typeof trustedTypes.getAttributeType === 'function') {\n if (namespaceURI) ; else {\n switch (trustedTypes.getAttributeType(lcTag, lcName)) {\n case 'TrustedHTML':\n {\n value = trustedTypesPolicy.createHTML(value);\n break;\n }\n case 'TrustedScriptURL':\n {\n value = trustedTypesPolicy.createScriptURL(value);\n break;\n }\n }\n }\n }\n /* Handle invalid data-* attribute set by try-catching it */\n if (value !== initValue) {\n try {\n if (namespaceURI) {\n currentNode.setAttributeNS(namespaceURI, name, value);\n } else {\n /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. \"x-schema\". */\n currentNode.setAttribute(name, value);\n }\n if (_isClobbered(currentNode)) {\n _forceRemove(currentNode);\n } else {\n arrayPop(DOMPurify.removed);\n }\n } catch (_) {\n _removeAttribute(name, currentNode);\n }\n }\n }\n /* Execute a hook if present */\n _executeHooks(hooks.afterSanitizeAttributes, currentNode, null);\n };\n /**\n * _sanitizeShadowDOM\n *\n * @param fragment to iterate over recursively\n */\n const _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {\n let shadowNode = null;\n const shadowIterator = _createNodeIterator(fragment);\n /* Execute a hook if present */\n _executeHooks(hooks.beforeSanitizeShadowDOM, fragment, null);\n while (shadowNode = shadowIterator.nextNode()) {\n /* Execute a hook if present */\n _executeHooks(hooks.uponSanitizeShadowNode, shadowNode, null);\n /* Sanitize tags and elements */\n _sanitizeElements(shadowNode);\n /* Check attributes next */\n _sanitizeAttributes(shadowNode);\n /* Deep shadow DOM detected */\n if (shadowNode.content instanceof DocumentFragment) {\n _sanitizeShadowDOM(shadowNode.content);\n }\n }\n /* Execute a hook if present */\n _executeHooks(hooks.afterSanitizeShadowDOM, fragment, null);\n };\n // eslint-disable-next-line complexity\n DOMPurify.sanitize = function (dirty) {\n let cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n let body = null;\n let importedNode = null;\n let currentNode = null;\n let returnNode = null;\n /* Make sure we have a string to sanitize.\n DO NOT return early, as this will return the wrong type if\n the user has requested a DOM object rather than a string */\n IS_EMPTY_INPUT = !dirty;\n if (IS_EMPTY_INPUT) {\n dirty = '';\n }\n /* Stringify, in case dirty is an object */\n if (typeof dirty !== 'string' && !_isNode(dirty)) {\n if (typeof dirty.toString === 'function') {\n dirty = dirty.toString();\n if (typeof dirty !== 'string') {\n throw typeErrorCreate('dirty is not a string, aborting');\n }\n } else {\n throw typeErrorCreate('toString is not a function');\n }\n }\n /* Return dirty HTML if DOMPurify cannot run */\n if (!DOMPurify.isSupported) {\n return dirty;\n }\n /* Assign config vars */\n if (!SET_CONFIG) {\n _parseConfig(cfg);\n }\n /* Clean up removed elements */\n DOMPurify.removed = [];\n /* Check if dirty is correctly typed for IN_PLACE */\n if (typeof dirty === 'string') {\n IN_PLACE = false;\n }\n if (IN_PLACE) {\n /* Do some early pre-sanitization to avoid unsafe root nodes */\n if (dirty.nodeName) {\n const tagName = transformCaseFunc(dirty.nodeName);\n if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {\n throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');\n }\n }\n } else if (dirty instanceof Node) {\n /* If dirty is a DOM element, append to an empty document to avoid\n elements being stripped by the parser */\n body = _initDocument('');\n importedNode = body.ownerDocument.importNode(dirty, true);\n if (importedNode.nodeType === NODE_TYPE.element && importedNode.nodeName === 'BODY') {\n /* Node is already a body, use as is */\n body = importedNode;\n } else if (importedNode.nodeName === 'HTML') {\n body = importedNode;\n } else {\n // eslint-disable-next-line unicorn/prefer-dom-node-append\n body.appendChild(importedNode);\n }\n } else {\n /* Exit directly if we have nothing to do */\n if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT &&\n // eslint-disable-next-line unicorn/prefer-includes\n dirty.indexOf('<') === -1) {\n return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;\n }\n /* Initialize the document to work on */\n body = _initDocument(dirty);\n /* Check we have a DOM node from the data */\n if (!body) {\n return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : '';\n }\n }\n /* Remove first element node (ours) if FORCE_BODY is set */\n if (body && FORCE_BODY) {\n _forceRemove(body.firstChild);\n }\n /* Get node iterator */\n const nodeIterator = _createNodeIterator(IN_PLACE ? dirty : body);\n /* Now start iterating over the created document */\n while (currentNode = nodeIterator.nextNode()) {\n /* Sanitize tags and elements */\n _sanitizeElements(currentNode);\n /* Check attributes next */\n _sanitizeAttributes(currentNode);\n /* Shadow DOM detected, sanitize it */\n if (currentNode.content instanceof DocumentFragment) {\n _sanitizeShadowDOM(currentNode.content);\n }\n }\n /* If we sanitized `dirty` in-place, return it. */\n if (IN_PLACE) {\n return dirty;\n }\n /* Return sanitized string or DOM */\n if (RETURN_DOM) {\n if (RETURN_DOM_FRAGMENT) {\n returnNode = createDocumentFragment.call(body.ownerDocument);\n while (body.firstChild) {\n // eslint-disable-next-line unicorn/prefer-dom-node-append\n returnNode.appendChild(body.firstChild);\n }\n } else {\n returnNode = body;\n }\n if (ALLOWED_ATTR.shadowroot || ALLOWED_ATTR.shadowrootmode) {\n /*\n AdoptNode() is not used because internal state is not reset\n (e.g. the past names map of a HTMLFormElement), this is safe\n in theory but we would rather not risk another attack vector.\n The state that is cloned by importNode() is explicitly defined\n by the specs.\n */\n returnNode = importNode.call(originalDocument, returnNode, true);\n }\n return returnNode;\n }\n let serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;\n /* Serialize doctype if allowed */\n if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {\n serializedHTML = '\\n' + serializedHTML;\n }\n /* Sanitize final string template-safe */\n if (SAFE_FOR_TEMPLATES) {\n arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {\n serializedHTML = stringReplace(serializedHTML, expr, ' ');\n });\n }\n return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;\n };\n DOMPurify.setConfig = function () {\n let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n _parseConfig(cfg);\n SET_CONFIG = true;\n };\n DOMPurify.clearConfig = function () {\n CONFIG = null;\n SET_CONFIG = false;\n };\n DOMPurify.isValidAttribute = function (tag, attr, value) {\n /* Initialize shared config vars if necessary. */\n if (!CONFIG) {\n _parseConfig({});\n }\n const lcTag = transformCaseFunc(tag);\n const lcName = transformCaseFunc(attr);\n return _isValidAttribute(lcTag, lcName, value);\n };\n DOMPurify.addHook = function (entryPoint, hookFunction) {\n if (typeof hookFunction !== 'function') {\n return;\n }\n arrayPush(hooks[entryPoint], hookFunction);\n };\n DOMPurify.removeHook = function (entryPoint, hookFunction) {\n if (hookFunction !== undefined) {\n const index = arrayLastIndexOf(hooks[entryPoint], hookFunction);\n return index === -1 ? undefined : arraySplice(hooks[entryPoint], index, 1)[0];\n }\n return arrayPop(hooks[entryPoint]);\n };\n DOMPurify.removeHooks = function (entryPoint) {\n hooks[entryPoint] = [];\n };\n DOMPurify.removeAllHooks = function () {\n hooks = _createHooksMap();\n };\n return DOMPurify;\n}\nvar purify = createDOMPurify();\n\nexport { purify as default };\n//# sourceMappingURL=purify.es.mjs.map\n","/**\n * marked v17.0.1 - a markdown parser\n * Copyright (c) 2018-2025, MarkedJS. (MIT License)\n * Copyright (c) 2011-2018, Christopher Jeffrey. (MIT License)\n * https://github.com/markedjs/marked\n */\n\n/**\n * DO NOT EDIT THIS FILE\n * The code in this file is generated from files in ./src/\n */\n\nfunction L(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}var T=L();function Z(u){T=u}var C={exec:()=>null};function k(u,e=\"\"){let t=typeof u==\"string\"?u:u.source,n={replace:(r,i)=>{let s=typeof i==\"string\"?i:i.source;return s=s.replace(m.caret,\"$1\"),t=t.replace(r,s),n},getRegex:()=>new RegExp(t,e)};return n}var me=(()=>{try{return!!new RegExp(\"(?<=1)(?/,blockquoteSetextReplace:/\\n {0,3}((?:=+|-+) *)(?=\\n|$)/g,blockquoteSetextReplace2:/^ {0,3}>[ \\t]?/gm,listReplaceTabs:/^\\t+/,listReplaceNesting:/^ {1,4}(?=( {4})*[^ ])/g,listIsTask:/^\\[[ xX]\\] +\\S/,listReplaceTask:/^\\[[ xX]\\] +/,listTaskCheckbox:/\\[[ xX]\\]/,anyLine:/\\n.*\\n/,hrefBrackets:/^<(.*)>$/,tableDelimiter:/[:|]/,tableAlignChars:/^\\||\\| *$/g,tableRowBlankLine:/\\n[ \\t]*$/,tableAlignRight:/^ *-+: *$/,tableAlignCenter:/^ *:-+: *$/,tableAlignLeft:/^ *:-+ *$/,startATag:/^/i,startPreScriptTag:/^<(pre|code|kbd|script)(\\s|>)/i,endPreScriptTag:/^<\\/(pre|code|kbd|script)(\\s|>)/i,startAngleBracket:/^$/,pedanticHrefTitle:/^([^'\"]*[^\\s])\\s+(['\"])(.*)\\2/,unicodeAlphaNumeric:/[\\p{L}\\p{N}]/u,escapeTest:/[&<>\"']/,escapeReplace:/[&<>\"']/g,escapeTestNoEncode:/[<>\"']|&(?!(#\\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\\w+);)/,escapeReplaceNoEncode:/[<>\"']|&(?!(#\\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\\w+);)/g,unescapeTest:/&(#(?:\\d+)|(?:#x[0-9A-Fa-f]+)|(?:\\w+));?/ig,caret:/(^|[^\\[])\\^/g,percentDecode:/%25/g,findPipe:/\\|/g,splitPipe:/ \\|/,slashPipe:/\\\\\\|/g,carriageReturn:/\\r\\n|\\r/g,spaceLine:/^ +$/gm,notSpaceStart:/^\\S*/,endingNewline:/\\n$/,listItemRegex:u=>new RegExp(`^( {0,3}${u})((?:[\t ][^\\\\n]*)?(?:\\\\n|$))`),nextBulletRegex:u=>new RegExp(`^ {0,${Math.min(3,u-1)}}(?:[*+-]|\\\\d{1,9}[.)])((?:[ \t][^\\\\n]*)?(?:\\\\n|$))`),hrRegex:u=>new RegExp(`^ {0,${Math.min(3,u-1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\\\* *){3,})(?:\\\\n+|$)`),fencesBeginRegex:u=>new RegExp(`^ {0,${Math.min(3,u-1)}}(?:\\`\\`\\`|~~~)`),headingBeginRegex:u=>new RegExp(`^ {0,${Math.min(3,u-1)}}#`),htmlBeginRegex:u=>new RegExp(`^ {0,${Math.min(3,u-1)}}<(?:[a-z].*>|!--)`,\"i\")},xe=/^(?:[ \\t]*(?:\\n|$))+/,be=/^((?: {4}| {0,3}\\t)[^\\n]+(?:\\n(?:[ \\t]*(?:\\n|$))*)?)+/,Re=/^ {0,3}(`{3,}(?=[^`\\n]*(?:\\n|$))|~{3,})([^\\n]*)(?:\\n|$)(?:|([\\s\\S]*?)(?:\\n|$))(?: {0,3}\\1[~`]* *(?=\\n|$)|$)/,I=/^ {0,3}((?:-[\\t ]*){3,}|(?:_[ \\t]*){3,}|(?:\\*[ \\t]*){3,})(?:\\n+|$)/,Te=/^ {0,3}(#{1,6})(?=\\s|$)(.*)(?:\\n+|$)/,N=/(?:[*+-]|\\d{1,9}[.)])/,re=/^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\\n(?!\\s*?\\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\\n {0,3}(=+|-+) *(?:\\n+|$)/,se=k(re).replace(/bull/g,N).replace(/blockCode/g,/(?: {4}| {0,3}\\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\\n>]+>\\n/).replace(/\\|table/g,\"\").getRegex(),Oe=k(re).replace(/bull/g,N).replace(/blockCode/g,/(?: {4}| {0,3}\\t)/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\\n>]+>\\n/).replace(/table/g,/ {0,3}\\|?(?:[:\\- ]*\\|)+[\\:\\- ]*\\n/).getRegex(),Q=/^([^\\n]+(?:\\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\\n)[^\\n]+)*)/,we=/^[^\\n]+/,F=/(?!\\s*\\])(?:\\\\[\\s\\S]|[^\\[\\]\\\\])+/,ye=k(/^ {0,3}\\[(label)\\]: *(?:\\n[ \\t]*)?([^<\\s][^\\s]*|<.*?>)(?:(?: +(?:\\n[ \\t]*)?| *\\n[ \\t]*)(title))? *(?:\\n+|$)/).replace(\"label\",F).replace(\"title\",/(?:\"(?:\\\\\"?|[^\"\\\\])*\"|'[^'\\n]*(?:\\n[^'\\n]+)*\\n?'|\\([^()]*\\))/).getRegex(),Pe=k(/^( {0,3}bull)([ \\t][^\\n]+?)?(?:\\n|$)/).replace(/bull/g,N).getRegex(),v=\"address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul\",j=/|$))/,Se=k(\"^ {0,3}(?:<(script|pre|style|textarea)[\\\\s>][\\\\s\\\\S]*?(?:[^\\\\n]*\\\\n+|$)|comment[^\\\\n]*(\\\\n+|$)|<\\\\?[\\\\s\\\\S]*?(?:\\\\?>\\\\n*|$)|\\\\n*|$)|\\\\n*|$)|)[\\\\s\\\\S]*?(?:(?:\\\\n[ \t]*)+\\\\n|$)|<(?!script|pre|style|textarea)([a-z][\\\\w-]*)(?:attribute)*? */?>(?=[ \\\\t]*(?:\\\\n|$))[\\\\s\\\\S]*?(?:(?:\\\\n[ \t]*)+\\\\n|$)|(?=[ \\\\t]*(?:\\\\n|$))[\\\\s\\\\S]*?(?:(?:\\\\n[ \t]*)+\\\\n|$))\",\"i\").replace(\"comment\",j).replace(\"tag\",v).replace(\"attribute\",/ +[a-zA-Z:_][\\w.:-]*(?: *= *\"[^\"\\n]*\"| *= *'[^'\\n]*'| *= *[^\\s\"'=<>`]+)?/).getRegex(),ie=k(Q).replace(\"hr\",I).replace(\"heading\",\" {0,3}#{1,6}(?:\\\\s|$)\").replace(\"|lheading\",\"\").replace(\"|table\",\"\").replace(\"blockquote\",\" {0,3}>\").replace(\"fences\",\" {0,3}(?:`{3,}(?=[^`\\\\n]*\\\\n)|~{3,})[^\\\\n]*\\\\n\").replace(\"list\",\" {0,3}(?:[*+-]|1[.)]) \").replace(\"html\",\")|<(?:script|pre|style|textarea|!--)\").replace(\"tag\",v).getRegex(),$e=k(/^( {0,3}> ?(paragraph|[^\\n]*)(?:\\n|$))+/).replace(\"paragraph\",ie).getRegex(),U={blockquote:$e,code:be,def:ye,fences:Re,heading:Te,hr:I,html:Se,lheading:se,list:Pe,newline:xe,paragraph:ie,table:C,text:we},te=k(\"^ *([^\\\\n ].*)\\\\n {0,3}((?:\\\\| *)?:?-+:? *(?:\\\\| *:?-+:? *)*(?:\\\\| *)?)(?:\\\\n((?:(?! *\\\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\\\n|$))*)\\\\n*|$)\").replace(\"hr\",I).replace(\"heading\",\" {0,3}#{1,6}(?:\\\\s|$)\").replace(\"blockquote\",\" {0,3}>\").replace(\"code\",\"(?: {4}| {0,3}\t)[^\\\\n]\").replace(\"fences\",\" {0,3}(?:`{3,}(?=[^`\\\\n]*\\\\n)|~{3,})[^\\\\n]*\\\\n\").replace(\"list\",\" {0,3}(?:[*+-]|1[.)]) \").replace(\"html\",\")|<(?:script|pre|style|textarea|!--)\").replace(\"tag\",v).getRegex(),_e={...U,lheading:Oe,table:te,paragraph:k(Q).replace(\"hr\",I).replace(\"heading\",\" {0,3}#{1,6}(?:\\\\s|$)\").replace(\"|lheading\",\"\").replace(\"table\",te).replace(\"blockquote\",\" {0,3}>\").replace(\"fences\",\" {0,3}(?:`{3,}(?=[^`\\\\n]*\\\\n)|~{3,})[^\\\\n]*\\\\n\").replace(\"list\",\" {0,3}(?:[*+-]|1[.)]) \").replace(\"html\",\")|<(?:script|pre|style|textarea|!--)\").replace(\"tag\",v).getRegex()},Le={...U,html:k(`^ *(?:comment *(?:\\\\n|\\\\s*$)|<(tag)[\\\\s\\\\S]+? *(?:\\\\n{2,}|\\\\s*$)|\\\\s]*)*?/?> *(?:\\\\n{2,}|\\\\s*$))`).replace(\"comment\",j).replace(/tag/g,\"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\\\b)\\\\w+(?!:|[^\\\\w\\\\s@]*@)\\\\b\").getRegex(),def:/^ *\\[([^\\]]+)\\]: *]+)>?(?: +([\"(][^\\n]+[\")]))? *(?:\\n+|$)/,heading:/^(#{1,6})(.*)(?:\\n+|$)/,fences:C,lheading:/^(.+?)\\n {0,3}(=+|-+) *(?:\\n+|$)/,paragraph:k(Q).replace(\"hr\",I).replace(\"heading\",` *#{1,6} *[^\n]`).replace(\"lheading\",se).replace(\"|table\",\"\").replace(\"blockquote\",\" {0,3}>\").replace(\"|fences\",\"\").replace(\"|list\",\"\").replace(\"|html\",\"\").replace(\"|tag\",\"\").getRegex()},Me=/^\\\\([!\"#$%&'()*+,\\-./:;<=>?@\\[\\]\\\\^_`{|}~])/,ze=/^(`+)([^`]|[^`][\\s\\S]*?[^`])\\1(?!`)/,oe=/^( {2,}|\\\\)\\n(?!\\s*$)/,Ae=/^(`+|[^`])(?:(?= {2,}\\n)|[\\s\\S]*?(?:(?=[\\\\`+)[^`]+\\k(?!`))*?\\]\\((?:\\\\[\\s\\S]|[^\\\\\\(\\)]|\\((?:\\\\[\\s\\S]|[^\\\\\\(\\)])*\\))*\\)/).replace(\"precode-\",me?\"(?`+)[^`]+\\k(?!`)/).replace(\"html\",/<(?! )[^<>]*?>/).getRegex(),ue=/^(?:\\*+(?:((?!\\*)punct)|[^\\s*]))|^_+(?:((?!_)punct)|([^\\s_]))/,qe=k(ue,\"u\").replace(/punct/g,D).getRegex(),ve=k(ue,\"u\").replace(/punct/g,le).getRegex(),pe=\"^[^_*]*?__[^_*]*?\\\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\\\*)punct(\\\\*+)(?=[\\\\s]|$)|notPunctSpace(\\\\*+)(?!\\\\*)(?=punctSpace|$)|(?!\\\\*)punctSpace(\\\\*+)(?=notPunctSpace)|[\\\\s](\\\\*+)(?!\\\\*)(?=punct)|(?!\\\\*)punct(\\\\*+)(?!\\\\*)(?=punct)|notPunctSpace(\\\\*+)(?=notPunctSpace)\",De=k(pe,\"gu\").replace(/notPunctSpace/g,ae).replace(/punctSpace/g,K).replace(/punct/g,D).getRegex(),He=k(pe,\"gu\").replace(/notPunctSpace/g,Ee).replace(/punctSpace/g,Ie).replace(/punct/g,le).getRegex(),Ze=k(\"^[^_*]*?\\\\*\\\\*[^_*]*?_[^_*]*?(?=\\\\*\\\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)\",\"gu\").replace(/notPunctSpace/g,ae).replace(/punctSpace/g,K).replace(/punct/g,D).getRegex(),Ge=k(/\\\\(punct)/,\"gu\").replace(/punct/g,D).getRegex(),Ne=k(/^<(scheme:[^\\s\\x00-\\x1f<>]*|email)>/).replace(\"scheme\",/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace(\"email\",/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(),Qe=k(j).replace(\"(?:-->|$)\",\"-->\").getRegex(),Fe=k(\"^comment|^|^<[a-zA-Z][\\\\w-]*(?:attribute)*?\\\\s*/?>|^<\\\\?[\\\\s\\\\S]*?\\\\?>|^|^\").replace(\"comment\",Qe).replace(\"attribute\",/\\s+[a-zA-Z:_][\\w.:-]*(?:\\s*=\\s*\"[^\"]*\"|\\s*=\\s*'[^']*'|\\s*=\\s*[^\\s\"'=<>`]+)?/).getRegex(),q=/(?:\\[(?:\\\\[\\s\\S]|[^\\[\\]\\\\])*\\]|\\\\[\\s\\S]|`+[^`]*?`+(?!`)|[^\\[\\]\\\\`])*?/,je=k(/^!?\\[(label)\\]\\(\\s*(href)(?:(?:[ \\t]*(?:\\n[ \\t]*)?)(title))?\\s*\\)/).replace(\"label\",q).replace(\"href\",/<(?:\\\\.|[^\\n<>\\\\])+>|[^ \\t\\n\\x00-\\x1f]*/).replace(\"title\",/\"(?:\\\\\"?|[^\"\\\\])*\"|'(?:\\\\'?|[^'\\\\])*'|\\((?:\\\\\\)?|[^)\\\\])*\\)/).getRegex(),ce=k(/^!?\\[(label)\\]\\[(ref)\\]/).replace(\"label\",q).replace(\"ref\",F).getRegex(),he=k(/^!?\\[(ref)\\](?:\\[\\])?/).replace(\"ref\",F).getRegex(),Ue=k(\"reflink|nolink(?!\\\\()\",\"g\").replace(\"reflink\",ce).replace(\"nolink\",he).getRegex(),ne=/[hH][tT][tT][pP][sS]?|[fF][tT][pP]/,W={_backpedal:C,anyPunctuation:Ge,autolink:Ne,blockSkip:Be,br:oe,code:ze,del:C,emStrongLDelim:qe,emStrongRDelimAst:De,emStrongRDelimUnd:Ze,escape:Me,link:je,nolink:he,punctuation:Ce,reflink:ce,reflinkSearch:Ue,tag:Fe,text:Ae,url:C},Ke={...W,link:k(/^!?\\[(label)\\]\\((.*?)\\)/).replace(\"label\",q).getRegex(),reflink:k(/^!?\\[(label)\\]\\s*\\[([^\\]]*)\\]/).replace(\"label\",q).getRegex()},G={...W,emStrongRDelimAst:He,emStrongLDelim:ve,url:k(/^((?:protocol):\\/\\/|www\\.)(?:[a-zA-Z0-9\\-]+\\.?)+[^\\s<]*|^email/).replace(\"protocol\",ne).replace(\"email\",/[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(),_backpedal:/(?:[^?!.,:;*_'\"~()&]+|\\([^)]*\\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'\"~)]+(?!$))+/,del:/^(~~?)(?=[^\\s~])((?:\\\\[\\s\\S]|[^\\\\])*?(?:\\\\[\\s\\S]|[^\\s~\\\\]))\\1(?=[^~]|$)/,text:k(/^([`~]+|[^`~])(?:(?= {2,}\\n)|(?=[a-zA-Z0-9.!#$%&'*+\\/=?_`{\\|}~-]+@)|[\\s\\S]*?(?:(?=[\\\\\":\">\",'\"':\""\",\"'\":\"'\"},ke=u=>Xe[u];function w(u,e){if(e){if(m.escapeTest.test(u))return u.replace(m.escapeReplace,ke)}else if(m.escapeTestNoEncode.test(u))return u.replace(m.escapeReplaceNoEncode,ke);return u}function X(u){try{u=encodeURI(u).replace(m.percentDecode,\"%\")}catch{return null}return u}function J(u,e){let t=u.replace(m.findPipe,(i,s,a)=>{let o=!1,l=s;for(;--l>=0&&a[l]===\"\\\\\";)o=!o;return o?\"|\":\" |\"}),n=t.split(m.splitPipe),r=0;if(n[0].trim()||n.shift(),n.length>0&&!n.at(-1)?.trim()&&n.pop(),e)if(n.length>e)n.splice(e);else for(;n.length0?-2:-1}function ge(u,e,t,n,r){let i=e.href,s=e.title||null,a=u[1].replace(r.other.outputLinkReplace,\"$1\");n.state.inLink=!0;let o={type:u[0].charAt(0)===\"!\"?\"image\":\"link\",raw:t,href:i,title:s,text:a,tokens:n.inlineTokens(a)};return n.state.inLink=!1,o}function Je(u,e,t){let n=u.match(t.other.indentCodeCompensation);if(n===null)return e;let r=n[1];return e.split(`\n`).map(i=>{let s=i.match(t.other.beginningSpace);if(s===null)return i;let[a]=s;return a.length>=r.length?i.slice(r.length):i}).join(`\n`)}var y=class{options;rules;lexer;constructor(e){this.options=e||T}space(e){let t=this.rules.block.newline.exec(e);if(t&&t[0].length>0)return{type:\"space\",raw:t[0]}}code(e){let t=this.rules.block.code.exec(e);if(t){let n=t[0].replace(this.rules.other.codeRemoveIndent,\"\");return{type:\"code\",raw:t[0],codeBlockStyle:\"indented\",text:this.options.pedantic?n:z(n,`\n`)}}}fences(e){let t=this.rules.block.fences.exec(e);if(t){let n=t[0],r=Je(n,t[3]||\"\",this.rules);return{type:\"code\",raw:n,lang:t[2]?t[2].trim().replace(this.rules.inline.anyPunctuation,\"$1\"):t[2],text:r}}}heading(e){let t=this.rules.block.heading.exec(e);if(t){let n=t[2].trim();if(this.rules.other.endingHash.test(n)){let r=z(n,\"#\");(this.options.pedantic||!r||this.rules.other.endingSpaceChar.test(r))&&(n=r.trim())}return{type:\"heading\",raw:t[0],depth:t[1].length,text:n,tokens:this.lexer.inline(n)}}}hr(e){let t=this.rules.block.hr.exec(e);if(t)return{type:\"hr\",raw:z(t[0],`\n`)}}blockquote(e){let t=this.rules.block.blockquote.exec(e);if(t){let n=z(t[0],`\n`).split(`\n`),r=\"\",i=\"\",s=[];for(;n.length>0;){let a=!1,o=[],l;for(l=0;l1,i={type:\"list\",raw:\"\",ordered:r,start:r?+n.slice(0,-1):\"\",loose:!1,items:[]};n=r?`\\\\d{1,9}\\\\${n.slice(-1)}`:`\\\\${n}`,this.options.pedantic&&(n=r?n:\"[*+-]\");let s=this.rules.other.listItemRegex(n),a=!1;for(;e;){let l=!1,p=\"\",c=\"\";if(!(t=s.exec(e))||this.rules.block.hr.test(e))break;p=t[0],e=e.substring(p.length);let g=t[2].split(`\n`,1)[0].replace(this.rules.other.listReplaceTabs,O=>\" \".repeat(3*O.length)),h=e.split(`\n`,1)[0],R=!g.trim(),f=0;if(this.options.pedantic?(f=2,c=g.trimStart()):R?f=t[1].length+1:(f=t[2].search(this.rules.other.nonSpaceChar),f=f>4?1:f,c=g.slice(f),f+=t[1].length),R&&this.rules.other.blankLine.test(h)&&(p+=h+`\n`,e=e.substring(h.length+1),l=!0),!l){let O=this.rules.other.nextBulletRegex(f),V=this.rules.other.hrRegex(f),Y=this.rules.other.fencesBeginRegex(f),ee=this.rules.other.headingBeginRegex(f),fe=this.rules.other.htmlBeginRegex(f);for(;e;){let H=e.split(`\n`,1)[0],A;if(h=H,this.options.pedantic?(h=h.replace(this.rules.other.listReplaceNesting,\" \"),A=h):A=h.replace(this.rules.other.tabCharGlobal,\" \"),Y.test(h)||ee.test(h)||fe.test(h)||O.test(h)||V.test(h))break;if(A.search(this.rules.other.nonSpaceChar)>=f||!h.trim())c+=`\n`+A.slice(f);else{if(R||g.replace(this.rules.other.tabCharGlobal,\" \").search(this.rules.other.nonSpaceChar)>=4||Y.test(g)||ee.test(g)||V.test(g))break;c+=`\n`+h}!R&&!h.trim()&&(R=!0),p+=H+`\n`,e=e.substring(H.length+1),g=A.slice(f)}}i.loose||(a?i.loose=!0:this.rules.other.doubleBlankLine.test(p)&&(a=!0)),i.items.push({type:\"list_item\",raw:p,task:!!this.options.gfm&&this.rules.other.listIsTask.test(c),loose:!1,text:c,tokens:[]}),i.raw+=p}let o=i.items.at(-1);if(o)o.raw=o.raw.trimEnd(),o.text=o.text.trimEnd();else return;i.raw=i.raw.trimEnd();for(let l of i.items){if(this.lexer.state.top=!1,l.tokens=this.lexer.blockTokens(l.text,[]),l.task){if(l.text=l.text.replace(this.rules.other.listReplaceTask,\"\"),l.tokens[0]?.type===\"text\"||l.tokens[0]?.type===\"paragraph\"){l.tokens[0].raw=l.tokens[0].raw.replace(this.rules.other.listReplaceTask,\"\"),l.tokens[0].text=l.tokens[0].text.replace(this.rules.other.listReplaceTask,\"\");for(let c=this.lexer.inlineQueue.length-1;c>=0;c--)if(this.rules.other.listIsTask.test(this.lexer.inlineQueue[c].src)){this.lexer.inlineQueue[c].src=this.lexer.inlineQueue[c].src.replace(this.rules.other.listReplaceTask,\"\");break}}let p=this.rules.other.listTaskCheckbox.exec(l.raw);if(p){let c={type:\"checkbox\",raw:p[0]+\" \",checked:p[0]!==\"[ ]\"};l.checked=c.checked,i.loose?l.tokens[0]&&[\"paragraph\",\"text\"].includes(l.tokens[0].type)&&\"tokens\"in l.tokens[0]&&l.tokens[0].tokens?(l.tokens[0].raw=c.raw+l.tokens[0].raw,l.tokens[0].text=c.raw+l.tokens[0].text,l.tokens[0].tokens.unshift(c)):l.tokens.unshift({type:\"paragraph\",raw:c.raw,text:c.raw,tokens:[c]}):l.tokens.unshift(c)}}if(!i.loose){let p=l.tokens.filter(g=>g.type===\"space\"),c=p.length>0&&p.some(g=>this.rules.other.anyLine.test(g.raw));i.loose=c}}if(i.loose)for(let l of i.items){l.loose=!0;for(let p of l.tokens)p.type===\"text\"&&(p.type=\"paragraph\")}return i}}html(e){let t=this.rules.block.html.exec(e);if(t)return{type:\"html\",block:!0,raw:t[0],pre:t[1]===\"pre\"||t[1]===\"script\"||t[1]===\"style\",text:t[0]}}def(e){let t=this.rules.block.def.exec(e);if(t){let n=t[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal,\" \"),r=t[2]?t[2].replace(this.rules.other.hrefBrackets,\"$1\").replace(this.rules.inline.anyPunctuation,\"$1\"):\"\",i=t[3]?t[3].substring(1,t[3].length-1).replace(this.rules.inline.anyPunctuation,\"$1\"):t[3];return{type:\"def\",tag:n,raw:t[0],href:r,title:i}}}table(e){let t=this.rules.block.table.exec(e);if(!t||!this.rules.other.tableDelimiter.test(t[2]))return;let n=J(t[1]),r=t[2].replace(this.rules.other.tableAlignChars,\"\").split(\"|\"),i=t[3]?.trim()?t[3].replace(this.rules.other.tableRowBlankLine,\"\").split(`\n`):[],s={type:\"table\",raw:t[0],header:[],align:[],rows:[]};if(n.length===r.length){for(let a of r)this.rules.other.tableAlignRight.test(a)?s.align.push(\"right\"):this.rules.other.tableAlignCenter.test(a)?s.align.push(\"center\"):this.rules.other.tableAlignLeft.test(a)?s.align.push(\"left\"):s.align.push(null);for(let a=0;a({text:o,tokens:this.lexer.inline(o),header:!1,align:s.align[l]})));return s}}lheading(e){let t=this.rules.block.lheading.exec(e);if(t)return{type:\"heading\",raw:t[0],depth:t[2].charAt(0)===\"=\"?1:2,text:t[1],tokens:this.lexer.inline(t[1])}}paragraph(e){let t=this.rules.block.paragraph.exec(e);if(t){let n=t[1].charAt(t[1].length-1)===`\n`?t[1].slice(0,-1):t[1];return{type:\"paragraph\",raw:t[0],text:n,tokens:this.lexer.inline(n)}}}text(e){let t=this.rules.block.text.exec(e);if(t)return{type:\"text\",raw:t[0],text:t[0],tokens:this.lexer.inline(t[0])}}escape(e){let t=this.rules.inline.escape.exec(e);if(t)return{type:\"escape\",raw:t[0],text:t[1]}}tag(e){let t=this.rules.inline.tag.exec(e);if(t)return!this.lexer.state.inLink&&this.rules.other.startATag.test(t[0])?this.lexer.state.inLink=!0:this.lexer.state.inLink&&this.rules.other.endATag.test(t[0])&&(this.lexer.state.inLink=!1),!this.lexer.state.inRawBlock&&this.rules.other.startPreScriptTag.test(t[0])?this.lexer.state.inRawBlock=!0:this.lexer.state.inRawBlock&&this.rules.other.endPreScriptTag.test(t[0])&&(this.lexer.state.inRawBlock=!1),{type:\"html\",raw:t[0],inLink:this.lexer.state.inLink,inRawBlock:this.lexer.state.inRawBlock,block:!1,text:t[0]}}link(e){let t=this.rules.inline.link.exec(e);if(t){let n=t[2].trim();if(!this.options.pedantic&&this.rules.other.startAngleBracket.test(n)){if(!this.rules.other.endAngleBracket.test(n))return;let s=z(n.slice(0,-1),\"\\\\\");if((n.length-s.length)%2===0)return}else{let s=de(t[2],\"()\");if(s===-2)return;if(s>-1){let o=(t[0].indexOf(\"!\")===0?5:4)+t[1].length+s;t[2]=t[2].substring(0,s),t[0]=t[0].substring(0,o).trim(),t[3]=\"\"}}let r=t[2],i=\"\";if(this.options.pedantic){let s=this.rules.other.pedanticHrefTitle.exec(r);s&&(r=s[1],i=s[3])}else i=t[3]?t[3].slice(1,-1):\"\";return r=r.trim(),this.rules.other.startAngleBracket.test(r)&&(this.options.pedantic&&!this.rules.other.endAngleBracket.test(n)?r=r.slice(1):r=r.slice(1,-1)),ge(t,{href:r&&r.replace(this.rules.inline.anyPunctuation,\"$1\"),title:i&&i.replace(this.rules.inline.anyPunctuation,\"$1\")},t[0],this.lexer,this.rules)}}reflink(e,t){let n;if((n=this.rules.inline.reflink.exec(e))||(n=this.rules.inline.nolink.exec(e))){let r=(n[2]||n[1]).replace(this.rules.other.multipleSpaceGlobal,\" \"),i=t[r.toLowerCase()];if(!i){let s=n[0].charAt(0);return{type:\"text\",raw:s,text:s}}return ge(n,i,n[0],this.lexer,this.rules)}}emStrong(e,t,n=\"\"){let r=this.rules.inline.emStrongLDelim.exec(e);if(!r||r[3]&&n.match(this.rules.other.unicodeAlphaNumeric))return;if(!(r[1]||r[2]||\"\")||!n||this.rules.inline.punctuation.exec(n)){let s=[...r[0]].length-1,a,o,l=s,p=0,c=r[0][0]===\"*\"?this.rules.inline.emStrongRDelimAst:this.rules.inline.emStrongRDelimUnd;for(c.lastIndex=0,t=t.slice(-1*e.length+s);(r=c.exec(t))!=null;){if(a=r[1]||r[2]||r[3]||r[4]||r[5]||r[6],!a)continue;if(o=[...a].length,r[3]||r[4]){l+=o;continue}else if((r[5]||r[6])&&s%3&&!((s+o)%3)){p+=o;continue}if(l-=o,l>0)continue;o=Math.min(o,o+l+p);let g=[...r[0]][0].length,h=e.slice(0,s+r.index+g+o);if(Math.min(s,o)%2){let f=h.slice(1,-1);return{type:\"em\",raw:h,text:f,tokens:this.lexer.inlineTokens(f)}}let R=h.slice(2,-2);return{type:\"strong\",raw:h,text:R,tokens:this.lexer.inlineTokens(R)}}}}codespan(e){let t=this.rules.inline.code.exec(e);if(t){let n=t[2].replace(this.rules.other.newLineCharGlobal,\" \"),r=this.rules.other.nonSpaceChar.test(n),i=this.rules.other.startingSpaceChar.test(n)&&this.rules.other.endingSpaceChar.test(n);return r&&i&&(n=n.substring(1,n.length-1)),{type:\"codespan\",raw:t[0],text:n}}}br(e){let t=this.rules.inline.br.exec(e);if(t)return{type:\"br\",raw:t[0]}}del(e){let t=this.rules.inline.del.exec(e);if(t)return{type:\"del\",raw:t[0],text:t[2],tokens:this.lexer.inlineTokens(t[2])}}autolink(e){let t=this.rules.inline.autolink.exec(e);if(t){let n,r;return t[2]===\"@\"?(n=t[1],r=\"mailto:\"+n):(n=t[1],r=n),{type:\"link\",raw:t[0],text:n,href:r,tokens:[{type:\"text\",raw:n,text:n}]}}}url(e){let t;if(t=this.rules.inline.url.exec(e)){let n,r;if(t[2]===\"@\")n=t[0],r=\"mailto:\"+n;else{let i;do i=t[0],t[0]=this.rules.inline._backpedal.exec(t[0])?.[0]??\"\";while(i!==t[0]);n=t[0],t[1]===\"www.\"?r=\"http://\"+t[0]:r=t[0]}return{type:\"link\",raw:t[0],text:n,href:r,tokens:[{type:\"text\",raw:n,text:n}]}}}inlineText(e){let t=this.rules.inline.text.exec(e);if(t){let n=this.lexer.state.inRawBlock;return{type:\"text\",raw:t[0],text:t[0],escaped:n}}}};var x=class u{tokens;options;state;inlineQueue;tokenizer;constructor(e){this.tokens=[],this.tokens.links=Object.create(null),this.options=e||T,this.options.tokenizer=this.options.tokenizer||new y,this.tokenizer=this.options.tokenizer,this.tokenizer.options=this.options,this.tokenizer.lexer=this,this.inlineQueue=[],this.state={inLink:!1,inRawBlock:!1,top:!0};let t={other:m,block:E.normal,inline:M.normal};this.options.pedantic?(t.block=E.pedantic,t.inline=M.pedantic):this.options.gfm&&(t.block=E.gfm,this.options.breaks?t.inline=M.breaks:t.inline=M.gfm),this.tokenizer.rules=t}static get rules(){return{block:E,inline:M}}static lex(e,t){return new u(t).lex(e)}static lexInline(e,t){return new u(t).inlineTokens(e)}lex(e){e=e.replace(m.carriageReturn,`\n`),this.blockTokens(e,this.tokens);for(let t=0;t(r=s.call({lexer:this},e,t))?(e=e.substring(r.raw.length),t.push(r),!0):!1))continue;if(r=this.tokenizer.space(e)){e=e.substring(r.raw.length);let s=t.at(-1);r.raw.length===1&&s!==void 0?s.raw+=`\n`:t.push(r);continue}if(r=this.tokenizer.code(e)){e=e.substring(r.raw.length);let s=t.at(-1);s?.type===\"paragraph\"||s?.type===\"text\"?(s.raw+=(s.raw.endsWith(`\n`)?\"\":`\n`)+r.raw,s.text+=`\n`+r.text,this.inlineQueue.at(-1).src=s.text):t.push(r);continue}if(r=this.tokenizer.fences(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.heading(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.hr(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.blockquote(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.list(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.html(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.def(e)){e=e.substring(r.raw.length);let s=t.at(-1);s?.type===\"paragraph\"||s?.type===\"text\"?(s.raw+=(s.raw.endsWith(`\n`)?\"\":`\n`)+r.raw,s.text+=`\n`+r.raw,this.inlineQueue.at(-1).src=s.text):this.tokens.links[r.tag]||(this.tokens.links[r.tag]={href:r.href,title:r.title},t.push(r));continue}if(r=this.tokenizer.table(e)){e=e.substring(r.raw.length),t.push(r);continue}if(r=this.tokenizer.lheading(e)){e=e.substring(r.raw.length),t.push(r);continue}let i=e;if(this.options.extensions?.startBlock){let s=1/0,a=e.slice(1),o;this.options.extensions.startBlock.forEach(l=>{o=l.call({lexer:this},a),typeof o==\"number\"&&o>=0&&(s=Math.min(s,o))}),s<1/0&&s>=0&&(i=e.substring(0,s+1))}if(this.state.top&&(r=this.tokenizer.paragraph(i))){let s=t.at(-1);n&&s?.type===\"paragraph\"?(s.raw+=(s.raw.endsWith(`\n`)?\"\":`\n`)+r.raw,s.text+=`\n`+r.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=s.text):t.push(r),n=i.length!==e.length,e=e.substring(r.raw.length);continue}if(r=this.tokenizer.text(e)){e=e.substring(r.raw.length);let s=t.at(-1);s?.type===\"text\"?(s.raw+=(s.raw.endsWith(`\n`)?\"\":`\n`)+r.raw,s.text+=`\n`+r.text,this.inlineQueue.pop(),this.inlineQueue.at(-1).src=s.text):t.push(r);continue}if(e){let s=\"Infinite loop on byte: \"+e.charCodeAt(0);if(this.options.silent){console.error(s);break}else throw new Error(s)}}return this.state.top=!0,t}inline(e,t=[]){return this.inlineQueue.push({src:e,tokens:t}),t}inlineTokens(e,t=[]){let n=e,r=null;if(this.tokens.links){let o=Object.keys(this.tokens.links);if(o.length>0)for(;(r=this.tokenizer.rules.inline.reflinkSearch.exec(n))!=null;)o.includes(r[0].slice(r[0].lastIndexOf(\"[\")+1,-1))&&(n=n.slice(0,r.index)+\"[\"+\"a\".repeat(r[0].length-2)+\"]\"+n.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex))}for(;(r=this.tokenizer.rules.inline.anyPunctuation.exec(n))!=null;)n=n.slice(0,r.index)+\"++\"+n.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);let i;for(;(r=this.tokenizer.rules.inline.blockSkip.exec(n))!=null;)i=r[2]?r[2].length:0,n=n.slice(0,r.index+i)+\"[\"+\"a\".repeat(r[0].length-i-2)+\"]\"+n.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);n=this.options.hooks?.emStrongMask?.call({lexer:this},n)??n;let s=!1,a=\"\";for(;e;){s||(a=\"\"),s=!1;let o;if(this.options.extensions?.inline?.some(p=>(o=p.call({lexer:this},e,t))?(e=e.substring(o.raw.length),t.push(o),!0):!1))continue;if(o=this.tokenizer.escape(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.tag(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.link(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.reflink(e,this.tokens.links)){e=e.substring(o.raw.length);let p=t.at(-1);o.type===\"text\"&&p?.type===\"text\"?(p.raw+=o.raw,p.text+=o.text):t.push(o);continue}if(o=this.tokenizer.emStrong(e,n,a)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.codespan(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.br(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.del(e)){e=e.substring(o.raw.length),t.push(o);continue}if(o=this.tokenizer.autolink(e)){e=e.substring(o.raw.length),t.push(o);continue}if(!this.state.inLink&&(o=this.tokenizer.url(e))){e=e.substring(o.raw.length),t.push(o);continue}let l=e;if(this.options.extensions?.startInline){let p=1/0,c=e.slice(1),g;this.options.extensions.startInline.forEach(h=>{g=h.call({lexer:this},c),typeof g==\"number\"&&g>=0&&(p=Math.min(p,g))}),p<1/0&&p>=0&&(l=e.substring(0,p+1))}if(o=this.tokenizer.inlineText(l)){e=e.substring(o.raw.length),o.raw.slice(-1)!==\"_\"&&(a=o.raw.slice(-1)),s=!0;let p=t.at(-1);p?.type===\"text\"?(p.raw+=o.raw,p.text+=o.text):t.push(o);continue}if(e){let p=\"Infinite loop on byte: \"+e.charCodeAt(0);if(this.options.silent){console.error(p);break}else throw new Error(p)}}return t}};var P=class{options;parser;constructor(e){this.options=e||T}space(e){return\"\"}code({text:e,lang:t,escaped:n}){let r=(t||\"\").match(m.notSpaceStart)?.[0],i=e.replace(m.endingNewline,\"\")+`\n`;return r?'
    '+(n?i:w(i,!0))+`
    \n`:\"
    \"+(n?i:w(i,!0))+`
    \n`}blockquote({tokens:e}){return`
    \n${this.parser.parse(e)}
    \n`}html({text:e}){return e}def(e){return\"\"}heading({tokens:e,depth:t}){return`${this.parser.parseInline(e)}\n`}hr(e){return`
    \n`}list(e){let t=e.ordered,n=e.start,r=\"\";for(let a=0;a\n`+r+\"\n`}listitem(e){return`
  • ${this.parser.parse(e.tokens)}
  • \n`}checkbox({checked:e}){return\" '}paragraph({tokens:e}){return`

    ${this.parser.parseInline(e)}

    \n`}table(e){let t=\"\",n=\"\";for(let i=0;i${r}`),`\n\n`+t+`\n`+r+`
    \n`}tablerow({text:e}){return`\n${e}\n`}tablecell(e){let t=this.parser.parseInline(e.tokens),n=e.header?\"th\":\"td\";return(e.align?`<${n} align=\"${e.align}\">`:`<${n}>`)+t+`\n`}strong({tokens:e}){return`${this.parser.parseInline(e)}`}em({tokens:e}){return`${this.parser.parseInline(e)}`}codespan({text:e}){return`${w(e,!0)}`}br(e){return\"
    \"}del({tokens:e}){return`${this.parser.parseInline(e)}`}link({href:e,title:t,tokens:n}){let r=this.parser.parseInline(n),i=X(e);if(i===null)return r;e=i;let s='
    \"+r+\"\",s}image({href:e,title:t,text:n,tokens:r}){r&&(n=this.parser.parseInline(r,this.parser.textRenderer));let i=X(e);if(i===null)return w(n);e=i;let s=`\"${n}\"`;return\",s}text(e){return\"tokens\"in e&&e.tokens?this.parser.parseInline(e.tokens):\"escaped\"in e&&e.escaped?e.text:w(e.text)}};var $=class{strong({text:e}){return e}em({text:e}){return e}codespan({text:e}){return e}del({text:e}){return e}html({text:e}){return e}text({text:e}){return e}link({text:e}){return\"\"+e}image({text:e}){return\"\"+e}br(){return\"\"}checkbox({raw:e}){return e}};var b=class u{options;renderer;textRenderer;constructor(e){this.options=e||T,this.options.renderer=this.options.renderer||new P,this.renderer=this.options.renderer,this.renderer.options=this.options,this.renderer.parser=this,this.textRenderer=new $}static parse(e,t){return new u(t).parse(e)}static parseInline(e,t){return new u(t).parseInline(e)}parse(e){let t=\"\";for(let n=0;n{let a=i[s].flat(1/0);n=n.concat(this.walkTokens(a,t))}):i.tokens&&(n=n.concat(this.walkTokens(i.tokens,t)))}}return n}use(...e){let t=this.defaults.extensions||{renderers:{},childTokens:{}};return e.forEach(n=>{let r={...n};if(r.async=this.defaults.async||r.async||!1,n.extensions&&(n.extensions.forEach(i=>{if(!i.name)throw new Error(\"extension name required\");if(\"renderer\"in i){let s=t.renderers[i.name];s?t.renderers[i.name]=function(...a){let o=i.renderer.apply(this,a);return o===!1&&(o=s.apply(this,a)),o}:t.renderers[i.name]=i.renderer}if(\"tokenizer\"in i){if(!i.level||i.level!==\"block\"&&i.level!==\"inline\")throw new Error(\"extension level must be 'block' or 'inline'\");let s=t[i.level];s?s.unshift(i.tokenizer):t[i.level]=[i.tokenizer],i.start&&(i.level===\"block\"?t.startBlock?t.startBlock.push(i.start):t.startBlock=[i.start]:i.level===\"inline\"&&(t.startInline?t.startInline.push(i.start):t.startInline=[i.start]))}\"childTokens\"in i&&i.childTokens&&(t.childTokens[i.name]=i.childTokens)}),r.extensions=t),n.renderer){let i=this.defaults.renderer||new P(this.defaults);for(let s in n.renderer){if(!(s in i))throw new Error(`renderer '${s}' does not exist`);if([\"options\",\"parser\"].includes(s))continue;let a=s,o=n.renderer[a],l=i[a];i[a]=(...p)=>{let c=o.apply(i,p);return c===!1&&(c=l.apply(i,p)),c||\"\"}}r.renderer=i}if(n.tokenizer){let i=this.defaults.tokenizer||new y(this.defaults);for(let s in n.tokenizer){if(!(s in i))throw new Error(`tokenizer '${s}' does not exist`);if([\"options\",\"rules\",\"lexer\"].includes(s))continue;let a=s,o=n.tokenizer[a],l=i[a];i[a]=(...p)=>{let c=o.apply(i,p);return c===!1&&(c=l.apply(i,p)),c}}r.tokenizer=i}if(n.hooks){let i=this.defaults.hooks||new S;for(let s in n.hooks){if(!(s in i))throw new Error(`hook '${s}' does not exist`);if([\"options\",\"block\"].includes(s))continue;let a=s,o=n.hooks[a],l=i[a];S.passThroughHooks.has(s)?i[a]=p=>{if(this.defaults.async&&S.passThroughHooksRespectAsync.has(s))return(async()=>{let g=await o.call(i,p);return l.call(i,g)})();let c=o.call(i,p);return l.call(i,c)}:i[a]=(...p)=>{if(this.defaults.async)return(async()=>{let g=await o.apply(i,p);return g===!1&&(g=await l.apply(i,p)),g})();let c=o.apply(i,p);return c===!1&&(c=l.apply(i,p)),c}}r.hooks=i}if(n.walkTokens){let i=this.defaults.walkTokens,s=n.walkTokens;r.walkTokens=function(a){let o=[];return o.push(s.call(this,a)),i&&(o=o.concat(i.call(this,a))),o}}this.defaults={...this.defaults,...r}}),this}setOptions(e){return this.defaults={...this.defaults,...e},this}lexer(e,t){return x.lex(e,t??this.defaults)}parser(e,t){return b.parse(e,t??this.defaults)}parseMarkdown(e){return(n,r)=>{let i={...r},s={...this.defaults,...i},a=this.onError(!!s.silent,!!s.async);if(this.defaults.async===!0&&i.async===!1)return a(new Error(\"marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise.\"));if(typeof n>\"u\"||n===null)return a(new Error(\"marked(): input parameter is undefined or null\"));if(typeof n!=\"string\")return a(new Error(\"marked(): input parameter is of type \"+Object.prototype.toString.call(n)+\", string expected\"));if(s.hooks&&(s.hooks.options=s,s.hooks.block=e),s.async)return(async()=>{let o=s.hooks?await s.hooks.preprocess(n):n,p=await(s.hooks?await s.hooks.provideLexer():e?x.lex:x.lexInline)(o,s),c=s.hooks?await s.hooks.processAllTokens(p):p;s.walkTokens&&await Promise.all(this.walkTokens(c,s.walkTokens));let h=await(s.hooks?await s.hooks.provideParser():e?b.parse:b.parseInline)(c,s);return s.hooks?await s.hooks.postprocess(h):h})().catch(a);try{s.hooks&&(n=s.hooks.preprocess(n));let l=(s.hooks?s.hooks.provideLexer():e?x.lex:x.lexInline)(n,s);s.hooks&&(l=s.hooks.processAllTokens(l)),s.walkTokens&&this.walkTokens(l,s.walkTokens);let c=(s.hooks?s.hooks.provideParser():e?b.parse:b.parseInline)(l,s);return s.hooks&&(c=s.hooks.postprocess(c)),c}catch(o){return a(o)}}}onError(e,t){return n=>{if(n.message+=`\nPlease report this to https://github.com/markedjs/marked.`,e){let r=\"

    An error occurred:

    \"+w(n.message+\"\",!0)+\"
    \";return t?Promise.resolve(r):r}if(t)return Promise.reject(n);throw n}}};var _=new B;function d(u,e){return _.parse(u,e)}d.options=d.setOptions=function(u){return _.setOptions(u),d.defaults=_.defaults,Z(d.defaults),d};d.getDefaults=L;d.defaults=T;d.use=function(...u){return _.use(...u),d.defaults=_.defaults,Z(d.defaults),d};d.walkTokens=function(u,e){return _.walkTokens(u,e)};d.parseInline=_.parseInline;d.Parser=b;d.parser=b.parse;d.Renderer=P;d.TextRenderer=$;d.Lexer=x;d.lexer=x.lex;d.Tokenizer=y;d.Hooks=S;d.parse=d;var Dt=d.options,Ht=d.setOptions,Zt=d.use,Gt=d.walkTokens,Nt=d.parseInline,Qt=d,Ft=b.parse,jt=x.lex;export{S as Hooks,x as Lexer,B as Marked,b as Parser,P as Renderer,$ as TextRenderer,y as Tokenizer,T as defaults,L as getDefaults,jt as lexer,d as marked,Dt as options,Qt as parse,Nt as parseInline,Ft as parser,Ht as setOptions,Zt as use,Gt as walkTokens};\n//# sourceMappingURL=marked.esm.js.map\n","import DOMPurify from \"dompurify\";\nimport { marked } from \"marked\";\nimport { truncateText } from \"./format\";\n\nmarked.setOptions({\n gfm: true,\n breaks: true,\n mangle: false,\n});\n\nconst allowedTags = [\n \"a\",\n \"b\",\n \"blockquote\",\n \"br\",\n \"code\",\n \"del\",\n \"em\",\n \"h1\",\n \"h2\",\n \"h3\",\n \"h4\",\n \"hr\",\n \"i\",\n \"li\",\n \"ol\",\n \"p\",\n \"pre\",\n \"strong\",\n \"table\",\n \"tbody\",\n \"td\",\n \"th\",\n \"thead\",\n \"tr\",\n \"ul\",\n];\n\nconst allowedAttrs = [\"class\", \"href\", \"rel\", \"target\", \"title\", \"start\"];\n\nlet hooksInstalled = false;\nconst MARKDOWN_CHAR_LIMIT = 140_000;\nconst MARKDOWN_PARSE_LIMIT = 40_000;\nconst MARKDOWN_CACHE_LIMIT = 200;\nconst MARKDOWN_CACHE_MAX_CHARS = 50_000;\nconst markdownCache = new Map();\n\nfunction getCachedMarkdown(key: string): string | null {\n const cached = markdownCache.get(key);\n if (cached === undefined) return null;\n markdownCache.delete(key);\n markdownCache.set(key, cached);\n return cached;\n}\n\nfunction setCachedMarkdown(key: string, value: string) {\n markdownCache.set(key, value);\n if (markdownCache.size <= MARKDOWN_CACHE_LIMIT) return;\n const oldest = markdownCache.keys().next().value;\n if (oldest) markdownCache.delete(oldest);\n}\n\nfunction installHooks() {\n if (hooksInstalled) return;\n hooksInstalled = true;\n\n DOMPurify.addHook(\"afterSanitizeAttributes\", (node) => {\n if (!(node instanceof HTMLAnchorElement)) return;\n const href = node.getAttribute(\"href\");\n if (!href) return;\n node.setAttribute(\"rel\", \"noreferrer noopener\");\n node.setAttribute(\"target\", \"_blank\");\n });\n}\n\nexport function toSanitizedMarkdownHtml(markdown: string): string {\n const input = markdown.trim();\n if (!input) return \"\";\n installHooks();\n if (input.length <= MARKDOWN_CACHE_MAX_CHARS) {\n const cached = getCachedMarkdown(input);\n if (cached !== null) return cached;\n }\n const truncated = truncateText(input, MARKDOWN_CHAR_LIMIT);\n const suffix = truncated.truncated\n ? `\\n\\n… truncated (${truncated.total} chars, showing first ${truncated.text.length}).`\n : \"\";\n if (truncated.text.length > MARKDOWN_PARSE_LIMIT) {\n const escaped = escapeHtml(`${truncated.text}${suffix}`);\n const html = `
    ${escaped}
    `;\n const sanitized = DOMPurify.sanitize(html, {\n ALLOWED_TAGS: allowedTags,\n ALLOWED_ATTR: allowedAttrs,\n });\n if (input.length <= MARKDOWN_CACHE_MAX_CHARS) {\n setCachedMarkdown(input, sanitized);\n }\n return sanitized;\n }\n const rendered = marked.parse(`${truncated.text}${suffix}`) as string;\n const sanitized = DOMPurify.sanitize(rendered, {\n ALLOWED_TAGS: allowedTags,\n ALLOWED_ATTR: allowedAttrs,\n });\n if (input.length <= MARKDOWN_CACHE_MAX_CHARS) {\n setCachedMarkdown(input, sanitized);\n }\n return sanitized;\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(//g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n","import { html, type TemplateResult } from \"lit\";\nimport { icons } from \"../icons\";\n\nconst COPIED_FOR_MS = 1500;\nconst ERROR_FOR_MS = 2000;\nconst COPY_LABEL = \"Copy as markdown\";\nconst COPIED_LABEL = \"Copied\";\nconst ERROR_LABEL = \"Copy failed\";\n\ntype CopyButtonOptions = {\n text: () => string;\n label?: string;\n};\n\nasync function copyTextToClipboard(text: string): Promise {\n if (!text) return false;\n\n try {\n await navigator.clipboard.writeText(text);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction setButtonLabel(button: HTMLButtonElement, label: string) {\n button.title = label;\n button.setAttribute(\"aria-label\", label);\n}\n\nfunction createCopyButton(options: CopyButtonOptions): TemplateResult {\n const idleLabel = options.label ?? COPY_LABEL;\n return html`\n {\n const btn = e.currentTarget as HTMLButtonElement | null;\n const iconContainer = btn?.querySelector(\n \".chat-copy-btn__icon\",\n ) as HTMLElement | null;\n\n if (!btn || btn.dataset.copying === \"1\") return;\n\n btn.dataset.copying = \"1\";\n btn.setAttribute(\"aria-busy\", \"true\");\n btn.disabled = true;\n\n const copied = await copyTextToClipboard(options.text());\n if (!btn.isConnected) return;\n\n delete btn.dataset.copying;\n btn.removeAttribute(\"aria-busy\");\n btn.disabled = false;\n\n if (!copied) {\n btn.dataset.error = \"1\";\n setButtonLabel(btn, ERROR_LABEL);\n\n window.setTimeout(() => {\n if (!btn.isConnected) return;\n delete btn.dataset.error;\n setButtonLabel(btn, idleLabel);\n }, ERROR_FOR_MS);\n return;\n }\n\n btn.dataset.copied = \"1\";\n setButtonLabel(btn, COPIED_LABEL);\n\n window.setTimeout(() => {\n if (!btn.isConnected) return;\n delete btn.dataset.copied;\n setButtonLabel(btn, idleLabel);\n }, COPIED_FOR_MS);\n }}\n >\n \n ${icons.copy}\n ${icons.check}\n \n \n `;\n}\n\nexport function renderCopyAsMarkdownButton(markdown: string): TemplateResult {\n return createCopyButton({ text: () => markdown, label: COPY_LABEL });\n}\n","import rawConfig from \"./tool-display.json\";\nimport type { IconName } from \"./icons\";\n\ntype ToolDisplayActionSpec = {\n label?: string;\n detailKeys?: string[];\n};\n\ntype ToolDisplaySpec = {\n icon?: string;\n title?: string;\n label?: string;\n detailKeys?: string[];\n actions?: Record;\n};\n\ntype ToolDisplayConfig = {\n version?: number;\n fallback?: ToolDisplaySpec;\n tools?: Record;\n};\n\nexport type ToolDisplay = {\n name: string;\n icon: IconName;\n title: string;\n label: string;\n verb?: string;\n detail?: string;\n};\n\nconst TOOL_DISPLAY_CONFIG = rawConfig as ToolDisplayConfig;\nconst FALLBACK = TOOL_DISPLAY_CONFIG.fallback ?? { icon: \"puzzle\" };\nconst TOOL_MAP = TOOL_DISPLAY_CONFIG.tools ?? {};\n\nfunction normalizeToolName(name?: string): string {\n return (name ?? \"tool\").trim();\n}\n\nfunction defaultTitle(name: string): string {\n const cleaned = name.replace(/_/g, \" \").trim();\n if (!cleaned) return \"Tool\";\n return cleaned\n .split(/\\s+/)\n .map((part) =>\n part.length <= 2 && part.toUpperCase() === part\n ? part\n : `${part.at(0)?.toUpperCase() ?? \"\"}${part.slice(1)}`,\n )\n .join(\" \");\n}\n\nfunction normalizeVerb(value?: string): string | undefined {\n const trimmed = value?.trim();\n if (!trimmed) return undefined;\n return trimmed.replace(/_/g, \" \");\n}\n\nfunction coerceDisplayValue(value: unknown): string | undefined {\n if (value === null || value === undefined) return undefined;\n if (typeof value === \"string\") {\n const trimmed = value.trim();\n if (!trimmed) return undefined;\n const firstLine = trimmed.split(/\\r?\\n/)[0]?.trim() ?? \"\";\n if (!firstLine) return undefined;\n return firstLine.length > 160 ? `${firstLine.slice(0, 157)}…` : firstLine;\n }\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n if (Array.isArray(value)) {\n const values = value\n .map((item) => coerceDisplayValue(item))\n .filter((item): item is string => Boolean(item));\n if (values.length === 0) return undefined;\n const preview = values.slice(0, 3).join(\", \");\n return values.length > 3 ? `${preview}…` : preview;\n }\n return undefined;\n}\n\nfunction lookupValueByPath(args: unknown, path: string): unknown {\n if (!args || typeof args !== \"object\") return undefined;\n let current: unknown = args;\n for (const segment of path.split(\".\")) {\n if (!segment) return undefined;\n if (!current || typeof current !== \"object\") return undefined;\n const record = current as Record;\n current = record[segment];\n }\n return current;\n}\n\nfunction resolveDetailFromKeys(args: unknown, keys: string[]): string | undefined {\n for (const key of keys) {\n const value = lookupValueByPath(args, key);\n const display = coerceDisplayValue(value);\n if (display) return display;\n }\n return undefined;\n}\n\nfunction resolveReadDetail(args: unknown): string | undefined {\n if (!args || typeof args !== \"object\") return undefined;\n const record = args as Record;\n const path = typeof record.path === \"string\" ? record.path : undefined;\n if (!path) return undefined;\n const offset = typeof record.offset === \"number\" ? record.offset : undefined;\n const limit = typeof record.limit === \"number\" ? record.limit : undefined;\n if (offset !== undefined && limit !== undefined) {\n return `${path}:${offset}-${offset + limit}`;\n }\n return path;\n}\n\nfunction resolveWriteDetail(args: unknown): string | undefined {\n if (!args || typeof args !== \"object\") return undefined;\n const record = args as Record;\n const path = typeof record.path === \"string\" ? record.path : undefined;\n return path;\n}\n\nfunction resolveActionSpec(\n spec: ToolDisplaySpec | undefined,\n action: string | undefined,\n): ToolDisplayActionSpec | undefined {\n if (!spec || !action) return undefined;\n return spec.actions?.[action] ?? undefined;\n}\n\nexport function resolveToolDisplay(params: {\n name?: string;\n args?: unknown;\n meta?: string;\n}): ToolDisplay {\n const name = normalizeToolName(params.name);\n const key = name.toLowerCase();\n const spec = TOOL_MAP[key];\n const icon = (spec?.icon ?? FALLBACK.icon ?? \"puzzle\") as IconName;\n const title = spec?.title ?? defaultTitle(name);\n const label = spec?.label ?? name;\n const actionRaw =\n params.args && typeof params.args === \"object\"\n ? ((params.args as Record).action as string | undefined)\n : undefined;\n const action = typeof actionRaw === \"string\" ? actionRaw.trim() : undefined;\n const actionSpec = resolveActionSpec(spec, action);\n const verb = normalizeVerb(actionSpec?.label ?? action);\n\n let detail: string | undefined;\n if (key === \"read\") detail = resolveReadDetail(params.args);\n if (!detail && (key === \"write\" || key === \"edit\" || key === \"attach\")) {\n detail = resolveWriteDetail(params.args);\n }\n\n const detailKeys =\n actionSpec?.detailKeys ?? spec?.detailKeys ?? FALLBACK.detailKeys ?? [];\n if (!detail && detailKeys.length > 0) {\n detail = resolveDetailFromKeys(params.args, detailKeys);\n }\n\n if (!detail && params.meta) {\n detail = params.meta;\n }\n\n if (detail) {\n detail = shortenHomeInString(detail);\n }\n\n return {\n name,\n icon,\n title,\n label,\n verb,\n detail,\n };\n}\n\nexport function formatToolDetail(display: ToolDisplay): string | undefined {\n const parts: string[] = [];\n if (display.verb) parts.push(display.verb);\n if (display.detail) parts.push(display.detail);\n if (parts.length === 0) return undefined;\n return parts.join(\" · \");\n}\n\nexport function formatToolSummary(display: ToolDisplay): string {\n const detail = formatToolDetail(display);\n return detail ? `${display.label}: ${detail}` : display.label;\n}\n\nfunction shortenHomeInString(input: string): string {\n if (!input) return input;\n return input\n .replace(/\\/Users\\/[^/]+/g, \"~\")\n .replace(/\\/home\\/[^/]+/g, \"~\");\n}\n","/**\n * Chat-related constants for the UI layer.\n */\n\n/** Character threshold for showing tool output inline vs collapsed */\nexport const TOOL_INLINE_THRESHOLD = 80;\n\n/** Maximum lines to show in collapsed preview */\nexport const PREVIEW_MAX_LINES = 2;\n\n/** Maximum characters to show in collapsed preview */\nexport const PREVIEW_MAX_CHARS = 100;\n","/**\n * Helper functions for tool card rendering.\n */\n\nimport { PREVIEW_MAX_CHARS, PREVIEW_MAX_LINES } from \"./constants\";\n\n/**\n * Format tool output content for display in the sidebar.\n * Detects JSON and wraps it in a code block with formatting.\n */\nexport function formatToolOutputForSidebar(text: string): string {\n const trimmed = text.trim();\n // Try to detect and format JSON\n if (trimmed.startsWith(\"{\") || trimmed.startsWith(\"[\")) {\n try {\n const parsed = JSON.parse(trimmed);\n return \"```json\\n\" + JSON.stringify(parsed, null, 2) + \"\\n```\";\n } catch {\n // Not valid JSON, return as-is\n }\n }\n return text;\n}\n\n/**\n * Get a truncated preview of tool output text.\n * Truncates to first N lines or first N characters, whichever is shorter.\n */\nexport function getTruncatedPreview(text: string): string {\n const allLines = text.split(\"\\n\");\n const lines = allLines.slice(0, PREVIEW_MAX_LINES);\n const preview = lines.join(\"\\n\");\n if (preview.length > PREVIEW_MAX_CHARS) {\n return preview.slice(0, PREVIEW_MAX_CHARS) + \"…\";\n }\n return lines.length < allLines.length ? preview + \"…\" : preview;\n}\n","import { html, nothing } from \"lit\";\n\nimport { formatToolDetail, resolveToolDisplay } from \"../tool-display\";\nimport { icons } from \"../icons\";\nimport type { ToolCard } from \"../types/chat-types\";\nimport { TOOL_INLINE_THRESHOLD } from \"./constants\";\nimport {\n formatToolOutputForSidebar,\n getTruncatedPreview,\n} from \"./tool-helpers\";\nimport { isToolResultMessage } from \"./message-normalizer\";\nimport { extractTextCached } from \"./message-extract\";\n\nexport function extractToolCards(message: unknown): ToolCard[] {\n const m = message as Record;\n const content = normalizeContent(m.content);\n const cards: ToolCard[] = [];\n\n for (const item of content) {\n const kind = String(item.type ?? \"\").toLowerCase();\n const isToolCall =\n [\"toolcall\", \"tool_call\", \"tooluse\", \"tool_use\"].includes(kind) ||\n (typeof item.name === \"string\" && item.arguments != null);\n if (isToolCall) {\n cards.push({\n kind: \"call\",\n name: (item.name as string) ?? \"tool\",\n args: coerceArgs(item.arguments ?? item.args),\n });\n }\n }\n\n for (const item of content) {\n const kind = String(item.type ?? \"\").toLowerCase();\n if (kind !== \"toolresult\" && kind !== \"tool_result\") continue;\n const text = extractToolText(item);\n const name = typeof item.name === \"string\" ? item.name : \"tool\";\n cards.push({ kind: \"result\", name, text });\n }\n\n if (\n isToolResultMessage(message) &&\n !cards.some((card) => card.kind === \"result\")\n ) {\n const name =\n (typeof m.toolName === \"string\" && m.toolName) ||\n (typeof m.tool_name === \"string\" && m.tool_name) ||\n \"tool\";\n const text = extractTextCached(message) ?? undefined;\n cards.push({ kind: \"result\", name, text });\n }\n\n return cards;\n}\n\nexport function renderToolCardSidebar(\n card: ToolCard,\n onOpenSidebar?: (content: string) => void,\n) {\n const display = resolveToolDisplay({ name: card.name, args: card.args });\n const detail = formatToolDetail(display);\n const hasText = Boolean(card.text?.trim());\n\n const canClick = Boolean(onOpenSidebar);\n const handleClick = canClick\n ? () => {\n if (hasText) {\n onOpenSidebar!(formatToolOutputForSidebar(card.text!));\n return;\n }\n const info = `## ${display.label}\\n\\n${\n detail ? `**Command:** \\`${detail}\\`\\n\\n` : \"\"\n }*No output — tool completed successfully.*`;\n onOpenSidebar!(info);\n }\n : undefined;\n\n const isShort = hasText && (card.text?.length ?? 0) <= TOOL_INLINE_THRESHOLD;\n const showCollapsed = hasText && !isShort;\n const showInline = hasText && isShort;\n const isEmpty = !hasText;\n\n return html`\n {\n if (e.key !== \"Enter\" && e.key !== \" \") return;\n e.preventDefault();\n handleClick?.();\n }\n : nothing}\n >\n
    \n
    \n ${icons[display.icon]}\n ${display.label}\n
    \n ${canClick\n ? html`${hasText ? \"View\" : \"\"} ${icons.check}`\n : nothing}\n ${isEmpty && !canClick ? html`${icons.check}` : nothing}\n
    \n ${detail\n ? html`
    ${detail}
    `\n : nothing}\n ${isEmpty\n ? html`
    Completed
    `\n : nothing}\n ${showCollapsed\n ? html`
    ${getTruncatedPreview(card.text!)}
    `\n : nothing}\n ${showInline\n ? html`
    ${card.text}
    `\n : nothing}\n \n `;\n}\n\nfunction normalizeContent(content: unknown): Array> {\n if (!Array.isArray(content)) return [];\n return content.filter(Boolean) as Array>;\n}\n\nfunction coerceArgs(value: unknown): unknown {\n if (typeof value !== \"string\") return value;\n const trimmed = value.trim();\n if (!trimmed) return value;\n if (!trimmed.startsWith(\"{\") && !trimmed.startsWith(\"[\")) return value;\n try {\n return JSON.parse(trimmed);\n } catch {\n return value;\n }\n}\n\nfunction extractToolText(item: Record): string | undefined {\n if (typeof item.text === \"string\") return item.text;\n if (typeof item.content === \"string\") return item.content;\n return undefined;\n}\n","import { html, nothing } from \"lit\";\nimport { unsafeHTML } from \"lit/directives/unsafe-html.js\";\n\nimport type { AssistantIdentity } from \"../assistant-identity\";\nimport { toSanitizedMarkdownHtml } from \"../markdown\";\nimport type { MessageGroup } from \"../types/chat-types\";\nimport { renderCopyAsMarkdownButton } from \"./copy-as-markdown\";\nimport { isToolResultMessage, normalizeRoleForGrouping } from \"./message-normalizer\";\nimport {\n extractTextCached,\n extractThinkingCached,\n formatReasoningMarkdown,\n} from \"./message-extract\";\nimport { extractToolCards, renderToolCardSidebar } from \"./tool-cards\";\n\nexport function renderReadingIndicatorGroup(assistant?: AssistantIdentity) {\n return html`\n
    \n ${renderAvatar(\"assistant\", assistant)}\n
    \n
    \n \n \n \n
    \n
    \n
    \n `;\n}\n\nexport function renderStreamingGroup(\n text: string,\n startedAt: number,\n onOpenSidebar?: (content: string) => void,\n assistant?: AssistantIdentity,\n) {\n const timestamp = new Date(startedAt).toLocaleTimeString([], {\n hour: \"numeric\",\n minute: \"2-digit\",\n });\n const name = assistant?.name ?? \"Assistant\";\n\n return html`\n
    \n ${renderAvatar(\"assistant\", assistant)}\n
    \n ${renderGroupedMessage(\n {\n role: \"assistant\",\n content: [{ type: \"text\", text }],\n timestamp: startedAt,\n },\n { isStreaming: true, showReasoning: false },\n onOpenSidebar,\n )}\n
    \n ${name}\n ${timestamp}\n
    \n
    \n
    \n `;\n}\n\nexport function renderMessageGroup(\n group: MessageGroup,\n opts: {\n onOpenSidebar?: (content: string) => void;\n showReasoning: boolean;\n assistantName?: string;\n assistantAvatar?: string | null;\n },\n) {\n const normalizedRole = normalizeRoleForGrouping(group.role);\n const assistantName = opts.assistantName ?? \"Assistant\";\n const who =\n normalizedRole === \"user\"\n ? \"You\"\n : normalizedRole === \"assistant\"\n ? assistantName\n : normalizedRole;\n const roleClass =\n normalizedRole === \"user\"\n ? \"user\"\n : normalizedRole === \"assistant\"\n ? \"assistant\"\n : \"other\";\n const timestamp = new Date(group.timestamp).toLocaleTimeString([], {\n hour: \"numeric\",\n minute: \"2-digit\",\n });\n\n return html`\n
    \n ${renderAvatar(group.role, {\n name: assistantName,\n avatar: opts.assistantAvatar ?? null,\n })}\n
    \n ${group.messages.map((item, index) =>\n renderGroupedMessage(\n item.message,\n {\n isStreaming:\n group.isStreaming && index === group.messages.length - 1,\n showReasoning: opts.showReasoning,\n },\n opts.onOpenSidebar,\n ),\n )}\n
    \n ${who}\n ${timestamp}\n
    \n
    \n
    \n `;\n}\n\nfunction renderAvatar(\n role: string,\n assistant?: Pick,\n) {\n const normalized = normalizeRoleForGrouping(role);\n const assistantName = assistant?.name?.trim() || \"Assistant\";\n const assistantAvatar = assistant?.avatar?.trim() || \"\";\n const initial =\n normalized === \"user\"\n ? \"U\"\n : normalized === \"assistant\"\n ? assistantName.charAt(0).toUpperCase() || \"A\"\n : normalized === \"tool\"\n ? \"⚙\"\n : \"?\";\n const className =\n normalized === \"user\"\n ? \"user\"\n : normalized === \"assistant\"\n ? \"assistant\"\n : normalized === \"tool\"\n ? \"tool\"\n : \"other\";\n\n if (assistantAvatar && normalized === \"assistant\") {\n if (isAvatarUrl(assistantAvatar)) {\n return html``;\n }\n return html`
    ${assistantAvatar}
    `;\n }\n\n return html`
    ${initial}
    `;\n}\n\nfunction isAvatarUrl(value: string): boolean {\n return (\n /^https?:\\/\\//i.test(value) ||\n /^data:image\\//i.test(value) ||\n /^\\//.test(value) // Relative paths from avatar endpoint\n );\n}\n\nfunction renderGroupedMessage(\n message: unknown,\n opts: { isStreaming: boolean; showReasoning: boolean },\n onOpenSidebar?: (content: string) => void,\n) {\n const m = message as Record;\n const role = typeof m.role === \"string\" ? m.role : \"unknown\";\n const isToolResult =\n isToolResultMessage(message) ||\n role.toLowerCase() === \"toolresult\" ||\n role.toLowerCase() === \"tool_result\" ||\n typeof m.toolCallId === \"string\" ||\n typeof m.tool_call_id === \"string\";\n\n const toolCards = extractToolCards(message);\n const hasToolCards = toolCards.length > 0;\n\n const extractedText = extractTextCached(message);\n const extractedThinking =\n opts.showReasoning && role === \"assistant\"\n ? extractThinkingCached(message)\n : null;\n const markdownBase = extractedText?.trim() ? extractedText : null;\n const reasoningMarkdown = extractedThinking\n ? formatReasoningMarkdown(extractedThinking)\n : null;\n const markdown = markdownBase;\n const canCopyMarkdown = role === \"assistant\" && Boolean(markdown?.trim());\n\n const bubbleClasses = [\n \"chat-bubble\",\n canCopyMarkdown ? \"has-copy\" : \"\",\n opts.isStreaming ? \"streaming\" : \"\",\n \"fade-in\",\n ]\n .filter(Boolean)\n .join(\" \");\n\n if (!markdown && hasToolCards && isToolResult) {\n return html`${toolCards.map((card) =>\n renderToolCardSidebar(card, onOpenSidebar),\n )}`;\n }\n\n if (!markdown && !hasToolCards) return nothing;\n\n return html`\n
    \n ${canCopyMarkdown ? renderCopyAsMarkdownButton(markdown!) : nothing}\n ${reasoningMarkdown\n ? html`
    ${unsafeHTML(\n toSanitizedMarkdownHtml(reasoningMarkdown),\n )}
    `\n : nothing}\n ${markdown\n ? html`
    ${unsafeHTML(toSanitizedMarkdownHtml(markdown))}
    `\n : nothing}\n ${toolCards.map((card) => renderToolCardSidebar(card, onOpenSidebar))}\n
    \n `;\n}\n","import { html, nothing } from \"lit\";\nimport { unsafeHTML } from \"lit/directives/unsafe-html.js\";\n\nimport { icons } from \"../icons\";\nimport { toSanitizedMarkdownHtml } from \"../markdown\";\n\nexport type MarkdownSidebarProps = {\n content: string | null;\n error: string | null;\n onClose: () => void;\n onViewRawText: () => void;\n};\n\nexport function renderMarkdownSidebar(props: MarkdownSidebarProps) {\n return html`\n
    \n
    \n
    Tool Output
    \n \n
    \n
    \n ${props.error\n ? html`\n
    ${props.error}
    \n \n `\n : props.content\n ? html`
    ${unsafeHTML(toSanitizedMarkdownHtml(props.content))}
    `\n : html`
    No content available
    `}\n
    \n
    \n `;\n}\n","import { LitElement, html, css } from \"lit\";\nimport { customElement, property } from \"lit/decorators.js\";\n\n/**\n * A draggable divider for resizable split views.\n * Dispatches 'resize' events with { splitRatio: number } detail.\n */\n@customElement(\"resizable-divider\")\nexport class ResizableDivider extends LitElement {\n @property({ type: Number }) splitRatio = 0.6;\n @property({ type: Number }) minRatio = 0.4;\n @property({ type: Number }) maxRatio = 0.7;\n\n private isDragging = false;\n private startX = 0;\n private startRatio = 0;\n\n static styles = css`\n :host {\n width: 4px;\n cursor: col-resize;\n background: var(--border, #333);\n transition: background 150ms ease-out;\n flex-shrink: 0;\n position: relative;\n }\n\n :host::before {\n content: \"\";\n position: absolute;\n top: 0;\n left: -4px;\n right: -4px;\n bottom: 0;\n }\n\n :host(:hover) {\n background: var(--accent, #007bff);\n }\n\n :host(.dragging) {\n background: var(--accent, #007bff);\n }\n `;\n\n render() {\n return html``;\n }\n\n connectedCallback() {\n super.connectedCallback();\n this.addEventListener(\"mousedown\", this.handleMouseDown);\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.removeEventListener(\"mousedown\", this.handleMouseDown);\n document.removeEventListener(\"mousemove\", this.handleMouseMove);\n document.removeEventListener(\"mouseup\", this.handleMouseUp);\n }\n\n private handleMouseDown = (e: MouseEvent) => {\n this.isDragging = true;\n this.startX = e.clientX;\n this.startRatio = this.splitRatio;\n this.classList.add(\"dragging\");\n\n document.addEventListener(\"mousemove\", this.handleMouseMove);\n document.addEventListener(\"mouseup\", this.handleMouseUp);\n\n e.preventDefault();\n };\n\n private handleMouseMove = (e: MouseEvent) => {\n if (!this.isDragging) return;\n\n const container = this.parentElement;\n if (!container) return;\n\n const containerWidth = container.getBoundingClientRect().width;\n const deltaX = e.clientX - this.startX;\n const deltaRatio = deltaX / containerWidth;\n\n let newRatio = this.startRatio + deltaRatio;\n newRatio = Math.max(this.minRatio, Math.min(this.maxRatio, newRatio));\n\n this.dispatchEvent(\n new CustomEvent(\"resize\", {\n detail: { splitRatio: newRatio },\n bubbles: true,\n composed: true,\n })\n );\n };\n\n private handleMouseUp = () => {\n this.isDragging = false;\n this.classList.remove(\"dragging\");\n\n document.removeEventListener(\"mousemove\", this.handleMouseMove);\n document.removeEventListener(\"mouseup\", this.handleMouseUp);\n };\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"resizable-divider\": ResizableDivider;\n }\n}\n","import { html, nothing } from \"lit\";\nimport { repeat } from \"lit/directives/repeat.js\";\nimport type { SessionsListResult } from \"../types\";\nimport type { ChatQueueItem } from \"../ui-types\";\nimport type { ChatItem, MessageGroup } from \"../types/chat-types\";\nimport { icons } from \"../icons\";\nimport {\n normalizeMessage,\n normalizeRoleForGrouping,\n} from \"../chat/message-normalizer\";\nimport {\n renderMessageGroup,\n renderReadingIndicatorGroup,\n renderStreamingGroup,\n} from \"../chat/grouped-render\";\nimport { renderMarkdownSidebar } from \"./markdown-sidebar\";\nimport \"../components/resizable-divider\";\n\nexport type CompactionIndicatorStatus = {\n active: boolean;\n startedAt: number | null;\n completedAt: number | null;\n};\n\nexport type ChatProps = {\n sessionKey: string;\n onSessionKeyChange: (next: string) => void;\n thinkingLevel: string | null;\n showThinking: boolean;\n loading: boolean;\n sending: boolean;\n canAbort?: boolean;\n compactionStatus?: CompactionIndicatorStatus | null;\n messages: unknown[];\n toolMessages: unknown[];\n stream: string | null;\n streamStartedAt: number | null;\n assistantAvatarUrl?: string | null;\n draft: string;\n queue: ChatQueueItem[];\n connected: boolean;\n canSend: boolean;\n disabledReason: string | null;\n error: string | null;\n sessions: SessionsListResult | null;\n // Focus mode\n focusMode: boolean;\n // Sidebar state\n sidebarOpen?: boolean;\n sidebarContent?: string | null;\n sidebarError?: string | null;\n splitRatio?: number;\n assistantName: string;\n assistantAvatar: string | null;\n // Event handlers\n onRefresh: () => void;\n onToggleFocusMode: () => void;\n onDraftChange: (next: string) => void;\n onSend: () => void;\n onAbort?: () => void;\n onQueueRemove: (id: string) => void;\n onNewSession: () => void;\n onOpenSidebar?: (content: string) => void;\n onCloseSidebar?: () => void;\n onSplitRatioChange?: (ratio: number) => void;\n onChatScroll?: (event: Event) => void;\n};\n\nconst COMPACTION_TOAST_DURATION_MS = 5000;\n\nfunction renderCompactionIndicator(status: CompactionIndicatorStatus | null | undefined) {\n if (!status) return nothing;\n \n // Show \"compacting...\" while active\n if (status.active) {\n return html`\n
    \n ${icons.loader} Compacting context...\n
    \n `;\n }\n\n // Show \"compaction complete\" briefly after completion\n if (status.completedAt) {\n const elapsed = Date.now() - status.completedAt;\n if (elapsed < COMPACTION_TOAST_DURATION_MS) {\n return html`\n
    \n ${icons.check} Context compacted\n
    \n `;\n }\n }\n \n return nothing;\n}\n\nexport function renderChat(props: ChatProps) {\n const canCompose = props.connected;\n const isBusy = props.sending || props.stream !== null;\n const canAbort = Boolean(props.canAbort && props.onAbort);\n const activeSession = props.sessions?.sessions?.find(\n (row) => row.key === props.sessionKey,\n );\n const reasoningLevel = activeSession?.reasoningLevel ?? \"off\";\n const showReasoning = props.showThinking && reasoningLevel !== \"off\";\n const assistantIdentity = {\n name: props.assistantName,\n avatar: props.assistantAvatar ?? props.assistantAvatarUrl ?? null,\n };\n\n const composePlaceholder = props.connected\n ? \"Message (↩ to send, Shift+↩ for line breaks)\"\n : \"Connect to the gateway to start chatting…\";\n\n const splitRatio = props.splitRatio ?? 0.6;\n const sidebarOpen = Boolean(props.sidebarOpen && props.onCloseSidebar);\n const thread = html`\n \n ${props.loading ? html`
    Loading chat…
    ` : nothing}\n ${repeat(buildChatItems(props), (item) => item.key, (item) => {\n if (item.kind === \"reading-indicator\") {\n return renderReadingIndicatorGroup(assistantIdentity);\n }\n\n if (item.kind === \"stream\") {\n return renderStreamingGroup(\n item.text,\n item.startedAt,\n props.onOpenSidebar,\n assistantIdentity,\n );\n }\n\n if (item.kind === \"group\") {\n return renderMessageGroup(item, {\n onOpenSidebar: props.onOpenSidebar,\n showReasoning,\n assistantName: props.assistantName,\n assistantAvatar: assistantIdentity.avatar,\n });\n }\n\n return nothing;\n })}\n \n `;\n\n return html`\n
    \n ${props.disabledReason\n ? html`
    ${props.disabledReason}
    `\n : nothing}\n\n ${props.error\n ? html`
    ${props.error}
    `\n : nothing}\n\n ${renderCompactionIndicator(props.compactionStatus)}\n\n ${props.focusMode\n ? html`\n \n ${icons.x}\n \n `\n : nothing}\n\n \n \n ${thread}\n \n\n ${sidebarOpen\n ? html`\n \n props.onSplitRatioChange?.(e.detail.splitRatio)}\n >\n
    \n ${renderMarkdownSidebar({\n content: props.sidebarContent ?? null,\n error: props.sidebarError ?? null,\n onClose: props.onCloseSidebar!,\n onViewRawText: () => {\n if (!props.sidebarContent || !props.onOpenSidebar) return;\n props.onOpenSidebar(`\\`\\`\\`\\n${props.sidebarContent}\\n\\`\\`\\``);\n },\n })}\n
    \n `\n : nothing}\n \n\n ${props.queue.length\n ? html`\n
    \n
    Queued (${props.queue.length})
    \n
    \n ${props.queue.map(\n (item) => html`\n
    \n
    ${item.text}
    \n props.onQueueRemove(item.id)}\n >\n ${icons.x}\n \n
    \n `,\n )}\n
    \n
    \n `\n : nothing}\n\n
    \n \n
    \n \n ${canAbort ? \"Stop\" : \"New session\"}\n \n \n ${isBusy ? \"Queue\" : \"Send\"}\n \n
    \n
    \n
    \n `;\n}\n\nconst CHAT_HISTORY_RENDER_LIMIT = 200;\n\nfunction groupMessages(items: ChatItem[]): Array {\n const result: Array = [];\n let currentGroup: MessageGroup | null = null;\n\n for (const item of items) {\n if (item.kind !== \"message\") {\n if (currentGroup) {\n result.push(currentGroup);\n currentGroup = null;\n }\n result.push(item);\n continue;\n }\n\n const normalized = normalizeMessage(item.message);\n const role = normalizeRoleForGrouping(normalized.role);\n const timestamp = normalized.timestamp || Date.now();\n\n if (!currentGroup || currentGroup.role !== role) {\n if (currentGroup) result.push(currentGroup);\n currentGroup = {\n kind: \"group\",\n key: `group:${role}:${item.key}`,\n role,\n messages: [{ message: item.message, key: item.key }],\n timestamp,\n isStreaming: false,\n };\n } else {\n currentGroup.messages.push({ message: item.message, key: item.key });\n }\n }\n\n if (currentGroup) result.push(currentGroup);\n return result;\n}\n\nfunction buildChatItems(props: ChatProps): Array {\n const items: ChatItem[] = [];\n const history = Array.isArray(props.messages) ? props.messages : [];\n const tools = Array.isArray(props.toolMessages) ? props.toolMessages : [];\n const historyStart = Math.max(0, history.length - CHAT_HISTORY_RENDER_LIMIT);\n if (historyStart > 0) {\n items.push({\n kind: \"message\",\n key: \"chat:history:notice\",\n message: {\n role: \"system\",\n content: `Showing last ${CHAT_HISTORY_RENDER_LIMIT} messages (${historyStart} hidden).`,\n timestamp: Date.now(),\n },\n });\n }\n for (let i = historyStart; i < history.length; i++) {\n const msg = history[i];\n const normalized = normalizeMessage(msg);\n\n if (!props.showThinking && normalized.role.toLowerCase() === \"toolresult\") {\n continue;\n }\n\n items.push({\n kind: \"message\",\n key: messageKey(msg, i),\n message: msg,\n });\n }\n if (props.showThinking) {\n for (let i = 0; i < tools.length; i++) {\n items.push({\n kind: \"message\",\n key: messageKey(tools[i], i + history.length),\n message: tools[i],\n });\n }\n }\n\n if (props.stream !== null) {\n const key = `stream:${props.sessionKey}:${props.streamStartedAt ?? \"live\"}`;\n if (props.stream.trim().length > 0) {\n items.push({\n kind: \"stream\",\n key,\n text: props.stream,\n startedAt: props.streamStartedAt ?? Date.now(),\n });\n } else {\n items.push({ kind: \"reading-indicator\", key });\n }\n }\n\n return groupMessages(items);\n}\n\nfunction messageKey(message: unknown, index: number): string {\n const m = message as Record;\n const toolCallId = typeof m.toolCallId === \"string\" ? m.toolCallId : \"\";\n if (toolCallId) return `tool:${toolCallId}`;\n const id = typeof m.id === \"string\" ? m.id : \"\";\n if (id) return `msg:${id}`;\n const messageId = typeof m.messageId === \"string\" ? m.messageId : \"\";\n if (messageId) return `msg:${messageId}`;\n const timestamp = typeof m.timestamp === \"number\" ? m.timestamp : null;\n const role = typeof m.role === \"string\" ? m.role : \"unknown\";\n if (timestamp != null) return `msg:${role}:${timestamp}:${index}`;\n return `msg:${role}:${index}`;\n}\n","import type { ConfigUiHints } from \"../types\";\n\nexport type JsonSchema = {\n type?: string | string[];\n title?: string;\n description?: string;\n properties?: Record;\n items?: JsonSchema | JsonSchema[];\n additionalProperties?: JsonSchema | boolean;\n enum?: unknown[];\n const?: unknown;\n default?: unknown;\n anyOf?: JsonSchema[];\n oneOf?: JsonSchema[];\n allOf?: JsonSchema[];\n nullable?: boolean;\n};\n\nexport function schemaType(schema: JsonSchema): string | undefined {\n if (!schema) return undefined;\n if (Array.isArray(schema.type)) {\n const filtered = schema.type.filter((t) => t !== \"null\");\n return filtered[0] ?? schema.type[0];\n }\n return schema.type;\n}\n\nexport function defaultValue(schema?: JsonSchema): unknown {\n if (!schema) return \"\";\n if (schema.default !== undefined) return schema.default;\n const type = schemaType(schema);\n switch (type) {\n case \"object\":\n return {};\n case \"array\":\n return [];\n case \"boolean\":\n return false;\n case \"number\":\n case \"integer\":\n return 0;\n case \"string\":\n return \"\";\n default:\n return \"\";\n }\n}\n\nexport function pathKey(path: Array): string {\n return path.filter((segment) => typeof segment === \"string\").join(\".\");\n}\n\nexport function hintForPath(path: Array, hints: ConfigUiHints) {\n const key = pathKey(path);\n const direct = hints[key];\n if (direct) return direct;\n const segments = key.split(\".\");\n for (const [hintKey, hint] of Object.entries(hints)) {\n if (!hintKey.includes(\"*\")) continue;\n const hintSegments = hintKey.split(\".\");\n if (hintSegments.length !== segments.length) continue;\n let match = true;\n for (let i = 0; i < segments.length; i += 1) {\n if (hintSegments[i] !== \"*\" && hintSegments[i] !== segments[i]) {\n match = false;\n break;\n }\n }\n if (match) return hint;\n }\n return undefined;\n}\n\nexport function humanize(raw: string) {\n return raw\n .replace(/_/g, \" \")\n .replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n .replace(/\\s+/g, \" \")\n .replace(/^./, (m) => m.toUpperCase());\n}\n\nexport function isSensitivePath(path: Array): boolean {\n const key = pathKey(path).toLowerCase();\n return (\n key.includes(\"token\") ||\n key.includes(\"password\") ||\n key.includes(\"secret\") ||\n key.includes(\"apikey\") ||\n key.endsWith(\"key\")\n );\n}\n\n","import { html, nothing, type TemplateResult } from \"lit\";\nimport type { ConfigUiHints } from \"../types\";\nimport {\n defaultValue,\n hintForPath,\n humanize,\n isSensitivePath,\n pathKey,\n schemaType,\n type JsonSchema,\n} from \"./config-form.shared\";\n\nconst META_KEYS = new Set([\"title\", \"description\", \"default\", \"nullable\"]);\n\nfunction isAnySchema(schema: JsonSchema): boolean {\n const keys = Object.keys(schema ?? {}).filter((key) => !META_KEYS.has(key));\n return keys.length === 0;\n}\n\nfunction jsonValue(value: unknown): string {\n if (value === undefined) return \"\";\n try {\n return JSON.stringify(value, null, 2) ?? \"\";\n } catch {\n return \"\";\n }\n}\n\n// SVG Icons as template literals\nconst icons = {\n chevronDown: html``,\n plus: html``,\n minus: html``,\n trash: html``,\n edit: html``,\n};\n\nexport function renderNode(params: {\n schema: JsonSchema;\n value: unknown;\n path: Array;\n hints: ConfigUiHints;\n unsupported: Set;\n disabled: boolean;\n showLabel?: boolean;\n onPatch: (path: Array, value: unknown) => void;\n}): TemplateResult | typeof nothing {\n const { schema, value, path, hints, unsupported, disabled, onPatch } = params;\n const showLabel = params.showLabel ?? true;\n const type = schemaType(schema);\n const hint = hintForPath(path, hints);\n const label = hint?.label ?? schema.title ?? humanize(String(path.at(-1)));\n const help = hint?.help ?? schema.description;\n const key = pathKey(path);\n\n if (unsupported.has(key)) {\n return html`
    \n
    ${label}
    \n
    Unsupported schema node. Use Raw mode.
    \n
    `;\n }\n\n // Handle anyOf/oneOf unions\n if (schema.anyOf || schema.oneOf) {\n const variants = schema.anyOf ?? schema.oneOf ?? [];\n const nonNull = variants.filter(\n (v) => !(v.type === \"null\" || (Array.isArray(v.type) && v.type.includes(\"null\")))\n );\n\n if (nonNull.length === 1) {\n return renderNode({ ...params, schema: nonNull[0] });\n }\n\n // Check if it's a set of literal values (enum-like)\n const extractLiteral = (v: JsonSchema): unknown | undefined => {\n if (v.const !== undefined) return v.const;\n if (v.enum && v.enum.length === 1) return v.enum[0];\n return undefined;\n };\n const literals = nonNull.map(extractLiteral);\n const allLiterals = literals.every((v) => v !== undefined);\n\n if (allLiterals && literals.length > 0 && literals.length <= 5) {\n // Use segmented control for small sets\n const resolvedValue = value ?? schema.default;\n return html`\n
    \n ${showLabel ? html`` : nothing}\n ${help ? html`
    ${help}
    ` : nothing}\n
    \n ${literals.map((lit, idx) => html`\n onPatch(path, lit)}\n >\n ${String(lit)}\n \n `)}\n
    \n
    \n `;\n }\n\n if (allLiterals && literals.length > 5) {\n // Use dropdown for larger sets\n return renderSelect({ ...params, options: literals, value: value ?? schema.default });\n }\n\n // Handle mixed primitive types\n const primitiveTypes = new Set(\n nonNull.map((variant) => schemaType(variant)).filter(Boolean)\n );\n const normalizedTypes = new Set(\n [...primitiveTypes].map((v) => (v === \"integer\" ? \"number\" : v))\n );\n\n if ([...normalizedTypes].every((v) => [\"string\", \"number\", \"boolean\"].includes(v as string))) {\n const hasString = normalizedTypes.has(\"string\");\n const hasNumber = normalizedTypes.has(\"number\");\n const hasBoolean = normalizedTypes.has(\"boolean\");\n \n if (hasBoolean && normalizedTypes.size === 1) {\n return renderNode({\n ...params,\n schema: { ...schema, type: \"boolean\", anyOf: undefined, oneOf: undefined },\n });\n }\n\n if (hasString || hasNumber) {\n return renderTextInput({\n ...params,\n inputType: hasNumber && !hasString ? \"number\" : \"text\",\n });\n }\n }\n }\n\n // Enum - use segmented for small, dropdown for large\n if (schema.enum) {\n const options = schema.enum;\n if (options.length <= 5) {\n const resolvedValue = value ?? schema.default;\n return html`\n
    \n ${showLabel ? html`` : nothing}\n ${help ? html`
    ${help}
    ` : nothing}\n
    \n ${options.map((opt) => html`\n onPatch(path, opt)}\n >\n ${String(opt)}\n \n `)}\n
    \n
    \n `;\n }\n return renderSelect({ ...params, options, value: value ?? schema.default });\n }\n\n // Object type - collapsible section\n if (type === \"object\") {\n return renderObject(params);\n }\n\n // Array type\n if (type === \"array\") {\n return renderArray(params);\n }\n\n // Boolean - toggle row\n if (type === \"boolean\") {\n const displayValue = typeof value === \"boolean\" ? value : typeof schema.default === \"boolean\" ? schema.default : false;\n return html`\n \n `;\n }\n\n // Number/Integer\n if (type === \"number\" || type === \"integer\") {\n return renderNumberInput(params);\n }\n\n // String\n if (type === \"string\") {\n return renderTextInput({ ...params, inputType: \"text\" });\n }\n\n // Fallback\n return html`\n
    \n
    ${label}
    \n
    Unsupported type: ${type}. Use Raw mode.
    \n
    \n `;\n}\n\nfunction renderTextInput(params: {\n schema: JsonSchema;\n value: unknown;\n path: Array;\n hints: ConfigUiHints;\n disabled: boolean;\n showLabel?: boolean;\n inputType: \"text\" | \"number\";\n onPatch: (path: Array, value: unknown) => void;\n}): TemplateResult {\n const { schema, value, path, hints, disabled, onPatch, inputType } = params;\n const showLabel = params.showLabel ?? true;\n const hint = hintForPath(path, hints);\n const label = hint?.label ?? schema.title ?? humanize(String(path.at(-1)));\n const help = hint?.help ?? schema.description;\n const isSensitive = hint?.sensitive ?? isSensitivePath(path);\n const placeholder =\n hint?.placeholder ??\n (isSensitive ? \"••••\" : schema.default !== undefined ? `Default: ${schema.default}` : \"\");\n const displayValue = value ?? \"\";\n\n return html`\n
    \n ${showLabel ? html`` : nothing}\n ${help ? html`
    ${help}
    ` : nothing}\n
    \n {\n const raw = (e.target as HTMLInputElement).value;\n if (inputType === \"number\") {\n if (raw.trim() === \"\") {\n onPatch(path, undefined);\n return;\n }\n const parsed = Number(raw);\n onPatch(path, Number.isNaN(parsed) ? raw : parsed);\n return;\n }\n onPatch(path, raw);\n }}\n />\n ${schema.default !== undefined ? html`\n onPatch(path, schema.default)}\n >↺\n ` : nothing}\n
    \n
    \n `;\n}\n\nfunction renderNumberInput(params: {\n schema: JsonSchema;\n value: unknown;\n path: Array;\n hints: ConfigUiHints;\n disabled: boolean;\n showLabel?: boolean;\n onPatch: (path: Array, value: unknown) => void;\n}): TemplateResult {\n const { schema, value, path, hints, disabled, onPatch } = params;\n const showLabel = params.showLabel ?? true;\n const hint = hintForPath(path, hints);\n const label = hint?.label ?? schema.title ?? humanize(String(path.at(-1)));\n const help = hint?.help ?? schema.description;\n const displayValue = value ?? schema.default ?? \"\";\n const numValue = typeof displayValue === \"number\" ? displayValue : 0;\n\n return html`\n
    \n ${showLabel ? html`` : nothing}\n ${help ? html`
    ${help}
    ` : nothing}\n
    \n onPatch(path, numValue - 1)}\n >−\n {\n const raw = (e.target as HTMLInputElement).value;\n const parsed = raw === \"\" ? undefined : Number(raw);\n onPatch(path, parsed);\n }}\n />\n onPatch(path, numValue + 1)}\n >+\n
    \n
    \n `;\n}\n\nfunction renderSelect(params: {\n schema: JsonSchema;\n value: unknown;\n path: Array;\n hints: ConfigUiHints;\n disabled: boolean;\n showLabel?: boolean;\n options: unknown[];\n onPatch: (path: Array, value: unknown) => void;\n}): TemplateResult {\n const { schema, value, path, hints, disabled, options, onPatch } = params;\n const showLabel = params.showLabel ?? true;\n const hint = hintForPath(path, hints);\n const label = hint?.label ?? schema.title ?? humanize(String(path.at(-1)));\n const help = hint?.help ?? schema.description;\n const resolvedValue = value ?? schema.default;\n const currentIndex = options.findIndex(\n (opt) => opt === resolvedValue || String(opt) === String(resolvedValue),\n );\n const unset = \"__unset__\";\n\n return html`\n
    \n ${showLabel ? html`` : nothing}\n ${help ? html`
    ${help}
    ` : nothing}\n = 0 ? String(currentIndex) : unset}\n @change=${(e: Event) => {\n const val = (e.target as HTMLSelectElement).value;\n onPatch(path, val === unset ? undefined : options[Number(val)]);\n }}\n >\n \n ${options.map((opt, idx) => html`\n \n `)}\n \n
    \n `;\n}\n\nfunction renderObject(params: {\n schema: JsonSchema;\n value: unknown;\n path: Array;\n hints: ConfigUiHints;\n unsupported: Set;\n disabled: boolean;\n showLabel?: boolean;\n onPatch: (path: Array, value: unknown) => void;\n}): TemplateResult {\n const { schema, value, path, hints, unsupported, disabled, onPatch } = params;\n const showLabel = params.showLabel ?? true;\n const hint = hintForPath(path, hints);\n const label = hint?.label ?? schema.title ?? humanize(String(path.at(-1)));\n const help = hint?.help ?? schema.description;\n \n const fallback = value ?? schema.default;\n const obj = fallback && typeof fallback === \"object\" && !Array.isArray(fallback)\n ? (fallback as Record)\n : {};\n const props = schema.properties ?? {};\n const entries = Object.entries(props);\n \n // Sort by hint order\n const sorted = entries.sort((a, b) => {\n const orderA = hintForPath([...path, a[0]], hints)?.order ?? 0;\n const orderB = hintForPath([...path, b[0]], hints)?.order ?? 0;\n if (orderA !== orderB) return orderA - orderB;\n return a[0].localeCompare(b[0]);\n });\n\n const reserved = new Set(Object.keys(props));\n const additional = schema.additionalProperties;\n const allowExtra = Boolean(additional) && typeof additional === \"object\";\n\n // For top-level, don't wrap in collapsible\n if (path.length === 1) {\n return html`\n
    \n ${sorted.map(([propKey, node]) =>\n renderNode({\n schema: node,\n value: obj[propKey],\n path: [...path, propKey],\n hints,\n unsupported,\n disabled,\n onPatch,\n })\n )}\n ${allowExtra ? renderMapField({\n schema: additional as JsonSchema,\n value: obj,\n path,\n hints,\n unsupported,\n disabled,\n reservedKeys: reserved,\n onPatch,\n }) : nothing}\n
    \n `;\n }\n\n // Nested objects get collapsible treatment\n return html`\n
    \n \n ${label}\n ${icons.chevronDown}\n \n ${help ? html`
    ${help}
    ` : nothing}\n
    \n ${sorted.map(([propKey, node]) =>\n renderNode({\n schema: node,\n value: obj[propKey],\n path: [...path, propKey],\n hints,\n unsupported,\n disabled,\n onPatch,\n })\n )}\n ${allowExtra ? renderMapField({\n schema: additional as JsonSchema,\n value: obj,\n path,\n hints,\n unsupported,\n disabled,\n reservedKeys: reserved,\n onPatch,\n }) : nothing}\n
    \n
    \n `;\n}\n\nfunction renderArray(params: {\n schema: JsonSchema;\n value: unknown;\n path: Array;\n hints: ConfigUiHints;\n unsupported: Set;\n disabled: boolean;\n showLabel?: boolean;\n onPatch: (path: Array, value: unknown) => void;\n}): TemplateResult {\n const { schema, value, path, hints, unsupported, disabled, onPatch } = params;\n const showLabel = params.showLabel ?? true;\n const hint = hintForPath(path, hints);\n const label = hint?.label ?? schema.title ?? humanize(String(path.at(-1)));\n const help = hint?.help ?? schema.description;\n\n const itemsSchema = Array.isArray(schema.items) ? schema.items[0] : schema.items;\n if (!itemsSchema) {\n return html`\n
    \n
    ${label}
    \n
    Unsupported array schema. Use Raw mode.
    \n
    \n `;\n }\n\n const arr = Array.isArray(value) ? value : Array.isArray(schema.default) ? schema.default : [];\n\n return html`\n
    \n
    \n ${showLabel ? html`${label}` : nothing}\n ${arr.length} item${arr.length !== 1 ? 's' : ''}\n {\n const next = [...arr, defaultValue(itemsSchema)];\n onPatch(path, next);\n }}\n >\n ${icons.plus}\n Add\n \n
    \n ${help ? html`
    ${help}
    ` : nothing}\n \n ${arr.length === 0 ? html`\n
    \n No items yet. Click \"Add\" to create one.\n
    \n ` : html`\n
    \n ${arr.map((item, idx) => html`\n
    \n
    \n #${idx + 1}\n {\n const next = [...arr];\n next.splice(idx, 1);\n onPatch(path, next);\n }}\n >\n ${icons.trash}\n \n
    \n
    \n ${renderNode({\n schema: itemsSchema,\n value: item,\n path: [...path, idx],\n hints,\n unsupported,\n disabled,\n showLabel: false,\n onPatch,\n })}\n
    \n
    \n `)}\n
    \n `}\n
    \n `;\n}\n\nfunction renderMapField(params: {\n schema: JsonSchema;\n value: Record;\n path: Array;\n hints: ConfigUiHints;\n unsupported: Set;\n disabled: boolean;\n reservedKeys: Set;\n onPatch: (path: Array, value: unknown) => void;\n}): TemplateResult {\n const { schema, value, path, hints, unsupported, disabled, reservedKeys, onPatch } = params;\n const anySchema = isAnySchema(schema);\n const entries = Object.entries(value ?? {}).filter(([key]) => !reservedKeys.has(key));\n\n return html`\n
    \n
    \n Custom entries\n {\n const next = { ...(value ?? {}) };\n let index = 1;\n let key = `custom-${index}`;\n while (key in next) {\n index += 1;\n key = `custom-${index}`;\n }\n next[key] = anySchema ? {} : defaultValue(schema);\n onPatch(path, next);\n }}\n >\n ${icons.plus}\n Add Entry\n \n
    \n \n ${entries.length === 0 ? html`\n
    No custom entries.
    \n ` : html`\n
    \n ${entries.map(([key, entryValue]) => {\n const valuePath = [...path, key];\n const fallback = jsonValue(entryValue);\n return html`\n
    \n
    \n {\n const nextKey = (e.target as HTMLInputElement).value.trim();\n if (!nextKey || nextKey === key) return;\n const next = { ...(value ?? {}) };\n if (nextKey in next) return;\n next[nextKey] = next[key];\n delete next[key];\n onPatch(path, next);\n }}\n />\n
    \n
    \n ${anySchema\n ? html`\n {\n const target = e.target as HTMLTextAreaElement;\n const raw = target.value.trim();\n if (!raw) {\n onPatch(valuePath, undefined);\n return;\n }\n try {\n onPatch(valuePath, JSON.parse(raw));\n } catch {\n target.value = fallback;\n }\n }}\n >\n `\n : renderNode({\n schema,\n value: entryValue,\n path: valuePath,\n hints,\n unsupported,\n disabled,\n showLabel: false,\n onPatch,\n })}\n
    \n {\n const next = { ...(value ?? {}) };\n delete next[key];\n onPatch(path, next);\n }}\n >\n ${icons.trash}\n \n
    \n `;\n })}\n
    \n `}\n
    \n `;\n}\n","import { html, nothing } from \"lit\";\nimport type { ConfigUiHints } from \"../types\";\nimport { icons } from \"../icons\";\nimport {\n hintForPath,\n humanize,\n schemaType,\n type JsonSchema,\n} from \"./config-form.shared\";\nimport { renderNode } from \"./config-form.node\";\n\nexport type ConfigFormProps = {\n schema: JsonSchema | null;\n uiHints: ConfigUiHints;\n value: Record | null;\n disabled?: boolean;\n unsupportedPaths?: string[];\n searchQuery?: string;\n activeSection?: string | null;\n activeSubsection?: string | null;\n onPatch: (path: Array, value: unknown) => void;\n};\n\n// SVG Icons for section cards (Lucide-style)\nconst sectionIcons = {\n env: html``,\n update: html``,\n agents: html``,\n auth: html``,\n channels: html``,\n messages: html``,\n commands: html``,\n hooks: html``,\n skills: html``,\n tools: html``,\n gateway: html``,\n wizard: html``,\n // Additional sections\n meta: html``,\n logging: html``,\n browser: html``,\n ui: html``,\n models: html``,\n bindings: html``,\n broadcast: html``,\n audio: html``,\n session: html``,\n cron: html``,\n web: html``,\n discovery: html``,\n canvasHost: html``,\n talk: html``,\n plugins: html``,\n default: html``,\n};\n\n// Section metadata\nexport const SECTION_META: Record = {\n env: { label: \"Environment Variables\", description: \"Environment variables passed to the gateway process\" },\n update: { label: \"Updates\", description: \"Auto-update settings and release channel\" },\n agents: { label: \"Agents\", description: \"Agent configurations, models, and identities\" },\n auth: { label: \"Authentication\", description: \"API keys and authentication profiles\" },\n channels: { label: \"Channels\", description: \"Messaging channels (Telegram, Discord, Slack, etc.)\" },\n messages: { label: \"Messages\", description: \"Message handling and routing settings\" },\n commands: { label: \"Commands\", description: \"Custom slash commands\" },\n hooks: { label: \"Hooks\", description: \"Webhooks and event hooks\" },\n skills: { label: \"Skills\", description: \"Skill packs and capabilities\" },\n tools: { label: \"Tools\", description: \"Tool configurations (browser, search, etc.)\" },\n gateway: { label: \"Gateway\", description: \"Gateway server settings (port, auth, binding)\" },\n wizard: { label: \"Setup Wizard\", description: \"Setup wizard state and history\" },\n // Additional sections\n meta: { label: \"Metadata\", description: \"Gateway metadata and version information\" },\n logging: { label: \"Logging\", description: \"Log levels and output configuration\" },\n browser: { label: \"Browser\", description: \"Browser automation settings\" },\n ui: { label: \"UI\", description: \"User interface preferences\" },\n models: { label: \"Models\", description: \"AI model configurations and providers\" },\n bindings: { label: \"Bindings\", description: \"Key bindings and shortcuts\" },\n broadcast: { label: \"Broadcast\", description: \"Broadcast and notification settings\" },\n audio: { label: \"Audio\", description: \"Audio input/output settings\" },\n session: { label: \"Session\", description: \"Session management and persistence\" },\n cron: { label: \"Cron\", description: \"Scheduled tasks and automation\" },\n web: { label: \"Web\", description: \"Web server and API settings\" },\n discovery: { label: \"Discovery\", description: \"Service discovery and networking\" },\n canvasHost: { label: \"Canvas Host\", description: \"Canvas rendering and display\" },\n talk: { label: \"Talk\", description: \"Voice and speech settings\" },\n plugins: { label: \"Plugins\", description: \"Plugin management and extensions\" },\n};\n\nfunction getSectionIcon(key: string) {\n return sectionIcons[key as keyof typeof sectionIcons] ?? sectionIcons.default;\n}\n\nfunction matchesSearch(key: string, schema: JsonSchema, query: string): boolean {\n if (!query) return true;\n const q = query.toLowerCase();\n const meta = SECTION_META[key];\n \n // Check key name\n if (key.toLowerCase().includes(q)) return true;\n \n // Check label and description\n if (meta) {\n if (meta.label.toLowerCase().includes(q)) return true;\n if (meta.description.toLowerCase().includes(q)) return true;\n }\n \n return schemaMatches(schema, q);\n}\n\nfunction schemaMatches(schema: JsonSchema, query: string): boolean {\n if (schema.title?.toLowerCase().includes(query)) return true;\n if (schema.description?.toLowerCase().includes(query)) return true;\n if (schema.enum?.some((value) => String(value).toLowerCase().includes(query))) return true;\n\n if (schema.properties) {\n for (const [propKey, propSchema] of Object.entries(schema.properties)) {\n if (propKey.toLowerCase().includes(query)) return true;\n if (schemaMatches(propSchema, query)) return true;\n }\n }\n\n if (schema.items) {\n const items = Array.isArray(schema.items) ? schema.items : [schema.items];\n for (const item of items) {\n if (item && schemaMatches(item, query)) return true;\n }\n }\n\n if (schema.additionalProperties && typeof schema.additionalProperties === \"object\") {\n if (schemaMatches(schema.additionalProperties, query)) return true;\n }\n\n const unions = schema.anyOf ?? schema.oneOf ?? schema.allOf;\n if (unions) {\n for (const entry of unions) {\n if (entry && schemaMatches(entry, query)) return true;\n }\n }\n\n return false;\n}\n\nexport function renderConfigForm(props: ConfigFormProps) {\n if (!props.schema) {\n return html`
    Schema unavailable.
    `;\n }\n const schema = props.schema;\n const value = props.value ?? {};\n if (schemaType(schema) !== \"object\" || !schema.properties) {\n return html`
    Unsupported schema. Use Raw.
    `;\n }\n const unsupported = new Set(props.unsupportedPaths ?? []);\n const properties = schema.properties;\n const searchQuery = props.searchQuery ?? \"\";\n const activeSection = props.activeSection;\n const activeSubsection = props.activeSubsection ?? null;\n\n const entries = Object.entries(properties).sort((a, b) => {\n const orderA = hintForPath([a[0]], props.uiHints)?.order ?? 50;\n const orderB = hintForPath([b[0]], props.uiHints)?.order ?? 50;\n if (orderA !== orderB) return orderA - orderB;\n return a[0].localeCompare(b[0]);\n });\n\n const filteredEntries = entries.filter(([key, node]) => {\n if (activeSection && key !== activeSection) return false;\n if (searchQuery && !matchesSearch(key, node, searchQuery)) return false;\n return true;\n });\n\n let subsectionContext:\n | { sectionKey: string; subsectionKey: string; schema: JsonSchema }\n | null = null;\n if (activeSection && activeSubsection && filteredEntries.length === 1) {\n const sectionSchema = filteredEntries[0]?.[1];\n if (\n sectionSchema &&\n schemaType(sectionSchema) === \"object\" &&\n sectionSchema.properties &&\n sectionSchema.properties[activeSubsection]\n ) {\n subsectionContext = {\n sectionKey: activeSection,\n subsectionKey: activeSubsection,\n schema: sectionSchema.properties[activeSubsection],\n };\n }\n }\n\n if (filteredEntries.length === 0) {\n return html`\n
    \n
    ${icons.search}
    \n
    \n ${searchQuery \n ? `No settings match \"${searchQuery}\"` \n : \"No settings in this section\"}\n
    \n
    \n `;\n }\n\n return html`\n
    \n ${subsectionContext\n ? (() => {\n const { sectionKey, subsectionKey, schema: node } = subsectionContext;\n const hint = hintForPath([sectionKey, subsectionKey], props.uiHints);\n const label = hint?.label ?? node.title ?? humanize(subsectionKey);\n const description = hint?.help ?? node.description ?? \"\";\n const sectionValue = (value as Record)[sectionKey];\n const scopedValue =\n sectionValue && typeof sectionValue === \"object\"\n ? (sectionValue as Record)[subsectionKey]\n : undefined;\n const id = `config-section-${sectionKey}-${subsectionKey}`;\n return html`\n
    \n
    \n ${getSectionIcon(sectionKey)}\n
    \n

    ${label}

    \n ${description\n ? html`

    ${description}

    `\n : nothing}\n
    \n
    \n
    \n ${renderNode({\n schema: node,\n value: scopedValue,\n path: [sectionKey, subsectionKey],\n hints: props.uiHints,\n unsupported,\n disabled: props.disabled ?? false,\n showLabel: false,\n onPatch: props.onPatch,\n })}\n
    \n
    \n `;\n })()\n : filteredEntries.map(([key, node]) => {\n const meta = SECTION_META[key] ?? {\n label: key.charAt(0).toUpperCase() + key.slice(1),\n description: node.description ?? \"\",\n };\n\n return html`\n
    \n
    \n ${getSectionIcon(key)}\n
    \n

    ${meta.label}

    \n ${meta.description\n ? html`

    ${meta.description}

    `\n : nothing}\n
    \n
    \n
    \n ${renderNode({\n schema: node,\n value: (value as Record)[key],\n path: [key],\n hints: props.uiHints,\n unsupported,\n disabled: props.disabled ?? false,\n showLabel: false,\n onPatch: props.onPatch,\n })}\n
    \n
    \n `;\n })}\n
    \n `;\n}\n","import { pathKey, schemaType, type JsonSchema } from \"./config-form.shared\";\n\nexport type ConfigSchemaAnalysis = {\n schema: JsonSchema | null;\n unsupportedPaths: string[];\n};\n\nconst META_KEYS = new Set([\"title\", \"description\", \"default\", \"nullable\"]);\n\nfunction isAnySchema(schema: JsonSchema): boolean {\n const keys = Object.keys(schema ?? {}).filter((key) => !META_KEYS.has(key));\n return keys.length === 0;\n}\n\nfunction normalizeEnum(values: unknown[]): { enumValues: unknown[]; nullable: boolean } {\n const filtered = values.filter((value) => value != null);\n const nullable = filtered.length !== values.length;\n const enumValues: unknown[] = [];\n for (const value of filtered) {\n if (!enumValues.some((existing) => Object.is(existing, value))) {\n enumValues.push(value);\n }\n }\n return { enumValues, nullable };\n}\n\nexport function analyzeConfigSchema(raw: unknown): ConfigSchemaAnalysis {\n if (!raw || typeof raw !== \"object\") {\n return { schema: null, unsupportedPaths: [\"\"] };\n }\n return normalizeSchemaNode(raw as JsonSchema, []);\n}\n\nfunction normalizeSchemaNode(\n schema: JsonSchema,\n path: Array,\n): ConfigSchemaAnalysis {\n const unsupported = new Set();\n const normalized: JsonSchema = { ...schema };\n const pathLabel = pathKey(path) || \"\";\n\n if (schema.anyOf || schema.oneOf || schema.allOf) {\n const union = normalizeUnion(schema, path);\n if (union) return union;\n return { schema, unsupportedPaths: [pathLabel] };\n }\n\n const nullable = Array.isArray(schema.type) && schema.type.includes(\"null\");\n const type =\n schemaType(schema) ??\n (schema.properties || schema.additionalProperties ? \"object\" : undefined);\n normalized.type = type ?? schema.type;\n normalized.nullable = nullable || schema.nullable;\n\n if (normalized.enum) {\n const { enumValues, nullable: enumNullable } = normalizeEnum(normalized.enum);\n normalized.enum = enumValues;\n if (enumNullable) normalized.nullable = true;\n if (enumValues.length === 0) unsupported.add(pathLabel);\n }\n\n if (type === \"object\") {\n const properties = schema.properties ?? {};\n const normalizedProps: Record = {};\n for (const [key, value] of Object.entries(properties)) {\n const res = normalizeSchemaNode(value, [...path, key]);\n if (res.schema) normalizedProps[key] = res.schema;\n for (const entry of res.unsupportedPaths) unsupported.add(entry);\n }\n normalized.properties = normalizedProps;\n\n if (schema.additionalProperties === true) {\n unsupported.add(pathLabel);\n } else if (schema.additionalProperties === false) {\n normalized.additionalProperties = false;\n } else if (\n schema.additionalProperties &&\n typeof schema.additionalProperties === \"object\"\n ) {\n if (!isAnySchema(schema.additionalProperties as JsonSchema)) {\n const res = normalizeSchemaNode(\n schema.additionalProperties as JsonSchema,\n [...path, \"*\"],\n );\n normalized.additionalProperties =\n res.schema ?? (schema.additionalProperties as JsonSchema);\n if (res.unsupportedPaths.length > 0) unsupported.add(pathLabel);\n }\n }\n } else if (type === \"array\") {\n const itemsSchema = Array.isArray(schema.items)\n ? schema.items[0]\n : schema.items;\n if (!itemsSchema) {\n unsupported.add(pathLabel);\n } else {\n const res = normalizeSchemaNode(itemsSchema, [...path, \"*\"]);\n normalized.items = res.schema ?? itemsSchema;\n if (res.unsupportedPaths.length > 0) unsupported.add(pathLabel);\n }\n } else if (\n type !== \"string\" &&\n type !== \"number\" &&\n type !== \"integer\" &&\n type !== \"boolean\" &&\n !normalized.enum\n ) {\n unsupported.add(pathLabel);\n }\n\n return {\n schema: normalized,\n unsupportedPaths: Array.from(unsupported),\n };\n}\n\nfunction normalizeUnion(\n schema: JsonSchema,\n path: Array,\n): ConfigSchemaAnalysis | null {\n if (schema.allOf) return null;\n const union = schema.anyOf ?? schema.oneOf;\n if (!union) return null;\n\n const literals: unknown[] = [];\n const remaining: JsonSchema[] = [];\n let nullable = false;\n\n for (const entry of union) {\n if (!entry || typeof entry !== \"object\") return null;\n if (Array.isArray(entry.enum)) {\n const { enumValues, nullable: enumNullable } = normalizeEnum(entry.enum);\n literals.push(...enumValues);\n if (enumNullable) nullable = true;\n continue;\n }\n if (\"const\" in entry) {\n if (entry.const == null) {\n nullable = true;\n continue;\n }\n literals.push(entry.const);\n continue;\n }\n if (schemaType(entry) === \"null\") {\n nullable = true;\n continue;\n }\n remaining.push(entry);\n }\n\n if (literals.length > 0 && remaining.length === 0) {\n const unique: unknown[] = [];\n for (const value of literals) {\n if (!unique.some((existing) => Object.is(existing, value))) {\n unique.push(value);\n }\n }\n return {\n schema: {\n ...schema,\n enum: unique,\n nullable,\n anyOf: undefined,\n oneOf: undefined,\n allOf: undefined,\n },\n unsupportedPaths: [],\n };\n }\n\n if (remaining.length === 1) {\n const res = normalizeSchemaNode(remaining[0], path);\n if (res.schema) {\n res.schema.nullable = nullable || res.schema.nullable;\n }\n return res;\n }\n\n const primitiveTypes = [\"string\", \"number\", \"integer\", \"boolean\"];\n if (\n remaining.length > 0 &&\n literals.length === 0 &&\n remaining.every((entry) => entry.type && primitiveTypes.includes(String(entry.type)))\n ) {\n return {\n schema: {\n ...schema,\n nullable,\n },\n unsupportedPaths: [],\n };\n }\n\n return null;\n}\n","import { html, nothing } from \"lit\";\nimport type { ConfigUiHints } from \"../types\";\nimport { analyzeConfigSchema, renderConfigForm, SECTION_META } from \"./config-form\";\nimport {\n hintForPath,\n humanize,\n schemaType,\n type JsonSchema,\n} from \"./config-form.shared\";\n\nexport type ConfigProps = {\n raw: string;\n originalRaw: string;\n valid: boolean | null;\n issues: unknown[];\n loading: boolean;\n saving: boolean;\n applying: boolean;\n updating: boolean;\n connected: boolean;\n schema: unknown | null;\n schemaLoading: boolean;\n uiHints: ConfigUiHints;\n formMode: \"form\" | \"raw\";\n formValue: Record | null;\n originalValue: Record | null;\n searchQuery: string;\n activeSection: string | null;\n activeSubsection: string | null;\n onRawChange: (next: string) => void;\n onFormModeChange: (mode: \"form\" | \"raw\") => void;\n onFormPatch: (path: Array, value: unknown) => void;\n onSearchChange: (query: string) => void;\n onSectionChange: (section: string | null) => void;\n onSubsectionChange: (section: string | null) => void;\n onReload: () => void;\n onSave: () => void;\n onApply: () => void;\n onUpdate: () => void;\n};\n\n// SVG Icons for sidebar (Lucide-style)\nconst sidebarIcons = {\n all: html``,\n env: html``,\n update: html``,\n agents: html``,\n auth: html``,\n channels: html``,\n messages: html``,\n commands: html``,\n hooks: html``,\n skills: html``,\n tools: html``,\n gateway: html``,\n wizard: html``,\n // Additional sections\n meta: html``,\n logging: html``,\n browser: html``,\n ui: html``,\n models: html``,\n bindings: html``,\n broadcast: html``,\n audio: html``,\n session: html``,\n cron: html``,\n web: html``,\n discovery: html``,\n canvasHost: html``,\n talk: html``,\n plugins: html``,\n default: html``,\n};\n\n// Section definitions\nconst SECTIONS: Array<{ key: string; label: string }> = [\n { key: \"env\", label: \"Environment\" },\n { key: \"update\", label: \"Updates\" },\n { key: \"agents\", label: \"Agents\" },\n { key: \"auth\", label: \"Authentication\" },\n { key: \"channels\", label: \"Channels\" },\n { key: \"messages\", label: \"Messages\" },\n { key: \"commands\", label: \"Commands\" },\n { key: \"hooks\", label: \"Hooks\" },\n { key: \"skills\", label: \"Skills\" },\n { key: \"tools\", label: \"Tools\" },\n { key: \"gateway\", label: \"Gateway\" },\n { key: \"wizard\", label: \"Setup Wizard\" },\n];\n\ntype SubsectionEntry = {\n key: string;\n label: string;\n description?: string;\n order: number;\n};\n\nconst ALL_SUBSECTION = \"__all__\";\n\nfunction getSectionIcon(key: string) {\n return sidebarIcons[key as keyof typeof sidebarIcons] ?? sidebarIcons.default;\n}\n\nfunction resolveSectionMeta(key: string, schema?: JsonSchema): {\n label: string;\n description?: string;\n} {\n const meta = SECTION_META[key];\n if (meta) return meta;\n return {\n label: schema?.title ?? humanize(key),\n description: schema?.description ?? \"\",\n };\n}\n\nfunction resolveSubsections(params: {\n key: string;\n schema: JsonSchema | undefined;\n uiHints: ConfigUiHints;\n}): SubsectionEntry[] {\n const { key, schema, uiHints } = params;\n if (!schema || schemaType(schema) !== \"object\" || !schema.properties) return [];\n const entries = Object.entries(schema.properties).map(([subKey, node]) => {\n const hint = hintForPath([key, subKey], uiHints);\n const label = hint?.label ?? node.title ?? humanize(subKey);\n const description = hint?.help ?? node.description ?? \"\";\n const order = hint?.order ?? 50;\n return { key: subKey, label, description, order };\n });\n entries.sort((a, b) => (a.order !== b.order ? a.order - b.order : a.key.localeCompare(b.key)));\n return entries;\n}\n\nfunction computeDiff(\n original: Record | null,\n current: Record | null\n): Array<{ path: string; from: unknown; to: unknown }> {\n if (!original || !current) return [];\n const changes: Array<{ path: string; from: unknown; to: unknown }> = [];\n \n function compare(orig: unknown, curr: unknown, path: string) {\n if (orig === curr) return;\n if (typeof orig !== typeof curr) {\n changes.push({ path, from: orig, to: curr });\n return;\n }\n if (typeof orig !== \"object\" || orig === null || curr === null) {\n if (orig !== curr) {\n changes.push({ path, from: orig, to: curr });\n }\n return;\n }\n if (Array.isArray(orig) && Array.isArray(curr)) {\n if (JSON.stringify(orig) !== JSON.stringify(curr)) {\n changes.push({ path, from: orig, to: curr });\n }\n return;\n }\n const origObj = orig as Record;\n const currObj = curr as Record;\n const allKeys = new Set([...Object.keys(origObj), ...Object.keys(currObj)]);\n for (const key of allKeys) {\n compare(origObj[key], currObj[key], path ? `${path}.${key}` : key);\n }\n }\n \n compare(original, current, \"\");\n return changes;\n}\n\nfunction truncateValue(value: unknown, maxLen = 40): string {\n let str: string;\n try {\n const json = JSON.stringify(value);\n str = json ?? String(value);\n } catch {\n str = String(value);\n }\n if (str.length <= maxLen) return str;\n return str.slice(0, maxLen - 3) + \"...\";\n}\n\nexport function renderConfig(props: ConfigProps) {\n const validity =\n props.valid == null ? \"unknown\" : props.valid ? \"valid\" : \"invalid\";\n const analysis = analyzeConfigSchema(props.schema);\n const formUnsafe = analysis.schema\n ? analysis.unsupportedPaths.length > 0\n : false;\n\n // Get available sections from schema\n const schemaProps = analysis.schema?.properties ?? {};\n const availableSections = SECTIONS.filter(s => s.key in schemaProps);\n\n // Add any sections in schema but not in our list\n const knownKeys = new Set(SECTIONS.map(s => s.key));\n const extraSections = Object.keys(schemaProps)\n .filter(k => !knownKeys.has(k))\n .map(k => ({ key: k, label: k.charAt(0).toUpperCase() + k.slice(1) }));\n\n const allSections = [...availableSections, ...extraSections];\n\n const activeSectionSchema =\n props.activeSection && analysis.schema && schemaType(analysis.schema) === \"object\"\n ? (analysis.schema.properties?.[props.activeSection] as JsonSchema | undefined)\n : undefined;\n const activeSectionMeta = props.activeSection\n ? resolveSectionMeta(props.activeSection, activeSectionSchema)\n : null;\n const subsections = props.activeSection\n ? resolveSubsections({\n key: props.activeSection,\n schema: activeSectionSchema,\n uiHints: props.uiHints,\n })\n : [];\n const allowSubnav =\n props.formMode === \"form\" &&\n Boolean(props.activeSection) &&\n subsections.length > 0;\n const isAllSubsection = props.activeSubsection === ALL_SUBSECTION;\n const effectiveSubsection = props.searchQuery\n ? null\n : isAllSubsection\n ? null\n : props.activeSubsection ?? (subsections[0]?.key ?? null);\n\n // Compute diff for showing changes (works for both form and raw modes)\n const diff = props.formMode === \"form\"\n ? computeDiff(props.originalValue, props.formValue)\n : [];\n const hasRawChanges = props.formMode === \"raw\" && props.raw !== props.originalRaw;\n const hasChanges = props.formMode === \"form\" ? diff.length > 0 : hasRawChanges;\n\n // Save/apply buttons require actual changes to be enabled.\n // Note: formUnsafe warns about unsupported schema paths but shouldn't block saving.\n const canSaveForm =\n Boolean(props.formValue) && !props.loading && Boolean(analysis.schema);\n const canSave =\n props.connected &&\n !props.saving &&\n hasChanges &&\n (props.formMode === \"raw\" ? true : canSaveForm);\n const canApply =\n props.connected &&\n !props.applying &&\n !props.updating &&\n hasChanges &&\n (props.formMode === \"raw\" ? true : canSaveForm);\n const canUpdate = props.connected && !props.applying && !props.updating;\n\n return html`\n
    \n \n \n \n \n
    \n \n
    \n
    \n ${hasChanges ? html`\n ${props.formMode === \"raw\" ? \"Unsaved changes\" : `${diff.length} unsaved change${diff.length !== 1 ? \"s\" : \"\"}`}\n ` : html`\n No changes\n `}\n
    \n
    \n \n \n ${props.saving ? \"Saving…\" : \"Save\"}\n \n \n ${props.applying ? \"Applying…\" : \"Apply\"}\n \n \n ${props.updating ? \"Updating…\" : \"Update\"}\n \n
    \n
    \n \n \n ${hasChanges && props.formMode === \"form\" ? html`\n
    \n \n View ${diff.length} pending change${diff.length !== 1 ? \"s\" : \"\"}\n \n \n \n \n
    \n ${diff.map(change => html`\n
    \n
    ${change.path}
    \n
    \n ${truncateValue(change.from)}\n \n ${truncateValue(change.to)}\n
    \n
    \n `)}\n
    \n
    \n ` : nothing}\n\n ${activeSectionMeta && props.formMode === \"form\"\n ? html`\n
    \n
    ${getSectionIcon(props.activeSection ?? \"\")}
    \n
    \n
    ${activeSectionMeta.label}
    \n ${activeSectionMeta.description\n ? html`
    ${activeSectionMeta.description}
    `\n : nothing}\n
    \n
    \n `\n : nothing}\n\n ${allowSubnav\n ? html`\n
    \n props.onSubsectionChange(ALL_SUBSECTION)}\n >\n All\n \n ${subsections.map(\n (entry) => html`\n props.onSubsectionChange(entry.key)}\n >\n ${entry.label}\n \n `,\n )}\n
    \n `\n : nothing}\n\n \n
    \n ${props.formMode === \"form\"\n ? html`\n ${props.schemaLoading\n ? html`
    \n
    \n Loading schema…\n
    `\n : renderConfigForm({\n schema: analysis.schema,\n uiHints: props.uiHints,\n value: props.formValue,\n disabled: props.loading || !props.formValue,\n unsupportedPaths: analysis.unsupportedPaths,\n onPatch: props.onFormPatch,\n searchQuery: props.searchQuery,\n activeSection: props.activeSection,\n activeSubsection: effectiveSubsection,\n })}\n ${formUnsafe\n ? html`
    \n Form view can't safely edit some fields.\n Use Raw to avoid losing config entries.\n
    `\n : nothing}\n `\n : html`\n \n `}\n
    \n\n ${props.issues.length > 0\n ? html`
    \n
    ${JSON.stringify(props.issues, null, 2)}
    \n
    `\n : nothing}\n
    \n
    \n `;\n}\n","import { html, nothing } from \"lit\";\n\nimport type { ChannelAccountSnapshot } from \"../types\";\nimport type { ChannelKey, ChannelsProps } from \"./channels.types\";\n\nexport function formatDuration(ms?: number | null) {\n if (!ms && ms !== 0) return \"n/a\";\n const sec = Math.round(ms / 1000);\n if (sec < 60) return `${sec}s`;\n const min = Math.round(sec / 60);\n if (min < 60) return `${min}m`;\n const hr = Math.round(min / 60);\n return `${hr}h`;\n}\n\nexport function channelEnabled(key: ChannelKey, props: ChannelsProps) {\n const snapshot = props.snapshot;\n const channels = snapshot?.channels as Record | null;\n if (!snapshot || !channels) return false;\n const channelStatus = channels[key] as Record | undefined;\n const configured = typeof channelStatus?.configured === \"boolean\" && channelStatus.configured;\n const running = typeof channelStatus?.running === \"boolean\" && channelStatus.running;\n const connected = typeof channelStatus?.connected === \"boolean\" && channelStatus.connected;\n const accounts = snapshot.channelAccounts?.[key] ?? [];\n const accountActive = accounts.some(\n (account) => account.configured || account.running || account.connected,\n );\n return configured || running || connected || accountActive;\n}\n\nexport function getChannelAccountCount(\n key: ChannelKey,\n channelAccounts?: Record | null,\n): number {\n return channelAccounts?.[key]?.length ?? 0;\n}\n\nexport function renderChannelAccountCount(\n key: ChannelKey,\n channelAccounts?: Record | null,\n) {\n const count = getChannelAccountCount(key, channelAccounts);\n if (count < 2) return nothing;\n return html`
    Accounts (${count})
    `;\n}\n\n","import { html } from \"lit\";\n\nimport type { ConfigUiHints } from \"../types\";\nimport type { ChannelsProps } from \"./channels.types\";\nimport {\n analyzeConfigSchema,\n renderNode,\n schemaType,\n type JsonSchema,\n} from \"./config-form\";\n\ntype ChannelConfigFormProps = {\n channelId: string;\n configValue: Record | null;\n schema: unknown | null;\n uiHints: ConfigUiHints;\n disabled: boolean;\n onPatch: (path: Array, value: unknown) => void;\n};\n\nfunction resolveSchemaNode(\n schema: JsonSchema | null,\n path: Array,\n): JsonSchema | null {\n let current = schema;\n for (const key of path) {\n if (!current) return null;\n const type = schemaType(current);\n if (type === \"object\") {\n const properties = current.properties ?? {};\n if (typeof key === \"string\" && properties[key]) {\n current = properties[key];\n continue;\n }\n const additional = current.additionalProperties;\n if (typeof key === \"string\" && additional && typeof additional === \"object\") {\n current = additional as JsonSchema;\n continue;\n }\n return null;\n }\n if (type === \"array\") {\n if (typeof key !== \"number\") return null;\n const items = Array.isArray(current.items) ? current.items[0] : current.items;\n current = items ?? null;\n continue;\n }\n return null;\n }\n return current;\n}\n\nfunction resolveChannelValue(\n config: Record,\n channelId: string,\n): Record {\n const channels = (config.channels ?? {}) as Record;\n const fromChannels = channels[channelId];\n const fallback = config[channelId];\n const resolved =\n (fromChannels && typeof fromChannels === \"object\"\n ? (fromChannels as Record)\n : null) ??\n (fallback && typeof fallback === \"object\"\n ? (fallback as Record)\n : null);\n return resolved ?? {};\n}\n\nexport function renderChannelConfigForm(props: ChannelConfigFormProps) {\n const analysis = analyzeConfigSchema(props.schema);\n const normalized = analysis.schema;\n if (!normalized) {\n return html`
    Schema unavailable. Use Raw.
    `;\n }\n const node = resolveSchemaNode(normalized, [\"channels\", props.channelId]);\n if (!node) {\n return html`
    Channel config schema unavailable.
    `;\n }\n const configValue = props.configValue ?? {};\n const value = resolveChannelValue(configValue, props.channelId);\n return html`\n
    \n ${renderNode({\n schema: node,\n value,\n path: [\"channels\", props.channelId],\n hints: props.uiHints,\n unsupported: new Set(analysis.unsupportedPaths),\n disabled: props.disabled,\n showLabel: false,\n onPatch: props.onPatch,\n })}\n
    \n `;\n}\n\nexport function renderChannelConfigSection(params: {\n channelId: string;\n props: ChannelsProps;\n}) {\n const { channelId, props } = params;\n const disabled = props.configSaving || props.configSchemaLoading;\n return html`\n
    \n ${props.configSchemaLoading\n ? html`
    Loading config schema…
    `\n : renderChannelConfigForm({\n channelId,\n configValue: props.configForm,\n schema: props.configSchema,\n uiHints: props.configUiHints,\n disabled,\n onPatch: props.onConfigPatch,\n })}\n
    \n props.onConfigSave()}\n >\n ${props.configSaving ? \"Saving…\" : \"Save\"}\n \n props.onConfigReload()}\n >\n Reload\n \n
    \n
    \n `;\n}\n","import { html, nothing } from \"lit\";\n\nimport { formatAgo } from \"../format\";\nimport type { DiscordStatus } from \"../types\";\nimport type { ChannelsProps } from \"./channels.types\";\nimport { renderChannelConfigSection } from \"./channels.config\";\n\nexport function renderDiscordCard(params: {\n props: ChannelsProps;\n discord?: DiscordStatus | null;\n accountCountLabel: unknown;\n}) {\n const { props, discord, accountCountLabel } = params;\n\n return html`\n
    \n
    Discord
    \n
    Bot status and channel configuration.
    \n ${accountCountLabel}\n\n
    \n
    \n Configured\n ${discord?.configured ? \"Yes\" : \"No\"}\n
    \n
    \n Running\n ${discord?.running ? \"Yes\" : \"No\"}\n
    \n
    \n Last start\n ${discord?.lastStartAt ? formatAgo(discord.lastStartAt) : \"n/a\"}\n
    \n
    \n Last probe\n ${discord?.lastProbeAt ? formatAgo(discord.lastProbeAt) : \"n/a\"}\n
    \n
    \n\n ${discord?.lastError\n ? html`
    \n ${discord.lastError}\n
    `\n : nothing}\n\n ${discord?.probe\n ? html`
    \n Probe ${discord.probe.ok ? \"ok\" : \"failed\"} ·\n ${discord.probe.status ?? \"\"} ${discord.probe.error ?? \"\"}\n
    `\n : nothing}\n\n ${renderChannelConfigSection({ channelId: \"discord\", props })}\n\n
    \n \n
    \n
    \n `;\n}\n","import { html, nothing } from \"lit\";\n\nimport { formatAgo } from \"../format\";\nimport type { GoogleChatStatus } from \"../types\";\nimport { renderChannelConfigSection } from \"./channels.config\";\nimport type { ChannelsProps } from \"./channels.types\";\n\nexport function renderGoogleChatCard(params: {\n props: ChannelsProps;\n googleChat?: GoogleChatStatus | null;\n accountCountLabel: unknown;\n}) {\n const { props, googleChat, accountCountLabel } = params;\n\n return html`\n
    \n
    Google Chat
    \n
    Chat API webhook status and channel configuration.
    \n ${accountCountLabel}\n\n
    \n
    \n Configured\n ${googleChat ? (googleChat.configured ? \"Yes\" : \"No\") : \"n/a\"}\n
    \n
    \n Running\n ${googleChat ? (googleChat.running ? \"Yes\" : \"No\") : \"n/a\"}\n
    \n
    \n Credential\n ${googleChat?.credentialSource ?? \"n/a\"}\n
    \n
    \n Audience\n \n ${googleChat?.audienceType\n ? `${googleChat.audienceType}${googleChat.audience ? ` · ${googleChat.audience}` : \"\"}`\n : \"n/a\"}\n \n
    \n
    \n Last start\n ${googleChat?.lastStartAt ? formatAgo(googleChat.lastStartAt) : \"n/a\"}\n
    \n
    \n Last probe\n ${googleChat?.lastProbeAt ? formatAgo(googleChat.lastProbeAt) : \"n/a\"}\n
    \n
    \n\n ${googleChat?.lastError\n ? html`
    \n ${googleChat.lastError}\n
    `\n : nothing}\n\n ${googleChat?.probe\n ? html`
    \n Probe ${googleChat.probe.ok ? \"ok\" : \"failed\"} ·\n ${googleChat.probe.status ?? \"\"} ${googleChat.probe.error ?? \"\"}\n
    `\n : nothing}\n\n ${renderChannelConfigSection({ channelId: \"googlechat\", props })}\n\n
    \n \n
    \n
    \n `;\n}\n","import { html, nothing } from \"lit\";\n\nimport { formatAgo } from \"../format\";\nimport type { IMessageStatus } from \"../types\";\nimport type { ChannelsProps } from \"./channels.types\";\nimport { renderChannelConfigSection } from \"./channels.config\";\n\nexport function renderIMessageCard(params: {\n props: ChannelsProps;\n imessage?: IMessageStatus | null;\n accountCountLabel: unknown;\n}) {\n const { props, imessage, accountCountLabel } = params;\n\n return html`\n
    \n
    iMessage
    \n
    macOS bridge status and channel configuration.
    \n ${accountCountLabel}\n\n
    \n
    \n Configured\n ${imessage?.configured ? \"Yes\" : \"No\"}\n
    \n
    \n Running\n ${imessage?.running ? \"Yes\" : \"No\"}\n
    \n
    \n Last start\n ${imessage?.lastStartAt ? formatAgo(imessage.lastStartAt) : \"n/a\"}\n
    \n
    \n Last probe\n ${imessage?.lastProbeAt ? formatAgo(imessage.lastProbeAt) : \"n/a\"}\n
    \n
    \n\n ${imessage?.lastError\n ? html`
    \n ${imessage.lastError}\n
    `\n : nothing}\n\n ${imessage?.probe\n ? html`
    \n Probe ${imessage.probe.ok ? \"ok\" : \"failed\"} ·\n ${imessage.probe.error ?? \"\"}\n
    `\n : nothing}\n\n ${renderChannelConfigSection({ channelId: \"imessage\", props })}\n\n
    \n \n
    \n
    \n `;\n}\n","/**\n * Nostr Profile Edit Form\n *\n * Provides UI for editing and publishing Nostr profile (kind:0).\n */\n\nimport { html, nothing, type TemplateResult } from \"lit\";\n\nimport type { NostrProfile as NostrProfileType } from \"../types\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface NostrProfileFormState {\n /** Current form values */\n values: NostrProfileType;\n /** Original values for dirty detection */\n original: NostrProfileType;\n /** Whether the form is currently submitting */\n saving: boolean;\n /** Whether import is in progress */\n importing: boolean;\n /** Last error message */\n error: string | null;\n /** Last success message */\n success: string | null;\n /** Validation errors per field */\n fieldErrors: Record;\n /** Whether to show advanced fields */\n showAdvanced: boolean;\n}\n\nexport interface NostrProfileFormCallbacks {\n /** Called when a field value changes */\n onFieldChange: (field: keyof NostrProfileType, value: string) => void;\n /** Called when save is clicked */\n onSave: () => void;\n /** Called when import is clicked */\n onImport: () => void;\n /** Called when cancel is clicked */\n onCancel: () => void;\n /** Called when toggle advanced is clicked */\n onToggleAdvanced: () => void;\n}\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction isFormDirty(state: NostrProfileFormState): boolean {\n const { values, original } = state;\n return (\n values.name !== original.name ||\n values.displayName !== original.displayName ||\n values.about !== original.about ||\n values.picture !== original.picture ||\n values.banner !== original.banner ||\n values.website !== original.website ||\n values.nip05 !== original.nip05 ||\n values.lud16 !== original.lud16\n );\n}\n\n// ============================================================================\n// Form Rendering\n// ============================================================================\n\nexport function renderNostrProfileForm(params: {\n state: NostrProfileFormState;\n callbacks: NostrProfileFormCallbacks;\n accountId: string;\n}): TemplateResult {\n const { state, callbacks, accountId } = params;\n const isDirty = isFormDirty(state);\n\n const renderField = (\n field: keyof NostrProfileType,\n label: string,\n opts: {\n type?: \"text\" | \"url\" | \"textarea\";\n placeholder?: string;\n maxLength?: number;\n help?: string;\n } = {}\n ) => {\n const { type = \"text\", placeholder, maxLength, help } = opts;\n const value = state.values[field] ?? \"\";\n const error = state.fieldErrors[field];\n\n const inputId = `nostr-profile-${field}`;\n\n if (type === \"textarea\") {\n return html`\n
    \n \n {\n const target = e.target as HTMLTextAreaElement;\n callbacks.onFieldChange(field, target.value);\n }}\n ?disabled=${state.saving}\n >\n ${help ? html`
    ${help}
    ` : nothing}\n ${error ? html`
    ${error}
    ` : nothing}\n
    \n `;\n }\n\n return html`\n
    \n \n {\n const target = e.target as HTMLInputElement;\n callbacks.onFieldChange(field, target.value);\n }}\n ?disabled=${state.saving}\n />\n ${help ? html`
    ${help}
    ` : nothing}\n ${error ? html`
    ${error}
    ` : nothing}\n
    \n `;\n };\n\n const renderPicturePreview = () => {\n const picture = state.values.picture;\n if (!picture) return nothing;\n\n return html`\n
    \n {\n const img = e.target as HTMLImageElement;\n img.style.display = \"none\";\n }}\n @load=${(e: Event) => {\n const img = e.target as HTMLImageElement;\n img.style.display = \"block\";\n }}\n />\n
    \n `;\n };\n\n return html`\n
    \n
    \n
    Edit Profile
    \n
    Account: ${accountId}
    \n
    \n\n ${state.error\n ? html`
    ${state.error}
    `\n : nothing}\n\n ${state.success\n ? html`
    ${state.success}
    `\n : nothing}\n\n ${renderPicturePreview()}\n\n ${renderField(\"name\", \"Username\", {\n placeholder: \"satoshi\",\n maxLength: 256,\n help: \"Short username (e.g., satoshi)\",\n })}\n\n ${renderField(\"displayName\", \"Display Name\", {\n placeholder: \"Satoshi Nakamoto\",\n maxLength: 256,\n help: \"Your full display name\",\n })}\n\n ${renderField(\"about\", \"Bio\", {\n type: \"textarea\",\n placeholder: \"Tell people about yourself...\",\n maxLength: 2000,\n help: \"A brief bio or description\",\n })}\n\n ${renderField(\"picture\", \"Avatar URL\", {\n type: \"url\",\n placeholder: \"https://example.com/avatar.jpg\",\n help: \"HTTPS URL to your profile picture\",\n })}\n\n ${state.showAdvanced\n ? html`\n
    \n
    Advanced
    \n\n ${renderField(\"banner\", \"Banner URL\", {\n type: \"url\",\n placeholder: \"https://example.com/banner.jpg\",\n help: \"HTTPS URL to a banner image\",\n })}\n\n ${renderField(\"website\", \"Website\", {\n type: \"url\",\n placeholder: \"https://example.com\",\n help: \"Your personal website\",\n })}\n\n ${renderField(\"nip05\", \"NIP-05 Identifier\", {\n placeholder: \"you@example.com\",\n help: \"Verifiable identifier (e.g., you@domain.com)\",\n })}\n\n ${renderField(\"lud16\", \"Lightning Address\", {\n placeholder: \"you@getalby.com\",\n help: \"Lightning address for tips (LUD-16)\",\n })}\n
    \n `\n : nothing}\n\n
    \n \n ${state.saving ? \"Saving...\" : \"Save & Publish\"}\n \n\n \n ${state.importing ? \"Importing...\" : \"Import from Relays\"}\n \n\n \n ${state.showAdvanced ? \"Hide Advanced\" : \"Show Advanced\"}\n \n\n \n Cancel\n \n
    \n\n ${isDirty\n ? html`
    \n You have unsaved changes\n
    `\n : nothing}\n
    \n `;\n}\n\n// ============================================================================\n// Factory\n// ============================================================================\n\n/**\n * Create initial form state from existing profile\n */\nexport function createNostrProfileFormState(\n profile: NostrProfileType | undefined\n): NostrProfileFormState {\n const values: NostrProfileType = {\n name: profile?.name ?? \"\",\n displayName: profile?.displayName ?? \"\",\n about: profile?.about ?? \"\",\n picture: profile?.picture ?? \"\",\n banner: profile?.banner ?? \"\",\n website: profile?.website ?? \"\",\n nip05: profile?.nip05 ?? \"\",\n lud16: profile?.lud16 ?? \"\",\n };\n\n return {\n values,\n original: { ...values },\n saving: false,\n importing: false,\n error: null,\n success: null,\n fieldErrors: {},\n showAdvanced: Boolean(\n profile?.banner || profile?.website || profile?.nip05 || profile?.lud16\n ),\n };\n}\n","import { html, nothing } from \"lit\";\n\nimport { formatAgo } from \"../format\";\nimport type { ChannelAccountSnapshot, NostrStatus } from \"../types\";\nimport type { ChannelsProps } from \"./channels.types\";\nimport { renderChannelConfigSection } from \"./channels.config\";\nimport {\n renderNostrProfileForm,\n type NostrProfileFormState,\n type NostrProfileFormCallbacks,\n} from \"./channels.nostr-profile-form\";\n\n/**\n * Truncate a pubkey for display (shows first and last 8 chars)\n */\nfunction truncatePubkey(pubkey: string | null | undefined): string {\n if (!pubkey) return \"n/a\";\n if (pubkey.length <= 20) return pubkey;\n return `${pubkey.slice(0, 8)}...${pubkey.slice(-8)}`;\n}\n\nexport function renderNostrCard(params: {\n props: ChannelsProps;\n nostr?: NostrStatus | null;\n nostrAccounts: ChannelAccountSnapshot[];\n accountCountLabel: unknown;\n /** Profile form state (optional - if provided, shows form) */\n profileFormState?: NostrProfileFormState | null;\n /** Profile form callbacks */\n profileFormCallbacks?: NostrProfileFormCallbacks | null;\n /** Called when Edit Profile is clicked */\n onEditProfile?: () => void;\n}) {\n const {\n props,\n nostr,\n nostrAccounts,\n accountCountLabel,\n profileFormState,\n profileFormCallbacks,\n onEditProfile,\n } = params;\n const primaryAccount = nostrAccounts[0];\n const summaryConfigured = nostr?.configured ?? primaryAccount?.configured ?? false;\n const summaryRunning = nostr?.running ?? primaryAccount?.running ?? false;\n const summaryPublicKey =\n nostr?.publicKey ??\n (primaryAccount as { publicKey?: string } | undefined)?.publicKey;\n const summaryLastStartAt = nostr?.lastStartAt ?? primaryAccount?.lastStartAt ?? null;\n const summaryLastError = nostr?.lastError ?? primaryAccount?.lastError ?? null;\n const hasMultipleAccounts = nostrAccounts.length > 1;\n const showingForm = profileFormState !== null && profileFormState !== undefined;\n\n const renderAccountCard = (account: ChannelAccountSnapshot) => {\n const publicKey = (account as { publicKey?: string }).publicKey;\n const profile = (account as { profile?: { name?: string; displayName?: string } }).profile;\n const displayName = profile?.displayName ?? profile?.name ?? account.name ?? account.accountId;\n\n return html`\n
    \n
    \n
    ${displayName}
    \n
    ${account.accountId}
    \n
    \n
    \n
    \n Running\n ${account.running ? \"Yes\" : \"No\"}\n
    \n
    \n Configured\n ${account.configured ? \"Yes\" : \"No\"}\n
    \n
    \n Public Key\n ${truncatePubkey(publicKey)}\n
    \n
    \n Last inbound\n ${account.lastInboundAt ? formatAgo(account.lastInboundAt) : \"n/a\"}\n
    \n ${account.lastError\n ? html`\n
    ${account.lastError}
    \n `\n : nothing}\n
    \n
    \n `;\n };\n\n const renderProfileSection = () => {\n // If showing form, render the form instead of the read-only view\n if (showingForm && profileFormCallbacks) {\n return renderNostrProfileForm({\n state: profileFormState,\n callbacks: profileFormCallbacks,\n accountId: nostrAccounts[0]?.accountId ?? \"default\",\n });\n }\n\n const profile =\n (primaryAccount as\n | {\n profile?: {\n name?: string;\n displayName?: string;\n about?: string;\n picture?: string;\n nip05?: string;\n };\n }\n | undefined)?.profile ?? nostr?.profile;\n const { name, displayName, about, picture, nip05 } = profile ?? {};\n const hasAnyProfileData = name || displayName || about || picture || nip05;\n\n return html`\n
    \n
    \n
    Profile
    \n ${summaryConfigured\n ? html`\n \n Edit Profile\n \n `\n : nothing}\n
    \n ${hasAnyProfileData\n ? html`\n
    \n ${picture\n ? html`\n
    \n {\n (e.target as HTMLImageElement).style.display = \"none\";\n }}\n />\n
    \n `\n : nothing}\n ${name ? html`
    Name${name}
    ` : nothing}\n ${displayName\n ? html`
    Display Name${displayName}
    `\n : nothing}\n ${about\n ? html`
    About${about}
    `\n : nothing}\n ${nip05 ? html`
    NIP-05${nip05}
    ` : nothing}\n
    \n `\n : html`\n
    \n No profile set. Click \"Edit Profile\" to add your name, bio, and avatar.\n
    \n `}\n
    \n `;\n };\n\n return html`\n
    \n
    Nostr
    \n
    Decentralized DMs via Nostr relays (NIP-04).
    \n ${accountCountLabel}\n\n ${hasMultipleAccounts\n ? html`\n
    \n ${nostrAccounts.map((account) => renderAccountCard(account))}\n
    \n `\n : html`\n
    \n
    \n Configured\n ${summaryConfigured ? \"Yes\" : \"No\"}\n
    \n
    \n Running\n ${summaryRunning ? \"Yes\" : \"No\"}\n
    \n
    \n Public Key\n ${truncatePubkey(summaryPublicKey)}\n
    \n
    \n Last start\n ${summaryLastStartAt ? formatAgo(summaryLastStartAt) : \"n/a\"}\n
    \n
    \n `}\n\n ${summaryLastError\n ? html`
    ${summaryLastError}
    `\n : nothing}\n\n ${renderProfileSection()}\n\n ${renderChannelConfigSection({ channelId: \"nostr\", props })}\n\n
    \n \n
    \n
    \n `;\n}\n","import { html, nothing } from \"lit\";\n\nimport { formatAgo } from \"../format\";\nimport type { SignalStatus } from \"../types\";\nimport type { ChannelsProps } from \"./channels.types\";\nimport { renderChannelConfigSection } from \"./channels.config\";\n\nexport function renderSignalCard(params: {\n props: ChannelsProps;\n signal?: SignalStatus | null;\n accountCountLabel: unknown;\n}) {\n const { props, signal, accountCountLabel } = params;\n\n return html`\n
    \n
    Signal
    \n
    signal-cli status and channel configuration.
    \n ${accountCountLabel}\n\n
    \n
    \n Configured\n ${signal?.configured ? \"Yes\" : \"No\"}\n
    \n
    \n Running\n ${signal?.running ? \"Yes\" : \"No\"}\n
    \n
    \n Base URL\n ${signal?.baseUrl ?? \"n/a\"}\n
    \n
    \n Last start\n ${signal?.lastStartAt ? formatAgo(signal.lastStartAt) : \"n/a\"}\n
    \n
    \n Last probe\n ${signal?.lastProbeAt ? formatAgo(signal.lastProbeAt) : \"n/a\"}\n
    \n
    \n\n ${signal?.lastError\n ? html`
    \n ${signal.lastError}\n
    `\n : nothing}\n\n ${signal?.probe\n ? html`
    \n Probe ${signal.probe.ok ? \"ok\" : \"failed\"} ·\n ${signal.probe.status ?? \"\"} ${signal.probe.error ?? \"\"}\n
    `\n : nothing}\n\n ${renderChannelConfigSection({ channelId: \"signal\", props })}\n\n
    \n \n
    \n
    \n `;\n}\n","import { html, nothing } from \"lit\";\n\nimport { formatAgo } from \"../format\";\nimport type { SlackStatus } from \"../types\";\nimport type { ChannelsProps } from \"./channels.types\";\nimport { renderChannelConfigSection } from \"./channels.config\";\n\nexport function renderSlackCard(params: {\n props: ChannelsProps;\n slack?: SlackStatus | null;\n accountCountLabel: unknown;\n}) {\n const { props, slack, accountCountLabel } = params;\n\n return html`\n
    \n
    Slack
    \n
    Socket mode status and channel configuration.
    \n ${accountCountLabel}\n\n
    \n
    \n Configured\n ${slack?.configured ? \"Yes\" : \"No\"}\n
    \n
    \n Running\n ${slack?.running ? \"Yes\" : \"No\"}\n
    \n
    \n Last start\n ${slack?.lastStartAt ? formatAgo(slack.lastStartAt) : \"n/a\"}\n
    \n
    \n Last probe\n ${slack?.lastProbeAt ? formatAgo(slack.lastProbeAt) : \"n/a\"}\n
    \n
    \n\n ${slack?.lastError\n ? html`
    \n ${slack.lastError}\n
    `\n : nothing}\n\n ${slack?.probe\n ? html`
    \n Probe ${slack.probe.ok ? \"ok\" : \"failed\"} ·\n ${slack.probe.status ?? \"\"} ${slack.probe.error ?? \"\"}\n
    `\n : nothing}\n\n ${renderChannelConfigSection({ channelId: \"slack\", props })}\n\n
    \n \n
    \n
    \n `;\n}\n","import { html, nothing } from \"lit\";\n\nimport { formatAgo } from \"../format\";\nimport type { ChannelAccountSnapshot, TelegramStatus } from \"../types\";\nimport type { ChannelsProps } from \"./channels.types\";\nimport { renderChannelConfigSection } from \"./channels.config\";\n\nexport function renderTelegramCard(params: {\n props: ChannelsProps;\n telegram?: TelegramStatus;\n telegramAccounts: ChannelAccountSnapshot[];\n accountCountLabel: unknown;\n}) {\n const { props, telegram, telegramAccounts, accountCountLabel } = params;\n const hasMultipleAccounts = telegramAccounts.length > 1;\n\n const renderAccountCard = (account: ChannelAccountSnapshot) => {\n const probe = account.probe as { bot?: { username?: string } } | undefined;\n const botUsername = probe?.bot?.username;\n const label = account.name || account.accountId;\n return html`\n
    \n
    \n
    \n ${botUsername ? `@${botUsername}` : label}\n
    \n
    ${account.accountId}
    \n
    \n
    \n
    \n Running\n ${account.running ? \"Yes\" : \"No\"}\n
    \n
    \n Configured\n ${account.configured ? \"Yes\" : \"No\"}\n
    \n
    \n Last inbound\n ${account.lastInboundAt ? formatAgo(account.lastInboundAt) : \"n/a\"}\n
    \n ${account.lastError\n ? html`\n
    \n ${account.lastError}\n
    \n `\n : nothing}\n
    \n
    \n `;\n };\n\n return html`\n
    \n
    Telegram
    \n
    Bot status and channel configuration.
    \n ${accountCountLabel}\n\n ${hasMultipleAccounts\n ? html`\n
    \n ${telegramAccounts.map((account) => renderAccountCard(account))}\n
    \n `\n : html`\n
    \n
    \n Configured\n ${telegram?.configured ? \"Yes\" : \"No\"}\n
    \n
    \n Running\n ${telegram?.running ? \"Yes\" : \"No\"}\n
    \n
    \n Mode\n ${telegram?.mode ?? \"n/a\"}\n
    \n
    \n Last start\n ${telegram?.lastStartAt ? formatAgo(telegram.lastStartAt) : \"n/a\"}\n
    \n
    \n Last probe\n ${telegram?.lastProbeAt ? formatAgo(telegram.lastProbeAt) : \"n/a\"}\n
    \n
    \n `}\n\n ${telegram?.lastError\n ? html`
    \n ${telegram.lastError}\n
    `\n : nothing}\n\n ${telegram?.probe\n ? html`
    \n Probe ${telegram.probe.ok ? \"ok\" : \"failed\"} ·\n ${telegram.probe.status ?? \"\"} ${telegram.probe.error ?? \"\"}\n
    `\n : nothing}\n\n ${renderChannelConfigSection({ channelId: \"telegram\", props })}\n\n
    \n \n
    \n
    \n `;\n}\n","import { html, nothing } from \"lit\";\n\nimport { formatAgo } from \"../format\";\nimport type { WhatsAppStatus } from \"../types\";\nimport type { ChannelsProps } from \"./channels.types\";\nimport { renderChannelConfigSection } from \"./channels.config\";\nimport { formatDuration } from \"./channels.shared\";\n\nexport function renderWhatsAppCard(params: {\n props: ChannelsProps;\n whatsapp?: WhatsAppStatus;\n accountCountLabel: unknown;\n}) {\n const { props, whatsapp, accountCountLabel } = params;\n\n return html`\n
    \n
    WhatsApp
    \n
    Link WhatsApp Web and monitor connection health.
    \n ${accountCountLabel}\n\n
    \n
    \n Configured\n ${whatsapp?.configured ? \"Yes\" : \"No\"}\n
    \n
    \n Linked\n ${whatsapp?.linked ? \"Yes\" : \"No\"}\n
    \n
    \n Running\n ${whatsapp?.running ? \"Yes\" : \"No\"}\n
    \n
    \n Connected\n ${whatsapp?.connected ? \"Yes\" : \"No\"}\n
    \n
    \n Last connect\n \n ${whatsapp?.lastConnectedAt\n ? formatAgo(whatsapp.lastConnectedAt)\n : \"n/a\"}\n \n
    \n
    \n Last message\n \n ${whatsapp?.lastMessageAt ? formatAgo(whatsapp.lastMessageAt) : \"n/a\"}\n \n
    \n
    \n Auth age\n \n ${whatsapp?.authAgeMs != null\n ? formatDuration(whatsapp.authAgeMs)\n : \"n/a\"}\n \n
    \n
    \n\n ${whatsapp?.lastError\n ? html`
    \n ${whatsapp.lastError}\n
    `\n : nothing}\n\n ${props.whatsappMessage\n ? html`
    \n ${props.whatsappMessage}\n
    `\n : nothing}\n\n ${props.whatsappQrDataUrl\n ? html`
    \n \"WhatsApp\n
    `\n : nothing}\n\n
    \n props.onWhatsAppStart(false)}\n >\n ${props.whatsappBusy ? \"Working…\" : \"Show QR\"}\n \n props.onWhatsAppStart(true)}\n >\n Relink\n \n props.onWhatsAppWait()}\n >\n Wait for scan\n \n props.onWhatsAppLogout()}\n >\n Logout\n \n \n
    \n\n ${renderChannelConfigSection({ channelId: \"whatsapp\", props })}\n
    \n `;\n}\n\n","import { html, nothing } from \"lit\";\n\nimport { formatAgo } from \"../format\";\nimport type {\n ChannelAccountSnapshot,\n ChannelUiMetaEntry,\n ChannelsStatusSnapshot,\n DiscordStatus,\n GoogleChatStatus,\n IMessageStatus,\n NostrProfile,\n NostrStatus,\n SignalStatus,\n SlackStatus,\n TelegramStatus,\n WhatsAppStatus,\n} from \"../types\";\nimport type {\n ChannelKey,\n ChannelsChannelData,\n ChannelsProps,\n} from \"./channels.types\";\nimport { channelEnabled, renderChannelAccountCount } from \"./channels.shared\";\nimport { renderChannelConfigSection } from \"./channels.config\";\nimport { renderDiscordCard } from \"./channels.discord\";\nimport { renderGoogleChatCard } from \"./channels.googlechat\";\nimport { renderIMessageCard } from \"./channels.imessage\";\nimport { renderNostrCard } from \"./channels.nostr\";\nimport { renderSignalCard } from \"./channels.signal\";\nimport { renderSlackCard } from \"./channels.slack\";\nimport { renderTelegramCard } from \"./channels.telegram\";\nimport { renderWhatsAppCard } from \"./channels.whatsapp\";\n\nexport function renderChannels(props: ChannelsProps) {\n const channels = props.snapshot?.channels as Record | null;\n const whatsapp = (channels?.whatsapp ?? undefined) as\n | WhatsAppStatus\n | undefined;\n const telegram = (channels?.telegram ?? undefined) as\n | TelegramStatus\n | undefined;\n const discord = (channels?.discord ?? null) as DiscordStatus | null;\n const googlechat = (channels?.googlechat ?? null) as GoogleChatStatus | null;\n const slack = (channels?.slack ?? null) as SlackStatus | null;\n const signal = (channels?.signal ?? null) as SignalStatus | null;\n const imessage = (channels?.imessage ?? null) as IMessageStatus | null;\n const nostr = (channels?.nostr ?? null) as NostrStatus | null;\n const channelOrder = resolveChannelOrder(props.snapshot);\n const orderedChannels = channelOrder\n .map((key, index) => ({\n key,\n enabled: channelEnabled(key, props),\n order: index,\n }))\n .sort((a, b) => {\n if (a.enabled !== b.enabled) return a.enabled ? -1 : 1;\n return a.order - b.order;\n });\n\n return html`\n
    \n ${orderedChannels.map((channel) =>\n renderChannel(channel.key, props, {\n whatsapp,\n telegram,\n discord,\n googlechat,\n slack,\n signal,\n imessage,\n nostr,\n channelAccounts: props.snapshot?.channelAccounts ?? null,\n }),\n )}\n
    \n\n
    \n
    \n
    \n
    Channel health
    \n
    Channel status snapshots from the gateway.
    \n
    \n
    ${props.lastSuccessAt ? formatAgo(props.lastSuccessAt) : \"n/a\"}
    \n
    \n ${props.lastError\n ? html`
    \n ${props.lastError}\n
    `\n : nothing}\n
    \n${props.snapshot ? JSON.stringify(props.snapshot, null, 2) : \"No snapshot yet.\"}\n      
    \n
    \n `;\n}\n\nfunction resolveChannelOrder(snapshot: ChannelsStatusSnapshot | null): ChannelKey[] {\n if (snapshot?.channelMeta?.length) {\n return snapshot.channelMeta.map((entry) => entry.id) as ChannelKey[];\n }\n if (snapshot?.channelOrder?.length) {\n return snapshot.channelOrder;\n }\n return [\n \"whatsapp\",\n \"telegram\",\n \"discord\",\n \"googlechat\",\n \"slack\",\n \"signal\",\n \"imessage\",\n \"nostr\",\n ];\n}\n\nfunction renderChannel(\n key: ChannelKey,\n props: ChannelsProps,\n data: ChannelsChannelData,\n) {\n const accountCountLabel = renderChannelAccountCount(\n key,\n data.channelAccounts,\n );\n switch (key) {\n case \"whatsapp\":\n return renderWhatsAppCard({\n props,\n whatsapp: data.whatsapp,\n accountCountLabel,\n });\n case \"telegram\":\n return renderTelegramCard({\n props,\n telegram: data.telegram,\n telegramAccounts: data.channelAccounts?.telegram ?? [],\n accountCountLabel,\n });\n case \"discord\":\n return renderDiscordCard({\n props,\n discord: data.discord,\n accountCountLabel,\n });\n case \"googlechat\":\n return renderGoogleChatCard({\n props,\n googlechat: data.googlechat,\n accountCountLabel,\n });\n case \"slack\":\n return renderSlackCard({\n props,\n slack: data.slack,\n accountCountLabel,\n });\n case \"signal\":\n return renderSignalCard({\n props,\n signal: data.signal,\n accountCountLabel,\n });\n case \"imessage\":\n return renderIMessageCard({\n props,\n imessage: data.imessage,\n accountCountLabel,\n });\n case \"nostr\": {\n const nostrAccounts = data.channelAccounts?.nostr ?? [];\n const primaryAccount = nostrAccounts[0];\n const accountId = primaryAccount?.accountId ?? \"default\";\n const profile =\n (primaryAccount as { profile?: NostrProfile | null } | undefined)?.profile ?? null;\n const showForm =\n props.nostrProfileAccountId === accountId ? props.nostrProfileFormState : null;\n const profileFormCallbacks = showForm\n ? {\n onFieldChange: props.onNostrProfileFieldChange,\n onSave: props.onNostrProfileSave,\n onImport: props.onNostrProfileImport,\n onCancel: props.onNostrProfileCancel,\n onToggleAdvanced: props.onNostrProfileToggleAdvanced,\n }\n : null;\n return renderNostrCard({\n props,\n nostr: data.nostr,\n nostrAccounts,\n accountCountLabel,\n profileFormState: showForm,\n profileFormCallbacks,\n onEditProfile: () => props.onNostrProfileEdit(accountId, profile),\n });\n }\n default:\n return renderGenericChannelCard(key, props, data.channelAccounts ?? {});\n }\n}\n\nfunction renderGenericChannelCard(\n key: ChannelKey,\n props: ChannelsProps,\n channelAccounts: Record,\n) {\n const label = resolveChannelLabel(props.snapshot, key);\n const status = props.snapshot?.channels?.[key] as Record | undefined;\n const configured = typeof status?.configured === \"boolean\" ? status.configured : undefined;\n const running = typeof status?.running === \"boolean\" ? status.running : undefined;\n const connected = typeof status?.connected === \"boolean\" ? status.connected : undefined;\n const lastError = typeof status?.lastError === \"string\" ? status.lastError : undefined;\n const accounts = channelAccounts[key] ?? [];\n const accountCountLabel = renderChannelAccountCount(key, channelAccounts);\n\n return html`\n
    \n
    ${label}
    \n
    Channel status and configuration.
    \n ${accountCountLabel}\n\n ${accounts.length > 0\n ? html`\n
    \n ${accounts.map((account) => renderGenericAccount(account))}\n
    \n `\n : html`\n
    \n
    \n Configured\n ${configured == null ? \"n/a\" : configured ? \"Yes\" : \"No\"}\n
    \n
    \n Running\n ${running == null ? \"n/a\" : running ? \"Yes\" : \"No\"}\n
    \n
    \n Connected\n ${connected == null ? \"n/a\" : connected ? \"Yes\" : \"No\"}\n
    \n
    \n `}\n\n ${lastError\n ? html`
    \n ${lastError}\n
    `\n : nothing}\n\n ${renderChannelConfigSection({ channelId: key, props })}\n
    \n `;\n}\n\nfunction resolveChannelMetaMap(\n snapshot: ChannelsStatusSnapshot | null,\n): Record {\n if (!snapshot?.channelMeta?.length) return {};\n return Object.fromEntries(snapshot.channelMeta.map((entry) => [entry.id, entry]));\n}\n\nfunction resolveChannelLabel(\n snapshot: ChannelsStatusSnapshot | null,\n key: string,\n): string {\n const meta = resolveChannelMetaMap(snapshot)[key];\n return meta?.label ?? snapshot?.channelLabels?.[key] ?? key;\n}\n\nconst RECENT_ACTIVITY_THRESHOLD_MS = 10 * 60 * 1000; // 10 minutes\n\nfunction hasRecentActivity(account: ChannelAccountSnapshot): boolean {\n if (!account.lastInboundAt) return false;\n return Date.now() - account.lastInboundAt < RECENT_ACTIVITY_THRESHOLD_MS;\n}\n\nfunction deriveRunningStatus(account: ChannelAccountSnapshot): \"Yes\" | \"No\" | \"Active\" {\n if (account.running) return \"Yes\";\n // If we have recent inbound activity, the channel is effectively running\n if (hasRecentActivity(account)) return \"Active\";\n return \"No\";\n}\n\nfunction deriveConnectedStatus(account: ChannelAccountSnapshot): \"Yes\" | \"No\" | \"Active\" | \"n/a\" {\n if (account.connected === true) return \"Yes\";\n if (account.connected === false) return \"No\";\n // If connected is null/undefined but we have recent activity, show as active\n if (hasRecentActivity(account)) return \"Active\";\n return \"n/a\";\n}\n\nfunction renderGenericAccount(account: ChannelAccountSnapshot) {\n const runningStatus = deriveRunningStatus(account);\n const connectedStatus = deriveConnectedStatus(account);\n\n return html`\n
    \n
    \n
    ${account.name || account.accountId}
    \n
    ${account.accountId}
    \n
    \n
    \n
    \n Running\n ${runningStatus}\n
    \n
    \n Configured\n ${account.configured ? \"Yes\" : \"No\"}\n
    \n
    \n Connected\n ${connectedStatus}\n
    \n
    \n Last inbound\n ${account.lastInboundAt ? formatAgo(account.lastInboundAt) : \"n/a\"}\n
    \n ${account.lastError\n ? html`\n
    \n ${account.lastError}\n
    \n `\n : nothing}\n
    \n
    \n `;\n}\n","import { formatAgo, formatDurationMs, formatMs } from \"./format\";\nimport type { CronJob, GatewaySessionRow, PresenceEntry } from \"./types\";\n\nexport function formatPresenceSummary(entry: PresenceEntry): string {\n const host = entry.host ?? \"unknown\";\n const ip = entry.ip ? `(${entry.ip})` : \"\";\n const mode = entry.mode ?? \"\";\n const version = entry.version ?? \"\";\n return `${host} ${ip} ${mode} ${version}`.trim();\n}\n\nexport function formatPresenceAge(entry: PresenceEntry): string {\n const ts = entry.ts ?? null;\n return ts ? formatAgo(ts) : \"n/a\";\n}\n\nexport function formatNextRun(ms?: number | null) {\n if (!ms) return \"n/a\";\n return `${formatMs(ms)} (${formatAgo(ms)})`;\n}\n\nexport function formatSessionTokens(row: GatewaySessionRow) {\n if (row.totalTokens == null) return \"n/a\";\n const total = row.totalTokens ?? 0;\n const ctx = row.contextTokens ?? 0;\n return ctx ? `${total} / ${ctx}` : String(total);\n}\n\nexport function formatEventPayload(payload: unknown): string {\n if (payload == null) return \"\";\n try {\n return JSON.stringify(payload, null, 2);\n } catch {\n return String(payload);\n }\n}\n\nexport function formatCronState(job: CronJob) {\n const state = job.state ?? {};\n const next = state.nextRunAtMs ? formatMs(state.nextRunAtMs) : \"n/a\";\n const last = state.lastRunAtMs ? formatMs(state.lastRunAtMs) : \"n/a\";\n const status = state.lastStatus ?? \"n/a\";\n return `${status} · next ${next} · last ${last}`;\n}\n\nexport function formatCronSchedule(job: CronJob) {\n const s = job.schedule;\n if (s.kind === \"at\") return `At ${formatMs(s.atMs)}`;\n if (s.kind === \"every\") return `Every ${formatDurationMs(s.everyMs)}`;\n return `Cron ${s.expr}${s.tz ? ` (${s.tz})` : \"\"}`;\n}\n\nexport function formatCronPayload(job: CronJob) {\n const p = job.payload;\n if (p.kind === \"systemEvent\") return `System: ${p.text}`;\n return `Agent: ${p.message}`;\n}\n\n","import { html, nothing } from \"lit\";\n\nimport { formatMs } from \"../format\";\nimport {\n formatCronPayload,\n formatCronSchedule,\n formatCronState,\n formatNextRun,\n} from \"../presenter\";\nimport type { ChannelUiMetaEntry, CronJob, CronRunLogEntry, CronStatus } from \"../types\";\nimport type { CronFormState } from \"../ui-types\";\n\nexport type CronProps = {\n loading: boolean;\n status: CronStatus | null;\n jobs: CronJob[];\n error: string | null;\n busy: boolean;\n form: CronFormState;\n channels: string[];\n channelLabels?: Record;\n channelMeta?: ChannelUiMetaEntry[];\n runsJobId: string | null;\n runs: CronRunLogEntry[];\n onFormChange: (patch: Partial) => void;\n onRefresh: () => void;\n onAdd: () => void;\n onToggle: (job: CronJob, enabled: boolean) => void;\n onRun: (job: CronJob) => void;\n onRemove: (job: CronJob) => void;\n onLoadRuns: (jobId: string) => void;\n};\n\nfunction buildChannelOptions(props: CronProps): string[] {\n const options = [\"last\", ...props.channels.filter(Boolean)];\n const current = props.form.channel?.trim();\n if (current && !options.includes(current)) {\n options.push(current);\n }\n const seen = new Set();\n return options.filter((value) => {\n if (seen.has(value)) return false;\n seen.add(value);\n return true;\n });\n}\n\nfunction resolveChannelLabel(props: CronProps, channel: string): string {\n if (channel === \"last\") return \"last\";\n const meta = props.channelMeta?.find((entry) => entry.id === channel);\n if (meta?.label) return meta.label;\n return props.channelLabels?.[channel] ?? channel;\n}\n\nexport function renderCron(props: CronProps) {\n const channelOptions = buildChannelOptions(props);\n return html`\n
    \n
    \n
    Scheduler
    \n
    Gateway-owned cron scheduler status.
    \n
    \n
    \n
    Enabled
    \n
    \n ${props.status\n ? props.status.enabled\n ? \"Yes\"\n : \"No\"\n : \"n/a\"}\n
    \n
    \n
    \n
    Jobs
    \n
    ${props.status?.jobs ?? \"n/a\"}
    \n
    \n
    \n
    Next wake
    \n
    ${formatNextRun(props.status?.nextWakeAtMs ?? null)}
    \n
    \n
    \n
    \n \n ${props.error ? html`${props.error}` : nothing}\n
    \n
    \n\n
    \n
    New Job
    \n
    Create a scheduled wakeup or agent run.
    \n
    \n \n \n \n \n \n
    \n ${renderScheduleFields(props)}\n
    \n \n \n \n
    \n \n\t ${props.form.payloadKind === \"agentTurn\"\n\t ? html`\n\t
    \n \n\t \n \n \n ${props.form.sessionTarget === \"isolated\"\n ? html`\n \n `\n : nothing}\n
    \n `\n : nothing}\n
    \n \n
    \n
    \n
    \n\n
    \n
    Jobs
    \n
    All scheduled jobs stored in the gateway.
    \n ${props.jobs.length === 0\n ? html`
    No jobs yet.
    `\n : html`\n
    \n ${props.jobs.map((job) => renderJob(job, props))}\n
    \n `}\n
    \n\n
    \n
    Run history
    \n
    Latest runs for ${props.runsJobId ?? \"(select a job)\"}.
    \n ${props.runsJobId == null\n ? html`\n
    \n Select a job to inspect run history.\n
    \n `\n : props.runs.length === 0\n ? html`
    No runs yet.
    `\n : html`\n
    \n ${props.runs.map((entry) => renderRun(entry))}\n
    \n `}\n
    \n `;\n}\n\nfunction renderScheduleFields(props: CronProps) {\n const form = props.form;\n if (form.scheduleKind === \"at\") {\n return html`\n \n `;\n }\n if (form.scheduleKind === \"every\") {\n return html`\n
    \n \n \n
    \n `;\n }\n return html`\n
    \n \n \n
    \n `;\n}\n\nfunction renderJob(job: CronJob, props: CronProps) {\n const isSelected = props.runsJobId === job.id;\n const itemClass = `list-item list-item-clickable${isSelected ? \" list-item-selected\" : \"\"}`;\n return html`\n
    props.onLoadRuns(job.id)}>\n
    \n
    ${job.name}
    \n
    ${formatCronSchedule(job)}
    \n
    ${formatCronPayload(job)}
    \n ${job.agentId ? html`
    Agent: ${job.agentId}
    ` : nothing}\n
    \n ${job.enabled ? \"enabled\" : \"disabled\"}\n ${job.sessionTarget}\n ${job.wakeMode}\n
    \n
    \n
    \n
    ${formatCronState(job)}
    \n
    \n {\n event.stopPropagation();\n props.onToggle(job, !job.enabled);\n }}\n >\n ${job.enabled ? \"Disable\" : \"Enable\"}\n \n {\n event.stopPropagation();\n props.onRun(job);\n }}\n >\n Run\n \n {\n event.stopPropagation();\n props.onLoadRuns(job.id);\n }}\n >\n Runs\n \n {\n event.stopPropagation();\n props.onRemove(job);\n }}\n >\n Remove\n \n
    \n
    \n
    \n `;\n}\n\nfunction renderRun(entry: CronRunLogEntry) {\n return html`\n
    \n
    \n
    ${entry.status}
    \n
    ${entry.summary ?? \"\"}
    \n
    \n
    \n
    ${formatMs(entry.ts)}
    \n
    ${entry.durationMs ?? 0}ms
    \n ${entry.error ? html`
    ${entry.error}
    ` : nothing}\n
    \n
    \n `;\n}\n","import { html, nothing } from \"lit\";\n\nimport { formatEventPayload } from \"../presenter\";\nimport type { EventLogEntry } from \"../app-events\";\n\nexport type DebugProps = {\n loading: boolean;\n status: Record | null;\n health: Record | null;\n models: unknown[];\n heartbeat: unknown;\n eventLog: EventLogEntry[];\n callMethod: string;\n callParams: string;\n callResult: string | null;\n callError: string | null;\n onCallMethodChange: (next: string) => void;\n onCallParamsChange: (next: string) => void;\n onRefresh: () => void;\n onCall: () => void;\n};\n\nexport function renderDebug(props: DebugProps) {\n return html`\n
    \n
    \n
    \n
    \n
    Snapshots
    \n
    Status, health, and heartbeat data.
    \n
    \n \n
    \n
    \n
    \n
    Status
    \n
    ${JSON.stringify(props.status ?? {}, null, 2)}
    \n
    \n
    \n
    Health
    \n
    ${JSON.stringify(props.health ?? {}, null, 2)}
    \n
    \n
    \n
    Last heartbeat
    \n
    ${JSON.stringify(props.heartbeat ?? {}, null, 2)}
    \n
    \n
    \n
    \n\n
    \n
    Manual RPC
    \n
    Send a raw gateway method with JSON params.
    \n
    \n \n \n
    \n
    \n \n
    \n ${props.callError\n ? html`
    \n ${props.callError}\n
    `\n : nothing}\n ${props.callResult\n ? html`
    ${props.callResult}
    `\n : nothing}\n
    \n
    \n\n
    \n
    Models
    \n
    Catalog from models.list.
    \n
    ${JSON.stringify(\n        props.models ?? [],\n        null,\n        2,\n      )}
    \n
    \n\n
    \n
    Event Log
    \n
    Latest gateway events.
    \n ${props.eventLog.length === 0\n ? html`
    No events yet.
    `\n : html`\n
    \n ${props.eventLog.map(\n (evt) => html`\n
    \n
    \n
    ${evt.event}
    \n
    ${new Date(evt.ts).toLocaleTimeString()}
    \n
    \n
    \n
    ${formatEventPayload(evt.payload)}
    \n
    \n
    \n `,\n )}\n
    \n `}\n
    \n `;\n}\n","import { html, nothing } from \"lit\";\n\nimport { formatPresenceAge, formatPresenceSummary } from \"../presenter\";\nimport type { PresenceEntry } from \"../types\";\n\nexport type InstancesProps = {\n loading: boolean;\n entries: PresenceEntry[];\n lastError: string | null;\n statusMessage: string | null;\n onRefresh: () => void;\n};\n\nexport function renderInstances(props: InstancesProps) {\n return html`\n
    \n
    \n
    \n
    Connected Instances
    \n
    Presence beacons from the gateway and clients.
    \n
    \n \n
    \n ${props.lastError\n ? html`
    \n ${props.lastError}\n
    `\n : nothing}\n ${props.statusMessage\n ? html`
    \n ${props.statusMessage}\n
    `\n : nothing}\n
    \n ${props.entries.length === 0\n ? html`
    No instances reported yet.
    `\n : props.entries.map((entry) => renderEntry(entry))}\n
    \n
    \n `;\n}\n\nfunction renderEntry(entry: PresenceEntry) {\n const lastInput =\n entry.lastInputSeconds != null\n ? `${entry.lastInputSeconds}s ago`\n : \"n/a\";\n const mode = entry.mode ?? \"unknown\";\n const roles = Array.isArray(entry.roles) ? entry.roles.filter(Boolean) : [];\n const scopes = Array.isArray(entry.scopes) ? entry.scopes.filter(Boolean) : [];\n const scopesLabel =\n scopes.length > 0\n ? scopes.length > 3\n ? `${scopes.length} scopes`\n : `scopes: ${scopes.join(\", \")}`\n : null;\n return html`\n
    \n
    \n
    ${entry.host ?? \"unknown host\"}
    \n
    ${formatPresenceSummary(entry)}
    \n
    \n ${mode}\n ${roles.map((role) => html`${role}`)}\n ${scopesLabel ? html`${scopesLabel}` : nothing}\n ${entry.platform ? html`${entry.platform}` : nothing}\n ${entry.deviceFamily\n ? html`${entry.deviceFamily}`\n : nothing}\n ${entry.modelIdentifier\n ? html`${entry.modelIdentifier}`\n : nothing}\n ${entry.version ? html`${entry.version}` : nothing}\n
    \n
    \n
    \n
    ${formatPresenceAge(entry)}
    \n
    Last input ${lastInput}
    \n
    Reason ${entry.reason ?? \"\"}
    \n
    \n
    \n `;\n}\n","import { html, nothing } from \"lit\";\n\nimport type { LogEntry, LogLevel } from \"../types\";\n\nconst LEVELS: LogLevel[] = [\"trace\", \"debug\", \"info\", \"warn\", \"error\", \"fatal\"];\n\nexport type LogsProps = {\n loading: boolean;\n error: string | null;\n file: string | null;\n entries: LogEntry[];\n filterText: string;\n levelFilters: Record;\n autoFollow: boolean;\n truncated: boolean;\n onFilterTextChange: (next: string) => void;\n onLevelToggle: (level: LogLevel, enabled: boolean) => void;\n onToggleAutoFollow: (next: boolean) => void;\n onRefresh: () => void;\n onExport: (lines: string[], label: string) => void;\n onScroll: (event: Event) => void;\n};\n\nfunction formatTime(value?: string | null) {\n if (!value) return \"\";\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return value;\n return date.toLocaleTimeString();\n}\n\nfunction matchesFilter(entry: LogEntry, needle: string) {\n if (!needle) return true;\n const haystack = [entry.message, entry.subsystem, entry.raw]\n .filter(Boolean)\n .join(\" \")\n .toLowerCase();\n return haystack.includes(needle);\n}\n\nexport function renderLogs(props: LogsProps) {\n const needle = props.filterText.trim().toLowerCase();\n const levelFiltered = LEVELS.some((level) => !props.levelFilters[level]);\n const filtered = props.entries.filter((entry) => {\n if (entry.level && !props.levelFilters[entry.level]) return false;\n return matchesFilter(entry, needle);\n });\n const exportLabel = needle || levelFiltered ? \"filtered\" : \"visible\";\n\n return html`\n
    \n
    \n
    \n
    Logs
    \n
    Gateway file logs (JSONL).
    \n
    \n
    \n \n props.onExport(filtered.map((entry) => entry.raw), exportLabel)}\n >\n Export ${exportLabel}\n \n
    \n
    \n\n
    \n \n \n
    \n\n
    \n ${LEVELS.map(\n (level) => html`\n \n `,\n )}\n
    \n\n ${props.file\n ? html`
    File: ${props.file}
    `\n : nothing}\n ${props.truncated\n ? html`
    \n Log output truncated; showing latest chunk.\n
    `\n : nothing}\n ${props.error\n ? html`
    ${props.error}
    `\n : nothing}\n\n
    \n ${filtered.length === 0\n ? html`
    No log entries.
    `\n : filtered.map(\n (entry) => html`\n
    \n
    ${formatTime(entry.time)}
    \n
    ${entry.level ?? \"\"}
    \n
    ${entry.subsystem ?? \"\"}
    \n
    ${entry.message ?? entry.raw}
    \n
    \n `,\n )}\n
    \n
    \n `;\n}\n","import { html, nothing } from \"lit\";\n\nimport { clampText, formatAgo, formatList } from \"../format\";\nimport type {\n ExecApprovalsAllowlistEntry,\n ExecApprovalsFile,\n ExecApprovalsSnapshot,\n} from \"../controllers/exec-approvals\";\nimport type {\n DevicePairingList,\n DeviceTokenSummary,\n PairedDevice,\n PendingDevice,\n} from \"../controllers/devices\";\n\nexport type NodesProps = {\n loading: boolean;\n nodes: Array>;\n devicesLoading: boolean;\n devicesError: string | null;\n devicesList: DevicePairingList | null;\n configForm: Record | null;\n configLoading: boolean;\n configSaving: boolean;\n configDirty: boolean;\n configFormMode: \"form\" | \"raw\";\n execApprovalsLoading: boolean;\n execApprovalsSaving: boolean;\n execApprovalsDirty: boolean;\n execApprovalsSnapshot: ExecApprovalsSnapshot | null;\n execApprovalsForm: ExecApprovalsFile | null;\n execApprovalsSelectedAgent: string | null;\n execApprovalsTarget: \"gateway\" | \"node\";\n execApprovalsTargetNodeId: string | null;\n onRefresh: () => void;\n onDevicesRefresh: () => void;\n onDeviceApprove: (requestId: string) => void;\n onDeviceReject: (requestId: string) => void;\n onDeviceRotate: (deviceId: string, role: string, scopes?: string[]) => void;\n onDeviceRevoke: (deviceId: string, role: string) => void;\n onLoadConfig: () => void;\n onLoadExecApprovals: () => void;\n onBindDefault: (nodeId: string | null) => void;\n onBindAgent: (agentIndex: number, nodeId: string | null) => void;\n onSaveBindings: () => void;\n onExecApprovalsTargetChange: (kind: \"gateway\" | \"node\", nodeId: string | null) => void;\n onExecApprovalsSelectAgent: (agentId: string) => void;\n onExecApprovalsPatch: (path: Array, value: unknown) => void;\n onExecApprovalsRemove: (path: Array) => void;\n onSaveExecApprovals: () => void;\n};\n\nexport function renderNodes(props: NodesProps) {\n const bindingState = resolveBindingsState(props);\n const approvalsState = resolveExecApprovalsState(props);\n return html`\n ${renderExecApprovals(approvalsState)}\n ${renderBindings(bindingState)}\n ${renderDevices(props)}\n
    \n
    \n
    \n
    Nodes
    \n
    Paired devices and live links.
    \n
    \n \n
    \n
    \n ${props.nodes.length === 0\n ? html`
    No nodes found.
    `\n : props.nodes.map((n) => renderNode(n))}\n
    \n
    \n `;\n}\n\nfunction renderDevices(props: NodesProps) {\n const list = props.devicesList ?? { pending: [], paired: [] };\n const pending = Array.isArray(list.pending) ? list.pending : [];\n const paired = Array.isArray(list.paired) ? list.paired : [];\n return html`\n
    \n
    \n
    \n
    Devices
    \n
    Pairing requests + role tokens.
    \n
    \n \n
    \n ${props.devicesError\n ? html`
    ${props.devicesError}
    `\n : nothing}\n
    \n ${pending.length > 0\n ? html`\n
    Pending
    \n ${pending.map((req) => renderPendingDevice(req, props))}\n `\n : nothing}\n ${paired.length > 0\n ? html`\n
    Paired
    \n ${paired.map((device) => renderPairedDevice(device, props))}\n `\n : nothing}\n ${pending.length === 0 && paired.length === 0\n ? html`
    No paired devices.
    `\n : nothing}\n
    \n
    \n `;\n}\n\nfunction renderPendingDevice(req: PendingDevice, props: NodesProps) {\n const name = req.displayName?.trim() || req.deviceId;\n const age = typeof req.ts === \"number\" ? formatAgo(req.ts) : \"n/a\";\n const role = req.role?.trim() ? `role: ${req.role}` : \"role: -\";\n const repair = req.isRepair ? \" · repair\" : \"\";\n const ip = req.remoteIp ? ` · ${req.remoteIp}` : \"\";\n return html`\n
    \n
    \n
    ${name}
    \n
    ${req.deviceId}${ip}
    \n
    \n ${role} · requested ${age}${repair}\n
    \n
    \n
    \n
    \n \n \n
    \n
    \n
    \n `;\n}\n\nfunction renderPairedDevice(device: PairedDevice, props: NodesProps) {\n const name = device.displayName?.trim() || device.deviceId;\n const ip = device.remoteIp ? ` · ${device.remoteIp}` : \"\";\n const roles = `roles: ${formatList(device.roles)}`;\n const scopes = `scopes: ${formatList(device.scopes)}`;\n const tokens = Array.isArray(device.tokens) ? device.tokens : [];\n return html`\n
    \n
    \n
    ${name}
    \n
    ${device.deviceId}${ip}
    \n
    ${roles} · ${scopes}
    \n ${tokens.length === 0\n ? html`
    Tokens: none
    `\n : html`\n
    Tokens
    \n
    \n ${tokens.map((token) => renderTokenRow(device.deviceId, token, props))}\n
    \n `}\n
    \n
    \n `;\n}\n\nfunction renderTokenRow(deviceId: string, token: DeviceTokenSummary, props: NodesProps) {\n const status = token.revokedAtMs ? \"revoked\" : \"active\";\n const scopes = `scopes: ${formatList(token.scopes)}`;\n const when = formatAgo(token.rotatedAtMs ?? token.createdAtMs ?? token.lastUsedAtMs ?? null);\n return html`\n
    \n
    ${token.role} · ${status} · ${scopes} · ${when}
    \n
    \n props.onDeviceRotate(deviceId, token.role, token.scopes)}\n >\n Rotate\n \n ${token.revokedAtMs\n ? nothing\n : html`\n props.onDeviceRevoke(deviceId, token.role)}\n >\n Revoke\n \n `}\n
    \n
    \n `;\n}\n\ntype BindingAgent = {\n id: string;\n name?: string;\n index: number;\n isDefault: boolean;\n binding?: string | null;\n};\n\ntype BindingNode = {\n id: string;\n label: string;\n};\n\ntype BindingState = {\n ready: boolean;\n disabled: boolean;\n configDirty: boolean;\n configLoading: boolean;\n configSaving: boolean;\n defaultBinding?: string | null;\n agents: BindingAgent[];\n nodes: BindingNode[];\n onBindDefault: (nodeId: string | null) => void;\n onBindAgent: (agentIndex: number, nodeId: string | null) => void;\n onSave: () => void;\n onLoadConfig: () => void;\n formMode: \"form\" | \"raw\";\n};\n\ntype ExecSecurity = \"deny\" | \"allowlist\" | \"full\";\ntype ExecAsk = \"off\" | \"on-miss\" | \"always\";\n\ntype ExecApprovalsResolvedDefaults = {\n security: ExecSecurity;\n ask: ExecAsk;\n askFallback: ExecSecurity;\n autoAllowSkills: boolean;\n};\n\ntype ExecApprovalsAgentOption = {\n id: string;\n name?: string;\n isDefault?: boolean;\n};\n\ntype ExecApprovalsTargetNode = {\n id: string;\n label: string;\n};\n\ntype ExecApprovalsState = {\n ready: boolean;\n disabled: boolean;\n dirty: boolean;\n loading: boolean;\n saving: boolean;\n form: ExecApprovalsFile | null;\n defaults: ExecApprovalsResolvedDefaults;\n selectedScope: string;\n selectedAgent: Record | null;\n agents: ExecApprovalsAgentOption[];\n allowlist: ExecApprovalsAllowlistEntry[];\n target: \"gateway\" | \"node\";\n targetNodeId: string | null;\n targetNodes: ExecApprovalsTargetNode[];\n onSelectScope: (agentId: string) => void;\n onSelectTarget: (kind: \"gateway\" | \"node\", nodeId: string | null) => void;\n onPatch: (path: Array, value: unknown) => void;\n onRemove: (path: Array) => void;\n onLoad: () => void;\n onSave: () => void;\n};\n\nconst EXEC_APPROVALS_DEFAULT_SCOPE = \"__defaults__\";\n\nconst SECURITY_OPTIONS: Array<{ value: ExecSecurity; label: string }> = [\n { value: \"deny\", label: \"Deny\" },\n { value: \"allowlist\", label: \"Allowlist\" },\n { value: \"full\", label: \"Full\" },\n];\n\nconst ASK_OPTIONS: Array<{ value: ExecAsk; label: string }> = [\n { value: \"off\", label: \"Off\" },\n { value: \"on-miss\", label: \"On miss\" },\n { value: \"always\", label: \"Always\" },\n];\n\nfunction resolveBindingsState(props: NodesProps): BindingState {\n const config = props.configForm;\n const nodes = resolveExecNodes(props.nodes);\n const { defaultBinding, agents } = resolveAgentBindings(config);\n const ready = Boolean(config);\n const disabled = props.configSaving || props.configFormMode === \"raw\";\n return {\n ready,\n disabled,\n configDirty: props.configDirty,\n configLoading: props.configLoading,\n configSaving: props.configSaving,\n defaultBinding,\n agents,\n nodes,\n onBindDefault: props.onBindDefault,\n onBindAgent: props.onBindAgent,\n onSave: props.onSaveBindings,\n onLoadConfig: props.onLoadConfig,\n formMode: props.configFormMode,\n };\n}\n\nfunction normalizeSecurity(value?: string): ExecSecurity {\n if (value === \"allowlist\" || value === \"full\" || value === \"deny\") return value;\n return \"deny\";\n}\n\nfunction normalizeAsk(value?: string): ExecAsk {\n if (value === \"always\" || value === \"off\" || value === \"on-miss\") return value;\n return \"on-miss\";\n}\n\nfunction resolveExecApprovalsDefaults(\n form: ExecApprovalsFile | null,\n): ExecApprovalsResolvedDefaults {\n const defaults = form?.defaults ?? {};\n return {\n security: normalizeSecurity(defaults.security),\n ask: normalizeAsk(defaults.ask),\n askFallback: normalizeSecurity(defaults.askFallback ?? \"deny\"),\n autoAllowSkills: Boolean(defaults.autoAllowSkills ?? false),\n };\n}\n\nfunction resolveConfigAgents(config: Record | null): ExecApprovalsAgentOption[] {\n const agentsNode = (config?.agents ?? {}) as Record;\n const list = Array.isArray(agentsNode.list) ? agentsNode.list : [];\n const agents: ExecApprovalsAgentOption[] = [];\n list.forEach((entry) => {\n if (!entry || typeof entry !== \"object\") return;\n const record = entry as Record;\n const id = typeof record.id === \"string\" ? record.id.trim() : \"\";\n if (!id) return;\n const name = typeof record.name === \"string\" ? record.name.trim() : undefined;\n const isDefault = record.default === true;\n agents.push({ id, name: name || undefined, isDefault });\n });\n return agents;\n}\n\nfunction resolveExecApprovalsAgents(\n config: Record | null,\n form: ExecApprovalsFile | null,\n): ExecApprovalsAgentOption[] {\n const configAgents = resolveConfigAgents(config);\n const approvalsAgents = Object.keys(form?.agents ?? {});\n const merged = new Map();\n configAgents.forEach((agent) => merged.set(agent.id, agent));\n approvalsAgents.forEach((id) => {\n if (merged.has(id)) return;\n merged.set(id, { id });\n });\n const agents = Array.from(merged.values());\n if (agents.length === 0) {\n agents.push({ id: \"main\", isDefault: true });\n }\n agents.sort((a, b) => {\n if (a.isDefault && !b.isDefault) return -1;\n if (!a.isDefault && b.isDefault) return 1;\n const aLabel = a.name?.trim() ? a.name : a.id;\n const bLabel = b.name?.trim() ? b.name : b.id;\n return aLabel.localeCompare(bLabel);\n });\n return agents;\n}\n\nfunction resolveExecApprovalsScope(\n selected: string | null,\n agents: ExecApprovalsAgentOption[],\n): string {\n if (selected === EXEC_APPROVALS_DEFAULT_SCOPE) return EXEC_APPROVALS_DEFAULT_SCOPE;\n if (selected && agents.some((agent) => agent.id === selected)) return selected;\n return EXEC_APPROVALS_DEFAULT_SCOPE;\n}\n\nfunction resolveExecApprovalsState(props: NodesProps): ExecApprovalsState {\n const form = props.execApprovalsForm ?? props.execApprovalsSnapshot?.file ?? null;\n const ready = Boolean(form);\n const defaults = resolveExecApprovalsDefaults(form);\n const agents = resolveExecApprovalsAgents(props.configForm, form);\n const targetNodes = resolveExecApprovalsNodes(props.nodes);\n const target = props.execApprovalsTarget;\n let targetNodeId =\n target === \"node\" && props.execApprovalsTargetNodeId\n ? props.execApprovalsTargetNodeId\n : null;\n if (target === \"node\" && targetNodeId && !targetNodes.some((node) => node.id === targetNodeId)) {\n targetNodeId = null;\n }\n const selectedScope = resolveExecApprovalsScope(props.execApprovalsSelectedAgent, agents);\n const selectedAgent =\n selectedScope !== EXEC_APPROVALS_DEFAULT_SCOPE\n ? ((form?.agents ?? {})[selectedScope] as Record | undefined) ??\n null\n : null;\n const allowlist = Array.isArray((selectedAgent as { allowlist?: unknown })?.allowlist)\n ? ((selectedAgent as { allowlist?: ExecApprovalsAllowlistEntry[] }).allowlist ??\n [])\n : [];\n return {\n ready,\n disabled: props.execApprovalsSaving || props.execApprovalsLoading,\n dirty: props.execApprovalsDirty,\n loading: props.execApprovalsLoading,\n saving: props.execApprovalsSaving,\n form,\n defaults,\n selectedScope,\n selectedAgent,\n agents,\n allowlist,\n target,\n targetNodeId,\n targetNodes,\n onSelectScope: props.onExecApprovalsSelectAgent,\n onSelectTarget: props.onExecApprovalsTargetChange,\n onPatch: props.onExecApprovalsPatch,\n onRemove: props.onExecApprovalsRemove,\n onLoad: props.onLoadExecApprovals,\n onSave: props.onSaveExecApprovals,\n };\n}\n\nfunction renderBindings(state: BindingState) {\n const supportsBinding = state.nodes.length > 0;\n const defaultValue = state.defaultBinding ?? \"\";\n return html`\n
    \n
    \n
    \n
    Exec node binding
    \n
    \n Pin agents to a specific node when using exec host=node.\n
    \n
    \n \n ${state.configSaving ? \"Saving…\" : \"Save\"}\n \n
    \n\n ${state.formMode === \"raw\"\n ? html`
    \n Switch the Config tab to Form mode to edit bindings here.\n
    `\n : nothing}\n\n ${!state.ready\n ? html`
    \n
    Load config to edit bindings.
    \n \n
    `\n : html`\n
    \n
    \n
    \n
    Default binding
    \n
    Used when agents do not override a node binding.
    \n
    \n
    \n \n ${!supportsBinding\n ? html`
    No nodes with system.run available.
    `\n : nothing}\n
    \n
    \n\n ${state.agents.length === 0\n ? html`
    No agents found.
    `\n : state.agents.map((agent) =>\n renderAgentBinding(agent, state),\n )}\n
    \n `}\n
    \n `;\n}\n\nfunction renderExecApprovals(state: ExecApprovalsState) {\n const ready = state.ready;\n const targetReady = state.target !== \"node\" || Boolean(state.targetNodeId);\n return html`\n
    \n
    \n
    \n
    Exec approvals
    \n
    \n Allowlist and approval policy for exec host=gateway/node.\n
    \n
    \n \n ${state.saving ? \"Saving…\" : \"Save\"}\n \n
    \n\n ${renderExecApprovalsTarget(state)}\n\n ${!ready\n ? html`
    \n
    Load exec approvals to edit allowlists.
    \n \n
    `\n : html`\n ${renderExecApprovalsTabs(state)}\n ${renderExecApprovalsPolicy(state)}\n ${state.selectedScope === EXEC_APPROVALS_DEFAULT_SCOPE\n ? nothing\n : renderExecApprovalsAllowlist(state)}\n `}\n
    \n `;\n}\n\nfunction renderExecApprovalsTarget(state: ExecApprovalsState) {\n const hasNodes = state.targetNodes.length > 0;\n const nodeValue = state.targetNodeId ?? \"\";\n return html`\n
    \n
    \n
    \n
    Target
    \n
    \n Gateway edits local approvals; node edits the selected node.\n
    \n
    \n
    \n \n ${state.target === \"node\"\n ? html`\n \n `\n : nothing}\n
    \n
    \n ${state.target === \"node\" && !hasNodes\n ? html`
    No nodes advertise exec approvals yet.
    `\n : nothing}\n
    \n `;\n}\n\nfunction renderExecApprovalsTabs(state: ExecApprovalsState) {\n return html`\n
    \n Scope\n
    \n state.onSelectScope(EXEC_APPROVALS_DEFAULT_SCOPE)}\n >\n Defaults\n \n ${state.agents.map((agent) => {\n const label = agent.name?.trim() ? `${agent.name} (${agent.id})` : agent.id;\n return html`\n state.onSelectScope(agent.id)}\n >\n ${label}\n \n `;\n })}\n
    \n
    \n `;\n}\n\nfunction renderExecApprovalsPolicy(state: ExecApprovalsState) {\n const isDefaults = state.selectedScope === EXEC_APPROVALS_DEFAULT_SCOPE;\n const defaults = state.defaults;\n const agent = state.selectedAgent ?? {};\n const basePath = isDefaults ? [\"defaults\"] : [\"agents\", state.selectedScope];\n const agentSecurity = typeof agent.security === \"string\" ? agent.security : undefined;\n const agentAsk = typeof agent.ask === \"string\" ? agent.ask : undefined;\n const agentAskFallback =\n typeof agent.askFallback === \"string\" ? agent.askFallback : undefined;\n const securityValue = isDefaults ? defaults.security : agentSecurity ?? \"__default__\";\n const askValue = isDefaults ? defaults.ask : agentAsk ?? \"__default__\";\n const askFallbackValue = isDefaults\n ? defaults.askFallback\n : agentAskFallback ?? \"__default__\";\n const autoOverride =\n typeof agent.autoAllowSkills === \"boolean\" ? agent.autoAllowSkills : undefined;\n const autoEffective = autoOverride ?? defaults.autoAllowSkills;\n const autoIsDefault = autoOverride == null;\n\n return html`\n
    \n
    \n
    \n
    Security
    \n
    \n ${isDefaults\n ? \"Default security mode.\"\n : `Default: ${defaults.security}.`}\n
    \n
    \n
    \n \n
    \n
    \n\n
    \n
    \n
    Ask
    \n
    \n ${isDefaults ? \"Default prompt policy.\" : `Default: ${defaults.ask}.`}\n
    \n
    \n
    \n \n
    \n
    \n\n
    \n
    \n
    Ask fallback
    \n
    \n ${isDefaults\n ? \"Applied when the UI prompt is unavailable.\"\n : `Default: ${defaults.askFallback}.`}\n
    \n
    \n
    \n \n
    \n
    \n\n
    \n
    \n
    Auto-allow skill CLIs
    \n
    \n ${isDefaults\n ? \"Allow skill executables listed by the Gateway.\"\n : autoIsDefault\n ? `Using default (${defaults.autoAllowSkills ? \"on\" : \"off\"}).`\n : `Override (${autoEffective ? \"on\" : \"off\"}).`}\n
    \n
    \n
    \n \n ${!isDefaults && !autoIsDefault\n ? html` state.onRemove([...basePath, \"autoAllowSkills\"])}\n >\n Use default\n `\n : nothing}\n
    \n
    \n
    \n `;\n}\n\nfunction renderExecApprovalsAllowlist(state: ExecApprovalsState) {\n const allowlistPath = [\"agents\", state.selectedScope, \"allowlist\"];\n const entries = state.allowlist;\n return html`\n
    \n
    \n
    Allowlist
    \n
    Case-insensitive glob patterns.
    \n
    \n {\n const next = [...entries, { pattern: \"\" }];\n state.onPatch(allowlistPath, next);\n }}\n >\n Add pattern\n \n
    \n
    \n ${entries.length === 0\n ? html`
    No allowlist entries yet.
    `\n : entries.map((entry, index) =>\n renderAllowlistEntry(state, entry, index),\n )}\n
    \n `;\n}\n\nfunction renderAllowlistEntry(\n state: ExecApprovalsState,\n entry: ExecApprovalsAllowlistEntry,\n index: number,\n) {\n const lastUsed = entry.lastUsedAt ? formatAgo(entry.lastUsedAt) : \"never\";\n const lastCommand = entry.lastUsedCommand\n ? clampText(entry.lastUsedCommand, 120)\n : null;\n const lastPath = entry.lastResolvedPath\n ? clampText(entry.lastResolvedPath, 120)\n : null;\n return html`\n
    \n
    \n
    ${entry.pattern?.trim() ? entry.pattern : \"New pattern\"}
    \n
    Last used: ${lastUsed}
    \n ${lastCommand ? html`
    ${lastCommand}
    ` : nothing}\n ${lastPath ? html`
    ${lastPath}
    ` : nothing}\n
    \n
    \n \n {\n if (state.allowlist.length <= 1) {\n state.onRemove([\"agents\", state.selectedScope, \"allowlist\"]);\n return;\n }\n state.onRemove([\"agents\", state.selectedScope, \"allowlist\", index]);\n }}\n >\n Remove\n \n
    \n
    \n `;\n}\n\nfunction renderAgentBinding(agent: BindingAgent, state: BindingState) {\n const bindingValue = agent.binding ?? \"__default__\";\n const label = agent.name?.trim() ? `${agent.name} (${agent.id})` : agent.id;\n const supportsBinding = state.nodes.length > 0;\n return html`\n
    \n
    \n
    ${label}
    \n
    \n ${agent.isDefault ? \"default agent\" : \"agent\"} ·\n ${bindingValue === \"__default__\"\n ? `uses default (${state.defaultBinding ?? \"any\"})`\n : `override: ${agent.binding}`}\n
    \n
    \n
    \n \n
    \n
    \n `;\n}\n\nfunction resolveExecNodes(nodes: Array>): BindingNode[] {\n const list: BindingNode[] = [];\n for (const node of nodes) {\n const commands = Array.isArray(node.commands) ? node.commands : [];\n const supports = commands.some((cmd) => String(cmd) === \"system.run\");\n if (!supports) continue;\n const nodeId = typeof node.nodeId === \"string\" ? node.nodeId.trim() : \"\";\n if (!nodeId) continue;\n const displayName =\n typeof node.displayName === \"string\" && node.displayName.trim()\n ? node.displayName.trim()\n : nodeId;\n list.push({ id: nodeId, label: displayName === nodeId ? nodeId : `${displayName} · ${nodeId}` });\n }\n list.sort((a, b) => a.label.localeCompare(b.label));\n return list;\n}\n\nfunction resolveExecApprovalsNodes(nodes: Array>): ExecApprovalsTargetNode[] {\n const list: ExecApprovalsTargetNode[] = [];\n for (const node of nodes) {\n const commands = Array.isArray(node.commands) ? node.commands : [];\n const supports = commands.some(\n (cmd) => String(cmd) === \"system.execApprovals.get\" || String(cmd) === \"system.execApprovals.set\",\n );\n if (!supports) continue;\n const nodeId = typeof node.nodeId === \"string\" ? node.nodeId.trim() : \"\";\n if (!nodeId) continue;\n const displayName =\n typeof node.displayName === \"string\" && node.displayName.trim()\n ? node.displayName.trim()\n : nodeId;\n list.push({ id: nodeId, label: displayName === nodeId ? nodeId : `${displayName} · ${nodeId}` });\n }\n list.sort((a, b) => a.label.localeCompare(b.label));\n return list;\n}\n\nfunction resolveAgentBindings(config: Record | null): {\n defaultBinding?: string | null;\n agents: BindingAgent[];\n} {\n const fallbackAgent: BindingAgent = {\n id: \"main\",\n name: undefined,\n index: 0,\n isDefault: true,\n binding: null,\n };\n if (!config || typeof config !== \"object\") {\n return { defaultBinding: null, agents: [fallbackAgent] };\n }\n const tools = (config.tools ?? {}) as Record;\n const exec = (tools.exec ?? {}) as Record;\n const defaultBinding =\n typeof exec.node === \"string\" && exec.node.trim() ? exec.node.trim() : null;\n\n const agentsNode = (config.agents ?? {}) as Record;\n const list = Array.isArray(agentsNode.list) ? agentsNode.list : [];\n if (list.length === 0) {\n return { defaultBinding, agents: [fallbackAgent] };\n }\n\n const agents: BindingAgent[] = [];\n list.forEach((entry, index) => {\n if (!entry || typeof entry !== \"object\") return;\n const record = entry as Record;\n const id = typeof record.id === \"string\" ? record.id.trim() : \"\";\n if (!id) return;\n const name = typeof record.name === \"string\" ? record.name.trim() : undefined;\n const isDefault = record.default === true;\n const toolsEntry = (record.tools ?? {}) as Record;\n const execEntry = (toolsEntry.exec ?? {}) as Record;\n const binding =\n typeof execEntry.node === \"string\" && execEntry.node.trim()\n ? execEntry.node.trim()\n : null;\n agents.push({\n id,\n name: name || undefined,\n index,\n isDefault,\n binding,\n });\n });\n\n if (agents.length === 0) {\n agents.push(fallbackAgent);\n }\n\n return { defaultBinding, agents };\n}\n\nfunction renderNode(node: Record) {\n const connected = Boolean(node.connected);\n const paired = Boolean(node.paired);\n const title =\n (typeof node.displayName === \"string\" && node.displayName.trim()) ||\n (typeof node.nodeId === \"string\" ? node.nodeId : \"unknown\");\n const caps = Array.isArray(node.caps) ? (node.caps as unknown[]) : [];\n const commands = Array.isArray(node.commands) ? (node.commands as unknown[]) : [];\n return html`\n
    \n
    \n
    ${title}
    \n
    \n ${typeof node.nodeId === \"string\" ? node.nodeId : \"\"}\n ${typeof node.remoteIp === \"string\" ? ` · ${node.remoteIp}` : \"\"}\n ${typeof node.version === \"string\" ? ` · ${node.version}` : \"\"}\n
    \n
    \n ${paired ? \"paired\" : \"unpaired\"}\n \n ${connected ? \"connected\" : \"offline\"}\n \n ${caps.slice(0, 12).map((c) => html`${String(c)}`)}\n ${commands\n .slice(0, 8)\n .map((c) => html`${String(c)}`)}\n
    \n
    \n
    \n `;\n}\n","import { html } from \"lit\";\n\nimport type { GatewayHelloOk } from \"../gateway\";\nimport { formatAgo, formatDurationMs } from \"../format\";\nimport { formatNextRun } from \"../presenter\";\nimport type { UiSettings } from \"../storage\";\n\nexport type OverviewProps = {\n connected: boolean;\n hello: GatewayHelloOk | null;\n settings: UiSettings;\n password: string;\n lastError: string | null;\n presenceCount: number;\n sessionsCount: number | null;\n cronEnabled: boolean | null;\n cronNext: number | null;\n lastChannelsRefresh: number | null;\n onSettingsChange: (next: UiSettings) => void;\n onPasswordChange: (next: string) => void;\n onSessionKeyChange: (next: string) => void;\n onConnect: () => void;\n onRefresh: () => void;\n};\n\nexport function renderOverview(props: OverviewProps) {\n const snapshot = props.hello?.snapshot as\n | { uptimeMs?: number; policy?: { tickIntervalMs?: number } }\n | undefined;\n const uptime = snapshot?.uptimeMs ? formatDurationMs(snapshot.uptimeMs) : \"n/a\";\n const tick = snapshot?.policy?.tickIntervalMs\n ? `${snapshot.policy.tickIntervalMs}ms`\n : \"n/a\";\n const authHint = (() => {\n if (props.connected || !props.lastError) return null;\n const lower = props.lastError.toLowerCase();\n const authFailed = lower.includes(\"unauthorized\") || lower.includes(\"connect failed\");\n if (!authFailed) return null;\n const hasToken = Boolean(props.settings.token.trim());\n const hasPassword = Boolean(props.password.trim());\n if (!hasToken && !hasPassword) {\n return html`\n
    \n This gateway requires auth. Add a token or password, then click Connect.\n
    \n clawdbot dashboard --no-open → tokenized URL
    \n clawdbot doctor --generate-gateway-token → set token\n
    \n
    \n Docs: Control UI auth\n
    \n
    \n `;\n }\n return html`\n
    \n Auth failed. Re-copy a tokenized URL with\n clawdbot dashboard --no-open, or update the token,\n then click Connect.\n
    \n Docs: Control UI auth\n
    \n
    \n `;\n })();\n const insecureContextHint = (() => {\n if (props.connected || !props.lastError) return null;\n const isSecureContext = typeof window !== \"undefined\" ? window.isSecureContext : true;\n if (isSecureContext !== false) return null;\n const lower = props.lastError.toLowerCase();\n if (!lower.includes(\"secure context\") && !lower.includes(\"device identity required\")) {\n return null;\n }\n return html`\n
    \n This page is HTTP, so the browser blocks device identity. Use HTTPS (Tailscale Serve) or\n open http://127.0.0.1:18789 on the gateway host.\n
    \n If you must stay on HTTP, set\n gateway.controlUi.allowInsecureAuth: true (token-only).\n
    \n
    \n Docs: Tailscale Serve\n · \n Docs: Insecure HTTP\n
    \n
    \n `;\n })();\n\n return html`\n
    \n
    \n
    Gateway Access
    \n
    Where the dashboard connects and how it authenticates.
    \n
    \n \n \n \n \n
    \n
    \n \n \n Click Connect to apply connection changes.\n
    \n
    \n\n
    \n
    Snapshot
    \n
    Latest gateway handshake information.
    \n
    \n
    \n
    Status
    \n
    \n ${props.connected ? \"Connected\" : \"Disconnected\"}\n
    \n
    \n
    \n
    Uptime
    \n
    ${uptime}
    \n
    \n
    \n
    Tick Interval
    \n
    ${tick}
    \n
    \n
    \n
    Last Channels Refresh
    \n
    \n ${props.lastChannelsRefresh\n ? formatAgo(props.lastChannelsRefresh)\n : \"n/a\"}\n
    \n
    \n
    \n ${props.lastError\n ? html`
    \n
    ${props.lastError}
    \n ${authHint ?? \"\"}\n ${insecureContextHint ?? \"\"}\n
    `\n : html`
    \n Use Channels to link WhatsApp, Telegram, Discord, Signal, or iMessage.\n
    `}\n
    \n
    \n\n
    \n
    \n
    Instances
    \n
    ${props.presenceCount}
    \n
    Presence beacons in the last 5 minutes.
    \n
    \n
    \n
    Sessions
    \n
    ${props.sessionsCount ?? \"n/a\"}
    \n
    Recent session keys tracked by the gateway.
    \n
    \n
    \n
    Cron
    \n
    \n ${props.cronEnabled == null\n ? \"n/a\"\n : props.cronEnabled\n ? \"Enabled\"\n : \"Disabled\"}\n
    \n
    Next wake ${formatNextRun(props.cronNext)}
    \n
    \n
    \n\n
    \n
    Notes
    \n
    Quick reminders for remote control setups.
    \n
    \n
    \n
    Tailscale serve
    \n
    \n Prefer serve mode to keep the gateway on loopback with tailnet auth.\n
    \n
    \n
    \n
    Session hygiene
    \n
    Use /new or sessions.patch to reset context.
    \n
    \n
    \n
    Cron reminders
    \n
    Use isolated sessions for recurring runs.
    \n
    \n
    \n
    \n `;\n}\n","import { html, nothing } from \"lit\";\n\nimport { formatAgo } from \"../format\";\nimport { formatSessionTokens } from \"../presenter\";\nimport { pathForTab } from \"../navigation\";\nimport type { GatewaySessionRow, SessionsListResult } from \"../types\";\n\nexport type SessionsProps = {\n loading: boolean;\n result: SessionsListResult | null;\n error: string | null;\n activeMinutes: string;\n limit: string;\n includeGlobal: boolean;\n includeUnknown: boolean;\n basePath: string;\n onFiltersChange: (next: {\n activeMinutes: string;\n limit: string;\n includeGlobal: boolean;\n includeUnknown: boolean;\n }) => void;\n onRefresh: () => void;\n onPatch: (\n key: string,\n patch: {\n label?: string | null;\n thinkingLevel?: string | null;\n verboseLevel?: string | null;\n reasoningLevel?: string | null;\n },\n ) => void;\n onDelete: (key: string) => void;\n};\n\nconst THINK_LEVELS = [\"\", \"off\", \"minimal\", \"low\", \"medium\", \"high\"] as const;\nconst BINARY_THINK_LEVELS = [\"\", \"off\", \"on\"] as const;\nconst VERBOSE_LEVELS = [\n { value: \"\", label: \"inherit\" },\n { value: \"off\", label: \"off (explicit)\" },\n { value: \"on\", label: \"on\" },\n] as const;\nconst REASONING_LEVELS = [\"\", \"off\", \"on\", \"stream\"] as const;\n\nfunction normalizeProviderId(provider?: string | null): string {\n if (!provider) return \"\";\n const normalized = provider.trim().toLowerCase();\n if (normalized === \"z.ai\" || normalized === \"z-ai\") return \"zai\";\n return normalized;\n}\n\nfunction isBinaryThinkingProvider(provider?: string | null): boolean {\n return normalizeProviderId(provider) === \"zai\";\n}\n\nfunction resolveThinkLevelOptions(provider?: string | null): readonly string[] {\n return isBinaryThinkingProvider(provider) ? BINARY_THINK_LEVELS : THINK_LEVELS;\n}\n\nfunction resolveThinkLevelDisplay(value: string, isBinary: boolean): string {\n if (!isBinary) return value;\n if (!value || value === \"off\") return value;\n return \"on\";\n}\n\nfunction resolveThinkLevelPatchValue(value: string, isBinary: boolean): string | null {\n if (!value) return null;\n if (!isBinary) return value;\n if (value === \"on\") return \"low\";\n return value;\n}\n\nexport function renderSessions(props: SessionsProps) {\n const rows = props.result?.sessions ?? [];\n return html`\n
    \n
    \n
    \n
    Sessions
    \n
    Active session keys and per-session overrides.
    \n
    \n \n
    \n\n
    \n \n \n \n \n
    \n\n ${props.error\n ? html`
    ${props.error}
    `\n : nothing}\n\n
    \n ${props.result ? `Store: ${props.result.path}` : \"\"}\n
    \n\n
    \n
    \n
    Key
    \n
    Label
    \n
    Kind
    \n
    Updated
    \n
    Tokens
    \n
    Thinking
    \n
    Verbose
    \n
    Reasoning
    \n
    Actions
    \n
    \n ${rows.length === 0\n ? html`
    No sessions found.
    `\n : rows.map((row) =>\n renderRow(row, props.basePath, props.onPatch, props.onDelete, props.loading),\n )}\n
    \n
    \n `;\n}\n\nfunction renderRow(\n row: GatewaySessionRow,\n basePath: string,\n onPatch: SessionsProps[\"onPatch\"],\n onDelete: SessionsProps[\"onDelete\"],\n disabled: boolean,\n) {\n const updated = row.updatedAt ? formatAgo(row.updatedAt) : \"n/a\";\n const rawThinking = row.thinkingLevel ?? \"\";\n const isBinaryThinking = isBinaryThinkingProvider(row.modelProvider);\n const thinking = resolveThinkLevelDisplay(rawThinking, isBinaryThinking);\n const thinkLevels = resolveThinkLevelOptions(row.modelProvider);\n const verbose = row.verboseLevel ?? \"\";\n const reasoning = row.reasoningLevel ?? \"\";\n const displayName = row.displayName ?? row.key;\n const canLink = row.kind !== \"global\";\n const chatUrl = canLink\n ? `${pathForTab(\"chat\", basePath)}?session=${encodeURIComponent(row.key)}`\n : null;\n\n return html`\n
    \n
    ${canLink\n ? html`${displayName}`\n : displayName}
    \n
    \n {\n const value = (e.target as HTMLInputElement).value.trim();\n onPatch(row.key, { label: value || null });\n }}\n />\n
    \n
    ${row.kind}
    \n
    ${updated}
    \n
    ${formatSessionTokens(row)}
    \n
    \n {\n const value = (e.target as HTMLSelectElement).value;\n onPatch(row.key, {\n thinkingLevel: resolveThinkLevelPatchValue(value, isBinaryThinking),\n });\n }}\n >\n ${thinkLevels.map((level) =>\n html``,\n )}\n \n
    \n
    \n {\n const value = (e.target as HTMLSelectElement).value;\n onPatch(row.key, { verboseLevel: value || null });\n }}\n >\n ${VERBOSE_LEVELS.map(\n (level) => html``,\n )}\n \n
    \n
    \n {\n const value = (e.target as HTMLSelectElement).value;\n onPatch(row.key, { reasoningLevel: value || null });\n }}\n >\n ${REASONING_LEVELS.map((level) =>\n html``,\n )}\n \n
    \n
    \n \n
    \n
    \n `;\n}\n","import { html, nothing } from \"lit\";\n\nimport type { AppViewState } from \"../app-view-state\";\n\nfunction formatRemaining(ms: number): string {\n const remaining = Math.max(0, ms);\n const totalSeconds = Math.floor(remaining / 1000);\n if (totalSeconds < 60) return `${totalSeconds}s`;\n const minutes = Math.floor(totalSeconds / 60);\n if (minutes < 60) return `${minutes}m`;\n const hours = Math.floor(minutes / 60);\n return `${hours}h`;\n}\n\nfunction renderMetaRow(label: string, value?: string | null) {\n if (!value) return nothing;\n return html`
    ${label}${value}
    `;\n}\n\nexport function renderExecApprovalPrompt(state: AppViewState) {\n const active = state.execApprovalQueue[0];\n if (!active) return nothing;\n const request = active.request;\n const remainingMs = active.expiresAtMs - Date.now();\n const remaining = remainingMs > 0 ? `expires in ${formatRemaining(remainingMs)}` : \"expired\";\n const queueCount = state.execApprovalQueue.length;\n return html`\n
    \n
    \n
    \n
    \n
    Exec approval needed
    \n
    ${remaining}
    \n
    \n ${queueCount > 1\n ? html`
    ${queueCount} pending
    `\n : nothing}\n
    \n
    ${request.command}
    \n
    \n ${renderMetaRow(\"Host\", request.host)}\n ${renderMetaRow(\"Agent\", request.agentId)}\n ${renderMetaRow(\"Session\", request.sessionKey)}\n ${renderMetaRow(\"CWD\", request.cwd)}\n ${renderMetaRow(\"Resolved\", request.resolvedPath)}\n ${renderMetaRow(\"Security\", request.security)}\n ${renderMetaRow(\"Ask\", request.ask)}\n
    \n ${state.execApprovalError\n ? html`
    ${state.execApprovalError}
    `\n : nothing}\n
    \n state.handleExecApprovalDecision(\"allow-once\")}\n >\n Allow once\n \n state.handleExecApprovalDecision(\"allow-always\")}\n >\n Always allow\n \n state.handleExecApprovalDecision(\"deny\")}\n >\n Deny\n \n
    \n
    \n
    \n `;\n}\n","import { html, nothing } from \"lit\";\n\nimport { clampText } from \"../format\";\nimport type { SkillStatusEntry, SkillStatusReport } from \"../types\";\nimport type { SkillMessageMap } from \"../controllers/skills\";\n\nexport type SkillsProps = {\n loading: boolean;\n report: SkillStatusReport | null;\n error: string | null;\n filter: string;\n edits: Record;\n busyKey: string | null;\n messages: SkillMessageMap;\n onFilterChange: (next: string) => void;\n onRefresh: () => void;\n onToggle: (skillKey: string, enabled: boolean) => void;\n onEdit: (skillKey: string, value: string) => void;\n onSaveKey: (skillKey: string) => void;\n onInstall: (skillKey: string, name: string, installId: string) => void;\n};\n\nexport function renderSkills(props: SkillsProps) {\n const skills = props.report?.skills ?? [];\n const filter = props.filter.trim().toLowerCase();\n const filtered = filter\n ? skills.filter((skill) =>\n [skill.name, skill.description, skill.source]\n .join(\" \")\n .toLowerCase()\n .includes(filter),\n )\n : skills;\n\n return html`\n
    \n
    \n
    \n
    Skills
    \n
    Bundled, managed, and workspace skills.
    \n
    \n \n
    \n\n
    \n \n
    ${filtered.length} shown
    \n
    \n\n ${props.error\n ? html`
    ${props.error}
    `\n : nothing}\n\n ${filtered.length === 0\n ? html`
    No skills found.
    `\n : html`\n
    \n ${filtered.map((skill) => renderSkill(skill, props))}\n
    \n `}\n
    \n `;\n}\n\nfunction renderSkill(skill: SkillStatusEntry, props: SkillsProps) {\n const busy = props.busyKey === skill.skillKey;\n const apiKey = props.edits[skill.skillKey] ?? \"\";\n const message = props.messages[skill.skillKey] ?? null;\n const canInstall =\n skill.install.length > 0 && skill.missing.bins.length > 0;\n const missing = [\n ...skill.missing.bins.map((b) => `bin:${b}`),\n ...skill.missing.env.map((e) => `env:${e}`),\n ...skill.missing.config.map((c) => `config:${c}`),\n ...skill.missing.os.map((o) => `os:${o}`),\n ];\n const reasons: string[] = [];\n if (skill.disabled) reasons.push(\"disabled\");\n if (skill.blockedByAllowlist) reasons.push(\"blocked by allowlist\");\n return html`\n
    \n
    \n
    \n ${skill.emoji ? `${skill.emoji} ` : \"\"}${skill.name}\n
    \n
    ${clampText(skill.description, 140)}
    \n
    \n ${skill.source}\n \n ${skill.eligible ? \"eligible\" : \"blocked\"}\n \n ${skill.disabled ? html`disabled` : nothing}\n
    \n ${missing.length > 0\n ? html`\n
    \n Missing: ${missing.join(\", \")}\n
    \n `\n : nothing}\n ${reasons.length > 0\n ? html`\n
    \n Reason: ${reasons.join(\", \")}\n
    \n `\n : nothing}\n
    \n
    \n
    \n props.onToggle(skill.skillKey, skill.disabled)}\n >\n ${skill.disabled ? \"Enable\" : \"Disable\"}\n \n ${canInstall\n ? html`\n props.onInstall(skill.skillKey, skill.name, skill.install[0].id)}\n >\n ${busy ? \"Installing…\" : skill.install[0].label}\n `\n : nothing}\n
    \n ${message\n ? html`\n ${message.message}\n
    `\n : nothing}\n ${skill.primaryEnv\n ? html`\n
    \n API key\n \n props.onEdit(skill.skillKey, (e.target as HTMLInputElement).value)}\n />\n
    \n props.onSaveKey(skill.skillKey)}\n >\n Save key\n \n `\n : nothing}\n
    \n \n `;\n}\n","import { html } from \"lit\";\nimport { repeat } from \"lit/directives/repeat.js\";\n\nimport type { AppViewState } from \"./app-view-state\";\nimport { iconForTab, pathForTab, titleForTab, type Tab } from \"./navigation\";\nimport { icons } from \"./icons\";\nimport { loadChatHistory } from \"./controllers/chat\";\nimport { syncUrlWithSessionKey } from \"./app-settings\";\nimport type { SessionsListResult } from \"./types\";\nimport type { ThemeMode } from \"./theme\";\nimport type { ThemeTransitionContext } from \"./theme-transition\";\n\nexport function renderTab(state: AppViewState, tab: Tab) {\n const href = pathForTab(tab, state.basePath);\n return html`\n {\n if (\n event.defaultPrevented ||\n event.button !== 0 ||\n event.metaKey ||\n event.ctrlKey ||\n event.shiftKey ||\n event.altKey\n ) {\n return;\n }\n event.preventDefault();\n state.setTab(tab);\n }}\n title=${titleForTab(tab)}\n >\n ${icons[iconForTab(tab)]}\n ${titleForTab(tab)}\n \n `;\n}\n\nexport function renderChatControls(state: AppViewState) {\n const sessionOptions = resolveSessionOptions(state.sessionKey, state.sessionsResult);\n const disableThinkingToggle = state.onboarding;\n const disableFocusToggle = state.onboarding;\n const showThinking = state.onboarding ? false : state.settings.chatShowThinking;\n const focusActive = state.onboarding ? true : state.settings.chatFocusMode;\n // Refresh icon\n const refreshIcon = html``;\n const focusIcon = html``;\n return html`\n
    \n \n {\n state.resetToolStream();\n void loadChatHistory(state);\n }}\n title=\"Refresh chat history\"\n >\n ${refreshIcon}\n \n |\n {\n if (disableThinkingToggle) return;\n state.applySettings({\n ...state.settings,\n chatShowThinking: !state.settings.chatShowThinking,\n });\n }}\n aria-pressed=${showThinking}\n title=${disableThinkingToggle\n ? \"Disabled during onboarding\"\n : \"Toggle assistant thinking/working output\"}\n >\n ${icons.brain}\n \n {\n if (disableFocusToggle) return;\n state.applySettings({\n ...state.settings,\n chatFocusMode: !state.settings.chatFocusMode,\n });\n }}\n aria-pressed=${focusActive}\n title=${disableFocusToggle\n ? \"Disabled during onboarding\"\n : \"Toggle focus mode (hide sidebar + page header)\"}\n >\n ${focusIcon}\n \n
    \n `;\n}\n\nfunction resolveSessionOptions(sessionKey: string, sessions: SessionsListResult | null) {\n const seen = new Set();\n const options: Array<{ key: string; displayName?: string }> = [];\n\n const resolvedCurrent = sessions?.sessions?.find((s) => s.key === sessionKey);\n\n // Add current session key first\n seen.add(sessionKey);\n options.push({ key: sessionKey, displayName: resolvedCurrent?.displayName });\n\n // Add sessions from the result\n if (sessions?.sessions) {\n for (const s of sessions.sessions) {\n if (!seen.has(s.key)) {\n seen.add(s.key);\n options.push({ key: s.key, displayName: s.displayName });\n }\n }\n }\n\n return options;\n}\n\nconst THEME_ORDER: ThemeMode[] = [\"system\", \"light\", \"dark\"];\n\nexport function renderThemeToggle(state: AppViewState) {\n const index = Math.max(0, THEME_ORDER.indexOf(state.theme));\n const applyTheme = (next: ThemeMode) => (event: MouseEvent) => {\n const element = event.currentTarget as HTMLElement;\n const context: ThemeTransitionContext = { element };\n if (event.clientX || event.clientY) {\n context.pointerClientX = event.clientX;\n context.pointerClientY = event.clientY;\n }\n state.setTheme(next, context);\n };\n\n return html`\n
    \n
    \n \n \n ${renderMonitorIcon()}\n \n \n ${renderSunIcon()}\n \n \n ${renderMoonIcon()}\n \n
    \n
    \n `;\n}\n\nfunction renderSunIcon() {\n return html`\n \n \n \n \n \n \n \n \n \n \n \n `;\n}\n\nfunction renderMoonIcon() {\n return html`\n \n \n \n `;\n}\n\nfunction renderMonitorIcon() {\n return html`\n \n \n \n \n \n `;\n}\n","import { html, nothing } from \"lit\";\n\nimport type { GatewayBrowserClient, GatewayHelloOk } from \"./gateway\";\nimport type { AppViewState } from \"./app-view-state\";\nimport { parseAgentSessionKey } from \"../../../src/routing/session-key.js\";\nimport {\n TAB_GROUPS,\n iconForTab,\n pathForTab,\n subtitleForTab,\n titleForTab,\n type Tab,\n} from \"./navigation\";\nimport { icons } from \"./icons\";\nimport type { UiSettings } from \"./storage\";\nimport type { ThemeMode } from \"./theme\";\nimport type { ThemeTransitionContext } from \"./theme-transition\";\nimport type {\n ConfigSnapshot,\n CronJob,\n CronRunLogEntry,\n CronStatus,\n HealthSnapshot,\n LogEntry,\n LogLevel,\n PresenceEntry,\n ChannelsStatusSnapshot,\n SessionsListResult,\n SkillStatusReport,\n StatusSummary,\n} from \"./types\";\nimport type { ChatQueueItem, CronFormState } from \"./ui-types\";\nimport { refreshChatAvatar } from \"./app-chat\";\nimport { renderChat } from \"./views/chat\";\nimport { renderConfig } from \"./views/config\";\nimport { renderChannels } from \"./views/channels\";\nimport { renderCron } from \"./views/cron\";\nimport { renderDebug } from \"./views/debug\";\nimport { renderInstances } from \"./views/instances\";\nimport { renderLogs } from \"./views/logs\";\nimport { renderNodes } from \"./views/nodes\";\nimport { renderOverview } from \"./views/overview\";\nimport { renderSessions } from \"./views/sessions\";\nimport { renderExecApprovalPrompt } from \"./views/exec-approval\";\nimport {\n approveDevicePairing,\n loadDevices,\n rejectDevicePairing,\n revokeDeviceToken,\n rotateDeviceToken,\n} from \"./controllers/devices\";\nimport { renderSkills } from \"./views/skills\";\nimport { renderChatControls, renderTab, renderThemeToggle } from \"./app-render.helpers\";\nimport { loadChannels } from \"./controllers/channels\";\nimport { loadPresence } from \"./controllers/presence\";\nimport { deleteSession, loadSessions, patchSession } from \"./controllers/sessions\";\nimport {\n installSkill,\n loadSkills,\n saveSkillApiKey,\n updateSkillEdit,\n updateSkillEnabled,\n type SkillMessage,\n} from \"./controllers/skills\";\nimport { loadNodes } from \"./controllers/nodes\";\nimport { loadChatHistory } from \"./controllers/chat\";\nimport {\n applyConfig,\n loadConfig,\n runUpdate,\n saveConfig,\n updateConfigFormValue,\n removeConfigFormValue,\n} from \"./controllers/config\";\nimport {\n loadExecApprovals,\n removeExecApprovalsFormValue,\n saveExecApprovals,\n updateExecApprovalsFormValue,\n} from \"./controllers/exec-approvals\";\nimport { loadCronRuns, toggleCronJob, runCronJob, removeCronJob, addCronJob } from \"./controllers/cron\";\nimport { loadDebug, callDebugMethod } from \"./controllers/debug\";\nimport { loadLogs } from \"./controllers/logs\";\n\nconst AVATAR_DATA_RE = /^data:/i;\nconst AVATAR_HTTP_RE = /^https?:\\/\\//i;\n\nfunction resolveAssistantAvatarUrl(state: AppViewState): string | undefined {\n const list = state.agentsList?.agents ?? [];\n const parsed = parseAgentSessionKey(state.sessionKey);\n const agentId =\n parsed?.agentId ??\n state.agentsList?.defaultId ??\n \"main\";\n const agent = list.find((entry) => entry.id === agentId);\n const identity = agent?.identity;\n const candidate = identity?.avatarUrl ?? identity?.avatar;\n if (!candidate) return undefined;\n if (AVATAR_DATA_RE.test(candidate) || AVATAR_HTTP_RE.test(candidate)) return candidate;\n return identity?.avatarUrl;\n}\n\nexport function renderApp(state: AppViewState) {\n const presenceCount = state.presenceEntries.length;\n const sessionsCount = state.sessionsResult?.count ?? null;\n const cronNext = state.cronStatus?.nextWakeAtMs ?? null;\n const chatDisabledReason = state.connected ? null : \"Disconnected from gateway.\";\n const isChat = state.tab === \"chat\";\n const chatFocus = isChat && (state.settings.chatFocusMode || state.onboarding);\n const showThinking = state.onboarding ? false : state.settings.chatShowThinking;\n const assistantAvatarUrl = resolveAssistantAvatarUrl(state);\n const chatAvatarUrl = state.chatAvatarUrl ?? assistantAvatarUrl ?? null;\n\n return html`\n
    \n
    \n
    \n \n state.applySettings({\n ...state.settings,\n navCollapsed: !state.settings.navCollapsed,\n })}\n title=\"${state.settings.navCollapsed ? \"Expand sidebar\" : \"Collapse sidebar\"}\"\n aria-label=\"${state.settings.navCollapsed ? \"Expand sidebar\" : \"Collapse sidebar\"}\"\n >\n ${icons.menu}\n \n
    \n
    \n \"Clawdbot\"\n
    \n
    \n
    CLAWDBOT
    \n
    Gateway Dashboard
    \n
    \n
    \n
    \n
    \n
    \n \n Health\n ${state.connected ? \"OK\" : \"Offline\"}\n
    \n ${renderThemeToggle(state)}\n
    \n
    \n \n
    \n
    \n
    \n
    ${titleForTab(state.tab)}
    \n
    ${subtitleForTab(state.tab)}
    \n
    \n
    \n ${state.lastError\n ? html`
    ${state.lastError}
    `\n : nothing}\n ${isChat ? renderChatControls(state) : nothing}\n
    \n
    \n\n ${state.tab === \"overview\"\n ? renderOverview({\n connected: state.connected,\n hello: state.hello,\n settings: state.settings,\n password: state.password,\n lastError: state.lastError,\n presenceCount,\n sessionsCount,\n cronEnabled: state.cronStatus?.enabled ?? null,\n cronNext,\n lastChannelsRefresh: state.channelsLastSuccess,\n onSettingsChange: (next) => state.applySettings(next),\n onPasswordChange: (next) => (state.password = next),\n onSessionKeyChange: (next) => {\n state.sessionKey = next;\n state.chatMessage = \"\";\n state.resetToolStream();\n state.applySettings({\n ...state.settings,\n sessionKey: next,\n lastActiveSessionKey: next,\n });\n void state.loadAssistantIdentity();\n },\n onConnect: () => state.connect(),\n onRefresh: () => state.loadOverview(),\n })\n : nothing}\n\n ${state.tab === \"channels\"\n ? renderChannels({\n connected: state.connected,\n loading: state.channelsLoading,\n snapshot: state.channelsSnapshot,\n lastError: state.channelsError,\n lastSuccessAt: state.channelsLastSuccess,\n whatsappMessage: state.whatsappLoginMessage,\n whatsappQrDataUrl: state.whatsappLoginQrDataUrl,\n whatsappConnected: state.whatsappLoginConnected,\n whatsappBusy: state.whatsappBusy,\n configSchema: state.configSchema,\n configSchemaLoading: state.configSchemaLoading,\n configForm: state.configForm,\n configUiHints: state.configUiHints,\n configSaving: state.configSaving,\n configFormDirty: state.configFormDirty,\n nostrProfileFormState: state.nostrProfileFormState,\n nostrProfileAccountId: state.nostrProfileAccountId,\n onRefresh: (probe) => loadChannels(state, probe),\n onWhatsAppStart: (force) => state.handleWhatsAppStart(force),\n onWhatsAppWait: () => state.handleWhatsAppWait(),\n onWhatsAppLogout: () => state.handleWhatsAppLogout(),\n onConfigPatch: (path, value) => updateConfigFormValue(state, path, value),\n onConfigSave: () => state.handleChannelConfigSave(),\n onConfigReload: () => state.handleChannelConfigReload(),\n onNostrProfileEdit: (accountId, profile) =>\n state.handleNostrProfileEdit(accountId, profile),\n onNostrProfileCancel: () => state.handleNostrProfileCancel(),\n onNostrProfileFieldChange: (field, value) =>\n state.handleNostrProfileFieldChange(field, value),\n onNostrProfileSave: () => state.handleNostrProfileSave(),\n onNostrProfileImport: () => state.handleNostrProfileImport(),\n onNostrProfileToggleAdvanced: () => state.handleNostrProfileToggleAdvanced(),\n })\n : nothing}\n\n ${state.tab === \"instances\"\n ? renderInstances({\n loading: state.presenceLoading,\n entries: state.presenceEntries,\n lastError: state.presenceError,\n statusMessage: state.presenceStatus,\n onRefresh: () => loadPresence(state),\n })\n : nothing}\n\n ${state.tab === \"sessions\"\n ? renderSessions({\n loading: state.sessionsLoading,\n result: state.sessionsResult,\n error: state.sessionsError,\n activeMinutes: state.sessionsFilterActive,\n limit: state.sessionsFilterLimit,\n includeGlobal: state.sessionsIncludeGlobal,\n includeUnknown: state.sessionsIncludeUnknown,\n basePath: state.basePath,\n onFiltersChange: (next) => {\n state.sessionsFilterActive = next.activeMinutes;\n state.sessionsFilterLimit = next.limit;\n state.sessionsIncludeGlobal = next.includeGlobal;\n state.sessionsIncludeUnknown = next.includeUnknown;\n\t },\n\t onRefresh: () => loadSessions(state),\n\t onPatch: (key, patch) => patchSession(state, key, patch),\n\t onDelete: (key) => deleteSession(state, key),\n\t })\n\t : nothing}\n\n ${state.tab === \"cron\"\n ? renderCron({\n loading: state.cronLoading,\n status: state.cronStatus,\n jobs: state.cronJobs,\n error: state.cronError,\n busy: state.cronBusy,\n form: state.cronForm,\n channels: state.channelsSnapshot?.channelMeta?.length\n ? state.channelsSnapshot.channelMeta.map((entry) => entry.id)\n : state.channelsSnapshot?.channelOrder ?? [],\n channelLabels: state.channelsSnapshot?.channelLabels ?? {},\n channelMeta: state.channelsSnapshot?.channelMeta ?? [],\n runsJobId: state.cronRunsJobId,\n runs: state.cronRuns,\n onFormChange: (patch) => (state.cronForm = { ...state.cronForm, ...patch }),\n onRefresh: () => state.loadCron(),\n onAdd: () => addCronJob(state),\n onToggle: (job, enabled) => toggleCronJob(state, job, enabled),\n onRun: (job) => runCronJob(state, job),\n onRemove: (job) => removeCronJob(state, job),\n onLoadRuns: (jobId) => loadCronRuns(state, jobId),\n })\n : nothing}\n\n ${state.tab === \"skills\"\n ? renderSkills({\n loading: state.skillsLoading,\n report: state.skillsReport,\n error: state.skillsError,\n filter: state.skillsFilter,\n edits: state.skillEdits,\n messages: state.skillMessages,\n busyKey: state.skillsBusyKey,\n onFilterChange: (next) => (state.skillsFilter = next),\n onRefresh: () => loadSkills(state, { clearMessages: true }),\n onToggle: (key, enabled) => updateSkillEnabled(state, key, enabled),\n onEdit: (key, value) => updateSkillEdit(state, key, value),\n onSaveKey: (key) => saveSkillApiKey(state, key),\n onInstall: (skillKey, name, installId) =>\n installSkill(state, skillKey, name, installId),\n })\n : nothing}\n\n ${state.tab === \"nodes\"\n ? renderNodes({\n loading: state.nodesLoading,\n nodes: state.nodes,\n devicesLoading: state.devicesLoading,\n devicesError: state.devicesError,\n devicesList: state.devicesList,\n configForm: state.configForm ?? (state.configSnapshot?.config as Record | null),\n configLoading: state.configLoading,\n configSaving: state.configSaving,\n configDirty: state.configFormDirty,\n configFormMode: state.configFormMode,\n execApprovalsLoading: state.execApprovalsLoading,\n execApprovalsSaving: state.execApprovalsSaving,\n execApprovalsDirty: state.execApprovalsDirty,\n execApprovalsSnapshot: state.execApprovalsSnapshot,\n execApprovalsForm: state.execApprovalsForm,\n execApprovalsSelectedAgent: state.execApprovalsSelectedAgent,\n execApprovalsTarget: state.execApprovalsTarget,\n execApprovalsTargetNodeId: state.execApprovalsTargetNodeId,\n onRefresh: () => loadNodes(state),\n onDevicesRefresh: () => loadDevices(state),\n onDeviceApprove: (requestId) => approveDevicePairing(state, requestId),\n onDeviceReject: (requestId) => rejectDevicePairing(state, requestId),\n onDeviceRotate: (deviceId, role, scopes) =>\n rotateDeviceToken(state, { deviceId, role, scopes }),\n onDeviceRevoke: (deviceId, role) =>\n revokeDeviceToken(state, { deviceId, role }),\n onLoadConfig: () => loadConfig(state),\n onLoadExecApprovals: () => {\n const target =\n state.execApprovalsTarget === \"node\" && state.execApprovalsTargetNodeId\n ? { kind: \"node\" as const, nodeId: state.execApprovalsTargetNodeId }\n : { kind: \"gateway\" as const };\n return loadExecApprovals(state, target);\n },\n onBindDefault: (nodeId) => {\n if (nodeId) {\n updateConfigFormValue(state, [\"tools\", \"exec\", \"node\"], nodeId);\n } else {\n removeConfigFormValue(state, [\"tools\", \"exec\", \"node\"]);\n }\n },\n onBindAgent: (agentIndex, nodeId) => {\n const basePath = [\"agents\", \"list\", agentIndex, \"tools\", \"exec\", \"node\"];\n if (nodeId) {\n updateConfigFormValue(state, basePath, nodeId);\n } else {\n removeConfigFormValue(state, basePath);\n }\n },\n onSaveBindings: () => saveConfig(state),\n onExecApprovalsTargetChange: (kind, nodeId) => {\n state.execApprovalsTarget = kind;\n state.execApprovalsTargetNodeId = nodeId;\n state.execApprovalsSnapshot = null;\n state.execApprovalsForm = null;\n state.execApprovalsDirty = false;\n state.execApprovalsSelectedAgent = null;\n },\n onExecApprovalsSelectAgent: (agentId) => {\n state.execApprovalsSelectedAgent = agentId;\n },\n onExecApprovalsPatch: (path, value) =>\n updateExecApprovalsFormValue(state, path, value),\n onExecApprovalsRemove: (path) =>\n removeExecApprovalsFormValue(state, path),\n onSaveExecApprovals: () => {\n const target =\n state.execApprovalsTarget === \"node\" && state.execApprovalsTargetNodeId\n ? { kind: \"node\" as const, nodeId: state.execApprovalsTargetNodeId }\n : { kind: \"gateway\" as const };\n return saveExecApprovals(state, target);\n },\n })\n : nothing}\n\n ${state.tab === \"chat\"\n ? renderChat({\n sessionKey: state.sessionKey,\n onSessionKeyChange: (next) => {\n state.sessionKey = next;\n state.chatMessage = \"\";\n state.chatStream = null;\n state.chatStreamStartedAt = null;\n state.chatRunId = null;\n state.chatQueue = [];\n state.resetToolStream();\n state.resetChatScroll();\n state.applySettings({\n ...state.settings,\n sessionKey: next,\n lastActiveSessionKey: next,\n });\n void state.loadAssistantIdentity();\n void loadChatHistory(state);\n void refreshChatAvatar(state);\n },\n thinkingLevel: state.chatThinkingLevel,\n showThinking,\n loading: state.chatLoading,\n sending: state.chatSending,\n compactionStatus: state.compactionStatus,\n assistantAvatarUrl: chatAvatarUrl,\n messages: state.chatMessages,\n toolMessages: state.chatToolMessages,\n stream: state.chatStream,\n streamStartedAt: state.chatStreamStartedAt,\n draft: state.chatMessage,\n queue: state.chatQueue,\n connected: state.connected,\n canSend: state.connected,\n disabledReason: chatDisabledReason,\n error: state.lastError,\n sessions: state.sessionsResult,\n focusMode: chatFocus,\n onRefresh: () => {\n state.resetToolStream();\n return Promise.all([loadChatHistory(state), refreshChatAvatar(state)]);\n },\n onToggleFocusMode: () => {\n if (state.onboarding) return;\n state.applySettings({\n ...state.settings,\n chatFocusMode: !state.settings.chatFocusMode,\n });\n },\n onChatScroll: (event) => state.handleChatScroll(event),\n onDraftChange: (next) => (state.chatMessage = next),\n onSend: () => state.handleSendChat(),\n canAbort: Boolean(state.chatRunId),\n onAbort: () => void state.handleAbortChat(),\n onQueueRemove: (id) => state.removeQueuedMessage(id),\n onNewSession: () =>\n state.handleSendChat(\"/new\", { restoreDraft: true }),\n // Sidebar props for tool output viewing\n sidebarOpen: state.sidebarOpen,\n sidebarContent: state.sidebarContent,\n sidebarError: state.sidebarError,\n splitRatio: state.splitRatio,\n onOpenSidebar: (content: string) => state.handleOpenSidebar(content),\n onCloseSidebar: () => state.handleCloseSidebar(),\n onSplitRatioChange: (ratio: number) => state.handleSplitRatioChange(ratio),\n assistantName: state.assistantName,\n assistantAvatar: state.assistantAvatar,\n })\n : nothing}\n\n ${state.tab === \"config\"\n ? renderConfig({\n raw: state.configRaw,\n originalRaw: state.configRawOriginal,\n valid: state.configValid,\n issues: state.configIssues,\n loading: state.configLoading,\n saving: state.configSaving,\n applying: state.configApplying,\n updating: state.updateRunning,\n connected: state.connected,\n schema: state.configSchema,\n schemaLoading: state.configSchemaLoading,\n uiHints: state.configUiHints,\n formMode: state.configFormMode,\n formValue: state.configForm,\n originalValue: state.configFormOriginal,\n searchQuery: state.configSearchQuery,\n activeSection: state.configActiveSection,\n activeSubsection: state.configActiveSubsection,\n onRawChange: (next) => {\n state.configRaw = next;\n },\n onFormModeChange: (mode) => (state.configFormMode = mode),\n onFormPatch: (path, value) => updateConfigFormValue(state, path, value),\n onSearchChange: (query) => (state.configSearchQuery = query),\n onSectionChange: (section) => {\n state.configActiveSection = section;\n state.configActiveSubsection = null;\n },\n onSubsectionChange: (section) => (state.configActiveSubsection = section),\n onReload: () => loadConfig(state),\n onSave: () => saveConfig(state),\n onApply: () => applyConfig(state),\n onUpdate: () => runUpdate(state),\n })\n : nothing}\n\n ${state.tab === \"debug\"\n ? renderDebug({\n loading: state.debugLoading,\n status: state.debugStatus,\n health: state.debugHealth,\n models: state.debugModels,\n heartbeat: state.debugHeartbeat,\n eventLog: state.eventLog,\n callMethod: state.debugCallMethod,\n callParams: state.debugCallParams,\n callResult: state.debugCallResult,\n callError: state.debugCallError,\n onCallMethodChange: (next) => (state.debugCallMethod = next),\n onCallParamsChange: (next) => (state.debugCallParams = next),\n onRefresh: () => loadDebug(state),\n onCall: () => callDebugMethod(state),\n })\n : nothing}\n\n ${state.tab === \"logs\"\n ? renderLogs({\n loading: state.logsLoading,\n error: state.logsError,\n file: state.logsFile,\n entries: state.logsEntries,\n filterText: state.logsFilterText,\n levelFilters: state.logsLevelFilters,\n autoFollow: state.logsAutoFollow,\n truncated: state.logsTruncated,\n onFilterTextChange: (next) => (state.logsFilterText = next),\n onLevelToggle: (level, enabled) => {\n state.logsLevelFilters = { ...state.logsLevelFilters, [level]: enabled };\n },\n onToggleAutoFollow: (next) => (state.logsAutoFollow = next),\n onRefresh: () => loadLogs(state, { reset: true }),\n onExport: (lines, label) => state.exportLogs(lines, label),\n onScroll: (event) => state.handleLogsScroll(event),\n })\n : nothing}\n
    \n ${renderExecApprovalPrompt(state)}\n
    \n `;\n}\n","import type { LogLevel } from \"./types\";\nimport type { CronFormState } from \"./ui-types\";\n\nexport const DEFAULT_LOG_LEVEL_FILTERS: Record = {\n trace: true,\n debug: true,\n info: true,\n warn: true,\n error: true,\n fatal: true,\n};\n\nexport const DEFAULT_CRON_FORM: CronFormState = {\n name: \"\",\n description: \"\",\n agentId: \"\",\n enabled: true,\n scheduleKind: \"every\",\n scheduleAt: \"\",\n everyAmount: \"30\",\n everyUnit: \"minutes\",\n cronExpr: \"0 7 * * *\",\n cronTz: \"\",\n sessionTarget: \"main\",\n wakeMode: \"next-heartbeat\",\n payloadKind: \"systemEvent\",\n payloadText: \"\",\n deliver: false,\n channel: \"last\",\n to: \"\",\n timeoutSeconds: \"\",\n postToMainPrefix: \"\",\n};\n","import type { GatewayBrowserClient } from \"../gateway\";\nimport type { AgentsListResult } from \"../types\";\n\nexport type AgentsState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n agentsLoading: boolean;\n agentsError: string | null;\n agentsList: AgentsListResult | null;\n};\n\nexport async function loadAgents(state: AgentsState) {\n if (!state.client || !state.connected) return;\n if (state.agentsLoading) return;\n state.agentsLoading = true;\n state.agentsError = null;\n try {\n const res = (await state.client.request(\"agents.list\", {})) as AgentsListResult | undefined;\n if (res) state.agentsList = res;\n } catch (err) {\n state.agentsError = String(err);\n } finally {\n state.agentsLoading = false;\n }\n}\n","export const GATEWAY_CLIENT_IDS = {\n WEBCHAT_UI: \"webchat-ui\",\n CONTROL_UI: \"clawdbot-control-ui\",\n WEBCHAT: \"webchat\",\n CLI: \"cli\",\n GATEWAY_CLIENT: \"gateway-client\",\n MACOS_APP: \"clawdbot-macos\",\n IOS_APP: \"clawdbot-ios\",\n ANDROID_APP: \"clawdbot-android\",\n NODE_HOST: \"node-host\",\n TEST: \"test\",\n FINGERPRINT: \"fingerprint\",\n PROBE: \"clawdbot-probe\",\n} as const;\n\nexport type GatewayClientId = (typeof GATEWAY_CLIENT_IDS)[keyof typeof GATEWAY_CLIENT_IDS];\n\n// Back-compat naming (internal): these values are IDs, not display names.\nexport const GATEWAY_CLIENT_NAMES = GATEWAY_CLIENT_IDS;\nexport type GatewayClientName = GatewayClientId;\n\nexport const GATEWAY_CLIENT_MODES = {\n WEBCHAT: \"webchat\",\n CLI: \"cli\",\n UI: \"ui\",\n BACKEND: \"backend\",\n NODE: \"node\",\n PROBE: \"probe\",\n TEST: \"test\",\n} as const;\n\nexport type GatewayClientMode = (typeof GATEWAY_CLIENT_MODES)[keyof typeof GATEWAY_CLIENT_MODES];\n\nexport type GatewayClientInfo = {\n id: GatewayClientId;\n displayName?: string;\n version: string;\n platform: string;\n deviceFamily?: string;\n modelIdentifier?: string;\n mode: GatewayClientMode;\n instanceId?: string;\n};\n\nconst GATEWAY_CLIENT_ID_SET = new Set(Object.values(GATEWAY_CLIENT_IDS));\nconst GATEWAY_CLIENT_MODE_SET = new Set(Object.values(GATEWAY_CLIENT_MODES));\n\nexport function normalizeGatewayClientId(raw?: string | null): GatewayClientId | undefined {\n const normalized = raw?.trim().toLowerCase();\n if (!normalized) return undefined;\n return GATEWAY_CLIENT_ID_SET.has(normalized as GatewayClientId)\n ? (normalized as GatewayClientId)\n : undefined;\n}\n\nexport function normalizeGatewayClientName(raw?: string | null): GatewayClientName | undefined {\n return normalizeGatewayClientId(raw);\n}\n\nexport function normalizeGatewayClientMode(raw?: string | null): GatewayClientMode | undefined {\n const normalized = raw?.trim().toLowerCase();\n if (!normalized) return undefined;\n return GATEWAY_CLIENT_MODE_SET.has(normalized as GatewayClientMode)\n ? (normalized as GatewayClientMode)\n : undefined;\n}\n","export type DeviceAuthPayloadParams = {\n deviceId: string;\n clientId: string;\n clientMode: string;\n role: string;\n scopes: string[];\n signedAtMs: number;\n token?: string | null;\n nonce?: string | null;\n version?: \"v1\" | \"v2\";\n};\n\nexport function buildDeviceAuthPayload(params: DeviceAuthPayloadParams): string {\n const version = params.version ?? (params.nonce ? \"v2\" : \"v1\");\n const scopes = params.scopes.join(\",\");\n const token = params.token ?? \"\";\n const base = [\n version,\n params.deviceId,\n params.clientId,\n params.clientMode,\n params.role,\n scopes,\n String(params.signedAtMs),\n token,\n ];\n if (version === \"v2\") {\n base.push(params.nonce ?? \"\");\n }\n return base.join(\"|\");\n}\n","import { generateUUID } from \"./uuid\";\nimport {\n GATEWAY_CLIENT_MODES,\n GATEWAY_CLIENT_NAMES,\n type GatewayClientMode,\n type GatewayClientName,\n} from \"../../../src/gateway/protocol/client-info.js\";\nimport { buildDeviceAuthPayload } from \"../../../src/gateway/device-auth.js\";\nimport { loadOrCreateDeviceIdentity, signDevicePayload } from \"./device-identity\";\nimport { clearDeviceAuthToken, loadDeviceAuthToken, storeDeviceAuthToken } from \"./device-auth\";\n\nexport type GatewayEventFrame = {\n type: \"event\";\n event: string;\n payload?: unknown;\n seq?: number;\n stateVersion?: { presence: number; health: number };\n};\n\nexport type GatewayResponseFrame = {\n type: \"res\";\n id: string;\n ok: boolean;\n payload?: unknown;\n error?: { code: string; message: string; details?: unknown };\n};\n\nexport type GatewayHelloOk = {\n type: \"hello-ok\";\n protocol: number;\n features?: { methods?: string[]; events?: string[] };\n snapshot?: unknown;\n auth?: {\n deviceToken?: string;\n role?: string;\n scopes?: string[];\n issuedAtMs?: number;\n };\n policy?: { tickIntervalMs?: number };\n};\n\ntype Pending = {\n resolve: (value: unknown) => void;\n reject: (err: unknown) => void;\n};\n\nexport type GatewayBrowserClientOptions = {\n url: string;\n token?: string;\n password?: string;\n clientName?: GatewayClientName;\n clientVersion?: string;\n platform?: string;\n mode?: GatewayClientMode;\n instanceId?: string;\n onHello?: (hello: GatewayHelloOk) => void;\n onEvent?: (evt: GatewayEventFrame) => void;\n onClose?: (info: { code: number; reason: string }) => void;\n onGap?: (info: { expected: number; received: number }) => void;\n};\n\n// 4008 = application-defined code (browser rejects 1008 \"Policy Violation\")\nconst CONNECT_FAILED_CLOSE_CODE = 4008;\n\nexport class GatewayBrowserClient {\n private ws: WebSocket | null = null;\n private pending = new Map();\n private closed = false;\n private lastSeq: number | null = null;\n private connectNonce: string | null = null;\n private connectSent = false;\n private connectTimer: number | null = null;\n private backoffMs = 800;\n\n constructor(private opts: GatewayBrowserClientOptions) {}\n\n start() {\n this.closed = false;\n this.connect();\n }\n\n stop() {\n this.closed = true;\n this.ws?.close();\n this.ws = null;\n this.flushPending(new Error(\"gateway client stopped\"));\n }\n\n get connected() {\n return this.ws?.readyState === WebSocket.OPEN;\n }\n\n private connect() {\n if (this.closed) return;\n this.ws = new WebSocket(this.opts.url);\n this.ws.onopen = () => this.queueConnect();\n this.ws.onmessage = (ev) => this.handleMessage(String(ev.data ?? \"\"));\n this.ws.onclose = (ev) => {\n const reason = String(ev.reason ?? \"\");\n this.ws = null;\n this.flushPending(new Error(`gateway closed (${ev.code}): ${reason}`));\n this.opts.onClose?.({ code: ev.code, reason });\n this.scheduleReconnect();\n };\n this.ws.onerror = () => {\n // ignored; close handler will fire\n };\n }\n\n private scheduleReconnect() {\n if (this.closed) return;\n const delay = this.backoffMs;\n this.backoffMs = Math.min(this.backoffMs * 1.7, 15_000);\n window.setTimeout(() => this.connect(), delay);\n }\n\n private flushPending(err: Error) {\n for (const [, p] of this.pending) p.reject(err);\n this.pending.clear();\n }\n\n private async sendConnect() {\n if (this.connectSent) return;\n this.connectSent = true;\n if (this.connectTimer !== null) {\n window.clearTimeout(this.connectTimer);\n this.connectTimer = null;\n }\n\n // crypto.subtle is only available in secure contexts (HTTPS, localhost).\n // Over plain HTTP, we skip device identity and fall back to token-only auth.\n // Gateways may reject this unless gateway.controlUi.allowInsecureAuth is enabled.\n const isSecureContext = typeof crypto !== \"undefined\" && !!crypto.subtle;\n\n const scopes = [\"operator.admin\", \"operator.approvals\", \"operator.pairing\"];\n const role = \"operator\";\n let deviceIdentity: Awaited> | null = null;\n let canFallbackToShared = false;\n let authToken = this.opts.token;\n\n if (isSecureContext) {\n deviceIdentity = await loadOrCreateDeviceIdentity();\n const storedToken = loadDeviceAuthToken({\n deviceId: deviceIdentity.deviceId,\n role,\n })?.token;\n authToken = storedToken ?? this.opts.token;\n canFallbackToShared = Boolean(storedToken && this.opts.token);\n }\n const auth =\n authToken || this.opts.password\n ? {\n token: authToken,\n password: this.opts.password,\n }\n : undefined;\n\n let device:\n | {\n id: string;\n publicKey: string;\n signature: string;\n signedAt: number;\n nonce: string | undefined;\n }\n | undefined;\n\n if (isSecureContext && deviceIdentity) {\n const signedAtMs = Date.now();\n const nonce = this.connectNonce ?? undefined;\n const payload = buildDeviceAuthPayload({\n deviceId: deviceIdentity.deviceId,\n clientId: this.opts.clientName ?? GATEWAY_CLIENT_NAMES.CONTROL_UI,\n clientMode: this.opts.mode ?? GATEWAY_CLIENT_MODES.WEBCHAT,\n role,\n scopes,\n signedAtMs,\n token: authToken ?? null,\n nonce,\n });\n const signature = await signDevicePayload(deviceIdentity.privateKey, payload);\n device = {\n id: deviceIdentity.deviceId,\n publicKey: deviceIdentity.publicKey,\n signature,\n signedAt: signedAtMs,\n nonce,\n };\n }\n const params = {\n minProtocol: 3,\n maxProtocol: 3,\n client: {\n id: this.opts.clientName ?? GATEWAY_CLIENT_NAMES.CONTROL_UI,\n version: this.opts.clientVersion ?? \"dev\",\n platform: this.opts.platform ?? navigator.platform ?? \"web\",\n mode: this.opts.mode ?? GATEWAY_CLIENT_MODES.WEBCHAT,\n instanceId: this.opts.instanceId,\n },\n role,\n scopes,\n device,\n caps: [],\n auth,\n userAgent: navigator.userAgent,\n locale: navigator.language,\n };\n\n void this.request(\"connect\", params)\n .then((hello) => {\n if (hello?.auth?.deviceToken && deviceIdentity) {\n storeDeviceAuthToken({\n deviceId: deviceIdentity.deviceId,\n role: hello.auth.role ?? role,\n token: hello.auth.deviceToken,\n scopes: hello.auth.scopes ?? [],\n });\n }\n this.backoffMs = 800;\n this.opts.onHello?.(hello);\n })\n .catch(() => {\n if (canFallbackToShared && deviceIdentity) {\n clearDeviceAuthToken({ deviceId: deviceIdentity.deviceId, role });\n }\n this.ws?.close(CONNECT_FAILED_CLOSE_CODE, \"connect failed\");\n });\n }\n\n private handleMessage(raw: string) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return;\n }\n\n const frame = parsed as { type?: unknown };\n if (frame.type === \"event\") {\n const evt = parsed as GatewayEventFrame;\n if (evt.event === \"connect.challenge\") {\n const payload = evt.payload as { nonce?: unknown } | undefined;\n const nonce = payload && typeof payload.nonce === \"string\" ? payload.nonce : null;\n if (nonce) {\n this.connectNonce = nonce;\n void this.sendConnect();\n }\n return;\n }\n const seq = typeof evt.seq === \"number\" ? evt.seq : null;\n if (seq !== null) {\n if (this.lastSeq !== null && seq > this.lastSeq + 1) {\n this.opts.onGap?.({ expected: this.lastSeq + 1, received: seq });\n }\n this.lastSeq = seq;\n }\n try {\n this.opts.onEvent?.(evt);\n } catch (err) {\n console.error(\"[gateway] event handler error:\", err);\n }\n return;\n }\n\n if (frame.type === \"res\") {\n const res = parsed as GatewayResponseFrame;\n const pending = this.pending.get(res.id);\n if (!pending) return;\n this.pending.delete(res.id);\n if (res.ok) pending.resolve(res.payload);\n else pending.reject(new Error(res.error?.message ?? \"request failed\"));\n return;\n }\n }\n\n request(method: string, params?: unknown): Promise {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n return Promise.reject(new Error(\"gateway not connected\"));\n }\n const id = generateUUID();\n const frame = { type: \"req\", id, method, params };\n const p = new Promise((resolve, reject) => {\n this.pending.set(id, { resolve: (v) => resolve(v as T), reject });\n });\n this.ws.send(JSON.stringify(frame));\n return p;\n }\n\n private queueConnect() {\n this.connectNonce = null;\n this.connectSent = false;\n if (this.connectTimer !== null) window.clearTimeout(this.connectTimer);\n this.connectTimer = window.setTimeout(() => {\n void this.sendConnect();\n }, 750);\n }\n}\n","export type ExecApprovalRequestPayload = {\n command: string;\n cwd?: string | null;\n host?: string | null;\n security?: string | null;\n ask?: string | null;\n agentId?: string | null;\n resolvedPath?: string | null;\n sessionKey?: string | null;\n};\n\nexport type ExecApprovalRequest = {\n id: string;\n request: ExecApprovalRequestPayload;\n createdAtMs: number;\n expiresAtMs: number;\n};\n\nexport type ExecApprovalResolved = {\n id: string;\n decision?: string | null;\n resolvedBy?: string | null;\n ts?: number | null;\n};\n\nfunction isRecord(value: unknown): value is Record {\n return typeof value === \"object\" && value !== null;\n}\n\nexport function parseExecApprovalRequested(payload: unknown): ExecApprovalRequest | null {\n if (!isRecord(payload)) return null;\n const id = typeof payload.id === \"string\" ? payload.id.trim() : \"\";\n const request = payload.request;\n if (!id || !isRecord(request)) return null;\n const command = typeof request.command === \"string\" ? request.command.trim() : \"\";\n if (!command) return null;\n const createdAtMs = typeof payload.createdAtMs === \"number\" ? payload.createdAtMs : 0;\n const expiresAtMs = typeof payload.expiresAtMs === \"number\" ? payload.expiresAtMs : 0;\n if (!createdAtMs || !expiresAtMs) return null;\n return {\n id,\n request: {\n command,\n cwd: typeof request.cwd === \"string\" ? request.cwd : null,\n host: typeof request.host === \"string\" ? request.host : null,\n security: typeof request.security === \"string\" ? request.security : null,\n ask: typeof request.ask === \"string\" ? request.ask : null,\n agentId: typeof request.agentId === \"string\" ? request.agentId : null,\n resolvedPath: typeof request.resolvedPath === \"string\" ? request.resolvedPath : null,\n sessionKey: typeof request.sessionKey === \"string\" ? request.sessionKey : null,\n },\n createdAtMs,\n expiresAtMs,\n };\n}\n\nexport function parseExecApprovalResolved(payload: unknown): ExecApprovalResolved | null {\n if (!isRecord(payload)) return null;\n const id = typeof payload.id === \"string\" ? payload.id.trim() : \"\";\n if (!id) return null;\n return {\n id,\n decision: typeof payload.decision === \"string\" ? payload.decision : null,\n resolvedBy: typeof payload.resolvedBy === \"string\" ? payload.resolvedBy : null,\n ts: typeof payload.ts === \"number\" ? payload.ts : null,\n };\n}\n\nexport function pruneExecApprovalQueue(queue: ExecApprovalRequest[]): ExecApprovalRequest[] {\n const now = Date.now();\n return queue.filter((entry) => entry.expiresAtMs > now);\n}\n\nexport function addExecApproval(\n queue: ExecApprovalRequest[],\n entry: ExecApprovalRequest,\n): ExecApprovalRequest[] {\n const next = pruneExecApprovalQueue(queue).filter((item) => item.id !== entry.id);\n next.push(entry);\n return next;\n}\n\nexport function removeExecApproval(queue: ExecApprovalRequest[], id: string): ExecApprovalRequest[] {\n return pruneExecApprovalQueue(queue).filter((entry) => entry.id !== id);\n}\n","import type { GatewayBrowserClient } from \"../gateway\";\nimport {\n normalizeAssistantIdentity,\n type AssistantIdentity,\n} from \"../assistant-identity\";\n\nexport type AssistantIdentityState = {\n client: GatewayBrowserClient | null;\n connected: boolean;\n sessionKey: string;\n assistantName: string;\n assistantAvatar: string | null;\n assistantAgentId: string | null;\n};\n\nexport async function loadAssistantIdentity(\n state: AssistantIdentityState,\n opts?: { sessionKey?: string },\n) {\n if (!state.client || !state.connected) return;\n const sessionKey = opts?.sessionKey?.trim() || state.sessionKey.trim();\n const params = sessionKey ? { sessionKey } : {};\n try {\n const res = (await state.client.request(\"agent.identity.get\", params)) as\n | Partial\n | undefined;\n if (!res) return;\n const normalized = normalizeAssistantIdentity(res);\n state.assistantName = normalized.name;\n state.assistantAvatar = normalized.avatar;\n state.assistantAgentId = normalized.agentId ?? null;\n } catch {\n // Ignore errors; keep last known identity.\n }\n}\n","import { loadChatHistory } from \"./controllers/chat\";\nimport { loadDevices } from \"./controllers/devices\";\nimport { loadNodes } from \"./controllers/nodes\";\nimport { loadAgents } from \"./controllers/agents\";\nimport type { GatewayEventFrame, GatewayHelloOk } from \"./gateway\";\nimport { GatewayBrowserClient } from \"./gateway\";\nimport type { EventLogEntry } from \"./app-events\";\nimport type { AgentsListResult, PresenceEntry, HealthSnapshot, StatusSummary } from \"./types\";\nimport type { Tab } from \"./navigation\";\nimport type { UiSettings } from \"./storage\";\nimport { handleAgentEvent, resetToolStream, type AgentEventPayload } from \"./app-tool-stream\";\nimport { flushChatQueueForEvent } from \"./app-chat\";\nimport {\n applySettings,\n loadCron,\n refreshActiveTab,\n setLastActiveSessionKey,\n} from \"./app-settings\";\nimport { handleChatEvent, type ChatEventPayload } from \"./controllers/chat\";\nimport {\n addExecApproval,\n parseExecApprovalRequested,\n parseExecApprovalResolved,\n removeExecApproval,\n} from \"./controllers/exec-approval\";\nimport type { ClawdbotApp } from \"./app\";\nimport type { ExecApprovalRequest } from \"./controllers/exec-approval\";\nimport { loadAssistantIdentity } from \"./controllers/assistant-identity\";\n\ntype GatewayHost = {\n settings: UiSettings;\n password: string;\n client: GatewayBrowserClient | null;\n connected: boolean;\n hello: GatewayHelloOk | null;\n lastError: string | null;\n onboarding?: boolean;\n eventLogBuffer: EventLogEntry[];\n eventLog: EventLogEntry[];\n tab: Tab;\n presenceEntries: PresenceEntry[];\n presenceError: string | null;\n presenceStatus: StatusSummary | null;\n agentsLoading: boolean;\n agentsList: AgentsListResult | null;\n agentsError: string | null;\n debugHealth: HealthSnapshot | null;\n assistantName: string;\n assistantAvatar: string | null;\n assistantAgentId: string | null;\n sessionKey: string;\n chatRunId: string | null;\n execApprovalQueue: ExecApprovalRequest[];\n execApprovalError: string | null;\n};\n\ntype SessionDefaultsSnapshot = {\n defaultAgentId?: string;\n mainKey?: string;\n mainSessionKey?: string;\n scope?: string;\n};\n\nfunction normalizeSessionKeyForDefaults(\n value: string | undefined,\n defaults: SessionDefaultsSnapshot,\n): string {\n const raw = (value ?? \"\").trim();\n const mainSessionKey = defaults.mainSessionKey?.trim();\n if (!mainSessionKey) return raw;\n if (!raw) return mainSessionKey;\n const mainKey = defaults.mainKey?.trim() || \"main\";\n const defaultAgentId = defaults.defaultAgentId?.trim();\n const isAlias =\n raw === \"main\" ||\n raw === mainKey ||\n (defaultAgentId &&\n (raw === `agent:${defaultAgentId}:main` ||\n raw === `agent:${defaultAgentId}:${mainKey}`));\n return isAlias ? mainSessionKey : raw;\n}\n\nfunction applySessionDefaults(host: GatewayHost, defaults?: SessionDefaultsSnapshot) {\n if (!defaults?.mainSessionKey) return;\n const resolvedSessionKey = normalizeSessionKeyForDefaults(host.sessionKey, defaults);\n const resolvedSettingsSessionKey = normalizeSessionKeyForDefaults(\n host.settings.sessionKey,\n defaults,\n );\n const resolvedLastActiveSessionKey = normalizeSessionKeyForDefaults(\n host.settings.lastActiveSessionKey,\n defaults,\n );\n const nextSessionKey = resolvedSessionKey || resolvedSettingsSessionKey || host.sessionKey;\n const nextSettings = {\n ...host.settings,\n sessionKey: resolvedSettingsSessionKey || nextSessionKey,\n lastActiveSessionKey: resolvedLastActiveSessionKey || nextSessionKey,\n };\n const shouldUpdateSettings =\n nextSettings.sessionKey !== host.settings.sessionKey ||\n nextSettings.lastActiveSessionKey !== host.settings.lastActiveSessionKey;\n if (nextSessionKey !== host.sessionKey) {\n host.sessionKey = nextSessionKey;\n }\n if (shouldUpdateSettings) {\n applySettings(host as unknown as Parameters[0], nextSettings);\n }\n}\n\nexport function connectGateway(host: GatewayHost) {\n host.lastError = null;\n host.hello = null;\n host.connected = false;\n host.execApprovalQueue = [];\n host.execApprovalError = null;\n\n host.client?.stop();\n host.client = new GatewayBrowserClient({\n url: host.settings.gatewayUrl,\n token: host.settings.token.trim() ? host.settings.token : undefined,\n password: host.password.trim() ? host.password : undefined,\n clientName: \"clawdbot-control-ui\",\n mode: \"webchat\",\n onHello: (hello) => {\n host.connected = true;\n host.lastError = null;\n host.hello = hello;\n applySnapshot(host, hello);\n void loadAssistantIdentity(host as unknown as ClawdbotApp);\n void loadAgents(host as unknown as ClawdbotApp);\n void loadNodes(host as unknown as ClawdbotApp, { quiet: true });\n void loadDevices(host as unknown as ClawdbotApp, { quiet: true });\n void refreshActiveTab(host as unknown as Parameters[0]);\n },\n onClose: ({ code, reason }) => {\n host.connected = false;\n // Code 1012 = Service Restart (expected during config saves, don't show as error)\n if (code !== 1012) {\n host.lastError = `disconnected (${code}): ${reason || \"no reason\"}`;\n }\n },\n onEvent: (evt) => handleGatewayEvent(host, evt),\n onGap: ({ expected, received }) => {\n host.lastError = `event gap detected (expected seq ${expected}, got ${received}); refresh recommended`;\n },\n });\n host.client.start();\n}\n\nexport function handleGatewayEvent(host: GatewayHost, evt: GatewayEventFrame) {\n try {\n handleGatewayEventUnsafe(host, evt);\n } catch (err) {\n console.error(\"[gateway] handleGatewayEvent error:\", evt.event, err);\n }\n}\n\nfunction handleGatewayEventUnsafe(host: GatewayHost, evt: GatewayEventFrame) {\n host.eventLogBuffer = [\n { ts: Date.now(), event: evt.event, payload: evt.payload },\n ...host.eventLogBuffer,\n ].slice(0, 250);\n if (host.tab === \"debug\") {\n host.eventLog = host.eventLogBuffer;\n }\n\n if (evt.event === \"agent\") {\n if (host.onboarding) return;\n handleAgentEvent(\n host as unknown as Parameters[0],\n evt.payload as AgentEventPayload | undefined,\n );\n return;\n }\n\n if (evt.event === \"chat\") {\n const payload = evt.payload as ChatEventPayload | undefined;\n if (payload?.sessionKey) {\n setLastActiveSessionKey(\n host as unknown as Parameters[0],\n payload.sessionKey,\n );\n }\n const state = handleChatEvent(host as unknown as ClawdbotApp, payload);\n if (state === \"final\" || state === \"error\" || state === \"aborted\") {\n resetToolStream(host as unknown as Parameters[0]);\n void flushChatQueueForEvent(\n host as unknown as Parameters[0],\n );\n }\n if (state === \"final\") void loadChatHistory(host as unknown as ClawdbotApp);\n return;\n }\n\n if (evt.event === \"presence\") {\n const payload = evt.payload as { presence?: PresenceEntry[] } | undefined;\n if (payload?.presence && Array.isArray(payload.presence)) {\n host.presenceEntries = payload.presence;\n host.presenceError = null;\n host.presenceStatus = null;\n }\n return;\n }\n\n if (evt.event === \"cron\" && host.tab === \"cron\") {\n void loadCron(host as unknown as Parameters[0]);\n }\n\n if (evt.event === \"device.pair.requested\" || evt.event === \"device.pair.resolved\") {\n void loadDevices(host as unknown as ClawdbotApp, { quiet: true });\n }\n\n if (evt.event === \"exec.approval.requested\") {\n const entry = parseExecApprovalRequested(evt.payload);\n if (entry) {\n host.execApprovalQueue = addExecApproval(host.execApprovalQueue, entry);\n host.execApprovalError = null;\n const delay = Math.max(0, entry.expiresAtMs - Date.now() + 500);\n window.setTimeout(() => {\n host.execApprovalQueue = removeExecApproval(host.execApprovalQueue, entry.id);\n }, delay);\n }\n return;\n }\n\n if (evt.event === \"exec.approval.resolved\") {\n const resolved = parseExecApprovalResolved(evt.payload);\n if (resolved) {\n host.execApprovalQueue = removeExecApproval(host.execApprovalQueue, resolved.id);\n }\n }\n}\n\nexport function applySnapshot(host: GatewayHost, hello: GatewayHelloOk) {\n const snapshot = hello.snapshot as\n | {\n presence?: PresenceEntry[];\n health?: HealthSnapshot;\n sessionDefaults?: SessionDefaultsSnapshot;\n }\n | undefined;\n if (snapshot?.presence && Array.isArray(snapshot.presence)) {\n host.presenceEntries = snapshot.presence;\n }\n if (snapshot?.health) {\n host.debugHealth = snapshot.health;\n }\n if (snapshot?.sessionDefaults) {\n applySessionDefaults(host, snapshot.sessionDefaults);\n }\n}\n","import type { Tab } from \"./navigation\";\nimport { connectGateway } from \"./app-gateway\";\nimport {\n applySettingsFromUrl,\n attachThemeListener,\n detachThemeListener,\n inferBasePath,\n syncTabWithLocation,\n syncThemeWithSettings,\n} from \"./app-settings\";\nimport { observeTopbar, scheduleChatScroll, scheduleLogsScroll } from \"./app-scroll\";\nimport {\n startLogsPolling,\n startNodesPolling,\n stopLogsPolling,\n stopNodesPolling,\n startDebugPolling,\n stopDebugPolling,\n} from \"./app-polling\";\n\ntype LifecycleHost = {\n basePath: string;\n tab: Tab;\n chatHasAutoScrolled: boolean;\n chatLoading: boolean;\n chatMessages: unknown[];\n chatToolMessages: unknown[];\n chatStream: string;\n logsAutoFollow: boolean;\n logsAtBottom: boolean;\n logsEntries: unknown[];\n popStateHandler: () => void;\n topbarObserver: ResizeObserver | null;\n};\n\nexport function handleConnected(host: LifecycleHost) {\n host.basePath = inferBasePath();\n syncTabWithLocation(\n host as unknown as Parameters[0],\n true,\n );\n syncThemeWithSettings(\n host as unknown as Parameters[0],\n );\n attachThemeListener(\n host as unknown as Parameters[0],\n );\n window.addEventListener(\"popstate\", host.popStateHandler);\n applySettingsFromUrl(\n host as unknown as Parameters[0],\n );\n connectGateway(host as unknown as Parameters[0]);\n startNodesPolling(host as unknown as Parameters[0]);\n if (host.tab === \"logs\") {\n startLogsPolling(host as unknown as Parameters[0]);\n }\n if (host.tab === \"debug\") {\n startDebugPolling(host as unknown as Parameters[0]);\n }\n}\n\nexport function handleFirstUpdated(host: LifecycleHost) {\n observeTopbar(host as unknown as Parameters[0]);\n}\n\nexport function handleDisconnected(host: LifecycleHost) {\n window.removeEventListener(\"popstate\", host.popStateHandler);\n stopNodesPolling(host as unknown as Parameters[0]);\n stopLogsPolling(host as unknown as Parameters[0]);\n stopDebugPolling(host as unknown as Parameters[0]);\n detachThemeListener(\n host as unknown as Parameters[0],\n );\n host.topbarObserver?.disconnect();\n host.topbarObserver = null;\n}\n\nexport function handleUpdated(\n host: LifecycleHost,\n changed: Map,\n) {\n if (\n host.tab === \"chat\" &&\n (changed.has(\"chatMessages\") ||\n changed.has(\"chatToolMessages\") ||\n changed.has(\"chatStream\") ||\n changed.has(\"chatLoading\") ||\n changed.has(\"tab\"))\n ) {\n const forcedByTab = changed.has(\"tab\");\n const forcedByLoad =\n changed.has(\"chatLoading\") &&\n changed.get(\"chatLoading\") === true &&\n host.chatLoading === false;\n scheduleChatScroll(\n host as unknown as Parameters[0],\n forcedByTab || forcedByLoad || !host.chatHasAutoScrolled,\n );\n }\n if (\n host.tab === \"logs\" &&\n (changed.has(\"logsEntries\") || changed.has(\"logsAutoFollow\") || changed.has(\"tab\"))\n ) {\n if (host.logsAutoFollow && host.logsAtBottom) {\n scheduleLogsScroll(\n host as unknown as Parameters[0],\n changed.has(\"tab\") || changed.has(\"logsAutoFollow\"),\n );\n }\n }\n}\n","import {\n loadChannels,\n logoutWhatsApp,\n startWhatsAppLogin,\n waitWhatsAppLogin,\n} from \"./controllers/channels\";\nimport { loadConfig, saveConfig } from \"./controllers/config\";\nimport type { ClawdbotApp } from \"./app\";\nimport type { NostrProfile } from \"./types\";\nimport { createNostrProfileFormState } from \"./views/channels.nostr-profile-form\";\n\nexport async function handleWhatsAppStart(host: ClawdbotApp, force: boolean) {\n await startWhatsAppLogin(host, force);\n await loadChannels(host, true);\n}\n\nexport async function handleWhatsAppWait(host: ClawdbotApp) {\n await waitWhatsAppLogin(host);\n await loadChannels(host, true);\n}\n\nexport async function handleWhatsAppLogout(host: ClawdbotApp) {\n await logoutWhatsApp(host);\n await loadChannels(host, true);\n}\n\nexport async function handleChannelConfigSave(host: ClawdbotApp) {\n await saveConfig(host);\n await loadConfig(host);\n await loadChannels(host, true);\n}\n\nexport async function handleChannelConfigReload(host: ClawdbotApp) {\n await loadConfig(host);\n await loadChannels(host, true);\n}\n\nfunction parseValidationErrors(details: unknown): Record {\n if (!Array.isArray(details)) return {};\n const errors: Record = {};\n for (const entry of details) {\n if (typeof entry !== \"string\") continue;\n const [rawField, ...rest] = entry.split(\":\");\n if (!rawField || rest.length === 0) continue;\n const field = rawField.trim();\n const message = rest.join(\":\").trim();\n if (field && message) errors[field] = message;\n }\n return errors;\n}\n\nfunction resolveNostrAccountId(host: ClawdbotApp): string {\n const accounts = host.channelsSnapshot?.channelAccounts?.nostr ?? [];\n return accounts[0]?.accountId ?? host.nostrProfileAccountId ?? \"default\";\n}\n\nfunction buildNostrProfileUrl(accountId: string, suffix = \"\"): string {\n return `/api/channels/nostr/${encodeURIComponent(accountId)}/profile${suffix}`;\n}\n\nexport function handleNostrProfileEdit(\n host: ClawdbotApp,\n accountId: string,\n profile: NostrProfile | null,\n) {\n host.nostrProfileAccountId = accountId;\n host.nostrProfileFormState = createNostrProfileFormState(profile ?? undefined);\n}\n\nexport function handleNostrProfileCancel(host: ClawdbotApp) {\n host.nostrProfileFormState = null;\n host.nostrProfileAccountId = null;\n}\n\nexport function handleNostrProfileFieldChange(\n host: ClawdbotApp,\n field: keyof NostrProfile,\n value: string,\n) {\n const state = host.nostrProfileFormState;\n if (!state) return;\n host.nostrProfileFormState = {\n ...state,\n values: {\n ...state.values,\n [field]: value,\n },\n fieldErrors: {\n ...state.fieldErrors,\n [field]: \"\",\n },\n };\n}\n\nexport function handleNostrProfileToggleAdvanced(host: ClawdbotApp) {\n const state = host.nostrProfileFormState;\n if (!state) return;\n host.nostrProfileFormState = {\n ...state,\n showAdvanced: !state.showAdvanced,\n };\n}\n\nexport async function handleNostrProfileSave(host: ClawdbotApp) {\n const state = host.nostrProfileFormState;\n if (!state || state.saving) return;\n const accountId = resolveNostrAccountId(host);\n\n host.nostrProfileFormState = {\n ...state,\n saving: true,\n error: null,\n success: null,\n fieldErrors: {},\n };\n\n try {\n const response = await fetch(buildNostrProfileUrl(accountId), {\n method: \"PUT\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(state.values),\n });\n const data = (await response.json().catch(() => null)) as\n | { ok?: boolean; error?: string; details?: unknown; persisted?: boolean }\n | null;\n\n if (!response.ok || data?.ok === false || !data) {\n const errorMessage = data?.error ?? `Profile update failed (${response.status})`;\n host.nostrProfileFormState = {\n ...state,\n saving: false,\n error: errorMessage,\n success: null,\n fieldErrors: parseValidationErrors(data?.details),\n };\n return;\n }\n\n if (!data.persisted) {\n host.nostrProfileFormState = {\n ...state,\n saving: false,\n error: \"Profile publish failed on all relays.\",\n success: null,\n };\n return;\n }\n\n host.nostrProfileFormState = {\n ...state,\n saving: false,\n error: null,\n success: \"Profile published to relays.\",\n fieldErrors: {},\n original: { ...state.values },\n };\n await loadChannels(host, true);\n } catch (err) {\n host.nostrProfileFormState = {\n ...state,\n saving: false,\n error: `Profile update failed: ${String(err)}`,\n success: null,\n };\n }\n}\n\nexport async function handleNostrProfileImport(host: ClawdbotApp) {\n const state = host.nostrProfileFormState;\n if (!state || state.importing) return;\n const accountId = resolveNostrAccountId(host);\n\n host.nostrProfileFormState = {\n ...state,\n importing: true,\n error: null,\n success: null,\n };\n\n try {\n const response = await fetch(buildNostrProfileUrl(accountId, \"/import\"), {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({ autoMerge: true }),\n });\n const data = (await response.json().catch(() => null)) as\n | { ok?: boolean; error?: string; imported?: NostrProfile; merged?: NostrProfile; saved?: boolean }\n | null;\n\n if (!response.ok || data?.ok === false || !data) {\n const errorMessage = data?.error ?? `Profile import failed (${response.status})`;\n host.nostrProfileFormState = {\n ...state,\n importing: false,\n error: errorMessage,\n success: null,\n };\n return;\n }\n\n const merged = data.merged ?? data.imported ?? null;\n const nextValues = merged ? { ...state.values, ...merged } : state.values;\n const showAdvanced = Boolean(\n nextValues.banner || nextValues.website || nextValues.nip05 || nextValues.lud16,\n );\n\n host.nostrProfileFormState = {\n ...state,\n importing: false,\n values: nextValues,\n error: null,\n success: data.saved\n ? \"Profile imported from relays. Review and publish.\"\n : \"Profile imported. Review and publish.\",\n showAdvanced,\n };\n\n if (data.saved) {\n await loadChannels(host, true);\n }\n } catch (err) {\n host.nostrProfileFormState = {\n ...state,\n importing: false,\n error: `Profile import failed: ${String(err)}`,\n success: null,\n };\n }\n}\n","import { LitElement, html, nothing } from \"lit\";\nimport { customElement, state } from \"lit/decorators.js\";\n\nimport type { GatewayBrowserClient, GatewayHelloOk } from \"./gateway\";\nimport { resolveInjectedAssistantIdentity } from \"./assistant-identity\";\nimport { loadSettings, type UiSettings } from \"./storage\";\nimport { renderApp } from \"./app-render\";\nimport type { Tab } from \"./navigation\";\nimport type { ResolvedTheme, ThemeMode } from \"./theme\";\nimport type {\n AgentsListResult,\n ConfigSnapshot,\n ConfigUiHints,\n CronJob,\n CronRunLogEntry,\n CronStatus,\n HealthSnapshot,\n LogEntry,\n LogLevel,\n PresenceEntry,\n ChannelsStatusSnapshot,\n SessionsListResult,\n SkillStatusReport,\n StatusSummary,\n NostrProfile,\n} from \"./types\";\nimport { type ChatQueueItem, type CronFormState } from \"./ui-types\";\nimport type { EventLogEntry } from \"./app-events\";\nimport { DEFAULT_CRON_FORM, DEFAULT_LOG_LEVEL_FILTERS } from \"./app-defaults\";\nimport type {\n ExecApprovalsFile,\n ExecApprovalsSnapshot,\n} from \"./controllers/exec-approvals\";\nimport type { DevicePairingList } from \"./controllers/devices\";\nimport type { ExecApprovalRequest } from \"./controllers/exec-approval\";\nimport {\n resetToolStream as resetToolStreamInternal,\n type ToolStreamEntry,\n} from \"./app-tool-stream\";\nimport {\n exportLogs as exportLogsInternal,\n handleChatScroll as handleChatScrollInternal,\n handleLogsScroll as handleLogsScrollInternal,\n resetChatScroll as resetChatScrollInternal,\n} from \"./app-scroll\";\nimport { connectGateway as connectGatewayInternal } from \"./app-gateway\";\nimport {\n handleConnected,\n handleDisconnected,\n handleFirstUpdated,\n handleUpdated,\n} from \"./app-lifecycle\";\nimport {\n applySettings as applySettingsInternal,\n loadCron as loadCronInternal,\n loadOverview as loadOverviewInternal,\n setTab as setTabInternal,\n setTheme as setThemeInternal,\n onPopState as onPopStateInternal,\n} from \"./app-settings\";\nimport {\n handleAbortChat as handleAbortChatInternal,\n handleSendChat as handleSendChatInternal,\n removeQueuedMessage as removeQueuedMessageInternal,\n} from \"./app-chat\";\nimport {\n handleChannelConfigReload as handleChannelConfigReloadInternal,\n handleChannelConfigSave as handleChannelConfigSaveInternal,\n handleNostrProfileCancel as handleNostrProfileCancelInternal,\n handleNostrProfileEdit as handleNostrProfileEditInternal,\n handleNostrProfileFieldChange as handleNostrProfileFieldChangeInternal,\n handleNostrProfileImport as handleNostrProfileImportInternal,\n handleNostrProfileSave as handleNostrProfileSaveInternal,\n handleNostrProfileToggleAdvanced as handleNostrProfileToggleAdvancedInternal,\n handleWhatsAppLogout as handleWhatsAppLogoutInternal,\n handleWhatsAppStart as handleWhatsAppStartInternal,\n handleWhatsAppWait as handleWhatsAppWaitInternal,\n} from \"./app-channels\";\nimport type { NostrProfileFormState } from \"./views/channels.nostr-profile-form\";\nimport { loadAssistantIdentity as loadAssistantIdentityInternal } from \"./controllers/assistant-identity\";\n\ndeclare global {\n interface Window {\n __CLAWDBOT_CONTROL_UI_BASE_PATH__?: string;\n }\n}\n\nconst injectedAssistantIdentity = resolveInjectedAssistantIdentity();\n\nfunction resolveOnboardingMode(): boolean {\n if (!window.location.search) return false;\n const params = new URLSearchParams(window.location.search);\n const raw = params.get(\"onboarding\");\n if (!raw) return false;\n const normalized = raw.trim().toLowerCase();\n return normalized === \"1\" || normalized === \"true\" || normalized === \"yes\" || normalized === \"on\";\n}\n\n@customElement(\"clawdbot-app\")\nexport class ClawdbotApp extends LitElement {\n @state() settings: UiSettings = loadSettings();\n @state() password = \"\";\n @state() tab: Tab = \"chat\";\n @state() onboarding = resolveOnboardingMode();\n @state() connected = false;\n @state() theme: ThemeMode = this.settings.theme ?? \"system\";\n @state() themeResolved: ResolvedTheme = \"dark\";\n @state() hello: GatewayHelloOk | null = null;\n @state() lastError: string | null = null;\n @state() eventLog: EventLogEntry[] = [];\n private eventLogBuffer: EventLogEntry[] = [];\n private toolStreamSyncTimer: number | null = null;\n private sidebarCloseTimer: number | null = null;\n\n @state() assistantName = injectedAssistantIdentity.name;\n @state() assistantAvatar = injectedAssistantIdentity.avatar;\n @state() assistantAgentId = injectedAssistantIdentity.agentId ?? null;\n\n @state() sessionKey = this.settings.sessionKey;\n @state() chatLoading = false;\n @state() chatSending = false;\n @state() chatMessage = \"\";\n @state() chatMessages: unknown[] = [];\n @state() chatToolMessages: unknown[] = [];\n @state() chatStream: string | null = null;\n @state() chatStreamStartedAt: number | null = null;\n @state() chatRunId: string | null = null;\n @state() compactionStatus: import(\"./app-tool-stream\").CompactionStatus | null = null;\n @state() chatAvatarUrl: string | null = null;\n @state() chatThinkingLevel: string | null = null;\n @state() chatQueue: ChatQueueItem[] = [];\n // Sidebar state for tool output viewing\n @state() sidebarOpen = false;\n @state() sidebarContent: string | null = null;\n @state() sidebarError: string | null = null;\n @state() splitRatio = this.settings.splitRatio;\n\n @state() nodesLoading = false;\n @state() nodes: Array> = [];\n @state() devicesLoading = false;\n @state() devicesError: string | null = null;\n @state() devicesList: DevicePairingList | null = null;\n @state() execApprovalsLoading = false;\n @state() execApprovalsSaving = false;\n @state() execApprovalsDirty = false;\n @state() execApprovalsSnapshot: ExecApprovalsSnapshot | null = null;\n @state() execApprovalsForm: ExecApprovalsFile | null = null;\n @state() execApprovalsSelectedAgent: string | null = null;\n @state() execApprovalsTarget: \"gateway\" | \"node\" = \"gateway\";\n @state() execApprovalsTargetNodeId: string | null = null;\n @state() execApprovalQueue: ExecApprovalRequest[] = [];\n @state() execApprovalBusy = false;\n @state() execApprovalError: string | null = null;\n\n @state() configLoading = false;\n @state() configRaw = \"{\\n}\\n\";\n @state() configRawOriginal = \"\";\n @state() configValid: boolean | null = null;\n @state() configIssues: unknown[] = [];\n @state() configSaving = false;\n @state() configApplying = false;\n @state() updateRunning = false;\n @state() applySessionKey = this.settings.lastActiveSessionKey;\n @state() configSnapshot: ConfigSnapshot | null = null;\n @state() configSchema: unknown | null = null;\n @state() configSchemaVersion: string | null = null;\n @state() configSchemaLoading = false;\n @state() configUiHints: ConfigUiHints = {};\n @state() configForm: Record | null = null;\n @state() configFormOriginal: Record | null = null;\n @state() configFormDirty = false;\n @state() configFormMode: \"form\" | \"raw\" = \"form\";\n @state() configSearchQuery = \"\";\n @state() configActiveSection: string | null = null;\n @state() configActiveSubsection: string | null = null;\n\n @state() channelsLoading = false;\n @state() channelsSnapshot: ChannelsStatusSnapshot | null = null;\n @state() channelsError: string | null = null;\n @state() channelsLastSuccess: number | null = null;\n @state() whatsappLoginMessage: string | null = null;\n @state() whatsappLoginQrDataUrl: string | null = null;\n @state() whatsappLoginConnected: boolean | null = null;\n @state() whatsappBusy = false;\n @state() nostrProfileFormState: NostrProfileFormState | null = null;\n @state() nostrProfileAccountId: string | null = null;\n\n @state() presenceLoading = false;\n @state() presenceEntries: PresenceEntry[] = [];\n @state() presenceError: string | null = null;\n @state() presenceStatus: string | null = null;\n\n @state() agentsLoading = false;\n @state() agentsList: AgentsListResult | null = null;\n @state() agentsError: string | null = null;\n\n @state() sessionsLoading = false;\n @state() sessionsResult: SessionsListResult | null = null;\n @state() sessionsError: string | null = null;\n @state() sessionsFilterActive = \"\";\n @state() sessionsFilterLimit = \"120\";\n @state() sessionsIncludeGlobal = true;\n @state() sessionsIncludeUnknown = false;\n\n @state() cronLoading = false;\n @state() cronJobs: CronJob[] = [];\n @state() cronStatus: CronStatus | null = null;\n @state() cronError: string | null = null;\n @state() cronForm: CronFormState = { ...DEFAULT_CRON_FORM };\n @state() cronRunsJobId: string | null = null;\n @state() cronRuns: CronRunLogEntry[] = [];\n @state() cronBusy = false;\n\n @state() skillsLoading = false;\n @state() skillsReport: SkillStatusReport | null = null;\n @state() skillsError: string | null = null;\n @state() skillsFilter = \"\";\n @state() skillEdits: Record = {};\n @state() skillsBusyKey: string | null = null;\n @state() skillMessages: Record = {};\n\n @state() debugLoading = false;\n @state() debugStatus: StatusSummary | null = null;\n @state() debugHealth: HealthSnapshot | null = null;\n @state() debugModels: unknown[] = [];\n @state() debugHeartbeat: unknown | null = null;\n @state() debugCallMethod = \"\";\n @state() debugCallParams = \"{}\";\n @state() debugCallResult: string | null = null;\n @state() debugCallError: string | null = null;\n\n @state() logsLoading = false;\n @state() logsError: string | null = null;\n @state() logsFile: string | null = null;\n @state() logsEntries: LogEntry[] = [];\n @state() logsFilterText = \"\";\n @state() logsLevelFilters: Record = {\n ...DEFAULT_LOG_LEVEL_FILTERS,\n };\n @state() logsAutoFollow = true;\n @state() logsTruncated = false;\n @state() logsCursor: number | null = null;\n @state() logsLastFetchAt: number | null = null;\n @state() logsLimit = 500;\n @state() logsMaxBytes = 250_000;\n @state() logsAtBottom = true;\n\n client: GatewayBrowserClient | null = null;\n private chatScrollFrame: number | null = null;\n private chatScrollTimeout: number | null = null;\n private chatHasAutoScrolled = false;\n private chatUserNearBottom = true;\n private nodesPollInterval: number | null = null;\n private logsPollInterval: number | null = null;\n private debugPollInterval: number | null = null;\n private logsScrollFrame: number | null = null;\n private toolStreamById = new Map();\n private toolStreamOrder: string[] = [];\n basePath = \"\";\n private popStateHandler = () =>\n onPopStateInternal(\n this as unknown as Parameters[0],\n );\n private themeMedia: MediaQueryList | null = null;\n private themeMediaHandler: ((event: MediaQueryListEvent) => void) | null = null;\n private topbarObserver: ResizeObserver | null = null;\n\n createRenderRoot() {\n return this;\n }\n\n connectedCallback() {\n super.connectedCallback();\n handleConnected(this as unknown as Parameters[0]);\n }\n\n protected firstUpdated() {\n handleFirstUpdated(this as unknown as Parameters[0]);\n }\n\n disconnectedCallback() {\n handleDisconnected(this as unknown as Parameters[0]);\n super.disconnectedCallback();\n }\n\n protected updated(changed: Map) {\n handleUpdated(\n this as unknown as Parameters[0],\n changed,\n );\n }\n\n connect() {\n connectGatewayInternal(\n this as unknown as Parameters[0],\n );\n }\n\n handleChatScroll(event: Event) {\n handleChatScrollInternal(\n this as unknown as Parameters[0],\n event,\n );\n }\n\n handleLogsScroll(event: Event) {\n handleLogsScrollInternal(\n this as unknown as Parameters[0],\n event,\n );\n }\n\n exportLogs(lines: string[], label: string) {\n exportLogsInternal(lines, label);\n }\n\n resetToolStream() {\n resetToolStreamInternal(\n this as unknown as Parameters[0],\n );\n }\n\n resetChatScroll() {\n resetChatScrollInternal(\n this as unknown as Parameters[0],\n );\n }\n\n async loadAssistantIdentity() {\n await loadAssistantIdentityInternal(this);\n }\n\n applySettings(next: UiSettings) {\n applySettingsInternal(\n this as unknown as Parameters[0],\n next,\n );\n }\n\n setTab(next: Tab) {\n setTabInternal(this as unknown as Parameters[0], next);\n }\n\n setTheme(next: ThemeMode, context?: Parameters[2]) {\n setThemeInternal(\n this as unknown as Parameters[0],\n next,\n context,\n );\n }\n\n async loadOverview() {\n await loadOverviewInternal(\n this as unknown as Parameters[0],\n );\n }\n\n async loadCron() {\n await loadCronInternal(\n this as unknown as Parameters[0],\n );\n }\n\n async handleAbortChat() {\n await handleAbortChatInternal(\n this as unknown as Parameters[0],\n );\n }\n\n removeQueuedMessage(id: string) {\n removeQueuedMessageInternal(\n this as unknown as Parameters[0],\n id,\n );\n }\n\n async handleSendChat(\n messageOverride?: string,\n opts?: Parameters[2],\n ) {\n await handleSendChatInternal(\n this as unknown as Parameters[0],\n messageOverride,\n opts,\n );\n }\n\n async handleWhatsAppStart(force: boolean) {\n await handleWhatsAppStartInternal(this, force);\n }\n\n async handleWhatsAppWait() {\n await handleWhatsAppWaitInternal(this);\n }\n\n async handleWhatsAppLogout() {\n await handleWhatsAppLogoutInternal(this);\n }\n\n async handleChannelConfigSave() {\n await handleChannelConfigSaveInternal(this);\n }\n\n async handleChannelConfigReload() {\n await handleChannelConfigReloadInternal(this);\n }\n\n handleNostrProfileEdit(accountId: string, profile: NostrProfile | null) {\n handleNostrProfileEditInternal(this, accountId, profile);\n }\n\n handleNostrProfileCancel() {\n handleNostrProfileCancelInternal(this);\n }\n\n handleNostrProfileFieldChange(field: keyof NostrProfile, value: string) {\n handleNostrProfileFieldChangeInternal(this, field, value);\n }\n\n async handleNostrProfileSave() {\n await handleNostrProfileSaveInternal(this);\n }\n\n async handleNostrProfileImport() {\n await handleNostrProfileImportInternal(this);\n }\n\n handleNostrProfileToggleAdvanced() {\n handleNostrProfileToggleAdvancedInternal(this);\n }\n\n async handleExecApprovalDecision(decision: \"allow-once\" | \"allow-always\" | \"deny\") {\n const active = this.execApprovalQueue[0];\n if (!active || !this.client || this.execApprovalBusy) return;\n this.execApprovalBusy = true;\n this.execApprovalError = null;\n try {\n await this.client.request(\"exec.approval.resolve\", {\n id: active.id,\n decision,\n });\n this.execApprovalQueue = this.execApprovalQueue.filter((entry) => entry.id !== active.id);\n } catch (err) {\n this.execApprovalError = `Exec approval failed: ${String(err)}`;\n } finally {\n this.execApprovalBusy = false;\n }\n }\n\n // Sidebar handlers for tool output viewing\n handleOpenSidebar(content: string) {\n if (this.sidebarCloseTimer != null) {\n window.clearTimeout(this.sidebarCloseTimer);\n this.sidebarCloseTimer = null;\n }\n this.sidebarContent = content;\n this.sidebarError = null;\n this.sidebarOpen = true;\n }\n\n handleCloseSidebar() {\n this.sidebarOpen = false;\n // Clear content after transition\n if (this.sidebarCloseTimer != null) {\n window.clearTimeout(this.sidebarCloseTimer);\n }\n this.sidebarCloseTimer = window.setTimeout(() => {\n if (this.sidebarOpen) return;\n this.sidebarContent = null;\n this.sidebarError = null;\n this.sidebarCloseTimer = null;\n }, 200);\n }\n\n handleSplitRatioChange(ratio: number) {\n const newRatio = Math.max(0.4, Math.min(0.7, ratio));\n this.splitRatio = newRatio;\n this.applySettings({ ...this.settings, splitRatio: newRatio });\n }\n\n render() {\n return renderApp(this);\n }\n}\n"],"names":["t","e","s","o","n$3","r","n","i","S","c","h","a","l","p","d","u","f","b","y$2","y","v","_","m","g","$","x","E","A","C","P","V","N","S$1","I","L","z","H","M","R","k","Z","I$2","Z$1","j","B","D","MAX_ASSISTANT_NAME","MAX_ASSISTANT_AVATAR","DEFAULT_ASSISTANT_NAME","coerceIdentityValue","value","maxLength","trimmed","normalizeAssistantIdentity","input","name","avatar","resolveInjectedAssistantIdentity","KEY","loadSettings","defaults","raw","parsed","saveSettings","next","parseAgentSessionKey","sessionKey","parts","agentId","rest","TAB_GROUPS","TAB_PATHS","PATH_TO_TAB","tab","path","normalizeBasePath","basePath","base","normalizePath","normalized","pathForTab","tabFromPath","pathname","inferBasePathFromPathname","segments","candidate","prefix","iconForTab","titleForTab","subtitleForTab","icons","html","QUICK_TAG_RE","FINAL_TAG_RE","THINKING_TAG_RE","applyTrim","mode","stripReasoningTagsFromText","text","options","cleaned","result","lastIndex","inThinking","match","idx","isClose","formatMs","ms","formatAgo","diff","sec","min","hr","formatDurationMs","formatList","values","clampText","max","truncateText","toNumber","fallback","stripThinkingTags","ENVELOPE_PREFIX","ENVELOPE_CHANNELS","textCache","thinkingCache","looksLikeEnvelopeHeader","header","label","stripEnvelope","extractText","message","role","content","item","joined","extractTextCached","obj","extractThinking","rawText","extractRawText","extracted","extractThinkingCached","formatReasoningMarkdown","lines","line","uuidFromBytes","bytes","hex","weakRandomBytes","now","generateUUID","cryptoLike","loadChatHistory","state","res","err","sendChatMessage","msg","runId","error","abortChatRun","handleChatEvent","payload","current","loadSessions","params","activeMinutes","limit","patchSession","key","patch","deleteSession","TOOL_STREAM_LIMIT","TOOL_STREAM_THROTTLE_MS","TOOL_OUTPUT_CHAR_LIMIT","extractToolOutputText","record","entry","part","formatToolOutput","contentText","truncated","buildToolStreamMessage","trimToolStream","host","overflow","removed","id","syncToolStreamMessages","flushToolStreamSync","scheduleToolStreamSync","force","resetToolStream","COMPACTION_TOAST_DURATION_MS","handleCompactionEvent","data","phase","handleAgentEvent","toolCallId","args","output","scheduleChatScroll","pickScrollTarget","container","overflowY","target","distanceFromBottom","retryDelay","latest","latestDistanceFromBottom","scheduleLogsScroll","handleChatScroll","event","handleLogsScroll","resetChatScroll","exportLogs","blob","url","anchor","stamp","observeTopbar","topbar","update","height","cloneConfigObject","serializeConfigForm","form","setPathValue","nextKey","lastKey","removePathValue","loadConfig","applyConfigSnapshot","loadConfigSchema","applyConfigSchema","snapshot","rawFromSnapshot","saveConfig","baseHash","applyConfig","runUpdate","updateConfigFormValue","removeConfigFormValue","loadCronStatus","loadCronJobs","buildCronSchedule","amount","unit","expr","buildCronPayload","timeoutSeconds","addCronJob","schedule","job","toggleCronJob","enabled","runCronJob","loadCronRuns","removeCronJob","jobId","loadChannels","probe","startWhatsAppLogin","waitWhatsAppLogin","logoutWhatsApp","loadDebug","status","health","models","heartbeat","modelPayload","callDebugMethod","LOG_BUFFER_LIMIT","LEVELS","parseMaybeJsonString","normalizeLevel","lowered","parseLogLine","meta","time","level","contextCandidate","contextObj","subsystem","loadLogs","opts","entries","shouldReset","ed25519_CURVE","Gx","Gy","_a","_d","L2","captureTrace","isBig","isStr","isBytes","abytes","length","title","len","needsLen","ofLen","got","u8n","u8fr","buf","padh","pad","bytesToHex","_ch","ch","hexToBytes","hl","al","array","ai","hi","n1","n2","cr","subtle","concatBytes","arrs","sum","randomBytes","big","assertRange","modN","invert","num","md","q","callHash","fn","hashes","apoint","Point","B256","X","Y","T","zip215","normed","lastByte","bytesToNumLE","y2","isValid","uvRatio","isXOdd","isLastByteOdd","X2","Y2","Z2","Z4","aX2","left","right","XY","ZT","other","X1","Y1","Z1","X1Z2","X2Z1","Y1Z2","Y2Z1","x1y1","G","F","X3","Y3","T3","Z3","T1","T2","safe","wNAF","scalar","iz","numTo32bLE","pow2","power","pow_2_252_3","b2","b4","b5","b10","b20","b40","b80","b160","b240","b250","RM1","v3","v7","pow","vx2","root1","root2","useRoot1","useRoot2","noRoot","modL_LE","hash","sha512a","sha512s","hash2extK","hashed","head","point","pointBytes","getExtendedPublicKeyAsync","secretKey","getExtendedPublicKey","getPublicKeyAsync","hashFinishA","_sign","rBytes","signAsync","randomSecretKey","seed","utils","W","scalarBits","pwindows","pwindowSize","precompute","points","w","Gpows","ctneg","cnd","comp","pow_2_w","maxNum","mask","shiftBy","wbits","off","offF","offP","isEven","isNeg","STORAGE_KEY","base64UrlEncode","binary","byte","base64UrlDecode","padded","out","fingerprintPublicKey","publicKey","generateIdentity","privateKey","loadOrCreateDeviceIdentity","derivedId","updated","identity","stored","signDevicePayload","privateKeyBase64Url","sig","normalizeRole","normalizeScopes","scopes","scope","readStore","writeStore","store","loadDeviceAuthToken","storeDeviceAuthToken","existing","clearDeviceAuthToken","loadDevices","approveDevicePairing","requestId","rejectDevicePairing","rotateDeviceToken","revokeDeviceToken","loadNodes","resolveExecApprovalsRpc","nodeId","resolveExecApprovalsSaveRpc","loadExecApprovals","rpc","applyExecApprovalsSnapshot","saveExecApprovals","file","updateExecApprovalsFormValue","removeExecApprovalsFormValue","loadPresence","setSkillMessage","getErrorMessage","loadSkills","updateSkillEdit","skillKey","updateSkillEnabled","saveSkillApiKey","apiKey","installSkill","installId","getSystemTheme","resolveTheme","clamp01","hasReducedMotionPreference","cleanupThemeTransition","root","startThemeTransition","nextTheme","applyTheme","context","currentTheme","documentReference","document_","prefersReducedMotion","xPercent","yPercent","rect","transition","startNodesPolling","stopNodesPolling","startLogsPolling","stopLogsPolling","startDebugPolling","stopDebugPolling","applySettings","applyResolvedTheme","setLastActiveSessionKey","applySettingsFromUrl","tokenRaw","passwordRaw","sessionRaw","gatewayUrlRaw","shouldCleanUrl","token","password","session","gatewayUrl","setTab","refreshActiveTab","syncUrlWithTab","setTheme","loadOverview","loadChannelsTab","loadCron","refreshChat","inferBasePath","configured","syncThemeWithSettings","resolved","attachThemeListener","detachThemeListener","syncTabWithLocation","replace","setTabFromRoute","onPopState","targetPath","currentPath","syncUrlWithSessionKey","isChatBusy","isChatStopCommand","handleAbortChat","enqueueChatMessage","sendChatMessageNow","ok","flushChatQueue","removeQueuedMessage","handleSendChat","messageOverride","previousDraft","refreshChatAvatar","flushChatQueueForEvent","resolveAgentIdForSession","buildAvatarMetaUrl","encoded","avatarUrl","i$1","normalizeMessage","hasToolId","contentRaw","contentItems","hasToolContent","hasToolName","timestamp","normalizeRoleForGrouping","lower","isToolResultMessage","setPrototypeOf","isFrozen","getPrototypeOf","getOwnPropertyDescriptor","freeze","seal","create","apply","construct","func","thisArg","_len","_key","Func","_len2","_key2","arrayForEach","unapply","arrayLastIndexOf","arrayPop","arrayPush","arraySplice","stringToLowerCase","stringToString","stringMatch","stringReplace","stringIndexOf","stringTrim","objectHasOwnProperty","regExpTest","typeErrorCreate","unconstruct","_len3","_key3","_len4","_key4","addToSet","set","transformCaseFunc","element","lcElement","cleanArray","index","clone","object","newObject","property","lookupGetter","prop","desc","fallbackValue","html$1","svg$1","svgFilters","svgDisallowed","mathMl$1","mathMlDisallowed","svg","mathMl","xml","MUSTACHE_EXPR","ERB_EXPR","TMPLIT_EXPR","DATA_ATTR","ARIA_ATTR","IS_ALLOWED_URI","IS_SCRIPT_OR_DATA","ATTR_WHITESPACE","DOCTYPE_NAME","CUSTOM_ELEMENT","EXPRESSIONS","NODE_TYPE","getGlobal","_createTrustedTypesPolicy","trustedTypes","purifyHostElement","suffix","ATTR_NAME","policyName","scriptUrl","_createHooksMap","createDOMPurify","window","DOMPurify","document","originalDocument","currentScript","DocumentFragment","HTMLTemplateElement","Node","Element","NodeFilter","NamedNodeMap","HTMLFormElement","DOMParser","ElementPrototype","cloneNode","remove","getNextSibling","getChildNodes","getParentNode","template","trustedTypesPolicy","emptyHTML","implementation","createNodeIterator","createDocumentFragment","getElementsByTagName","importNode","hooks","IS_ALLOWED_URI$1","ALLOWED_TAGS","DEFAULT_ALLOWED_TAGS","ALLOWED_ATTR","DEFAULT_ALLOWED_ATTR","CUSTOM_ELEMENT_HANDLING","FORBID_TAGS","FORBID_ATTR","EXTRA_ELEMENT_HANDLING","ALLOW_ARIA_ATTR","ALLOW_DATA_ATTR","ALLOW_UNKNOWN_PROTOCOLS","ALLOW_SELF_CLOSE_IN_ATTR","SAFE_FOR_TEMPLATES","SAFE_FOR_XML","WHOLE_DOCUMENT","SET_CONFIG","FORCE_BODY","RETURN_DOM","RETURN_DOM_FRAGMENT","RETURN_TRUSTED_TYPE","SANITIZE_DOM","SANITIZE_NAMED_PROPS","SANITIZE_NAMED_PROPS_PREFIX","KEEP_CONTENT","IN_PLACE","USE_PROFILES","FORBID_CONTENTS","DEFAULT_FORBID_CONTENTS","DATA_URI_TAGS","DEFAULT_DATA_URI_TAGS","URI_SAFE_ATTRIBUTES","DEFAULT_URI_SAFE_ATTRIBUTES","MATHML_NAMESPACE","SVG_NAMESPACE","HTML_NAMESPACE","NAMESPACE","IS_EMPTY_INPUT","ALLOWED_NAMESPACES","DEFAULT_ALLOWED_NAMESPACES","MATHML_TEXT_INTEGRATION_POINTS","HTML_INTEGRATION_POINTS","COMMON_SVG_AND_HTML_ELEMENTS","PARSER_MEDIA_TYPE","SUPPORTED_PARSER_MEDIA_TYPES","DEFAULT_PARSER_MEDIA_TYPE","CONFIG","formElement","isRegexOrFunction","testValue","_parseConfig","cfg","ALL_SVG_TAGS","ALL_MATHML_TAGS","_checkValidNamespace","parent","tagName","parentTagName","_forceRemove","node","_removeAttribute","_initDocument","dirty","doc","leadingWhitespace","matches","dirtyPayload","body","_createNodeIterator","_isClobbered","_isNode","_executeHooks","currentNode","hook","_sanitizeElements","_isBasicCustomElement","parentNode","childNodes","childCount","childClone","_isValidAttribute","lcTag","lcName","_sanitizeAttributes","attributes","hookEvent","attr","namespaceURI","attrValue","initValue","_sanitizeShadowDOM","fragment","shadowNode","shadowIterator","importedNode","returnNode","nodeIterator","serializedHTML","tag","entryPoint","hookFunction","purify","me","xe","be","Re","Te","re","se","Oe","Q","we","ye","Pe","Se","ie","$e","U","te","_e","Le","Me","ze","oe","Ae","K","ae","Ce","le","Ie","Ee","Be","ue","qe","ve","pe","De","He","Ze","Ge","Ne","Qe","Fe","je","ce","he","Ue","ne","Ke","We","Xe","ke","J","de","ge","Je","O","ee","fe","marked","allowedTags","allowedAttrs","hooksInstalled","MARKDOWN_CHAR_LIMIT","MARKDOWN_PARSE_LIMIT","MARKDOWN_CACHE_LIMIT","MARKDOWN_CACHE_MAX_CHARS","markdownCache","getCachedMarkdown","cached","setCachedMarkdown","oldest","installHooks","toSanitizedMarkdownHtml","markdown","escapeHtml","sanitized","rendered","COPIED_FOR_MS","ERROR_FOR_MS","COPY_LABEL","COPIED_LABEL","ERROR_LABEL","copyTextToClipboard","setButtonLabel","button","createCopyButton","idleLabel","btn","copied","renderCopyAsMarkdownButton","TOOL_DISPLAY_CONFIG","rawConfig","FALLBACK","TOOL_MAP","normalizeToolName","defaultTitle","normalizeVerb","coerceDisplayValue","firstLine","preview","lookupValueByPath","segment","resolveDetailFromKeys","keys","display","resolveReadDetail","offset","resolveWriteDetail","resolveActionSpec","spec","action","resolveToolDisplay","icon","actionRaw","actionSpec","verb","detail","detailKeys","shortenHomeInString","formatToolDetail","TOOL_INLINE_THRESHOLD","PREVIEW_MAX_LINES","PREVIEW_MAX_CHARS","formatToolOutputForSidebar","getTruncatedPreview","allLines","extractToolCards","normalizeContent","cards","kind","coerceArgs","extractToolText","card","renderToolCardSidebar","onOpenSidebar","hasText","canClick","handleClick","info","isShort","showCollapsed","showInline","isEmpty","nothing","renderReadingIndicatorGroup","assistant","renderAvatar","renderStreamingGroup","startedAt","renderGroupedMessage","renderMessageGroup","group","normalizedRole","assistantName","who","roleClass","assistantAvatar","initial","className","isAvatarUrl","isToolResult","toolCards","hasToolCards","extractedText","extractedThinking","markdownBase","reasoningMarkdown","canCopyMarkdown","bubbleClasses","unsafeHTML","renderMarkdownSidebar","props","ResizableDivider","LitElement","containerWidth","deltaRatio","newRatio","css","__decorateClass","customElement","renderCompactionIndicator","renderChat","canCompose","isBusy","canAbort","reasoningLevel","row","showReasoning","assistantIdentity","composePlaceholder","splitRatio","sidebarOpen","thread","repeat","buildChatItems","CHAT_HISTORY_RENDER_LIMIT","groupMessages","items","currentGroup","history","tools","historyStart","messageKey","messageId","schemaType","schema","defaultValue","pathKey","hintForPath","hints","direct","hintKey","hint","hintSegments","humanize","isSensitivePath","META_KEYS","isAnySchema","jsonValue","renderNode","unsupported","disabled","onPatch","showLabel","type","help","nonNull","extractLiteral","literals","allLiterals","resolvedValue","lit","renderSelect","primitiveTypes","variant","normalizedTypes","hasString","hasNumber","renderTextInput","opt","renderObject","renderArray","displayValue","renderNumberInput","inputType","isSensitive","placeholder","numValue","currentIndex","unset","val","sorted","orderA","orderB","reserved","additional","allowExtra","propKey","renderMapField","itemsSchema","arr","reservedKeys","anySchema","entryValue","valuePath","sectionIcons","SECTION_META","getSectionIcon","matchesSearch","query","schemaMatches","propSchema","unions","renderConfigForm","properties","searchQuery","activeSection","activeSubsection","filteredEntries","subsectionContext","sectionSchema","sectionKey","subsectionKey","description","sectionValue","scopedValue","normalizeEnum","filtered","nullable","enumValues","analyzeConfigSchema","normalizeSchemaNode","pathLabel","union","normalizeUnion","enumNullable","normalizedProps","remaining","unique","sidebarIcons","SECTIONS","ALL_SUBSECTION","resolveSectionMeta","resolveSubsections","uiHints","subKey","order","computeDiff","original","changes","compare","orig","curr","origObj","currObj","allKeys","truncateValue","maxLen","str","renderConfig","validity","analysis","formUnsafe","schemaProps","availableSections","knownKeys","extraSections","allSections","activeSectionSchema","activeSectionMeta","subsections","allowSubnav","isAllSubsection","effectiveSubsection","hasRawChanges","hasChanges","canSaveForm","canSave","canApply","canUpdate","section","change","formatDuration","channelEnabled","channels","channelStatus","running","connected","accountActive","account","getChannelAccountCount","channelAccounts","renderChannelAccountCount","count","resolveSchemaNode","resolveChannelValue","config","channelId","fromChannels","renderChannelConfigForm","configValue","renderChannelConfigSection","renderDiscordCard","discord","accountCountLabel","renderGoogleChatCard","googleChat","renderIMessageCard","imessage","isFormDirty","renderNostrProfileForm","callbacks","accountId","isDirty","renderField","field","inputId","renderPicturePreview","picture","img","createNostrProfileFormState","profile","truncatePubkey","pubkey","renderNostrCard","nostr","nostrAccounts","profileFormState","profileFormCallbacks","onEditProfile","primaryAccount","summaryConfigured","summaryRunning","summaryPublicKey","summaryLastStartAt","summaryLastError","hasMultipleAccounts","showingForm","renderAccountCard","displayName","renderProfileSection","about","nip05","hasAnyProfileData","renderSignalCard","signal","renderSlackCard","slack","renderTelegramCard","telegram","telegramAccounts","botUsername","renderWhatsAppCard","whatsapp","renderChannels","orderedChannels","resolveChannelOrder","channel","renderChannel","showForm","renderGenericChannelCard","resolveChannelLabel","lastError","accounts","renderGenericAccount","resolveChannelMetaMap","RECENT_ACTIVITY_THRESHOLD_MS","hasRecentActivity","deriveRunningStatus","deriveConnectedStatus","runningStatus","connectedStatus","formatPresenceSummary","ip","version","formatPresenceAge","ts","formatNextRun","formatSessionTokens","total","ctx","formatEventPayload","formatCronState","last","formatCronSchedule","formatCronPayload","buildChannelOptions","seen","renderCron","channelOptions","renderScheduleFields","renderJob","renderRun","itemClass","renderDebug","evt","renderInstances","renderEntry","lastInput","roles","scopesLabel","formatTime","date","matchesFilter","needle","renderLogs","levelFiltered","exportLabel","renderNodes","bindingState","resolveBindingsState","approvalsState","resolveExecApprovalsState","renderExecApprovals","renderBindings","renderDevices","list","pending","paired","req","renderPendingDevice","device","renderPairedDevice","age","repair","tokens","renderTokenRow","deviceId","when","EXEC_APPROVALS_DEFAULT_SCOPE","SECURITY_OPTIONS","ASK_OPTIONS","nodes","resolveExecNodes","defaultBinding","agents","resolveAgentBindings","ready","normalizeSecurity","normalizeAsk","resolveExecApprovalsDefaults","resolveConfigAgents","agentsNode","isDefault","resolveExecApprovalsAgents","configAgents","approvalsAgents","merged","agent","aLabel","bLabel","resolveExecApprovalsScope","selected","targetNodes","resolveExecApprovalsNodes","targetNodeId","selectedScope","selectedAgent","allowlist","supportsBinding","renderAgentBinding","targetReady","renderExecApprovalsTarget","renderExecApprovalsTabs","renderExecApprovalsPolicy","renderExecApprovalsAllowlist","hasNodes","nodeValue","first","isDefaults","agentSecurity","agentAsk","agentAskFallback","securityValue","askValue","askFallbackValue","autoOverride","autoEffective","autoIsDefault","option","allowlistPath","renderAllowlistEntry","lastUsed","lastCommand","lastPath","bindingValue","cmd","fallbackAgent","exec","execEntry","binding","caps","commands","renderOverview","uptime","tick","authHint","hasToken","hasPassword","insecureContextHint","THINK_LEVELS","BINARY_THINK_LEVELS","VERBOSE_LEVELS","REASONING_LEVELS","normalizeProviderId","provider","isBinaryThinkingProvider","resolveThinkLevelOptions","resolveThinkLevelDisplay","isBinary","resolveThinkLevelPatchValue","renderSessions","rows","renderRow","onDelete","rawThinking","isBinaryThinking","thinking","thinkLevels","verbose","reasoning","canLink","chatUrl","formatRemaining","totalSeconds","minutes","renderMetaRow","renderExecApprovalPrompt","active","request","remainingMs","queueCount","renderSkills","skills","filter","skill","renderSkill","busy","canInstall","missing","reasons","renderTab","href","renderChatControls","sessionOptions","resolveSessionOptions","disableThinkingToggle","disableFocusToggle","showThinking","focusActive","refreshIcon","focusIcon","sessions","resolvedCurrent","THEME_ORDER","renderThemeToggle","renderMonitorIcon","renderSunIcon","renderMoonIcon","AVATAR_DATA_RE","AVATAR_HTTP_RE","resolveAssistantAvatarUrl","renderApp","presenceCount","sessionsCount","cronNext","chatDisabledReason","isChat","chatFocus","assistantAvatarUrl","chatAvatarUrl","isGroupCollapsed","hasActiveTab","agentIndex","ratio","DEFAULT_LOG_LEVEL_FILTERS","DEFAULT_CRON_FORM","loadAgents","GATEWAY_CLIENT_IDS","GATEWAY_CLIENT_NAMES","GATEWAY_CLIENT_MODES","buildDeviceAuthPayload","CONNECT_FAILED_CLOSE_CODE","GatewayBrowserClient","ev","reason","delay","isSecureContext","deviceIdentity","canFallbackToShared","authToken","storedToken","auth","signedAtMs","nonce","signature","hello","frame","seq","method","resolve","reject","isRecord","parseExecApprovalRequested","command","createdAtMs","expiresAtMs","parseExecApprovalResolved","pruneExecApprovalQueue","queue","addExecApproval","removeExecApproval","loadAssistantIdentity","normalizeSessionKeyForDefaults","mainSessionKey","mainKey","defaultAgentId","applySessionDefaults","resolvedSessionKey","resolvedSettingsSessionKey","resolvedLastActiveSessionKey","nextSessionKey","nextSettings","shouldUpdateSettings","connectGateway","applySnapshot","code","handleGatewayEvent","expected","received","handleGatewayEventUnsafe","handleConnected","handleFirstUpdated","handleDisconnected","handleUpdated","changed","forcedByTab","forcedByLoad","handleWhatsAppStart","handleWhatsAppWait","handleWhatsAppLogout","handleChannelConfigSave","handleChannelConfigReload","parseValidationErrors","details","errors","rawField","resolveNostrAccountId","buildNostrProfileUrl","handleNostrProfileEdit","handleNostrProfileCancel","handleNostrProfileFieldChange","handleNostrProfileToggleAdvanced","handleNostrProfileSave","response","errorMessage","handleNostrProfileImport","nextValues","showAdvanced","injectedAssistantIdentity","resolveOnboardingMode","ClawdbotApp","onPopStateInternal","connectGatewayInternal","handleChatScrollInternal","handleLogsScrollInternal","exportLogsInternal","resetToolStreamInternal","resetChatScrollInternal","loadAssistantIdentityInternal","applySettingsInternal","setTabInternal","setThemeInternal","loadOverviewInternal","loadCronInternal","handleAbortChatInternal","removeQueuedMessageInternal","handleSendChatInternal","handleWhatsAppStartInternal","handleWhatsAppWaitInternal","handleWhatsAppLogoutInternal","handleChannelConfigSaveInternal","handleChannelConfigReloadInternal","handleNostrProfileEditInternal","handleNostrProfileCancelInternal","handleNostrProfileFieldChangeInternal","handleNostrProfileSaveInternal","handleNostrProfileImportInternal","handleNostrProfileToggleAdvancedInternal","decision"],"mappings":"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","x_google_ignoreList":[0,1,2,3,4,5,6,26,39,40,41,43,44,45]} \ No newline at end of file diff --git a/dist/control-ui/index.html b/dist/control-ui/index.html deleted file mode 100644 index 9407eea99..000000000 --- a/dist/control-ui/index.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - Clawdbot Control - - - - - - - - - diff --git a/src/canvas-host/a2ui/a2ui.bundle.js b/src/canvas-host/a2ui/a2ui.bundle.js deleted file mode 100644 index c29280acd..000000000 --- a/src/canvas-host/a2ui/a2ui.bundle.js +++ /dev/null @@ -1,17768 +0,0 @@ -var __defProp$1 = Object.defineProperty; -var __exportAll = (all, symbols) => { - let target = {}; - for (var name in all) { - __defProp$1(target, name, { - get: all[name], - enumerable: true - }); - } - if (symbols) { - __defProp$1(target, Symbol.toStringTag, { value: "Module" }); - } - return target; -}; - -/** -* @license -* Copyright 2019 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ -const t$6 = globalThis, e$13 = t$6.ShadowRoot && (void 0 === t$6.ShadyCSS || t$6.ShadyCSS.nativeShadow) && "adoptedStyleSheets" in Document.prototype && "replace" in CSSStyleSheet.prototype, s$8 = Symbol(), o$14 = new WeakMap(); -var n$12 = class { - constructor(t$7, e$14, o$15) { - if (this._$cssResult$ = !0, o$15 !== s$8) throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead."); - this.cssText = t$7, this.t = e$14; - } - get styleSheet() { - let t$7 = this.o; - const s$9 = this.t; - if (e$13 && void 0 === t$7) { - const e$14 = void 0 !== s$9 && 1 === s$9.length; - e$14 && (t$7 = o$14.get(s$9)), void 0 === t$7 && ((this.o = t$7 = new CSSStyleSheet()).replaceSync(this.cssText), e$14 && o$14.set(s$9, t$7)); - } - return t$7; - } - toString() { - return this.cssText; - } -}; -const r$11 = (t$7) => new n$12("string" == typeof t$7 ? t$7 : t$7 + "", void 0, s$8), i$9 = (t$7, ...e$14) => { - const o$15 = 1 === t$7.length ? t$7[0] : e$14.reduce((e$15, s$9, o$16) => e$15 + ((t$8) => { - if (!0 === t$8._$cssResult$) return t$8.cssText; - if ("number" == typeof t$8) return t$8; - throw Error("Value passed to 'css' function must be a 'css' function result: " + t$8 + ". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security."); - })(s$9) + t$7[o$16 + 1], t$7[0]); - return new n$12(o$15, t$7, s$8); -}, S$1 = (s$9, o$15) => { - if (e$13) s$9.adoptedStyleSheets = o$15.map((t$7) => t$7 instanceof CSSStyleSheet ? t$7 : t$7.styleSheet); - else for (const e$14 of o$15) { - const o$16 = document.createElement("style"), n$13 = t$6.litNonce; - void 0 !== n$13 && o$16.setAttribute("nonce", n$13), o$16.textContent = e$14.cssText, s$9.appendChild(o$16); - } -}, c$6 = e$13 ? (t$7) => t$7 : (t$7) => t$7 instanceof CSSStyleSheet ? ((t$8) => { - let e$14 = ""; - for (const s$9 of t$8.cssRules) e$14 += s$9.cssText; - return r$11(e$14); -})(t$7) : t$7; - -/** -* @license -* Copyright 2017 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ const { is: i$8, defineProperty: e$12, getOwnPropertyDescriptor: h$6, getOwnPropertyNames: r$10, getOwnPropertySymbols: o$13, getPrototypeOf: n$11 } = Object, a$1 = globalThis, c$5 = a$1.trustedTypes, l$4 = c$5 ? c$5.emptyScript : "", p$2 = a$1.reactiveElementPolyfillSupport, d$2 = (t$7, s$9) => t$7, u$3 = { - toAttribute(t$7, s$9) { - switch (s$9) { - case Boolean: - t$7 = t$7 ? l$4 : null; - break; - case Object: - case Array: t$7 = null == t$7 ? t$7 : JSON.stringify(t$7); - } - return t$7; - }, - fromAttribute(t$7, s$9) { - let i$10 = t$7; - switch (s$9) { - case Boolean: - i$10 = null !== t$7; - break; - case Number: - i$10 = null === t$7 ? null : Number(t$7); - break; - case Object: - case Array: try { - i$10 = JSON.parse(t$7); - } catch (t$8) { - i$10 = null; - } - } - return i$10; - } -}, f$3 = (t$7, s$9) => !i$8(t$7, s$9), b$1 = { - attribute: !0, - type: String, - converter: u$3, - reflect: !1, - useDefault: !1, - hasChanged: f$3 -}; -Symbol.metadata ??= Symbol("metadata"), a$1.litPropertyMetadata ??= new WeakMap(); -var y$1 = class extends HTMLElement { - static addInitializer(t$7) { - this._$Ei(), (this.l ??= []).push(t$7); - } - static get observedAttributes() { - return this.finalize(), this._$Eh && [...this._$Eh.keys()]; - } - static createProperty(t$7, s$9 = b$1) { - if (s$9.state && (s$9.attribute = !1), this._$Ei(), this.prototype.hasOwnProperty(t$7) && ((s$9 = Object.create(s$9)).wrapped = !0), this.elementProperties.set(t$7, s$9), !s$9.noAccessor) { - const i$10 = Symbol(), h$7 = this.getPropertyDescriptor(t$7, i$10, s$9); - void 0 !== h$7 && e$12(this.prototype, t$7, h$7); - } - } - static getPropertyDescriptor(t$7, s$9, i$10) { - const { get: e$14, set: r$12 } = h$6(this.prototype, t$7) ?? { - get() { - return this[s$9]; - }, - set(t$8) { - this[s$9] = t$8; - } - }; - return { - get: e$14, - set(s$10) { - const h$7 = e$14?.call(this); - r$12?.call(this, s$10), this.requestUpdate(t$7, h$7, i$10); - }, - configurable: !0, - enumerable: !0 - }; - } - static getPropertyOptions(t$7) { - return this.elementProperties.get(t$7) ?? b$1; - } - static _$Ei() { - if (this.hasOwnProperty(d$2("elementProperties"))) return; - const t$7 = n$11(this); - t$7.finalize(), void 0 !== t$7.l && (this.l = [...t$7.l]), this.elementProperties = new Map(t$7.elementProperties); - } - static finalize() { - if (this.hasOwnProperty(d$2("finalized"))) return; - if (this.finalized = !0, this._$Ei(), this.hasOwnProperty(d$2("properties"))) { - const t$8 = this.properties, s$9 = [...r$10(t$8), ...o$13(t$8)]; - for (const i$10 of s$9) this.createProperty(i$10, t$8[i$10]); - } - const t$7 = this[Symbol.metadata]; - if (null !== t$7) { - const s$9 = litPropertyMetadata.get(t$7); - if (void 0 !== s$9) for (const [t$8, i$10] of s$9) this.elementProperties.set(t$8, i$10); - } - this._$Eh = new Map(); - for (const [t$8, s$9] of this.elementProperties) { - const i$10 = this._$Eu(t$8, s$9); - void 0 !== i$10 && this._$Eh.set(i$10, t$8); - } - this.elementStyles = this.finalizeStyles(this.styles); - } - static finalizeStyles(s$9) { - const i$10 = []; - if (Array.isArray(s$9)) { - const e$14 = new Set(s$9.flat(1 / 0).reverse()); - for (const s$10 of e$14) i$10.unshift(c$6(s$10)); - } else void 0 !== s$9 && i$10.push(c$6(s$9)); - return i$10; - } - static _$Eu(t$7, s$9) { - const i$10 = s$9.attribute; - return !1 === i$10 ? void 0 : "string" == typeof i$10 ? i$10 : "string" == typeof t$7 ? t$7.toLowerCase() : void 0; - } - constructor() { - super(), this._$Ep = void 0, this.isUpdatePending = !1, this.hasUpdated = !1, this._$Em = null, this._$Ev(); - } - _$Ev() { - this._$ES = new Promise((t$7) => this.enableUpdating = t$7), this._$AL = new Map(), this._$E_(), this.requestUpdate(), this.constructor.l?.forEach((t$7) => t$7(this)); - } - addController(t$7) { - (this._$EO ??= new Set()).add(t$7), void 0 !== this.renderRoot && this.isConnected && t$7.hostConnected?.(); - } - removeController(t$7) { - this._$EO?.delete(t$7); - } - _$E_() { - const t$7 = new Map(), s$9 = this.constructor.elementProperties; - for (const i$10 of s$9.keys()) this.hasOwnProperty(i$10) && (t$7.set(i$10, this[i$10]), delete this[i$10]); - t$7.size > 0 && (this._$Ep = t$7); - } - createRenderRoot() { - const t$7 = this.shadowRoot ?? this.attachShadow(this.constructor.shadowRootOptions); - return S$1(t$7, this.constructor.elementStyles), t$7; - } - connectedCallback() { - this.renderRoot ??= this.createRenderRoot(), this.enableUpdating(!0), this._$EO?.forEach((t$7) => t$7.hostConnected?.()); - } - enableUpdating(t$7) {} - disconnectedCallback() { - this._$EO?.forEach((t$7) => t$7.hostDisconnected?.()); - } - attributeChangedCallback(t$7, s$9, i$10) { - this._$AK(t$7, i$10); - } - _$ET(t$7, s$9) { - const i$10 = this.constructor.elementProperties.get(t$7), e$14 = this.constructor._$Eu(t$7, i$10); - if (void 0 !== e$14 && !0 === i$10.reflect) { - const h$7 = (void 0 !== i$10.converter?.toAttribute ? i$10.converter : u$3).toAttribute(s$9, i$10.type); - this._$Em = t$7, null == h$7 ? this.removeAttribute(e$14) : this.setAttribute(e$14, h$7), this._$Em = null; - } - } - _$AK(t$7, s$9) { - const i$10 = this.constructor, e$14 = i$10._$Eh.get(t$7); - if (void 0 !== e$14 && this._$Em !== e$14) { - const t$8 = i$10.getPropertyOptions(e$14), h$7 = "function" == typeof t$8.converter ? { fromAttribute: t$8.converter } : void 0 !== t$8.converter?.fromAttribute ? t$8.converter : u$3; - this._$Em = e$14; - const r$12 = h$7.fromAttribute(s$9, t$8.type); - this[e$14] = r$12 ?? this._$Ej?.get(e$14) ?? r$12, this._$Em = null; - } - } - requestUpdate(t$7, s$9, i$10, e$14 = !1, h$7) { - if (void 0 !== t$7) { - const r$12 = this.constructor; - if (!1 === e$14 && (h$7 = this[t$7]), i$10 ??= r$12.getPropertyOptions(t$7), !((i$10.hasChanged ?? f$3)(h$7, s$9) || i$10.useDefault && i$10.reflect && h$7 === this._$Ej?.get(t$7) && !this.hasAttribute(r$12._$Eu(t$7, i$10)))) return; - this.C(t$7, s$9, i$10); - } - !1 === this.isUpdatePending && (this._$ES = this._$EP()); - } - C(t$7, s$9, { useDefault: i$10, reflect: e$14, wrapped: h$7 }, r$12) { - i$10 && !(this._$Ej ??= new Map()).has(t$7) && (this._$Ej.set(t$7, r$12 ?? s$9 ?? this[t$7]), !0 !== h$7 || void 0 !== r$12) || (this._$AL.has(t$7) || (this.hasUpdated || i$10 || (s$9 = void 0), this._$AL.set(t$7, s$9)), !0 === e$14 && this._$Em !== t$7 && (this._$Eq ??= new Set()).add(t$7)); - } - async _$EP() { - this.isUpdatePending = !0; - try { - await this._$ES; - } catch (t$8) { - Promise.reject(t$8); - } - const t$7 = this.scheduleUpdate(); - return null != t$7 && await t$7, !this.isUpdatePending; - } - scheduleUpdate() { - return this.performUpdate(); - } - performUpdate() { - if (!this.isUpdatePending) return; - if (!this.hasUpdated) { - if (this.renderRoot ??= this.createRenderRoot(), this._$Ep) { - for (const [t$9, s$10] of this._$Ep) this[t$9] = s$10; - this._$Ep = void 0; - } - const t$8 = this.constructor.elementProperties; - if (t$8.size > 0) for (const [s$10, i$10] of t$8) { - const { wrapped: t$9 } = i$10, e$14 = this[s$10]; - !0 !== t$9 || this._$AL.has(s$10) || void 0 === e$14 || this.C(s$10, void 0, i$10, e$14); - } - } - let t$7 = !1; - const s$9 = this._$AL; - try { - t$7 = this.shouldUpdate(s$9), t$7 ? (this.willUpdate(s$9), this._$EO?.forEach((t$8) => t$8.hostUpdate?.()), this.update(s$9)) : this._$EM(); - } catch (s$10) { - throw t$7 = !1, this._$EM(), s$10; - } - t$7 && this._$AE(s$9); - } - willUpdate(t$7) {} - _$AE(t$7) { - this._$EO?.forEach((t$8) => t$8.hostUpdated?.()), this.hasUpdated || (this.hasUpdated = !0, this.firstUpdated(t$7)), this.updated(t$7); - } - _$EM() { - this._$AL = new Map(), this.isUpdatePending = !1; - } - get updateComplete() { - return this.getUpdateComplete(); - } - getUpdateComplete() { - return this._$ES; - } - shouldUpdate(t$7) { - return !0; - } - update(t$7) { - this._$Eq &&= this._$Eq.forEach((t$8) => this._$ET(t$8, this[t$8])), this._$EM(); - } - updated(t$7) {} - firstUpdated(t$7) {} -}; -y$1.elementStyles = [], y$1.shadowRootOptions = { mode: "open" }, y$1[d$2("elementProperties")] = new Map(), y$1[d$2("finalized")] = new Map(), p$2?.({ ReactiveElement: y$1 }), (a$1.reactiveElementVersions ??= []).push("2.1.2"); - -/** -* @license -* Copyright 2017 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ -const t$5 = globalThis, i$7 = (t$7) => t$7, s$7 = t$5.trustedTypes, e$11 = s$7 ? s$7.createPolicy("lit-html", { createHTML: (t$7) => t$7 }) : void 0, h$5 = "$lit$", o$12 = `lit$${Math.random().toFixed(9).slice(2)}$`, n$10 = "?" + o$12, r$9 = `<${n$10}>`, l$3 = document, c$4 = () => l$3.createComment(""), a = (t$7) => null === t$7 || "object" != typeof t$7 && "function" != typeof t$7, u$2 = Array.isArray, d$1 = (t$7) => u$2(t$7) || "function" == typeof t$7?.[Symbol.iterator], f$2 = "[ \n\f\r]", v$1 = /<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g, _ = /-->/g, m$2 = />/g, p$1 = RegExp(`>|${f$2}(?:([^\\s"'>=/]+)(${f$2}*=${f$2}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`, "g"), g = /'/g, $ = /"/g, y = /^(?:script|style|textarea|title)$/i, x = (t$7) => (i$10, ...s$9) => ({ - _$litType$: t$7, - strings: i$10, - values: s$9 -}), b = x(1), w = x(2), T = x(3), E = Symbol.for("lit-noChange"), A = Symbol.for("lit-nothing"), C = new WeakMap(), P = l$3.createTreeWalker(l$3, 129); -function V(t$7, i$10) { - if (!u$2(t$7) || !t$7.hasOwnProperty("raw")) throw Error("invalid template strings array"); - return void 0 !== e$11 ? e$11.createHTML(i$10) : i$10; -} -const N = (t$7, i$10) => { - const s$9 = t$7.length - 1, e$14 = []; - let n$13, l$5 = 2 === i$10 ? "" : 3 === i$10 ? "" : "", c$7 = v$1; - for (let i$11 = 0; i$11 < s$9; i$11++) { - const s$10 = t$7[i$11]; - let a, u$4, d$3 = -1, f$4 = 0; - for (; f$4 < s$10.length && (c$7.lastIndex = f$4, u$4 = c$7.exec(s$10), null !== u$4);) f$4 = c$7.lastIndex, c$7 === v$1 ? "!--" === u$4[1] ? c$7 = _ : void 0 !== u$4[1] ? c$7 = m$2 : void 0 !== u$4[2] ? (y.test(u$4[2]) && (n$13 = RegExp("" === u$4[0] ? (c$7 = n$13 ?? v$1, d$3 = -1) : void 0 === u$4[1] ? d$3 = -2 : (d$3 = c$7.lastIndex - u$4[2].length, a = u$4[1], c$7 = void 0 === u$4[3] ? p$1 : "\"" === u$4[3] ? $ : g) : c$7 === $ || c$7 === g ? c$7 = p$1 : c$7 === _ || c$7 === m$2 ? c$7 = v$1 : (c$7 = p$1, n$13 = void 0); - const x = c$7 === p$1 && t$7[i$11 + 1].startsWith("/>") ? " " : ""; - l$5 += c$7 === v$1 ? s$10 + r$9 : d$3 >= 0 ? (e$14.push(a), s$10.slice(0, d$3) + h$5 + s$10.slice(d$3) + o$12 + x) : s$10 + o$12 + (-2 === d$3 ? i$11 : x); - } - return [V(t$7, l$5 + (t$7[s$9] || "") + (2 === i$10 ? "" : 3 === i$10 ? "" : "")), e$14]; -}; -var S = class S { - constructor({ strings: t$7, _$litType$: i$10 }, e$14) { - let r$12; - this.parts = []; - let l$5 = 0, a = 0; - const u$4 = t$7.length - 1, d$3 = this.parts, [f$4, v$2] = N(t$7, i$10); - if (this.el = S.createElement(f$4, e$14), P.currentNode = this.el.content, 2 === i$10 || 3 === i$10) { - const t$8 = this.el.content.firstChild; - t$8.replaceWith(...t$8.childNodes); - } - for (; null !== (r$12 = P.nextNode()) && d$3.length < u$4;) { - if (1 === r$12.nodeType) { - if (r$12.hasAttributes()) for (const t$8 of r$12.getAttributeNames()) if (t$8.endsWith(h$5)) { - const i$11 = v$2[a++], s$9 = r$12.getAttribute(t$8).split(o$12), e$15 = /([.?@])?(.*)/.exec(i$11); - d$3.push({ - type: 1, - index: l$5, - name: e$15[2], - strings: s$9, - ctor: "." === e$15[1] ? I : "?" === e$15[1] ? L : "@" === e$15[1] ? z : H - }), r$12.removeAttribute(t$8); - } else t$8.startsWith(o$12) && (d$3.push({ - type: 6, - index: l$5 - }), r$12.removeAttribute(t$8)); - if (y.test(r$12.tagName)) { - const t$8 = r$12.textContent.split(o$12), i$11 = t$8.length - 1; - if (i$11 > 0) { - r$12.textContent = s$7 ? s$7.emptyScript : ""; - for (let s$9 = 0; s$9 < i$11; s$9++) r$12.append(t$8[s$9], c$4()), P.nextNode(), d$3.push({ - type: 2, - index: ++l$5 - }); - r$12.append(t$8[i$11], c$4()); - } - } - } else if (8 === r$12.nodeType) if (r$12.data === n$10) d$3.push({ - type: 2, - index: l$5 - }); - else { - let t$8 = -1; - for (; -1 !== (t$8 = r$12.data.indexOf(o$12, t$8 + 1));) d$3.push({ - type: 7, - index: l$5 - }), t$8 += o$12.length - 1; - } - l$5++; - } - } - static createElement(t$7, i$10) { - const s$9 = l$3.createElement("template"); - return s$9.innerHTML = t$7, s$9; - } -}; -function M$1(t$7, i$10, s$9 = t$7, e$14) { - if (i$10 === E) return i$10; - let h$7 = void 0 !== e$14 ? s$9._$Co?.[e$14] : s$9._$Cl; - const o$15 = a(i$10) ? void 0 : i$10._$litDirective$; - return h$7?.constructor !== o$15 && (h$7?._$AO?.(!1), void 0 === o$15 ? h$7 = void 0 : (h$7 = new o$15(t$7), h$7._$AT(t$7, s$9, e$14)), void 0 !== e$14 ? (s$9._$Co ??= [])[e$14] = h$7 : s$9._$Cl = h$7), void 0 !== h$7 && (i$10 = M$1(t$7, h$7._$AS(t$7, i$10.values), h$7, e$14)), i$10; -} -var R = class { - constructor(t$7, i$10) { - this._$AV = [], this._$AN = void 0, this._$AD = t$7, this._$AM = i$10; - } - get parentNode() { - return this._$AM.parentNode; - } - get _$AU() { - return this._$AM._$AU; - } - u(t$7) { - const { el: { content: i$10 }, parts: s$9 } = this._$AD, e$14 = (t$7?.creationScope ?? l$3).importNode(i$10, !0); - P.currentNode = e$14; - let h$7 = P.nextNode(), o$15 = 0, n$13 = 0, r$12 = s$9[0]; - for (; void 0 !== r$12;) { - if (o$15 === r$12.index) { - let i$11; - 2 === r$12.type ? i$11 = new k(h$7, h$7.nextSibling, this, t$7) : 1 === r$12.type ? i$11 = new r$12.ctor(h$7, r$12.name, r$12.strings, this, t$7) : 6 === r$12.type && (i$11 = new Z(h$7, this, t$7)), this._$AV.push(i$11), r$12 = s$9[++n$13]; - } - o$15 !== r$12?.index && (h$7 = P.nextNode(), o$15++); - } - return P.currentNode = l$3, e$14; - } - p(t$7) { - let i$10 = 0; - for (const s$9 of this._$AV) void 0 !== s$9 && (void 0 !== s$9.strings ? (s$9._$AI(t$7, s$9, i$10), i$10 += s$9.strings.length - 2) : s$9._$AI(t$7[i$10])), i$10++; - } -}; -var k = class k { - get _$AU() { - return this._$AM?._$AU ?? this._$Cv; - } - constructor(t$7, i$10, s$9, e$14) { - this.type = 2, this._$AH = A, this._$AN = void 0, this._$AA = t$7, this._$AB = i$10, this._$AM = s$9, this.options = e$14, this._$Cv = e$14?.isConnected ?? !0; - } - get parentNode() { - let t$7 = this._$AA.parentNode; - const i$10 = this._$AM; - return void 0 !== i$10 && 11 === t$7?.nodeType && (t$7 = i$10.parentNode), t$7; - } - get startNode() { - return this._$AA; - } - get endNode() { - return this._$AB; - } - _$AI(t$7, i$10 = this) { - t$7 = M$1(this, t$7, i$10), a(t$7) ? t$7 === A || null == t$7 || "" === t$7 ? (this._$AH !== A && this._$AR(), this._$AH = A) : t$7 !== this._$AH && t$7 !== E && this._(t$7) : void 0 !== t$7._$litType$ ? this.$(t$7) : void 0 !== t$7.nodeType ? this.T(t$7) : d$1(t$7) ? this.k(t$7) : this._(t$7); - } - O(t$7) { - return this._$AA.parentNode.insertBefore(t$7, this._$AB); - } - T(t$7) { - this._$AH !== t$7 && (this._$AR(), this._$AH = this.O(t$7)); - } - _(t$7) { - this._$AH !== A && a(this._$AH) ? this._$AA.nextSibling.data = t$7 : this.T(l$3.createTextNode(t$7)), this._$AH = t$7; - } - $(t$7) { - const { values: i$10, _$litType$: s$9 } = t$7, e$14 = "number" == typeof s$9 ? this._$AC(t$7) : (void 0 === s$9.el && (s$9.el = S.createElement(V(s$9.h, s$9.h[0]), this.options)), s$9); - if (this._$AH?._$AD === e$14) this._$AH.p(i$10); - else { - const t$8 = new R(e$14, this), s$10 = t$8.u(this.options); - t$8.p(i$10), this.T(s$10), this._$AH = t$8; - } - } - _$AC(t$7) { - let i$10 = C.get(t$7.strings); - return void 0 === i$10 && C.set(t$7.strings, i$10 = new S(t$7)), i$10; - } - k(t$7) { - u$2(this._$AH) || (this._$AH = [], this._$AR()); - const i$10 = this._$AH; - let s$9, e$14 = 0; - for (const h$7 of t$7) e$14 === i$10.length ? i$10.push(s$9 = new k(this.O(c$4()), this.O(c$4()), this, this.options)) : s$9 = i$10[e$14], s$9._$AI(h$7), e$14++; - e$14 < i$10.length && (this._$AR(s$9 && s$9._$AB.nextSibling, e$14), i$10.length = e$14); - } - _$AR(t$7 = this._$AA.nextSibling, s$9) { - for (this._$AP?.(!1, !0, s$9); t$7 !== this._$AB;) { - const s$10 = i$7(t$7).nextSibling; - i$7(t$7).remove(), t$7 = s$10; - } - } - setConnected(t$7) { - void 0 === this._$AM && (this._$Cv = t$7, this._$AP?.(t$7)); - } -}; -var H = class { - get tagName() { - return this.element.tagName; - } - get _$AU() { - return this._$AM._$AU; - } - constructor(t$7, i$10, s$9, e$14, h$7) { - this.type = 1, this._$AH = A, this._$AN = void 0, this.element = t$7, this.name = i$10, this._$AM = e$14, this.options = h$7, s$9.length > 2 || "" !== s$9[0] || "" !== s$9[1] ? (this._$AH = Array(s$9.length - 1).fill(new String()), this.strings = s$9) : this._$AH = A; - } - _$AI(t$7, i$10 = this, s$9, e$14) { - const h$7 = this.strings; - let o$15 = !1; - if (void 0 === h$7) t$7 = M$1(this, t$7, i$10, 0), o$15 = !a(t$7) || t$7 !== this._$AH && t$7 !== E, o$15 && (this._$AH = t$7); - else { - const e$15 = t$7; - let n$13, r$12; - for (t$7 = h$7[0], n$13 = 0; n$13 < h$7.length - 1; n$13++) r$12 = M$1(this, e$15[s$9 + n$13], i$10, n$13), r$12 === E && (r$12 = this._$AH[n$13]), o$15 ||= !a(r$12) || r$12 !== this._$AH[n$13], r$12 === A ? t$7 = A : t$7 !== A && (t$7 += (r$12 ?? "") + h$7[n$13 + 1]), this._$AH[n$13] = r$12; - } - o$15 && !e$14 && this.j(t$7); - } - j(t$7) { - t$7 === A ? this.element.removeAttribute(this.name) : this.element.setAttribute(this.name, t$7 ?? ""); - } -}; -var I = class extends H { - constructor() { - super(...arguments), this.type = 3; - } - j(t$7) { - this.element[this.name] = t$7 === A ? void 0 : t$7; - } -}; -var L = class extends H { - constructor() { - super(...arguments), this.type = 4; - } - j(t$7) { - this.element.toggleAttribute(this.name, !!t$7 && t$7 !== A); - } -}; -var z = class extends H { - constructor(t$7, i$10, s$9, e$14, h$7) { - super(t$7, i$10, s$9, e$14, h$7), this.type = 5; - } - _$AI(t$7, i$10 = this) { - if ((t$7 = M$1(this, t$7, i$10, 0) ?? A) === E) return; - const s$9 = this._$AH, e$14 = t$7 === A && s$9 !== A || t$7.capture !== s$9.capture || t$7.once !== s$9.once || t$7.passive !== s$9.passive, h$7 = t$7 !== A && (s$9 === A || e$14); - e$14 && this.element.removeEventListener(this.name, this, s$9), h$7 && this.element.addEventListener(this.name, this, t$7), this._$AH = t$7; - } - handleEvent(t$7) { - "function" == typeof this._$AH ? this._$AH.call(this.options?.host ?? this.element, t$7) : this._$AH.handleEvent(t$7); - } -}; -var Z = class { - constructor(t$7, i$10, s$9) { - this.element = t$7, this.type = 6, this._$AN = void 0, this._$AM = i$10, this.options = s$9; - } - get _$AU() { - return this._$AM._$AU; - } - _$AI(t$7) { - M$1(this, t$7); - } -}; -const j$1 = { - M: h$5, - P: o$12, - A: n$10, - C: 1, - L: N, - R, - D: d$1, - V: M$1, - I: k, - H, - N: L, - U: z, - B: I, - F: Z -}, B = t$5.litHtmlPolyfillSupport; -B?.(S, k), (t$5.litHtmlVersions ??= []).push("3.3.2"); -const D = (t$7, i$10, s$9) => { - const e$14 = s$9?.renderBefore ?? i$10; - let h$7 = e$14._$litPart$; - if (void 0 === h$7) { - const t$8 = s$9?.renderBefore ?? null; - e$14._$litPart$ = h$7 = new k(i$10.insertBefore(c$4(), t$8), t$8, void 0, s$9 ?? {}); - } - return h$7._$AI(t$7), h$7; -}; - -/** -* @license -* Copyright 2017 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ const s$6 = globalThis; -var i$6 = class extends y$1 { - constructor() { - super(...arguments), this.renderOptions = { host: this }, this._$Do = void 0; - } - createRenderRoot() { - const t$7 = super.createRenderRoot(); - return this.renderOptions.renderBefore ??= t$7.firstChild, t$7; - } - update(t$7) { - const r$12 = this.render(); - this.hasUpdated || (this.renderOptions.isConnected = this.isConnected), super.update(t$7), this._$Do = D(r$12, this.renderRoot, this.renderOptions); - } - connectedCallback() { - super.connectedCallback(), this._$Do?.setConnected(!0); - } - disconnectedCallback() { - super.disconnectedCallback(), this._$Do?.setConnected(!1); - } - render() { - return E; - } -}; -i$6._$litElement$ = !0, i$6["finalized"] = !0, s$6.litElementHydrateSupport?.({ LitElement: i$6 }); -const o$11 = s$6.litElementPolyfillSupport; -o$11?.({ LitElement: i$6 }); -const n$9 = { - _$AK: (t$7, e$14, r$12) => { - t$7._$AK(e$14, r$12); - }, - _$AL: (t$7) => t$7._$AL -}; -(s$6.litElementVersions ??= []).push("4.2.2"); - -/** -* @license -* Copyright 2022 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ -const o$10 = !1; - -/** -* @license -* Copyright 2017 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ -const t$4 = { - ATTRIBUTE: 1, - CHILD: 2, - PROPERTY: 3, - BOOLEAN_ATTRIBUTE: 4, - EVENT: 5, - ELEMENT: 6 -}, e$10 = (t$7) => (...e$14) => ({ - _$litDirective$: t$7, - values: e$14 -}); -var i$5 = class { - constructor(t$7) {} - get _$AU() { - return this._$AM._$AU; - } - _$AT(t$7, e$14, i$10) { - this._$Ct = t$7, this._$AM = e$14, this._$Ci = i$10; - } - _$AS(t$7, e$14) { - return this.update(t$7, e$14); - } - update(t$7, e$14) { - return this.render(...e$14); - } -}; - -/** -* @license -* Copyright 2020 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ const { I: t$3 } = j$1, i$4 = (o$15) => o$15, n$8 = (o$15) => null === o$15 || "object" != typeof o$15 && "function" != typeof o$15, e$9 = { - HTML: 1, - SVG: 2, - MATHML: 3 -}, l$2 = (o$15, t$7) => void 0 === t$7 ? void 0 !== o$15?._$litType$ : o$15?._$litType$ === t$7, d = (o$15) => null != o$15?._$litType$?.h, c$3 = (o$15) => void 0 !== o$15?._$litDirective$, f$1 = (o$15) => o$15?._$litDirective$, r$8 = (o$15) => void 0 === o$15.strings, s$5 = () => document.createComment(""), v = (o$15, n$13, e$14) => { - const l$5 = o$15._$AA.parentNode, d = void 0 === n$13 ? o$15._$AB : n$13._$AA; - if (void 0 === e$14) { - const i$10 = l$5.insertBefore(s$5(), d), n$14 = l$5.insertBefore(s$5(), d); - e$14 = new t$3(i$10, n$14, o$15, o$15.options); - } else { - const t$7 = e$14._$AB.nextSibling, n$14 = e$14._$AM, c$7 = n$14 !== o$15; - if (c$7) { - let t$8; - e$14._$AQ?.(o$15), e$14._$AM = o$15, void 0 !== e$14._$AP && (t$8 = o$15._$AU) !== n$14._$AU && e$14._$AP(t$8); - } - if (t$7 !== d || c$7) { - let o$16 = e$14._$AA; - for (; o$16 !== t$7;) { - const t$8 = i$4(o$16).nextSibling; - i$4(l$5).insertBefore(o$16, d), o$16 = t$8; - } - } - } - return e$14; -}, u$1 = (o$15, t$7, i$10 = o$15) => (o$15._$AI(t$7, i$10), o$15), m$1 = {}, p = (o$15, t$7 = m$1) => o$15._$AH = t$7, M = (o$15) => o$15._$AH, h$4 = (o$15) => { - o$15._$AR(), o$15._$AA.remove(); -}, j = (o$15) => { - o$15._$AR(); -}; - -/** -* @license -* Copyright 2017 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ -const u = (e$14, s$9, t$7) => { - const r$12 = new Map(); - for (let l$5 = s$9; l$5 <= t$7; l$5++) r$12.set(e$14[l$5], l$5); - return r$12; -}, c$2 = e$10(class extends i$5 { - constructor(e$14) { - if (super(e$14), e$14.type !== t$4.CHILD) throw Error("repeat() can only be used in text expressions"); - } - dt(e$14, s$9, t$7) { - let r$12; - void 0 === t$7 ? t$7 = s$9 : void 0 !== s$9 && (r$12 = s$9); - const l$5 = [], o$15 = []; - let i$10 = 0; - for (const s$10 of e$14) l$5[i$10] = r$12 ? r$12(s$10, i$10) : i$10, o$15[i$10] = t$7(s$10, i$10), i$10++; - return { - values: o$15, - keys: l$5 - }; - } - render(e$14, s$9, t$7) { - return this.dt(e$14, s$9, t$7).values; - } - update(s$9, [t$7, r$12, c$7]) { - const d$3 = M(s$9), { values: p$3, keys: a$2 } = this.dt(t$7, r$12, c$7); - if (!Array.isArray(d$3)) return this.ut = a$2, p$3; - const h$7 = this.ut ??= [], v$2 = []; - let m$3, y$2, x$1 = 0, j$2 = d$3.length - 1, k$1 = 0, w$1 = p$3.length - 1; - for (; x$1 <= j$2 && k$1 <= w$1;) if (null === d$3[x$1]) x$1++; - else if (null === d$3[j$2]) j$2--; - else if (h$7[x$1] === a$2[k$1]) v$2[k$1] = u$1(d$3[x$1], p$3[k$1]), x$1++, k$1++; - else if (h$7[j$2] === a$2[w$1]) v$2[w$1] = u$1(d$3[j$2], p$3[w$1]), j$2--, w$1--; - else if (h$7[x$1] === a$2[w$1]) v$2[w$1] = u$1(d$3[x$1], p$3[w$1]), v(s$9, v$2[w$1 + 1], d$3[x$1]), x$1++, w$1--; - else if (h$7[j$2] === a$2[k$1]) v$2[k$1] = u$1(d$3[j$2], p$3[k$1]), v(s$9, d$3[x$1], d$3[j$2]), j$2--, k$1++; - else if (void 0 === m$3 && (m$3 = u(a$2, k$1, w$1), y$2 = u(h$7, x$1, j$2)), m$3.has(h$7[x$1])) if (m$3.has(h$7[j$2])) { - const e$14 = y$2.get(a$2[k$1]), t$8 = void 0 !== e$14 ? d$3[e$14] : null; - if (null === t$8) { - const e$15 = v(s$9, d$3[x$1]); - u$1(e$15, p$3[k$1]), v$2[k$1] = e$15; - } else v$2[k$1] = u$1(t$8, p$3[k$1]), v(s$9, d$3[x$1], t$8), d$3[e$14] = null; - k$1++; - } else h$4(d$3[j$2]), j$2--; - else h$4(d$3[x$1]), x$1++; - for (; k$1 <= w$1;) { - const e$14 = v(s$9, v$2[w$1 + 1]); - u$1(e$14, p$3[k$1]), v$2[k$1++] = e$14; - } - for (; x$1 <= j$2;) { - const e$14 = d$3[x$1++]; - null !== e$14 && h$4(e$14); - } - return this.ut = a$2, p(s$9, v$2), E; - } -}); - -/** -* @license -* Copyright 2021 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ -var s$4 = class extends Event { - constructor(s$9, t$7, e$14, o$15) { - super("context-request", { - bubbles: !0, - composed: !0 - }), this.context = s$9, this.contextTarget = t$7, this.callback = e$14, this.subscribe = o$15 ?? !1; - } -}; - -/** -* @license -* Copyright 2021 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ -function n$7(n$13) { - return n$13; -} - -/** -* @license -* Copyright 2021 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ var s$3 = class { - constructor(t$7, s$9, i$10, h$7) { - if (this.subscribe = !1, this.provided = !1, this.value = void 0, this.t = (t$8, s$10) => { - this.unsubscribe && (this.unsubscribe !== s$10 && (this.provided = !1, this.unsubscribe()), this.subscribe || this.unsubscribe()), this.value = t$8, this.host.requestUpdate(), this.provided && !this.subscribe || (this.provided = !0, this.callback && this.callback(t$8, s$10)), this.unsubscribe = s$10; - }, this.host = t$7, void 0 !== s$9.context) { - const t$8 = s$9; - this.context = t$8.context, this.callback = t$8.callback, this.subscribe = t$8.subscribe ?? !1; - } else this.context = s$9, this.callback = i$10, this.subscribe = h$7 ?? !1; - this.host.addController(this); - } - hostConnected() { - this.dispatchRequest(); - } - hostDisconnected() { - this.unsubscribe && (this.unsubscribe(), this.unsubscribe = void 0); - } - dispatchRequest() { - this.host.dispatchEvent(new s$4(this.context, this.host, this.t, this.subscribe)); - } -}; - -/** -* @license -* Copyright 2021 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ -var s$2 = class { - get value() { - return this.o; - } - set value(s$9) { - this.setValue(s$9); - } - setValue(s$9, t$7 = !1) { - const i$10 = t$7 || !Object.is(s$9, this.o); - this.o = s$9, i$10 && this.updateObservers(); - } - constructor(s$9) { - this.subscriptions = new Map(), this.updateObservers = () => { - for (const [s$10, { disposer: t$7 }] of this.subscriptions) s$10(this.o, t$7); - }, void 0 !== s$9 && (this.value = s$9); - } - addCallback(s$9, t$7, i$10) { - if (!i$10) return void s$9(this.value); - this.subscriptions.has(s$9) || this.subscriptions.set(s$9, { - disposer: () => { - this.subscriptions.delete(s$9); - }, - consumerHost: t$7 - }); - const { disposer: h$7 } = this.subscriptions.get(s$9); - s$9(this.value, h$7); - } - clearCallbacks() { - this.subscriptions.clear(); - } -}; - -/** -* @license -* Copyright 2021 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ var e$8 = class extends Event { - constructor(t$7, s$9) { - super("context-provider", { - bubbles: !0, - composed: !0 - }), this.context = t$7, this.contextTarget = s$9; - } -}; -var i$3 = class extends s$2 { - constructor(s$9, e$14, i$10) { - super(void 0 !== e$14.context ? e$14.initialValue : i$10), this.onContextRequest = (t$7) => { - if (t$7.context !== this.context) return; - const s$10 = t$7.contextTarget ?? t$7.composedPath()[0]; - s$10 !== this.host && (t$7.stopPropagation(), this.addCallback(t$7.callback, s$10, t$7.subscribe)); - }, this.onProviderRequest = (s$10) => { - if (s$10.context !== this.context) return; - if ((s$10.contextTarget ?? s$10.composedPath()[0]) === this.host) return; - const e$15 = new Set(); - for (const [s$11, { consumerHost: i$11 }] of this.subscriptions) e$15.has(s$11) || (e$15.add(s$11), i$11.dispatchEvent(new s$4(this.context, i$11, s$11, !0))); - s$10.stopPropagation(); - }, this.host = s$9, void 0 !== e$14.context ? this.context = e$14.context : this.context = e$14, this.attachListeners(), this.host.addController?.(this); - } - attachListeners() { - this.host.addEventListener("context-request", this.onContextRequest), this.host.addEventListener("context-provider", this.onProviderRequest); - } - hostConnected() { - this.host.dispatchEvent(new e$8(this.context, this.host)); - } -}; - -/** -* @license -* Copyright 2021 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ var t$2 = class { - constructor() { - this.pendingContextRequests = new Map(), this.onContextProvider = (t$7) => { - const s$9 = this.pendingContextRequests.get(t$7.context); - if (void 0 === s$9) return; - this.pendingContextRequests.delete(t$7.context); - const { requests: o$15 } = s$9; - for (const { elementRef: s$10, callbackRef: n$13 } of o$15) { - const o$16 = s$10.deref(), c$7 = n$13.deref(); - void 0 === o$16 || void 0 === c$7 || o$16.dispatchEvent(new s$4(t$7.context, o$16, c$7, !0)); - } - }, this.onContextRequest = (e$14) => { - if (!0 !== e$14.subscribe) return; - const t$7 = e$14.contextTarget ?? e$14.composedPath()[0], s$9 = e$14.callback; - let o$15 = this.pendingContextRequests.get(e$14.context); - void 0 === o$15 && this.pendingContextRequests.set(e$14.context, o$15 = { - callbacks: new WeakMap(), - requests: [] - }); - let n$13 = o$15.callbacks.get(t$7); - void 0 === n$13 && o$15.callbacks.set(t$7, n$13 = new WeakSet()), n$13.has(s$9) || (n$13.add(s$9), o$15.requests.push({ - elementRef: new WeakRef(t$7), - callbackRef: new WeakRef(s$9) - })); - }; - } - attach(e$14) { - e$14.addEventListener("context-request", this.onContextRequest), e$14.addEventListener("context-provider", this.onContextProvider); - } - detach(e$14) { - e$14.removeEventListener("context-request", this.onContextRequest), e$14.removeEventListener("context-provider", this.onContextProvider); - } -}; - -/** -* @license -* Copyright 2017 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ function e$7({ context: e$14 }) { - return (n$13, i$10) => { - const r$12 = new WeakMap(); - if ("object" == typeof i$10) return { - get() { - return n$13.get.call(this); - }, - set(t$7) { - return r$12.get(this).setValue(t$7), n$13.set.call(this, t$7); - }, - init(n$14) { - return r$12.set(this, new i$3(this, { - context: e$14, - initialValue: n$14 - })), n$14; - } - }; - { - n$13.constructor.addInitializer(((n$14) => { - r$12.set(n$14, new i$3(n$14, { context: e$14 })); - })); - const o$15 = Object.getOwnPropertyDescriptor(n$13, i$10); - let s$9; - if (void 0 === o$15) { - const t$7 = new WeakMap(); - s$9 = { - get() { - return t$7.get(this); - }, - set(e$15) { - r$12.get(this).setValue(e$15), t$7.set(this, e$15); - }, - configurable: !0, - enumerable: !0 - }; - } else { - const t$7 = o$15.set; - s$9 = { - ...o$15, - set(e$15) { - r$12.get(this).setValue(e$15), t$7?.call(this, e$15); - } - }; - } - return void Object.defineProperty(n$13, i$10, s$9); - } - }; -} - -/** -* @license -* Copyright 2022 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ function c$1({ context: c$7, subscribe: e$14 }) { - return (o$15, n$13) => { - "object" == typeof n$13 ? n$13.addInitializer((function() { - new s$3(this, { - context: c$7, - callback: (t$7) => { - o$15.set.call(this, t$7); - }, - subscribe: e$14 - }); - })) : o$15.constructor.addInitializer(((o$16) => { - new s$3(o$16, { - context: c$7, - callback: (t$7) => { - o$16[n$13] = t$7; - }, - subscribe: e$14 - }); - })); - }; -} - -const eventInit = { - bubbles: true, - cancelable: true, - composed: true -}; -var StateEvent = class StateEvent extends CustomEvent { - static { - this.eventName = "a2uiaction"; - } - constructor(payload) { - super(StateEvent.eventName, { - detail: payload, - ...eventInit - }); - this.payload = payload; - } -}; - -const opacityBehavior = ` - &:not([disabled]) { - cursor: pointer; - opacity: var(--opacity, 0); - transition: opacity var(--speed, 0.2s) cubic-bezier(0, 0, 0.3, 1); - - &:hover, - &:focus { - opacity: 1; - } - }`; -const behavior = ` - ${new Array(21).fill(0).map((_$1, idx) => { - return `.behavior-ho-${idx * 5} { - --opacity: ${idx / 20}; - ${opacityBehavior} - }`; -}).join("\n")} - - .behavior-o-s { - overflow: scroll; - } - - .behavior-o-a { - overflow: auto; - } - - .behavior-o-h { - overflow: hidden; - } - - .behavior-sw-n { - scrollbar-width: none; - } -`; - -const grid = 4; - -const border = ` - ${new Array(25).fill(0).map((_$1, idx) => { - return ` - .border-bw-${idx} { border-width: ${idx}px; } - .border-btw-${idx} { border-top-width: ${idx}px; } - .border-bbw-${idx} { border-bottom-width: ${idx}px; } - .border-blw-${idx} { border-left-width: ${idx}px; } - .border-brw-${idx} { border-right-width: ${idx}px; } - - .border-ow-${idx} { outline-width: ${idx}px; } - .border-br-${idx} { border-radius: ${idx * grid}px; overflow: hidden;}`; -}).join("\n")} - - .border-br-50pc { - border-radius: 50%; - } - - .border-bs-s { - border-style: solid; - } -`; - -const shades = [ - 0, - 5, - 10, - 15, - 20, - 25, - 30, - 35, - 40, - 50, - 60, - 70, - 80, - 90, - 95, - 98, - 99, - 100 -]; - -function merge(...classes) { - const styles = {}; - for (const clazz of classes) { - for (const [key, val] of Object.entries(clazz)) { - const prefix = key.split("-").with(-1, "").join("-"); - const existingKeys = Object.keys(styles).filter((key$1) => key$1.startsWith(prefix)); - for (const existingKey of existingKeys) { - delete styles[existingKey]; - } - styles[key] = val; - } - } - return styles; -} -function appendToAll(target, exclusions, ...classes) { - const updatedTarget = structuredClone(target); - for (const clazz of classes) { - for (const key of Object.keys(clazz)) { - const prefix = key.split("-").with(-1, "").join("-"); - for (const [tagName, classesToAdd] of Object.entries(updatedTarget)) { - if (exclusions.includes(tagName)) { - continue; - } - let found = false; - for (let t$7 = 0; t$7 < classesToAdd.length; t$7++) { - if (classesToAdd[t$7].startsWith(prefix)) { - found = true; - classesToAdd[t$7] = key; - } - } - if (!found) { - classesToAdd.push(key); - } - } - } - } - return updatedTarget; -} -function createThemeStyles(palettes) { - const styles = {}; - for (const palette of Object.values(palettes)) { - for (const [key, val] of Object.entries(palette)) { - const prop = toProp(key); - styles[prop] = val; - } - } - return styles; -} -function toProp(key) { - if (key.startsWith("nv")) { - return `--nv-${key.slice(2)}`; - } - return `--${key[0]}-${key.slice(1)}`; -} - -const color = (src) => ` - ${src.map((key) => { - const inverseKey = getInverseKey(key); - return `.color-bc-${key} { border-color: light-dark(var(${toProp(key)}), var(${toProp(inverseKey)})); }`; -}).join("\n")} - - ${src.map((key) => { - const inverseKey = getInverseKey(key); - const vals = [`.color-bgc-${key} { background-color: light-dark(var(${toProp(key)}), var(${toProp(inverseKey)})); }`, `.color-bbgc-${key}::backdrop { background-color: light-dark(var(${toProp(key)}), var(${toProp(inverseKey)})); }`]; - for (let o$15 = .1; o$15 < 1; o$15 += .1) { - vals.push(`.color-bbgc-${key}_${(o$15 * 100).toFixed(0)}::backdrop { - background-color: light-dark(oklch(from var(${toProp(key)}) l c h / calc(alpha * ${o$15.toFixed(1)})), oklch(from var(${toProp(inverseKey)}) l c h / calc(alpha * ${o$15.toFixed(1)})) ); - } - `); - } - return vals.join("\n"); -}).join("\n")} - - ${src.map((key) => { - const inverseKey = getInverseKey(key); - return `.color-c-${key} { color: light-dark(var(${toProp(key)}), var(${toProp(inverseKey)})); }`; -}).join("\n")} - `; -const getInverseKey = (key) => { - const match = key.match(/^([a-z]+)(\d+)$/); - if (!match) return key; - const [, prefix, shadeStr] = match; - const shade = parseInt(shadeStr, 10); - const target = 100 - shade; - const inverseShade = shades.reduce((prev, curr) => Math.abs(curr - target) < Math.abs(prev - target) ? curr : prev); - return `${prefix}${inverseShade}`; -}; -const keyFactory = (prefix) => { - return shades.map((v$2) => `${prefix}${v$2}`); -}; -const colors = [ - color(keyFactory("p")), - color(keyFactory("s")), - color(keyFactory("t")), - color(keyFactory("n")), - color(keyFactory("nv")), - color(keyFactory("e")), - ` - .color-bgc-transparent { - background-color: transparent; - } - - :host { - color-scheme: var(--color-scheme); - } - ` -]; - -/** -* CSS classes for Google Symbols. -* -* Usage: -* -* ```html -* pen_spark -* ``` -*/ -const icons = ` - .g-icon { - font-family: "Material Symbols Outlined", "Google Symbols"; - font-weight: normal; - font-style: normal; - font-display: optional; - font-size: 20px; - width: 1em; - height: 1em; - user-select: none; - line-height: 1; - letter-spacing: normal; - text-transform: none; - display: inline-block; - white-space: nowrap; - word-wrap: normal; - direction: ltr; - -webkit-font-feature-settings: "liga"; - -webkit-font-smoothing: antialiased; - overflow: hidden; - - font-variation-settings: "FILL" 0, "wght" 300, "GRAD" 0, "opsz" 48, - "ROND" 100; - - &.filled { - font-variation-settings: "FILL" 1, "wght" 300, "GRAD" 0, "opsz" 48, - "ROND" 100; - } - - &.filled-heavy { - font-variation-settings: "FILL" 1, "wght" 700, "GRAD" 0, "opsz" 48, - "ROND" 100; - } - } -`; - -const layout = ` - :host { - ${new Array(16).fill(0).map((_$1, idx) => { - return `--g-${idx + 1}: ${(idx + 1) * grid}px;`; -}).join("\n")} - } - - ${new Array(49).fill(0).map((_$1, index) => { - const idx = index - 24; - const lbl = idx < 0 ? `n${Math.abs(idx)}` : idx.toString(); - return ` - .layout-p-${lbl} { --padding: ${idx * grid}px; padding: var(--padding); } - .layout-pt-${lbl} { padding-top: ${idx * grid}px; } - .layout-pr-${lbl} { padding-right: ${idx * grid}px; } - .layout-pb-${lbl} { padding-bottom: ${idx * grid}px; } - .layout-pl-${lbl} { padding-left: ${idx * grid}px; } - - .layout-m-${lbl} { --margin: ${idx * grid}px; margin: var(--margin); } - .layout-mt-${lbl} { margin-top: ${idx * grid}px; } - .layout-mr-${lbl} { margin-right: ${idx * grid}px; } - .layout-mb-${lbl} { margin-bottom: ${idx * grid}px; } - .layout-ml-${lbl} { margin-left: ${idx * grid}px; } - - .layout-t-${lbl} { top: ${idx * grid}px; } - .layout-r-${lbl} { right: ${idx * grid}px; } - .layout-b-${lbl} { bottom: ${idx * grid}px; } - .layout-l-${lbl} { left: ${idx * grid}px; }`; -}).join("\n")} - - ${new Array(25).fill(0).map((_$1, idx) => { - return ` - .layout-g-${idx} { gap: ${idx * grid}px; }`; -}).join("\n")} - - ${new Array(8).fill(0).map((_$1, idx) => { - return ` - .layout-grd-col${idx + 1} { grid-template-columns: ${"1fr ".repeat(idx + 1).trim()}; }`; -}).join("\n")} - - .layout-pos-a { - position: absolute; - } - - .layout-pos-rel { - position: relative; - } - - .layout-dsp-none { - display: none; - } - - .layout-dsp-block { - display: block; - } - - .layout-dsp-grid { - display: grid; - } - - .layout-dsp-iflex { - display: inline-flex; - } - - .layout-dsp-flexvert { - display: flex; - flex-direction: column; - } - - .layout-dsp-flexhor { - display: flex; - flex-direction: row; - } - - .layout-fw-w { - flex-wrap: wrap; - } - - .layout-al-fs { - align-items: start; - } - - .layout-al-fe { - align-items: end; - } - - .layout-al-c { - align-items: center; - } - - .layout-as-n { - align-self: normal; - } - - .layout-js-c { - justify-self: center; - } - - .layout-sp-c { - justify-content: center; - } - - .layout-sp-ev { - justify-content: space-evenly; - } - - .layout-sp-bt { - justify-content: space-between; - } - - .layout-sp-s { - justify-content: start; - } - - .layout-sp-e { - justify-content: end; - } - - .layout-ji-e { - justify-items: end; - } - - .layout-r-none { - resize: none; - } - - .layout-fs-c { - field-sizing: content; - } - - .layout-fs-n { - field-sizing: none; - } - - .layout-flx-0 { - flex: 0 0 auto; - } - - .layout-flx-1 { - flex: 1 0 auto; - } - - .layout-c-s { - contain: strict; - } - - /** Widths **/ - - ${new Array(10).fill(0).map((_$1, idx) => { - const weight = (idx + 1) * 10; - return `.layout-w-${weight} { width: ${weight}%; max-width: ${weight}%; }`; -}).join("\n")} - - ${new Array(16).fill(0).map((_$1, idx) => { - const weight = idx * grid; - return `.layout-wp-${idx} { width: ${weight}px; }`; -}).join("\n")} - - /** Heights **/ - - ${new Array(10).fill(0).map((_$1, idx) => { - const height = (idx + 1) * 10; - return `.layout-h-${height} { height: ${height}%; }`; -}).join("\n")} - - ${new Array(16).fill(0).map((_$1, idx) => { - const height = idx * grid; - return `.layout-hp-${idx} { height: ${height}px; }`; -}).join("\n")} - - .layout-el-cv { - & img, - & video { - width: 100%; - height: 100%; - object-fit: cover; - margin: 0; - } - } - - .layout-ar-sq { - aspect-ratio: 1 / 1; - } - - .layout-ex-fb { - margin: calc(var(--padding) * -1) 0 0 calc(var(--padding) * -1); - width: calc(100% + var(--padding) * 2); - height: calc(100% + var(--padding) * 2); - } -`; - -const opacity = ` - ${new Array(21).fill(0).map((_$1, idx) => { - return `.opacity-el-${idx * 5} { opacity: ${idx / 20}; }`; -}).join("\n")} -`; - -const type$1 = ` - :host { - --default-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - --default-font-family-mono: "Courier New", Courier, monospace; - } - - .typography-f-s { - font-family: var(--font-family, var(--default-font-family)); - font-optical-sizing: auto; - font-variation-settings: "slnt" 0, "wdth" 100, "GRAD" 0; - } - - .typography-f-sf { - font-family: var(--font-family-flex, var(--default-font-family)); - font-optical-sizing: auto; - } - - .typography-f-c { - font-family: var(--font-family-mono, var(--default-font-family)); - font-optical-sizing: auto; - font-variation-settings: "slnt" 0, "wdth" 100, "GRAD" 0; - } - - .typography-v-r { - font-variation-settings: "slnt" 0, "wdth" 100, "GRAD" 0, "ROND" 100; - } - - .typography-ta-s { - text-align: start; - } - - .typography-ta-c { - text-align: center; - } - - .typography-fs-n { - font-style: normal; - } - - .typography-fs-i { - font-style: italic; - } - - .typography-sz-ls { - font-size: 11px; - line-height: 16px; - } - - .typography-sz-lm { - font-size: 12px; - line-height: 16px; - } - - .typography-sz-ll { - font-size: 14px; - line-height: 20px; - } - - .typography-sz-bs { - font-size: 12px; - line-height: 16px; - } - - .typography-sz-bm { - font-size: 14px; - line-height: 20px; - } - - .typography-sz-bl { - font-size: 16px; - line-height: 24px; - } - - .typography-sz-ts { - font-size: 14px; - line-height: 20px; - } - - .typography-sz-tm { - font-size: 16px; - line-height: 24px; - } - - .typography-sz-tl { - font-size: 22px; - line-height: 28px; - } - - .typography-sz-hs { - font-size: 24px; - line-height: 32px; - } - - .typography-sz-hm { - font-size: 28px; - line-height: 36px; - } - - .typography-sz-hl { - font-size: 32px; - line-height: 40px; - } - - .typography-sz-ds { - font-size: 36px; - line-height: 44px; - } - - .typography-sz-dm { - font-size: 45px; - line-height: 52px; - } - - .typography-sz-dl { - font-size: 57px; - line-height: 64px; - } - - .typography-ws-p { - white-space: pre-line; - } - - .typography-ws-nw { - white-space: nowrap; - } - - .typography-td-none { - text-decoration: none; - } - - /** Weights **/ - - ${new Array(9).fill(0).map((_$1, idx) => { - const weight = (idx + 1) * 100; - return `.typography-w-${weight} { font-weight: ${weight}; }`; -}).join("\n")} -`; - -const structuralStyles$1 = [ - behavior, - border, - colors, - icons, - layout, - opacity, - type$1 -].flat(Infinity).join("\n"); - -var guards_exports = /* @__PURE__ */ __exportAll({ - isComponentArrayReference: () => isComponentArrayReference, - isObject: () => isObject$1, - isPath: () => isPath, - isResolvedAudioPlayer: () => isResolvedAudioPlayer, - isResolvedButton: () => isResolvedButton, - isResolvedCard: () => isResolvedCard, - isResolvedCheckbox: () => isResolvedCheckbox, - isResolvedColumn: () => isResolvedColumn, - isResolvedDateTimeInput: () => isResolvedDateTimeInput, - isResolvedDivider: () => isResolvedDivider, - isResolvedIcon: () => isResolvedIcon, - isResolvedImage: () => isResolvedImage, - isResolvedList: () => isResolvedList, - isResolvedModal: () => isResolvedModal, - isResolvedMultipleChoice: () => isResolvedMultipleChoice, - isResolvedRow: () => isResolvedRow, - isResolvedSlider: () => isResolvedSlider, - isResolvedTabs: () => isResolvedTabs, - isResolvedText: () => isResolvedText, - isResolvedTextField: () => isResolvedTextField, - isResolvedVideo: () => isResolvedVideo, - isValueMap: () => isValueMap -}); -function isValueMap(value) { - return isObject$1(value) && "key" in value; -} -function isPath(key, value) { - return key === "path" && typeof value === "string"; -} -function isObject$1(value) { - return typeof value === "object" && value !== null && !Array.isArray(value); -} -function isComponentArrayReference(value) { - if (!isObject$1(value)) return false; - return "explicitList" in value || "template" in value; -} -function isStringValue(value) { - return isObject$1(value) && ("path" in value || "literal" in value && typeof value.literal === "string" || "literalString" in value); -} -function isNumberValue(value) { - return isObject$1(value) && ("path" in value || "literal" in value && typeof value.literal === "number" || "literalNumber" in value); -} -function isBooleanValue(value) { - return isObject$1(value) && ("path" in value || "literal" in value && typeof value.literal === "boolean" || "literalBoolean" in value); -} -function isAnyComponentNode(value) { - if (!isObject$1(value)) return false; - const hasBaseKeys = "id" in value && "type" in value && "properties" in value; - if (!hasBaseKeys) return false; - return true; -} -function isResolvedAudioPlayer(props) { - return isObject$1(props) && "url" in props && isStringValue(props.url); -} -function isResolvedButton(props) { - return isObject$1(props) && "child" in props && isAnyComponentNode(props.child) && "action" in props; -} -function isResolvedCard(props) { - if (!isObject$1(props)) return false; - if (!("child" in props)) { - if (!("children" in props)) { - return false; - } else { - return Array.isArray(props.children) && props.children.every(isAnyComponentNode); - } - } - return isAnyComponentNode(props.child); -} -function isResolvedCheckbox(props) { - return isObject$1(props) && "label" in props && isStringValue(props.label) && "value" in props && isBooleanValue(props.value); -} -function isResolvedColumn(props) { - return isObject$1(props) && "children" in props && Array.isArray(props.children) && props.children.every(isAnyComponentNode); -} -function isResolvedDateTimeInput(props) { - return isObject$1(props) && "value" in props && isStringValue(props.value); -} -function isResolvedDivider(props) { - return isObject$1(props); -} -function isResolvedImage(props) { - return isObject$1(props) && "url" in props && isStringValue(props.url); -} -function isResolvedIcon(props) { - return isObject$1(props) && "name" in props && isStringValue(props.name); -} -function isResolvedList(props) { - return isObject$1(props) && "children" in props && Array.isArray(props.children) && props.children.every(isAnyComponentNode); -} -function isResolvedModal(props) { - return isObject$1(props) && "entryPointChild" in props && isAnyComponentNode(props.entryPointChild) && "contentChild" in props && isAnyComponentNode(props.contentChild); -} -function isResolvedMultipleChoice(props) { - return isObject$1(props) && "selections" in props; -} -function isResolvedRow(props) { - return isObject$1(props) && "children" in props && Array.isArray(props.children) && props.children.every(isAnyComponentNode); -} -function isResolvedSlider(props) { - return isObject$1(props) && "value" in props && isNumberValue(props.value); -} -function isResolvedTabItem(item) { - return isObject$1(item) && "title" in item && isStringValue(item.title) && "child" in item && isAnyComponentNode(item.child); -} -function isResolvedTabs(props) { - return isObject$1(props) && "tabItems" in props && Array.isArray(props.tabItems) && props.tabItems.every(isResolvedTabItem); -} -function isResolvedText(props) { - return isObject$1(props) && "text" in props && isStringValue(props.text); -} -function isResolvedTextField(props) { - return isObject$1(props) && "label" in props && isStringValue(props.label); -} -function isResolvedVideo(props) { - return isObject$1(props) && "url" in props && isStringValue(props.url); -} - -/** -* Processes and consolidates A2UIProtocolMessage objects into a structured, -* hierarchical model of UI surfaces. -*/ -var A2uiMessageProcessor = class A2uiMessageProcessor { - static { - this.DEFAULT_SURFACE_ID = "@default"; - } - #mapCtor = Map; - #arrayCtor = Array; - #setCtor = Set; - #objCtor = Object; - #surfaces; - constructor(opts = { - mapCtor: Map, - arrayCtor: Array, - setCtor: Set, - objCtor: Object - }) { - this.opts = opts; - this.#arrayCtor = opts.arrayCtor; - this.#mapCtor = opts.mapCtor; - this.#setCtor = opts.setCtor; - this.#objCtor = opts.objCtor; - this.#surfaces = new opts.mapCtor(); - } - getSurfaces() { - return this.#surfaces; - } - clearSurfaces() { - this.#surfaces.clear(); - } - processMessages(messages) { - for (const message of messages) { - if (message.beginRendering) { - this.#handleBeginRendering(message.beginRendering, message.beginRendering.surfaceId); - } - if (message.surfaceUpdate) { - this.#handleSurfaceUpdate(message.surfaceUpdate, message.surfaceUpdate.surfaceId); - } - if (message.dataModelUpdate) { - this.#handleDataModelUpdate(message.dataModelUpdate, message.dataModelUpdate.surfaceId); - } - if (message.deleteSurface) { - this.#handleDeleteSurface(message.deleteSurface); - } - } - } - /** - * Retrieves the data for a given component node and a relative path string. - * This correctly handles the special `.` path, which refers to the node's - * own data context. - */ - getData(node, relativePath, surfaceId = A2uiMessageProcessor.DEFAULT_SURFACE_ID) { - const surface = this.#getOrCreateSurface(surfaceId); - if (!surface) return null; - let finalPath; - if (relativePath === "." || relativePath === "") { - finalPath = node.dataContextPath ?? "/"; - } else { - finalPath = this.resolvePath(relativePath, node.dataContextPath); - } - return this.#getDataByPath(surface.dataModel, finalPath); - } - setData(node, relativePath, value, surfaceId = A2uiMessageProcessor.DEFAULT_SURFACE_ID) { - if (!node) { - console.warn("No component node set"); - return; - } - const surface = this.#getOrCreateSurface(surfaceId); - if (!surface) return; - let finalPath; - if (relativePath === "." || relativePath === "") { - finalPath = node.dataContextPath ?? "/"; - } else { - finalPath = this.resolvePath(relativePath, node.dataContextPath); - } - this.#setDataByPath(surface.dataModel, finalPath, value); - } - resolvePath(path, dataContextPath) { - if (path.startsWith("/")) { - return path; - } - if (dataContextPath && dataContextPath !== "/") { - return dataContextPath.endsWith("/") ? `${dataContextPath}${path}` : `${dataContextPath}/${path}`; - } - return `/${path}`; - } - #parseIfJsonString(value) { - if (typeof value !== "string") { - return value; - } - const trimmedValue = value.trim(); - if (trimmedValue.startsWith("{") && trimmedValue.endsWith("}") || trimmedValue.startsWith("[") && trimmedValue.endsWith("]")) { - try { - return JSON.parse(value); - } catch (e$14) { - console.warn(`Failed to parse potential JSON string: "${value.substring(0, 50)}..."`, e$14); - return value; - } - } - return value; - } - /** - * Converts a specific array format [{key: "...", value_string: "..."}, ...] - * into a standard Map. It also attempts to parse any string values that - * appear to be stringified JSON. - */ - #convertKeyValueArrayToMap(arr) { - const map$1 = new this.#mapCtor(); - for (const item of arr) { - if (!isObject$1(item) || !("key" in item)) continue; - const key = item.key; - const valueKey = this.#findValueKey(item); - if (!valueKey) continue; - let value = item[valueKey]; - if (valueKey === "valueMap" && Array.isArray(value)) { - value = this.#convertKeyValueArrayToMap(value); - } else if (typeof value === "string") { - value = this.#parseIfJsonString(value); - } - this.#setDataByPath(map$1, key, value); - } - return map$1; - } - #setDataByPath(root, path, value) { - if (Array.isArray(value) && (value.length === 0 || isObject$1(value[0]) && "key" in value[0])) { - if (value.length === 1 && isObject$1(value[0]) && value[0].key === ".") { - const item = value[0]; - const valueKey = this.#findValueKey(item); - if (valueKey) { - value = item[valueKey]; - if (valueKey === "valueMap" && Array.isArray(value)) { - value = this.#convertKeyValueArrayToMap(value); - } else if (typeof value === "string") { - value = this.#parseIfJsonString(value); - } - } else { - value = this.#convertKeyValueArrayToMap(value); - } - } else { - value = this.#convertKeyValueArrayToMap(value); - } - } - const segments = this.#normalizePath(path).split("/").filter((s$9) => s$9); - if (segments.length === 0) { - if (value instanceof Map || isObject$1(value)) { - if (!(value instanceof Map) && isObject$1(value)) { - value = new this.#mapCtor(Object.entries(value)); - } - root.clear(); - for (const [key, v$2] of value.entries()) { - root.set(key, v$2); - } - } else { - console.error("Cannot set root of DataModel to a non-Map value."); - } - return; - } - let current = root; - for (let i$10 = 0; i$10 < segments.length - 1; i$10++) { - const segment = segments[i$10]; - let target; - if (current instanceof Map) { - target = current.get(segment); - } else if (Array.isArray(current) && /^\d+$/.test(segment)) { - target = current[parseInt(segment, 10)]; - } - if (target === undefined || typeof target !== "object" || target === null) { - target = new this.#mapCtor(); - if (current instanceof this.#mapCtor) { - current.set(segment, target); - } else if (Array.isArray(current)) { - current[parseInt(segment, 10)] = target; - } - } - current = target; - } - const finalSegment = segments[segments.length - 1]; - const storedValue = value; - if (current instanceof this.#mapCtor) { - current.set(finalSegment, storedValue); - } else if (Array.isArray(current) && /^\d+$/.test(finalSegment)) { - current[parseInt(finalSegment, 10)] = storedValue; - } - } - /** - * Normalizes a path string into a consistent, slash-delimited format. - * Converts bracket notation and dot notation in a two-pass. - * e.g., "bookRecommendations[0].title" -> "/bookRecommendations/0/title" - * e.g., "book.0.title" -> "/book/0/title" - */ - #normalizePath(path) { - const dotPath = path.replace(/\[(\d+)\]/g, ".$1"); - const segments = dotPath.split("."); - return "/" + segments.filter((s$9) => s$9.length > 0).join("/"); - } - #getDataByPath(root, path) { - const segments = this.#normalizePath(path).split("/").filter((s$9) => s$9); - let current = root; - for (const segment of segments) { - if (current === undefined || current === null) return null; - if (current instanceof Map) { - current = current.get(segment); - } else if (Array.isArray(current) && /^\d+$/.test(segment)) { - current = current[parseInt(segment, 10)]; - } else if (isObject$1(current)) { - current = current[segment]; - } else { - return null; - } - } - return current; - } - #getOrCreateSurface(surfaceId) { - let surface = this.#surfaces.get(surfaceId); - if (!surface) { - surface = new this.#objCtor({ - rootComponentId: null, - componentTree: null, - dataModel: new this.#mapCtor(), - components: new this.#mapCtor(), - styles: new this.#objCtor() - }); - this.#surfaces.set(surfaceId, surface); - } - return surface; - } - #handleBeginRendering(message, surfaceId) { - const surface = this.#getOrCreateSurface(surfaceId); - surface.rootComponentId = message.root; - surface.styles = message.styles ?? {}; - this.#rebuildComponentTree(surface); - } - #handleSurfaceUpdate(message, surfaceId) { - const surface = this.#getOrCreateSurface(surfaceId); - for (const component of message.components) { - surface.components.set(component.id, component); - } - this.#rebuildComponentTree(surface); - } - #handleDataModelUpdate(message, surfaceId) { - const surface = this.#getOrCreateSurface(surfaceId); - const path = message.path ?? "/"; - this.#setDataByPath(surface.dataModel, path, message.contents); - this.#rebuildComponentTree(surface); - } - #handleDeleteSurface(message) { - this.#surfaces.delete(message.surfaceId); - } - /** - * Starts at the root component of the surface and builds out the tree - * recursively. This process involves resolving all properties of the child - * components, and expanding on any explicit children lists or templates - * found in the structure. - * - * @param surface The surface to be built. - */ - #rebuildComponentTree(surface) { - if (!surface.rootComponentId) { - surface.componentTree = null; - return; - } - const visited = new this.#setCtor(); - surface.componentTree = this.#buildNodeRecursive(surface.rootComponentId, surface, visited, "/", ""); - } - /** Finds a value key in a map. */ - #findValueKey(value) { - return Object.keys(value).find((k$1) => k$1.startsWith("value")); - } - /** - * Builds out the nodes recursively. - */ - #buildNodeRecursive(baseComponentId, surface, visited, dataContextPath, idSuffix = "") { - const fullId = `${baseComponentId}${idSuffix}`; - const { components } = surface; - if (!components.has(baseComponentId)) { - return null; - } - if (visited.has(fullId)) { - throw new Error(`Circular dependency for component "${fullId}".`); - } - visited.add(fullId); - const componentData = components.get(baseComponentId); - const componentProps = componentData.component ?? {}; - const componentType = Object.keys(componentProps)[0]; - const unresolvedProperties = componentProps[componentType]; - const resolvedProperties = new this.#objCtor(); - if (isObject$1(unresolvedProperties)) { - for (const [key, value] of Object.entries(unresolvedProperties)) { - resolvedProperties[key] = this.#resolvePropertyValue(value, surface, visited, dataContextPath, idSuffix, key); - } - } - visited.delete(fullId); - const baseNode = { - id: fullId, - dataContextPath, - weight: componentData.weight ?? "initial" - }; - switch (componentType) { - case "Text": - if (!isResolvedText(resolvedProperties)) { - throw new Error(`Invalid data; expected ${componentType}`); - } - return new this.#objCtor({ - ...baseNode, - type: "Text", - properties: resolvedProperties - }); - case "Image": - if (!isResolvedImage(resolvedProperties)) { - throw new Error(`Invalid data; expected ${componentType}`); - } - return new this.#objCtor({ - ...baseNode, - type: "Image", - properties: resolvedProperties - }); - case "Icon": - if (!isResolvedIcon(resolvedProperties)) { - throw new Error(`Invalid data; expected ${componentType}`); - } - return new this.#objCtor({ - ...baseNode, - type: "Icon", - properties: resolvedProperties - }); - case "Video": - if (!isResolvedVideo(resolvedProperties)) { - throw new Error(`Invalid data; expected ${componentType}`); - } - return new this.#objCtor({ - ...baseNode, - type: "Video", - properties: resolvedProperties - }); - case "AudioPlayer": - if (!isResolvedAudioPlayer(resolvedProperties)) { - throw new Error(`Invalid data; expected ${componentType}`); - } - return new this.#objCtor({ - ...baseNode, - type: "AudioPlayer", - properties: resolvedProperties - }); - case "Row": - if (!isResolvedRow(resolvedProperties)) { - throw new Error(`Invalid data; expected ${componentType}`); - } - return new this.#objCtor({ - ...baseNode, - type: "Row", - properties: resolvedProperties - }); - case "Column": - if (!isResolvedColumn(resolvedProperties)) { - throw new Error(`Invalid data; expected ${componentType}`); - } - return new this.#objCtor({ - ...baseNode, - type: "Column", - properties: resolvedProperties - }); - case "List": - if (!isResolvedList(resolvedProperties)) { - throw new Error(`Invalid data; expected ${componentType}`); - } - return new this.#objCtor({ - ...baseNode, - type: "List", - properties: resolvedProperties - }); - case "Card": - if (!isResolvedCard(resolvedProperties)) { - throw new Error(`Invalid data; expected ${componentType}`); - } - return new this.#objCtor({ - ...baseNode, - type: "Card", - properties: resolvedProperties - }); - case "Tabs": - if (!isResolvedTabs(resolvedProperties)) { - throw new Error(`Invalid data; expected ${componentType}`); - } - return new this.#objCtor({ - ...baseNode, - type: "Tabs", - properties: resolvedProperties - }); - case "Divider": - if (!isResolvedDivider(resolvedProperties)) { - throw new Error(`Invalid data; expected ${componentType}`); - } - return new this.#objCtor({ - ...baseNode, - type: "Divider", - properties: resolvedProperties - }); - case "Modal": - if (!isResolvedModal(resolvedProperties)) { - throw new Error(`Invalid data; expected ${componentType}`); - } - return new this.#objCtor({ - ...baseNode, - type: "Modal", - properties: resolvedProperties - }); - case "Button": - if (!isResolvedButton(resolvedProperties)) { - throw new Error(`Invalid data; expected ${componentType}`); - } - return new this.#objCtor({ - ...baseNode, - type: "Button", - properties: resolvedProperties - }); - case "CheckBox": - if (!isResolvedCheckbox(resolvedProperties)) { - throw new Error(`Invalid data; expected ${componentType}`); - } - return new this.#objCtor({ - ...baseNode, - type: "CheckBox", - properties: resolvedProperties - }); - case "TextField": - if (!isResolvedTextField(resolvedProperties)) { - throw new Error(`Invalid data; expected ${componentType}`); - } - return new this.#objCtor({ - ...baseNode, - type: "TextField", - properties: resolvedProperties - }); - case "DateTimeInput": - if (!isResolvedDateTimeInput(resolvedProperties)) { - throw new Error(`Invalid data; expected ${componentType}`); - } - return new this.#objCtor({ - ...baseNode, - type: "DateTimeInput", - properties: resolvedProperties - }); - case "MultipleChoice": - if (!isResolvedMultipleChoice(resolvedProperties)) { - throw new Error(`Invalid data; expected ${componentType}`); - } - return new this.#objCtor({ - ...baseNode, - type: "MultipleChoice", - properties: resolvedProperties - }); - case "Slider": - if (!isResolvedSlider(resolvedProperties)) { - throw new Error(`Invalid data; expected ${componentType}`); - } - return new this.#objCtor({ - ...baseNode, - type: "Slider", - properties: resolvedProperties - }); - default: return new this.#objCtor({ - ...baseNode, - type: componentType, - properties: resolvedProperties - }); - } - } - /** - * Recursively resolves an individual property value. If a property indicates - * a child node (a string that matches a component ID), an explicitList of - * children, or a template, these will be built out here. - */ - #resolvePropertyValue(value, surface, visited, dataContextPath, idSuffix = "", propertyKey = null) { - const isComponentIdReferenceKey = (key) => key === "child" || key.endsWith("Child"); - if (typeof value === "string" && propertyKey && isComponentIdReferenceKey(propertyKey) && surface.components.has(value)) { - return this.#buildNodeRecursive(value, surface, visited, dataContextPath, idSuffix); - } - if (isComponentArrayReference(value)) { - if (value.explicitList) { - return value.explicitList.map((id) => this.#buildNodeRecursive(id, surface, visited, dataContextPath, idSuffix)); - } - if (value.template) { - const fullDataPath = this.resolvePath(value.template.dataBinding, dataContextPath); - const data = this.#getDataByPath(surface.dataModel, fullDataPath); - const template = value.template; - if (Array.isArray(data)) { - return data.map((_$1, index) => { - const parentIndices = dataContextPath.split("/").filter((segment) => /^\d+$/.test(segment)); - const newIndices = [...parentIndices, index]; - const newSuffix = `:${newIndices.join(":")}`; - const childDataContextPath = `${fullDataPath}/${index}`; - return this.#buildNodeRecursive(template.componentId, surface, visited, childDataContextPath, newSuffix); - }); - } - const mapCtor = this.#mapCtor; - if (data instanceof mapCtor) { - return Array.from(data.keys(), (key) => { - const newSuffix = `:${key}`; - const childDataContextPath = `${fullDataPath}/${key}`; - return this.#buildNodeRecursive(template.componentId, surface, visited, childDataContextPath, newSuffix); - }); - } - return new this.#arrayCtor(); - } - } - if (Array.isArray(value)) { - return value.map((item) => this.#resolvePropertyValue(item, surface, visited, dataContextPath, idSuffix, propertyKey)); - } - if (isObject$1(value)) { - const newObj = new this.#objCtor(); - for (const [key, propValue] of Object.entries(value)) { - let propertyValue = propValue; - if (isPath(key, propValue) && dataContextPath !== "/") { - propertyValue = propValue.replace(/^\.?\/item/, "").replace(/^\.?\/text/, "").replace(/^\.?\/label/, "").replace(/^\.?\//, ""); - newObj[key] = propertyValue; - continue; - } - newObj[key] = this.#resolvePropertyValue(propertyValue, surface, visited, dataContextPath, idSuffix, key); - } - return newObj; - } - return value; - } -}; - -var __defProp = Object.defineProperty; -var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { - enumerable: true, - configurable: true, - writable: true, - value -}) : obj[key] = value; -var __publicField = (obj, key, value) => { - __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); - return value; -}; -var __accessCheck = (obj, member, msg) => { - if (!member.has(obj)) throw TypeError("Cannot " + msg); -}; -var __privateIn = (member, obj) => { - if (Object(obj) !== obj) throw TypeError("Cannot use the \"in\" operator on this value"); - return member.has(obj); -}; -var __privateAdd = (obj, member, value) => { - if (member.has(obj)) throw TypeError("Cannot add the same private member more than once"); - member instanceof WeakSet ? member.add(obj) : member.set(obj, value); -}; -var __privateMethod = (obj, member, method) => { - __accessCheck(obj, member, "access private method"); - return method; -}; -/** -* @license -* Copyright Google LLC All Rights Reserved. -* -* Use of this source code is governed by an MIT-style license that can be -* found in the LICENSE file at https://angular.io/license -*/ -function defaultEquals(a$2, b$2) { - return Object.is(a$2, b$2); -} -/** -* @license -* Copyright Google LLC All Rights Reserved. -* -* Use of this source code is governed by an MIT-style license that can be -* found in the LICENSE file at https://angular.io/license -*/ -let activeConsumer = null; -let inNotificationPhase = false; -let epoch = 1; -const SIGNAL = /* @__PURE__ */ Symbol("SIGNAL"); -function setActiveConsumer(consumer) { - const prev = activeConsumer; - activeConsumer = consumer; - return prev; -} -function getActiveConsumer() { - return activeConsumer; -} -function isInNotificationPhase() { - return inNotificationPhase; -} -const REACTIVE_NODE = { - version: 0, - lastCleanEpoch: 0, - dirty: false, - producerNode: void 0, - producerLastReadVersion: void 0, - producerIndexOfThis: void 0, - nextProducerIndex: 0, - liveConsumerNode: void 0, - liveConsumerIndexOfThis: void 0, - consumerAllowSignalWrites: false, - consumerIsAlwaysLive: false, - producerMustRecompute: () => false, - producerRecomputeValue: () => {}, - consumerMarkedDirty: () => {}, - consumerOnSignalRead: () => {} -}; -function producerAccessed(node) { - if (inNotificationPhase) { - throw new Error(typeof ngDevMode !== "undefined" && ngDevMode ? `Assertion error: signal read during notification phase` : ""); - } - if (activeConsumer === null) { - return; - } - activeConsumer.consumerOnSignalRead(node); - const idx = activeConsumer.nextProducerIndex++; - assertConsumerNode(activeConsumer); - if (idx < activeConsumer.producerNode.length && activeConsumer.producerNode[idx] !== node) { - if (consumerIsLive(activeConsumer)) { - const staleProducer = activeConsumer.producerNode[idx]; - producerRemoveLiveConsumerAtIndex(staleProducer, activeConsumer.producerIndexOfThis[idx]); - } - } - if (activeConsumer.producerNode[idx] !== node) { - activeConsumer.producerNode[idx] = node; - activeConsumer.producerIndexOfThis[idx] = consumerIsLive(activeConsumer) ? producerAddLiveConsumer(node, activeConsumer, idx) : 0; - } - activeConsumer.producerLastReadVersion[idx] = node.version; -} -function producerIncrementEpoch() { - epoch++; -} -function producerUpdateValueVersion(node) { - if (!node.dirty && node.lastCleanEpoch === epoch) { - return; - } - if (!node.producerMustRecompute(node) && !consumerPollProducersForChange(node)) { - node.dirty = false; - node.lastCleanEpoch = epoch; - return; - } - node.producerRecomputeValue(node); - node.dirty = false; - node.lastCleanEpoch = epoch; -} -function producerNotifyConsumers(node) { - if (node.liveConsumerNode === void 0) { - return; - } - const prev = inNotificationPhase; - inNotificationPhase = true; - try { - for (const consumer of node.liveConsumerNode) { - if (!consumer.dirty) { - consumerMarkDirty(consumer); - } - } - } finally { - inNotificationPhase = prev; - } -} -function producerUpdatesAllowed() { - return (activeConsumer == null ? void 0 : activeConsumer.consumerAllowSignalWrites) !== false; -} -function consumerMarkDirty(node) { - var _a$1; - node.dirty = true; - producerNotifyConsumers(node); - (_a$1 = node.consumerMarkedDirty) == null ? void 0 : _a$1.call(node.wrapper ?? node); -} -function consumerBeforeComputation(node) { - node && (node.nextProducerIndex = 0); - return setActiveConsumer(node); -} -function consumerAfterComputation(node, prevConsumer) { - setActiveConsumer(prevConsumer); - if (!node || node.producerNode === void 0 || node.producerIndexOfThis === void 0 || node.producerLastReadVersion === void 0) { - return; - } - if (consumerIsLive(node)) { - for (let i$10 = node.nextProducerIndex; i$10 < node.producerNode.length; i$10++) { - producerRemoveLiveConsumerAtIndex(node.producerNode[i$10], node.producerIndexOfThis[i$10]); - } - } - while (node.producerNode.length > node.nextProducerIndex) { - node.producerNode.pop(); - node.producerLastReadVersion.pop(); - node.producerIndexOfThis.pop(); - } -} -function consumerPollProducersForChange(node) { - assertConsumerNode(node); - for (let i$10 = 0; i$10 < node.producerNode.length; i$10++) { - const producer = node.producerNode[i$10]; - const seenVersion = node.producerLastReadVersion[i$10]; - if (seenVersion !== producer.version) { - return true; - } - producerUpdateValueVersion(producer); - if (seenVersion !== producer.version) { - return true; - } - } - return false; -} -function producerAddLiveConsumer(node, consumer, indexOfThis) { - var _a$1; - assertProducerNode(node); - assertConsumerNode(node); - if (node.liveConsumerNode.length === 0) { - (_a$1 = node.watched) == null ? void 0 : _a$1.call(node.wrapper); - for (let i$10 = 0; i$10 < node.producerNode.length; i$10++) { - node.producerIndexOfThis[i$10] = producerAddLiveConsumer(node.producerNode[i$10], node, i$10); - } - } - node.liveConsumerIndexOfThis.push(indexOfThis); - return node.liveConsumerNode.push(consumer) - 1; -} -function producerRemoveLiveConsumerAtIndex(node, idx) { - var _a$1; - assertProducerNode(node); - assertConsumerNode(node); - if (typeof ngDevMode !== "undefined" && ngDevMode && idx >= node.liveConsumerNode.length) { - throw new Error(`Assertion error: active consumer index ${idx} is out of bounds of ${node.liveConsumerNode.length} consumers)`); - } - if (node.liveConsumerNode.length === 1) { - (_a$1 = node.unwatched) == null ? void 0 : _a$1.call(node.wrapper); - for (let i$10 = 0; i$10 < node.producerNode.length; i$10++) { - producerRemoveLiveConsumerAtIndex(node.producerNode[i$10], node.producerIndexOfThis[i$10]); - } - } - const lastIdx = node.liveConsumerNode.length - 1; - node.liveConsumerNode[idx] = node.liveConsumerNode[lastIdx]; - node.liveConsumerIndexOfThis[idx] = node.liveConsumerIndexOfThis[lastIdx]; - node.liveConsumerNode.length--; - node.liveConsumerIndexOfThis.length--; - if (idx < node.liveConsumerNode.length) { - const idxProducer = node.liveConsumerIndexOfThis[idx]; - const consumer = node.liveConsumerNode[idx]; - assertConsumerNode(consumer); - consumer.producerIndexOfThis[idxProducer] = idx; - } -} -function consumerIsLive(node) { - var _a$1; - return node.consumerIsAlwaysLive || (((_a$1 = node == null ? void 0 : node.liveConsumerNode) == null ? void 0 : _a$1.length) ?? 0) > 0; -} -function assertConsumerNode(node) { - node.producerNode ?? (node.producerNode = []); - node.producerIndexOfThis ?? (node.producerIndexOfThis = []); - node.producerLastReadVersion ?? (node.producerLastReadVersion = []); -} -function assertProducerNode(node) { - node.liveConsumerNode ?? (node.liveConsumerNode = []); - node.liveConsumerIndexOfThis ?? (node.liveConsumerIndexOfThis = []); -} -/** -* @license -* Copyright Google LLC All Rights Reserved. -* -* Use of this source code is governed by an MIT-style license that can be -* found in the LICENSE file at https://angular.io/license -*/ -function computedGet(node) { - producerUpdateValueVersion(node); - producerAccessed(node); - if (node.value === ERRORED) { - throw node.error; - } - return node.value; -} -function createComputed(computation) { - const node = Object.create(COMPUTED_NODE); - node.computation = computation; - const computed = () => computedGet(node); - computed[SIGNAL] = node; - return computed; -} -const UNSET = /* @__PURE__ */ Symbol("UNSET"); -const COMPUTING = /* @__PURE__ */ Symbol("COMPUTING"); -const ERRORED = /* @__PURE__ */ Symbol("ERRORED"); -const COMPUTED_NODE = /* @__PURE__ */ (() => { - return { - ...REACTIVE_NODE, - value: UNSET, - dirty: true, - error: null, - equal: defaultEquals, - producerMustRecompute(node) { - return node.value === UNSET || node.value === COMPUTING; - }, - producerRecomputeValue(node) { - if (node.value === COMPUTING) { - throw new Error("Detected cycle in computations."); - } - const oldValue = node.value; - node.value = COMPUTING; - const prevConsumer = consumerBeforeComputation(node); - let newValue; - let wasEqual = false; - try { - newValue = node.computation.call(node.wrapper); - const oldOk = oldValue !== UNSET && oldValue !== ERRORED; - wasEqual = oldOk && node.equal.call(node.wrapper, oldValue, newValue); - } catch (err) { - newValue = ERRORED; - node.error = err; - } finally { - consumerAfterComputation(node, prevConsumer); - } - if (wasEqual) { - node.value = oldValue; - return; - } - node.value = newValue; - node.version++; - } - }; -})(); -/** -* @license -* Copyright Google LLC All Rights Reserved. -* -* Use of this source code is governed by an MIT-style license that can be -* found in the LICENSE file at https://angular.io/license -*/ -function defaultThrowError() { - throw new Error(); -} -let throwInvalidWriteToSignalErrorFn = defaultThrowError; -function throwInvalidWriteToSignalError() { - throwInvalidWriteToSignalErrorFn(); -} -/** -* @license -* Copyright Google LLC All Rights Reserved. -* -* Use of this source code is governed by an MIT-style license that can be -* found in the LICENSE file at https://angular.io/license -*/ -function createSignal(initialValue) { - const node = Object.create(SIGNAL_NODE); - node.value = initialValue; - const getter = () => { - producerAccessed(node); - return node.value; - }; - getter[SIGNAL] = node; - return getter; -} -function signalGetFn() { - producerAccessed(this); - return this.value; -} -function signalSetFn(node, newValue) { - if (!producerUpdatesAllowed()) { - throwInvalidWriteToSignalError(); - } - if (!node.equal.call(node.wrapper, node.value, newValue)) { - node.value = newValue; - signalValueChanged(node); - } -} -const SIGNAL_NODE = /* @__PURE__ */ (() => { - return { - ...REACTIVE_NODE, - equal: defaultEquals, - value: void 0 - }; -})(); -function signalValueChanged(node) { - node.version++; - producerIncrementEpoch(); - producerNotifyConsumers(node); -} -/** -* @license -* Copyright 2024 Bloomberg Finance L.P. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -const NODE = Symbol("node"); -var Signal; -((Signal2) => { - var _a$1, _brand, brand_fn, _b, _brand2, brand_fn2; - class State { - constructor(initialValue, options = {}) { - __privateAdd(this, _brand); - __publicField(this, _a$1); - const ref = createSignal(initialValue); - const node = ref[SIGNAL]; - this[NODE] = node; - node.wrapper = this; - if (options) { - const equals = options.equals; - if (equals) { - node.equal = equals; - } - node.watched = options[Signal2.subtle.watched]; - node.unwatched = options[Signal2.subtle.unwatched]; - } - } - get() { - if (!(0, Signal2.isState)(this)) throw new TypeError("Wrong receiver type for Signal.State.prototype.get"); - return signalGetFn.call(this[NODE]); - } - set(newValue) { - if (!(0, Signal2.isState)(this)) throw new TypeError("Wrong receiver type for Signal.State.prototype.set"); - if (isInNotificationPhase()) { - throw new Error("Writes to signals not permitted during Watcher callback"); - } - const ref = this[NODE]; - signalSetFn(ref, newValue); - } - } - _a$1 = NODE; - _brand = new WeakSet(); - brand_fn = function() {}; - Signal2.isState = (s$9) => typeof s$9 === "object" && __privateIn(_brand, s$9); - Signal2.State = State; - class Computed { - constructor(computation, options) { - __privateAdd(this, _brand2); - __publicField(this, _b); - const ref = createComputed(computation); - const node = ref[SIGNAL]; - node.consumerAllowSignalWrites = true; - this[NODE] = node; - node.wrapper = this; - if (options) { - const equals = options.equals; - if (equals) { - node.equal = equals; - } - node.watched = options[Signal2.subtle.watched]; - node.unwatched = options[Signal2.subtle.unwatched]; - } - } - get() { - if (!(0, Signal2.isComputed)(this)) throw new TypeError("Wrong receiver type for Signal.Computed.prototype.get"); - return computedGet(this[NODE]); - } - } - _b = NODE; - _brand2 = new WeakSet(); - brand_fn2 = function() {}; - Signal2.isComputed = (c$7) => typeof c$7 === "object" && __privateIn(_brand2, c$7); - Signal2.Computed = Computed; - ((subtle2) => { - var _a2, _brand3, brand_fn3, _assertSignals, assertSignals_fn; - function untrack(cb) { - let output; - let prevActiveConsumer = null; - try { - prevActiveConsumer = setActiveConsumer(null); - output = cb(); - } finally { - setActiveConsumer(prevActiveConsumer); - } - return output; - } - subtle2.untrack = untrack; - function introspectSources(sink) { - var _a3; - if (!(0, Signal2.isComputed)(sink) && !(0, Signal2.isWatcher)(sink)) { - throw new TypeError("Called introspectSources without a Computed or Watcher argument"); - } - return ((_a3 = sink[NODE].producerNode) == null ? void 0 : _a3.map((n$13) => n$13.wrapper)) ?? []; - } - subtle2.introspectSources = introspectSources; - function introspectSinks(signal) { - var _a3; - if (!(0, Signal2.isComputed)(signal) && !(0, Signal2.isState)(signal)) { - throw new TypeError("Called introspectSinks without a Signal argument"); - } - return ((_a3 = signal[NODE].liveConsumerNode) == null ? void 0 : _a3.map((n$13) => n$13.wrapper)) ?? []; - } - subtle2.introspectSinks = introspectSinks; - function hasSinks(signal) { - if (!(0, Signal2.isComputed)(signal) && !(0, Signal2.isState)(signal)) { - throw new TypeError("Called hasSinks without a Signal argument"); - } - const liveConsumerNode = signal[NODE].liveConsumerNode; - if (!liveConsumerNode) return false; - return liveConsumerNode.length > 0; - } - subtle2.hasSinks = hasSinks; - function hasSources(signal) { - if (!(0, Signal2.isComputed)(signal) && !(0, Signal2.isWatcher)(signal)) { - throw new TypeError("Called hasSources without a Computed or Watcher argument"); - } - const producerNode = signal[NODE].producerNode; - if (!producerNode) return false; - return producerNode.length > 0; - } - subtle2.hasSources = hasSources; - class Watcher { - constructor(notify) { - __privateAdd(this, _brand3); - __privateAdd(this, _assertSignals); - __publicField(this, _a2); - let node = Object.create(REACTIVE_NODE); - node.wrapper = this; - node.consumerMarkedDirty = notify; - node.consumerIsAlwaysLive = true; - node.consumerAllowSignalWrites = false; - node.producerNode = []; - this[NODE] = node; - } - watch(...signals) { - if (!(0, Signal2.isWatcher)(this)) { - throw new TypeError("Called unwatch without Watcher receiver"); - } - __privateMethod(this, _assertSignals, assertSignals_fn).call(this, signals); - const node = this[NODE]; - node.dirty = false; - const prev = setActiveConsumer(node); - for (const signal of signals) { - producerAccessed(signal[NODE]); - } - setActiveConsumer(prev); - } - unwatch(...signals) { - if (!(0, Signal2.isWatcher)(this)) { - throw new TypeError("Called unwatch without Watcher receiver"); - } - __privateMethod(this, _assertSignals, assertSignals_fn).call(this, signals); - const node = this[NODE]; - assertConsumerNode(node); - for (let i$10 = node.producerNode.length - 1; i$10 >= 0; i$10--) { - if (signals.includes(node.producerNode[i$10].wrapper)) { - producerRemoveLiveConsumerAtIndex(node.producerNode[i$10], node.producerIndexOfThis[i$10]); - const lastIdx = node.producerNode.length - 1; - node.producerNode[i$10] = node.producerNode[lastIdx]; - node.producerIndexOfThis[i$10] = node.producerIndexOfThis[lastIdx]; - node.producerNode.length--; - node.producerIndexOfThis.length--; - node.nextProducerIndex--; - if (i$10 < node.producerNode.length) { - const idxConsumer = node.producerIndexOfThis[i$10]; - const producer = node.producerNode[i$10]; - assertProducerNode(producer); - producer.liveConsumerIndexOfThis[idxConsumer] = i$10; - } - } - } - } - getPending() { - if (!(0, Signal2.isWatcher)(this)) { - throw new TypeError("Called getPending without Watcher receiver"); - } - const node = this[NODE]; - return node.producerNode.filter((n$13) => n$13.dirty).map((n$13) => n$13.wrapper); - } - } - _a2 = NODE; - _brand3 = new WeakSet(); - brand_fn3 = function() {}; - _assertSignals = new WeakSet(); - assertSignals_fn = function(signals) { - for (const signal of signals) { - if (!(0, Signal2.isComputed)(signal) && !(0, Signal2.isState)(signal)) { - throw new TypeError("Called watch/unwatch without a Computed or State argument"); - } - } - }; - Signal2.isWatcher = (w$1) => __privateIn(_brand3, w$1); - subtle2.Watcher = Watcher; - function currentComputed() { - var _a3; - return (_a3 = getActiveConsumer()) == null ? void 0 : _a3.wrapper; - } - subtle2.currentComputed = currentComputed; - subtle2.watched = Symbol("watched"); - subtle2.unwatched = Symbol("unwatched"); - })(Signal2.subtle || (Signal2.subtle = {})); -})(Signal || (Signal = {})); - -/** -* equality check here is always false so that we can dirty the storage -* via setting to _anything_ -* -* -* This is for a pattern where we don't *directly* use signals to back the values used in collections -* so that instanceof checks and getters and other native features "just work" without having -* to do nested proxying. -* -* (though, see deep.ts for nested / deep behavior) -*/ -const createStorage = (initial = null) => new Signal.State(initial, { equals: () => false }); -/** -* Just an alias for brevity -*/ -const BOUND_FUNS = new WeakMap(); -function fnCacheFor(context) { - let fnCache = BOUND_FUNS.get(context); - if (!fnCache) { - fnCache = new Map(); - BOUND_FUNS.set(context, fnCache); - } - return fnCache; -} - -const ARRAY_GETTER_METHODS = new Set([ - Symbol.iterator, - "concat", - "entries", - "every", - "filter", - "find", - "findIndex", - "flat", - "flatMap", - "forEach", - "includes", - "indexOf", - "join", - "keys", - "lastIndexOf", - "map", - "reduce", - "reduceRight", - "slice", - "some", - "values" -]); -const ARRAY_WRITE_THEN_READ_METHODS = new Set([ - "fill", - "push", - "unshift" -]); -function convertToInt(prop) { - if (typeof prop === "symbol") return null; - const num = Number(prop); - if (isNaN(num)) return null; - return num % 1 === 0 ? num : null; -} -var SignalArray = class SignalArray { - /** - * Creates an array from an iterable object. - * @param iterable An iterable object to convert to an array. - */ - /** - * Creates an array from an iterable object. - * @param iterable An iterable object to convert to an array. - * @param mapfn A mapping function to call on every element of the array. - * @param thisArg Value of 'this' used to invoke the mapfn. - */ - static from(iterable, mapfn, thisArg) { - return mapfn ? new SignalArray(Array.from(iterable, mapfn, thisArg)) : new SignalArray(Array.from(iterable)); - } - static of(...arr) { - return new SignalArray(arr); - } - constructor(arr = []) { - let clone = arr.slice(); - let self = this; - let boundFns = new Map(); - /** - Flag to track whether we have *just* intercepted a call to `.push()` or - `.unshift()`, since in those cases (and only those cases!) the `Array` - itself checks `.length` to return from the function call. - */ - let nativelyAccessingLengthFromPushOrUnshift = false; - return new Proxy(clone, { - get(target, prop) { - let index = convertToInt(prop); - if (index !== null) { - self.#readStorageFor(index); - self.#collection.get(); - return target[index]; - } - if (prop === "length") { - if (nativelyAccessingLengthFromPushOrUnshift) { - nativelyAccessingLengthFromPushOrUnshift = false; - } else { - self.#collection.get(); - } - return target[prop]; - } - if (ARRAY_WRITE_THEN_READ_METHODS.has(prop)) { - nativelyAccessingLengthFromPushOrUnshift = true; - } - if (ARRAY_GETTER_METHODS.has(prop)) { - let fn = boundFns.get(prop); - if (fn === undefined) { - fn = (...args) => { - self.#collection.get(); - return target[prop](...args); - }; - boundFns.set(prop, fn); - } - return fn; - } - return target[prop]; - }, - set(target, prop, value) { - target[prop] = value; - let index = convertToInt(prop); - if (index !== null) { - self.#dirtyStorageFor(index); - self.#collection.set(null); - } else if (prop === "length") { - self.#collection.set(null); - } - return true; - }, - getPrototypeOf() { - return SignalArray.prototype; - } - }); - } - #collection = createStorage(); - #storages = new Map(); - #readStorageFor(index) { - let storage = this.#storages.get(index); - if (storage === undefined) { - storage = createStorage(); - this.#storages.set(index, storage); - } - storage.get(); - } - #dirtyStorageFor(index) { - const storage = this.#storages.get(index); - if (storage) { - storage.set(null); - } - } -}; -Object.setPrototypeOf(SignalArray.prototype, Array.prototype); -function signalArray(x$1) { - return new SignalArray(x$1); -} - -var SignalMap = class { - collection = createStorage(); - storages = new Map(); - vals; - readStorageFor(key) { - const { storages } = this; - let storage = storages.get(key); - if (storage === undefined) { - storage = createStorage(); - storages.set(key, storage); - } - storage.get(); - } - dirtyStorageFor(key) { - const storage = this.storages.get(key); - if (storage) { - storage.set(null); - } - } - constructor(existing) { - this.vals = existing ? new Map(existing) : new Map(); - } - get(key) { - this.readStorageFor(key); - return this.vals.get(key); - } - has(key) { - this.readStorageFor(key); - return this.vals.has(key); - } - entries() { - this.collection.get(); - return this.vals.entries(); - } - keys() { - this.collection.get(); - return this.vals.keys(); - } - values() { - this.collection.get(); - return this.vals.values(); - } - forEach(fn) { - this.collection.get(); - this.vals.forEach(fn); - } - get size() { - this.collection.get(); - return this.vals.size; - } - [Symbol.iterator]() { - this.collection.get(); - return this.vals[Symbol.iterator](); - } - get [Symbol.toStringTag]() { - return this.vals[Symbol.toStringTag]; - } - set(key, value) { - this.dirtyStorageFor(key); - this.collection.set(null); - this.vals.set(key, value); - return this; - } - delete(key) { - this.dirtyStorageFor(key); - this.collection.set(null); - return this.vals.delete(key); - } - clear() { - this.storages.forEach((s$9) => s$9.set(null)); - this.collection.set(null); - this.vals.clear(); - } -}; -Object.setPrototypeOf(SignalMap.prototype, Map.prototype); - -/** -* Implementation based of tracked-built-ins' TrackedObject -* https://github.com/tracked-tools/tracked-built-ins/blob/master/addon/src/-private/object.js -*/ -var SignalObjectImpl = class SignalObjectImpl { - static fromEntries(entries) { - return new SignalObjectImpl(Object.fromEntries(entries)); - } - #storages = new Map(); - #collection = createStorage(); - constructor(obj = {}) { - let proto = Object.getPrototypeOf(obj); - let descs = Object.getOwnPropertyDescriptors(obj); - let clone = Object.create(proto); - for (let prop in descs) { - Object.defineProperty(clone, prop, descs[prop]); - } - let self = this; - return new Proxy(clone, { - get(target, prop, receiver) { - self.#readStorageFor(prop); - return Reflect.get(target, prop, receiver); - }, - has(target, prop) { - self.#readStorageFor(prop); - return prop in target; - }, - ownKeys(target) { - self.#collection.get(); - return Reflect.ownKeys(target); - }, - set(target, prop, value, receiver) { - let result = Reflect.set(target, prop, value, receiver); - self.#dirtyStorageFor(prop); - self.#dirtyCollection(); - return result; - }, - deleteProperty(target, prop) { - if (prop in target) { - delete target[prop]; - self.#dirtyStorageFor(prop); - self.#dirtyCollection(); - } - return true; - }, - getPrototypeOf() { - return SignalObjectImpl.prototype; - } - }); - } - #readStorageFor(key) { - let storage = this.#storages.get(key); - if (storage === undefined) { - storage = createStorage(); - this.#storages.set(key, storage); - } - storage.get(); - } - #dirtyStorageFor(key) { - const storage = this.#storages.get(key); - if (storage) { - storage.set(null); - } - } - #dirtyCollection() { - this.#collection.set(null); - } -}; -/** -* Create a reactive Object, backed by Signals, using a Proxy. -* This allows dynamic creation and deletion of signals using the object primitive -* APIs that most folks are familiar with -- the only difference is instantiation. -* ```js -* const obj = new SignalObject({ foo: 123 }); -* -* obj.foo // 123 -* obj.foo = 456 -* obj.foo // 456 -* obj.bar = 2 -* obj.bar // 2 -* ``` -*/ -const SignalObject = SignalObjectImpl; -function signalObject(obj) { - return new SignalObject(obj); -} - -var SignalSet = class { - collection = createStorage(); - storages = new Map(); - vals; - storageFor(key) { - const storages = this.storages; - let storage = storages.get(key); - if (storage === undefined) { - storage = createStorage(); - storages.set(key, storage); - } - return storage; - } - dirtyStorageFor(key) { - const storage = this.storages.get(key); - if (storage) { - storage.set(null); - } - } - constructor(existing) { - this.vals = new Set(existing); - } - has(value) { - this.storageFor(value).get(); - return this.vals.has(value); - } - entries() { - this.collection.get(); - return this.vals.entries(); - } - keys() { - this.collection.get(); - return this.vals.keys(); - } - values() { - this.collection.get(); - return this.vals.values(); - } - forEach(fn) { - this.collection.get(); - this.vals.forEach(fn); - } - get size() { - this.collection.get(); - return this.vals.size; - } - [Symbol.iterator]() { - this.collection.get(); - return this.vals[Symbol.iterator](); - } - get [Symbol.toStringTag]() { - return this.vals[Symbol.toStringTag]; - } - add(value) { - this.dirtyStorageFor(value); - this.collection.set(null); - this.vals.add(value); - return this; - } - delete(value) { - this.dirtyStorageFor(value); - this.collection.set(null); - return this.vals.delete(value); - } - clear() { - this.storages.forEach((s$9) => s$9.set(null)); - this.collection.set(null); - this.vals.clear(); - } -}; -Object.setPrototypeOf(SignalSet.prototype, Set.prototype); - -function create() { - return new A2uiMessageProcessor({ - arrayCtor: SignalArray, - mapCtor: SignalMap, - objCtor: SignalObject, - setCtor: SignalSet - }); -} - -var server_to_client_with_standard_catalog_default = { - title: "A2UI Message Schema", - description: "Describes a JSON payload for an A2UI (Agent to UI) message, which is used to dynamically construct and update user interfaces. A message MUST contain exactly ONE of the action properties: 'beginRendering', 'surfaceUpdate', 'dataModelUpdate', or 'deleteSurface'.", - type: "object", - additionalProperties: false, - properties: { - "beginRendering": { - "type": "object", - "description": "Signals the client to begin rendering a surface with a root component and specific styles.", - "additionalProperties": false, - "properties": { - "surfaceId": { - "type": "string", - "description": "The unique identifier for the UI surface to be rendered." - }, - "root": { - "type": "string", - "description": "The ID of the root component to render." - }, - "styles": { - "type": "object", - "description": "Styling information for the UI.", - "additionalProperties": false, - "properties": { - "font": { - "type": "string", - "description": "The primary font for the UI." - }, - "primaryColor": { - "type": "string", - "description": "The primary UI color as a hexadecimal code (e.g., '#00BFFF').", - "pattern": "^#[0-9a-fA-F]{6}$" - } - } - } - }, - "required": ["root", "surfaceId"] - }, - "surfaceUpdate": { - "type": "object", - "description": "Updates a surface with a new set of components.", - "additionalProperties": false, - "properties": { - "surfaceId": { - "type": "string", - "description": "The unique identifier for the UI surface to be updated. If you are adding a new surface this *must* be a new, unique identified that has never been used for any existing surfaces shown." - }, - "components": { - "type": "array", - "description": "A list containing all UI components for the surface.", - "minItems": 1, - "items": { - "type": "object", - "description": "Represents a *single* component in a UI widget tree. This component could be one of many supported types.", - "additionalProperties": false, - "properties": { - "id": { - "type": "string", - "description": "The unique identifier for this component." - }, - "weight": { - "type": "number", - "description": "The relative weight of this component within a Row or Column. This corresponds to the CSS 'flex-grow' property. Note: this may ONLY be set when the component is a direct descendant of a Row or Column." - }, - "component": { - "type": "object", - "description": "A wrapper object that MUST contain exactly one key, which is the name of the component type (e.g., 'Heading'). The value is an object containing the properties for that specific component.", - "additionalProperties": false, - "properties": { - "Text": { - "type": "object", - "additionalProperties": false, - "properties": { - "text": { - "type": "object", - "description": "The text content to display. This can be a literal string or a reference to a value in the data model ('path', e.g., '/doc/title'). While simple Markdown formatting is supported (i.e. without HTML, images, or links), utilizing dedicated UI components is generally preferred for a richer and more structured presentation.", - "additionalProperties": false, - "properties": { - "literalString": { "type": "string" }, - "path": { "type": "string" } - } - }, - "usageHint": { - "type": "string", - "description": "A hint for the base text style. One of:\n- `h1`: Largest heading.\n- `h2`: Second largest heading.\n- `h3`: Third largest heading.\n- `h4`: Fourth largest heading.\n- `h5`: Fifth largest heading.\n- `caption`: Small text for captions.\n- `body`: Standard body text.", - "enum": [ - "h1", - "h2", - "h3", - "h4", - "h5", - "caption", - "body" - ] - } - }, - "required": ["text"] - }, - "Image": { - "type": "object", - "additionalProperties": false, - "properties": { - "url": { - "type": "object", - "description": "The URL of the image to display. This can be a literal string ('literal') or a reference to a value in the data model ('path', e.g. '/thumbnail/url').", - "additionalProperties": false, - "properties": { - "literalString": { "type": "string" }, - "path": { "type": "string" } - } - }, - "fit": { - "type": "string", - "description": "Specifies how the image should be resized to fit its container. This corresponds to the CSS 'object-fit' property.", - "enum": [ - "contain", - "cover", - "fill", - "none", - "scale-down" - ] - }, - "usageHint": { - "type": "string", - "description": "A hint for the image size and style. One of:\n- `icon`: Small square icon.\n- `avatar`: Circular avatar image.\n- `smallFeature`: Small feature image.\n- `mediumFeature`: Medium feature image.\n- `largeFeature`: Large feature image.\n- `header`: Full-width, full bleed, header image.", - "enum": [ - "icon", - "avatar", - "smallFeature", - "mediumFeature", - "largeFeature", - "header" - ] - } - }, - "required": ["url"] - }, - "Icon": { - "type": "object", - "additionalProperties": false, - "properties": { "name": { - "type": "object", - "description": "The name of the icon to display. This can be a literal string or a reference to a value in the data model ('path', e.g. '/form/submit').", - "additionalProperties": false, - "properties": { - "literalString": { - "type": "string", - "enum": [ - "accountCircle", - "add", - "arrowBack", - "arrowForward", - "attachFile", - "calendarToday", - "call", - "camera", - "check", - "close", - "delete", - "download", - "edit", - "event", - "error", - "favorite", - "favoriteOff", - "folder", - "help", - "home", - "info", - "locationOn", - "lock", - "lockOpen", - "mail", - "menu", - "moreVert", - "moreHoriz", - "notificationsOff", - "notifications", - "payment", - "person", - "phone", - "photo", - "print", - "refresh", - "search", - "send", - "settings", - "share", - "shoppingCart", - "star", - "starHalf", - "starOff", - "upload", - "visibility", - "visibilityOff", - "warning" - ] - }, - "path": { "type": "string" } - } - } }, - "required": ["name"] - }, - "Video": { - "type": "object", - "additionalProperties": false, - "properties": { "url": { - "type": "object", - "description": "The URL of the video to display. This can be a literal string or a reference to a value in the data model ('path', e.g. '/video/url').", - "additionalProperties": false, - "properties": { - "literalString": { "type": "string" }, - "path": { "type": "string" } - } - } }, - "required": ["url"] - }, - "AudioPlayer": { - "type": "object", - "additionalProperties": false, - "properties": { - "url": { - "type": "object", - "description": "The URL of the audio to be played. This can be a literal string ('literal') or a reference to a value in the data model ('path', e.g. '/song/url').", - "additionalProperties": false, - "properties": { - "literalString": { "type": "string" }, - "path": { "type": "string" } - } - }, - "description": { - "type": "object", - "description": "A description of the audio, such as a title or summary. This can be a literal string or a reference to a value in the data model ('path', e.g. '/song/title').", - "additionalProperties": false, - "properties": { - "literalString": { "type": "string" }, - "path": { "type": "string" } - } - } - }, - "required": ["url"] - }, - "Row": { - "type": "object", - "additionalProperties": false, - "properties": { - "children": { - "type": "object", - "description": "Defines the children. Use 'explicitList' for a fixed set of children, or 'template' to generate children from a data list.", - "additionalProperties": false, - "properties": { - "explicitList": { - "type": "array", - "items": { "type": "string" } - }, - "template": { - "type": "object", - "description": "A template for generating a dynamic list of children from a data model list. `componentId` is the component to use as a template, and `dataBinding` is the path to the map of components in the data model. Values in the map will define the list of children.", - "additionalProperties": false, - "properties": { - "componentId": { "type": "string" }, - "dataBinding": { "type": "string" } - }, - "required": ["componentId", "dataBinding"] - } - } - }, - "distribution": { - "type": "string", - "description": "Defines the arrangement of children along the main axis (horizontally). This corresponds to the CSS 'justify-content' property.", - "enum": [ - "center", - "end", - "spaceAround", - "spaceBetween", - "spaceEvenly", - "start" - ] - }, - "alignment": { - "type": "string", - "description": "Defines the alignment of children along the cross axis (vertically). This corresponds to the CSS 'align-items' property.", - "enum": [ - "start", - "center", - "end", - "stretch" - ] - } - }, - "required": ["children"] - }, - "Column": { - "type": "object", - "additionalProperties": false, - "properties": { - "children": { - "type": "object", - "description": "Defines the children. Use 'explicitList' for a fixed set of children, or 'template' to generate children from a data list.", - "additionalProperties": false, - "properties": { - "explicitList": { - "type": "array", - "items": { "type": "string" } - }, - "template": { - "type": "object", - "description": "A template for generating a dynamic list of children from a data model list. `componentId` is the component to use as a template, and `dataBinding` is the path to the map of components in the data model. Values in the map will define the list of children.", - "additionalProperties": false, - "properties": { - "componentId": { "type": "string" }, - "dataBinding": { "type": "string" } - }, - "required": ["componentId", "dataBinding"] - } - } - }, - "distribution": { - "type": "string", - "description": "Defines the arrangement of children along the main axis (vertically). This corresponds to the CSS 'justify-content' property.", - "enum": [ - "start", - "center", - "end", - "spaceBetween", - "spaceAround", - "spaceEvenly" - ] - }, - "alignment": { - "type": "string", - "description": "Defines the alignment of children along the cross axis (horizontally). This corresponds to the CSS 'align-items' property.", - "enum": [ - "center", - "end", - "start", - "stretch" - ] - } - }, - "required": ["children"] - }, - "List": { - "type": "object", - "additionalProperties": false, - "properties": { - "children": { - "type": "object", - "description": "Defines the children. Use 'explicitList' for a fixed set of children, or 'template' to generate children from a data list.", - "additionalProperties": false, - "properties": { - "explicitList": { - "type": "array", - "items": { "type": "string" } - }, - "template": { - "type": "object", - "description": "A template for generating a dynamic list of children from a data model list. `componentId` is the component to use as a template, and `dataBinding` is the path to the map of components in the data model. Values in the map will define the list of children.", - "additionalProperties": false, - "properties": { - "componentId": { "type": "string" }, - "dataBinding": { "type": "string" } - }, - "required": ["componentId", "dataBinding"] - } - } - }, - "direction": { - "type": "string", - "description": "The direction in which the list items are laid out.", - "enum": ["vertical", "horizontal"] - }, - "alignment": { - "type": "string", - "description": "Defines the alignment of children along the cross axis.", - "enum": [ - "start", - "center", - "end", - "stretch" - ] - } - }, - "required": ["children"] - }, - "Card": { - "type": "object", - "additionalProperties": false, - "properties": { "child": { - "type": "string", - "description": "The ID of the component to be rendered inside the card." - } }, - "required": ["child"] - }, - "Tabs": { - "type": "object", - "additionalProperties": false, - "properties": { "tabItems": { - "type": "array", - "description": "An array of objects, where each object defines a tab with a title and a child component.", - "items": { - "type": "object", - "additionalProperties": false, - "properties": { - "title": { - "type": "object", - "description": "The tab title. Defines the value as either a literal value or a path to data model value (e.g. '/options/title').", - "additionalProperties": false, - "properties": { - "literalString": { "type": "string" }, - "path": { "type": "string" } - } - }, - "child": { "type": "string" } - }, - "required": ["title", "child"] - } - } }, - "required": ["tabItems"] - }, - "Divider": { - "type": "object", - "additionalProperties": false, - "properties": { "axis": { - "type": "string", - "description": "The orientation of the divider.", - "enum": ["horizontal", "vertical"] - } } - }, - "Modal": { - "type": "object", - "additionalProperties": false, - "properties": { - "entryPointChild": { - "type": "string", - "description": "The ID of the component that opens the modal when interacted with (e.g., a button)." - }, - "contentChild": { - "type": "string", - "description": "The ID of the component to be displayed inside the modal." - } - }, - "required": ["entryPointChild", "contentChild"] - }, - "Button": { - "type": "object", - "additionalProperties": false, - "properties": { - "child": { - "type": "string", - "description": "The ID of the component to display in the button, typically a Text component." - }, - "primary": { - "type": "boolean", - "description": "Indicates if this button should be styled as the primary action." - }, - "action": { - "type": "object", - "description": "The client-side action to be dispatched when the button is clicked. It includes the action's name and an optional context payload.", - "additionalProperties": false, - "properties": { - "name": { "type": "string" }, - "context": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": false, - "properties": { - "key": { "type": "string" }, - "value": { - "type": "object", - "description": "Defines the value to be included in the context as either a literal value or a path to a data model value (e.g. '/user/name').", - "additionalProperties": false, - "properties": { - "path": { "type": "string" }, - "literalString": { "type": "string" }, - "literalNumber": { "type": "number" }, - "literalBoolean": { "type": "boolean" } - } - } - }, - "required": ["key", "value"] - } - } - }, - "required": ["name"] - } - }, - "required": ["child", "action"] - }, - "CheckBox": { - "type": "object", - "additionalProperties": false, - "properties": { - "label": { - "type": "object", - "description": "The text to display next to the checkbox. Defines the value as either a literal value or a path to data model ('path', e.g. '/option/label').", - "additionalProperties": false, - "properties": { - "literalString": { "type": "string" }, - "path": { "type": "string" } - } - }, - "value": { - "type": "object", - "description": "The current state of the checkbox (true for checked, false for unchecked). This can be a literal boolean ('literalBoolean') or a reference to a value in the data model ('path', e.g. '/filter/open').", - "additionalProperties": false, - "properties": { - "literalBoolean": { "type": "boolean" }, - "path": { "type": "string" } - } - } - }, - "required": ["label", "value"] - }, - "TextField": { - "type": "object", - "additionalProperties": false, - "properties": { - "label": { - "type": "object", - "description": "The text label for the input field. This can be a literal string or a reference to a value in the data model ('path, e.g. '/user/name').", - "additionalProperties": false, - "properties": { - "literalString": { "type": "string" }, - "path": { "type": "string" } - } - }, - "text": { - "type": "object", - "description": "The value of the text field. This can be a literal string or a reference to a value in the data model ('path', e.g. '/user/name').", - "additionalProperties": false, - "properties": { - "literalString": { "type": "string" }, - "path": { "type": "string" } - } - }, - "textFieldType": { - "type": "string", - "description": "The type of input field to display.", - "enum": [ - "date", - "longText", - "number", - "shortText", - "obscured" - ] - }, - "validationRegexp": { - "type": "string", - "description": "A regular expression used for client-side validation of the input." - } - }, - "required": ["label"] - }, - "DateTimeInput": { - "type": "object", - "additionalProperties": false, - "properties": { - "value": { - "type": "object", - "description": "The selected date and/or time value. This can be a literal string ('literalString') or a reference to a value in the data model ('path', e.g. '/user/dob').", - "additionalProperties": false, - "properties": { - "literalString": { "type": "string" }, - "path": { "type": "string" } - } - }, - "enableDate": { - "type": "boolean", - "description": "If true, allows the user to select a date." - }, - "enableTime": { - "type": "boolean", - "description": "If true, allows the user to select a time." - }, - "outputFormat": { - "type": "string", - "description": "The desired format for the output string after a date or time is selected." - } - }, - "required": ["value"] - }, - "MultipleChoice": { - "type": "object", - "additionalProperties": false, - "properties": { - "selections": { - "type": "object", - "description": "The currently selected values for the component. This can be a literal array of strings or a path to an array in the data model('path', e.g. '/hotel/options').", - "additionalProperties": false, - "properties": { - "literalArray": { - "type": "array", - "items": { "type": "string" } - }, - "path": { "type": "string" } - } - }, - "options": { - "type": "array", - "description": "An array of available options for the user to choose from.", - "items": { - "type": "object", - "additionalProperties": false, - "properties": { - "label": { - "type": "object", - "description": "The text to display for this option. This can be a literal string or a reference to a value in the data model (e.g. '/option/label').", - "additionalProperties": false, - "properties": { - "literalString": { "type": "string" }, - "path": { "type": "string" } - } - }, - "value": { - "type": "string", - "description": "The value to be associated with this option when selected." - } - }, - "required": ["label", "value"] - } - }, - "maxAllowedSelections": { - "type": "integer", - "description": "The maximum number of options that the user is allowed to select." - } - }, - "required": ["selections", "options"] - }, - "Slider": { - "type": "object", - "additionalProperties": false, - "properties": { - "value": { - "type": "object", - "description": "The current value of the slider. This can be a literal number ('literalNumber') or a reference to a value in the data model ('path', e.g. '/restaurant/cost').", - "additionalProperties": false, - "properties": { - "literalNumber": { "type": "number" }, - "path": { "type": "string" } - } - }, - "minValue": { - "type": "number", - "description": "The minimum value of the slider." - }, - "maxValue": { - "type": "number", - "description": "The maximum value of the slider." - } - }, - "required": ["value"] - } - } - } - }, - "required": ["id", "component"] - } - } - }, - "required": ["surfaceId", "components"] - }, - "dataModelUpdate": { - "type": "object", - "description": "Updates the data model for a surface.", - "additionalProperties": false, - "properties": { - "surfaceId": { - "type": "string", - "description": "The unique identifier for the UI surface this data model update applies to." - }, - "path": { - "type": "string", - "description": "An optional path to a location within the data model (e.g., '/user/name'). If omitted, or set to '/', the entire data model will be replaced." - }, - "contents": { - "type": "array", - "description": "An array of data entries. Each entry must contain a 'key' and exactly one corresponding typed 'value*' property.", - "items": { - "type": "object", - "description": "A single data entry. Exactly one 'value*' property should be provided alongside the key.", - "additionalProperties": false, - "properties": { - "key": { - "type": "string", - "description": "The key for this data entry." - }, - "valueString": { "type": "string" }, - "valueNumber": { "type": "number" }, - "valueBoolean": { "type": "boolean" }, - "valueMap": { - "description": "Represents a map as an adjacency list.", - "type": "array", - "items": { - "type": "object", - "description": "One entry in the map. Exactly one 'value*' property should be provided alongside the key.", - "additionalProperties": false, - "properties": { - "key": { "type": "string" }, - "valueString": { "type": "string" }, - "valueNumber": { "type": "number" }, - "valueBoolean": { "type": "boolean" } - }, - "required": ["key"] - } - } - }, - "required": ["key"] - } - } - }, - "required": ["contents", "surfaceId"] - }, - "deleteSurface": { - "type": "object", - "description": "Signals the client to delete the surface identified by 'surfaceId'.", - "additionalProperties": false, - "properties": { "surfaceId": { - "type": "string", - "description": "The unique identifier for the UI surface to be deleted." - } }, - "required": ["surfaceId"] - } - } -}; - -const Data = { - createSignalA2uiMessageProcessor: create, - A2uiMessageProcessor, - Guards: guards_exports -}; -const Schemas = { A2UIClientEventMessage: server_to_client_with_standard_catalog_default }; - -/** -* @license -* Copyright 2017 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ -const t$1 = (t$7) => (e$14, o$15) => { - void 0 !== o$15 ? o$15.addInitializer(() => { - customElements.define(t$7, e$14); - }) : customElements.define(t$7, e$14); -}; - -/** -* @license -* Copyright 2017 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ const o$9 = { - attribute: !0, - type: String, - converter: u$3, - reflect: !1, - hasChanged: f$3 -}, r$7 = (t$7 = o$9, e$14, r$12) => { - const { kind: n$13, metadata: i$10 } = r$12; - let s$9 = globalThis.litPropertyMetadata.get(i$10); - if (void 0 === s$9 && globalThis.litPropertyMetadata.set(i$10, s$9 = new Map()), "setter" === n$13 && ((t$7 = Object.create(t$7)).wrapped = !0), s$9.set(r$12.name, t$7), "accessor" === n$13) { - const { name: o$15 } = r$12; - return { - set(r$13) { - const n$14 = e$14.get.call(this); - e$14.set.call(this, r$13), this.requestUpdate(o$15, n$14, t$7, !0, r$13); - }, - init(e$15) { - return void 0 !== e$15 && this.C(o$15, void 0, t$7, e$15), e$15; - } - }; - } - if ("setter" === n$13) { - const { name: o$15 } = r$12; - return function(r$13) { - const n$14 = this[o$15]; - e$14.call(this, r$13), this.requestUpdate(o$15, n$14, t$7, !0, r$13); - }; - } - throw Error("Unsupported decorator location: " + n$13); -}; -function n$6(t$7) { - return (e$14, o$15) => "object" == typeof o$15 ? r$7(t$7, e$14, o$15) : ((t$8, e$15, o$16) => { - const r$12 = e$15.hasOwnProperty(o$16); - return e$15.constructor.createProperty(o$16, t$8), r$12 ? Object.getOwnPropertyDescriptor(e$15, o$16) : void 0; - })(t$7, e$14, o$15); -} - -/** -* @license -* Copyright 2017 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ function r$6(r$12) { - return n$6({ - ...r$12, - state: !0, - attribute: !1 - }); -} - -/** -* @license -* Copyright 2017 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ -function t(t) { - return (n$13, o$15) => { - const c$7 = "function" == typeof n$13 ? n$13 : n$13[o$15]; - Object.assign(c$7, t); - }; -} - -/** -* @license -* Copyright 2017 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ -const e$6 = (e$14, t$7, c$7) => (c$7.configurable = !0, c$7.enumerable = !0, Reflect.decorate && "object" != typeof t$7 && Object.defineProperty(e$14, t$7, c$7), c$7); - -/** -* @license -* Copyright 2017 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ function e$5(e$14, r$12) { - return (n$13, s$9, i$10) => { - const o$15 = (t$7) => t$7.renderRoot?.querySelector(e$14) ?? null; - if (r$12) { - const { get: e$15, set: r$13 } = "object" == typeof s$9 ? n$13 : i$10 ?? (() => { - const t$7 = Symbol(); - return { - get() { - return this[t$7]; - }, - set(e$16) { - this[t$7] = e$16; - } - }; - })(); - return e$6(n$13, s$9, { get() { - let t$7 = e$15.call(this); - return void 0 === t$7 && (t$7 = o$15(this), (null !== t$7 || this.hasUpdated) && r$13.call(this, t$7)), t$7; - } }); - } - return e$6(n$13, s$9, { get() { - return o$15(this); - } }); - }; -} - -/** -* @license -* Copyright 2017 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ -let e$4; -function r$5(r$12) { - return (n$13, o$15) => e$6(n$13, o$15, { get() { - return (this.renderRoot ?? (e$4 ??= document.createDocumentFragment())).querySelectorAll(r$12); - } }); -} - -/** -* @license -* Copyright 2017 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ -function r$4(r$12) { - return (n$13, e$14) => e$6(n$13, e$14, { async get() { - return await this.updateComplete, this.renderRoot?.querySelector(r$12) ?? null; - } }); -} - -/** -* @license -* Copyright 2021 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ function o$8(o$15) { - return (e$14, n$13) => { - const { slot: r$12, selector: s$9 } = o$15 ?? {}, c$7 = "slot" + (r$12 ? `[name=${r$12}]` : ":not([name])"); - return e$6(e$14, n$13, { get() { - const t$7 = this.renderRoot?.querySelector(c$7), e$15 = t$7?.assignedElements(o$15) ?? []; - return void 0 === s$9 ? e$15 : e$15.filter((t$8) => t$8.matches(s$9)); - } }); - }; -} - -/** -* @license -* Copyright 2017 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ function n$5(n$13) { - return (o$15, r$12) => { - const { slot: e$14 } = n$13 ?? {}, s$9 = "slot" + (e$14 ? `[name=${e$14}]` : ":not([name])"); - return e$6(o$15, r$12, { get() { - const t$7 = this.renderRoot?.querySelector(s$9); - return t$7?.assignedNodes(n$13) ?? []; - } }); - }; -} - -/** -* @license -* Copyright 2023 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ let i$2 = !1; -const s$1 = new Signal.subtle.Watcher(() => { - i$2 || (i$2 = !0, queueMicrotask(() => { - i$2 = !1; - for (const t$7 of s$1.getPending()) t$7.get(); - s$1.watch(); - })); -}), h$3 = Symbol("SignalWatcherBrand"), e$3 = new FinalizationRegistry((i$10) => { - i$10.unwatch(...Signal.subtle.introspectSources(i$10)); -}), n$4 = new WeakMap(); -function o$7(i$10) { - return !0 === i$10[h$3] ? (console.warn("SignalWatcher should not be applied to the same class more than once."), i$10) : class extends i$10 { - constructor() { - super(...arguments), this._$St = new Map(), this._$So = new Signal.State(0), this._$Si = !1; - } - _$Sl() { - var t$7, i$11; - const s$9 = [], h$7 = []; - this._$St.forEach((t$8, i$12) => { - ((null == t$8 ? void 0 : t$8.beforeUpdate) ? s$9 : h$7).push(i$12); - }); - const e$14 = null === (t$7 = this.h) || void 0 === t$7 ? void 0 : t$7.getPending().filter((t$8) => t$8 !== this._$Su && !this._$St.has(t$8)); - s$9.forEach((t$8) => t$8.get()), null === (i$11 = this._$Su) || void 0 === i$11 || i$11.get(), e$14.forEach((t$8) => t$8.get()), h$7.forEach((t$8) => t$8.get()); - } - _$Sv() { - this.isUpdatePending || queueMicrotask(() => { - this.isUpdatePending || this._$Sl(); - }); - } - _$S_() { - if (void 0 !== this.h) return; - this._$Su = new Signal.Computed(() => { - this._$So.get(), super.performUpdate(); - }); - const i$11 = this.h = new Signal.subtle.Watcher(function() { - const t$7 = n$4.get(this); - void 0 !== t$7 && (!1 === t$7._$Si && (new Set(this.getPending()).has(t$7._$Su) ? t$7.requestUpdate() : t$7._$Sv()), this.watch()); - }); - n$4.set(i$11, this), e$3.register(this, i$11), i$11.watch(this._$Su), i$11.watch(...Array.from(this._$St).map(([t$7]) => t$7)); - } - _$Sp() { - if (void 0 === this.h) return; - let i$11 = !1; - this.h.unwatch(...Signal.subtle.introspectSources(this.h).filter((t$7) => { - var s$9; - const h$7 = !0 !== (null === (s$9 = this._$St.get(t$7)) || void 0 === s$9 ? void 0 : s$9.manualDispose); - return h$7 && this._$St.delete(t$7), i$11 || (i$11 = !h$7), h$7; - })), i$11 || (this._$Su = void 0, this.h = void 0, this._$St.clear()); - } - updateEffect(i$11, s$9) { - var h$7; - this._$S_(); - const e$14 = new Signal.Computed(() => { - i$11(); - }); - return this.h.watch(e$14), this._$St.set(e$14, s$9), null !== (h$7 = null == s$9 ? void 0 : s$9.beforeUpdate) && void 0 !== h$7 && h$7 ? Signal.subtle.untrack(() => e$14.get()) : this.updateComplete.then(() => Signal.subtle.untrack(() => e$14.get())), () => { - this._$St.delete(e$14), this.h.unwatch(e$14), !1 === this.isConnected && this._$Sp(); - }; - } - performUpdate() { - this.isUpdatePending && (this._$S_(), this._$Si = !0, this._$So.set(this._$So.get() + 1), this._$Si = !1, this._$Sl()); - } - connectedCallback() { - super.connectedCallback(), this.requestUpdate(); - } - disconnectedCallback() { - super.disconnectedCallback(), queueMicrotask(() => { - !1 === this.isConnected && this._$Sp(); - }); - } - }; -} - -/** -* @license -* Copyright 2017 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ const s = (i$10, t$7) => { - const e$14 = i$10._$AN; - if (void 0 === e$14) return !1; - for (const i$11 of e$14) i$11._$AO?.(t$7, !1), s(i$11, t$7); - return !0; -}, o$6 = (i$10) => { - let t$7, e$14; - do { - if (void 0 === (t$7 = i$10._$AM)) break; - e$14 = t$7._$AN, e$14.delete(i$10), i$10 = t$7; - } while (0 === e$14?.size); -}, r$3 = (i$10) => { - for (let t$7; t$7 = i$10._$AM; i$10 = t$7) { - let e$14 = t$7._$AN; - if (void 0 === e$14) t$7._$AN = e$14 = new Set(); - else if (e$14.has(i$10)) break; - e$14.add(i$10), c(t$7); - } -}; -function h$2(i$10) { - void 0 !== this._$AN ? (o$6(this), this._$AM = i$10, r$3(this)) : this._$AM = i$10; -} -function n$3(i$10, t$7 = !1, e$14 = 0) { - const r$12 = this._$AH, h$7 = this._$AN; - if (void 0 !== h$7 && 0 !== h$7.size) if (t$7) if (Array.isArray(r$12)) for (let i$11 = e$14; i$11 < r$12.length; i$11++) s(r$12[i$11], !1), o$6(r$12[i$11]); - else null != r$12 && (s(r$12, !1), o$6(r$12)); - else s(this, i$10); -} -const c = (i$10) => { - i$10.type == t$4.CHILD && (i$10._$AP ??= n$3, i$10._$AQ ??= h$2); -}; -var f = class extends i$5 { - constructor() { - super(...arguments), this._$AN = void 0; - } - _$AT(i$10, t$7, e$14) { - super._$AT(i$10, t$7, e$14), r$3(this), this.isConnected = i$10._$AU; - } - _$AO(i$10, t$7 = !0) { - i$10 !== this.isConnected && (this.isConnected = i$10, i$10 ? this.reconnected?.() : this.disconnected?.()), t$7 && (s(this, i$10), o$6(this)); - } - setValue(t$7) { - if (r$8(this._$Ct)) this._$Ct._$AI(t$7, this); - else { - const i$10 = [...this._$Ct._$AH]; - i$10[this._$Ci] = t$7, this._$Ct._$AI(i$10, this, 0); - } - } - disconnected() {} - reconnected() {} -}; - -/** -* @license -* Copyright 2023 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ -let o$5 = !1; -const n$2 = new Signal.subtle.Watcher(async () => { - o$5 || (o$5 = !0, queueMicrotask(() => { - o$5 = !1; - for (const i$10 of n$2.getPending()) i$10.get(); - n$2.watch(); - })); -}); -var r$2 = class extends f { - _$S_() { - var i$10, t$7; - void 0 === this._$Sm && (this._$Sj = new Signal.Computed(() => { - var i$11; - const t$8 = null === (i$11 = this._$SW) || void 0 === i$11 ? void 0 : i$11.get(); - return this.setValue(t$8), t$8; - }), this._$Sm = null !== (t$7 = null === (i$10 = this._$Sk) || void 0 === i$10 ? void 0 : i$10.h) && void 0 !== t$7 ? t$7 : n$2, this._$Sm.watch(this._$Sj), Signal.subtle.untrack(() => { - var i$11; - return null === (i$11 = this._$Sj) || void 0 === i$11 ? void 0 : i$11.get(); - })); - } - _$Sp() { - void 0 !== this._$Sm && (this._$Sm.unwatch(this._$SW), this._$Sm = void 0); - } - render(i$10) { - return Signal.subtle.untrack(() => i$10.get()); - } - update(i$10, [t$7]) { - var o$15, n$13; - return null !== (o$15 = this._$Sk) && void 0 !== o$15 || (this._$Sk = null === (n$13 = i$10.options) || void 0 === n$13 ? void 0 : n$13.host), t$7 !== this._$SW && void 0 !== this._$SW && this._$Sp(), this._$SW = t$7, this._$S_(), Signal.subtle.untrack(() => this._$SW.get()); - } - disconnected() { - this._$Sp(); - } - reconnected() { - this._$S_(); - } -}; -const h$1 = e$10(r$2); - -/** -* @license -* Copyright 2023 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ const m = (o$15) => (t$7, ...m) => o$15(t$7, ...m.map((o$16) => o$16 instanceof Signal.State || o$16 instanceof Signal.Computed ? h$1(o$16) : o$16)), l$1 = m(b), r$1 = m(w); - -/** -* @license -* Copyright 2023 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ const l = Signal.State, o$4 = Signal.Computed, r = (l, o$15) => new Signal.State(l, o$15), i$1 = (l, o$15) => new Signal.Computed(l, o$15); - -/** -* @license -* Copyright 2021 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ -function* o$3(o$15, f$4) { - if (void 0 !== o$15) { - let i$10 = 0; - for (const t$7 of o$15) yield f$4(t$7, i$10++); - } -} - -let pending = false; -let watcher = new Signal.subtle.Watcher(() => { - if (!pending) { - pending = true; - queueMicrotask(() => { - pending = false; - flushPending(); - }); - } -}); -function flushPending() { - for (const signal of watcher.getPending()) { - signal.get(); - } - watcher.watch(); -} -/** -* ⚠️ WARNING: Nothing unwatches ⚠️ -* This will produce a memory leak. -*/ -function effect(cb) { - let c$7 = new Signal.Computed(() => cb()); - watcher.watch(c$7); - c$7.get(); - return () => { - watcher.unwatch(c$7); - }; -} - -const themeContext = n$7("A2UITheme"); - -const structuralStyles = r$11(structuralStyles$1); - -var ComponentRegistry = class { - constructor() { - this.registry = new Map(); - } - register(typeName, constructor, tagName) { - if (!/^[a-zA-Z0-9]+$/.test(typeName)) { - throw new Error(`[Registry] Invalid typeName '${typeName}'. Must be alphanumeric.`); - } - this.registry.set(typeName, constructor); - const actualTagName = tagName || `a2ui-custom-${typeName.toLowerCase()}`; - const existingName = customElements.getName(constructor); - if (existingName) { - if (existingName !== actualTagName) { - throw new Error(`Component ${typeName} is already registered as ${existingName}, but requested as ${actualTagName}.`); - } - return; - } - if (!customElements.get(actualTagName)) { - customElements.define(actualTagName, constructor); - } - } - get(typeName) { - return this.registry.get(typeName); - } -}; -const componentRegistry = new ComponentRegistry(); - -var __runInitializers$19 = void 0 && (void 0).__runInitializers || function(thisArg, initializers, value) { - var useValue = arguments.length > 2; - for (var i$10 = 0; i$10 < initializers.length; i$10++) { - value = useValue ? initializers[i$10].call(thisArg, value) : initializers[i$10].call(thisArg); - } - return useValue ? value : void 0; -}; -var __esDecorate$19 = void 0 && (void 0).__esDecorate || function(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) { - function accept(f$4) { - if (f$4 !== void 0 && typeof f$4 !== "function") throw new TypeError("Function expected"); - return f$4; - } - var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value"; - var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null; - var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {}); - var _$1, done = false; - for (var i$10 = decorators.length - 1; i$10 >= 0; i$10--) { - var context = {}; - for (var p$3 in contextIn) context[p$3] = p$3 === "access" ? {} : contextIn[p$3]; - for (var p$3 in contextIn.access) context.access[p$3] = contextIn.access[p$3]; - context.addInitializer = function(f$4) { - if (done) throw new TypeError("Cannot add initializers after decoration has completed"); - extraInitializers.push(accept(f$4 || null)); - }; - var result = (0, decorators[i$10])(kind === "accessor" ? { - get: descriptor.get, - set: descriptor.set - } : descriptor[key], context); - if (kind === "accessor") { - if (result === void 0) continue; - if (result === null || typeof result !== "object") throw new TypeError("Object expected"); - if (_$1 = accept(result.get)) descriptor.get = _$1; - if (_$1 = accept(result.set)) descriptor.set = _$1; - if (_$1 = accept(result.init)) initializers.unshift(_$1); - } else if (_$1 = accept(result)) { - if (kind === "field") initializers.unshift(_$1); - else descriptor[key] = _$1; - } - } - if (target) Object.defineProperty(target, contextIn.name, descriptor); - done = true; -}; -let Root = (() => { - let _classDecorators = [t$1("a2ui-root")]; - let _classDescriptor; - let _classExtraInitializers = []; - let _classThis; - let _classSuper = o$7(i$6); - let _instanceExtraInitializers = []; - let _surfaceId_decorators; - let _surfaceId_initializers = []; - let _surfaceId_extraInitializers = []; - let _component_decorators; - let _component_initializers = []; - let _component_extraInitializers = []; - let _theme_decorators; - let _theme_initializers = []; - let _theme_extraInitializers = []; - let _childComponents_decorators; - let _childComponents_initializers = []; - let _childComponents_extraInitializers = []; - let _processor_decorators; - let _processor_initializers = []; - let _processor_extraInitializers = []; - let _dataContextPath_decorators; - let _dataContextPath_initializers = []; - let _dataContextPath_extraInitializers = []; - let _enableCustomElements_decorators; - let _enableCustomElements_initializers = []; - let _enableCustomElements_extraInitializers = []; - let _set_weight_decorators; - var Root = class extends _classSuper { - static { - _classThis = this; - } - static { - const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0; - _surfaceId_decorators = [n$6()]; - _component_decorators = [n$6()]; - _theme_decorators = [c$1({ context: themeContext })]; - _childComponents_decorators = [n$6({ attribute: false })]; - _processor_decorators = [n$6({ attribute: false })]; - _dataContextPath_decorators = [n$6()]; - _enableCustomElements_decorators = [n$6()]; - _set_weight_decorators = [n$6()]; - __esDecorate$19(this, null, _surfaceId_decorators, { - kind: "accessor", - name: "surfaceId", - static: false, - private: false, - access: { - has: (obj) => "surfaceId" in obj, - get: (obj) => obj.surfaceId, - set: (obj, value) => { - obj.surfaceId = value; - } - }, - metadata: _metadata - }, _surfaceId_initializers, _surfaceId_extraInitializers); - __esDecorate$19(this, null, _component_decorators, { - kind: "accessor", - name: "component", - static: false, - private: false, - access: { - has: (obj) => "component" in obj, - get: (obj) => obj.component, - set: (obj, value) => { - obj.component = value; - } - }, - metadata: _metadata - }, _component_initializers, _component_extraInitializers); - __esDecorate$19(this, null, _theme_decorators, { - kind: "accessor", - name: "theme", - static: false, - private: false, - access: { - has: (obj) => "theme" in obj, - get: (obj) => obj.theme, - set: (obj, value) => { - obj.theme = value; - } - }, - metadata: _metadata - }, _theme_initializers, _theme_extraInitializers); - __esDecorate$19(this, null, _childComponents_decorators, { - kind: "accessor", - name: "childComponents", - static: false, - private: false, - access: { - has: (obj) => "childComponents" in obj, - get: (obj) => obj.childComponents, - set: (obj, value) => { - obj.childComponents = value; - } - }, - metadata: _metadata - }, _childComponents_initializers, _childComponents_extraInitializers); - __esDecorate$19(this, null, _processor_decorators, { - kind: "accessor", - name: "processor", - static: false, - private: false, - access: { - has: (obj) => "processor" in obj, - get: (obj) => obj.processor, - set: (obj, value) => { - obj.processor = value; - } - }, - metadata: _metadata - }, _processor_initializers, _processor_extraInitializers); - __esDecorate$19(this, null, _dataContextPath_decorators, { - kind: "accessor", - name: "dataContextPath", - static: false, - private: false, - access: { - has: (obj) => "dataContextPath" in obj, - get: (obj) => obj.dataContextPath, - set: (obj, value) => { - obj.dataContextPath = value; - } - }, - metadata: _metadata - }, _dataContextPath_initializers, _dataContextPath_extraInitializers); - __esDecorate$19(this, null, _enableCustomElements_decorators, { - kind: "accessor", - name: "enableCustomElements", - static: false, - private: false, - access: { - has: (obj) => "enableCustomElements" in obj, - get: (obj) => obj.enableCustomElements, - set: (obj, value) => { - obj.enableCustomElements = value; - } - }, - metadata: _metadata - }, _enableCustomElements_initializers, _enableCustomElements_extraInitializers); - __esDecorate$19(this, null, _set_weight_decorators, { - kind: "setter", - name: "weight", - static: false, - private: false, - access: { - has: (obj) => "weight" in obj, - set: (obj, value) => { - obj.weight = value; - } - }, - metadata: _metadata - }, null, _instanceExtraInitializers); - __esDecorate$19(null, _classDescriptor = { value: _classThis }, _classDecorators, { - kind: "class", - name: _classThis.name, - metadata: _metadata - }, null, _classExtraInitializers); - Root = _classThis = _classDescriptor.value; - if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { - enumerable: true, - configurable: true, - writable: true, - value: _metadata - }); - } - #surfaceId_accessor_storage = (__runInitializers$19(this, _instanceExtraInitializers), __runInitializers$19(this, _surfaceId_initializers, null)); - get surfaceId() { - return this.#surfaceId_accessor_storage; - } - set surfaceId(value) { - this.#surfaceId_accessor_storage = value; - } - #component_accessor_storage = (__runInitializers$19(this, _surfaceId_extraInitializers), __runInitializers$19(this, _component_initializers, null)); - get component() { - return this.#component_accessor_storage; - } - set component(value) { - this.#component_accessor_storage = value; - } - #theme_accessor_storage = (__runInitializers$19(this, _component_extraInitializers), __runInitializers$19(this, _theme_initializers, void 0)); - get theme() { - return this.#theme_accessor_storage; - } - set theme(value) { - this.#theme_accessor_storage = value; - } - #childComponents_accessor_storage = (__runInitializers$19(this, _theme_extraInitializers), __runInitializers$19(this, _childComponents_initializers, null)); - get childComponents() { - return this.#childComponents_accessor_storage; - } - set childComponents(value) { - this.#childComponents_accessor_storage = value; - } - #processor_accessor_storage = (__runInitializers$19(this, _childComponents_extraInitializers), __runInitializers$19(this, _processor_initializers, null)); - get processor() { - return this.#processor_accessor_storage; - } - set processor(value) { - this.#processor_accessor_storage = value; - } - #dataContextPath_accessor_storage = (__runInitializers$19(this, _processor_extraInitializers), __runInitializers$19(this, _dataContextPath_initializers, "")); - get dataContextPath() { - return this.#dataContextPath_accessor_storage; - } - set dataContextPath(value) { - this.#dataContextPath_accessor_storage = value; - } - #enableCustomElements_accessor_storage = (__runInitializers$19(this, _dataContextPath_extraInitializers), __runInitializers$19(this, _enableCustomElements_initializers, false)); - get enableCustomElements() { - return this.#enableCustomElements_accessor_storage; - } - set enableCustomElements(value) { - this.#enableCustomElements_accessor_storage = value; - } - set weight(weight) { - this.#weight = weight; - this.style.setProperty("--weight", `${weight}`); - } - get weight() { - return this.#weight; - } - #weight = (__runInitializers$19(this, _enableCustomElements_extraInitializers), 1); - static { - this.styles = [structuralStyles, i$9` - :host { - display: flex; - flex-direction: column; - gap: 8px; - max-height: 80%; - } - `]; - } - /** - * Holds the cleanup function for our effect. - * We need this to stop the effect when the component is disconnected. - */ - #lightDomEffectDisposer = null; - willUpdate(changedProperties) { - if (changedProperties.has("childComponents")) { - if (this.#lightDomEffectDisposer) { - this.#lightDomEffectDisposer(); - } - this.#lightDomEffectDisposer = effect(() => { - const allChildren = this.childComponents ?? null; - const lightDomTemplate = this.renderComponentTree(allChildren); - D(lightDomTemplate, this, { host: this }); - }); - } - } - /** - * Clean up the effect when the component is removed from the DOM. - */ - disconnectedCallback() { - super.disconnectedCallback(); - if (this.#lightDomEffectDisposer) { - this.#lightDomEffectDisposer(); - } - } - /** - * Turns the SignalMap into a renderable TemplateResult for Lit. - */ - renderComponentTree(components) { - if (!components) { - return A; - } - if (!Array.isArray(components)) { - return A; - } - return b` ${o$3(components, (component) => { - if (this.enableCustomElements) { - const registeredCtor = componentRegistry.get(component.type); - const elCtor = registeredCtor || customElements.get(component.type); - if (elCtor) { - const node = component; - const el = new elCtor(); - el.id = node.id; - if (node.slotName) { - el.slot = node.slotName; - } - el.component = node; - el.weight = node.weight ?? "initial"; - el.processor = this.processor; - el.surfaceId = this.surfaceId; - el.dataContextPath = node.dataContextPath ?? "/"; - for (const [prop, val] of Object.entries(component.properties)) { - el[prop] = val; - } - return b`${el}`; - } - } - switch (component.type) { - case "List": { - const node = component; - const childComponents = node.properties.children; - return b``; - } - case "Card": { - const node = component; - let childComponents = node.properties.children; - if (!childComponents && node.properties.child) { - childComponents = [node.properties.child]; - } - return b``; - } - case "Column": { - const node = component; - return b``; - } - case "Row": { - const node = component; - return b``; - } - case "Image": { - const node = component; - return b``; - } - case "Icon": { - const node = component; - return b``; - } - case "AudioPlayer": { - const node = component; - return b``; - } - case "Button": { - const node = component; - return b``; - } - case "Text": { - const node = component; - return b``; - } - case "CheckBox": { - const node = component; - return b``; - } - case "DateTimeInput": { - const node = component; - return b``; - } - case "Divider": { - const node = component; - return b``; - } - case "MultipleChoice": { - const node = component; - return b``; - } - case "Slider": { - const node = component; - return b``; - } - case "TextField": { - const node = component; - return b``; - } - case "Video": { - const node = component; - return b``; - } - case "Tabs": { - const node = component; - const titles = []; - const childComponents = []; - if (node.properties.tabItems) { - for (const item of node.properties.tabItems) { - titles.push(item.title); - childComponents.push(item.child); - } - } - return b``; - } - case "Modal": { - const node = component; - const childComponents = [node.properties.entryPointChild, node.properties.contentChild]; - node.properties.entryPointChild.slotName = "entry"; - return b``; - } - default: { - return this.renderCustomComponent(component); - } - } - })}`; - } - renderCustomComponent(component) { - if (!this.enableCustomElements) { - return; - } - const node = component; - const registeredCtor = componentRegistry.get(component.type); - const elCtor = registeredCtor || customElements.get(component.type); - if (!elCtor) { - return b`Unknown element ${component.type}`; - } - const el = new elCtor(); - el.id = node.id; - if (node.slotName) { - el.slot = node.slotName; - } - el.component = node; - el.weight = node.weight ?? "initial"; - el.processor = this.processor; - el.surfaceId = this.surfaceId; - el.dataContextPath = node.dataContextPath ?? "/"; - for (const [prop, val] of Object.entries(component.properties)) { - el[prop] = val; - } - return b`${el}`; - } - render() { - return b``; - } - static { - __runInitializers$19(_classThis, _classExtraInitializers); - } - }; - return Root = _classThis; -})(); - -/** -* @license -* Copyright 2018 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ const e$2 = e$10(class extends i$5 { - constructor(t$7) { - if (super(t$7), t$7.type !== t$4.ATTRIBUTE || "class" !== t$7.name || t$7.strings?.length > 2) throw Error("`classMap()` can only be used in the `class` attribute and must be the only part in the attribute."); - } - render(t$7) { - return " " + Object.keys(t$7).filter((s$9) => t$7[s$9]).join(" ") + " "; - } - update(s$9, [i$10]) { - if (void 0 === this.st) { - this.st = new Set(), void 0 !== s$9.strings && (this.nt = new Set(s$9.strings.join(" ").split(/\s/).filter((t$7) => "" !== t$7))); - for (const t$7 in i$10) i$10[t$7] && !this.nt?.has(t$7) && this.st.add(t$7); - return this.render(i$10); - } - const r$12 = s$9.element.classList; - for (const t$7 of this.st) t$7 in i$10 || (r$12.remove(t$7), this.st.delete(t$7)); - for (const t$7 in i$10) { - const s$10 = !!i$10[t$7]; - s$10 === this.st.has(t$7) || this.nt?.has(t$7) || (s$10 ? (r$12.add(t$7), this.st.add(t$7)) : (r$12.remove(t$7), this.st.delete(t$7))); - } - return E; - } -}); - -/** -* @license -* Copyright 2018 Google LLC -* SPDX-License-Identifier: BSD-3-Clause -*/ const n$1 = "important", i = " !" + n$1, o$2 = e$10(class extends i$5 { - constructor(t$7) { - if (super(t$7), t$7.type !== t$4.ATTRIBUTE || "style" !== t$7.name || t$7.strings?.length > 2) throw Error("The `styleMap` directive must be used in the `style` attribute and must be the only part in the attribute."); - } - render(t$7) { - return Object.keys(t$7).reduce((e$14, r$12) => { - const s$9 = t$7[r$12]; - return null == s$9 ? e$14 : e$14 + `${r$12 = r$12.includes("-") ? r$12 : r$12.replace(/(?:^(webkit|moz|ms|o)|)(?=[A-Z])/g, "-$&").toLowerCase()}:${s$9};`; - }, ""); - } - update(e$14, [r$12]) { - const { style: s$9 } = e$14.element; - if (void 0 === this.ft) return this.ft = new Set(Object.keys(r$12)), this.render(r$12); - for (const t$7 of this.ft) null == r$12[t$7] && (this.ft.delete(t$7), t$7.includes("-") ? s$9.removeProperty(t$7) : s$9[t$7] = null); - for (const t$7 in r$12) { - const e$15 = r$12[t$7]; - if (null != e$15) { - this.ft.add(t$7); - const r$13 = "string" == typeof e$15 && e$15.endsWith(i); - t$7.includes("-") || r$13 ? s$9.setProperty(t$7, r$13 ? e$15.slice(0, -11) : e$15, r$13 ? n$1 : "") : s$9[t$7] = e$15; - } - } - return E; - } -}); - -var __esDecorate$18 = void 0 && (void 0).__esDecorate || function(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) { - function accept(f$4) { - if (f$4 !== void 0 && typeof f$4 !== "function") throw new TypeError("Function expected"); - return f$4; - } - var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value"; - var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null; - var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {}); - var _$1, done = false; - for (var i$10 = decorators.length - 1; i$10 >= 0; i$10--) { - var context = {}; - for (var p$3 in contextIn) context[p$3] = p$3 === "access" ? {} : contextIn[p$3]; - for (var p$3 in contextIn.access) context.access[p$3] = contextIn.access[p$3]; - context.addInitializer = function(f$4) { - if (done) throw new TypeError("Cannot add initializers after decoration has completed"); - extraInitializers.push(accept(f$4 || null)); - }; - var result = (0, decorators[i$10])(kind === "accessor" ? { - get: descriptor.get, - set: descriptor.set - } : descriptor[key], context); - if (kind === "accessor") { - if (result === void 0) continue; - if (result === null || typeof result !== "object") throw new TypeError("Object expected"); - if (_$1 = accept(result.get)) descriptor.get = _$1; - if (_$1 = accept(result.set)) descriptor.set = _$1; - if (_$1 = accept(result.init)) initializers.unshift(_$1); - } else if (_$1 = accept(result)) { - if (kind === "field") initializers.unshift(_$1); - else descriptor[key] = _$1; - } - } - if (target) Object.defineProperty(target, contextIn.name, descriptor); - done = true; -}; -var __runInitializers$18 = void 0 && (void 0).__runInitializers || function(thisArg, initializers, value) { - var useValue = arguments.length > 2; - for (var i$10 = 0; i$10 < initializers.length; i$10++) { - value = useValue ? initializers[i$10].call(thisArg, value) : initializers[i$10].call(thisArg); - } - return useValue ? value : void 0; -}; -let Audio = (() => { - let _classDecorators = [t$1("a2ui-audioplayer")]; - let _classDescriptor; - let _classExtraInitializers = []; - let _classThis; - let _classSuper = Root; - let _url_decorators; - let _url_initializers = []; - let _url_extraInitializers = []; - var Audio = class extends _classSuper { - static { - _classThis = this; - } - static { - const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0; - _url_decorators = [n$6()]; - __esDecorate$18(this, null, _url_decorators, { - kind: "accessor", - name: "url", - static: false, - private: false, - access: { - has: (obj) => "url" in obj, - get: (obj) => obj.url, - set: (obj, value) => { - obj.url = value; - } - }, - metadata: _metadata - }, _url_initializers, _url_extraInitializers); - __esDecorate$18(null, _classDescriptor = { value: _classThis }, _classDecorators, { - kind: "class", - name: _classThis.name, - metadata: _metadata - }, null, _classExtraInitializers); - Audio = _classThis = _classDescriptor.value; - if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { - enumerable: true, - configurable: true, - writable: true, - value: _metadata - }); - } - #url_accessor_storage = __runInitializers$18(this, _url_initializers, null); - get url() { - return this.#url_accessor_storage; - } - set url(value) { - this.#url_accessor_storage = value; - } - static { - this.styles = [structuralStyles, i$9` - * { - box-sizing: border-box; - } - - :host { - display: block; - flex: var(--weight); - min-height: 0; - overflow: auto; - } - - audio { - display: block; - width: 100%; - } - `]; - } - #renderAudio() { - if (!this.url) { - return A; - } - if (this.url && typeof this.url === "object") { - if ("literalString" in this.url) { - return b`
    "; -}; -default_rules.code_block = function(tokens, idx, options, env, slf) { - const token = tokens[idx]; - return "" + escapeHtml(tokens[idx].content) + "\n"; -}; -default_rules.fence = function(tokens, idx, options, env, slf) { - const token = tokens[idx]; - const info = token.info ? unescapeAll(token.info).trim() : ""; - let langName = ""; - let langAttrs = ""; - if (info) { - const arr = info.split(/(\s+)/g); - langName = arr[0]; - langAttrs = arr.slice(2).join(""); - } - let highlighted; - if (options.highlight) { - highlighted = options.highlight(token.content, langName, langAttrs) || escapeHtml(token.content); - } else { - highlighted = escapeHtml(token.content); - } - if (highlighted.indexOf("${highlighted}
    \n`; - } - return `
    ${highlighted}
    \n`; -}; -default_rules.image = function(tokens, idx, options, env, slf) { - const token = tokens[idx]; - token.attrs[token.attrIndex("alt")][1] = slf.renderInlineAsText(token.children, options, env); - return slf.renderToken(tokens, idx, options); -}; -default_rules.hardbreak = function(tokens, idx, options) { - return options.xhtmlOut ? "
    \n" : "
    \n"; -}; -default_rules.softbreak = function(tokens, idx, options) { - return options.breaks ? options.xhtmlOut ? "
    \n" : "
    \n" : "\n"; -}; -default_rules.text = function(tokens, idx) { - return escapeHtml(tokens[idx].content); -}; -default_rules.html_block = function(tokens, idx) { - return tokens[idx].content; -}; -default_rules.html_inline = function(tokens, idx) { - return tokens[idx].content; -}; -/** -* new Renderer() -* -* Creates new [[Renderer]] instance and fill [[Renderer#rules]] with defaults. -**/ -function Renderer() { - /** - * Renderer#rules -> Object - * - * Contains render rules for tokens. Can be updated and extended. - * - * ##### Example - * - * ```javascript - * var md = require('markdown-it')(); - * - * md.renderer.rules.strong_open = function () { return ''; }; - * md.renderer.rules.strong_close = function () { return ''; }; - * - * var result = md.renderInline(...); - * ``` - * - * Each rule is called as independent static function with fixed signature: - * - * ```javascript - * function my_token_render(tokens, idx, options, env, renderer) { - * // ... - * return renderedHTML; - * } - * ``` - * - * See [source code](https://github.com/markdown-it/markdown-it/blob/master/lib/renderer.mjs) - * for more details and examples. - **/ - this.rules = assign$1({}, default_rules); -} -/** -* Renderer.renderAttrs(token) -> String -* -* Render token attributes to string. -**/ -Renderer.prototype.renderAttrs = function renderAttrs(token) { - let i$10, l$5, result; - if (!token.attrs) { - return ""; - } - result = ""; - for (i$10 = 0, l$5 = token.attrs.length; i$10 < l$5; i$10++) { - result += " " + escapeHtml(token.attrs[i$10][0]) + "=\"" + escapeHtml(token.attrs[i$10][1]) + "\""; - } - return result; -}; -/** -* Renderer.renderToken(tokens, idx, options) -> String -* - tokens (Array): list of tokens -* - idx (Numbed): token index to render -* - options (Object): params of parser instance -* -* Default token renderer. Can be overriden by custom function -* in [[Renderer#rules]]. -**/ -Renderer.prototype.renderToken = function renderToken(tokens, idx, options) { - const token = tokens[idx]; - let result = ""; - if (token.hidden) { - return ""; - } - if (token.block && token.nesting !== -1 && idx && tokens[idx - 1].hidden) { - result += "\n"; - } - result += (token.nesting === -1 ? "\n" : ">"; - return result; -}; -/** -* Renderer.renderInline(tokens, options, env) -> String -* - tokens (Array): list on block tokens to render -* - options (Object): params of parser instance -* - env (Object): additional data from parsed input (references, for example) -* -* The same as [[Renderer.render]], but for single token of `inline` type. -**/ -Renderer.prototype.renderInline = function(tokens, options, env) { - let result = ""; - const rules = this.rules; - for (let i$10 = 0, len = tokens.length; i$10 < len; i$10++) { - const type$2 = tokens[i$10].type; - if (typeof rules[type$2] !== "undefined") { - result += rules[type$2](tokens, i$10, options, env, this); - } else { - result += this.renderToken(tokens, i$10, options); - } - } - return result; -}; -/** internal -* Renderer.renderInlineAsText(tokens, options, env) -> String -* - tokens (Array): list on block tokens to render -* - options (Object): params of parser instance -* - env (Object): additional data from parsed input (references, for example) -* -* Special kludge for image `alt` attributes to conform CommonMark spec. -* Don't try to use it! Spec requires to show `alt` content with stripped markup, -* instead of simple escaping. -**/ -Renderer.prototype.renderInlineAsText = function(tokens, options, env) { - let result = ""; - for (let i$10 = 0, len = tokens.length; i$10 < len; i$10++) { - switch (tokens[i$10].type) { - case "text": - result += tokens[i$10].content; - break; - case "image": - result += this.renderInlineAsText(tokens[i$10].children, options, env); - break; - case "html_inline": - case "html_block": - result += tokens[i$10].content; - break; - case "softbreak": - case "hardbreak": - result += "\n"; - break; - default: - } - } - return result; -}; -/** -* Renderer.render(tokens, options, env) -> String -* - tokens (Array): list on block tokens to render -* - options (Object): params of parser instance -* - env (Object): additional data from parsed input (references, for example) -* -* Takes token stream and generates HTML. Probably, you will never need to call -* this method directly. -**/ -Renderer.prototype.render = function(tokens, options, env) { - let result = ""; - const rules = this.rules; - for (let i$10 = 0, len = tokens.length; i$10 < len; i$10++) { - const type$2 = tokens[i$10].type; - if (type$2 === "inline") { - result += this.renderInline(tokens[i$10].children, options, env); - } else if (typeof rules[type$2] !== "undefined") { - result += rules[type$2](tokens, i$10, options, env, this); - } else { - result += this.renderToken(tokens, i$10, options, env); - } - } - return result; -}; -var renderer_default = Renderer; - -/** -* class Ruler -* -* Helper class, used by [[MarkdownIt#core]], [[MarkdownIt#block]] and -* [[MarkdownIt#inline]] to manage sequences of functions (rules): -* -* - keep rules in defined order -* - assign the name to each rule -* - enable/disable rules -* - add/replace rules -* - allow assign rules to additional named chains (in the same) -* - cacheing lists of active rules -* -* You will not need use this class directly until write plugins. For simple -* rules control use [[MarkdownIt.disable]], [[MarkdownIt.enable]] and -* [[MarkdownIt.use]]. -**/ -/** -* new Ruler() -**/ -function Ruler() { - this.__rules__ = []; - this.__cache__ = null; -} -Ruler.prototype.__find__ = function(name) { - for (let i$10 = 0; i$10 < this.__rules__.length; i$10++) { - if (this.__rules__[i$10].name === name) { - return i$10; - } - } - return -1; -}; -Ruler.prototype.__compile__ = function() { - const self = this; - const chains = [""]; - self.__rules__.forEach(function(rule) { - if (!rule.enabled) { - return; - } - rule.alt.forEach(function(altName) { - if (chains.indexOf(altName) < 0) { - chains.push(altName); - } - }); - }); - self.__cache__ = {}; - chains.forEach(function(chain) { - self.__cache__[chain] = []; - self.__rules__.forEach(function(rule) { - if (!rule.enabled) { - return; - } - if (chain && rule.alt.indexOf(chain) < 0) { - return; - } - self.__cache__[chain].push(rule.fn); - }); - }); -}; -/** -* Ruler.at(name, fn [, options]) -* - name (String): rule name to replace. -* - fn (Function): new rule function. -* - options (Object): new rule options (not mandatory). -* -* Replace rule by name with new function & options. Throws error if name not -* found. -* -* ##### Options: -* -* - __alt__ - array with names of "alternate" chains. -* -* ##### Example -* -* Replace existing typographer replacement rule with new one: -* -* ```javascript -* var md = require('markdown-it')(); -* -* md.core.ruler.at('replacements', function replace(state) { -* //... -* }); -* ``` -**/ -Ruler.prototype.at = function(name, fn, options) { - const index = this.__find__(name); - const opt = options || {}; - if (index === -1) { - throw new Error("Parser rule not found: " + name); - } - this.__rules__[index].fn = fn; - this.__rules__[index].alt = opt.alt || []; - this.__cache__ = null; -}; -/** -* Ruler.before(beforeName, ruleName, fn [, options]) -* - beforeName (String): new rule will be added before this one. -* - ruleName (String): name of added rule. -* - fn (Function): rule function. -* - options (Object): rule options (not mandatory). -* -* Add new rule to chain before one with given name. See also -* [[Ruler.after]], [[Ruler.push]]. -* -* ##### Options: -* -* - __alt__ - array with names of "alternate" chains. -* -* ##### Example -* -* ```javascript -* var md = require('markdown-it')(); -* -* md.block.ruler.before('paragraph', 'my_rule', function replace(state) { -* //... -* }); -* ``` -**/ -Ruler.prototype.before = function(beforeName, ruleName, fn, options) { - const index = this.__find__(beforeName); - const opt = options || {}; - if (index === -1) { - throw new Error("Parser rule not found: " + beforeName); - } - this.__rules__.splice(index, 0, { - name: ruleName, - enabled: true, - fn, - alt: opt.alt || [] - }); - this.__cache__ = null; -}; -/** -* Ruler.after(afterName, ruleName, fn [, options]) -* - afterName (String): new rule will be added after this one. -* - ruleName (String): name of added rule. -* - fn (Function): rule function. -* - options (Object): rule options (not mandatory). -* -* Add new rule to chain after one with given name. See also -* [[Ruler.before]], [[Ruler.push]]. -* -* ##### Options: -* -* - __alt__ - array with names of "alternate" chains. -* -* ##### Example -* -* ```javascript -* var md = require('markdown-it')(); -* -* md.inline.ruler.after('text', 'my_rule', function replace(state) { -* //... -* }); -* ``` -**/ -Ruler.prototype.after = function(afterName, ruleName, fn, options) { - const index = this.__find__(afterName); - const opt = options || {}; - if (index === -1) { - throw new Error("Parser rule not found: " + afterName); - } - this.__rules__.splice(index + 1, 0, { - name: ruleName, - enabled: true, - fn, - alt: opt.alt || [] - }); - this.__cache__ = null; -}; -/** -* Ruler.push(ruleName, fn [, options]) -* - ruleName (String): name of added rule. -* - fn (Function): rule function. -* - options (Object): rule options (not mandatory). -* -* Push new rule to the end of chain. See also -* [[Ruler.before]], [[Ruler.after]]. -* -* ##### Options: -* -* - __alt__ - array with names of "alternate" chains. -* -* ##### Example -* -* ```javascript -* var md = require('markdown-it')(); -* -* md.core.ruler.push('my_rule', function replace(state) { -* //... -* }); -* ``` -**/ -Ruler.prototype.push = function(ruleName, fn, options) { - const opt = options || {}; - this.__rules__.push({ - name: ruleName, - enabled: true, - fn, - alt: opt.alt || [] - }); - this.__cache__ = null; -}; -/** -* Ruler.enable(list [, ignoreInvalid]) -> Array -* - list (String|Array): list of rule names to enable. -* - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found. -* -* Enable rules with given names. If any rule name not found - throw Error. -* Errors can be disabled by second param. -* -* Returns list of found rule names (if no exception happened). -* -* See also [[Ruler.disable]], [[Ruler.enableOnly]]. -**/ -Ruler.prototype.enable = function(list$1, ignoreInvalid) { - if (!Array.isArray(list$1)) { - list$1 = [list$1]; - } - const result = []; - list$1.forEach(function(name) { - const idx = this.__find__(name); - if (idx < 0) { - if (ignoreInvalid) { - return; - } - throw new Error("Rules manager: invalid rule name " + name); - } - this.__rules__[idx].enabled = true; - result.push(name); - }, this); - this.__cache__ = null; - return result; -}; -/** -* Ruler.enableOnly(list [, ignoreInvalid]) -* - list (String|Array): list of rule names to enable (whitelist). -* - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found. -* -* Enable rules with given names, and disable everything else. If any rule name -* not found - throw Error. Errors can be disabled by second param. -* -* See also [[Ruler.disable]], [[Ruler.enable]]. -**/ -Ruler.prototype.enableOnly = function(list$1, ignoreInvalid) { - if (!Array.isArray(list$1)) { - list$1 = [list$1]; - } - this.__rules__.forEach(function(rule) { - rule.enabled = false; - }); - this.enable(list$1, ignoreInvalid); -}; -/** -* Ruler.disable(list [, ignoreInvalid]) -> Array -* - list (String|Array): list of rule names to disable. -* - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found. -* -* Disable rules with given names. If any rule name not found - throw Error. -* Errors can be disabled by second param. -* -* Returns list of found rule names (if no exception happened). -* -* See also [[Ruler.enable]], [[Ruler.enableOnly]]. -**/ -Ruler.prototype.disable = function(list$1, ignoreInvalid) { - if (!Array.isArray(list$1)) { - list$1 = [list$1]; - } - const result = []; - list$1.forEach(function(name) { - const idx = this.__find__(name); - if (idx < 0) { - if (ignoreInvalid) { - return; - } - throw new Error("Rules manager: invalid rule name " + name); - } - this.__rules__[idx].enabled = false; - result.push(name); - }, this); - this.__cache__ = null; - return result; -}; -/** -* Ruler.getRules(chainName) -> Array -* -* Return array of active functions (rules) for given chain name. It analyzes -* rules configuration, compiles caches if not exists and returns result. -* -* Default chain name is `''` (empty string). It can't be skipped. That's -* done intentionally, to keep signature monomorphic for high speed. -**/ -Ruler.prototype.getRules = function(chainName) { - if (this.__cache__ === null) { - this.__compile__(); - } - return this.__cache__[chainName] || []; -}; -var ruler_default = Ruler; - -/** -* class Token -**/ -/** -* new Token(type, tag, nesting) -* -* Create new token and fill passed properties. -**/ -function Token(type$2, tag, nesting) { - /** - * Token#type -> String - * - * Type of the token (string, e.g. "paragraph_open") - **/ - this.type = type$2; - /** - * Token#tag -> String - * - * html tag name, e.g. "p" - **/ - this.tag = tag; - /** - * Token#attrs -> Array - * - * Html attributes. Format: `[ [ name1, value1 ], [ name2, value2 ] ]` - **/ - this.attrs = null; - /** - * Token#map -> Array - * - * Source map info. Format: `[ line_begin, line_end ]` - **/ - this.map = null; - /** - * Token#nesting -> Number - * - * Level change (number in {-1, 0, 1} set), where: - * - * - `1` means the tag is opening - * - `0` means the tag is self-closing - * - `-1` means the tag is closing - **/ - this.nesting = nesting; - /** - * Token#level -> Number - * - * nesting level, the same as `state.level` - **/ - this.level = 0; - /** - * Token#children -> Array - * - * An array of child nodes (inline and img tokens) - **/ - this.children = null; - /** - * Token#content -> String - * - * In a case of self-closing tag (code, html, fence, etc.), - * it has contents of this tag. - **/ - this.content = ""; - /** - * Token#markup -> String - * - * '*' or '_' for emphasis, fence string for fence, etc. - **/ - this.markup = ""; - /** - * Token#info -> String - * - * Additional information: - * - * - Info string for "fence" tokens - * - The value "auto" for autolink "link_open" and "link_close" tokens - * - The string value of the item marker for ordered-list "list_item_open" tokens - **/ - this.info = ""; - /** - * Token#meta -> Object - * - * A place for plugins to store an arbitrary data - **/ - this.meta = null; - /** - * Token#block -> Boolean - * - * True for block-level tokens, false for inline tokens. - * Used in renderer to calculate line breaks - **/ - this.block = false; - /** - * Token#hidden -> Boolean - * - * If it's true, ignore this element when rendering. Used for tight lists - * to hide paragraphs. - **/ - this.hidden = false; -} -/** -* Token.attrIndex(name) -> Number -* -* Search attribute index by name. -**/ -Token.prototype.attrIndex = function attrIndex(name) { - if (!this.attrs) { - return -1; - } - const attrs = this.attrs; - for (let i$10 = 0, len = attrs.length; i$10 < len; i$10++) { - if (attrs[i$10][0] === name) { - return i$10; - } - } - return -1; -}; -/** -* Token.attrPush(attrData) -* -* Add `[ name, value ]` attribute to list. Init attrs if necessary -**/ -Token.prototype.attrPush = function attrPush(attrData) { - if (this.attrs) { - this.attrs.push(attrData); - } else { - this.attrs = [attrData]; - } -}; -/** -* Token.attrSet(name, value) -* -* Set `name` attribute to `value`. Override old value if exists. -**/ -Token.prototype.attrSet = function attrSet(name, value) { - const idx = this.attrIndex(name); - const attrData = [name, value]; - if (idx < 0) { - this.attrPush(attrData); - } else { - this.attrs[idx] = attrData; - } -}; -/** -* Token.attrGet(name) -* -* Get the value of attribute `name`, or null if it does not exist. -**/ -Token.prototype.attrGet = function attrGet(name) { - const idx = this.attrIndex(name); - let value = null; - if (idx >= 0) { - value = this.attrs[idx][1]; - } - return value; -}; -/** -* Token.attrJoin(name, value) -* -* Join value to existing attribute via space. Or create new attribute if not -* exists. Useful to operate with token classes. -**/ -Token.prototype.attrJoin = function attrJoin(name, value) { - const idx = this.attrIndex(name); - if (idx < 0) { - this.attrPush([name, value]); - } else { - this.attrs[idx][1] = this.attrs[idx][1] + " " + value; - } -}; -var token_default = Token; - -function StateCore(src, md, env) { - this.src = src; - this.env = env; - this.tokens = []; - this.inlineMode = false; - this.md = md; -} -StateCore.prototype.Token = token_default; -var state_core_default = StateCore; - -const NEWLINES_RE = /\r\n?|\n/g; -const NULL_RE = /\0/g; -function normalize(state) { - let str; - str = state.src.replace(NEWLINES_RE, "\n"); - str = str.replace(NULL_RE, "�"); - state.src = str; -} - -function block(state) { - let token; - if (state.inlineMode) { - token = new state.Token("inline", "", 0); - token.content = state.src; - token.map = [0, 1]; - token.children = []; - state.tokens.push(token); - } else { - state.md.block.parse(state.src, state.md, state.env, state.tokens); - } -} - -function inline(state) { - const tokens = state.tokens; - for (let i$10 = 0, l$5 = tokens.length; i$10 < l$5; i$10++) { - const tok = tokens[i$10]; - if (tok.type === "inline") { - state.md.inline.parse(tok.content, state.md, state.env, tok.children); - } - } -} - -function isLinkOpen$1(str) { - return /^\s]/i.test(str); -} -function isLinkClose$1(str) { - return /^<\/a\s*>/i.test(str); -} -function linkify$1(state) { - const blockTokens = state.tokens; - if (!state.md.options.linkify) { - return; - } - for (let j$2 = 0, l$5 = blockTokens.length; j$2 < l$5; j$2++) { - if (blockTokens[j$2].type !== "inline" || !state.md.linkify.pretest(blockTokens[j$2].content)) { - continue; - } - let tokens = blockTokens[j$2].children; - let htmlLinkLevel = 0; - for (let i$10 = tokens.length - 1; i$10 >= 0; i$10--) { - const currentToken = tokens[i$10]; - if (currentToken.type === "link_close") { - i$10--; - while (tokens[i$10].level !== currentToken.level && tokens[i$10].type !== "link_open") { - i$10--; - } - continue; - } - if (currentToken.type === "html_inline") { - if (isLinkOpen$1(currentToken.content) && htmlLinkLevel > 0) { - htmlLinkLevel--; - } - if (isLinkClose$1(currentToken.content)) { - htmlLinkLevel++; - } - } - if (htmlLinkLevel > 0) { - continue; - } - if (currentToken.type === "text" && state.md.linkify.test(currentToken.content)) { - const text$1 = currentToken.content; - let links = state.md.linkify.match(text$1); - const nodes = []; - let level = currentToken.level; - let lastPos = 0; - if (links.length > 0 && links[0].index === 0 && i$10 > 0 && tokens[i$10 - 1].type === "text_special") { - links = links.slice(1); - } - for (let ln = 0; ln < links.length; ln++) { - const url = links[ln].url; - const fullUrl = state.md.normalizeLink(url); - if (!state.md.validateLink(fullUrl)) { - continue; - } - let urlText = links[ln].text; - if (!links[ln].schema) { - urlText = state.md.normalizeLinkText("http://" + urlText).replace(/^http:\/\//, ""); - } else if (links[ln].schema === "mailto:" && !/^mailto:/i.test(urlText)) { - urlText = state.md.normalizeLinkText("mailto:" + urlText).replace(/^mailto:/, ""); - } else { - urlText = state.md.normalizeLinkText(urlText); - } - const pos = links[ln].index; - if (pos > lastPos) { - const token = new state.Token("text", "", 0); - token.content = text$1.slice(lastPos, pos); - token.level = level; - nodes.push(token); - } - const token_o = new state.Token("link_open", "a", 1); - token_o.attrs = [["href", fullUrl]]; - token_o.level = level++; - token_o.markup = "linkify"; - token_o.info = "auto"; - nodes.push(token_o); - const token_t = new state.Token("text", "", 0); - token_t.content = urlText; - token_t.level = level; - nodes.push(token_t); - const token_c = new state.Token("link_close", "a", -1); - token_c.level = --level; - token_c.markup = "linkify"; - token_c.info = "auto"; - nodes.push(token_c); - lastPos = links[ln].lastIndex; - } - if (lastPos < text$1.length) { - const token = new state.Token("text", "", 0); - token.content = text$1.slice(lastPos); - token.level = level; - nodes.push(token); - } - blockTokens[j$2].children = tokens = arrayReplaceAt(tokens, i$10, nodes); - } - } - } -} - -const RARE_RE = /\+-|\.\.|\?\?\?\?|!!!!|,,|--/; -const SCOPED_ABBR_TEST_RE = /\((c|tm|r)\)/i; -const SCOPED_ABBR_RE = /\((c|tm|r)\)/gi; -const SCOPED_ABBR = { - c: "©", - r: "®", - tm: "™" -}; -function replaceFn(match, name) { - return SCOPED_ABBR[name.toLowerCase()]; -} -function replace_scoped(inlineTokens) { - let inside_autolink = 0; - for (let i$10 = inlineTokens.length - 1; i$10 >= 0; i$10--) { - const token = inlineTokens[i$10]; - if (token.type === "text" && !inside_autolink) { - token.content = token.content.replace(SCOPED_ABBR_RE, replaceFn); - } - if (token.type === "link_open" && token.info === "auto") { - inside_autolink--; - } - if (token.type === "link_close" && token.info === "auto") { - inside_autolink++; - } - } -} -function replace_rare(inlineTokens) { - let inside_autolink = 0; - for (let i$10 = inlineTokens.length - 1; i$10 >= 0; i$10--) { - const token = inlineTokens[i$10]; - if (token.type === "text" && !inside_autolink) { - if (RARE_RE.test(token.content)) { - token.content = token.content.replace(/\+-/g, "±").replace(/\.{2,}/g, "…").replace(/([?!])…/g, "$1..").replace(/([?!]){4,}/g, "$1$1$1").replace(/,{2,}/g, ",").replace(/(^|[^-])---(?=[^-]|$)/gm, "$1—").replace(/(^|\s)--(?=\s|$)/gm, "$1–").replace(/(^|[^-\s])--(?=[^-\s]|$)/gm, "$1–"); - } - } - if (token.type === "link_open" && token.info === "auto") { - inside_autolink--; - } - if (token.type === "link_close" && token.info === "auto") { - inside_autolink++; - } - } -} -function replace(state) { - let blkIdx; - if (!state.md.options.typographer) { - return; - } - for (blkIdx = state.tokens.length - 1; blkIdx >= 0; blkIdx--) { - if (state.tokens[blkIdx].type !== "inline") { - continue; - } - if (SCOPED_ABBR_TEST_RE.test(state.tokens[blkIdx].content)) { - replace_scoped(state.tokens[blkIdx].children); - } - if (RARE_RE.test(state.tokens[blkIdx].content)) { - replace_rare(state.tokens[blkIdx].children); - } - } -} - -const QUOTE_TEST_RE = /['"]/; -const QUOTE_RE = /['"]/g; -const APOSTROPHE = "’"; -function replaceAt(str, index, ch) { - return str.slice(0, index) + ch + str.slice(index + 1); -} -function process_inlines(tokens, state) { - let j$2; - const stack = []; - for (let i$10 = 0; i$10 < tokens.length; i$10++) { - const token = tokens[i$10]; - const thisLevel = tokens[i$10].level; - for (j$2 = stack.length - 1; j$2 >= 0; j$2--) { - if (stack[j$2].level <= thisLevel) { - break; - } - } - stack.length = j$2 + 1; - if (token.type !== "text") { - continue; - } - let text$1 = token.content; - let pos = 0; - let max = text$1.length; - OUTER: while (pos < max) { - QUOTE_RE.lastIndex = pos; - const t$7 = QUOTE_RE.exec(text$1); - if (!t$7) { - break; - } - let canOpen = true; - let canClose = true; - pos = t$7.index + 1; - const isSingle = t$7[0] === "'"; - let lastChar = 32; - if (t$7.index - 1 >= 0) { - lastChar = text$1.charCodeAt(t$7.index - 1); - } else { - for (j$2 = i$10 - 1; j$2 >= 0; j$2--) { - if (tokens[j$2].type === "softbreak" || tokens[j$2].type === "hardbreak") break; - if (!tokens[j$2].content) continue; - lastChar = tokens[j$2].content.charCodeAt(tokens[j$2].content.length - 1); - break; - } - } - let nextChar = 32; - if (pos < max) { - nextChar = text$1.charCodeAt(pos); - } else { - for (j$2 = i$10 + 1; j$2 < tokens.length; j$2++) { - if (tokens[j$2].type === "softbreak" || tokens[j$2].type === "hardbreak") break; - if (!tokens[j$2].content) continue; - nextChar = tokens[j$2].content.charCodeAt(0); - break; - } - } - const isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctChar(String.fromCharCode(lastChar)); - const isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctChar(String.fromCharCode(nextChar)); - const isLastWhiteSpace = isWhiteSpace(lastChar); - const isNextWhiteSpace = isWhiteSpace(nextChar); - if (isNextWhiteSpace) { - canOpen = false; - } else if (isNextPunctChar) { - if (!(isLastWhiteSpace || isLastPunctChar)) { - canOpen = false; - } - } - if (isLastWhiteSpace) { - canClose = false; - } else if (isLastPunctChar) { - if (!(isNextWhiteSpace || isNextPunctChar)) { - canClose = false; - } - } - if (nextChar === 34 && t$7[0] === "\"") { - if (lastChar >= 48 && lastChar <= 57) { - canClose = canOpen = false; - } - } - if (canOpen && canClose) { - canOpen = isLastPunctChar; - canClose = isNextPunctChar; - } - if (!canOpen && !canClose) { - if (isSingle) { - token.content = replaceAt(token.content, t$7.index, APOSTROPHE); - } - continue; - } - if (canClose) { - for (j$2 = stack.length - 1; j$2 >= 0; j$2--) { - let item = stack[j$2]; - if (stack[j$2].level < thisLevel) { - break; - } - if (item.single === isSingle && stack[j$2].level === thisLevel) { - item = stack[j$2]; - let openQuote; - let closeQuote; - if (isSingle) { - openQuote = state.md.options.quotes[2]; - closeQuote = state.md.options.quotes[3]; - } else { - openQuote = state.md.options.quotes[0]; - closeQuote = state.md.options.quotes[1]; - } - token.content = replaceAt(token.content, t$7.index, closeQuote); - tokens[item.token].content = replaceAt(tokens[item.token].content, item.pos, openQuote); - pos += closeQuote.length - 1; - if (item.token === i$10) { - pos += openQuote.length - 1; - } - text$1 = token.content; - max = text$1.length; - stack.length = j$2; - continue OUTER; - } - } - } - if (canOpen) { - stack.push({ - token: i$10, - pos: t$7.index, - single: isSingle, - level: thisLevel - }); - } else if (canClose && isSingle) { - token.content = replaceAt(token.content, t$7.index, APOSTROPHE); - } - } - } -} -function smartquotes(state) { - if (!state.md.options.typographer) { - return; - } - for (let blkIdx = state.tokens.length - 1; blkIdx >= 0; blkIdx--) { - if (state.tokens[blkIdx].type !== "inline" || !QUOTE_TEST_RE.test(state.tokens[blkIdx].content)) { - continue; - } - process_inlines(state.tokens[blkIdx].children, state); - } -} - -function text_join(state) { - let curr, last; - const blockTokens = state.tokens; - const l$5 = blockTokens.length; - for (let j$2 = 0; j$2 < l$5; j$2++) { - if (blockTokens[j$2].type !== "inline") continue; - const tokens = blockTokens[j$2].children; - const max = tokens.length; - for (curr = 0; curr < max; curr++) { - if (tokens[curr].type === "text_special") { - tokens[curr].type = "text"; - } - } - for (curr = last = 0; curr < max; curr++) { - if (tokens[curr].type === "text" && curr + 1 < max && tokens[curr + 1].type === "text") { - tokens[curr + 1].content = tokens[curr].content + tokens[curr + 1].content; - } else { - if (curr !== last) { - tokens[last] = tokens[curr]; - } - last++; - } - } - if (curr !== last) { - tokens.length = last; - } - } -} - -/** internal -* class Core -* -* Top-level rules executor. Glues block/inline parsers and does intermediate -* transformations. -**/ -const _rules$2 = [ - ["normalize", normalize], - ["block", block], - ["inline", inline], - ["linkify", linkify$1], - ["replacements", replace], - ["smartquotes", smartquotes], - ["text_join", text_join] -]; -/** -* new Core() -**/ -function Core() { - /** - * Core#ruler -> Ruler - * - * [[Ruler]] instance. Keep configuration of core rules. - **/ - this.ruler = new ruler_default(); - for (let i$10 = 0; i$10 < _rules$2.length; i$10++) { - this.ruler.push(_rules$2[i$10][0], _rules$2[i$10][1]); - } -} -/** -* Core.process(state) -* -* Executes core chain rules. -**/ -Core.prototype.process = function(state) { - const rules = this.ruler.getRules(""); - for (let i$10 = 0, l$5 = rules.length; i$10 < l$5; i$10++) { - rules[i$10](state); - } -}; -Core.prototype.State = state_core_default; -var parser_core_default = Core; - -function StateBlock(src, md, env, tokens) { - this.src = src; - this.md = md; - this.env = env; - this.tokens = tokens; - this.bMarks = []; - this.eMarks = []; - this.tShift = []; - this.sCount = []; - this.bsCount = []; - this.blkIndent = 0; - this.line = 0; - this.lineMax = 0; - this.tight = false; - this.ddIndent = -1; - this.listIndent = -1; - this.parentType = "root"; - this.level = 0; - const s$9 = this.src; - for (let start = 0, pos = 0, indent = 0, offset = 0, len = s$9.length, indent_found = false; pos < len; pos++) { - const ch = s$9.charCodeAt(pos); - if (!indent_found) { - if (isSpace(ch)) { - indent++; - if (ch === 9) { - offset += 4 - offset % 4; - } else { - offset++; - } - continue; - } else { - indent_found = true; - } - } - if (ch === 10 || pos === len - 1) { - if (ch !== 10) { - pos++; - } - this.bMarks.push(start); - this.eMarks.push(pos); - this.tShift.push(indent); - this.sCount.push(offset); - this.bsCount.push(0); - indent_found = false; - indent = 0; - offset = 0; - start = pos + 1; - } - } - this.bMarks.push(s$9.length); - this.eMarks.push(s$9.length); - this.tShift.push(0); - this.sCount.push(0); - this.bsCount.push(0); - this.lineMax = this.bMarks.length - 1; -} -StateBlock.prototype.push = function(type$2, tag, nesting) { - const token = new token_default(type$2, tag, nesting); - token.block = true; - if (nesting < 0) this.level--; - token.level = this.level; - if (nesting > 0) this.level++; - this.tokens.push(token); - return token; -}; -StateBlock.prototype.isEmpty = function isEmpty(line) { - return this.bMarks[line] + this.tShift[line] >= this.eMarks[line]; -}; -StateBlock.prototype.skipEmptyLines = function skipEmptyLines(from) { - for (let max = this.lineMax; from < max; from++) { - if (this.bMarks[from] + this.tShift[from] < this.eMarks[from]) { - break; - } - } - return from; -}; -StateBlock.prototype.skipSpaces = function skipSpaces(pos) { - for (let max = this.src.length; pos < max; pos++) { - const ch = this.src.charCodeAt(pos); - if (!isSpace(ch)) { - break; - } - } - return pos; -}; -StateBlock.prototype.skipSpacesBack = function skipSpacesBack(pos, min) { - if (pos <= min) { - return pos; - } - while (pos > min) { - if (!isSpace(this.src.charCodeAt(--pos))) { - return pos + 1; - } - } - return pos; -}; -StateBlock.prototype.skipChars = function skipChars(pos, code$1) { - for (let max = this.src.length; pos < max; pos++) { - if (this.src.charCodeAt(pos) !== code$1) { - break; - } - } - return pos; -}; -StateBlock.prototype.skipCharsBack = function skipCharsBack(pos, code$1, min) { - if (pos <= min) { - return pos; - } - while (pos > min) { - if (code$1 !== this.src.charCodeAt(--pos)) { - return pos + 1; - } - } - return pos; -}; -StateBlock.prototype.getLines = function getLines(begin, end, indent, keepLastLF) { - if (begin >= end) { - return ""; - } - const queue = new Array(end - begin); - for (let i$10 = 0, line = begin; line < end; line++, i$10++) { - let lineIndent = 0; - const lineStart = this.bMarks[line]; - let first = lineStart; - let last; - if (line + 1 < end || keepLastLF) { - last = this.eMarks[line] + 1; - } else { - last = this.eMarks[line]; - } - while (first < last && lineIndent < indent) { - const ch = this.src.charCodeAt(first); - if (isSpace(ch)) { - if (ch === 9) { - lineIndent += 4 - (lineIndent + this.bsCount[line]) % 4; - } else { - lineIndent++; - } - } else if (first - lineStart < this.tShift[line]) { - lineIndent++; - } else { - break; - } - first++; - } - if (lineIndent > indent) { - queue[i$10] = new Array(lineIndent - indent + 1).join(" ") + this.src.slice(first, last); - } else { - queue[i$10] = this.src.slice(first, last); - } - } - return queue.join(""); -}; -StateBlock.prototype.Token = token_default; -var state_block_default = StateBlock; - -const MAX_AUTOCOMPLETED_CELLS = 65536; -function getLine(state, line) { - const pos = state.bMarks[line] + state.tShift[line]; - const max = state.eMarks[line]; - return state.src.slice(pos, max); -} -function escapedSplit(str) { - const result = []; - const max = str.length; - let pos = 0; - let ch = str.charCodeAt(pos); - let isEscaped = false; - let lastPos = 0; - let current = ""; - while (pos < max) { - if (ch === 124) { - if (!isEscaped) { - result.push(current + str.substring(lastPos, pos)); - current = ""; - lastPos = pos + 1; - } else { - current += str.substring(lastPos, pos - 1); - lastPos = pos; - } - } - isEscaped = ch === 92; - pos++; - ch = str.charCodeAt(pos); - } - result.push(current + str.substring(lastPos)); - return result; -} -function table(state, startLine, endLine, silent) { - if (startLine + 2 > endLine) { - return false; - } - let nextLine = startLine + 1; - if (state.sCount[nextLine] < state.blkIndent) { - return false; - } - if (state.sCount[nextLine] - state.blkIndent >= 4) { - return false; - } - let pos = state.bMarks[nextLine] + state.tShift[nextLine]; - if (pos >= state.eMarks[nextLine]) { - return false; - } - const firstCh = state.src.charCodeAt(pos++); - if (firstCh !== 124 && firstCh !== 45 && firstCh !== 58) { - return false; - } - if (pos >= state.eMarks[nextLine]) { - return false; - } - const secondCh = state.src.charCodeAt(pos++); - if (secondCh !== 124 && secondCh !== 45 && secondCh !== 58 && !isSpace(secondCh)) { - return false; - } - if (firstCh === 45 && isSpace(secondCh)) { - return false; - } - while (pos < state.eMarks[nextLine]) { - const ch = state.src.charCodeAt(pos); - if (ch !== 124 && ch !== 45 && ch !== 58 && !isSpace(ch)) { - return false; - } - pos++; - } - let lineText = getLine(state, startLine + 1); - let columns = lineText.split("|"); - const aligns = []; - for (let i$10 = 0; i$10 < columns.length; i$10++) { - const t$7 = columns[i$10].trim(); - if (!t$7) { - if (i$10 === 0 || i$10 === columns.length - 1) { - continue; - } else { - return false; - } - } - if (!/^:?-+:?$/.test(t$7)) { - return false; - } - if (t$7.charCodeAt(t$7.length - 1) === 58) { - aligns.push(t$7.charCodeAt(0) === 58 ? "center" : "right"); - } else if (t$7.charCodeAt(0) === 58) { - aligns.push("left"); - } else { - aligns.push(""); - } - } - lineText = getLine(state, startLine).trim(); - if (lineText.indexOf("|") === -1) { - return false; - } - if (state.sCount[startLine] - state.blkIndent >= 4) { - return false; - } - columns = escapedSplit(lineText); - if (columns.length && columns[0] === "") columns.shift(); - if (columns.length && columns[columns.length - 1] === "") columns.pop(); - const columnCount = columns.length; - if (columnCount === 0 || columnCount !== aligns.length) { - return false; - } - if (silent) { - return true; - } - const oldParentType = state.parentType; - state.parentType = "table"; - const terminatorRules = state.md.block.ruler.getRules("blockquote"); - const token_to = state.push("table_open", "table", 1); - const tableLines = [startLine, 0]; - token_to.map = tableLines; - const token_tho = state.push("thead_open", "thead", 1); - token_tho.map = [startLine, startLine + 1]; - const token_htro = state.push("tr_open", "tr", 1); - token_htro.map = [startLine, startLine + 1]; - for (let i$10 = 0; i$10 < columns.length; i$10++) { - const token_ho = state.push("th_open", "th", 1); - if (aligns[i$10]) { - token_ho.attrs = [["style", "text-align:" + aligns[i$10]]]; - } - const token_il = state.push("inline", "", 0); - token_il.content = columns[i$10].trim(); - token_il.children = []; - state.push("th_close", "th", -1); - } - state.push("tr_close", "tr", -1); - state.push("thead_close", "thead", -1); - let tbodyLines; - let autocompletedCells = 0; - for (nextLine = startLine + 2; nextLine < endLine; nextLine++) { - if (state.sCount[nextLine] < state.blkIndent) { - break; - } - let terminate = false; - for (let i$10 = 0, l$5 = terminatorRules.length; i$10 < l$5; i$10++) { - if (terminatorRules[i$10](state, nextLine, endLine, true)) { - terminate = true; - break; - } - } - if (terminate) { - break; - } - lineText = getLine(state, nextLine).trim(); - if (!lineText) { - break; - } - if (state.sCount[nextLine] - state.blkIndent >= 4) { - break; - } - columns = escapedSplit(lineText); - if (columns.length && columns[0] === "") columns.shift(); - if (columns.length && columns[columns.length - 1] === "") columns.pop(); - autocompletedCells += columnCount - columns.length; - if (autocompletedCells > MAX_AUTOCOMPLETED_CELLS) { - break; - } - if (nextLine === startLine + 2) { - const token_tbo = state.push("tbody_open", "tbody", 1); - token_tbo.map = tbodyLines = [startLine + 2, 0]; - } - const token_tro = state.push("tr_open", "tr", 1); - token_tro.map = [nextLine, nextLine + 1]; - for (let i$10 = 0; i$10 < columnCount; i$10++) { - const token_tdo = state.push("td_open", "td", 1); - if (aligns[i$10]) { - token_tdo.attrs = [["style", "text-align:" + aligns[i$10]]]; - } - const token_il = state.push("inline", "", 0); - token_il.content = columns[i$10] ? columns[i$10].trim() : ""; - token_il.children = []; - state.push("td_close", "td", -1); - } - state.push("tr_close", "tr", -1); - } - if (tbodyLines) { - state.push("tbody_close", "tbody", -1); - tbodyLines[1] = nextLine; - } - state.push("table_close", "table", -1); - tableLines[1] = nextLine; - state.parentType = oldParentType; - state.line = nextLine; - return true; -} - -function code(state, startLine, endLine) { - if (state.sCount[startLine] - state.blkIndent < 4) { - return false; - } - let nextLine = startLine + 1; - let last = nextLine; - while (nextLine < endLine) { - if (state.isEmpty(nextLine)) { - nextLine++; - continue; - } - if (state.sCount[nextLine] - state.blkIndent >= 4) { - nextLine++; - last = nextLine; - continue; - } - break; - } - state.line = last; - const token = state.push("code_block", "code", 0); - token.content = state.getLines(startLine, last, 4 + state.blkIndent, false) + "\n"; - token.map = [startLine, state.line]; - return true; -} - -function fence(state, startLine, endLine, silent) { - let pos = state.bMarks[startLine] + state.tShift[startLine]; - let max = state.eMarks[startLine]; - if (state.sCount[startLine] - state.blkIndent >= 4) { - return false; - } - if (pos + 3 > max) { - return false; - } - const marker = state.src.charCodeAt(pos); - if (marker !== 126 && marker !== 96) { - return false; - } - let mem = pos; - pos = state.skipChars(pos, marker); - let len = pos - mem; - if (len < 3) { - return false; - } - const markup = state.src.slice(mem, pos); - const params = state.src.slice(pos, max); - if (marker === 96) { - if (params.indexOf(String.fromCharCode(marker)) >= 0) { - return false; - } - } - if (silent) { - return true; - } - let nextLine = startLine; - let haveEndMarker = false; - for (;;) { - nextLine++; - if (nextLine >= endLine) { - break; - } - pos = mem = state.bMarks[nextLine] + state.tShift[nextLine]; - max = state.eMarks[nextLine]; - if (pos < max && state.sCount[nextLine] < state.blkIndent) { - break; - } - if (state.src.charCodeAt(pos) !== marker) { - continue; - } - if (state.sCount[nextLine] - state.blkIndent >= 4) { - continue; - } - pos = state.skipChars(pos, marker); - if (pos - mem < len) { - continue; - } - pos = state.skipSpaces(pos); - if (pos < max) { - continue; - } - haveEndMarker = true; - break; - } - len = state.sCount[startLine]; - state.line = nextLine + (haveEndMarker ? 1 : 0); - const token = state.push("fence", "code", 0); - token.info = params; - token.content = state.getLines(startLine + 1, nextLine, len, true); - token.markup = markup; - token.map = [startLine, state.line]; - return true; -} - -function blockquote(state, startLine, endLine, silent) { - let pos = state.bMarks[startLine] + state.tShift[startLine]; - let max = state.eMarks[startLine]; - const oldLineMax = state.lineMax; - if (state.sCount[startLine] - state.blkIndent >= 4) { - return false; - } - if (state.src.charCodeAt(pos) !== 62) { - return false; - } - if (silent) { - return true; - } - const oldBMarks = []; - const oldBSCount = []; - const oldSCount = []; - const oldTShift = []; - const terminatorRules = state.md.block.ruler.getRules("blockquote"); - const oldParentType = state.parentType; - state.parentType = "blockquote"; - let lastLineEmpty = false; - let nextLine; - for (nextLine = startLine; nextLine < endLine; nextLine++) { - const isOutdented = state.sCount[nextLine] < state.blkIndent; - pos = state.bMarks[nextLine] + state.tShift[nextLine]; - max = state.eMarks[nextLine]; - if (pos >= max) { - break; - } - if (state.src.charCodeAt(pos++) === 62 && !isOutdented) { - let initial = state.sCount[nextLine] + 1; - let spaceAfterMarker; - let adjustTab; - if (state.src.charCodeAt(pos) === 32) { - pos++; - initial++; - adjustTab = false; - spaceAfterMarker = true; - } else if (state.src.charCodeAt(pos) === 9) { - spaceAfterMarker = true; - if ((state.bsCount[nextLine] + initial) % 4 === 3) { - pos++; - initial++; - adjustTab = false; - } else { - adjustTab = true; - } - } else { - spaceAfterMarker = false; - } - let offset = initial; - oldBMarks.push(state.bMarks[nextLine]); - state.bMarks[nextLine] = pos; - while (pos < max) { - const ch = state.src.charCodeAt(pos); - if (isSpace(ch)) { - if (ch === 9) { - offset += 4 - (offset + state.bsCount[nextLine] + (adjustTab ? 1 : 0)) % 4; - } else { - offset++; - } - } else { - break; - } - pos++; - } - lastLineEmpty = pos >= max; - oldBSCount.push(state.bsCount[nextLine]); - state.bsCount[nextLine] = state.sCount[nextLine] + 1 + (spaceAfterMarker ? 1 : 0); - oldSCount.push(state.sCount[nextLine]); - state.sCount[nextLine] = offset - initial; - oldTShift.push(state.tShift[nextLine]); - state.tShift[nextLine] = pos - state.bMarks[nextLine]; - continue; - } - if (lastLineEmpty) { - break; - } - let terminate = false; - for (let i$10 = 0, l$5 = terminatorRules.length; i$10 < l$5; i$10++) { - if (terminatorRules[i$10](state, nextLine, endLine, true)) { - terminate = true; - break; - } - } - if (terminate) { - state.lineMax = nextLine; - if (state.blkIndent !== 0) { - oldBMarks.push(state.bMarks[nextLine]); - oldBSCount.push(state.bsCount[nextLine]); - oldTShift.push(state.tShift[nextLine]); - oldSCount.push(state.sCount[nextLine]); - state.sCount[nextLine] -= state.blkIndent; - } - break; - } - oldBMarks.push(state.bMarks[nextLine]); - oldBSCount.push(state.bsCount[nextLine]); - oldTShift.push(state.tShift[nextLine]); - oldSCount.push(state.sCount[nextLine]); - state.sCount[nextLine] = -1; - } - const oldIndent = state.blkIndent; - state.blkIndent = 0; - const token_o = state.push("blockquote_open", "blockquote", 1); - token_o.markup = ">"; - const lines = [startLine, 0]; - token_o.map = lines; - state.md.block.tokenize(state, startLine, nextLine); - const token_c = state.push("blockquote_close", "blockquote", -1); - token_c.markup = ">"; - state.lineMax = oldLineMax; - state.parentType = oldParentType; - lines[1] = state.line; - for (let i$10 = 0; i$10 < oldTShift.length; i$10++) { - state.bMarks[i$10 + startLine] = oldBMarks[i$10]; - state.tShift[i$10 + startLine] = oldTShift[i$10]; - state.sCount[i$10 + startLine] = oldSCount[i$10]; - state.bsCount[i$10 + startLine] = oldBSCount[i$10]; - } - state.blkIndent = oldIndent; - return true; -} - -function hr(state, startLine, endLine, silent) { - const max = state.eMarks[startLine]; - if (state.sCount[startLine] - state.blkIndent >= 4) { - return false; - } - let pos = state.bMarks[startLine] + state.tShift[startLine]; - const marker = state.src.charCodeAt(pos++); - if (marker !== 42 && marker !== 45 && marker !== 95) { - return false; - } - let cnt = 1; - while (pos < max) { - const ch = state.src.charCodeAt(pos++); - if (ch !== marker && !isSpace(ch)) { - return false; - } - if (ch === marker) { - cnt++; - } - } - if (cnt < 3) { - return false; - } - if (silent) { - return true; - } - state.line = startLine + 1; - const token = state.push("hr", "hr", 0); - token.map = [startLine, state.line]; - token.markup = Array(cnt + 1).join(String.fromCharCode(marker)); - return true; -} - -function skipBulletListMarker(state, startLine) { - const max = state.eMarks[startLine]; - let pos = state.bMarks[startLine] + state.tShift[startLine]; - const marker = state.src.charCodeAt(pos++); - if (marker !== 42 && marker !== 45 && marker !== 43) { - return -1; - } - if (pos < max) { - const ch = state.src.charCodeAt(pos); - if (!isSpace(ch)) { - return -1; - } - } - return pos; -} -function skipOrderedListMarker(state, startLine) { - const start = state.bMarks[startLine] + state.tShift[startLine]; - const max = state.eMarks[startLine]; - let pos = start; - if (pos + 1 >= max) { - return -1; - } - let ch = state.src.charCodeAt(pos++); - if (ch < 48 || ch > 57) { - return -1; - } - for (;;) { - if (pos >= max) { - return -1; - } - ch = state.src.charCodeAt(pos++); - if (ch >= 48 && ch <= 57) { - if (pos - start >= 10) { - return -1; - } - continue; - } - if (ch === 41 || ch === 46) { - break; - } - return -1; - } - if (pos < max) { - ch = state.src.charCodeAt(pos); - if (!isSpace(ch)) { - return -1; - } - } - return pos; -} -function markTightParagraphs(state, idx) { - const level = state.level + 2; - for (let i$10 = idx + 2, l$5 = state.tokens.length - 2; i$10 < l$5; i$10++) { - if (state.tokens[i$10].level === level && state.tokens[i$10].type === "paragraph_open") { - state.tokens[i$10 + 2].hidden = true; - state.tokens[i$10].hidden = true; - i$10 += 2; - } - } -} -function list(state, startLine, endLine, silent) { - let max, pos, start, token; - let nextLine = startLine; - let tight = true; - if (state.sCount[nextLine] - state.blkIndent >= 4) { - return false; - } - if (state.listIndent >= 0 && state.sCount[nextLine] - state.listIndent >= 4 && state.sCount[nextLine] < state.blkIndent) { - return false; - } - let isTerminatingParagraph = false; - if (silent && state.parentType === "paragraph") { - if (state.sCount[nextLine] >= state.blkIndent) { - isTerminatingParagraph = true; - } - } - let isOrdered; - let markerValue; - let posAfterMarker; - if ((posAfterMarker = skipOrderedListMarker(state, nextLine)) >= 0) { - isOrdered = true; - start = state.bMarks[nextLine] + state.tShift[nextLine]; - markerValue = Number(state.src.slice(start, posAfterMarker - 1)); - if (isTerminatingParagraph && markerValue !== 1) return false; - } else if ((posAfterMarker = skipBulletListMarker(state, nextLine)) >= 0) { - isOrdered = false; - } else { - return false; - } - if (isTerminatingParagraph) { - if (state.skipSpaces(posAfterMarker) >= state.eMarks[nextLine]) return false; - } - if (silent) { - return true; - } - const markerCharCode = state.src.charCodeAt(posAfterMarker - 1); - const listTokIdx = state.tokens.length; - if (isOrdered) { - token = state.push("ordered_list_open", "ol", 1); - if (markerValue !== 1) { - token.attrs = [["start", markerValue]]; - } - } else { - token = state.push("bullet_list_open", "ul", 1); - } - const listLines = [nextLine, 0]; - token.map = listLines; - token.markup = String.fromCharCode(markerCharCode); - let prevEmptyEnd = false; - const terminatorRules = state.md.block.ruler.getRules("list"); - const oldParentType = state.parentType; - state.parentType = "list"; - while (nextLine < endLine) { - pos = posAfterMarker; - max = state.eMarks[nextLine]; - const initial = state.sCount[nextLine] + posAfterMarker - (state.bMarks[nextLine] + state.tShift[nextLine]); - let offset = initial; - while (pos < max) { - const ch = state.src.charCodeAt(pos); - if (ch === 9) { - offset += 4 - (offset + state.bsCount[nextLine]) % 4; - } else if (ch === 32) { - offset++; - } else { - break; - } - pos++; - } - const contentStart = pos; - let indentAfterMarker; - if (contentStart >= max) { - indentAfterMarker = 1; - } else { - indentAfterMarker = offset - initial; - } - if (indentAfterMarker > 4) { - indentAfterMarker = 1; - } - const indent = initial + indentAfterMarker; - token = state.push("list_item_open", "li", 1); - token.markup = String.fromCharCode(markerCharCode); - const itemLines = [nextLine, 0]; - token.map = itemLines; - if (isOrdered) { - token.info = state.src.slice(start, posAfterMarker - 1); - } - const oldTight = state.tight; - const oldTShift = state.tShift[nextLine]; - const oldSCount = state.sCount[nextLine]; - const oldListIndent = state.listIndent; - state.listIndent = state.blkIndent; - state.blkIndent = indent; - state.tight = true; - state.tShift[nextLine] = contentStart - state.bMarks[nextLine]; - state.sCount[nextLine] = offset; - if (contentStart >= max && state.isEmpty(nextLine + 1)) { - state.line = Math.min(state.line + 2, endLine); - } else { - state.md.block.tokenize(state, nextLine, endLine, true); - } - if (!state.tight || prevEmptyEnd) { - tight = false; - } - prevEmptyEnd = state.line - nextLine > 1 && state.isEmpty(state.line - 1); - state.blkIndent = state.listIndent; - state.listIndent = oldListIndent; - state.tShift[nextLine] = oldTShift; - state.sCount[nextLine] = oldSCount; - state.tight = oldTight; - token = state.push("list_item_close", "li", -1); - token.markup = String.fromCharCode(markerCharCode); - nextLine = state.line; - itemLines[1] = nextLine; - if (nextLine >= endLine) { - break; - } - if (state.sCount[nextLine] < state.blkIndent) { - break; - } - if (state.sCount[nextLine] - state.blkIndent >= 4) { - break; - } - let terminate = false; - for (let i$10 = 0, l$5 = terminatorRules.length; i$10 < l$5; i$10++) { - if (terminatorRules[i$10](state, nextLine, endLine, true)) { - terminate = true; - break; - } - } - if (terminate) { - break; - } - if (isOrdered) { - posAfterMarker = skipOrderedListMarker(state, nextLine); - if (posAfterMarker < 0) { - break; - } - start = state.bMarks[nextLine] + state.tShift[nextLine]; - } else { - posAfterMarker = skipBulletListMarker(state, nextLine); - if (posAfterMarker < 0) { - break; - } - } - if (markerCharCode !== state.src.charCodeAt(posAfterMarker - 1)) { - break; - } - } - if (isOrdered) { - token = state.push("ordered_list_close", "ol", -1); - } else { - token = state.push("bullet_list_close", "ul", -1); - } - token.markup = String.fromCharCode(markerCharCode); - listLines[1] = nextLine; - state.line = nextLine; - state.parentType = oldParentType; - if (tight) { - markTightParagraphs(state, listTokIdx); - } - return true; -} - -function reference(state, startLine, _endLine, silent) { - let pos = state.bMarks[startLine] + state.tShift[startLine]; - let max = state.eMarks[startLine]; - let nextLine = startLine + 1; - if (state.sCount[startLine] - state.blkIndent >= 4) { - return false; - } - if (state.src.charCodeAt(pos) !== 91) { - return false; - } - function getNextLine(nextLine$1) { - const endLine = state.lineMax; - if (nextLine$1 >= endLine || state.isEmpty(nextLine$1)) { - return null; - } - let isContinuation = false; - if (state.sCount[nextLine$1] - state.blkIndent > 3) { - isContinuation = true; - } - if (state.sCount[nextLine$1] < 0) { - isContinuation = true; - } - if (!isContinuation) { - const terminatorRules = state.md.block.ruler.getRules("reference"); - const oldParentType = state.parentType; - state.parentType = "reference"; - let terminate = false; - for (let i$10 = 0, l$5 = terminatorRules.length; i$10 < l$5; i$10++) { - if (terminatorRules[i$10](state, nextLine$1, endLine, true)) { - terminate = true; - break; - } - } - state.parentType = oldParentType; - if (terminate) { - return null; - } - } - const pos$1 = state.bMarks[nextLine$1] + state.tShift[nextLine$1]; - const max$1 = state.eMarks[nextLine$1]; - return state.src.slice(pos$1, max$1 + 1); - } - let str = state.src.slice(pos, max + 1); - max = str.length; - let labelEnd = -1; - for (pos = 1; pos < max; pos++) { - const ch = str.charCodeAt(pos); - if (ch === 91) { - return false; - } else if (ch === 93) { - labelEnd = pos; - break; - } else if (ch === 10) { - const lineContent = getNextLine(nextLine); - if (lineContent !== null) { - str += lineContent; - max = str.length; - nextLine++; - } - } else if (ch === 92) { - pos++; - if (pos < max && str.charCodeAt(pos) === 10) { - const lineContent = getNextLine(nextLine); - if (lineContent !== null) { - str += lineContent; - max = str.length; - nextLine++; - } - } - } - } - if (labelEnd < 0 || str.charCodeAt(labelEnd + 1) !== 58) { - return false; - } - for (pos = labelEnd + 2; pos < max; pos++) { - const ch = str.charCodeAt(pos); - if (ch === 10) { - const lineContent = getNextLine(nextLine); - if (lineContent !== null) { - str += lineContent; - max = str.length; - nextLine++; - } - } else if (isSpace(ch)) {} else { - break; - } - } - const destRes = state.md.helpers.parseLinkDestination(str, pos, max); - if (!destRes.ok) { - return false; - } - const href = state.md.normalizeLink(destRes.str); - if (!state.md.validateLink(href)) { - return false; - } - pos = destRes.pos; - const destEndPos = pos; - const destEndLineNo = nextLine; - const start = pos; - for (; pos < max; pos++) { - const ch = str.charCodeAt(pos); - if (ch === 10) { - const lineContent = getNextLine(nextLine); - if (lineContent !== null) { - str += lineContent; - max = str.length; - nextLine++; - } - } else if (isSpace(ch)) {} else { - break; - } - } - let titleRes = state.md.helpers.parseLinkTitle(str, pos, max); - while (titleRes.can_continue) { - const lineContent = getNextLine(nextLine); - if (lineContent === null) break; - str += lineContent; - pos = max; - max = str.length; - nextLine++; - titleRes = state.md.helpers.parseLinkTitle(str, pos, max, titleRes); - } - let title$1; - if (pos < max && start !== pos && titleRes.ok) { - title$1 = titleRes.str; - pos = titleRes.pos; - } else { - title$1 = ""; - pos = destEndPos; - nextLine = destEndLineNo; - } - while (pos < max) { - const ch = str.charCodeAt(pos); - if (!isSpace(ch)) { - break; - } - pos++; - } - if (pos < max && str.charCodeAt(pos) !== 10) { - if (title$1) { - title$1 = ""; - pos = destEndPos; - nextLine = destEndLineNo; - while (pos < max) { - const ch = str.charCodeAt(pos); - if (!isSpace(ch)) { - break; - } - pos++; - } - } - } - if (pos < max && str.charCodeAt(pos) !== 10) { - return false; - } - const label = normalizeReference(str.slice(1, labelEnd)); - if (!label) { - return false; - } - /* istanbul ignore if */ - if (silent) { - return true; - } - if (typeof state.env.references === "undefined") { - state.env.references = {}; - } - if (typeof state.env.references[label] === "undefined") { - state.env.references[label] = { - title: title$1, - href - }; - } - state.line = nextLine; - return true; -} - -var html_blocks_default = [ - "address", - "article", - "aside", - "base", - "basefont", - "blockquote", - "body", - "caption", - "center", - "col", - "colgroup", - "dd", - "details", - "dialog", - "dir", - "div", - "dl", - "dt", - "fieldset", - "figcaption", - "figure", - "footer", - "form", - "frame", - "frameset", - "h1", - "h2", - "h3", - "h4", - "h5", - "h6", - "head", - "header", - "hr", - "html", - "iframe", - "legend", - "li", - "link", - "main", - "menu", - "menuitem", - "nav", - "noframes", - "ol", - "optgroup", - "option", - "p", - "param", - "search", - "section", - "summary", - "table", - "tbody", - "td", - "tfoot", - "th", - "thead", - "title", - "tr", - "track", - "ul" -]; - -const attr_name = "[a-zA-Z_:][a-zA-Z0-9:._-]*"; -const unquoted = "[^\"'=<>`\\x00-\\x20]+"; -const single_quoted = "'[^']*'"; -const double_quoted = "\"[^\"]*\""; -const attr_value = "(?:" + unquoted + "|" + single_quoted + "|" + double_quoted + ")"; -const attribute = "(?:\\s+" + attr_name + "(?:\\s*=\\s*" + attr_value + ")?)"; -const open_tag = "<[A-Za-z][A-Za-z0-9\\-]*" + attribute + "*\\s*\\/?>"; -const close_tag = "<\\/[A-Za-z][A-Za-z0-9\\-]*\\s*>"; -const comment = ""; -const processing = "<[?][\\s\\S]*?[?]>"; -const declaration = "]*>"; -const cdata = ""; -const HTML_TAG_RE = new RegExp("^(?:" + open_tag + "|" + close_tag + "|" + comment + "|" + processing + "|" + declaration + "|" + cdata + ")"); -const HTML_OPEN_CLOSE_TAG_RE = new RegExp("^(?:" + open_tag + "|" + close_tag + ")"); - -const HTML_SEQUENCES = [ - [ - /^<(script|pre|style|textarea)(?=(\s|>|$))/i, - /<\/(script|pre|style|textarea)>/i, - true - ], - [ - /^/, - true - ], - [ - /^<\?/, - /\?>/, - true - ], - [ - /^/, - true - ], - [ - /^/, - true - ], - [ - new RegExp("^|$))", "i"), - /^$/, - true - ], - [ - new RegExp(HTML_OPEN_CLOSE_TAG_RE.source + "\\s*$"), - /^$/, - false - ] -]; -function html_block(state, startLine, endLine, silent) { - let pos = state.bMarks[startLine] + state.tShift[startLine]; - let max = state.eMarks[startLine]; - if (state.sCount[startLine] - state.blkIndent >= 4) { - return false; - } - if (!state.md.options.html) { - return false; - } - if (state.src.charCodeAt(pos) !== 60) { - return false; - } - let lineText = state.src.slice(pos, max); - let i$10 = 0; - for (; i$10 < HTML_SEQUENCES.length; i$10++) { - if (HTML_SEQUENCES[i$10][0].test(lineText)) { - break; - } - } - if (i$10 === HTML_SEQUENCES.length) { - return false; - } - if (silent) { - return HTML_SEQUENCES[i$10][2]; - } - let nextLine = startLine + 1; - if (!HTML_SEQUENCES[i$10][1].test(lineText)) { - for (; nextLine < endLine; nextLine++) { - if (state.sCount[nextLine] < state.blkIndent) { - break; - } - pos = state.bMarks[nextLine] + state.tShift[nextLine]; - max = state.eMarks[nextLine]; - lineText = state.src.slice(pos, max); - if (HTML_SEQUENCES[i$10][1].test(lineText)) { - if (lineText.length !== 0) { - nextLine++; - } - break; - } - } - } - state.line = nextLine; - const token = state.push("html_block", "", 0); - token.map = [startLine, nextLine]; - token.content = state.getLines(startLine, nextLine, state.blkIndent, true); - return true; -} - -function heading(state, startLine, endLine, silent) { - let pos = state.bMarks[startLine] + state.tShift[startLine]; - let max = state.eMarks[startLine]; - if (state.sCount[startLine] - state.blkIndent >= 4) { - return false; - } - let ch = state.src.charCodeAt(pos); - if (ch !== 35 || pos >= max) { - return false; - } - let level = 1; - ch = state.src.charCodeAt(++pos); - while (ch === 35 && pos < max && level <= 6) { - level++; - ch = state.src.charCodeAt(++pos); - } - if (level > 6 || pos < max && !isSpace(ch)) { - return false; - } - if (silent) { - return true; - } - max = state.skipSpacesBack(max, pos); - const tmp = state.skipCharsBack(max, 35, pos); - if (tmp > pos && isSpace(state.src.charCodeAt(tmp - 1))) { - max = tmp; - } - state.line = startLine + 1; - const token_o = state.push("heading_open", "h" + String(level), 1); - token_o.markup = "########".slice(0, level); - token_o.map = [startLine, state.line]; - const token_i = state.push("inline", "", 0); - token_i.content = state.src.slice(pos, max).trim(); - token_i.map = [startLine, state.line]; - token_i.children = []; - const token_c = state.push("heading_close", "h" + String(level), -1); - token_c.markup = "########".slice(0, level); - return true; -} - -function lheading(state, startLine, endLine) { - const terminatorRules = state.md.block.ruler.getRules("paragraph"); - if (state.sCount[startLine] - state.blkIndent >= 4) { - return false; - } - const oldParentType = state.parentType; - state.parentType = "paragraph"; - let level = 0; - let marker; - let nextLine = startLine + 1; - for (; nextLine < endLine && !state.isEmpty(nextLine); nextLine++) { - if (state.sCount[nextLine] - state.blkIndent > 3) { - continue; - } - if (state.sCount[nextLine] >= state.blkIndent) { - let pos = state.bMarks[nextLine] + state.tShift[nextLine]; - const max = state.eMarks[nextLine]; - if (pos < max) { - marker = state.src.charCodeAt(pos); - if (marker === 45 || marker === 61) { - pos = state.skipChars(pos, marker); - pos = state.skipSpaces(pos); - if (pos >= max) { - level = marker === 61 ? 1 : 2; - break; - } - } - } - } - if (state.sCount[nextLine] < 0) { - continue; - } - let terminate = false; - for (let i$10 = 0, l$5 = terminatorRules.length; i$10 < l$5; i$10++) { - if (terminatorRules[i$10](state, nextLine, endLine, true)) { - terminate = true; - break; - } - } - if (terminate) { - break; - } - } - if (!level) { - return false; - } - const content = state.getLines(startLine, nextLine, state.blkIndent, false).trim(); - state.line = nextLine + 1; - const token_o = state.push("heading_open", "h" + String(level), 1); - token_o.markup = String.fromCharCode(marker); - token_o.map = [startLine, state.line]; - const token_i = state.push("inline", "", 0); - token_i.content = content; - token_i.map = [startLine, state.line - 1]; - token_i.children = []; - const token_c = state.push("heading_close", "h" + String(level), -1); - token_c.markup = String.fromCharCode(marker); - state.parentType = oldParentType; - return true; -} - -function paragraph(state, startLine, endLine) { - const terminatorRules = state.md.block.ruler.getRules("paragraph"); - const oldParentType = state.parentType; - let nextLine = startLine + 1; - state.parentType = "paragraph"; - for (; nextLine < endLine && !state.isEmpty(nextLine); nextLine++) { - if (state.sCount[nextLine] - state.blkIndent > 3) { - continue; - } - if (state.sCount[nextLine] < 0) { - continue; - } - let terminate = false; - for (let i$10 = 0, l$5 = terminatorRules.length; i$10 < l$5; i$10++) { - if (terminatorRules[i$10](state, nextLine, endLine, true)) { - terminate = true; - break; - } - } - if (terminate) { - break; - } - } - const content = state.getLines(startLine, nextLine, state.blkIndent, false).trim(); - state.line = nextLine; - const token_o = state.push("paragraph_open", "p", 1); - token_o.map = [startLine, state.line]; - const token_i = state.push("inline", "", 0); - token_i.content = content; - token_i.map = [startLine, state.line]; - token_i.children = []; - state.push("paragraph_close", "p", -1); - state.parentType = oldParentType; - return true; -} - -/** internal -* class ParserBlock -* -* Block-level tokenizer. -**/ -const _rules$1 = [ - [ - "table", - table, - ["paragraph", "reference"] - ], - ["code", code], - [ - "fence", - fence, - [ - "paragraph", - "reference", - "blockquote", - "list" - ] - ], - [ - "blockquote", - blockquote, - [ - "paragraph", - "reference", - "blockquote", - "list" - ] - ], - [ - "hr", - hr, - [ - "paragraph", - "reference", - "blockquote", - "list" - ] - ], - [ - "list", - list, - [ - "paragraph", - "reference", - "blockquote" - ] - ], - ["reference", reference], - [ - "html_block", - html_block, - [ - "paragraph", - "reference", - "blockquote" - ] - ], - [ - "heading", - heading, - [ - "paragraph", - "reference", - "blockquote" - ] - ], - ["lheading", lheading], - ["paragraph", paragraph] -]; -/** -* new ParserBlock() -**/ -function ParserBlock() { - /** - * ParserBlock#ruler -> Ruler - * - * [[Ruler]] instance. Keep configuration of block rules. - **/ - this.ruler = new ruler_default(); - for (let i$10 = 0; i$10 < _rules$1.length; i$10++) { - this.ruler.push(_rules$1[i$10][0], _rules$1[i$10][1], { alt: (_rules$1[i$10][2] || []).slice() }); - } -} -ParserBlock.prototype.tokenize = function(state, startLine, endLine) { - const rules = this.ruler.getRules(""); - const len = rules.length; - const maxNesting = state.md.options.maxNesting; - let line = startLine; - let hasEmptyLines = false; - while (line < endLine) { - state.line = line = state.skipEmptyLines(line); - if (line >= endLine) { - break; - } - if (state.sCount[line] < state.blkIndent) { - break; - } - if (state.level >= maxNesting) { - state.line = endLine; - break; - } - const prevLine = state.line; - let ok = false; - for (let i$10 = 0; i$10 < len; i$10++) { - ok = rules[i$10](state, line, endLine, false); - if (ok) { - if (prevLine >= state.line) { - throw new Error("block rule didn't increment state.line"); - } - break; - } - } - if (!ok) throw new Error("none of the block rules matched"); - state.tight = !hasEmptyLines; - if (state.isEmpty(state.line - 1)) { - hasEmptyLines = true; - } - line = state.line; - if (line < endLine && state.isEmpty(line)) { - hasEmptyLines = true; - line++; - state.line = line; - } - } -}; -/** -* ParserBlock.parse(str, md, env, outTokens) -* -* Process input string and push block tokens into `outTokens` -**/ -ParserBlock.prototype.parse = function(src, md, env, outTokens) { - if (!src) { - return; - } - const state = new this.State(src, md, env, outTokens); - this.tokenize(state, state.line, state.lineMax); -}; -ParserBlock.prototype.State = state_block_default; -var parser_block_default = ParserBlock; - -function StateInline(src, md, env, outTokens) { - this.src = src; - this.env = env; - this.md = md; - this.tokens = outTokens; - this.tokens_meta = Array(outTokens.length); - this.pos = 0; - this.posMax = this.src.length; - this.level = 0; - this.pending = ""; - this.pendingLevel = 0; - this.cache = {}; - this.delimiters = []; - this._prev_delimiters = []; - this.backticks = {}; - this.backticksScanned = false; - this.linkLevel = 0; -} -StateInline.prototype.pushPending = function() { - const token = new token_default("text", "", 0); - token.content = this.pending; - token.level = this.pendingLevel; - this.tokens.push(token); - this.pending = ""; - return token; -}; -StateInline.prototype.push = function(type$2, tag, nesting) { - if (this.pending) { - this.pushPending(); - } - const token = new token_default(type$2, tag, nesting); - let token_meta = null; - if (nesting < 0) { - this.level--; - this.delimiters = this._prev_delimiters.pop(); - } - token.level = this.level; - if (nesting > 0) { - this.level++; - this._prev_delimiters.push(this.delimiters); - this.delimiters = []; - token_meta = { delimiters: this.delimiters }; - } - this.pendingLevel = this.level; - this.tokens.push(token); - this.tokens_meta.push(token_meta); - return token; -}; -StateInline.prototype.scanDelims = function(start, canSplitWord) { - const max = this.posMax; - const marker = this.src.charCodeAt(start); - const lastChar = start > 0 ? this.src.charCodeAt(start - 1) : 32; - let pos = start; - while (pos < max && this.src.charCodeAt(pos) === marker) { - pos++; - } - const count = pos - start; - const nextChar = pos < max ? this.src.charCodeAt(pos) : 32; - const isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctChar(String.fromCharCode(lastChar)); - const isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctChar(String.fromCharCode(nextChar)); - const isLastWhiteSpace = isWhiteSpace(lastChar); - const isNextWhiteSpace = isWhiteSpace(nextChar); - const left_flanking = !isNextWhiteSpace && (!isNextPunctChar || isLastWhiteSpace || isLastPunctChar); - const right_flanking = !isLastWhiteSpace && (!isLastPunctChar || isNextWhiteSpace || isNextPunctChar); - const can_open = left_flanking && (canSplitWord || !right_flanking || isLastPunctChar); - const can_close = right_flanking && (canSplitWord || !left_flanking || isNextPunctChar); - return { - can_open, - can_close, - length: count - }; -}; -StateInline.prototype.Token = token_default; -var state_inline_default = StateInline; - -function isTerminatorChar(ch) { - switch (ch) { - case 10: - case 33: - case 35: - case 36: - case 37: - case 38: - case 42: - case 43: - case 45: - case 58: - case 60: - case 61: - case 62: - case 64: - case 91: - case 92: - case 93: - case 94: - case 95: - case 96: - case 123: - case 125: - case 126: return true; - default: return false; - } -} -function text(state, silent) { - let pos = state.pos; - while (pos < state.posMax && !isTerminatorChar(state.src.charCodeAt(pos))) { - pos++; - } - if (pos === state.pos) { - return false; - } - if (!silent) { - state.pending += state.src.slice(state.pos, pos); - } - state.pos = pos; - return true; -} - -const SCHEME_RE = /(?:^|[^a-z0-9.+-])([a-z][a-z0-9.+-]*)$/i; -function linkify(state, silent) { - if (!state.md.options.linkify) return false; - if (state.linkLevel > 0) return false; - const pos = state.pos; - const max = state.posMax; - if (pos + 3 > max) return false; - if (state.src.charCodeAt(pos) !== 58) return false; - if (state.src.charCodeAt(pos + 1) !== 47) return false; - if (state.src.charCodeAt(pos + 2) !== 47) return false; - const match = state.pending.match(SCHEME_RE); - if (!match) return false; - const proto = match[1]; - const link$1 = state.md.linkify.matchAtStart(state.src.slice(pos - proto.length)); - if (!link$1) return false; - let url = link$1.url; - if (url.length <= proto.length) return false; - url = url.replace(/\*+$/, ""); - const fullUrl = state.md.normalizeLink(url); - if (!state.md.validateLink(fullUrl)) return false; - if (!silent) { - state.pending = state.pending.slice(0, -proto.length); - const token_o = state.push("link_open", "a", 1); - token_o.attrs = [["href", fullUrl]]; - token_o.markup = "linkify"; - token_o.info = "auto"; - const token_t = state.push("text", "", 0); - token_t.content = state.md.normalizeLinkText(url); - const token_c = state.push("link_close", "a", -1); - token_c.markup = "linkify"; - token_c.info = "auto"; - } - state.pos += url.length - proto.length; - return true; -} - -function newline(state, silent) { - let pos = state.pos; - if (state.src.charCodeAt(pos) !== 10) { - return false; - } - const pmax = state.pending.length - 1; - const max = state.posMax; - if (!silent) { - if (pmax >= 0 && state.pending.charCodeAt(pmax) === 32) { - if (pmax >= 1 && state.pending.charCodeAt(pmax - 1) === 32) { - let ws = pmax - 1; - while (ws >= 1 && state.pending.charCodeAt(ws - 1) === 32) ws--; - state.pending = state.pending.slice(0, ws); - state.push("hardbreak", "br", 0); - } else { - state.pending = state.pending.slice(0, -1); - state.push("softbreak", "br", 0); - } - } else { - state.push("softbreak", "br", 0); - } - } - pos++; - while (pos < max && isSpace(state.src.charCodeAt(pos))) { - pos++; - } - state.pos = pos; - return true; -} - -const ESCAPED = []; -for (let i$10 = 0; i$10 < 256; i$10++) { - ESCAPED.push(0); -} -"\\!\"#$%&'()*+,./:;<=>?@[]^_`{|}~-".split("").forEach(function(ch) { - ESCAPED[ch.charCodeAt(0)] = 1; -}); -function escape(state, silent) { - let pos = state.pos; - const max = state.posMax; - if (state.src.charCodeAt(pos) !== 92) return false; - pos++; - if (pos >= max) return false; - let ch1 = state.src.charCodeAt(pos); - if (ch1 === 10) { - if (!silent) { - state.push("hardbreak", "br", 0); - } - pos++; - while (pos < max) { - ch1 = state.src.charCodeAt(pos); - if (!isSpace(ch1)) break; - pos++; - } - state.pos = pos; - return true; - } - let escapedStr = state.src[pos]; - if (ch1 >= 55296 && ch1 <= 56319 && pos + 1 < max) { - const ch2 = state.src.charCodeAt(pos + 1); - if (ch2 >= 56320 && ch2 <= 57343) { - escapedStr += state.src[pos + 1]; - pos++; - } - } - const origStr = "\\" + escapedStr; - if (!silent) { - const token = state.push("text_special", "", 0); - if (ch1 < 256 && ESCAPED[ch1] !== 0) { - token.content = escapedStr; - } else { - token.content = origStr; - } - token.markup = origStr; - token.info = "escape"; - } - state.pos = pos + 1; - return true; -} - -function backtick(state, silent) { - let pos = state.pos; - const ch = state.src.charCodeAt(pos); - if (ch !== 96) { - return false; - } - const start = pos; - pos++; - const max = state.posMax; - while (pos < max && state.src.charCodeAt(pos) === 96) { - pos++; - } - const marker = state.src.slice(start, pos); - const openerLength = marker.length; - if (state.backticksScanned && (state.backticks[openerLength] || 0) <= start) { - if (!silent) state.pending += marker; - state.pos += openerLength; - return true; - } - let matchEnd = pos; - let matchStart; - while ((matchStart = state.src.indexOf("`", matchEnd)) !== -1) { - matchEnd = matchStart + 1; - while (matchEnd < max && state.src.charCodeAt(matchEnd) === 96) { - matchEnd++; - } - const closerLength = matchEnd - matchStart; - if (closerLength === openerLength) { - if (!silent) { - const token = state.push("code_inline", "code", 0); - token.markup = marker; - token.content = state.src.slice(pos, matchStart).replace(/\n/g, " ").replace(/^ (.+) $/, "$1"); - } - state.pos = matchEnd; - return true; - } - state.backticks[closerLength] = matchStart; - } - state.backticksScanned = true; - if (!silent) state.pending += marker; - state.pos += openerLength; - return true; -} - -function strikethrough_tokenize(state, silent) { - const start = state.pos; - const marker = state.src.charCodeAt(start); - if (silent) { - return false; - } - if (marker !== 126) { - return false; - } - const scanned = state.scanDelims(state.pos, true); - let len = scanned.length; - const ch = String.fromCharCode(marker); - if (len < 2) { - return false; - } - let token; - if (len % 2) { - token = state.push("text", "", 0); - token.content = ch; - len--; - } - for (let i$10 = 0; i$10 < len; i$10 += 2) { - token = state.push("text", "", 0); - token.content = ch + ch; - state.delimiters.push({ - marker, - length: 0, - token: state.tokens.length - 1, - end: -1, - open: scanned.can_open, - close: scanned.can_close - }); - } - state.pos += scanned.length; - return true; -} -function postProcess$1(state, delimiters) { - let token; - const loneMarkers = []; - const max = delimiters.length; - for (let i$10 = 0; i$10 < max; i$10++) { - const startDelim = delimiters[i$10]; - if (startDelim.marker !== 126) { - continue; - } - if (startDelim.end === -1) { - continue; - } - const endDelim = delimiters[startDelim.end]; - token = state.tokens[startDelim.token]; - token.type = "s_open"; - token.tag = "s"; - token.nesting = 1; - token.markup = "~~"; - token.content = ""; - token = state.tokens[endDelim.token]; - token.type = "s_close"; - token.tag = "s"; - token.nesting = -1; - token.markup = "~~"; - token.content = ""; - if (state.tokens[endDelim.token - 1].type === "text" && state.tokens[endDelim.token - 1].content === "~") { - loneMarkers.push(endDelim.token - 1); - } - } - while (loneMarkers.length) { - const i$10 = loneMarkers.pop(); - let j$2 = i$10 + 1; - while (j$2 < state.tokens.length && state.tokens[j$2].type === "s_close") { - j$2++; - } - j$2--; - if (i$10 !== j$2) { - token = state.tokens[j$2]; - state.tokens[j$2] = state.tokens[i$10]; - state.tokens[i$10] = token; - } - } -} -function strikethrough_postProcess(state) { - const tokens_meta = state.tokens_meta; - const max = state.tokens_meta.length; - postProcess$1(state, state.delimiters); - for (let curr = 0; curr < max; curr++) { - if (tokens_meta[curr] && tokens_meta[curr].delimiters) { - postProcess$1(state, tokens_meta[curr].delimiters); - } - } -} -var strikethrough_default = { - tokenize: strikethrough_tokenize, - postProcess: strikethrough_postProcess -}; - -function emphasis_tokenize(state, silent) { - const start = state.pos; - const marker = state.src.charCodeAt(start); - if (silent) { - return false; - } - if (marker !== 95 && marker !== 42) { - return false; - } - const scanned = state.scanDelims(state.pos, marker === 42); - for (let i$10 = 0; i$10 < scanned.length; i$10++) { - const token = state.push("text", "", 0); - token.content = String.fromCharCode(marker); - state.delimiters.push({ - marker, - length: scanned.length, - token: state.tokens.length - 1, - end: -1, - open: scanned.can_open, - close: scanned.can_close - }); - } - state.pos += scanned.length; - return true; -} -function postProcess(state, delimiters) { - const max = delimiters.length; - for (let i$10 = max - 1; i$10 >= 0; i$10--) { - const startDelim = delimiters[i$10]; - if (startDelim.marker !== 95 && startDelim.marker !== 42) { - continue; - } - if (startDelim.end === -1) { - continue; - } - const endDelim = delimiters[startDelim.end]; - const isStrong = i$10 > 0 && delimiters[i$10 - 1].end === startDelim.end + 1 && delimiters[i$10 - 1].marker === startDelim.marker && delimiters[i$10 - 1].token === startDelim.token - 1 && delimiters[startDelim.end + 1].token === endDelim.token + 1; - const ch = String.fromCharCode(startDelim.marker); - const token_o = state.tokens[startDelim.token]; - token_o.type = isStrong ? "strong_open" : "em_open"; - token_o.tag = isStrong ? "strong" : "em"; - token_o.nesting = 1; - token_o.markup = isStrong ? ch + ch : ch; - token_o.content = ""; - const token_c = state.tokens[endDelim.token]; - token_c.type = isStrong ? "strong_close" : "em_close"; - token_c.tag = isStrong ? "strong" : "em"; - token_c.nesting = -1; - token_c.markup = isStrong ? ch + ch : ch; - token_c.content = ""; - if (isStrong) { - state.tokens[delimiters[i$10 - 1].token].content = ""; - state.tokens[delimiters[startDelim.end + 1].token].content = ""; - i$10--; - } - } -} -function emphasis_post_process(state) { - const tokens_meta = state.tokens_meta; - const max = state.tokens_meta.length; - postProcess(state, state.delimiters); - for (let curr = 0; curr < max; curr++) { - if (tokens_meta[curr] && tokens_meta[curr].delimiters) { - postProcess(state, tokens_meta[curr].delimiters); - } - } -} -var emphasis_default = { - tokenize: emphasis_tokenize, - postProcess: emphasis_post_process -}; - -function link(state, silent) { - let code$1, label, res, ref; - let href = ""; - let title$1 = ""; - let start = state.pos; - let parseReference = true; - if (state.src.charCodeAt(state.pos) !== 91) { - return false; - } - const oldPos = state.pos; - const max = state.posMax; - const labelStart = state.pos + 1; - const labelEnd = state.md.helpers.parseLinkLabel(state, state.pos, true); - if (labelEnd < 0) { - return false; - } - let pos = labelEnd + 1; - if (pos < max && state.src.charCodeAt(pos) === 40) { - parseReference = false; - pos++; - for (; pos < max; pos++) { - code$1 = state.src.charCodeAt(pos); - if (!isSpace(code$1) && code$1 !== 10) { - break; - } - } - if (pos >= max) { - return false; - } - start = pos; - res = state.md.helpers.parseLinkDestination(state.src, pos, state.posMax); - if (res.ok) { - href = state.md.normalizeLink(res.str); - if (state.md.validateLink(href)) { - pos = res.pos; - } else { - href = ""; - } - start = pos; - for (; pos < max; pos++) { - code$1 = state.src.charCodeAt(pos); - if (!isSpace(code$1) && code$1 !== 10) { - break; - } - } - res = state.md.helpers.parseLinkTitle(state.src, pos, state.posMax); - if (pos < max && start !== pos && res.ok) { - title$1 = res.str; - pos = res.pos; - for (; pos < max; pos++) { - code$1 = state.src.charCodeAt(pos); - if (!isSpace(code$1) && code$1 !== 10) { - break; - } - } - } - } - if (pos >= max || state.src.charCodeAt(pos) !== 41) { - parseReference = true; - } - pos++; - } - if (parseReference) { - if (typeof state.env.references === "undefined") { - return false; - } - if (pos < max && state.src.charCodeAt(pos) === 91) { - start = pos + 1; - pos = state.md.helpers.parseLinkLabel(state, pos); - if (pos >= 0) { - label = state.src.slice(start, pos++); - } else { - pos = labelEnd + 1; - } - } else { - pos = labelEnd + 1; - } - if (!label) { - label = state.src.slice(labelStart, labelEnd); - } - ref = state.env.references[normalizeReference(label)]; - if (!ref) { - state.pos = oldPos; - return false; - } - href = ref.href; - title$1 = ref.title; - } - if (!silent) { - state.pos = labelStart; - state.posMax = labelEnd; - const token_o = state.push("link_open", "a", 1); - const attrs = [["href", href]]; - token_o.attrs = attrs; - if (title$1) { - attrs.push(["title", title$1]); - } - state.linkLevel++; - state.md.inline.tokenize(state); - state.linkLevel--; - state.push("link_close", "a", -1); - } - state.pos = pos; - state.posMax = max; - return true; -} - -function image(state, silent) { - let code$1, content, label, pos, ref, res, title$1, start; - let href = ""; - const oldPos = state.pos; - const max = state.posMax; - if (state.src.charCodeAt(state.pos) !== 33) { - return false; - } - if (state.src.charCodeAt(state.pos + 1) !== 91) { - return false; - } - const labelStart = state.pos + 2; - const labelEnd = state.md.helpers.parseLinkLabel(state, state.pos + 1, false); - if (labelEnd < 0) { - return false; - } - pos = labelEnd + 1; - if (pos < max && state.src.charCodeAt(pos) === 40) { - pos++; - for (; pos < max; pos++) { - code$1 = state.src.charCodeAt(pos); - if (!isSpace(code$1) && code$1 !== 10) { - break; - } - } - if (pos >= max) { - return false; - } - start = pos; - res = state.md.helpers.parseLinkDestination(state.src, pos, state.posMax); - if (res.ok) { - href = state.md.normalizeLink(res.str); - if (state.md.validateLink(href)) { - pos = res.pos; - } else { - href = ""; - } - } - start = pos; - for (; pos < max; pos++) { - code$1 = state.src.charCodeAt(pos); - if (!isSpace(code$1) && code$1 !== 10) { - break; - } - } - res = state.md.helpers.parseLinkTitle(state.src, pos, state.posMax); - if (pos < max && start !== pos && res.ok) { - title$1 = res.str; - pos = res.pos; - for (; pos < max; pos++) { - code$1 = state.src.charCodeAt(pos); - if (!isSpace(code$1) && code$1 !== 10) { - break; - } - } - } else { - title$1 = ""; - } - if (pos >= max || state.src.charCodeAt(pos) !== 41) { - state.pos = oldPos; - return false; - } - pos++; - } else { - if (typeof state.env.references === "undefined") { - return false; - } - if (pos < max && state.src.charCodeAt(pos) === 91) { - start = pos + 1; - pos = state.md.helpers.parseLinkLabel(state, pos); - if (pos >= 0) { - label = state.src.slice(start, pos++); - } else { - pos = labelEnd + 1; - } - } else { - pos = labelEnd + 1; - } - if (!label) { - label = state.src.slice(labelStart, labelEnd); - } - ref = state.env.references[normalizeReference(label)]; - if (!ref) { - state.pos = oldPos; - return false; - } - href = ref.href; - title$1 = ref.title; - } - if (!silent) { - content = state.src.slice(labelStart, labelEnd); - const tokens = []; - state.md.inline.parse(content, state.md, state.env, tokens); - const token = state.push("image", "img", 0); - const attrs = [["src", href], ["alt", ""]]; - token.attrs = attrs; - token.children = tokens; - token.content = content; - if (title$1) { - attrs.push(["title", title$1]); - } - } - state.pos = pos; - state.posMax = max; - return true; -} - -const EMAIL_RE = /^([a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)$/; -const AUTOLINK_RE = /^([a-zA-Z][a-zA-Z0-9+.-]{1,31}):([^<>\x00-\x20]*)$/; -function autolink(state, silent) { - let pos = state.pos; - if (state.src.charCodeAt(pos) !== 60) { - return false; - } - const start = state.pos; - const max = state.posMax; - for (;;) { - if (++pos >= max) return false; - const ch = state.src.charCodeAt(pos); - if (ch === 60) return false; - if (ch === 62) break; - } - const url = state.src.slice(start + 1, pos); - if (AUTOLINK_RE.test(url)) { - const fullUrl = state.md.normalizeLink(url); - if (!state.md.validateLink(fullUrl)) { - return false; - } - if (!silent) { - const token_o = state.push("link_open", "a", 1); - token_o.attrs = [["href", fullUrl]]; - token_o.markup = "autolink"; - token_o.info = "auto"; - const token_t = state.push("text", "", 0); - token_t.content = state.md.normalizeLinkText(url); - const token_c = state.push("link_close", "a", -1); - token_c.markup = "autolink"; - token_c.info = "auto"; - } - state.pos += url.length + 2; - return true; - } - if (EMAIL_RE.test(url)) { - const fullUrl = state.md.normalizeLink("mailto:" + url); - if (!state.md.validateLink(fullUrl)) { - return false; - } - if (!silent) { - const token_o = state.push("link_open", "a", 1); - token_o.attrs = [["href", fullUrl]]; - token_o.markup = "autolink"; - token_o.info = "auto"; - const token_t = state.push("text", "", 0); - token_t.content = state.md.normalizeLinkText(url); - const token_c = state.push("link_close", "a", -1); - token_c.markup = "autolink"; - token_c.info = "auto"; - } - state.pos += url.length + 2; - return true; - } - return false; -} - -function isLinkOpen(str) { - return /^\s]/i.test(str); -} -function isLinkClose(str) { - return /^<\/a\s*>/i.test(str); -} -function isLetter(ch) { - const lc = ch | 32; - return lc >= 97 && lc <= 122; -} -function html_inline(state, silent) { - if (!state.md.options.html) { - return false; - } - const max = state.posMax; - const pos = state.pos; - if (state.src.charCodeAt(pos) !== 60 || pos + 2 >= max) { - return false; - } - const ch = state.src.charCodeAt(pos + 1); - if (ch !== 33 && ch !== 63 && ch !== 47 && !isLetter(ch)) { - return false; - } - const match = state.src.slice(pos).match(HTML_TAG_RE); - if (!match) { - return false; - } - if (!silent) { - const token = state.push("html_inline", "", 0); - token.content = match[0]; - if (isLinkOpen(token.content)) state.linkLevel++; - if (isLinkClose(token.content)) state.linkLevel--; - } - state.pos += match[0].length; - return true; -} - -const DIGITAL_RE = /^&#((?:x[a-f0-9]{1,6}|[0-9]{1,7}));/i; -const NAMED_RE = /^&([a-z][a-z0-9]{1,31});/i; -function entity(state, silent) { - const pos = state.pos; - const max = state.posMax; - if (state.src.charCodeAt(pos) !== 38) return false; - if (pos + 1 >= max) return false; - const ch = state.src.charCodeAt(pos + 1); - if (ch === 35) { - const match = state.src.slice(pos).match(DIGITAL_RE); - if (match) { - if (!silent) { - const code$1 = match[1][0].toLowerCase() === "x" ? parseInt(match[1].slice(1), 16) : parseInt(match[1], 10); - const token = state.push("text_special", "", 0); - token.content = isValidEntityCode(code$1) ? fromCodePoint(code$1) : fromCodePoint(65533); - token.markup = match[0]; - token.info = "entity"; - } - state.pos += match[0].length; - return true; - } - } else { - const match = state.src.slice(pos).match(NAMED_RE); - if (match) { - const decoded = decodeHTML(match[0]); - if (decoded !== match[0]) { - if (!silent) { - const token = state.push("text_special", "", 0); - token.content = decoded; - token.markup = match[0]; - token.info = "entity"; - } - state.pos += match[0].length; - return true; - } - } - } - return false; -} - -function processDelimiters(delimiters) { - const openersBottom = {}; - const max = delimiters.length; - if (!max) return; - let headerIdx = 0; - let lastTokenIdx = -2; - const jumps = []; - for (let closerIdx = 0; closerIdx < max; closerIdx++) { - const closer = delimiters[closerIdx]; - jumps.push(0); - if (delimiters[headerIdx].marker !== closer.marker || lastTokenIdx !== closer.token - 1) { - headerIdx = closerIdx; - } - lastTokenIdx = closer.token; - closer.length = closer.length || 0; - if (!closer.close) continue; - if (!openersBottom.hasOwnProperty(closer.marker)) { - openersBottom[closer.marker] = [ - -1, - -1, - -1, - -1, - -1, - -1 - ]; - } - const minOpenerIdx = openersBottom[closer.marker][(closer.open ? 3 : 0) + closer.length % 3]; - let openerIdx = headerIdx - jumps[headerIdx] - 1; - let newMinOpenerIdx = openerIdx; - for (; openerIdx > minOpenerIdx; openerIdx -= jumps[openerIdx] + 1) { - const opener = delimiters[openerIdx]; - if (opener.marker !== closer.marker) continue; - if (opener.open && opener.end < 0) { - let isOddMatch = false; - if (opener.close || closer.open) { - if ((opener.length + closer.length) % 3 === 0) { - if (opener.length % 3 !== 0 || closer.length % 3 !== 0) { - isOddMatch = true; - } - } - } - if (!isOddMatch) { - const lastJump = openerIdx > 0 && !delimiters[openerIdx - 1].open ? jumps[openerIdx - 1] + 1 : 0; - jumps[closerIdx] = closerIdx - openerIdx + lastJump; - jumps[openerIdx] = lastJump; - closer.open = false; - opener.end = closerIdx; - opener.close = false; - newMinOpenerIdx = -1; - lastTokenIdx = -2; - break; - } - } - } - if (newMinOpenerIdx !== -1) { - openersBottom[closer.marker][(closer.open ? 3 : 0) + (closer.length || 0) % 3] = newMinOpenerIdx; - } - } -} -function link_pairs(state) { - const tokens_meta = state.tokens_meta; - const max = state.tokens_meta.length; - processDelimiters(state.delimiters); - for (let curr = 0; curr < max; curr++) { - if (tokens_meta[curr] && tokens_meta[curr].delimiters) { - processDelimiters(tokens_meta[curr].delimiters); - } - } -} - -function fragments_join(state) { - let curr, last; - let level = 0; - const tokens = state.tokens; - const max = state.tokens.length; - for (curr = last = 0; curr < max; curr++) { - if (tokens[curr].nesting < 0) level--; - tokens[curr].level = level; - if (tokens[curr].nesting > 0) level++; - if (tokens[curr].type === "text" && curr + 1 < max && tokens[curr + 1].type === "text") { - tokens[curr + 1].content = tokens[curr].content + tokens[curr + 1].content; - } else { - if (curr !== last) { - tokens[last] = tokens[curr]; - } - last++; - } - } - if (curr !== last) { - tokens.length = last; - } -} - -/** internal -* class ParserInline -* -* Tokenizes paragraph content. -**/ -const _rules = [ - ["text", text], - ["linkify", linkify], - ["newline", newline], - ["escape", escape], - ["backticks", backtick], - ["strikethrough", strikethrough_default.tokenize], - ["emphasis", emphasis_default.tokenize], - ["link", link], - ["image", image], - ["autolink", autolink], - ["html_inline", html_inline], - ["entity", entity] -]; -const _rules2 = [ - ["balance_pairs", link_pairs], - ["strikethrough", strikethrough_default.postProcess], - ["emphasis", emphasis_default.postProcess], - ["fragments_join", fragments_join] -]; -/** -* new ParserInline() -**/ -function ParserInline() { - /** - * ParserInline#ruler -> Ruler - * - * [[Ruler]] instance. Keep configuration of inline rules. - **/ - this.ruler = new ruler_default(); - for (let i$10 = 0; i$10 < _rules.length; i$10++) { - this.ruler.push(_rules[i$10][0], _rules[i$10][1]); - } - /** - * ParserInline#ruler2 -> Ruler - * - * [[Ruler]] instance. Second ruler used for post-processing - * (e.g. in emphasis-like rules). - **/ - this.ruler2 = new ruler_default(); - for (let i$10 = 0; i$10 < _rules2.length; i$10++) { - this.ruler2.push(_rules2[i$10][0], _rules2[i$10][1]); - } -} -ParserInline.prototype.skipToken = function(state) { - const pos = state.pos; - const rules = this.ruler.getRules(""); - const len = rules.length; - const maxNesting = state.md.options.maxNesting; - const cache = state.cache; - if (typeof cache[pos] !== "undefined") { - state.pos = cache[pos]; - return; - } - let ok = false; - if (state.level < maxNesting) { - for (let i$10 = 0; i$10 < len; i$10++) { - state.level++; - ok = rules[i$10](state, true); - state.level--; - if (ok) { - if (pos >= state.pos) { - throw new Error("inline rule didn't increment state.pos"); - } - break; - } - } - } else { - state.pos = state.posMax; - } - if (!ok) { - state.pos++; - } - cache[pos] = state.pos; -}; -ParserInline.prototype.tokenize = function(state) { - const rules = this.ruler.getRules(""); - const len = rules.length; - const end = state.posMax; - const maxNesting = state.md.options.maxNesting; - while (state.pos < end) { - const prevPos = state.pos; - let ok = false; - if (state.level < maxNesting) { - for (let i$10 = 0; i$10 < len; i$10++) { - ok = rules[i$10](state, false); - if (ok) { - if (prevPos >= state.pos) { - throw new Error("inline rule didn't increment state.pos"); - } - break; - } - } - } - if (ok) { - if (state.pos >= end) { - break; - } - continue; - } - state.pending += state.src[state.pos++]; - } - if (state.pending) { - state.pushPending(); - } -}; -/** -* ParserInline.parse(str, md, env, outTokens) -* -* Process input string and push inline tokens into `outTokens` -**/ -ParserInline.prototype.parse = function(str, md, env, outTokens) { - const state = new this.State(str, md, env, outTokens); - this.tokenize(state); - const rules = this.ruler2.getRules(""); - const len = rules.length; - for (let i$10 = 0; i$10 < len; i$10++) { - rules[i$10](state); - } -}; -ParserInline.prototype.State = state_inline_default; -var parser_inline_default = ParserInline; - -function re_default(opts) { - const re = {}; - opts = opts || {}; - re.src_Any = regex_default$5.source; - re.src_Cc = regex_default$4.source; - re.src_Z = regex_default.source; - re.src_P = regex_default$2.source; - re.src_ZPCc = [ - re.src_Z, - re.src_P, - re.src_Cc - ].join("|"); - re.src_ZCc = [re.src_Z, re.src_Cc].join("|"); - const text_separators = "[><|]"; - re.src_pseudo_letter = "(?:(?!" + text_separators + "|" + re.src_ZPCc + ")" + re.src_Any + ")"; - re.src_ip4 = "(?:(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"; - re.src_auth = "(?:(?:(?!" + re.src_ZCc + "|[@/\\[\\]()]).)+@)?"; - re.src_port = "(?::(?:6(?:[0-4]\\d{3}|5(?:[0-4]\\d{2}|5(?:[0-2]\\d|3[0-5])))|[1-5]?\\d{1,4}))?"; - re.src_host_terminator = "(?=$|" + text_separators + "|" + re.src_ZPCc + ")" + "(?!" + (opts["---"] ? "-(?!--)|" : "-|") + "_|:\\d|\\.-|\\.(?!$|" + re.src_ZPCc + "))"; - re.src_path = "(?:" + "[/?#]" + "(?:" + "(?!" + re.src_ZCc + "|" + text_separators + "|[()[\\]{}.,\"'?!\\-;]).|" + "\\[(?:(?!" + re.src_ZCc + "|\\]).)*\\]|" + "\\((?:(?!" + re.src_ZCc + "|[)]).)*\\)|" + "\\{(?:(?!" + re.src_ZCc + "|[}]).)*\\}|" + "\\\"(?:(?!" + re.src_ZCc + "|[\"]).)+\\\"|" + "\\'(?:(?!" + re.src_ZCc + "|[']).)+\\'|" + "\\'(?=" + re.src_pseudo_letter + "|[-])|" + "\\.{2,}[a-zA-Z0-9%/&]|" + "\\.(?!" + re.src_ZCc + "|[.]|$)|" + (opts["---"] ? "\\-(?!--(?:[^-]|$))(?:-*)|" : "\\-+|") + ",(?!" + re.src_ZCc + "|$)|" + ";(?!" + re.src_ZCc + "|$)|" + "\\!+(?!" + re.src_ZCc + "|[!]|$)|" + "\\?(?!" + re.src_ZCc + "|[?]|$)" + ")+" + "|\\/" + ")?"; - re.src_email_name = "[\\-;:&=\\+\\$,\\.a-zA-Z0-9_][\\-;:&=\\+\\$,\\\"\\.a-zA-Z0-9_]*"; - re.src_xn = "xn--[a-z0-9\\-]{1,59}"; - re.src_domain_root = "(?:" + re.src_xn + "|" + re.src_pseudo_letter + "{1,63}" + ")"; - re.src_domain = "(?:" + re.src_xn + "|" + "(?:" + re.src_pseudo_letter + ")" + "|" + "(?:" + re.src_pseudo_letter + "(?:-|" + re.src_pseudo_letter + "){0,61}" + re.src_pseudo_letter + ")" + ")"; - re.src_host = "(?:" + "(?:(?:(?:" + re.src_domain + ")\\.)*" + re.src_domain + ")" + ")"; - re.tpl_host_fuzzy = "(?:" + re.src_ip4 + "|" + "(?:(?:(?:" + re.src_domain + ")\\.)+(?:%TLDS%))" + ")"; - re.tpl_host_no_ip_fuzzy = "(?:(?:(?:" + re.src_domain + ")\\.)+(?:%TLDS%))"; - re.src_host_strict = re.src_host + re.src_host_terminator; - re.tpl_host_fuzzy_strict = re.tpl_host_fuzzy + re.src_host_terminator; - re.src_host_port_strict = re.src_host + re.src_port + re.src_host_terminator; - re.tpl_host_port_fuzzy_strict = re.tpl_host_fuzzy + re.src_port + re.src_host_terminator; - re.tpl_host_port_no_ip_fuzzy_strict = re.tpl_host_no_ip_fuzzy + re.src_port + re.src_host_terminator; - re.tpl_host_fuzzy_test = "localhost|www\\.|\\.\\d{1,3}\\.|(?:\\.(?:%TLDS%)(?:" + re.src_ZPCc + "|>|$))"; - re.tpl_email_fuzzy = "(^|" + text_separators + "|\"|\\(|" + re.src_ZCc + ")" + "(" + re.src_email_name + "@" + re.tpl_host_fuzzy_strict + ")"; - re.tpl_link_fuzzy = "(^|(?![.:/\\-_@])(?:[$+<=>^`||]|" + re.src_ZPCc + "))" + "((?![$+<=>^`||])" + re.tpl_host_port_fuzzy_strict + re.src_path + ")"; - re.tpl_link_no_ip_fuzzy = "(^|(?![.:/\\-_@])(?:[$+<=>^`||]|" + re.src_ZPCc + "))" + "((?![$+<=>^`||])" + re.tpl_host_port_no_ip_fuzzy_strict + re.src_path + ")"; - return re; -} - -function assign(obj) { - const sources = Array.prototype.slice.call(arguments, 1); - sources.forEach(function(source) { - if (!source) { - return; - } - Object.keys(source).forEach(function(key) { - obj[key] = source[key]; - }); - }); - return obj; -} -function _class(obj) { - return Object.prototype.toString.call(obj); -} -function isString(obj) { - return _class(obj) === "[object String]"; -} -function isObject(obj) { - return _class(obj) === "[object Object]"; -} -function isRegExp(obj) { - return _class(obj) === "[object RegExp]"; -} -function isFunction(obj) { - return _class(obj) === "[object Function]"; -} -function escapeRE(str) { - return str.replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&"); -} -const defaultOptions = { - fuzzyLink: true, - fuzzyEmail: true, - fuzzyIP: false -}; -function isOptionsObj(obj) { - return Object.keys(obj || {}).reduce(function(acc, k$1) { - return acc || defaultOptions.hasOwnProperty(k$1); - }, false); -} -const defaultSchemas = { - "http:": { validate: function(text$1, pos, self) { - const tail = text$1.slice(pos); - if (!self.re.http) { - self.re.http = new RegExp("^\\/\\/" + self.re.src_auth + self.re.src_host_port_strict + self.re.src_path, "i"); - } - if (self.re.http.test(tail)) { - return tail.match(self.re.http)[0].length; - } - return 0; - } }, - "https:": "http:", - "ftp:": "http:", - "//": { validate: function(text$1, pos, self) { - const tail = text$1.slice(pos); - if (!self.re.no_http) { - self.re.no_http = new RegExp("^" + self.re.src_auth + "(?:localhost|(?:(?:" + self.re.src_domain + ")\\.)+" + self.re.src_domain_root + ")" + self.re.src_port + self.re.src_host_terminator + self.re.src_path, "i"); - } - if (self.re.no_http.test(tail)) { - if (pos >= 3 && text$1[pos - 3] === ":") { - return 0; - } - if (pos >= 3 && text$1[pos - 3] === "/") { - return 0; - } - return tail.match(self.re.no_http)[0].length; - } - return 0; - } }, - "mailto:": { validate: function(text$1, pos, self) { - const tail = text$1.slice(pos); - if (!self.re.mailto) { - self.re.mailto = new RegExp("^" + self.re.src_email_name + "@" + self.re.src_host_strict, "i"); - } - if (self.re.mailto.test(tail)) { - return tail.match(self.re.mailto)[0].length; - } - return 0; - } } -}; -const tlds_2ch_src_re = "a[cdefgilmnoqrstuwxz]|b[abdefghijmnorstvwyz]|c[acdfghiklmnoruvwxyz]|d[ejkmoz]|e[cegrstu]|f[ijkmor]|g[abdefghilmnpqrstuwy]|h[kmnrtu]|i[delmnoqrst]|j[emop]|k[eghimnprwyz]|l[abcikrstuvy]|m[acdeghklmnopqrstuvwxyz]|n[acefgilopruz]|om|p[aefghklmnrstwy]|qa|r[eosuw]|s[abcdeghijklmnortuvxyz]|t[cdfghjklmnortvwz]|u[agksyz]|v[aceginu]|w[fs]|y[et]|z[amw]"; -const tlds_default = "biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|рф".split("|"); -function resetScanCache(self) { - self.__index__ = -1; - self.__text_cache__ = ""; -} -function createValidator(re) { - return function(text$1, pos) { - const tail = text$1.slice(pos); - if (re.test(tail)) { - return tail.match(re)[0].length; - } - return 0; - }; -} -function createNormalizer() { - return function(match, self) { - self.normalize(match); - }; -} -function compile(self) { - const re = self.re = re_default(self.__opts__); - const tlds = self.__tlds__.slice(); - self.onCompile(); - if (!self.__tlds_replaced__) { - tlds.push(tlds_2ch_src_re); - } - tlds.push(re.src_xn); - re.src_tlds = tlds.join("|"); - function untpl(tpl) { - return tpl.replace("%TLDS%", re.src_tlds); - } - re.email_fuzzy = RegExp(untpl(re.tpl_email_fuzzy), "i"); - re.link_fuzzy = RegExp(untpl(re.tpl_link_fuzzy), "i"); - re.link_no_ip_fuzzy = RegExp(untpl(re.tpl_link_no_ip_fuzzy), "i"); - re.host_fuzzy_test = RegExp(untpl(re.tpl_host_fuzzy_test), "i"); - const aliases = []; - self.__compiled__ = {}; - function schemaError(name, val) { - throw new Error("(LinkifyIt) Invalid schema \"" + name + "\": " + val); - } - Object.keys(self.__schemas__).forEach(function(name) { - const val = self.__schemas__[name]; - if (val === null) { - return; - } - const compiled = { - validate: null, - link: null - }; - self.__compiled__[name] = compiled; - if (isObject(val)) { - if (isRegExp(val.validate)) { - compiled.validate = createValidator(val.validate); - } else if (isFunction(val.validate)) { - compiled.validate = val.validate; - } else { - schemaError(name, val); - } - if (isFunction(val.normalize)) { - compiled.normalize = val.normalize; - } else if (!val.normalize) { - compiled.normalize = createNormalizer(); - } else { - schemaError(name, val); - } - return; - } - if (isString(val)) { - aliases.push(name); - return; - } - schemaError(name, val); - }); - aliases.forEach(function(alias) { - if (!self.__compiled__[self.__schemas__[alias]]) { - return; - } - self.__compiled__[alias].validate = self.__compiled__[self.__schemas__[alias]].validate; - self.__compiled__[alias].normalize = self.__compiled__[self.__schemas__[alias]].normalize; - }); - self.__compiled__[""] = { - validate: null, - normalize: createNormalizer() - }; - const slist = Object.keys(self.__compiled__).filter(function(name) { - return name.length > 0 && self.__compiled__[name]; - }).map(escapeRE).join("|"); - self.re.schema_test = RegExp("(^|(?!_)(?:[><|]|" + re.src_ZPCc + "))(" + slist + ")", "i"); - self.re.schema_search = RegExp("(^|(?!_)(?:[><|]|" + re.src_ZPCc + "))(" + slist + ")", "ig"); - self.re.schema_at_start = RegExp("^" + self.re.schema_search.source, "i"); - self.re.pretest = RegExp("(" + self.re.schema_test.source + ")|(" + self.re.host_fuzzy_test.source + ")|@", "i"); - resetScanCache(self); -} -/** -* class Match -* -* Match result. Single element of array, returned by [[LinkifyIt#match]] -**/ -function Match(self, shift) { - const start = self.__index__; - const end = self.__last_index__; - const text$1 = self.__text_cache__.slice(start, end); - /** - * Match#schema -> String - * - * Prefix (protocol) for matched string. - **/ - this.schema = self.__schema__.toLowerCase(); - /** - * Match#index -> Number - * - * First position of matched string. - **/ - this.index = start + shift; - /** - * Match#lastIndex -> Number - * - * Next position after matched string. - **/ - this.lastIndex = end + shift; - /** - * Match#raw -> String - * - * Matched string. - **/ - this.raw = text$1; - /** - * Match#text -> String - * - * Notmalized text of matched string. - **/ - this.text = text$1; - /** - * Match#url -> String - * - * Normalized url of matched string. - **/ - this.url = text$1; -} -function createMatch(self, shift) { - const match = new Match(self, shift); - self.__compiled__[match.schema].normalize(match, self); - return match; -} -/** -* class LinkifyIt -**/ -/** -* new LinkifyIt(schemas, options) -* - schemas (Object): Optional. Additional schemas to validate (prefix/validator) -* - options (Object): { fuzzyLink|fuzzyEmail|fuzzyIP: true|false } -* -* Creates new linkifier instance with optional additional schemas. -* Can be called without `new` keyword for convenience. -* -* By default understands: -* -* - `http(s)://...` , `ftp://...`, `mailto:...` & `//...` links -* - "fuzzy" links and emails (example.com, foo@bar.com). -* -* `schemas` is an object, where each key/value describes protocol/rule: -* -* - __key__ - link prefix (usually, protocol name with `:` at the end, `skype:` -* for example). `linkify-it` makes shure that prefix is not preceeded with -* alphanumeric char and symbols. Only whitespaces and punctuation allowed. -* - __value__ - rule to check tail after link prefix -* - _String_ - just alias to existing rule -* - _Object_ -* - _validate_ - validator function (should return matched length on success), -* or `RegExp`. -* - _normalize_ - optional function to normalize text & url of matched result -* (for example, for @twitter mentions). -* -* `options`: -* -* - __fuzzyLink__ - recognige URL-s without `http(s):` prefix. Default `true`. -* - __fuzzyIP__ - allow IPs in fuzzy links above. Can conflict with some texts -* like version numbers. Default `false`. -* - __fuzzyEmail__ - recognize emails without `mailto:` prefix. -* -**/ -function LinkifyIt(schemas, options) { - if (!(this instanceof LinkifyIt)) { - return new LinkifyIt(schemas, options); - } - if (!options) { - if (isOptionsObj(schemas)) { - options = schemas; - schemas = {}; - } - } - this.__opts__ = assign({}, defaultOptions, options); - this.__index__ = -1; - this.__last_index__ = -1; - this.__schema__ = ""; - this.__text_cache__ = ""; - this.__schemas__ = assign({}, defaultSchemas, schemas); - this.__compiled__ = {}; - this.__tlds__ = tlds_default; - this.__tlds_replaced__ = false; - this.re = {}; - compile(this); -} -/** chainable -* LinkifyIt#add(schema, definition) -* - schema (String): rule name (fixed pattern prefix) -* - definition (String|RegExp|Object): schema definition -* -* Add new rule definition. See constructor description for details. -**/ -LinkifyIt.prototype.add = function add(schema, definition) { - this.__schemas__[schema] = definition; - compile(this); - return this; -}; -/** chainable -* LinkifyIt#set(options) -* - options (Object): { fuzzyLink|fuzzyEmail|fuzzyIP: true|false } -* -* Set recognition options for links without schema. -**/ -LinkifyIt.prototype.set = function set(options) { - this.__opts__ = assign(this.__opts__, options); - return this; -}; -/** -* LinkifyIt#test(text) -> Boolean -* -* Searches linkifiable pattern and returns `true` on success or `false` on fail. -**/ -LinkifyIt.prototype.test = function test(text$1) { - this.__text_cache__ = text$1; - this.__index__ = -1; - if (!text$1.length) { - return false; - } - let m$3, ml, me, len, shift, next, re, tld_pos, at_pos; - if (this.re.schema_test.test(text$1)) { - re = this.re.schema_search; - re.lastIndex = 0; - while ((m$3 = re.exec(text$1)) !== null) { - len = this.testSchemaAt(text$1, m$3[2], re.lastIndex); - if (len) { - this.__schema__ = m$3[2]; - this.__index__ = m$3.index + m$3[1].length; - this.__last_index__ = m$3.index + m$3[0].length + len; - break; - } - } - } - if (this.__opts__.fuzzyLink && this.__compiled__["http:"]) { - tld_pos = text$1.search(this.re.host_fuzzy_test); - if (tld_pos >= 0) { - if (this.__index__ < 0 || tld_pos < this.__index__) { - if ((ml = text$1.match(this.__opts__.fuzzyIP ? this.re.link_fuzzy : this.re.link_no_ip_fuzzy)) !== null) { - shift = ml.index + ml[1].length; - if (this.__index__ < 0 || shift < this.__index__) { - this.__schema__ = ""; - this.__index__ = shift; - this.__last_index__ = ml.index + ml[0].length; - } - } - } - } - } - if (this.__opts__.fuzzyEmail && this.__compiled__["mailto:"]) { - at_pos = text$1.indexOf("@"); - if (at_pos >= 0) { - if ((me = text$1.match(this.re.email_fuzzy)) !== null) { - shift = me.index + me[1].length; - next = me.index + me[0].length; - if (this.__index__ < 0 || shift < this.__index__ || shift === this.__index__ && next > this.__last_index__) { - this.__schema__ = "mailto:"; - this.__index__ = shift; - this.__last_index__ = next; - } - } - } - } - return this.__index__ >= 0; -}; -/** -* LinkifyIt#pretest(text) -> Boolean -* -* Very quick check, that can give false positives. Returns true if link MAY BE -* can exists. Can be used for speed optimization, when you need to check that -* link NOT exists. -**/ -LinkifyIt.prototype.pretest = function pretest(text$1) { - return this.re.pretest.test(text$1); -}; -/** -* LinkifyIt#testSchemaAt(text, name, position) -> Number -* - text (String): text to scan -* - name (String): rule (schema) name -* - position (Number): text offset to check from -* -* Similar to [[LinkifyIt#test]] but checks only specific protocol tail exactly -* at given position. Returns length of found pattern (0 on fail). -**/ -LinkifyIt.prototype.testSchemaAt = function testSchemaAt(text$1, schema, pos) { - if (!this.__compiled__[schema.toLowerCase()]) { - return 0; - } - return this.__compiled__[schema.toLowerCase()].validate(text$1, pos, this); -}; -/** -* LinkifyIt#match(text) -> Array|null -* -* Returns array of found link descriptions or `null` on fail. We strongly -* recommend to use [[LinkifyIt#test]] first, for best speed. -* -* ##### Result match description -* -* - __schema__ - link schema, can be empty for fuzzy links, or `//` for -* protocol-neutral links. -* - __index__ - offset of matched text -* - __lastIndex__ - index of next char after mathch end -* - __raw__ - matched text -* - __text__ - normalized text -* - __url__ - link, generated from matched text -**/ -LinkifyIt.prototype.match = function match(text$1) { - const result = []; - let shift = 0; - if (this.__index__ >= 0 && this.__text_cache__ === text$1) { - result.push(createMatch(this, shift)); - shift = this.__last_index__; - } - let tail = shift ? text$1.slice(shift) : text$1; - while (this.test(tail)) { - result.push(createMatch(this, shift)); - tail = tail.slice(this.__last_index__); - shift += this.__last_index__; - } - if (result.length) { - return result; - } - return null; -}; -/** -* LinkifyIt#matchAtStart(text) -> Match|null -* -* Returns fully-formed (not fuzzy) link if it starts at the beginning -* of the string, and null otherwise. -**/ -LinkifyIt.prototype.matchAtStart = function matchAtStart(text$1) { - this.__text_cache__ = text$1; - this.__index__ = -1; - if (!text$1.length) return null; - const m$3 = this.re.schema_at_start.exec(text$1); - if (!m$3) return null; - const len = this.testSchemaAt(text$1, m$3[2], m$3[0].length); - if (!len) return null; - this.__schema__ = m$3[2]; - this.__index__ = m$3.index + m$3[1].length; - this.__last_index__ = m$3.index + m$3[0].length + len; - return createMatch(this, 0); -}; -/** chainable -* LinkifyIt#tlds(list [, keepOld]) -> this -* - list (Array): list of tlds -* - keepOld (Boolean): merge with current list if `true` (`false` by default) -* -* Load (or merge) new tlds list. Those are user for fuzzy links (without prefix) -* to avoid false positives. By default this algorythm used: -* -* - hostname with any 2-letter root zones are ok. -* - biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|рф -* are ok. -* - encoded (`xn--...`) root zones are ok. -* -* If list is replaced, then exact match for 2-chars root zones will be checked. -**/ -LinkifyIt.prototype.tlds = function tlds(list$1, keepOld) { - list$1 = Array.isArray(list$1) ? list$1 : [list$1]; - if (!keepOld) { - this.__tlds__ = list$1.slice(); - this.__tlds_replaced__ = true; - compile(this); - return this; - } - this.__tlds__ = this.__tlds__.concat(list$1).sort().filter(function(el, idx, arr) { - return el !== arr[idx - 1]; - }).reverse(); - compile(this); - return this; -}; -/** -* LinkifyIt#normalize(match) -* -* Default normalizer (if schema does not define it's own). -**/ -LinkifyIt.prototype.normalize = function normalize$1(match) { - if (!match.schema) { - match.url = "http://" + match.url; - } - if (match.schema === "mailto:" && !/^mailto:/i.test(match.url)) { - match.url = "mailto:" + match.url; - } -}; -/** -* LinkifyIt#onCompile() -* -* Override to modify basic RegExp-s. -**/ -LinkifyIt.prototype.onCompile = function onCompile() {}; -var linkify_it_default = LinkifyIt; - -/** Highest positive signed 32-bit float value */ -const maxInt = 2147483647; -/** Bootstring parameters */ -const base = 36; -const tMin = 1; -const tMax = 26; -const skew = 38; -const damp = 700; -const initialBias = 72; -const initialN = 128; -const delimiter = "-"; -/** Regular expressions */ -const regexPunycode = /^xn--/; -const regexNonASCII = /[^\0-\x7F]/; -const regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g; -/** Error messages */ -const errors = { - "overflow": "Overflow: input needs wider integers to process", - "not-basic": "Illegal input >= 0x80 (not a basic code point)", - "invalid-input": "Invalid input" -}; -/** Convenience shortcuts */ -const baseMinusTMin = base - tMin; -const floor = Math.floor; -const stringFromCharCode = String.fromCharCode; -/** -* A generic error utility function. -* @private -* @param {String} type The error type. -* @returns {Error} Throws a `RangeError` with the applicable error message. -*/ -function error(type$2) { - throw new RangeError(errors[type$2]); -} -/** -* A generic `Array#map` utility function. -* @private -* @param {Array} array The array to iterate over. -* @param {Function} callback The function that gets called for every array -* item. -* @returns {Array} A new array of values returned by the callback function. -*/ -function map(array, callback) { - const result = []; - let length = array.length; - while (length--) { - result[length] = callback(array[length]); - } - return result; -} -/** -* A simple `Array#map`-like wrapper to work with domain name strings or email -* addresses. -* @private -* @param {String} domain The domain name or email address. -* @param {Function} callback The function that gets called for every -* character. -* @returns {String} A new string of characters returned by the callback -* function. -*/ -function mapDomain(domain, callback) { - const parts = domain.split("@"); - let result = ""; - if (parts.length > 1) { - result = parts[0] + "@"; - domain = parts[1]; - } - domain = domain.replace(regexSeparators, "."); - const labels = domain.split("."); - const encoded = map(labels, callback).join("."); - return result + encoded; -} -/** -* Creates an array containing the numeric code points of each Unicode -* character in the string. While JavaScript uses UCS-2 internally, -* this function will convert a pair of surrogate halves (each of which -* UCS-2 exposes as separate characters) into a single code point, -* matching UTF-16. -* @see `punycode.ucs2.encode` -* @see -* @memberOf punycode.ucs2 -* @name decode -* @param {String} string The Unicode input string (UCS-2). -* @returns {Array} The new array of code points. -*/ -function ucs2decode(string) { - const output = []; - let counter = 0; - const length = string.length; - while (counter < length) { - const value = string.charCodeAt(counter++); - if (value >= 55296 && value <= 56319 && counter < length) { - const extra = string.charCodeAt(counter++); - if ((extra & 64512) == 56320) { - output.push(((value & 1023) << 10) + (extra & 1023) + 65536); - } else { - output.push(value); - counter--; - } - } else { - output.push(value); - } - } - return output; -} -/** -* Creates a string based on an array of numeric code points. -* @see `punycode.ucs2.decode` -* @memberOf punycode.ucs2 -* @name encode -* @param {Array} codePoints The array of numeric code points. -* @returns {String} The new Unicode string (UCS-2). -*/ -const ucs2encode = (codePoints) => String.fromCodePoint(...codePoints); -/** -* Converts a basic code point into a digit/integer. -* @see `digitToBasic()` -* @private -* @param {Number} codePoint The basic numeric code point value. -* @returns {Number} The numeric value of a basic code point (for use in -* representing integers) in the range `0` to `base - 1`, or `base` if -* the code point does not represent a value. -*/ -const basicToDigit = function(codePoint) { - if (codePoint >= 48 && codePoint < 58) { - return 26 + (codePoint - 48); - } - if (codePoint >= 65 && codePoint < 91) { - return codePoint - 65; - } - if (codePoint >= 97 && codePoint < 123) { - return codePoint - 97; - } - return base; -}; -/** -* Converts a digit/integer into a basic code point. -* @see `basicToDigit()` -* @private -* @param {Number} digit The numeric value of a basic code point. -* @returns {Number} The basic code point whose value (when used for -* representing integers) is `digit`, which needs to be in the range -* `0` to `base - 1`. If `flag` is non-zero, the uppercase form is -* used; else, the lowercase form is used. The behavior is undefined -* if `flag` is non-zero and `digit` has no uppercase form. -*/ -const digitToBasic = function(digit, flag) { - return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); -}; -/** -* Bias adaptation function as per section 3.4 of RFC 3492. -* https://tools.ietf.org/html/rfc3492#section-3.4 -* @private -*/ -const adapt = function(delta, numPoints, firstTime) { - let k$1 = 0; - delta = firstTime ? floor(delta / damp) : delta >> 1; - delta += floor(delta / numPoints); - for (; delta > baseMinusTMin * tMax >> 1; k$1 += base) { - delta = floor(delta / baseMinusTMin); - } - return floor(k$1 + (baseMinusTMin + 1) * delta / (delta + skew)); -}; -/** -* Converts a Punycode string of ASCII-only symbols to a string of Unicode -* symbols. -* @memberOf punycode -* @param {String} input The Punycode string of ASCII-only symbols. -* @returns {String} The resulting string of Unicode symbols. -*/ -const decode = function(input) { - const output = []; - const inputLength = input.length; - let i$10 = 0; - let n$13 = initialN; - let bias = initialBias; - let basic = input.lastIndexOf(delimiter); - if (basic < 0) { - basic = 0; - } - for (let j$2 = 0; j$2 < basic; ++j$2) { - if (input.charCodeAt(j$2) >= 128) { - error("not-basic"); - } - output.push(input.charCodeAt(j$2)); - } - for (let index = basic > 0 ? basic + 1 : 0; index < inputLength;) { - const oldi = i$10; - for (let w$1 = 1, k$1 = base;; k$1 += base) { - if (index >= inputLength) { - error("invalid-input"); - } - const digit = basicToDigit(input.charCodeAt(index++)); - if (digit >= base) { - error("invalid-input"); - } - if (digit > floor((maxInt - i$10) / w$1)) { - error("overflow"); - } - i$10 += digit * w$1; - const t$7 = k$1 <= bias ? tMin : k$1 >= bias + tMax ? tMax : k$1 - bias; - if (digit < t$7) { - break; - } - const baseMinusT = base - t$7; - if (w$1 > floor(maxInt / baseMinusT)) { - error("overflow"); - } - w$1 *= baseMinusT; - } - const out = output.length + 1; - bias = adapt(i$10 - oldi, out, oldi == 0); - if (floor(i$10 / out) > maxInt - n$13) { - error("overflow"); - } - n$13 += floor(i$10 / out); - i$10 %= out; - output.splice(i$10++, 0, n$13); - } - return String.fromCodePoint(...output); -}; -/** -* Converts a string of Unicode symbols (e.g. a domain name label) to a -* Punycode string of ASCII-only symbols. -* @memberOf punycode -* @param {String} input The string of Unicode symbols. -* @returns {String} The resulting Punycode string of ASCII-only symbols. -*/ -const encode = function(input) { - const output = []; - input = ucs2decode(input); - const inputLength = input.length; - let n$13 = initialN; - let delta = 0; - let bias = initialBias; - for (const currentValue of input) { - if (currentValue < 128) { - output.push(stringFromCharCode(currentValue)); - } - } - const basicLength = output.length; - let handledCPCount = basicLength; - if (basicLength) { - output.push(delimiter); - } - while (handledCPCount < inputLength) { - let m$3 = maxInt; - for (const currentValue of input) { - if (currentValue >= n$13 && currentValue < m$3) { - m$3 = currentValue; - } - } - const handledCPCountPlusOne = handledCPCount + 1; - if (m$3 - n$13 > floor((maxInt - delta) / handledCPCountPlusOne)) { - error("overflow"); - } - delta += (m$3 - n$13) * handledCPCountPlusOne; - n$13 = m$3; - for (const currentValue of input) { - if (currentValue < n$13 && ++delta > maxInt) { - error("overflow"); - } - if (currentValue === n$13) { - let q = delta; - for (let k$1 = base;; k$1 += base) { - const t$7 = k$1 <= bias ? tMin : k$1 >= bias + tMax ? tMax : k$1 - bias; - if (q < t$7) { - break; - } - const qMinusT = q - t$7; - const baseMinusT = base - t$7; - output.push(stringFromCharCode(digitToBasic(t$7 + qMinusT % baseMinusT, 0))); - q = floor(qMinusT / baseMinusT); - } - output.push(stringFromCharCode(digitToBasic(q, 0))); - bias = adapt(delta, handledCPCountPlusOne, handledCPCount === basicLength); - delta = 0; - ++handledCPCount; - } - } - ++delta; - ++n$13; - } - return output.join(""); -}; -/** -* Converts a Punycode string representing a domain name or an email address -* to Unicode. Only the Punycoded parts of the input will be converted, i.e. -* it doesn't matter if you call it on a string that has already been -* converted to Unicode. -* @memberOf punycode -* @param {String} input The Punycoded domain name or email address to -* convert to Unicode. -* @returns {String} The Unicode representation of the given Punycode -* string. -*/ -const toUnicode = function(input) { - return mapDomain(input, function(string) { - return regexPunycode.test(string) ? decode(string.slice(4).toLowerCase()) : string; - }); -}; -/** -* Converts a Unicode string representing a domain name or an email address to -* Punycode. Only the non-ASCII parts of the domain name will be converted, -* i.e. it doesn't matter if you call it with a domain that's already in -* ASCII. -* @memberOf punycode -* @param {String} input The domain name or email address to convert, as a -* Unicode string. -* @returns {String} The Punycode representation of the given domain name or -* email address. -*/ -const toASCII = function(input) { - return mapDomain(input, function(string) { - return regexNonASCII.test(string) ? "xn--" + encode(string) : string; - }); -}; -/** Define the public API */ -const punycode = { - "version": "2.3.1", - "ucs2": { - "decode": ucs2decode, - "encode": ucs2encode - }, - "decode": decode, - "encode": encode, - "toASCII": toASCII, - "toUnicode": toUnicode -}; -var punycode_es6_default = punycode; - -var default_default = { - options: { - html: false, - xhtmlOut: false, - breaks: false, - langPrefix: "language-", - linkify: false, - typographer: false, - quotes: "“”‘’", - highlight: null, - maxNesting: 100 - }, - components: { - core: {}, - block: {}, - inline: {} - } -}; - -var zero_default = { - options: { - html: false, - xhtmlOut: false, - breaks: false, - langPrefix: "language-", - linkify: false, - typographer: false, - quotes: "“”‘’", - highlight: null, - maxNesting: 20 - }, - components: { - core: { rules: [ - "normalize", - "block", - "inline", - "text_join" - ] }, - block: { rules: ["paragraph"] }, - inline: { - rules: ["text"], - rules2: ["balance_pairs", "fragments_join"] - } - } -}; - -var commonmark_default = { - options: { - html: true, - xhtmlOut: true, - breaks: false, - langPrefix: "language-", - linkify: false, - typographer: false, - quotes: "“”‘’", - highlight: null, - maxNesting: 20 - }, - components: { - core: { rules: [ - "normalize", - "block", - "inline", - "text_join" - ] }, - block: { rules: [ - "blockquote", - "code", - "fence", - "heading", - "hr", - "html_block", - "lheading", - "list", - "reference", - "paragraph" - ] }, - inline: { - rules: [ - "autolink", - "backticks", - "emphasis", - "entity", - "escape", - "html_inline", - "image", - "link", - "newline", - "text" - ], - rules2: [ - "balance_pairs", - "emphasis", - "fragments_join" - ] - } - } -}; - -const config = { - default: default_default, - zero: zero_default, - commonmark: commonmark_default -}; -const BAD_PROTO_RE = /^(vbscript|javascript|file|data):/; -const GOOD_DATA_RE = /^data:image\/(gif|png|jpeg|webp);/; -function validateLink(url) { - const str = url.trim().toLowerCase(); - return BAD_PROTO_RE.test(str) ? GOOD_DATA_RE.test(str) : true; -} -const RECODE_HOSTNAME_FOR = [ - "http:", - "https:", - "mailto:" -]; -function normalizeLink(url) { - const parsed = parse_default(url, true); - if (parsed.hostname) { - if (!parsed.protocol || RECODE_HOSTNAME_FOR.indexOf(parsed.protocol) >= 0) { - try { - parsed.hostname = punycode_es6_default.toASCII(parsed.hostname); - } catch (er) {} - } - } - return encode_default(format(parsed)); -} -function normalizeLinkText(url) { - const parsed = parse_default(url, true); - if (parsed.hostname) { - if (!parsed.protocol || RECODE_HOSTNAME_FOR.indexOf(parsed.protocol) >= 0) { - try { - parsed.hostname = punycode_es6_default.toUnicode(parsed.hostname); - } catch (er) {} - } - } - return decode_default(format(parsed), decode_default.defaultChars + "%"); -} -/** -* class MarkdownIt -* -* Main parser/renderer class. -* -* ##### Usage -* -* ```javascript -* // node.js, "classic" way: -* var MarkdownIt = require('markdown-it'), -* md = new MarkdownIt(); -* var result = md.render('# markdown-it rulezz!'); -* -* // node.js, the same, but with sugar: -* var md = require('markdown-it')(); -* var result = md.render('# markdown-it rulezz!'); -* -* // browser without AMD, added to "window" on script load -* // Note, there are no dash. -* var md = window.markdownit(); -* var result = md.render('# markdown-it rulezz!'); -* ``` -* -* Single line rendering, without paragraph wrap: -* -* ```javascript -* var md = require('markdown-it')(); -* var result = md.renderInline('__markdown-it__ rulezz!'); -* ``` -**/ -/** -* new MarkdownIt([presetName, options]) -* - presetName (String): optional, `commonmark` / `zero` -* - options (Object) -* -* Creates parser instanse with given config. Can be called without `new`. -* -* ##### presetName -* -* MarkdownIt provides named presets as a convenience to quickly -* enable/disable active syntax rules and options for common use cases. -* -* - ["commonmark"](https://github.com/markdown-it/markdown-it/blob/master/lib/presets/commonmark.mjs) - -* configures parser to strict [CommonMark](http://commonmark.org/) mode. -* - [default](https://github.com/markdown-it/markdown-it/blob/master/lib/presets/default.mjs) - -* similar to GFM, used when no preset name given. Enables all available rules, -* but still without html, typographer & autolinker. -* - ["zero"](https://github.com/markdown-it/markdown-it/blob/master/lib/presets/zero.mjs) - -* all rules disabled. Useful to quickly setup your config via `.enable()`. -* For example, when you need only `bold` and `italic` markup and nothing else. -* -* ##### options: -* -* - __html__ - `false`. Set `true` to enable HTML tags in source. Be careful! -* That's not safe! You may need external sanitizer to protect output from XSS. -* It's better to extend features via plugins, instead of enabling HTML. -* - __xhtmlOut__ - `false`. Set `true` to add '/' when closing single tags -* (`
    `). This is needed only for full CommonMark compatibility. In real -* world you will need HTML output. -* - __breaks__ - `false`. Set `true` to convert `\n` in paragraphs into `
    `. -* - __langPrefix__ - `language-`. CSS language class prefix for fenced blocks. -* Can be useful for external highlighters. -* - __linkify__ - `false`. Set `true` to autoconvert URL-like text to links. -* - __typographer__ - `false`. Set `true` to enable [some language-neutral -* replacement](https://github.com/markdown-it/markdown-it/blob/master/lib/rules_core/replacements.mjs) + -* quotes beautification (smartquotes). -* - __quotes__ - `“”‘’`, String or Array. Double + single quotes replacement -* pairs, when typographer enabled and smartquotes on. For example, you can -* use `'«»„“'` for Russian, `'„“‚‘'` for German, and -* `['«\xA0', '\xA0»', '‹\xA0', '\xA0›']` for French (including nbsp). -* - __highlight__ - `null`. Highlighter function for fenced code blocks. -* Highlighter `function (str, lang)` should return escaped HTML. It can also -* return empty string if the source was not changed and should be escaped -* externaly. If result starts with ` or ``): -* -* ```javascript -* var hljs = require('highlight.js') // https://highlightjs.org/ -* -* // Actual default values -* var md = require('markdown-it')({ -* highlight: function (str, lang) { -* if (lang && hljs.getLanguage(lang)) { -* try { -* return '
    ' +
    -*                hljs.highlight(str, { language: lang, ignoreIllegals: true }).value +
    -*                '
    '; -* } catch (__) {} -* } -* -* return '
    ' + md.utils.escapeHtml(str) + '
    '; -* } -* }); -* ``` -* -**/ -function MarkdownIt(presetName, options) { - if (!(this instanceof MarkdownIt)) { - return new MarkdownIt(presetName, options); - } - if (!options) { - if (!isString$1(presetName)) { - options = presetName || {}; - presetName = "default"; - } - } - /** - * MarkdownIt#inline -> ParserInline - * - * Instance of [[ParserInline]]. You may need it to add new rules when - * writing plugins. For simple rules control use [[MarkdownIt.disable]] and - * [[MarkdownIt.enable]]. - **/ - this.inline = new parser_inline_default(); - /** - * MarkdownIt#block -> ParserBlock - * - * Instance of [[ParserBlock]]. You may need it to add new rules when - * writing plugins. For simple rules control use [[MarkdownIt.disable]] and - * [[MarkdownIt.enable]]. - **/ - this.block = new parser_block_default(); - /** - * MarkdownIt#core -> Core - * - * Instance of [[Core]] chain executor. You may need it to add new rules when - * writing plugins. For simple rules control use [[MarkdownIt.disable]] and - * [[MarkdownIt.enable]]. - **/ - this.core = new parser_core_default(); - /** - * MarkdownIt#renderer -> Renderer - * - * Instance of [[Renderer]]. Use it to modify output look. Or to add rendering - * rules for new token types, generated by plugins. - * - * ##### Example - * - * ```javascript - * var md = require('markdown-it')(); - * - * function myToken(tokens, idx, options, env, self) { - * //... - * return result; - * }; - * - * md.renderer.rules['my_token'] = myToken - * ``` - * - * See [[Renderer]] docs and [source code](https://github.com/markdown-it/markdown-it/blob/master/lib/renderer.mjs). - **/ - this.renderer = new renderer_default(); - /** - * MarkdownIt#linkify -> LinkifyIt - * - * [linkify-it](https://github.com/markdown-it/linkify-it) instance. - * Used by [linkify](https://github.com/markdown-it/markdown-it/blob/master/lib/rules_core/linkify.mjs) - * rule. - **/ - this.linkify = new linkify_it_default(); - /** - * MarkdownIt#validateLink(url) -> Boolean - * - * Link validation function. CommonMark allows too much in links. By default - * we disable `javascript:`, `vbscript:`, `file:` schemas, and almost all `data:...` schemas - * except some embedded image types. - * - * You can change this behaviour: - * - * ```javascript - * var md = require('markdown-it')(); - * // enable everything - * md.validateLink = function () { return true; } - * ``` - **/ - this.validateLink = validateLink; - /** - * MarkdownIt#normalizeLink(url) -> String - * - * Function used to encode link url to a machine-readable format, - * which includes url-encoding, punycode, etc. - **/ - this.normalizeLink = normalizeLink; - /** - * MarkdownIt#normalizeLinkText(url) -> String - * - * Function used to decode link url to a human-readable format` - **/ - this.normalizeLinkText = normalizeLinkText; - /** - * MarkdownIt#utils -> utils - * - * Assorted utility functions, useful to write plugins. See details - * [here](https://github.com/markdown-it/markdown-it/blob/master/lib/common/utils.mjs). - **/ - this.utils = utils_exports; - /** - * MarkdownIt#helpers -> helpers - * - * Link components parser functions, useful to write plugins. See details - * [here](https://github.com/markdown-it/markdown-it/blob/master/lib/helpers). - **/ - this.helpers = assign$1({}, helpers_exports); - this.options = {}; - this.configure(presetName); - if (options) { - this.set(options); - } -} -/** chainable -* MarkdownIt.set(options) -* -* Set parser options (in the same format as in constructor). Probably, you -* will never need it, but you can change options after constructor call. -* -* ##### Example -* -* ```javascript -* var md = require('markdown-it')() -* .set({ html: true, breaks: true }) -* .set({ typographer, true }); -* ``` -* -* __Note:__ To achieve the best possible performance, don't modify a -* `markdown-it` instance options on the fly. If you need multiple configurations -* it's best to create multiple instances and initialize each with separate -* config. -**/ -MarkdownIt.prototype.set = function(options) { - assign$1(this.options, options); - return this; -}; -/** chainable, internal -* MarkdownIt.configure(presets) -* -* Batch load of all options and compenent settings. This is internal method, -* and you probably will not need it. But if you will - see available presets -* and data structure [here](https://github.com/markdown-it/markdown-it/tree/master/lib/presets) -* -* We strongly recommend to use presets instead of direct config loads. That -* will give better compatibility with next versions. -**/ -MarkdownIt.prototype.configure = function(presets) { - const self = this; - if (isString$1(presets)) { - const presetName = presets; - presets = config[presetName]; - if (!presets) { - throw new Error("Wrong `markdown-it` preset \"" + presetName + "\", check name"); - } - } - if (!presets) { - throw new Error("Wrong `markdown-it` preset, can't be empty"); - } - if (presets.options) { - self.set(presets.options); - } - if (presets.components) { - Object.keys(presets.components).forEach(function(name) { - if (presets.components[name].rules) { - self[name].ruler.enableOnly(presets.components[name].rules); - } - if (presets.components[name].rules2) { - self[name].ruler2.enableOnly(presets.components[name].rules2); - } - }); - } - return this; -}; -/** chainable -* MarkdownIt.enable(list, ignoreInvalid) -* - list (String|Array): rule name or list of rule names to enable -* - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found. -* -* Enable list or rules. It will automatically find appropriate components, -* containing rules with given names. If rule not found, and `ignoreInvalid` -* not set - throws exception. -* -* ##### Example -* -* ```javascript -* var md = require('markdown-it')() -* .enable(['sub', 'sup']) -* .disable('smartquotes'); -* ``` -**/ -MarkdownIt.prototype.enable = function(list$1, ignoreInvalid) { - let result = []; - if (!Array.isArray(list$1)) { - list$1 = [list$1]; - } - [ - "core", - "block", - "inline" - ].forEach(function(chain) { - result = result.concat(this[chain].ruler.enable(list$1, true)); - }, this); - result = result.concat(this.inline.ruler2.enable(list$1, true)); - const missed = list$1.filter(function(name) { - return result.indexOf(name) < 0; - }); - if (missed.length && !ignoreInvalid) { - throw new Error("MarkdownIt. Failed to enable unknown rule(s): " + missed); - } - return this; -}; -/** chainable -* MarkdownIt.disable(list, ignoreInvalid) -* - list (String|Array): rule name or list of rule names to disable. -* - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found. -* -* The same as [[MarkdownIt.enable]], but turn specified rules off. -**/ -MarkdownIt.prototype.disable = function(list$1, ignoreInvalid) { - let result = []; - if (!Array.isArray(list$1)) { - list$1 = [list$1]; - } - [ - "core", - "block", - "inline" - ].forEach(function(chain) { - result = result.concat(this[chain].ruler.disable(list$1, true)); - }, this); - result = result.concat(this.inline.ruler2.disable(list$1, true)); - const missed = list$1.filter(function(name) { - return result.indexOf(name) < 0; - }); - if (missed.length && !ignoreInvalid) { - throw new Error("MarkdownIt. Failed to disable unknown rule(s): " + missed); - } - return this; -}; -/** chainable -* MarkdownIt.use(plugin, params) -* -* Load specified plugin with given params into current parser instance. -* It's just a sugar to call `plugin(md, params)` with curring. -* -* ##### Example -* -* ```javascript -* var iterator = require('markdown-it-for-inline'); -* var md = require('markdown-it')() -* .use(iterator, 'foo_replace', 'text', function (tokens, idx) { -* tokens[idx].content = tokens[idx].content.replace(/foo/g, 'bar'); -* }); -* ``` -**/ -MarkdownIt.prototype.use = function(plugin) { - const args = [this].concat(Array.prototype.slice.call(arguments, 1)); - plugin.apply(plugin, args); - return this; -}; -/** internal -* MarkdownIt.parse(src, env) -> Array -* - src (String): source string -* - env (Object): environment sandbox -* -* Parse input string and return list of block tokens (special token type -* "inline" will contain list of inline tokens). You should not call this -* method directly, until you write custom renderer (for example, to produce -* AST). -* -* `env` is used to pass data between "distributed" rules and return additional -* metadata like reference info, needed for the renderer. It also can be used to -* inject data in specific cases. Usually, you will be ok to pass `{}`, -* and then pass updated object to renderer. -**/ -MarkdownIt.prototype.parse = function(src, env) { - if (typeof src !== "string") { - throw new Error("Input data should be a String"); - } - const state = new this.core.State(src, this, env); - this.core.process(state); - return state.tokens; -}; -/** -* MarkdownIt.render(src [, env]) -> String -* - src (String): source string -* - env (Object): environment sandbox -* -* Render markdown string into html. It does all magic for you :). -* -* `env` can be used to inject additional metadata (`{}` by default). -* But you will not need it with high probability. See also comment -* in [[MarkdownIt.parse]]. -**/ -MarkdownIt.prototype.render = function(src, env) { - env = env || {}; - return this.renderer.render(this.parse(src, env), this.options, env); -}; -/** internal -* MarkdownIt.parseInline(src, env) -> Array -* - src (String): source string -* - env (Object): environment sandbox -* -* The same as [[MarkdownIt.parse]] but skip all block rules. It returns the -* block tokens list with the single `inline` element, containing parsed inline -* tokens in `children` property. Also updates `env` object. -**/ -MarkdownIt.prototype.parseInline = function(src, env) { - const state = new this.core.State(src, this, env); - state.inlineMode = true; - this.core.process(state); - return state.tokens; -}; -/** -* MarkdownIt.renderInline(src [, env]) -> String -* - src (String): source string -* - env (Object): environment sandbox -* -* Similar to [[MarkdownIt.render]] but for single paragraph content. Result -* will NOT be wrapped into `

    ` tags. -**/ -MarkdownIt.prototype.renderInline = function(src, env) { - env = env || {}; - return this.renderer.render(this.parseInline(src, env), this.options, env); -}; -var lib_default = MarkdownIt; - -/** -* This is only safe for (and intended to be used for) text node positions. If -* you are using attribute position, then this is only safe if the attribute -* value is surrounded by double-quotes, and is unsafe otherwise (because the -* value could break out of the attribute value and e.g. add another attribute). -*/ -function escapeNodeText(str) { - const frag = document.createElement("div"); - D(b`${str}`, frag); - return frag.innerHTML.replaceAll(//gim, ""); -} -function unescapeNodeText(str) { - if (!str) { - return ""; - } - const frag = document.createElement("textarea"); - frag.innerHTML = str; - return frag.value; -} - -var MarkdownDirective = class extends i$5 { - #markdownIt = lib_default({ highlight: (str, lang) => { - switch (lang) { - case "html": { - const iframe = document.createElement("iframe"); - iframe.classList.add("html-view"); - iframe.srcdoc = str; - iframe.sandbox = ""; - return iframe.innerHTML; - } - default: return escapeNodeText(str); - } - } }); - #lastValue = null; - #lastTagClassMap = null; - update(_part, [value, tagClassMap]) { - if (this.#lastValue === value && JSON.stringify(tagClassMap) === this.#lastTagClassMap) { - return E; - } - this.#lastValue = value; - this.#lastTagClassMap = JSON.stringify(tagClassMap); - return this.render(value, tagClassMap); - } - #originalClassMap = new Map(); - #applyTagClassMap(tagClassMap) { - Object.entries(tagClassMap).forEach(([tag]) => { - let tokenName; - switch (tag) { - case "p": - tokenName = "paragraph"; - break; - case "h1": - case "h2": - case "h3": - case "h4": - case "h5": - case "h6": - tokenName = "heading"; - break; - case "ul": - tokenName = "bullet_list"; - break; - case "ol": - tokenName = "ordered_list"; - break; - case "li": - tokenName = "list_item"; - break; - case "a": - tokenName = "link"; - break; - case "strong": - tokenName = "strong"; - break; - case "em": - tokenName = "em"; - break; - } - if (!tokenName) { - return; - } - const key = `${tokenName}_open`; - this.#markdownIt.renderer.rules[key] = (tokens, idx, options, _env, self) => { - const token = tokens[idx]; - const tokenClasses = tagClassMap[token.tag] ?? []; - for (const clazz of tokenClasses) { - token.attrJoin("class", clazz); - } - return self.renderToken(tokens, idx, options); - }; - }); - } - #unapplyTagClassMap() { - for (const [key] of this.#originalClassMap) { - delete this.#markdownIt.renderer.rules[key]; - } - this.#originalClassMap.clear(); - } - /** - * Renders the markdown string to HTML using MarkdownIt. - * - * Note: MarkdownIt doesn't enable HTML in its output, so we render the - * value directly without further sanitization. - * @see https://github.com/markdown-it/markdown-it/blob/master/docs/security.md - */ - render(value, tagClassMap) { - if (tagClassMap) { - this.#applyTagClassMap(tagClassMap); - } - const htmlString = this.#markdownIt.render(value); - this.#unapplyTagClassMap(); - return o(htmlString); - } -}; -const markdown = e$10(MarkdownDirective); -const markdownItStandalone = lib_default(); -function renderMarkdownToHtmlString(value) { - return markdownItStandalone.render(value); -} - -var __esDecorate$1 = void 0 && (void 0).__esDecorate || function(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) { - function accept(f$4) { - if (f$4 !== void 0 && typeof f$4 !== "function") throw new TypeError("Function expected"); - return f$4; - } - var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value"; - var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null; - var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {}); - var _$1, done = false; - for (var i$10 = decorators.length - 1; i$10 >= 0; i$10--) { - var context = {}; - for (var p$3 in contextIn) context[p$3] = p$3 === "access" ? {} : contextIn[p$3]; - for (var p$3 in contextIn.access) context.access[p$3] = contextIn.access[p$3]; - context.addInitializer = function(f$4) { - if (done) throw new TypeError("Cannot add initializers after decoration has completed"); - extraInitializers.push(accept(f$4 || null)); - }; - var result = (0, decorators[i$10])(kind === "accessor" ? { - get: descriptor.get, - set: descriptor.set - } : descriptor[key], context); - if (kind === "accessor") { - if (result === void 0) continue; - if (result === null || typeof result !== "object") throw new TypeError("Object expected"); - if (_$1 = accept(result.get)) descriptor.get = _$1; - if (_$1 = accept(result.set)) descriptor.set = _$1; - if (_$1 = accept(result.init)) initializers.unshift(_$1); - } else if (_$1 = accept(result)) { - if (kind === "field") initializers.unshift(_$1); - else descriptor[key] = _$1; - } - } - if (target) Object.defineProperty(target, contextIn.name, descriptor); - done = true; -}; -var __runInitializers$1 = void 0 && (void 0).__runInitializers || function(thisArg, initializers, value) { - var useValue = arguments.length > 2; - for (var i$10 = 0; i$10 < initializers.length; i$10++) { - value = useValue ? initializers[i$10].call(thisArg, value) : initializers[i$10].call(thisArg); - } - return useValue ? value : void 0; -}; -let Text = (() => { - let _classDecorators = [t$1("a2ui-text")]; - let _classDescriptor; - let _classExtraInitializers = []; - let _classThis; - let _classSuper = Root; - let _text_decorators; - let _text_initializers = []; - let _text_extraInitializers = []; - let _usageHint_decorators; - let _usageHint_initializers = []; - let _usageHint_extraInitializers = []; - var Text = class extends _classSuper { - static { - _classThis = this; - } - static { - const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0; - _text_decorators = [n$6()]; - _usageHint_decorators = [n$6({ - reflect: true, - attribute: "usage-hint" - })]; - __esDecorate$1(this, null, _text_decorators, { - kind: "accessor", - name: "text", - static: false, - private: false, - access: { - has: (obj) => "text" in obj, - get: (obj) => obj.text, - set: (obj, value) => { - obj.text = value; - } - }, - metadata: _metadata - }, _text_initializers, _text_extraInitializers); - __esDecorate$1(this, null, _usageHint_decorators, { - kind: "accessor", - name: "usageHint", - static: false, - private: false, - access: { - has: (obj) => "usageHint" in obj, - get: (obj) => obj.usageHint, - set: (obj, value) => { - obj.usageHint = value; - } - }, - metadata: _metadata - }, _usageHint_initializers, _usageHint_extraInitializers); - __esDecorate$1(null, _classDescriptor = { value: _classThis }, _classDecorators, { - kind: "class", - name: _classThis.name, - metadata: _metadata - }, null, _classExtraInitializers); - Text = _classThis = _classDescriptor.value; - if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { - enumerable: true, - configurable: true, - writable: true, - value: _metadata - }); - } - #text_accessor_storage = __runInitializers$1(this, _text_initializers, null); - get text() { - return this.#text_accessor_storage; - } - set text(value) { - this.#text_accessor_storage = value; - } - #usageHint_accessor_storage = (__runInitializers$1(this, _text_extraInitializers), __runInitializers$1(this, _usageHint_initializers, null)); - get usageHint() { - return this.#usageHint_accessor_storage; - } - set usageHint(value) { - this.#usageHint_accessor_storage = value; - } - static { - this.styles = [structuralStyles, i$9` - :host { - display: block; - flex: var(--weight); - } - - h1, - h2, - h3, - h4, - h5 { - line-height: inherit; - font: inherit; - } - `]; - } - #renderText() { - let textValue = null; - if (this.text && typeof this.text === "object") { - if ("literalString" in this.text && this.text.literalString) { - textValue = this.text.literalString; - } else if ("literal" in this.text && this.text.literal !== undefined) { - textValue = this.text.literal; - } else if (this.text && "path" in this.text && this.text.path) { - if (!this.processor || !this.component) { - return b`(no model)`; - } - const value = this.processor.getData(this.component, this.text.path, this.surfaceId ?? A2uiMessageProcessor.DEFAULT_SURFACE_ID); - if (value !== null && value !== undefined) { - textValue = value.toString(); - } - } - } - if (textValue === null || textValue === undefined) { - return b`(empty)`; - } - let markdownText = textValue; - switch (this.usageHint) { - case "h1": - markdownText = `# ${markdownText}`; - break; - case "h2": - markdownText = `## ${markdownText}`; - break; - case "h3": - markdownText = `### ${markdownText}`; - break; - case "h4": - markdownText = `#### ${markdownText}`; - break; - case "h5": - markdownText = `##### ${markdownText}`; - break; - case "caption": - markdownText = `*${markdownText}*`; - break; - default: break; - } - return b`${markdown(markdownText, appendToAll(this.theme.markdown, [ - "ol", - "ul", - "li" - ], {}))}`; - } - #areHintedStyles(styles) { - if (typeof styles !== "object") return false; - if (Array.isArray(styles)) return false; - if (!styles) return false; - const expected = [ - "h1", - "h2", - "h3", - "h4", - "h5", - "h6", - "caption", - "body" - ]; - return expected.every((v$2) => v$2 in styles); - } - #getAdditionalStyles() { - let additionalStyles = {}; - const styles = this.theme.additionalStyles?.Text; - if (!styles) return additionalStyles; - if (this.#areHintedStyles(styles)) { - const hint = this.usageHint ?? "body"; - additionalStyles = styles[hint]; - } else { - additionalStyles = styles; - } - return additionalStyles; - } - render() { - const classes = merge(this.theme.components.Text.all, this.usageHint ? this.theme.components.Text[this.usageHint] : {}); - return b`

    - ${this.#renderText()} -
    `; - } - constructor() { - super(...arguments); - __runInitializers$1(this, _usageHint_extraInitializers); - } - static { - __runInitializers$1(_classThis, _classExtraInitializers); - } - }; - return Text = _classThis; -})(); - -var __esDecorate = void 0 && (void 0).__esDecorate || function(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) { - function accept(f$4) { - if (f$4 !== void 0 && typeof f$4 !== "function") throw new TypeError("Function expected"); - return f$4; - } - var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value"; - var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null; - var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {}); - var _$1, done = false; - for (var i$10 = decorators.length - 1; i$10 >= 0; i$10--) { - var context = {}; - for (var p$3 in contextIn) context[p$3] = p$3 === "access" ? {} : contextIn[p$3]; - for (var p$3 in contextIn.access) context.access[p$3] = contextIn.access[p$3]; - context.addInitializer = function(f$4) { - if (done) throw new TypeError("Cannot add initializers after decoration has completed"); - extraInitializers.push(accept(f$4 || null)); - }; - var result = (0, decorators[i$10])(kind === "accessor" ? { - get: descriptor.get, - set: descriptor.set - } : descriptor[key], context); - if (kind === "accessor") { - if (result === void 0) continue; - if (result === null || typeof result !== "object") throw new TypeError("Object expected"); - if (_$1 = accept(result.get)) descriptor.get = _$1; - if (_$1 = accept(result.set)) descriptor.set = _$1; - if (_$1 = accept(result.init)) initializers.unshift(_$1); - } else if (_$1 = accept(result)) { - if (kind === "field") initializers.unshift(_$1); - else descriptor[key] = _$1; - } - } - if (target) Object.defineProperty(target, contextIn.name, descriptor); - done = true; -}; -var __runInitializers = void 0 && (void 0).__runInitializers || function(thisArg, initializers, value) { - var useValue = arguments.length > 2; - for (var i$10 = 0; i$10 < initializers.length; i$10++) { - value = useValue ? initializers[i$10].call(thisArg, value) : initializers[i$10].call(thisArg); - } - return useValue ? value : void 0; -}; -let Video = (() => { - let _classDecorators = [t$1("a2ui-video")]; - let _classDescriptor; - let _classExtraInitializers = []; - let _classThis; - let _classSuper = Root; - let _url_decorators; - let _url_initializers = []; - let _url_extraInitializers = []; - var Video = class extends _classSuper { - static { - _classThis = this; - } - static { - const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0; - _url_decorators = [n$6()]; - __esDecorate(this, null, _url_decorators, { - kind: "accessor", - name: "url", - static: false, - private: false, - access: { - has: (obj) => "url" in obj, - get: (obj) => obj.url, - set: (obj, value) => { - obj.url = value; - } - }, - metadata: _metadata - }, _url_initializers, _url_extraInitializers); - __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { - kind: "class", - name: _classThis.name, - metadata: _metadata - }, null, _classExtraInitializers); - Video = _classThis = _classDescriptor.value; - if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { - enumerable: true, - configurable: true, - writable: true, - value: _metadata - }); - } - #url_accessor_storage = __runInitializers(this, _url_initializers, null); - get url() { - return this.#url_accessor_storage; - } - set url(value) { - this.#url_accessor_storage = value; - } - static { - this.styles = [structuralStyles, i$9` - * { - box-sizing: border-box; - } - - :host { - display: block; - flex: var(--weight); - min-height: 0; - overflow: auto; - } - - video { - display: block; - width: 100%; - } - `]; - } - #renderVideo() { - if (!this.url) { - return A; - } - if (this.url && typeof this.url === "object") { - if ("literalString" in this.url) { - return b`