@undefineds.co/xpod 0.3.6 → 0.3.15

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 (249) hide show
  1. package/config/cli.json +1 -1
  2. package/config/cloud.json +54 -22
  3. package/config/local.json +56 -12
  4. package/config/resolver.json +10 -2
  5. package/config/xpod.base.json +50 -0
  6. package/config/xpod.json +8 -8
  7. package/dist/agents/config/resolve.js +10 -10
  8. package/dist/agents/config/resolve.js.map +1 -1
  9. package/dist/api/chatkit/index.d.ts +1 -1
  10. package/dist/api/chatkit/index.js.map +1 -1
  11. package/dist/api/chatkit/pod-store.d.ts +14 -11
  12. package/dist/api/chatkit/pod-store.js +114 -78
  13. package/dist/api/chatkit/pod-store.js.map +1 -1
  14. package/dist/api/chatkit/runtime/AcpAgentRuntime.js +1 -1
  15. package/dist/api/chatkit/runtime/AcpAgentRuntime.js.map +1 -1
  16. package/dist/api/chatkit/service.js +1 -1
  17. package/dist/api/chatkit/service.js.map +1 -1
  18. package/dist/api/chatkit/types.d.ts +11 -11
  19. package/dist/api/chatkit/types.js +3 -3
  20. package/dist/api/chatkit/types.js.map +1 -1
  21. package/dist/api/container/cloud.js +0 -8
  22. package/dist/api/container/cloud.js.map +1 -1
  23. package/dist/api/container/index.js +2 -1
  24. package/dist/api/container/index.js.map +1 -1
  25. package/dist/api/container/local.js +0 -7
  26. package/dist/api/container/local.js.map +1 -1
  27. package/dist/api/container/routes.js +3 -17
  28. package/dist/api/container/routes.js.map +1 -1
  29. package/dist/api/container/types.d.ts +0 -2
  30. package/dist/api/container/types.js.map +1 -1
  31. package/dist/api/handlers/PodManagementHandler.d.ts +3 -0
  32. package/dist/api/handlers/PodManagementHandler.js +71 -1
  33. package/dist/api/handlers/PodManagementHandler.js.map +1 -1
  34. package/dist/api/handlers/RunHandler.js +5 -5
  35. package/dist/api/handlers/RunHandler.js.map +1 -1
  36. package/dist/api/runs/AgentRuntimeTypes.d.ts +7 -8
  37. package/dist/api/runs/AgentRuntimeTypes.js.map +1 -1
  38. package/dist/api/runs/InngestRunExecutionBackend.d.ts +2 -2
  39. package/dist/api/runs/ManagedRunWorker.d.ts +1 -1
  40. package/dist/api/runs/ManagedRunWorker.js +6 -6
  41. package/dist/api/runs/ManagedRunWorker.js.map +1 -1
  42. package/dist/api/runs/PiAgentRuntimeDriver.d.ts +16 -1
  43. package/dist/api/runs/PiAgentRuntimeDriver.js +182 -23
  44. package/dist/api/runs/PiAgentRuntimeDriver.js.map +1 -1
  45. package/dist/api/runs/RunStateCenter.d.ts +3 -3
  46. package/dist/api/runs/RunStateCenter.js +13 -13
  47. package/dist/api/runs/RunStateCenter.js.map +1 -1
  48. package/dist/api/runs/store.d.ts +4 -4
  49. package/dist/api/runs/store.js +2 -2
  50. package/dist/api/runs/store.js.map +1 -1
  51. package/dist/api/service/VectorStoreService.d.ts +1 -1
  52. package/dist/api/service/VectorStoreService.js +16 -16
  53. package/dist/api/service/VectorStoreService.js.map +1 -1
  54. package/dist/api/tasks/InngestTaskScheduler.d.ts +4 -4
  55. package/dist/api/tasks/TaskMaterializer.d.ts +3 -3
  56. package/dist/api/tasks/TaskMaterializer.js +11 -11
  57. package/dist/api/tasks/TaskMaterializer.js.map +1 -1
  58. package/dist/api/tasks/TaskService.d.ts +3 -3
  59. package/dist/api/tasks/TaskService.js +11 -7
  60. package/dist/api/tasks/TaskService.js.map +1 -1
  61. package/dist/api/tasks/store.d.ts +10 -4
  62. package/dist/api/tasks/store.js +14 -4
  63. package/dist/api/tasks/store.js.map +1 -1
  64. package/dist/api/workspace/types.d.ts +3 -3
  65. package/dist/api/workspace/types.js +6 -6
  66. package/dist/api/workspace/types.js.map +1 -1
  67. package/dist/cli/commands/config.js +2 -2
  68. package/dist/cli/commands/config.js.map +1 -1
  69. package/dist/cli/commands/start.js +9 -3
  70. package/dist/cli/commands/start.js.map +1 -1
  71. package/dist/components/components.jsonld +8 -2
  72. package/dist/components/context.jsonld +308 -51
  73. package/dist/http/search/SearchHttpHandler.js +8 -8
  74. package/dist/http/search/SearchHttpHandler.js.map +1 -1
  75. package/dist/identity/drizzle/PodLookupRepository.d.ts +11 -1
  76. package/dist/identity/drizzle/PodLookupRepository.js +95 -4
  77. package/dist/identity/drizzle/PodLookupRepository.js.map +1 -1
  78. package/dist/identity/drizzle/db.js +4 -43
  79. package/dist/identity/drizzle/db.js.map +1 -1
  80. package/dist/identity/drizzle/schema.pg.d.ts +0 -5
  81. package/dist/identity/drizzle/schema.pg.js +2 -16
  82. package/dist/identity/drizzle/schema.pg.js.map +1 -1
  83. package/dist/identity/drizzle/schema.sqlite.d.ts +19 -176
  84. package/dist/identity/drizzle/schema.sqlite.js +2 -16
  85. package/dist/identity/drizzle/schema.sqlite.js.map +1 -1
  86. package/dist/identity/oidc/AutoDetectIdentityProviderHandler.d.ts +4 -4
  87. package/dist/identity/oidc/AutoDetectIdentityProviderHandler.js +7 -7
  88. package/dist/identity/oidc/AutoDetectIdentityProviderHandler.js.map +1 -1
  89. package/dist/identity/oidc/AutoDetectIdentityProviderHandler.jsonld +6 -6
  90. package/dist/identity/oidc/AutoDetectOidcHandler.d.ts +4 -4
  91. package/dist/identity/oidc/AutoDetectOidcHandler.js +6 -6
  92. package/dist/identity/oidc/AutoDetectOidcHandler.js.map +1 -1
  93. package/dist/identity/oidc/AutoDetectOidcHandler.jsonld +6 -6
  94. package/dist/identity/oidc/ScopedPickWebIdHandler.d.ts +37 -0
  95. package/dist/identity/oidc/ScopedPickWebIdHandler.js +211 -0
  96. package/dist/identity/oidc/ScopedPickWebIdHandler.js.map +1 -0
  97. package/dist/identity/oidc/ScopedPickWebIdHandler.jsonld +158 -0
  98. package/dist/index.d.ts +12 -2
  99. package/dist/index.js +16 -4
  100. package/dist/index.js.map +1 -1
  101. package/dist/main.js +8 -2
  102. package/dist/main.js.map +1 -1
  103. package/dist/provision/ProvisionPodCreator.d.ts +3 -4
  104. package/dist/provision/ProvisionPodCreator.js +8 -13
  105. package/dist/provision/ProvisionPodCreator.js.map +1 -1
  106. package/dist/provision/ProvisionPodCreator.jsonld +7 -7
  107. package/dist/runtime/Proxy.d.ts +0 -1
  108. package/dist/runtime/Proxy.js +0 -9
  109. package/dist/runtime/Proxy.js.map +1 -1
  110. package/dist/runtime/bootstrap.d.ts +1 -0
  111. package/dist/runtime/bootstrap.js +5 -2
  112. package/dist/runtime/bootstrap.js.map +1 -1
  113. package/dist/runtime/css-process.d.ts +12 -4
  114. package/dist/runtime/css-process.js +61 -14
  115. package/dist/runtime/css-process.js.map +1 -1
  116. package/dist/runtime/oidc-issuer.d.ts +3 -2
  117. package/dist/runtime/oidc-issuer.js +3 -2
  118. package/dist/runtime/oidc-issuer.js.map +1 -1
  119. package/dist/runtime/runtime-types.d.ts +1 -0
  120. package/dist/runtime/runtime-types.js.map +1 -1
  121. package/dist/solidfs/LocalFirstRdfRepresentationResolver.d.ts +21 -0
  122. package/dist/solidfs/LocalFirstRdfRepresentationResolver.js +38 -0
  123. package/dist/solidfs/LocalFirstRdfRepresentationResolver.js.map +1 -0
  124. package/dist/solidfs/LocalSolidFS.d.ts +18 -0
  125. package/dist/solidfs/LocalSolidFS.js +539 -0
  126. package/dist/solidfs/LocalSolidFS.js.map +1 -0
  127. package/dist/solidfs/PodSolidFsHttpClient.d.ts +16 -0
  128. package/dist/solidfs/PodSolidFsHttpClient.js +93 -0
  129. package/dist/solidfs/PodSolidFsHttpClient.js.map +1 -0
  130. package/dist/solidfs/PodSolidFsHydrator.d.ts +27 -0
  131. package/dist/solidfs/PodSolidFsHydrator.js +127 -0
  132. package/dist/solidfs/PodSolidFsHydrator.js.map +1 -0
  133. package/dist/solidfs/PodSolidFsSyncer.d.ts +21 -0
  134. package/dist/solidfs/PodSolidFsSyncer.js +78 -0
  135. package/dist/solidfs/PodSolidFsSyncer.js.map +1 -0
  136. package/dist/solidfs/RdfIndexSolidFsSyncer.d.ts +22 -0
  137. package/dist/solidfs/RdfIndexSolidFsSyncer.js +131 -0
  138. package/dist/solidfs/RdfIndexSolidFsSyncer.js.map +1 -0
  139. package/dist/solidfs/index.d.ts +7 -0
  140. package/dist/solidfs/index.js +24 -0
  141. package/dist/solidfs/index.js.map +1 -0
  142. package/dist/solidfs/types.d.ts +131 -0
  143. package/dist/solidfs/types.js +19 -0
  144. package/dist/solidfs/types.js.map +1 -0
  145. package/dist/storage/RepresentationPartialConvertingStore.js +6 -13
  146. package/dist/storage/RepresentationPartialConvertingStore.js.map +1 -1
  147. package/dist/storage/SparqlUpdateResourceStore.d.ts +4 -0
  148. package/dist/storage/SparqlUpdateResourceStore.js +13 -0
  149. package/dist/storage/SparqlUpdateResourceStore.js.map +1 -1
  150. package/dist/storage/SparqlUpdateResourceStore.jsonld +26 -0
  151. package/dist/storage/accessors/MixDataAccessor.d.ts +85 -4
  152. package/dist/storage/accessors/MixDataAccessor.js +511 -16
  153. package/dist/storage/accessors/MixDataAccessor.js.map +1 -1
  154. package/dist/storage/accessors/MixDataAccessor.jsonld +176 -1
  155. package/dist/storage/accessors/QuintStoreSparqlDataAccessor.d.ts +7 -0
  156. package/dist/storage/accessors/QuintStoreSparqlDataAccessor.js +72 -4
  157. package/dist/storage/accessors/QuintStoreSparqlDataAccessor.js.map +1 -1
  158. package/dist/storage/accessors/QuintStoreSparqlDataAccessor.jsonld +24 -0
  159. package/dist/storage/quint/BaseQuintStore.d.ts +3 -0
  160. package/dist/storage/quint/BaseQuintStore.js +51 -27
  161. package/dist/storage/quint/BaseQuintStore.js.map +1 -1
  162. package/dist/storage/quint/PgQuintStore.d.ts +1 -0
  163. package/dist/storage/quint/PgQuintStore.js +50 -32
  164. package/dist/storage/quint/PgQuintStore.js.map +1 -1
  165. package/dist/storage/quint/PgQuintStore.jsonld +4 -3
  166. package/dist/storage/quint/SqliteQuintStore.d.ts +5 -0
  167. package/dist/storage/quint/SqliteQuintStore.js +100 -0
  168. package/dist/storage/quint/SqliteQuintStore.js.map +1 -1
  169. package/dist/storage/quint/SqliteQuintStore.jsonld +20 -0
  170. package/dist/storage/quint/types.d.ts +16 -0
  171. package/dist/storage/quint/types.js.map +1 -1
  172. package/dist/storage/rdf/Rdf3xTripleIndex.d.ts +55 -0
  173. package/dist/storage/rdf/Rdf3xTripleIndex.js +1235 -0
  174. package/dist/storage/rdf/Rdf3xTripleIndex.js.map +1 -0
  175. package/dist/storage/rdf/RdfContentTypes.d.ts +9 -0
  176. package/dist/storage/rdf/RdfContentTypes.js +79 -0
  177. package/dist/storage/rdf/RdfContentTypes.js.map +1 -0
  178. package/dist/storage/rdf/RdfLocalQueryEngine.d.ts +79 -0
  179. package/dist/storage/rdf/RdfLocalQueryEngine.js +2705 -0
  180. package/dist/storage/rdf/RdfLocalQueryEngine.js.map +1 -0
  181. package/dist/storage/rdf/RdfQuadIndex.d.ts +98 -0
  182. package/dist/storage/rdf/RdfQuadIndex.js +1840 -0
  183. package/dist/storage/rdf/RdfQuadIndex.js.map +1 -0
  184. package/dist/storage/rdf/RdfQuadIndex.jsonld +416 -0
  185. package/dist/storage/rdf/RdfShadowComparator.d.ts +12 -0
  186. package/dist/storage/rdf/RdfShadowComparator.js +47 -0
  187. package/dist/storage/rdf/RdfShadowComparator.js.map +1 -0
  188. package/dist/storage/rdf/RdfSparqlAdapter.d.ts +147 -0
  189. package/dist/storage/rdf/RdfSparqlAdapter.js +2420 -0
  190. package/dist/storage/rdf/RdfSparqlAdapter.js.map +1 -0
  191. package/dist/storage/rdf/RdfSparqlAdapter.jsonld +414 -0
  192. package/dist/storage/rdf/RdfTermDictionary.d.ts +27 -0
  193. package/dist/storage/rdf/RdfTermDictionary.js +352 -0
  194. package/dist/storage/rdf/RdfTermDictionary.js.map +1 -0
  195. package/dist/storage/rdf/RdfTermDictionary.jsonld +114 -0
  196. package/dist/storage/rdf/RdfTermSemantics.d.ts +6 -0
  197. package/dist/storage/rdf/RdfTermSemantics.js +40 -0
  198. package/dist/storage/rdf/RdfTermSemantics.js.map +1 -0
  199. package/dist/storage/rdf/RdfTextIndex.d.ts +23 -0
  200. package/dist/storage/rdf/RdfTextIndex.js +569 -0
  201. package/dist/storage/rdf/RdfTextIndex.js.map +1 -0
  202. package/dist/storage/rdf/RdfVectorIndex.d.ts +22 -0
  203. package/dist/storage/rdf/RdfVectorIndex.js +631 -0
  204. package/dist/storage/rdf/RdfVectorIndex.js.map +1 -0
  205. package/dist/storage/rdf/RdfXmlSerializer.d.ts +2 -0
  206. package/dist/storage/rdf/RdfXmlSerializer.js +123 -0
  207. package/dist/storage/rdf/RdfXmlSerializer.js.map +1 -0
  208. package/dist/storage/rdf/ShadowRdfQuintStore.d.ts +58 -0
  209. package/dist/storage/rdf/ShadowRdfQuintStore.js +202 -0
  210. package/dist/storage/rdf/ShadowRdfQuintStore.js.map +1 -0
  211. package/dist/storage/rdf/ShadowRdfQuintStore.jsonld +308 -0
  212. package/dist/storage/rdf/SolidRdfEngine.d.ts +56 -0
  213. package/dist/storage/rdf/SolidRdfEngine.js +292 -0
  214. package/dist/storage/rdf/SolidRdfEngine.js.map +1 -0
  215. package/dist/storage/rdf/SolidRdfEngine.jsonld +372 -0
  216. package/dist/storage/rdf/SolidRdfSparqlEngine.d.ts +92 -0
  217. package/dist/storage/rdf/SolidRdfSparqlEngine.js +477 -0
  218. package/dist/storage/rdf/SolidRdfSparqlEngine.js.map +1 -0
  219. package/dist/storage/rdf/SolidRdfSparqlEngine.jsonld +257 -0
  220. package/dist/storage/rdf/index.d.ts +15 -0
  221. package/dist/storage/rdf/index.js +61 -0
  222. package/dist/storage/rdf/index.js.map +1 -0
  223. package/dist/storage/rdf/models-benchmark.d.ts +260 -0
  224. package/dist/storage/rdf/models-benchmark.js +1405 -0
  225. package/dist/storage/rdf/models-benchmark.js.map +1 -0
  226. package/dist/storage/rdf/types.d.ts +726 -0
  227. package/dist/storage/rdf/types.js +3 -0
  228. package/dist/storage/rdf/types.js.map +1 -0
  229. package/dist/storage/rdf/types.jsonld +316 -0
  230. package/dist/storage/vector/VectorIndexingListener.d.ts +5 -5
  231. package/dist/storage/vector/VectorIndexingListener.js +19 -19
  232. package/dist/storage/vector/VectorIndexingListener.js.map +1 -1
  233. package/package.json +3 -2
  234. package/templates/pod/acp/.acr.hbs +39 -0
  235. package/templates/pod/acp/README.acr +18 -0
  236. package/templates/pod/acp/profile/card.acr +22 -0
  237. package/templates/pod/base/README$.md.hbs +27 -0
  238. package/templates/pod/base/profile/card$.ttl.hbs +13 -0
  239. package/templates/pod/wac/.acl.hbs +26 -0
  240. package/templates/pod/wac/README.acl.hbs +14 -0
  241. package/templates/pod/wac/profile/card.acl.hbs +19 -0
  242. package/dist/api/handlers/WebIdProfileHandler.d.ts +0 -16
  243. package/dist/api/handlers/WebIdProfileHandler.js +0 -423
  244. package/dist/api/handlers/WebIdProfileHandler.js.map +0 -1
  245. package/dist/identity/drizzle/WebIdProfileRepository.d.ts +0 -63
  246. package/dist/identity/drizzle/WebIdProfileRepository.js +0 -168
  247. package/dist/identity/drizzle/WebIdProfileRepository.js.map +0 -1
  248. package/dist/identity/drizzle/WebIdProfileRepository.jsonld +0 -112
  249. package/dist/storage/quint/BaseQuintStore.jsonld +0 -257
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/api/chatkit/types.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ChatKit Types\n * \n * Type definitions for OpenAI ChatKit protocol.\n * Based on https://github.com/openai/chatkit-python\n */\n\nimport type { WorkspaceUri } from '../workspace/types';\n\n// ============================================================================\n// Generic Types\n// ============================================================================\n\nexport interface Page<T> {\n data: T[];\n has_more: boolean;\n after?: string;\n}\n\n// ============================================================================\n// Thread Types\n// ============================================================================\n\nexport type ThreadStatusType = 'active' | 'locked' | 'closed';\n\nexport interface ActiveStatus {\n type: 'active';\n}\n\nexport interface LockedStatus {\n type: 'locked';\n reason?: string;\n}\n\nexport interface ClosedStatus {\n type: 'closed';\n}\n\nexport type ThreadStatus = ActiveStatus | LockedStatus | ClosedStatus;\n\nexport interface ThreadMetadata {\n id: string;\n title?: string;\n status: ThreadStatus;\n /**\n * Workspace Container URI selected for this thread.\n * The Solid schema stores this as an RDF URI relation.\n */\n workspace?: WorkspaceUri;\n created_at: number;\n updated_at: number;\n metadata?: Record<string, unknown>;\n}\n\nexport interface Thread extends ThreadMetadata {\n items: Page<ThreadItem>;\n}\n\nexport const DEFAULT_THREAD_CHAT_ID = 'default';\n\nexport type HttpIri = `http://${string}` | `https://${string}`;\n\nexport interface ThreadSurfaceRef {\n thread_id: string;\n chat_id: string;\n}\n\nexport interface ThreadIriRef {\n thread_id: HttpIri;\n chat_id?: never;\n}\n\nexport type ThreadRef = ThreadSurfaceRef | ThreadIriRef;\n\nexport function isHttpIri(value: string): value is HttpIri {\n return value.startsWith('http://') || value.startsWith('https://');\n}\n\nexport function isBaseRelativeThreadResourceId(value: string): boolean {\n return /^(chat|task)\\/[^/]+\\/index\\.ttl#[^#]+$/.test(value);\n}\n\nexport function toThreadRef(params: { thread_id: string; chat_id?: string }): ThreadRef {\n if (isHttpIri(params.thread_id)) {\n return { thread_id: params.thread_id };\n }\n if (isBaseRelativeThreadResourceId(params.thread_id)) {\n return { thread_id: params.thread_id, chat_id: params.chat_id ?? DEFAULT_THREAD_CHAT_ID };\n }\n if (params.chat_id) {\n return { thread_id: params.thread_id, chat_id: params.chat_id };\n }\n throw new Error(`chat_id is required when thread_id \"${params.thread_id}\" is not a full thread resource id`);\n}\n\nexport function getThreadIdFromRef(thread: ThreadRef): string {\n if ('chat_id' in thread || isBaseRelativeThreadResourceId(thread.thread_id)) {\n return thread.thread_id;\n }\n try {\n const url = new URL(thread.thread_id);\n const dataIndex = url.pathname.indexOf('/.data/');\n if (dataIndex >= 0 && url.hash) {\n return `${url.pathname.slice(dataIndex + '/.data/'.length)}${url.hash}`;\n }\n return url.hash.startsWith('#') ? decodeURIComponent(url.hash.slice(1)) : thread.thread_id;\n } catch {\n return thread.thread_id;\n }\n}\n\nexport function getChatIdFromThreadMetadata(thread: ThreadMetadata): string {\n const chatId = thread.metadata?.chat_id;\n return typeof chatId === 'string' && chatId.length > 0\n ? chatId\n : DEFAULT_THREAD_CHAT_ID;\n}\n\n// ============================================================================\n// Thread Item Types\n// ============================================================================\n\nexport interface ThreadItemBase {\n id: string;\n thread_id: string;\n created_at: number;\n}\n\n// User Message\nexport interface UserMessageTextContent {\n type: 'input_text';\n text: string;\n}\n\nexport interface UserMessageTagContent {\n type: 'input_tag';\n tag: string;\n label?: string;\n}\n\nexport type UserMessageContent = UserMessageTextContent | UserMessageTagContent;\n\nexport interface InferenceOptions {\n model?: string;\n temperature?: number;\n max_tokens?: number;\n tools?: unknown[];\n tool_choice?: ToolChoice;\n}\n\nexport interface ToolChoice {\n type: 'function';\n function: {\n name: string;\n };\n}\n\nexport interface UserMessageItem extends ThreadItemBase {\n type: 'user_message';\n content: UserMessageContent[];\n inference_options?: InferenceOptions;\n}\n\n// Assistant Message\nexport interface Annotation {\n type: string;\n text: string;\n start_index?: number;\n end_index?: number;\n file_citation?: {\n file_id: string;\n quote?: string;\n };\n file_path?: {\n file_id: string;\n };\n url_citation?: {\n url: string;\n title?: string;\n };\n}\n\nexport interface AssistantMessageContent {\n type: 'output_text';\n text: string;\n annotations?: Annotation[];\n}\n\nexport interface AssistantMessageItem extends ThreadItemBase {\n type: 'assistant_message';\n content: AssistantMessageContent[];\n status?: 'in_progress' | 'completed' | 'incomplete';\n}\n\n// Client Tool Call\nexport interface ClientToolCallItem extends ThreadItemBase {\n type: 'client_tool_call';\n name: string;\n arguments: string;\n call_id: string;\n status?: 'pending' | 'completed';\n output?: string;\n metadata?: Record<string, unknown>;\n}\n\n// Widget\nexport interface WidgetItem extends ThreadItemBase {\n type: 'widget';\n widget_type: string;\n data: unknown;\n}\n\n// Generated Image\nexport interface GeneratedImage {\n id: string;\n url?: string;\n b64_json?: string;\n}\n\nexport interface GeneratedImageItem extends ThreadItemBase {\n type: 'generated_image';\n image: GeneratedImage;\n prompt?: string;\n status?: 'in_progress' | 'completed' | 'failed';\n}\n\n// Task\nexport interface BaseTask {\n id: string;\n status: 'pending' | 'in_progress' | 'completed' | 'failed';\n}\n\nexport interface CustomTask extends BaseTask {\n type: 'custom';\n title: string;\n description?: string;\n}\n\nexport interface SearchTask extends BaseTask {\n type: 'web_search';\n query: string;\n}\n\nexport interface ThoughtTask extends BaseTask {\n type: 'thought';\n content: string;\n}\n\nexport interface FileTask extends BaseTask {\n type: 'file';\n file_id: string;\n filename?: string;\n}\n\nexport interface ImageTask extends BaseTask {\n type: 'image';\n image_id: string;\n}\n\nexport type Task = CustomTask | SearchTask | ThoughtTask | FileTask | ImageTask;\n\nexport interface TaskItem extends ThreadItemBase {\n type: 'task';\n task: Task;\n}\n\n// Workflow\nexport interface CustomSummary {\n type: 'custom';\n title: string;\n icon?: string;\n}\n\nexport interface DurationSummary {\n type: 'duration';\n duration_ms: number;\n}\n\nexport type WorkflowSummary = CustomSummary | DurationSummary;\n\nexport interface Workflow {\n tasks: Task[];\n summary?: WorkflowSummary;\n}\n\nexport interface WorkflowItem extends ThreadItemBase {\n type: 'workflow';\n workflow: Workflow;\n}\n\n// End of Turn\nexport interface EndOfTurnItem extends ThreadItemBase {\n type: 'end_of_turn';\n}\n\n// Hidden Context\nexport interface HiddenContextItem extends ThreadItemBase {\n type: 'hidden_context_item';\n context: unknown;\n}\n\nexport interface SDKHiddenContextItem extends ThreadItemBase {\n type: 'sdk_hidden_context';\n data: unknown;\n}\n\n// Union of all thread items\nexport type ThreadItem =\n | UserMessageItem\n | AssistantMessageItem\n | ClientToolCallItem\n | WidgetItem\n | GeneratedImageItem\n | TaskItem\n | WorkflowItem\n | EndOfTurnItem\n | HiddenContextItem\n | SDKHiddenContextItem;\n\nexport type StoreItemType = ThreadItem['type'];\n\n// ============================================================================\n// Attachment Types\n// ============================================================================\n\nexport interface AttachmentBase {\n id: string;\n name: string;\n size: number;\n mime_type: string;\n created_at: number;\n}\n\nexport interface FileAttachment extends AttachmentBase {\n type: 'file';\n url?: string;\n}\n\nexport interface ImageAttachment extends AttachmentBase {\n type: 'image';\n url?: string;\n width?: number;\n height?: number;\n}\n\nexport type Attachment = FileAttachment | ImageAttachment;\n\nexport interface AttachmentUploadDescriptor {\n attachment_id: string;\n upload_url: string;\n upload_headers?: Record<string, string>;\n}\n\n// ============================================================================\n// Request Types\n// ============================================================================\n\nexport interface BaseReq {\n metadata?: Record<string, unknown>;\n}\n\n// Thread Requests\nexport type ThreadGetByIdParams = ThreadRef;\n\nexport interface ThreadsGetByIdReq extends BaseReq {\n type: 'threads.get_by_id';\n params: ThreadGetByIdParams;\n}\n\nexport interface ThreadCreateParams {\n chat_id?: string;\n workspace?: WorkspaceUri;\n input?: UserMessageInput;\n}\n\nexport interface UserMessageInput {\n content: UserMessageContent[];\n inference_options?: InferenceOptions;\n attachments?: string[];\n}\n\nexport interface ThreadsCreateReq extends BaseReq {\n type: 'threads.create';\n params: ThreadCreateParams;\n}\n\nexport interface ThreadListParams {\n limit?: number;\n order?: 'asc' | 'desc';\n after?: string;\n}\n\nexport interface ThreadsListReq extends BaseReq {\n type: 'threads.list';\n params: ThreadListParams;\n}\n\nexport type ThreadAddUserMessageParams = ThreadRef & {\n input: UserMessageInput;\n};\n\nexport interface ThreadsAddUserMessageReq extends BaseReq {\n type: 'threads.add_user_message';\n params: ThreadAddUserMessageParams;\n}\n\nexport type ThreadAddClientToolOutputParams = ThreadRef & {\n item_id: string;\n output: string;\n};\n\nexport interface ThreadsAddClientToolOutputReq extends BaseReq {\n type: 'threads.add_client_tool_output';\n params: ThreadAddClientToolOutputParams;\n}\n\nexport type ThreadCustomActionParams = ThreadRef & {\n item_id: string;\n action: string;\n data?: unknown;\n};\n\nexport interface ThreadsCustomActionReq extends BaseReq {\n type: 'threads.custom_action';\n params: ThreadCustomActionParams;\n}\n\nexport type ThreadRetryAfterItemParams = ThreadRef & {\n item_id: string;\n};\n\nexport interface ThreadsRetryAfterItemReq extends BaseReq {\n type: 'threads.retry_after_item';\n params: ThreadRetryAfterItemParams;\n}\n\nexport type ThreadUpdateParams = ThreadRef & {\n title?: string;\n workspace?: WorkspaceUri;\n};\n\nexport interface ThreadsUpdateReq extends BaseReq {\n type: 'threads.update';\n params: ThreadUpdateParams;\n}\n\nexport type ThreadDeleteParams = ThreadRef;\n\nexport interface ThreadsDeleteReq extends BaseReq {\n type: 'threads.delete';\n params: ThreadDeleteParams;\n}\n\n// Items Requests\nexport type ItemsListParams = ThreadRef & {\n limit?: number;\n order?: 'asc' | 'desc';\n after?: string;\n};\n\nexport interface ItemsListReq extends BaseReq {\n type: 'items.list';\n params: ItemsListParams;\n}\n\nexport type ItemFeedbackParams = ThreadRef & {\n item_ids: string[];\n feedback: FeedbackKind;\n};\n\nexport type FeedbackKind = 'positive' | 'negative';\n\nexport interface ItemsFeedbackReq extends BaseReq {\n type: 'items.feedback';\n params: ItemFeedbackParams;\n}\n\n// Attachment Requests\nexport interface AttachmentCreateParams {\n name: string;\n size: number;\n mime_type: string;\n}\n\nexport interface AttachmentsCreateReq extends BaseReq {\n type: 'attachments.create';\n params: AttachmentCreateParams;\n}\n\nexport interface AttachmentDeleteParams {\n attachment_id: string;\n}\n\nexport interface AttachmentsDeleteReq extends BaseReq {\n type: 'attachments.delete';\n params: AttachmentDeleteParams;\n}\n\n// Request Union Types\nexport type StreamingReq =\n | ThreadsCreateReq\n | ThreadsAddUserMessageReq\n | ThreadsAddClientToolOutputReq\n | ThreadsRetryAfterItemReq\n | ThreadsCustomActionReq;\n\nexport type NonStreamingReq =\n | ThreadsGetByIdReq\n | ThreadsListReq\n | ItemsListReq\n | ItemsFeedbackReq\n | AttachmentsCreateReq\n | AttachmentsDeleteReq\n | ThreadsUpdateReq\n | ThreadsDeleteReq;\n\nexport type ChatKitReq = StreamingReq | NonStreamingReq;\n\n// ============================================================================\n// Stream Event Types\n// ============================================================================\n\nexport interface ThreadCreatedEvent {\n type: 'thread.created';\n thread: ThreadMetadata;\n}\n\nexport interface ThreadUpdatedEvent {\n type: 'thread.updated';\n thread: ThreadMetadata;\n}\n\nexport interface ThreadItemAddedEvent {\n type: 'thread.item.added';\n item: ThreadItem;\n}\n\nexport interface ThreadItemUpdatedEvent {\n type: 'thread.item.updated';\n item_id: string;\n update: ThreadItemUpdate;\n}\n\nexport interface ThreadItemDoneEvent {\n type: 'thread.item.done';\n item: ThreadItem;\n}\n\nexport interface ThreadItemRemovedEvent {\n type: 'thread.item.removed';\n item_id: string;\n}\n\nexport interface ThreadItemReplacedEvent {\n type: 'thread.item.replaced';\n item: ThreadItem;\n}\n\nexport interface StreamOptions {\n allow_cancel?: boolean;\n}\n\nexport interface StreamOptionsEvent {\n type: 'stream_options';\n options: StreamOptions;\n}\n\nexport interface ProgressUpdate {\n progress: number;\n message?: string;\n}\n\nexport interface ProgressUpdateEvent {\n type: 'progress_update';\n update: ProgressUpdate;\n}\n\nexport interface ClientEffect {\n effect_type: string;\n data?: unknown;\n}\n\nexport interface ClientEffectEvent {\n type: 'client_effect';\n effect: ClientEffect;\n}\n\nexport interface ErrorEvent {\n type: 'error';\n error: {\n code: string;\n message: string;\n details?: unknown;\n };\n}\n\nexport interface NoticeEvent {\n type: 'notice';\n notice: {\n level: 'info' | 'warning' | 'error';\n message: string;\n };\n}\n\nexport type ThreadStreamEvent =\n | ThreadCreatedEvent\n | ThreadUpdatedEvent\n | ThreadItemAddedEvent\n | ThreadItemUpdatedEvent\n | ThreadItemDoneEvent\n | ThreadItemRemovedEvent\n | ThreadItemReplacedEvent\n | StreamOptionsEvent\n | ProgressUpdateEvent\n | ClientEffectEvent\n | ErrorEvent\n | NoticeEvent;\n\n// ============================================================================\n// Thread Item Update Types (for streaming)\n// ============================================================================\n\nexport interface AssistantMessageContentPartAdded {\n type: 'assistant_message.content_part.added';\n part_index: number;\n part: AssistantMessageContent;\n}\n\nexport interface AssistantMessageContentPartTextDelta {\n type: 'assistant_message.content_part.text_delta';\n part_index: number;\n delta: string;\n}\n\nexport interface AssistantMessageContentPartAnnotationAdded {\n type: 'assistant_message.content_part.annotation_added';\n part_index: number;\n annotation: Annotation;\n}\n\nexport interface AssistantMessageContentPartDone {\n type: 'assistant_message.content_part.done';\n part_index: number;\n}\n\nexport interface WidgetStreamingTextValueDelta {\n type: 'widget.streaming_text.value_delta';\n path: string;\n delta: string;\n}\n\nexport interface WidgetRootUpdated {\n type: 'widget.root.updated';\n data: unknown;\n}\n\nexport interface WidgetComponentUpdated {\n type: 'widget.component.updated';\n component_id: string;\n data: unknown;\n}\n\nexport interface WorkflowTaskAdded {\n type: 'workflow.task.added';\n task: Task;\n}\n\nexport interface WorkflowTaskUpdated {\n type: 'workflow.task.updated';\n task_id: string;\n task: Partial<Task>;\n}\n\nexport interface GeneratedImageUpdated {\n type: 'generated_image.updated';\n image: GeneratedImage;\n}\n\nexport type ThreadItemUpdate =\n | AssistantMessageContentPartAdded\n | AssistantMessageContentPartTextDelta\n | AssistantMessageContentPartAnnotationAdded\n | AssistantMessageContentPartDone\n | WidgetStreamingTextValueDelta\n | WidgetRootUpdated\n | WidgetComponentUpdated\n | WorkflowTaskAdded\n | WorkflowTaskUpdated\n | GeneratedImageUpdated;\n\n// ============================================================================\n// Response Types\n// ============================================================================\n\nexport interface StreamingResult {\n type: 'streaming';\n stream: AsyncIterable<ThreadStreamEvent>;\n}\n\nexport interface NonStreamingResult {\n type: 'non_streaming';\n data: unknown;\n}\n\nexport type ChatKitResult = StreamingResult | NonStreamingResult;\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\nexport function isStreamingReq(req: ChatKitReq): req is StreamingReq {\n return (\n req.type === 'threads.create' ||\n req.type === 'threads.add_user_message' ||\n req.type === 'threads.add_client_tool_output' ||\n req.type === 'threads.retry_after_item' ||\n req.type === 'threads.custom_action'\n );\n}\n\nexport function isNonStreamingReq(req: ChatKitReq): req is NonStreamingReq {\n return !isStreamingReq(req);\n}\n\n/**\n * Generate a unique ID with prefix\n */\nexport function generateId(prefix: string): string {\n const timestamp = Date.now().toString(36);\n const random = Math.random().toString(36).substring(2, 10);\n return `${prefix}_${timestamp}${random}`;\n}\n\n/**\n * Get current timestamp in seconds\n */\nexport function nowTimestamp(): number {\n return Math.floor(Date.now() / 1000);\n}\n\n/**\n * Extract text content from user message\n */\nexport function extractUserMessageText(content: UserMessageContent[]): string {\n return content\n .filter((c): c is UserMessageTextContent => c.type === 'input_text')\n .map((c) => c.text)\n .join('\\n');\n}\n\n/**\n * Extract text content from assistant message\n */\nexport function extractAssistantMessageText(content: AssistantMessageContent[]): string {\n return content\n .filter((c): c is AssistantMessageContent => c.type === 'output_text')\n .map((c) => c.text)\n .join('\\n');\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/api/chatkit/types.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ChatKit Types\n * \n * Type definitions for OpenAI ChatKit protocol.\n * Based on https://github.com/openai/chatkit-python\n */\n\nimport type { WorkspaceRef } from '../workspace/types';\n\n// ============================================================================\n// Generic Types\n// ============================================================================\n\nexport interface Page<T> {\n data: T[];\n has_more: boolean;\n after?: string;\n}\n\n// ============================================================================\n// Thread Types\n// ============================================================================\n\nexport type ThreadStatusType = 'active' | 'locked' | 'closed';\n\nexport interface ActiveStatus {\n type: 'active';\n}\n\nexport interface LockedStatus {\n type: 'locked';\n reason?: string;\n}\n\nexport interface ClosedStatus {\n type: 'closed';\n}\n\nexport type ThreadStatus = ActiveStatus | LockedStatus | ClosedStatus;\n\nexport interface ThreadMetadata {\n id: string;\n title?: string;\n status: ThreadStatus;\n /**\n * Workspace Container selected for this thread.\n * The Solid schema stores this as the `workspace` RDF relation.\n */\n workspace?: WorkspaceRef;\n created_at: number;\n updated_at: number;\n metadata?: Record<string, unknown>;\n}\n\nexport interface Thread extends ThreadMetadata {\n items: Page<ThreadItem>;\n}\n\nexport const DEFAULT_THREAD_CHAT_ID = 'default';\n\nexport type HttpResource = `http://${string}` | `https://${string}`;\n\nexport interface ThreadSurfaceRef {\n thread_id: string;\n chat_id: string;\n}\n\nexport interface ThreadResourceRef {\n thread_id: HttpResource;\n chat_id?: never;\n}\n\nexport type ThreadRef = ThreadSurfaceRef | ThreadResourceRef;\n\nexport function isHttpResource(value: string): value is HttpResource {\n return value.startsWith('http://') || value.startsWith('https://');\n}\n\nexport function isBaseRelativeThreadResourceId(value: string): boolean {\n return /^(chat|task)\\/[^/]+\\/index\\.ttl#[^#]+$/.test(value);\n}\n\nexport function toThreadRef(params: { thread_id: string; chat_id?: string }): ThreadRef {\n if (isHttpResource(params.thread_id)) {\n return { thread_id: params.thread_id };\n }\n if (isBaseRelativeThreadResourceId(params.thread_id)) {\n return { thread_id: params.thread_id, chat_id: params.chat_id ?? DEFAULT_THREAD_CHAT_ID };\n }\n if (params.chat_id) {\n return { thread_id: params.thread_id, chat_id: params.chat_id };\n }\n throw new Error(`chat_id is required when thread_id \"${params.thread_id}\" is not a full thread resource id`);\n}\n\nexport function getThreadIdFromRef(thread: ThreadRef): string {\n if ('chat_id' in thread || isBaseRelativeThreadResourceId(thread.thread_id)) {\n return thread.thread_id;\n }\n try {\n const url = new URL(thread.thread_id);\n const dataIndex = url.pathname.indexOf('/.data/');\n if (dataIndex >= 0 && url.hash) {\n return `${url.pathname.slice(dataIndex + '/.data/'.length)}${url.hash}`;\n }\n return url.hash.startsWith('#') ? decodeURIComponent(url.hash.slice(1)) : thread.thread_id;\n } catch {\n return thread.thread_id;\n }\n}\n\nexport function getChatIdFromThreadMetadata(thread: ThreadMetadata): string {\n const chatId = thread.metadata?.chat_id;\n return typeof chatId === 'string' && chatId.length > 0\n ? chatId\n : DEFAULT_THREAD_CHAT_ID;\n}\n\n// ============================================================================\n// Thread Item Types\n// ============================================================================\n\nexport interface ThreadItemBase {\n id: string;\n thread_id: string;\n created_at: number;\n}\n\n// User Message\nexport interface UserMessageTextContent {\n type: 'input_text';\n text: string;\n}\n\nexport interface UserMessageTagContent {\n type: 'input_tag';\n tag: string;\n label?: string;\n}\n\nexport type UserMessageContent = UserMessageTextContent | UserMessageTagContent;\n\nexport interface InferenceOptions {\n model?: string;\n temperature?: number;\n max_tokens?: number;\n tools?: unknown[];\n tool_choice?: ToolChoice;\n}\n\nexport interface ToolChoice {\n type: 'function';\n function: {\n name: string;\n };\n}\n\nexport interface UserMessageItem extends ThreadItemBase {\n type: 'user_message';\n content: UserMessageContent[];\n inference_options?: InferenceOptions;\n}\n\n// Assistant Message\nexport interface Annotation {\n type: string;\n text: string;\n start_index?: number;\n end_index?: number;\n file_citation?: {\n file_id: string;\n quote?: string;\n };\n file_path?: {\n file_id: string;\n };\n url_citation?: {\n url: string;\n title?: string;\n };\n}\n\nexport interface AssistantMessageContent {\n type: 'output_text';\n text: string;\n annotations?: Annotation[];\n}\n\nexport interface AssistantMessageItem extends ThreadItemBase {\n type: 'assistant_message';\n content: AssistantMessageContent[];\n status?: 'in_progress' | 'completed' | 'incomplete';\n}\n\n// Client Tool Call\nexport interface ClientToolCallItem extends ThreadItemBase {\n type: 'client_tool_call';\n name: string;\n arguments: string;\n call_id: string;\n status?: 'pending' | 'completed';\n output?: string;\n metadata?: Record<string, unknown>;\n}\n\n// Widget\nexport interface WidgetItem extends ThreadItemBase {\n type: 'widget';\n widget_type: string;\n data: unknown;\n}\n\n// Generated Image\nexport interface GeneratedImage {\n id: string;\n url?: string;\n b64_json?: string;\n}\n\nexport interface GeneratedImageItem extends ThreadItemBase {\n type: 'generated_image';\n image: GeneratedImage;\n prompt?: string;\n status?: 'in_progress' | 'completed' | 'failed';\n}\n\n// Task\nexport interface BaseTask {\n id: string;\n status: 'pending' | 'in_progress' | 'completed' | 'failed';\n}\n\nexport interface CustomTask extends BaseTask {\n type: 'custom';\n title: string;\n description?: string;\n}\n\nexport interface SearchTask extends BaseTask {\n type: 'web_search';\n query: string;\n}\n\nexport interface ThoughtTask extends BaseTask {\n type: 'thought';\n content: string;\n}\n\nexport interface FileTask extends BaseTask {\n type: 'file';\n file_id: string;\n filename?: string;\n}\n\nexport interface ImageTask extends BaseTask {\n type: 'image';\n image_id: string;\n}\n\nexport type Task = CustomTask | SearchTask | ThoughtTask | FileTask | ImageTask;\n\nexport interface TaskItem extends ThreadItemBase {\n type: 'task';\n task: Task;\n}\n\n// Workflow\nexport interface CustomSummary {\n type: 'custom';\n title: string;\n icon?: string;\n}\n\nexport interface DurationSummary {\n type: 'duration';\n duration_ms: number;\n}\n\nexport type WorkflowSummary = CustomSummary | DurationSummary;\n\nexport interface Workflow {\n tasks: Task[];\n summary?: WorkflowSummary;\n}\n\nexport interface WorkflowItem extends ThreadItemBase {\n type: 'workflow';\n workflow: Workflow;\n}\n\n// End of Turn\nexport interface EndOfTurnItem extends ThreadItemBase {\n type: 'end_of_turn';\n}\n\n// Hidden Context\nexport interface HiddenContextItem extends ThreadItemBase {\n type: 'hidden_context_item';\n context: unknown;\n}\n\nexport interface SDKHiddenContextItem extends ThreadItemBase {\n type: 'sdk_hidden_context';\n data: unknown;\n}\n\n// Union of all thread items\nexport type ThreadItem =\n | UserMessageItem\n | AssistantMessageItem\n | ClientToolCallItem\n | WidgetItem\n | GeneratedImageItem\n | TaskItem\n | WorkflowItem\n | EndOfTurnItem\n | HiddenContextItem\n | SDKHiddenContextItem;\n\nexport type StoreItemType = ThreadItem['type'];\n\n// ============================================================================\n// Attachment Types\n// ============================================================================\n\nexport interface AttachmentBase {\n id: string;\n name: string;\n size: number;\n mime_type: string;\n created_at: number;\n}\n\nexport interface FileAttachment extends AttachmentBase {\n type: 'file';\n url?: string;\n}\n\nexport interface ImageAttachment extends AttachmentBase {\n type: 'image';\n url?: string;\n width?: number;\n height?: number;\n}\n\nexport type Attachment = FileAttachment | ImageAttachment;\n\nexport interface AttachmentUploadDescriptor {\n attachment_id: string;\n upload_url: string;\n upload_headers?: Record<string, string>;\n}\n\n// ============================================================================\n// Request Types\n// ============================================================================\n\nexport interface BaseReq {\n metadata?: Record<string, unknown>;\n}\n\n// Thread Requests\nexport type ThreadGetByIdParams = ThreadRef;\n\nexport interface ThreadsGetByIdReq extends BaseReq {\n type: 'threads.get_by_id';\n params: ThreadGetByIdParams;\n}\n\nexport interface ThreadCreateParams {\n chat_id?: string;\n workspace?: WorkspaceRef;\n input?: UserMessageInput;\n}\n\nexport interface UserMessageInput {\n content: UserMessageContent[];\n inference_options?: InferenceOptions;\n attachments?: string[];\n}\n\nexport interface ThreadsCreateReq extends BaseReq {\n type: 'threads.create';\n params: ThreadCreateParams;\n}\n\nexport interface ThreadListParams {\n limit?: number;\n order?: 'asc' | 'desc';\n after?: string;\n}\n\nexport interface ThreadsListReq extends BaseReq {\n type: 'threads.list';\n params: ThreadListParams;\n}\n\nexport type ThreadAddUserMessageParams = ThreadRef & {\n input: UserMessageInput;\n};\n\nexport interface ThreadsAddUserMessageReq extends BaseReq {\n type: 'threads.add_user_message';\n params: ThreadAddUserMessageParams;\n}\n\nexport type ThreadAddClientToolOutputParams = ThreadRef & {\n item_id: string;\n output: string;\n};\n\nexport interface ThreadsAddClientToolOutputReq extends BaseReq {\n type: 'threads.add_client_tool_output';\n params: ThreadAddClientToolOutputParams;\n}\n\nexport type ThreadCustomActionParams = ThreadRef & {\n item_id: string;\n action: string;\n data?: unknown;\n};\n\nexport interface ThreadsCustomActionReq extends BaseReq {\n type: 'threads.custom_action';\n params: ThreadCustomActionParams;\n}\n\nexport type ThreadRetryAfterItemParams = ThreadRef & {\n item_id: string;\n};\n\nexport interface ThreadsRetryAfterItemReq extends BaseReq {\n type: 'threads.retry_after_item';\n params: ThreadRetryAfterItemParams;\n}\n\nexport type ThreadUpdateParams = ThreadRef & {\n title?: string;\n workspace?: WorkspaceRef;\n};\n\nexport interface ThreadsUpdateReq extends BaseReq {\n type: 'threads.update';\n params: ThreadUpdateParams;\n}\n\nexport type ThreadDeleteParams = ThreadRef;\n\nexport interface ThreadsDeleteReq extends BaseReq {\n type: 'threads.delete';\n params: ThreadDeleteParams;\n}\n\n// Items Requests\nexport type ItemsListParams = ThreadRef & {\n limit?: number;\n order?: 'asc' | 'desc';\n after?: string;\n};\n\nexport interface ItemsListReq extends BaseReq {\n type: 'items.list';\n params: ItemsListParams;\n}\n\nexport type ItemFeedbackParams = ThreadRef & {\n item_ids: string[];\n feedback: FeedbackKind;\n};\n\nexport type FeedbackKind = 'positive' | 'negative';\n\nexport interface ItemsFeedbackReq extends BaseReq {\n type: 'items.feedback';\n params: ItemFeedbackParams;\n}\n\n// Attachment Requests\nexport interface AttachmentCreateParams {\n name: string;\n size: number;\n mime_type: string;\n}\n\nexport interface AttachmentsCreateReq extends BaseReq {\n type: 'attachments.create';\n params: AttachmentCreateParams;\n}\n\nexport interface AttachmentDeleteParams {\n attachment_id: string;\n}\n\nexport interface AttachmentsDeleteReq extends BaseReq {\n type: 'attachments.delete';\n params: AttachmentDeleteParams;\n}\n\n// Request Union Types\nexport type StreamingReq =\n | ThreadsCreateReq\n | ThreadsAddUserMessageReq\n | ThreadsAddClientToolOutputReq\n | ThreadsRetryAfterItemReq\n | ThreadsCustomActionReq;\n\nexport type NonStreamingReq =\n | ThreadsGetByIdReq\n | ThreadsListReq\n | ItemsListReq\n | ItemsFeedbackReq\n | AttachmentsCreateReq\n | AttachmentsDeleteReq\n | ThreadsUpdateReq\n | ThreadsDeleteReq;\n\nexport type ChatKitReq = StreamingReq | NonStreamingReq;\n\n// ============================================================================\n// Stream Event Types\n// ============================================================================\n\nexport interface ThreadCreatedEvent {\n type: 'thread.created';\n thread: ThreadMetadata;\n}\n\nexport interface ThreadUpdatedEvent {\n type: 'thread.updated';\n thread: ThreadMetadata;\n}\n\nexport interface ThreadItemAddedEvent {\n type: 'thread.item.added';\n item: ThreadItem;\n}\n\nexport interface ThreadItemUpdatedEvent {\n type: 'thread.item.updated';\n item_id: string;\n update: ThreadItemUpdate;\n}\n\nexport interface ThreadItemDoneEvent {\n type: 'thread.item.done';\n item: ThreadItem;\n}\n\nexport interface ThreadItemRemovedEvent {\n type: 'thread.item.removed';\n item_id: string;\n}\n\nexport interface ThreadItemReplacedEvent {\n type: 'thread.item.replaced';\n item: ThreadItem;\n}\n\nexport interface StreamOptions {\n allow_cancel?: boolean;\n}\n\nexport interface StreamOptionsEvent {\n type: 'stream_options';\n options: StreamOptions;\n}\n\nexport interface ProgressUpdate {\n progress: number;\n message?: string;\n}\n\nexport interface ProgressUpdateEvent {\n type: 'progress_update';\n update: ProgressUpdate;\n}\n\nexport interface ClientEffect {\n effect_type: string;\n data?: unknown;\n}\n\nexport interface ClientEffectEvent {\n type: 'client_effect';\n effect: ClientEffect;\n}\n\nexport interface ErrorEvent {\n type: 'error';\n error: {\n code: string;\n message: string;\n details?: unknown;\n };\n}\n\nexport interface NoticeEvent {\n type: 'notice';\n notice: {\n level: 'info' | 'warning' | 'error';\n message: string;\n };\n}\n\nexport type ThreadStreamEvent =\n | ThreadCreatedEvent\n | ThreadUpdatedEvent\n | ThreadItemAddedEvent\n | ThreadItemUpdatedEvent\n | ThreadItemDoneEvent\n | ThreadItemRemovedEvent\n | ThreadItemReplacedEvent\n | StreamOptionsEvent\n | ProgressUpdateEvent\n | ClientEffectEvent\n | ErrorEvent\n | NoticeEvent;\n\n// ============================================================================\n// Thread Item Update Types (for streaming)\n// ============================================================================\n\nexport interface AssistantMessageContentPartAdded {\n type: 'assistant_message.content_part.added';\n part_index: number;\n part: AssistantMessageContent;\n}\n\nexport interface AssistantMessageContentPartTextDelta {\n type: 'assistant_message.content_part.text_delta';\n part_index: number;\n delta: string;\n}\n\nexport interface AssistantMessageContentPartAnnotationAdded {\n type: 'assistant_message.content_part.annotation_added';\n part_index: number;\n annotation: Annotation;\n}\n\nexport interface AssistantMessageContentPartDone {\n type: 'assistant_message.content_part.done';\n part_index: number;\n}\n\nexport interface WidgetStreamingTextValueDelta {\n type: 'widget.streaming_text.value_delta';\n path: string;\n delta: string;\n}\n\nexport interface WidgetRootUpdated {\n type: 'widget.root.updated';\n data: unknown;\n}\n\nexport interface WidgetComponentUpdated {\n type: 'widget.component.updated';\n component_id: string;\n data: unknown;\n}\n\nexport interface WorkflowTaskAdded {\n type: 'workflow.task.added';\n task: Task;\n}\n\nexport interface WorkflowTaskUpdated {\n type: 'workflow.task.updated';\n task_id: string;\n task: Partial<Task>;\n}\n\nexport interface GeneratedImageUpdated {\n type: 'generated_image.updated';\n image: GeneratedImage;\n}\n\nexport type ThreadItemUpdate =\n | AssistantMessageContentPartAdded\n | AssistantMessageContentPartTextDelta\n | AssistantMessageContentPartAnnotationAdded\n | AssistantMessageContentPartDone\n | WidgetStreamingTextValueDelta\n | WidgetRootUpdated\n | WidgetComponentUpdated\n | WorkflowTaskAdded\n | WorkflowTaskUpdated\n | GeneratedImageUpdated;\n\n// ============================================================================\n// Response Types\n// ============================================================================\n\nexport interface StreamingResult {\n type: 'streaming';\n stream: AsyncIterable<ThreadStreamEvent>;\n}\n\nexport interface NonStreamingResult {\n type: 'non_streaming';\n data: unknown;\n}\n\nexport type ChatKitResult = StreamingResult | NonStreamingResult;\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\nexport function isStreamingReq(req: ChatKitReq): req is StreamingReq {\n return (\n req.type === 'threads.create' ||\n req.type === 'threads.add_user_message' ||\n req.type === 'threads.add_client_tool_output' ||\n req.type === 'threads.retry_after_item' ||\n req.type === 'threads.custom_action'\n );\n}\n\nexport function isNonStreamingReq(req: ChatKitReq): req is NonStreamingReq {\n return !isStreamingReq(req);\n}\n\n/**\n * Generate a unique ID with prefix\n */\nexport function generateId(prefix: string): string {\n const timestamp = Date.now().toString(36);\n const random = Math.random().toString(36).substring(2, 10);\n return `${prefix}_${timestamp}${random}`;\n}\n\n/**\n * Get current timestamp in seconds\n */\nexport function nowTimestamp(): number {\n return Math.floor(Date.now() / 1000);\n}\n\n/**\n * Extract text content from user message\n */\nexport function extractUserMessageText(content: UserMessageContent[]): string {\n return content\n .filter((c): c is UserMessageTextContent => c.type === 'input_text')\n .map((c) => c.text)\n .join('\\n');\n}\n\n/**\n * Extract text content from assistant message\n */\nexport function extractAssistantMessageText(content: AssistantMessageContent[]): string {\n return content\n .filter((c): c is AssistantMessageContent => c.type === 'output_text')\n .map((c) => c.text)\n .join('\\n');\n}\n"]}
@@ -14,7 +14,6 @@ const CloudflareTunnelProvider_1 = require("../../tunnel/CloudflareTunnelProvide
14
14
  const SubdomainService_1 = require("../../subdomain/SubdomainService");
15
15
  const EdgeNodeDnsCoordinator_1 = require("../../edge/EdgeNodeDnsCoordinator");
16
16
  const EdgeNodeHealthProbeService_1 = require("../../edge/EdgeNodeHealthProbeService");
17
- const WebIdProfileRepository_1 = require("../../identity/drizzle/WebIdProfileRepository");
18
17
  const DdnsRepository_1 = require("../../identity/drizzle/DdnsRepository");
19
18
  const PodLookupRepository_1 = require("../../identity/drizzle/PodLookupRepository");
20
19
  const global_logger_factory_1 = require("global-logger-factory");
@@ -25,18 +24,11 @@ const logger = (0, global_logger_factory_1.getLoggerFor)('CloudServices');
25
24
  function registerCloudServices(container) {
26
25
  const config = container.resolve('config');
27
26
  const db = container.resolve('db');
28
- // 获取 baseUrl 用于 WebID Profile
29
- const baseUrl = process.env.CSS_BASE_URL || `http://localhost:${process.env.CSS_PORT || 3000}`;
30
- // 注册 WebID Profile Repository (始终注册,用于身份服务)
31
27
  container.register({
32
- webIdProfileRepo: (0, awilix_1.asFunction)(() => {
33
- return new WebIdProfileRepository_1.WebIdProfileRepository({ db, baseUrl });
34
- }).singleton(),
35
28
  podLookupRepo: (0, awilix_1.asFunction)(() => {
36
29
  return new PodLookupRepository_1.PodLookupRepository(db);
37
30
  }).singleton(),
38
31
  });
39
- logger.info('WebID Profile repository registered');
40
32
  logger.info('Pod lookup repository registered');
41
33
  // 注册 DDNS Repository (始终注册,用于 DDNS 服务)
42
34
  container.register({
@@ -1 +1 @@
1
- {"version":3,"file":"cloud.js","sourceRoot":"","sources":["../../../src/api/container/cloud.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Cloud 模式服务注册\n *\n * Cloud 模式持有 DNS/Tunnel 密钥,直接操作子域名\n * 提供身份服务 (IdP) 和可选的托管存储 (SP)\n */\n\nimport { asFunction, type AwilixContainer } from 'awilix';\nimport type { ApiContainerCradle, ApiContainerConfig } from './types';\n\nimport { TencentDnsProvider } from '../../dns/tencent/TencentDnsProvider';\nimport { CloudflareDnsProvider } from '../../dns/cloudflare/CloudflareDnsProvider';\nimport { CloudflareTunnelProvider } from '../../tunnel/CloudflareTunnelProvider';\nimport { SubdomainService } from '../../subdomain/SubdomainService';\nimport { EdgeNodeDnsCoordinator } from '../../edge/EdgeNodeDnsCoordinator';\nimport { EdgeNodeHealthProbeService } from '../../edge/EdgeNodeHealthProbeService';\nimport { WebIdProfileRepository } from '../../identity/drizzle/WebIdProfileRepository';\nimport { DdnsRepository } from '../../identity/drizzle/DdnsRepository';\nimport { PodLookupRepository } from '../../identity/drizzle/PodLookupRepository';\nimport { getLoggerFor } from 'global-logger-factory';\n\nconst logger = getLoggerFor('CloudServices');\n\n/**\n * 注册 Cloud 模式专属服务\n */\nexport function registerCloudServices(\n container: AwilixContainer<ApiContainerCradle>,\n): void {\n const config = container.resolve('config') as ApiContainerConfig;\n const db = container.resolve('db');\n\n // 获取 baseUrl 用于 WebID Profile\n const baseUrl = process.env.CSS_BASE_URL || `http://localhost:${process.env.CSS_PORT || 3000}`;\n\n // 注册 WebID Profile Repository (始终注册,用于身份服务)\n container.register({\n webIdProfileRepo: asFunction(() => {\n return new WebIdProfileRepository({ db, baseUrl });\n }).singleton(),\n podLookupRepo: asFunction(() => {\n return new PodLookupRepository(db);\n }).singleton(),\n });\n logger.info('WebID Profile repository registered');\n logger.info('Pod lookup repository registered');\n\n // 注册 DDNS Repository (始终注册,用于 DDNS 服务)\n container.register({\n ddnsRepo: asFunction(() => {\n return new DdnsRepository(db);\n }).singleton(),\n });\n logger.info('DDNS repository registered');\n\n // 只有配置了 baseStorageDomain 才注册 DNS/Tunnel 服务\n const baseStorageDomain = config.subdomain?.baseStorageDomain;\n if (!baseStorageDomain) {\n logger.info('Subdomain service disabled (no CSS_BASE_STORAGE_DOMAIN)');\n return;\n }\n\n const {\n tencentDnsSecretId,\n tencentDnsSecretKey,\n cloudflareAccountId,\n cloudflareApiToken,\n } = config.subdomain!;\n\n // DNS Provider (腾讯云优先,否则回退到 Cloudflare)\n if (tencentDnsSecretId && tencentDnsSecretKey) {\n container.register({\n dnsProvider: asFunction(() => {\n return new TencentDnsProvider({\n tokenId: tencentDnsSecretId,\n token: tencentDnsSecretKey,\n });\n }).singleton(),\n });\n logger.info('Tencent DNS provider registered');\n } else if (cloudflareApiToken) {\n container.register({\n dnsProvider: asFunction(() => {\n return new CloudflareDnsProvider({\n apiToken: cloudflareApiToken,\n });\n }).singleton(),\n });\n logger.info('Cloudflare DNS provider registered');\n }\n\n // Tunnel Provider (Cloudflare)\n if (cloudflareAccountId && cloudflareApiToken) {\n container.register({\n tunnelProvider: asFunction(() => {\n return new CloudflareTunnelProvider({\n accountId: cloudflareAccountId,\n apiToken: cloudflareApiToken,\n baseDomain: baseStorageDomain,\n });\n }).singleton(),\n });\n logger.info('Cloudflare Tunnel provider registered');\n }\n\n // Subdomain Service (需要 DNS 和 Tunnel Provider)\n try {\n const dnsProvider = container.resolve('dnsProvider', { allowUnregistered: true });\n const tunnelProvider = container.resolve('tunnelProvider', { allowUnregistered: true });\n\n if (dnsProvider && tunnelProvider) {\n const nodeRepo = container.resolve('nodeRepo');\n container.register({\n subdomainService: asFunction(() => {\n return new SubdomainService({\n baseDomain: baseStorageDomain,\n dnsProvider: dnsProvider as any,\n tunnelProvider: tunnelProvider as any,\n edgeNodeRepo: nodeRepo,\n });\n }).singleton(),\n });\n logger.info(`Subdomain service registered for domain: ${baseStorageDomain}`);\n }\n } catch {\n logger.warn('Subdomain service not registered (missing DNS or Tunnel provider)');\n }\n\n // DNS Coordinator (心跳→DNS 同步,需要 dnsProvider)\n const dnsProvider = container.resolve('dnsProvider', { allowUnregistered: true });\n if (dnsProvider) {\n container.register({\n dnsCoordinator: asFunction(() => {\n return new EdgeNodeDnsCoordinator({\n provider: dnsProvider as any,\n rootDomain: baseStorageDomain,\n });\n }).singleton(),\n });\n logger.info('DNS coordinator registered');\n }\n\n // Health Probe Service (心跳时探测节点可达性)\n const nodeRepo = container.resolve('nodeRepo');\n container.register({\n healthProbeService: asFunction(() => {\n return new EdgeNodeHealthProbeService({\n repository: nodeRepo,\n enabled: true,\n });\n }).singleton(),\n });\n logger.info('Health probe service registered');\n}\n"]}
1
+ {"version":3,"file":"cloud.js","sourceRoot":"","sources":["../../../src/api/container/cloud.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Cloud 模式服务注册\n *\n * Cloud 模式持有 DNS/Tunnel 密钥,直接操作子域名\n * 提供身份服务 (IdP) 和可选的托管存储 (SP)\n */\n\nimport { asFunction, type AwilixContainer } from 'awilix';\nimport type { ApiContainerCradle, ApiContainerConfig } from './types';\n\nimport { TencentDnsProvider } from '../../dns/tencent/TencentDnsProvider';\nimport { CloudflareDnsProvider } from '../../dns/cloudflare/CloudflareDnsProvider';\nimport { CloudflareTunnelProvider } from '../../tunnel/CloudflareTunnelProvider';\nimport { SubdomainService } from '../../subdomain/SubdomainService';\nimport { EdgeNodeDnsCoordinator } from '../../edge/EdgeNodeDnsCoordinator';\nimport { EdgeNodeHealthProbeService } from '../../edge/EdgeNodeHealthProbeService';\nimport { DdnsRepository } from '../../identity/drizzle/DdnsRepository';\nimport { PodLookupRepository } from '../../identity/drizzle/PodLookupRepository';\nimport { getLoggerFor } from 'global-logger-factory';\n\nconst logger = getLoggerFor('CloudServices');\n\n/**\n * 注册 Cloud 模式专属服务\n */\nexport function registerCloudServices(\n container: AwilixContainer<ApiContainerCradle>,\n): void {\n const config = container.resolve('config') as ApiContainerConfig;\n const db = container.resolve('db');\n\n container.register({\n podLookupRepo: asFunction(() => {\n return new PodLookupRepository(db);\n }).singleton(),\n });\n logger.info('Pod lookup repository registered');\n\n // 注册 DDNS Repository (始终注册,用于 DDNS 服务)\n container.register({\n ddnsRepo: asFunction(() => {\n return new DdnsRepository(db);\n }).singleton(),\n });\n logger.info('DDNS repository registered');\n\n // 只有配置了 baseStorageDomain 才注册 DNS/Tunnel 服务\n const baseStorageDomain = config.subdomain?.baseStorageDomain;\n if (!baseStorageDomain) {\n logger.info('Subdomain service disabled (no CSS_BASE_STORAGE_DOMAIN)');\n return;\n }\n\n const {\n tencentDnsSecretId,\n tencentDnsSecretKey,\n cloudflareAccountId,\n cloudflareApiToken,\n } = config.subdomain!;\n\n // DNS Provider (腾讯云优先,否则回退到 Cloudflare)\n if (tencentDnsSecretId && tencentDnsSecretKey) {\n container.register({\n dnsProvider: asFunction(() => {\n return new TencentDnsProvider({\n tokenId: tencentDnsSecretId,\n token: tencentDnsSecretKey,\n });\n }).singleton(),\n });\n logger.info('Tencent DNS provider registered');\n } else if (cloudflareApiToken) {\n container.register({\n dnsProvider: asFunction(() => {\n return new CloudflareDnsProvider({\n apiToken: cloudflareApiToken,\n });\n }).singleton(),\n });\n logger.info('Cloudflare DNS provider registered');\n }\n\n // Tunnel Provider (Cloudflare)\n if (cloudflareAccountId && cloudflareApiToken) {\n container.register({\n tunnelProvider: asFunction(() => {\n return new CloudflareTunnelProvider({\n accountId: cloudflareAccountId,\n apiToken: cloudflareApiToken,\n baseDomain: baseStorageDomain,\n });\n }).singleton(),\n });\n logger.info('Cloudflare Tunnel provider registered');\n }\n\n // Subdomain Service (需要 DNS 和 Tunnel Provider)\n try {\n const dnsProvider = container.resolve('dnsProvider', { allowUnregistered: true });\n const tunnelProvider = container.resolve('tunnelProvider', { allowUnregistered: true });\n\n if (dnsProvider && tunnelProvider) {\n const nodeRepo = container.resolve('nodeRepo');\n container.register({\n subdomainService: asFunction(() => {\n return new SubdomainService({\n baseDomain: baseStorageDomain,\n dnsProvider: dnsProvider as any,\n tunnelProvider: tunnelProvider as any,\n edgeNodeRepo: nodeRepo,\n });\n }).singleton(),\n });\n logger.info(`Subdomain service registered for domain: ${baseStorageDomain}`);\n }\n } catch {\n logger.warn('Subdomain service not registered (missing DNS or Tunnel provider)');\n }\n\n // DNS Coordinator (心跳→DNS 同步,需要 dnsProvider)\n const dnsProvider = container.resolve('dnsProvider', { allowUnregistered: true });\n if (dnsProvider) {\n container.register({\n dnsCoordinator: asFunction(() => {\n return new EdgeNodeDnsCoordinator({\n provider: dnsProvider as any,\n rootDomain: baseStorageDomain,\n });\n }).singleton(),\n });\n logger.info('DNS coordinator registered');\n }\n\n // Health Probe Service (心跳时探测节点可达性)\n const nodeRepo = container.resolve('nodeRepo');\n container.register({\n healthProbeService: asFunction(() => {\n return new EdgeNodeHealthProbeService({\n repository: nodeRepo,\n enabled: true,\n });\n }).singleton(),\n });\n logger.info('Health probe service registered');\n}\n"]}
@@ -39,6 +39,7 @@ const common_1 = require("./common");
39
39
  const cloud_1 = require("./cloud");
40
40
  const local_1 = require("./local");
41
41
  const business_token_1 = require("./business-token");
42
+ const oidc_issuer_1 = require("../../runtime/oidc-issuer");
42
43
  const OFFICIAL_CLOUD_IDENTITY_ORIGIN = 'https://id.undefineds.co';
43
44
  function ensureTrailingSlash(url) {
44
45
  return url.endsWith('/') ? url : `${url}/`;
@@ -124,7 +125,7 @@ function loadConfigFromEnv() {
124
125
  nodeToken: process.env.XPOD_NODE_TOKEN,
125
126
  // OIDC Issuer (Local 托管式使用 Cloud IdP)
126
127
  // 如果配置了 XPOD_NODE_TOKEN,默认使用 Cloud IdP
127
- oidcIssuer: process.env.CSS_OIDC_ISSUER ?? (process.env.XPOD_NODE_TOKEN
128
+ oidcIssuer: (0, oidc_issuer_1.resolveExternalOidcIssuer)(process.env) ?? (process.env.XPOD_NODE_TOKEN
128
129
  ? OFFICIAL_CLOUD_IDENTITY_ORIGIN
129
130
  : undefined),
130
131
  // 隧道配置
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/api/container/index.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;;;;;;;;;;;;;;;;;;;;;;;AAoCH,gDA0BC;AAKD,8CA8DC;AA/HD,mCAAuF;AACvF,6CAAqD;AACrD,4CAA8B;AAC9B,4CAA8B;AAC9B,gDAAkC;AAElC,qCAAkD;AAClD,mCAAgD;AAChD,mCAAgD;AAChD,qDAAyD;AAIzD,MAAM,8BAA8B,GAAG,0BAA0B,CAAC;AAElE,SAAS,mBAAmB,CAAC,GAAW;IACtC,OAAO,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC;AAC7C,CAAC;AAED,SAAS,uBAAuB;IAC9B,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,CAAC;QACnC,OAAO,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;IACxC,CAAC;IAED,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;QAC7B,OAAO,GAAG,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,aAAa,CAAC;IACvE,CAAC;IAED,OAAO,mCAAmC,CAAC;AAC7C,CAAC;AAED;;GAEG;AACH,SAAgB,kBAAkB,CAAC,MAA0B;IAC3D,MAAM,SAAS,GAAG,IAAA,wBAAe,EAAqB;QACpD,aAAa,EAAE,sBAAa,CAAC,KAAK;QAClC,MAAM,EAAE,IAAI;KACb,CAAC,CAAC;IAEH,OAAO;IACP,SAAS,CAAC,QAAQ,CAAC;QACjB,MAAM,EAAE,IAAA,gBAAO,EAAC,MAAM,CAAC;QACvB,oBAAoB,EAAE,IAAA,gBAAO,EAAC,MAAM,CAAC,oBAAoB,CAAC;KAC3D,CAAC,CAAC;IAEH,SAAS;IACT,IAAA,+BAAsB,EAAC,SAAS,CAAC,CAAC;IAElC,oBAAoB;IACpB,IAAI,MAAM,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;QAC/B,IAAA,6BAAqB,EAAC,SAAS,CAAC,CAAC;IACnC,CAAC;SAAM,CAAC;QACN,IAAA,6BAAqB,EAAC,SAAS,CAAC,CAAC;IACnC,CAAC;IAED,gDAAgD;IAChD,IAAA,sCAAqB,EAAC,SAAS,CAAC,CAAC;IAEjC,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,SAAgB,iBAAiB;IAC/B,MAAM,OAAO,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,OAAO,CAAsB,CAAC;IAE3E,qEAAqE;IACrE,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;IAC7D,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ;QAClC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC;QACpC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC;IAEhB,OAAO;QACL,OAAO;QACP,IAAI,EAAE,OAAO;QACb,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,SAAS;QACvC,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe;QACvC,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE;QAC9E,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS;QAC/D,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC;QAC7E,gBAAgB,EAAE,uBAAuB,EAAE;QAC3C,OAAO,EAAE;YACP,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,oBAAoB,KAAK,OAAO;YACrD,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,KAAK,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,KAAK,SAAS;gBAC5F,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB;gBAC/B,CAAC,CAAC,SAAS;YACb,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;YAC7F,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,WAAW;YAClD,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB;YAC1C,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB;YAC7E,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,wBAAwB,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB;YACnF,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB;YACxC,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,uBAAuB;SAC/C;QAED,mBAAmB;QACnB,SAAS,EAAE;YACT,iBAAiB,EAAE,OAAO,CAAC,GAAG,CAAC,uBAAuB;YACtD,mBAAmB,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB;YACtD,kBAAkB,EAAE,OAAO,CAAC,GAAG,CAAC,oBAAoB;YACpD,kBAAkB,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB;YACrD,mBAAmB,EAAE,OAAO,CAAC,GAAG,CAAC,sBAAsB;SACxD;QAED,qBAAqB;QACrB,gBAAgB,EAAE,OAAO,CAAC,GAAG,CAAC,uBAAuB;QACrD,MAAM,EAAE,sBAAsB,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;QACxD,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe;QAEtC,sCAAsC;QACtC,uCAAuC;QACvC,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,CACzC,OAAO,CAAC,GAAG,CAAC,eAAe;YACzB,CAAC,CAAC,8BAA8B;YAChC,CAAC,CAAC,SAAS,CACd;QAED,OAAO;QACP,qBAAqB,EAAE,OAAO,CAAC,GAAG,CAAC,uBAAuB;QAC1D,4EAA4E;QAC5E,iBAAiB,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY;QAE9E,uBAAuB;QACvB,gBAAgB,EAAE,OAAO,CAAC,GAAG,CAAC,uBAAuB,KAAK,MAAM;KACjE,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,kBAAkB;IACzB,MAAM,UAAU,GAAG,EAAE,CAAC,iBAAiB,EAAE,CAAC;IAC1C,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3C,KAAK,MAAM,KAAK,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;YAC3C,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,GAAG,IAAI,KAAK,CAAC,GAAG,KAAK,mBAAmB,EAAE,CAAC;gBACtE,OAAO,KAAK,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;YACjC,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAS,sBAAsB,CAAC,SAAkB;IAChD,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,QAAQ,CAAC;IAC3D,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IAEtD,UAAU;IACV,IAAI,CAAC;QACH,IAAI,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YAChC,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;YAC9D,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,OAAO,CAAC;YACjB,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,YAAY;IACd,CAAC;IAED,0BAA0B;IAC1B,MAAM,GAAG,GAAG,kBAAkB,EAAE,CAAC;IACjC,MAAM,QAAQ,GAAG,GAAG;QAClB,CAAC,CAAC,IAAA,wBAAU,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;QAC7D,CAAC,CAAC,IAAA,wBAAU,GAAE,CAAC;IAEjB,IAAI,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5B,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7C,CAAC;QACD,EAAE,CAAC,aAAa,CAAC,YAAY,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IACpD,CAAC;IAAC,MAAM,CAAC;QACP,YAAY;IACd,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC","sourcesContent":["/**\n * API Container 入口\n *\n * 使用 Awilix 进行依赖注入,根据 edition 注册不同服务\n */\n\nimport { createContainer, asValue, InjectionMode, type AwilixContainer } from 'awilix';\nimport { randomUUID, createHash } from 'node:crypto';\nimport * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport type { ApiContainerCradle, ApiContainerConfig } from './types';\nimport { registerCommonServices } from './common';\nimport { registerCloudServices } from './cloud';\nimport { registerLocalServices } from './local';\nimport { registerBusinessToken } from './business-token';\n\nexport type { ApiContainerCradle, ApiContainerConfig } from './types';\n\nconst OFFICIAL_CLOUD_IDENTITY_ORIGIN = 'https://id.undefineds.co';\n\nfunction ensureTrailingSlash(url: string): string {\n return url.endsWith('/') ? url : `${url}/`;\n}\n\nfunction resolveCssTokenEndpoint(): string {\n if (process.env.CSS_TOKEN_ENDPOINT) {\n return process.env.CSS_TOKEN_ENDPOINT;\n }\n\n if (process.env.CSS_BASE_URL) {\n return `${ensureTrailingSlash(process.env.CSS_BASE_URL)}.oidc/token`;\n }\n\n return 'http://localhost:3000/.oidc/token';\n}\n\n/**\n * 创建 API 容器\n */\nexport function createApiContainer(config: ApiContainerConfig): AwilixContainer<ApiContainerCradle> {\n const container = createContainer<ApiContainerCradle>({\n injectionMode: InjectionMode.PROXY,\n strict: true,\n });\n\n // 注册配置\n container.register({\n config: asValue(config),\n inngestRuntimeConfig: asValue(config.inngestRuntimeConfig),\n });\n\n // 注册共享服务\n registerCommonServices(container);\n\n // 根据 edition 注册专属服务\n if (config.edition === 'cloud') {\n registerCloudServices(container);\n } else {\n registerLocalServices(container);\n }\n\n // 注册 Business Token (如果配置了 XPOD_BUSINESS_TOKEN)\n registerBusinessToken(container);\n\n return container;\n}\n\n/**\n * 从环境变量读取配置\n */\nexport function loadConfigFromEnv(): ApiContainerConfig {\n const edition = (process.env.XPOD_EDITION ?? 'local') as 'cloud' | 'local';\n\n // Port auto-increment: API_PORT = CSS_PORT + 1 if not explicitly set\n const cssPort = parseInt(process.env.CSS_PORT ?? '3000', 10);\n const apiPort = process.env.API_PORT\n ? parseInt(process.env.API_PORT, 10)\n : cssPort + 1;\n\n return {\n edition,\n port: apiPort,\n host: process.env.API_HOST ?? '0.0.0.0',\n socketPath: process.env.API_SOCKET_PATH,\n databaseUrl: process.env.CSS_IDENTITY_DB_URL ?? process.env.DATABASE_URL ?? '',\n redisUrl: process.env.CSS_REDIS_CLIENT ?? process.env.REDIS_URL,\n corsOrigins: process.env.CORS_ORIGINS?.split(',').map(s => s.trim()) ?? ['*'],\n cssTokenEndpoint: resolveCssTokenEndpoint(),\n inngest: {\n enabled: process.env.XPOD_INNGEST_ENABLED !== 'false',\n mode: process.env.XPOD_INNGEST_MODE === 'spawn' || process.env.XPOD_INNGEST_MODE === 'managed'\n ? process.env.XPOD_INNGEST_MODE\n : undefined,\n port: process.env.XPOD_INNGEST_PORT ? parseInt(process.env.XPOD_INNGEST_PORT, 10) : undefined,\n host: process.env.XPOD_INNGEST_HOST ?? '127.0.0.1',\n baseUrl: process.env.XPOD_INNGEST_BASE_URL,\n eventKey: process.env.XPOD_INNGEST_EVENT_KEY ?? process.env.INNGEST_EVENT_KEY,\n signingKey: process.env.XPOD_INNGEST_SIGNING_KEY ?? process.env.INNGEST_SIGNING_KEY,\n binaryPath: process.env.XPOD_INNGEST_BIN,\n sqliteDir: process.env.XPOD_INNGEST_SQLITE_DIR,\n },\n\n // 子域名配置 (cloud 模式)\n subdomain: {\n baseStorageDomain: process.env.CSS_BASE_STORAGE_DOMAIN,\n cloudflareAccountId: process.env.CLOUDFLARE_ACCOUNT_ID,\n cloudflareApiToken: process.env.CLOUDFLARE_API_TOKEN,\n tencentDnsSecretId: process.env.TENCENT_DNS_SECRET_ID,\n tencentDnsSecretKey: process.env.TENCENT_DNS_SECRET_KEY,\n },\n\n // Local 托管式:连接 Cloud\n cloudApiEndpoint: process.env.XPOD_CLOUD_API_ENDPOINT,\n nodeId: loadOrGenerateDeviceId(process.env.XPOD_NODE_ID),\n nodeToken: process.env.XPOD_NODE_TOKEN,\n\n // OIDC Issuer (Local 托管式使用 Cloud IdP)\n // 如果配置了 XPOD_NODE_TOKEN,默认使用 Cloud IdP\n oidcIssuer: process.env.CSS_OIDC_ISSUER ?? (\n process.env.XPOD_NODE_TOKEN\n ? OFFICIAL_CLOUD_IDENTITY_ORIGIN\n : undefined\n ),\n\n // 隧道配置\n cloudflareTunnelToken: process.env.CLOUDFLARE_TUNNEL_TOKEN,\n // Prefer SAKURA_TUNNEL_TOKEN; keep SAKURA_TOKEN for backward compatibility.\n sakuraTunnelToken: process.env.SAKURA_TUNNEL_TOKEN ?? process.env.SAKURA_TOKEN,\n\n // Edge 节点管理 (cloud 模式)\n edgeNodesEnabled: process.env.XPOD_EDGE_NODES_ENABLED === 'true',\n };\n}\n\n/**\n * 获取设备首个非内部网卡的 MAC 地址。\n * 返回小写冒号分隔格式,如 \"aa:bb:cc:dd:ee:ff\"。\n * 容器/虚拟机中可能拿不到稳定 MAC,此时返回 undefined。\n */\nfunction getFirstMacAddress(): string | undefined {\n const interfaces = os.networkInterfaces();\n for (const name of Object.keys(interfaces)) {\n for (const iface of interfaces[name] ?? []) {\n if (!iface.internal && iface.mac && iface.mac !== '00:00:00:00:00:00') {\n return iface.mac.toLowerCase();\n }\n }\n }\n return undefined;\n}\n\n/**\n * 读取或生成设备 ID(持久化到 data/.device-id)。\n *\n * 优先级:\n * 1. 环境变量 XPOD_NODE_ID\n * 2. 已持久化的 data/.device-id\n * 3. 基于 MAC 地址的 SHA-256 哈希(截取前 32 位 hex)\n * 4. 随机 UUID(容器/虚拟机无稳定 MAC 时兜底)\n *\n * 生成后写入 data/.device-id,后续启动直接读取,保证同一设备 ID 稳定。\n */\nfunction loadOrGenerateDeviceId(envNodeId?: string): string | undefined {\n if (envNodeId) {\n return envNodeId;\n }\n\n const rootDir = process.env.CSS_ROOT_FILE_PATH || './data';\n const deviceIdPath = path.join(rootDir, '.device-id');\n\n // 尝试从文件读取\n try {\n if (fs.existsSync(deviceIdPath)) {\n const content = fs.readFileSync(deviceIdPath, 'utf-8').trim();\n if (content) {\n return content;\n }\n }\n } catch {\n // 读取失败,继续生成\n }\n\n // 优先用 MAC 哈希,拿不到则 UUID 兜底\n const mac = getFirstMacAddress();\n const deviceId = mac\n ? createHash('sha256').update(mac).digest('hex').slice(0, 32)\n : randomUUID();\n\n try {\n if (!fs.existsSync(rootDir)) {\n fs.mkdirSync(rootDir, { recursive: true });\n }\n fs.writeFileSync(deviceIdPath, deviceId, 'utf-8');\n } catch {\n // 写入失败不阻塞启动\n }\n\n return deviceId;\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/api/container/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * API Container 入口\n *\n * 使用 Awilix 进行依赖注入,根据 edition 注册不同服务\n */\n\nimport { createContainer, asValue, InjectionMode, type AwilixContainer } from 'awilix';\nimport { randomUUID, createHash } from 'node:crypto';\nimport * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport type { ApiContainerCradle, ApiContainerConfig } from './types';\nimport { registerCommonServices } from './common';\nimport { registerCloudServices } from './cloud';\nimport { registerLocalServices } from './local';\nimport { registerBusinessToken } from './business-token';\nimport { resolveExternalOidcIssuer } from '../../runtime/oidc-issuer';\n\nexport type { ApiContainerCradle, ApiContainerConfig } from './types';\n\nconst OFFICIAL_CLOUD_IDENTITY_ORIGIN = 'https://id.undefineds.co';\n\nfunction ensureTrailingSlash(url: string): string {\n return url.endsWith('/') ? url : `${url}/`;\n}\n\nfunction resolveCssTokenEndpoint(): string {\n if (process.env.CSS_TOKEN_ENDPOINT) {\n return process.env.CSS_TOKEN_ENDPOINT;\n }\n\n if (process.env.CSS_BASE_URL) {\n return `${ensureTrailingSlash(process.env.CSS_BASE_URL)}.oidc/token`;\n }\n\n return 'http://localhost:3000/.oidc/token';\n}\n\n/**\n * 创建 API 容器\n */\nexport function createApiContainer(config: ApiContainerConfig): AwilixContainer<ApiContainerCradle> {\n const container = createContainer<ApiContainerCradle>({\n injectionMode: InjectionMode.PROXY,\n strict: true,\n });\n\n // 注册配置\n container.register({\n config: asValue(config),\n inngestRuntimeConfig: asValue(config.inngestRuntimeConfig),\n });\n\n // 注册共享服务\n registerCommonServices(container);\n\n // 根据 edition 注册专属服务\n if (config.edition === 'cloud') {\n registerCloudServices(container);\n } else {\n registerLocalServices(container);\n }\n\n // 注册 Business Token (如果配置了 XPOD_BUSINESS_TOKEN)\n registerBusinessToken(container);\n\n return container;\n}\n\n/**\n * 从环境变量读取配置\n */\nexport function loadConfigFromEnv(): ApiContainerConfig {\n const edition = (process.env.XPOD_EDITION ?? 'local') as 'cloud' | 'local';\n\n // Port auto-increment: API_PORT = CSS_PORT + 1 if not explicitly set\n const cssPort = parseInt(process.env.CSS_PORT ?? '3000', 10);\n const apiPort = process.env.API_PORT\n ? parseInt(process.env.API_PORT, 10)\n : cssPort + 1;\n\n return {\n edition,\n port: apiPort,\n host: process.env.API_HOST ?? '0.0.0.0',\n socketPath: process.env.API_SOCKET_PATH,\n databaseUrl: process.env.CSS_IDENTITY_DB_URL ?? process.env.DATABASE_URL ?? '',\n redisUrl: process.env.CSS_REDIS_CLIENT ?? process.env.REDIS_URL,\n corsOrigins: process.env.CORS_ORIGINS?.split(',').map(s => s.trim()) ?? ['*'],\n cssTokenEndpoint: resolveCssTokenEndpoint(),\n inngest: {\n enabled: process.env.XPOD_INNGEST_ENABLED !== 'false',\n mode: process.env.XPOD_INNGEST_MODE === 'spawn' || process.env.XPOD_INNGEST_MODE === 'managed'\n ? process.env.XPOD_INNGEST_MODE\n : undefined,\n port: process.env.XPOD_INNGEST_PORT ? parseInt(process.env.XPOD_INNGEST_PORT, 10) : undefined,\n host: process.env.XPOD_INNGEST_HOST ?? '127.0.0.1',\n baseUrl: process.env.XPOD_INNGEST_BASE_URL,\n eventKey: process.env.XPOD_INNGEST_EVENT_KEY ?? process.env.INNGEST_EVENT_KEY,\n signingKey: process.env.XPOD_INNGEST_SIGNING_KEY ?? process.env.INNGEST_SIGNING_KEY,\n binaryPath: process.env.XPOD_INNGEST_BIN,\n sqliteDir: process.env.XPOD_INNGEST_SQLITE_DIR,\n },\n\n // 子域名配置 (cloud 模式)\n subdomain: {\n baseStorageDomain: process.env.CSS_BASE_STORAGE_DOMAIN,\n cloudflareAccountId: process.env.CLOUDFLARE_ACCOUNT_ID,\n cloudflareApiToken: process.env.CLOUDFLARE_API_TOKEN,\n tencentDnsSecretId: process.env.TENCENT_DNS_SECRET_ID,\n tencentDnsSecretKey: process.env.TENCENT_DNS_SECRET_KEY,\n },\n\n // Local 托管式:连接 Cloud\n cloudApiEndpoint: process.env.XPOD_CLOUD_API_ENDPOINT,\n nodeId: loadOrGenerateDeviceId(process.env.XPOD_NODE_ID),\n nodeToken: process.env.XPOD_NODE_TOKEN,\n\n // OIDC Issuer (Local 托管式使用 Cloud IdP)\n // 如果配置了 XPOD_NODE_TOKEN,默认使用 Cloud IdP\n oidcIssuer: resolveExternalOidcIssuer(process.env) ?? (\n process.env.XPOD_NODE_TOKEN\n ? OFFICIAL_CLOUD_IDENTITY_ORIGIN\n : undefined\n ),\n\n // 隧道配置\n cloudflareTunnelToken: process.env.CLOUDFLARE_TUNNEL_TOKEN,\n // Prefer SAKURA_TUNNEL_TOKEN; keep SAKURA_TOKEN for backward compatibility.\n sakuraTunnelToken: process.env.SAKURA_TUNNEL_TOKEN ?? process.env.SAKURA_TOKEN,\n\n // Edge 节点管理 (cloud 模式)\n edgeNodesEnabled: process.env.XPOD_EDGE_NODES_ENABLED === 'true',\n };\n}\n\n/**\n * 获取设备首个非内部网卡的 MAC 地址。\n * 返回小写冒号分隔格式,如 \"aa:bb:cc:dd:ee:ff\"。\n * 容器/虚拟机中可能拿不到稳定 MAC,此时返回 undefined。\n */\nfunction getFirstMacAddress(): string | undefined {\n const interfaces = os.networkInterfaces();\n for (const name of Object.keys(interfaces)) {\n for (const iface of interfaces[name] ?? []) {\n if (!iface.internal && iface.mac && iface.mac !== '00:00:00:00:00:00') {\n return iface.mac.toLowerCase();\n }\n }\n }\n return undefined;\n}\n\n/**\n * 读取或生成设备 ID(持久化到 data/.device-id)。\n *\n * 优先级:\n * 1. 环境变量 XPOD_NODE_ID\n * 2. 已持久化的 data/.device-id\n * 3. 基于 MAC 地址的 SHA-256 哈希(截取前 32 位 hex)\n * 4. 随机 UUID(容器/虚拟机无稳定 MAC 时兜底)\n *\n * 生成后写入 data/.device-id,后续启动直接读取,保证同一设备 ID 稳定。\n */\nfunction loadOrGenerateDeviceId(envNodeId?: string): string | undefined {\n if (envNodeId) {\n return envNodeId;\n }\n\n const rootDir = process.env.CSS_ROOT_FILE_PATH || './data';\n const deviceIdPath = path.join(rootDir, '.device-id');\n\n // 尝试从文件读取\n try {\n if (fs.existsSync(deviceIdPath)) {\n const content = fs.readFileSync(deviceIdPath, 'utf-8').trim();\n if (content) {\n return content;\n }\n }\n } catch {\n // 读取失败,继续生成\n }\n\n // 优先用 MAC 哈希,拿不到则 UUID 兜底\n const mac = getFirstMacAddress();\n const deviceId = mac\n ? createHash('sha256').update(mac).digest('hex').slice(0, 32)\n : randomUUID();\n\n try {\n if (!fs.existsSync(rootDir)) {\n fs.mkdirSync(rootDir, { recursive: true });\n }\n fs.writeFileSync(deviceIdPath, deviceId, 'utf-8');\n } catch {\n // 写入失败不阻塞启动\n }\n\n return deviceId;\n}\n"]}
@@ -18,7 +18,6 @@ const EdgeNodeDnsCoordinator_1 = require("../../edge/EdgeNodeDnsCoordinator");
18
18
  const EdgeNodeCapabilityDetector_1 = require("../../edge/EdgeNodeCapabilityDetector");
19
19
  const LocalNetworkManager_1 = require("../../edge/LocalNetworkManager");
20
20
  const DdnsManager_1 = require("../../edge/DdnsManager");
21
- const WebIdProfileRepository_1 = require("../../identity/drizzle/WebIdProfileRepository");
22
21
  const PodLookupRepository_1 = require("../../identity/drizzle/PodLookupRepository");
23
22
  /**
24
23
  * 注册 Local 模式专属服务
@@ -27,12 +26,6 @@ function registerLocalServices(container) {
27
26
  const config = container.resolve('config');
28
27
  const { cloudApiEndpoint, nodeId, nodeToken, cloudflareTunnelToken, sakuraTunnelToken, subdomain: subdomainConfig, } = config;
29
28
  container.register({
30
- webIdProfileRepo: (0, awilix_1.asFunction)(({ db }) => {
31
- return new WebIdProfileRepository_1.WebIdProfileRepository({
32
- db,
33
- baseUrl: process.env.CSS_BASE_URL || `http://localhost:${process.env.CSS_PORT || 3000}`,
34
- });
35
- }).singleton(),
36
29
  podLookupRepo: (0, awilix_1.asFunction)(({ db }) => {
37
30
  return new PodLookupRepository_1.PodLookupRepository(db);
38
31
  }).singleton(),
@@ -1 +1 @@
1
- {"version":3,"file":"local.js","sourceRoot":"","sources":["../../../src/api/container/local.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Local 模式服务注册\n *\n * Local 模式有两种配置:\n * - 托管式 (managed): 配置 XPOD_NODE_TOKEN,自动连接 Cloud 获取身份服务和 DDNS\n * - 独立式 (standalone): 不配置 XPOD_NODE_TOKEN,用户自己配置 CSS_BASE_URL 和 IdP\n */\n\nimport { asFunction, type AwilixContainer } from 'awilix';\nimport type { ApiContainerCradle, ApiContainerConfig } from './types';\n\nimport { SubdomainClient } from '../../subdomain/SubdomainClient';\nimport { LocalTunnelProvider } from '../../tunnel/LocalTunnelProvider';\nimport { SakuraFrpTunnelProvider } from '../../tunnel/SakuraFrpTunnelProvider';\nimport { CloudflareDnsProvider } from '../../dns/cloudflare/CloudflareDnsProvider';\nimport { SubdomainService } from '../../subdomain/SubdomainService';\nimport { EdgeNodeDnsCoordinator } from '../../edge/EdgeNodeDnsCoordinator';\nimport { EdgeNodeCapabilityDetector } from '../../edge/EdgeNodeCapabilityDetector';\nimport { LocalNetworkManager } from '../../edge/LocalNetworkManager';\nimport { DdnsManager } from '../../edge/DdnsManager';\nimport type { TunnelProvider, TunnelStatus } from '../../tunnel/TunnelProvider';\nimport { WebIdProfileRepository } from '../../identity/drizzle/WebIdProfileRepository';\nimport { PodLookupRepository } from '../../identity/drizzle/PodLookupRepository';\n\n/**\n * 注册 Local 模式专属服务\n */\nexport function registerLocalServices(\n container: AwilixContainer<ApiContainerCradle>,\n): void {\n const config = container.resolve('config') as ApiContainerConfig;\n\n const {\n cloudApiEndpoint,\n nodeId,\n nodeToken,\n cloudflareTunnelToken,\n sakuraTunnelToken,\n subdomain: subdomainConfig,\n } = config;\n\n container.register({\n webIdProfileRepo: asFunction(({ db }: ApiContainerCradle) => {\n return new WebIdProfileRepository({\n db,\n baseUrl: process.env.CSS_BASE_URL || `http://localhost:${process.env.CSS_PORT || 3000}`,\n });\n }).singleton(),\n podLookupRepo: asFunction(({ db }: ApiContainerCradle) => {\n return new PodLookupRepository(db);\n }).singleton(),\n });\n\n // 1. 注册 Tunnel Provider (优先 Cloudflare,其次 SakuraFRP)\n if (cloudflareTunnelToken) {\n container.register({\n localTunnelProvider: asFunction(() => {\n return new LocalTunnelProvider({\n tunnelToken: cloudflareTunnelToken,\n });\n }).singleton(),\n });\n console.log('[Local] Tunnel provider registered (CLOUDFLARE_TUNNEL_TOKEN configured)');\n } else if (sakuraTunnelToken) {\n container.register({\n localTunnelProvider: asFunction(() => {\n return new SakuraFrpTunnelProvider({\n token: sakuraTunnelToken,\n });\n }).singleton(),\n });\n console.log('[Local] Tunnel provider registered (SAKURA_TUNNEL_TOKEN configured)');\n }\n\n // 2. 自适应 DNS 管理 (Self-Hosted DNS)\n // 如果配置了 Cloudflare API Token 和 Base Domain,启用本地 DNS 管理\n const apiToken = subdomainConfig?.cloudflareApiToken;\n\n // 在 Local 模式下,强制使用 CSS_BASE_URL 作为域名来源\n // 简化用户配置心智\n let baseDomain: string | undefined;\n if (process.env.CSS_BASE_URL) {\n try {\n const url = new URL(process.env.CSS_BASE_URL);\n baseDomain = url.hostname;\n } catch {\n console.warn('[Local] Invalid CSS_BASE_URL, cannot derive domain for DNS management');\n }\n }\n\n // DEBUG: 打印变量状态\n console.log(`[Local] Debug: apiToken=${apiToken ? '***' : 'undefined'}, baseDomain=${baseDomain}, CSS_BASE_URL=${process.env.CSS_BASE_URL}`);\n\n if (apiToken && baseDomain) {\n console.log('[Local] Self-hosted DNS mode detected (IPv6 Ready)');\n\n container.register({\n // DNS Provider\n dnsProvider: asFunction(() => {\n return new CloudflareDnsProvider({\n apiToken: apiToken!,\n });\n }).singleton(),\n\n // DNS Coordinator (DnsMaintainer)\n dnsCoordinator: asFunction(({ dnsProvider }: ApiContainerCradle) => {\n return new EdgeNodeDnsCoordinator({\n provider: dnsProvider!,\n rootDomain: baseDomain,\n });\n }).singleton(),\n\n // Network Detector\n capabilityDetector: asFunction(() => {\n return new EdgeNodeCapabilityDetector({\n dynamicDetection: { enableNetworkDetection: true },\n });\n }).singleton(),\n\n // Local Network Manager (Orchestrator)\n localNetworkManager: asFunction(({ capabilityDetector, dnsCoordinator }: ApiContainerCradle) => {\n return new LocalNetworkManager({\n detector: capabilityDetector!,\n dnsCoordinator: dnsCoordinator!,\n });\n }).singleton(),\n\n // Subdomain Service (Keep for API support)\n subdomainService: asFunction(({ dnsProvider, localTunnelProvider, nodeRepo }: ApiContainerCradle) => {\n // 如果没有配置 Tunnel Token,使用一个 Mock Provider\n const tunnelProvider = localTunnelProvider ?? {\n name: 'noop',\n setup: async () => { throw new Error('Tunnel not configured'); },\n start: async () => { throw new Error('Tunnel not configured'); },\n stop: async () => {},\n cleanup: async () => {},\n getStatus: () => ({ running: false, connected: false } as TunnelStatus),\n getEndpoint: () => undefined,\n } as TunnelProvider;\n\n return new SubdomainService({\n baseDomain: baseDomain!,\n dnsProvider: dnsProvider!,\n tunnelProvider,\n edgeNodeRepo: nodeRepo,\n });\n }).singleton(),\n });\n console.log(`[Local] Local DNS maintenance services registered for: ${baseDomain}`);\n // 继续进行后续逻辑,不要 return,因为用户可能既用了自管 DNS 又开启了 Managed Client\n }\n\n // 独立式:没有配置 Node Token,用户自己管理域名和 IdP\n if (!nodeToken) {\n console.log('[Local] Standalone mode (no XPOD_NODE_TOKEN)');\n console.log('[Local] User manages DNS and IdP externally');\n if (cloudflareTunnelToken) {\n console.log('[Local] Will start cloudflared with provided CLOUDFLARE_TUNNEL_TOKEN');\n }\n return;\n }\n\n // 托管式:有 Node Token,连接 Cloud\n // Cloud API endpoint 可以从 Token 解析或使用默认值\n const effectiveCloudApiEndpoint = cloudApiEndpoint || 'https://pods.undefineds.co';\n const effectiveLocalPort = parseInt(process.env.XPOD_MAIN_PORT || process.env.CSS_PORT || '3000', 10);\n\n // 从 Node Token 解析用户名作为子域名 (格式: username:secret)\n const subdomain = parseSubdomainFromToken(nodeToken);\n const tunnelProviderHint: 'cloudflare' | 'sakura_frp' | 'none' = cloudflareTunnelToken\n ? 'cloudflare'\n : sakuraTunnelToken\n ? 'sakura_frp'\n : 'none';\n\n container.register({\n subdomainClient: asFunction(() => {\n return new SubdomainClient({\n cloudApiEndpoint: effectiveCloudApiEndpoint,\n nodeId: nodeId || 'auto', // 可以从 Token 解析\n nodeToken: nodeToken!,\n });\n }).singleton(),\n\n // 注册网络检测器 (如果尚未注册)\n capabilityDetector: asFunction(() => {\n return new EdgeNodeCapabilityDetector({\n dynamicDetection: { enableNetworkDetection: true },\n });\n }).singleton(),\n\n // DDNS Manager: 自动分配和更新 DDNS\n ddnsManager: asFunction(({ subdomainClient, capabilityDetector }: ApiContainerCradle) => {\n return new DdnsManager({\n client: subdomainClient!,\n detector: capabilityDetector!,\n subdomain: subdomain || nodeId || 'auto',\n localPort: effectiveLocalPort,\n autoAllocate: true,\n tunnelProvider: tunnelProviderHint,\n });\n }).singleton(),\n });\n\n console.log('[Local] Managed mode, SubdomainClient and DdnsManager registered');\n console.log(`[Local] Cloud API endpoint: ${effectiveCloudApiEndpoint}`);\n if (subdomain) {\n console.log(`[Local] DDNS subdomain: ${subdomain}`);\n }\n if (config.oidcIssuer) {\n console.log(`[Local] Using Cloud IdP: ${config.oidcIssuer}`);\n }\n\n if (!cloudflareTunnelToken && !sakuraTunnelToken) {\n console.log('[Local] Note: No tunnel token configured, assuming direct network access');\n }\n}\n\n/**\n * 从 Node Token 解析子域名/用户名\n * Token 格式: username:secret 或 base64 编码\n */\nfunction parseSubdomainFromToken(token: string): string | undefined {\n // 尝试直接解析 username:secret 格式\n if (token.includes(':')) {\n const [username] = token.split(':');\n if (username && /^[a-z0-9][a-z0-9-]{0,61}[a-z0-9]$/.test(username)) {\n return username;\n }\n }\n\n // 尝试 base64 解码\n try {\n const decoded = Buffer.from(token, 'base64').toString('utf8');\n if (decoded.includes(':')) {\n const [username] = decoded.split(':');\n if (username && /^[a-z0-9][a-z0-9-]{0,61}[a-z0-9]$/.test(username)) {\n return username;\n }\n }\n } catch {\n // ignore\n }\n\n return undefined;\n}\n"]}
1
+ {"version":3,"file":"local.js","sourceRoot":"","sources":["../../../src/api/container/local.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Local 模式服务注册\n *\n * Local 模式有两种配置:\n * - 托管式 (managed): 配置 XPOD_NODE_TOKEN,自动连接 Cloud 获取身份服务和 DDNS\n * - 独立式 (standalone): 不配置 XPOD_NODE_TOKEN,用户自己配置 CSS_BASE_URL 和 IdP\n */\n\nimport { asFunction, type AwilixContainer } from 'awilix';\nimport type { ApiContainerCradle, ApiContainerConfig } from './types';\n\nimport { SubdomainClient } from '../../subdomain/SubdomainClient';\nimport { LocalTunnelProvider } from '../../tunnel/LocalTunnelProvider';\nimport { SakuraFrpTunnelProvider } from '../../tunnel/SakuraFrpTunnelProvider';\nimport { CloudflareDnsProvider } from '../../dns/cloudflare/CloudflareDnsProvider';\nimport { SubdomainService } from '../../subdomain/SubdomainService';\nimport { EdgeNodeDnsCoordinator } from '../../edge/EdgeNodeDnsCoordinator';\nimport { EdgeNodeCapabilityDetector } from '../../edge/EdgeNodeCapabilityDetector';\nimport { LocalNetworkManager } from '../../edge/LocalNetworkManager';\nimport { DdnsManager } from '../../edge/DdnsManager';\nimport type { TunnelProvider, TunnelStatus } from '../../tunnel/TunnelProvider';\nimport { PodLookupRepository } from '../../identity/drizzle/PodLookupRepository';\n\n/**\n * 注册 Local 模式专属服务\n */\nexport function registerLocalServices(\n container: AwilixContainer<ApiContainerCradle>,\n): void {\n const config = container.resolve('config') as ApiContainerConfig;\n\n const {\n cloudApiEndpoint,\n nodeId,\n nodeToken,\n cloudflareTunnelToken,\n sakuraTunnelToken,\n subdomain: subdomainConfig,\n } = config;\n\n container.register({\n podLookupRepo: asFunction(({ db }: ApiContainerCradle) => {\n return new PodLookupRepository(db);\n }).singleton(),\n });\n\n // 1. 注册 Tunnel Provider (优先 Cloudflare,其次 SakuraFRP)\n if (cloudflareTunnelToken) {\n container.register({\n localTunnelProvider: asFunction(() => {\n return new LocalTunnelProvider({\n tunnelToken: cloudflareTunnelToken,\n });\n }).singleton(),\n });\n console.log('[Local] Tunnel provider registered (CLOUDFLARE_TUNNEL_TOKEN configured)');\n } else if (sakuraTunnelToken) {\n container.register({\n localTunnelProvider: asFunction(() => {\n return new SakuraFrpTunnelProvider({\n token: sakuraTunnelToken,\n });\n }).singleton(),\n });\n console.log('[Local] Tunnel provider registered (SAKURA_TUNNEL_TOKEN configured)');\n }\n\n // 2. 自适应 DNS 管理 (Self-Hosted DNS)\n // 如果配置了 Cloudflare API Token 和 Base Domain,启用本地 DNS 管理\n const apiToken = subdomainConfig?.cloudflareApiToken;\n\n // 在 Local 模式下,强制使用 CSS_BASE_URL 作为域名来源\n // 简化用户配置心智\n let baseDomain: string | undefined;\n if (process.env.CSS_BASE_URL) {\n try {\n const url = new URL(process.env.CSS_BASE_URL);\n baseDomain = url.hostname;\n } catch {\n console.warn('[Local] Invalid CSS_BASE_URL, cannot derive domain for DNS management');\n }\n }\n\n // DEBUG: 打印变量状态\n console.log(`[Local] Debug: apiToken=${apiToken ? '***' : 'undefined'}, baseDomain=${baseDomain}, CSS_BASE_URL=${process.env.CSS_BASE_URL}`);\n\n if (apiToken && baseDomain) {\n console.log('[Local] Self-hosted DNS mode detected (IPv6 Ready)');\n\n container.register({\n // DNS Provider\n dnsProvider: asFunction(() => {\n return new CloudflareDnsProvider({\n apiToken: apiToken!,\n });\n }).singleton(),\n\n // DNS Coordinator (DnsMaintainer)\n dnsCoordinator: asFunction(({ dnsProvider }: ApiContainerCradle) => {\n return new EdgeNodeDnsCoordinator({\n provider: dnsProvider!,\n rootDomain: baseDomain,\n });\n }).singleton(),\n\n // Network Detector\n capabilityDetector: asFunction(() => {\n return new EdgeNodeCapabilityDetector({\n dynamicDetection: { enableNetworkDetection: true },\n });\n }).singleton(),\n\n // Local Network Manager (Orchestrator)\n localNetworkManager: asFunction(({ capabilityDetector, dnsCoordinator }: ApiContainerCradle) => {\n return new LocalNetworkManager({\n detector: capabilityDetector!,\n dnsCoordinator: dnsCoordinator!,\n });\n }).singleton(),\n\n // Subdomain Service (Keep for API support)\n subdomainService: asFunction(({ dnsProvider, localTunnelProvider, nodeRepo }: ApiContainerCradle) => {\n // 如果没有配置 Tunnel Token,使用一个 Mock Provider\n const tunnelProvider = localTunnelProvider ?? {\n name: 'noop',\n setup: async () => { throw new Error('Tunnel not configured'); },\n start: async () => { throw new Error('Tunnel not configured'); },\n stop: async () => {},\n cleanup: async () => {},\n getStatus: () => ({ running: false, connected: false } as TunnelStatus),\n getEndpoint: () => undefined,\n } as TunnelProvider;\n\n return new SubdomainService({\n baseDomain: baseDomain!,\n dnsProvider: dnsProvider!,\n tunnelProvider,\n edgeNodeRepo: nodeRepo,\n });\n }).singleton(),\n });\n console.log(`[Local] Local DNS maintenance services registered for: ${baseDomain}`);\n // 继续进行后续逻辑,不要 return,因为用户可能既用了自管 DNS 又开启了 Managed Client\n }\n\n // 独立式:没有配置 Node Token,用户自己管理域名和 IdP\n if (!nodeToken) {\n console.log('[Local] Standalone mode (no XPOD_NODE_TOKEN)');\n console.log('[Local] User manages DNS and IdP externally');\n if (cloudflareTunnelToken) {\n console.log('[Local] Will start cloudflared with provided CLOUDFLARE_TUNNEL_TOKEN');\n }\n return;\n }\n\n // 托管式:有 Node Token,连接 Cloud\n // Cloud API endpoint 可以从 Token 解析或使用默认值\n const effectiveCloudApiEndpoint = cloudApiEndpoint || 'https://pods.undefineds.co';\n const effectiveLocalPort = parseInt(process.env.XPOD_MAIN_PORT || process.env.CSS_PORT || '3000', 10);\n\n // 从 Node Token 解析用户名作为子域名 (格式: username:secret)\n const subdomain = parseSubdomainFromToken(nodeToken);\n const tunnelProviderHint: 'cloudflare' | 'sakura_frp' | 'none' = cloudflareTunnelToken\n ? 'cloudflare'\n : sakuraTunnelToken\n ? 'sakura_frp'\n : 'none';\n\n container.register({\n subdomainClient: asFunction(() => {\n return new SubdomainClient({\n cloudApiEndpoint: effectiveCloudApiEndpoint,\n nodeId: nodeId || 'auto', // 可以从 Token 解析\n nodeToken: nodeToken!,\n });\n }).singleton(),\n\n // 注册网络检测器 (如果尚未注册)\n capabilityDetector: asFunction(() => {\n return new EdgeNodeCapabilityDetector({\n dynamicDetection: { enableNetworkDetection: true },\n });\n }).singleton(),\n\n // DDNS Manager: 自动分配和更新 DDNS\n ddnsManager: asFunction(({ subdomainClient, capabilityDetector }: ApiContainerCradle) => {\n return new DdnsManager({\n client: subdomainClient!,\n detector: capabilityDetector!,\n subdomain: subdomain || nodeId || 'auto',\n localPort: effectiveLocalPort,\n autoAllocate: true,\n tunnelProvider: tunnelProviderHint,\n });\n }).singleton(),\n });\n\n console.log('[Local] Managed mode, SubdomainClient and DdnsManager registered');\n console.log(`[Local] Cloud API endpoint: ${effectiveCloudApiEndpoint}`);\n if (subdomain) {\n console.log(`[Local] DDNS subdomain: ${subdomain}`);\n }\n if (config.oidcIssuer) {\n console.log(`[Local] Using Cloud IdP: ${config.oidcIssuer}`);\n }\n\n if (!cloudflareTunnelToken && !sakuraTunnelToken) {\n console.log('[Local] Note: No tunnel token configured, assuming direct network access');\n }\n}\n\n/**\n * 从 Node Token 解析子域名/用户名\n * Token 格式: username:secret 或 base64 编码\n */\nfunction parseSubdomainFromToken(token: string): string | undefined {\n // 尝试直接解析 username:secret 格式\n if (token.includes(':')) {\n const [username] = token.split(':');\n if (username && /^[a-z0-9][a-z0-9-]{0,61}[a-z0-9]$/.test(username)) {\n return username;\n }\n }\n\n // 尝试 base64 解码\n try {\n const decoded = Buffer.from(token, 'base64').toString('utf8');\n if (decoded.includes(':')) {\n const [username] = decoded.split(':');\n if (username && /^[a-z0-9][a-z0-9-]{0,61}[a-z0-9]$/.test(username)) {\n return username;\n }\n }\n } catch {\n // ignore\n }\n\n return undefined;\n}\n"]}
@@ -35,7 +35,6 @@ const ChatHandler_1 = require("../handlers/ChatHandler");
35
35
  const ApiKeyHandler_1 = require("../handlers/ApiKeyHandler");
36
36
  const SubdomainHandler_1 = require("../handlers/SubdomainHandler");
37
37
  const SubdomainClientHandler_1 = require("../handlers/SubdomainClientHandler");
38
- const WebIdProfileHandler_1 = require("../handlers/WebIdProfileHandler");
39
38
  const DdnsHandler_1 = require("../handlers/DdnsHandler");
40
39
  const ChatKitHandler_1 = require("../handlers/ChatKitHandler");
41
40
  const ChatKitV1Handler_1 = require("../handlers/ChatKitV1Handler");
@@ -122,20 +121,6 @@ function registerSharedRoutes(container, server) {
122
121
  taskScheduler: inngestTaskScheduler,
123
122
  runtimeConfig: inngestRuntimeConfig,
124
123
  });
125
- try {
126
- const profileRepo = container.resolve('webIdProfileRepo', { allowUnregistered: true });
127
- const podLookupRepo = container.resolve('podLookupRepo', { allowUnregistered: true });
128
- if (profileRepo) {
129
- (0, WebIdProfileHandler_1.registerWebIdProfileRoutes)(server, {
130
- profileRepo: profileRepo,
131
- podLookupRepo: podLookupRepo,
132
- });
133
- console.log('[Shared] WebID Profile routes registered');
134
- }
135
- }
136
- catch {
137
- console.log('[Shared] WebID Profile routes not registered (repo not available)');
138
- }
139
124
  // Quota & Usage API (Business 对接)
140
125
  try {
141
126
  const quotaService = new DrizzleQuotaService_1.DrizzleQuotaService({ identityDbUrl: config.databaseUrl });
@@ -252,15 +237,16 @@ function registerLocalRoutes(container, server) {
252
237
  rootDir,
253
238
  sparqlEndpoint,
254
239
  identityDbUrl,
255
- oidcIssuer: process.env.CSS_OIDC_ISSUER ?? config.oidcIssuer,
240
+ oidcIssuer: process.env.oidcIssuer ?? config.oidcIssuer,
256
241
  })
257
242
  : undefined;
258
243
  (0, PodManagementHandler_1.registerPodManagementRoutes)(server, {
259
244
  rootDir,
260
245
  verifyServiceToken: async (token) => token === expectedServiceToken,
261
246
  provisioningService,
247
+ podLookupRepository: container.resolve('podLookupRepo', { allowUnregistered: true }),
262
248
  });
263
- console.log(`[Local] Pod provision routes registered (/provision/pods, ${provisioningService ? 'css-compatible' : 'directory-only'})`);
249
+ console.log(`[Local] Pod provision routes registered (/provision/pods, /provision/webids, ${provisioningService ? 'css-compatible' : 'directory-only'})`);
264
250
  }
265
251
  else {
266
252
  console.log('[Local] Pod provision routes not registered (XPOD_SERVICE_TOKEN not configured)');
@@ -1 +1 @@
1
- {"version":3,"file":"routes.js","sourceRoot":"","sources":["../../../src/api/container/routes.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * 路由注册\n *\n * 根据容器中的服务注册 API 路由\n */\n\nimport type { AwilixContainer } from 'awilix';\nimport type { ApiContainerCradle, ApiContainerConfig } from './types';\nimport type { ApiServer } from '../ApiServer';\n\nimport { registerEdgeNodeSignalRoutes } from '../handlers/EdgeNodeSignalHandler';\nimport { registerNodeRoutes } from '../handlers/NodeHandler';\nimport { registerChatRoutes } from '../handlers/ChatHandler';\nimport { registerApiKeyRoutes } from '../handlers/ApiKeyHandler';\nimport { registerSubdomainRoutes } from '../handlers/SubdomainHandler';\nimport { registerSubdomainClientRoutes } from '../handlers/SubdomainClientHandler';\nimport { registerWebIdProfileRoutes } from '../handlers/WebIdProfileHandler';\nimport { registerDdnsRoutes } from '../handlers/DdnsHandler';\nimport { registerChatKitRoutes } from '../handlers/ChatKitHandler';\nimport { registerChatKitV1Routes } from '../handlers/ChatKitV1Handler';\nimport { registerInngestRoutes } from '../handlers/InngestHandler';\nimport { registerRunRoutes } from '../handlers/RunHandler';\nimport { registerMatrixRoutes } from '../handlers/MatrixHandler';\nimport { registerDashboardRoutes } from '../handlers/DashboardHandler';\nimport { registerAdminRoutes } from '../handlers/AdminHandler';\nimport { registerAdminDdnsRoutes } from '../handlers/AdminDdnsHandler';\nimport { registerLinxCapabilitiesRoutes } from '../handlers/LinxCapabilitiesHandler';\nimport { registerProvisionRoutes, registerProvisionStatusRoute } from '../handlers/ProvisionHandler';\nimport { registerPodManagementRoutes } from '../handlers/PodManagementHandler';\nimport { registerQuotaRoutes } from '../handlers/QuotaHandler';\nimport { registerUsageRoutes } from '../handlers/UsageHandler';\nimport type { EdgeNodeRepository } from '../../identity/drizzle/EdgeNodeRepository';\nimport type { DrizzleClientCredentialsStore } from '../store/DrizzleClientCredentialsStore';\nimport { UsageRepository } from '../../storage/quota/UsageRepository';\nimport { DrizzleQuotaService } from '../../quota/DrizzleQuotaService';\nimport { LocalPodProvisioningService } from '../../provision/LocalPodProvisioningService';\nimport * as path from 'node:path';\nimport { PACKAGE_ROOT } from '../../runtime';\n\n/**\n * 注册所有 API 路由\n */\nexport function registerRoutes(container: AwilixContainer<ApiContainerCradle>): void {\n const server = container.resolve('apiServer') as ApiServer;\n const config = container.resolve('config') as ApiContainerConfig;\n\n // 公共健康检查端点\n registerHealthRoutes(server);\n\n // 共享路由\n registerSharedRoutes(container, server);\n\n // 根据 edition 注册专属路由\n if (config.edition === 'cloud') {\n registerCloudRoutes(container, server);\n } else {\n registerLocalRoutes(container, server);\n }\n}\n\n/**\n * 健康检查路由\n */\nfunction registerHealthRoutes(server: ApiServer): void {\n server.get('/health', async (_req, res) => {\n res.statusCode = 200;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ status: 'ok' }));\n }, { public: true });\n\n server.get('/ready', async (_req, res) => {\n res.statusCode = 200;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ status: 'ready' }));\n }, { public: true });\n\n // Dashboard 静态资源\n const staticDir = path.resolve(PACKAGE_ROOT, 'static/dashboard');\n registerDashboardRoutes(server, { staticDir });\n}\n\n/**\n * 共享路由 (cloud 和 local 都有)\n */\nfunction registerSharedRoutes(\n container: AwilixContainer<ApiContainerCradle>,\n server: ApiServer,\n): void {\n const nodeRepo = container.resolve('nodeRepo') as EdgeNodeRepository;\n const apiKeyStore = container.resolve('apiKeyStore') as DrizzleClientCredentialsStore;\n const chatService = container.resolve('chatService');\n const chatKitService = container.resolve('chatKitService');\n const chatKitStore = container.resolve('chatKitStore');\n const runExecutionBackend = container.resolve('runExecutionBackend');\n const matrixStore = container.resolve('matrixStore');\n const inngestTaskScheduler = container.resolve('inngestTaskScheduler');\n const inngestRuntimeConfig = container.resolve('inngestRuntimeConfig');\n const config = container.resolve('config') as ApiContainerConfig;\n\n registerEdgeNodeSignalRoutes(server, {\n repository: nodeRepo,\n dnsCoordinator: container.resolve('dnsCoordinator', { allowUnregistered: true }) as any,\n healthProbeService: container.resolve('healthProbeService', { allowUnregistered: true }) as any,\n });\n registerNodeRoutes(server, { repository: nodeRepo });\n registerApiKeyRoutes(server, { store: apiKeyStore });\n registerChatRoutes(server, { chatService });\n registerChatKitRoutes(server, { chatKitService });\n registerChatKitV1Routes(server, { store: chatKitStore });\n registerRunRoutes(server, { runStore: chatKitStore });\n registerMatrixRoutes(server, { store: matrixStore });\n registerInngestRoutes(server, {\n backend: runExecutionBackend,\n taskScheduler: inngestTaskScheduler,\n runtimeConfig: inngestRuntimeConfig,\n });\n\n try {\n const profileRepo = container.resolve('webIdProfileRepo', { allowUnregistered: true });\n const podLookupRepo = container.resolve('podLookupRepo', { allowUnregistered: true });\n if (profileRepo) {\n registerWebIdProfileRoutes(server, {\n profileRepo: profileRepo as any,\n podLookupRepo: podLookupRepo as any,\n });\n console.log('[Shared] WebID Profile routes registered');\n }\n } catch {\n console.log('[Shared] WebID Profile routes not registered (repo not available)');\n }\n\n // Quota & Usage API (Business 对接)\n try {\n const quotaService = new DrizzleQuotaService({ identityDbUrl: config.databaseUrl });\n const usageRepo = new UsageRepository(container.resolve('db'));\n registerQuotaRoutes(server, { quotaService, usageRepo });\n registerUsageRoutes(server, { usageRepo });\n console.log('[Shared] Quota & Usage routes registered');\n } catch (error) {\n console.log(`[Shared] Quota & Usage routes not registered: ${error}`);\n }\n}\n\n/**\n * Cloud 模式专属路由\n */\nfunction registerCloudRoutes(\n container: AwilixContainer<ApiContainerCradle>,\n server: ApiServer,\n): void {\n // 子域名管理 API (需要 SubdomainService)\n try {\n const subdomainService = container.resolve('subdomainService') as ApiContainerCradle['subdomainService'];\n if (subdomainService) {\n registerSubdomainRoutes(server, { subdomainService });\n console.log('[Cloud] Subdomain routes registered');\n }\n } catch {\n console.log('[Cloud] Subdomain routes not registered (service not available)');\n }\n\n // DDNS 服务\n try {\n const ddnsRepo = container.resolve('ddnsRepo', { allowUnregistered: true });\n const dnsProvider = container.resolve('dnsProvider', { allowUnregistered: true });\n const config = container.resolve('config') as ApiContainerConfig;\n\n if (ddnsRepo) {\n const baseStorageDomain = config.subdomain?.baseStorageDomain;\n if (baseStorageDomain) {\n registerDdnsRoutes(server, {\n ddnsRepo: ddnsRepo as any,\n dnsProvider: dnsProvider as any,\n defaultDomain: baseStorageDomain,\n });\n console.log(`[Cloud] DDNS routes registered (domain: ${baseStorageDomain})`);\n } else {\n console.log('[Cloud] DDNS routes not registered (no CSS_BASE_STORAGE_DOMAIN)');\n }\n }\n } catch {\n console.log('[Cloud] DDNS routes not registered (repo not available)');\n }\n\n // SP Provision API (SP 注册)\n try {\n const nodeRepo = container.resolve('nodeRepo') as EdgeNodeRepository;\n const config = container.resolve('config') as ApiContainerConfig;\n const baseUrl = process.env.CSS_BASE_URL || 'http://localhost:3000/';\n const baseStorageDomain = config.subdomain?.baseStorageDomain;\n const ddnsRepo = container.resolve('ddnsRepo', { allowUnregistered: true }) as any;\n const dnsProvider = container.resolve('dnsProvider', { allowUnregistered: true }) as any;\n const tunnelProvider = container.resolve('tunnelProvider', { allowUnregistered: true }) as any;\n registerProvisionRoutes(server, {\n repository: nodeRepo,\n ddnsRepo,\n dnsProvider,\n tunnelProvider,\n baseUrl,\n baseStorageDomain,\n });\n console.log(`[Cloud] Provision routes registered${baseStorageDomain ? ` (baseStorageDomain: ${baseStorageDomain})` : ''}`);\n } catch {\n console.log('[Cloud] Provision routes not registered (dependencies not available)');\n }\n}\n\n/**\n * Local 模式专属路由\n */\nfunction registerLocalRoutes(\n container: AwilixContainer<ApiContainerCradle>,\n server: ApiServer,\n): void {\n registerLinxCapabilitiesRoutes(server);\n\n // Admin API (配置管理、重启)\n registerAdminRoutes(server);\n\n // DDNS status (托管式 Local 模式)\n try {\n const ddnsManager = container.resolve('ddnsManager', { allowUnregistered: true }) as any;\n registerAdminDdnsRoutes(server, { ddnsManager });\n } catch {\n // ignore\n }\n\n // 子域名客户端 API (通过 SubdomainClient 调用 Cloud)\n try {\n const subdomainClient = container.resolve('subdomainClient') as ApiContainerCradle['subdomainClient'];\n if (subdomainClient) {\n registerSubdomainClientRoutes(server, { subdomainClient });\n console.log('[Local] Subdomain client routes registered');\n }\n } catch {\n console.log('[Local] Subdomain client routes not registered (client not available)');\n }\n\n // Pod Provision API (SP 端,供 Cloud 回调创建 Pod)\n try {\n // rootDir: CSS 数据目录,默认 ./data\n const rootDir = process.env.CSS_ROOT_FILE_PATH || './data';\n // serviceToken 验证:从 SP 配置中读取\n const expectedServiceToken = process.env.XPOD_SERVICE_TOKEN;\n\n if (expectedServiceToken) {\n const config = container.resolve('config') as ApiContainerConfig;\n const baseUrl = process.env.CSS_BASE_URL || 'http://localhost:3000/';\n const sparqlEndpoint = process.env.CSS_SPARQL_ENDPOINT || process.env.SPARQL_ENDPOINT;\n const identityDbUrl = process.env.CSS_IDENTITY_DB_URL || process.env.DATABASE_URL;\n const provisioningService = sparqlEndpoint && identityDbUrl\n ? new LocalPodProvisioningService({\n baseUrl,\n rootDir,\n sparqlEndpoint,\n identityDbUrl,\n oidcIssuer: process.env.CSS_OIDC_ISSUER ?? config.oidcIssuer,\n })\n : undefined;\n\n registerPodManagementRoutes(server, {\n rootDir,\n verifyServiceToken: async (token: string) => token === expectedServiceToken,\n provisioningService,\n });\n console.log(`[Local] Pod provision routes registered (/provision/pods, ${provisioningService ? 'css-compatible' : 'directory-only'})`);\n } else {\n console.log('[Local] Pod provision routes not registered (XPOD_SERVICE_TOKEN not configured)');\n }\n } catch (error) {\n console.log(`[Local] Pod provision routes not registered: ${error}`);\n }\n\n // SP 状态查询 (供 Linx 查询 SP 配置状态)\n try {\n const config = container.resolve('config') as ApiContainerConfig;\n registerProvisionStatusRoute(server, {\n cloudUrl: config.cloudApiEndpoint,\n nodeId: config.nodeId,\n cloudBaseUrl: config.oidcIssuer || config.cloudApiEndpoint,\n });\n console.log('[Local] Provision status route registered (/provision/status)');\n } catch (error) {\n console.log(`[Local] Provision status route not registered: ${error}`);\n }\n}\n"]}
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../../../src/api/container/routes.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * 路由注册\n *\n * 根据容器中的服务注册 API 路由\n */\n\nimport type { AwilixContainer } from 'awilix';\nimport type { ApiContainerCradle, ApiContainerConfig } from './types';\nimport type { ApiServer } from '../ApiServer';\n\nimport { registerEdgeNodeSignalRoutes } from '../handlers/EdgeNodeSignalHandler';\nimport { registerNodeRoutes } from '../handlers/NodeHandler';\nimport { registerChatRoutes } from '../handlers/ChatHandler';\nimport { registerApiKeyRoutes } from '../handlers/ApiKeyHandler';\nimport { registerSubdomainRoutes } from '../handlers/SubdomainHandler';\nimport { registerSubdomainClientRoutes } from '../handlers/SubdomainClientHandler';\nimport { registerDdnsRoutes } from '../handlers/DdnsHandler';\nimport { registerChatKitRoutes } from '../handlers/ChatKitHandler';\nimport { registerChatKitV1Routes } from '../handlers/ChatKitV1Handler';\nimport { registerInngestRoutes } from '../handlers/InngestHandler';\nimport { registerRunRoutes } from '../handlers/RunHandler';\nimport { registerMatrixRoutes } from '../handlers/MatrixHandler';\nimport { registerDashboardRoutes } from '../handlers/DashboardHandler';\nimport { registerAdminRoutes } from '../handlers/AdminHandler';\nimport { registerAdminDdnsRoutes } from '../handlers/AdminDdnsHandler';\nimport { registerLinxCapabilitiesRoutes } from '../handlers/LinxCapabilitiesHandler';\nimport { registerProvisionRoutes, registerProvisionStatusRoute } from '../handlers/ProvisionHandler';\nimport { registerPodManagementRoutes } from '../handlers/PodManagementHandler';\nimport { registerQuotaRoutes } from '../handlers/QuotaHandler';\nimport { registerUsageRoutes } from '../handlers/UsageHandler';\nimport type { EdgeNodeRepository } from '../../identity/drizzle/EdgeNodeRepository';\nimport type { DrizzleClientCredentialsStore } from '../store/DrizzleClientCredentialsStore';\nimport { UsageRepository } from '../../storage/quota/UsageRepository';\nimport { DrizzleQuotaService } from '../../quota/DrizzleQuotaService';\nimport { LocalPodProvisioningService } from '../../provision/LocalPodProvisioningService';\nimport * as path from 'node:path';\nimport { PACKAGE_ROOT } from '../../runtime';\n\n/**\n * 注册所有 API 路由\n */\nexport function registerRoutes(container: AwilixContainer<ApiContainerCradle>): void {\n const server = container.resolve('apiServer') as ApiServer;\n const config = container.resolve('config') as ApiContainerConfig;\n\n // 公共健康检查端点\n registerHealthRoutes(server);\n\n // 共享路由\n registerSharedRoutes(container, server);\n\n // 根据 edition 注册专属路由\n if (config.edition === 'cloud') {\n registerCloudRoutes(container, server);\n } else {\n registerLocalRoutes(container, server);\n }\n}\n\n/**\n * 健康检查路由\n */\nfunction registerHealthRoutes(server: ApiServer): void {\n server.get('/health', async (_req, res) => {\n res.statusCode = 200;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ status: 'ok' }));\n }, { public: true });\n\n server.get('/ready', async (_req, res) => {\n res.statusCode = 200;\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ status: 'ready' }));\n }, { public: true });\n\n // Dashboard 静态资源\n const staticDir = path.resolve(PACKAGE_ROOT, 'static/dashboard');\n registerDashboardRoutes(server, { staticDir });\n}\n\n/**\n * 共享路由 (cloud 和 local 都有)\n */\nfunction registerSharedRoutes(\n container: AwilixContainer<ApiContainerCradle>,\n server: ApiServer,\n): void {\n const nodeRepo = container.resolve('nodeRepo') as EdgeNodeRepository;\n const apiKeyStore = container.resolve('apiKeyStore') as DrizzleClientCredentialsStore;\n const chatService = container.resolve('chatService');\n const chatKitService = container.resolve('chatKitService');\n const chatKitStore = container.resolve('chatKitStore');\n const runExecutionBackend = container.resolve('runExecutionBackend');\n const matrixStore = container.resolve('matrixStore');\n const inngestTaskScheduler = container.resolve('inngestTaskScheduler');\n const inngestRuntimeConfig = container.resolve('inngestRuntimeConfig');\n const config = container.resolve('config') as ApiContainerConfig;\n\n registerEdgeNodeSignalRoutes(server, {\n repository: nodeRepo,\n dnsCoordinator: container.resolve('dnsCoordinator', { allowUnregistered: true }) as any,\n healthProbeService: container.resolve('healthProbeService', { allowUnregistered: true }) as any,\n });\n registerNodeRoutes(server, { repository: nodeRepo });\n registerApiKeyRoutes(server, { store: apiKeyStore });\n registerChatRoutes(server, { chatService });\n registerChatKitRoutes(server, { chatKitService });\n registerChatKitV1Routes(server, { store: chatKitStore });\n registerRunRoutes(server, { runStore: chatKitStore });\n registerMatrixRoutes(server, { store: matrixStore });\n registerInngestRoutes(server, {\n backend: runExecutionBackend,\n taskScheduler: inngestTaskScheduler,\n runtimeConfig: inngestRuntimeConfig,\n });\n\n // Quota & Usage API (Business 对接)\n try {\n const quotaService = new DrizzleQuotaService({ identityDbUrl: config.databaseUrl });\n const usageRepo = new UsageRepository(container.resolve('db'));\n registerQuotaRoutes(server, { quotaService, usageRepo });\n registerUsageRoutes(server, { usageRepo });\n console.log('[Shared] Quota & Usage routes registered');\n } catch (error) {\n console.log(`[Shared] Quota & Usage routes not registered: ${error}`);\n }\n}\n\n/**\n * Cloud 模式专属路由\n */\nfunction registerCloudRoutes(\n container: AwilixContainer<ApiContainerCradle>,\n server: ApiServer,\n): void {\n // 子域名管理 API (需要 SubdomainService)\n try {\n const subdomainService = container.resolve('subdomainService') as ApiContainerCradle['subdomainService'];\n if (subdomainService) {\n registerSubdomainRoutes(server, { subdomainService });\n console.log('[Cloud] Subdomain routes registered');\n }\n } catch {\n console.log('[Cloud] Subdomain routes not registered (service not available)');\n }\n\n // DDNS 服务\n try {\n const ddnsRepo = container.resolve('ddnsRepo', { allowUnregistered: true });\n const dnsProvider = container.resolve('dnsProvider', { allowUnregistered: true });\n const config = container.resolve('config') as ApiContainerConfig;\n\n if (ddnsRepo) {\n const baseStorageDomain = config.subdomain?.baseStorageDomain;\n if (baseStorageDomain) {\n registerDdnsRoutes(server, {\n ddnsRepo: ddnsRepo as any,\n dnsProvider: dnsProvider as any,\n defaultDomain: baseStorageDomain,\n });\n console.log(`[Cloud] DDNS routes registered (domain: ${baseStorageDomain})`);\n } else {\n console.log('[Cloud] DDNS routes not registered (no CSS_BASE_STORAGE_DOMAIN)');\n }\n }\n } catch {\n console.log('[Cloud] DDNS routes not registered (repo not available)');\n }\n\n // SP Provision API (SP 注册)\n try {\n const nodeRepo = container.resolve('nodeRepo') as EdgeNodeRepository;\n const config = container.resolve('config') as ApiContainerConfig;\n const baseUrl = process.env.CSS_BASE_URL || 'http://localhost:3000/';\n const baseStorageDomain = config.subdomain?.baseStorageDomain;\n const ddnsRepo = container.resolve('ddnsRepo', { allowUnregistered: true }) as any;\n const dnsProvider = container.resolve('dnsProvider', { allowUnregistered: true }) as any;\n const tunnelProvider = container.resolve('tunnelProvider', { allowUnregistered: true }) as any;\n registerProvisionRoutes(server, {\n repository: nodeRepo,\n ddnsRepo,\n dnsProvider,\n tunnelProvider,\n baseUrl,\n baseStorageDomain,\n });\n console.log(`[Cloud] Provision routes registered${baseStorageDomain ? ` (baseStorageDomain: ${baseStorageDomain})` : ''}`);\n } catch {\n console.log('[Cloud] Provision routes not registered (dependencies not available)');\n }\n}\n\n/**\n * Local 模式专属路由\n */\nfunction registerLocalRoutes(\n container: AwilixContainer<ApiContainerCradle>,\n server: ApiServer,\n): void {\n registerLinxCapabilitiesRoutes(server);\n\n // Admin API (配置管理、重启)\n registerAdminRoutes(server);\n\n // DDNS status (托管式 Local 模式)\n try {\n const ddnsManager = container.resolve('ddnsManager', { allowUnregistered: true }) as any;\n registerAdminDdnsRoutes(server, { ddnsManager });\n } catch {\n // ignore\n }\n\n // 子域名客户端 API (通过 SubdomainClient 调用 Cloud)\n try {\n const subdomainClient = container.resolve('subdomainClient') as ApiContainerCradle['subdomainClient'];\n if (subdomainClient) {\n registerSubdomainClientRoutes(server, { subdomainClient });\n console.log('[Local] Subdomain client routes registered');\n }\n } catch {\n console.log('[Local] Subdomain client routes not registered (client not available)');\n }\n\n // Pod Provision API (SP 端,供 Cloud 回调创建 Pod)\n try {\n // rootDir: CSS 数据目录,默认 ./data\n const rootDir = process.env.CSS_ROOT_FILE_PATH || './data';\n // serviceToken 验证:从 SP 配置中读取\n const expectedServiceToken = process.env.XPOD_SERVICE_TOKEN;\n\n if (expectedServiceToken) {\n const config = container.resolve('config') as ApiContainerConfig;\n const baseUrl = process.env.CSS_BASE_URL || 'http://localhost:3000/';\n const sparqlEndpoint = process.env.CSS_SPARQL_ENDPOINT || process.env.SPARQL_ENDPOINT;\n const identityDbUrl = process.env.CSS_IDENTITY_DB_URL || process.env.DATABASE_URL;\n const provisioningService = sparqlEndpoint && identityDbUrl\n ? new LocalPodProvisioningService({\n baseUrl,\n rootDir,\n sparqlEndpoint,\n identityDbUrl,\n oidcIssuer: process.env.oidcIssuer ?? config.oidcIssuer,\n })\n : undefined;\n\n registerPodManagementRoutes(server, {\n rootDir,\n verifyServiceToken: async (token: string) => token === expectedServiceToken,\n provisioningService,\n podLookupRepository: container.resolve('podLookupRepo', { allowUnregistered: true }),\n });\n console.log(`[Local] Pod provision routes registered (/provision/pods, /provision/webids, ${provisioningService ? 'css-compatible' : 'directory-only'})`);\n } else {\n console.log('[Local] Pod provision routes not registered (XPOD_SERVICE_TOKEN not configured)');\n }\n } catch (error) {\n console.log(`[Local] Pod provision routes not registered: ${error}`);\n }\n\n // SP 状态查询 (供 Linx 查询 SP 配置状态)\n try {\n const config = container.resolve('config') as ApiContainerConfig;\n registerProvisionStatusRoute(server, {\n cloudUrl: config.cloudApiEndpoint,\n nodeId: config.nodeId,\n cloudBaseUrl: config.oidcIssuer || config.cloudApiEndpoint,\n });\n console.log('[Local] Provision status route registered (/provision/status)');\n } catch (error) {\n console.log(`[Local] Provision status route not registered: ${error}`);\n }\n}\n"]}
@@ -15,7 +15,6 @@ import type { SubdomainClient } from '../../subdomain/SubdomainClient';
15
15
  import type { DnsProvider } from '../../dns/DnsProvider';
16
16
  import type { TunnelProvider } from '../../tunnel/TunnelProvider';
17
17
  import type { IdentityDatabase } from '../../identity/drizzle/db';
18
- import type { WebIdProfileRepository } from '../../identity/drizzle/WebIdProfileRepository';
19
18
  import type { DdnsRepository } from '../../identity/drizzle/DdnsRepository';
20
19
  import type { PodLookupRepository } from '../../identity/drizzle/PodLookupRepository';
21
20
  import type { ChatKitService, AiProvider } from '../chatkit';
@@ -120,7 +119,6 @@ export interface ApiContainerCradle {
120
119
  providerRegistry: ProviderRegistry;
121
120
  embeddingService: EmbeddingService;
122
121
  vectorService: VectorService;
123
- webIdProfileRepo?: WebIdProfileRepository;
124
122
  ddnsRepo?: DdnsRepository;
125
123
  podLookupRepo?: PodLookupRepository;
126
124
  dnsProvider?: DnsProvider;
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/api/container/types.ts"],"names":[],"mappings":";AAAA;;;;GAIG","sourcesContent":["/**\n * API Container 依赖类型定义\n *\n * 定义容器中注册的所有服务接口\n */\n\nimport type { ApiServer } from '../ApiServer';\nimport type { AuthMiddleware } from '../middleware/AuthMiddleware';\nimport type { Authenticator } from '../auth/Authenticator';\nimport type { EdgeNodeRepository } from '../../identity/drizzle/EdgeNodeRepository';\nimport type { ServiceTokenRepository } from '../../identity/drizzle/ServiceTokenRepository';\nimport type { DrizzleClientCredentialsStore } from '../store/DrizzleClientCredentialsStore';\nimport type { VercelChatService } from '../service/VercelChatService';\nimport type { SubdomainService } from '../../subdomain/SubdomainService';\nimport type { SubdomainClient } from '../../subdomain/SubdomainClient';\nimport type { DnsProvider } from '../../dns/DnsProvider';\nimport type { TunnelProvider } from '../../tunnel/TunnelProvider';\nimport type { IdentityDatabase } from '../../identity/drizzle/db';\nimport type { WebIdProfileRepository } from '../../identity/drizzle/WebIdProfileRepository';\nimport type { DdnsRepository } from '../../identity/drizzle/DdnsRepository';\nimport type { PodLookupRepository } from '../../identity/drizzle/PodLookupRepository';\nimport type { ChatKitService, AiProvider } from '../chatkit';\nimport type { StoreContext } from '../chatkit/store';\nimport type { PodChatKitStore } from '../chatkit/pod-store';\nimport type { RuntimeHost } from '../../runtime/host/types';\nimport type { ProviderRegistry, EmbeddingService } from '../../ai/service';\nimport type { VectorService } from '../service/VectorService';\nimport type { InngestRunExecutionBackend } from '../runs/InngestRunExecutionBackend';\nimport type { EmbeddedInngestRuntimeConfig } from '../runs/EmbeddedInngestService';\nimport type { RunAuthContextRegistry } from '../runs/RunAuthContextRegistry';\nimport type { TaskAuthBindingService, TaskService, InngestTaskScheduler } from '../tasks';\nimport type { PodMatrixStore } from '../matrix';\n\n/**\n * 容器配置\n */\nexport interface ApiContainerConfig {\n /** 运行模式: cloud 持有密钥, local 调用远程 */\n edition: 'cloud' | 'local';\n\n /** API Server 端口 */\n port: number;\n\n /** API Server 主机 */\n host: string;\n\n /** API Server Unix socket 路径 */\n socketPath?: string;\n\n /** Runtime host implementation */\n runtimeHost?: RuntimeHost;\n /** 数据库连接 URL */\n databaseUrl: string;\n\n /** Redis connection URL, used by embedded infrastructure such as Inngest in cloud mode. */\n redisUrl?: string;\n\n /** Embedded Inngest runtime configuration. */\n inngest?: {\n enabled: boolean;\n mode?: 'managed' | 'spawn';\n port?: number;\n host?: string;\n baseUrl?: string;\n eventKey?: string;\n signingKey?: string;\n binaryPath?: string;\n sqliteDir?: string;\n };\n\n /** Resolved runtime config passed from API bootstrap after starting/locating Inngest. */\n inngestRuntimeConfig?: EmbeddedInngestRuntimeConfig;\n\n /** CORS 允许的源 */\n corsOrigins: string[];\n\n /** CSS Token 端点 */\n cssTokenEndpoint: string;\n\n /** 子域名功能配置 (cloud 模式) */\n subdomain?: {\n /** 节点域名根域名 (如 undefineds.site),有值即启用子域名功能 */\n baseStorageDomain?: string;\n cloudflareAccountId?: string;\n cloudflareApiToken?: string;\n tencentDnsSecretId?: string;\n tencentDnsSecretKey?: string;\n };\n\n /** Cloud API 端点 (local 托管式,调用 cloud 的子域名 API) */\n cloudApiEndpoint?: string;\n\n /** 节点 ID (local 托管式) */\n nodeId?: string;\n\n /** 节点 Token (local 托管式,调用 Cloud API 的认证) */\n nodeToken?: string;\n\n /** OIDC Issuer URL (local 托管式,使用 Cloud IdP) */\n oidcIssuer?: string;\n\n /** Cloudflare Tunnel Token (local 托管式/自管式,启动 cloudflared) */\n cloudflareTunnelToken?: string;\n\n /** SakuraFRP Tunnel Token (SAKURA_TUNNEL_TOKEN;local 托管式/自管式,启动 frpc) */\n sakuraTunnelToken?: string;\n\n /** 是否接受 Edge 节点注册 (cloud 模式) */\n edgeNodesEnabled?: boolean;\n}\n\nimport { EdgeNodeDnsCoordinator } from '../../edge/EdgeNodeDnsCoordinator';\nimport { EdgeNodeHealthProbeService } from '../../edge/EdgeNodeHealthProbeService';\nimport { EdgeNodeCapabilityDetector } from '../../edge/EdgeNodeCapabilityDetector';\nimport { LocalNetworkManager } from '../../edge/LocalNetworkManager';\nimport { DdnsManager } from '../../edge/DdnsManager';\n\n/**\n * 容器中注册的所有服务\n */\nexport interface ApiContainerCradle {\n // 配置\n config: ApiContainerConfig;\n\n // 核心服务\n db: IdentityDatabase;\n apiServer: ApiServer;\n authMiddleware: AuthMiddleware;\n authenticator: Authenticator;\n\n // 仓库\n nodeRepo: EdgeNodeRepository;\n serviceTokenRepo: ServiceTokenRepository;\n apiKeyStore: DrizzleClientCredentialsStore;\n\n // 业务服务\n chatService: VercelChatService;\n\n // ChatKit 服务 (OpenAI ChatKit 协议)\n chatKitStore: PodChatKitStore;\n chatKitAiProvider: AiProvider;\n inngestRuntimeConfig: EmbeddedInngestRuntimeConfig | undefined;\n runAuthContextRegistry: RunAuthContextRegistry;\n runExecutionBackend: InngestRunExecutionBackend;\n taskAuthBindingService: TaskAuthBindingService<StoreContext>;\n taskService: TaskService<StoreContext>;\n inngestTaskScheduler: InngestTaskScheduler<StoreContext>;\n chatKitService: ChatKitService<StoreContext>;\n matrixStore: PodMatrixStore;\n providerRegistry: ProviderRegistry;\n embeddingService: EmbeddingService;\n vectorService: VectorService;\n\n // Cloud 模式: 身份服务\n webIdProfileRepo?: WebIdProfileRepository;\n ddnsRepo?: DdnsRepository;\n podLookupRepo?: PodLookupRepository;\n\n // 子域名相关 (可选,按 edition 注册)\n // Cloud 模式 或 Local 自管模式\n dnsProvider?: DnsProvider;\n dnsCoordinator?: EdgeNodeDnsCoordinator;\n healthProbeService?: EdgeNodeHealthProbeService;\n capabilityDetector?: EdgeNodeCapabilityDetector;\n localNetworkManager?: LocalNetworkManager;\n\n tunnelProvider?: TunnelProvider;\n subdomainService?: SubdomainService;\n // Local 托管式\n subdomainClient?: SubdomainClient;\n // Local 托管式 DDNS 管理\n ddnsManager?: DdnsManager;\n // Local 托管式/自管式 (启动 cloudflared)\n localTunnelProvider?: TunnelProvider;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/api/container/types.ts"],"names":[],"mappings":";AAAA;;;;GAIG","sourcesContent":["/**\n * API Container 依赖类型定义\n *\n * 定义容器中注册的所有服务接口\n */\n\nimport type { ApiServer } from '../ApiServer';\nimport type { AuthMiddleware } from '../middleware/AuthMiddleware';\nimport type { Authenticator } from '../auth/Authenticator';\nimport type { EdgeNodeRepository } from '../../identity/drizzle/EdgeNodeRepository';\nimport type { ServiceTokenRepository } from '../../identity/drizzle/ServiceTokenRepository';\nimport type { DrizzleClientCredentialsStore } from '../store/DrizzleClientCredentialsStore';\nimport type { VercelChatService } from '../service/VercelChatService';\nimport type { SubdomainService } from '../../subdomain/SubdomainService';\nimport type { SubdomainClient } from '../../subdomain/SubdomainClient';\nimport type { DnsProvider } from '../../dns/DnsProvider';\nimport type { TunnelProvider } from '../../tunnel/TunnelProvider';\nimport type { IdentityDatabase } from '../../identity/drizzle/db';\nimport type { DdnsRepository } from '../../identity/drizzle/DdnsRepository';\nimport type { PodLookupRepository } from '../../identity/drizzle/PodLookupRepository';\nimport type { ChatKitService, AiProvider } from '../chatkit';\nimport type { StoreContext } from '../chatkit/store';\nimport type { PodChatKitStore } from '../chatkit/pod-store';\nimport type { RuntimeHost } from '../../runtime/host/types';\nimport type { ProviderRegistry, EmbeddingService } from '../../ai/service';\nimport type { VectorService } from '../service/VectorService';\nimport type { InngestRunExecutionBackend } from '../runs/InngestRunExecutionBackend';\nimport type { EmbeddedInngestRuntimeConfig } from '../runs/EmbeddedInngestService';\nimport type { RunAuthContextRegistry } from '../runs/RunAuthContextRegistry';\nimport type { TaskAuthBindingService, TaskService, InngestTaskScheduler } from '../tasks';\nimport type { PodMatrixStore } from '../matrix';\n\n/**\n * 容器配置\n */\nexport interface ApiContainerConfig {\n /** 运行模式: cloud 持有密钥, local 调用远程 */\n edition: 'cloud' | 'local';\n\n /** API Server 端口 */\n port: number;\n\n /** API Server 主机 */\n host: string;\n\n /** API Server Unix socket 路径 */\n socketPath?: string;\n\n /** Runtime host implementation */\n runtimeHost?: RuntimeHost;\n /** 数据库连接 URL */\n databaseUrl: string;\n\n /** Redis connection URL, used by embedded infrastructure such as Inngest in cloud mode. */\n redisUrl?: string;\n\n /** Embedded Inngest runtime configuration. */\n inngest?: {\n enabled: boolean;\n mode?: 'managed' | 'spawn';\n port?: number;\n host?: string;\n baseUrl?: string;\n eventKey?: string;\n signingKey?: string;\n binaryPath?: string;\n sqliteDir?: string;\n };\n\n /** Resolved runtime config passed from API bootstrap after starting/locating Inngest. */\n inngestRuntimeConfig?: EmbeddedInngestRuntimeConfig;\n\n /** CORS 允许的源 */\n corsOrigins: string[];\n\n /** CSS Token 端点 */\n cssTokenEndpoint: string;\n\n /** 子域名功能配置 (cloud 模式) */\n subdomain?: {\n /** 节点域名根域名 (如 undefineds.site),有值即启用子域名功能 */\n baseStorageDomain?: string;\n cloudflareAccountId?: string;\n cloudflareApiToken?: string;\n tencentDnsSecretId?: string;\n tencentDnsSecretKey?: string;\n };\n\n /** Cloud API 端点 (local 托管式,调用 cloud 的子域名 API) */\n cloudApiEndpoint?: string;\n\n /** 节点 ID (local 托管式) */\n nodeId?: string;\n\n /** 节点 Token (local 托管式,调用 Cloud API 的认证) */\n nodeToken?: string;\n\n /** OIDC Issuer URL (local 托管式,使用 Cloud IdP) */\n oidcIssuer?: string;\n\n /** Cloudflare Tunnel Token (local 托管式/自管式,启动 cloudflared) */\n cloudflareTunnelToken?: string;\n\n /** SakuraFRP Tunnel Token (SAKURA_TUNNEL_TOKEN;local 托管式/自管式,启动 frpc) */\n sakuraTunnelToken?: string;\n\n /** 是否接受 Edge 节点注册 (cloud 模式) */\n edgeNodesEnabled?: boolean;\n}\n\nimport { EdgeNodeDnsCoordinator } from '../../edge/EdgeNodeDnsCoordinator';\nimport { EdgeNodeHealthProbeService } from '../../edge/EdgeNodeHealthProbeService';\nimport { EdgeNodeCapabilityDetector } from '../../edge/EdgeNodeCapabilityDetector';\nimport { LocalNetworkManager } from '../../edge/LocalNetworkManager';\nimport { DdnsManager } from '../../edge/DdnsManager';\n\n/**\n * 容器中注册的所有服务\n */\nexport interface ApiContainerCradle {\n // 配置\n config: ApiContainerConfig;\n\n // 核心服务\n db: IdentityDatabase;\n apiServer: ApiServer;\n authMiddleware: AuthMiddleware;\n authenticator: Authenticator;\n\n // 仓库\n nodeRepo: EdgeNodeRepository;\n serviceTokenRepo: ServiceTokenRepository;\n apiKeyStore: DrizzleClientCredentialsStore;\n\n // 业务服务\n chatService: VercelChatService;\n\n // ChatKit 服务 (OpenAI ChatKit 协议)\n chatKitStore: PodChatKitStore;\n chatKitAiProvider: AiProvider;\n inngestRuntimeConfig: EmbeddedInngestRuntimeConfig | undefined;\n runAuthContextRegistry: RunAuthContextRegistry;\n runExecutionBackend: InngestRunExecutionBackend;\n taskAuthBindingService: TaskAuthBindingService<StoreContext>;\n taskService: TaskService<StoreContext>;\n inngestTaskScheduler: InngestTaskScheduler<StoreContext>;\n chatKitService: ChatKitService<StoreContext>;\n matrixStore: PodMatrixStore;\n providerRegistry: ProviderRegistry;\n embeddingService: EmbeddingService;\n vectorService: VectorService;\n\n // Cloud 模式: 身份服务\n ddnsRepo?: DdnsRepository;\n podLookupRepo?: PodLookupRepository;\n\n // 子域名相关 (可选,按 edition 注册)\n // Cloud 模式 或 Local 自管模式\n dnsProvider?: DnsProvider;\n dnsCoordinator?: EdgeNodeDnsCoordinator;\n healthProbeService?: EdgeNodeHealthProbeService;\n capabilityDetector?: EdgeNodeCapabilityDetector;\n localNetworkManager?: LocalNetworkManager;\n\n tunnelProvider?: TunnelProvider;\n subdomainService?: SubdomainService;\n // Local 托管式\n subdomainClient?: SubdomainClient;\n // Local 托管式 DDNS 管理\n ddnsManager?: DdnsManager;\n // Local 托管式/自管式 (启动 cloudflared)\n localTunnelProvider?: TunnelProvider;\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  import type { ApiServer } from '../ApiServer';
2
+ import type { PodLookupRepository } from '../../identity/drizzle/PodLookupRepository';
2
3
  export interface PodManagementHandlerOptions {
3
4
  /** Pod 存储根目录 */
4
5
  rootDir: string;
@@ -12,6 +13,8 @@ export interface PodManagementHandlerOptions {
12
13
  podUrl: string;
13
14
  }>;
14
15
  };
16
+ /** SP-local Pod lookup used by Cloud consent to scope account WebIDs. */
17
+ podLookupRepository?: Pick<PodLookupRepository, 'findByWebIds'>;
15
18
  }
16
19
  export interface CreatePodRequest {
17
20
  /** Pod 名称(通常是用户名) */