@undefineds.co/xpod 0.1.7 → 0.2.0

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 (350) hide show
  1. package/README.md +164 -3
  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/agents/AgentExecutorFactory.js +1 -1
  11. package/dist/agents/AgentExecutorFactory.js.map +1 -1
  12. package/dist/agents/AgentManager.js +1 -1
  13. package/dist/agents/AgentManager.js.map +1 -1
  14. package/dist/agents/config/agent-meta-schema.d.ts +7 -7
  15. package/dist/agents/config/agent-meta-schema.js +1 -1
  16. package/dist/agents/config/agent-meta-schema.js.map +1 -1
  17. package/dist/agents/config/resolve.js +1 -1
  18. package/dist/agents/config/resolve.js.map +1 -1
  19. package/dist/agents/schema/agent-config.d.ts +18 -18
  20. package/dist/agents/schema/agent-config.js +1 -1
  21. package/dist/agents/schema/agent-config.js.map +1 -1
  22. package/dist/agents/schema/tables.d.ts +8 -8
  23. package/dist/agents/schema/tables.js +1 -1
  24. package/dist/agents/schema/tables.js.map +1 -1
  25. package/dist/ai/schema/config.d.ts +7 -7
  26. package/dist/ai/schema/config.js +1 -1
  27. package/dist/ai/schema/config.js.map +1 -1
  28. package/dist/ai/schema/model.d.ts +13 -13
  29. package/dist/ai/schema/model.js +1 -1
  30. package/dist/ai/schema/model.js.map +1 -1
  31. package/dist/ai/schema/provider.d.ts +7 -7
  32. package/dist/ai/schema/provider.js +1 -1
  33. package/dist/ai/schema/provider.js.map +1 -1
  34. package/dist/ai/schema/vector-store.d.ts +17 -17
  35. package/dist/ai/schema/vector-store.js +1 -1
  36. package/dist/ai/schema/vector-store.js.map +1 -1
  37. package/dist/ai/service/CredentialReaderImpl.js +1 -1
  38. package/dist/ai/service/CredentialReaderImpl.js.map +1 -1
  39. package/dist/ai/service/DefaultAiConfigService.js.map +1 -1
  40. package/dist/api/ApiServer.d.ts +3 -1
  41. package/dist/api/ApiServer.js +14 -1
  42. package/dist/api/ApiServer.js.map +1 -1
  43. package/dist/api/auth/AuthContext.d.ts +12 -1
  44. package/dist/api/auth/AuthContext.js +18 -1
  45. package/dist/api/auth/AuthContext.js.map +1 -1
  46. package/dist/api/auth/ClientCredentialsAuthenticator.d.ts +0 -1
  47. package/dist/api/auth/ClientCredentialsAuthenticator.js.map +1 -1
  48. package/dist/api/auth/ServiceTokenAuthenticator.d.ts +18 -0
  49. package/dist/api/auth/ServiceTokenAuthenticator.js +50 -0
  50. package/dist/api/auth/ServiceTokenAuthenticator.js.map +1 -0
  51. package/dist/api/auth/index.d.ts +1 -0
  52. package/dist/api/auth/index.js +1 -0
  53. package/dist/api/auth/index.js.map +1 -1
  54. package/dist/api/chatkit/ai-provider.d.ts +0 -10
  55. package/dist/api/chatkit/ai-provider.js +11 -120
  56. package/dist/api/chatkit/ai-provider.js.map +1 -1
  57. package/dist/api/chatkit/default-agent.js +11 -8
  58. package/dist/api/chatkit/default-agent.js.map +1 -1
  59. package/dist/api/chatkit/pod-store.d.ts +6 -0
  60. package/dist/api/chatkit/pod-store.js +103 -36
  61. package/dist/api/chatkit/pod-store.js.map +1 -1
  62. package/dist/api/chatkit/schema.d.ts +32 -26
  63. package/dist/api/chatkit/schema.js +16 -8
  64. package/dist/api/chatkit/schema.js.map +1 -1
  65. package/dist/api/container/business-token.d.ts +9 -0
  66. package/dist/api/container/business-token.js +32 -0
  67. package/dist/api/container/business-token.js.map +1 -0
  68. package/dist/api/container/cloud.js +36 -12
  69. package/dist/api/container/cloud.js.map +1 -1
  70. package/dist/api/container/common.js +13 -5
  71. package/dist/api/container/common.js.map +1 -1
  72. package/dist/api/container/index.js +94 -14
  73. package/dist/api/container/index.js.map +1 -1
  74. package/dist/api/container/local.js +2 -1
  75. package/dist/api/container/local.js.map +1 -1
  76. package/dist/api/container/routes.js +81 -9
  77. package/dist/api/container/routes.js.map +1 -1
  78. package/dist/api/container/types.d.ts +8 -6
  79. package/dist/api/container/types.js.map +1 -1
  80. package/dist/api/handlers/AdminHandler.js +9 -9
  81. package/dist/api/handlers/AdminHandler.js.map +1 -1
  82. package/dist/api/handlers/ApiKeyHandler.js +0 -6
  83. package/dist/api/handlers/ApiKeyHandler.js.map +1 -1
  84. package/dist/api/handlers/EdgeNodeSignalHandler.d.ts +17 -0
  85. package/dist/api/handlers/EdgeNodeSignalHandler.js +171 -0
  86. package/dist/api/handlers/EdgeNodeSignalHandler.js.map +1 -0
  87. package/dist/api/handlers/PodManagementHandler.d.ts +5 -4
  88. package/dist/api/handlers/PodManagementHandler.js +11 -10
  89. package/dist/api/handlers/PodManagementHandler.js.map +1 -1
  90. package/dist/api/handlers/ProvisionHandler.d.ts +42 -0
  91. package/dist/api/handlers/ProvisionHandler.js +161 -0
  92. package/dist/api/handlers/ProvisionHandler.js.map +1 -0
  93. package/dist/api/handlers/QuotaHandler.d.ts +7 -7
  94. package/dist/api/handlers/QuotaHandler.js +143 -73
  95. package/dist/api/handlers/QuotaHandler.js.map +1 -1
  96. package/dist/api/handlers/SubdomainClientHandler.js +2 -2
  97. package/dist/api/handlers/SubdomainClientHandler.js.map +1 -1
  98. package/dist/api/handlers/SubdomainHandler.js +13 -8
  99. package/dist/api/handlers/SubdomainHandler.js.map +1 -1
  100. package/dist/api/handlers/UsageHandler.d.ts +14 -0
  101. package/dist/api/handlers/UsageHandler.js +123 -0
  102. package/dist/api/handlers/UsageHandler.js.map +1 -0
  103. package/dist/api/handlers/index.d.ts +3 -1
  104. package/dist/api/handlers/index.js +3 -1
  105. package/dist/api/handlers/index.js.map +1 -1
  106. package/dist/api/main.js +18 -0
  107. package/dist/api/main.js.map +1 -1
  108. package/dist/api/middleware/OpenAuthMiddleware.d.ts +12 -0
  109. package/dist/api/middleware/OpenAuthMiddleware.js +27 -0
  110. package/dist/api/middleware/OpenAuthMiddleware.js.map +1 -0
  111. package/dist/api/runtime.d.ts +15 -0
  112. package/dist/api/runtime.js +125 -0
  113. package/dist/api/runtime.js.map +1 -0
  114. package/dist/api/service/VectorStoreService.js +1 -1
  115. package/dist/api/service/VectorStoreService.js.map +1 -1
  116. package/dist/api/service/VercelChatService.d.ts +16 -7
  117. package/dist/api/service/VercelChatService.js +98 -178
  118. package/dist/api/service/VercelChatService.js.map +1 -1
  119. package/dist/api/store/DrizzleClientCredentialsStore.d.ts +6 -11
  120. package/dist/api/store/DrizzleClientCredentialsStore.js +9 -39
  121. package/dist/api/store/DrizzleClientCredentialsStore.js.map +1 -1
  122. package/dist/authorization/AuthModeSelector.d.ts +10 -0
  123. package/dist/authorization/AuthModeSelector.js +27 -0
  124. package/dist/authorization/AuthModeSelector.js.map +1 -0
  125. package/dist/authorization/AuthModeSelector.jsonld +81 -0
  126. package/dist/cli/commands/account.d.ts +6 -0
  127. package/dist/cli/commands/account.js +119 -0
  128. package/dist/cli/commands/account.js.map +1 -0
  129. package/dist/cli/commands/auth.js +20 -29
  130. package/dist/cli/commands/auth.js.map +1 -1
  131. package/dist/cli/commands/backup.d.ts +15 -0
  132. package/dist/cli/commands/backup.js +286 -0
  133. package/dist/cli/commands/backup.js.map +1 -0
  134. package/dist/cli/commands/config.d.ts +34 -3
  135. package/dist/cli/commands/config.js +195 -258
  136. package/dist/cli/commands/config.js.map +1 -1
  137. package/dist/cli/commands/doctor.d.ts +6 -0
  138. package/dist/cli/commands/doctor.js +94 -0
  139. package/dist/cli/commands/doctor.js.map +1 -0
  140. package/dist/cli/commands/pod.d.ts +6 -0
  141. package/dist/cli/commands/pod.js +124 -0
  142. package/dist/cli/commands/pod.js.map +1 -0
  143. package/dist/cli/commands/start.js +28 -5
  144. package/dist/cli/commands/start.js.map +1 -1
  145. package/dist/cli/index.js +9 -0
  146. package/dist/cli/index.js.map +1 -1
  147. package/dist/cli/lib/credentials-store.d.ts +17 -0
  148. package/dist/cli/lib/credentials-store.js +73 -0
  149. package/dist/cli/lib/credentials-store.js.map +1 -0
  150. package/dist/cli/lib/css-account.d.ts +17 -0
  151. package/dist/cli/lib/css-account.js +56 -0
  152. package/dist/cli/lib/css-account.js.map +1 -1
  153. package/dist/cli/lib/pod-thread-store.d.ts +57 -0
  154. package/dist/cli/lib/pod-thread-store.js +310 -0
  155. package/dist/cli/lib/pod-thread-store.js.map +1 -0
  156. package/dist/cli/lib/solid-auth.d.ts +20 -0
  157. package/dist/cli/lib/solid-auth.js +70 -0
  158. package/dist/cli/lib/solid-auth.js.map +1 -0
  159. package/dist/components/components.jsonld +5 -8
  160. package/dist/components/context.jsonld +114 -244
  161. package/dist/credential/schema/tables.d.ts +14 -14
  162. package/dist/credential/schema/tables.js +1 -1
  163. package/dist/credential/schema/tables.js.map +1 -1
  164. package/dist/edge/EdgeNodeAgent.js +2 -2
  165. package/dist/edge/EdgeNodeAgent.js.map +1 -1
  166. package/dist/edge/EdgeNodeDnsCoordinator.d.ts +1 -7
  167. package/dist/edge/EdgeNodeDnsCoordinator.js +31 -41
  168. package/dist/edge/EdgeNodeDnsCoordinator.js.map +1 -1
  169. package/dist/edge/EdgeNodeDnsCoordinator.jsonld +1 -27
  170. package/dist/edge/EdgeNodeModeDetector.d.ts +1 -1
  171. package/dist/edge/EdgeNodeModeDetector.js +9 -11
  172. package/dist/edge/EdgeNodeModeDetector.js.map +1 -1
  173. package/dist/http/ClusterIngressRouter.js +3 -3
  174. package/dist/http/ClusterIngressRouter.js.map +1 -1
  175. package/dist/http/ClusterWebSocketConfigurator.js +2 -2
  176. package/dist/http/ClusterWebSocketConfigurator.js.map +1 -1
  177. package/dist/http/PodRoutingHttpHandler.js +2 -2
  178. package/dist/http/PodRoutingHttpHandler.js.map +1 -1
  179. package/dist/http/cluster/PodMigrationHttpHandler.d.ts +1 -1
  180. package/dist/http/cluster/PodMigrationHttpHandler.js +1 -1
  181. package/dist/http/cluster/PodMigrationHttpHandler.js.map +1 -1
  182. package/dist/identity/drizzle/EdgeNodeRepository.d.ts +37 -4
  183. package/dist/identity/drizzle/EdgeNodeRepository.js +120 -128
  184. package/dist/identity/drizzle/EdgeNodeRepository.js.map +1 -1
  185. package/dist/identity/drizzle/ServiceTokenRepository.d.ts +52 -0
  186. package/dist/identity/drizzle/ServiceTokenRepository.js +142 -0
  187. package/dist/identity/drizzle/ServiceTokenRepository.js.map +1 -0
  188. package/dist/identity/drizzle/db.d.ts +9 -0
  189. package/dist/identity/drizzle/db.js +235 -3
  190. package/dist/identity/drizzle/db.js.map +1 -1
  191. package/dist/identity/drizzle/schema.pg.d.ts +5 -0
  192. package/dist/identity/drizzle/schema.pg.js +49 -20
  193. package/dist/identity/drizzle/schema.pg.js.map +1 -1
  194. package/dist/identity/drizzle/schema.sqlite.d.ts +332 -57
  195. package/dist/identity/drizzle/schema.sqlite.js +48 -18
  196. package/dist/identity/drizzle/schema.sqlite.js.map +1 -1
  197. package/dist/identity/oidc/AutoDetectIdentityProviderHandler.js +6 -4
  198. package/dist/identity/oidc/AutoDetectIdentityProviderHandler.js.map +1 -1
  199. package/dist/index.d.ts +6 -9
  200. package/dist/index.js +12 -14
  201. package/dist/index.js.map +1 -1
  202. package/dist/main.js +25 -8
  203. package/dist/main.js.map +1 -1
  204. package/dist/provision/ProvisionCodeCodec.d.ts +39 -0
  205. package/dist/provision/ProvisionCodeCodec.js +65 -0
  206. package/dist/provision/ProvisionCodeCodec.js.map +1 -0
  207. package/dist/provision/ProvisionCodeCodec.jsonld +47 -0
  208. package/dist/provision/ProvisionPodCreator.d.ts +20 -0
  209. package/dist/provision/ProvisionPodCreator.js +84 -0
  210. package/dist/provision/ProvisionPodCreator.js.map +1 -0
  211. package/dist/provision/ProvisionPodCreator.jsonld +118 -0
  212. package/dist/quota/DrizzleQuotaService.d.ts +17 -3
  213. package/dist/quota/DrizzleQuotaService.js +108 -8
  214. package/dist/quota/DrizzleQuotaService.js.map +1 -1
  215. package/dist/quota/DrizzleQuotaService.jsonld +33 -22
  216. package/dist/quota/NoopQuotaService.d.ts +7 -1
  217. package/dist/quota/NoopQuotaService.js +12 -0
  218. package/dist/quota/NoopQuotaService.js.map +1 -1
  219. package/dist/quota/NoopQuotaService.jsonld +24 -0
  220. package/dist/quota/QuotaService.d.ts +17 -0
  221. package/dist/quota/QuotaService.js +5 -0
  222. package/dist/quota/QuotaService.js.map +1 -1
  223. package/dist/quota/QuotaService.jsonld +50 -0
  224. package/dist/runtime/Proxy.d.ts +22 -4
  225. package/dist/runtime/Proxy.js +154 -35
  226. package/dist/runtime/Proxy.js.map +1 -1
  227. package/dist/runtime/XpodRuntime.d.ts +49 -0
  228. package/dist/runtime/XpodRuntime.js +374 -0
  229. package/dist/runtime/XpodRuntime.js.map +1 -0
  230. package/dist/runtime/env-utils.d.ts +2 -0
  231. package/dist/runtime/env-utils.js +55 -0
  232. package/dist/runtime/env-utils.js.map +1 -0
  233. package/dist/runtime/index.d.ts +4 -0
  234. package/dist/runtime/index.js +8 -1
  235. package/dist/runtime/index.js.map +1 -1
  236. package/dist/runtime/socket-fetch.d.ts +1 -0
  237. package/dist/runtime/socket-fetch.js +72 -0
  238. package/dist/runtime/socket-fetch.js.map +1 -0
  239. package/dist/runtime/socket-http.d.ts +1 -0
  240. package/dist/runtime/socket-http.js +142 -0
  241. package/dist/runtime/socket-http.js.map +1 -0
  242. package/dist/runtime/socket-utils.d.ts +2 -0
  243. package/dist/runtime/socket-utils.js +34 -0
  244. package/dist/runtime/socket-utils.js.map +1 -0
  245. package/dist/service/{EdgeNodeHeartbeatService.d.ts → EdgeNodeSignalClient.d.ts} +3 -3
  246. package/dist/service/{EdgeNodeHeartbeatService.js → EdgeNodeSignalClient.js} +4 -4
  247. package/dist/service/EdgeNodeSignalClient.js.map +1 -0
  248. package/dist/service/PodMigrationService.d.ts +1 -2
  249. package/dist/service/PodMigrationService.js +1 -2
  250. package/dist/service/PodMigrationService.js.map +1 -1
  251. package/dist/storage/SparqlUpdateResourceStore.js +1 -1
  252. package/dist/storage/SparqlUpdateResourceStore.js.map +1 -1
  253. package/dist/storage/accessors/MinioDataAccessor.d.ts +6 -0
  254. package/dist/storage/accessors/MinioDataAccessor.js +10 -0
  255. package/dist/storage/accessors/MinioDataAccessor.js.map +1 -1
  256. package/dist/storage/accessors/MinioDataAccessor.jsonld +4 -0
  257. package/dist/storage/accessors/MixDataAccessor.d.ts +2 -1
  258. package/dist/storage/accessors/MixDataAccessor.js +12 -1
  259. package/dist/storage/accessors/MixDataAccessor.js.map +1 -1
  260. package/dist/storage/accessors/MixDataAccessor.jsonld +19 -0
  261. package/dist/storage/locking/UrlAwareRedisLocker.d.ts +18 -0
  262. package/dist/storage/locking/UrlAwareRedisLocker.js +60 -0
  263. package/dist/storage/locking/UrlAwareRedisLocker.js.map +1 -0
  264. package/dist/storage/locking/UrlAwareRedisLocker.jsonld +123 -0
  265. package/dist/storage/quota/UsageRepository.d.ts +41 -8
  266. package/dist/storage/quota/UsageRepository.js +252 -50
  267. package/dist/storage/quota/UsageRepository.js.map +1 -1
  268. package/dist/storage/sparql/ComunicaQuintEngine.d.ts +9 -0
  269. package/dist/storage/sparql/ComunicaQuintEngine.js +50 -9
  270. package/dist/storage/sparql/ComunicaQuintEngine.js.map +1 -1
  271. package/dist/storage/sparql/QueryOptimizer.js +13 -1
  272. package/dist/storage/sparql/QueryOptimizer.js.map +1 -1
  273. package/dist/storage/sparql/QuintQuerySource.d.ts +14 -0
  274. package/dist/storage/sparql/QuintQuerySource.js +152 -1
  275. package/dist/storage/sparql/QuintQuerySource.js.map +1 -1
  276. package/dist/storage/sparql/SubgraphQueryEngine.d.ts +1 -0
  277. package/dist/storage/sparql/SubgraphQueryEngine.js +6 -2
  278. package/dist/storage/sparql/SubgraphQueryEngine.js.map +1 -1
  279. package/dist/storage/sparql/SubgraphQueryEngine.jsonld +4 -0
  280. package/dist/subdomain/SubdomainClient.d.ts +3 -3
  281. package/dist/subdomain/SubdomainClient.js +1 -1
  282. package/dist/subdomain/SubdomainClient.js.map +1 -1
  283. package/dist/subdomain/SubdomainService.d.ts +15 -16
  284. package/dist/subdomain/SubdomainService.js +80 -54
  285. package/dist/subdomain/SubdomainService.js.map +1 -1
  286. package/dist/subdomain/SubdomainService.jsonld +22 -26
  287. package/dist/supervisor/Supervisor.d.ts +7 -2
  288. package/dist/supervisor/Supervisor.js +33 -1
  289. package/dist/supervisor/Supervisor.js.map +1 -1
  290. package/dist/task/DrizzleTaskQueue.d.ts +1 -1
  291. package/dist/task/DrizzleTaskQueue.js +1 -1
  292. package/dist/task/DrizzleTaskQueue.js.map +1 -1
  293. package/dist/task/schema.d.ts +10 -10
  294. package/dist/task/schema.js +1 -1
  295. package/dist/task/schema.js.map +1 -1
  296. package/dist/test-utils/index.d.ts +4 -0
  297. package/dist/test-utils/index.js +8 -0
  298. package/dist/test-utils/index.js.map +1 -0
  299. package/dist/test-utils/no-auth-xpod.d.ts +11 -0
  300. package/dist/test-utils/no-auth-xpod.js +25 -0
  301. package/dist/test-utils/no-auth-xpod.js.map +1 -0
  302. package/dist/test-utils/seed-pod.d.ts +5 -0
  303. package/dist/test-utils/seed-pod.js +61 -0
  304. package/dist/test-utils/seed-pod.js.map +1 -0
  305. package/package.json +38 -10
  306. package/templates/identity/account/create-pod.html.ejs +110 -0
  307. package/templates/main.html.ejs +10 -0
  308. package/dist/api/handlers/DevHandler.d.ts +0 -18
  309. package/dist/api/handlers/DevHandler.js +0 -276
  310. package/dist/api/handlers/DevHandler.js.map +0 -1
  311. package/dist/api/handlers/SignalHandler.d.ts +0 -13
  312. package/dist/api/handlers/SignalHandler.js +0 -122
  313. package/dist/api/handlers/SignalHandler.js.map +0 -1
  314. package/dist/gateway/Proxy.d.ts +0 -24
  315. package/dist/gateway/Proxy.js +0 -209
  316. package/dist/gateway/Proxy.js.map +0 -1
  317. package/dist/gateway/Supervisor.d.ts +0 -2
  318. package/dist/gateway/Supervisor.js +0 -7
  319. package/dist/gateway/Supervisor.js.map +0 -1
  320. package/dist/gateway/port-finder.d.ts +0 -4
  321. package/dist/gateway/port-finder.js +0 -15
  322. package/dist/gateway/port-finder.js.map +0 -1
  323. package/dist/gateway/types.d.ts +0 -1
  324. package/dist/gateway/types.js +0 -3
  325. package/dist/gateway/types.js.map +0 -1
  326. package/dist/http/SignalInterceptHttpHandler.d.ts +0 -24
  327. package/dist/http/SignalInterceptHttpHandler.js +0 -47
  328. package/dist/http/SignalInterceptHttpHandler.js.map +0 -1
  329. package/dist/http/SignalInterceptHttpHandler.jsonld +0 -103
  330. package/dist/http/admin/EdgeNodeSignalHttpHandler.d.ts +0 -71
  331. package/dist/http/admin/EdgeNodeSignalHttpHandler.js +0 -674
  332. package/dist/http/admin/EdgeNodeSignalHttpHandler.js.map +0 -1
  333. package/dist/http/admin/EdgeNodeSignalHttpHandler.jsonld +0 -406
  334. package/dist/http/cluster/PodMigrationHttpHandler.jsonld +0 -169
  335. package/dist/quota/DefaultQuotaService.d.ts +0 -16
  336. package/dist/quota/DefaultQuotaService.js +0 -37
  337. package/dist/quota/DefaultQuotaService.js.map +0 -1
  338. package/dist/quota/DefaultQuotaService.jsonld +0 -85
  339. package/dist/service/EdgeNodeHeartbeatService.js.map +0 -1
  340. package/dist/service/PodMigrationService.jsonld +0 -76
  341. package/dist/storage/MigratableDataAccessor.d.ts +0 -63
  342. package/dist/storage/MigratableDataAccessor.js +0 -11
  343. package/dist/storage/MigratableDataAccessor.js.map +0 -1
  344. package/dist/storage/MigratableDataAccessor.jsonld +0 -60
  345. package/dist/storage/accessors/TieredMinioDataAccessor.d.ts +0 -150
  346. package/dist/storage/accessors/TieredMinioDataAccessor.js +0 -582
  347. package/dist/storage/accessors/TieredMinioDataAccessor.js.map +0 -1
  348. package/dist/storage/accessors/TieredMinioDataAccessor.jsonld +0 -333
  349. package/static/app/assets/index.css +0 -1
  350. package/static/app/assets/main.js +0 -11
@@ -0,0 +1,18 @@
1
+ import type { IncomingMessage } from 'node:http';
2
+ import type { Authenticator, AuthResult } from './Authenticator';
3
+ import type { ServiceTokenRepository } from '../../identity/drizzle/ServiceTokenRepository';
4
+ export interface ServiceTokenAuthenticatorOptions {
5
+ repository: ServiceTokenRepository;
6
+ }
7
+ /**
8
+ * Authenticator for service tokens (Business, Local SP, Cloud, Compute).
9
+ *
10
+ * Format: Bearer svc-xxx
11
+ */
12
+ export declare class ServiceTokenAuthenticator implements Authenticator {
13
+ private readonly logger;
14
+ private readonly repo;
15
+ constructor(options: ServiceTokenAuthenticatorOptions);
16
+ canAuthenticate(request: IncomingMessage): boolean;
17
+ authenticate(request: IncomingMessage): Promise<AuthResult>;
18
+ }
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ServiceTokenAuthenticator = void 0;
4
+ const global_logger_factory_1 = require("global-logger-factory");
5
+ /**
6
+ * Authenticator for service tokens (Business, Local SP, Cloud, Compute).
7
+ *
8
+ * Format: Bearer svc-xxx
9
+ */
10
+ class ServiceTokenAuthenticator {
11
+ constructor(options) {
12
+ this.logger = (0, global_logger_factory_1.getLoggerFor)(this);
13
+ this.repo = options.repository;
14
+ }
15
+ canAuthenticate(request) {
16
+ const auth = request.headers.authorization;
17
+ if (!auth?.startsWith('Bearer ')) {
18
+ return false;
19
+ }
20
+ const token = auth.slice(7).trim();
21
+ // Service tokens start with 'svc-'
22
+ return token.startsWith('svc-');
23
+ }
24
+ async authenticate(request) {
25
+ const auth = request.headers.authorization;
26
+ const token = auth.slice(7).trim();
27
+ try {
28
+ const record = await this.repo.verifyToken(token);
29
+ if (!record) {
30
+ return { success: false, error: 'Invalid service token' };
31
+ }
32
+ this.logger.debug(`Authenticated service: ${record.serviceType}:${record.serviceId}`);
33
+ return {
34
+ success: true,
35
+ context: {
36
+ type: 'service',
37
+ serviceType: record.serviceType,
38
+ serviceId: record.serviceId,
39
+ scopes: record.scopes,
40
+ },
41
+ };
42
+ }
43
+ catch (error) {
44
+ this.logger.error(`Service token authentication failed: ${error}`);
45
+ return { success: false, error: 'Internal authentication error' };
46
+ }
47
+ }
48
+ }
49
+ exports.ServiceTokenAuthenticator = ServiceTokenAuthenticator;
50
+ //# sourceMappingURL=ServiceTokenAuthenticator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ServiceTokenAuthenticator.js","sourceRoot":"","sources":["../../../src/api/auth/ServiceTokenAuthenticator.ts"],"names":[],"mappings":";;;AACA,iEAAqD;AAQrD;;;;GAIG;AACH,MAAa,yBAAyB;IAIpC,YAAmB,OAAyC;QAH3C,WAAM,GAAG,IAAA,oCAAY,EAAC,IAAI,CAAC,CAAC;QAI3C,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC;IACjC,CAAC;IAEM,eAAe,CAAC,OAAwB;QAC7C,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC;QAC3C,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACjC,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACnC,mCAAmC;QACnC,OAAO,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAClC,CAAC;IAEM,KAAK,CAAC,YAAY,CAAC,OAAwB;QAChD,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,aAAc,CAAC;QAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAEnC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YAClD,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAC;YAC5D,CAAC;YAED,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,0BAA0B,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;YAEtF,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE;oBACP,IAAI,EAAE,SAAS;oBACf,WAAW,EAAE,MAAM,CAAC,WAAW;oBAC/B,SAAS,EAAE,MAAM,CAAC,SAAS;oBAC3B,MAAM,EAAE,MAAM,CAAC,MAAM;iBACtB;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,wCAAwC,KAAK,EAAE,CAAC,CAAC;YACnE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,+BAA+B,EAAE,CAAC;QACpE,CAAC;IACH,CAAC;CACF;AA5CD,8DA4CC","sourcesContent":["import type { IncomingMessage } from 'node:http';\nimport { getLoggerFor } from 'global-logger-factory';\nimport type { Authenticator, AuthResult } from './Authenticator';\nimport type { ServiceTokenRepository } from '../../identity/drizzle/ServiceTokenRepository';\n\nexport interface ServiceTokenAuthenticatorOptions {\n repository: ServiceTokenRepository;\n}\n\n/**\n * Authenticator for service tokens (Business, Local SP, Cloud, Compute).\n *\n * Format: Bearer svc-xxx\n */\nexport class ServiceTokenAuthenticator implements Authenticator {\n private readonly logger = getLoggerFor(this);\n private readonly repo: ServiceTokenRepository;\n\n public constructor(options: ServiceTokenAuthenticatorOptions) {\n this.repo = options.repository;\n }\n\n public canAuthenticate(request: IncomingMessage): boolean {\n const auth = request.headers.authorization;\n if (!auth?.startsWith('Bearer ')) {\n return false;\n }\n const token = auth.slice(7).trim();\n // Service tokens start with 'svc-'\n return token.startsWith('svc-');\n }\n\n public async authenticate(request: IncomingMessage): Promise<AuthResult> {\n const auth = request.headers.authorization!;\n const token = auth.slice(7).trim();\n\n try {\n const record = await this.repo.verifyToken(token);\n if (!record) {\n return { success: false, error: 'Invalid service token' };\n }\n\n this.logger.debug(`Authenticated service: ${record.serviceType}:${record.serviceId}`);\n\n return {\n success: true,\n context: {\n type: 'service',\n serviceType: record.serviceType,\n serviceId: record.serviceId,\n scopes: record.scopes,\n },\n };\n } catch (error) {\n this.logger.error(`Service token authentication failed: ${error}`);\n return { success: false, error: 'Internal authentication error' };\n }\n }\n}\n"]}
@@ -2,4 +2,5 @@ export * from './Authenticator';
2
2
  export * from './AuthContext';
3
3
  export * from './SolidTokenAuthenticator';
4
4
  export * from './ClientCredentialsAuthenticator';
5
+ export * from './ServiceTokenAuthenticator';
5
6
  export * from './MultiAuthenticator';
@@ -18,6 +18,7 @@ __exportStar(require("./Authenticator"), exports);
18
18
  __exportStar(require("./AuthContext"), exports);
19
19
  __exportStar(require("./SolidTokenAuthenticator"), exports);
20
20
  __exportStar(require("./ClientCredentialsAuthenticator"), exports);
21
+ __exportStar(require("./ServiceTokenAuthenticator"), exports);
21
22
  // export * from './NodeTokenAuthenticator'; // TODO: Fix later
22
23
  __exportStar(require("./MultiAuthenticator"), exports);
23
24
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/api/auth/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kDAAgC;AAChC,gDAA8B;AAC9B,4DAA0C;AAC1C,mEAAiD;AACjD,gEAAgE;AAChE,uDAAqC","sourcesContent":["export * from './Authenticator';\nexport * from './AuthContext';\nexport * from './SolidTokenAuthenticator';\nexport * from './ClientCredentialsAuthenticator';\n// export * from './NodeTokenAuthenticator'; // TODO: Fix later\nexport * from './MultiAuthenticator';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/api/auth/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,kDAAgC;AAChC,gDAA8B;AAC9B,4DAA0C;AAC1C,mEAAiD;AACjD,8DAA4C;AAC5C,gEAAgE;AAChE,uDAAqC","sourcesContent":["export * from './Authenticator';\nexport * from './AuthContext';\nexport * from './SolidTokenAuthenticator';\nexport * from './ClientCredentialsAuthenticator';\nexport * from './ServiceTokenAuthenticator';\n// export * from './NodeTokenAuthenticator'; // TODO: Fix later\nexport * from './MultiAuthenticator';\n"]}
@@ -41,14 +41,4 @@ export declare class VercelAiProvider implements AiProvider {
41
41
  private handleRateLimitError;
42
42
  private getProviderConfig;
43
43
  private createProvider;
44
- private getPodBaseUrlFromWebId;
45
- private getDefaultBaseUrl;
46
- /**
47
- * 使用 Default Agent 流式响应
48
- */
49
- private streamWithDefaultAgent;
50
- /**
51
- * 从上下文获取 Solid Token
52
- */
53
- private getSolidToken;
54
44
  }
@@ -13,7 +13,7 @@ const global_logger_factory_1 = require("global-logger-factory");
13
13
  const undici_1 = require("undici");
14
14
  const AuthContext_1 = require("../auth/AuthContext");
15
15
  const types_1 = require("../../credential/schema/types");
16
- const default_agent_1 = require("./default-agent");
16
+ const provider_registry_1 = require("../service/provider-registry");
17
17
  // Create a proxy-aware fetch function
18
18
  function createProxyFetch(proxyUrl) {
19
19
  const agent = new undici_1.ProxyAgent(proxyUrl);
@@ -40,11 +40,8 @@ class VercelAiProvider {
40
40
  const userId = auth ? ((0, AuthContext_1.getWebId)(auth) ?? (0, AuthContext_1.getAccountId)(auth) ?? 'anonymous') : 'anonymous';
41
41
  // 从 Pod 获取配置
42
42
  const config = await this.getProviderConfig(context);
43
- // 无有效配置,降级到 Default Agent
44
43
  if (!config) {
45
- this.logger.info(`No valid AI config for ${userId}, falling back to Default Agent`);
46
- yield* this.streamWithDefaultAgent(messages, context);
47
- return;
44
+ throw new Error('No AI provider configured. Please configure Pod AI provider or set DEFAULT_API_BASE.');
48
45
  }
49
46
  const model = options?.model ?? config.defaultModel ?? process.env.DEFAULT_MODEL ?? 'stepfun/step-3.5-flash:free';
50
47
  this.logger.debug(`Streaming response for ${userId}, model: ${model}`);
@@ -141,38 +138,25 @@ Model: ${model}
141
138
  config = undefined;
142
139
  }
143
140
  }
144
- // 用户 Pod 有配置,优先使用
141
+ // 1. 用户 Pod 有配置,优先使用
145
142
  if (config?.apiKey) {
146
143
  return {
147
- baseURL: config.baseUrl || this.getDefaultBaseUrl('openrouter'),
144
+ baseURL: config.baseUrl || (0, provider_registry_1.getDefaultBaseUrl)(),
148
145
  apiKey: config.apiKey,
149
146
  proxy: config.proxyUrl,
150
147
  credentialId: config.credentialId,
151
148
  };
152
149
  }
153
- // 环境变量配置(开发/测试用)
154
- if (process.env.XPOD_AI_API_KEY) {
150
+ // 2. 平台 Provider
151
+ const platformBase = process.env.DEFAULT_API_BASE;
152
+ if (platformBase) {
155
153
  return {
156
- baseURL: process.env.XPOD_AI_BASE_URL || 'https://openrouter.ai/api/v1',
157
- apiKey: process.env.XPOD_AI_API_KEY,
154
+ baseURL: platformBase,
155
+ apiKey: process.env.DEFAULT_API_KEY || '',
158
156
  };
159
157
  }
160
- // Google API Key 特殊处理
161
- if (process.env.GOOGLE_API_KEY) {
162
- return {
163
- baseURL: 'https://generativelanguage.googleapis.com/v1beta/openai',
164
- apiKey: process.env.GOOGLE_API_KEY,
165
- };
166
- }
167
- // OpenRouter API Key
168
- if (process.env.OPENROUTER_API_KEY) {
169
- return {
170
- baseURL: 'https://openrouter.ai/api/v1',
171
- apiKey: process.env.OPENROUTER_API_KEY,
172
- };
173
- }
174
- // 无有效配置,返回 null 表示需要降级到 Default Agent
175
- this.logger.debug('No valid AI config found, will use Default Agent');
158
+ // 3. 无配置
159
+ this.logger.debug('No valid AI config found');
176
160
  return null;
177
161
  }
178
162
  createProvider(config) {
@@ -184,99 +168,6 @@ Model: ${model}
184
168
  }
185
169
  return (0, openai_1.createOpenAI)(options);
186
170
  }
187
- getPodBaseUrlFromWebId(webId) {
188
- try {
189
- const url = new URL(webId);
190
- url.hash = ''; // 清除 fragment
191
- const pathParts = url.pathname.split('/');
192
- if (pathParts.includes('profile')) {
193
- const profileIndex = pathParts.indexOf('profile');
194
- url.pathname = pathParts.slice(0, profileIndex).join('/');
195
- }
196
- return url.toString().replace(/\/$/, '') + '/';
197
- }
198
- catch {
199
- return '';
200
- }
201
- }
202
- getDefaultBaseUrl(provider) {
203
- const urls = {
204
- openai: 'https://api.openai.com/v1',
205
- google: 'https://generativelanguage.googleapis.com/v1beta/openai',
206
- anthropic: 'https://api.anthropic.com/v1',
207
- deepseek: 'https://api.deepseek.com/v1',
208
- openrouter: 'https://openrouter.ai/api/v1',
209
- ollama: 'http://localhost:11434/v1',
210
- mistral: 'https://api.mistral.ai/v1',
211
- cohere: 'https://api.cohere.ai/v1',
212
- zhipu: 'https://open.bigmodel.cn/api/paas/v4',
213
- };
214
- return urls[provider.toLowerCase()] || urls.openrouter;
215
- }
216
- /**
217
- * 使用 Default Agent 流式响应
218
- */
219
- async *streamWithDefaultAgent(messages, context) {
220
- // 检查 Default Agent 是否可用
221
- if (!(0, default_agent_1.isDefaultAgentAvailable)()) {
222
- yield '抱歉,您还没有配置 AI 服务,且系统默认 AI 也未配置。请先配置您的 AI API Key。';
223
- return;
224
- }
225
- // 构建 Default Agent 上下文
226
- const auth = context?.auth;
227
- const webId = auth ? (0, AuthContext_1.getWebId)(auth) : undefined;
228
- if (!webId) {
229
- yield '抱歉,无法获取您的身份信息,请先登录。';
230
- return;
231
- }
232
- const podBaseUrl = this.getPodBaseUrlFromWebId(webId);
233
- const solidToken = this.getSolidToken(context);
234
- if (!solidToken) {
235
- yield '抱歉,无法获取访问令牌,请重新登录。';
236
- return;
237
- }
238
- const agentContext = {
239
- solidToken,
240
- podBaseUrl,
241
- webId,
242
- };
243
- // 获取最后一条用户消息
244
- const lastUserMessage = messages.filter(m => m.role === 'user').pop()?.content || '';
245
- try {
246
- yield* (0, default_agent_1.streamDefaultAgent)(lastUserMessage, agentContext);
247
- }
248
- catch (error) {
249
- this.logger.error(`Default Agent error: ${error}`);
250
- yield `抱歉,Default Agent 出现错误:${error instanceof Error ? error.message : String(error)}`;
251
- }
252
- }
253
- /**
254
- * 从上下文获取 Solid Token
255
- */
256
- getSolidToken(context) {
257
- // 尝试从 context 中获取 token
258
- // 这里需要根据实际的 auth 实现来获取
259
- const auth = context?.auth;
260
- if (!auth)
261
- return undefined;
262
- // 如果 auth 中有 token,直接返回
263
- if ('token' in auth && typeof auth.token === 'string') {
264
- return auth.token;
265
- }
266
- // 如果有 accessToken
267
- if ('accessToken' in auth && typeof auth.accessToken === 'string') {
268
- return auth.accessToken;
269
- }
270
- // 尝试从 credentials 获取
271
- if ('credentials' in auth && auth.credentials) {
272
- const creds = auth.credentials;
273
- if (creds.accessToken)
274
- return creds.accessToken;
275
- if (creds.token)
276
- return creds.token;
277
- }
278
- return undefined;
279
- }
280
171
  }
281
172
  exports.VercelAiProvider = VercelAiProvider;
282
173
  //# sourceMappingURL=ai-provider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ai-provider.js","sourceRoot":"","sources":["../../../src/api/chatkit/ai-provider.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * AI Provider Adapter\n *\n * Adapts existing AI services to the ChatKit AiProvider interface.\n * Includes 429 rate limit handling with credential status backfill.\n */\n\nimport { createOpenAI } from '@ai-sdk/openai';\nimport { streamText, APICallError } from 'ai';\nimport { getLoggerFor } from 'global-logger-factory';\nimport { ProxyAgent } from 'undici';\nimport type { AiProvider } from './service';\nimport type { StoreContext } from './store';\nimport type { PodChatKitStore } from './pod-store';\nimport type { AuthContext } from '../auth/AuthContext';\nimport { getWebId, getAccountId } from '../auth/AuthContext';\nimport { CredentialStatus } from '../../credential/schema/types';\nimport { isDefaultAgentAvailable, streamDefaultAgent, type DefaultAgentContext } from './default-agent';\n\n// Create a proxy-aware fetch function\nfunction createProxyFetch(proxyUrl: string): typeof fetch {\n const agent = new ProxyAgent(proxyUrl);\n return (url, init) => fetch(url, { ...init, dispatcher: agent } as any);\n}\n\nexport interface VercelAiProviderOptions {\n store: PodChatKitStore;\n}\n\n/**\n * Vercel AI SDK based provider\n *\n * Uses PodChatKitStore to get AI provider settings from Pod.\n * Reuses the same Session cached in StoreContext.\n */\nexport class VercelAiProvider implements AiProvider {\n private readonly logger = getLoggerFor(this);\n private readonly store: PodChatKitStore;\n\n public constructor(options: VercelAiProviderOptions) {\n this.store = options.store;\n }\n\n /**\n * Stream a response for the given messages\n */\n public async *streamResponse(\n messages: Array<{ role: 'system' | 'user' | 'assistant'; content: string }>,\n options?: {\n model?: string;\n temperature?: number;\n maxTokens?: number;\n context?: unknown;\n },\n ): AsyncIterable<string> {\n // Get context (contains auth and cached session)\n const context = options?.context as StoreContext | undefined;\n const auth = context?.auth as AuthContext | undefined;\n const userId = auth ? (getWebId(auth) ?? getAccountId(auth) ?? 'anonymous') : 'anonymous';\n\n // 从 Pod 获取配置\n const config = await this.getProviderConfig(context);\n\n // 无有效配置,降级到 Default Agent\n if (!config) {\n this.logger.info(`No valid AI config for ${userId}, falling back to Default Agent`);\n yield* this.streamWithDefaultAgent(messages, context);\n return;\n }\n\n const model = options?.model ?? config.defaultModel ?? process.env.DEFAULT_MODEL ?? 'stepfun/step-3.5-flash:free';\n\n this.logger.debug(`Streaming response for ${userId}, model: ${model}`);\n\n const provider = this.createProvider(config);\n\n try {\n const result = streamText({\n model: provider.chat(model),\n messages: messages as any,\n temperature: options?.temperature,\n maxTokens: options?.maxTokens,\n system: `You are a helpful AI assistant running on Xpod (a Solid Pod-based platform).\n\nYour capabilities:\n1. Help users with various tasks\n2. Use user's configured provider/model to respond consistently\n\nCurrent AI Provider: ${config.baseURL.includes('openrouter') ? 'OpenRouter (Free)' : 'Custom'}\nModel: ${model}\n`,\n } as any);\n\n // Stream text chunks\n for await (const chunk of result.textStream) {\n yield chunk;\n }\n } catch (error) {\n // Handle 429 rate limit errors\n if (this.isRateLimitError(error)) {\n await this.handleRateLimitError(error, context, config.credentialId);\n }\n throw error;\n }\n }\n\n /**\n * Check if error is a 429 rate limit error\n */\n private isRateLimitError(error: unknown): boolean {\n if (error instanceof APICallError) {\n return error.statusCode === 429;\n }\n if (error && typeof error === 'object') {\n const err = error as any;\n return err.status === 429 || err.statusCode === 429 || err.code === 'rate_limit_exceeded';\n }\n return false;\n }\n\n /**\n * Handle 429 rate limit error by updating credential status\n */\n private async handleRateLimitError(\n error: unknown,\n context: StoreContext | undefined,\n credentialId: string | undefined,\n ): Promise<void> {\n if (!context || !credentialId) {\n this.logger.debug('Cannot update credential status: missing context or credentialId');\n return;\n }\n\n let rateLimitResetAt: Date | undefined;\n if (error instanceof APICallError && error.responseHeaders) {\n const retryAfter = error.responseHeaders['retry-after'];\n if (retryAfter) {\n const seconds = parseInt(retryAfter, 10);\n if (!isNaN(seconds)) {\n rateLimitResetAt = new Date(Date.now() + seconds * 1000);\n } else {\n const date = new Date(retryAfter);\n if (!isNaN(date.getTime())) {\n rateLimitResetAt = date;\n }\n }\n }\n }\n\n if (!rateLimitResetAt) {\n rateLimitResetAt = new Date(Date.now() + 60 * 1000);\n }\n\n this.logger.warn(`Rate limited for credential ${credentialId}, reset at ${rateLimitResetAt.toISOString()}`);\n\n try {\n await this.store.updateCredentialStatus(context, credentialId, CredentialStatus.RATE_LIMITED, {\n rateLimitResetAt,\n incrementFailCount: true,\n });\n } catch (updateError) {\n this.logger.error(`Failed to update credential status: ${updateError}`);\n }\n }\n\n private async getProviderConfig(\n context: StoreContext | undefined,\n ): Promise<{\n baseURL: string;\n apiKey: string;\n proxy?: string;\n defaultModel?: string;\n credentialId?: string;\n } | null> {\n let config: Awaited<ReturnType<PodChatKitStore['getAiConfig']>> | undefined;\n\n if (context) {\n try {\n config = await this.store.getAiConfig(context);\n this.logger.debug(`Pod config: ${JSON.stringify(config)}`);\n } catch (error) {\n this.logger.debug(`Failed to get Pod config: ${error}`);\n config = undefined;\n }\n }\n\n // 用户 Pod 有配置,优先使用\n if (config?.apiKey) {\n return {\n baseURL: config.baseUrl || this.getDefaultBaseUrl('openrouter'),\n apiKey: config.apiKey,\n proxy: config.proxyUrl,\n credentialId: config.credentialId,\n };\n }\n\n // 环境变量配置(开发/测试用)\n if (process.env.XPOD_AI_API_KEY) {\n return {\n baseURL: process.env.XPOD_AI_BASE_URL || 'https://openrouter.ai/api/v1',\n apiKey: process.env.XPOD_AI_API_KEY,\n };\n }\n\n // Google API Key 特殊处理\n if (process.env.GOOGLE_API_KEY) {\n return {\n baseURL: 'https://generativelanguage.googleapis.com/v1beta/openai',\n apiKey: process.env.GOOGLE_API_KEY,\n };\n }\n\n // OpenRouter API Key\n if (process.env.OPENROUTER_API_KEY) {\n return {\n baseURL: 'https://openrouter.ai/api/v1',\n apiKey: process.env.OPENROUTER_API_KEY,\n };\n }\n\n // 无有效配置,返回 null 表示需要降级到 Default Agent\n this.logger.debug('No valid AI config found, will use Default Agent');\n return null;\n }\n\n private createProvider(config: { baseURL: string; apiKey: string; proxy?: string }) {\n const { baseURL, apiKey, proxy } = config;\n\n this.logger.debug(`Using AI Provider: ${baseURL} (proxy: ${proxy || 'none'})`);\n\n const options: any = { baseURL, apiKey };\n if (proxy) {\n options.fetch = createProxyFetch(proxy);\n }\n\n return createOpenAI(options);\n }\n\n private getPodBaseUrlFromWebId(webId: string): string {\n try {\n const url = new URL(webId);\n url.hash = ''; // 清除 fragment\n const pathParts = url.pathname.split('/');\n if (pathParts.includes('profile')) {\n const profileIndex = pathParts.indexOf('profile');\n url.pathname = pathParts.slice(0, profileIndex).join('/');\n }\n return url.toString().replace(/\\/$/, '') + '/';\n } catch {\n return '';\n }\n }\n\n private getDefaultBaseUrl(provider: string): string {\n const urls: Record<string, string> = {\n openai: 'https://api.openai.com/v1',\n google: 'https://generativelanguage.googleapis.com/v1beta/openai',\n anthropic: 'https://api.anthropic.com/v1',\n deepseek: 'https://api.deepseek.com/v1',\n openrouter: 'https://openrouter.ai/api/v1',\n ollama: 'http://localhost:11434/v1',\n mistral: 'https://api.mistral.ai/v1',\n cohere: 'https://api.cohere.ai/v1',\n zhipu: 'https://open.bigmodel.cn/api/paas/v4',\n };\n return urls[provider.toLowerCase()] || urls.openrouter;\n }\n\n /**\n * 使用 Default Agent 流式响应\n */\n private async *streamWithDefaultAgent(\n messages: Array<{ role: 'system' | 'user' | 'assistant'; content: string }>,\n context: StoreContext | undefined,\n ): AsyncIterable<string> {\n // 检查 Default Agent 是否可用\n if (!isDefaultAgentAvailable()) {\n yield '抱歉,您还没有配置 AI 服务,且系统默认 AI 也未配置。请先配置您的 AI API Key。';\n return;\n }\n\n // 构建 Default Agent 上下文\n const auth = context?.auth as AuthContext | undefined;\n const webId = auth ? getWebId(auth) : undefined;\n\n if (!webId) {\n yield '抱歉,无法获取您的身份信息,请先登录。';\n return;\n }\n\n const podBaseUrl = this.getPodBaseUrlFromWebId(webId);\n const solidToken = this.getSolidToken(context);\n\n if (!solidToken) {\n yield '抱歉,无法获取访问令牌,请重新登录。';\n return;\n }\n\n const agentContext: DefaultAgentContext = {\n solidToken,\n podBaseUrl,\n webId,\n };\n\n // 获取最后一条用户消息\n const lastUserMessage = messages.filter(m => m.role === 'user').pop()?.content || '';\n\n try {\n yield* streamDefaultAgent(lastUserMessage, agentContext);\n } catch (error) {\n this.logger.error(`Default Agent error: ${error}`);\n yield `抱歉,Default Agent 出现错误:${error instanceof Error ? error.message : String(error)}`;\n }\n }\n\n /**\n * 从上下文获取 Solid Token\n */\n private getSolidToken(context: StoreContext | undefined): string | undefined {\n // 尝试从 context 中获取 token\n // 这里需要根据实际的 auth 实现来获取\n const auth = context?.auth as AuthContext | undefined;\n if (!auth) return undefined;\n\n // 如果 auth 中有 token,直接返回\n if ('token' in auth && typeof auth.token === 'string') {\n return auth.token;\n }\n\n // 如果有 accessToken\n if ('accessToken' in auth && typeof auth.accessToken === 'string') {\n return auth.accessToken;\n }\n\n // 尝试从 credentials 获取\n if ('credentials' in auth && auth.credentials) {\n const creds = auth.credentials as any;\n if (creds.accessToken) return creds.accessToken;\n if (creds.token) return creds.token;\n }\n\n return undefined;\n }\n}\n"]}
1
+ {"version":3,"file":"ai-provider.js","sourceRoot":"","sources":["../../../src/api/chatkit/ai-provider.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * AI Provider Adapter\n *\n * Adapts existing AI services to the ChatKit AiProvider interface.\n * Includes 429 rate limit handling with credential status backfill.\n */\n\nimport { createOpenAI } from '@ai-sdk/openai';\nimport { streamText, APICallError } from 'ai';\nimport { getLoggerFor } from 'global-logger-factory';\nimport { ProxyAgent } from 'undici';\nimport type { AiProvider } from './service';\nimport type { StoreContext } from './store';\nimport type { PodChatKitStore } from './pod-store';\nimport type { AuthContext } from '../auth/AuthContext';\nimport { getWebId, getAccountId } from '../auth/AuthContext';\nimport { CredentialStatus } from '../../credential/schema/types';\nimport { getDefaultBaseUrl } from '../service/provider-registry';\n\n// Create a proxy-aware fetch function\nfunction createProxyFetch(proxyUrl: string): typeof fetch {\n const agent = new ProxyAgent(proxyUrl);\n return (url, init) => fetch(url, { ...init, dispatcher: agent } as any);\n}\n\nexport interface VercelAiProviderOptions {\n store: PodChatKitStore;\n}\n\n/**\n * Vercel AI SDK based provider\n *\n * Uses PodChatKitStore to get AI provider settings from Pod.\n * Reuses the same Session cached in StoreContext.\n */\nexport class VercelAiProvider implements AiProvider {\n private readonly logger = getLoggerFor(this);\n private readonly store: PodChatKitStore;\n\n public constructor(options: VercelAiProviderOptions) {\n this.store = options.store;\n }\n\n /**\n * Stream a response for the given messages\n */\n public async *streamResponse(\n messages: Array<{ role: 'system' | 'user' | 'assistant'; content: string }>,\n options?: {\n model?: string;\n temperature?: number;\n maxTokens?: number;\n context?: unknown;\n },\n ): AsyncIterable<string> {\n // Get context (contains auth and cached session)\n const context = options?.context as StoreContext | undefined;\n const auth = context?.auth as AuthContext | undefined;\n const userId = auth ? (getWebId(auth) ?? getAccountId(auth) ?? 'anonymous') : 'anonymous';\n\n // 从 Pod 获取配置\n const config = await this.getProviderConfig(context);\n\n if (!config) {\n throw new Error('No AI provider configured. Please configure Pod AI provider or set DEFAULT_API_BASE.');\n }\n\n const model = options?.model ?? config.defaultModel ?? process.env.DEFAULT_MODEL ?? 'stepfun/step-3.5-flash:free';\n\n this.logger.debug(`Streaming response for ${userId}, model: ${model}`);\n\n const provider = this.createProvider(config);\n\n try {\n const result = streamText({\n model: provider.chat(model),\n messages: messages as any,\n temperature: options?.temperature,\n maxTokens: options?.maxTokens,\n system: `You are a helpful AI assistant running on Xpod (a Solid Pod-based platform).\n\nYour capabilities:\n1. Help users with various tasks\n2. Use user's configured provider/model to respond consistently\n\nCurrent AI Provider: ${config.baseURL.includes('openrouter') ? 'OpenRouter (Free)' : 'Custom'}\nModel: ${model}\n`,\n } as any);\n\n // Stream text chunks\n for await (const chunk of result.textStream) {\n yield chunk;\n }\n } catch (error) {\n // Handle 429 rate limit errors\n if (this.isRateLimitError(error)) {\n await this.handleRateLimitError(error, context, config.credentialId);\n }\n throw error;\n }\n }\n\n /**\n * Check if error is a 429 rate limit error\n */\n private isRateLimitError(error: unknown): boolean {\n if (error instanceof APICallError) {\n return error.statusCode === 429;\n }\n if (error && typeof error === 'object') {\n const err = error as any;\n return err.status === 429 || err.statusCode === 429 || err.code === 'rate_limit_exceeded';\n }\n return false;\n }\n\n /**\n * Handle 429 rate limit error by updating credential status\n */\n private async handleRateLimitError(\n error: unknown,\n context: StoreContext | undefined,\n credentialId: string | undefined,\n ): Promise<void> {\n if (!context || !credentialId) {\n this.logger.debug('Cannot update credential status: missing context or credentialId');\n return;\n }\n\n let rateLimitResetAt: Date | undefined;\n if (error instanceof APICallError && error.responseHeaders) {\n const retryAfter = error.responseHeaders['retry-after'];\n if (retryAfter) {\n const seconds = parseInt(retryAfter, 10);\n if (!isNaN(seconds)) {\n rateLimitResetAt = new Date(Date.now() + seconds * 1000);\n } else {\n const date = new Date(retryAfter);\n if (!isNaN(date.getTime())) {\n rateLimitResetAt = date;\n }\n }\n }\n }\n\n if (!rateLimitResetAt) {\n rateLimitResetAt = new Date(Date.now() + 60 * 1000);\n }\n\n this.logger.warn(`Rate limited for credential ${credentialId}, reset at ${rateLimitResetAt.toISOString()}`);\n\n try {\n await this.store.updateCredentialStatus(context, credentialId, CredentialStatus.RATE_LIMITED, {\n rateLimitResetAt,\n incrementFailCount: true,\n });\n } catch (updateError) {\n this.logger.error(`Failed to update credential status: ${updateError}`);\n }\n }\n\n private async getProviderConfig(\n context: StoreContext | undefined,\n ): Promise<{\n baseURL: string;\n apiKey: string;\n proxy?: string;\n defaultModel?: string;\n credentialId?: string;\n } | null> {\n let config: Awaited<ReturnType<PodChatKitStore['getAiConfig']>> | undefined;\n\n if (context) {\n try {\n config = await this.store.getAiConfig(context);\n this.logger.debug(`Pod config: ${JSON.stringify(config)}`);\n } catch (error) {\n this.logger.debug(`Failed to get Pod config: ${error}`);\n config = undefined;\n }\n }\n\n // 1. 用户 Pod 有配置,优先使用\n if (config?.apiKey) {\n return {\n baseURL: config.baseUrl || getDefaultBaseUrl(),\n apiKey: config.apiKey,\n proxy: config.proxyUrl,\n credentialId: config.credentialId,\n };\n }\n\n // 2. 平台 Provider\n const platformBase = process.env.DEFAULT_API_BASE;\n if (platformBase) {\n return {\n baseURL: platformBase,\n apiKey: process.env.DEFAULT_API_KEY || '',\n };\n }\n\n // 3. 无配置\n this.logger.debug('No valid AI config found');\n return null;\n }\n\n private createProvider(config: { baseURL: string; apiKey: string; proxy?: string }) {\n const { baseURL, apiKey, proxy } = config;\n\n this.logger.debug(`Using AI Provider: ${baseURL} (proxy: ${proxy || 'none'})`);\n\n const options: any = { baseURL, apiKey };\n if (proxy) {\n options.fetch = createProxyFetch(proxy);\n }\n\n return createOpenAI(options);\n }\n\n}\n"]}
@@ -91,8 +91,7 @@ function getDefaultAgentConfig() {
91
91
  * 检查 Default Agent 是否可用
92
92
  */
93
93
  function isDefaultAgentAvailable() {
94
- const config = getDefaultAgentConfig();
95
- return !!config.apiKey;
94
+ return !!(process.env.DEFAULT_API_KEY || process.env.DEFAULT_API_BASE);
96
95
  }
97
96
  /**
98
97
  * Default Agent System Prompt
@@ -224,7 +223,9 @@ function buildClaudeEnv(config, context) {
224
223
  if (isOpenRouterLike) {
225
224
  // Claude Code expects Anthropic-shaped settings; OpenRouter is compatible after base path normalization.
226
225
  env.ANTHROPIC_BASE_URL = normalizeClaudeBaseUrl(baseUrl);
227
- env.ANTHROPIC_AUTH_TOKEN = config.apiKey;
226
+ if (config.apiKey) {
227
+ env.ANTHROPIC_AUTH_TOKEN = config.apiKey;
228
+ }
228
229
  if (model) {
229
230
  env.ANTHROPIC_DEFAULT_SONNET_MODEL = model;
230
231
  env.ANTHROPIC_DEFAULT_HAIKU_MODEL = model;
@@ -234,7 +235,9 @@ function buildClaudeEnv(config, context) {
234
235
  }
235
236
  else {
236
237
  env.ANTHROPIC_BASE_URL = baseUrl;
237
- env.ANTHROPIC_API_KEY = config.apiKey;
238
+ if (config.apiKey) {
239
+ env.ANTHROPIC_API_KEY = config.apiKey;
240
+ }
238
241
  delete env.ANTHROPIC_AUTH_TOKEN;
239
242
  }
240
243
  return env;
@@ -255,11 +258,11 @@ function resolveClaudeModel(config) {
255
258
  */
256
259
  async function runDefaultAgent(message, context, options) {
257
260
  const config = getDefaultAgentConfig();
258
- if (!config.apiKey) {
261
+ if (!config.apiKey && !process.env.DEFAULT_API_BASE) {
259
262
  return {
260
263
  content: '',
261
264
  success: false,
262
- error: 'Default Agent not configured: DEFAULT_API_KEY is required',
265
+ error: 'Default Agent not configured: DEFAULT_API_KEY or DEFAULT_API_BASE is required',
263
266
  };
264
267
  }
265
268
  const abortController = new AbortController();
@@ -324,8 +327,8 @@ async function runDefaultAgent(message, context, options) {
324
327
  */
325
328
  async function* streamDefaultAgent(message, context, options) {
326
329
  const config = getDefaultAgentConfig();
327
- if (!config.apiKey) {
328
- throw new Error('Default Agent not configured: DEFAULT_API_KEY is required');
330
+ if (!config.apiKey && !process.env.DEFAULT_API_BASE) {
331
+ throw new Error('Default Agent not configured: DEFAULT_API_KEY or DEFAULT_API_BASE is required');
329
332
  }
330
333
  const abortController = new AbortController();
331
334
  const timeout = options?.timeout || 60000;
@@ -1 +1 @@
1
- {"version":3,"file":"default-agent.js","sourceRoot":"","sources":["../../../src/api/chatkit/default-agent.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Default Agent\n *\n * 基于 Claude Code SDK 的默认 AI Agent,用于:\n * 1. 用户未配置 AI 时的降级方案\n * 2. 帮助用户完成初始化配置\n * 3. 识别并收纳结构化数据到 Pod\n */\n\nimport { getLoggerFor } from 'global-logger-factory';\n\n/**\n * CC SDK 运行时消息结构(避免直接静态导入 ESM 包导致 CJS 启动崩溃)\n */\ntype ClaudeAssistantBlock = { type: 'text'; text: string } | { type: string; [key: string]: unknown };\ntype ClaudeAssistantMessage = { type: 'assistant'; message: { content: ClaudeAssistantBlock[] | unknown } };\ntype ClaudeResultMessage = { type: 'result'; subtype?: string; result?: string; total_cost_usd?: number };\ntype ClaudeQueryMessage = ClaudeAssistantMessage | ClaudeResultMessage | { type: string; [key: string]: unknown };\ntype ClaudeQuery = (args: unknown) => AsyncIterable<ClaudeQueryMessage>;\n\nlet cachedClaudeQuery: ClaudeQuery | undefined;\n\nasync function loadClaudeQuery(): Promise<ClaudeQuery> {\n if (cachedClaudeQuery) {\n return cachedClaudeQuery;\n }\n\n // Keep native dynamic import so CJS build can load ESM-only SDK lazily.\n const mod = await import('@anthropic-ai/claude-agent-sdk') as Record<string, unknown>;\n const maybeQuery = (mod as { query?: unknown }).query;\n\n if (typeof maybeQuery !== 'function') {\n throw new Error('Invalid Claude Agent SDK: query() not found');\n }\n\n cachedClaudeQuery = maybeQuery as ClaudeQuery;\n return cachedClaudeQuery;\n}\n\nconst logger = getLoggerFor('DefaultAgent');\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction isAssistantMessage(value: ClaudeQueryMessage): value is ClaudeAssistantMessage {\n return value.type === 'assistant' && isObject((value as { message?: unknown }).message);\n}\n\nfunction isResultMessage(value: ClaudeQueryMessage): value is ClaudeResultMessage {\n return value.type === 'result';\n}\n\nfunction getAssistantText(value: ClaudeQueryMessage): string {\n if (!isAssistantMessage(value)) {\n return '';\n }\n\n const content = value.message.content;\n if (!Array.isArray(content)) {\n return '';\n }\n\n let text = '';\n for (const block of content) {\n if (isObject(block) && block.type === 'text' && typeof block.text === 'string') {\n text += block.text;\n }\n }\n\n return text;\n}\n\n/**\n * Default Agent 配置\n */\nexport interface DefaultAgentConfig {\n /** Claude Code 可执行文件路径 */\n claudeCodePath?: string;\n /** 默认 AI 提供商 */\n provider?: string;\n /** 默认模型 */\n model?: string;\n /** API Key */\n apiKey?: string;\n}\n\n/**\n * Default Agent 会话上下文\n */\nexport interface DefaultAgentContext {\n /** 用户的访问令牌 */\n solidToken: string;\n /** 用户的 Pod 基础 URL */\n podBaseUrl: string;\n /** 用户 WebID */\n webId?: string;\n}\n\n/**\n * Default Agent 响应\n */\nexport interface DefaultAgentResponse {\n /** 响应内容 */\n content: string;\n /** 是否成功 */\n success: boolean;\n /** 错误信息 */\n error?: string;\n /** 使用的模型 */\n model?: string;\n /** 花费(USD) */\n costUsd?: number;\n}\n\n/**\n * 获取 Default Agent 配置\n */\nexport function getDefaultAgentConfig(): DefaultAgentConfig {\n return {\n claudeCodePath: process.env.CLAUDE_CODE_PATH || undefined,\n provider: process.env.DEFAULT_PROVIDER || 'openrouter',\n model: process.env.DEFAULT_MODEL || 'stepfun/step-3.5-flash:free',\n apiKey: process.env.DEFAULT_API_KEY || '',\n };\n}\n\n/**\n * 检查 Default Agent 是否可用\n */\nexport function isDefaultAgentAvailable(): boolean {\n const config = getDefaultAgentConfig();\n return !!config.apiKey;\n}\n\n/**\n * Default Agent System Prompt\n */\nconst DEFAULT_AGENT_SYSTEM_PROMPT = `你是 Xpod Default Agent,运行在用户的 Solid Pod 上。\n\n## 你的职责\n1. 帮助用户完成初始化配置(特别是 AI 配置)\n2. 识别用户消息中的结构化数据并存储到 Pod\n3. 按语义网规范组织数据\n\n## 数据收纳能力\n当用户的消息中包含以下类型的信息时,识别并保存:\n\n### AI 配置(最重要)\n- API Key、Provider、Model、Base URL\n- 存储位置:/settings/ai/credentials.ttl\n- 识别模式:\n - \"我的 OpenAI key 是 sk-xxx\"\n - \"用这个 API key: xxx\"\n - \"anthropic 密钥 xxx\"\n\n### 联系人\n- 姓名、邮箱、电话、WebID\n- 存储位置:/contacts/<name>.ttl\n- 词汇表:vCard (http://www.w3.org/2006/vcard/ns#)\n\n### 日程/事件\n- 时间、地点、标题\n- 存储位置:/calendar/events.ttl\n- 词汇表:schema:Event\n\n### 笔记\n- 标题、内容\n- 存储位置:/notes/<title>.ttl\n- 词汇表:schema:Note\n\n## Pod 访问方式\n使用 curl 访问用户 Pod,鉴权信息已在环境变量中:\n\n### 读取资源\n\\`\\`\\`bash\ncurl -s -H \"Authorization: Bearer $SOLID_TOKEN\" \"$POD_BASE_URL<path>\"\n\\`\\`\\`\n\n### 写入 Turtle 数据\n\\`\\`\\`bash\ncurl -s -X PUT \\\\\n -H \"Authorization: Bearer $SOLID_TOKEN\" \\\\\n -H \"Content-Type: text/turtle\" \\\\\n -d '<turtle-content>' \\\\\n \"$POD_BASE_URL<path>\"\n\\`\\`\\`\n\n### 创建容器(目录)\n\\`\\`\\`bash\ncurl -s -X PUT \\\\\n -H \"Authorization: Bearer $SOLID_TOKEN\" \\\\\n -H \"Content-Type: text/turtle\" \\\\\n -H \"Link: <http://www.w3.org/ns/ldp#BasicContainer>; rel=\\\\\"type\\\\\"\" \\\\\n \"$POD_BASE_URL<path>/\"\n\\`\\`\\`\n\n## 语义网规范\n使用 Turtle 格式,优先使用标准词汇表。\n\n### AI 配置示例\n\\`\\`\\`turtle\n@prefix xpod: <http://xpod.dev/ns#> .\n@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n\n<#openai-credential> a xpod:AiCredential ;\n rdfs:label \"OpenAI\" ;\n xpod:provider \"openai\" ;\n xpod:apiKey \"sk-xxx\" ;\n xpod:baseUrl \"https://api.openai.com/v1\" .\n\\`\\`\\`\n\n### 联系人示例\n\\`\\`\\`turtle\n@prefix vcard: <http://www.w3.org/2006/vcard/ns#> .\n\n<#person> a vcard:Individual ;\n vcard:fn \"张三\" ;\n vcard:hasEmail <mailto:zhangsan@example.com> ;\n vcard:hasTelephone <tel:+8613800138000> .\n\\`\\`\\`\n\n## 交互原则\n1. 识别到结构化数据时,直接保存(不需要确认)\n2. 保存成功后简短告知用户\n3. 如果是 AI 配置,提示用户\"已保存,后续对话将使用你的 AI 配置\"\n4. 其他情况正常对话即可\n5. 回复使用中文`;\n\n\nfunction getDefaultBaseUrl(provider?: string): string {\n const normalized = (provider || 'openrouter').toLowerCase();\n const urls: Record<string, string> = {\n openai: 'https://api.openai.com/v1',\n google: 'https://generativelanguage.googleapis.com/v1beta/openai',\n anthropic: 'https://api.anthropic.com/v1',\n deepseek: 'https://api.deepseek.com/v1',\n openrouter: 'https://openrouter.ai/api/v1',\n ollama: 'http://localhost:11434/v1',\n mistral: 'https://api.mistral.ai/v1',\n cohere: 'https://api.cohere.ai/v1',\n zhipu: 'https://open.bigmodel.cn/api/paas/v4',\n };\n return urls[normalized] || urls.openrouter;\n}\n\nfunction normalizeClaudeBaseUrl(baseUrl: string): string {\n if (baseUrl.endsWith('/v1')) {\n return baseUrl.slice(0, -3);\n }\n if (baseUrl.endsWith('/v1/')) {\n return baseUrl.slice(0, -4);\n }\n return baseUrl;\n}\n\nfunction buildClaudeEnv(config: DefaultAgentConfig, context: DefaultAgentContext): NodeJS.ProcessEnv {\n const provider = (config.provider || '').toLowerCase();\n const model = (config.model || '').trim();\n const baseUrl = process.env.DEFAULT_API_BASE || getDefaultBaseUrl(config.provider);\n const isOpenRouterLike = provider === 'openrouter' || baseUrl.includes('openrouter.ai');\n\n const env: NodeJS.ProcessEnv = {\n ...process.env,\n SOLID_TOKEN: context.solidToken,\n POD_BASE_URL: context.podBaseUrl,\n };\n\n if (isOpenRouterLike) {\n // Claude Code expects Anthropic-shaped settings; OpenRouter is compatible after base path normalization.\n env.ANTHROPIC_BASE_URL = normalizeClaudeBaseUrl(baseUrl);\n env.ANTHROPIC_AUTH_TOKEN = config.apiKey;\n if (model) {\n env.ANTHROPIC_DEFAULT_SONNET_MODEL = model;\n env.ANTHROPIC_DEFAULT_HAIKU_MODEL = model;\n env.ANTHROPIC_DEFAULT_OPUS_MODEL = model;\n }\n delete env.ANTHROPIC_API_KEY;\n } else {\n env.ANTHROPIC_BASE_URL = baseUrl;\n env.ANTHROPIC_API_KEY = config.apiKey;\n delete env.ANTHROPIC_AUTH_TOKEN;\n }\n\n return env;\n}\n\nfunction resolveClaudeModel(config: DefaultAgentConfig): string {\n const model = (config.model || '').trim();\n if (!model) {\n return 'sonnet';\n }\n\n if (model.startsWith('claude') || model.includes('anthropic/')) {\n return model;\n }\n\n // Non-Anthropic models (OpenRouter route) are mapped via ANTHROPIC_DEFAULT_SONNET_MODEL.\n return 'sonnet';\n}\n\n/**\n * 运行 Default Agent\n */\nexport async function runDefaultAgent(\n message: string,\n context: DefaultAgentContext,\n options?: {\n timeout?: number;\n maxTurns?: number;\n },\n): Promise<DefaultAgentResponse> {\n const config = getDefaultAgentConfig();\n\n if (!config.apiKey) {\n return {\n content: '',\n success: false,\n error: 'Default Agent not configured: DEFAULT_API_KEY is required',\n };\n }\n\n const abortController = new AbortController();\n const timeout = options?.timeout || 60000;\n\n const timeoutId = setTimeout(() => {\n logger.warn('Default Agent timeout, aborting...');\n abortController.abort();\n }, timeout);\n\n try {\n logger.info(`Running Default Agent for Pod: ${context.podBaseUrl}`);\n\n const queryFn = await loadClaudeQuery();\n const q = queryFn({\n prompt: message,\n options: {\n abortController,\n pathToClaudeCodeExecutable: config.claudeCodePath,\n env: buildClaudeEnv(config, context),\n systemPrompt: DEFAULT_AGENT_SYSTEM_PROMPT,\n model: resolveClaudeModel(config),\n permissionMode: 'acceptEdits',\n allowedTools: ['Bash', 'Read', 'Write'],\n maxTurns: options?.maxTurns || 10,\n },\n });\n\n let content = '';\n let costUsd: number | undefined;\n\n for await (const msg of q) {\n const assistantText = getAssistantText(msg);\n if (assistantText) {\n content += assistantText;\n }\n\n if (isResultMessage(msg)) {\n if (msg.subtype === 'success' && typeof msg.result === 'string' && msg.result.trim()) {\n content = msg.result;\n }\n if (typeof msg.total_cost_usd === 'number') {\n costUsd = msg.total_cost_usd;\n }\n }\n }\n\n clearTimeout(timeoutId);\n\n return {\n content,\n success: true,\n model: config.model || resolveClaudeModel(config),\n costUsd,\n };\n } catch (error) {\n clearTimeout(timeoutId);\n\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.error(`Default Agent error: ${errorMessage}`);\n\n return {\n content: '',\n success: false,\n error: errorMessage,\n };\n }\n}\n\n/**\n * 流式运行 Default Agent\n */\nexport async function* streamDefaultAgent(\n message: string,\n context: DefaultAgentContext,\n options?: {\n timeout?: number;\n maxTurns?: number;\n },\n): AsyncGenerator<string, void, unknown> {\n const config = getDefaultAgentConfig();\n\n if (!config.apiKey) {\n throw new Error('Default Agent not configured: DEFAULT_API_KEY is required');\n }\n\n const abortController = new AbortController();\n const timeout = options?.timeout || 60000;\n\n const timeoutId = setTimeout(() => {\n logger.warn('Default Agent timeout, aborting...');\n abortController.abort();\n }, timeout);\n\n try {\n logger.info(`Streaming Default Agent for Pod: ${context.podBaseUrl}`);\n\n const queryFn = await loadClaudeQuery();\n const q = queryFn({\n prompt: message,\n options: {\n abortController,\n pathToClaudeCodeExecutable: config.claudeCodePath,\n env: buildClaudeEnv(config, context),\n systemPrompt: DEFAULT_AGENT_SYSTEM_PROMPT,\n model: resolveClaudeModel(config),\n permissionMode: 'acceptEdits',\n allowedTools: ['Bash', 'Read', 'Write'],\n maxTurns: options?.maxTurns || 10,\n includePartialMessages: true,\n },\n });\n\n for await (const msg of q) {\n const assistantText = getAssistantText(msg);\n if (assistantText) {\n yield assistantText;\n }\n }\n\n clearTimeout(timeoutId);\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n}\n"]}
1
+ {"version":3,"file":"default-agent.js","sourceRoot":"","sources":["../../../src/api/chatkit/default-agent.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Default Agent\n *\n * 基于 Claude Code SDK 的默认 AI Agent,用于:\n * 1. 用户未配置 AI 时的降级方案\n * 2. 帮助用户完成初始化配置\n * 3. 识别并收纳结构化数据到 Pod\n */\n\nimport { getLoggerFor } from 'global-logger-factory';\n\n/**\n * CC SDK 运行时消息结构(避免直接静态导入 ESM 包导致 CJS 启动崩溃)\n */\ntype ClaudeAssistantBlock = { type: 'text'; text: string } | { type: string; [key: string]: unknown };\ntype ClaudeAssistantMessage = { type: 'assistant'; message: { content: ClaudeAssistantBlock[] | unknown } };\ntype ClaudeResultMessage = { type: 'result'; subtype?: string; result?: string; total_cost_usd?: number };\ntype ClaudeQueryMessage = ClaudeAssistantMessage | ClaudeResultMessage | { type: string; [key: string]: unknown };\ntype ClaudeQuery = (args: unknown) => AsyncIterable<ClaudeQueryMessage>;\n\nlet cachedClaudeQuery: ClaudeQuery | undefined;\n\nasync function loadClaudeQuery(): Promise<ClaudeQuery> {\n if (cachedClaudeQuery) {\n return cachedClaudeQuery;\n }\n\n // Keep native dynamic import so CJS build can load ESM-only SDK lazily.\n const mod = await import('@anthropic-ai/claude-agent-sdk') as Record<string, unknown>;\n const maybeQuery = (mod as { query?: unknown }).query;\n\n if (typeof maybeQuery !== 'function') {\n throw new Error('Invalid Claude Agent SDK: query() not found');\n }\n\n cachedClaudeQuery = maybeQuery as ClaudeQuery;\n return cachedClaudeQuery;\n}\n\nconst logger = getLoggerFor('DefaultAgent');\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction isAssistantMessage(value: ClaudeQueryMessage): value is ClaudeAssistantMessage {\n return value.type === 'assistant' && isObject((value as { message?: unknown }).message);\n}\n\nfunction isResultMessage(value: ClaudeQueryMessage): value is ClaudeResultMessage {\n return value.type === 'result';\n}\n\nfunction getAssistantText(value: ClaudeQueryMessage): string {\n if (!isAssistantMessage(value)) {\n return '';\n }\n\n const content = value.message.content;\n if (!Array.isArray(content)) {\n return '';\n }\n\n let text = '';\n for (const block of content) {\n if (isObject(block) && block.type === 'text' && typeof block.text === 'string') {\n text += block.text;\n }\n }\n\n return text;\n}\n\n/**\n * Default Agent 配置\n */\nexport interface DefaultAgentConfig {\n /** Claude Code 可执行文件路径 */\n claudeCodePath?: string;\n /** 默认 AI 提供商 */\n provider?: string;\n /** 默认模型 */\n model?: string;\n /** API Key */\n apiKey?: string;\n}\n\n/**\n * Default Agent 会话上下文\n */\nexport interface DefaultAgentContext {\n /** 用户的访问令牌 */\n solidToken: string;\n /** 用户的 Pod 基础 URL */\n podBaseUrl: string;\n /** 用户 WebID */\n webId?: string;\n}\n\n/**\n * Default Agent 响应\n */\nexport interface DefaultAgentResponse {\n /** 响应内容 */\n content: string;\n /** 是否成功 */\n success: boolean;\n /** 错误信息 */\n error?: string;\n /** 使用的模型 */\n model?: string;\n /** 花费(USD) */\n costUsd?: number;\n}\n\n/**\n * 获取 Default Agent 配置\n */\nexport function getDefaultAgentConfig(): DefaultAgentConfig {\n return {\n claudeCodePath: process.env.CLAUDE_CODE_PATH || undefined,\n provider: process.env.DEFAULT_PROVIDER || 'openrouter',\n model: process.env.DEFAULT_MODEL || 'stepfun/step-3.5-flash:free',\n apiKey: process.env.DEFAULT_API_KEY || '',\n };\n}\n\n/**\n * 检查 Default Agent 是否可用\n */\nexport function isDefaultAgentAvailable(): boolean {\n return !!(process.env.DEFAULT_API_KEY || process.env.DEFAULT_API_BASE);\n}\n\n/**\n * Default Agent System Prompt\n */\nconst DEFAULT_AGENT_SYSTEM_PROMPT = `你是 Xpod Default Agent,运行在用户的 Solid Pod 上。\n\n## 你的职责\n1. 帮助用户完成初始化配置(特别是 AI 配置)\n2. 识别用户消息中的结构化数据并存储到 Pod\n3. 按语义网规范组织数据\n\n## 数据收纳能力\n当用户的消息中包含以下类型的信息时,识别并保存:\n\n### AI 配置(最重要)\n- API Key、Provider、Model、Base URL\n- 存储位置:/settings/ai/credentials.ttl\n- 识别模式:\n - \"我的 OpenAI key 是 sk-xxx\"\n - \"用这个 API key: xxx\"\n - \"anthropic 密钥 xxx\"\n\n### 联系人\n- 姓名、邮箱、电话、WebID\n- 存储位置:/contacts/<name>.ttl\n- 词汇表:vCard (http://www.w3.org/2006/vcard/ns#)\n\n### 日程/事件\n- 时间、地点、标题\n- 存储位置:/calendar/events.ttl\n- 词汇表:schema:Event\n\n### 笔记\n- 标题、内容\n- 存储位置:/notes/<title>.ttl\n- 词汇表:schema:Note\n\n## Pod 访问方式\n使用 curl 访问用户 Pod,鉴权信息已在环境变量中:\n\n### 读取资源\n\\`\\`\\`bash\ncurl -s -H \"Authorization: Bearer $SOLID_TOKEN\" \"$POD_BASE_URL<path>\"\n\\`\\`\\`\n\n### 写入 Turtle 数据\n\\`\\`\\`bash\ncurl -s -X PUT \\\\\n -H \"Authorization: Bearer $SOLID_TOKEN\" \\\\\n -H \"Content-Type: text/turtle\" \\\\\n -d '<turtle-content>' \\\\\n \"$POD_BASE_URL<path>\"\n\\`\\`\\`\n\n### 创建容器(目录)\n\\`\\`\\`bash\ncurl -s -X PUT \\\\\n -H \"Authorization: Bearer $SOLID_TOKEN\" \\\\\n -H \"Content-Type: text/turtle\" \\\\\n -H \"Link: <http://www.w3.org/ns/ldp#BasicContainer>; rel=\\\\\"type\\\\\"\" \\\\\n \"$POD_BASE_URL<path>/\"\n\\`\\`\\`\n\n## 语义网规范\n使用 Turtle 格式,优先使用标准词汇表。\n\n### AI 配置示例\n\\`\\`\\`turtle\n@prefix xpod: <http://xpod.dev/ns#> .\n@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n\n<#openai-credential> a xpod:AiCredential ;\n rdfs:label \"OpenAI\" ;\n xpod:provider \"openai\" ;\n xpod:apiKey \"sk-xxx\" ;\n xpod:baseUrl \"https://api.openai.com/v1\" .\n\\`\\`\\`\n\n### 联系人示例\n\\`\\`\\`turtle\n@prefix vcard: <http://www.w3.org/2006/vcard/ns#> .\n\n<#person> a vcard:Individual ;\n vcard:fn \"张三\" ;\n vcard:hasEmail <mailto:zhangsan@example.com> ;\n vcard:hasTelephone <tel:+8613800138000> .\n\\`\\`\\`\n\n## 交互原则\n1. 识别到结构化数据时,直接保存(不需要确认)\n2. 保存成功后简短告知用户\n3. 如果是 AI 配置,提示用户\"已保存,后续对话将使用你的 AI 配置\"\n4. 其他情况正常对话即可\n5. 回复使用中文`;\n\n\nfunction getDefaultBaseUrl(provider?: string): string {\n const normalized = (provider || 'openrouter').toLowerCase();\n const urls: Record<string, string> = {\n openai: 'https://api.openai.com/v1',\n google: 'https://generativelanguage.googleapis.com/v1beta/openai',\n anthropic: 'https://api.anthropic.com/v1',\n deepseek: 'https://api.deepseek.com/v1',\n openrouter: 'https://openrouter.ai/api/v1',\n ollama: 'http://localhost:11434/v1',\n mistral: 'https://api.mistral.ai/v1',\n cohere: 'https://api.cohere.ai/v1',\n zhipu: 'https://open.bigmodel.cn/api/paas/v4',\n };\n return urls[normalized] || urls.openrouter;\n}\n\nfunction normalizeClaudeBaseUrl(baseUrl: string): string {\n if (baseUrl.endsWith('/v1')) {\n return baseUrl.slice(0, -3);\n }\n if (baseUrl.endsWith('/v1/')) {\n return baseUrl.slice(0, -4);\n }\n return baseUrl;\n}\n\nfunction buildClaudeEnv(config: DefaultAgentConfig, context: DefaultAgentContext): NodeJS.ProcessEnv {\n const provider = (config.provider || '').toLowerCase();\n const model = (config.model || '').trim();\n const baseUrl = process.env.DEFAULT_API_BASE || getDefaultBaseUrl(config.provider);\n const isOpenRouterLike = provider === 'openrouter' || baseUrl.includes('openrouter.ai');\n\n const env: NodeJS.ProcessEnv = {\n ...process.env,\n SOLID_TOKEN: context.solidToken,\n POD_BASE_URL: context.podBaseUrl,\n };\n\n if (isOpenRouterLike) {\n // Claude Code expects Anthropic-shaped settings; OpenRouter is compatible after base path normalization.\n env.ANTHROPIC_BASE_URL = normalizeClaudeBaseUrl(baseUrl);\n if (config.apiKey) {\n env.ANTHROPIC_AUTH_TOKEN = config.apiKey;\n }\n if (model) {\n env.ANTHROPIC_DEFAULT_SONNET_MODEL = model;\n env.ANTHROPIC_DEFAULT_HAIKU_MODEL = model;\n env.ANTHROPIC_DEFAULT_OPUS_MODEL = model;\n }\n delete env.ANTHROPIC_API_KEY;\n } else {\n env.ANTHROPIC_BASE_URL = baseUrl;\n if (config.apiKey) {\n env.ANTHROPIC_API_KEY = config.apiKey;\n }\n delete env.ANTHROPIC_AUTH_TOKEN;\n }\n\n return env;\n}\n\nfunction resolveClaudeModel(config: DefaultAgentConfig): string {\n const model = (config.model || '').trim();\n if (!model) {\n return 'sonnet';\n }\n\n if (model.startsWith('claude') || model.includes('anthropic/')) {\n return model;\n }\n\n // Non-Anthropic models (OpenRouter route) are mapped via ANTHROPIC_DEFAULT_SONNET_MODEL.\n return 'sonnet';\n}\n\n/**\n * 运行 Default Agent\n */\nexport async function runDefaultAgent(\n message: string,\n context: DefaultAgentContext,\n options?: {\n timeout?: number;\n maxTurns?: number;\n },\n): Promise<DefaultAgentResponse> {\n const config = getDefaultAgentConfig();\n\n if (!config.apiKey && !process.env.DEFAULT_API_BASE) {\n return {\n content: '',\n success: false,\n error: 'Default Agent not configured: DEFAULT_API_KEY or DEFAULT_API_BASE is required',\n };\n }\n\n const abortController = new AbortController();\n const timeout = options?.timeout || 60000;\n\n const timeoutId = setTimeout(() => {\n logger.warn('Default Agent timeout, aborting...');\n abortController.abort();\n }, timeout);\n\n try {\n logger.info(`Running Default Agent for Pod: ${context.podBaseUrl}`);\n\n const queryFn = await loadClaudeQuery();\n const q = queryFn({\n prompt: message,\n options: {\n abortController,\n pathToClaudeCodeExecutable: config.claudeCodePath,\n env: buildClaudeEnv(config, context),\n systemPrompt: DEFAULT_AGENT_SYSTEM_PROMPT,\n model: resolveClaudeModel(config),\n permissionMode: 'acceptEdits',\n allowedTools: ['Bash', 'Read', 'Write'],\n maxTurns: options?.maxTurns || 10,\n },\n });\n\n let content = '';\n let costUsd: number | undefined;\n\n for await (const msg of q) {\n const assistantText = getAssistantText(msg);\n if (assistantText) {\n content += assistantText;\n }\n\n if (isResultMessage(msg)) {\n if (msg.subtype === 'success' && typeof msg.result === 'string' && msg.result.trim()) {\n content = msg.result;\n }\n if (typeof msg.total_cost_usd === 'number') {\n costUsd = msg.total_cost_usd;\n }\n }\n }\n\n clearTimeout(timeoutId);\n\n return {\n content,\n success: true,\n model: config.model || resolveClaudeModel(config),\n costUsd,\n };\n } catch (error) {\n clearTimeout(timeoutId);\n\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.error(`Default Agent error: ${errorMessage}`);\n\n return {\n content: '',\n success: false,\n error: errorMessage,\n };\n }\n}\n\n/**\n * 流式运行 Default Agent\n */\nexport async function* streamDefaultAgent(\n message: string,\n context: DefaultAgentContext,\n options?: {\n timeout?: number;\n maxTurns?: number;\n },\n): AsyncGenerator<string, void, unknown> {\n const config = getDefaultAgentConfig();\n\n if (!config.apiKey && !process.env.DEFAULT_API_BASE) {\n throw new Error('Default Agent not configured: DEFAULT_API_KEY or DEFAULT_API_BASE is required');\n }\n\n const abortController = new AbortController();\n const timeout = options?.timeout || 60000;\n\n const timeoutId = setTimeout(() => {\n logger.warn('Default Agent timeout, aborting...');\n abortController.abort();\n }, timeout);\n\n try {\n logger.info(`Streaming Default Agent for Pod: ${context.podBaseUrl}`);\n\n const queryFn = await loadClaudeQuery();\n const q = queryFn({\n prompt: message,\n options: {\n abortController,\n pathToClaudeCodeExecutable: config.claudeCodePath,\n env: buildClaudeEnv(config, context),\n systemPrompt: DEFAULT_AGENT_SYSTEM_PROMPT,\n model: resolveClaudeModel(config),\n permissionMode: 'acceptEdits',\n allowedTools: ['Bash', 'Read', 'Write'],\n maxTurns: options?.maxTurns || 10,\n includePartialMessages: true,\n },\n });\n\n for await (const msg of q) {\n const assistantText = getAssistantText(msg);\n if (assistantText) {\n yield assistantText;\n }\n }\n\n clearTimeout(timeoutId);\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n}\n"]}
@@ -36,6 +36,7 @@ export declare class PodChatKitStore implements ChatKitStore<StoreContext> {
36
36
  * 获取认证后的 drizzle 实例 (缓存到 context 中)
37
37
  */
38
38
  private getDb;
39
+ private getClientCredentialsAccessToken;
39
40
  private createAccessTokenFetch;
40
41
  /**
41
42
  * 从 context 获取 webId
@@ -71,6 +72,11 @@ export declare class PodChatKitStore implements ChatKitStore<StoreContext> {
71
72
  * 从 Thread 获取 chatId(提取纯 ID)
72
73
  */
73
74
  private extractChatId;
75
+ private extractThreadId;
76
+ private getPodBaseUrl;
77
+ private buildThreadUri;
78
+ private selectMessagesForThread;
79
+ private deleteMessageRecord;
74
80
  /**
75
81
  * 获取 Thread 的 chatId
76
82
  * 先从缓存获取,如果没有再查询数据库