@haseebuchiha/silvr 2026.3.20 → 2026.3.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build-info.json +3 -3
- package/dist/canvas-host/a2ui/.bundle.hash +1 -1
- package/dist/control-ui/assets/{agents-koDAA2JN.js → agents-CRGOH5CC.js} +2 -2
- package/dist/control-ui/assets/{agents-koDAA2JN.js.map → agents-CRGOH5CC.js.map} +1 -1
- package/dist/control-ui/assets/{channels-CH1TfFn-.js → channels-CtcAfpMH.js} +2 -2
- package/dist/control-ui/assets/{channels-CH1TfFn-.js.map → channels-CtcAfpMH.js.map} +1 -1
- package/dist/control-ui/assets/{cron-SRhGYXwl.js → cron-B6kPzumc.js} +2 -2
- package/dist/control-ui/assets/{cron-SRhGYXwl.js.map → cron-B6kPzumc.js.map} +1 -1
- package/dist/control-ui/assets/{debug-DHAgRpkQ.js → debug-Bh_xMppa.js} +2 -2
- package/dist/control-ui/assets/{debug-DHAgRpkQ.js.map → debug-Bh_xMppa.js.map} +1 -1
- package/dist/control-ui/assets/index-Cl_cokMI.css +1 -0
- package/dist/control-ui/assets/{index-5bbJdGkA.js → index-UVvtebBp.js} +3 -3
- package/dist/control-ui/assets/{index-5bbJdGkA.js.map → index-UVvtebBp.js.map} +1 -1
- package/dist/control-ui/assets/{instances-BNHf94QX.js → instances-hORRbm4_.js} +2 -2
- package/dist/control-ui/assets/{instances-BNHf94QX.js.map → instances-hORRbm4_.js.map} +1 -1
- package/dist/control-ui/assets/{sessions-CJXulDV_.js → sessions-CD0lX6kk.js} +2 -2
- package/dist/control-ui/assets/{sessions-CJXulDV_.js.map → sessions-CD0lX6kk.js.map} +1 -1
- package/dist/control-ui/index.html +2 -2
- package/package.json +1 -1
- package/dist/control-ui/assets/index-0HMsCpxg.css +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channels-CH1TfFn-.js","names":[],"sources":["../../../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.ts","../../../ui/src/ui/views/channels.shared.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"],"sourcesContent":["import { html } from \"lit\";\nimport type { ConfigUiHints } from \"../types.ts\";\nimport { formatChannelExtraValue, resolveChannelConfigValue } from \"./channel-config-extras.ts\";\nimport type { ChannelsProps } from \"./channels.types.ts\";\nimport { analyzeConfigSchema, renderNode, schemaType, type JsonSchema } from \"./config-form.ts\";\n\ntype ChannelConfigFormProps = {\n channelId: string;\n configValue: Record<string, unknown> | null;\n schema: unknown;\n uiHints: ConfigUiHints;\n disabled: boolean;\n onPatch: (path: Array<string | number>, value: unknown) => void;\n};\n\nfunction resolveSchemaNode(\n schema: JsonSchema | null,\n path: Array<string | number>,\n): JsonSchema | null {\n let current = schema;\n for (const key of path) {\n if (!current) {\n return null;\n }\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;\n continue;\n }\n return null;\n }\n if (type === \"array\") {\n if (typeof key !== \"number\") {\n return null;\n }\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<string, unknown>,\n channelId: string,\n): Record<string, unknown> {\n return resolveChannelConfigValue(config, channelId) ?? {};\n}\n\nconst EXTRA_CHANNEL_FIELDS = [\"groupPolicy\", \"streamMode\", \"dmPolicy\"] as const;\n\nfunction renderExtraChannelFields(value: Record<string, unknown>) {\n const entries = EXTRA_CHANNEL_FIELDS.flatMap((field) => {\n if (!(field in value)) {\n return [];\n }\n return [[field, value[field]]] as Array<[string, unknown]>;\n });\n if (entries.length === 0) {\n return null;\n }\n return html`\n <div class=\"status-list\" style=\"margin-top: 12px;\">\n ${entries.map(\n ([field, raw]) => html`\n <div>\n <span class=\"label\">${field}</span>\n <span>${formatChannelExtraValue(raw)}</span>\n </div>\n `,\n )}\n </div>\n `;\n}\n\nexport function renderChannelConfigForm(props: ChannelConfigFormProps) {\n const analysis = analyzeConfigSchema(props.schema);\n const normalized = analysis.schema;\n if (!normalized) {\n return html`\n <div class=\"callout danger\">Schema unavailable. Use Raw.</div>\n `;\n }\n const node = resolveSchemaNode(normalized, [\"channels\", props.channelId]);\n if (!node) {\n return html`\n <div class=\"callout danger\">Channel config schema unavailable.</div>\n `;\n }\n const configValue = props.configValue ?? {};\n const value = resolveChannelValue(configValue, props.channelId);\n return html`\n <div class=\"config-form\">\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 </div>\n ${renderExtraChannelFields(value)}\n `;\n}\n\nexport function renderChannelConfigSection(params: { channelId: string; props: ChannelsProps }) {\n const { channelId, props } = params;\n const disabled = props.configSaving || props.configSchemaLoading;\n return html`\n <div style=\"margin-top: 16px;\">\n ${\n props.configSchemaLoading\n ? html`\n <div class=\"muted\">Loading config schema…</div>\n `\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 <div class=\"row\" style=\"margin-top: 12px;\">\n <button\n class=\"btn primary\"\n ?disabled=${disabled || !props.configFormDirty}\n @click=${() => props.onConfigSave()}\n >\n ${props.configSaving ? \"Saving…\" : \"Save\"}\n </button>\n <button\n class=\"btn\"\n ?disabled=${disabled}\n @click=${() => props.onConfigReload()}\n >\n Reload\n </button>\n </div>\n </div>\n `;\n}\n","import { html, nothing } from \"lit\";\nimport { formatRelativeTimestamp } from \"../format.ts\";\nimport type { DiscordStatus } from \"../types.ts\";\nimport { renderChannelConfigSection } from \"./channels.config.ts\";\nimport type { ChannelsProps } from \"./channels.types.ts\";\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 <div class=\"card\">\n <div class=\"card-title\">Discord</div>\n <div class=\"card-sub\">Bot status and channel configuration.</div>\n ${accountCountLabel}\n\n <div class=\"status-list\" style=\"margin-top: 16px;\">\n <div>\n <span class=\"label\">Configured</span>\n <span>${discord?.configured ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Running</span>\n <span>${discord?.running ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Last start</span>\n <span>${discord?.lastStartAt ? formatRelativeTimestamp(discord.lastStartAt) : \"n/a\"}</span>\n </div>\n <div>\n <span class=\"label\">Last probe</span>\n <span>${discord?.lastProbeAt ? formatRelativeTimestamp(discord.lastProbeAt) : \"n/a\"}</span>\n </div>\n </div>\n\n ${\n discord?.lastError\n ? html`<div class=\"callout danger\" style=\"margin-top: 12px;\">\n ${discord.lastError}\n </div>`\n : nothing\n }\n\n ${\n discord?.probe\n ? html`<div class=\"callout\" style=\"margin-top: 12px;\">\n Probe ${discord.probe.ok ? \"ok\" : \"failed\"} ·\n ${discord.probe.status ?? \"\"} ${discord.probe.error ?? \"\"}\n </div>`\n : nothing\n }\n\n ${renderChannelConfigSection({ channelId: \"discord\", props })}\n\n <div class=\"row\" style=\"margin-top: 12px;\">\n <button class=\"btn\" @click=${() => props.onRefresh(true)}>\n Probe\n </button>\n </div>\n </div>\n `;\n}\n","import { html, nothing } from \"lit\";\nimport { formatRelativeTimestamp } from \"../format.ts\";\nimport type { GoogleChatStatus } from \"../types.ts\";\nimport { renderChannelConfigSection } from \"./channels.config.ts\";\nimport type { ChannelsProps } from \"./channels.types.ts\";\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 <div class=\"card\">\n <div class=\"card-title\">Google Chat</div>\n <div class=\"card-sub\">Chat API webhook status and channel configuration.</div>\n ${accountCountLabel}\n\n <div class=\"status-list\" style=\"margin-top: 16px;\">\n <div>\n <span class=\"label\">Configured</span>\n <span>${googleChat ? (googleChat.configured ? \"Yes\" : \"No\") : \"n/a\"}</span>\n </div>\n <div>\n <span class=\"label\">Running</span>\n <span>${googleChat ? (googleChat.running ? \"Yes\" : \"No\") : \"n/a\"}</span>\n </div>\n <div>\n <span class=\"label\">Credential</span>\n <span>${googleChat?.credentialSource ?? \"n/a\"}</span>\n </div>\n <div>\n <span class=\"label\">Audience</span>\n <span>\n ${\n googleChat?.audienceType\n ? `${googleChat.audienceType}${googleChat.audience ? ` · ${googleChat.audience}` : \"\"}`\n : \"n/a\"\n }\n </span>\n </div>\n <div>\n <span class=\"label\">Last start</span>\n <span>${googleChat?.lastStartAt ? formatRelativeTimestamp(googleChat.lastStartAt) : \"n/a\"}</span>\n </div>\n <div>\n <span class=\"label\">Last probe</span>\n <span>${googleChat?.lastProbeAt ? formatRelativeTimestamp(googleChat.lastProbeAt) : \"n/a\"}</span>\n </div>\n </div>\n\n ${\n googleChat?.lastError\n ? html`<div class=\"callout danger\" style=\"margin-top: 12px;\">\n ${googleChat.lastError}\n </div>`\n : nothing\n }\n\n ${\n googleChat?.probe\n ? html`<div class=\"callout\" style=\"margin-top: 12px;\">\n Probe ${googleChat.probe.ok ? \"ok\" : \"failed\"} ·\n ${googleChat.probe.status ?? \"\"} ${googleChat.probe.error ?? \"\"}\n </div>`\n : nothing\n }\n\n ${renderChannelConfigSection({ channelId: \"googlechat\", props })}\n\n <div class=\"row\" style=\"margin-top: 12px;\">\n <button class=\"btn\" @click=${() => props.onRefresh(true)}>\n Probe\n </button>\n </div>\n </div>\n `;\n}\n","import { html, nothing } from \"lit\";\nimport { formatRelativeTimestamp } from \"../format.ts\";\nimport type { IMessageStatus } from \"../types.ts\";\nimport { renderChannelConfigSection } from \"./channels.config.ts\";\nimport type { ChannelsProps } from \"./channels.types.ts\";\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 <div class=\"card\">\n <div class=\"card-title\">iMessage</div>\n <div class=\"card-sub\">macOS bridge status and channel configuration.</div>\n ${accountCountLabel}\n\n <div class=\"status-list\" style=\"margin-top: 16px;\">\n <div>\n <span class=\"label\">Configured</span>\n <span>${imessage?.configured ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Running</span>\n <span>${imessage?.running ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Last start</span>\n <span>${imessage?.lastStartAt ? formatRelativeTimestamp(imessage.lastStartAt) : \"n/a\"}</span>\n </div>\n <div>\n <span class=\"label\">Last probe</span>\n <span>${imessage?.lastProbeAt ? formatRelativeTimestamp(imessage.lastProbeAt) : \"n/a\"}</span>\n </div>\n </div>\n\n ${\n imessage?.lastError\n ? html`<div class=\"callout danger\" style=\"margin-top: 12px;\">\n ${imessage.lastError}\n </div>`\n : nothing\n }\n\n ${\n imessage?.probe\n ? html`<div class=\"callout\" style=\"margin-top: 12px;\">\n Probe ${imessage.probe.ok ? \"ok\" : \"failed\"} ·\n ${imessage.probe.error ?? \"\"}\n </div>`\n : nothing\n }\n\n ${renderChannelConfigSection({ channelId: \"imessage\", props })}\n\n <div class=\"row\" style=\"margin-top: 12px;\">\n <button class=\"btn\" @click=${() => props.onRefresh(true)}>\n Probe\n </button>\n </div>\n </div>\n `;\n}\n","import { html, nothing } from \"lit\";\nimport { formatRelativeTimestamp } from \"../format.ts\";\nimport type { ChannelAccountSnapshot, NostrStatus } from \"../types.ts\";\nimport { renderChannelConfigSection } from \"./channels.config.ts\";\nimport {\n renderNostrProfileForm,\n type NostrProfileFormState,\n type NostrProfileFormCallbacks,\n} from \"./channels.nostr-profile-form.ts\";\nimport type { ChannelsProps } from \"./channels.types.ts\";\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) {\n return \"n/a\";\n }\n if (pubkey.length <= 20) {\n return pubkey;\n }\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 ?? (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 <div class=\"account-card\">\n <div class=\"account-card-header\">\n <div class=\"account-card-title\">${displayName}</div>\n <div class=\"account-card-id\">${account.accountId}</div>\n </div>\n <div class=\"status-list account-card-status\">\n <div>\n <span class=\"label\">Running</span>\n <span>${account.running ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Configured</span>\n <span>${account.configured ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Public Key</span>\n <span class=\"monospace\" title=\"${publicKey ?? \"\"}\">${truncatePubkey(publicKey)}</span>\n </div>\n <div>\n <span class=\"label\">Last inbound</span>\n <span>${account.lastInboundAt ? formatRelativeTimestamp(account.lastInboundAt) : \"n/a\"}</span>\n </div>\n ${\n account.lastError\n ? html`\n <div class=\"account-card-error\">${account.lastError}</div>\n `\n : nothing\n }\n </div>\n </div>\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 (\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\n )?.profile ?? nostr?.profile;\n const { name, displayName, about, picture, nip05 } = profile ?? {};\n const hasAnyProfileData = name || displayName || about || picture || nip05;\n\n return html`\n <div style=\"margin-top: 16px; padding: 12px; background: var(--bg-secondary); border-radius: 8px;\">\n <div style=\"display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;\">\n <div style=\"font-weight: 500;\">Profile</div>\n ${\n summaryConfigured\n ? html`\n <button\n class=\"btn btn-sm\"\n @click=${onEditProfile}\n style=\"font-size: 12px; padding: 4px 8px;\"\n >\n Edit Profile\n </button>\n `\n : nothing\n }\n </div>\n ${\n hasAnyProfileData\n ? html`\n <div class=\"status-list\">\n ${\n picture\n ? html`\n <div style=\"margin-bottom: 8px;\">\n <img\n src=${picture}\n alt=\"Profile picture\"\n style=\"width: 48px; height: 48px; border-radius: 50%; object-fit: cover; border: 2px solid var(--border-color);\"\n @error=${(e: Event) => {\n (e.target as HTMLImageElement).style.display = \"none\";\n }}\n />\n </div>\n `\n : nothing\n }\n ${name ? html`<div><span class=\"label\">Name</span><span>${name}</span></div>` : nothing}\n ${\n displayName\n ? html`<div><span class=\"label\">Display Name</span><span>${displayName}</span></div>`\n : nothing\n }\n ${\n about\n ? html`<div><span class=\"label\">About</span><span style=\"max-width: 300px; overflow: hidden; text-overflow: ellipsis;\">${about}</span></div>`\n : nothing\n }\n ${nip05 ? html`<div><span class=\"label\">NIP-05</span><span>${nip05}</span></div>` : nothing}\n </div>\n `\n : html`\n <div style=\"color: var(--text-muted); font-size: 13px\">\n No profile set. Click \"Edit Profile\" to add your name, bio, and avatar.\n </div>\n `\n }\n </div>\n `;\n };\n\n return html`\n <div class=\"card\">\n <div class=\"card-title\">Nostr</div>\n <div class=\"card-sub\">Decentralized DMs via Nostr relays (NIP-04).</div>\n ${accountCountLabel}\n\n ${\n hasMultipleAccounts\n ? html`\n <div class=\"account-card-list\">\n ${nostrAccounts.map((account) => renderAccountCard(account))}\n </div>\n `\n : html`\n <div class=\"status-list\" style=\"margin-top: 16px;\">\n <div>\n <span class=\"label\">Configured</span>\n <span>${summaryConfigured ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Running</span>\n <span>${summaryRunning ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Public Key</span>\n <span class=\"monospace\" title=\"${summaryPublicKey ?? \"\"}\"\n >${truncatePubkey(summaryPublicKey)}</span\n >\n </div>\n <div>\n <span class=\"label\">Last start</span>\n <span>${summaryLastStartAt ? formatRelativeTimestamp(summaryLastStartAt) : \"n/a\"}</span>\n </div>\n </div>\n `\n }\n\n ${\n summaryLastError\n ? html`<div class=\"callout danger\" style=\"margin-top: 12px;\">${summaryLastError}</div>`\n : nothing\n }\n\n ${renderProfileSection()}\n\n ${renderChannelConfigSection({ channelId: \"nostr\", props })}\n\n <div class=\"row\" style=\"margin-top: 12px;\">\n <button class=\"btn\" @click=${() => props.onRefresh(false)}>Refresh</button>\n </div>\n </div>\n `;\n}\n","import { html, nothing } from \"lit\";\nimport type { ChannelAccountSnapshot } from \"../types.ts\";\nimport type { ChannelKey, ChannelsProps } from \"./channels.types.ts\";\n\nexport function channelEnabled(key: ChannelKey, props: ChannelsProps) {\n const snapshot = props.snapshot;\n const channels = snapshot?.channels as Record<string, unknown> | null;\n if (!snapshot || !channels) {\n return false;\n }\n const channelStatus = channels[key] as Record<string, unknown> | 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<string, ChannelAccountSnapshot[]> | null,\n): number {\n return channelAccounts?.[key]?.length ?? 0;\n}\n\nexport function renderChannelAccountCount(\n key: ChannelKey,\n channelAccounts?: Record<string, ChannelAccountSnapshot[]> | null,\n) {\n const count = getChannelAccountCount(key, channelAccounts);\n if (count < 2) {\n return nothing;\n }\n return html`<div class=\"account-count\">Accounts (${count})</div>`;\n}\n","import { html, nothing } from \"lit\";\nimport { formatRelativeTimestamp } from \"../format.ts\";\nimport type { SignalStatus } from \"../types.ts\";\nimport { renderChannelConfigSection } from \"./channels.config.ts\";\nimport type { ChannelsProps } from \"./channels.types.ts\";\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 <div class=\"card\">\n <div class=\"card-title\">Signal</div>\n <div class=\"card-sub\">signal-cli status and channel configuration.</div>\n ${accountCountLabel}\n\n <div class=\"status-list\" style=\"margin-top: 16px;\">\n <div>\n <span class=\"label\">Configured</span>\n <span>${signal?.configured ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Running</span>\n <span>${signal?.running ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Base URL</span>\n <span>${signal?.baseUrl ?? \"n/a\"}</span>\n </div>\n <div>\n <span class=\"label\">Last start</span>\n <span>${signal?.lastStartAt ? formatRelativeTimestamp(signal.lastStartAt) : \"n/a\"}</span>\n </div>\n <div>\n <span class=\"label\">Last probe</span>\n <span>${signal?.lastProbeAt ? formatRelativeTimestamp(signal.lastProbeAt) : \"n/a\"}</span>\n </div>\n </div>\n\n ${\n signal?.lastError\n ? html`<div class=\"callout danger\" style=\"margin-top: 12px;\">\n ${signal.lastError}\n </div>`\n : nothing\n }\n\n ${\n signal?.probe\n ? html`<div class=\"callout\" style=\"margin-top: 12px;\">\n Probe ${signal.probe.ok ? \"ok\" : \"failed\"} ·\n ${signal.probe.status ?? \"\"} ${signal.probe.error ?? \"\"}\n </div>`\n : nothing\n }\n\n ${renderChannelConfigSection({ channelId: \"signal\", props })}\n\n <div class=\"row\" style=\"margin-top: 12px;\">\n <button class=\"btn\" @click=${() => props.onRefresh(true)}>\n Probe\n </button>\n </div>\n </div>\n `;\n}\n","import { html, nothing } from \"lit\";\nimport { formatRelativeTimestamp } from \"../format.ts\";\nimport type { SlackStatus } from \"../types.ts\";\nimport { renderChannelConfigSection } from \"./channels.config.ts\";\nimport type { ChannelsProps } from \"./channels.types.ts\";\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 <div class=\"card\">\n <div class=\"card-title\">Slack</div>\n <div class=\"card-sub\">Socket mode status and channel configuration.</div>\n ${accountCountLabel}\n\n <div class=\"status-list\" style=\"margin-top: 16px;\">\n <div>\n <span class=\"label\">Configured</span>\n <span>${slack?.configured ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Running</span>\n <span>${slack?.running ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Last start</span>\n <span>${slack?.lastStartAt ? formatRelativeTimestamp(slack.lastStartAt) : \"n/a\"}</span>\n </div>\n <div>\n <span class=\"label\">Last probe</span>\n <span>${slack?.lastProbeAt ? formatRelativeTimestamp(slack.lastProbeAt) : \"n/a\"}</span>\n </div>\n </div>\n\n ${\n slack?.lastError\n ? html`<div class=\"callout danger\" style=\"margin-top: 12px;\">\n ${slack.lastError}\n </div>`\n : nothing\n }\n\n ${\n slack?.probe\n ? html`<div class=\"callout\" style=\"margin-top: 12px;\">\n Probe ${slack.probe.ok ? \"ok\" : \"failed\"} ·\n ${slack.probe.status ?? \"\"} ${slack.probe.error ?? \"\"}\n </div>`\n : nothing\n }\n\n ${renderChannelConfigSection({ channelId: \"slack\", props })}\n\n <div class=\"row\" style=\"margin-top: 12px;\">\n <button class=\"btn\" @click=${() => props.onRefresh(true)}>\n Probe\n </button>\n </div>\n </div>\n `;\n}\n","import { html, nothing } from \"lit\";\nimport { formatRelativeTimestamp } from \"../format.ts\";\nimport type { ChannelAccountSnapshot, TelegramStatus } from \"../types.ts\";\nimport { renderChannelConfigSection } from \"./channels.config.ts\";\nimport type { ChannelsProps } from \"./channels.types.ts\";\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 <div class=\"account-card\">\n <div class=\"account-card-header\">\n <div class=\"account-card-title\">\n ${botUsername ? `@${botUsername}` : label}\n </div>\n <div class=\"account-card-id\">${account.accountId}</div>\n </div>\n <div class=\"status-list account-card-status\">\n <div>\n <span class=\"label\">Running</span>\n <span>${account.running ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Configured</span>\n <span>${account.configured ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Last inbound</span>\n <span>${account.lastInboundAt ? formatRelativeTimestamp(account.lastInboundAt) : \"n/a\"}</span>\n </div>\n ${\n account.lastError\n ? html`\n <div class=\"account-card-error\">\n ${account.lastError}\n </div>\n `\n : nothing\n }\n </div>\n </div>\n `;\n };\n\n return html`\n <div class=\"card\">\n <div class=\"card-title\">Telegram</div>\n <div class=\"card-sub\">Bot status and channel configuration.</div>\n ${accountCountLabel}\n\n ${\n hasMultipleAccounts\n ? html`\n <div class=\"account-card-list\">\n ${telegramAccounts.map((account) => renderAccountCard(account))}\n </div>\n `\n : html`\n <div class=\"status-list\" style=\"margin-top: 16px;\">\n <div>\n <span class=\"label\">Configured</span>\n <span>${telegram?.configured ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Running</span>\n <span>${telegram?.running ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Mode</span>\n <span>${telegram?.mode ?? \"n/a\"}</span>\n </div>\n <div>\n <span class=\"label\">Last start</span>\n <span>${telegram?.lastStartAt ? formatRelativeTimestamp(telegram.lastStartAt) : \"n/a\"}</span>\n </div>\n <div>\n <span class=\"label\">Last probe</span>\n <span>${telegram?.lastProbeAt ? formatRelativeTimestamp(telegram.lastProbeAt) : \"n/a\"}</span>\n </div>\n </div>\n `\n }\n\n ${\n telegram?.lastError\n ? html`<div class=\"callout danger\" style=\"margin-top: 12px;\">\n ${telegram.lastError}\n </div>`\n : nothing\n }\n\n ${\n telegram?.probe\n ? html`<div class=\"callout\" style=\"margin-top: 12px;\">\n Probe ${telegram.probe.ok ? \"ok\" : \"failed\"} ·\n ${telegram.probe.status ?? \"\"} ${telegram.probe.error ?? \"\"}\n </div>`\n : nothing\n }\n\n ${renderChannelConfigSection({ channelId: \"telegram\", props })}\n\n <div class=\"row\" style=\"margin-top: 12px;\">\n <button class=\"btn\" @click=${() => props.onRefresh(true)}>\n Probe\n </button>\n </div>\n </div>\n `;\n}\n","import { html, nothing } from \"lit\";\nimport { formatRelativeTimestamp, formatDurationHuman } from \"../format.ts\";\nimport type { WhatsAppStatus } from \"../types.ts\";\nimport { renderChannelConfigSection } from \"./channels.config.ts\";\nimport type { ChannelsProps } from \"./channels.types.ts\";\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 <div class=\"card\">\n <div class=\"card-title\">WhatsApp</div>\n <div class=\"card-sub\">Link WhatsApp Web and monitor connection health.</div>\n ${accountCountLabel}\n\n <div class=\"status-list\" style=\"margin-top: 16px;\">\n <div>\n <span class=\"label\">Configured</span>\n <span>${whatsapp?.configured ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Linked</span>\n <span>${whatsapp?.linked ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Running</span>\n <span>${whatsapp?.running ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Connected</span>\n <span>${whatsapp?.connected ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Last connect</span>\n <span>\n ${whatsapp?.lastConnectedAt ? formatRelativeTimestamp(whatsapp.lastConnectedAt) : \"n/a\"}\n </span>\n </div>\n <div>\n <span class=\"label\">Last message</span>\n <span>\n ${whatsapp?.lastMessageAt ? formatRelativeTimestamp(whatsapp.lastMessageAt) : \"n/a\"}\n </span>\n </div>\n <div>\n <span class=\"label\">Auth age</span>\n <span>\n ${whatsapp?.authAgeMs != null ? formatDurationHuman(whatsapp.authAgeMs) : \"n/a\"}\n </span>\n </div>\n </div>\n\n ${\n whatsapp?.lastError\n ? html`<div class=\"callout danger\" style=\"margin-top: 12px;\">\n ${whatsapp.lastError}\n </div>`\n : nothing\n }\n\n ${\n props.whatsappMessage\n ? html`<div class=\"callout\" style=\"margin-top: 12px;\">\n ${props.whatsappMessage}\n </div>`\n : nothing\n }\n\n ${\n props.whatsappQrDataUrl\n ? html`<div class=\"qr-wrap\">\n <img src=${props.whatsappQrDataUrl} alt=\"WhatsApp QR\" />\n </div>`\n : nothing\n }\n\n <div class=\"row\" style=\"margin-top: 14px; flex-wrap: wrap;\">\n <button\n class=\"btn primary\"\n ?disabled=${props.whatsappBusy}\n @click=${() => props.onWhatsAppStart(false)}\n >\n ${props.whatsappBusy ? \"Working…\" : \"Show QR\"}\n </button>\n <button\n class=\"btn\"\n ?disabled=${props.whatsappBusy}\n @click=${() => props.onWhatsAppStart(true)}\n >\n Relink\n </button>\n <button\n class=\"btn\"\n ?disabled=${props.whatsappBusy}\n @click=${() => props.onWhatsAppWait()}\n >\n Wait for scan\n </button>\n <button\n class=\"btn danger\"\n ?disabled=${props.whatsappBusy}\n @click=${() => props.onWhatsAppLogout()}\n >\n Logout\n </button>\n <button class=\"btn\" @click=${() => props.onRefresh(true)}>\n Refresh\n </button>\n </div>\n\n ${renderChannelConfigSection({ channelId: \"whatsapp\", props })}\n </div>\n `;\n}\n","import { html, nothing } from \"lit\";\nimport { formatRelativeTimestamp } from \"../format.ts\";\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.ts\";\nimport { renderChannelConfigSection } from \"./channels.config.ts\";\nimport { renderDiscordCard } from \"./channels.discord.ts\";\nimport { renderGoogleChatCard } from \"./channels.googlechat.ts\";\nimport { renderIMessageCard } from \"./channels.imessage.ts\";\nimport { renderNostrCard } from \"./channels.nostr.ts\";\nimport { channelEnabled, renderChannelAccountCount } from \"./channels.shared.ts\";\nimport { renderSignalCard } from \"./channels.signal.ts\";\nimport { renderSlackCard } from \"./channels.slack.ts\";\nimport { renderTelegramCard } from \"./channels.telegram.ts\";\nimport type { ChannelKey, ChannelsChannelData, ChannelsProps } from \"./channels.types.ts\";\nimport { renderWhatsAppCard } from \"./channels.whatsapp.ts\";\n\nexport function renderChannels(props: ChannelsProps) {\n const channels = props.snapshot?.channels as Record<string, unknown> | null;\n const whatsapp = (channels?.whatsapp ?? undefined) as WhatsAppStatus | undefined;\n const telegram = (channels?.telegram ?? undefined) as TelegramStatus | 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 .toSorted((a, b) => {\n if (a.enabled !== b.enabled) {\n return a.enabled ? -1 : 1;\n }\n return a.order - b.order;\n });\n\n return html`\n <section class=\"grid grid-cols-2\">\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 </section>\n\n <section class=\"card\" style=\"margin-top: 18px;\">\n <div class=\"row\" style=\"justify-content: space-between;\">\n <div>\n <div class=\"card-title\">Channel health</div>\n <div class=\"card-sub\">Channel status snapshots from the gateway.</div>\n </div>\n <div class=\"muted\">${props.lastSuccessAt ? formatRelativeTimestamp(props.lastSuccessAt) : \"n/a\"}</div>\n </div>\n ${\n props.lastError\n ? html`<div class=\"callout danger\" style=\"margin-top: 12px;\">\n ${props.lastError}\n </div>`\n : nothing\n }\n <pre class=\"code-block\" style=\"margin-top: 12px;\">\n${props.snapshot ? JSON.stringify(props.snapshot, null, 2) : \"No snapshot yet.\"}\n </pre>\n </section>\n `;\n}\n\nfunction resolveChannelOrder(snapshot: ChannelsStatusSnapshot | null): ChannelKey[] {\n if (snapshot?.channelMeta?.length) {\n return snapshot.channelMeta.map((entry) => entry.id);\n }\n if (snapshot?.channelOrder?.length) {\n return snapshot.channelOrder;\n }\n return [\"whatsapp\", \"telegram\", \"discord\", \"googlechat\", \"slack\", \"signal\", \"imessage\", \"nostr\"];\n}\n\nfunction renderChannel(key: ChannelKey, props: ChannelsProps, data: ChannelsChannelData) {\n const accountCountLabel = renderChannelAccountCount(key, data.channelAccounts);\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<string, ChannelAccountSnapshot[]>,\n) {\n const label = resolveChannelLabel(props.snapshot, key);\n const status = props.snapshot?.channels?.[key] as Record<string, unknown> | 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 <div class=\"card\">\n <div class=\"card-title\">${label}</div>\n <div class=\"card-sub\">Channel status and configuration.</div>\n ${accountCountLabel}\n\n ${\n accounts.length > 0\n ? html`\n <div class=\"account-card-list\">\n ${accounts.map((account) => renderGenericAccount(account))}\n </div>\n `\n : html`\n <div class=\"status-list\" style=\"margin-top: 16px;\">\n <div>\n <span class=\"label\">Configured</span>\n <span>${configured == null ? \"n/a\" : configured ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Running</span>\n <span>${running == null ? \"n/a\" : running ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Connected</span>\n <span>${connected == null ? \"n/a\" : connected ? \"Yes\" : \"No\"}</span>\n </div>\n </div>\n `\n }\n\n ${\n lastError\n ? html`<div class=\"callout danger\" style=\"margin-top: 12px;\">\n ${lastError}\n </div>`\n : nothing\n }\n\n ${renderChannelConfigSection({ channelId: key, props })}\n </div>\n `;\n}\n\nfunction resolveChannelMetaMap(\n snapshot: ChannelsStatusSnapshot | null,\n): Record<string, ChannelUiMetaEntry> {\n if (!snapshot?.channelMeta?.length) {\n return {};\n }\n return Object.fromEntries(snapshot.channelMeta.map((entry) => [entry.id, entry]));\n}\n\nfunction resolveChannelLabel(snapshot: ChannelsStatusSnapshot | null, key: string): 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) {\n return false;\n }\n return Date.now() - account.lastInboundAt < RECENT_ACTIVITY_THRESHOLD_MS;\n}\n\nfunction deriveRunningStatus(account: ChannelAccountSnapshot): \"Yes\" | \"No\" | \"Active\" {\n if (account.running) {\n return \"Yes\";\n }\n // If we have recent inbound activity, the channel is effectively running\n if (hasRecentActivity(account)) {\n return \"Active\";\n }\n return \"No\";\n}\n\nfunction deriveConnectedStatus(account: ChannelAccountSnapshot): \"Yes\" | \"No\" | \"Active\" | \"n/a\" {\n if (account.connected === true) {\n return \"Yes\";\n }\n if (account.connected === false) {\n return \"No\";\n }\n // If connected is null/undefined but we have recent activity, show as active\n if (hasRecentActivity(account)) {\n return \"Active\";\n }\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 <div class=\"account-card\">\n <div class=\"account-card-header\">\n <div class=\"account-card-title\">${account.name || account.accountId}</div>\n <div class=\"account-card-id\">${account.accountId}</div>\n </div>\n <div class=\"status-list account-card-status\">\n <div>\n <span class=\"label\">Running</span>\n <span>${runningStatus}</span>\n </div>\n <div>\n <span class=\"label\">Configured</span>\n <span>${account.configured ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Connected</span>\n <span>${connectedStatus}</span>\n </div>\n <div>\n <span class=\"label\">Last inbound</span>\n <span>${account.lastInboundAt ? formatRelativeTimestamp(account.lastInboundAt) : \"n/a\"}</span>\n </div>\n ${\n account.lastError\n ? html`\n <div class=\"account-card-error\">\n ${account.lastError}\n </div>\n `\n : nothing\n }\n </div>\n </div>\n `;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"channels-CtcAfpMH.js","names":[],"sources":["../../../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.ts","../../../ui/src/ui/views/channels.shared.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"],"sourcesContent":["import { html } from \"lit\";\nimport type { ConfigUiHints } from \"../types.ts\";\nimport { formatChannelExtraValue, resolveChannelConfigValue } from \"./channel-config-extras.ts\";\nimport type { ChannelsProps } from \"./channels.types.ts\";\nimport { analyzeConfigSchema, renderNode, schemaType, type JsonSchema } from \"./config-form.ts\";\n\ntype ChannelConfigFormProps = {\n channelId: string;\n configValue: Record<string, unknown> | null;\n schema: unknown;\n uiHints: ConfigUiHints;\n disabled: boolean;\n onPatch: (path: Array<string | number>, value: unknown) => void;\n};\n\nfunction resolveSchemaNode(\n schema: JsonSchema | null,\n path: Array<string | number>,\n): JsonSchema | null {\n let current = schema;\n for (const key of path) {\n if (!current) {\n return null;\n }\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;\n continue;\n }\n return null;\n }\n if (type === \"array\") {\n if (typeof key !== \"number\") {\n return null;\n }\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<string, unknown>,\n channelId: string,\n): Record<string, unknown> {\n return resolveChannelConfigValue(config, channelId) ?? {};\n}\n\nconst EXTRA_CHANNEL_FIELDS = [\"groupPolicy\", \"streamMode\", \"dmPolicy\"] as const;\n\nfunction renderExtraChannelFields(value: Record<string, unknown>) {\n const entries = EXTRA_CHANNEL_FIELDS.flatMap((field) => {\n if (!(field in value)) {\n return [];\n }\n return [[field, value[field]]] as Array<[string, unknown]>;\n });\n if (entries.length === 0) {\n return null;\n }\n return html`\n <div class=\"status-list\" style=\"margin-top: 12px;\">\n ${entries.map(\n ([field, raw]) => html`\n <div>\n <span class=\"label\">${field}</span>\n <span>${formatChannelExtraValue(raw)}</span>\n </div>\n `,\n )}\n </div>\n `;\n}\n\nexport function renderChannelConfigForm(props: ChannelConfigFormProps) {\n const analysis = analyzeConfigSchema(props.schema);\n const normalized = analysis.schema;\n if (!normalized) {\n return html`\n <div class=\"callout danger\">Schema unavailable. Use Raw.</div>\n `;\n }\n const node = resolveSchemaNode(normalized, [\"channels\", props.channelId]);\n if (!node) {\n return html`\n <div class=\"callout danger\">Channel config schema unavailable.</div>\n `;\n }\n const configValue = props.configValue ?? {};\n const value = resolveChannelValue(configValue, props.channelId);\n return html`\n <div class=\"config-form\">\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 </div>\n ${renderExtraChannelFields(value)}\n `;\n}\n\nexport function renderChannelConfigSection(params: { channelId: string; props: ChannelsProps }) {\n const { channelId, props } = params;\n const disabled = props.configSaving || props.configSchemaLoading;\n return html`\n <div style=\"margin-top: 16px;\">\n ${\n props.configSchemaLoading\n ? html`\n <div class=\"muted\">Loading config schema…</div>\n `\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 <div class=\"row\" style=\"margin-top: 12px;\">\n <button\n class=\"btn primary\"\n ?disabled=${disabled || !props.configFormDirty}\n @click=${() => props.onConfigSave()}\n >\n ${props.configSaving ? \"Saving…\" : \"Save\"}\n </button>\n <button\n class=\"btn\"\n ?disabled=${disabled}\n @click=${() => props.onConfigReload()}\n >\n Reload\n </button>\n </div>\n </div>\n `;\n}\n","import { html, nothing } from \"lit\";\nimport { formatRelativeTimestamp } from \"../format.ts\";\nimport type { DiscordStatus } from \"../types.ts\";\nimport { renderChannelConfigSection } from \"./channels.config.ts\";\nimport type { ChannelsProps } from \"./channels.types.ts\";\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 <div class=\"card\">\n <div class=\"card-title\">Discord</div>\n <div class=\"card-sub\">Bot status and channel configuration.</div>\n ${accountCountLabel}\n\n <div class=\"status-list\" style=\"margin-top: 16px;\">\n <div>\n <span class=\"label\">Configured</span>\n <span>${discord?.configured ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Running</span>\n <span>${discord?.running ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Last start</span>\n <span>${discord?.lastStartAt ? formatRelativeTimestamp(discord.lastStartAt) : \"n/a\"}</span>\n </div>\n <div>\n <span class=\"label\">Last probe</span>\n <span>${discord?.lastProbeAt ? formatRelativeTimestamp(discord.lastProbeAt) : \"n/a\"}</span>\n </div>\n </div>\n\n ${\n discord?.lastError\n ? html`<div class=\"callout danger\" style=\"margin-top: 12px;\">\n ${discord.lastError}\n </div>`\n : nothing\n }\n\n ${\n discord?.probe\n ? html`<div class=\"callout\" style=\"margin-top: 12px;\">\n Probe ${discord.probe.ok ? \"ok\" : \"failed\"} ·\n ${discord.probe.status ?? \"\"} ${discord.probe.error ?? \"\"}\n </div>`\n : nothing\n }\n\n ${renderChannelConfigSection({ channelId: \"discord\", props })}\n\n <div class=\"row\" style=\"margin-top: 12px;\">\n <button class=\"btn\" @click=${() => props.onRefresh(true)}>\n Probe\n </button>\n </div>\n </div>\n `;\n}\n","import { html, nothing } from \"lit\";\nimport { formatRelativeTimestamp } from \"../format.ts\";\nimport type { GoogleChatStatus } from \"../types.ts\";\nimport { renderChannelConfigSection } from \"./channels.config.ts\";\nimport type { ChannelsProps } from \"./channels.types.ts\";\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 <div class=\"card\">\n <div class=\"card-title\">Google Chat</div>\n <div class=\"card-sub\">Chat API webhook status and channel configuration.</div>\n ${accountCountLabel}\n\n <div class=\"status-list\" style=\"margin-top: 16px;\">\n <div>\n <span class=\"label\">Configured</span>\n <span>${googleChat ? (googleChat.configured ? \"Yes\" : \"No\") : \"n/a\"}</span>\n </div>\n <div>\n <span class=\"label\">Running</span>\n <span>${googleChat ? (googleChat.running ? \"Yes\" : \"No\") : \"n/a\"}</span>\n </div>\n <div>\n <span class=\"label\">Credential</span>\n <span>${googleChat?.credentialSource ?? \"n/a\"}</span>\n </div>\n <div>\n <span class=\"label\">Audience</span>\n <span>\n ${\n googleChat?.audienceType\n ? `${googleChat.audienceType}${googleChat.audience ? ` · ${googleChat.audience}` : \"\"}`\n : \"n/a\"\n }\n </span>\n </div>\n <div>\n <span class=\"label\">Last start</span>\n <span>${googleChat?.lastStartAt ? formatRelativeTimestamp(googleChat.lastStartAt) : \"n/a\"}</span>\n </div>\n <div>\n <span class=\"label\">Last probe</span>\n <span>${googleChat?.lastProbeAt ? formatRelativeTimestamp(googleChat.lastProbeAt) : \"n/a\"}</span>\n </div>\n </div>\n\n ${\n googleChat?.lastError\n ? html`<div class=\"callout danger\" style=\"margin-top: 12px;\">\n ${googleChat.lastError}\n </div>`\n : nothing\n }\n\n ${\n googleChat?.probe\n ? html`<div class=\"callout\" style=\"margin-top: 12px;\">\n Probe ${googleChat.probe.ok ? \"ok\" : \"failed\"} ·\n ${googleChat.probe.status ?? \"\"} ${googleChat.probe.error ?? \"\"}\n </div>`\n : nothing\n }\n\n ${renderChannelConfigSection({ channelId: \"googlechat\", props })}\n\n <div class=\"row\" style=\"margin-top: 12px;\">\n <button class=\"btn\" @click=${() => props.onRefresh(true)}>\n Probe\n </button>\n </div>\n </div>\n `;\n}\n","import { html, nothing } from \"lit\";\nimport { formatRelativeTimestamp } from \"../format.ts\";\nimport type { IMessageStatus } from \"../types.ts\";\nimport { renderChannelConfigSection } from \"./channels.config.ts\";\nimport type { ChannelsProps } from \"./channels.types.ts\";\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 <div class=\"card\">\n <div class=\"card-title\">iMessage</div>\n <div class=\"card-sub\">macOS bridge status and channel configuration.</div>\n ${accountCountLabel}\n\n <div class=\"status-list\" style=\"margin-top: 16px;\">\n <div>\n <span class=\"label\">Configured</span>\n <span>${imessage?.configured ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Running</span>\n <span>${imessage?.running ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Last start</span>\n <span>${imessage?.lastStartAt ? formatRelativeTimestamp(imessage.lastStartAt) : \"n/a\"}</span>\n </div>\n <div>\n <span class=\"label\">Last probe</span>\n <span>${imessage?.lastProbeAt ? formatRelativeTimestamp(imessage.lastProbeAt) : \"n/a\"}</span>\n </div>\n </div>\n\n ${\n imessage?.lastError\n ? html`<div class=\"callout danger\" style=\"margin-top: 12px;\">\n ${imessage.lastError}\n </div>`\n : nothing\n }\n\n ${\n imessage?.probe\n ? html`<div class=\"callout\" style=\"margin-top: 12px;\">\n Probe ${imessage.probe.ok ? \"ok\" : \"failed\"} ·\n ${imessage.probe.error ?? \"\"}\n </div>`\n : nothing\n }\n\n ${renderChannelConfigSection({ channelId: \"imessage\", props })}\n\n <div class=\"row\" style=\"margin-top: 12px;\">\n <button class=\"btn\" @click=${() => props.onRefresh(true)}>\n Probe\n </button>\n </div>\n </div>\n `;\n}\n","import { html, nothing } from \"lit\";\nimport { formatRelativeTimestamp } from \"../format.ts\";\nimport type { ChannelAccountSnapshot, NostrStatus } from \"../types.ts\";\nimport { renderChannelConfigSection } from \"./channels.config.ts\";\nimport {\n renderNostrProfileForm,\n type NostrProfileFormState,\n type NostrProfileFormCallbacks,\n} from \"./channels.nostr-profile-form.ts\";\nimport type { ChannelsProps } from \"./channels.types.ts\";\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) {\n return \"n/a\";\n }\n if (pubkey.length <= 20) {\n return pubkey;\n }\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 ?? (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 <div class=\"account-card\">\n <div class=\"account-card-header\">\n <div class=\"account-card-title\">${displayName}</div>\n <div class=\"account-card-id\">${account.accountId}</div>\n </div>\n <div class=\"status-list account-card-status\">\n <div>\n <span class=\"label\">Running</span>\n <span>${account.running ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Configured</span>\n <span>${account.configured ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Public Key</span>\n <span class=\"monospace\" title=\"${publicKey ?? \"\"}\">${truncatePubkey(publicKey)}</span>\n </div>\n <div>\n <span class=\"label\">Last inbound</span>\n <span>${account.lastInboundAt ? formatRelativeTimestamp(account.lastInboundAt) : \"n/a\"}</span>\n </div>\n ${\n account.lastError\n ? html`\n <div class=\"account-card-error\">${account.lastError}</div>\n `\n : nothing\n }\n </div>\n </div>\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 (\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\n )?.profile ?? nostr?.profile;\n const { name, displayName, about, picture, nip05 } = profile ?? {};\n const hasAnyProfileData = name || displayName || about || picture || nip05;\n\n return html`\n <div style=\"margin-top: 16px; padding: 12px; background: var(--bg-secondary); border-radius: 8px;\">\n <div style=\"display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;\">\n <div style=\"font-weight: 500;\">Profile</div>\n ${\n summaryConfigured\n ? html`\n <button\n class=\"btn btn-sm\"\n @click=${onEditProfile}\n style=\"font-size: 12px; padding: 4px 8px;\"\n >\n Edit Profile\n </button>\n `\n : nothing\n }\n </div>\n ${\n hasAnyProfileData\n ? html`\n <div class=\"status-list\">\n ${\n picture\n ? html`\n <div style=\"margin-bottom: 8px;\">\n <img\n src=${picture}\n alt=\"Profile picture\"\n style=\"width: 48px; height: 48px; border-radius: 50%; object-fit: cover; border: 2px solid var(--border-color);\"\n @error=${(e: Event) => {\n (e.target as HTMLImageElement).style.display = \"none\";\n }}\n />\n </div>\n `\n : nothing\n }\n ${name ? html`<div><span class=\"label\">Name</span><span>${name}</span></div>` : nothing}\n ${\n displayName\n ? html`<div><span class=\"label\">Display Name</span><span>${displayName}</span></div>`\n : nothing\n }\n ${\n about\n ? html`<div><span class=\"label\">About</span><span style=\"max-width: 300px; overflow: hidden; text-overflow: ellipsis;\">${about}</span></div>`\n : nothing\n }\n ${nip05 ? html`<div><span class=\"label\">NIP-05</span><span>${nip05}</span></div>` : nothing}\n </div>\n `\n : html`\n <div style=\"color: var(--text-muted); font-size: 13px\">\n No profile set. Click \"Edit Profile\" to add your name, bio, and avatar.\n </div>\n `\n }\n </div>\n `;\n };\n\n return html`\n <div class=\"card\">\n <div class=\"card-title\">Nostr</div>\n <div class=\"card-sub\">Decentralized DMs via Nostr relays (NIP-04).</div>\n ${accountCountLabel}\n\n ${\n hasMultipleAccounts\n ? html`\n <div class=\"account-card-list\">\n ${nostrAccounts.map((account) => renderAccountCard(account))}\n </div>\n `\n : html`\n <div class=\"status-list\" style=\"margin-top: 16px;\">\n <div>\n <span class=\"label\">Configured</span>\n <span>${summaryConfigured ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Running</span>\n <span>${summaryRunning ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Public Key</span>\n <span class=\"monospace\" title=\"${summaryPublicKey ?? \"\"}\"\n >${truncatePubkey(summaryPublicKey)}</span\n >\n </div>\n <div>\n <span class=\"label\">Last start</span>\n <span>${summaryLastStartAt ? formatRelativeTimestamp(summaryLastStartAt) : \"n/a\"}</span>\n </div>\n </div>\n `\n }\n\n ${\n summaryLastError\n ? html`<div class=\"callout danger\" style=\"margin-top: 12px;\">${summaryLastError}</div>`\n : nothing\n }\n\n ${renderProfileSection()}\n\n ${renderChannelConfigSection({ channelId: \"nostr\", props })}\n\n <div class=\"row\" style=\"margin-top: 12px;\">\n <button class=\"btn\" @click=${() => props.onRefresh(false)}>Refresh</button>\n </div>\n </div>\n `;\n}\n","import { html, nothing } from \"lit\";\nimport type { ChannelAccountSnapshot } from \"../types.ts\";\nimport type { ChannelKey, ChannelsProps } from \"./channels.types.ts\";\n\nexport function channelEnabled(key: ChannelKey, props: ChannelsProps) {\n const snapshot = props.snapshot;\n const channels = snapshot?.channels as Record<string, unknown> | null;\n if (!snapshot || !channels) {\n return false;\n }\n const channelStatus = channels[key] as Record<string, unknown> | 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<string, ChannelAccountSnapshot[]> | null,\n): number {\n return channelAccounts?.[key]?.length ?? 0;\n}\n\nexport function renderChannelAccountCount(\n key: ChannelKey,\n channelAccounts?: Record<string, ChannelAccountSnapshot[]> | null,\n) {\n const count = getChannelAccountCount(key, channelAccounts);\n if (count < 2) {\n return nothing;\n }\n return html`<div class=\"account-count\">Accounts (${count})</div>`;\n}\n","import { html, nothing } from \"lit\";\nimport { formatRelativeTimestamp } from \"../format.ts\";\nimport type { SignalStatus } from \"../types.ts\";\nimport { renderChannelConfigSection } from \"./channels.config.ts\";\nimport type { ChannelsProps } from \"./channels.types.ts\";\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 <div class=\"card\">\n <div class=\"card-title\">Signal</div>\n <div class=\"card-sub\">signal-cli status and channel configuration.</div>\n ${accountCountLabel}\n\n <div class=\"status-list\" style=\"margin-top: 16px;\">\n <div>\n <span class=\"label\">Configured</span>\n <span>${signal?.configured ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Running</span>\n <span>${signal?.running ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Base URL</span>\n <span>${signal?.baseUrl ?? \"n/a\"}</span>\n </div>\n <div>\n <span class=\"label\">Last start</span>\n <span>${signal?.lastStartAt ? formatRelativeTimestamp(signal.lastStartAt) : \"n/a\"}</span>\n </div>\n <div>\n <span class=\"label\">Last probe</span>\n <span>${signal?.lastProbeAt ? formatRelativeTimestamp(signal.lastProbeAt) : \"n/a\"}</span>\n </div>\n </div>\n\n ${\n signal?.lastError\n ? html`<div class=\"callout danger\" style=\"margin-top: 12px;\">\n ${signal.lastError}\n </div>`\n : nothing\n }\n\n ${\n signal?.probe\n ? html`<div class=\"callout\" style=\"margin-top: 12px;\">\n Probe ${signal.probe.ok ? \"ok\" : \"failed\"} ·\n ${signal.probe.status ?? \"\"} ${signal.probe.error ?? \"\"}\n </div>`\n : nothing\n }\n\n ${renderChannelConfigSection({ channelId: \"signal\", props })}\n\n <div class=\"row\" style=\"margin-top: 12px;\">\n <button class=\"btn\" @click=${() => props.onRefresh(true)}>\n Probe\n </button>\n </div>\n </div>\n `;\n}\n","import { html, nothing } from \"lit\";\nimport { formatRelativeTimestamp } from \"../format.ts\";\nimport type { SlackStatus } from \"../types.ts\";\nimport { renderChannelConfigSection } from \"./channels.config.ts\";\nimport type { ChannelsProps } from \"./channels.types.ts\";\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 <div class=\"card\">\n <div class=\"card-title\">Slack</div>\n <div class=\"card-sub\">Socket mode status and channel configuration.</div>\n ${accountCountLabel}\n\n <div class=\"status-list\" style=\"margin-top: 16px;\">\n <div>\n <span class=\"label\">Configured</span>\n <span>${slack?.configured ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Running</span>\n <span>${slack?.running ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Last start</span>\n <span>${slack?.lastStartAt ? formatRelativeTimestamp(slack.lastStartAt) : \"n/a\"}</span>\n </div>\n <div>\n <span class=\"label\">Last probe</span>\n <span>${slack?.lastProbeAt ? formatRelativeTimestamp(slack.lastProbeAt) : \"n/a\"}</span>\n </div>\n </div>\n\n ${\n slack?.lastError\n ? html`<div class=\"callout danger\" style=\"margin-top: 12px;\">\n ${slack.lastError}\n </div>`\n : nothing\n }\n\n ${\n slack?.probe\n ? html`<div class=\"callout\" style=\"margin-top: 12px;\">\n Probe ${slack.probe.ok ? \"ok\" : \"failed\"} ·\n ${slack.probe.status ?? \"\"} ${slack.probe.error ?? \"\"}\n </div>`\n : nothing\n }\n\n ${renderChannelConfigSection({ channelId: \"slack\", props })}\n\n <div class=\"row\" style=\"margin-top: 12px;\">\n <button class=\"btn\" @click=${() => props.onRefresh(true)}>\n Probe\n </button>\n </div>\n </div>\n `;\n}\n","import { html, nothing } from \"lit\";\nimport { formatRelativeTimestamp } from \"../format.ts\";\nimport type { ChannelAccountSnapshot, TelegramStatus } from \"../types.ts\";\nimport { renderChannelConfigSection } from \"./channels.config.ts\";\nimport type { ChannelsProps } from \"./channels.types.ts\";\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 <div class=\"account-card\">\n <div class=\"account-card-header\">\n <div class=\"account-card-title\">\n ${botUsername ? `@${botUsername}` : label}\n </div>\n <div class=\"account-card-id\">${account.accountId}</div>\n </div>\n <div class=\"status-list account-card-status\">\n <div>\n <span class=\"label\">Running</span>\n <span>${account.running ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Configured</span>\n <span>${account.configured ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Last inbound</span>\n <span>${account.lastInboundAt ? formatRelativeTimestamp(account.lastInboundAt) : \"n/a\"}</span>\n </div>\n ${\n account.lastError\n ? html`\n <div class=\"account-card-error\">\n ${account.lastError}\n </div>\n `\n : nothing\n }\n </div>\n </div>\n `;\n };\n\n return html`\n <div class=\"card\">\n <div class=\"card-title\">Telegram</div>\n <div class=\"card-sub\">Bot status and channel configuration.</div>\n ${accountCountLabel}\n\n ${\n hasMultipleAccounts\n ? html`\n <div class=\"account-card-list\">\n ${telegramAccounts.map((account) => renderAccountCard(account))}\n </div>\n `\n : html`\n <div class=\"status-list\" style=\"margin-top: 16px;\">\n <div>\n <span class=\"label\">Configured</span>\n <span>${telegram?.configured ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Running</span>\n <span>${telegram?.running ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Mode</span>\n <span>${telegram?.mode ?? \"n/a\"}</span>\n </div>\n <div>\n <span class=\"label\">Last start</span>\n <span>${telegram?.lastStartAt ? formatRelativeTimestamp(telegram.lastStartAt) : \"n/a\"}</span>\n </div>\n <div>\n <span class=\"label\">Last probe</span>\n <span>${telegram?.lastProbeAt ? formatRelativeTimestamp(telegram.lastProbeAt) : \"n/a\"}</span>\n </div>\n </div>\n `\n }\n\n ${\n telegram?.lastError\n ? html`<div class=\"callout danger\" style=\"margin-top: 12px;\">\n ${telegram.lastError}\n </div>`\n : nothing\n }\n\n ${\n telegram?.probe\n ? html`<div class=\"callout\" style=\"margin-top: 12px;\">\n Probe ${telegram.probe.ok ? \"ok\" : \"failed\"} ·\n ${telegram.probe.status ?? \"\"} ${telegram.probe.error ?? \"\"}\n </div>`\n : nothing\n }\n\n ${renderChannelConfigSection({ channelId: \"telegram\", props })}\n\n <div class=\"row\" style=\"margin-top: 12px;\">\n <button class=\"btn\" @click=${() => props.onRefresh(true)}>\n Probe\n </button>\n </div>\n </div>\n `;\n}\n","import { html, nothing } from \"lit\";\nimport { formatRelativeTimestamp, formatDurationHuman } from \"../format.ts\";\nimport type { WhatsAppStatus } from \"../types.ts\";\nimport { renderChannelConfigSection } from \"./channels.config.ts\";\nimport type { ChannelsProps } from \"./channels.types.ts\";\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 <div class=\"card\">\n <div class=\"card-title\">WhatsApp</div>\n <div class=\"card-sub\">Link WhatsApp Web and monitor connection health.</div>\n ${accountCountLabel}\n\n <div class=\"status-list\" style=\"margin-top: 16px;\">\n <div>\n <span class=\"label\">Configured</span>\n <span>${whatsapp?.configured ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Linked</span>\n <span>${whatsapp?.linked ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Running</span>\n <span>${whatsapp?.running ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Connected</span>\n <span>${whatsapp?.connected ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Last connect</span>\n <span>\n ${whatsapp?.lastConnectedAt ? formatRelativeTimestamp(whatsapp.lastConnectedAt) : \"n/a\"}\n </span>\n </div>\n <div>\n <span class=\"label\">Last message</span>\n <span>\n ${whatsapp?.lastMessageAt ? formatRelativeTimestamp(whatsapp.lastMessageAt) : \"n/a\"}\n </span>\n </div>\n <div>\n <span class=\"label\">Auth age</span>\n <span>\n ${whatsapp?.authAgeMs != null ? formatDurationHuman(whatsapp.authAgeMs) : \"n/a\"}\n </span>\n </div>\n </div>\n\n ${\n whatsapp?.lastError\n ? html`<div class=\"callout danger\" style=\"margin-top: 12px;\">\n ${whatsapp.lastError}\n </div>`\n : nothing\n }\n\n ${\n props.whatsappMessage\n ? html`<div class=\"callout\" style=\"margin-top: 12px;\">\n ${props.whatsappMessage}\n </div>`\n : nothing\n }\n\n ${\n props.whatsappQrDataUrl\n ? html`<div class=\"qr-wrap\">\n <img src=${props.whatsappQrDataUrl} alt=\"WhatsApp QR\" />\n </div>`\n : nothing\n }\n\n <div class=\"row\" style=\"margin-top: 14px; flex-wrap: wrap;\">\n <button\n class=\"btn primary\"\n ?disabled=${props.whatsappBusy}\n @click=${() => props.onWhatsAppStart(false)}\n >\n ${props.whatsappBusy ? \"Working…\" : \"Show QR\"}\n </button>\n <button\n class=\"btn\"\n ?disabled=${props.whatsappBusy}\n @click=${() => props.onWhatsAppStart(true)}\n >\n Relink\n </button>\n <button\n class=\"btn\"\n ?disabled=${props.whatsappBusy}\n @click=${() => props.onWhatsAppWait()}\n >\n Wait for scan\n </button>\n <button\n class=\"btn danger\"\n ?disabled=${props.whatsappBusy}\n @click=${() => props.onWhatsAppLogout()}\n >\n Logout\n </button>\n <button class=\"btn\" @click=${() => props.onRefresh(true)}>\n Refresh\n </button>\n </div>\n\n ${renderChannelConfigSection({ channelId: \"whatsapp\", props })}\n </div>\n `;\n}\n","import { html, nothing } from \"lit\";\nimport { formatRelativeTimestamp } from \"../format.ts\";\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.ts\";\nimport { renderChannelConfigSection } from \"./channels.config.ts\";\nimport { renderDiscordCard } from \"./channels.discord.ts\";\nimport { renderGoogleChatCard } from \"./channels.googlechat.ts\";\nimport { renderIMessageCard } from \"./channels.imessage.ts\";\nimport { renderNostrCard } from \"./channels.nostr.ts\";\nimport { channelEnabled, renderChannelAccountCount } from \"./channels.shared.ts\";\nimport { renderSignalCard } from \"./channels.signal.ts\";\nimport { renderSlackCard } from \"./channels.slack.ts\";\nimport { renderTelegramCard } from \"./channels.telegram.ts\";\nimport type { ChannelKey, ChannelsChannelData, ChannelsProps } from \"./channels.types.ts\";\nimport { renderWhatsAppCard } from \"./channels.whatsapp.ts\";\n\nexport function renderChannels(props: ChannelsProps) {\n const channels = props.snapshot?.channels as Record<string, unknown> | null;\n const whatsapp = (channels?.whatsapp ?? undefined) as WhatsAppStatus | undefined;\n const telegram = (channels?.telegram ?? undefined) as TelegramStatus | 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 .toSorted((a, b) => {\n if (a.enabled !== b.enabled) {\n return a.enabled ? -1 : 1;\n }\n return a.order - b.order;\n });\n\n return html`\n <section class=\"grid grid-cols-2\">\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 </section>\n\n <section class=\"card\" style=\"margin-top: 18px;\">\n <div class=\"row\" style=\"justify-content: space-between;\">\n <div>\n <div class=\"card-title\">Channel health</div>\n <div class=\"card-sub\">Channel status snapshots from the gateway.</div>\n </div>\n <div class=\"muted\">${props.lastSuccessAt ? formatRelativeTimestamp(props.lastSuccessAt) : \"n/a\"}</div>\n </div>\n ${\n props.lastError\n ? html`<div class=\"callout danger\" style=\"margin-top: 12px;\">\n ${props.lastError}\n </div>`\n : nothing\n }\n <pre class=\"code-block\" style=\"margin-top: 12px;\">\n${props.snapshot ? JSON.stringify(props.snapshot, null, 2) : \"No snapshot yet.\"}\n </pre>\n </section>\n `;\n}\n\nfunction resolveChannelOrder(snapshot: ChannelsStatusSnapshot | null): ChannelKey[] {\n if (snapshot?.channelMeta?.length) {\n return snapshot.channelMeta.map((entry) => entry.id);\n }\n if (snapshot?.channelOrder?.length) {\n return snapshot.channelOrder;\n }\n return [\"whatsapp\", \"telegram\", \"discord\", \"googlechat\", \"slack\", \"signal\", \"imessage\", \"nostr\"];\n}\n\nfunction renderChannel(key: ChannelKey, props: ChannelsProps, data: ChannelsChannelData) {\n const accountCountLabel = renderChannelAccountCount(key, data.channelAccounts);\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<string, ChannelAccountSnapshot[]>,\n) {\n const label = resolveChannelLabel(props.snapshot, key);\n const status = props.snapshot?.channels?.[key] as Record<string, unknown> | 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 <div class=\"card\">\n <div class=\"card-title\">${label}</div>\n <div class=\"card-sub\">Channel status and configuration.</div>\n ${accountCountLabel}\n\n ${\n accounts.length > 0\n ? html`\n <div class=\"account-card-list\">\n ${accounts.map((account) => renderGenericAccount(account))}\n </div>\n `\n : html`\n <div class=\"status-list\" style=\"margin-top: 16px;\">\n <div>\n <span class=\"label\">Configured</span>\n <span>${configured == null ? \"n/a\" : configured ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Running</span>\n <span>${running == null ? \"n/a\" : running ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Connected</span>\n <span>${connected == null ? \"n/a\" : connected ? \"Yes\" : \"No\"}</span>\n </div>\n </div>\n `\n }\n\n ${\n lastError\n ? html`<div class=\"callout danger\" style=\"margin-top: 12px;\">\n ${lastError}\n </div>`\n : nothing\n }\n\n ${renderChannelConfigSection({ channelId: key, props })}\n </div>\n `;\n}\n\nfunction resolveChannelMetaMap(\n snapshot: ChannelsStatusSnapshot | null,\n): Record<string, ChannelUiMetaEntry> {\n if (!snapshot?.channelMeta?.length) {\n return {};\n }\n return Object.fromEntries(snapshot.channelMeta.map((entry) => [entry.id, entry]));\n}\n\nfunction resolveChannelLabel(snapshot: ChannelsStatusSnapshot | null, key: string): 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) {\n return false;\n }\n return Date.now() - account.lastInboundAt < RECENT_ACTIVITY_THRESHOLD_MS;\n}\n\nfunction deriveRunningStatus(account: ChannelAccountSnapshot): \"Yes\" | \"No\" | \"Active\" {\n if (account.running) {\n return \"Yes\";\n }\n // If we have recent inbound activity, the channel is effectively running\n if (hasRecentActivity(account)) {\n return \"Active\";\n }\n return \"No\";\n}\n\nfunction deriveConnectedStatus(account: ChannelAccountSnapshot): \"Yes\" | \"No\" | \"Active\" | \"n/a\" {\n if (account.connected === true) {\n return \"Yes\";\n }\n if (account.connected === false) {\n return \"No\";\n }\n // If connected is null/undefined but we have recent activity, show as active\n if (hasRecentActivity(account)) {\n return \"Active\";\n }\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 <div class=\"account-card\">\n <div class=\"account-card-header\">\n <div class=\"account-card-title\">${account.name || account.accountId}</div>\n <div class=\"account-card-id\">${account.accountId}</div>\n </div>\n <div class=\"status-list account-card-status\">\n <div>\n <span class=\"label\">Running</span>\n <span>${runningStatus}</span>\n </div>\n <div>\n <span class=\"label\">Configured</span>\n <span>${account.configured ? \"Yes\" : \"No\"}</span>\n </div>\n <div>\n <span class=\"label\">Connected</span>\n <span>${connectedStatus}</span>\n </div>\n <div>\n <span class=\"label\">Last inbound</span>\n <span>${account.lastInboundAt ? formatRelativeTimestamp(account.lastInboundAt) : \"n/a\"}</span>\n </div>\n ${\n account.lastError\n ? html`\n <div class=\"account-card-error\">\n ${account.lastError}\n </div>\n `\n : nothing\n }\n </div>\n </div>\n `;\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{i as e,n as t}from"./lit-BZwq2xLD.js";import{i as n,l as r}from"./format-DeRVtGzv.js";import{A as i,N as a,a as o,n as s}from"./index-
|
|
1
|
+
import{i as e,n as t}from"./lit-BZwq2xLD.js";import{i as n,l as r}from"./format-DeRVtGzv.js";import{A as i,N as a,a as o,n as s}from"./index-UVvtebBp.js";var c=e=>e??t;function l(){return[{value:`ok`,label:a(`cron.runs.runStatusOk`)},{value:`error`,label:a(`cron.runs.runStatusError`)},{value:`skipped`,label:a(`cron.runs.runStatusSkipped`)}]}function u(){return[{value:`delivered`,label:a(`cron.runs.deliveryDelivered`)},{value:`not-delivered`,label:a(`cron.runs.deliveryNotDelivered`)},{value:`unknown`,label:a(`cron.runs.deliveryUnknown`)},{value:`not-requested`,label:a(`cron.runs.deliveryNotRequested`)}]}function d(e,t,n){let r=new Set(e);return n?r.add(t):r.delete(t),Array.from(r)}function f(e,t){return e.length===0?t:e.length<=2?e.join(`, `):`${e[0]} +${e.length-1}`}function p(e){let t=[`last`,...e.channels.filter(Boolean)],n=e.form.deliveryChannel?.trim();n&&!t.includes(n)&&t.push(n);let r=new Set;return t.filter(e=>r.has(e)?!1:(r.add(e),!0))}function m(e,t){if(t===`last`)return`last`;let n=e.channelMeta?.find(e=>e.id===t);return n?.label?n.label:e.channelLabels?.[t]??t}function h(t){return e`
|
|
2
2
|
<div class="field cron-filter-dropdown" data-filter=${t.id}>
|
|
3
3
|
<span>${t.title}</span>
|
|
4
4
|
<details class="cron-filter-dropdown__details">
|
|
@@ -906,4 +906,4 @@ import{i as e,n as t}from"./lit-BZwq2xLD.js";import{i as n,l as r}from"./format-
|
|
|
906
906
|
</div>
|
|
907
907
|
</div>
|
|
908
908
|
`}export{C as renderCron};
|
|
909
|
-
//# sourceMappingURL=cron-
|
|
909
|
+
//# sourceMappingURL=cron-B6kPzumc.js.map
|