@downcity/city 0.2.200 → 0.2.211

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 (221) hide show
  1. package/README.md +89 -13
  2. package/bin/client/bureau.d.ts +41 -0
  3. package/bin/client/bureau.d.ts.map +1 -0
  4. package/bin/client/bureau.js +240 -0
  5. package/bin/client/bureau.js.map +1 -0
  6. package/bin/client/city.d.ts +15 -79
  7. package/bin/client/city.d.ts.map +1 -1
  8. package/bin/client/city.js +15 -99
  9. package/bin/client/city.js.map +1 -1
  10. package/bin/client/federation-admin.d.ts +32 -0
  11. package/bin/client/federation-admin.d.ts.map +1 -0
  12. package/bin/client/federation-admin.js +54 -0
  13. package/bin/client/federation-admin.js.map +1 -0
  14. package/bin/client/types.d.ts +10 -70
  15. package/bin/client/types.d.ts.map +1 -1
  16. package/bin/client/types.js +3 -3
  17. package/bin/federation/auth/authenticator.d.ts +17 -13
  18. package/bin/federation/auth/authenticator.d.ts.map +1 -1
  19. package/bin/federation/auth/authenticator.js +38 -27
  20. package/bin/federation/auth/authenticator.js.map +1 -1
  21. package/bin/federation/auth/bureau-token-schema.d.ts +274 -0
  22. package/bin/federation/auth/bureau-token-schema.d.ts.map +1 -0
  23. package/bin/federation/auth/bureau-token-schema.js +43 -0
  24. package/bin/federation/auth/bureau-token-schema.js.map +1 -0
  25. package/bin/federation/auth/bureau-token-store.d.ts +22 -0
  26. package/bin/federation/auth/bureau-token-store.d.ts.map +1 -0
  27. package/bin/federation/auth/bureau-token-store.js +122 -0
  28. package/bin/federation/auth/bureau-token-store.js.map +1 -0
  29. package/bin/federation/auth/federation-key-store.d.ts +26 -0
  30. package/bin/federation/auth/federation-key-store.d.ts.map +1 -0
  31. package/bin/federation/auth/federation-key-store.js +96 -0
  32. package/bin/federation/auth/federation-key-store.js.map +1 -0
  33. package/bin/federation/auth/key-schema.d.ts +275 -0
  34. package/bin/federation/auth/key-schema.d.ts.map +1 -0
  35. package/bin/federation/auth/key-schema.js +44 -0
  36. package/bin/federation/auth/key-schema.js.map +1 -0
  37. package/bin/federation/auth/types.d.ts +62 -4
  38. package/bin/federation/auth/types.d.ts.map +1 -1
  39. package/bin/federation/auth/user-token-authority.d.ts +26 -0
  40. package/bin/federation/auth/user-token-authority.d.ts.map +1 -0
  41. package/bin/federation/auth/user-token-authority.js +179 -0
  42. package/bin/federation/auth/user-token-authority.js.map +1 -0
  43. package/bin/federation/federation-init.d.ts.map +1 -1
  44. package/bin/federation/federation-init.js +23 -4
  45. package/bin/federation/federation-init.js.map +1 -1
  46. package/bin/federation/federation-router.d.ts +3 -1
  47. package/bin/federation/federation-router.d.ts.map +1 -1
  48. package/bin/federation/federation-router.js +17 -0
  49. package/bin/federation/federation-router.js.map +1 -1
  50. package/bin/federation/federation-runtime.d.ts.map +1 -1
  51. package/bin/federation/federation-runtime.js +14 -2
  52. package/bin/federation/federation-runtime.js.map +1 -1
  53. package/bin/federation/federation.d.ts.map +1 -1
  54. package/bin/federation/federation.js +2 -0
  55. package/bin/federation/federation.js.map +1 -1
  56. package/bin/federation/runtime.d.ts +4 -0
  57. package/bin/federation/runtime.d.ts.map +1 -1
  58. package/bin/index.d.ts +11 -10
  59. package/bin/index.d.ts.map +1 -1
  60. package/bin/index.js +5 -3
  61. package/bin/index.js.map +1 -1
  62. package/bin/pact/admin/index.d.ts +7 -19
  63. package/bin/pact/admin/index.d.ts.map +1 -1
  64. package/bin/pact/admin/index.js +10 -18
  65. package/bin/pact/admin/index.js.map +1 -1
  66. package/bin/pact/admin/types.d.ts +4 -10
  67. package/bin/pact/admin/types.d.ts.map +1 -1
  68. package/bin/pact/invoker/ai/CityModel.d.ts +1 -1
  69. package/bin/pact/invoker/ai/CityModel.d.ts.map +1 -1
  70. package/bin/pact/invoker/ai/CityModel.js +3 -65
  71. package/bin/pact/invoker/ai/CityModel.js.map +1 -1
  72. package/bin/pact/invoker/ai/types.d.ts +1 -1
  73. package/bin/pact/invoker/ai/types.js +1 -1
  74. package/bin/pact/invoker/bureaus/index.d.ts +25 -0
  75. package/bin/pact/invoker/bureaus/index.d.ts.map +1 -0
  76. package/bin/pact/invoker/bureaus/index.js +36 -0
  77. package/bin/pact/invoker/bureaus/index.js.map +1 -0
  78. package/bin/pact/invoker/cities/types.d.ts +2 -2
  79. package/bin/pact/invoker/cities/types.d.ts.map +1 -1
  80. package/bin/pact/invoker/user/index.d.ts +19 -0
  81. package/bin/pact/invoker/user/index.d.ts.map +1 -0
  82. package/bin/pact/invoker/user/index.js +24 -0
  83. package/bin/pact/invoker/user/index.js.map +1 -0
  84. package/bin/pact/user/index.d.ts +2 -1
  85. package/bin/pact/user/index.d.ts.map +1 -1
  86. package/bin/pact/user/index.js +7 -3
  87. package/bin/pact/user/index.js.map +1 -1
  88. package/bin/pact/user/types.d.ts +11 -6
  89. package/bin/pact/user/types.d.ts.map +1 -1
  90. package/bin/service/ai/AIChannel.d.ts +57 -0
  91. package/bin/service/ai/AIChannel.d.ts.map +1 -0
  92. package/bin/service/ai/AIChannel.js +151 -0
  93. package/bin/service/ai/AIChannel.js.map +1 -0
  94. package/bin/service/ai/OpenAIChatCompletionsAdapter.d.ts +23 -0
  95. package/bin/service/ai/OpenAIChatCompletionsAdapter.d.ts.map +1 -0
  96. package/bin/service/ai/OpenAIChatCompletionsAdapter.js +503 -0
  97. package/bin/service/ai/OpenAIChatCompletionsAdapter.js.map +1 -0
  98. package/bin/service/ai/ai-service-values.d.ts +16 -19
  99. package/bin/service/ai/ai-service-values.d.ts.map +1 -1
  100. package/bin/service/ai/ai-service-values.js +9 -13
  101. package/bin/service/ai/ai-service-values.js.map +1 -1
  102. package/bin/service/ai/ai-service.d.ts +16 -15
  103. package/bin/service/ai/ai-service.d.ts.map +1 -1
  104. package/bin/service/ai/ai-service.js +97 -106
  105. package/bin/service/ai/ai-service.js.map +1 -1
  106. package/bin/service/ai/helpers.d.ts +8 -35
  107. package/bin/service/ai/helpers.d.ts.map +1 -1
  108. package/bin/service/ai/helpers.js +8 -140
  109. package/bin/service/ai/helpers.js.map +1 -1
  110. package/bin/service/ai/image-job-store.d.ts +2 -3
  111. package/bin/service/ai/image-job-store.d.ts.map +1 -1
  112. package/bin/service/ai/image-job-store.js.map +1 -1
  113. package/bin/service/ai/language-model-stream.d.ts +9 -4
  114. package/bin/service/ai/language-model-stream.d.ts.map +1 -1
  115. package/bin/service/ai/language-model-stream.js +8 -4
  116. package/bin/service/ai/language-model-stream.js.map +1 -1
  117. package/bin/service/ai/language-model-text.d.ts +15 -0
  118. package/bin/service/ai/language-model-text.d.ts.map +1 -0
  119. package/bin/service/ai/language-model-text.js +67 -0
  120. package/bin/service/ai/language-model-text.js.map +1 -0
  121. package/bin/service/ai/model-context-window.d.ts +2 -2
  122. package/bin/service/ai/model-context-window.d.ts.map +1 -1
  123. package/bin/service/ai/model-context-window.js.map +1 -1
  124. package/bin/service/ai/model-registry.d.ts +9 -8
  125. package/bin/service/ai/model-registry.d.ts.map +1 -1
  126. package/bin/service/ai/model-registry.js +1 -5
  127. package/bin/service/ai/model-registry.js.map +1 -1
  128. package/bin/service/ai/model-routing.d.ts +1 -1
  129. package/bin/service/ai/model-routing.d.ts.map +1 -1
  130. package/bin/service/ai/model-routing.js +1 -1
  131. package/bin/service/ai/model-routing.js.map +1 -1
  132. package/bin/service/ai/reasoning.d.ts +4 -4
  133. package/bin/service/ai/reasoning.d.ts.map +1 -1
  134. package/bin/service/ai/reasoning.js.map +1 -1
  135. package/bin/service/bureaus/bureaus-service.d.ts +15 -0
  136. package/bin/service/bureaus/bureaus-service.d.ts.map +1 -0
  137. package/bin/service/bureaus/bureaus-service.js +55 -0
  138. package/bin/service/bureaus/bureaus-service.js.map +1 -0
  139. package/bin/service/installable-service.d.ts +5 -2
  140. package/bin/service/installable-service.d.ts.map +1 -1
  141. package/bin/service/installable-service.js +1 -0
  142. package/bin/service/installable-service.js.map +1 -1
  143. package/bin/service/instruction.js +1 -1
  144. package/bin/service/instruction.js.map +1 -1
  145. package/bin/service/service.d.ts +15 -2
  146. package/bin/service/service.d.ts.map +1 -1
  147. package/bin/service/service.js +2 -0
  148. package/bin/service/service.js.map +1 -1
  149. package/bin/types/AI.d.ts +289 -0
  150. package/bin/types/AI.d.ts.map +1 -0
  151. package/bin/types/AI.js +8 -0
  152. package/bin/types/AI.js.map +1 -0
  153. package/bin/types/AITransport.d.ts +251 -0
  154. package/bin/types/AITransport.d.ts.map +1 -0
  155. package/bin/types/AITransport.js +12 -0
  156. package/bin/types/AITransport.js.map +1 -0
  157. package/bin/types/Bureau.d.ts +96 -0
  158. package/bin/types/Bureau.d.ts.map +1 -0
  159. package/bin/types/Bureau.js +8 -0
  160. package/bin/types/Bureau.js.map +1 -0
  161. package/bin/types/FederationAdmin.d.ts +16 -0
  162. package/bin/types/FederationAdmin.d.ts.map +1 -0
  163. package/bin/types/FederationAdmin.js +7 -0
  164. package/bin/types/FederationAdmin.js.map +1 -0
  165. package/bin/types/Metering.d.ts +2 -2
  166. package/bin/types/Metering.d.ts.map +1 -1
  167. package/bin/types/User.d.ts +24 -0
  168. package/bin/types/User.d.ts.map +1 -0
  169. package/bin/types/User.js +8 -0
  170. package/bin/types/User.js.map +1 -0
  171. package/bin/utils/CityLanguageModelCodec.d.ts +1 -1
  172. package/bin/utils/CityLanguageModelCodec.d.ts.map +1 -1
  173. package/bin/utils/CityLanguageModelResult.d.ts +11 -0
  174. package/bin/utils/CityLanguageModelResult.d.ts.map +1 -0
  175. package/bin/utils/CityLanguageModelResult.js +76 -0
  176. package/bin/utils/CityLanguageModelResult.js.map +1 -0
  177. package/package.json +4 -3
  178. package/bin/federation/auth/token-signer.d.ts +0 -27
  179. package/bin/federation/auth/token-signer.d.ts.map +0 -1
  180. package/bin/federation/auth/token-signer.js +0 -116
  181. package/bin/federation/auth/token-signer.js.map +0 -1
  182. package/bin/service/ai/charge.d.ts +0 -76
  183. package/bin/service/ai/charge.d.ts.map +0 -1
  184. package/bin/service/ai/charge.js +0 -10
  185. package/bin/service/ai/charge.js.map +0 -1
  186. package/bin/service/ai/job-types.d.ts +0 -69
  187. package/bin/service/ai/job-types.d.ts.map +0 -1
  188. package/bin/service/ai/job-types.js +0 -9
  189. package/bin/service/ai/job-types.js.map +0 -1
  190. package/bin/service/ai/provider.d.ts +0 -143
  191. package/bin/service/ai/provider.d.ts.map +0 -1
  192. package/bin/service/ai/provider.js +0 -221
  193. package/bin/service/ai/provider.js.map +0 -1
  194. package/bin/service/ai/types.d.ts +0 -174
  195. package/bin/service/ai/types.d.ts.map +0 -1
  196. package/bin/service/ai/types.js +0 -7
  197. package/bin/service/ai/types.js.map +0 -1
  198. package/bin/types/AIImageJobClaim.d.ts +0 -14
  199. package/bin/types/AIImageJobClaim.d.ts.map +0 -1
  200. package/bin/types/AIImageJobClaim.js +0 -7
  201. package/bin/types/AIImageJobClaim.js.map +0 -1
  202. package/bin/types/AIReasoning.d.ts +0 -25
  203. package/bin/types/AIReasoning.d.ts.map +0 -1
  204. package/bin/types/AIReasoning.js +0 -7
  205. package/bin/types/AIReasoning.js.map +0 -1
  206. package/bin/types/AIRouting.d.ts +0 -37
  207. package/bin/types/AIRouting.d.ts.map +0 -1
  208. package/bin/types/AIRouting.js +0 -7
  209. package/bin/types/AIRouting.js.map +0 -1
  210. package/bin/types/CityLanguageModelRuntime.d.ts +0 -46
  211. package/bin/types/CityLanguageModelRuntime.d.ts.map +0 -1
  212. package/bin/types/CityLanguageModelRuntime.js +0 -8
  213. package/bin/types/CityLanguageModelRuntime.js.map +0 -1
  214. package/bin/types/CityLanguageModelTransport.d.ts +0 -49
  215. package/bin/types/CityLanguageModelTransport.d.ts.map +0 -1
  216. package/bin/types/CityLanguageModelTransport.js +0 -9
  217. package/bin/types/CityLanguageModelTransport.js.map +0 -1
  218. package/bin/types/CityModelRuntime.d.ts +0 -17
  219. package/bin/types/CityModelRuntime.d.ts.map +0 -1
  220. package/bin/types/CityModelRuntime.js +0 -8
  221. package/bin/types/CityModelRuntime.js.map +0 -1
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Bureau 公共类型模块。
3
+ *
4
+ * Bureau 是某个 City 部署在独立服务器上的可选后端。它使用 Bureau Token
5
+ * 获取自身 City 上下文,并使用 Federation 公钥在本地验证 user_token。
6
+ */
7
+ /** Bureau 使用的标准 fetch 能力。 */
8
+ export type BureauFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
9
+ /** Bureau Token 可访问的 Federation 服务端能力。 */
10
+ export type BureauCapability = "accounts:read";
11
+ /** Federation 数据库中的 Bureau Token 记录。 */
12
+ export interface BureauTokenRecord extends Record<string, unknown> {
13
+ /** Bureau Token 的公开查找 ID。 */
14
+ token_id: string;
15
+ /** Bureau 所属的唯一 City ID。 */
16
+ city_id: string;
17
+ /** Bureau Token 完整明文的 SHA-256 Base64URL hash。 */
18
+ token_hash: string;
19
+ /** JSON 编码的 Bureau capability 列表。 */
20
+ capabilities: string;
21
+ /** Token 当前状态。 */
22
+ status: "active" | "revoked";
23
+ /** Token 创建时间。 */
24
+ created_at: string;
25
+ /** Token 最后更新时间。 */
26
+ updated_at: string;
27
+ }
28
+ /** 已通过 Federation 验证的 Bureau 服务端身份。 */
29
+ export interface RuntimeBureau {
30
+ /** Bureau Token ID。 */
31
+ token_id: string;
32
+ /** Bureau 所属的唯一 City ID。 */
33
+ city_id: string;
34
+ /** Bureau 被授予的 Federation 能力。 */
35
+ capabilities: BureauCapability[];
36
+ }
37
+ /** Federation 管理端登记 Bureau Token 的输入。 */
38
+ export interface RegisterBureauTokenInput {
39
+ /** CLI 生成的 Bureau Token 查找 ID。 */
40
+ token_id: string;
41
+ /** CLI 对完整 Bureau Token 计算的 SHA-256 Base64URL hash。 */
42
+ token_hash: string;
43
+ /** Bureau 所属的唯一 City ID。 */
44
+ city_id: string;
45
+ /** Bureau capability;默认允许读取用户账户数据。 */
46
+ capabilities?: BureauCapability[];
47
+ }
48
+ /** Federation 服务端列出的 Bureau Token 元数据。 */
49
+ export interface BureauTokenSummary {
50
+ /** Bureau Token 的公开查找 ID。 */
51
+ token_id: string;
52
+ /** Bureau 所属的唯一 City ID。 */
53
+ city_id: string;
54
+ /** Bureau capability。 */
55
+ capabilities: BureauCapability[];
56
+ /** Token 当前状态。 */
57
+ status: "active" | "revoked";
58
+ /** Token 创建时间。 */
59
+ created_at: string;
60
+ /** Token 最后更新时间。 */
61
+ updated_at: string;
62
+ }
63
+ /** Bureau 从 Federation 获取的可信运行上下文。 */
64
+ export interface BureauContext {
65
+ /** Bureau Token ID。 */
66
+ token_id: string;
67
+ /** Bureau 所属的唯一 City ID。 */
68
+ city_id: string;
69
+ /** Bureau 被授予的 Federation 能力。 */
70
+ capabilities: BureauCapability[];
71
+ }
72
+ /** Bureau 构造参数。 */
73
+ export interface BureauOptions {
74
+ /** 预先信任的 Federation HTTP 入口地址。 */
75
+ federation_url: string;
76
+ /** Federation 注册表中属于该 City 后端的 Bureau Token。 */
77
+ bureau_token: string;
78
+ /** 自定义 fetch 实现。 */
79
+ fetch?: BureauFetch;
80
+ /** Federation 上下文与 JWKS 的本地缓存时间,单位毫秒。 */
81
+ jwks_cache_ttl?: number;
82
+ }
83
+ /** Bureau 本地验签后得到的 Federation 用户身份。 */
84
+ export interface BureauIdentity {
85
+ /** Federation 用户 ID,来源于已验证 JWT。 */
86
+ user_id: string;
87
+ /** 与当前 Bureau 注册记录一致的 City ID。 */
88
+ city_id: string;
89
+ /** user_token 中携带的可信业务元数据。 */
90
+ metadata: Record<string, unknown>;
91
+ /** user_token 唯一 ID,来源于 JWT jti。 */
92
+ token_id: string;
93
+ /** user_token 过期时间,Unix 秒。 */
94
+ expires_at: number;
95
+ }
96
+ //# sourceMappingURL=Bureau.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Bureau.d.ts","sourceRoot":"","sources":["../../src/types/Bureau.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,6BAA6B;AAC7B,MAAM,MAAM,WAAW,GAAG,CACxB,KAAK,EAAE,WAAW,GAAG,GAAG,EACxB,IAAI,CAAC,EAAE,WAAW,KACf,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEvB,0CAA0C;AAC1C,MAAM,MAAM,gBAAgB,GAAG,eAAe,CAAC;AAE/C,wCAAwC;AACxC,MAAM,WAAW,iBAAkB,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAChE,6BAA6B;IAC7B,QAAQ,EAAE,MAAM,CAAC;IAEjB,4BAA4B;IAC5B,OAAO,EAAE,MAAM,CAAC;IAEhB,iDAAiD;IACjD,UAAU,EAAE,MAAM,CAAC;IAEnB,qCAAqC;IACrC,YAAY,EAAE,MAAM,CAAC;IAErB,kBAAkB;IAClB,MAAM,EAAE,QAAQ,GAAG,SAAS,CAAC;IAE7B,kBAAkB;IAClB,UAAU,EAAE,MAAM,CAAC;IAEnB,oBAAoB;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,uCAAuC;AACvC,MAAM,WAAW,aAAa;IAC5B,uBAAuB;IACvB,QAAQ,EAAE,MAAM,CAAC;IAEjB,4BAA4B;IAC5B,OAAO,EAAE,MAAM,CAAC;IAEhB,iCAAiC;IACjC,YAAY,EAAE,gBAAgB,EAAE,CAAC;CAClC;AAED,yCAAyC;AACzC,MAAM,WAAW,wBAAwB;IACvC,kCAAkC;IAClC,QAAQ,EAAE,MAAM,CAAC;IAEjB,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;IAEnB,4BAA4B;IAC5B,OAAO,EAAE,MAAM,CAAC;IAEhB,sCAAsC;IACtC,YAAY,CAAC,EAAE,gBAAgB,EAAE,CAAC;CACnC;AAED,0CAA0C;AAC1C,MAAM,WAAW,kBAAkB;IACjC,6BAA6B;IAC7B,QAAQ,EAAE,MAAM,CAAC;IAEjB,4BAA4B;IAC5B,OAAO,EAAE,MAAM,CAAC;IAEhB,yBAAyB;IACzB,YAAY,EAAE,gBAAgB,EAAE,CAAC;IAEjC,kBAAkB;IAClB,MAAM,EAAE,QAAQ,GAAG,SAAS,CAAC;IAE7B,kBAAkB;IAClB,UAAU,EAAE,MAAM,CAAC;IAEnB,oBAAoB;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,sCAAsC;AACtC,MAAM,WAAW,aAAa;IAC5B,uBAAuB;IACvB,QAAQ,EAAE,MAAM,CAAC;IAEjB,4BAA4B;IAC5B,OAAO,EAAE,MAAM,CAAC;IAEhB,iCAAiC;IACjC,YAAY,EAAE,gBAAgB,EAAE,CAAC;CAClC;AAED,mBAAmB;AACnB,MAAM,WAAW,aAAa;IAC5B,kCAAkC;IAClC,cAAc,EAAE,MAAM,CAAC;IAEvB,gDAAgD;IAChD,YAAY,EAAE,MAAM,CAAC;IAErB,oBAAoB;IACpB,KAAK,CAAC,EAAE,WAAW,CAAC;IAEpB,yCAAyC;IACzC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,uCAAuC;AACvC,MAAM,WAAW,cAAc;IAC7B,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAC;IAEhB,kCAAkC;IAClC,OAAO,EAAE,MAAM,CAAC;IAEhB,8BAA8B;IAC9B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAElC,oCAAoC;IACpC,QAAQ,EAAE,MAAM,CAAC;IAEjB,8BAA8B;IAC9B,UAAU,EAAE,MAAM,CAAC;CACpB"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Bureau 公共类型模块。
3
+ *
4
+ * Bureau 是某个 City 部署在独立服务器上的可选后端。它使用 Bureau Token
5
+ * 获取自身 City 上下文,并使用 Federation 公钥在本地验证 user_token。
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=Bureau.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Bureau.js","sourceRoot":"","sources":["../../src/types/Bureau.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * FederationAdmin 公共类型模块。
3
+ *
4
+ * FederationAdmin 只属于 Federation 控制面,不参与 City 或 Bureau 用户请求。
5
+ */
6
+ import type { FetchLike } from "../pact/http.js";
7
+ /** FederationAdmin 构造参数。 */
8
+ export interface FederationAdminOptions {
9
+ /** Federation 的 HTTP 入口地址。 */
10
+ federation_url: string;
11
+ /** Federation 全局管理 Bearer Secret。 */
12
+ admin_secret_key: string;
13
+ /** 自定义 fetch 实现。 */
14
+ fetch?: FetchLike;
15
+ }
16
+ //# sourceMappingURL=FederationAdmin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FederationAdmin.d.ts","sourceRoot":"","sources":["../../src/types/FederationAdmin.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,4BAA4B;AAC5B,MAAM,WAAW,sBAAsB;IACrC,8BAA8B;IAC9B,cAAc,EAAE,MAAM,CAAC;IAEvB,qCAAqC;IACrC,gBAAgB,EAAE,MAAM,CAAC;IAEzB,oBAAoB;IACpB,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * FederationAdmin 公共类型模块。
3
+ *
4
+ * FederationAdmin 只属于 Federation 控制面,不参与 City 或 Bureau 用户请求。
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=FederationAdmin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FederationAdmin.js","sourceRoot":"","sources":["../../src/types/FederationAdmin.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -11,9 +11,9 @@
11
11
  */
12
12
  export interface RuntimeMetering {
13
13
  /**
14
- * 计量所属 provider ID,例如 `deepseek`、`openai-image`。
14
+ * 计量所属 AIChannel ID,例如 `deepseek`、`openai-image`。
15
15
  */
16
- provider_id?: string;
16
+ channel_id?: string;
17
17
  /**
18
18
  * Downcity 模型 ID。
19
19
  */
@@ -1 +1 @@
1
- {"version":3,"file":"Metering.d.ts","sourceRoot":"","sources":["../../src/types/Metering.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC"}
1
+ {"version":3,"file":"Metering.d.ts","sourceRoot":"","sources":["../../src/types/Metering.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Federation 用户公共类型模块。
3
+ *
4
+ * City 直接访问 Federation,Bureau 也可以在完成本地验签后按需读取同一份
5
+ * 用户数据,因此两端共用这些类型。
6
+ */
7
+ /** Federation Accounts 当前用户 Profile。 */
8
+ export interface UserProfile {
9
+ /** Federation 用户 ID。 */
10
+ user_id: string;
11
+ /** 用户资料邮箱。 */
12
+ email: string;
13
+ /** 用户展示名称。 */
14
+ display_name: string;
15
+ /** 用户头像 URL。 */
16
+ avatar_url: string;
17
+ /** 用户个人简介。 */
18
+ bio: string;
19
+ /** 资料创建时间。 */
20
+ created_at: string;
21
+ /** 资料更新时间。 */
22
+ updated_at: string;
23
+ }
24
+ //# sourceMappingURL=User.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"User.d.ts","sourceRoot":"","sources":["../../src/types/User.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,wCAAwC;AACxC,MAAM,WAAW,WAAW;IAC1B,wBAAwB;IACxB,OAAO,EAAE,MAAM,CAAC;IAEhB,cAAc;IACd,KAAK,EAAE,MAAM,CAAC;IAEd,cAAc;IACd,YAAY,EAAE,MAAM,CAAC;IAErB,gBAAgB;IAChB,UAAU,EAAE,MAAM,CAAC;IAEnB,cAAc;IACd,GAAG,EAAE,MAAM,CAAC;IAEZ,cAAc;IACd,UAAU,EAAE,MAAM,CAAC;IAEnB,cAAc;IACd,UAAU,EAAE,MAAM,CAAC;CACpB"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Federation 用户公共类型模块。
3
+ *
4
+ * City 直接访问 Federation,Bureau 也可以在完成本地验签后按需读取同一份
5
+ * 用户数据,因此两端共用这些类型。
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=User.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"User.js","sourceRoot":"","sources":["../../src/types/User.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -4,7 +4,7 @@
4
4
  * LanguageModelV3 中的 URL、Uint8Array 和 Date 不是普通 JSON 值。本模块使用
5
5
  * 明确标签完成无损转换,并拒绝函数、symbol、bigint 和未知 class 实例。
6
6
  */
7
- import type { CityTransportJsonObject, CityTransportJsonValue } from "../types/CityLanguageModelTransport.js";
7
+ import type { CityTransportJsonObject, CityTransportJsonValue } from "../types/AITransport.js";
8
8
  /** 把 LanguageModelV3 值编码成 transport JSON。 */
9
9
  export declare function encode_city_transport_value(value: unknown): CityTransportJsonValue;
10
10
  /** 把 transport JSON 解码回 LanguageModelV3 可消费的值。 */
@@ -1 +1 @@
1
- {"version":3,"file":"CityLanguageModelCodec.d.ts","sourceRoot":"","sources":["../../src/utils/CityLanguageModelCodec.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,uBAAuB,EACvB,sBAAsB,EACvB,MAAM,wCAAwC,CAAC;AAIhD,6CAA6C;AAC7C,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,sBAAsB,CA0ClF;AAED,kDAAkD;AAClD,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAsBlF;AAED,uBAAuB;AACvB,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,GAAG,uBAAuB,CAMpF"}
1
+ {"version":3,"file":"CityLanguageModelCodec.d.ts","sourceRoot":"","sources":["../../src/utils/CityLanguageModelCodec.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,uBAAuB,EACvB,sBAAsB,EACvB,MAAM,yBAAyB,CAAC;AAIjC,6CAA6C;AAC7C,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,GAAG,sBAAsB,CA0ClF;AAED,kDAAkD;AAClD,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAsBlF;AAED,uBAAuB;AACvB,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,GAAG,uBAAuB,CAMpF"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * LanguageModelV3 流结果聚合工具。
3
+ *
4
+ * 该模块只理解 AI SDK LanguageModelV3 的标准流事件,不了解 Federation transport
5
+ * 或具体上游协议。CityModel 非流式调用和 AIChannel 通用 text action 复用这里,
6
+ * 保证两条入口对 text、reasoning、tool、usage 和 metadata 的收口语义一致。
7
+ */
8
+ import type { LanguageModelV3GenerateResult, LanguageModelV3StreamPart } from "../types/AI.js";
9
+ /** 将标准 LanguageModelV3 流聚合为一次非流式生成结果。 */
10
+ export declare function collect_city_language_model_stream(stream: ReadableStream<LanguageModelV3StreamPart>, request_body?: unknown): Promise<LanguageModelV3GenerateResult>;
11
+ //# sourceMappingURL=CityLanguageModelResult.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CityLanguageModelResult.d.ts","sourceRoot":"","sources":["../../src/utils/CityLanguageModelResult.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,6BAA6B,EAC7B,yBAAyB,EAC1B,MAAM,gBAAgB,CAAC;AAExB,yCAAyC;AACzC,wBAAsB,kCAAkC,CACtD,MAAM,EAAE,cAAc,CAAC,yBAAyB,CAAC,EACjD,YAAY,CAAC,EAAE,OAAO,GACrB,OAAO,CAAC,6BAA6B,CAAC,CA+DxC"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * LanguageModelV3 流结果聚合工具。
3
+ *
4
+ * 该模块只理解 AI SDK LanguageModelV3 的标准流事件,不了解 Federation transport
5
+ * 或具体上游协议。CityModel 非流式调用和 AIChannel 通用 text action 复用这里,
6
+ * 保证两条入口对 text、reasoning、tool、usage 和 metadata 的收口语义一致。
7
+ */
8
+ /** 将标准 LanguageModelV3 流聚合为一次非流式生成结果。 */
9
+ export async function collect_city_language_model_stream(stream, request_body) {
10
+ const reader = stream.getReader();
11
+ const content = [];
12
+ const text_blocks = new Map();
13
+ const reasoning_blocks = new Map();
14
+ let warnings = [];
15
+ let response;
16
+ let finish_reason;
17
+ let usage;
18
+ let provider_metadata;
19
+ while (true) {
20
+ const chunk = await reader.read();
21
+ if (chunk.done)
22
+ break;
23
+ const part = chunk.value;
24
+ const type = String(part.type ?? "");
25
+ if (type === "error")
26
+ throw part.error;
27
+ if (type === "stream-start") {
28
+ warnings = Array.isArray(part.warnings) ? part.warnings : [];
29
+ }
30
+ else if (type === "response-metadata") {
31
+ const { type: _type, ...metadata } = part;
32
+ response = metadata;
33
+ }
34
+ else if (type === "text-start" || type === "reasoning-start") {
35
+ const block = {
36
+ type: type === "text-start" ? "text" : "reasoning",
37
+ text: "",
38
+ ...(part.providerMetadata
39
+ ? { providerMetadata: part.providerMetadata }
40
+ : {}),
41
+ };
42
+ content.push(block);
43
+ const blocks = type === "text-start" ? text_blocks : reasoning_blocks;
44
+ blocks.set(String(part.id), block);
45
+ }
46
+ else if (type === "text-delta" || type === "reasoning-delta") {
47
+ const blocks = type === "text-delta" ? text_blocks : reasoning_blocks;
48
+ const block = blocks.get(String(part.id));
49
+ if (block) {
50
+ block.text = `${String(block.text ?? "")}${String(part.delta ?? "")}`;
51
+ }
52
+ }
53
+ else if (["file", "source", "tool-call", "tool-result", "tool-approval-request"]
54
+ .includes(type)) {
55
+ content.push(part);
56
+ }
57
+ else if (type === "finish") {
58
+ finish_reason = part.finishReason;
59
+ usage = part.usage;
60
+ provider_metadata = part.providerMetadata;
61
+ }
62
+ }
63
+ if (!finish_reason || !usage) {
64
+ throw new Error("Language model stream ended without finish usage");
65
+ }
66
+ return {
67
+ content,
68
+ finishReason: finish_reason,
69
+ usage,
70
+ warnings,
71
+ ...(provider_metadata ? { providerMetadata: provider_metadata } : {}),
72
+ ...(request_body !== undefined ? { request: { body: request_body } } : {}),
73
+ ...(response ? { response } : {}),
74
+ };
75
+ }
76
+ //# sourceMappingURL=CityLanguageModelResult.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CityLanguageModelResult.js","sourceRoot":"","sources":["../../src/utils/CityLanguageModelResult.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@downcity/city",
3
- "version": "0.2.200",
3
+ "version": "0.2.211",
4
4
  "description": "Downcity City runtime and City access SDK for services, actions, auth, env, and cities.",
5
5
  "type": "module",
6
6
  "main": "./bin/index.js",
@@ -41,10 +41,11 @@
41
41
  "typescript": "^6.0.3"
42
42
  },
43
43
  "dependencies": {
44
- "@downcity/type": "0.1.153",
44
+ "@downcity/type": "0.1.158",
45
45
  "ai": "^6.0.193",
46
46
  "drizzle-orm": "^0.45.2",
47
- "hono": "^4.12.23"
47
+ "hono": "^4.12.23",
48
+ "jose": "^6.2.3"
48
49
  },
49
50
  "scripts": {
50
51
  "build": "rm -rf bin tsconfig.tsbuildinfo && tsc",
@@ -1,27 +0,0 @@
1
- /**
2
- * user_token 签发与校验模块。
3
- *
4
- * Downcity 使用 Web Crypto API 的 HMAC-SHA256 生成最小可用的 user_token。
5
- * 零 Node.js 依赖,兼容所有现代运行时(Node、Workers、Deno、Bun、浏览器)。
6
- */
7
- import type { CreateUserTokenInput, UserTokenPayload } from "./types.js";
8
- export declare class TokenSigner {
9
- readonly signingKey: string;
10
- /** 缓存的 CryptoKey,避免每次签名都重新 import */
11
- private cryptoKey?;
12
- constructor(signingKey: string);
13
- /**
14
- * 获取(或缓存)HMAC CryptoKey。
15
- *
16
- * 使用 Web Crypto API 的 crypto.subtle.importKey,
17
- * 首次调用时创建并缓存 Promise,后续复用。
18
- */
19
- private getCryptoKey;
20
- /** 签发 user_token */
21
- sign(input: CreateUserTokenInput): Promise<string>;
22
- /** 校验并解析 user_token,失败抛 httpError(401) */
23
- verify(token: string): Promise<UserTokenPayload>;
24
- /** 把 ttl 解析成秒数 */
25
- static parseTTL(ttl: string | number): number;
26
- }
27
- //# sourceMappingURL=token-signer.d.ts.map
@@ -1 +0,0 @@
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"}
@@ -1,116 +0,0 @@
1
- /**
2
- * user_token 签发与校验模块。
3
- *
4
- * Downcity 使用 Web Crypto API 的 HMAC-SHA256 生成最小可用的 user_token。
5
- * 零 Node.js 依赖,兼容所有现代运行时(Node、Workers、Deno、Bun、浏览器)。
6
- */
7
- import { httpError, base64UrlEncode, base64UrlDecode, base64UrlEncodeBytes, base64UrlDecodeBytes, timingSafeEqualBytes } from "../../utils/helpers.js";
8
- export class TokenSigner {
9
- signingKey;
10
- /** 缓存的 CryptoKey,避免每次签名都重新 import */
11
- cryptoKey;
12
- constructor(signingKey) {
13
- if (!signingKey) {
14
- throw new Error("TokenSigner requires a signing key");
15
- }
16
- this.signingKey = signingKey;
17
- }
18
- /**
19
- * 获取(或缓存)HMAC CryptoKey。
20
- *
21
- * 使用 Web Crypto API 的 crypto.subtle.importKey,
22
- * 首次调用时创建并缓存 Promise,后续复用。
23
- */
24
- getCryptoKey() {
25
- if (!this.cryptoKey) {
26
- const encoder = new TextEncoder();
27
- this.cryptoKey = crypto.subtle.importKey("raw", encoder.encode(this.signingKey), { name: "HMAC", hash: "SHA-256" }, false, ["sign", "verify"]);
28
- }
29
- return this.cryptoKey;
30
- }
31
- /** 签发 user_token */
32
- async sign(input) {
33
- if (!input || typeof input.city_id !== "string" || input.city_id.length === 0) {
34
- throw new TypeError("city_id is required");
35
- }
36
- if (typeof input.user_id !== "string" || input.user_id.length === 0) {
37
- throw new TypeError("user_id is required");
38
- }
39
- const ttl = input.ttl;
40
- const now = Math.floor(Date.now() / 1000);
41
- const payload = {
42
- aud: "downcity:user",
43
- city_id: input.city_id,
44
- user_id: input.user_id,
45
- metadata: input.metadata ?? {},
46
- iat: now,
47
- };
48
- if (ttl) {
49
- payload.exp = now + TokenSigner.parseTTL(ttl);
50
- }
51
- const encodedPayload = base64UrlEncode(JSON.stringify(payload));
52
- const signature = await signPayload(await this.getCryptoKey(), encodedPayload);
53
- return `ub_${encodedPayload}.${signature}`;
54
- }
55
- /** 校验并解析 user_token,失败抛 httpError(401) */
56
- async verify(token) {
57
- const rawToken = token.startsWith("ub_") ? token.slice(3) : token;
58
- const [encodedPayload, signature] = rawToken.split(".");
59
- if (!encodedPayload || !signature) {
60
- throw httpError(401, "Invalid user token");
61
- }
62
- if (!await verifyPayload(await this.getCryptoKey(), encodedPayload, signature)) {
63
- throw httpError(401, "Invalid user token signature");
64
- }
65
- const payload = JSON.parse(base64UrlDecode(encodedPayload));
66
- const now = Math.floor(Date.now() / 1000);
67
- if (payload.exp && payload.exp <= now) {
68
- throw httpError(401, "User token expired");
69
- }
70
- if (payload.aud !== "downcity:user") {
71
- throw httpError(401, "Invalid user token audience");
72
- }
73
- if (!payload.city_id || !payload.user_id) {
74
- throw httpError(401, "Invalid user token payload");
75
- }
76
- return payload;
77
- }
78
- /** 把 ttl 解析成秒数 */
79
- static parseTTL(ttl) {
80
- if (typeof ttl === "number" && Number.isFinite(ttl) && ttl > 0) {
81
- return ttl;
82
- }
83
- if (typeof ttl !== "string") {
84
- throw new TypeError("ttl must be a positive number of seconds or a string like 1h");
85
- }
86
- const match = ttl.match(/^(\d+)(s|m|h|d)$/);
87
- if (!match) {
88
- throw new Error(`Invalid ttl: ${ttl}`);
89
- }
90
- const value = Number(match[1]);
91
- const unit = match[2];
92
- const multipliers = {
93
- s: 1,
94
- m: 60,
95
- h: 60 * 60,
96
- d: 24 * 60 * 60,
97
- };
98
- return value * multipliers[unit];
99
- }
100
- }
101
- /**
102
- * 使用 HMAC-SHA256 对 payload 签名,返回 base64url 编码的签名。
103
- */
104
- async function signPayload(cryptoKey, encodedPayload) {
105
- const signature = await crypto.subtle.sign("HMAC", cryptoKey, new TextEncoder().encode(encodedPayload));
106
- return base64UrlEncodeBytes(new Uint8Array(signature));
107
- }
108
- /**
109
- * 验证 HMAC-SHA256 签名是否匹配。
110
- */
111
- async function verifyPayload(cryptoKey, encodedPayload, signature) {
112
- const expected = base64UrlDecodeBytes(signature);
113
- const actual = await crypto.subtle.sign("HMAC", cryptoKey, new TextEncoder().encode(encodedPayload));
114
- return timingSafeEqualBytes(new Uint8Array(actual), expected);
115
- }
116
- //# sourceMappingURL=token-signer.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"token-signer.js","sourceRoot":"","sources":["../../../src/federation/auth/token-signer.ts"],"names":[],"mappings":"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"}
@@ -1,76 +0,0 @@
1
- /**
2
- * AI Provider 扣费协议。
3
- *
4
- * 关键说明(中文)
5
- * - Provider 自己理解上游 usage 与价格规则,并返回最终应扣金额。
6
- * - AIService 只负责在正确的生命周期内提交扣费,不理解 token/cache 等 provider 细节。
7
- * - Balance bridge 只暴露通用 charge 能力,避免 @downcity/city 反向依赖 @downcity/services。
8
- */
9
- import type { Context } from "../service.js";
10
- /**
11
- * Provider 计算出的单次扣费结果。
12
- */
13
- export interface AIProviderChargeLine {
14
- /**
15
- * 可选扣费用户 ID。
16
- *
17
- * 图片 result 轮询可能由 admin 或服务端代发,没有当前 user。
18
- * 这时 bill() 应从已保存任务归属中返回 user_id,AIService 会优先使用它。
19
- */
20
- user_id?: string;
21
- /** 扣费额度,单位为 credits。 */
22
- credits: number;
23
- /** 账单说明。 */
24
- note?: string;
25
- /** 外部引用 ID。 */
26
- ref?: string;
27
- /** 内部审计信息,不作为跨 provider 的公共 usage 协议。 */
28
- metadata?: Record<string, unknown>;
29
- }
30
- /**
31
- * AIService 提交给外部 Balance bridge 的扣费输入。
32
- */
33
- export interface AIBalanceChargeInput extends AIProviderChargeLine {
34
- /** 当前用户 ID。 */
35
- user_id: string;
36
- /** 可选幂等键;相同键的重复提交必须只产生一次扣费。 */
37
- idempotency_key?: string;
38
- }
39
- /**
40
- * AIService 依赖的最小 Balance bridge。
41
- */
42
- export interface AIBalanceBridge {
43
- /**
44
- * 执行余额前置检查。
45
- *
46
- * AIService 默认调用时不传 needed_credits,只拦截已经欠费的用户。
47
- */
48
- precheck?(user_id: string, needed_credits?: number): Promise<{
49
- credits: number;
50
- }>;
51
- /** 执行扣费并记录账单。 */
52
- charge(input: AIBalanceChargeInput): Promise<unknown>;
53
- }
54
- /**
55
- * Provider 或模型生成扣费行的方法。
56
- */
57
- export type AIProviderBillFn = (ctx: Context, output: unknown) => AIProviderChargeLine | Promise<AIProviderChargeLine | undefined> | undefined;
58
- /**
59
- * Provider action 可返回的带扣费普通输出。
60
- */
61
- export interface AIProviderChargedOutput<T = unknown> {
62
- /** 对外返回的原始 action 输出。 */
63
- output: T;
64
- /** Provider 已计算好的扣费结果。 */
65
- charge?: AIProviderChargeLine | Promise<AIProviderChargeLine | undefined> | undefined;
66
- }
67
- /**
68
- * Provider action 可返回的带扣费 Response 输出。
69
- */
70
- export interface AIProviderChargedResponse {
71
- /** 对外返回的 HTTP Response。 */
72
- response: Response;
73
- /** Provider 已计算好的扣费结果。 */
74
- charge?: AIProviderChargeLine | Promise<AIProviderChargeLine | undefined> | undefined;
75
- }
76
- //# sourceMappingURL=charge.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"charge.d.ts","sourceRoot":"","sources":["../../../src/service/ai/charge.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wBAAwB;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,oBAAoB;IAChE,eAAe;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,+BAA+B;IAC/B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAElF,iBAAiB;IACjB,MAAM,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACvD;AAED;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAC7B,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,OAAO,KACZ,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC;AAElF;;GAEG;AACH,MAAM,WAAW,uBAAuB,CAAC,CAAC,GAAG,OAAO;IAClD,yBAAyB;IACzB,MAAM,EAAE,CAAC,CAAC;IACV,0BAA0B;IAC1B,MAAM,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC;CACvF;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,2BAA2B;IAC3B,QAAQ,EAAE,QAAQ,CAAC;IACnB,0BAA0B;IAC1B,MAAM,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC;CACvF"}
@@ -1,10 +0,0 @@
1
- /**
2
- * AI Provider 扣费协议。
3
- *
4
- * 关键说明(中文)
5
- * - Provider 自己理解上游 usage 与价格规则,并返回最终应扣金额。
6
- * - AIService 只负责在正确的生命周期内提交扣费,不理解 token/cache 等 provider 细节。
7
- * - Balance bridge 只暴露通用 charge 能力,避免 @downcity/city 反向依赖 @downcity/services。
8
- */
9
- export {};
10
- //# sourceMappingURL=charge.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"charge.js","sourceRoot":"","sources":["../../../src/service/ai/charge.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}