参考

环境变量

Federation 常见环境变量。

变量用途
DOWNCITY_FEDERATION_TOKEN_SIGNING_KEYFederation 内部签发和校验 user_token
DOWNCITY_CITY_DATABASE_URL可选。指定 Federation 使用的数据库 URL
OPENAI_API_KEY示例 provider key,建议通过 Admin env 写入 Federation 数据库
OPENAI_BASE_URL示例 provider base URL,建议通过 Admin env 写入 Federation 数据库

fed deploy 会交互式配置管理员 ID 和密码。密码只保存为 PBKDF2 摘要,管理员会话保存在服务端;不再使用管理员 key 环境变量。DOWNCITY_FEDERATION_TOKEN_SIGNING_KEYBETTER_AUTH_SECRET 会在 Federation 首次启动时自动写入数据库的 env 表。

DOWNCITY_CITY_DATABASE_URL 不填时,默认数据库路径是:

.base/downcity.sqlite

provider env 的使用方式

model handler 直接读取 input.env

import { createDeepSeek } from "@ai-sdk/deepseek";
import {
  AIChannel,
  read_required_env,
  type AIChannelStreamInput,
  type LanguageModelV3StreamResult,
} from "@downcity/federation";

class DeepSeekChannel extends AIChannel {
  constructor() {
    super({
      id: "deepseek",
      env: { DEEPSEEK_API_KEY: "DeepSeek API Key" },
      env_key: "DEEPSEEK_API_KEY",
      base_url: "https://api.deepseek.com",
      ai_sdk_provider_id: "deepseek",
    });
  }

  protected async stream(
    input: AIChannelStreamInput,
  ): Promise<LanguageModelV3StreamResult> {
    const deepseek = createDeepSeek({
      apiKey: read_required_env(input, this.env_key ?? ""),
      baseURL: this.base_url,
    });
    const model = deepseek(input.model.upstream_model);
    return model.doStream(input.call);
  }
}

const deepseek = new DeepSeekChannel();

所以实际约束很简单:

  • env key 名称由你自己决定
  • 建议使用大写下划线命名
  • stream() 里通过 input.env(key)read_required_env() 读取

写入数据库

可信后端可以用 FederationAdmin 写入 provider key:

await admin.env.upsert({
  key: "DEEPSEEK_API_KEY",
  value: "sk-xxx",
});

这些值会保存到 Federation 数据库的 env 表。业务 Runtime 只从 Federation 自己的 env 表读取,不再回退到 .env 或进程环境变量。

详见 AIChannel 环境变量