@undefineds.co/xpod 0.3.70 → 0.3.71-rc.13

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 (172) hide show
  1. package/config/cloud.json +3 -0
  2. package/config/local.json +3 -0
  3. package/config/resolver.json +7 -0
  4. package/config/xpod.base.json +20 -0
  5. package/dist/agents/ClaudeExecutor.js +1 -1
  6. package/dist/agents/ClaudeExecutor.js.map +1 -1
  7. package/dist/agents/types.d.ts +5 -5
  8. package/dist/agents/types.js.map +1 -1
  9. package/dist/api/ai-gateway/AiGatewayService.d.ts +5 -16
  10. package/dist/api/ai-gateway/AiGatewayService.js +13 -35
  11. package/dist/api/ai-gateway/AiGatewayService.js.map +1 -1
  12. package/dist/api/ai-gateway/auth/AiConnectionInvocationKeyIssuer.d.ts +3 -2
  13. package/dist/api/ai-gateway/auth/AiConnectionInvocationKeyIssuer.js +37 -12
  14. package/dist/api/ai-gateway/auth/AiConnectionInvocationKeyIssuer.js.map +1 -1
  15. package/dist/api/ai-gateway/auth/GatewayPrincipal.d.ts +2 -16
  16. package/dist/api/ai-gateway/auth/GatewayPrincipal.js +3 -33
  17. package/dist/api/ai-gateway/auth/GatewayPrincipal.js.map +1 -1
  18. package/dist/api/ai-gateway/auth/InvocationTokenAuthenticator.d.ts +23 -0
  19. package/dist/api/ai-gateway/auth/InvocationTokenAuthenticator.js +81 -0
  20. package/dist/api/ai-gateway/auth/InvocationTokenAuthenticator.js.map +1 -0
  21. package/dist/api/ai-gateway/auth/InvocationTokenCodec.d.ts +7 -4
  22. package/dist/api/ai-gateway/auth/InvocationTokenCodec.js.map +1 -1
  23. package/dist/api/ai-gateway/connect/index.d.ts +7 -26
  24. package/dist/api/ai-gateway/connect/index.js +40 -67
  25. package/dist/api/ai-gateway/connect/index.js.map +1 -1
  26. package/dist/api/ai-gateway/credentials/PlaintextCredentialPayload.d.ts +17 -0
  27. package/dist/api/ai-gateway/credentials/PlaintextCredentialPayload.js +65 -0
  28. package/dist/api/ai-gateway/credentials/PlaintextCredentialPayload.js.map +1 -0
  29. package/dist/api/ai-gateway/pod/HostedPodDataAccess.d.ts +24 -0
  30. package/dist/api/ai-gateway/pod/HostedPodDataAccess.js +149 -0
  31. package/dist/api/ai-gateway/pod/HostedPodDataAccess.js.map +1 -0
  32. package/dist/api/ai-gateway/quota/ProviderQuotaAdapter.d.ts +13 -5
  33. package/dist/api/ai-gateway/quota/ProviderQuotaAdapter.js +16 -19
  34. package/dist/api/ai-gateway/quota/ProviderQuotaAdapter.js.map +1 -1
  35. package/dist/api/ai-gateway/service-access/AiConnectionServiceAccess.d.ts +1 -1
  36. package/dist/api/ai-gateway/service-access/AiConnectionServiceAccess.js +0 -2
  37. package/dist/api/ai-gateway/service-access/AiConnectionServiceAccess.js.map +1 -1
  38. package/dist/api/auth/AuthContext.d.ts +1 -12
  39. package/dist/api/auth/AuthContext.js +0 -11
  40. package/dist/api/auth/AuthContext.js.map +1 -1
  41. package/dist/api/auth/ClientCredentialsAuthenticator.js +4 -11
  42. package/dist/api/auth/ClientCredentialsAuthenticator.js.map +1 -1
  43. package/dist/api/chatkit/default-agent.d.ts +2 -2
  44. package/dist/api/chatkit/default-agent.js +4 -4
  45. package/dist/api/chatkit/default-agent.js.map +1 -1
  46. package/dist/api/chatkit/runtime/AcpAgentRuntime.js +1 -1
  47. package/dist/api/chatkit/runtime/AcpAgentRuntime.js.map +1 -1
  48. package/dist/api/container/common.js +28 -69
  49. package/dist/api/container/common.js.map +1 -1
  50. package/dist/api/container/index.js +5 -6
  51. package/dist/api/container/index.js.map +1 -1
  52. package/dist/api/container/routes.js +2 -5
  53. package/dist/api/container/routes.js.map +1 -1
  54. package/dist/api/container/types.d.ts +8 -10
  55. package/dist/api/container/types.js.map +1 -1
  56. package/dist/api/handlers/AiClientConfigurationHandler.js +3 -3
  57. package/dist/api/handlers/AiClientConfigurationHandler.js.map +1 -1
  58. package/dist/api/handlers/AiGatewayHandler.js +2 -2
  59. package/dist/api/handlers/AiGatewayHandler.js.map +1 -1
  60. package/dist/api/handlers/AiGatewayManagementHandler.d.ts +2 -10
  61. package/dist/api/handlers/AiGatewayManagementHandler.js +4 -154
  62. package/dist/api/handlers/AiGatewayManagementHandler.js.map +1 -1
  63. package/dist/api/handlers/NetworkSettingsHandler.js +0 -3
  64. package/dist/api/handlers/NetworkSettingsHandler.js.map +1 -1
  65. package/dist/api/handlers/PodSettingsHandler.d.ts +5 -2
  66. package/dist/api/handlers/PodSettingsHandler.js +3 -3
  67. package/dist/api/handlers/PodSettingsHandler.js.map +1 -1
  68. package/dist/api/runs/AgentRuntimeTypes.d.ts +3 -3
  69. package/dist/api/runs/AgentRuntimeTypes.js +10 -10
  70. package/dist/api/runs/AgentRuntimeTypes.js.map +1 -1
  71. package/dist/api/runs/InngestRunExecutionBackend.d.ts +15 -9
  72. package/dist/api/runs/InngestRunExecutionBackend.js +25 -10
  73. package/dist/api/runs/InngestRunExecutionBackend.js.map +1 -1
  74. package/dist/api/runs/PiAgentRuntimeDriver.js +2 -2
  75. package/dist/api/runs/PiAgentRuntimeDriver.js.map +1 -1
  76. package/dist/api/runs/RunStateCenter.js +1 -1
  77. package/dist/api/runs/RunStateCenter.js.map +1 -1
  78. package/dist/api/service/AiClientConfigurationService.d.ts +2 -2
  79. package/dist/api/service/AiClientConfigurationService.js +11 -11
  80. package/dist/api/service/AiClientConfigurationService.js.map +1 -1
  81. package/dist/api/tasks/InngestTaskScheduler.d.ts +16 -10
  82. package/dist/api/tasks/InngestTaskScheduler.js +24 -12
  83. package/dist/api/tasks/InngestTaskScheduler.js.map +1 -1
  84. package/dist/cli/commands/start.js +7 -7
  85. package/dist/cli/commands/start.js.map +1 -1
  86. package/dist/components/components.jsonld +1 -0
  87. package/dist/components/context.jsonld +36 -0
  88. package/dist/http/InternalPodDataHttpHandler.d.ts +32 -0
  89. package/dist/http/InternalPodDataHttpHandler.js +258 -0
  90. package/dist/http/InternalPodDataHttpHandler.js.map +1 -0
  91. package/dist/http/InternalPodDataHttpHandler.jsonld +201 -0
  92. package/dist/index.d.ts +2 -1
  93. package/dist/index.js +4 -2
  94. package/dist/index.js.map +1 -1
  95. package/dist/main.js +13 -13
  96. package/dist/main.js.map +1 -1
  97. package/dist/runtime/GatewayAdminProxyAuth.d.ts +15 -1
  98. package/dist/runtime/GatewayAdminProxyAuth.js +57 -2
  99. package/dist/runtime/GatewayAdminProxyAuth.js.map +1 -1
  100. package/dist/runtime/bootstrap.js +3 -0
  101. package/dist/runtime/bootstrap.js.map +1 -1
  102. package/dist/runtime/css-process.d.ts +1 -1
  103. package/dist/runtime/css-process.js +4 -1
  104. package/dist/runtime/css-process.js.map +1 -1
  105. package/dist/runtime/runner/node/CommunitySolidServerCssRunner.d.ts +2 -0
  106. package/dist/runtime/runner/node/CommunitySolidServerCssRunner.js +50 -0
  107. package/dist/runtime/runner/node/CommunitySolidServerCssRunner.js.map +1 -1
  108. package/node_modules/@undefineds.co/ai-connection/dist/AiClientConfigurationSection.d.ts +5 -5
  109. package/node_modules/@undefineds.co/ai-connection/dist/AiClientConfigurationSection.js +7 -7
  110. package/node_modules/@undefineds.co/ai-connection/dist/AiConnectionMain.js +1 -1
  111. package/node_modules/@undefineds.co/ai-connection/dist/AiConnectionPanel.d.ts +3 -1
  112. package/node_modules/@undefineds.co/ai-connection/dist/AiConnectionPanel.js +74 -60
  113. package/node_modules/@undefineds.co/ai-connection/dist/ai-connection-client.d.ts +0 -21
  114. package/node_modules/@undefineds.co/ai-connection/dist/ai-connection-client.js +0 -41
  115. package/node_modules/@undefineds.co/ai-connection/dist/client-config/base-adapter.d.ts +1 -0
  116. package/node_modules/@undefineds.co/ai-connection/dist/client-config/base-adapter.js +7 -2
  117. package/node_modules/@undefineds.co/ai-connection/dist/client-config/codex.js +3 -3
  118. package/node_modules/@undefineds.co/ai-connection/dist/client-config/index.cjs +15 -9
  119. package/node_modules/@undefineds.co/ai-connection/dist/client-config/json-env-adapter.js +4 -4
  120. package/node_modules/@undefineds.co/ai-connection/dist/client-config/pi.js +3 -3
  121. package/node_modules/@undefineds.co/ai-connection/dist/client-config/types.d.ts +1 -1
  122. package/node_modules/@undefineds.co/ai-connection/dist/controller.d.ts +2 -1
  123. package/node_modules/@undefineds.co/ai-connection/dist/controller.js +1 -0
  124. package/node_modules/@undefineds.co/ai-connection/dist/service-access.js +0 -1
  125. package/node_modules/@undefineds.co/extension-sdk/dist/web.d.ts +22 -1
  126. package/package.json +3 -3
  127. package/static/app/assets/main.js +7 -7
  128. package/static/dashboard/assets/NetworkPage-CXjiUMR1.js +2 -0
  129. package/static/dashboard/assets/{PaneListHeader-57nvMwH6.js → PaneListHeader-BSipfl0W.js} +1 -1
  130. package/static/dashboard/assets/PodPage-Bd3Xhmp-.js +2 -0
  131. package/static/dashboard/assets/ServicesPage-CI3jWZGe.js +1 -0
  132. package/static/dashboard/assets/{card-B9Zjf_2p.js → card-z5BV5hTo.js} +1 -1
  133. package/static/dashboard/assets/{dashboard-8C6o666W.js → dashboard-CSrqAv2L.js} +2 -2
  134. package/static/dashboard/assets/{database-DPh9wDY9.js → database-Ct5ZPe6L.js} +1 -1
  135. package/static/dashboard/assets/{external-link-VbMQvVMz.js → external-link-B7wD1hkm.js} +1 -1
  136. package/static/dashboard/assets/index-tOBaUnM1.js +44 -0
  137. package/static/dashboard/assets/{refresh-cw-BxVxNxNr.js → refresh-cw-CFDZPaE8.js} +1 -1
  138. package/static/dashboard/assets/{services-status-context-DKmJ7ISr.js → services-status-context-DN1Icg4A.js} +1 -1
  139. package/static/dashboard/dashboard.html +1 -1
  140. package/static/settings/assets/ModelsPage-03NPWzoX.js +1 -0
  141. package/static/settings/assets/{PaneListHeader-Bgaze006.js → PaneListHeader-DMD8OJef.js} +1 -1
  142. package/static/settings/assets/PodPage-DT4EMYhL.js +2 -0
  143. package/static/settings/assets/ServicesPage-CJ0ub6IH.js +1 -0
  144. package/static/settings/assets/SettingsPage-BkR7ZK18.js +41 -0
  145. package/static/settings/assets/{card-B_bXSIn-.js → card-Cjsia0_V.js} +1 -1
  146. package/static/settings/assets/{services-status-context-DiX-AbrP.js → services-status-context-CkuKmH5h.js} +1 -1
  147. package/static/settings/assets/{settings-B30oMfZq.js → settings-Cyyv6-SD.js} +2 -2
  148. package/static/settings/assets/{workspace-layout-Dv1Yn9Ci.js → workspace-layout-B47luv6r.js} +1 -1
  149. package/static/settings/settings.html +1 -1
  150. package/dist/api/ai-gateway/auth/ClientCredentialsInternalPodAccessTokenProvider.d.ts +0 -25
  151. package/dist/api/ai-gateway/auth/ClientCredentialsInternalPodAccessTokenProvider.js +0 -91
  152. package/dist/api/ai-gateway/auth/ClientCredentialsInternalPodAccessTokenProvider.js.map +0 -1
  153. package/dist/api/ai-gateway/auth/GatewayApiKey.d.ts +0 -28
  154. package/dist/api/ai-gateway/auth/GatewayApiKey.js +0 -162
  155. package/dist/api/ai-gateway/auth/GatewayApiKey.js.map +0 -1
  156. package/dist/api/ai-gateway/auth/GatewayApiKeyAuthenticator.d.ts +0 -56
  157. package/dist/api/ai-gateway/auth/GatewayApiKeyAuthenticator.js +0 -143
  158. package/dist/api/ai-gateway/auth/GatewayApiKeyAuthenticator.js.map +0 -1
  159. package/dist/api/ai-gateway/auth/GatewayKeyLocatorCodec.d.ts +0 -26
  160. package/dist/api/ai-gateway/auth/GatewayKeyLocatorCodec.js +0 -97
  161. package/dist/api/ai-gateway/auth/GatewayKeyLocatorCodec.js.map +0 -1
  162. package/dist/api/ai-gateway/auth/PodGatewayAccessKeyRepository.d.ts +0 -54
  163. package/dist/api/ai-gateway/auth/PodGatewayAccessKeyRepository.js +0 -152
  164. package/dist/api/ai-gateway/auth/PodGatewayAccessKeyRepository.js.map +0 -1
  165. package/static/dashboard/assets/NetworkPage-Brt79fuQ.js +0 -2
  166. package/static/dashboard/assets/PodPage-CM6do1vB.js +0 -2
  167. package/static/dashboard/assets/ServicesPage-BUNxGJRz.js +0 -1
  168. package/static/dashboard/assets/index-RfiFckzb.js +0 -51
  169. package/static/settings/assets/ModelsPage-D_IH7AH3.js +0 -1
  170. package/static/settings/assets/PodPage-Cy1VNObw.js +0 -2
  171. package/static/settings/assets/ServicesPage-BsFaxVWC.js +0 -1
  172. package/static/settings/assets/SettingsPage-UafNWE_p.js +0 -48
@@ -1 +1 @@
1
- import{j as t,c as s,a as d,r as o}from"./settings-B30oMfZq.js";const n=d("inline-flex items-center rounded-lg border px-2.5 py-0.5 text-xs font-semibold transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-ring/50 focus:ring-offset-2",{variants:{variant:{default:"border-transparent bg-primary text-primary-foreground shadow-sm shadow-primary/20 hover:bg-primary/90",secondary:"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",destructive:"border-transparent bg-destructive text-destructive-foreground shadow-sm shadow-destructive/20 hover:bg-destructive/90",outline:"border-border/40 text-foreground bg-muted/30 backdrop-blur-sm"}},defaultVariants:{variant:"default"}});function x({className:r,variant:e,...a}){return t.jsx("div",{className:s(n({variant:e}),r),...a})}const i=o.forwardRef(({className:r,...e},a)=>t.jsx("div",{ref:a,className:s("rounded-2xl border border-border/50 bg-card shadow-lg shadow-black/5 transition-all duration-200",r),...e}));i.displayName="Card";const c=o.forwardRef(({className:r,...e},a)=>t.jsx("div",{ref:a,className:s("flex flex-col gap-1 p-6",r),...e}));c.displayName="CardHeader";const f=o.forwardRef(({className:r,...e},a)=>t.jsx("h3",{ref:a,className:s("text-2xl font-semibold tracking-tight",r),...e}));f.displayName="CardTitle";const l=o.forwardRef(({className:r,...e},a)=>t.jsx("p",{ref:a,className:s("text-sm text-muted-foreground",r),...e}));l.displayName="CardDescription";const m=o.forwardRef(({className:r,...e},a)=>t.jsx("div",{ref:a,className:s("p-6 pt-0",r),...e}));m.displayName="CardContent";const p=o.forwardRef(({className:r,...e},a)=>t.jsx("div",{ref:a,className:s("flex items-center p-6 pt-0",r),...e}));p.displayName="CardFooter";export{x as B,i as C,c as a,f as b,l as c,m as d};
1
+ import{j as t,c as s,a as d,r as o}from"./settings-Cyyv6-SD.js";const n=d("inline-flex items-center rounded-lg border px-2.5 py-0.5 text-xs font-semibold transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-ring/50 focus:ring-offset-2",{variants:{variant:{default:"border-transparent bg-primary text-primary-foreground shadow-sm shadow-primary/20 hover:bg-primary/90",secondary:"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",destructive:"border-transparent bg-destructive text-destructive-foreground shadow-sm shadow-destructive/20 hover:bg-destructive/90",outline:"border-border/40 text-foreground bg-muted/30 backdrop-blur-sm"}},defaultVariants:{variant:"default"}});function x({className:r,variant:e,...a}){return t.jsx("div",{className:s(n({variant:e}),r),...a})}const i=o.forwardRef(({className:r,...e},a)=>t.jsx("div",{ref:a,className:s("rounded-2xl border border-border/50 bg-card shadow-lg shadow-black/5 transition-all duration-200",r),...e}));i.displayName="Card";const c=o.forwardRef(({className:r,...e},a)=>t.jsx("div",{ref:a,className:s("flex flex-col gap-1 p-6",r),...e}));c.displayName="CardHeader";const f=o.forwardRef(({className:r,...e},a)=>t.jsx("h3",{ref:a,className:s("text-2xl font-semibold tracking-tight",r),...e}));f.displayName="CardTitle";const l=o.forwardRef(({className:r,...e},a)=>t.jsx("p",{ref:a,className:s("text-sm text-muted-foreground",r),...e}));l.displayName="CardDescription";const m=o.forwardRef(({className:r,...e},a)=>t.jsx("div",{ref:a,className:s("p-6 pt-0",r),...e}));m.displayName="CardContent";const p=o.forwardRef(({className:r,...e},a)=>t.jsx("div",{ref:a,className:s("flex items-center p-6 pt-0",r),...e}));p.displayName="CardFooter";export{x as B,i as C,c as a,f as b,l as c,m as d};
@@ -1 +1 @@
1
- import{r as c}from"./settings-B30oMfZq.js";const n="/api/admin";async function o(t={}){try{const e=await fetch(`${n}/status`,{signal:t.signal});if(e.ok)return await e.json()}catch(e){console.error("Failed to get admin status:",e)}return null}async function u(t={}){try{const e=await fetch(`${n}/config`,{signal:t.signal});if(e.ok)return await e.json()}catch(e){console.error("Failed to get admin config:",e)}return null}async function l(t,e={}){try{const a=t?"?baseUrl="+encodeURIComponent(t):"",s=await fetch(n+"/public-ip"+a,{signal:e.signal});if(s.ok)return await s.json()}catch(a){console.error("Failed to get public ip check:",a)}return null}async function w(t){try{return(await fetch(`${n}/config`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({env:t})})).ok}catch(e){return console.error("Failed to update admin config:",e),!1}}async function S(){try{return(await fetch(`${n}/restart`,{method:"POST"})).ok}catch(t){return console.error("Failed to trigger restart:",t),!1}}async function f(t={}){try{const e=await fetch("/service/status",{signal:t.signal});if(e.ok)return await e.json()}catch(e){console.error("Failed to get gateway status:",e)}return null}function g(t){return t?t.startsWith("http://")||t.startsWith("https://")?t:`https://${t}/`:""}function h(t,e,a=""){return e?.baseUrl||g(e?.fqdn)||t.CSS_BASE_URL||a}async function d(t={}){try{const e=await fetch(`${n}/ddns`,{signal:t.signal});if(e.ok)return await e.json()}catch(e){console.error("Failed to get ddns status:",e)}return null}async function m(t={}){const[e,a,s,r]=await Promise.all([f(t),o(t),u(t),d(t)]),i=await l(h(s?.env??{},r),t);return{servicesData:e,adminData:a,configData:s,ddnsData:r,publicCheck:i,checkedAt:new Date}}const y=c.createContext(null);function k(){return c.useContext(y)}export{y as S,u as a,l as b,w as c,m as f,d as g,S as t,k as u};
1
+ import{r as c}from"./settings-Cyyv6-SD.js";const n="/api/admin";async function o(t={}){try{const e=await fetch(`${n}/status`,{signal:t.signal});if(e.ok)return await e.json()}catch(e){console.error("Failed to get admin status:",e)}return null}async function u(t={}){try{const e=await fetch(`${n}/config`,{signal:t.signal});if(e.ok)return await e.json()}catch(e){console.error("Failed to get admin config:",e)}return null}async function l(t,e={}){try{const a=t?"?baseUrl="+encodeURIComponent(t):"",s=await fetch(n+"/public-ip"+a,{signal:e.signal});if(s.ok)return await s.json()}catch(a){console.error("Failed to get public ip check:",a)}return null}async function w(t){try{return(await fetch(`${n}/config`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({env:t})})).ok}catch(e){return console.error("Failed to update admin config:",e),!1}}async function S(){try{return(await fetch(`${n}/restart`,{method:"POST"})).ok}catch(t){return console.error("Failed to trigger restart:",t),!1}}async function f(t={}){try{const e=await fetch("/service/status",{signal:t.signal});if(e.ok)return await e.json()}catch(e){console.error("Failed to get gateway status:",e)}return null}function g(t){return t?t.startsWith("http://")||t.startsWith("https://")?t:`https://${t}/`:""}function h(t,e,a=""){return e?.baseUrl||g(e?.fqdn)||t.CSS_BASE_URL||a}async function d(t={}){try{const e=await fetch(`${n}/ddns`,{signal:t.signal});if(e.ok)return await e.json()}catch(e){console.error("Failed to get ddns status:",e)}return null}async function m(t={}){const[e,a,s,r]=await Promise.all([f(t),o(t),u(t),d(t)]),i=await l(h(s?.env??{},r),t);return{servicesData:e,adminData:a,configData:s,ddnsData:r,publicCheck:i,checkedAt:new Date}}const y=c.createContext(null);function k(){return c.useContext(y)}export{y as S,u as a,l as b,w as c,m as f,d as g,S as t,k as u};
@@ -1,4 +1,4 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ModelsPage-D_IH7AH3.js","assets/card-B_bXSIn-.js","assets/workspace-layout-Dv1Yn9Ci.js","assets/PodPage-Cy1VNObw.js","assets/PaneListHeader-Bgaze006.js","assets/ServicesPage-BsFaxVWC.js","assets/services-status-context-DiX-AbrP.js","assets/SettingsPage-UafNWE_p.js"])))=>i.map(i=>d[i]);
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ModelsPage-03NPWzoX.js","assets/card-Cjsia0_V.js","assets/workspace-layout-B47luv6r.js","assets/PodPage-DT4EMYhL.js","assets/PaneListHeader-DMD8OJef.js","assets/ServicesPage-CJ0ub6IH.js","assets/services-status-context-CkuKmH5h.js","assets/SettingsPage-BkR7ZK18.js"])))=>i.map(i=>d[i]);
2
2
  function _mergeNamespaces(i,e){for(var t=0;t<e.length;t++){const n=e[t];if(typeof n!="string"&&!Array.isArray(n)){for(const s in n)if(s!=="default"&&!(s in i)){const a=Object.getOwnPropertyDescriptor(n,s);a&&Object.defineProperty(i,s,a.get?a:{enumerable:!0,get:()=>n[s]})}}}return Object.freeze(Object.defineProperty(i,Symbol.toStringTag,{value:"Module"}))}(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const s of document.querySelectorAll('link[rel="modulepreload"]'))n(s);new MutationObserver(s=>{for(const a of s)if(a.type==="childList")for(const u of a.addedNodes)u.tagName==="LINK"&&u.rel==="modulepreload"&&n(u)}).observe(document,{childList:!0,subtree:!0});function t(s){const a={};return s.integrity&&(a.integrity=s.integrity),s.referrerPolicy&&(a.referrerPolicy=s.referrerPolicy),s.crossOrigin==="use-credentials"?a.credentials="include":s.crossOrigin==="anonymous"?a.credentials="omit":a.credentials="same-origin",a}function n(s){if(s.ep)return;s.ep=!0;const a=t(s);fetch(s.href,a)}})();function getDefaultExportFromCjs(i){return i&&i.__esModule&&Object.prototype.hasOwnProperty.call(i,"default")?i.default:i}var jsxRuntime={exports:{}},reactJsxRuntime_production={};var hasRequiredReactJsxRuntime_production;function requireReactJsxRuntime_production(){if(hasRequiredReactJsxRuntime_production)return reactJsxRuntime_production;hasRequiredReactJsxRuntime_production=1;var i=Symbol.for("react.transitional.element"),e=Symbol.for("react.fragment");function t(n,s,a){var u=null;if(a!==void 0&&(u=""+a),s.key!==void 0&&(u=""+s.key),"key"in s){a={};for(var c in s)c!=="key"&&(a[c]=s[c])}else a=s;return s=a.ref,{$$typeof:i,type:n,key:u,ref:s!==void 0?s:null,props:a}}return reactJsxRuntime_production.Fragment=e,reactJsxRuntime_production.jsx=t,reactJsxRuntime_production.jsxs=t,reactJsxRuntime_production}var hasRequiredJsxRuntime;function requireJsxRuntime(){return hasRequiredJsxRuntime||(hasRequiredJsxRuntime=1,jsxRuntime.exports=requireReactJsxRuntime_production()),jsxRuntime.exports}var jsxRuntimeExports=requireJsxRuntime(),react={exports:{}},react_production={};var hasRequiredReact_production;function requireReact_production(){if(hasRequiredReact_production)return react_production;hasRequiredReact_production=1;var i=Symbol.for("react.transitional.element"),e=Symbol.for("react.portal"),t=Symbol.for("react.fragment"),n=Symbol.for("react.strict_mode"),s=Symbol.for("react.profiler"),a=Symbol.for("react.consumer"),u=Symbol.for("react.context"),c=Symbol.for("react.forward_ref"),h=Symbol.for("react.suspense"),f=Symbol.for("react.memo"),p=Symbol.for("react.lazy"),g=Symbol.for("react.activity"),y=Symbol.iterator;function S(G){return G===null||typeof G!="object"?null:(G=y&&G[y]||G["@@iterator"],typeof G=="function"?G:null)}var w={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},R=Object.assign,T={};function A(G,ce,oe){this.props=G,this.context=ce,this.refs=T,this.updater=oe||w}A.prototype.isReactComponent={},A.prototype.setState=function(G,ce){if(typeof G!="object"&&typeof G!="function"&&G!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,G,ce,"setState")},A.prototype.forceUpdate=function(G){this.updater.enqueueForceUpdate(this,G,"forceUpdate")};function F(){}F.prototype=A.prototype;function x(G,ce,oe){this.props=G,this.context=ce,this.refs=T,this.updater=oe||w}var D=x.prototype=new F;D.constructor=x,R(D,A.prototype),D.isPureReactComponent=!0;var O=Array.isArray;function K(){}var z={H:null,A:null,T:null,S:null},X=Object.prototype.hasOwnProperty;function Ee(G,ce,oe){var Fe=oe.ref;return{$$typeof:i,type:G,key:ce,ref:Fe!==void 0?Fe:null,props:oe}}function q(G,ce){return Ee(G.type,ce,G.props)}function Y(G){return typeof G=="object"&&G!==null&&G.$$typeof===i}function Te(G){var ce={"=":"=0",":":"=2"};return"$"+G.replace(/[=:]/g,function(oe){return ce[oe]})}var re=/\/+/g;function $e(G,ce){return typeof G=="object"&&G!==null&&G.key!=null?Te(""+G.key):ce.toString(36)}function ze(G){switch(G.status){case"fulfilled":return G.value;case"rejected":throw G.reason;default:switch(typeof G.status=="string"?G.then(K,K):(G.status="pending",G.then(function(ce){G.status==="pending"&&(G.status="fulfilled",G.value=ce)},function(ce){G.status==="pending"&&(G.status="rejected",G.reason=ce)})),G.status){case"fulfilled":return G.value;case"rejected":throw G.reason}}throw G}function ye(G,ce,oe,Fe,Ue){var Je=typeof G;(Je==="undefined"||Je==="boolean")&&(G=null);var He=!1;if(G===null)He=!0;else switch(Je){case"bigint":case"string":case"number":He=!0;break;case"object":switch(G.$$typeof){case i:case e:He=!0;break;case p:return He=G._init,ye(He(G._payload),ce,oe,Fe,Ue)}}if(He)return Ue=Ue(G),He=Fe===""?"."+$e(G,0):Fe,O(Ue)?(oe="",He!=null&&(oe=He.replace(re,"$&/")+"/"),ye(Ue,ce,oe,"",function(Oe){return Oe})):Ue!=null&&(Y(Ue)&&(Ue=q(Ue,oe+(Ue.key==null||G&&G.key===Ue.key?"":(""+Ue.key).replace(re,"$&/")+"/")+He)),ce.push(Ue)),1;He=0;var he=Fe===""?".":Fe+":";if(O(G))for(var fe=0;fe<G.length;fe++)Fe=G[fe],Je=he+$e(Fe,fe),He+=ye(Fe,ce,oe,Je,Ue);else if(fe=S(G),typeof fe=="function")for(G=fe.call(G),fe=0;!(Fe=G.next()).done;)Fe=Fe.value,Je=he+$e(Fe,fe++),He+=ye(Fe,ce,oe,Je,Ue);else if(Je==="object"){if(typeof G.then=="function")return ye(ze(G),ce,oe,Fe,Ue);throw ce=String(G),Error("Objects are not valid as a React child (found: "+(ce==="[object Object]"?"object with keys {"+Object.keys(G).join(", ")+"}":ce)+"). If you meant to render a collection of children, use an array instead.")}return He}function Ve(G,ce,oe){if(G==null)return G;var Fe=[],Ue=0;return ye(G,Fe,"","",function(Je){return ce.call(oe,Je,Ue++)}),Fe}function pe(G){if(G._status===-1){var ce=G._result;ce=ce(),ce.then(function(oe){(G._status===0||G._status===-1)&&(G._status=1,G._result=oe)},function(oe){(G._status===0||G._status===-1)&&(G._status=2,G._result=oe)}),G._status===-1&&(G._status=0,G._result=ce)}if(G._status===1)return G._result.default;throw G._result}var De=typeof reportError=="function"?reportError:function(G){if(typeof window=="object"&&typeof window.ErrorEvent=="function"){var ce=new window.ErrorEvent("error",{bubbles:!0,cancelable:!0,message:typeof G=="object"&&G!==null&&typeof G.message=="string"?String(G.message):String(G),error:G});if(!window.dispatchEvent(ce))return}else if(typeof process=="object"&&typeof process.emit=="function"){process.emit("uncaughtException",G);return}console.error(G)},$={map:Ve,forEach:function(G,ce,oe){Ve(G,function(){ce.apply(this,arguments)},oe)},count:function(G){var ce=0;return Ve(G,function(){ce++}),ce},toArray:function(G){return Ve(G,function(ce){return ce})||[]},only:function(G){if(!Y(G))throw Error("React.Children.only expected to receive a single React element child.");return G}};return react_production.Activity=g,react_production.Children=$,react_production.Component=A,react_production.Fragment=t,react_production.Profiler=s,react_production.PureComponent=x,react_production.StrictMode=n,react_production.Suspense=h,react_production.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE=z,react_production.__COMPILER_RUNTIME={__proto__:null,c:function(G){return z.H.useMemoCache(G)}},react_production.cache=function(G){return function(){return G.apply(null,arguments)}},react_production.cacheSignal=function(){return null},react_production.cloneElement=function(G,ce,oe){if(G==null)throw Error("The argument must be a React element, but you passed "+G+".");var Fe=R({},G.props),Ue=G.key;if(ce!=null)for(Je in ce.key!==void 0&&(Ue=""+ce.key),ce)!X.call(ce,Je)||Je==="key"||Je==="__self"||Je==="__source"||Je==="ref"&&ce.ref===void 0||(Fe[Je]=ce[Je]);var Je=arguments.length-2;if(Je===1)Fe.children=oe;else if(1<Je){for(var He=Array(Je),he=0;he<Je;he++)He[he]=arguments[he+2];Fe.children=He}return Ee(G.type,Ue,Fe)},react_production.createContext=function(G){return G={$$typeof:u,_currentValue:G,_currentValue2:G,_threadCount:0,Provider:null,Consumer:null},G.Provider=G,G.Consumer={$$typeof:a,_context:G},G},react_production.createElement=function(G,ce,oe){var Fe,Ue={},Je=null;if(ce!=null)for(Fe in ce.key!==void 0&&(Je=""+ce.key),ce)X.call(ce,Fe)&&Fe!=="key"&&Fe!=="__self"&&Fe!=="__source"&&(Ue[Fe]=ce[Fe]);var He=arguments.length-2;if(He===1)Ue.children=oe;else if(1<He){for(var he=Array(He),fe=0;fe<He;fe++)he[fe]=arguments[fe+2];Ue.children=he}if(G&&G.defaultProps)for(Fe in He=G.defaultProps,He)Ue[Fe]===void 0&&(Ue[Fe]=He[Fe]);return Ee(G,Je,Ue)},react_production.createRef=function(){return{current:null}},react_production.forwardRef=function(G){return{$$typeof:c,render:G}},react_production.isValidElement=Y,react_production.lazy=function(G){return{$$typeof:p,_payload:{_status:-1,_result:G},_init:pe}},react_production.memo=function(G,ce){return{$$typeof:f,type:G,compare:ce===void 0?null:ce}},react_production.startTransition=function(G){var ce=z.T,oe={};z.T=oe;try{var Fe=G(),Ue=z.S;Ue!==null&&Ue(oe,Fe),typeof Fe=="object"&&Fe!==null&&typeof Fe.then=="function"&&Fe.then(K,De)}catch(Je){De(Je)}finally{ce!==null&&oe.types!==null&&(ce.types=oe.types),z.T=ce}},react_production.unstable_useCacheRefresh=function(){return z.H.useCacheRefresh()},react_production.use=function(G){return z.H.use(G)},react_production.useActionState=function(G,ce,oe){return z.H.useActionState(G,ce,oe)},react_production.useCallback=function(G,ce){return z.H.useCallback(G,ce)},react_production.useContext=function(G){return z.H.useContext(G)},react_production.useDebugValue=function(){},react_production.useDeferredValue=function(G,ce){return z.H.useDeferredValue(G,ce)},react_production.useEffect=function(G,ce){return z.H.useEffect(G,ce)},react_production.useEffectEvent=function(G){return z.H.useEffectEvent(G)},react_production.useId=function(){return z.H.useId()},react_production.useImperativeHandle=function(G,ce,oe){return z.H.useImperativeHandle(G,ce,oe)},react_production.useInsertionEffect=function(G,ce){return z.H.useInsertionEffect(G,ce)},react_production.useLayoutEffect=function(G,ce){return z.H.useLayoutEffect(G,ce)},react_production.useMemo=function(G,ce){return z.H.useMemo(G,ce)},react_production.useOptimistic=function(G,ce){return z.H.useOptimistic(G,ce)},react_production.useReducer=function(G,ce,oe){return z.H.useReducer(G,ce,oe)},react_production.useRef=function(G){return z.H.useRef(G)},react_production.useState=function(G){return z.H.useState(G)},react_production.useSyncExternalStore=function(G,ce,oe){return z.H.useSyncExternalStore(G,ce,oe)},react_production.useTransition=function(){return z.H.useTransition()},react_production.version="19.2.8",react_production}var hasRequiredReact;function requireReact(){return hasRequiredReact||(hasRequiredReact=1,react.exports=requireReact_production()),react.exports}var reactExports=requireReact();const React3=getDefaultExportFromCjs(reactExports),React=_mergeNamespaces({__proto__:null,default:React3},[reactExports]);var client={exports:{}},reactDomClient_production={},scheduler={exports:{}},scheduler_production={};var hasRequiredScheduler_production;function requireScheduler_production(){return hasRequiredScheduler_production||(hasRequiredScheduler_production=1,(function(i){function e(ye,Ve){var pe=ye.length;ye.push(Ve);e:for(;0<pe;){var De=pe-1>>>1,$=ye[De];if(0<s($,Ve))ye[De]=Ve,ye[pe]=$,pe=De;else break e}}function t(ye){return ye.length===0?null:ye[0]}function n(ye){if(ye.length===0)return null;var Ve=ye[0],pe=ye.pop();if(pe!==Ve){ye[0]=pe;e:for(var De=0,$=ye.length,G=$>>>1;De<G;){var ce=2*(De+1)-1,oe=ye[ce],Fe=ce+1,Ue=ye[Fe];if(0>s(oe,pe))Fe<$&&0>s(Ue,oe)?(ye[De]=Ue,ye[Fe]=pe,De=Fe):(ye[De]=oe,ye[ce]=pe,De=ce);else if(Fe<$&&0>s(Ue,pe))ye[De]=Ue,ye[Fe]=pe,De=Fe;else break e}}return Ve}function s(ye,Ve){var pe=ye.sortIndex-Ve.sortIndex;return pe!==0?pe:ye.id-Ve.id}if(i.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var a=performance;i.unstable_now=function(){return a.now()}}else{var u=Date,c=u.now();i.unstable_now=function(){return u.now()-c}}var h=[],f=[],p=1,g=null,y=3,S=!1,w=!1,R=!1,T=!1,A=typeof setTimeout=="function"?setTimeout:null,F=typeof clearTimeout=="function"?clearTimeout:null,x=typeof setImmediate<"u"?setImmediate:null;function D(ye){for(var Ve=t(f);Ve!==null;){if(Ve.callback===null)n(f);else if(Ve.startTime<=ye)n(f),Ve.sortIndex=Ve.expirationTime,e(h,Ve);else break;Ve=t(f)}}function O(ye){if(R=!1,D(ye),!w)if(t(h)!==null)w=!0,K||(K=!0,Te());else{var Ve=t(f);Ve!==null&&ze(O,Ve.startTime-ye)}}var K=!1,z=-1,X=5,Ee=-1;function q(){return T?!0:!(i.unstable_now()-Ee<X)}function Y(){if(T=!1,K){var ye=i.unstable_now();Ee=ye;var Ve=!0;try{e:{w=!1,R&&(R=!1,F(z),z=-1),S=!0;var pe=y;try{t:{for(D(ye),g=t(h);g!==null&&!(g.expirationTime>ye&&q());){var De=g.callback;if(typeof De=="function"){g.callback=null,y=g.priorityLevel;var $=De(g.expirationTime<=ye);if(ye=i.unstable_now(),typeof $=="function"){g.callback=$,D(ye),Ve=!0;break t}g===t(h)&&n(h),D(ye)}else n(h);g=t(h)}if(g!==null)Ve=!0;else{var G=t(f);G!==null&&ze(O,G.startTime-ye),Ve=!1}}break e}finally{g=null,y=pe,S=!1}Ve=void 0}}finally{Ve?Te():K=!1}}}var Te;if(typeof x=="function")Te=function(){x(Y)};else if(typeof MessageChannel<"u"){var re=new MessageChannel,$e=re.port2;re.port1.onmessage=Y,Te=function(){$e.postMessage(null)}}else Te=function(){A(Y,0)};function ze(ye,Ve){z=A(function(){ye(i.unstable_now())},Ve)}i.unstable_IdlePriority=5,i.unstable_ImmediatePriority=1,i.unstable_LowPriority=4,i.unstable_NormalPriority=3,i.unstable_Profiling=null,i.unstable_UserBlockingPriority=2,i.unstable_cancelCallback=function(ye){ye.callback=null},i.unstable_forceFrameRate=function(ye){0>ye||125<ye?console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"):X=0<ye?Math.floor(1e3/ye):5},i.unstable_getCurrentPriorityLevel=function(){return y},i.unstable_next=function(ye){switch(y){case 1:case 2:case 3:var Ve=3;break;default:Ve=y}var pe=y;y=Ve;try{return ye()}finally{y=pe}},i.unstable_requestPaint=function(){T=!0},i.unstable_runWithPriority=function(ye,Ve){switch(ye){case 1:case 2:case 3:case 4:case 5:break;default:ye=3}var pe=y;y=ye;try{return Ve()}finally{y=pe}},i.unstable_scheduleCallback=function(ye,Ve,pe){var De=i.unstable_now();switch(typeof pe=="object"&&pe!==null?(pe=pe.delay,pe=typeof pe=="number"&&0<pe?De+pe:De):pe=De,ye){case 1:var $=-1;break;case 2:$=250;break;case 5:$=1073741823;break;case 4:$=1e4;break;default:$=5e3}return $=pe+$,ye={id:p++,callback:Ve,priorityLevel:ye,startTime:pe,expirationTime:$,sortIndex:-1},pe>De?(ye.sortIndex=pe,e(f,ye),t(h)===null&&ye===t(f)&&(R?(F(z),z=-1):R=!0,ze(O,pe-De))):(ye.sortIndex=$,e(h,ye),w||S||(w=!0,K||(K=!0,Te()))),ye},i.unstable_shouldYield=q,i.unstable_wrapCallback=function(ye){var Ve=y;return function(){var pe=y;y=Ve;try{return ye.apply(this,arguments)}finally{y=pe}}}})(scheduler_production)),scheduler_production}var hasRequiredScheduler;function requireScheduler(){return hasRequiredScheduler||(hasRequiredScheduler=1,scheduler.exports=requireScheduler_production()),scheduler.exports}var reactDom={exports:{}},reactDom_production={};var hasRequiredReactDom_production;function requireReactDom_production(){if(hasRequiredReactDom_production)return reactDom_production;hasRequiredReactDom_production=1;var i=requireReact();function e(h){var f="https://react.dev/errors/"+h;if(1<arguments.length){f+="?args[]="+encodeURIComponent(arguments[1]);for(var p=2;p<arguments.length;p++)f+="&args[]="+encodeURIComponent(arguments[p])}return"Minified React error #"+h+"; visit "+f+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}function t(){}var n={d:{f:t,r:function(){throw Error(e(522))},D:t,C:t,L:t,m:t,X:t,S:t,M:t},p:0,findDOMNode:null},s=Symbol.for("react.portal");function a(h,f,p){var g=3<arguments.length&&arguments[3]!==void 0?arguments[3]:null;return{$$typeof:s,key:g==null?null:""+g,children:h,containerInfo:f,implementation:p}}var u=i.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;function c(h,f){if(h==="font")return"";if(typeof f=="string")return f==="use-credentials"?f:""}return reactDom_production.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE=n,reactDom_production.createPortal=function(h,f){var p=2<arguments.length&&arguments[2]!==void 0?arguments[2]:null;if(!f||f.nodeType!==1&&f.nodeType!==9&&f.nodeType!==11)throw Error(e(299));return a(h,f,null,p)},reactDom_production.flushSync=function(h){var f=u.T,p=n.p;try{if(u.T=null,n.p=2,h)return h()}finally{u.T=f,n.p=p,n.d.f()}},reactDom_production.preconnect=function(h,f){typeof h=="string"&&(f?(f=f.crossOrigin,f=typeof f=="string"?f==="use-credentials"?f:"":void 0):f=null,n.d.C(h,f))},reactDom_production.prefetchDNS=function(h){typeof h=="string"&&n.d.D(h)},reactDom_production.preinit=function(h,f){if(typeof h=="string"&&f&&typeof f.as=="string"){var p=f.as,g=c(p,f.crossOrigin),y=typeof f.integrity=="string"?f.integrity:void 0,S=typeof f.fetchPriority=="string"?f.fetchPriority:void 0;p==="style"?n.d.S(h,typeof f.precedence=="string"?f.precedence:void 0,{crossOrigin:g,integrity:y,fetchPriority:S}):p==="script"&&n.d.X(h,{crossOrigin:g,integrity:y,fetchPriority:S,nonce:typeof f.nonce=="string"?f.nonce:void 0})}},reactDom_production.preinitModule=function(h,f){if(typeof h=="string")if(typeof f=="object"&&f!==null){if(f.as==null||f.as==="script"){var p=c(f.as,f.crossOrigin);n.d.M(h,{crossOrigin:p,integrity:typeof f.integrity=="string"?f.integrity:void 0,nonce:typeof f.nonce=="string"?f.nonce:void 0})}}else f==null&&n.d.M(h)},reactDom_production.preload=function(h,f){if(typeof h=="string"&&typeof f=="object"&&f!==null&&typeof f.as=="string"){var p=f.as,g=c(p,f.crossOrigin);n.d.L(h,p,{crossOrigin:g,integrity:typeof f.integrity=="string"?f.integrity:void 0,nonce:typeof f.nonce=="string"?f.nonce:void 0,type:typeof f.type=="string"?f.type:void 0,fetchPriority:typeof f.fetchPriority=="string"?f.fetchPriority:void 0,referrerPolicy:typeof f.referrerPolicy=="string"?f.referrerPolicy:void 0,imageSrcSet:typeof f.imageSrcSet=="string"?f.imageSrcSet:void 0,imageSizes:typeof f.imageSizes=="string"?f.imageSizes:void 0,media:typeof f.media=="string"?f.media:void 0})}},reactDom_production.preloadModule=function(h,f){if(typeof h=="string")if(f){var p=c(f.as,f.crossOrigin);n.d.m(h,{as:typeof f.as=="string"&&f.as!=="script"?f.as:void 0,crossOrigin:p,integrity:typeof f.integrity=="string"?f.integrity:void 0})}else n.d.m(h)},reactDom_production.requestFormReset=function(h){n.d.r(h)},reactDom_production.unstable_batchedUpdates=function(h,f){return h(f)},reactDom_production.useFormState=function(h,f,p){return u.H.useFormState(h,f,p)},reactDom_production.useFormStatus=function(){return u.H.useHostTransitionStatus()},reactDom_production.version="19.2.8",reactDom_production}var hasRequiredReactDom;function requireReactDom(){if(hasRequiredReactDom)return reactDom.exports;hasRequiredReactDom=1;function i(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(i)}catch(e){console.error(e)}}return i(),reactDom.exports=requireReactDom_production(),reactDom.exports}var hasRequiredReactDomClient_production;function requireReactDomClient_production(){if(hasRequiredReactDomClient_production)return reactDomClient_production;hasRequiredReactDomClient_production=1;var i=requireScheduler(),e=requireReact(),t=requireReactDom();function n(o){var l="https://react.dev/errors/"+o;if(1<arguments.length){l+="?args[]="+encodeURIComponent(arguments[1]);for(var d=2;d<arguments.length;d++)l+="&args[]="+encodeURIComponent(arguments[d])}return"Minified React error #"+o+"; visit "+l+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}function s(o){return!(!o||o.nodeType!==1&&o.nodeType!==9&&o.nodeType!==11)}function a(o){var l=o,d=o;if(o.alternate)for(;l.return;)l=l.return;else{o=l;do l=o,(l.flags&4098)!==0&&(d=l.return),o=l.return;while(o)}return l.tag===3?d:null}function u(o){if(o.tag===13){var l=o.memoizedState;if(l===null&&(o=o.alternate,o!==null&&(l=o.memoizedState)),l!==null)return l.dehydrated}return null}function c(o){if(o.tag===31){var l=o.memoizedState;if(l===null&&(o=o.alternate,o!==null&&(l=o.memoizedState)),l!==null)return l.dehydrated}return null}function h(o){if(a(o)!==o)throw Error(n(188))}function f(o){var l=o.alternate;if(!l){if(l=a(o),l===null)throw Error(n(188));return l!==o?null:o}for(var d=o,m=l;;){var E=d.return;if(E===null)break;var C=E.alternate;if(C===null){if(m=E.return,m!==null){d=m;continue}break}if(E.child===C.child){for(C=E.child;C;){if(C===d)return h(E),o;if(C===m)return h(E),l;C=C.sibling}throw Error(n(188))}if(d.return!==m.return)d=E,m=C;else{for(var W=!1,le=E.child;le;){if(le===d){W=!0,d=E,m=C;break}if(le===m){W=!0,m=E,d=C;break}le=le.sibling}if(!W){for(le=C.child;le;){if(le===d){W=!0,d=C,m=E;break}if(le===m){W=!0,m=C,d=E;break}le=le.sibling}if(!W)throw Error(n(189))}}if(d.alternate!==m)throw Error(n(190))}if(d.tag!==3)throw Error(n(188));return d.stateNode.current===d?o:l}function p(o){var l=o.tag;if(l===5||l===26||l===27||l===6)return o;for(o=o.child;o!==null;){if(l=p(o),l!==null)return l;o=o.sibling}return null}var g=Object.assign,y=Symbol.for("react.element"),S=Symbol.for("react.transitional.element"),w=Symbol.for("react.portal"),R=Symbol.for("react.fragment"),T=Symbol.for("react.strict_mode"),A=Symbol.for("react.profiler"),F=Symbol.for("react.consumer"),x=Symbol.for("react.context"),D=Symbol.for("react.forward_ref"),O=Symbol.for("react.suspense"),K=Symbol.for("react.suspense_list"),z=Symbol.for("react.memo"),X=Symbol.for("react.lazy"),Ee=Symbol.for("react.activity"),q=Symbol.for("react.memo_cache_sentinel"),Y=Symbol.iterator;function Te(o){return o===null||typeof o!="object"?null:(o=Y&&o[Y]||o["@@iterator"],typeof o=="function"?o:null)}var re=Symbol.for("react.client.reference");function $e(o){if(o==null)return null;if(typeof o=="function")return o.$$typeof===re?null:o.displayName||o.name||null;if(typeof o=="string")return o;switch(o){case R:return"Fragment";case A:return"Profiler";case T:return"StrictMode";case O:return"Suspense";case K:return"SuspenseList";case Ee:return"Activity"}if(typeof o=="object")switch(o.$$typeof){case w:return"Portal";case x:return o.displayName||"Context";case F:return(o._context.displayName||"Context")+".Consumer";case D:var l=o.render;return o=o.displayName,o||(o=l.displayName||l.name||"",o=o!==""?"ForwardRef("+o+")":"ForwardRef"),o;case z:return l=o.displayName||null,l!==null?l:$e(o.type)||"Memo";case X:l=o._payload,o=o._init;try{return $e(o(l))}catch{}}return null}var ze=Array.isArray,ye=e.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,Ve=t.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,pe={pending:!1,data:null,method:null,action:null},De=[],$=-1;function G(o){return{current:o}}function ce(o){0>$||(o.current=De[$],De[$]=null,$--)}function oe(o,l){$++,De[$]=o.current,o.current=l}var Fe=G(null),Ue=G(null),Je=G(null),He=G(null);function he(o,l){switch(oe(Je,l),oe(Ue,o),oe(Fe,null),l.nodeType){case 9:case 11:o=(o=l.documentElement)&&(o=o.namespaceURI)?Of(o):0;break;default:if(o=l.tagName,l=l.namespaceURI)l=Of(l),o=$f(l,o);else switch(o){case"svg":o=1;break;case"math":o=2;break;default:o=0}}ce(Fe),oe(Fe,o)}function fe(){ce(Fe),ce(Ue),ce(Je)}function Oe(o){o.memoizedState!==null&&oe(He,o);var l=Fe.current,d=$f(l,o.type);l!==d&&(oe(Ue,o),oe(Fe,d))}function ie(o){Ue.current===o&&(ce(Fe),ce(Ue)),He.current===o&&(ce(He),ia._currentValue=pe)}var j,N;function L(o){if(j===void 0)try{throw Error()}catch(d){var l=d.stack.trim().match(/\n( *(at )?)/);j=l&&l[1]||"",N=-1<d.stack.indexOf(`
3
3
  at`)?" (<anonymous>)":-1<d.stack.indexOf("@")?"@unknown:0:0":""}return`
4
4
  `+j+o+N}var V=!1;function ee(o,l){if(!o||V)return"";V=!0;var d=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{var m={DetermineComponentFrameRoot:function(){try{if(l){var dt=function(){throw Error()};if(Object.defineProperty(dt.prototype,"props",{set:function(){throw Error()}}),typeof Reflect=="object"&&Reflect.construct){try{Reflect.construct(dt,[])}catch(it){var tt=it}Reflect.construct(o,[],dt)}else{try{dt.call()}catch(it){tt=it}o.call(dt.prototype)}}else{try{throw Error()}catch(it){tt=it}(dt=o())&&typeof dt.catch=="function"&&dt.catch(function(){})}}catch(it){if(it&&tt&&typeof it.stack=="string")return[it.stack,tt.stack]}return[null,null]}};m.DetermineComponentFrameRoot.displayName="DetermineComponentFrameRoot";var E=Object.getOwnPropertyDescriptor(m.DetermineComponentFrameRoot,"name");E&&E.configurable&&Object.defineProperty(m.DetermineComponentFrameRoot,"name",{value:"DetermineComponentFrameRoot"});var C=m.DetermineComponentFrameRoot(),W=C[0],le=C[1];if(W&&le){var ke=W.split(`
@@ -302,4 +302,4 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
302
302
  SELECT ?resource WHERE {
303
303
  <${t}> ldp:contains ?resource .
304
304
  }
305
- `,prefixes:{ldp:"http://www.w3.org/ns/ldp#"}},a=await this.sparqlExecutor.queryContainer(t,s);for(const u of a){const c=u.resource;if(c){const h=hasStringValue(c)?c.value:String(c);n.push(h)}}}catch(s){console.warn("[listContainerResources] SPARQL query failed:",s)}return n}}_a=entityKind;PodDialect[_a]="PodDialect";function drizzle(i,e){if(!i||!i.info.isLoggedIn)throw new Error("需要有效的已认证Session");const t={session:i,preferredChannels:e?.notifications?.preferredChannels,createQueryEngine:e?.sparql?.createQueryEngine,disableInteropDiscovery:e?.disableInteropDiscovery,podUrl:e?.podUrl??i.info.podUrl,resourcePreparation:e?.resourcePreparation,storageTTL:e?.storageTTL,debug:e?.debug??e?.logger},n=new PodDialect(t);e?.schema&&n.setSchema(e.schema);const s=new PodAsyncSession(n);return new PodDatabase(n,s,e?.schema)}const SOLID_STORAGE_KEYS=new Set(["solid:storage","http://www.w3.org/ns/solid/terms#storage","pim:storage","http://www.w3.org/ns/pim/space#storage"]);async function fetchProfileStorageUrls(i,e){const t=await i(e,{headers:{Accept:"text/turtle, application/ld+json, application/json"},credentials:"include"}).catch(()=>{});if(!t?.ok)return[];const n=t.headers?.get?.("content-type")??"",s=await t.text().catch(()=>"");if(!s)return[];if(n.includes("json"))try{return uniqueNormalizedStorageUrls(extractStorageUrlsFromJson(JSON.parse(s)))}catch{return[]}return uniqueNormalizedStorageUrls(extractStorageUrlsFromTurtle(s))}function extractStorageUrlsFromTurtle(i){return Array.from(i.matchAll(/(?:solid:storage|pim:storage|<http:\/\/www\.w3\.org\/ns\/solid\/terms#storage>|<http:\/\/www\.w3\.org\/ns\/pim\/space#storage>)\s+<([^>]+)>/giu)).map(e=>e[1]).filter(e=>typeof e=="string"&&e.length>0)}function extractStorageUrlsFromJson(i){const e=new Set,t=new WeakSet,n=(s,a=!1)=>{if(typeof s=="string"){a&&e.add(s);return}if(!(!s||typeof s!="object")&&!t.has(s)){if(t.add(s),Array.isArray(s)){for(const u of s)n(u,a);return}for(const[u,c]of Object.entries(s)){const h=SOLID_STORAGE_KEYS.has(u);if(a&&u==="@id"){n(c,!0);continue}n(c,a||h)}}};return n(i),Array.from(e)}function normalizeStorageUrl(i){try{return ensureTrailingSlash(new URL(i).toString())}catch{return}}function uniqueNormalizedStorageUrls(i){const e=new Set;for(const t of i){const n=normalizeStorageUrl(t);n&&e.add(n)}return Array.from(e)}function ensureTrailingSlash(i){return i.replace(/\/+$/u,"")+"/"}const XPOD_LAST_OIDC_ISSUER_STORAGE_KEY="xpod.solid.lastOidcIssuer",XpodSolidRuntimeContext=reactExports.createContext(null),initializedRuntimes=new WeakSet;function snapshotToState(i,e,t){return i.status==="initializing"?{status:"loading",issuer:t}:i.status==="anonymous"?{status:"anonymous",issuer:t}:i.status==="error"?{status:"error",webId:i.webId,error:i.error,podUrl:e?.podUrl,issuer:t}:{status:"authenticated",webId:i.webId,podUrl:e?.podUrl,issuer:t}}async function discoverPodUrlFromWebId({webId:i,fetch:e}){const n=(await fetchProfileStorageUrls(e,i))[0];if(!n)throw new Error("WebID profile does not declare a Solid storage URL");return ensureTrailingSlash(new URL(n).toString())}function createXpodSolidRuntimeValue(i={}){const e=i.sessionFactory?.()??new Session;let t=readIssuerFromSessionInfo(e.info)??readStoredOidcIssuer();const n=createSolidSessionRuntime({session:e}),s={get info(){return e.info},fetch:e.fetch},a=createPodRuntime({adapter:{discoverPod:({webId:u,fetch:c})=>discoverPodUrlFromWebId({webId:u,fetch:c}),openDatabase:({podUrl:u})=>drizzle(s,{podUrl:u,resourcePreparation:"off"}),hydrateCollections:()=>{}}});return{session:n,pod:a,getIssuer:()=>readIssuerFromSessionInfo(e.info)??t??readStoredOidcIssuer(),setIssuer:u=>{const c=normalizeXpodOidcIssuer(u);t=c,c&&writeStoredOidcIssuer(c)}}}let defaultRuntime;function getXpodSolidRuntimeValue(){return defaultRuntime??=createXpodSolidRuntimeValue(),defaultRuntime}function safeAuthError(i){return i.message==="Solid session expired"?i:new Error("Solid login failed. Please reconnect your Pod.")}function useXpodSolidRuntimeContext(){const i=reactExports.useContext(XpodSolidRuntimeContext);if(!i)throw new Error("useXpodSolidRuntime must be used within XpodSolidRuntimeProvider");return i}function readIssuerFromSessionInfo(i){const e=i.issuer??i.oidcIssuer;return normalizeXpodOidcIssuer(e)}function normalizeXpodOidcIssuer(i){if(!(typeof i!="string"||!i.trim()))try{const e=new URL(i.trim());return e.protocol!=="https:"&&e.protocol!=="http:"||e.username||e.password||e.search||e.hash?void 0:e.toString()}catch{return}}function readStoredOidcIssuer(){try{return normalizeXpodOidcIssuer(globalThis.window?.sessionStorage.getItem(XPOD_LAST_OIDC_ISSUER_STORAGE_KEY))}catch{return}}function writeStoredOidcIssuer(i){try{globalThis.window?.sessionStorage.setItem(XPOD_LAST_OIDC_ISSUER_STORAGE_KEY,i)}catch{}}const useXpodSolidRuntime=useXpodSolidRuntimeContext;function SettingsAuthBoundary({children:i,product:e="Settings"}){const t=useXpodSolidRuntime(),n=t.state.status==="loading"?{status:"loading"}:t.state.status==="authenticated"?{status:"authenticated"}:t.state.status==="error"?{status:"error",message:t.state.error.message}:{status:"anonymous"};return jsxRuntimeExports.jsx(AuthBoundary,{state:n,login:t.login,loginView:{title:`Connect Xpod ${e}`,description:e==="Dashboard"?"Use your Solid identity to inspect Xpod status, runtime, logs, RDF, network, and usage.":"Use your Solid identity to manage model, Pod, network, and service settings.",defaultIssuer:window.location.origin},children:i})}const ModelsPage=reactExports.lazy(()=>__vitePreload(()=>import("./ModelsPage-D_IH7AH3.js"),__vite__mapDeps([0,1,2]))),PodPage=reactExports.lazy(()=>__vitePreload(()=>import("./PodPage-Cy1VNObw.js"),__vite__mapDeps([3,4,2,1]))),ServicesPage=reactExports.lazy(()=>__vitePreload(()=>import("./ServicesPage-BsFaxVWC.js"),__vite__mapDeps([5,6,4,2]))),SettingsPage=reactExports.lazy(()=>__vitePreload(()=>import("./SettingsPage-UafNWE_p.js"),__vite__mapDeps([7,6])).then(i=>({default:i.SettingsPage})));function lazyRoute(i){return jsxRuntimeExports.jsx(reactExports.Suspense,{fallback:jsxRuntimeExports.jsx("div",{className:"p-6 text-sm text-muted-foreground",children:"Loading settings..."}),children:i})}function guardedRoute(i){return jsxRuntimeExports.jsx(SettingsAuthBoundary,{children:i})}const settingsRoutes=[{element:jsxRuntimeExports.jsx(XpodSettingsLayout,{}),children:[{index:!0,element:jsxRuntimeExports.jsx(Navigate,{to:"/models",replace:!0})},{path:"models",element:guardedRoute(lazyRoute(jsxRuntimeExports.jsx(ModelsPage,{})))},{path:"pod",element:guardedRoute(lazyRoute(jsxRuntimeExports.jsx(PodPage,{view:"settings"})))},{path:"network",element:guardedRoute(lazyRoute(jsxRuntimeExports.jsx(ServicesPage,{product:"settings"}))),children:[{index:!0,element:lazyRoute(jsxRuntimeExports.jsx(SettingsPage,{}))}]},{path:"services",element:guardedRoute(lazyRoute(jsxRuntimeExports.jsx(ServicesPage,{product:"settings"}))),children:[{index:!0,element:lazyRoute(jsxRuntimeExports.jsx(SettingsPage,{}))},{path:"configuration",element:lazyRoute(jsxRuntimeExports.jsx(SettingsPage,{}))}]},{path:"*",element:jsxRuntimeExports.jsx(Navigate,{to:"/models",replace:!0})}]}];function XpodSolidRuntimeProvider({children:i,value:e}){const t=e??getXpodSolidRuntimeValue(),[n,s]=reactExports.useState(()=>t.session.getSnapshot()),[a,u]=reactExports.useState(()=>t.getIssuer()),[c,h]=reactExports.useState(),[f,p]=reactExports.useState(),[g,y]=reactExports.useState();reactExports.useEffect(()=>t.session.subscribe(R=>{s(R),u(t.getIssuer()),R.status!=="authenticated"?(h(void 0),p(void 0),t.pod.clear()):R.webId!==n.webId&&y(void 0)}),[t,n.webId]),reactExports.useEffect(()=>{initializedRuntimes.has(t)||(initializedRuntimes.add(t),t.session.initialize({restorePreviousSession:!0}).then(R=>{s(R),u(t.getIssuer())}))},[t]),reactExports.useEffect(()=>{if(n.status!=="authenticated")return;let R=!1;return t.pod.open({webId:n.webId,fetch:t.session.fetch}).then(T=>{R||(h(T),p(void 0))},T=>{R||p({webId:n.webId,error:T instanceof Error?T:new Error(String(T))})}),()=>{R=!0}},[t,n]);const S=n.status==="authenticated"?n.webId:void 0;reactExports.useEffect(()=>{if(!S)return;let R=!1;return discoverAiClientConfigurationCapability(t.session.fetch).then(T=>{!R&&t.session.getSnapshot().status==="authenticated"&&t.session.getSnapshot().webId===S&&y(T)}),()=>{R=!0}},[S,t]);const w=reactExports.useMemo(()=>{const R=a??t.getIssuer(),T=n.status==="authenticated"&&f?.webId===n.webId?f.error:void 0,A=T?{status:"error",webId:n.webId,podUrl:c?.podUrl,issuer:R,error:T}:snapshotToState(n,c,R);return{session:t.session,pod:t.pod,fetch:t.session.fetch,state:A.status==="error"?{...A,error:safeAuthError(A.error)}:A,webId:A.webId,podUrl:A.podUrl,issuer:A.issuer,currentPod:c,aiClientConfiguration:g,login:async F=>{const x=normalizeXpodOidcIssuer(F);x&&(t.setIssuer(x),u(x),await t.session.login({oidcIssuer:x,redirectUrl:window.location.href}))},logout:async()=>{t.pod.clear(),h(void 0),await t.session.logout()}}},[g,c,a,f,t,n]);return jsxRuntimeExports.jsx(SolidRuntimeProvider,{value:{session:t.session,pod:t.pod,currentPod:c},children:jsxRuntimeExports.jsx(XpodSolidRuntimeContext.Provider,{value:w,children:i})})}async function discoverAiClientConfigurationCapability(i){try{const e=await i("/api/ai/client-configuration/capability",{method:"GET",credentials:"include",headers:{accept:"application/json"}});if(!e.ok||!e.headers.get("content-type")?.includes("application/json"))return await e.arrayBuffer().catch(()=>{}),manualAiClientConfigurationCapability();const t=await e.json();if(isRecord(t)&&t.available===!0&&t.authority==="local-filesystem")return{available:!0,authority:"local-filesystem",manualInstructions:typeof t.manualInstructions=="string"?t.manualInstructions:manualAiClientConfigurationCapability().manualInstructions}}catch{}return manualAiClientConfigurationCapability()}function manualAiClientConfigurationCapability(){return{available:!1,manualInstructions:"manual client setup is available"}}function isRecord(i){return!!(i&&typeof i=="object"&&!Array.isArray(i))}function SettingsRoutes(){return useRoutes(settingsRoutes)}function SettingsApp(){return jsxRuntimeExports.jsx(XpodSolidRuntimeProvider,{children:jsxRuntimeExports.jsx(BrowserRouter,{basename:"/settings",children:jsxRuntimeExports.jsx(SettingsRoutes,{})})})}clientExports.createRoot(document.getElementById("root")).render(jsxRuntimeExports.jsx(reactExports.StrictMode,{children:jsxRuntimeExports.jsx(SettingsApp,{})}));export{Button as B,Input as I,NavLink as N,Outlet as O,React as R,Server as S,cva as a,createLucideIcon as b,cn as c,clsx as d,useXpodSolidRuntime as e,requireReact as f,useComposedRefs as g,createSlot as h,jsxRuntimeExports as j,reactExports as r,useLocation as u};
305
+ `,prefixes:{ldp:"http://www.w3.org/ns/ldp#"}},a=await this.sparqlExecutor.queryContainer(t,s);for(const u of a){const c=u.resource;if(c){const h=hasStringValue(c)?c.value:String(c);n.push(h)}}}catch(s){console.warn("[listContainerResources] SPARQL query failed:",s)}return n}}_a=entityKind;PodDialect[_a]="PodDialect";function drizzle(i,e){if(!i||!i.info.isLoggedIn)throw new Error("需要有效的已认证Session");const t={session:i,preferredChannels:e?.notifications?.preferredChannels,createQueryEngine:e?.sparql?.createQueryEngine,disableInteropDiscovery:e?.disableInteropDiscovery,podUrl:e?.podUrl??i.info.podUrl,resourcePreparation:e?.resourcePreparation,storageTTL:e?.storageTTL,debug:e?.debug??e?.logger},n=new PodDialect(t);e?.schema&&n.setSchema(e.schema);const s=new PodAsyncSession(n);return new PodDatabase(n,s,e?.schema)}const SOLID_STORAGE_KEYS=new Set(["solid:storage","http://www.w3.org/ns/solid/terms#storage","pim:storage","http://www.w3.org/ns/pim/space#storage"]);async function fetchProfileStorageUrls(i,e){const t=await i(e,{headers:{Accept:"text/turtle, application/ld+json, application/json"},credentials:"include"}).catch(()=>{});if(!t?.ok)return[];const n=t.headers?.get?.("content-type")??"",s=await t.text().catch(()=>"");if(!s)return[];if(n.includes("json"))try{return uniqueNormalizedStorageUrls(extractStorageUrlsFromJson(JSON.parse(s)))}catch{return[]}return uniqueNormalizedStorageUrls(extractStorageUrlsFromTurtle(s))}function extractStorageUrlsFromTurtle(i){return Array.from(i.matchAll(/(?:solid:storage|pim:storage|<http:\/\/www\.w3\.org\/ns\/solid\/terms#storage>|<http:\/\/www\.w3\.org\/ns\/pim\/space#storage>)\s+<([^>]+)>/giu)).map(e=>e[1]).filter(e=>typeof e=="string"&&e.length>0)}function extractStorageUrlsFromJson(i){const e=new Set,t=new WeakSet,n=(s,a=!1)=>{if(typeof s=="string"){a&&e.add(s);return}if(!(!s||typeof s!="object")&&!t.has(s)){if(t.add(s),Array.isArray(s)){for(const u of s)n(u,a);return}for(const[u,c]of Object.entries(s)){const h=SOLID_STORAGE_KEYS.has(u);if(a&&u==="@id"){n(c,!0);continue}n(c,a||h)}}};return n(i),Array.from(e)}function normalizeStorageUrl(i){try{return ensureTrailingSlash(new URL(i).toString())}catch{return}}function uniqueNormalizedStorageUrls(i){const e=new Set;for(const t of i){const n=normalizeStorageUrl(t);n&&e.add(n)}return Array.from(e)}function ensureTrailingSlash(i){return i.replace(/\/+$/u,"")+"/"}const XPOD_LAST_OIDC_ISSUER_STORAGE_KEY="xpod.solid.lastOidcIssuer",XpodSolidRuntimeContext=reactExports.createContext(null),initializedRuntimes=new WeakSet;function snapshotToState(i,e,t){return i.status==="initializing"?{status:"loading",issuer:t}:i.status==="anonymous"?{status:"anonymous",issuer:t}:i.status==="error"?{status:"error",webId:i.webId,error:i.error,podUrl:e?.podUrl,issuer:t}:{status:"authenticated",webId:i.webId,podUrl:e?.podUrl,issuer:t}}async function discoverPodUrlFromWebId({webId:i,fetch:e}){const n=(await fetchProfileStorageUrls(e,i))[0];if(!n)throw new Error("WebID profile does not declare a Solid storage URL");return ensureTrailingSlash(new URL(n).toString())}function createXpodSolidRuntimeValue(i={}){const e=i.sessionFactory?.()??new Session;let t=readIssuerFromSessionInfo(e.info)??readStoredOidcIssuer();const n=createSolidSessionRuntime({session:e}),s={get info(){return e.info},fetch:e.fetch},a=createPodRuntime({adapter:{discoverPod:({webId:u,fetch:c})=>discoverPodUrlFromWebId({webId:u,fetch:c}),openDatabase:({podUrl:u})=>drizzle(s,{podUrl:u,resourcePreparation:"off"}),hydrateCollections:()=>{}}});return{session:n,pod:a,getIssuer:()=>readIssuerFromSessionInfo(e.info)??t??readStoredOidcIssuer(),setIssuer:u=>{const c=normalizeXpodOidcIssuer(u);t=c,c&&writeStoredOidcIssuer(c)}}}let defaultRuntime;function getXpodSolidRuntimeValue(){return defaultRuntime??=createXpodSolidRuntimeValue(),defaultRuntime}function safeAuthError(i){return i.message==="Solid session expired"?i:new Error("Solid login failed. Please reconnect your Pod.")}function useXpodSolidRuntimeContext(){const i=reactExports.useContext(XpodSolidRuntimeContext);if(!i)throw new Error("useXpodSolidRuntime must be used within XpodSolidRuntimeProvider");return i}function readIssuerFromSessionInfo(i){const e=i.issuer??i.oidcIssuer;return normalizeXpodOidcIssuer(e)}function normalizeXpodOidcIssuer(i){if(!(typeof i!="string"||!i.trim()))try{const e=new URL(i.trim());return e.protocol!=="https:"&&e.protocol!=="http:"||e.username||e.password||e.search||e.hash?void 0:e.toString()}catch{return}}function readStoredOidcIssuer(){try{return normalizeXpodOidcIssuer(globalThis.window?.sessionStorage.getItem(XPOD_LAST_OIDC_ISSUER_STORAGE_KEY))}catch{return}}function writeStoredOidcIssuer(i){try{globalThis.window?.sessionStorage.setItem(XPOD_LAST_OIDC_ISSUER_STORAGE_KEY,i)}catch{}}const useXpodSolidRuntime=useXpodSolidRuntimeContext;function SettingsAuthBoundary({children:i,product:e="Settings"}){const t=useXpodSolidRuntime(),n=t.state.status==="loading"?{status:"loading"}:t.state.status==="authenticated"?{status:"authenticated"}:t.state.status==="error"?{status:"error",message:t.state.error.message}:{status:"anonymous"};return jsxRuntimeExports.jsx(AuthBoundary,{state:n,login:t.login,loginView:{title:`Connect Xpod ${e}`,description:e==="Dashboard"?"Use your Solid identity to inspect Xpod status, runtime, logs, RDF, network, and usage.":"Use your Solid identity to manage model, Pod, network, and service settings.",defaultIssuer:window.location.origin},children:i})}const ModelsPage=reactExports.lazy(()=>__vitePreload(()=>import("./ModelsPage-03NPWzoX.js"),__vite__mapDeps([0,1,2]))),PodPage=reactExports.lazy(()=>__vitePreload(()=>import("./PodPage-DT4EMYhL.js"),__vite__mapDeps([3,4,2,1]))),ServicesPage=reactExports.lazy(()=>__vitePreload(()=>import("./ServicesPage-CJ0ub6IH.js"),__vite__mapDeps([5,6,4,2]))),SettingsPage=reactExports.lazy(()=>__vitePreload(()=>import("./SettingsPage-BkR7ZK18.js"),__vite__mapDeps([7,6])).then(i=>({default:i.SettingsPage})));function lazyRoute(i){return jsxRuntimeExports.jsx(reactExports.Suspense,{fallback:jsxRuntimeExports.jsx("div",{className:"p-6 text-sm text-muted-foreground",children:"Loading settings..."}),children:i})}function guardedRoute(i){return jsxRuntimeExports.jsx(SettingsAuthBoundary,{children:i})}const settingsRoutes=[{element:jsxRuntimeExports.jsx(XpodSettingsLayout,{}),children:[{index:!0,element:jsxRuntimeExports.jsx(Navigate,{to:"/models",replace:!0})},{path:"models",element:guardedRoute(lazyRoute(jsxRuntimeExports.jsx(ModelsPage,{})))},{path:"pod",element:guardedRoute(lazyRoute(jsxRuntimeExports.jsx(PodPage,{view:"settings"})))},{path:"network",element:guardedRoute(lazyRoute(jsxRuntimeExports.jsx(ServicesPage,{product:"settings"}))),children:[{index:!0,element:lazyRoute(jsxRuntimeExports.jsx(SettingsPage,{}))}]},{path:"services",element:guardedRoute(lazyRoute(jsxRuntimeExports.jsx(ServicesPage,{product:"settings"}))),children:[{index:!0,element:lazyRoute(jsxRuntimeExports.jsx(SettingsPage,{}))},{path:"configuration",element:lazyRoute(jsxRuntimeExports.jsx(SettingsPage,{}))}]},{path:"*",element:jsxRuntimeExports.jsx(Navigate,{to:"/models",replace:!0})}]}];function XpodSolidRuntimeProvider({children:i,value:e}){const t=e??getXpodSolidRuntimeValue(),[n,s]=reactExports.useState(()=>t.session.getSnapshot()),[a,u]=reactExports.useState(()=>t.getIssuer()),[c,h]=reactExports.useState(),[f,p]=reactExports.useState(),[g,y]=reactExports.useState();reactExports.useEffect(()=>t.session.subscribe(R=>{s(R),u(t.getIssuer()),R.status!=="authenticated"?(h(void 0),p(void 0),t.pod.clear()):R.webId!==n.webId&&y(void 0)}),[t,n.webId]),reactExports.useEffect(()=>{initializedRuntimes.has(t)||(initializedRuntimes.add(t),t.session.initialize({restorePreviousSession:!0}).then(R=>{s(R),u(t.getIssuer())}))},[t]),reactExports.useEffect(()=>{if(n.status!=="authenticated")return;let R=!1;return t.pod.open({webId:n.webId,fetch:t.session.fetch}).then(T=>{R||(h(T),p(void 0))},T=>{R||p({webId:n.webId,error:T instanceof Error?T:new Error(String(T))})}),()=>{R=!0}},[t,n]);const S=n.status==="authenticated"?n.webId:void 0;reactExports.useEffect(()=>{if(!S)return;let R=!1;return discoverAiClientConfigurationCapability(t.session.fetch).then(T=>{!R&&t.session.getSnapshot().status==="authenticated"&&t.session.getSnapshot().webId===S&&y(T)}),()=>{R=!0}},[S,t]);const w=reactExports.useMemo(()=>{const R=a??t.getIssuer(),T=n.status==="authenticated"&&f?.webId===n.webId?f.error:void 0,A=T?{status:"error",webId:n.webId,podUrl:c?.podUrl,issuer:R,error:T}:snapshotToState(n,c,R);return{session:t.session,pod:t.pod,fetch:t.session.fetch,state:A.status==="error"?{...A,error:safeAuthError(A.error)}:A,webId:A.webId,podUrl:A.podUrl,issuer:A.issuer,currentPod:c,aiClientConfiguration:g,login:async F=>{const x=normalizeXpodOidcIssuer(F);x&&(t.setIssuer(x),u(x),await t.session.login({oidcIssuer:x,redirectUrl:window.location.href}))},logout:async()=>{t.pod.clear(),h(void 0),await t.session.logout()}}},[g,c,a,f,t,n]);return jsxRuntimeExports.jsx(SolidRuntimeProvider,{value:{session:t.session,pod:t.pod,currentPod:c},children:jsxRuntimeExports.jsx(XpodSolidRuntimeContext.Provider,{value:w,children:i})})}async function discoverAiClientConfigurationCapability(i){try{const e=await i("/api/ai/client-configuration/capability",{method:"GET",credentials:"include",headers:{accept:"application/json"}});if(!e.ok||!e.headers.get("content-type")?.includes("application/json"))return await e.arrayBuffer().catch(()=>{}),manualAiClientConfigurationCapability();const t=await e.json();if(isRecord(t)&&t.available===!0&&t.authority==="local-filesystem")return{available:!0,authority:"local-filesystem",manualInstructions:typeof t.manualInstructions=="string"?t.manualInstructions:manualAiClientConfigurationCapability().manualInstructions}}catch{}return manualAiClientConfigurationCapability()}function manualAiClientConfigurationCapability(){return{available:!1,manualInstructions:"manual client setup is available"}}function isRecord(i){return!!(i&&typeof i=="object"&&!Array.isArray(i))}function SettingsRoutes(){return useRoutes(settingsRoutes)}function SettingsApp(){return jsxRuntimeExports.jsx(XpodSolidRuntimeProvider,{children:jsxRuntimeExports.jsx(BrowserRouter,{basename:"/settings",children:jsxRuntimeExports.jsx(SettingsRoutes,{})})})}clientExports.createRoot(document.getElementById("root")).render(jsxRuntimeExports.jsx(reactExports.StrictMode,{children:jsxRuntimeExports.jsx(SettingsApp,{})}));export{Button as B,Input as I,NavLink as N,Outlet as O,React as R,Server as S,cva as a,createLucideIcon as b,cn as c,clsx as d,useXpodSolidRuntime as e,requireReactDom as f,useComposedRefs as g,createSlot as h,jsxRuntimeExports as j,reactExports as r,useLocation as u};
@@ -1 +1 @@
1
- import{r as t,j as s,c as k}from"./settings-B30oMfZq.js";const y=t.createContext(null);function P(){const e=t.useContext(y);if(!e)throw new Error("useWorkspaceLayout must be used inside TwoPaneLayout");return e}const g="(max-width: 767px)",v={gridTemplateColumns:"210px minmax(0, 1fr)"};function j(e){return e==="context"?"main":e}function C(e){if(typeof window>"u"||typeof window.matchMedia!="function")return()=>{};const a=window.matchMedia(g);return a.addEventListener("change",e),()=>a.removeEventListener("change",e)}function R(){return typeof window>"u"||typeof window.matchMedia!="function"?"split":window.matchMedia(g).matches?"stack":"split"}function L(){return"split"}function M(e){const a=t.useSyncExternalStore(C,R,L);return e==="auto"?a:e}function N({resolvedMode:e,history:a,resolvePane:l}){const[f,m]=t.useState("list"),c=t.useRef(null),h=t.useRef(null),r=t.useRef(null),i=t.useRef(null),u=t.useMemo(()=>({list:h,main:r,context:i}),[]),o=t.useCallback((n,b={})=>{const d=l?.(n)??n;m(d),e==="stack"&&(c.current=d,b.fromHistory||a?.push(d))},[a,l,e]),p=t.useCallback(()=>o("list"),[o]),x=t.useCallback(()=>o("main"),[o]),w=t.useCallback(()=>o("context"),[o]);return t.useLayoutEffect(()=>{if(e!=="stack"){c.current=null;return}const n=c.current;n&&(c.current=null,u[n].current?.focus())},[f,u,e]),t.useLayoutEffect(()=>{if(!(e!=="stack"||!a))return a.subscribe(n=>{o(n,{fromHistory:!0})})},[a,o,e]),{activePane:f,paneRefs:u,openList:p,openMain:x,openContext:w}}function S({listHeader:e,list:a,mainHeader:l,main:f,mode:m="auto",history:c,className:h}){const r=M(m),{activePane:i,paneRefs:u,openList:o,openMain:p,openContext:x}=N({resolvedMode:r,history:c,resolvePane:j}),w=t.useMemo(()=>({mode:r,activePane:i,openList:o,openMain:p,openContext:x}),[i,x,o,p,r]),n=r==="stack",b=n&&i!=="list",d=n&&i!=="main";return s.jsx(y.Provider,{value:w,children:s.jsx("section",{className:k("flex min-h-0 flex-1 flex-col bg-background",h),"data-workspace-layout":"two-pane","data-workspace-mode":r,children:s.jsxs("div",{className:k("grid min-h-0 flex-1",n?"grid-cols-1":null),style:n?void 0:v,"data-workspace-layout-mode":m,"data-workspace-active-pane":i,children:[s.jsxs("aside",{ref:u.list,className:k("flex min-h-0 flex-col overflow-hidden bg-layout-list-item @container",n?"border-r-0":"border-r border-border"),"data-testid":"workspace-list-pane","data-workspace-pane":"list",hidden:b,tabIndex:n?-1:void 0,children:[s.jsx("header",{className:"h-12 shrink-0 border-b border-border bg-layout-list-header","data-workspace-list-header":"true",children:e}),s.jsx("div",{className:"min-h-0 flex-1 overflow-y-auto",children:a})]}),s.jsxs("main",{ref:u.main,className:"flex min-h-0 flex-col overflow-hidden bg-layout-content @container","data-testid":"workspace-main-pane","data-workspace-pane":"main",hidden:d,tabIndex:n?-1:void 0,children:[s.jsx("header",{className:"h-12 shrink-0 border-b border-border bg-layout-content","data-workspace-main-header":"true",children:l}),s.jsxs("div",{className:"min-h-0 flex-1 overflow-y-auto",children:[n?s.jsx("button",{type:"button",className:"inline-flex items-center px-4 py-3 text-sm text-muted-foreground hover:text-foreground",onClick:o,children:"返回列表"}):null,f]})]})]})})})}export{S as T,P as u};
1
+ import{r as t,j as s,c as k}from"./settings-Cyyv6-SD.js";const y=t.createContext(null);function P(){const e=t.useContext(y);if(!e)throw new Error("useWorkspaceLayout must be used inside TwoPaneLayout");return e}const g="(max-width: 767px)",v={gridTemplateColumns:"210px minmax(0, 1fr)"};function j(e){return e==="context"?"main":e}function C(e){if(typeof window>"u"||typeof window.matchMedia!="function")return()=>{};const a=window.matchMedia(g);return a.addEventListener("change",e),()=>a.removeEventListener("change",e)}function R(){return typeof window>"u"||typeof window.matchMedia!="function"?"split":window.matchMedia(g).matches?"stack":"split"}function L(){return"split"}function M(e){const a=t.useSyncExternalStore(C,R,L);return e==="auto"?a:e}function N({resolvedMode:e,history:a,resolvePane:l}){const[f,m]=t.useState("list"),c=t.useRef(null),h=t.useRef(null),r=t.useRef(null),i=t.useRef(null),u=t.useMemo(()=>({list:h,main:r,context:i}),[]),o=t.useCallback((n,b={})=>{const d=l?.(n)??n;m(d),e==="stack"&&(c.current=d,b.fromHistory||a?.push(d))},[a,l,e]),p=t.useCallback(()=>o("list"),[o]),x=t.useCallback(()=>o("main"),[o]),w=t.useCallback(()=>o("context"),[o]);return t.useLayoutEffect(()=>{if(e!=="stack"){c.current=null;return}const n=c.current;n&&(c.current=null,u[n].current?.focus())},[f,u,e]),t.useLayoutEffect(()=>{if(!(e!=="stack"||!a))return a.subscribe(n=>{o(n,{fromHistory:!0})})},[a,o,e]),{activePane:f,paneRefs:u,openList:p,openMain:x,openContext:w}}function S({listHeader:e,list:a,mainHeader:l,main:f,mode:m="auto",history:c,className:h}){const r=M(m),{activePane:i,paneRefs:u,openList:o,openMain:p,openContext:x}=N({resolvedMode:r,history:c,resolvePane:j}),w=t.useMemo(()=>({mode:r,activePane:i,openList:o,openMain:p,openContext:x}),[i,x,o,p,r]),n=r==="stack",b=n&&i!=="list",d=n&&i!=="main";return s.jsx(y.Provider,{value:w,children:s.jsx("section",{className:k("flex min-h-0 flex-1 flex-col bg-background",h),"data-workspace-layout":"two-pane","data-workspace-mode":r,children:s.jsxs("div",{className:k("grid min-h-0 flex-1",n?"grid-cols-1":null),style:n?void 0:v,"data-workspace-layout-mode":m,"data-workspace-active-pane":i,children:[s.jsxs("aside",{ref:u.list,className:k("flex min-h-0 flex-col overflow-hidden bg-layout-list-item @container",n?"border-r-0":"border-r border-border"),"data-testid":"workspace-list-pane","data-workspace-pane":"list",hidden:b,tabIndex:n?-1:void 0,children:[s.jsx("header",{className:"h-12 shrink-0 border-b border-border bg-layout-list-header","data-workspace-list-header":"true",children:e}),s.jsx("div",{className:"min-h-0 flex-1 overflow-y-auto",children:a})]}),s.jsxs("main",{ref:u.main,className:"flex min-h-0 flex-col overflow-hidden bg-layout-content @container","data-testid":"workspace-main-pane","data-workspace-pane":"main",hidden:d,tabIndex:n?-1:void 0,children:[s.jsx("header",{className:"h-12 shrink-0 border-b border-border bg-layout-content","data-workspace-main-header":"true",children:l}),s.jsxs("div",{className:"min-h-0 flex-1 overflow-y-auto",children:[n?s.jsx("button",{type:"button",className:"inline-flex items-center px-4 py-3 text-sm text-muted-foreground hover:text-foreground",onClick:o,children:"返回列表"}):null,f]})]})]})})})}export{S as T,P as u};
@@ -4,7 +4,7 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>Xpod Settings</title>
7
- <script type="module" crossorigin src="/settings/assets/settings-B30oMfZq.js"></script>
7
+ <script type="module" crossorigin src="/settings/assets/settings-Cyyv6-SD.js"></script>
8
8
  <link rel="stylesheet" crossorigin href="/settings/assets/settings-CSdewNeA.css">
9
9
  </head>
10
10
  <body>
@@ -1,25 +0,0 @@
1
- import type { InternalPodAccessTokenProvider } from './PodGatewayAccessKeyRepository';
2
- export interface ClientCredentialsInternalPodAccessTokenProviderOptions {
3
- tokenEndpoint: string;
4
- clientId: string;
5
- clientSecret: string;
6
- fetchImpl?: typeof fetch;
7
- now?: () => number;
8
- }
9
- export declare class ClientCredentialsInternalPodAccessTokenProvider implements InternalPodAccessTokenProvider {
10
- private readonly tokenEndpoint;
11
- private readonly clientId;
12
- private readonly clientSecret;
13
- private readonly fetchImpl;
14
- private readonly now;
15
- private cachedToken?;
16
- private tokenRequest?;
17
- private serviceWebId?;
18
- constructor(options: ClientCredentialsInternalPodAccessTokenProviderOptions);
19
- getTrustedFetch(_owner: string): Promise<typeof fetch | undefined>;
20
- getServicePrincipal(): Promise<{
21
- webId: string;
22
- }>;
23
- private getAccessToken;
24
- private exchangeToken;
25
- }
@@ -1,91 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ClientCredentialsInternalPodAccessTokenProvider = void 0;
4
- const TokenIdentity_1 = require("../../auth/TokenIdentity");
5
- class ClientCredentialsInternalPodAccessTokenProvider {
6
- constructor(options) {
7
- if (!options.clientId.trim() || !options.clientSecret.trim()) {
8
- throw new Error('Gateway internal Pod access client credentials are required');
9
- }
10
- this.tokenEndpoint = options.tokenEndpoint;
11
- this.clientId = options.clientId;
12
- this.clientSecret = options.clientSecret;
13
- this.fetchImpl = options.fetchImpl ?? fetch;
14
- this.now = options.now ?? Date.now;
15
- }
16
- async getTrustedFetch(_owner) {
17
- const token = await this.getAccessToken();
18
- return async (input, init) => {
19
- const headers = new Headers(init?.headers);
20
- if (!headers.has('Authorization')) {
21
- headers.set('Authorization', `Bearer ${token.accessToken}`);
22
- }
23
- return this.fetchImpl(input, { ...init, headers });
24
- };
25
- }
26
- async getServicePrincipal() {
27
- const token = await this.getAccessToken();
28
- return { webId: token.webId };
29
- }
30
- async getAccessToken() {
31
- const now = this.now();
32
- if (this.cachedToken && this.cachedToken.expiresAt - 30_000 > now) {
33
- return this.cachedToken;
34
- }
35
- if (this.tokenRequest) {
36
- return this.tokenRequest;
37
- }
38
- this.tokenRequest = this.exchangeToken(now);
39
- try {
40
- return await this.tokenRequest;
41
- }
42
- finally {
43
- this.tokenRequest = undefined;
44
- }
45
- }
46
- async exchangeToken(now) {
47
- const response = await this.fetchImpl(this.tokenEndpoint, {
48
- method: 'POST',
49
- headers: {
50
- 'Content-Type': 'application/x-www-form-urlencoded',
51
- },
52
- body: new URLSearchParams({
53
- grant_type: 'client_credentials',
54
- client_id: this.clientId,
55
- client_secret: this.clientSecret,
56
- scope: 'webid',
57
- }),
58
- });
59
- if (!response.ok) {
60
- throw new Error(`Gateway internal Pod token exchange failed: HTTP ${response.status}`);
61
- }
62
- const body = await response.json();
63
- const accessToken = typeof body.access_token === 'string' ? body.access_token : undefined;
64
- if (!accessToken) {
65
- throw new Error('Gateway internal Pod token response missing access_token');
66
- }
67
- if (body.token_type !== 'Bearer') {
68
- throw new Error('Gateway internal service token must be Bearer');
69
- }
70
- const tokenWebId = (0, TokenIdentity_1.extractAuthoritativeWebIdFromTokenResponse)(body);
71
- if (!tokenWebId) {
72
- throw new Error('Gateway internal Pod token response missing authoritative WebID');
73
- }
74
- if (this.serviceWebId && tokenWebId !== this.serviceWebId) {
75
- throw new Error('Gateway internal service WebID changed');
76
- }
77
- const expiresIn = typeof body.expires_in === 'number' && Number.isFinite(body.expires_in)
78
- ? body.expires_in
79
- : 300;
80
- const token = {
81
- accessToken,
82
- webId: tokenWebId,
83
- expiresAt: now + expiresIn * 1000,
84
- };
85
- this.serviceWebId = tokenWebId;
86
- this.cachedToken = token;
87
- return token;
88
- }
89
- }
90
- exports.ClientCredentialsInternalPodAccessTokenProvider = ClientCredentialsInternalPodAccessTokenProvider;
91
- //# sourceMappingURL=ClientCredentialsInternalPodAccessTokenProvider.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ClientCredentialsInternalPodAccessTokenProvider.js","sourceRoot":"","sources":["../../../../src/api/ai-gateway/auth/ClientCredentialsInternalPodAccessTokenProvider.ts"],"names":[],"mappings":"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","sourcesContent":["import type { InternalPodAccessTokenProvider } from './PodGatewayAccessKeyRepository';\nimport { extractAuthoritativeWebIdFromTokenResponse } from '../../auth/TokenIdentity';\n\nexport interface ClientCredentialsInternalPodAccessTokenProviderOptions {\n tokenEndpoint: string;\n clientId: string;\n clientSecret: string;\n fetchImpl?: typeof fetch;\n now?: () => number;\n}\n\ntype CachedToken = {\n accessToken: string;\n webId: string;\n expiresAt: number;\n};\n\nexport class ClientCredentialsInternalPodAccessTokenProvider implements InternalPodAccessTokenProvider {\n private readonly tokenEndpoint: string;\n private readonly clientId: string;\n private readonly clientSecret: string;\n private readonly fetchImpl: typeof fetch;\n private readonly now: () => number;\n private cachedToken?: CachedToken;\n private tokenRequest?: Promise<CachedToken>;\n private serviceWebId?: string;\n\n public constructor(options: ClientCredentialsInternalPodAccessTokenProviderOptions) {\n if (!options.clientId.trim() || !options.clientSecret.trim()) {\n throw new Error('Gateway internal Pod access client credentials are required');\n }\n this.tokenEndpoint = options.tokenEndpoint;\n this.clientId = options.clientId;\n this.clientSecret = options.clientSecret;\n this.fetchImpl = options.fetchImpl ?? fetch;\n this.now = options.now ?? Date.now;\n }\n\n public async getTrustedFetch(_owner: string): Promise<typeof fetch | undefined> {\n const token = await this.getAccessToken();\n return async (input, init) => {\n const headers = new Headers(init?.headers);\n if (!headers.has('Authorization')) {\n headers.set('Authorization', `Bearer ${token.accessToken}`);\n }\n return this.fetchImpl(input, { ...init, headers });\n };\n }\n\n public async getServicePrincipal(): Promise<{ webId: string }> {\n const token = await this.getAccessToken();\n return { webId: token.webId };\n }\n\n private async getAccessToken(): Promise<CachedToken> {\n const now = this.now();\n if (this.cachedToken && this.cachedToken.expiresAt - 30_000 > now) {\n return this.cachedToken;\n }\n if (this.tokenRequest) {\n return this.tokenRequest;\n }\n\n this.tokenRequest = this.exchangeToken(now);\n try {\n return await this.tokenRequest;\n } finally {\n this.tokenRequest = undefined;\n }\n }\n\n private async exchangeToken(now: number): Promise<CachedToken> {\n const response = await this.fetchImpl(this.tokenEndpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams({\n grant_type: 'client_credentials',\n client_id: this.clientId,\n client_secret: this.clientSecret,\n scope: 'webid',\n }),\n });\n if (!response.ok) {\n throw new Error(`Gateway internal Pod token exchange failed: HTTP ${response.status}`);\n }\n const body = await response.json() as Record<string, unknown>;\n const accessToken = typeof body.access_token === 'string' ? body.access_token : undefined;\n if (!accessToken) {\n throw new Error('Gateway internal Pod token response missing access_token');\n }\n if (body.token_type !== 'Bearer') {\n throw new Error('Gateway internal service token must be Bearer');\n }\n const tokenWebId = extractAuthoritativeWebIdFromTokenResponse(body);\n if (!tokenWebId) {\n throw new Error('Gateway internal Pod token response missing authoritative WebID');\n }\n if (this.serviceWebId && tokenWebId !== this.serviceWebId) {\n throw new Error('Gateway internal service WebID changed');\n }\n const expiresIn = typeof body.expires_in === 'number' && Number.isFinite(body.expires_in)\n ? body.expires_in\n : 300;\n const token: CachedToken = {\n accessToken,\n webId: tokenWebId,\n expiresAt: now + expiresIn * 1000,\n };\n this.serviceWebId = tokenWebId;\n this.cachedToken = token;\n return token;\n }\n}\n"]}
@@ -1,28 +0,0 @@
1
- export type GatewayDeployment = 'local' | 'cloud';
2
- export interface ParsedGatewayApiKey {
3
- version: 'v1';
4
- deployment: GatewayDeployment;
5
- keyId: string;
6
- secret: string;
7
- }
8
- export interface GatewayApiKeyRecordInput {
9
- id: string;
10
- secretHash: string;
11
- deployment: GatewayDeployment;
12
- }
13
- export interface CreatedGatewayApiKey {
14
- plaintext: string;
15
- secret: string;
16
- record: GatewayApiKeyRecordInput;
17
- }
18
- export interface CreateGatewayApiKeyInput {
19
- deployment: GatewayDeployment;
20
- keyId?: string;
21
- secret?: string;
22
- }
23
- export declare function createGatewayApiKey(input: CreateGatewayApiKeyInput): Promise<CreatedGatewayApiKey>;
24
- export declare function createGatewayKeyId(): string;
25
- export declare function formatGatewayApiKey(parsed: ParsedGatewayApiKey): string;
26
- export declare function parseGatewayApiKey(value: string): ParsedGatewayApiKey | undefined;
27
- export declare function hashGatewayApiKeySecret(secret: string): Promise<string>;
28
- export declare function verifyGatewayApiKeySecret(secret: string, encodedHash: string): Promise<boolean>;
@@ -1,162 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createGatewayApiKey = createGatewayApiKey;
4
- exports.createGatewayKeyId = createGatewayKeyId;
5
- exports.formatGatewayApiKey = formatGatewayApiKey;
6
- exports.parseGatewayApiKey = parseGatewayApiKey;
7
- exports.hashGatewayApiKeySecret = hashGatewayApiKeySecret;
8
- exports.verifyGatewayApiKeySecret = verifyGatewayApiKeySecret;
9
- const node_crypto_1 = require("node:crypto");
10
- const PREFIX = 'xpod_gw';
11
- const VERSION = 'v1';
12
- const SECRET_BYTES = 32;
13
- const KEY_ID_BYTES = 18;
14
- const SCRYPT_KEY_BYTES = 32;
15
- const SCRYPT_N = 16_384;
16
- const SCRYPT_R = 8;
17
- const SCRYPT_P = 1;
18
- const SCRYPT_MAXMEM = 32 * 1024 * 1024;
19
- async function createGatewayApiKey(input) {
20
- const keyId = input.keyId ?? createGatewayKeyId();
21
- const secret = input.secret ?? randomBase64Url(SECRET_BYTES);
22
- const plaintext = formatGatewayApiKey({
23
- version: VERSION,
24
- deployment: input.deployment,
25
- keyId,
26
- secret,
27
- });
28
- return {
29
- plaintext,
30
- secret,
31
- record: {
32
- id: keyId,
33
- deployment: input.deployment,
34
- secretHash: await hashGatewayApiKeySecret(secret),
35
- },
36
- };
37
- }
38
- function createGatewayKeyId() {
39
- return `gak_${randomBase64Url(KEY_ID_BYTES)}`;
40
- }
41
- function formatGatewayApiKey(parsed) {
42
- assertDeployment(parsed.deployment);
43
- if (!parsed.keyId || parsed.keyId.includes(' ') || parsed.keyId.includes('/')) {
44
- throw new Error('Invalid Gateway API key id');
45
- }
46
- if (!parsed.secret || !/^[A-Za-z0-9-]+$/.test(parsed.secret)) {
47
- throw new Error('Invalid Gateway API key secret');
48
- }
49
- return `${PREFIX}_${parsed.version}_${parsed.deployment}_${parsed.keyId}_${parsed.secret}`;
50
- }
51
- function parseGatewayApiKey(value) {
52
- const parts = value.split('_');
53
- if (parts.length < 6 || parts[0] !== 'xpod' || parts[1] !== 'gw' || parts[2] !== VERSION) {
54
- return undefined;
55
- }
56
- const deployment = parts[3];
57
- if (deployment !== 'local' && deployment !== 'cloud') {
58
- return undefined;
59
- }
60
- const secret = parts[parts.length - 1];
61
- const keyId = parts.slice(4, -1).join('_');
62
- if (!keyId || !secret || !/^[A-Za-z0-9-]+$/.test(secret)) {
63
- return undefined;
64
- }
65
- return {
66
- version: VERSION,
67
- deployment,
68
- keyId,
69
- secret,
70
- };
71
- }
72
- async function hashGatewayApiKeySecret(secret) {
73
- const salt = randomBase64Url(16);
74
- const key = await deriveScrypt(secret, salt, SCRYPT_N, SCRYPT_R, SCRYPT_P);
75
- return [
76
- 'scrypt',
77
- 'v=1',
78
- `N=${SCRYPT_N}`,
79
- `r=${SCRYPT_R}`,
80
- `p=${SCRYPT_P}`,
81
- `salt=${salt}`,
82
- `key=${key.toString('base64url')}`,
83
- ].join('$');
84
- }
85
- async function verifyGatewayApiKeySecret(secret, encodedHash) {
86
- const parsed = parseScryptHash(encodedHash);
87
- if (!parsed) {
88
- return false;
89
- }
90
- let actual;
91
- try {
92
- actual = await deriveScrypt(secret, parsed.salt, parsed.N, parsed.r, parsed.p);
93
- }
94
- catch {
95
- return false;
96
- }
97
- const expected = Buffer.from(parsed.key, 'base64url');
98
- if (actual.byteLength !== expected.byteLength) {
99
- const paddedActual = Buffer.alloc(SCRYPT_KEY_BYTES);
100
- const paddedExpected = Buffer.alloc(SCRYPT_KEY_BYTES);
101
- actual.copy(paddedActual, 0, 0, Math.min(actual.byteLength, SCRYPT_KEY_BYTES));
102
- expected.copy(paddedExpected, 0, 0, Math.min(expected.byteLength, SCRYPT_KEY_BYTES));
103
- (0, node_crypto_1.timingSafeEqual)(paddedActual, paddedExpected);
104
- return false;
105
- }
106
- return (0, node_crypto_1.timingSafeEqual)(actual, expected);
107
- }
108
- function parseScryptHash(encodedHash) {
109
- const parts = encodedHash.split('$');
110
- if (parts.length !== 7
111
- || parts[0] !== 'scrypt'
112
- || parts[1] !== 'v=1'
113
- || parts[2] !== `N=${SCRYPT_N}`
114
- || parts[3] !== `r=${SCRYPT_R}`
115
- || parts[4] !== `p=${SCRYPT_P}`
116
- || !parts[5]?.startsWith('salt=')
117
- || !parts[6]?.startsWith('key=')) {
118
- return undefined;
119
- }
120
- const salt = parts[5].slice('salt='.length);
121
- const key = parts[6].slice('key='.length);
122
- if (!isBase64UrlBytes(salt, 16) || !isBase64UrlBytes(key, SCRYPT_KEY_BYTES)) {
123
- return undefined;
124
- }
125
- return { N: SCRYPT_N, r: SCRYPT_R, p: SCRYPT_P, salt, key };
126
- }
127
- function isBase64UrlBytes(value, bytes) {
128
- if (!/^[A-Za-z0-9_-]+$/.test(value)) {
129
- return false;
130
- }
131
- try {
132
- return Buffer.from(value, 'base64url').byteLength === bytes;
133
- }
134
- catch {
135
- return false;
136
- }
137
- }
138
- async function deriveScrypt(secret, salt, N, r, p) {
139
- return await new Promise((resolve, reject) => {
140
- (0, node_crypto_1.scrypt)(secret, salt, SCRYPT_KEY_BYTES, {
141
- N,
142
- r,
143
- p,
144
- maxmem: SCRYPT_MAXMEM,
145
- }, (error, derivedKey) => {
146
- if (error) {
147
- reject(error);
148
- return;
149
- }
150
- resolve(derivedKey);
151
- });
152
- });
153
- }
154
- function randomBase64Url(bytes) {
155
- return (0, node_crypto_1.randomBytes)(bytes).toString('base64url').replaceAll('_', '-');
156
- }
157
- function assertDeployment(deployment) {
158
- if (deployment !== 'local' && deployment !== 'cloud') {
159
- throw new Error(`Invalid Gateway API key deployment: ${deployment}`);
160
- }
161
- }
162
- //# sourceMappingURL=GatewayApiKey.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"GatewayApiKey.js","sourceRoot":"","sources":["../../../../src/api/ai-gateway/auth/GatewayApiKey.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomBytes, scrypt, timingSafeEqual } from 'node:crypto';\n\nexport type GatewayDeployment = 'local' | 'cloud';\n\nexport interface ParsedGatewayApiKey {\n version: 'v1';\n deployment: GatewayDeployment;\n keyId: string;\n secret: string;\n}\n\nexport interface GatewayApiKeyRecordInput {\n id: string;\n secretHash: string;\n deployment: GatewayDeployment;\n}\n\nexport interface CreatedGatewayApiKey {\n plaintext: string;\n secret: string;\n record: GatewayApiKeyRecordInput;\n}\n\nexport interface CreateGatewayApiKeyInput {\n deployment: GatewayDeployment;\n keyId?: string;\n secret?: string;\n}\n\nconst PREFIX = 'xpod_gw';\nconst VERSION = 'v1';\nconst SECRET_BYTES = 32;\nconst KEY_ID_BYTES = 18;\nconst SCRYPT_KEY_BYTES = 32;\nconst SCRYPT_N = 16_384;\nconst SCRYPT_R = 8;\nconst SCRYPT_P = 1;\nconst SCRYPT_MAXMEM = 32 * 1024 * 1024;\n\nexport async function createGatewayApiKey(input: CreateGatewayApiKeyInput): Promise<CreatedGatewayApiKey> {\n const keyId = input.keyId ?? createGatewayKeyId();\n const secret = input.secret ?? randomBase64Url(SECRET_BYTES);\n const plaintext = formatGatewayApiKey({\n version: VERSION,\n deployment: input.deployment,\n keyId,\n secret,\n });\n return {\n plaintext,\n secret,\n record: {\n id: keyId,\n deployment: input.deployment,\n secretHash: await hashGatewayApiKeySecret(secret),\n },\n };\n}\n\nexport function createGatewayKeyId(): string {\n return `gak_${randomBase64Url(KEY_ID_BYTES)}`;\n}\n\n\nexport function formatGatewayApiKey(parsed: ParsedGatewayApiKey): string {\n assertDeployment(parsed.deployment);\n if (!parsed.keyId || parsed.keyId.includes(' ') || parsed.keyId.includes('/')) {\n throw new Error('Invalid Gateway API key id');\n }\n if (!parsed.secret || !/^[A-Za-z0-9-]+$/.test(parsed.secret)) {\n throw new Error('Invalid Gateway API key secret');\n }\n return `${PREFIX}_${parsed.version}_${parsed.deployment}_${parsed.keyId}_${parsed.secret}`;\n}\n\nexport function parseGatewayApiKey(value: string): ParsedGatewayApiKey | undefined {\n const parts = value.split('_');\n if (parts.length < 6 || parts[0] !== 'xpod' || parts[1] !== 'gw' || parts[2] !== VERSION) {\n return undefined;\n }\n const deployment = parts[3];\n if (deployment !== 'local' && deployment !== 'cloud') {\n return undefined;\n }\n const secret = parts[parts.length - 1];\n const keyId = parts.slice(4, -1).join('_');\n if (!keyId || !secret || !/^[A-Za-z0-9-]+$/.test(secret)) {\n return undefined;\n }\n return {\n version: VERSION,\n deployment,\n keyId,\n secret,\n };\n}\n\nexport async function hashGatewayApiKeySecret(secret: string): Promise<string> {\n const salt = randomBase64Url(16);\n const key = await deriveScrypt(secret, salt, SCRYPT_N, SCRYPT_R, SCRYPT_P);\n return [\n 'scrypt',\n 'v=1',\n `N=${SCRYPT_N}`,\n `r=${SCRYPT_R}`,\n `p=${SCRYPT_P}`,\n `salt=${salt}`,\n `key=${key.toString('base64url')}`,\n ].join('$');\n}\n\nexport async function verifyGatewayApiKeySecret(secret: string, encodedHash: string): Promise<boolean> {\n const parsed = parseScryptHash(encodedHash);\n if (!parsed) {\n return false;\n }\n let actual: Buffer;\n try {\n actual = await deriveScrypt(secret, parsed.salt, parsed.N, parsed.r, parsed.p);\n } catch {\n return false;\n }\n const expected = Buffer.from(parsed.key, 'base64url');\n if (actual.byteLength !== expected.byteLength) {\n const paddedActual = Buffer.alloc(SCRYPT_KEY_BYTES);\n const paddedExpected = Buffer.alloc(SCRYPT_KEY_BYTES);\n actual.copy(paddedActual, 0, 0, Math.min(actual.byteLength, SCRYPT_KEY_BYTES));\n expected.copy(paddedExpected, 0, 0, Math.min(expected.byteLength, SCRYPT_KEY_BYTES));\n timingSafeEqual(paddedActual, paddedExpected);\n return false;\n }\n return timingSafeEqual(actual, expected);\n}\n\nfunction parseScryptHash(encodedHash: string): {\n N: number;\n r: number;\n p: number;\n salt: string;\n key: string;\n} | undefined {\n const parts = encodedHash.split('$');\n if (\n parts.length !== 7\n || parts[0] !== 'scrypt'\n || parts[1] !== 'v=1'\n || parts[2] !== `N=${SCRYPT_N}`\n || parts[3] !== `r=${SCRYPT_R}`\n || parts[4] !== `p=${SCRYPT_P}`\n || !parts[5]?.startsWith('salt=')\n || !parts[6]?.startsWith('key=')\n ) {\n return undefined;\n }\n const salt = parts[5].slice('salt='.length);\n const key = parts[6].slice('key='.length);\n if (!isBase64UrlBytes(salt, 16) || !isBase64UrlBytes(key, SCRYPT_KEY_BYTES)) {\n return undefined;\n }\n return { N: SCRYPT_N, r: SCRYPT_R, p: SCRYPT_P, salt, key };\n}\n\nfunction isBase64UrlBytes(value: string, bytes: number): boolean {\n if (!/^[A-Za-z0-9_-]+$/.test(value)) {\n return false;\n }\n try {\n return Buffer.from(value, 'base64url').byteLength === bytes;\n } catch {\n return false;\n }\n}\n\nasync function deriveScrypt(\n secret: string,\n salt: string,\n N: number,\n r: number,\n p: number,\n): Promise<Buffer> {\n return await new Promise((resolve, reject) => {\n scrypt(secret, salt, SCRYPT_KEY_BYTES, {\n N,\n r,\n p,\n maxmem: SCRYPT_MAXMEM,\n }, (error, derivedKey) => {\n if (error) {\n reject(error);\n return;\n }\n resolve(derivedKey);\n });\n });\n}\n\nfunction randomBase64Url(bytes: number): string {\n return randomBytes(bytes).toString('base64url').replaceAll('_', '-');\n}\n\nfunction assertDeployment(deployment: string): asserts deployment is GatewayDeployment {\n if (deployment !== 'local' && deployment !== 'cloud') {\n throw new Error(`Invalid Gateway API key deployment: ${deployment}`);\n }\n}\n"]}
@@ -1,56 +0,0 @@
1
- import type { IncomingMessage } from 'node:http';
2
- import type { Authenticator, AuthResult } from '../../auth/Authenticator';
3
- import type { AuthContext } from '../../auth/AuthContext';
4
- import { type GatewayDeployment } from './GatewayApiKey';
5
- import type { InvocationTokenCodec } from './InvocationTokenCodec';
6
- export interface GatewayAccessKeyRecord {
7
- id: string;
8
- owner: string;
9
- secretHash: string;
10
- deployment: GatewayDeployment;
11
- scopes: string[];
12
- createdAt: Date;
13
- expiresAt?: Date;
14
- lastUsedAt?: Date;
15
- revokedAt?: Date;
16
- name?: string;
17
- }
18
- export interface GatewayAccessKeyRepositoryContext {
19
- auth?: AuthContext;
20
- }
21
- export interface GatewayAccessKeyRepository {
22
- createKeyId?(owner: string, deployment: GatewayDeployment): string;
23
- create(record: GatewayAccessKeyRecord, context?: GatewayAccessKeyRepositoryContext): Promise<GatewayAccessKeyRecord>;
24
- findById(id: string): Promise<GatewayAccessKeyRecord | undefined>;
25
- listByOwner(owner: string, context?: GatewayAccessKeyRepositoryContext): Promise<GatewayAccessKeyRecord[]>;
26
- revoke(id: string, revokedAt: Date, context?: GatewayAccessKeyRepositoryContext): Promise<GatewayAccessKeyRecord | undefined>;
27
- touchLastUsed(id: string, lastUsedAt: Date): Promise<void>;
28
- }
29
- export interface GatewayApiKeyAuthenticatorOptions {
30
- repository: GatewayAccessKeyRepository;
31
- deployment: GatewayDeployment;
32
- requiredScopes?: string[];
33
- invocationTokenCodec?: InvocationTokenCodec;
34
- invocationTokenAudience?: string;
35
- invocationTokenIssuer?: string;
36
- now?: () => Date;
37
- maxClockSkewMs?: number;
38
- }
39
- export declare const DEFAULT_GATEWAY_API_KEY_SCOPES: readonly ["models:read", "inference:write"];
40
- export declare class GatewayApiKeyAuthenticator implements Authenticator {
41
- private readonly repository;
42
- private readonly deployment;
43
- private readonly requiredScopes;
44
- private readonly invocationTokenCodec?;
45
- private readonly invocationTokenAudience?;
46
- private readonly invocationTokenIssuer?;
47
- private readonly now;
48
- private readonly maxClockSkewMs;
49
- private readonly dummyHash;
50
- constructor(options: GatewayApiKeyAuthenticatorOptions);
51
- canAuthenticate(request: IncomingMessage): boolean;
52
- authenticate(request: IncomingMessage): Promise<AuthResult>;
53
- private authenticateInvocationToken;
54
- private validInvocationClaims;
55
- private readBearer;
56
- }