参考
SDK 概览
Downcity SDK 按角色拆分:User City 负责产品运行时调用,Admin City 负责可信侧管理调用。
这一页只做一件事:把 @downcity/city 里的调用方式总览收口到一张图里。
如果你想先看接入场景,优先读 @downcity/city。如果你要查具体方法签名,再往下读 User City 和 Admin City。
两个角色
| User City | Admin City | |
|---|---|---|
| 面向谁 | 前端、App、扩展、桌面端 | 产品后端、运维脚本、内部工具 |
| 负责什么 | AI service、custom service、公开 service | city、token、runtime env、管理侧 service |
| 常见鉴权 | user_token | admin_secret_key |
| 是否可放浏览器 | 可以 | 不可以 |
HTTP 入口
federation_url 远程和本机都统一使用 HTTP(S):
http:///https://:远程 HTTP 入口,按角色携带user_token或admin_secret_key。http://127.0.0.1:15315:本机 loopback HTTP 入口,仍然使用同一套user_token或admin_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 AIService | client.ai.text() / client.ai.stream() |
| Downcity Agent 使用 Fed 模型 | 从 client.ai.listModels() 取 CityModel,直接传给 Agent |
外部 AI SDK 生态需要 LanguageModel | 用 createOpenAICompatible({ baseURL: client.ai.base_url }) |
| 非 Fed 模型 API | 产品侧自己创建对应 provider |
OpenAI-compatible provider 请求的仍然是 Federation。Federation 会根据请求体里的
model 找到对应 provider,再由 provider 调用真实上游模型。前端只需要携带
user_token,city_id 由服务端从 token 中解析。
service、AI service 的关系
- AI service:走
client.ai.* - custom service:走
client.service(name)... - service:本质上还是
client.service(name)...,只是 service 来源于 service
例如:
rewrite、translate是你自己注册的 custom serviceaccounts、usage、payment是官方 service;Stripe、Creem 这类支付能力作为payment里的 provider 选择
对调用方来说,统一都是 City 的 service 路由空间。
注册登录链路在 SDK 里的位置
最常见的两种方式:
- 你的业务后端完成登录,再用
Admin City申请user_token - 前端直接用 guest
User City走accounts.login/start -> login/continue -> login/result或注册流程,由 accounts service 返回user_token
这两条路最终都会进入同一个用户态:
federation_url + city_id + user_token
-> new City({ role: "user", ... })
-> client.ai.* 或 client.service(...)什么时候看哪一页
- 想理解 package 组合方式,读 Packages 包
- 想理解产品接入路径,读 @downcity/city
- 想看产品侧细节,读 User City
- 想看可信侧细节,读 Admin City
- 想看最小注册登录,读 Federation Services Docs / Accounts