Download src/server/runtime-config.ts from Echocq/clawemail: direct link, hf CLI and curl.
- Browser
- Download file 7.76 kB
-
https://huggingface.co/spaces/Echocq/clawemail/resolve/main/src/server/runtime-config.ts
- Command line
-
hf download hf://spaces/Echocq/clawemail/src/server/runtime-config.ts
-
curl -L -o runtime-config.ts https://huggingface.co/spaces/Echocq/clawemail/resolve/main/src/server/runtime-config.ts
7.76 kB
| import { config } from "./config"; | |
| import { deleteSettings, getSetting, setSetting } from "./db"; | |
| import { addProvider, getProvider, removeProvider, tempConfigured, updateProvider } from "./temp-providers"; | |
| const AUTH_SETTING_KEYS = [ | |
| "claw.apiKey", | |
| "claw.dashboardCookie", | |
| "claw.userEmail", | |
| "claw.workspaceId", | |
| "claw.workspaceName", | |
| "claw.parentMailboxId", | |
| "claw.rootPrefix", | |
| "claw.domain" | |
| ]; | |
| export function getClawApiKey(): string | undefined { | |
| return getSetting("claw.apiKey") ?? config.CLAW_API_KEY; | |
| } | |
| export function requireClawApiKey(): string { | |
| const value = getClawApiKey(); | |
| if (!value) { | |
| throw new Error("CLAW_API_KEY is required for mail operations; connect Claw first"); | |
| } | |
| return value; | |
| } | |
| export function getDashboardCookie(): string | undefined { | |
| return getSetting("claw.dashboardCookie") ?? config.CLAW_DASHBOARD_COOKIE; | |
| } | |
| export function requireDashboardCookie(): string { | |
| const value = getDashboardCookie(); | |
| if (!value) { | |
| throw new Error("CLAW_DASHBOARD_COOKIE is required for mailbox management; connect Claw first"); | |
| } | |
| return value; | |
| } | |
| export function getWorkspaceId(): string { | |
| const value = getStoredWorkspaceId(); | |
| if (!value) { | |
| throw new Error("Claw workspace is not configured; connect Claw first"); | |
| } | |
| return value; | |
| } | |
| export function getParentMailboxId(): string { | |
| const value = getStoredParentMailboxId(); | |
| if (!value) { | |
| throw new Error("Claw parent mailbox is not configured; connect Claw first"); | |
| } | |
| return value; | |
| } | |
| export function getRootPrefix(): string { | |
| const value = getStoredRootPrefix(); | |
| if (!value) { | |
| throw new Error("Claw root prefix is not configured; connect Claw first"); | |
| } | |
| return value; | |
| } | |
| export function getDomain(): string { | |
| return getStoredDomain(); | |
| } | |
| export function hasClawMailConfig(): boolean { | |
| return Boolean(getClawApiKey()); | |
| } | |
| export function hasClawDashboardConfig(): boolean { | |
| return Boolean(getDashboardCookie()); | |
| } | |
| function getStoredWorkspaceId(): string | null { | |
| return getSetting("claw.workspaceId") ?? config.CLAW_WORKSPACE_ID ?? null; | |
| } | |
| function getStoredParentMailboxId(): string | null { | |
| return getSetting("claw.parentMailboxId") ?? config.CLAW_PARENT_MAILBOX_ID ?? null; | |
| } | |
| function getStoredRootPrefix(): string | null { | |
| return getSetting("claw.rootPrefix") ?? config.CLAW_ROOT_PREFIX ?? null; | |
| } | |
| function getStoredDomain(): string { | |
| return getSetting("claw.domain") ?? config.CLAW_DOMAIN; | |
| } | |
| export function getClawAuthStatus() { | |
| const apiKey = getClawApiKey(); | |
| const cookie = getDashboardCookie(); | |
| const workspaceId = cookie ? getStoredWorkspaceId() : null; | |
| const parentMailboxId = cookie ? getStoredParentMailboxId() : null; | |
| const rootPrefix = cookie ? getStoredRootPrefix() : null; | |
| const domain = cookie ? getStoredDomain() : null; | |
| return { | |
| connected: Boolean(apiKey && cookie && workspaceId && parentMailboxId && rootPrefix && domain), | |
| hasApiKey: Boolean(apiKey), | |
| hasDashboardCookie: Boolean(cookie), | |
| userEmail: getSetting("claw.userEmail") ?? null, | |
| workspaceId, | |
| workspaceName: getSetting("claw.workspaceName") ?? null, | |
| parentMailboxId, | |
| rootPrefix, | |
| domain, | |
| apiKeyPrefix: apiKey ? apiKey.slice(0, 10) : null, | |
| apiKeySuffix: apiKey ? apiKey.slice(-4) : null | |
| }; | |
| } | |
| export function saveClawAuthSettings(input: { | |
| apiKey: string; | |
| dashboardCookie: string; | |
| userEmail?: string | null; | |
| workspaceId: string; | |
| workspaceName?: string | null; | |
| parentMailboxId: string; | |
| rootPrefix: string; | |
| domain: string; | |
| }): void { | |
| setSetting("claw.apiKey", input.apiKey); | |
| setSetting("claw.dashboardCookie", input.dashboardCookie); | |
| setSetting("claw.workspaceId", input.workspaceId); | |
| setSetting("claw.parentMailboxId", input.parentMailboxId); | |
| setSetting("claw.rootPrefix", input.rootPrefix); | |
| setSetting("claw.domain", input.domain); | |
| if (input.userEmail) setSetting("claw.userEmail", input.userEmail); | |
| if (input.workspaceName) setSetting("claw.workspaceName", input.workspaceName); | |
| } | |
| export function clearClawAuthSettings(): void { | |
| deleteSettings(AUTH_SETTING_KEYS); | |
| } | |
| // ---------- 临时邮箱(多 provider;见 temp-providers.ts)---------- | |
| // 旧的「单配置」表单/接口仍可用,作用于「主 provider」(列表第一个), | |
| // 向后兼容现有 edu;新增/管理多个源走 temp-providers 的 add/update/remove。 | |
| // 密码只写不回显。 | |
| export function cfConfigured(): boolean { | |
| return tempConfigured(); | |
| } | |
| export function getCfDomain(): string { | |
| return getProvider()?.domain ?? ""; | |
| } | |
| export function getCfConfigStatus() { | |
| const primary = getProvider(); | |
| return { | |
| configured: Boolean(primary), | |
| endpoint: primary?.endpoint ?? "", | |
| domain: primary?.domain ?? "", | |
| hasPassword: Boolean(primary?.password), | |
| source: primary ? (primary.id === "edu" ? "env" : "ui") : "none" | |
| }; | |
| } | |
| export function saveCfConfig(input: { | |
| endpoint: string; | |
| domain?: string | null; | |
| password?: string | null; | |
| }): void { | |
| const primary = getProvider(); | |
| if (primary) { | |
| updateProvider(primary.id, { | |
| endpoint: input.endpoint, | |
| domain: input.domain ?? undefined, | |
| password: input.password ?? undefined | |
| }); | |
| } else { | |
| addProvider({ | |
| name: (input.domain ?? "").trim() || "temp", | |
| type: "php", | |
| endpoint: input.endpoint, | |
| domain: input.domain ?? "", | |
| password: input.password ?? "" | |
| }); | |
| } | |
| } | |
| export function clearCfConfig(): void { | |
| const primary = getProvider(); | |
| if (primary) removeProvider(primary.id); | |
| } | |
| // ---------- AI 助手(右下角气泡)配置 ---------- | |
| // OpenAI 兼容端点(base_url + key + model),provider 无关。UI 可配,存 app_settings | |
| // (随 Supabase 持久化),env 兜底。api key 只写不回显。 | |
| const AI_SETTING_KEYS = ["ai.baseUrl", "ai.apiKey", "ai.model"]; | |
| const DEFAULT_AI_MODEL = "gpt-4o-mini"; | |
| export function getAiBaseUrl(): string | undefined { | |
| const v = getSetting("ai.baseUrl") ?? config.AI_BASE_URL; | |
| return v?.replace(/\/+$/, ""); | |
| } | |
| export function getAiApiKey(): string | undefined { | |
| return getSetting("ai.apiKey") ?? config.AI_API_KEY; | |
| } | |
| export function getAiModel(): string { | |
| return getSetting("ai.model") ?? config.AI_MODEL ?? DEFAULT_AI_MODEL; | |
| } | |
| export function aiConfigured(): boolean { | |
| return Boolean(getAiBaseUrl() && getAiApiKey()); | |
| } | |
| export function getAiConfigStatus() { | |
| const baseUrl = getAiBaseUrl(); | |
| const hasKey = Boolean(getAiApiKey()); | |
| const fromSettings = Boolean(getSetting("ai.baseUrl") || getSetting("ai.apiKey")); | |
| // 只回显用户/env 真正设过的模型;没设就返回空,避免 UI 凭空冒出 gpt-4o-mini 默认值。 | |
| // (实际调用 getAiModel() 仍有 DEFAULT_AI_MODEL 兜底,不影响气泡可用。) | |
| return { | |
| configured: Boolean(baseUrl && hasKey), | |
| baseUrl: baseUrl ?? "", | |
| model: getSetting("ai.model") ?? config.AI_MODEL ?? "", | |
| hasKey, | |
| source: fromSettings ? "ui" : baseUrl || hasKey ? "env" : "none" | |
| }; | |
| } | |
| export function saveAiConfig(input: { | |
| baseUrl: string; | |
| model?: string | null; | |
| apiKey?: string | null; | |
| }): void { | |
| setSetting("ai.baseUrl", input.baseUrl.trim().replace(/\/+$/, "")); | |
| if (input.model && input.model.trim()) setSetting("ai.model", input.model.trim()); | |
| // 只在传入非空时覆盖 key,方便改 baseUrl/model 时不必重输密钥。 | |
| if (input.apiKey && input.apiKey.trim()) setSetting("ai.apiKey", input.apiKey.trim()); | |
| } | |
| export function clearAiConfig(): void { | |
| deleteSettings(AI_SETTING_KEYS); | |
| } | |