@downcity/city 0.2.82 → 0.2.93

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (230) hide show
  1. package/README.md +10 -10
  2. package/bin/client/city.d.ts +90 -0
  3. package/bin/client/city.d.ts.map +1 -0
  4. package/bin/{city → client}/city.js +32 -22
  5. package/bin/client/city.js.map +1 -0
  6. package/bin/client/types.d.ts +77 -0
  7. package/bin/client/types.d.ts.map +1 -0
  8. package/bin/client/types.js +8 -0
  9. package/bin/{core → client}/types.js.map +1 -1
  10. package/bin/{core → federation}/auth/authenticator.d.ts +7 -7
  11. package/bin/federation/auth/authenticator.d.ts.map +1 -0
  12. package/bin/{core → federation}/auth/authenticator.js +15 -15
  13. package/bin/federation/auth/authenticator.js.map +1 -0
  14. package/bin/federation/auth/token-signer.d.ts.map +1 -0
  15. package/bin/{core → federation}/auth/token-signer.js +4 -4
  16. package/bin/federation/auth/token-signer.js.map +1 -0
  17. package/bin/{core → federation}/auth/types.d.ts +6 -6
  18. package/bin/federation/auth/types.d.ts.map +1 -0
  19. package/bin/federation/auth/types.js.map +1 -0
  20. package/bin/federation/federation-env-catalog.d.ts +13 -0
  21. package/bin/federation/federation-env-catalog.d.ts.map +1 -0
  22. package/bin/{core/base/base-env-catalog.js → federation/federation-env-catalog.js} +5 -5
  23. package/bin/federation/federation-env-catalog.js.map +1 -0
  24. package/bin/{core/base/base-init.d.ts → federation/federation-init.d.ts} +17 -17
  25. package/bin/federation/federation-init.d.ts.map +1 -0
  26. package/bin/{core/base/base-init.js → federation/federation-init.js} +27 -27
  27. package/bin/federation/federation-init.js.map +1 -0
  28. package/bin/federation/federation-instruction.d.ts +11 -0
  29. package/bin/federation/federation-instruction.d.ts.map +1 -0
  30. package/bin/{core/base/base-instruction.js → federation/federation-instruction.js} +4 -4
  31. package/bin/federation/federation-instruction.js.map +1 -0
  32. package/bin/{core/base/base-router.d.ts → federation/federation-router.d.ts} +11 -11
  33. package/bin/federation/federation-router.d.ts.map +1 -0
  34. package/bin/{core/base/base-router.js → federation/federation-router.js} +62 -45
  35. package/bin/federation/federation-router.js.map +1 -0
  36. package/bin/{core/base/base-runtime.d.ts → federation/federation-runtime.d.ts} +6 -6
  37. package/bin/federation/federation-runtime.d.ts.map +1 -0
  38. package/bin/{core/base/base-runtime.js → federation/federation-runtime.js} +10 -10
  39. package/bin/federation/federation-runtime.js.map +1 -0
  40. package/bin/{core/base/base.d.ts → federation/federation.d.ts} +15 -15
  41. package/bin/federation/federation.d.ts.map +1 -0
  42. package/bin/{core/base/base.js → federation/federation.js} +22 -22
  43. package/bin/federation/federation.js.map +1 -0
  44. package/bin/{core → federation}/runtime.d.ts +9 -9
  45. package/bin/federation/runtime.d.ts.map +1 -0
  46. package/bin/federation/runtime.js +13 -0
  47. package/bin/federation/runtime.js.map +1 -0
  48. package/bin/{core → federation}/types.d.ts +6 -6
  49. package/bin/federation/types.d.ts.map +1 -0
  50. package/bin/{city/user → federation}/types.js.map +1 -1
  51. package/bin/index.d.ts +23 -26
  52. package/bin/index.d.ts.map +1 -1
  53. package/bin/index.js +13 -15
  54. package/bin/index.js.map +1 -1
  55. package/bin/{city → pact}/admin/index.d.ts +23 -7
  56. package/bin/pact/admin/index.d.ts.map +1 -0
  57. package/bin/{city → pact}/admin/index.js +21 -8
  58. package/bin/pact/admin/index.js.map +1 -0
  59. package/bin/{city → pact}/admin/types.d.ts +7 -1
  60. package/bin/pact/admin/types.d.ts.map +1 -0
  61. package/bin/pact/admin/types.js.map +1 -0
  62. package/bin/{city → pact}/http.d.ts.map +1 -1
  63. package/bin/{city → pact}/http.js.map +1 -1
  64. package/bin/{city → pact}/invoker/ai/index.d.ts +1 -1
  65. package/bin/{city → pact}/invoker/ai/index.d.ts.map +1 -1
  66. package/bin/{city → pact}/invoker/ai/index.js +1 -1
  67. package/bin/{city → pact}/invoker/ai/index.js.map +1 -1
  68. package/bin/{city → pact}/invoker/ai/stream.d.ts +1 -1
  69. package/bin/{city → pact}/invoker/ai/stream.d.ts.map +1 -1
  70. package/bin/{city → pact}/invoker/ai/stream.js +1 -1
  71. package/bin/{city → pact}/invoker/ai/stream.js.map +1 -1
  72. package/bin/{city → pact}/invoker/ai/types.d.ts +2 -2
  73. package/bin/{city → pact}/invoker/ai/types.d.ts.map +1 -1
  74. package/bin/pact/invoker/ai/types.js +9 -0
  75. package/bin/pact/invoker/ai/types.js.map +1 -0
  76. package/bin/{city → pact}/invoker/balance/index.d.ts.map +1 -1
  77. package/bin/{city → pact}/invoker/balance/index.js.map +1 -1
  78. package/bin/{city → pact}/invoker/balance/types.d.ts.map +1 -1
  79. package/bin/pact/invoker/balance/types.js.map +1 -0
  80. package/bin/pact/invoker/cities/index.d.ts +46 -0
  81. package/bin/pact/invoker/cities/index.d.ts.map +1 -0
  82. package/bin/{city/invoker/towns → pact/invoker/cities}/index.js +16 -16
  83. package/bin/pact/invoker/cities/index.js.map +1 -0
  84. package/bin/pact/invoker/cities/types.d.ts +46 -0
  85. package/bin/pact/invoker/cities/types.d.ts.map +1 -0
  86. package/bin/pact/invoker/cities/types.js +5 -0
  87. package/bin/pact/invoker/cities/types.js.map +1 -0
  88. package/bin/{city → pact}/invoker/env/index.d.ts +2 -2
  89. package/bin/{city → pact}/invoker/env/index.d.ts.map +1 -1
  90. package/bin/{city → pact}/invoker/env/index.js +2 -2
  91. package/bin/{city → pact}/invoker/env/index.js.map +1 -1
  92. package/bin/{city → pact}/invoker/env/types.d.ts +2 -2
  93. package/bin/{city → pact}/invoker/env/types.d.ts.map +1 -1
  94. package/bin/pact/invoker/env/types.js +5 -0
  95. package/bin/pact/invoker/env/types.js.map +1 -0
  96. package/bin/{city → pact}/invoker/invoker.d.ts +9 -9
  97. package/bin/{city → pact}/invoker/invoker.d.ts.map +1 -1
  98. package/bin/{city → pact}/invoker/invoker.js +11 -11
  99. package/bin/{city → pact}/invoker/invoker.js.map +1 -1
  100. package/bin/{city → pact}/invoker/payment/index.d.ts +1 -1
  101. package/bin/{city → pact}/invoker/payment/index.d.ts.map +1 -1
  102. package/bin/{city → pact}/invoker/payment/index.js +1 -1
  103. package/bin/{city → pact}/invoker/payment/index.js.map +1 -1
  104. package/bin/{city → pact}/invoker/payment/types.d.ts +1 -1
  105. package/bin/{city → pact}/invoker/payment/types.d.ts.map +1 -1
  106. package/bin/pact/invoker/payment/types.js.map +1 -0
  107. package/bin/{city → pact}/user/index.d.ts +5 -5
  108. package/bin/{city → pact}/user/index.d.ts.map +1 -1
  109. package/bin/{city → pact}/user/index.js +9 -9
  110. package/bin/{city → pact}/user/index.js.map +1 -1
  111. package/bin/{city → pact}/user/types.d.ts +3 -3
  112. package/bin/{city → pact}/user/types.d.ts.map +1 -1
  113. package/bin/pact/user/types.js.map +1 -0
  114. package/bin/service/ai/ai-service.js +3 -3
  115. package/bin/service/ai/helpers.js +2 -2
  116. package/bin/service/ai/job-types.d.ts +8 -8
  117. package/bin/service/ai/job-types.d.ts.map +1 -1
  118. package/bin/service/ai/schema.d.ts +4 -4
  119. package/bin/service/ai/schema.js +6 -6
  120. package/bin/service/ai/schema.js.map +1 -1
  121. package/bin/service/cities/cities-service.d.ts +15 -0
  122. package/bin/service/cities/cities-service.d.ts.map +1 -0
  123. package/bin/service/{towns/towns-service.js → cities/cities-service.js} +17 -17
  124. package/bin/service/cities/cities-service.js.map +1 -0
  125. package/bin/service/cities/city-store.d.ts +17 -0
  126. package/bin/service/cities/city-store.d.ts.map +1 -0
  127. package/bin/service/{towns/town-store.js → cities/city-store.js} +17 -17
  128. package/bin/service/cities/city-store.js.map +1 -0
  129. package/bin/service/{towns → cities}/schema.d.ts +23 -23
  130. package/bin/service/cities/schema.d.ts.map +1 -0
  131. package/bin/service/cities/schema.js +60 -0
  132. package/bin/service/cities/schema.js.map +1 -0
  133. package/bin/service/cities/types.d.ts +51 -0
  134. package/bin/service/cities/types.d.ts.map +1 -0
  135. package/bin/service/cities/types.js +7 -0
  136. package/bin/service/cities/types.js.map +1 -0
  137. package/bin/service/env/env-service.d.ts +2 -2
  138. package/bin/service/env/env-service.js +3 -3
  139. package/bin/service/env/env-service.js.map +1 -1
  140. package/bin/service/env/types.d.ts +2 -2
  141. package/bin/service/env/types.js +1 -1
  142. package/bin/service/installable-service.d.ts +43 -12
  143. package/bin/service/installable-service.d.ts.map +1 -1
  144. package/bin/service/installable-service.js +20 -3
  145. package/bin/service/installable-service.js.map +1 -1
  146. package/bin/service/instruction.d.ts +2 -2
  147. package/bin/service/instruction.js +5 -5
  148. package/bin/service/instruction.js.map +1 -1
  149. package/bin/service/service.d.ts +45 -9
  150. package/bin/service/service.d.ts.map +1 -1
  151. package/bin/service/service.js +32 -2
  152. package/bin/service/service.js.map +1 -1
  153. package/package.json +3 -3
  154. package/bin/city/admin/index.d.ts.map +0 -1
  155. package/bin/city/admin/index.js.map +0 -1
  156. package/bin/city/admin/types.d.ts.map +0 -1
  157. package/bin/city/admin/types.js.map +0 -1
  158. package/bin/city/city.d.ts +0 -73
  159. package/bin/city/city.d.ts.map +0 -1
  160. package/bin/city/city.js.map +0 -1
  161. package/bin/city/index.d.ts +0 -20
  162. package/bin/city/index.d.ts.map +0 -1
  163. package/bin/city/index.js +0 -14
  164. package/bin/city/index.js.map +0 -1
  165. package/bin/city/invoker/ai/types.js +0 -9
  166. package/bin/city/invoker/ai/types.js.map +0 -1
  167. package/bin/city/invoker/balance/types.js.map +0 -1
  168. package/bin/city/invoker/env/types.js +0 -5
  169. package/bin/city/invoker/env/types.js.map +0 -1
  170. package/bin/city/invoker/payment/types.js.map +0 -1
  171. package/bin/city/invoker/towns/index.d.ts +0 -46
  172. package/bin/city/invoker/towns/index.d.ts.map +0 -1
  173. package/bin/city/invoker/towns/index.js.map +0 -1
  174. package/bin/city/invoker/towns/types.d.ts +0 -46
  175. package/bin/city/invoker/towns/types.d.ts.map +0 -1
  176. package/bin/city/invoker/towns/types.js +0 -5
  177. package/bin/city/invoker/towns/types.js.map +0 -1
  178. package/bin/city/types/city.d.ts +0 -71
  179. package/bin/city/types/city.d.ts.map +0 -1
  180. package/bin/city/types/city.js +0 -8
  181. package/bin/city/types/city.js.map +0 -1
  182. package/bin/core/auth/authenticator.d.ts.map +0 -1
  183. package/bin/core/auth/authenticator.js.map +0 -1
  184. package/bin/core/auth/token-signer.d.ts.map +0 -1
  185. package/bin/core/auth/token-signer.js.map +0 -1
  186. package/bin/core/auth/types.d.ts.map +0 -1
  187. package/bin/core/auth/types.js.map +0 -1
  188. package/bin/core/base/base-env-catalog.d.ts +0 -13
  189. package/bin/core/base/base-env-catalog.d.ts.map +0 -1
  190. package/bin/core/base/base-env-catalog.js.map +0 -1
  191. package/bin/core/base/base-init.d.ts.map +0 -1
  192. package/bin/core/base/base-init.js.map +0 -1
  193. package/bin/core/base/base-instruction.d.ts +0 -11
  194. package/bin/core/base/base-instruction.d.ts.map +0 -1
  195. package/bin/core/base/base-instruction.js.map +0 -1
  196. package/bin/core/base/base-router.d.ts.map +0 -1
  197. package/bin/core/base/base-router.js.map +0 -1
  198. package/bin/core/base/base-runtime.d.ts.map +0 -1
  199. package/bin/core/base/base-runtime.js.map +0 -1
  200. package/bin/core/base/base.d.ts.map +0 -1
  201. package/bin/core/base/base.js.map +0 -1
  202. package/bin/core/runtime.d.ts.map +0 -1
  203. package/bin/core/runtime.js +0 -13
  204. package/bin/core/runtime.js.map +0 -1
  205. package/bin/core/types.d.ts.map +0 -1
  206. package/bin/service/towns/schema.d.ts.map +0 -1
  207. package/bin/service/towns/schema.js +0 -60
  208. package/bin/service/towns/schema.js.map +0 -1
  209. package/bin/service/towns/town-store.d.ts +0 -17
  210. package/bin/service/towns/town-store.d.ts.map +0 -1
  211. package/bin/service/towns/town-store.js.map +0 -1
  212. package/bin/service/towns/towns-service.d.ts +0 -15
  213. package/bin/service/towns/towns-service.d.ts.map +0 -1
  214. package/bin/service/towns/towns-service.js.map +0 -1
  215. package/bin/service/towns/types.d.ts +0 -51
  216. package/bin/service/towns/types.d.ts.map +0 -1
  217. package/bin/service/towns/types.js +0 -7
  218. package/bin/service/towns/types.js.map +0 -1
  219. /package/bin/{core → federation}/auth/token-signer.d.ts +0 -0
  220. /package/bin/{core → federation}/auth/types.js +0 -0
  221. /package/bin/{core → federation}/types.js +0 -0
  222. /package/bin/{city → pact}/admin/types.js +0 -0
  223. /package/bin/{city → pact}/http.d.ts +0 -0
  224. /package/bin/{city → pact}/http.js +0 -0
  225. /package/bin/{city → pact}/invoker/balance/index.d.ts +0 -0
  226. /package/bin/{city → pact}/invoker/balance/index.js +0 -0
  227. /package/bin/{city → pact}/invoker/balance/types.d.ts +0 -0
  228. /package/bin/{city → pact}/invoker/balance/types.js +0 -0
  229. /package/bin/{city → pact}/invoker/payment/types.js +0 -0
  230. /package/bin/{city → pact}/user/types.js +0 -0
package/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  它负责这些共用能力:
6
6
 
7
7
  - 挂载 `Service` / `AIService`
8
- - 初始化内置 `towns` / `env` 表
8
+ - 初始化内置 `cities` / `env` 表
9
9
  - 校验 `user_token` 和 `admin_secret_key`
10
10
  - 暴露统一的 `/v1/*` HTTP 路由
11
11
  - 提供 env、数据库、hook 和鉴权上下文
@@ -19,7 +19,7 @@ pnpm add @downcity/city
19
19
  ## 最小示例
20
20
 
21
21
  ```ts
22
- import { CityBase, AIService } from "@downcity/city";
22
+ import { Federation, AIService } from "@downcity/city";
23
23
  import Database from "better-sqlite3";
24
24
  import { drizzle } from "drizzle-orm/better-sqlite3";
25
25
 
@@ -30,7 +30,7 @@ const db = Object.assign(drizzle(sqlite), {
30
30
  $client: { exec: (sql: string) => sqlite.exec(sql) },
31
31
  });
32
32
 
33
- const base = new CityBase({ db, dialect: "sqlite", raw: sqlite });
33
+ const base = new Federation({ db, dialect: "sqlite", raw: sqlite });
34
34
 
35
35
  const ai = new AIService();
36
36
  ai.use({
@@ -66,9 +66,9 @@ serve({ fetch: base.router().fetch, port: 43127, hostname: "127.0.0.1" });
66
66
 
67
67
  ## City 说明文档
68
68
 
69
- `base.instruction()` 会返回当前 CityBase 实例的聚合说明文档字符串,内容包含:
69
+ `base.instruction()` 会返回当前 Federation 实例的聚合说明文档字符串,内容包含:
70
70
 
71
- - CityBase 的基本使用方式
71
+ - Federation 的基本使用方式
72
72
  - 当前已挂载的 service
73
73
  - 每个模块需要的 env 配置
74
74
  - 每个模块补充的使用说明
@@ -81,7 +81,7 @@ console.log(text);
81
81
  如果你需要从远程管理端读取同一份说明,可以请求:
82
82
 
83
83
  ```txt
84
- GET /v1/city/instruction
84
+ GET /v1/federation/instruction
85
85
  ```
86
86
 
87
87
  这个接口只允许 `admin_secret_key` 访问,返回 `text/plain`。
@@ -142,7 +142,7 @@ base.use(ai);
142
142
 
143
143
  ## 官方服务
144
144
 
145
- 官方服务用于封装多 town 复用能力:
145
+ 官方服务用于封装多 city 复用能力:
146
146
 
147
147
  ```ts
148
148
  import { accountsService } from "@downcity/services";
@@ -163,12 +163,12 @@ base.use(usageService());
163
163
  - `auth: ["admin"]` 只允许 `admin_secret_key`
164
164
  - `auth: []` 表示免登录
165
165
 
166
- 对于用户侧请求,`user_token` 绑定 town 身份。如果请求体或 query 中传了 `town_id`,它必须与 token 里的 town 一致。
166
+ 对于用户侧请求,`user_token` 绑定 city 身份。如果请求体或 query 中传了 `city_id`,它必须与 token 里的 city 一致。
167
167
 
168
168
  ## 主要导出
169
169
 
170
170
  - `City`
171
- - `CityBase`
171
+ - `Federation`
172
172
  - `Service`
173
173
  - `ServiceDefinition`
174
174
  - `AIService`
@@ -177,7 +177,7 @@ base.use(usageService());
177
177
  - `CityModelDescriptor`
178
178
  - `TokenSigner`
179
179
  - `EnvService`
180
- - `TownsService`
180
+ - `CitiesService`
181
181
 
182
182
  ## City 模型目录
183
183
 
@@ -0,0 +1,90 @@
1
+ /**
2
+ * City 客户端统一访问入口。
3
+ *
4
+ * City 面向开发者表达“我以某种角色进入 Federation”,内部再委托给
5
+ * admin / user 协议访问层(`pact/`),让用户在第一层概念上无需关心 client 拆分。
6
+ */
7
+ import { AdminPactAccess } from "../pact/admin/index.js";
8
+ import { UserPactAccess } from "../pact/user/index.js";
9
+ import type { ServiceClient } from "../pact/invoker/invoker.js";
10
+ import type { CityOptionsForRole, CityRole } from "./types.js";
11
+ import type { AdminModelRecord, AdminServiceSummary } from "../pact/admin/types.js";
12
+ import type { UserServiceSummary } from "../pact/user/types.js";
13
+ /**
14
+ * Downcity City 客户端。
15
+ */
16
+ export declare class City<TRole extends CityRole = CityRole> {
17
+ /**
18
+ * 当前 City 客户端的访问角色。
19
+ */
20
+ readonly role: TRole;
21
+ /**
22
+ * Admin 能力面。
23
+ *
24
+ * 仅 `role: "admin"` 时可用。
25
+ */
26
+ private readonly admin_access?;
27
+ /**
28
+ * User 能力面。
29
+ *
30
+ * 仅 `role: "user"` 时可用。
31
+ */
32
+ private readonly user_access?;
33
+ constructor(options: CityOptionsForRole<TRole>);
34
+ /**
35
+ * User 角色的 AI 调用入口。
36
+ */
37
+ get ai(): UserPactAccess["ai"];
38
+ /**
39
+ * User 角色的支付入口。
40
+ */
41
+ get payment(): UserPactAccess["payment"];
42
+ /**
43
+ * Admin 角色的余额服务入口。
44
+ */
45
+ get balance(): AdminPactAccess["balance"];
46
+ /**
47
+ * Admin 角色的 City 管理入口。
48
+ */
49
+ get cities(): AdminPactAccess["cities"];
50
+ /**
51
+ * Admin 角色的环境变量服务入口。
52
+ */
53
+ get env(): AdminPactAccess["env"];
54
+ /**
55
+ * Token 管理入口。
56
+ *
57
+ * 不需要传 city_id,构造时传入的 city_id 会自动注入。
58
+ */
59
+ get tokens(): {
60
+ apply: (input: {
61
+ user_id: string;
62
+ metadata?: Record<string, unknown>;
63
+ ttl?: string | number;
64
+ }) => Promise<{
65
+ user_token: string;
66
+ city_id: string;
67
+ user_id: string;
68
+ expires_at?: string;
69
+ }>;
70
+ };
71
+ /**
72
+ * 获取普通 service 调用器。
73
+ */
74
+ service(name: string): ServiceClient;
75
+ /**
76
+ * 列出当前 Federation 暴露的 service。
77
+ */
78
+ listServices(): Promise<AdminServiceSummary[] | UserServiceSummary[]>;
79
+ /**
80
+ * 列出 Federation 模型目录。
81
+ */
82
+ listModels(): Promise<AdminModelRecord[]>;
83
+ /**
84
+ * 读取 Federation 聚合说明文档。
85
+ */
86
+ instruction(): Promise<string>;
87
+ private require_admin;
88
+ private require_user;
89
+ }
90
+ //# sourceMappingURL=city.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"city.d.ts","sourceRoot":"","sources":["../../src/client/city.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,KAAK,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,KAAK,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AACpF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAEhE;;GAEG;AACH,qBAAa,IAAI,CAAC,KAAK,SAAS,QAAQ,GAAG,QAAQ;IACjD;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IAErB;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAkB;IAEhD;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAiB;gBAElC,OAAO,EAAE,kBAAkB,CAAC,KAAK,CAAC;IAyB9C;;OAEG;IACH,IAAI,EAAE,IAAI,cAAc,CAAC,IAAI,CAAC,CAE7B;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,cAAc,CAAC,SAAS,CAAC,CAEvC;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,eAAe,CAAC,SAAS,CAAC,CAExC;IAED;;OAEG;IACH,IAAI,MAAM,IAAI,eAAe,CAAC,QAAQ,CAAC,CAEtC;IAED;;OAEG;IACH,IAAI,GAAG,IAAI,eAAe,CAAC,KAAK,CAAC,CAEhC;IAED;;;;OAIG;IACH,IAAI,MAAM,IAAI;QAAE,KAAK,EAAE,CAAC,KAAK,EAAE;YAAE,OAAO,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;SAAE,KAAK,OAAO,CAAC;YAAE,UAAU,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAC;YAAC,UAAU,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,CAGzM;IAED;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa;IAIpC;;OAEG;IACH,YAAY,IAAI,OAAO,CAAC,mBAAmB,EAAE,GAAG,kBAAkB,EAAE,CAAC;IAIrE;;OAEG;IACH,UAAU,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAIzC;;OAEG;IACH,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC;IAI9B,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,YAAY;CAMrB"}
@@ -1,17 +1,17 @@
1
1
  /**
2
- * City 统一访问入口。
2
+ * City 客户端统一访问入口。
3
3
  *
4
- * City 面向开发者表达“我以某种角色进入 City”,内部再委托给
5
- * admin / user 访问层,避免用户在第一层概念上关心 client 拆分。
4
+ * City 面向开发者表达“我以某种角色进入 Federation”,内部再委托给
5
+ * admin / user 协议访问层(`pact/`),让用户在第一层概念上无需关心 client 拆分。
6
6
  */
7
- import { AdminCityAccess } from "./admin/index.js";
8
- import { UserCityAccess } from "./user/index.js";
7
+ import { AdminPactAccess } from "../pact/admin/index.js";
8
+ import { UserPactAccess } from "../pact/user/index.js";
9
9
  /**
10
- * Downcity City
10
+ * Downcity City 客户端。
11
11
  */
12
12
  export class City {
13
13
  /**
14
- * 当前 City 访问角色。
14
+ * 当前 City 客户端的访问角色。
15
15
  */
16
16
  role;
17
17
  /**
@@ -32,49 +32,59 @@ export class City {
32
32
  }
33
33
  this.role = options.role;
34
34
  if (options.role === "admin") {
35
- this.admin_access = new AdminCityAccess({
36
- base_url: options.city_url,
35
+ this.admin_access = new AdminPactAccess({
36
+ base_url: options.federation_url,
37
+ city_id: options.city_id,
37
38
  admin_secret_key: options.admin_secret_key,
38
39
  fetch: options.fetch,
39
40
  });
40
41
  return;
41
42
  }
42
- this.user_access = new UserCityAccess({
43
- base_url: options.city_url,
44
- town_id: options.town_id,
43
+ this.user_access = new UserPactAccess({
44
+ base_url: options.federation_url,
45
+ city_id: options.city_id,
45
46
  user_token: options.user_token,
46
47
  fetch: options.fetch,
47
48
  });
48
49
  }
49
50
  /**
50
- * User City AI 调用入口。
51
+ * User 角色的 AI 调用入口。
51
52
  */
52
53
  get ai() {
53
54
  return this.require_user().ai;
54
55
  }
55
56
  /**
56
- * User City 的支付入口。
57
+ * User 角色的支付入口。
57
58
  */
58
59
  get payment() {
59
60
  return this.require_user().payment;
60
61
  }
61
62
  /**
62
- * Admin City 的余额服务入口。
63
+ * Admin 角色的余额服务入口。
63
64
  */
64
65
  get balance() {
65
66
  return this.require_admin().balance;
66
67
  }
67
68
  /**
68
- * Admin City 的环境变量服务入口。
69
+ * Admin 角色的 City 管理入口。
70
+ */
71
+ get cities() {
72
+ return this.require_admin().cities;
73
+ }
74
+ /**
75
+ * Admin 角色的环境变量服务入口。
69
76
  */
70
77
  get env() {
71
78
  return this.require_admin().env;
72
79
  }
73
80
  /**
74
- * Admin City 的 Town 管理入口。
81
+ * Token 管理入口。
82
+ *
83
+ * 不需要传 city_id,构造时传入的 city_id 会自动注入。
75
84
  */
76
- get towns() {
77
- return this.require_admin().towns;
85
+ get tokens() {
86
+ const admin = this.require_admin();
87
+ return { apply: (input) => admin.applyToken(input) };
78
88
  }
79
89
  /**
80
90
  * 获取普通 service 调用器。
@@ -83,19 +93,19 @@ export class City {
83
93
  return this.admin_access?.service(name) ?? this.require_user().service(name);
84
94
  }
85
95
  /**
86
- * 列出当前 City 暴露的 service。
96
+ * 列出当前 Federation 暴露的 service。
87
97
  */
88
98
  listServices() {
89
99
  return this.admin_access?.listServices() ?? this.require_user().listServices();
90
100
  }
91
101
  /**
92
- * 列出 City 模型目录。
102
+ * 列出 Federation 模型目录。
93
103
  */
94
104
  listModels() {
95
105
  return this.require_admin().listModels();
96
106
  }
97
107
  /**
98
- * 读取 City 聚合说明文档。
108
+ * 读取 Federation 聚合说明文档。
99
109
  */
100
110
  instruction() {
101
111
  return this.require_admin().instruction();
@@ -0,0 +1 @@
1
+ {"version":3,"file":"city.js","sourceRoot":"","sources":["../../src/client/city.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * City 客户端构造类型模块。
3
+ *
4
+ * City 是访问 Federation 的统一客户端入口:开发者只需要声明访问角色,
5
+ * SDK 会在内部选择 admin 或 user 能力面。底层 HTTP 协议实现位于 `pact/`。
6
+ */
7
+ import type { FetchLike } from "../pact/http.js";
8
+ /**
9
+ * City 访问角色。
10
+ */
11
+ export type CityRole = "admin" | "user";
12
+ /**
13
+ * City 客户端共享构造参数。
14
+ */
15
+ export interface CityBaseOptions {
16
+ /**
17
+ * Federation 的 HTTP 入口地址。
18
+ *
19
+ * 示例:`https://city.example.com` 或 `http://localhost:43127`。
20
+ */
21
+ federation_url: string;
22
+ /**
23
+ * 自定义 fetch 实现。
24
+ *
25
+ * 主要用于测试、Worker 运行时适配,或在请求层注入日志与追踪。
26
+ */
27
+ fetch?: FetchLike;
28
+ }
29
+ /**
30
+ * Admin 角色的 City 构造参数。
31
+ */
32
+ export interface AdminCityOptions extends CityBaseOptions {
33
+ /**
34
+ * 使用 admin 身份访问 Federation。
35
+ */
36
+ role: "admin";
37
+ /**
38
+ * 当前管理的 City ID。
39
+ *
40
+ * token 签发等服务会自动使用该 ID,调用方无需再传 city_id。
41
+ */
42
+ city_id: string;
43
+ /**
44
+ * Federation 管理密钥。
45
+ *
46
+ * 未传入时会由 Federation 回退读取 `DOWNCITY_FEDERATION_ADMIN_SECRET_KEY`。
47
+ */
48
+ admin_secret_key?: string;
49
+ }
50
+ /**
51
+ * User 角色的 City 构造参数。
52
+ */
53
+ export interface UserCityOptions extends CityBaseOptions {
54
+ /**
55
+ * 使用 user 身份访问 Federation。
56
+ */
57
+ role: "user";
58
+ /**
59
+ * 当前 user_token 绑定的 City ID。
60
+ *
61
+ * AI 与普通 service action 调用会自动把该值注入为 `city_id`。
62
+ */
63
+ city_id?: string;
64
+ /**
65
+ * 终端用户访问 token。
66
+ */
67
+ user_token?: string;
68
+ }
69
+ /**
70
+ * City 构造参数。
71
+ */
72
+ export type CityOptions = AdminCityOptions | UserCityOptions;
73
+ /**
74
+ * 按角色收窄后的 City 构造参数。
75
+ */
76
+ export type CityOptionsForRole<TRole extends CityRole> = TRole extends "admin" ? AdminCityOptions : UserCityOptions;
77
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/client/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AAExC;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,cAAc,EAAE,MAAM,CAAC;IAEvB;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAiB,SAAQ,eAAe;IACvD;;OAEG;IACH,IAAI,EAAE,OAAO,CAAC;IAEd;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,eAAgB,SAAQ,eAAe;IACtD;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,gBAAgB,GAAG,eAAe,CAAC;AAE7D;;GAEG;AACH,MAAM,MAAM,kBAAkB,CAAC,KAAK,SAAS,QAAQ,IAAI,KAAK,SAAS,OAAO,GAC1E,gBAAgB,GAChB,eAAe,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * City 客户端构造类型模块。
3
+ *
4
+ * City 是访问 Federation 的统一客户端入口:开发者只需要声明访问角色,
5
+ * SDK 会在内部选择 admin 或 user 能力面。底层 HTTP 协议实现位于 `pact/`。
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/client/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -16,9 +16,9 @@ export interface AuthResult {
16
16
  level: RouteIdentity;
17
17
  /** 解析出的用户信息(user 级别时可用) */
18
18
  user?: RuntimeUser;
19
- /** 解析出的 Town 信息(user 级别时可用) */
20
- town?: {
21
- town_id: string;
19
+ /** 解析出的 City 信息(user 级别时可用) */
20
+ city?: {
21
+ city_id: string;
22
22
  status: string;
23
23
  };
24
24
  }
@@ -29,9 +29,9 @@ export declare class Authenticator {
29
29
  /** 缓存的 TokenSigner 实例 */
30
30
  private tokenSigner?;
31
31
  constructor(env: EnvProvider, store: () => Promise<{
32
- town: {
32
+ city: {
33
33
  get(id: string): Promise<{
34
- town_id: string;
34
+ city_id: string;
35
35
  status: string;
36
36
  } | undefined>;
37
37
  };
@@ -39,7 +39,7 @@ export declare class Authenticator {
39
39
  /**
40
40
  * 获取(或创建)TokenSigner 单例。
41
41
  *
42
- * 首次调用时从 env 读取 DOWNCITY_CITY_TOKEN_SIGNING_KEY 创建实例并缓存。
42
+ * 首次调用时从 env 读取 DOWNCITY_FEDERATION_TOKEN_SIGNING_KEY 创建实例并缓存。
43
43
  */
44
44
  private getSigner;
45
45
  /**
@@ -62,7 +62,7 @@ export declare class Authenticator {
62
62
  */
63
63
  authenticate(request: Request, required?: RouteAuth): Promise<AuthResult>;
64
64
  /**
65
- * 签发 user_token(验证 town 状态后签发)。
65
+ * 签发 user_token(验证 city 状态后签发)。
66
66
  *
67
67
  * @param input - token 创建参数
68
68
  * @returns 签发结果(含 token 字符串)
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authenticator.d.ts","sourceRoot":"","sources":["../../../src/federation/auth/authenticator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAAsB,KAAK,SAAS,EAAE,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAClG,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,KAAK,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE5G,WAAW;AACX,WAAW;AACX,MAAM,WAAW,UAAU;IACzB,eAAe;IACf,KAAK,EAAE,aAAa,CAAC;IACrB,2BAA2B;IAC3B,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,+BAA+B;IAC/B,IAAI,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5C;AAED,YAAY;AACZ,qBAAa,aAAa;IAKtB,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,KAAK;IALf,yBAAyB;IACzB,OAAO,CAAC,WAAW,CAAC,CAAc;gBAGxB,GAAG,EAAE,WAAW,EAChB,KAAK,EAAE,MAAM,OAAO,CAAC;QAAE,IAAI,EAAE;YAAE,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;gBAAE,OAAO,EAAE,MAAM,CAAC;gBAAC,MAAM,EAAE,MAAM,CAAA;aAAE,GAAG,SAAS,CAAC,CAAA;SAAE,CAAA;KAAE,CAAC;IAGvH;;;;OAIG;IACH,OAAO,CAAC,SAAS;IASjB;;;;;OAKG;IACG,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC;IA0BpD;;;;;;OAMG;IACH,SAAS,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,SAAS,GAAG,UAAU;IAY/D;;OAEG;IACG,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC;IAI/E;;;;;OAKG;IACG,WAAW,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAiB7E;;;;;OAKG;IACG,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAG5D"}
@@ -22,13 +22,13 @@ export class Authenticator {
22
22
  /**
23
23
  * 获取(或创建)TokenSigner 单例。
24
24
  *
25
- * 首次调用时从 env 读取 DOWNCITY_CITY_TOKEN_SIGNING_KEY 创建实例并缓存。
25
+ * 首次调用时从 env 读取 DOWNCITY_FEDERATION_TOKEN_SIGNING_KEY 创建实例并缓存。
26
26
  */
27
27
  getSigner() {
28
28
  if (!this.tokenSigner) {
29
- const signingKey = this.env.get("DOWNCITY_CITY_TOKEN_SIGNING_KEY");
29
+ const signingKey = this.env.get("DOWNCITY_FEDERATION_TOKEN_SIGNING_KEY");
30
30
  if (!signingKey)
31
- throw new Error("DOWNCITY_CITY_TOKEN_SIGNING_KEY is required");
31
+ throw new Error("DOWNCITY_FEDERATION_TOKEN_SIGNING_KEY is required");
32
32
  this.tokenSigner = new TokenSigner(signingKey);
33
33
  }
34
34
  return this.tokenSigner;
@@ -43,22 +43,22 @@ export class Authenticator {
43
43
  const token = bearerToken(request);
44
44
  if (!token)
45
45
  return { level: "guest" };
46
- const adminKey = this.env.get("DOWNCITY_CITY_ADMIN_SECRET_KEY");
46
+ const adminKey = this.env.get("DOWNCITY_FEDERATION_ADMIN_SECRET_KEY");
47
47
  if (adminKey && token === adminKey) {
48
48
  return { level: "admin" };
49
49
  }
50
50
  try {
51
51
  const payload = await this.getSigner().verify(token);
52
52
  const store = await this.store();
53
- const town = await store.town.get(payload.town_id);
54
- if (!town)
53
+ const city = await store.city.get(payload.city_id);
54
+ if (!city)
55
55
  return { level: "guest" };
56
- if (town.status !== "active")
56
+ if (city.status !== "active")
57
57
  return { level: "guest" };
58
58
  return {
59
59
  level: "user",
60
60
  user: { user_id: payload.user_id, metadata: payload.metadata ?? {} },
61
- town,
61
+ city,
62
62
  };
63
63
  }
64
64
  catch {
@@ -90,22 +90,22 @@ export class Authenticator {
90
90
  return this.authorize(await this.resolve(request), required);
91
91
  }
92
92
  /**
93
- * 签发 user_token(验证 town 状态后签发)。
93
+ * 签发 user_token(验证 city 状态后签发)。
94
94
  *
95
95
  * @param input - token 创建参数
96
96
  * @returns 签发结果(含 token 字符串)
97
97
  */
98
98
  async createToken(input) {
99
99
  const store = await this.store();
100
- const town = await store.town.get(input.town_id);
101
- if (!town)
102
- throw httpError(404, `Unknown town: ${input.town_id}`);
103
- if (town.status !== "active")
104
- throw httpError(403, `Town is not active: ${input.town_id}`);
100
+ const city = await store.city.get(input.city_id);
101
+ if (!city)
102
+ throw httpError(404, `Unknown city: ${input.city_id}`);
103
+ if (city.status !== "active")
104
+ throw httpError(403, `City is not active: ${input.city_id}`);
105
105
  const user_token = await this.getSigner().sign(input);
106
106
  return {
107
107
  user_token,
108
- town_id: input.town_id,
108
+ city_id: input.city_id,
109
109
  user_id: input.user_id,
110
110
  ...(input.ttl
111
111
  ? { expires_at: new Date(Date.now() + TokenSigner.parseTTL(input.ttl) * 1000).toISOString() }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authenticator.js","sourceRoot":"","sources":["../../../src/federation/auth/authenticator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-signer.d.ts","sourceRoot":"","sources":["../../../src/federation/auth/token-signer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEzE,qBAAa,WAAW;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAE5B,qCAAqC;IACrC,OAAO,CAAC,SAAS,CAAC,CAAqB;gBAE3B,UAAU,EAAE,MAAM;IAO9B;;;;;OAKG;IACH,OAAO,CAAC,YAAY;IAcpB,oBAAoB;IACd,IAAI,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC;IA4BxD,0CAA0C;IACpC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA6BtD,kBAAkB;IAClB,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM;CAyB9C"}
@@ -30,8 +30,8 @@ export class TokenSigner {
30
30
  }
31
31
  /** 签发 user_token */
32
32
  async sign(input) {
33
- if (!input || typeof input.town_id !== "string" || input.town_id.length === 0) {
34
- throw new TypeError("town_id is required");
33
+ if (!input || typeof input.city_id !== "string" || input.city_id.length === 0) {
34
+ throw new TypeError("city_id is required");
35
35
  }
36
36
  if (typeof input.user_id !== "string" || input.user_id.length === 0) {
37
37
  throw new TypeError("user_id is required");
@@ -40,7 +40,7 @@ export class TokenSigner {
40
40
  const now = Math.floor(Date.now() / 1000);
41
41
  const payload = {
42
42
  aud: "downcity:user",
43
- town_id: input.town_id,
43
+ city_id: input.city_id,
44
44
  user_id: input.user_id,
45
45
  metadata: input.metadata ?? {},
46
46
  iat: now,
@@ -70,7 +70,7 @@ export class TokenSigner {
70
70
  if (payload.aud !== "downcity:user") {
71
71
  throw httpError(401, "Invalid user token audience");
72
72
  }
73
- if (!payload.town_id || !payload.user_id) {
73
+ if (!payload.city_id || !payload.user_id) {
74
74
  throw httpError(401, "Invalid user token payload");
75
75
  }
76
76
  return payload;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-signer.js","sourceRoot":"","sources":["../../../src/federation/auth/token-signer.ts"],"names":[],"mappings":"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"}
@@ -21,9 +21,9 @@ export interface RuntimeUser {
21
21
  */
22
22
  export interface CreateUserTokenInput {
23
23
  /**
24
- * token 所属的 Town ID。
24
+ * token 所属的 City ID。
25
25
  */
26
- town_id: string;
26
+ city_id: string;
27
27
  /**
28
28
  * token 所属的终端用户 ID。
29
29
  */
@@ -48,9 +48,9 @@ export interface UserTokenPayload {
48
48
  */
49
49
  aud: "downcity:user";
50
50
  /**
51
- * token 所属 Town ID。
51
+ * token 所属 City ID。
52
52
  */
53
- town_id: string;
53
+ city_id: string;
54
54
  /**
55
55
  * token 所属用户 ID。
56
56
  */
@@ -77,9 +77,9 @@ export interface UserTokenIssueResult {
77
77
  */
78
78
  user_token: string;
79
79
  /**
80
- * token 所属 Town ID。
80
+ * token 所属 City ID。
81
81
  */
82
- town_id: string;
82
+ city_id: string;
83
83
  /**
84
84
  * token 所属用户 ID。
85
85
  */
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/federation/auth/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAEnC;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,GAAG,EAAE,eAAe,CAAC;IAErB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAEnC;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/federation/auth/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Federation env requirement 聚合模块。
3
+ *
4
+ * 负责把 service.env 与 AI 模型 env requirement 汇总成统一目录。
5
+ */
6
+ import type { Service } from "../service/service.js";
7
+ import type { EnvCatalogScope } from "../service/env/types.js";
8
+ import type { EnvProvider } from "./runtime.js";
9
+ /**
10
+ * 聚合当前 Federation 暴露的 env requirement。
11
+ */
12
+ export declare function collect_federation_env_catalog(services: Service[], env_provider: EnvProvider): EnvCatalogScope[];
13
+ //# sourceMappingURL=federation-env-catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"federation-env-catalog.d.ts","sourceRoot":"","sources":["../../src/federation/federation-env-catalog.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EAAE,eAAe,EAAwB,MAAM,yBAAyB,CAAC;AACrF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD;;GAEG;AACH,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,OAAO,EAAE,EACnB,YAAY,EAAE,WAAW,GACxB,eAAe,EAAE,CAsBnB"}