@undefineds.co/xpod 0.1.6 → 0.2.0-preview.2

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 (307) hide show
  1. package/README.md +141 -2
  2. package/config/cli.json +9 -71
  3. package/config/cloud.json +34 -7
  4. package/config/local.json +6 -2
  5. package/config/resolver.json +11 -49
  6. package/config/runtime-open.json +22 -0
  7. package/config/xpod.base.json +32 -0
  8. package/config/xpod.cluster.json +2 -44
  9. package/config/xpod.json +5 -2
  10. package/dist/api/ApiServer.js +1 -1
  11. package/dist/api/ApiServer.js.map +1 -1
  12. package/dist/api/auth/AuthContext.d.ts +12 -1
  13. package/dist/api/auth/AuthContext.js +18 -1
  14. package/dist/api/auth/AuthContext.js.map +1 -1
  15. package/dist/api/auth/ClientCredentialsAuthenticator.d.ts +0 -1
  16. package/dist/api/auth/ClientCredentialsAuthenticator.js.map +1 -1
  17. package/dist/api/auth/ServiceTokenAuthenticator.d.ts +18 -0
  18. package/dist/api/auth/ServiceTokenAuthenticator.js +50 -0
  19. package/dist/api/auth/ServiceTokenAuthenticator.js.map +1 -0
  20. package/dist/api/auth/index.d.ts +1 -0
  21. package/dist/api/auth/index.js +1 -0
  22. package/dist/api/auth/index.js.map +1 -1
  23. package/dist/api/chatkit/ai-provider.d.ts +0 -10
  24. package/dist/api/chatkit/ai-provider.js +11 -120
  25. package/dist/api/chatkit/ai-provider.js.map +1 -1
  26. package/dist/api/chatkit/default-agent.js +11 -8
  27. package/dist/api/chatkit/default-agent.js.map +1 -1
  28. package/dist/api/chatkit/pod-store.js +19 -3
  29. package/dist/api/chatkit/pod-store.js.map +1 -1
  30. package/dist/api/chatkit/schema.d.ts +9 -3
  31. package/dist/api/chatkit/schema.js +14 -6
  32. package/dist/api/chatkit/schema.js.map +1 -1
  33. package/dist/api/container/business-token.d.ts +9 -0
  34. package/dist/api/container/business-token.js +32 -0
  35. package/dist/api/container/business-token.js.map +1 -0
  36. package/dist/api/container/cloud.js +36 -12
  37. package/dist/api/container/cloud.js.map +1 -1
  38. package/dist/api/container/common.js +12 -5
  39. package/dist/api/container/common.js.map +1 -1
  40. package/dist/api/container/index.js +94 -14
  41. package/dist/api/container/index.js.map +1 -1
  42. package/dist/api/container/local.js +2 -1
  43. package/dist/api/container/local.js.map +1 -1
  44. package/dist/api/container/routes.js +81 -15
  45. package/dist/api/container/routes.js.map +1 -1
  46. package/dist/api/container/types.d.ts +8 -6
  47. package/dist/api/container/types.js.map +1 -1
  48. package/dist/api/handlers/AdminHandler.js +9 -9
  49. package/dist/api/handlers/AdminHandler.js.map +1 -1
  50. package/dist/api/handlers/ApiKeyHandler.js +0 -6
  51. package/dist/api/handlers/ApiKeyHandler.js.map +1 -1
  52. package/dist/api/handlers/EdgeNodeSignalHandler.d.ts +17 -0
  53. package/dist/api/handlers/EdgeNodeSignalHandler.js +171 -0
  54. package/dist/api/handlers/EdgeNodeSignalHandler.js.map +1 -0
  55. package/dist/api/handlers/PodManagementHandler.d.ts +5 -4
  56. package/dist/api/handlers/PodManagementHandler.js +11 -10
  57. package/dist/api/handlers/PodManagementHandler.js.map +1 -1
  58. package/dist/api/handlers/ProvisionHandler.d.ts +42 -0
  59. package/dist/api/handlers/ProvisionHandler.js +161 -0
  60. package/dist/api/handlers/ProvisionHandler.js.map +1 -0
  61. package/dist/api/handlers/QuotaHandler.d.ts +7 -7
  62. package/dist/api/handlers/QuotaHandler.js +143 -73
  63. package/dist/api/handlers/QuotaHandler.js.map +1 -1
  64. package/dist/api/handlers/SubdomainClientHandler.js +2 -2
  65. package/dist/api/handlers/SubdomainClientHandler.js.map +1 -1
  66. package/dist/api/handlers/SubdomainHandler.js +13 -8
  67. package/dist/api/handlers/SubdomainHandler.js.map +1 -1
  68. package/dist/api/handlers/UsageHandler.d.ts +14 -0
  69. package/dist/api/handlers/UsageHandler.js +123 -0
  70. package/dist/api/handlers/UsageHandler.js.map +1 -0
  71. package/dist/api/handlers/index.d.ts +3 -1
  72. package/dist/api/handlers/index.js +3 -1
  73. package/dist/api/handlers/index.js.map +1 -1
  74. package/dist/api/main.js +18 -0
  75. package/dist/api/main.js.map +1 -1
  76. package/dist/api/middleware/OpenAuthMiddleware.d.ts +12 -0
  77. package/dist/api/middleware/OpenAuthMiddleware.js +27 -0
  78. package/dist/api/middleware/OpenAuthMiddleware.js.map +1 -0
  79. package/dist/api/runtime.d.ts +15 -0
  80. package/dist/api/runtime.js +104 -0
  81. package/dist/api/runtime.js.map +1 -0
  82. package/dist/api/service/VercelChatService.d.ts +16 -7
  83. package/dist/api/service/VercelChatService.js +98 -178
  84. package/dist/api/service/VercelChatService.js.map +1 -1
  85. package/dist/api/store/DrizzleClientCredentialsStore.d.ts +6 -11
  86. package/dist/api/store/DrizzleClientCredentialsStore.js +9 -39
  87. package/dist/api/store/DrizzleClientCredentialsStore.js.map +1 -1
  88. package/dist/authorization/AuthModeSelector.d.ts +10 -0
  89. package/dist/authorization/AuthModeSelector.js +27 -0
  90. package/dist/authorization/AuthModeSelector.js.map +1 -0
  91. package/dist/authorization/AuthModeSelector.jsonld +81 -0
  92. package/dist/cli/commands/account.d.ts +6 -0
  93. package/dist/cli/commands/account.js +119 -0
  94. package/dist/cli/commands/account.js.map +1 -0
  95. package/dist/cli/commands/auth.js +20 -29
  96. package/dist/cli/commands/auth.js.map +1 -1
  97. package/dist/cli/commands/backup.d.ts +15 -0
  98. package/dist/cli/commands/backup.js +286 -0
  99. package/dist/cli/commands/backup.js.map +1 -0
  100. package/dist/cli/commands/config.d.ts +34 -3
  101. package/dist/cli/commands/config.js +195 -258
  102. package/dist/cli/commands/config.js.map +1 -1
  103. package/dist/cli/commands/doctor.d.ts +6 -0
  104. package/dist/cli/commands/doctor.js +94 -0
  105. package/dist/cli/commands/doctor.js.map +1 -0
  106. package/dist/cli/commands/pod.d.ts +6 -0
  107. package/dist/cli/commands/pod.js +124 -0
  108. package/dist/cli/commands/pod.js.map +1 -0
  109. package/dist/cli/commands/start.js +28 -5
  110. package/dist/cli/commands/start.js.map +1 -1
  111. package/dist/cli/index.js +9 -0
  112. package/dist/cli/index.js.map +1 -1
  113. package/dist/cli/lib/credentials-store.d.ts +17 -0
  114. package/dist/cli/lib/credentials-store.js +73 -0
  115. package/dist/cli/lib/credentials-store.js.map +1 -0
  116. package/dist/cli/lib/css-account.d.ts +17 -0
  117. package/dist/cli/lib/css-account.js +56 -0
  118. package/dist/cli/lib/css-account.js.map +1 -1
  119. package/dist/cli/lib/pod-thread-store.d.ts +57 -0
  120. package/dist/cli/lib/pod-thread-store.js +310 -0
  121. package/dist/cli/lib/pod-thread-store.js.map +1 -0
  122. package/dist/cli/lib/solid-auth.d.ts +20 -0
  123. package/dist/cli/lib/solid-auth.js +70 -0
  124. package/dist/cli/lib/solid-auth.js.map +1 -0
  125. package/dist/components/components.jsonld +5 -8
  126. package/dist/components/context.jsonld +114 -244
  127. package/dist/edge/EdgeNodeAgent.js +2 -2
  128. package/dist/edge/EdgeNodeAgent.js.map +1 -1
  129. package/dist/edge/EdgeNodeDnsCoordinator.d.ts +1 -7
  130. package/dist/edge/EdgeNodeDnsCoordinator.js +31 -41
  131. package/dist/edge/EdgeNodeDnsCoordinator.js.map +1 -1
  132. package/dist/edge/EdgeNodeDnsCoordinator.jsonld +1 -27
  133. package/dist/edge/EdgeNodeModeDetector.d.ts +1 -1
  134. package/dist/edge/EdgeNodeModeDetector.js +9 -11
  135. package/dist/edge/EdgeNodeModeDetector.js.map +1 -1
  136. package/dist/http/ClusterIngressRouter.js +3 -3
  137. package/dist/http/ClusterIngressRouter.js.map +1 -1
  138. package/dist/http/ClusterWebSocketConfigurator.js +2 -2
  139. package/dist/http/ClusterWebSocketConfigurator.js.map +1 -1
  140. package/dist/http/PodRoutingHttpHandler.js +2 -2
  141. package/dist/http/PodRoutingHttpHandler.js.map +1 -1
  142. package/dist/http/cluster/PodMigrationHttpHandler.d.ts +1 -1
  143. package/dist/http/cluster/PodMigrationHttpHandler.js +1 -1
  144. package/dist/http/cluster/PodMigrationHttpHandler.js.map +1 -1
  145. package/dist/identity/drizzle/EdgeNodeRepository.d.ts +37 -4
  146. package/dist/identity/drizzle/EdgeNodeRepository.js +120 -128
  147. package/dist/identity/drizzle/EdgeNodeRepository.js.map +1 -1
  148. package/dist/identity/drizzle/ServiceTokenRepository.d.ts +52 -0
  149. package/dist/identity/drizzle/ServiceTokenRepository.js +143 -0
  150. package/dist/identity/drizzle/ServiceTokenRepository.js.map +1 -0
  151. package/dist/identity/drizzle/db.d.ts +9 -0
  152. package/dist/identity/drizzle/db.js +208 -1
  153. package/dist/identity/drizzle/db.js.map +1 -1
  154. package/dist/identity/drizzle/schema.pg.d.ts +5 -0
  155. package/dist/identity/drizzle/schema.pg.js +49 -20
  156. package/dist/identity/drizzle/schema.pg.js.map +1 -1
  157. package/dist/identity/drizzle/schema.sqlite.d.ts +332 -57
  158. package/dist/identity/drizzle/schema.sqlite.js +48 -18
  159. package/dist/identity/drizzle/schema.sqlite.js.map +1 -1
  160. package/dist/identity/oidc/AutoDetectIdentityProviderHandler.js +6 -4
  161. package/dist/identity/oidc/AutoDetectIdentityProviderHandler.js.map +1 -1
  162. package/dist/index.d.ts +6 -9
  163. package/dist/index.js +12 -14
  164. package/dist/index.js.map +1 -1
  165. package/dist/main.js +25 -8
  166. package/dist/main.js.map +1 -1
  167. package/dist/provision/ProvisionCodeCodec.d.ts +39 -0
  168. package/dist/provision/ProvisionCodeCodec.js +65 -0
  169. package/dist/provision/ProvisionCodeCodec.js.map +1 -0
  170. package/dist/provision/ProvisionCodeCodec.jsonld +47 -0
  171. package/dist/provision/ProvisionPodCreator.d.ts +20 -0
  172. package/dist/provision/ProvisionPodCreator.js +84 -0
  173. package/dist/provision/ProvisionPodCreator.js.map +1 -0
  174. package/dist/provision/ProvisionPodCreator.jsonld +118 -0
  175. package/dist/quota/DrizzleQuotaService.d.ts +17 -3
  176. package/dist/quota/DrizzleQuotaService.js +108 -8
  177. package/dist/quota/DrizzleQuotaService.js.map +1 -1
  178. package/dist/quota/DrizzleQuotaService.jsonld +33 -22
  179. package/dist/quota/NoopQuotaService.d.ts +7 -1
  180. package/dist/quota/NoopQuotaService.js +12 -0
  181. package/dist/quota/NoopQuotaService.js.map +1 -1
  182. package/dist/quota/NoopQuotaService.jsonld +24 -0
  183. package/dist/quota/QuotaService.d.ts +17 -0
  184. package/dist/quota/QuotaService.js +5 -0
  185. package/dist/quota/QuotaService.js.map +1 -1
  186. package/dist/quota/QuotaService.jsonld +50 -0
  187. package/dist/runtime/Proxy.d.ts +22 -4
  188. package/dist/runtime/Proxy.js +154 -35
  189. package/dist/runtime/Proxy.js.map +1 -1
  190. package/dist/runtime/XpodRuntime.d.ts +49 -0
  191. package/dist/runtime/XpodRuntime.js +374 -0
  192. package/dist/runtime/XpodRuntime.js.map +1 -0
  193. package/dist/runtime/env-utils.d.ts +2 -0
  194. package/dist/runtime/env-utils.js +55 -0
  195. package/dist/runtime/env-utils.js.map +1 -0
  196. package/dist/runtime/index.d.ts +4 -0
  197. package/dist/runtime/index.js +8 -1
  198. package/dist/runtime/index.js.map +1 -1
  199. package/dist/runtime/socket-fetch.d.ts +1 -0
  200. package/dist/runtime/socket-fetch.js +72 -0
  201. package/dist/runtime/socket-fetch.js.map +1 -0
  202. package/dist/runtime/socket-http.d.ts +1 -0
  203. package/dist/runtime/socket-http.js +142 -0
  204. package/dist/runtime/socket-http.js.map +1 -0
  205. package/dist/runtime/socket-utils.d.ts +2 -0
  206. package/dist/runtime/socket-utils.js +34 -0
  207. package/dist/runtime/socket-utils.js.map +1 -0
  208. package/dist/service/{EdgeNodeHeartbeatService.d.ts → EdgeNodeSignalClient.d.ts} +3 -3
  209. package/dist/service/{EdgeNodeHeartbeatService.js → EdgeNodeSignalClient.js} +4 -4
  210. package/dist/service/EdgeNodeSignalClient.js.map +1 -0
  211. package/dist/service/PodMigrationService.d.ts +1 -2
  212. package/dist/service/PodMigrationService.js +1 -2
  213. package/dist/service/PodMigrationService.js.map +1 -1
  214. package/dist/storage/SparqlUpdateResourceStore.js +1 -1
  215. package/dist/storage/SparqlUpdateResourceStore.js.map +1 -1
  216. package/dist/storage/accessors/MinioDataAccessor.d.ts +6 -0
  217. package/dist/storage/accessors/MinioDataAccessor.js +10 -0
  218. package/dist/storage/accessors/MinioDataAccessor.js.map +1 -1
  219. package/dist/storage/accessors/MinioDataAccessor.jsonld +4 -0
  220. package/dist/storage/accessors/MixDataAccessor.d.ts +2 -1
  221. package/dist/storage/accessors/MixDataAccessor.js +12 -1
  222. package/dist/storage/accessors/MixDataAccessor.js.map +1 -1
  223. package/dist/storage/accessors/MixDataAccessor.jsonld +19 -0
  224. package/dist/storage/locking/UrlAwareRedisLocker.d.ts +18 -0
  225. package/dist/storage/locking/UrlAwareRedisLocker.js +60 -0
  226. package/dist/storage/locking/UrlAwareRedisLocker.js.map +1 -0
  227. package/dist/storage/locking/UrlAwareRedisLocker.jsonld +123 -0
  228. package/dist/storage/quota/UsageRepository.d.ts +41 -8
  229. package/dist/storage/quota/UsageRepository.js +252 -50
  230. package/dist/storage/quota/UsageRepository.js.map +1 -1
  231. package/dist/storage/sparql/ComunicaQuintEngine.d.ts +9 -0
  232. package/dist/storage/sparql/ComunicaQuintEngine.js +50 -9
  233. package/dist/storage/sparql/ComunicaQuintEngine.js.map +1 -1
  234. package/dist/storage/sparql/QueryOptimizer.js +13 -1
  235. package/dist/storage/sparql/QueryOptimizer.js.map +1 -1
  236. package/dist/storage/sparql/QuintQuerySource.d.ts +14 -0
  237. package/dist/storage/sparql/QuintQuerySource.js +152 -1
  238. package/dist/storage/sparql/QuintQuerySource.js.map +1 -1
  239. package/dist/storage/sparql/SubgraphQueryEngine.d.ts +1 -0
  240. package/dist/storage/sparql/SubgraphQueryEngine.js +6 -2
  241. package/dist/storage/sparql/SubgraphQueryEngine.js.map +1 -1
  242. package/dist/storage/sparql/SubgraphQueryEngine.jsonld +4 -0
  243. package/dist/subdomain/SubdomainClient.d.ts +3 -3
  244. package/dist/subdomain/SubdomainClient.js +1 -1
  245. package/dist/subdomain/SubdomainClient.js.map +1 -1
  246. package/dist/subdomain/SubdomainService.d.ts +15 -16
  247. package/dist/subdomain/SubdomainService.js +80 -54
  248. package/dist/subdomain/SubdomainService.js.map +1 -1
  249. package/dist/subdomain/SubdomainService.jsonld +22 -26
  250. package/dist/supervisor/Supervisor.d.ts +7 -2
  251. package/dist/supervisor/Supervisor.js +33 -1
  252. package/dist/supervisor/Supervisor.js.map +1 -1
  253. package/dist/test-utils/index.d.ts +4 -0
  254. package/dist/test-utils/index.js +8 -0
  255. package/dist/test-utils/index.js.map +1 -0
  256. package/dist/test-utils/no-auth-xpod.d.ts +11 -0
  257. package/dist/test-utils/no-auth-xpod.js +25 -0
  258. package/dist/test-utils/no-auth-xpod.js.map +1 -0
  259. package/dist/test-utils/seed-pod.d.ts +5 -0
  260. package/dist/test-utils/seed-pod.js +61 -0
  261. package/dist/test-utils/seed-pod.js.map +1 -0
  262. package/package.json +23 -5
  263. package/templates/identity/account/create-pod.html.ejs +110 -0
  264. package/templates/main.html.ejs +10 -0
  265. package/dist/api/handlers/DevHandler.d.ts +0 -18
  266. package/dist/api/handlers/DevHandler.js +0 -276
  267. package/dist/api/handlers/DevHandler.js.map +0 -1
  268. package/dist/api/handlers/SignalHandler.d.ts +0 -13
  269. package/dist/api/handlers/SignalHandler.js +0 -122
  270. package/dist/api/handlers/SignalHandler.js.map +0 -1
  271. package/dist/gateway/Proxy.d.ts +0 -24
  272. package/dist/gateway/Proxy.js +0 -209
  273. package/dist/gateway/Proxy.js.map +0 -1
  274. package/dist/gateway/Supervisor.d.ts +0 -2
  275. package/dist/gateway/Supervisor.js +0 -7
  276. package/dist/gateway/Supervisor.js.map +0 -1
  277. package/dist/gateway/port-finder.d.ts +0 -4
  278. package/dist/gateway/port-finder.js +0 -15
  279. package/dist/gateway/port-finder.js.map +0 -1
  280. package/dist/gateway/types.d.ts +0 -1
  281. package/dist/gateway/types.js +0 -3
  282. package/dist/gateway/types.js.map +0 -1
  283. package/dist/http/SignalInterceptHttpHandler.d.ts +0 -24
  284. package/dist/http/SignalInterceptHttpHandler.js +0 -47
  285. package/dist/http/SignalInterceptHttpHandler.js.map +0 -1
  286. package/dist/http/SignalInterceptHttpHandler.jsonld +0 -103
  287. package/dist/http/admin/EdgeNodeSignalHttpHandler.d.ts +0 -71
  288. package/dist/http/admin/EdgeNodeSignalHttpHandler.js +0 -674
  289. package/dist/http/admin/EdgeNodeSignalHttpHandler.js.map +0 -1
  290. package/dist/http/admin/EdgeNodeSignalHttpHandler.jsonld +0 -406
  291. package/dist/http/cluster/PodMigrationHttpHandler.jsonld +0 -169
  292. package/dist/quota/DefaultQuotaService.d.ts +0 -16
  293. package/dist/quota/DefaultQuotaService.js +0 -37
  294. package/dist/quota/DefaultQuotaService.js.map +0 -1
  295. package/dist/quota/DefaultQuotaService.jsonld +0 -85
  296. package/dist/service/EdgeNodeHeartbeatService.js.map +0 -1
  297. package/dist/service/PodMigrationService.jsonld +0 -76
  298. package/dist/storage/MigratableDataAccessor.d.ts +0 -63
  299. package/dist/storage/MigratableDataAccessor.js +0 -11
  300. package/dist/storage/MigratableDataAccessor.js.map +0 -1
  301. package/dist/storage/MigratableDataAccessor.jsonld +0 -60
  302. package/dist/storage/accessors/TieredMinioDataAccessor.d.ts +0 -150
  303. package/dist/storage/accessors/TieredMinioDataAccessor.js +0 -582
  304. package/dist/storage/accessors/TieredMinioDataAccessor.js.map +0 -1
  305. package/dist/storage/accessors/TieredMinioDataAccessor.jsonld +0 -333
  306. package/static/app/assets/index.css +0 -1
  307. package/static/app/assets/main.js +0 -11
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.startApiService = startApiService;
4
+ const awilix_1 = require("awilix");
5
+ const global_logger_factory_1 = require("global-logger-factory");
6
+ const ConfigurableLoggerFactory_1 = require("../logging/ConfigurableLoggerFactory");
7
+ const container_1 = require("./container");
8
+ const routes_1 = require("./container/routes");
9
+ const OpenAuthMiddleware_1 = require("./middleware/OpenAuthMiddleware");
10
+ function initApiLogger() {
11
+ const loggerFactory = new ConfigurableLoggerFactory_1.ConfigurableLoggerFactory(process.env.CSS_LOGGING_LEVEL || 'info', {
12
+ fileName: './logs/xpod-%DATE%.log',
13
+ showLocation: true,
14
+ });
15
+ (0, global_logger_factory_1.setGlobalLoggerFactory)(loggerFactory);
16
+ }
17
+ async function startBackgroundServices(container, logger) {
18
+ try {
19
+ const localNetworkManager = container.resolve('localNetworkManager', { allowUnregistered: true });
20
+ if (localNetworkManager) {
21
+ localNetworkManager.start();
22
+ }
23
+ }
24
+ catch (error) {
25
+ logger.error(`Failed to initialize LocalNetworkManager: ${error}`);
26
+ }
27
+ try {
28
+ const ddnsManager = container.resolve('ddnsManager', { allowUnregistered: true });
29
+ if (ddnsManager) {
30
+ await ddnsManager.start();
31
+ logger.info('DDNS Manager started');
32
+ }
33
+ }
34
+ catch (error) {
35
+ logger.error(`Failed to initialize DdnsManager: ${error}`);
36
+ }
37
+ try {
38
+ const localNetworkManager = container.resolve('localNetworkManager', { allowUnregistered: true });
39
+ const localTunnelProvider = container.resolve('localTunnelProvider', { allowUnregistered: true });
40
+ if (!localNetworkManager && localTunnelProvider) {
41
+ logger.info('Starting Cloudflare Tunnel (standalone mode)...');
42
+ await localTunnelProvider.start();
43
+ logger.info('Cloudflare Tunnel started');
44
+ }
45
+ }
46
+ catch (error) {
47
+ logger.error(`Failed to start Cloudflare Tunnel: ${error}`);
48
+ }
49
+ }
50
+ async function stopBackgroundServices(container) {
51
+ try {
52
+ const ddnsManager = container.resolve('ddnsManager', { allowUnregistered: true });
53
+ ddnsManager?.stop();
54
+ }
55
+ catch {
56
+ // ignore shutdown errors
57
+ }
58
+ try {
59
+ const localNetworkManager = container.resolve('localNetworkManager', { allowUnregistered: true });
60
+ await localNetworkManager?.stop();
61
+ }
62
+ catch {
63
+ // ignore shutdown errors
64
+ }
65
+ try {
66
+ const localTunnelProvider = container.resolve('localTunnelProvider', { allowUnregistered: true });
67
+ await localTunnelProvider?.stop();
68
+ }
69
+ catch {
70
+ // ignore shutdown errors
71
+ }
72
+ }
73
+ async function startApiService(options = {}) {
74
+ if (options.initializeLogger !== false) {
75
+ initApiLogger();
76
+ }
77
+ const config = options.config ?? (0, container_1.loadConfigFromEnv)();
78
+ const logger = (0, global_logger_factory_1.getLoggerFor)('ApiRuntime');
79
+ if (!config.databaseUrl) {
80
+ throw new Error('CSS_IDENTITY_DB_URL or DATABASE_URL environment variable is required');
81
+ }
82
+ logger.info(`Starting API Service (edition: ${config.edition})...`);
83
+ const container = (0, container_1.createApiContainer)(config);
84
+ if (options.open) {
85
+ container.register({
86
+ authMiddleware: (0, awilix_1.asValue)(new OpenAuthMiddleware_1.OpenAuthMiddleware({ context: options.authContext })),
87
+ });
88
+ }
89
+ (0, routes_1.registerRoutes)(container);
90
+ await startBackgroundServices(container, logger);
91
+ const server = container.resolve('apiServer');
92
+ await server.start();
93
+ logger.info(`API Service active on ${config.socketPath ? `unix://${config.socketPath}` : `${config.host}:${config.port}`}`);
94
+ return {
95
+ config,
96
+ container,
97
+ stop: async () => {
98
+ logger.info('Stopping API Service...');
99
+ await stopBackgroundServices(container);
100
+ await server.stop();
101
+ },
102
+ };
103
+ }
104
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/api/runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import { asValue, type AwilixContainer } from 'awilix';\nimport { setGlobalLoggerFactory, getLoggerFor } from 'global-logger-factory';\nimport { ConfigurableLoggerFactory } from '../logging/ConfigurableLoggerFactory';\nimport { createApiContainer, loadConfigFromEnv, type ApiContainerConfig, type ApiContainerCradle } from './container';\nimport { registerRoutes } from './container/routes';\nimport type { AuthContext } from './auth/AuthContext';\nimport { OpenAuthMiddleware } from './middleware/OpenAuthMiddleware';\n\nexport interface StartApiServiceOptions {\n config?: ApiContainerConfig;\n open?: boolean;\n authContext?: AuthContext;\n initializeLogger?: boolean;\n}\n\nexport interface ApiServiceHandle {\n config: ApiContainerConfig;\n container: AwilixContainer<ApiContainerCradle>;\n stop: () => Promise<void>;\n}\n\nfunction initApiLogger(): void {\n const loggerFactory = new ConfigurableLoggerFactory(process.env.CSS_LOGGING_LEVEL || 'info', {\n fileName: './logs/xpod-%DATE%.log',\n showLocation: true,\n });\n setGlobalLoggerFactory(loggerFactory);\n}\n\nasync function startBackgroundServices(\n container: AwilixContainer<ApiContainerCradle>,\n logger: ReturnType<typeof getLoggerFor>,\n): Promise<void> {\n try {\n const localNetworkManager = container.resolve('localNetworkManager', { allowUnregistered: true }) as any;\n if (localNetworkManager) {\n localNetworkManager.start();\n }\n } catch (error) {\n logger.error(`Failed to initialize LocalNetworkManager: ${error}`);\n }\n\n try {\n const ddnsManager = container.resolve('ddnsManager', { allowUnregistered: true }) as any;\n if (ddnsManager) {\n await ddnsManager.start();\n logger.info('DDNS Manager started');\n }\n } catch (error) {\n logger.error(`Failed to initialize DdnsManager: ${error}`);\n }\n\n try {\n const localNetworkManager = container.resolve('localNetworkManager', { allowUnregistered: true });\n const localTunnelProvider = container.resolve('localTunnelProvider', { allowUnregistered: true }) as any;\n\n if (!localNetworkManager && localTunnelProvider) {\n logger.info('Starting Cloudflare Tunnel (standalone mode)...');\n await localTunnelProvider.start();\n logger.info('Cloudflare Tunnel started');\n }\n } catch (error) {\n logger.error(`Failed to start Cloudflare Tunnel: ${error}`);\n }\n}\n\nasync function stopBackgroundServices(container: AwilixContainer<ApiContainerCradle>): Promise<void> {\n try {\n const ddnsManager = container.resolve('ddnsManager', { allowUnregistered: true }) as any;\n ddnsManager?.stop();\n } catch {\n // ignore shutdown errors\n }\n\n try {\n const localNetworkManager = container.resolve('localNetworkManager', { allowUnregistered: true });\n await localNetworkManager?.stop();\n } catch {\n // ignore shutdown errors\n }\n\n try {\n const localTunnelProvider = container.resolve('localTunnelProvider', { allowUnregistered: true }) as any;\n await localTunnelProvider?.stop();\n } catch {\n // ignore shutdown errors\n }\n}\n\nexport async function startApiService(options: StartApiServiceOptions = {}): Promise<ApiServiceHandle> {\n if (options.initializeLogger !== false) {\n initApiLogger();\n }\n\n const config = options.config ?? loadConfigFromEnv();\n const logger = getLoggerFor('ApiRuntime');\n\n if (!config.databaseUrl) {\n throw new Error('CSS_IDENTITY_DB_URL or DATABASE_URL environment variable is required');\n }\n\n logger.info(`Starting API Service (edition: ${config.edition})...`);\n\n const container = createApiContainer(config);\n\n if (options.open) {\n container.register({\n authMiddleware: asValue(new OpenAuthMiddleware({ context: options.authContext })),\n });\n }\n\n registerRoutes(container);\n await startBackgroundServices(container, logger);\n\n const server = container.resolve('apiServer');\n await server.start();\n logger.info(`API Service active on ${config.socketPath ? `unix://${config.socketPath}` : `${config.host}:${config.port}`}`);\n\n return {\n config,\n container,\n stop: async(): Promise<void> => {\n logger.info('Stopping API Service...');\n await stopBackgroundServices(container);\n await server.stop();\n },\n };\n}\n"]}
@@ -1,10 +1,18 @@
1
1
  import type { ChatCompletionRequest, ChatCompletionResponse } from '../handlers/ChatHandler';
2
2
  import type { PodChatKitStore } from '../chatkit/pod-store';
3
3
  import { type AuthContext } from '../auth/AuthContext';
4
+ import type { UsageRepository } from '../../storage/quota/UsageRepository';
5
+ import type { QuotaService } from '../../quota/QuotaService';
4
6
  export declare class VercelChatService {
5
7
  private readonly store;
6
8
  private readonly logger;
9
+ private usageRepo?;
10
+ private quotaService?;
7
11
  constructor(store: PodChatKitStore);
12
+ /**
13
+ * Set optional usage tracking dependencies (injected after construction)
14
+ */
15
+ setUsageTracking(usageRepo: UsageRepository, quotaService: QuotaService): void;
8
16
  /**
9
17
  * Create a StoreContext from AuthContext for Pod operations
10
18
  */
@@ -17,16 +25,9 @@ export declare class VercelChatService {
17
25
  messages(body: any, auth: AuthContext): Promise<any>;
18
26
  private responsesViaCompletions;
19
27
  private messagesViaCompletions;
20
- private responsesWithDefaultAgent;
21
- private messagesWithDefaultAgent;
22
28
  private extractPromptFromResponsesBody;
23
29
  private extractPromptFromMessagesBody;
24
30
  listModels(_auth?: AuthContext): Promise<any[]>;
25
- private completeWithDefaultAgent;
26
- private streamWithDefaultAgent;
27
- private buildDefaultAgentContext;
28
- private getPodBaseUrlFromWebId;
29
- private getSolidToken;
30
31
  private mapFinishReason;
31
32
  /**
32
33
  * Handle API errors and update credential status accordingly
@@ -36,4 +37,12 @@ export declare class VercelChatService {
36
37
  * Parse error to extract status code and retry-after header
37
38
  */
38
39
  private parseApiError;
40
+ /**
41
+ * Check if account has remaining token quota
42
+ */
43
+ private checkTokenQuota;
44
+ /**
45
+ * Record token usage (fire-and-forget)
46
+ */
47
+ private recordTokenUsage;
39
48
  }
@@ -6,7 +6,6 @@ const ai_1 = require("ai");
6
6
  const global_logger_factory_1 = require("global-logger-factory");
7
7
  const undici_1 = require("undici");
8
8
  const AuthContext_1 = require("../auth/AuthContext");
9
- const default_agent_1 = require("../chatkit/default-agent");
10
9
  const types_1 = require("../../credential/schema/types");
11
10
  const provider_registry_1 = require("./provider-registry");
12
11
  // Create a proxy-aware fetch function
@@ -20,6 +19,13 @@ class VercelChatService {
20
19
  this.logger = (0, global_logger_factory_1.getLoggerFor)(this);
21
20
  this.logger.info('Initializing VercelChatService with Pod-based config support');
22
21
  }
22
+ /**
23
+ * Set optional usage tracking dependencies (injected after construction)
24
+ */
25
+ setUsageTracking(usageRepo, quotaService) {
26
+ this.usageRepo = usageRepo;
27
+ this.quotaService = quotaService;
28
+ }
23
29
  /**
24
30
  * Create a StoreContext from AuthContext for Pod operations
25
31
  */
@@ -39,26 +45,26 @@ class VercelChatService {
39
45
  this.logger.warn(`Failed to get Pod config, falling back to defaults: ${error}`);
40
46
  config = undefined;
41
47
  }
42
- // Priority: Pod config > DEFAULT_API_KEY env > Default Agent fallback
48
+ // Priority: Pod config > Platform Provider
43
49
  if (config?.apiKey) {
44
50
  const baseURL = config.baseUrl || (0, provider_registry_1.getDefaultBaseUrl)();
45
51
  const proxy = config.proxyUrl;
46
52
  this.logger.info(`Provider config: baseURL=${baseURL}, proxy=${proxy || 'none'} (source=pod)`);
47
53
  return { baseURL, apiKey: config.apiKey, proxy, credentialId: config.credentialId };
48
54
  }
49
- if (process.env.DEFAULT_API_KEY) {
50
- const provider = process.env.DEFAULT_PROVIDER || 'openrouter';
51
- const baseURL = process.env.DEFAULT_API_BASE || (0, provider_registry_1.getDefaultBaseUrl)(provider);
52
- this.logger.info(`Provider config: baseURL=${baseURL}, proxy=none (source=default-env)`);
53
- return { baseURL, apiKey: process.env.DEFAULT_API_KEY, proxy: undefined, credentialId: undefined };
55
+ // 平台 Provider
56
+ const platformBase = process.env.DEFAULT_API_BASE;
57
+ if (platformBase) {
58
+ this.logger.info(`Provider config: baseURL=${platformBase}, proxy=none (source=platform)`);
59
+ return { baseURL: platformBase, apiKey: process.env.DEFAULT_API_KEY || '', proxy: undefined, credentialId: undefined };
54
60
  }
55
- this.logger.warn('No AI provider config found in Pod or DEFAULT_API_KEY');
61
+ this.logger.warn('No AI provider config found in Pod or DEFAULT_API_BASE');
56
62
  return null;
57
63
  }
58
64
  async getProvider(context) {
59
65
  const providerConfig = await this.getProviderConfig(context);
60
66
  if (!providerConfig) {
61
- const err = new Error('No AI provider configured. Please configure Pod AI provider or DEFAULT_API_KEY');
67
+ const err = new Error('No AI provider configured. Please configure Pod AI provider or set DEFAULT_API_BASE.');
62
68
  err.code = 'model_not_configured';
63
69
  throw err;
64
70
  }
@@ -75,7 +81,14 @@ class VercelChatService {
75
81
  const context = this.createStoreContext(auth);
76
82
  const config = await this.getProviderConfig(context);
77
83
  if (!config) {
78
- return this.completeWithDefaultAgent(messages, auth, model);
84
+ const err = new Error('No AI provider configured. Please configure Pod AI provider or set DEFAULT_API_BASE.');
85
+ err.code = 'model_not_configured';
86
+ throw err;
87
+ }
88
+ // Token quota check
89
+ const accountId = (0, AuthContext_1.getAccountId)(auth);
90
+ if (accountId) {
91
+ await this.checkTokenQuota(accountId);
79
92
  }
80
93
  try {
81
94
  const provider = await this.getProvider(context);
@@ -95,6 +108,11 @@ class VercelChatService {
95
108
  this.logger.debug(`Failed to record credential success: ${err}`);
96
109
  });
97
110
  }
111
+ // Record token usage
112
+ const totalTokens = result.usage?.totalTokens ?? 0;
113
+ if (accountId && totalTokens > 0) {
114
+ this.recordTokenUsage(accountId, String(context.userId), totalTokens);
115
+ }
98
116
  return {
99
117
  id: `chatcmpl-${Date.now()}`,
100
118
  object: 'chat.completion',
@@ -131,7 +149,9 @@ class VercelChatService {
131
149
  const context = this.createStoreContext(auth);
132
150
  const config = await this.getProviderConfig(context);
133
151
  if (!config) {
134
- return this.streamWithDefaultAgent(messages, auth, model);
152
+ const err = new Error('No AI provider configured. Please configure Pod AI provider or set DEFAULT_API_BASE.');
153
+ err.code = 'model_not_configured';
154
+ throw err;
135
155
  }
136
156
  const provider = await this.getProvider(context);
137
157
  const coreMessages = messages.map((m) => ({
@@ -151,7 +171,9 @@ class VercelChatService {
151
171
  const accountId = (0, AuthContext_1.getAccountId)(auth);
152
172
  const providerConfig = await this.getProviderConfig(context);
153
173
  if (!providerConfig) {
154
- return this.responsesWithDefaultAgent(body, auth);
174
+ const err = new Error('No AI provider configured. Please configure Pod AI provider or set DEFAULT_API_BASE.');
175
+ err.code = 'model_not_configured';
176
+ throw err;
155
177
  }
156
178
  const { baseURL } = providerConfig;
157
179
  // Only OpenAI natively supports /v1/responses; all others go through Chat Completions
@@ -202,7 +224,9 @@ class VercelChatService {
202
224
  const accountId = (0, AuthContext_1.getAccountId)(auth);
203
225
  const providerConfig = await this.getProviderConfig(context);
204
226
  if (!providerConfig) {
205
- return this.messagesWithDefaultAgent(body, auth);
227
+ const err = new Error('No AI provider configured. Please configure Pod AI provider or set DEFAULT_API_BASE.');
228
+ err.code = 'model_not_configured';
229
+ throw err;
206
230
  }
207
231
  const { baseURL } = providerConfig;
208
232
  // Only Anthropic natively supports /v1/messages; all others go through Chat Completions
@@ -336,57 +360,6 @@ class VercelChatService {
336
360
  },
337
361
  };
338
362
  }
339
- async responsesWithDefaultAgent(body, auth) {
340
- const prompt = this.extractPromptFromResponsesBody(body);
341
- const result = await (0, default_agent_1.runDefaultAgent)(prompt, this.buildDefaultAgentContext(auth));
342
- if (!result.success) {
343
- const err = new Error(result.error || 'Default Agent is not available');
344
- err.code = 'model_not_configured';
345
- throw err;
346
- }
347
- const outputText = result.content;
348
- const now = Math.floor(Date.now() / 1000);
349
- return {
350
- id: `resp_${Date.now()}`,
351
- object: 'response',
352
- created: now,
353
- status: 'completed',
354
- model: body?.model || process.env.DEFAULT_MODEL || 'stepfun/step-3.5-flash:free',
355
- output: [{
356
- type: 'message',
357
- role: 'assistant',
358
- content: [{ type: 'output_text', text: outputText }],
359
- }],
360
- usage: {
361
- input_tokens: prompt.length,
362
- output_tokens: outputText.length,
363
- total_tokens: prompt.length + outputText.length,
364
- },
365
- };
366
- }
367
- async messagesWithDefaultAgent(body, auth) {
368
- const prompt = this.extractPromptFromMessagesBody(body);
369
- const result = await (0, default_agent_1.runDefaultAgent)(prompt, this.buildDefaultAgentContext(auth));
370
- if (!result.success) {
371
- const err = new Error(result.error || 'Default Agent is not available');
372
- err.code = 'model_not_configured';
373
- throw err;
374
- }
375
- const text = result.content;
376
- return {
377
- id: `msg_${Date.now()}`,
378
- type: 'message',
379
- role: 'assistant',
380
- model: body?.model || process.env.DEFAULT_MODEL || 'stepfun/step-3.5-flash:free',
381
- content: [{ type: 'text', text }],
382
- stop_reason: 'end_turn',
383
- stop_sequence: null,
384
- usage: {
385
- input_tokens: prompt.length,
386
- output_tokens: text.length,
387
- },
388
- };
389
- }
390
363
  extractPromptFromResponsesBody(body) {
391
364
  if (!body || typeof body !== 'object') {
392
365
  return '';
@@ -444,126 +417,34 @@ class VercelChatService {
444
417
  return '';
445
418
  }
446
419
  async listModels(_auth) {
447
- // TODO: Get models from Pod when store.listModels is implemented
448
- // Fallback to default models
449
- return [
450
- {
451
- id: 'llama3',
452
- object: 'model',
453
- created: Math.floor(Date.now() / 1000),
454
- owned_by: 'ollama',
455
- },
456
- {
457
- id: 'gpt-4o',
458
- object: 'model',
459
- created: Math.floor(Date.now() / 1000),
460
- owned_by: 'openai',
461
- },
462
- ];
463
- }
464
- async completeWithDefaultAgent(messages, auth, requestedModel) {
465
- const agentContext = this.buildDefaultAgentContext(auth);
466
- const prompt = messages.filter((m) => m.role === 'user').pop()?.content || '';
467
- const result = await (0, default_agent_1.runDefaultAgent)(prompt, agentContext);
468
- if (!result.success) {
469
- const err = new Error(result.error || 'Default Agent is not available');
470
- err.code = 'model_not_configured';
471
- throw err;
472
- }
473
- const completionTokens = result.content.length;
474
- return {
475
- id: `chatcmpl-${Date.now()}`,
476
- object: 'chat.completion',
477
- created: Math.floor(Date.now() / 1000),
478
- model: requestedModel,
479
- choices: [{
480
- index: 0,
481
- message: { role: 'assistant', content: result.content },
482
- finish_reason: 'stop',
483
- }],
484
- usage: {
485
- prompt_tokens: prompt.length,
486
- completion_tokens: completionTokens,
487
- total_tokens: prompt.length + completionTokens,
488
- },
489
- };
490
- }
491
- async streamWithDefaultAgent(messages, auth, _requestedModel) {
492
- const agentContext = this.buildDefaultAgentContext(auth);
493
- const prompt = messages.filter((m) => m.role === 'user').pop()?.content || '';
494
- const encoder = new TextEncoder();
495
- const stream = new ReadableStream({
496
- start: async (controller) => {
497
- try {
498
- for await (const chunk of (0, default_agent_1.streamDefaultAgent)(prompt, agentContext)) {
499
- controller.enqueue(encoder.encode(chunk));
420
+ const models = [];
421
+ // 平台 Provider 模型(从 DEFAULT_API_BASE 获取)
422
+ const platformBase = process.env.DEFAULT_API_BASE;
423
+ const platformKey = process.env.DEFAULT_API_KEY;
424
+ if (platformBase) {
425
+ try {
426
+ const url = platformBase.replace(/\/$/, '') + '/models';
427
+ const headers = { 'Content-Type': 'application/json' };
428
+ if (platformKey) {
429
+ headers['Authorization'] = `Bearer ${platformKey}`;
430
+ }
431
+ const resp = await fetch(url, { headers });
432
+ if (resp.ok) {
433
+ const data = await resp.json();
434
+ if (data.data) {
435
+ models.push(...data.data);
500
436
  }
501
- controller.close();
502
437
  }
503
- catch (error) {
504
- controller.error(error);
438
+ else {
439
+ this.logger.warn(`Failed to fetch platform models: ${resp.status}`);
505
440
  }
506
- },
507
- });
508
- return {
509
- toTextStreamResponse: () => new Response(stream, {
510
- status: 200,
511
- headers: {
512
- 'Content-Type': 'text/plain; charset=utf-8',
513
- 'X-Vercel-AI-Data-Stream': 'v1',
514
- },
515
- }),
516
- };
517
- }
518
- buildDefaultAgentContext(auth) {
519
- if (!(0, default_agent_1.isDefaultAgentAvailable)()) {
520
- const err = new Error('No AI provider configured. Please configure Pod AI provider or DEFAULT_API_KEY');
521
- err.code = 'model_not_configured';
522
- throw err;
523
- }
524
- const webId = (0, AuthContext_1.getWebId)(auth);
525
- if (!webId) {
526
- const err = new Error('No WebID in auth context');
527
- err.code = 'model_not_configured';
528
- throw err;
529
- }
530
- const solidToken = this.getSolidToken(auth);
531
- if (!solidToken) {
532
- const err = new Error('No Solid token available for Default Agent');
533
- err.code = 'model_not_configured';
534
- throw err;
535
- }
536
- return {
537
- solidToken,
538
- podBaseUrl: this.getPodBaseUrlFromWebId(webId),
539
- webId,
540
- };
541
- }
542
- getPodBaseUrlFromWebId(webId) {
543
- const url = new URL(webId);
544
- if (url.pathname.endsWith('/profile/card')) {
545
- const podPath = url.pathname.replace('/profile/card', '');
546
- return `${url.protocol}//${url.host}${podPath}/`;
547
- }
548
- return `${url.protocol}//${url.host}/`;
549
- }
550
- getSolidToken(auth) {
551
- const candidate = auth;
552
- if (typeof candidate.token === 'string') {
553
- return candidate.token;
554
- }
555
- if (typeof candidate.accessToken === 'string') {
556
- return candidate.accessToken;
557
- }
558
- if (candidate.credentials && typeof candidate.credentials === 'object') {
559
- if (typeof candidate.credentials.accessToken === 'string') {
560
- return candidate.credentials.accessToken;
561
441
  }
562
- if (typeof candidate.credentials.token === 'string') {
563
- return candidate.credentials.token;
442
+ catch (error) {
443
+ this.logger.warn(`Failed to fetch platform models: ${error}`);
564
444
  }
565
445
  }
566
- return undefined;
446
+ // TODO: 合并用户 Pod Providers 的模型
447
+ return models;
567
448
  }
568
449
  mapFinishReason(reason) {
569
450
  return reason;
@@ -623,6 +504,45 @@ class VercelChatService {
623
504
  }
624
505
  return { statusCode: 0 };
625
506
  }
507
+ /**
508
+ * Check if account has remaining token quota
509
+ */
510
+ async checkTokenQuota(accountId) {
511
+ if (!this.quotaService || !this.usageRepo) {
512
+ return; // No quota enforcement if not configured
513
+ }
514
+ try {
515
+ const quota = await this.quotaService.getAccountQuota(accountId);
516
+ if (!quota.tokenLimitMonthly) {
517
+ return; // No limit set
518
+ }
519
+ const usage = await this.usageRepo.getAccountUsage(accountId);
520
+ const tokensUsed = usage?.tokensUsed ?? 0;
521
+ if (tokensUsed >= quota.tokenLimitMonthly) {
522
+ const err = new Error('Token quota exceeded for this month');
523
+ err.code = 'quota_exceeded';
524
+ throw err;
525
+ }
526
+ }
527
+ catch (error) {
528
+ if (error.code === 'quota_exceeded') {
529
+ throw error;
530
+ }
531
+ // Log but don't block on quota check errors
532
+ this.logger.warn(`Token quota check failed: ${error}`);
533
+ }
534
+ }
535
+ /**
536
+ * Record token usage (fire-and-forget)
537
+ */
538
+ recordTokenUsage(accountId, podId, tokens) {
539
+ if (!this.usageRepo) {
540
+ return;
541
+ }
542
+ this.usageRepo.incrementTokenUsage(accountId, podId, tokens).catch((err) => {
543
+ this.logger.warn(`Failed to record token usage: ${err}`);
544
+ });
545
+ }
626
546
  }
627
547
  exports.VercelChatService = VercelChatService;
628
548
  //# sourceMappingURL=VercelChatService.js.map