参考

SDK 概览

Downcity SDK 按角色拆分:User City 负责产品运行时调用,Admin City 负责可信侧管理调用。

这一页只做一件事:把 @downcity/city 里的调用方式总览收口到一张图里。

如果你想先看接入场景,优先读 @downcity/city。如果你要查具体方法签名,再往下读 User CityAdmin City

两个角色

User CityAdmin City
面向谁前端、App、扩展、桌面端产品后端、运维脚本、内部工具
负责什么AI service、custom service、公开 servicecity、token、runtime env、管理侧 service
常见鉴权user_tokenadmin_secret_key
是否可放浏览器可以不可以

HTTP 入口

federation_url 远程和本机都统一使用 HTTP(S):

  • http:// / https://:远程 HTTP 入口,按角色携带 user_tokenadmin_secret_key
  • http://127.0.0.1:15315:本机 loopback HTTP 入口,仍然使用同一套 user_tokenadmin_secret_key 鉴权模型。

用你自己的本机 HTTP server 暴露 Federation 时,产品侧仍然只拿到普通 HTTP URL。如果 AccountsService 配置了 local_login: true/v1/accounts/providers 会只返回本地登录方式,调用 accounts.login/start 并传入 provider: "local" 后会得到 login_id,再从 accounts.login/result 读取正常 user_token

四类常见调用

// 产品侧
const client = new City({
  role: "user",
  federation_url,
  city_id,
  user_token,
});

// AI Service
await client.ai.text({ prompt: "hello", model: "deepseek-v4-flash" });
await client.ai.stream({ prompt: "hello", model: "deepseek-v4-flash" });

// OpenAI-compatible AI SDK provider
const provider = createOpenAICompatible({
  name: "downcity",
  baseURL: client.ai.base_url,
  apiKey: user_token,
});

const language_model = provider.languageModel("deepseek-v4-flash");

// 自定义 Service
await client.service("translate").action("zh2en").invoke({ text: "hello" });
const login = await client.service("accounts").action("login/start").invoke({
  provider: "email",
});
await client.service("accounts").action("login/continue").invoke({
  login_id: login.login_id,
  input: { email: "[email protected]", password: "..." },
});
const session = await client.service("accounts").get("login/result", { login_id: login.login_id });

// GET action
const items = await client.service("cities").get("list");

// 支付方式
const methods = await client.payment.methods();
const checkout = await client.payment.method("stripe").invoke({
  topup_id: "topup_demo",
});

// 管理端
const admin = new City({
  role: "admin",
  federation_url,
  admin_secret_key,
});
await admin.service("cities").action("create").invoke({ name: "My App" });

AI 模型调用选择

场景推荐方式
产品代码直接请求 Fed AIServiceclient.ai.text() / client.ai.stream()
Downcity Agent 使用 Fed 模型client.ai.listModels()CityModel,直接传给 Agent
外部 AI SDK 生态需要 LanguageModelcreateOpenAICompatible({ baseURL: client.ai.base_url })
非 Fed 模型 API产品侧自己创建对应 provider

OpenAI-compatible provider 请求的仍然是 Federation。Federation 会根据请求体里的 model 找到对应 provider,再由 provider 调用真实上游模型。前端只需要携带 user_tokencity_id 由服务端从 token 中解析。

service、AI service 的关系

  • AI service:走 client.ai.*
  • custom service:走 client.service(name)...
  • service:本质上还是 client.service(name)...,只是 service 来源于 service

例如:

  • rewritetranslate 是你自己注册的 custom service
  • accountsusagepayment 是官方 service;Stripe、Creem 这类支付能力作为 payment 里的 provider 选择

对调用方来说,统一都是 City 的 service 路由空间。

注册登录链路在 SDK 里的位置

最常见的两种方式:

  1. 你的业务后端完成登录,再用 Admin City 申请 user_token
  2. 前端直接用 guest User Cityaccounts.login/start -> login/continue -> login/result 或注册流程,由 accounts service 返回 user_token

这两条路最终都会进入同一个用户态:

federation_url + city_id + user_token
  -> new City({ role: "user", ... })
  -> client.ai.* 或 client.service(...)

什么时候看哪一页

  1. 想理解 package 组合方式,读 Packages 包
  2. 想理解产品接入路径,读 @downcity/city
  3. 想看产品侧细节,读 User City
  4. 想看可信侧细节,读 Admin City
  5. 想看最小注册登录,读 Federation Services Docs / Accounts