@xenon-device-management/xenon 2.15.0 → 2.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -26
- package/lib/package.json +2 -1
- package/lib/public/assets/{AnnotationOverlay-Btq3dZRI.js → AnnotationOverlay-2W4JvEyZ.js} +1 -1
- package/lib/public/assets/{ApiKeyGate-C9OoAgg_.js → ApiKeyGate-GmckX_7r.js} +1 -1
- package/lib/public/assets/{DeviceMosaicView-DBC_xczB.js → DeviceMosaicView-DqODzkyo.js} +1 -1
- package/lib/public/assets/{EmptyState-DqWU2-vM.js → EmptyState-7hETKEWb.js} +1 -1
- package/lib/public/assets/{FieldGroup-CveQ3xrA.js → FieldGroup-GOgssFEP.js} +1 -1
- package/lib/public/assets/{FilterMenu-BfKDSfHz.js → FilterMenu-Yvf6RGMd.js} +1 -1
- package/lib/public/assets/{Menu-CtdCybzA.js → Menu-KrPnfdsf.js} +1 -1
- package/lib/public/assets/{Modal-Bsvj1tm2.js → Modal-C6WjZFeI.js} +1 -1
- package/lib/public/assets/{RecordingPage-CRofOiyx.js → RecordingPage-CSRIhZEh.js} +1 -1
- package/lib/public/assets/{RecordingsPage-jNQHb2IR.js → RecordingsPage-CB8ST3nE.js} +1 -1
- package/lib/public/assets/{SegmentedControl-C8HtTha-.js → SegmentedControl-C9o90KId.js} +1 -1
- package/lib/public/assets/{SettingCard-D8K1LZNo.js → SettingCard-CPm3w9l2.js} +1 -1
- package/lib/public/assets/{Table-zNTX92Pn.js → Table-DwIgERRt.js} +1 -1
- package/lib/public/assets/{activity-CJ8LwZq9.js → activity-DrLbHifn.js} +1 -1
- package/lib/public/assets/{ai-settings-CgxQZqrc.js → ai-settings-DU_Ls06P.js} +1 -1
- package/lib/public/assets/{api-keys-ECpo-zTo.js → api-keys-CWYdEzJ_.js} +1 -1
- package/lib/public/assets/{apps-BjGymyf3.js → apps-BqNVdln7.js} +1 -1
- package/lib/public/assets/{arrow-left-BWfCbeHP.js → arrow-left-BtB0_Jg_.js} +1 -1
- package/lib/public/assets/{arrow-right-DC7UGf_n.js → arrow-right-C8NhdtyN.js} +1 -1
- package/lib/public/assets/{arrow-up-right-BOjwybDk.js → arrow-up-right-gMg0ffvv.js} +1 -1
- package/lib/public/assets/{auth-shell-CxMTo9aH.js → auth-shell-CiYZ3N4M.js} +2 -2
- package/lib/public/assets/{builds-page-DOCm4HkA.js → builds-page-EaaqDmLN.js} +1 -1
- package/lib/public/assets/{button-Cg08-EMT.js → button-DDau4Axv.js} +1 -1
- package/lib/public/assets/{calendar-CA1ikLJs.js → calendar-DQ83B1ed.js} +1 -1
- package/lib/public/assets/{check-BMTaH72W.js → check-K1ovTQam.js} +1 -1
- package/lib/public/assets/{chevron-right-B2QOv9Nx.js → chevron-right-Biq00pMt.js} +1 -1
- package/lib/public/assets/{circle-check-CYXBoUqT.js → circle-check-CBv88cH7.js} +1 -1
- package/lib/public/assets/{circle-x-DTwnSAnl.js → circle-x-Bmltailn.js} +1 -1
- package/lib/public/assets/{clock-C8_HViQP.js → clock-BPrld-3h.js} +1 -1
- package/lib/public/assets/{copy-Be7LNMXV.js → copy-t0QB14JI.js} +1 -1
- package/lib/public/assets/{device-explorer-BOqtfGXz.js → device-explorer-BgGZ8AvV.js} +1 -1
- package/lib/public/assets/{download-B56lwxWP.js → download-BroHxNOh.js} +1 -1
- package/lib/public/assets/{forgot-password-CCU6bzLn.js → forgot-password-Bjmf49i6.js} +1 -1
- package/lib/public/assets/{h264Stream-C-OtmIuk.js → h264Stream-DeD__6wa.js} +1 -1
- package/lib/public/assets/{index-CfxsUslp.js → index-72oF89LJ.js} +1 -1
- package/lib/public/assets/{index-B9KQ6LsY.js → index-B0JeuZbg.js} +1 -1
- package/lib/public/assets/index-B0gQkEg0.js +219 -0
- package/lib/public/assets/{input-CZHFjbSg.js → input-DIc4MSC7.js} +1 -1
- package/lib/public/assets/{line-chart-Gl_Dz3X_.js → line-chart-BcWm2vW8.js} +1 -1
- package/lib/public/assets/{list-checks-CCgjeyGY.js → list-checks-B06IJJad.js} +1 -1
- package/lib/public/assets/{lock-CkOwgDcx.js → lock-pVLvnN30.js} +1 -1
- package/lib/public/assets/{login-D5cc4w7M.js → login-CN77vy--.js} +1 -1
- package/lib/public/assets/{maintenance-settings-t7qr3fvX.js → maintenance-settings-CSdzQSkY.js} +1 -1
- package/lib/public/assets/{monitor-DEJixKQO.js → monitor-BtrN5IkI.js} +1 -1
- package/lib/public/assets/{mouse-pointer-2-CtOrk4M8.js → mouse-pointer-2-CNsQfo6w.js} +1 -1
- package/lib/public/assets/{network-Dii9qdvk.js → network-BSfA8ZxG.js} +1 -1
- package/lib/public/assets/{overview-rolAACrO.js → overview-BfTebCK5.js} +1 -1
- package/lib/public/assets/{page-header-COQZxJfR.js → page-header-D8KUX6Qg.js} +1 -1
- package/lib/public/assets/{play-DrN1Se_R.js → play-Cvc8xzic.js} +1 -1
- package/lib/public/assets/{plus-5aq-9uRx.js → plus-C9Zj84UF.js} +1 -1
- package/lib/public/assets/{profile-page-6i5kY6kF.js → profile-page-Bi27STgs.js} +1 -1
- package/lib/public/assets/{reset-password-sp2IBrc7.js → reset-password-CPsOuwSu.js} +1 -1
- package/lib/public/assets/{runbook-page-DJDjeopU.js → runbook-page-DEQ-DBOX.js} +153 -102
- package/lib/public/assets/{select-Bpyn7rWO.js → select-BWpnhWXj.js} +1 -1
- package/lib/public/assets/{selector-detail-redirect-BH74vmKv.js → selector-detail-redirect-BefSCSpe.js} +1 -1
- package/lib/public/assets/{selector-health-page-Cw_g218H.js → selector-health-page-MSk96Zz7.js} +1 -1
- package/lib/public/assets/session-detail-page-DPyBNef_.js +4 -0
- package/lib/public/assets/{settings-C3uyGhyc.js → settings-V6x-cXwy.js} +1 -1
- package/lib/public/assets/{stat-tile-xVqAKIlI.js → stat-tile-Duex-GZD.js} +1 -1
- package/lib/public/assets/{tablet-BxUScAeO.js → tablet-BBcoqBmL.js} +1 -1
- package/lib/public/assets/{teams-B5ljGkY2.js → teams-ts8p5rEh.js} +1 -1
- package/lib/public/assets/{trash-2-B701i8sy.js → trash-2-CZ2ew6AZ.js} +1 -1
- package/lib/public/assets/{upload-C2gr44RS.js → upload-Dv99y_le.js} +1 -1
- package/lib/public/assets/{use-builds-data-NeQOFEoy.js → use-builds-data-DrYC8JCF.js} +1 -1
- package/lib/public/assets/{use-password-reset-mode-DEzJq5ef.js → use-password-reset-mode-C7QkBNkP.js} +1 -1
- package/lib/public/assets/{users-D_vv_yz4.js → users-D7tKMESH.js} +1 -1
- package/lib/public/assets/{users-MY6eNe6s.js → users-gJ5Y01yo.js} +1 -1
- package/lib/public/assets/{video-off-OK1lNZQn.js → video-off-CqZVuZGs.js} +1 -1
- package/lib/public/assets/{webhook-settings-BU-C9lBf.js → webhook-settings-DI5DSW99.js} +1 -1
- package/lib/public/assets/{zap-DO9ry1iz.js → zap-ClcHFxfo.js} +1 -1
- package/lib/public/index.html +1 -1
- package/lib/schema.json +11 -7
- package/lib/src/InternalHttpClient.js +27 -5
- package/lib/src/XenonCapabilityManager.js +10 -3
- package/lib/src/app/openapi/sessions.yaml +7 -5
- package/lib/src/app/routers/auth.js +2 -1
- package/lib/src/app/routers/users.js +2 -1
- package/lib/src/app/ws/nodeSocketRelay.js +77 -11
- package/lib/src/dashboard/commandLogFields.js +42 -0
- package/lib/src/dashboard/event-manager.js +26 -154
- package/lib/src/dashboard/services/failure-analysis-service.js +8 -86
- package/lib/src/dashboard/services/failureCategories.js +264 -0
- package/lib/src/device-managers/AndroidDeviceManager.js +61 -23
- package/lib/src/device-managers/IOSDeviceManager.js +10 -0
- package/lib/src/device-utils.js +14 -6
- package/lib/src/gateway/forwardToNode.js +4 -11
- package/lib/src/gateway/hubSessionToken.js +27 -4
- package/lib/src/gateway/nodeWebDriverUrl.js +3 -5
- package/lib/src/helpers/outboundProxy.js +219 -0
- package/lib/src/index.js +21 -0
- package/lib/src/interceptors/CommandInterceptor.js +13 -15
- package/lib/src/interceptors/xenonScripts.js +28 -7
- package/lib/src/logger.js +3 -1
- package/lib/src/plugin.js +8 -3
- package/lib/src/scripts/database-check.js +3 -3
- package/lib/src/scripts/initialize-database.js +35 -33
- package/lib/src/scripts/run-migrations.js +1079 -27
- package/lib/src/services/ApiKeyService.js +16 -5
- package/lib/src/services/InterceptorService.js +6 -2
- package/lib/src/services/OrphanSweeper.js +6 -0
- package/lib/src/services/SelectorStateService.js +11 -7
- package/lib/src/services/SelectorVerificationJob.js +6 -2
- package/lib/src/services/SessionLifecycleService.js +32 -18
- package/lib/src/services/SocketClient.js +11 -0
- package/lib/src/services/SocketServer.js +361 -42
- package/lib/src/services/TeamService.js +5 -1
- package/lib/src/services/TracingService.js +171 -60
- package/lib/src/services/UserService.js +14 -3
- package/lib/src/services/UserSessionService.js +16 -4
- package/lib/src/services/healing/HealingOrchestrator.js +3 -1
- package/lib/src/services/identity/identityChanges.js +41 -0
- package/lib/src/services/logcat/SessionDeviceLogs.js +97 -10
- package/lib/src/services/logcat/deviceLogBook.js +5 -4
- package/lib/src/services/logcat/iosDriverLog.js +178 -0
- package/lib/src/services/selector-health/SelectorVisibilityResolver.js +121 -0
- package/lib/src/services/token/JwtKeyService.js +8 -2
- package/lib/src/services/token/mcpTokenTtl.js +27 -0
- package/lib/src/sessions/LocalSession.js +29 -1
- package/lib/src/sessions/RemoteSession.js +12 -2
- package/lib/src/sessions/SessionManager.js +5 -8
- package/lib/test/helpers/driver-log.js +38 -0
- package/lib/test/helpers/fake-http-proxy.js +106 -0
- package/lib/test/helpers/otlp-probe.js +107 -0
- package/lib/test/integration/androidDevices.spec.js +1 -1
- package/lib/test/integration/ios/01iOSSimulator.spec.js +1 -1
- package/lib/test/integration/ios/02iOSDevices.spec.js +1 -1
- package/lib/test/integration/selector-state-flow.spec.js +5 -5
- package/lib/test/unit/XenonCapabilityManager.spec.js +23 -0
- package/lib/test/unit/android-adb-retry.spec.js +112 -0
- package/lib/test/unit/command-log-network-capture.spec.js +191 -0
- package/lib/test/unit/dashboard-events-device-logs.spec.js +59 -11
- package/lib/test/unit/dashboard-events-team-scope.spec.js +6 -3
- package/lib/test/unit/database-check.spec.js +1 -0
- package/lib/test/unit/device-utils.spec.js +13 -4
- package/lib/test/unit/event-log-session-data.spec.js +11 -4
- package/lib/test/unit/failure-analysis.spec.js +22 -8
- package/lib/test/unit/failure-categories.spec.js +24 -22
- package/lib/test/unit/failure-categorization.spec.js +393 -0
- package/lib/test/unit/healing-tier-gate.spec.js +3 -2
- package/lib/test/unit/hub-node-gateway-appium-server.spec.js +72 -1
- package/lib/test/unit/ios-driver-log.spec.js +168 -0
- package/lib/test/unit/ios-simulator-session-readiness.spec.js +187 -0
- package/lib/test/unit/ios-simulator-session-teardown.spec.js +158 -0
- package/lib/test/unit/logcat-ws.spec.js +78 -37
- package/lib/test/unit/logger-json-levels.spec.js +44 -0
- package/lib/test/unit/mcp-token-ttl.spec.js +38 -0
- package/lib/test/unit/observability-example-loki.spec.js +25 -0
- package/lib/test/unit/openapi-for-site.spec.js +80 -0
- package/lib/test/unit/outbound-proxy.spec.js +320 -0
- package/lib/test/unit/port-exhaustion.spec.js +2 -1
- package/lib/test/unit/proxy-option.spec.js +358 -0
- package/lib/test/unit/run-migrations-database.spec.js +807 -0
- package/lib/test/unit/run-migrations-fail-fast.test.js +41 -27
- package/lib/test/unit/run-migrations.test.js +864 -0
- package/lib/test/unit/selector-health-actions.spec.js +3 -1
- package/lib/test/unit/selector-state-service.spec.js +72 -23
- package/lib/test/unit/selector-verification-clean-build.spec.js +1 -1
- package/lib/test/unit/selector-verification-job.spec.js +15 -6
- package/lib/test/unit/selector-verification-missed-regression.spec.js +2 -2
- package/lib/test/unit/selector-visibility-resolver.spec.js +209 -0
- package/lib/test/unit/session-device-logs-ios.spec.js +180 -0
- package/lib/test/unit/session-device-logs.spec.js +11 -2
- package/lib/test/unit/session-end-failure-analysis.spec.js +5 -5
- package/lib/test/unit/session-log-indexes.spec.js +1 -1
- package/lib/test/unit/socket-team-scope.integration.spec.js +749 -0
- package/lib/test/unit/socketServer.scopedEmit.spec.js +237 -5
- package/lib/test/unit/tracing-export-routing.spec.js +137 -0
- package/lib/test/unit/tracing-session-spans.spec.js +337 -0
- package/lib/test/unit/unexpected-shutdown-reason.spec.js +2 -2
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -1
- package/schema.json +11 -7
- package/scripts/dev/readme-screenshots.js +276 -23
- package/scripts/dev/screenshot-fixtures/logcat.js +157 -0
- package/scripts/dev/screenshot-fixtures/phone-screen.html +469 -0
- package/scripts/dev/screenshot-fixtures/session.js +242 -0
- package/scripts/export-openapi.js +32 -0
- package/scripts/lib/openapi-for-site.js +79 -0
- package/lib/public/assets/index-BOxe43p1.js +0 -219
- package/lib/public/assets/session-detail-page-AZJE6XXE.js +0 -4
- package/lib/src/scripts/prepare-prisma.js +0 -89
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import{r as x,X as S,j as e,e as te,f as Ae,t as I,y as Ee,R as Le,p as De,i as Me,u as Oe}from"./index-BOxe43p1.js";import{C as Fe,d as Pe,p as Ne,e as He,r as ye,f as Ie,j as we,k as X,c as Be,h as re,u as Ue,b as Ve,q as ze}from"./use-builds-data-NeQOFEoy.js";import{A as Je}from"./arrow-left-BWfCbeHP.js";import{C as K}from"./chevron-right-B2QOv9Nx.js";import{s as We}from"./labels-C21SA4JG.js";import{B as Ke,S as ke,u as qe,P as $}from"./index-B9KQ6LsY.js";import{C as Xe}from"./circle-x-DTwnSAnl.js";import{C as Ge}from"./circle-check-CYXBoUqT.js";import{S as F}from"./stat-tile-xVqAKIlI.js";import{h as G,p as Ye,a as se,b as ae}from"./derive-UnLRp4r3.js";import{C as Y}from"./copy-Be7LNMXV.js";import{A as Qe}from"./arrow-up-right-BOjwybDk.js";import{A as Ze}from"./arrow-right-DC7UGf_n.js";import{f as et,a as ne,C as Se,b as tt,s as rt,L as st,n as ie}from"./line-chart-Gl_Dz3X_.js";import{E as M}from"./EmptyState-DqWU2-vM.js";import{A as at}from"./activity-CJ8LwZq9.js";import{V as nt}from"./video-off-OK1lNZQn.js";import{D as _e}from"./download-B56lwxWP.js";import{T as it,a as ot,b as oe,c as E,d as lt,e as L}from"./Table-zNTX92Pn.js";import{M as ct}from"./Modal-Bsvj1tm2.js";import{N as dt}from"./network-Dii9qdvk.js";import"./time-D-gjmE1o.js";import"./index-CfxsUslp.js";const xt=4e3,le=t=>!!t&&typeof t=="object"&&typeof t.id=="string"&&typeof t.status=="string";function mt(t){const[r,s]=x.useState(null),[a,n]=x.useState([]),[o,l]=x.useState([]),[i,c]=x.useState([]),[m,b]=x.useState([]),[f,j]=x.useState(!0),[p,g]=x.useState(null),[y,w]=x.useState(!1),[R,A]=x.useState(0),_=x.useRef(null);x.useEffect(()=>{if(!t){s(null),n([]),l([]),c([]),b([]),w(!1),j(!1);return}let v=!0;return _.current!==t&&j(!0),Promise.all([S.getSession(t),S.getSessionLogs(t),S.getDeviceLogs(t),S.getDebugLogs(t),S.getProfilingData(t).catch(()=>[])]).then(([h,C,d,N,D])=>{if(!v)return;const O=le(h);s(O?h:null),O?(_.current=t,w(!1),g(null)):(w(!!h&&typeof h=="object"&&(h.error===!0||typeof h.message=="string")),g(typeof(h==null?void 0:h.message)=="string"?h.message:"Session not found")),n(Array.isArray(C)?C:[]),l(Array.isArray(d)?d:[]),c(Array.isArray(N)?N:[]),b(Array.isArray(D)?D:[])}).catch(h=>{v&&g(h instanceof Error?h.message:String(h))}).finally(()=>{v&&j(!1)}),()=>{v=!1}},[t,R]);const u=(r==null?void 0:r.status)==="running";return x.useEffect(()=>{if(!t||!u)return;let v=!0;const h=setInterval(async()=>{try{const[C,d]=await Promise.all([S.getSession(t),S.getSessionLogs(t)]);if(!v||!le(C))return;s(C),Array.isArray(d)&&n(d),C.status!=="running"&&A(N=>N+1)}catch{}},xt);return()=>{v=!1,clearInterval(h)}},[t,u]),{session:r,sessionLogs:a,deviceLogs:o,debugLogs:i,profiling:m,loading:f,error:p,notFound:y,refresh:()=>A(v=>v+1)}}const ce=({buildId:t,buildName:r,sessionId:s})=>e.jsxs("nav",{"aria-label":"Breadcrumb",className:"flex items-center gap-2 px-4 py-2 border-b border-[var(--border)] bg-[var(--surface)]",children:[e.jsxs(te,{to:"/builds",className:"inline-flex items-center gap-1.5 text-xs text-[var(--text-muted)] hover:text-[var(--text)] transition-colors",children:[e.jsx(Je,{className:"h-3.5 w-3.5"}),"Sessions"]}),e.jsx(K,{className:"h-3 w-3 text-[var(--text-dim)]"}),r&&e.jsxs(e.Fragment,{children:[e.jsx(te,{to:`/builds/${t}`,className:"text-[11px] text-[var(--color-accent)] hover:underline",children:r}),e.jsx(K,{className:"h-3 w-3 text-[var(--text-dim)]"})]}),e.jsxs("span",{className:"font-mono text-[11px] text-[var(--text-muted)]",title:s,children:["#",s.slice(0,8)]})]}),ut={passed:{label:"Passed",Icon:Ge,cls:"text-[var(--color-success)]"},failed:{label:"Failed",Icon:Xe,cls:"text-[var(--color-danger)]"},running:{label:"Running",Icon:Ae,cls:"text-[var(--color-warning)]"},other:{Icon:Fe,cls:"text-[var(--text-dim)]"}};function Q(t){const r=Be(t),s=ut[r];return{bucket:r,...s,label:s.label??We(t||"unknown")}}const ht=({session:t})=>{var o,l;const r=Q(t.status),s=Pe(t),a=[Ne(t),t.device_version].filter(i=>i&&i!=="—").join(" "),n=[[He(t),a].filter(Boolean).join(" · "),ye(t.ranOn),(o=t.owner)==null?void 0:o.name,Ie(t.startTime),we(X(t))].filter(i=>i&&i!=="—");return e.jsxs("header",{className:"flex items-start justify-between gap-4 px-4 py-4 border-b border-[var(--border)] bg-[var(--surface)]",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[e.jsxs("span",{className:`inline-flex items-center gap-1.5 text-xs font-medium shrink-0 ${r.cls}`,children:[e.jsx(r.Icon,{className:`h-3.5 w-3.5 ${r.bucket==="running"?"animate-spin":""}`,"aria-hidden":"true"}),r.label]}),e.jsx("h1",{className:`text-lg font-semibold truncate ${s.source==="name"?"text-[var(--text)]":"text-[var(--text-muted)]"}`,title:s.source==="name"?s.text:`${s.text}
|
|
2
|
-
Unnamed session. Set xe:options.name in its capabilities to name it.`,children:s.text})]}),e.jsx("p",{"data-testid":"outcome-meta",className:"mt-1 text-xs text-[var(--text-muted)] tabular-nums truncate",title:((l=t.owner)==null?void 0:l.email)??void 0,children:n.join(" · ")})]}),e.jsx("div",{className:"shrink-0",children:e.jsx(Ke,{sessionId:t.id,mode:"full",variant:"inline"})})]})},B=t=>t.command_name||t.title||"command",q=t=>{const r=t.createdAt?Date.parse(t.createdAt):NaN;return Number.isFinite(r)?r:0},Z=t=>[...t].sort((r,s)=>q(r)-q(s));function U(t){return t.is_success===!1||t.is_error===!0}function Ce(t){const r=[];let s=null;for(const a of Z(t))a.is_healed&&a.healing_tier&&!r.includes(a.healing_tier)&&r.push(a.healing_tier),typeof a.duration=="number"&&(!s||a.duration>s.ms)&&(s={name:B(a),ms:a.duration});return{total:t.length,failed:t.filter(U).length,healed:t.filter(a=>a.is_healed).length,healedTiers:r,slowest:s,screenshots:t.filter(a=>a.screenshot).length}}const de=(t,r)=>r?t?`${t}=${r}`:r:null;function ft(t){return Z(t.filter(r=>r.is_healed)).map(r=>({id:r.id,command:B(r),original:de(r.original_strategy,r.original_selector),healed:de(r.healed_strategy,r.healed_selector),tier:r.healing_tier??null,confidence:typeof r.healing_confidence=="number"?Math.round(r.healing_confidence*100):null,at:r.createdAt}))}function pt(t){var r;if(!t.response)return null;try{const s=(r=JSON.parse(t.response))==null?void 0:r.value;if(!s||typeof s!="object")return null;const a=typeof s.message=="string"?s.message.trim():"";return a||(typeof s.error=="string"&&s.error?s.error:null)}catch{return null}}function vt(t){if(t.length===0)return{spanMs:0,bars:[]};const r=t.map(n=>{const o=q(n),l=typeof n.duration=="number"&&n.duration>0?n.duration:0;return{l:n,start:o-l,end:o,durationMs:l}}),s=Math.min(...r.map(n=>n.start)),a=Math.max(...r.map(n=>n.end));return{spanMs:Math.max(1,a-s),bars:r.sort((n,o)=>n.start-o.start).map(({l:n,start:o,durationMs:l})=>({id:n.id,label:B(n),startMs:o-s,durationMs:l,failed:U(n),healed:!!n.is_healed}))}}function bt(t){return Z(t.filter(r=>r.screenshot)).map(r=>({id:r.id,path:r.screenshot,command:B(r),at:r.createdAt,failed:U(r)}))}function H(t){if(t==null||!Number.isFinite(t)||t<0)return"—";if(t<1e3)return`${Math.round(t)}ms`;if(t<6e4)return`${(t/1e3).toFixed(1)}s`;const r=Math.round(t/1e3);return`${Math.floor(r/60)}m ${r%60}s`}const gt=({session:t,commands:r})=>{var l,i;const s=Q(t.status),a=Ce(r),n=we(X(t)),o=s.bucket==="failed"?G(t.failure_category)||"No category recorded":s.bucket==="running"?`Running for ${n}`:`Ran ${n}`;return e.jsxs("div",{className:"grid grid-cols-4 gap-3",children:[e.jsx(F,{label:"Result",value:s.label,valueCls:s.cls,note:o,noteTone:s.bucket==="failed"?"bad":"neutral"}),e.jsx(F,{label:"Commands",value:a.total,note:a.failed>0?`${a.failed} failed`:"None failed",noteTone:a.failed>0?"bad":"neutral"}),e.jsx(F,{label:"Self-healing",value:a.healed>0?`${a.healed} healed`:"None",note:a.healed>0?a.healedTiers.join(", ")||"Tier not recorded":"No selector needed healing"}),e.jsx(F,{label:"Slowest command",value:H((l=a.slowest)==null?void 0:l.ms),note:((i=a.slowest)==null?void 0:i.name)??"No timings recorded"})]})};function jt(t){const r=t.filter(U),s=r[r.length-1];return s?{command:s.command_name||s.title||"command",message:pt(s)}:null}function Nt(t,r,s,a,n){var m;const o=G(t.failure_category),l=((m=t.device_name)==null?void 0:m.trim())||"Unknown Device",i=t.device_version?` ${t.device_version}`:"",c=n?`${n.command}${n.message?`: ${n.message}`:""}`:"(no failed command recorded)";return[`**Session:** ${t.id}`,`**Build:** ${r} (#${s})`,`**Device:** ${l} (${t.node_id||"unknown-node"}) · ${t.device_platform||"unknown"}${i}`,`**Duration:** ${a}`,`**Failure category:** ${o||"(uncategorized)"}`,`**Failure reason:** ${t.failure_reason||"(not set)"}`,`**First failed command:** ${c}`,...t.ai_analysis?[`**AI analysis:** ${t.ai_analysis}`]:[]].join(`
|
|
3
|
-
`)}function yt({text:t}){return e.jsx(e.Fragment,{children:t.split(/(\*\*[^*]+\*\*|`[^`]+`)/g).map((r,s)=>/^\*\*[^*]+\*\*$/.test(r)?e.jsx("strong",{children:r.slice(2,-2)},s):/^`[^`]+`$/.test(r)?e.jsx("code",{className:"font-mono text-[11px] px-1 rounded bg-[var(--surface-2)]",children:r.slice(1,-1)},s):e.jsx(Le.Fragment,{children:r},s))})}const P=({children:t})=>e.jsx("div",{className:"text-[11px] font-semibold text-[var(--text-dim)] mb-1",children:t}),wt=({session:t,buildName:r,buildId:s,commands:a,durationText:n})=>{var y;const{toast:o}=I(),[l,i]=x.useState(!1),c=G(t.failure_category),m=jt(a),b=Ye(t.failure_reason),f=(y=t.ai_analysis)==null?void 0:y.trim(),j=!!f&&f.length>480,p=async()=>{const w=Nt(t,r,s,n,m);try{await navigator.clipboard.writeText(w),o("Failure report copied","success")}catch{o("Clipboard unavailable","error")}},g=t.failure_category?`/xenon/runbooks/${encodeURIComponent(t.failure_category.toLowerCase())}`:void 0;return e.jsxs("section",{className:"rounded-lg border border-[var(--red)]/30 bg-[var(--surface)] overflow-hidden",children:[e.jsxs("header",{className:"flex items-center justify-between gap-4 px-4 py-3 border-b border-[var(--border)] bg-[var(--red)]/5",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Ee,{className:"h-4 w-4 text-[var(--red)]","aria-hidden":"true"}),e.jsx("h2",{className:"text-sm font-semibold text-[var(--red)]",children:"Why it failed"}),c&&e.jsx("span",{className:"text-[11px] text-[var(--text-dim)] ml-2",children:c})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("button",{type:"button",onClick:p,className:"inline-flex items-center gap-1.5 h-7 px-2.5 rounded-md border border-[var(--border)] text-xs text-[var(--text)] hover:border-[var(--border-strong)] hover:bg-[var(--surface-2)] transition-colors",children:[e.jsx(Y,{className:"h-3 w-3"}),"Copy"]}),e.jsxs("a",{...g?{href:g,target:"_blank",rel:"noreferrer"}:{"aria-disabled":!0,onClick:w=>w.preventDefault()},className:`inline-flex items-center gap-1.5 h-7 px-2.5 rounded-md border border-[var(--border)] text-xs text-[var(--text)] hover:border-[var(--border-strong)] hover:bg-[var(--surface-2)] transition-colors ${g?"":"opacity-50 cursor-not-allowed"}`,title:g?"Open runbook in new tab":"No runbook — failure category not set",children:[e.jsx(Qe,{className:"h-3 w-3"}),"Open runbook"]})]})]}),e.jsxs("div",{className:"px-4 py-4 space-y-4",children:[e.jsxs("div",{children:[e.jsx(P,{children:"Reason"}),e.jsx("div",{className:"text-sm text-[var(--text)] break-words",children:t.failure_reason||e.jsx("span",{className:"text-[var(--text-dim)]",children:"(not set)"})})]}),e.jsxs("div",{children:[e.jsx(P,{children:"First failed command"}),m?e.jsxs("div",{className:"flex items-baseline gap-2 min-w-0 text-sm",children:[e.jsx("span",{className:"font-mono text-xs text-[var(--color-danger)] shrink-0",children:m.command}),m.message&&e.jsx("span",{className:"text-[var(--text-muted)] break-words min-w-0",children:m.message})]}):e.jsx("span",{className:"text-sm text-[var(--text-dim)]",children:"No failed command recorded."})]}),f&&e.jsxs("div",{"data-testid":"ai-analysis",children:[e.jsx(P,{children:e.jsxs("span",{className:"inline-flex items-center gap-1.5",children:[e.jsx(ke,{className:"h-3 w-3","aria-hidden":"true"}),"AI analysis"]})}),e.jsx("div",{className:`text-sm text-[var(--text)] whitespace-pre-wrap break-words ${j&&!l?"line-clamp-6":""}`,children:e.jsx(yt,{text:f})}),j&&e.jsx("button",{type:"button",onClick:()=>i(w=>!w),"aria-expanded":l,className:"mt-1 text-xs text-[var(--color-accent)] hover:underline",children:l?"Show less":"Show all"})]}),b.length>0&&e.jsxs("div",{children:[e.jsx(P,{children:"Stack trace"}),e.jsx("pre",{className:"rounded-md border border-[var(--border)] bg-[var(--bg)] p-3 font-mono text-[11px] leading-relaxed text-[var(--color-accent)] overflow-x-auto",children:b.join(`
|
|
4
|
-
`)})]})]})]})};function kt(t){return t>=1e3?`${(t/1e3).toFixed(1).replace(/\.0$/,"")}k`:String(t)}function V(t){const r=t;return typeof r.message=="string"&&!r.command_name&&!r.title}const St=/^\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2}\.\d+\s+\d+\s+\d+\s+([VDIWEF])\s/,_t=/^([VDIWEF])\/[^(:]*[(:]/,Ct=/<(Error|Fault|Warning)>/;function Re(t){var a,n,o;const r=((a=St.exec(t))==null?void 0:a[1])??((n=_t.exec(t))==null?void 0:n[1]);if(r)return r==="E"||r==="F"?"error":r==="W"?"warn":null;const s=(o=Ct.exec(t))==null?void 0:o[1];return s?s==="Warning"?"warn":"error":null}function z(t){const r=t.timestamp;if(!r){const l=t.createdAt;return l?z({timestamp:l}):"--:--:--"}const s=typeof r=="number"?new Date(r):new Date(String(r));if(Number.isNaN(s.getTime()))return"--:--:--";const a=String(s.getHours()).padStart(2,"0"),n=String(s.getMinutes()).padStart(2,"0"),o=String(s.getSeconds()).padStart(2,"0");return`${a}:${n}:${o}`}function Rt(t){if(V(t)){const s=Re(t.message);return s==="error"?{label:"error",tone:"red"}:s==="warn"?{label:"warn",tone:"amber"}:{label:"",tone:"neutral"}}if(t.is_healed===!0)return{label:String(t.command_name||"healed"),tone:"amber"};if(t.is_success===!1||t.is_error===!0)return{label:String(t.command_name||t.title||"error"),tone:"red"};if(t.is_success===!0)return{label:String(t.command_name||t.title||"ok"),tone:"green"};const r=t.title||t.event||t.command_name;return typeof r=="string"?/stop|fail|error/i.test(r)?{label:r,tone:"red"}:/start|begin|init/i.test(r)?{label:r,tone:"green"}:{label:r,tone:"blue"}:{label:"log",tone:"neutral"}}function Tt(t){if(t==null)return"";if(typeof t=="string")try{return JSON.stringify(JSON.parse(t),null,2)}catch{return t}try{return JSON.stringify(t,null,2)}catch{return String(t)}}function $t(t){if(!t||typeof t!="string")return[{text:String(t??""),kind:"plain"}];const r=[],s=/("(?:\\.|[^"\\])*")(\s*:)|("(?:\\.|[^"\\])*")|(-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)|\b(true|false)\b|\b(null)\b|([{}[\],])/g;let a=0,n;for(;(n=s.exec(t))!==null;)n.index>a&&r.push({text:t.slice(a,n.index),kind:"plain"}),n[1]&&n[2]!==void 0?(r.push({text:n[1],kind:"key"}),r.push({text:n[2],kind:"punct"})):n[3]?r.push({text:n[3],kind:"string"}):n[4]?r.push({text:n[4],kind:"number"}):n[5]?r.push({text:n[5],kind:"boolean"}):n[6]?r.push({text:n[6],kind:"null"}):n[7]&&r.push({text:n[7],kind:"punct"}),a=s.lastIndex;return a<t.length&&r.push({text:t.slice(a),kind:"plain"}),r}function At(t){if(V(t))return t.message.split(/\r?\n/,1)[0].trimEnd();const r=t,s=typeof r.title=="string"&&r.title.trim()?r.title.trim():null,a=typeof r.command_name=="string"&&r.command_name.trim()?r.command_name.trim():null;return s??a??"Command"}function xe(t){const r=t.subtitle;return typeof r=="string"&&r.trim()?r.trim():null}function Et(t,r){return r?t.filter(s=>s.is_success===!1||s.is_error===!0||V(s)&&Re(s.message)==="error"):t}const Lt=({commands:t})=>{const r=ft(t);return r.length===0?null:e.jsxs("section",{className:"rounded-lg border border-[var(--border)] bg-[var(--surface)] overflow-hidden",children:[e.jsxs("header",{className:"flex items-center gap-2 px-4 py-3 border-b border-[var(--border)]",children:[e.jsx(ke,{className:"h-4 w-4 text-[var(--color-warning)]","aria-hidden":"true"}),e.jsx("h2",{className:"text-sm font-semibold text-[var(--text)]",children:"Self-healing"}),e.jsxs("span",{className:"text-[11px] text-[var(--text-muted)]",children:[r.length," selector",r.length===1?"":"s"," healed. Update the test so the next run doesn't need to."]})]}),e.jsxs("table",{className:"w-full table-fixed text-left",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b border-[var(--border)] text-[11px] text-[var(--text-dim)]",children:[e.jsx("th",{className:"px-4 py-2 font-medium w-[88px]",children:"Time"}),e.jsx("th",{className:"px-3 py-2 font-medium w-[128px]",children:"Command"}),e.jsx("th",{className:"px-3 py-2 font-medium",children:"Asked for"}),e.jsx("th",{className:"w-[28px]",children:e.jsx("span",{className:"sr-only",children:"healed to"})}),e.jsx("th",{className:"px-3 py-2 font-medium",children:"Healed to"}),e.jsx("th",{className:"px-3 py-2 font-medium w-[112px]",children:"Tier"}),e.jsx("th",{className:"px-4 py-2 font-medium w-[96px] text-right",children:"Confidence"})]})}),e.jsx("tbody",{children:r.map((s,a)=>e.jsxs("tr",{className:"border-b border-[var(--border)] last:border-b-0 align-top",children:[e.jsx("td",{className:"px-4 py-2 text-xs text-[var(--text-muted)] tabular-nums",children:z({timestamp:s.at??null})}),e.jsx("td",{className:"px-3 py-2 text-xs text-[var(--text)] truncate",children:s.command}),e.jsx("td",{className:"px-3 py-2 font-mono text-[11px] text-[var(--text-muted)] break-all",children:s.original??"—"}),e.jsx("td",{className:"py-2 text-[var(--text-dim)]",children:e.jsx(Ze,{className:"h-3.5 w-3.5","aria-hidden":"true"})}),e.jsx("td",{className:"px-3 py-2 font-mono text-[11px] text-[var(--text)] break-all",children:s.healed??"—"}),e.jsx("td",{className:"px-3 py-2 text-xs text-[var(--text)]",children:s.tier??"—"}),e.jsx("td",{className:"px-4 py-2 text-xs text-[var(--text)] tabular-nums text-right",children:s.confidence===null?"—":`${s.confidence}%`})]},s.id??a))})]})]})},Dt=1e4,me="var(--color-info)",ue="var(--color-accent)",Mt="var(--border-strong)";function he(t){return t>=1024?ie(t/1024)*1024:ie(t)}const fe=t=>{let r=0;for(const s of t)for(const a of s.values)a!==null&&a>r&&(r=a);return r},W=({title:t,series:r,times:s,yMax:a,format:n,ariaLabel:o})=>e.jsxs("section",{"aria-label":t,children:[e.jsxs("div",{className:"mb-2 flex flex-wrap items-baseline gap-x-4 gap-y-1",children:[e.jsx("h3",{className:"text-xs font-semibold text-[var(--text)]",children:t}),r.map(l=>{const i=rt(l.values);return e.jsxs("span",{className:"flex min-w-0 items-center gap-1.5 text-[11px] tabular-nums text-[var(--text-muted)]",children:[e.jsx("span",{className:"inline-block h-0.5 w-3 shrink-0",style:{background:l.color}}),e.jsx("span",{className:"max-w-[16rem] truncate",title:l.label,children:l.label}),i&&(l.dashed?e.jsx("span",{children:n(i.peak)}):e.jsxs("span",{children:["peak ",n(i.peak)," · avg ",n(i.average)]}))]},l.key)})]}),e.jsx(st,{times:s,series:r,yMax:a,formatValue:n,ariaLabel:o})]}),Ot=({sessionId:t,running:r,hasTrace:s})=>{const[a,n]=x.useState(null),[o,l]=x.useState(!1);x.useEffect(()=>{let u=!0;const v=()=>S.getSessionMetrics(t).then(C=>{u&&(n(tt(C)),l(!0))}).catch(()=>{u&&l(!0)});if(v(),!r)return()=>{u=!1};const h=setInterval(()=>void v(),Dt);return()=>{u=!1,clearInterval(h)}},[t,r]);const i=(a==null?void 0:a.samples)??[],c=x.useMemo(()=>i.map(u=>{var v;return u.t-(((v=i[0])==null?void 0:v.t)??0)}),[i]),m=new Set(i.map(u=>u.app).filter(u=>!!u)),b=m.size>1?"Foreground app":Array.from(m)[0]??(a==null?void 0:a.appId)??"App",f=i.map(u=>u.app??null),j=u=>u>0&&!!f[u]&&!!f[u-1]&&f[u]!==f[u-1],p=[],g=[],y=[];a&&(a.series.deviceCpu&&p.push({key:"deviceCpu",label:"Device",color:me,values:i.map(u=>u.deviceCpu)}),a.series.appCpu&&p.push({key:"appCpu",label:b,color:ue,values:i.map((u,v)=>j(v)?null:u.appCpu),pointLabels:f}),a.series.appMem&&g.push({key:"appMem",label:b,color:ue,values:i.map((u,v)=>j(v)?null:u.appMemMb),pointLabels:f}),a.series.deviceMem&&(y.push({key:"deviceMem",label:"Device used",color:me,values:i.map(u=>u.deviceMemMb)}),y.push({key:"deviceTotal",label:"Device total",color:Mt,values:i.map(u=>u.deviceMemTotalMb),dashed:!0})));const w=r&&(a==null?void 0:a.recording)==="off",R=(a==null?void 0:a.recording)==="stopped",A="Recording stopped: the device stopped responding.";let _;return o?w?_=e.jsx(M,{title:"Performance isn't recorded for this session",description:"CPU and memory are recorded for Android devices and iPhones. This session runs on an iOS simulator or on a machine that needs updating, or recording is turned off."}):i.length===0&&!r?_=e.jsx(M,{title:"No performance data for this session",description:"CPU and memory are recorded for Android devices and iPhones. This session ran on an iOS simulator or on a machine that needed updating, before recording was available, or with recording turned off."}):i.length<2?_=e.jsx("div",{className:"text-xs text-[var(--text-dim)]",children:R?A:r?"Collecting… The first figures appear within 10 seconds.":"Too few figures were recorded to draw a chart."}):_=e.jsxs("div",{className:"space-y-4",children:[R&&e.jsxs("p",{className:"text-xs text-[var(--color-warning)]",children:[A," The data ends there."]}),(a==null?void 0:a.platform)==="ios"&&e.jsxs("p",{className:"text-xs text-[var(--text-dim)]",children:["On iPhones, only the device's overall CPU is recorded.",s?" For more detail, download the Performance trace under Details.":""]}),p.length>0&&e.jsx(W,{title:"CPU",series:p,times:c,yMax:100,format:et,ariaLabel:"CPU over the session"}),g.length>0&&e.jsx(W,{title:"App memory",series:g,times:c,yMax:he(fe(g)),format:ne,ariaLabel:"App memory over the session"}),y.length>0&&e.jsx(W,{title:"Device memory",series:y,times:c,yMax:he(fe(y)),format:ne,ariaLabel:"Device memory over the session"})]}):_=e.jsx("div",{className:"text-xs text-[var(--text-dim)]",children:"Loading performance…"}),e.jsx(Se,{header:e.jsxs("span",{className:"flex items-center gap-2",children:[e.jsx(at,{size:14})," Performance"]}),children:_})};function Ft(t){const r=t.status==="running";return t.video_recording_enabled===!1?r?"Recording is off for this session.":"Recording was off for this session.":r?"Any video appears here after the session ends.":"No video was saved for this session."}const Pt=({session:t})=>{const r=t.status==="running",s=!!t.video_recording;return e.jsxs("section",{className:"rounded-lg border border-[var(--border)] bg-[var(--surface)] overflow-hidden",children:[e.jsxs("header",{className:"px-3 py-2 border-b border-[var(--border)] flex items-center justify-between",children:[e.jsx("span",{className:"text-[11px] font-semibold text-[var(--text-dim)]",children:"Recording"}),r&&e.jsxs("span",{className:"inline-flex items-center gap-1.5 text-[11px] text-[var(--red)]",children:[e.jsx("span",{className:"h-1.5 w-1.5 rounded-full bg-[var(--red)] pulse-dot"}),"Live"]})]}),e.jsx("div",{className:"aspect-video bg-[var(--bg)] flex items-center justify-center",children:r&&t.has_live_video?e.jsx("img",{src:S.getSessionLiveVideoUrl(t.id),alt:`Live view of session ${t.id}`,className:"w-full h-full object-contain"}):s?e.jsx("video",{controls:!0,src:S.getAssetUrl(t.video_recording),className:"w-full h-full object-contain"}):e.jsxs("div",{className:"flex flex-col items-center text-center px-6 py-8 gap-2",children:[e.jsx("div",{className:"h-10 w-10 rounded-full bg-[var(--surface-2)] border border-[var(--border)] flex items-center justify-center",children:e.jsx(nt,{className:"h-5 w-5 text-[var(--text-dim)]"})}),e.jsx("div",{className:"text-sm text-[var(--text)] font-medium",children:"No video available"}),e.jsx("div",{className:"text-xs text-[var(--text-dim)] max-w-xs",children:Ft(t)})]})})]})},T=({label:t,children:r,title:s,mono:a})=>e.jsxs("div",{className:"flex items-baseline justify-between gap-3 px-3 py-2",children:[e.jsx("dt",{className:"text-xs text-[var(--text-muted)] shrink-0",children:t}),e.jsx("dd",{className:`text-xs text-[var(--text)] text-right min-w-0 break-all ${a?"font-mono text-[11px]":""}`,title:s,children:r})]}),Ht=({session:t,buildName:r})=>{var l,i;const{toast:s}=I(),a=ye(t.ranOn),n=t.performance_trace?S.getAssetUrl(t.performance_trace):"",o=async()=>{try{await navigator.clipboard.writeText(t.id),s("Session ID copied","success")}catch{s("Clipboard unavailable","error")}};return e.jsxs("section",{className:"rounded-lg border border-[var(--border)] bg-[var(--surface)] overflow-hidden",children:[e.jsx("header",{className:"px-3 py-2 border-b border-[var(--border)]",children:e.jsx("h2",{className:"text-[11px] font-semibold text-[var(--text-dim)]",children:"Details"})}),e.jsxs("dl",{className:"divide-y divide-[var(--border)]",children:[e.jsx(T,{label:"Session ID",mono:!0,children:e.jsxs("span",{className:"inline-flex items-center gap-1",children:[e.jsx("span",{children:t.id}),e.jsx("button",{type:"button",onClick:o,"aria-label":"Copy session ID",className:"p-0.5 rounded text-[var(--text-dim)] hover:text-[var(--text)]",children:e.jsx(Y,{className:"h-3 w-3"})})]})}),r&&e.jsx(T,{label:"Build",children:r}),e.jsx(T,{label:"Device UDID",mono:!0,children:t.device_udid||"—"}),e.jsx(T,{label:"Platform",children:[Ne(t),t.device_version].filter(c=>c&&c!=="—").join(" ")||"—"}),e.jsx(T,{label:"Ran on",title:t.node_id?`Node ${t.node_id}`:void 0,children:a??"Not known"}),e.jsx(T,{label:"Run by",title:(l=t.owner)==null?void 0:l.email,children:((i=t.owner)==null?void 0:i.name)??"Not recorded"}),e.jsx(T,{label:"Started",children:re(t.startTime)}),e.jsx(T,{label:"Ended",children:t.endTime?re(t.endTime):"—"}),t.tags&&e.jsx(T,{label:"Tags",children:t.tags}),n&&e.jsx(T,{label:"iOS trace",children:e.jsxs("a",{href:n,className:"inline-flex items-center gap-1 text-[var(--color-accent)] hover:underline",children:[e.jsx(_e,{className:"h-3 w-3","aria-hidden":"true"}),"Performance trace"]})})]})]})},pe={desired:"Requested",session:"Actual"},It=({session:t})=>{const[r,s]=x.useState("desired"),a=se(t.desired_capabilities),n=se(t.session_capabilities),l=Object.entries(r==="desired"?a:n);return e.jsxs("section",{className:"rounded-lg border border-[var(--border)] bg-[var(--surface)] overflow-hidden",children:[e.jsx("header",{className:"flex items-center border-b border-[var(--border)]",children:["desired","session"].map(i=>e.jsx("button",{type:"button",onClick:()=>s(i),"aria-pressed":r===i,className:`flex-1 h-9 text-[11px] font-semibold transition-colors border-b-2 ${r===i?"border-[var(--color-accent)] text-[var(--text)]":"border-transparent text-[var(--text-muted)] hover:text-[var(--text)]"}`,children:pe[i]},i))}),l.length===0?e.jsxs("div",{className:"px-3 py-6 text-center text-xs text-[var(--text-dim)]",children:["No ",pe[r].toLowerCase()," capabilities recorded for this session."]}):e.jsx("dl",{className:"divide-y divide-[var(--border)]",children:l.map(([i,c])=>e.jsxs("div",{className:"grid grid-cols-[minmax(0,1fr)_minmax(0,1fr)] items-baseline gap-3 px-3 py-2",children:[e.jsx("dt",{className:"text-xs text-[var(--text-muted)] break-all",children:i}),e.jsx("dd",{className:"font-mono text-xs text-[var(--text)] truncate text-right min-w-0",title:ae(c,500),children:ae(c)})]},i))})]})},Bt=({tabs:t,active:r,onChange:s,errorsOnly:a,onErrorsOnlyChange:n,showErrorsOnly:o=!0})=>{const l=t.filter(i=>!(i.hideWhenEmpty&&i.count===0));return e.jsxs("div",{className:"flex items-center justify-between gap-4 px-3 border-b border-[var(--border)] bg-[var(--surface)]",children:[e.jsx("div",{className:"flex items-center gap-1 overflow-x-auto",children:l.map(i=>{const c=i.key===r;return e.jsxs("button",{type:"button",onClick:()=>s(i.key),"aria-pressed":c,"data-empty":i.count===0?"true":"false",className:`relative inline-flex items-center gap-1.5 h-9 px-3 text-xs whitespace-nowrap transition-colors ${c?"text-[var(--text)]":i.count===0?"text-[var(--text-dim)] hover:text-[var(--text-muted)]":"text-[var(--text-muted)] hover:text-[var(--text)]"}`,children:[e.jsx("span",{children:i.label}),i.count>0&&e.jsx("span",{className:`text-[10px] tabular-nums ${c?"text-[var(--text-muted)]":"text-[var(--text-dim)]"}`,children:kt(i.count)}),c&&e.jsx("span",{className:"absolute left-2 right-2 bottom-0 h-[2px] bg-[var(--color-accent)] rounded-t"})]},i.key)})}),o&&e.jsxs("label",{className:"inline-flex items-center gap-2 text-[11px] text-[var(--text-muted)] cursor-pointer select-none whitespace-nowrap",children:[e.jsx("input",{type:"checkbox",checked:a,onChange:i=>n(i.target.checked),"aria-label":"Show only error rows"}),"Errors only"]})]})},Ut={key:"text-[var(--blue)]",string:"text-[var(--color-accent)]",number:"text-[var(--amber)]",boolean:"text-[var(--amber)]",null:"text-[var(--text-dim)] italic",punct:"text-[var(--text-muted)]",plain:"text-[var(--text)]"},Vt=({value:t,maxHeightPx:r})=>{const s=Tt(t);if(!s)return e.jsx("span",{className:"text-[var(--text-dim)] text-xs",children:"(empty)"});let a;try{a=$t(s)}catch{a=[{text:s,kind:"plain"}]}return e.jsx("pre",{className:"font-mono text-[11px] leading-relaxed bg-[var(--bg)] border border-[var(--border)] rounded-md p-3 overflow-x-auto whitespace-pre",style:r?{maxHeight:r,overflowY:"auto"}:void 0,children:a.map((n,o)=>e.jsx("span",{className:Ut[n.kind],children:n.text},o))})},zt={green:"bg-[var(--color-success)]",red:"bg-[var(--red)]",amber:"bg-[var(--amber)]",blue:"bg-[var(--blue)]",neutral:"bg-[var(--text-dim)]"},Jt={green:"text-[var(--color-success)]",red:"text-[var(--red)]",amber:"text-[var(--amber)]",blue:"text-[var(--blue)]",neutral:"text-[var(--text-muted)]"},Te=({log:t})=>{const[r,s]=x.useState(!1),{toast:a}=I(),n=z(t),o=Rt(t),l=V(t),i=l?String(t.message):"",c=async m=>{m.stopPropagation();try{const b=l?i:t.body??t,f=typeof b=="string"?b:JSON.stringify(b,null,2);await navigator.clipboard.writeText(f),a("Log entry copied","success")}catch{a("Clipboard unavailable","error")}};return e.jsxs("div",{className:"border-b border-[var(--border)] last:border-b-0",children:[e.jsxs("button",{type:"button",onClick:()=>s(m=>!m),"aria-expanded":r,className:"group w-full flex items-center gap-2 px-3 py-2 text-left hover:bg-[var(--surface-2)]/60 transition-colors",children:[e.jsx(K,{className:`h-3 w-3 text-[var(--text-dim)] transition-transform shrink-0 ${r?"rotate-90":""}`}),e.jsx("span",{className:"font-mono text-[11px] text-[var(--text-muted)] w-[64px] shrink-0",children:n}),e.jsx("span",{className:`h-1.5 w-1.5 rounded-full shrink-0 ${zt[o.tone]}`}),o.label&&e.jsx("span",{className:`font-mono text-[11px] font-medium shrink-0 ${Jt[o.tone]}`,children:o.label}),e.jsxs("span",{className:"min-w-0 flex-1 flex items-baseline gap-2 truncate",children:[e.jsx("span",{className:l?"font-mono text-[11px] text-[var(--text)] truncate min-w-0":"text-[12px] text-[var(--text)] shrink-0",children:At(t)}),xe(t)&&e.jsx("span",{className:"font-mono text-[11px] text-[var(--text-dim)] truncate min-w-0",children:xe(t)})]}),typeof t.duration=="number"&&e.jsx("span",{className:"text-[11px] tabular-nums text-[var(--text-muted)] shrink-0",children:H(t.duration)}),e.jsx("span",{role:"button",tabIndex:0,onClick:c,onKeyDown:m=>{(m.key==="Enter"||m.key===" ")&&c(m)},"aria-label":"Copy log entry",className:"opacity-0 group-hover:opacity-100 p-1 rounded text-[var(--text-dim)] hover:text-[var(--text)] transition-opacity shrink-0",children:e.jsx(Y,{className:"h-3 w-3"})})]}),r&&e.jsx("div",{className:"px-3 pb-3 pl-9",children:l?e.jsx("pre",{className:"font-mono text-[11px] leading-relaxed text-[var(--text)] bg-[var(--bg)] border border-[var(--border)] rounded-md p-3 max-h-[400px] overflow-auto whitespace-pre-wrap break-words",children:i}):e.jsx(Vt,{value:t.body??t,maxHeightPx:400})})]})},Wt=(t,r)=>t?"bg-[var(--color-danger)]":r?"bg-[var(--color-warning)]":"bg-[var(--color-success)]",Kt=({commands:t})=>{const{spanMs:r,bars:s}=vt(t);return s.length===0?e.jsx("div",{className:"px-4 py-10 text-center text-xs text-[var(--text-dim)]",children:"No commands recorded for this session."}):e.jsxs("div",{className:"px-3 py-3",children:[e.jsxs("div",{className:"flex items-center justify-between pb-2 text-[11px] text-[var(--text-dim)] tabular-nums",children:[e.jsxs("span",{children:[s.length," command",s.length===1?"":"s"," over ",H(r)]}),e.jsxs("span",{className:"inline-flex items-center gap-3",children:[e.jsxs("span",{className:"inline-flex items-center gap-1",children:[e.jsx("span",{className:"h-2 w-2 rounded-sm bg-[var(--color-danger)]"})," Failed"]}),e.jsxs("span",{className:"inline-flex items-center gap-1",children:[e.jsx("span",{className:"h-2 w-2 rounded-sm bg-[var(--color-warning)]"})," Healed"]})]})]}),e.jsx("ol",{className:"space-y-1",children:s.map((a,n)=>e.jsxs("li",{"data-testid":"timeline-bar","data-command":a.label,"data-failed":a.failed?"true":"false",className:"grid grid-cols-[128px_minmax(0,1fr)_64px] items-center gap-2",children:[e.jsx("span",{className:"truncate text-[11px] font-mono text-[var(--text-muted)]",title:a.label,children:a.label}),e.jsx("span",{className:"relative h-3 rounded-sm bg-[rgb(var(--rgb-fg)/0.05)]",children:e.jsx("span",{className:`absolute inset-y-0 rounded-sm ${Wt(a.failed,a.healed)}`,style:{left:`${a.startMs/r*100}%`,width:`max(2px, ${a.durationMs/r*100}%)`}})}),e.jsx("span",{className:"text-right text-[11px] tabular-nums text-[var(--text-muted)]",children:a.durationMs>0?H(a.durationMs):"—"})]},a.id??n))})]})},qt=({commands:t})=>{const r=bt(t);return r.length===0?e.jsxs("div",{className:"px-4 py-10 text-center text-xs text-[var(--text-dim)]",children:["No screenshots were kept. A failed command keeps one unless"," ",e.jsx("code",{className:"font-mono",children:"xe:options.screenshotOnFailure"})," is false; set"," ",e.jsx("code",{className:"font-mono",children:"xe:options.screenshotOnEveryCommand"})," to keep one for every command."]}):e.jsx("ul",{className:"grid grid-cols-[repeat(auto-fill,minmax(140px,1fr))] gap-3 p-3",children:r.map((s,a)=>{const n=S.getAssetUrl(s.path),o=z({timestamp:s.at??null});return e.jsx("li",{children:e.jsxs("a",{href:n,target:"_blank",rel:"noreferrer",className:`block rounded-md border overflow-hidden hover:border-[var(--border-strong)] ${s.failed?"border-[var(--color-danger)]":"border-[var(--border)]"}`,children:[e.jsx("img",{src:n,alt:`${s.command} at ${o}`,loading:"lazy",className:"block w-full aspect-[9/16] object-contain bg-[rgb(var(--rgb-fg)/0.03)]"}),e.jsxs("span",{className:"flex items-center justify-between gap-2 px-2 py-1 text-[11px]",children:[e.jsx("span",{className:`truncate font-mono ${s.failed?"text-[var(--color-danger)]":"text-[var(--text)]"}`,children:s.command}),e.jsx("span",{className:"tabular-nums text-[var(--text-dim)] shrink-0",children:o})]})]})},s.id??a)})})},ve=["commands","device","debug","profiling"],Xt=500,Gt=33,Yt=({rows:t,scroller:r})=>{const s=qe({count:t.length,getScrollElement:()=>r.current,estimateSize:()=>Gt,getItemKey:a=>t[a].id??a,overscan:20});return e.jsx("div",{className:"relative",style:{height:s.getTotalSize()},children:s.getVirtualItems().map(a=>e.jsx("div",{"data-index":a.index,ref:s.measureElement,className:`absolute left-0 top-0 w-full${a.index<t.length-1?" border-b border-[var(--border)]":""}`,style:{transform:`translateY(${a.start}px)`},children:e.jsx(Te,{log:t[a.index]})},String(a.key)))})},Qt=({sessionLogs:t,deviceLogs:r,debugLogs:s,profiling:a})=>{const[n,o]=x.useState("commands"),[l,i]=x.useState(!1),c=x.useRef(null),m=t,b=x.useMemo(()=>Ce(m).screenshots,[m]),f=x.useMemo(()=>[{key:"commands",label:"Commands",count:t.length},{key:"timeline",label:"Timeline",count:t.length},{key:"screenshots",label:"Screenshots",count:b},{key:"device",label:"Device logs",count:r.length},{key:"debug",label:"Debug logs",count:s.length},{key:"profiling",label:"System profiling",count:a.length,hideWhenEmpty:!0}],[t.length,b,r.length,s.length,a.length]),j=x.useMemo(()=>{let p=[];return n==="commands"?p=t:n==="device"?p=r:n==="debug"?p=s:n==="profiling"&&(p=a),Et(p,l)},[n,t,r,s,a,l]);return e.jsxs("section",{className:"rounded-lg border border-[var(--border)] bg-[var(--surface)] flex flex-col min-h-[280px] max-h-[640px]",children:[e.jsx(Bt,{tabs:f,active:n,onChange:o,errorsOnly:l,onErrorsOnlyChange:i,showErrorsOnly:ve.includes(n)}),e.jsxs("div",{ref:c,className:"flex-1 overflow-y-auto","data-log-scroller":"",children:[n==="timeline"&&e.jsx(Kt,{commands:m}),n==="screenshots"&&e.jsx(qt,{commands:m}),ve.includes(n)&&(j.length===0?e.jsx("div",{className:"px-4 py-10 text-center text-xs text-[var(--text-dim)]",children:l?"No error rows in this tab.":"No log entries in this tab."}):j.length>=Xt?e.jsx(Yt,{rows:j,scroller:c},n):j.map((p,g)=>e.jsx(Te,{log:p},p.id??g)))]})]})};function $e(t){if(!t)return"failed";switch(t){case"HTTPS_CLIENT_ERROR":case"HTTPS_SERVER_ERROR":case"OPEN_HTTPS_SERVER_ERROR":case"ON_CONNECT_ERROR":return"tls";case"PROXY_TO_SERVER_REQUEST_ERROR":return"net";default:return"failed"}}const ee="/xenon/api/interceptor";async function be(t){const r=await fetch(`${ee}/sessions/${encodeURIComponent(t)}/requests`);if(r.status===403)return{active:!1,forbidden:!0};if(r.status===404){const a=await r.json().catch(()=>({}));return{active:!1,error:a==null?void 0:a.error}}return r.ok?{active:!0,requests:(await r.json()).requests||[]}:{active:!1,error:`request failed (${r.status})`}}async function Zt(t,r){const s=await fetch(`${ee}/sessions/${encodeURIComponent(t)}/requests/${encodeURIComponent(r)}`);return s.ok?s.json():null}function er(t){return`${ee}/sessions/${encodeURIComponent(t)}/har`}function tr(t){return t>=200&&t<300?"ready":t>=300&&t<400?"neutral":t>=400&&t<500?"busy":t>=500?"error":"neutral"}const ge=({headers:t})=>{const r=Object.entries(t||{});return r.length===0?e.jsx("div",{className:"text-xs text-[var(--text-dim)]",children:"No headers"}):e.jsx("div",{className:"space-y-0.5 font-mono text-xs",children:r.map(([s,a])=>e.jsxs("div",{className:"flex gap-2",children:[e.jsxs("span",{className:"text-[var(--text-dim)] shrink-0",children:[s,":"]}),e.jsx("span",{className:"break-all",children:a})]},s))})},je=({body:t})=>{if(t==null||t==="")return e.jsx("div",{className:"text-xs text-[var(--text-dim)]",children:"No body"});let r=t;try{r=JSON.stringify(JSON.parse(t),null,2)}catch{}return e.jsx("pre",{className:"font-mono text-xs whitespace-pre-wrap break-all bg-[var(--surface-2,var(--surface))] rounded p-2 max-h-64 overflow-auto",children:r})},rr=({request:t,onClose:r})=>{if(!t)return null;const s=e.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[e.jsx($,{tone:"accent",children:t.method}),t.failed?e.jsx($,{tone:"error",children:$e(t.failureKind)}):e.jsx($,{tone:tr(t.resStatus),children:t.resStatus||"—"}),e.jsx("span",{className:"font-mono text-xs truncate",title:t.url,children:t.url})]});return e.jsx(ct,{open:!!t,title:s,onClose:r,width:720,children:e.jsxs("div",{className:"space-y-4 text-xs",children:[t.failed&&e.jsxs("div",{className:"border border-[var(--red)] rounded p-2 bg-[rgb(var(--rgb-red-600)/0.08)]",children:[e.jsx("div",{className:"text-[var(--red)] text-[11px] mb-1",children:"Failure"}),e.jsx("div",{className:"text-xs",children:t.failureReason||"Request failed"}),t.failureKind&&e.jsx("div",{className:"font-mono text-[10px] text-[var(--text-dim)] mt-1",children:t.failureKind})]}),!t.failed&&e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-[var(--text-dim)] text-[11px] mb-1",children:"Duration"}),e.jsxs("div",{className:"font-mono",children:[t.durationMs," ms"]})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-[var(--text-dim)] text-[11px] mb-1",children:"Flags"}),e.jsxs("div",{className:"flex gap-1",children:[t.mocked&&e.jsx($,{tone:"accent",children:"mocked"}),t.modified&&e.jsx($,{tone:"busy",children:"modified"}),!t.mocked&&!t.modified&&e.jsx("span",{className:"text-[var(--text-dim)]",children:"passthrough"})]})]})]}),t.commandHint&&e.jsxs("div",{children:[e.jsx("div",{className:"text-[var(--text-dim)] text-[11px] mb-1",children:"Triggered by"}),e.jsx("div",{className:"font-mono",children:t.commandHint.commandName})]}),!t.failed&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-[var(--text-dim)] text-[11px] mb-1",children:"Request Headers"}),e.jsx(ge,{headers:t.reqHeaders})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-[var(--text-dim)] text-[11px] mb-1",children:"Request Body"}),e.jsx(je,{body:t.reqBody})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-[var(--text-dim)] text-[11px] mb-1",children:"Response Headers"}),e.jsx(ge,{headers:t.resHeaders})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-[var(--text-dim)] text-[11px] mb-1",children:"Response Body"}),e.jsx(je,{body:t.resBody})]})]})]})})};function sr(t){return t?new Date(t).toLocaleTimeString(void 0,{hour12:!1}):"—"}function ar(t){return t>=200&&t<300?"ready":t>=300&&t<400?"neutral":t>=400&&t<500?"busy":t>=500?"error":"neutral"}const nr=({sessionId:t,sessionEnded:r})=>{const[s,a]=x.useState(null),[n,o]=x.useState(!1),[l,i]=x.useState(null),[c,m]=x.useState([]),[b,f]=x.useState(!0),[j,p]=x.useState(null),g=x.useRef(new Set),{on:y,isConnected:w}=De(),R=x.useCallback(d=>{o(!!d.forbidden),a(d.active),i(d.error||null);const N=d.requests||[];m(N),g.current=new Set(N.map(D=>D.id))},[]);x.useEffect(()=>{let d=!0;return f(!0),be(t).then(N=>{d&&R(N)}).catch(()=>{d&&R({active:!1,error:"the server could not be reached"})}).finally(()=>{d&&f(!1)}),()=>{d=!1}},[t,R]),x.useEffect(()=>{if(r)return;let d=!0;const N=y("interceptor_request",k=>{!k||k.sessionId!==t||g.current.has(k.id)||(g.current.add(k.id),m(J=>[k,...J]),a(!0))}),D=y("interceptor_session_started",k=>{(k==null?void 0:k.sessionId)===t&&a(!0)}),O=y("interceptor_session_stopped",k=>{(k==null?void 0:k.sessionId)===t&&be(t).then(J=>{d&&R(J)}).catch(()=>{})});return()=>{d=!1,N(),D(),O()}},[y,t,r,w,R]);const A=x.useMemo(()=>[...c].sort((d,N)=>N.ts-d.ts),[c]),_=async d=>{if(p(d),s){const N=await Zt(t,d.id);N&&p(N)}},u=s&&c.length>0?e.jsxs("a",{href:er(t),className:"inline-flex items-center gap-1 text-xs text-[var(--text-dim)] hover:text-[var(--text)]",title:"Download HAR",children:[e.jsx(_e,{className:"h-3 w-3"}),"HAR"]}):null,v=e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(dt,{className:"h-3.5 w-3.5 text-[var(--text-dim)]"}),e.jsx("span",{children:"Network"}),s&&c.length>0&&e.jsxs("span",{className:"text-xs text-[var(--text-dim)]",children:["(",c.length,")"]})]});let h;const C=s===!1&&(!l||l==="interceptor inactive");return b?h=e.jsx("div",{className:"p-4 text-xs text-[var(--text-dim)]",children:"Loading…"}):n?h=e.jsx(M,{title:"Only admins can see network requests",description:"Captured requests can carry sign-in details and personal data, so only admins can open them. Ask an admin to look at this session's requests."}):C&&r?h=e.jsx(M,{title:"No network capture",description:"This session didn't capture its network requests."}):C?h=e.jsx(M,{title:"Network capture is off",description:"This session isn't capturing its network requests. Android sessions capture them when the test turns network capture on in its capabilities, or when it is on for every session in the server settings."}):l?h=e.jsxs("div",{className:"p-4 text-xs text-[var(--red)]",children:["Failed to load requests: ",l]}):A.length===0?h=e.jsx(M,{title:"Waiting for requests",description:r?"No HTTP traffic was captured during this session.":"Captured requests will appear here as the device makes calls."}):h=e.jsx("div",{className:"overflow-auto max-h-96",children:e.jsxs(it,{children:[e.jsx(ot,{children:e.jsxs(oe,{children:[e.jsx(E,{style:{width:80},children:"Time"}),e.jsx(E,{style:{width:70},children:"Method"}),e.jsx(E,{style:{width:70},children:"Status"}),e.jsx(E,{children:"Host"}),e.jsx(E,{children:"Path"}),e.jsx(E,{style:{width:80},children:"Duration"}),e.jsx(E,{style:{width:90},children:"Flags"})]})}),e.jsx(lt,{children:A.map(d=>e.jsxs(oe,{onClick:()=>_(d),style:{cursor:"pointer"},title:d.failed?d.failureReason:void 0,children:[e.jsx(L,{className:"font-mono text-[11px]",children:sr(d.ts)}),e.jsx(L,{children:e.jsx($,{tone:"accent",children:d.method})}),e.jsx(L,{children:d.failed?e.jsx($,{tone:"error",children:$e(d.failureKind)}):e.jsx($,{tone:ar(d.resStatus),children:d.resStatus||"—"})}),e.jsx(L,{className:"font-mono text-[11px] truncate",title:d.host,children:d.host}),e.jsx(L,{className:"font-mono text-[11px] truncate",title:d.path,children:d.failed?"—":d.path}),e.jsx(L,{className:"font-mono text-[11px]",children:d.failed?"—":`${d.durationMs}ms`}),e.jsx(L,{children:e.jsxs("div",{className:"flex gap-1",children:[d.mocked&&e.jsx($,{tone:"accent",children:"mock"}),d.modified&&e.jsx($,{tone:"busy",children:"mod"})]})})]},d.id))})]})}),e.jsxs(e.Fragment,{children:[e.jsx(Se,{header:v,action:u,padded:!1,children:h}),e.jsx(rr,{request:j,onClose:()=>p(null)})]})},Tr=()=>{const{buildId:t="",sessionId:r=""}=Me(),{toast:s}=I(),a=Oe(),n=Ue(),o=mt(r||null),l=x.useMemo(()=>n.builds.find(f=>f.id===t)??null,[n.builds,t]),i=l?Ve(l):"Build";if(x.useEffect(()=>{!o.loading&&o.notFound&&(s("Session not available — it may belong to a team you are not on.","info"),a("/builds",{replace:!0}))},[o.loading,o.notFound,a,s]),o.loading)return e.jsx("div",{className:"p-6 text-xs text-[var(--text-dim)]",children:"Loading session…"});if(o.error||!o.session)return e.jsxs("div",{className:"p-6 space-y-2",children:[e.jsx(ce,{buildId:t,buildName:l?i:null,sessionId:r}),e.jsx("div",{className:"mt-6 rounded-md border border-[var(--red)]/30 bg-[var(--surface)] p-4 text-xs text-[var(--red)]",children:o.error||"Session not found."})]});const c=o.session,m=o.sessionLogs,b=Q(c.status).bucket==="failed";return e.jsxs("div",{className:"flex flex-col h-full min-h-0",children:[e.jsx(ce,{buildId:t,buildName:l?i:null,sessionId:c.id}),e.jsx(ht,{session:c}),e.jsx("div",{className:"flex-1 overflow-y-auto overflow-x-hidden",children:e.jsxs("div",{className:"px-4 py-4 space-y-4",children:[e.jsx(gt,{session:c,commands:m}),b&&e.jsx(wt,{session:c,buildName:i,buildId:t,commands:m,durationText:ze(X(c))}),e.jsx(Lt,{commands:m}),e.jsx(Ot,{sessionId:c.id,running:c.status==="running",hasTrace:!!c.performance_trace}),e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-[minmax(0,1fr)_340px] gap-4",children:[e.jsx("div",{className:"min-w-0",children:e.jsx(Qt,{sessionLogs:o.sessionLogs,deviceLogs:o.deviceLogs,debugLogs:o.debugLogs,profiling:o.profiling})}),e.jsxs("div",{className:"flex flex-col gap-4 min-w-0",children:[e.jsx(Pt,{session:c}),e.jsx(Ht,{session:c,buildName:l?i:null}),e.jsx(It,{session:c})]})]}),e.jsx(nr,{sessionId:c.id,sessionEnded:c.status!=="running"})]})})]})};export{Tr as SessionDetailPage,Tr as default};
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
38
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
40
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
41
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
42
|
-
});
|
|
43
|
-
};
|
|
44
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
45
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
46
|
-
};
|
|
47
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
-
exports.preparePrismaSchema = preparePrismaSchema;
|
|
49
|
-
const fs = __importStar(require("fs"));
|
|
50
|
-
const path = __importStar(require("path"));
|
|
51
|
-
const logger_1 = __importDefault(require("../logger"));
|
|
52
|
-
const config_1 = require("../config");
|
|
53
|
-
/**
|
|
54
|
-
* Prisma Schema Preparer
|
|
55
|
-
*
|
|
56
|
-
* Dynamically switches the database provider in schema.prisma
|
|
57
|
-
* based on the XENON_DB_PROVIDER environment variable.
|
|
58
|
-
*/
|
|
59
|
-
function preparePrismaSchema() {
|
|
60
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
61
|
-
const schemaPath = path.join(process.cwd(), 'prisma', 'schema.prisma');
|
|
62
|
-
const provider = config_1.config.databaseProvider; // defaults to sqlite
|
|
63
|
-
if (!fs.existsSync(schemaPath)) {
|
|
64
|
-
logger_1.default.error(`[PrismaPrepare] Schema not found at ${schemaPath}`);
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
const schema = fs.readFileSync(schemaPath, 'utf8');
|
|
68
|
-
const currentProviderMatch = schema.match(/datasource\s+db\s*{[\s\S]*?provider\s*=\s*"([^"]+)"/);
|
|
69
|
-
const currentProvider = currentProviderMatch ? currentProviderMatch[1] : null;
|
|
70
|
-
if (currentProvider === provider) {
|
|
71
|
-
logger_1.default.info(`[PrismaPrepare] Schema already configured for ${provider}`);
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
logger_1.default.info(`[PrismaPrepare] Switching provider from ${currentProvider} to ${provider}`);
|
|
75
|
-
// Replace the provider in the datasource block
|
|
76
|
-
// We target the provider inside the 'datasource db' block specifically
|
|
77
|
-
const newSchema = schema.replace(/(datasource\s+db\s*{[\s\S]*?provider\s*=\s*")([^"]*)(")/, `$1${provider}$3`);
|
|
78
|
-
fs.writeFileSync(schemaPath, newSchema);
|
|
79
|
-
logger_1.default.info('[PrismaPrepare] schema.prisma updated successfully.');
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
if (require.main === module) {
|
|
83
|
-
preparePrismaSchema().catch((err) => {
|
|
84
|
-
var _a;
|
|
85
|
-
const msg = (_a = err === null || err === void 0 ? void 0 : err.message) !== null && _a !== void 0 ? _a : String(err);
|
|
86
|
-
logger_1.default.error(`[PrismaPrepare] Critical failure: ${msg}`, err);
|
|
87
|
-
process.exit(1);
|
|
88
|
-
});
|
|
89
|
-
}
|