export const SECRET_KEYS = new Set([
    "TELEGRAM_BOT_TOKEN",
    "DISCORD_BOT_TOKEN",
    "SLACK_BOT_TOKEN",
    "SLACK_APP_TOKEN",
    "SLACK_SIGNING_SECRET",
    "MATRIX_ACCESS_TOKEN",
    "CODEX_API_KEY",
    "HERMES_API_KEY",
    "OPENCLAW_GATEWAY_TOKEN",
    "OPENCLAW_GATEWAY_PASSWORD",
    "OPENAI_API_KEY",
    "HF_TOKEN",
    "HUGGINGFACE_HUB_TOKEN",
    "TELEGRAM_WEBHOOK_SECRET",
]);
const DISCORD_SETTING_HELP = {
    DISCORD_ENABLED: "Set this to true after you create the Discord application, configure the bot token, and invite the bot to the server.",
    DISCORD_BOT_TOKEN: "Discord Developer Portal: open your application, go to Bot, then copy or reset the bot token. Store only the token value here.",
    DISCORD_CLIENT_ID: "Discord Developer Portal: open your application, go to General Information, then copy Application ID. This is the client id used for slash commands.",
    DISCORD_GUILD_IDS: "Enable Developer Mode in Discord, right-click a server, choose Copy Server ID, then paste one or more comma-separated ids for fast guild slash-command registration.",
    DISCORD_ALLOWED_GUILD_IDS: "Enable Developer Mode in Discord, right-click each allowed server, choose Copy Server ID, then enter the comma-separated allow-list. Leave blank to rely on NordRelay user/group access.",
    DISCORD_ALLOWED_CHANNEL_IDS: "Enable Developer Mode in Discord, right-click a channel or thread, choose Copy Channel ID or Copy Thread ID, then enter the comma-separated allow-list. Leave blank to rely on registered channel access.",
    DISCORD_MESSAGE_CONTENT_ENABLED: "Turn this on only if the bot has Message Content Intent enabled in the Discord Developer Portal under Bot > Privileged Gateway Intents.",
    DISCORD_COMMAND_MODE: "Use slash for registered slash commands only, message for text commands like /session only, or both when Message Content Intent is enabled.",
    DISCORD_AUTO_REGISTER_COMMANDS: "When enabled, NordRelay registers slash commands at startup. Guild ids update quickly; global command registration can take longer to appear in Discord.",
    DISCORD_CLI_MIRROR_MODE: "Overrides the channel-neutral mirror default for Discord only. Leave blank to use NORDRELAY_CLI_MIRROR_MODE.",
    DISCORD_CLI_MIRROR_MIN_UPDATE_MS: "Discord edit/update throttle for mirrored CLI activity. Increase this if Discord rate limits streaming status updates.",
    DISCORD_NOTIFY_MODE: "Overrides the channel-neutral completion notification default for Discord only. Leave blank to use NORDRELAY_NOTIFY_MODE.",
    DISCORD_QUIET_HOURS: "Use a local-time range like 22-7, off, or blank to inherit the channel-neutral quiet-hours setting.",
    DISCORD_AUTO_SEND_ARTIFACTS: "Overrides automatic artifact upload behavior for Discord only. Leave blank to use NORDRELAY_AUTO_SEND_ARTIFACTS.",
};
const SLACK_SETTING_HELP = {
    SLACK_ENABLED: "Create a Slack app, install it into the workspace, then set bot/app tokens before enabling Slack.",
    SLACK_BOT_TOKEN: "Slack app OAuth & Permissions: copy the bot token that starts with xoxb-.",
    SLACK_APP_TOKEN: "Slack app Basic Information: create an app-level token with connections:write. Required for Socket Mode.",
    SLACK_SIGNING_SECRET: "Slack app Basic Information: copy Signing Secret. Required only when Socket Mode is disabled.",
    SLACK_ALLOWED_TEAM_IDS: "Optional workspace allow-list. Copy Team IDs from Slack event payloads or app diagnostics.",
    SLACK_ALLOWED_CHANNEL_IDS: "Optional channel allow-list before NordRelay user/group checks. Copy channel IDs from Slack channel details.",
    SLACK_COMMAND: "Slash command configured in the Slack app. Defaults to /nordrelay.",
};
const MATRIX_SETTING_HELP = {
    MATRIX_ENABLED: "Create a Matrix bot user or access token, invite it to the desired rooms, then enable Matrix.",
    MATRIX_HOMESERVER_URL: "Base URL of the Matrix homeserver, for example https://matrix.org or https://matrix.example.com.",
    MATRIX_ACCESS_TOKEN: "Matrix access token for the bot user. Create it from the bot account or your homeserver admin tooling and store only the token value here.",
    MATRIX_USER_ID: "Full Matrix user id for the bot account, for example @nordrelay:example.com.",
    MATRIX_DEVICE_ID: "Optional device id belonging to the access token.",
    MATRIX_AUTOJOIN_INVITES: "Automatically join rooms when the bot user is invited.",
    MATRIX_ALLOWED_ROOM_IDS: "Optional room allow-list before NordRelay user/group checks. Use room ids like !roomid:example.com.",
    MATRIX_MESSAGE_CONTENT_ENABLED: "Read regular Matrix text messages as prompts. Disable this if commands should be the only message surface.",
    MATRIX_COMMAND_PREFIX: "Text command prefix for Matrix, for example !nr. Slash-style /session messages are also recognized.",
};
const TELEGRAM_SETTING_HELP = {
    TELEGRAM_ENABLED: "Enable this only after the BotFather token is configured and NordRelay users/chats are allowed through the user management system.",
    TELEGRAM_BOT_TOKEN: "Telegram BotFather: open @BotFather, create a bot with /newbot, then paste only the token value.",
    TELEGRAM_TRANSPORT: "Use polling for the simplest setup. Use webhook only when this NordRelay instance is reachable from Telegram through public HTTPS.",
    TELEGRAM_WEBHOOK_URL: "Public HTTPS base URL for Telegram webhook delivery, for example https://relay.example.com.",
    TELEGRAM_WEBHOOK_HOST: "Local interface where NordRelay binds the webhook listener. Use 127.0.0.1 behind a reverse proxy or 0.0.0.0 only when the endpoint is protected.",
    TELEGRAM_WEBHOOK_PORT: "Local port for the Telegram webhook listener.",
    TELEGRAM_WEBHOOK_PATH: "Webhook request path registered with Telegram. It must start with /.",
    TELEGRAM_WEBHOOK_SECRET: "Optional secret token Telegram sends in X-Telegram-Bot-Api-Secret-Token. Use a random value for webhook mode.",
};
export const SETTING_DEFINITIONS = [
    setting("NORDRELAY_WEBUI_ENABLED", "Enable WebUI", "Dashboard", "boolean", "Allow the local dashboard to start and count as a valid access surface.", true, undefined, "Controls whether the local WebUI dashboard may start. Keep enabled for browser-only setups without chat adapters."),
    setting("NORDRELAY_AUTOSTART_ENABLED", "Auto-start NordRelay", "Dashboard", "boolean", "Create or remove a user-level autostart entry for the NordRelay connector.", false, undefined, "On Linux this manages a systemd user service, on macOS a LaunchAgent, and on Windows a Task Scheduler entry."),
    setting("NORDRELAY_WEBUI_AUTOSTART_ENABLED", "Auto-start WebUI", "Dashboard", "boolean", "Create or remove a user-level autostart entry for the NordRelay WebUI dashboard.", false, undefined, "The WebUI autostart runs `nordrelay web`, which also starts the connector when needed."),
    setting("NORDRELAY_WEBAUTHN_ENABLED", "Enable passkeys", "Security", "boolean", "Allow WebAuthn/passkey registration and login in the WebUI.", true),
    setting("NORDRELAY_WEBAUTHN_RP_NAME", "Passkey RP name", "Security", "string", "Display name shown by browsers during passkey registration.", true),
    setting("NORDRELAY_WEBAUTHN_RP_ID", "Passkey RP ID", "Security", "string", "Optional relying-party domain. Leave empty to use the dashboard hostname.", true),
    setting("NORDRELAY_WEBAUTHN_ORIGIN", "Passkey origin", "Security", "string", "Optional expected WebUI origin, for example https://relay.example.com. Leave empty to derive it from the request.", true),
    setting("NORDRELAY_PLUGINS_ENABLED", "Enable plugins", "Plugins", "boolean", "Allow NordRelay to load installed plugin metadata and expose plugin extension points.", true),
    setting("NORDRELAY_PLUGIN_GITHUB_INSTALL_ENABLED", "Allow GitHub plugin installs", "Plugins", "boolean", "Allow installing plugins directly from GitHub repository URLs.", true),
    setting("NORDRELAY_PLUGIN_ALLOW_BUILD_SCRIPTS", "Allow plugin build scripts", "Plugins", "boolean", "Reserved for plugin package build hooks. Keep disabled unless you trust the plugin source.", false),
    telegramSetting("TELEGRAM_ENABLED", "Enable Telegram", "boolean", "Start the Telegram bot adapter.", true),
    telegramSetting("TELEGRAM_BOT_TOKEN", "Telegram bot token", "secret", "BotFather token.", true),
    telegramSetting("TELEGRAM_TRANSPORT", "Telegram transport", "string", "polling or webhook.", true, ["polling", "webhook"]),
    telegramSetting("TELEGRAM_WEBHOOK_URL", "Webhook public URL", "string", "Public base URL for webhook mode.", true),
    telegramSetting("TELEGRAM_WEBHOOK_HOST", "Webhook bind host", "string", "Local webhook bind host.", true),
    telegramSetting("TELEGRAM_WEBHOOK_PORT", "Webhook bind port", "number", "Local webhook bind port.", true),
    telegramSetting("TELEGRAM_WEBHOOK_PATH", "Webhook path", "string", "Webhook request path.", true),
    telegramSetting("TELEGRAM_WEBHOOK_SECRET", "Webhook secret", "secret", "Optional Telegram webhook secret token.", true),
    discordSetting("DISCORD_ENABLED", "Enable Discord", "boolean", "Start the Discord bot adapter.", true),
    discordSetting("DISCORD_BOT_TOKEN", "Discord bot token", "secret", "Discord bot token.", true),
    discordSetting("DISCORD_CLIENT_ID", "Discord client ID", "string", "Discord application/client id used for slash command registration.", true),
    discordSetting("DISCORD_GUILD_IDS", "Discord guild IDs", "list", "Comma-separated guild ids for instant guild slash-command registration.", true),
    discordSetting("DISCORD_ALLOWED_GUILD_IDS", "Allowed Discord guilds", "list", "Optional comma-separated guild allow-list.", true),
    discordSetting("DISCORD_ALLOWED_CHANNEL_IDS", "Allowed Discord channels", "list", "Optional comma-separated channel allow-list before user/group checks.", true),
    discordSetting("DISCORD_MESSAGE_CONTENT_ENABLED", "Message content intent", "boolean", "Read regular Discord text messages as prompts. Requires enabling the privileged intent in Discord.", true),
    discordSetting("DISCORD_COMMAND_MODE", "Discord command mode", "string", "slash, message, or both.", true, ["slash", "message", "both"]),
    discordSetting("DISCORD_AUTO_REGISTER_COMMANDS", "Auto-register slash commands", "boolean", "Register Discord slash commands on startup when client id is configured.", true),
    discordSetting("DISCORD_CLI_MIRROR_MODE", "Discord mirror override", "string", "Optional Discord override for CLI mirror mode. Uses the NordRelay default when unset.", false, ["off", "status", "final", "full"]),
    discordSetting("DISCORD_CLI_MIRROR_MIN_UPDATE_MS", "Discord mirror update override", "number", "Optional Discord override for mirrored edit interval.", true),
    discordSetting("DISCORD_NOTIFY_MODE", "Discord notify override", "string", "Optional Discord override for completion notifications.", false, ["off", "minimal", "all"]),
    discordSetting("DISCORD_QUIET_HOURS", "Discord quiet hours override", "string", "Optional Discord quiet hours override. Use HH-HH, off, or leave blank for default.", false),
    discordSetting("DISCORD_AUTO_SEND_ARTIFACTS", "Discord auto-send artifacts override", "boolean", "Optional Discord override for automatic artifact summaries/uploads.", false),
    slackSetting("SLACK_ENABLED", "Enable Slack", "boolean", "Start the Slack bot adapter.", true),
    slackSetting("SLACK_BOT_TOKEN", "Slack bot token", "secret", "Slack bot token.", true),
    slackSetting("SLACK_APP_TOKEN", "Slack app token", "secret", "Slack app-level token for Socket Mode.", true),
    slackSetting("SLACK_SIGNING_SECRET", "Slack signing secret", "secret", "Slack signing secret for HTTP Events mode.", true),
    slackSetting("SLACK_SOCKET_MODE", "Slack Socket Mode", "boolean", "Use Slack Socket Mode instead of an HTTP events receiver.", true),
    slackSetting("SLACK_PORT", "Slack HTTP port", "number", "HTTP port used when Slack Socket Mode is disabled.", true),
    slackSetting("SLACK_ALLOWED_TEAM_IDS", "Allowed Slack teams", "list", "Optional comma-separated Slack team/workspace allow-list.", true),
    slackSetting("SLACK_ALLOWED_CHANNEL_IDS", "Allowed Slack channels", "list", "Optional comma-separated Slack channel allow-list before user/group checks.", true),
    slackSetting("SLACK_MESSAGE_CONTENT_ENABLED", "Slack message content", "boolean", "Read regular Slack text messages as prompts.", true),
    slackSetting("SLACK_COMMAND", "Slack Slash command", "string", "Slash command configured in Slack.", true),
    slackSetting("SLACK_CLI_MIRROR_MODE", "Slack mirror override", "string", "Optional Slack override for CLI mirror mode. Uses the NordRelay default when unset.", false, ["off", "status", "final", "full"]),
    slackSetting("SLACK_CLI_MIRROR_MIN_UPDATE_MS", "Slack mirror update override", "number", "Optional Slack override for mirrored edit interval.", true),
    slackSetting("SLACK_NOTIFY_MODE", "Slack notify override", "string", "Optional Slack override for completion notifications.", false, ["off", "minimal", "all"]),
    slackSetting("SLACK_QUIET_HOURS", "Slack quiet hours override", "string", "Optional Slack quiet hours override. Use HH-HH, off, or leave blank for default.", false),
    slackSetting("SLACK_AUTO_SEND_ARTIFACTS", "Slack auto-send artifacts override", "boolean", "Optional Slack override for automatic artifact summaries/uploads.", false),
    matrixSetting("MATRIX_ENABLED", "Enable Matrix", "boolean", "Start the Matrix bot adapter.", true),
    matrixSetting("MATRIX_HOMESERVER_URL", "Matrix homeserver URL", "string", "Matrix homeserver base URL.", true),
    matrixSetting("MATRIX_ACCESS_TOKEN", "Matrix access token", "secret", "Matrix access token for the bot user.", true),
    matrixSetting("MATRIX_USER_ID", "Matrix bot user ID", "string", "Full Matrix user id for the bot account.", true),
    matrixSetting("MATRIX_DEVICE_ID", "Matrix device ID", "string", "Optional Matrix device id.", true),
    matrixSetting("MATRIX_AUTOJOIN_INVITES", "Auto-join invites", "boolean", "Automatically join rooms where the bot is invited.", true),
    matrixSetting("MATRIX_ALLOWED_ROOM_IDS", "Allowed Matrix rooms", "list", "Optional comma-separated room allow-list before user/group checks.", true),
    matrixSetting("MATRIX_MESSAGE_CONTENT_ENABLED", "Matrix message content", "boolean", "Read regular Matrix text messages as prompts.", true),
    matrixSetting("MATRIX_COMMAND_PREFIX", "Matrix command prefix", "string", "Text command prefix, for example !nr.", true),
    matrixSetting("MATRIX_SYNC_TIMEOUT_MS", "Matrix sync timeout", "number", "Matrix /sync long-poll timeout.", true),
    matrixSetting("MATRIX_POLL_TIMEOUT_MS", "Matrix poll timeout", "number", "HTTP timeout for each Matrix /sync request.", true),
    matrixSetting("MATRIX_CLI_MIRROR_MODE", "Matrix mirror override", "string", "Optional Matrix override for CLI mirror mode. Uses the NordRelay default when unset.", false, ["off", "status", "final", "full"]),
    matrixSetting("MATRIX_CLI_MIRROR_MIN_UPDATE_MS", "Matrix mirror update override", "number", "Optional Matrix override for mirrored edit interval.", true),
    matrixSetting("MATRIX_NOTIFY_MODE", "Matrix notify override", "string", "Optional Matrix override for completion notifications.", false, ["off", "minimal", "all"]),
    matrixSetting("MATRIX_QUIET_HOURS", "Matrix quiet hours override", "string", "Optional Matrix quiet hours override. Use HH-HH, off, or leave blank for default.", false),
    matrixSetting("MATRIX_AUTO_SEND_ARTIFACTS", "Matrix auto-send artifacts override", "boolean", "Optional Matrix override for automatic artifact summaries/uploads.", false),
    setting("NORDRELAY_CODEX_ENABLED", "Enable Codex", "Agents", "boolean", "Allow Codex sessions.", true),
    setting("NORDRELAY_PI_ENABLED", "Enable Pi", "Agents", "boolean", "Allow Pi sessions.", true),
    setting("NORDRELAY_HERMES_ENABLED", "Enable Hermes", "Agents", "boolean", "Allow Hermes sessions through the Hermes API Server.", true),
    setting("NORDRELAY_OPENCLAW_ENABLED", "Enable OpenClaw", "Agents", "boolean", "Allow OpenClaw sessions through the OpenClaw Gateway.", true),
    setting("NORDRELAY_CLAUDE_CODE_ENABLED", "Enable Claude Code", "Agents", "boolean", "Allow Claude Code sessions through the Claude Agent SDK.", true),
    setting("NORDRELAY_DEFAULT_AGENT", "Default agent", "Agents", "string", "codex, pi, hermes, openclaw, or claude-code.", true, ["codex", "pi", "hermes", "openclaw", "claude-code"]),
    setting("CODEX_API_KEY", "Codex API key", "Codex", "secret", "Optional Codex SDK API key.", true),
    setting("CODEX_CLI_PATH", "Codex CLI path", "Codex", "string", "Optional explicit Codex executable path.", true),
    setting("CODEX_USE_BUNDLED_CLI", "Use bundled Codex CLI", "Codex", "boolean", "Force SDK-bundled CLI instead of host CLI.", true),
    setting("CODEX_MODEL", "Default Codex model", "Codex", "string", "Default model for new Codex threads.", false),
    setting("CODEX_SYNC_INTERVAL_MS", "Codex sync interval", "Codex", "number", "Local state sync interval.", true),
    setting("CODEX_EXTERNAL_BUSY_CHECK_MS", "External busy check", "Codex", "number", "External CLI busy polling interval.", true),
    setting("CODEX_EXTERNAL_BUSY_STALE_MS", "External busy stale timeout", "Codex", "number", "External CLI stale timeout.", true),
    setting("CODEX_EXTERNAL_APPROVAL_CONTROL", "External approval control", "Codex", "boolean", "Allow NordRelay to submit approval choices to a trusted local Codex CLI terminal when the OS permits TTY input control.", true, undefined, "Leave disabled unless this machine is trusted. Detection and display still work when disabled; only remote approval button submission is blocked."),
    setting("CODEX_EXTERNAL_APPROVAL_SUDO_HELPER", "External approval sudo helper", "Codex", "boolean", "Allow NordRelay to fall back to a passwordless sudo helper for local Codex CLI terminal input when same-user TTY injection is denied.", true, undefined, "This is for trusted local machines only. It requires sudo -n python3 to work and never runs through a shell."),
    setting("CODEX_SANDBOX_MODE", "Codex sandbox mode", "Codex", "string", "read-only, workspace-write, or danger-full-access.", true, ["read-only", "workspace-write", "danger-full-access"]),
    setting("CODEX_APPROVAL_POLICY", "Codex approval policy", "Codex", "string", "never, on-request, on-failure, or untrusted.", true, ["never", "on-request", "on-failure", "untrusted"]),
    setting("CODEX_LAUNCH_PROFILES_JSON", "Launch profiles JSON", "Codex", "json", "Additional launch profile definitions.", true),
    setting("CODEX_DEFAULT_LAUNCH_PROFILE", "Default launch profile", "Codex", "string", "Launch profile ID used by default.", true),
    setting("ENABLE_UNSAFE_LAUNCH_PROFILES", "Enable unsafe profiles", "Codex", "boolean", "Expose danger-full-access profiles.", true),
    setting("PI_CLI_PATH", "Pi CLI path", "Pi", "string", "Optional Pi executable path.", true),
    setting("PI_SESSION_DIR", "Pi session dir", "Pi", "string", "Optional Pi session directory.", true),
    setting("PI_DEFAULT_MODEL", "Default Pi model", "Pi", "string", "Default Pi model slug.", false),
    setting("PI_DEFAULT_THINKING", "Default Pi thinking", "Pi", "string", "off, minimal, low, medium, high, or xhigh.", false, ["off", "minimal", "low", "medium", "high", "xhigh"]),
    setting("PI_DEFAULT_PROFILE", "Default Pi profile", "Pi", "string", "default, readonly, no-tools, offline, or safe-offline.", true, ["default", "readonly", "no-tools", "offline", "safe-offline"]),
    setting("HERMES_CLI_PATH", "Hermes CLI path", "Hermes", "string", "Optional Hermes executable path.", true),
    setting("HERMES_HOME", "Hermes home", "Hermes", "string", "Optional Hermes home directory. Defaults to ~/.hermes.", true),
    setting("HERMES_STATE_DB_PATH", "Hermes state DB path", "Hermes", "string", "Optional explicit Hermes state.db path.", true),
    setting("HERMES_API_BASE_URL", "Hermes API base URL", "Hermes", "string", "Hermes API Server base URL.", true),
    setting("HERMES_API_KEY", "Hermes API key", "Hermes", "secret", "Bearer token for the Hermes API Server.", true),
    setting("HERMES_DEFAULT_MODEL", "Default Hermes model", "Hermes", "string", "Default model label sent to Hermes API runs.", false),
    setting("HERMES_DEFAULT_REASONING", "Default Hermes reasoning", "Hermes", "string", "none, minimal, low, medium, high, or xhigh.", false, ["none", "minimal", "low", "medium", "high", "xhigh"]),
    setting("HERMES_DEFAULT_PROFILE", "Default Hermes profile", "Hermes", "string", "default, safe, readonly, or yolo.", true, ["default", "safe", "readonly", "yolo"]),
    setting("OPENCLAW_CLI_PATH", "OpenClaw CLI path", "OpenClaw", "string", "Optional OpenClaw executable path.", true),
    setting("OPENCLAW_GATEWAY_URL", "OpenClaw Gateway URL", "OpenClaw", "string", "OpenClaw Gateway WebSocket URL.", true),
    setting("OPENCLAW_GATEWAY_TOKEN", "OpenClaw Gateway token", "OpenClaw", "secret", "Shared-secret token for the OpenClaw Gateway.", true),
    setting("OPENCLAW_GATEWAY_PASSWORD", "OpenClaw Gateway password", "OpenClaw", "secret", "Shared-secret password for the OpenClaw Gateway.", true),
    setting("OPENCLAW_AGENT_ID", "OpenClaw agent ID", "OpenClaw", "string", "Configured OpenClaw agent id, for example main or work.", false),
    setting("OPENCLAW_HOME", "OpenClaw home", "OpenClaw", "string", "Optional OpenClaw home directory. Defaults to ~/.openclaw.", true),
    setting("OPENCLAW_STATE_DIR", "OpenClaw state dir", "OpenClaw", "string", "Optional OpenClaw state directory.", true),
    setting("OPENCLAW_DEFAULT_MODEL", "Default OpenClaw model", "OpenClaw", "string", "Default OpenClaw model id.", false),
    setting("OPENCLAW_DEFAULT_THINKING", "Default OpenClaw thinking", "OpenClaw", "string", "off, minimal, low, medium, high, or xhigh.", false, ["off", "minimal", "low", "medium", "high", "xhigh"]),
    setting("OPENCLAW_DEFAULT_PROFILE", "Default OpenClaw profile", "OpenClaw", "string", "default, safe, readonly, local, or deliver.", true, ["default", "safe", "readonly", "local", "deliver"]),
    setting("CLAUDE_CODE_CLI_PATH", "Claude Code CLI path", "Claude Code", "string", "Optional Claude Code executable path. Defaults to claude on PATH or the SDK bundled runtime.", true),
    setting("CLAUDE_CONFIG_DIR", "Claude config dir", "Claude Code", "string", "Optional Claude config directory. Defaults to ~/.claude.", true),
    setting("CLAUDE_CODE_DEFAULT_MODEL", "Default Claude Code model", "Claude Code", "string", "Default Claude Code model alias or model id.", false),
    setting("CLAUDE_CODE_DEFAULT_EFFORT", "Default Claude Code effort", "Claude Code", "string", "off, low, medium, high, or xhigh.", false, ["off", "low", "medium", "high", "xhigh"]),
    setting("CLAUDE_CODE_DEFAULT_PROFILE", "Default Claude Code profile", "Claude Code", "string", "default, accept-edits, plan, readonly, no-tools, or bypass-permissions.", true, ["default", "accept-edits", "plan", "readonly", "no-tools", "bypass-permissions"]),
    setting("CLAUDE_CODE_MAX_TURNS", "Claude Code max turns", "Claude Code", "number", "Maximum agentic turns for each Claude Code prompt.", false),
    setting("CONNECTOR_LOG_FORMAT", "Log format", "Operations", "string", "text or json.", true, ["text", "json"]),
    setting("TOOL_VERBOSITY", "Tool verbosity", "Operations", "string", "all, summary, errors-only, or none.", false, ["all", "summary", "errors-only", "none"]),
    setting("SHOW_TURN_TOKEN_USAGE", "Show turn token usage", "Operations", "boolean", "Append per-turn token usage.", false),
    setting("ENABLE_TELEGRAM_LOGIN", "Enable Telegram login", "Operations", "boolean", "Allow /login and /logout.", true),
    setting("ENABLE_TELEGRAM_REACTIONS", "Enable Telegram reactions", "Operations", "boolean", "Send Telegram reactions.", true),
    setting("TELEGRAM_RATE_LIMIT_MIN_INTERVAL_MS", "Telegram send interval", "Operations", "number", "Minimum send interval.", true),
    setting("TELEGRAM_EDIT_MIN_INTERVAL_MS", "Telegram edit interval", "Operations", "number", "Minimum edit interval.", true),
    setting("NORDRELAY_CLI_MIRROR_MODE", "Default CLI mirror mode", "Operations", "string", "Default mirror mode for chat adapters: off, status, final, or full.", false, ["off", "status", "final", "full"]),
    setting("NORDRELAY_CLI_MIRROR_MIN_UPDATE_MS", "Default mirror update interval", "Operations", "number", "Default minimum mirrored edit interval.", true),
    setting("NORDRELAY_WEB_CLI_MIRROR_MODE", "WebUI mirror override", "Operations", "string", "Optional WebUI override for CLI mirror mode. Uses the NordRelay default when unset.", false, ["off", "status", "final", "full"]),
    setting("NORDRELAY_WEB_CLI_MIRROR_MIN_UPDATE_MS", "WebUI mirror update override", "Operations", "number", "Optional WebUI override for mirrored status interval.", true),
    setting("NORDRELAY_NOTIFY_MODE", "Default notify mode", "Operations", "string", "Default completion notifications: off, minimal, or all.", false, ["off", "minimal", "all"]),
    setting("NORDRELAY_QUIET_HOURS", "Default quiet hours", "Operations", "string", "Default quiet hours. Use HH-HH, off, or leave blank.", false),
    setting("NORDRELAY_ARTIFACTS_ENABLED", "Enable artifact tracking", "Artifacts", "boolean", "Scan and persist generated artifact reports after turns. Disabled by default; enable only when needed.", false),
    setting("NORDRELAY_AUTO_SEND_ARTIFACTS", "Default auto-send artifacts", "Artifacts", "boolean", "Default automatic artifact summaries/uploads for chat adapters.", false),
    setting("NORDRELAY_ARTIFACT_DELIVERY", "Default artifact delivery", "Artifacts", "string", "Default artifact delivery mode for chat adapters.", false, ["manual-only", "summary", "summary-with-actions", "auto-files", "auto-zip", "images-only", "off"]),
    setting("TELEGRAM_CLI_MIRROR_MODE", "Telegram mirror override", "Operations", "string", "Optional Telegram override for CLI mirror mode. Uses the NordRelay default when unset.", false, ["off", "status", "final", "full"]),
    setting("TELEGRAM_CLI_MIRROR_MIN_UPDATE_MS", "Telegram mirror update override", "Operations", "number", "Optional Telegram override for mirrored edit interval.", true),
    setting("TELEGRAM_NOTIFY_MODE", "Telegram notify override", "Operations", "string", "Optional Telegram override for completion notifications.", false, ["off", "minimal", "all"]),
    setting("TELEGRAM_QUIET_HOURS", "Telegram quiet hours override", "Operations", "string", "Optional Telegram quiet hours override. Use HH-HH, off, or leave blank for default.", false),
    setting("TELEGRAM_REDACT_PATTERNS", "Redaction patterns", "Operations", "list", "Additional comma-separated regex patterns.", true),
    setting("NORDRELAY_UPDATE_METHOD", "Update method", "Operations", "string", "auto, npm, or git.", true, ["auto", "npm", "git"]),
    setting("MAX_FILE_SIZE", "Max file size", "Artifacts", "number", "Max inbound/outbound file size.", true),
    setting("ARTIFACT_MAX_TOTAL_BYTES", "Artifact quota bytes", "Artifacts", "number", "Maximum managed artifact storage size. 0 disables quota enforcement.", true),
    setting("ARTIFACT_WARN_PERCENT", "Artifact quota warning percent", "Artifacts", "number", "Warn when managed artifact storage reaches this percentage.", true),
    setting("ARTIFACT_SAFE_FILE_POLICY", "Artifact safe-file policy", "Artifacts", "string", "off, warn, or block for sensitive-looking artifact paths.", false, ["off", "warn", "block"]),
    setting("ARTIFACT_RETENTION_DAYS", "Artifact retention days", "Artifacts", "number", "Days before pruning.", true),
    setting("ARTIFACT_MAX_TURNS", "Max artifact turns", "Artifacts", "number", "Maximum artifact turns retained.", true),
    setting("ARTIFACT_MAX_INBOX_DIRS", "Max inbox dirs", "Artifacts", "number", "Maximum inbox dirs retained.", true),
    setting("ARTIFACT_IGNORE_DIRS", "Artifact ignore dirs", "Artifacts", "list", "Extra ignored dirs or relative paths.", true),
    setting("ARTIFACT_IGNORE_GLOBS", "Artifact ignore globs", "Artifacts", "list", "Extra ignored glob patterns.", true),
    setting("TELEGRAM_AUTO_SEND_ARTIFACTS", "Telegram auto-send artifacts override", "Artifacts", "boolean", "Optional Telegram override for automatic artifact summaries/uploads.", false),
    setting("TELEGRAM_ARTIFACT_DELIVERY", "Telegram artifact delivery", "Artifacts", "string", "Optional Telegram artifact delivery mode override.", false, ["manual-only", "summary", "summary-with-actions", "auto-files", "auto-zip", "images-only", "off"]),
    setting("DISCORD_ARTIFACT_DELIVERY", "Discord artifact delivery", "Artifacts", "string", "Optional Discord artifact delivery mode override.", false, ["manual-only", "summary", "summary-with-actions", "auto-files", "auto-zip", "images-only", "off"]),
    setting("SLACK_ARTIFACT_DELIVERY", "Slack artifact delivery", "Artifacts", "string", "Optional Slack artifact delivery mode override.", false, ["manual-only", "summary", "summary-with-actions", "auto-files", "auto-zip", "images-only", "off"]),
    setting("MATRIX_ARTIFACT_DELIVERY", "Matrix artifact delivery", "Artifacts", "string", "Optional Matrix artifact delivery mode override.", false, ["manual-only", "summary", "summary-with-actions", "auto-files", "auto-zip", "images-only", "off"]),
    setting("WORKSPACE_ALLOWED_ROOTS", "Workspace allowed roots", "Workspace", "list", "Restrict selectable workspaces.", true),
    setting("WORKSPACE_WARN_ROOTS", "Workspace warn roots", "Workspace", "list", "Warn for broad workspace roots.", true),
    setting("NORDRELAY_WORKSPACE", "Default workspace", "Workspace", "string", "Default workspace for new sessions, workspace policies, and workspace-scoped artifact grouping.", true),
    setting("NORDRELAY_SESSION_WORKSPACE_MODE", "Session workspace mode", "Workspace", "string", "shared keeps current behavior, worktree creates an isolated Git worktree per new session, attached leaves external CLI sessions untouched.", false, ["shared", "worktree", "attached"]),
    setting("NORDRELAY_SESSION_WORKTREE_ROOT", "Session worktree root", "Workspace", "string", "Directory where isolated session worktrees and integration worktrees are created.", true),
    setting("NORDRELAY_SESSION_WORKTREE_BRANCH_PREFIX", "Worktree branch prefix", "Workspace", "string", "Git branch prefix used for session and integration worktrees.", true),
    setting("NORDRELAY_STATE_BACKEND", "State backend", "Workspace", "string", "json or sqlite.", true, ["json", "sqlite"]),
    setting("NORDRELAY_AUDIT_MAX_EVENTS", "Audit max events", "Workspace", "number", "Retained audit events.", true),
    setting("NORDRELAY_SESSION_LOCK_TTL_MS", "Session lock TTL", "Workspace", "number", "Write-lock TTL.", true),
    setting("NORDRELAY_DASHBOARD_CACHE_TTL_MS", "Dashboard cache TTL", "Workspace", "number", "Stale-while-refresh TTL for expensive dashboard API snapshots.", true),
    setting("NORDRELAY_ACTIVE_DISCOVERY_CACHE_TTL_MS", "Active discovery cache TTL", "Workspace", "number", "TTL for active-session discovery snapshots across Codex, Pi, Hermes, Claude Code, and recorded sessions. Set 0 to disable this cache.", true),
    setting("NORDRELAY_OPENCLAW_ACTIVE_DISCOVERY_CACHE_TTL_MS", "OpenClaw active discovery TTL", "Workspace", "number", "TTL for OpenClaw active-session discovery. Use a higher value when OpenClaw discovery is slow; set 0 to disable this cache.", true),
    setting("NORDRELAY_UNIFIED_JOB_MAX_ITEMS", "Unified job history", "Workspace", "number", "Maximum persisted unified jobs retained for the WebUI jobs view.", true),
    setting("NORDRELAY_VERSION_CACHE_TTL_MS", "Version cache TTL", "Workspace", "number", "NPM version cache TTL.", true),
    setting("NORDRELAY_CLI_VERSION_CACHE_TTL_MS", "CLI version cache TTL", "Workspace", "number", "Installed agent CLI version cache TTL.", true),
    setting("NORDRELAY_PEER_ENABLED", "Enable peer server", "Peers", "boolean", "Expose the dedicated authenticated NordRelay peer API.", true),
    setting("NORDRELAY_PEER_NAME", "Peer display name", "Peers", "string", "Human-readable name shown to paired NordRelay instances.", true),
    setting("NORDRELAY_PEER_HOST", "Peer bind host", "Peers", "string", "Bind host for the peer API. Use 127.0.0.1 for local-only or a LAN/interface IP when explicitly exposing peers.", true),
    setting("NORDRELAY_PEER_PORT", "Peer port", "Peers", "number", "Port for the peer API.", true),
    setting("NORDRELAY_PEER_PUBLIC_URL", "Peer public URL", "Peers", "string", "Optional public URL other instances should use for this node.", true),
    setting("NORDRELAY_PEER_TLS_ENABLED", "Peer TLS enabled", "Peers", "boolean", "Serve the peer API over HTTPS with an automatically generated local certificate.", true),
    setting("NORDRELAY_PEER_REQUIRE_TLS", "Require peer TLS", "Peers", "boolean", "Reject plaintext peer serving on non-loopback hosts.", true),
    setting("NORDRELAY_PEER_HEALTH_CHECK_MS", "Peer health interval", "Peers", "number", "Background reachability check interval for configured peers. Use 0 to disable.", true),
    setting("NORDRELAY_PEER_DISCOVERY_TIMEOUT_MS", "Peer discovery timeout", "Peers", "number", "Per-host LAN discovery timeout in milliseconds.", true),
    setting("NORDRELAY_PEER_OUTBOUND_RELAY_ENABLED", "Outbound peer relay", "Peers", "boolean", "Poll paired peers for relay requests so this node can be controlled without inbound port forwarding.", true),
    setting("NORDRELAY_PEER_OUTBOUND_RELAY_PEERS", "Outbound relay peers", "Peers", "list", "Optional peer IDs/node IDs to poll. Leave empty to poll all enabled outbound peers.", true),
    setting("NORDRELAY_PEER_OUTBOUND_RELAY_POLL_MS", "Outbound relay poll interval", "Peers", "number", "Delay between outbound relay polls in milliseconds.", true),
    setting("OPENAI_API_KEY", "OpenAI API key", "Voice", "secret", "Whisper fallback API key.", true),
    setting("VOICE_PREFERRED_BACKEND", "Voice backend", "Voice", "string", "auto, parakeet, faster-whisper, cohere-transcribe, or openai.", false, ["auto", "parakeet", "faster-whisper", "cohere-transcribe", "openai"]),
    setting("VOICE_DEFAULT_LANGUAGE", "Voice language", "Voice", "string", "Default transcription language. Leave empty or use auto for backend auto-detect where supported. Use ISO language codes such as de or en; Parakeet ignores this value and Cohere Transcribe expects one of its 14 supported language codes.", false),
    setting("VOICE_TRANSCRIBE_ONLY", "Voice transcribe only", "Voice", "boolean", "Do not send voice transcripts as prompts.", false),
    setting("FFMPEG_PATH", "ffmpeg path", "Voice", "string", "Optional absolute ffmpeg executable path used when service/autostart PATH cannot find ffmpeg.", true),
    setting("FASTER_WHISPER_PYTHON", "faster-whisper Python", "Voice", "string", "Python executable.", true),
    setting("FASTER_WHISPER_MODEL", "faster-whisper model", "Voice", "string", "Model name.", true),
    setting("FASTER_WHISPER_DEVICE", "faster-whisper device", "Voice", "string", "cpu, cuda, etc.", true),
    setting("FASTER_WHISPER_COMPUTE_TYPE", "faster-whisper compute type", "Voice", "string", "int8, float16, etc.", true),
    setting("FASTER_WHISPER_LANGUAGE", "faster-whisper language", "Voice", "string", "Fixed transcription language.", true),
    setting("FASTER_WHISPER_TIMEOUT_MS", "faster-whisper timeout", "Voice", "number", "Transcription timeout.", true),
    setting("COHERE_TRANSCRIBE_PYTHON", "Cohere Transcribe Python", "Voice", "string", "Python executable with torch and transformers installed. Defaults to FASTER_WHISPER_PYTHON.", true),
    setting("COHERE_TRANSCRIBE_MODEL", "Cohere Transcribe model", "Voice", "string", "Hugging Face model id.", true),
    setting("COHERE_TRANSCRIBE_DEVICE", "Cohere Transcribe device", "Voice", "string", "auto, cpu, cuda, etc.", true),
    setting("COHERE_TRANSCRIBE_DTYPE", "Cohere Transcribe dtype", "Voice", "string", "auto, float16, bfloat16, float32, etc.", true),
    setting("COHERE_TRANSCRIBE_PUNCTUATION", "Cohere punctuation", "Voice", "boolean", "Enable punctuation/casing for Cohere Transcribe output.", true),
    setting("COHERE_TRANSCRIBE_MAX_NEW_TOKENS", "Cohere max tokens", "Voice", "number", "Maximum generated transcription tokens.", true),
    setting("COHERE_TRANSCRIBE_TIMEOUT_MS", "Cohere timeout", "Voice", "number", "Local Cohere Transcribe timeout.", true),
    setting("HF_TOKEN", "Hugging Face token", "Voice", "secret", "Optional Hugging Face token for gated local model downloads.", true),
    setting("NORDRELAY_DASHBOARD_HOST", "Dashboard host", "Dashboard", "string", "WebUI bind host.", true),
    setting("NORDRELAY_DASHBOARD_PORT", "Dashboard port", "Dashboard", "number", "WebUI bind port.", true),
    setting("NORDRELAY_ENV_FILE", "Env file path", "Dashboard", "string", "Optional explicit env-file path used by the CLI wrapper and dashboard.", true),
];
const EXAMPLE_VALUES = {
    "NORDRELAY_WEBUI_ENABLED": "true",
    "NORDRELAY_AUTOSTART_ENABLED": "false",
    "NORDRELAY_WEBUI_AUTOSTART_ENABLED": "false",
    "NORDRELAY_WEBAUTHN_ENABLED": "true",
    "NORDRELAY_WEBAUTHN_RP_NAME": "NordRelay",
    "NORDRELAY_WEBAUTHN_RP_ID": "",
    "NORDRELAY_WEBAUTHN_ORIGIN": "",
    "NORDRELAY_PLUGINS_ENABLED": "true",
    "NORDRELAY_PLUGIN_GITHUB_INSTALL_ENABLED": "true",
    "NORDRELAY_PLUGIN_ALLOW_BUILD_SCRIPTS": "false",
    "TELEGRAM_ENABLED": "true",
    "TELEGRAM_BOT_TOKEN": "123456789:replace-me",
    "DISCORD_ENABLED": "false",
    "DISCORD_BOT_TOKEN": "",
    "DISCORD_CLIENT_ID": "",
    "DISCORD_GUILD_IDS": "",
    "DISCORD_ALLOWED_GUILD_IDS": "",
    "DISCORD_ALLOWED_CHANNEL_IDS": "",
    "DISCORD_MESSAGE_CONTENT_ENABLED": "true",
    "DISCORD_COMMAND_MODE": "both",
    "DISCORD_AUTO_REGISTER_COMMANDS": "true",
    "DISCORD_CLI_MIRROR_MODE": "",
    "DISCORD_CLI_MIRROR_MIN_UPDATE_MS": "",
    "DISCORD_NOTIFY_MODE": "",
    "DISCORD_QUIET_HOURS": "",
    "DISCORD_AUTO_SEND_ARTIFACTS": "",
    "SLACK_ENABLED": "false",
    "SLACK_BOT_TOKEN": "",
    "SLACK_APP_TOKEN": "",
    "SLACK_SIGNING_SECRET": "",
    "SLACK_SOCKET_MODE": "true",
    "SLACK_PORT": "3000",
    "SLACK_ALLOWED_TEAM_IDS": "",
    "SLACK_ALLOWED_CHANNEL_IDS": "",
    "SLACK_MESSAGE_CONTENT_ENABLED": "true",
    "SLACK_COMMAND": "/nordrelay",
    "SLACK_CLI_MIRROR_MODE": "",
    "SLACK_CLI_MIRROR_MIN_UPDATE_MS": "",
    "SLACK_NOTIFY_MODE": "",
    "SLACK_QUIET_HOURS": "",
    "SLACK_AUTO_SEND_ARTIFACTS": "",
    "MATRIX_ENABLED": "false",
    "MATRIX_HOMESERVER_URL": "",
    "MATRIX_ACCESS_TOKEN": "",
    "MATRIX_USER_ID": "",
    "MATRIX_DEVICE_ID": "",
    "MATRIX_AUTOJOIN_INVITES": "true",
    "MATRIX_ALLOWED_ROOM_IDS": "",
    "MATRIX_MESSAGE_CONTENT_ENABLED": "true",
    "MATRIX_COMMAND_PREFIX": "!nr",
    "MATRIX_SYNC_TIMEOUT_MS": "30000",
    "MATRIX_POLL_TIMEOUT_MS": "35000",
    "MATRIX_CLI_MIRROR_MODE": "",
    "MATRIX_CLI_MIRROR_MIN_UPDATE_MS": "",
    "MATRIX_NOTIFY_MODE": "",
    "MATRIX_QUIET_HOURS": "",
    "MATRIX_AUTO_SEND_ARTIFACTS": "",
    "NORDRELAY_CODEX_ENABLED": "true",
    "NORDRELAY_PI_ENABLED": "false",
    "NORDRELAY_HERMES_ENABLED": "false",
    "NORDRELAY_OPENCLAW_ENABLED": "false",
    "NORDRELAY_CLAUDE_CODE_ENABLED": "false",
    "NORDRELAY_DEFAULT_AGENT": "codex",
    "NORDRELAY_SESSION_WORKSPACE_MODE": "shared",
    "NORDRELAY_SESSION_WORKTREE_ROOT": "",
    "NORDRELAY_SESSION_WORKTREE_BRANCH_PREFIX": "nr/session",
    "CODEX_API_KEY": "",
    "CODEX_CLI_PATH": "",
    "CODEX_USE_BUNDLED_CLI": "false",
    "CODEX_MODEL": "",
    "CODEX_SYNC_INTERVAL_MS": "10000",
    "CODEX_EXTERNAL_BUSY_CHECK_MS": "5000",
    "CODEX_EXTERNAL_BUSY_STALE_MS": "300000",
    "CODEX_EXTERNAL_APPROVAL_CONTROL": "false",
    "CODEX_EXTERNAL_APPROVAL_SUDO_HELPER": "false",
    "CODEX_SANDBOX_MODE": "workspace-write",
    "CODEX_APPROVAL_POLICY": "never",
    "CODEX_LAUNCH_PROFILES_JSON": "",
    "CODEX_DEFAULT_LAUNCH_PROFILE": "default",
    "ENABLE_UNSAFE_LAUNCH_PROFILES": "false",
    "PI_CLI_PATH": "",
    "PI_SESSION_DIR": "",
    "PI_DEFAULT_MODEL": "",
    "PI_DEFAULT_THINKING": "medium",
    "PI_DEFAULT_PROFILE": "default",
    "HERMES_CLI_PATH": "",
    "HERMES_HOME": "",
    "HERMES_STATE_DB_PATH": "",
    "HERMES_API_BASE_URL": "http://127.0.0.1:8642",
    "HERMES_API_KEY": "",
    "HERMES_DEFAULT_MODEL": "",
    "HERMES_DEFAULT_REASONING": "",
    "HERMES_DEFAULT_PROFILE": "default",
    "OPENCLAW_CLI_PATH": "",
    "OPENCLAW_GATEWAY_URL": "ws://127.0.0.1:18789",
    "OPENCLAW_GATEWAY_TOKEN": "",
    "OPENCLAW_GATEWAY_PASSWORD": "",
    "OPENCLAW_AGENT_ID": "main",
    "OPENCLAW_HOME": "",
    "OPENCLAW_STATE_DIR": "",
    "OPENCLAW_DEFAULT_MODEL": "",
    "OPENCLAW_DEFAULT_THINKING": "",
    "OPENCLAW_DEFAULT_PROFILE": "default",
    "CLAUDE_CODE_CLI_PATH": "",
    "CLAUDE_CONFIG_DIR": "",
    "CLAUDE_CODE_DEFAULT_MODEL": "",
    "CLAUDE_CODE_DEFAULT_EFFORT": "",
    "CLAUDE_CODE_DEFAULT_PROFILE": "default",
    "CLAUDE_CODE_MAX_TURNS": "100",
    "CONNECTOR_LOG_FORMAT": "text",
    "TOOL_VERBOSITY": "summary",
    "SHOW_TURN_TOKEN_USAGE": "false",
    "ENABLE_TELEGRAM_LOGIN": "true",
    "ENABLE_TELEGRAM_REACTIONS": "false",
    "TELEGRAM_RATE_LIMIT_MIN_INTERVAL_MS": "80",
    "TELEGRAM_EDIT_MIN_INTERVAL_MS": "1200",
    "TELEGRAM_TRANSPORT": "polling",
    "TELEGRAM_WEBHOOK_URL": "",
    "TELEGRAM_WEBHOOK_HOST": "127.0.0.1",
    "TELEGRAM_WEBHOOK_PORT": "8080",
    "TELEGRAM_WEBHOOK_PATH": "/telegram/webhook",
    "TELEGRAM_WEBHOOK_SECRET": "",
    "NORDRELAY_CLI_MIRROR_MODE": "status",
    "NORDRELAY_CLI_MIRROR_MIN_UPDATE_MS": "4000",
    "NORDRELAY_WEB_CLI_MIRROR_MODE": "",
    "NORDRELAY_WEB_CLI_MIRROR_MIN_UPDATE_MS": "",
    "NORDRELAY_NOTIFY_MODE": "minimal",
    "NORDRELAY_QUIET_HOURS": "",
    "NORDRELAY_ARTIFACTS_ENABLED": "false",
    "NORDRELAY_AUTO_SEND_ARTIFACTS": "false",
    "NORDRELAY_ARTIFACT_DELIVERY": "manual-only",
    "TELEGRAM_CLI_MIRROR_MODE": "",
    "TELEGRAM_CLI_MIRROR_MIN_UPDATE_MS": "",
    "TELEGRAM_NOTIFY_MODE": "",
    "TELEGRAM_QUIET_HOURS": "",
    "TELEGRAM_REDACT_PATTERNS": "",
    "MAX_FILE_SIZE": "20971520",
    "ARTIFACT_MAX_TOTAL_BYTES": "0",
    "ARTIFACT_WARN_PERCENT": "80",
    "ARTIFACT_SAFE_FILE_POLICY": "warn",
    "ARTIFACT_RETENTION_DAYS": "7",
    "ARTIFACT_MAX_TURNS": "30",
    "ARTIFACT_MAX_INBOX_DIRS": "30",
    "ARTIFACT_IGNORE_DIRS": "",
    "ARTIFACT_IGNORE_GLOBS": "",
    "TELEGRAM_AUTO_SEND_ARTIFACTS": "",
    "TELEGRAM_ARTIFACT_DELIVERY": "",
    "DISCORD_ARTIFACT_DELIVERY": "",
    "SLACK_ARTIFACT_DELIVERY": "",
    "MATRIX_ARTIFACT_DELIVERY": "",
    "NORDRELAY_STATE_BACKEND": "json",
    "NORDRELAY_AUDIT_MAX_EVENTS": "1000",
    "NORDRELAY_SESSION_LOCK_TTL_MS": "1800000",
    "NORDRELAY_DASHBOARD_CACHE_TTL_MS": "10000",
    "NORDRELAY_ACTIVE_DISCOVERY_CACHE_TTL_MS": "5000",
    "NORDRELAY_OPENCLAW_ACTIVE_DISCOVERY_CACHE_TTL_MS": "120000",
    "NORDRELAY_UNIFIED_JOB_MAX_ITEMS": "1000",
    "NORDRELAY_VERSION_CACHE_TTL_MS": "3600000",
    "NORDRELAY_CLI_VERSION_CACHE_TTL_MS": "60000",
    "NORDRELAY_PEER_ENABLED": "false",
    "NORDRELAY_PEER_NAME": "",
    "NORDRELAY_PEER_HOST": "127.0.0.1",
    "NORDRELAY_PEER_PORT": "31979",
    "NORDRELAY_PEER_PUBLIC_URL": "",
    "NORDRELAY_PEER_TLS_ENABLED": "true",
    "NORDRELAY_PEER_REQUIRE_TLS": "true",
    "NORDRELAY_PEER_HEALTH_CHECK_MS": "60000",
    "NORDRELAY_PEER_DISCOVERY_TIMEOUT_MS": "650",
    "NORDRELAY_PEER_OUTBOUND_RELAY_ENABLED": "false",
    "NORDRELAY_PEER_OUTBOUND_RELAY_PEERS": "",
    "NORDRELAY_PEER_OUTBOUND_RELAY_POLL_MS": "1000",
    "NORDRELAY_DASHBOARD_HOST": "127.0.0.1",
    "NORDRELAY_DASHBOARD_PORT": "31878",
    "NORDRELAY_ENV_FILE": "",
    "WORKSPACE_ALLOWED_ROOTS": "",
    "WORKSPACE_WARN_ROOTS": "",
    "OPENAI_API_KEY": "",
    "VOICE_PREFERRED_BACKEND": "auto",
    "VOICE_DEFAULT_LANGUAGE": "",
    "VOICE_TRANSCRIBE_ONLY": "false",
    "FFMPEG_PATH": "",
    "FASTER_WHISPER_PYTHON": ".venv/bin/python",
    "FASTER_WHISPER_MODEL": "base",
    "FASTER_WHISPER_DEVICE": "cpu",
    "FASTER_WHISPER_COMPUTE_TYPE": "int8",
    "FASTER_WHISPER_LANGUAGE": "",
    "FASTER_WHISPER_TIMEOUT_MS": "600000",
    "COHERE_TRANSCRIBE_PYTHON": "",
    "COHERE_TRANSCRIBE_MODEL": "CohereLabs/cohere-transcribe-03-2026",
    "COHERE_TRANSCRIBE_DEVICE": "auto",
    "COHERE_TRANSCRIBE_DTYPE": "auto",
    "COHERE_TRANSCRIBE_PUNCTUATION": "true",
    "COHERE_TRANSCRIBE_MAX_NEW_TOKENS": "1024",
    "COHERE_TRANSCRIBE_TIMEOUT_MS": "1800000",
    "HF_TOKEN": "",
};
const GROUP_INTROS = {
    Telegram: "Telegram bot and transport settings.",
    Discord: "Discord bot settings. Discord is opt-in and uses the same NordRelay users, groups, and permissions as Telegram.",
    Slack: "Slack bot settings. Slack is opt-in and uses the same NordRelay users, groups, and permissions as Telegram and Discord.",
    Matrix: "Matrix bot settings. Matrix is opt-in and uses the same NordRelay users, groups, and permissions as Telegram, Discord, and Slack.",
    Agents: "Agent access. Codex is enabled by default; Pi, Hermes, OpenClaw, and Claude Code are opt-in.",
    Codex: "Codex defaults for newly created or reattached sessions.",
    Pi: "Pi coding agent defaults.",
    Hermes: "Hermes Agent defaults. Hermes uses the Hermes API Server.",
    OpenClaw: "OpenClaw Agent defaults. OpenClaw uses the OpenClaw Gateway WebSocket RPC endpoint.",
    "Claude Code": "Claude Code defaults. NordRelay uses the Claude Agent SDK and the host claude CLI when present.",
    Operations: "Runtime output, logging, update, and Telegram behavior controls.",
    Artifacts: "File, artifact, and retention controls.",
    Workspace: "State and workspace guardrails.",
    Peers: "Optional NordRelay-to-NordRelay federation. Pairing is explicit, authenticated, scoped, and TLS-protected.",
    Voice: "Optional voice transcription settings.",
    Dashboard: "Local WebUI dashboard. User login is required for every page, API route, SSE stream, artifact download, and health endpoint.",
    Plugins: "Local and GitHub plugin management. Plugins are explicit installs, permission-gated, and disabled unless enabled by an admin.",
};
export function envExampleValue(key) {
    return EXAMPLE_VALUES[key] ?? "";
}
export function renderEnvExample() {
    const lines = [
        "# NordRelay runtime config example.",
        "# Access is managed with NordRelay users, groups, linked chat identities, and enabled group/guild channels.",
        "# Create the first admin with `nordrelay init` or `nordrelay user create-admin`.",
    ];
    let currentGroup = "";
    for (const definition of SETTING_DEFINITIONS) {
        if (definition.group !== currentGroup) {
            currentGroup = definition.group;
            lines.push('', `# ${currentGroup}`, `# ${GROUP_INTROS[currentGroup] ?? definition.description}`);
        }
        lines.push(`# ${definition.description}`);
        if (definition.options?.length) {
            lines.push(`# Options: ${definition.options.join(", ")}`);
        }
        lines.push(`${definition.key}=${envExampleValue(definition.key)}`);
    }
    return `${lines.join('\n')}\n`;
}
function setting(key, label, group, kind, description, restartRequired, options, help) {
    return { key, label, group, kind, description, help, restartRequired, options };
}
function discordSetting(key, label, kind, description, restartRequired, options) {
    return setting(key, label, "Discord", kind, description, restartRequired, options, DISCORD_SETTING_HELP[key]);
}
function telegramSetting(key, label, kind, description, restartRequired, options) {
    return setting(key, label, "Telegram", kind, description, restartRequired, options, TELEGRAM_SETTING_HELP[key]);
}
function slackSetting(key, label, kind, description, restartRequired, options) {
    return setting(key, label, "Slack", kind, description, restartRequired, options, SLACK_SETTING_HELP[key]);
}
function matrixSetting(key, label, kind, description, restartRequired, options) {
    return setting(key, label, "Matrix", kind, description, restartRequired, options, MATRIX_SETTING_HELP[key]);
}
