hanoman 0.9.30 → 0.9.31

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 (24) hide show
  1. package/dist/build-info.json +3 -3
  2. package/dist/cli.js +12 -2
  3. package/dist/server.js +323 -235
  4. package/package.json +1 -1
  5. package/web/assets/{DalangHanomanScreen-Fd7_DcSP.js → DalangHanomanScreen-DdsEmtBl.js} +1 -1
  6. package/web/assets/{DocPreviewModal-SMRN2K98.js → DocPreviewModal-BbOqdfaH.js} +1 -1
  7. package/web/assets/{DocsWorkspace-pxj0N6QW.js → DocsWorkspace-Cr7AXz9z.js} +1 -1
  8. package/web/assets/{IdeScreen-Cr9Vqdrc.js → IdeScreen-hdbQW-ui.js} +1 -1
  9. package/web/assets/{LeadScreen-CQXpJy0y.js → LeadScreen-BWE4mfJI.js} +1 -1
  10. package/web/assets/{ReviewScreen-B7NNEjxk.js → ReviewScreen-BIkpEspG.js} +1 -1
  11. package/web/assets/{SchedulerScreen-D3rPdS-F.js → SchedulerScreen-3KVE-d_d.js} +1 -1
  12. package/web/assets/SettingsScreen-B0-W2TeR.js +62 -0
  13. package/web/assets/{TeamScreen-BBAsYLpT.js → TeamScreen-DNdt2P1g.js} +1 -1
  14. package/web/assets/{TerminalScreen-DpVp4h1n.js → TerminalScreen-BjQF48XI.js} +1 -1
  15. package/web/assets/{TriageScreen-wAPnttRe.js → TriageScreen-CzM99CrG.js} +1 -1
  16. package/web/assets/{VpsScreen-DeQVx9Jy.js → VpsScreen-SGB_BpbS.js} +1 -1
  17. package/web/assets/fields-of8G961J.js +1 -0
  18. package/web/assets/{index-BQw6xQI4.js → index-C5P4ykKO.js} +3 -3
  19. package/web/assets/{live-CONO0GTu.js → live-DQen7wLm.js} +1 -1
  20. package/web/assets/{sched-lead-shared-CDR0pOqs.js → sched-lead-shared-C34TvLVv.js} +1 -1
  21. package/web/assets/{settings-rebase-CpaFw0Tm.js → settings-rebase-DHIWk4mV.js} +1 -1
  22. package/web/index.html +1 -1
  23. package/web/assets/SettingsScreen-Bx13PWKQ.js +0 -62
  24. package/web/assets/fields-qnBoIMR_.js +0 -1
@@ -1,2 +1,2 @@
1
- import{h as F,i as Q,j as a,M as te,f as St,g as ee,a3 as xn,a4 as ja,m as ze,n as vt,I as De,a2 as vn,Z as yn,B as L,a5 as jn,C as Qe,a6 as ta,a7 as aa,a8 as na,e as we,a9 as wn,aa as Sn,ab as Nn,ac as In,ad as Cn,ae as Rn,af as Fe,ag as wa,ah as Me,ai as Tn,r as En,a1 as An,Y as ge,O as Ne,aj as zn,ak as Dn,al as yt,am as Mn,q as fe,an as Sa,b as Fn,ao as $n,d as Pn,ap as Ln,p as On,aq as Bn,ar as ia,as as Kn,o as gt,at as _n,au as Gn,c as Wn,av as qn,aw as sa,ax as Un,ay as Hn,V as Vn,az as Yn,aA as Jn,aB as Je,aC as Nt,aD as Xn,aE as Zn,D as Qn,aF as ei,aG as ra,aH as ti}from"./index-BQw6xQI4.js";import{R as d,r as P}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import{A as ai}from"./fields-qnBoIMR_.js";import"./xterm-3VOAfa_q.js";function It(e){return e.endedAt?e.endedReason==="reconciled"?"interrupted":e.exitCode===null||e.exitCode===0?"completed":"failed":"running"}const Xe=new Set;let Ae;function ni(e){return Xe.add(e),Ae||(Ae=setInterval(()=>{for(const n of[...Xe])n()},1e3)),()=>{Xe.delete(e),Xe.size===0&&Ae&&(clearInterval(Ae),Ae=void 0)}}const la=20;function ii(e,n){if(!n)return"—";const s=new Date(n).getTime()-new Date(e).getTime();if(!Number.isFinite(s)||s<0)return"—";const r=Math.round(s/1e3);if(r<60)return`${r} dtk`;const l=Math.round(r/60);return l<60?`${l} mnt`:`${Math.floor(l/60)} jam ${l%60} mnt`}function si(e){switch(It(e)){case"running":return{label:"berjalan",tone:"neutral"};case"interrupted":return{label:"terputus",tone:"warn"};case"failed":return{label:`exit ${e.exitCode}`,tone:"err"};default:return{label:"selesai",tone:"ok"}}}const Na=e=>It(e)==="interrupted"?"—":ii(e.startedAt,e.endedAt),Ia=e=>ja[e]??e;function ri({projects:e,onClose:n,onRestart:s}){const[r,l]=d.useState([]),[u,x]=d.useState(0),[g,N]=d.useState(1),[h,k]=d.useState(!1),[p,b]=d.useState(""),[j,C]=d.useState(""),[E,A]=d.useState(""),[R,y]=d.useState(""),[f,M]=d.useState(null),[K,W]=d.useState(null),[v,I]=d.useState(0);d.useEffect(()=>{const o=setTimeout(()=>y(E.trim()),250);return()=>clearTimeout(o)},[E]),d.useEffect(()=>{N(1)},[p,j,R]),d.useEffect(()=>{let o=!0;return k(!0),F.listSessionHistory({projectId:p||void 0,kind:j||void 0,q:R||void 0,page:g,limit:la}).then(T=>{o&&(W(null),x(T.total),l(T.items))}).catch(T=>{o&&(l([]),x(0),W(Q("memuat riwayat sesi",T)))}).finally(()=>{o&&k(!1)}),()=>{o=!1}},[p,j,R,g,v]);const D=yn(u,g,la),w=o=>{var T;return((T=e.find(V=>V.id===o))==null?void 0:T.name)??o};return a.jsxs(te,{open:!0,title:"Riwayat sesi",icon:"history",onClose:n,width:900,children:[a.jsxs("div",{className:"hn-terminal-hist-toolbar",children:[a.jsx(St,{size:"sm",leftIcon:"search",placeholder:"mis. spec-412 atau reverse","aria-label":"Cari riwayat sesi",value:E,onChange:o=>A(o.target.value),className:"hn-terminal-hist-search"}),a.jsx(ee,{size:"sm","aria-label":"Filter project",value:p,onChange:o=>b(o.target.value),options:[{value:"",label:"Semua project"}].concat(e.map(o=>({value:o.id,label:o.name})))}),a.jsx(ee,{size:"sm","aria-label":"Filter jenis",value:j,onChange:o=>C(o.target.value),options:[{value:"",label:"Semua jenis"}].concat(xn.map(o=>({value:o,label:ja[o]})))})]}),K?a.jsx(ze,{kind:"error",icon:"history",title:"Riwayat belum bisa dimuat",hint:K,action:()=>I(o=>o+1),actionLabel:"Coba lagi"}):r.length===0&&!h?a.jsx(ze,{kind:"empty",icon:"history",title:"Belum ada riwayat sesi",hint:"Riwayat terisi sendiri saat sesi terminal dibuka lalu ditutup — termasuk sesi backlog, terminal biasa, dan sesi project-level."}):a.jsxs("div",{className:"hn-terminal-hist-list",children:[r.map(o=>{const T=si(o);return a.jsx("button",{onClick:()=>M(o),className:"hn-terminal-hist-row",children:a.jsxs("span",{className:"hn-dense-row hn-picker-row hn-terminal-hist-main",children:[a.jsx("span",{className:"hn-terminal-hist-when",children:new Date(o.startedAt).toLocaleString("id-ID")}),a.jsx(vt,{size:"sm",tone:"neutral",children:Ia(o.kind)}),a.jsx("span",{className:"hn-picker-title hn-terminal-hist-title",children:o.title??o.specId??w(o.projectId)}),o.transcriptBytes!==null&&a.jsx(De,{name:"file-text",size:12,color:"var(--text-subtle)"}),a.jsx("span",{className:"hn-terminal-hist-duration",children:Na(o)}),a.jsx(vt,{size:"sm",tone:T.tone,children:T.label})]})},o.id)}),h&&a.jsx("div",{className:"hn-terminal-hist-loading",children:"memuat…"})]}),a.jsx(vn,{page:D.page,pageCount:D.pageCount,total:u,from:D.from,to:D.to,onPage:N,unit:"sesi"}),f&&a.jsx(li,{row:f,projectName:w(f.projectId),onBack:()=>M(null),onRestart:s})]})}function li({row:e,projectName:n,onBack:s,onRestart:r}){const[l,u]=d.useState(null),[x,g]=d.useState("idle"),[N,h]=d.useState(null);async function k(j){try{if(!navigator.clipboard)throw new Error("clipboard tidak tersedia di browser ini");await navigator.clipboard.writeText(j),h({tone:"ok",text:"Transkrip disalin."})}catch(C){h({tone:"err",text:Q("menyalin transkrip",C)})}}d.useEffect(()=>{if(e.transcriptBytes===null){g("none"),u(null);return}let j=!0;return g("loading"),F.sessionTranscript(e.id).then(C=>{j&&(u(C.text),g("idle"))}).catch(()=>{j&&(u(null),g("error"))}),()=>{j=!1}},[e.id,e.transcriptBytes]);const p=It(e)==="interrupted",b=[["Project",n],["Sesi",e.sessionId],["Jenis",Ia(e.kind)],["Agen",[e.agent,e.model,e.effort].filter(Boolean).join(" · ")],["Mulai",new Date(e.startedAt).toLocaleString("id-ID")],[p?"Terakhir terlihat hidup":"Selesai",e.endedAt?new Date(e.endedAt).toLocaleString("id-ID"):"berjalan"],...p&&e.reconciledAt?[["Terdeteksi mati",new Date(e.reconciledAt).toLocaleString("id-ID")]]:[],["Durasi",Na(e)],["Direktori",e.cwd]];return e.specId&&b.splice(1,0,["Backlog",`${e.specId}${e.title?` · ${e.title}`:""}`]),e.branch&&b.push(["Branch",e.branch]),a.jsxs(te,{open:!0,title:e.title??e.specId??e.sessionId,icon:"history",onClose:s,width:1e3,children:[a.jsxs("div",{className:"hn-terminal-hist-actions",children:[a.jsx(L,{size:"sm",variant:"ghost",leftIcon:"arrow-left",onClick:s,children:"Kembali"}),a.jsx("div",{className:"hn-terminal-hist-spacer"}),l&&a.jsx(L,{size:"sm",variant:"secondary",leftIcon:"copy",onClick:()=>void k(l),children:"Salin transkrip"}),jn(e.kind)&&a.jsx(L,{size:"sm",leftIcon:"play",onClick:()=>r(e),children:"Mulai lagi"})]}),p&&a.jsxs(Qe,{tone:"warn",title:"Sesi terputus — hasilnya tak diketahui",className:"hn-terminal-notice",children:["Panenya sudah lenyap saat hanoman menyala lagi (reboot, ",a.jsx("code",{children:"tmux kill-server"}),", atau host mati), jadi sesi ini tak meninggalkan exit code dan transkripnya kemungkinan besar tak sempat diambil — capture berjalan tepat sebelum pane dibunuh, dan di jalur ini sudah tak ada pane untuk dibaca. Periksa worktree & branch sesi ini sebelum menganggapnya selesai, lalu mulai lagi bila pekerjaannya belum tuntas."]}),a.jsx("div",{className:"hn-terminal-hist-meta",children:b.map(([j,C])=>a.jsxs(d.Fragment,{children:[a.jsx("span",{className:"hn-terminal-hist-key",children:j}),a.jsx("span",{className:"hn-terminal-hist-val",children:C})]},j))}),x==="loading"&&a.jsx("div",{className:"hn-terminal-hist-note",children:"memuat transkrip…"}),x==="none"&&a.jsx("div",{className:"hn-terminal-hist-note",children:p?"Tanpa transkrip — panenya sudah lenyap sebelum hanoman sempat mengambilnya.":"Tanpa transkrip — sesi ini ditutup sebelum fitur riwayat ada, atau panenya tak menyisakan keluaran."}),N&&a.jsx("div",{role:"status",className:N.tone==="err"?"hn-terminal-hist-copy is-err":"hn-terminal-hist-copy",children:N.text}),x==="error"&&a.jsx("div",{className:"hn-terminal-hist-error",children:"Transkrip tak terbaca lagi di server."}),l!==null&&a.jsx("pre",{className:"hn-terminal-hist-pre",children:l})]})}function oi({open:e,projectId:n,projectName:s,projects:r,onProjectChange:l,onClose:u,onCreated:x}){var w;const[g,N]=d.useState("claude"),[h,k]=d.useState("sonnet"),[p,b]=d.useState("medium"),[j,C]=d.useState({claude:{model:"sonnet",effort:"medium"},codex:{...aa},antigravity:{...ta}}),[E,A]=d.useState(!1),[R,y]=d.useState(null),[f,M]=d.useState(null),[K,W]=d.useState(null);d.useEffect(()=>{e&&(y(null),M(null),F.getSettings().then(o=>{const T={claude:{model:o.model,effort:o.effort},codex:{...aa,...o.codex??{}},antigravity:{...ta,...o.antigravity??{}}},V=o.agent??"claude",O=na(T,V);C(T),N(V),k(O.model),b(O.effort)}).catch(o=>{y(`${Q("memuat pengaturan",o)} · memakai default bawaan`)}),F.getCodexVersion().then(o=>W(o.version)).catch(o=>{y(T=>(T?`${T} · `:"")+Q("membaca versi Codex CLI",o))}))},[e]);const v=o=>{N(o);const T=na(j,o);k(T.model),b(T.effort)},I=o=>{k(o),b(T=>Rn(g,o,T))};async function D(){A(!0),M(null);try{const{id:o}=await F.createTerminal(n,{agent:g,model:h,effort:p});x(o),u()}catch(o){M(Q("membuka sesi",o))}finally{A(!1)}}return a.jsxs(te,{open:e,onClose:u,icon:"plus",eyebrow:s,title:"Sesi baru",footer:a.jsxs(a.Fragment,{children:[a.jsx(L,{variant:"ghost",onClick:u,children:"Batal"}),a.jsx(L,{leftIcon:"play",disabled:E,onClick:()=>void D(),children:"Buka sesi"})]}),children:[R&&a.jsx(Qe,{tone:"warn",title:"Pengaturan belum terbaca",className:"hn-terminal-notice",children:R}),f&&a.jsx(Qe,{tone:"err",title:"Sesi belum terbuka",className:"hn-terminal-notice",children:f}),a.jsxs("div",{className:"hn-terminal-intro",children:["Runtime untuk sesi ini. Default dari setelan global; ubah bila perlu. Sesi lahir dengan pilihan ini untuk seluruh hidupnya — ",a.jsx("code",{children:"/model"})," di terminal tetap bisa mengubahnya."]}),r&&l&&r.length>1&&a.jsx(we,{label:"Project",hint:"Direktori repo tempat sesi dibuka.",children:a.jsx(ee,{"aria-label":"Project",value:n,className:"hn-terminal-field-full",options:r.map(o=>({value:o.id,label:o.name})),onChange:o=>l(o.target.value)})}),a.jsx(we,{label:"Agen",hint:"Mesin yang menjalankan sesi ini. Perilaku sesi sama; hanya CLI-nya berbeda.",children:a.jsx(ee,{"aria-label":"Agen",value:g,className:"hn-terminal-field-full",options:wn,onChange:o=>v(o.target.value)})}),a.jsx(we,{label:"Model",children:a.jsx(ee,{"aria-label":"Model",value:h,className:"hn-terminal-field-full",options:Sn(g,h),onChange:o=>I(o.target.value)})}),a.jsx(we,{label:"Effort",children:a.jsx(ee,{"aria-label":"Effort",value:p,className:"hn-terminal-field-full",options:Nn(g,h).map(o=>({value:o,label:o})),onChange:o=>b(o.target.value)})}),g==="antigravity"&&a.jsx(ai,{}),g==="codex"&&In(h,K)&&a.jsxs("div",{"data-testid":"codex-version-note",className:"hn-terminal-codex-note",children:["Codex CLI terpasang ",a.jsx("b",{children:K}),", sedangkan ",a.jsx("b",{children:h})," butuh ",a.jsx("b",{children:(w=Cn(h))==null?void 0:w.minClient}),". Sesi tetap boleh dijalankan, tapi modelnya belum tentu dikenali CLI ini."]})]})}function ci({projectId:e,projects:n,onProjectChange:s,onClose:r,onConfirm:l}){return a.jsx(te,{open:!0,onClose:r,icon:"terminal",title:"Terminal biasa",footer:a.jsxs(a.Fragment,{children:[a.jsx(L,{variant:"ghost",onClick:r,children:"Batal"}),a.jsx(L,{leftIcon:"play",disabled:!e,onClick:()=>l(e),children:"Buka terminal"})]}),children:a.jsx(we,{label:"Project",hint:"Shell dibuka di direktori repo project ini.",children:a.jsx(ee,{"aria-label":"Project",value:e,className:"hn-terminal-field-full",options:n.map(u=>({value:u.id,label:u.name})),onChange:u=>s(u.target.value)})})})}const Ca=()=>({rows:1,cols:1,cells:[null]}),Ra=(e,n)=>[...e.slice(0,n),...e.slice(n+1)],oa=e=>({...e,rows:e.rows+1,cells:[...e.cells,...Array(e.cols).fill(null)],...e.rowSizes?{rowSizes:[...e.rowSizes,1]}:{}});function ca(e){const n=e.cols+1,s=[];for(let r=0;r<e.rows;r++)for(let l=0;l<n;l++)s.push(l<e.cols?e.cells[r*e.cols+l]??null:null);return{...e,cols:n,cells:s,...e.colSizes?{colSizes:[...e.colSizes,1]}:{}}}function ua(e,n){if(e.rows===1||n<0||n>=e.rows)return e;const s=[...e.cells];return s.splice(n*e.cols,e.cols),{...e,rows:e.rows-1,cells:s,...e.rowSizes?{rowSizes:Ra(e.rowSizes,n)}:{}}}function da(e,n){if(e.cols===1||n<0||n>=e.cols)return e;const s=e.cols-1,r=[];for(let l=0;l<e.rows;l++)for(let u=0;u<e.cols;u++)u!==n&&r.push(e.cells[l*e.cols+u]??null);return{...e,cols:s,cells:r,...e.colSizes?{colSizes:Ra(e.colSizes,n)}:{}}}const Ta=.3,ui=(e,n,s)=>Math.min(s,Math.max(n,e));function Ct(e,n,s){if(n<0||n+1>=e.length||s===0)return e;const l=e.reduce((N,h)=>N+h,0)/e.length*Ta,u=e[n]+e[n+1],x=ui(e[n]+s,l,u-l);if(x===e[n])return e;const g=[...e];return g[n]=x,g[n+1]=u-x,g}function Ea(e,n,s){const r=e.colSizes??Array(e.cols).fill(1),l=Ct(r,n,s);return l===r?e:{...e,colSizes:l}}function Aa(e,n,s){const r=e.rowSizes??Array(e.rows).fill(1),l=Ct(r,n,s);return l===r?e:{...e,rowSizes:l}}const di=.05,mi=.15,za=(e,n)=>e.reduce((s,r)=>s+r,0)*(n?mi:di);function hi(e,n,s,r=!1){const l=e.colSizes??Array(e.cols).fill(1);return Ea(e,n,s*za(l,r))}function pi(e,n,s,r=!1){const l=e.rowSizes??Array(e.rows).fill(1);return Aa(e,n,s*za(l,r))}function ma(e,n){const r=e.reduce((x,g)=>x+g,0)/e.length*Ta,l=e[n]+e[n+1],u=Math.round(r/l*100);return{now:Math.round(e[n]/l*100),min:u,max:100-u}}function jt(e,n,s){if(n<0||n>=e.cells.length)return e;const r=e.cells.map(l=>s!==null&&l===s?null:l);return r[n]=s,{...e,cells:r}}const fi=(e,n)=>({...e,cells:e.cells.map(s=>s&&n.has(s)?s:null)}),Da=e=>({id:crypto.randomUUID(),name:e,layout:Ca()});function ha(){const e=Da("Utama");return{groups:[e],active:e.id}}const $e=e=>e.groups.find(n=>n.id===e.active)??e.groups[0];function gi(e,n){const s=Da(n);return{groups:[...e.groups,s],active:s.id}}const bi=(e,n,s)=>({...e,groups:e.groups.map(r=>r.id===n?{...r,name:s}:r)});function ki(e,n){if(e.groups.length===1)return e;const s=e.groups.filter(r=>r.id!==n);return s.length===e.groups.length?e:{groups:s,active:e.active===n?s[0].id:e.active}}const xi=(e,n)=>e.groups.some(s=>s.id===n)?{...e,active:n}:e;function H(e,n){const s=$e(e);return{...e,groups:e.groups.map(r=>r.id===s.id?{...r,layout:n(r.layout)}:r)}}function wt(e,n,s){const r=$e(e),l=s===null?e.groups:e.groups.map(u=>u.id===r.id?u:{...u,layout:jt(u.layout,u.layout.cells.indexOf(s),null)});return{...e,groups:l.map(u=>u.id===r.id?{...u,layout:jt(u.layout,n,s)}:u)}}function je(e,n){const s=$e(e).layout.cells.indexOf(null);return s===-1?e:wt(e,s,n)}const vi=(e,n)=>({...e,groups:e.groups.map(s=>({...s,layout:jt(s.layout,s.layout.cells.indexOf(n),null)}))}),pa=e=>new Set(e.groups.flatMap(n=>n.layout.cells.filter(s=>s!==null))),fa=(e,n)=>({...e,groups:e.groups.map(s=>({...s,layout:fi(s.layout,n)}))}),Ma="hanoman.terminal.workspace",Fa="hanoman.terminal.layout",Se=e=>Fe.parse({version:1,groups:e.groups});function Ze(e,n){const s=e.groups,r=n&&s.some(l=>l.id===n)?n:s[0].id;return{groups:s,active:r}}function yi(e){try{const n=JSON.parse(e);if(!n||typeof n!="object")return null;const s=n,r=Fe.parse({version:1,groups:s.groups});return{workspace:r,active:typeof s.active=="string"&&r.groups.some(l=>l.id===s.active)?s.active:r.groups[0].id}}catch{return null}}function ji(){try{const e=localStorage.getItem(Ma);if(e)return yi(e);const n=localStorage.getItem(Fa);if(!n)return null;const s=JSON.parse(n),r={id:crypto.randomUUID(),name:"Utama",layout:s};return{workspace:Fe.parse({version:1,groups:[r]}),active:r.id}}catch{return null}}function bt(){try{localStorage.removeItem(Ma),localStorage.removeItem(Fa)}catch{}}const $a=e=>`hanoman.terminal.workspace.v2.${encodeURIComponent(e)}`;function wi(e){try{const n=localStorage.getItem($a(e));if(!n)return null;const s=JSON.parse(n),r=Fe.parse(s.workspace);if(!Number.isInteger(s.revision)||(s.revision??-1)<0)return null;const l=typeof s.active=="string"&&r.groups.some(u=>u.id===s.active)?s.active:r.groups[0].id;return{workspace:r,revision:s.revision,active:l}}catch{return null}}function kt(e,n){try{const s=Fe.parse(n.workspace);if(!Number.isInteger(n.revision)||n.revision<0)return;const r=s.groups.some(l=>l.id===n.active)?n.active:s.groups[0].id;localStorage.setItem($a(e),JSON.stringify({workspace:s,revision:n.revision,active:r}))}catch{}}function xt(e){if(!(e instanceof Me)||e.status!==409)return null;const n=e.detail;if((n==null?void 0:n.code)!=="revision-conflict")return null;const s=Tn.safeParse(n.current);return s.success?s.data:null}function Si(e){const n=P.useRef(null);n.current||(n.current=ha());const[s,r]=P.useState(n.current),[l,u]=P.useState("loading"),[x,g]=P.useState(null),[N,h]=P.useState(!1),k=P.useRef(s),p=P.useRef(0),b=P.useRef(!1),j=P.useRef(Promise.resolve()),C=P.useRef(0),E=P.useCallback(v=>{k.current=v,r(v)},[]),A=P.useCallback(v=>{b.current=v,h(v)},[]),R=P.useCallback(v=>{const I=j.current.then(v,v);return j.current=I.then(()=>{},()=>{}),I},[]),y=P.useCallback((v,I="ready",D=null,w=k.current.active)=>{const o=v.workspace?Ze(v.workspace,w):ha();p.current=v.revision,E(o),u(I),g(D),A(!0),v.workspace&&kt(e,{workspace:v.workspace,revision:v.revision,active:o.active})},[E,A,e]),f=P.useCallback(v=>{const I=wi(e);I&&(p.current=I.revision,E(Ze(I.workspace,I.active))),A(!1),u("recovering"),g(v instanceof Error?v.message:"Layout server belum tersambung")},[E,A,e]),M=P.useCallback(()=>R(async()=>{try{y(await F.getTerminalWorkspace())}catch(v){f(v)}}),[y,R,f]);P.useEffect(()=>{const v=++C.current;return u("loading"),g(null),A(!1),R(async()=>{try{const I=await F.getTerminalWorkspace();if(v!==C.current)return;if(I.workspace){y(I),bt();return}const D=ji();if(!D){y(I);return}try{const w=await F.putTerminalWorkspace({baseRevision:I.revision,workspace:D.workspace});if(v!==C.current)return;E(Ze(w.workspace,D.active)),p.current=w.revision,kt(e,{workspace:w.workspace,revision:w.revision,active:D.active}),bt(),u("ready"),g(null),A(!0)}catch(w){const o=xt(w);o!=null&&o.workspace?(y(o,"conflict","Layout server lebih baru; layout lokal lama tidak diunggah"),bt()):f(w)}}catch(I){v===C.current&&f(I)}}),()=>{C.current+=1}},[y,R,f,E,A,e]),P.useEffect(()=>{const v=()=>{M()},I=()=>{document.visibilityState==="visible"&&M()};return window.addEventListener("focus",v),document.addEventListener("visibilitychange",I),()=>{window.removeEventListener("focus",v),document.removeEventListener("visibilitychange",I)}},[M]);const K=P.useCallback(v=>R(async()=>{if(!b.current)return!1;const I=v(k.current);let D,w;try{D=Se(I),w=Se(k.current)}catch{return u("conflict"),g("Layout tidak valid dan tidak disimpan"),!1}if(wa(D,w))return!0;try{return y(await F.putTerminalWorkspace({baseRevision:p.current,workspace:D}),"ready",null,I.active),!0}catch(o){const T=xt(o);if(!(T!=null&&T.workspace))return f(o),!1;const V=v(Ze(T.workspace,k.current.active));try{const O=await F.putTerminalWorkspace({baseRevision:T.revision,workspace:Se(V)});return y(O,"conflict","Layout berubah di perangkat lain; perubahan ini diterapkan ulang",V.active),!0}catch(O){if(!xt(O)&&!(O instanceof Me&&O.status===409))return f(O),!1;try{y(await F.getTerminalWorkspace(),"conflict","Layout berubah lagi di perangkat lain; state terbaru dimuat")}catch(ue){f(ue)}return!1}}}),[y,R,f]),W=P.useCallback(v=>{const I=xi(k.current,v);E(I);const D=Se(I);kt(e,{workspace:D,revision:p.current,active:I.active})},[E,e]);return{workspace:s,status:l,message:x,writable:N,mutate:K,setActive:W,refresh:M}}const Ni=En("focus","grid"),ga={attention:0,running:1,open:1,failed:2,done:3};function Pa(e,n){return e.exited?e.exitCode?{tone:"failed",label:`Gagal · exit ${e.exitCode}`}:{tone:"done",label:"Selesai"}:n?{tone:"done",label:"Selesai"}:e.deciding?{tone:"attention",label:"Lead memutuskan"}:e.decision?{tone:"attention",label:"Menunggu keputusan"}:e.specId?{tone:"running",label:"Berjalan"}:{tone:"open",label:"Terbuka"}}function Ii(e){const n=e.startedAt;return typeof n=="number"&&Number.isFinite(n)&&n>0?n*1e3:null}function Ci(e,n){const s=e.map((r,l)=>({session:r,index:l,rank:ga[Pa(r,n.has(r.id)).tone]}));return s.sort((r,l)=>{if(r.rank!==l.rank)return r.rank-l.rank;if(r.rank===ga.attention){const u=r.session.decisionAt?Date.parse(r.session.decisionAt):Number.NaN,x=l.session.decisionAt?Date.parse(l.session.decisionAt):Number.NaN,g=Number.isNaN(u)?Number.POSITIVE_INFINITY:u,N=Number.isNaN(x)?Number.POSITIVE_INFINITY:x;if(g!==N)return g<N?-1:1}return r.index-l.index}),s.map(r=>r.session)}function Ri(e){const n=new Map;for(const s of e){const r=n.get(s.projectId);r?r.push(s):n.set(s.projectId,[s])}return[...n.values()].flat()}function Ti(e,n){if(n){const s=e.find(r=>r.id===n);if(s)return s}return e[0]??null}function Ei(e,n,s){if(s<=0)return null;const r=e<0?0:e;switch(n){case"ArrowDown":return Math.min(r+1,s-1);case"ArrowUp":return Math.max(r-1,0);case"Home":return 0;case"End":return s-1;default:return null}}const La={attention:"awaiting",running:"running",open:"idle",failed:"failed",done:"done"};function Ai(e){const[n,s]=d.useState(()=>Date.now());return d.useEffect(()=>{const r=setInterval(()=>s(Date.now()),e);return()=>clearInterval(r)},[e]),n}function ba({items:e,focusedId:n,onFocus:s,menuFor:r,label:l="Daftar sesi"}){const u=Ai(3e4),x=d.useRef([]),g=new Set(e.map(k=>k.session.projectId)).size>1,N=e.findIndex(k=>k.session.id===n),h=k=>{var C;const p=x.current.indexOf(k.target);if(p<0)return;const b=Ei(p,k.key,e.length);if(b===null)return;k.preventDefault();const j=e[b];j&&(s(j.session.id),(C=x.current[b])==null||C.focus())};return a.jsx("ul",{role:"list","aria-label":l,className:"hn-terminal-rail-list",onKeyDown:h,children:e.map((k,p)=>{var R;const{session:b,status:j}=k,C=b.id===n,E=C||N<0&&p===0,A=k.startedMs!==null?An(k.startedMs,u):"";return a.jsxs(d.Fragment,{children:[g&&k.session.projectId!==((R=e[p-1])==null?void 0:R.session.projectId)&&a.jsx("li",{role:"presentation",className:"hn-terminal-rail-group",children:k.projectName}),a.jsx("li",{className:"hn-terminal-rail-item",children:a.jsxs("div",{className:`hn-terminal-rail-row${C?" is-focused":""}`,"data-tone":j.tone,children:[a.jsxs("button",{type:"button",className:"hn-terminal-rail-main",ref:y=>{x.current[p]=y},tabIndex:E?0:-1,"aria-current":C?"true":void 0,title:k.label,onClick:()=>s(b.id),children:[a.jsx("span",{className:"hn-terminal-rail-name",children:k.label}),a.jsxs("span",{className:"hn-terminal-rail-meta",children:[a.jsx(ge,{status:La[j.tone],variant:"dot",size:"sm",children:j.label}),A&&a.jsx("span",{className:"hn-terminal-rail-time",children:A})]})]}),a.jsx(Ne,{label:`Aksi sesi ${b.id} di daftar`,items:r(b)})]})})]},b.id)})})}const zi=[],Di=e=>!!(e.binding??e.repoDir),Mi=e=>{var n;return((n=e.find(Di)??e[0])==null?void 0:n.id)??""},Fi=e=>e instanceof Me&&e.status===400&&typeof e.detail=="object"&&e.detail!==null&&e.detail.needsBind===!0;function Xi({userId:e="test-user",projects:n,backlog:s=zi,focusSession:r,startedSession:l,onStartedSessionHandled:u,onStartBacklog:x,onOpenReview:g,onOpenSessionReview:N,titleOf:h,onIntegrate:k,onIntegrateSession:p,specOf:b,sessions:j,setSessions:C,onOpenProject:E}){const[A,R]=d.useState([]),y=j??A,f=C??R,[M,K]=d.useState([]),W=Si(e),{workspace:v,status:I,message:D,writable:w,mutate:o,setActive:T,refresh:V}=W,[O,ue]=fe("terminal","project",Mi(n),Qn),Ie=Sa(),ke=Fn(),re=ke==="mobile",[J,de]=fe("terminal","fontSize",Ie?Yn:Jn,Vn),[le,Pe]=fe("terminal","keys",Ie&&!re,Je),[q,xe]=fe("terminal","predict",!0,Je),[ae,Le]=fe("terminal","diag",!1,Je),[ne,Ka]=fe("terminal","sr",!1,Je),Tt=t=>de(i=>Hn(i+t)),[me,Et]=d.useState(!1),[ie,et]=d.useState(null),[_a,Oe]=d.useState(!1),[Ga,Be]=d.useState(null),[Wa,At]=d.useState(!1),[qa,tt]=d.useState(!1),[Ua,Ke]=d.useState(!1),[Ha,at]=fe("terminal","view","focus",Ni),U=Ha==="focus",[nt,Ce]=d.useState(null),[it,Va]=d.useState(()=>new Set),[Ya,Ja]=d.useState(null),[zt,Dt]=d.useState(!1),[Xa,Mt]=d.useState(!1),[he,Re]=d.useState(null),[_e,Ft]=d.useState(!1),[Ge,$t]=d.useState(null),st=$n(),{confirm:Za,dialog:Qa}=Pn(),z=$e(v).layout,rt=z.rows===1&&z.cols===1&&!z.cells[0]&&y.length===0,lt=d.useRef(null),[en,tn]=d.useState(Number.POSITIVE_INFINITY);d.useEffect(()=>{const t=lt.current;if(!t||typeof ResizeObserver!="function")return;const i=new ResizeObserver(c=>{var S;const m=((S=c[0])==null?void 0:S.contentRect.width)??t.getBoundingClientRect().width;m>0&&tn(m)});return i.observe(t),()=>i.disconnect()},[rt]);const an=ke==="tablet"&&Ln(z.cols,en,Un),B=re||an,[X,We]=d.useState(0),[se,qe]=d.useState(null),ot=d.useRef(null),Te=t=>{Ce(t),qe(t)},nn=d.useCallback((t,i)=>{Va(c=>{if(c.has(t)===i)return c;const m=new Set(c);return i?m.add(t):m.delete(t),m})},[]),Pt=d.useMemo(()=>Ri(Ci(y,it)),[y,it]),Ue=Ti(Pt,nt),He=(Ue==null?void 0:Ue.id)??null;d.useEffect(()=>{He&&He!==nt&&Ce(He)},[He,nt]);const[ve,sn]=d.useState(!1),[Ve,Lt]=d.useState(null),[rn,ln]=d.useState(0);d.useEffect(()=>{let t=!0;return F.listTerminals().then(i=>{t&&(Lt(null),f(i),sn(!0))}).catch(i=>{t&&Lt(Q("memuat daftar sesi",i))}),()=>{t=!1}},[rn]);const[on,oe]=On();d.useEffect(()=>Bn(t=>{t.t==="sessions"&&!j?f(t.sessions):t.t==="cleanups"&&K(t.cleanups)}),[]),d.useEffect(()=>{if(!ve||!w)return;const t=new Set(y.map(c=>c.id)),i=fa(v,t);wa(Se(i),Se(v))||o(c=>fa(c,t))},[o,y,ve,w,v]),d.useEffect(()=>{!l||l.specId==null||!ve||(f(t=>t.some(i=>i.id===l.id)?t:[...t,{...l,cwd:"",exited:!1}]),Ce(l.id),qe(l.id),u==null||u())},[u,ve,l]);const ct=d.useRef(null);d.useEffect(()=>{if(!r){ot.current=null,ct.current=null;return}if(!(!ve||ot.current===r)){if(!y.some(t=>t.id===r&&!t.exited)){if(ct.current===r)return;ct.current=r,F.listSessionHistory({q:r,limit:1}).then(t=>oe(ia,"warn","history",t.total>0?{action:{label:Kn,onAction:()=>Ke(!0)},duration:7e3}:void 0)).catch(()=>{oe(ia,"warn","history")});return}ot.current=r,Ce(r),qe(r)}},[r,y,ve,oe]),d.useEffect(()=>{if(!se)return;const t=v.groups.find(i=>i.layout.cells.includes(se));if(t){t.id!==v.active&&T(t.id);return}w&&o(i=>{if(pa(i).has(se))return i;const c=je(i,se);return c!==i||!B?c:wt(i,X,se)})},[X,B,o,se,T,w,v]),d.useEffect(()=>{ie&&!y.some(t=>t.id===ie)&&et(null)},[ie,y]);const ut=M.filter(t=>t.error),Z=t=>y.find(i=>i.id===t)??null,Y=d.useCallback(t=>{var i;return((i=n.find(c=>c.id===t))==null?void 0:i.name)??t},[n]);function cn(t){f(i=>i.some(c=>c.id===t)?i:[...i,{id:t,projectId:O,cwd:"",exited:!1}]),o(i=>je(i,t)),Te(t)}async function Ot(t){if(!t)return;tt(!1);let i;try{({id:i}=await F.createShell(t))}catch(c){Fi(c)?oe(`Project ${Y(t)} belum terhubung ke folder repo — hubungkan dulu.`,"err","folder-git-2",E?{action:{label:"Buka project",onAction:()=>E(t)}}:void 0):oe(Q("membuka terminal biasa",c),"err","x-circle");return}f(c=>[...c,{id:i,projectId:t,cwd:"",exited:!1}]),o(c=>je(c,i)),Te(i)}async function Bt(t,i){if(x&&!i){Oe(!1),Be(null),x(t);return}const c=Zn(t.source);try{const{id:m}=await F.startSession({spec:t.id,flow:c,...i?{force:i}:{}});f(S=>S.some($=>$.id===m)?S:[...S,{id:m,projectId:t.projectId,specId:t.id,flow:c,cwd:"",exited:!1}]),o(S=>je(S,m)),Te(m),Oe(!1),Be(null)}catch(m){if(st.offerRetry(m,t.id,$=>Bt(t,$)))return;const S=m instanceof Me&&(m.status===400||m.status===422);Be(`${t.id} · gagal mulai${S?" · project belum punya repoDir":""}`)}}async function Kt(t,i){try{const c=t.specId?await F.startSession({spec:t.specId,flow:t.flow??"feature",agent:t.agent==="antigravity"?"antigravity":t.agent==="codex"?"codex":"claude",...t.model?{model:t.model}:{},...t.effort?{effort:t.effort}:{},...i?{force:i}:{}}):t.kind==="shell"?await F.createShell(t.projectId):t.kind==="terminal"?await F.createTerminal(t.projectId,{agent:t.agent==="antigravity"?"antigravity":t.agent==="codex"?"codex":"claude",...t.model?{model:t.model}:{},...t.effort?{effort:t.effort}:{}}):await(i?F.createTerminalFlow(t.projectId,t.kind,{force:i}):F.createTerminalFlow(t.projectId,t.kind));f(m=>m.some(S=>S.id===c.id)?m:[...m,{id:c.id,projectId:t.projectId,specId:t.specId??void 0,cwd:"",exited:!1}]),o(m=>je(m,c.id)),Te(c.id),Ke(!1)}catch(c){if((t.specId||t.kind!=="shell"&&t.kind!=="terminal")&&st.offerRetry(c,`${t.projectId} · ${t.title??t.specId??t.kind}`,m=>Kt(t,m)))return}}const _t=new Set(y.filter(t=>t.specId&&!t.exited).map(t=>t.specId)),un=s.filter(t=>t.stage!=="done"&&!_t.has(t.id));function Gt(t){f(i=>i.filter(c=>c.id!==t)),F.deleteTerminal(t).catch(i=>{i instanceof Me&&i.status===404||oe(Q(`menutup sesi ${t.slice(0,6)}`,i),"err","x-circle")})}async function Wt(){if(!he||_e)return;const{id:t,value:i}=he;Ft(!0);try{const c=await F.renameTerminal(t,i);f(m=>m.map(S=>{if(S.id!==t)return S;const{name:$,...G}=S;return c.name?{...G,name:c.name}:G})),Re(null),oe(c.name?"Nama sesi disimpan":"Nama kustom dihapus","ok")}catch(c){oe(Q("mengganti nama sesi",c),"err","x-circle")}finally{Ft(!1)}}async function dt(t){const i=Z(t),c=`${i?be(i,Y,h):t} · ${t.slice(0,6)}`,m=!!i&&!i.exited;await Za({title:`Tutup sesi "${c}"?`,impact:[m?"Agen yang sedang berjalan di sesi ini akan dihentikan.":"Sesi ini sudah berhenti, jadi tidak ada agen yang perlu dihentikan.","Worktree sesi ini ikut dibersihkan dari disk."],confirmLabel:"Tutup sesi",icon:"square",tone:"danger"})&&Gt(t)}const dn=d.useCallback((t,i)=>{f(c=>c.map(m=>m.id===t?{...m,exited:!0,exitCode:i}:m))},[]),qt={killSession:Gt,requestKill:dt,detach:t=>{o(i=>vi(i,t))},markExited:dn,setFullId:et,openDialog:(t,i)=>$t({kind:t,sessionId:i}),openRename:t=>{var i;return Re({id:t,value:((i=Z(t))==null?void 0:i.name)??""})},props:{onOpenReview:g,onOpenSessionReview:N,titleOf:h,onIntegrate:k,onIntegrateSession:p,specOf:b}},_=d.useRef(qt);_.current=qt;const Ut=d.useRef(new Map),pe=t=>{let i=Ut.current.get(t);return i||(i={onClose:()=>void _.current.requestKill(t),onForget:()=>_.current.killSession(t),onDetach:()=>_.current.detach(t),onExit:c=>_.current.markExited(t,c),onFullscreen:()=>_.current.setFullId(t),onDialog:c=>_.current.openDialog(c,t),onRename:()=>_.current.openRename(t)},Ut.current.set(t,i)),i},Ht=d.useRef(new Map),mn=t=>{let i=Ht.current.get(t);return i||(i=(c,m)=>{Ja({sessionId:t,phases:c}),nn(t,m)},Ht.current.set(t,i)),i},hn=t=>Ba(t,{label:be(t,Y,h),canArrange:w,specOf:b,onReview:g,onSessionReview:N,onIntegrate:k,onIntegrateSession:p,onDialog:pe(t.id).onDialog,onDetach:pe(t.id).onDetach,onFullscreen:pe(t.id).onFullscreen,onKill:()=>void dt(t.id),onRename:pe(t.id).onRename}),ye=d.useRef({onOpenReview:t=>{var i,c;return(c=(i=_.current.props).onOpenReview)==null?void 0:c.call(i,t)},onOpenSessionReview:(t,i)=>{var c,m;return(m=(c=_.current.props).onOpenSessionReview)==null?void 0:m.call(c,t,i)},titleOf:t=>{var i,c;return(c=(i=_.current.props).titleOf)==null?void 0:c.call(i,t)},onIntegrate:(t,i,c)=>{var m,S;return(S=(m=_.current.props).onIntegrate)==null?void 0:S.call(m,t,i,c)},onIntegrateSession:(t,i,c)=>{var m,S;return(S=(m=_.current.props).onIntegrateSession)==null?void 0:S.call(m,t,i,c)},specOf:t=>{var i,c;return(c=(i=_.current.props).specOf)==null?void 0:c.call(i,t)}}).current,pn=(t,i)=>{We(t),o(c=>wt(c,t,i))},fn=t=>{Te(t),o(i=>je(i,t))},gn=pa(v),mt=y.filter(t=>!gn.has(t.id));d.useEffect(()=>{if(!se)return;const t=z.cells.indexOf(se);t<0||(We(t),qe(null))},[z.cells,se]),d.useEffect(()=>{X>=z.cells.length&&We(Math.max(0,z.cells.length-1))},[X,z.cells.length]);const Ye=d.useRef(null),[ce,ht]=d.useState(null),pt=(ce==null?void 0:ce.axis)==="col"?ce.sizes:z.colSizes??Array(z.cols).fill(1),ft=(ce==null?void 0:ce.axis)==="row"?ce.sizes:z.rowSizes??Array(z.rows).fill(1);function Vt(t,i,c){var $,G,Ee;if(!w)return;const m=($=lt.current)==null?void 0:$.getBoundingClientRect();if(!m)return;(Ee=(G=c.currentTarget).setPointerCapture)==null||Ee.call(G,c.pointerId);const S=t==="col"?pt:ft;Ye.current={axis:t,index:i,pointerId:c.pointerId,start:t==="col"?c.clientX:c.clientY,extent:t==="col"?m.width:m.height,startSizes:S,latest:S},ht({axis:t,sizes:S})}function Yt(t){const i=Ye.current;if(!i||i.pointerId!==t.pointerId)return;const c=i.axis==="col"?t.clientX:t.clientY,m=i.startSizes.reduce(($,G)=>$+G,0),S=(c-i.start)/i.extent*m;i.latest=Ct(i.startSizes,i.index,S),ht({axis:i.axis,sizes:i.latest})}function Jt(t){var c,m;const i=Ye.current;!i||i.pointerId!==t.pointerId||(Ye.current=null,(m=(c=t.currentTarget).releasePointerCapture)==null||m.call(c,t.pointerId),ht(null),i.latest!==i.startSizes&&o(S=>H(S,$=>i.axis==="col"?{...$,colSizes:i.latest}:{...$,rowSizes:i.latest})))}function Xt(t,i,c){if(!w)return;const m=t==="col"?"ArrowRight":"ArrowDown",S=t==="col"?"ArrowLeft":"ArrowUp",$=c.key===m?1:c.key===S?-1:0;$!==0&&(c.preventDefault(),o(G=>H(G,Ee=>t==="col"?hi(Ee,i,$,c.shiftKey):pi(Ee,i,$,c.shiftKey))))}function Zt(t,i){w&&o(c=>H(c,m=>{const S=t==="col"?m.colSizes??Array(m.cols).fill(1):m.rowSizes??Array(m.rows).fill(1),G=(S[i]+S[i+1])/2-S[i];return t==="col"?Ea(m,i,G):Aa(m,i,G)}))}const Qt=a.jsxs("div",{className:"hn-terminal-display",children:[a.jsxs("div",{className:"hn-dense-row hn-terminal-display-row",children:[a.jsx("span",{className:"hn-terminal-display-label",children:"Ukuran teks terminal"}),a.jsx(gt,{size:"sm",icon:"minus",label:"Perkecil teks terminal",disabled:J<=_n,onClick:()=>Tt(-1)}),a.jsxs("span",{className:"hn-terminal-display-value",children:[J,"px"]}),a.jsx(gt,{size:"sm",icon:"plus",label:"Perbesar teks terminal",disabled:J>=Gn,onClick:()=>Tt(1)})]}),a.jsxs("div",{className:"hn-dense-row hn-terminal-display-row",children:[a.jsx("span",{className:"hn-terminal-display-label",children:"Papan tombol layar (Esc · panah · Enter)"}),a.jsx(L,{size:"sm",variant:"secondary","aria-pressed":le,onClick:()=>Pe(t=>!t),children:le?"Sembunyikan":"Tampilkan"})]}),a.jsxs("div",{className:"hn-dense-row hn-terminal-display-row",children:[a.jsx("span",{className:"hn-terminal-display-label",children:"Ketik responsif (huruf tampil sebelum echo server)"}),a.jsx(L,{size:"sm",variant:"secondary","aria-pressed":q,"aria-label":`${q?"Matikan":"Nyalakan"} ketik responsif`,onClick:()=>xe(t=>!t),children:q?"Matikan":"Nyalakan"})]}),a.jsxs("div",{className:"hn-dense-row hn-terminal-display-row",children:[a.jsx("span",{id:"terminal-sr-label",className:"hn-terminal-display-label",children:"Mode pembaca layar"}),a.jsx(L,{size:"sm",variant:"secondary","aria-pressed":ne,"aria-describedby":"terminal-sr-hint","aria-label":`${ne?"Matikan":"Nyalakan"} mode pembaca layar`,onClick:()=>Ka(t=>!t),children:ne?"Matikan":"Nyalakan"})]}),a.jsx("p",{id:"terminal-sr-hint",className:"hn-terminal-sr-hint",children:"Untuk pembaca layar: teks terminal tersedia di DOM; kecepatan lebih rendah. Tab dikirim ke sesi (tidak memindahkan fokus). Untuk keluar dari terminal tekan Ctrl+Shift+Esc."}),!U&&a.jsxs("div",{className:"hn-dense-row hn-terminal-display-row",children:[a.jsx("span",{id:"terminal-reset-grid-hint",className:"hn-terminal-display-label",children:'Kembalikan grid ke 1 kolom × 1 baris (sesi lain pindah ke "belum di grid")'}),a.jsx(L,{size:"sm",variant:"secondary","aria-describedby":"terminal-reset-grid-hint",disabled:!w||z.cols===1&&z.rows===1,onClick:()=>void o(t=>H(t,()=>Ca())),children:"Reset grid"})]}),a.jsxs("details",{className:"hn-terminal-diag",children:[a.jsxs("summary",{className:"hn-terminal-diag-summary",children:["Diagnostik",ae?" · perekaman aktif":""]}),a.jsxs("div",{className:"hn-dense-row hn-terminal-display-row hn-terminal-diag-row",children:[a.jsx("span",{className:"hn-terminal-display-label",children:"Rekam jalur ketik — mencatat setiap tombol yang ditekan di pane. Nyalakan hanya saat menyelidiki masalah ketik."}),a.jsx(L,{size:"sm",variant:"secondary","aria-pressed":ae,"aria-label":`${ae?"Matikan":"Nyalakan"} rekam jalur ketik`,onClick:()=>Le(t=>!t),children:ae?"Matikan":"Nyalakan"})]})]})]}),ea=[{key:"backlog",label:"Ambil backlog",icon:"inbox",onSelect:()=>{Be(null),Oe(!0)}},{key:"history",label:"Riwayat sesi",icon:"history",onSelect:()=>Ke(!0)},{key:"shell",label:"Terminal biasa",icon:"terminal",onSelect:()=>n.length>1?tt(!0):void Ot(O)}],bn=[{key:"col+",label:"+ Kolom",icon:"columns-2",disabled:!w,onSelect:()=>void o(t=>H(t,ca))},{key:"row+",label:"+ Baris",icon:"rows-2",disabled:!w,onSelect:()=>void o(t=>H(t,oa))},{key:"col-",label:"Hapus kolom aktif",icon:"columns-2",disabled:!w||z.cols===1,onSelect:()=>void o(t=>H(t,i=>da(i,X%i.cols)))},{key:"row-",label:"Hapus baris aktif",icon:"rows-2",disabled:!w||z.rows===1,onSelect:()=>void o(t=>H(t,i=>ua(i,Math.floor(X/i.cols))))}],kn=[{key:"mode",label:U?"Pakai mode Grid":"Pakai mode Fokus",icon:U?"columns-2":"terminal",onSelect:()=>at(U?"grid":"focus")},{key:"full",label:me?"Keluar layar penuh":"Layar penuh",icon:me?"minimize-2":"maximize-2",onSelect:()=>Et(t=>!t)},{key:"display",label:"Tampilan terminal",icon:"sliders",onSelect:()=>Mt(!0)}];return a.jsxs("div",{"data-testid":"terminal-root",className:me?"hn-terminal-screen is-maxed":"hn-terminal-screen",children:[a.jsxs("div",{className:"hn-terminal-toolbar",role:"group","aria-label":"Terminal",children:[a.jsx(L,{size:"sm",leftIcon:"plus",title:"Pilih runtime lalu buka sesi agen di direktori project. Agen berjalan dengan izin penuh (claude --dangerously-skip-permissions).",onClick:()=>At(!0),children:"Sesi baru"}),re?a.jsxs(a.Fragment,{children:[a.jsx(ya,{compact:!0,items:ea}),U&&y.length>0&&a.jsxs("button",{type:"button",className:"hn-terminal-rail-toggle","aria-haspopup":"dialog","aria-expanded":zt,onClick:()=>Dt(!0),children:["Sesi · ",y.length]}),a.jsx(Ne,{label:"Menu terminal",title:"Terminal",items:kn})]}):a.jsxs(a.Fragment,{children:[a.jsx(ya,{items:ea}),a.jsxs("div",{className:"hn-terminal-seg",role:"group","aria-label":"Mode tampilan terminal",children:[a.jsx("button",{type:"button",className:"hn-terminal-seg-btn","aria-pressed":U,title:"Satu terminal fokus dengan daftar sesi di samping",onClick:()=>at("focus"),children:"Fokus"}),a.jsx("button",{type:"button",className:"hn-terminal-seg-btn","aria-pressed":!U,title:"Beberapa terminal sekaligus dalam grid",onClick:()=>at("grid"),children:"Grid"})]}),a.jsx(Ne,{label:"Tampilan terminal",icon:"sliders",items:[],children:Qt}),a.jsx(gt,{size:"sm",icon:me?"minimize-2":"maximize-2",label:me?"Keluar layar penuh":"Layar penuh","aria-pressed":me,onClick:()=>Et(t=>!t)})]})]}),(I!=="ready"||M.length>0)&&a.jsxs("div",{className:"hn-terminal-status",children:[I!=="ready"&&a.jsx("span",{"data-testid":"terminal-workspace-status",title:D??void 0,className:I==="conflict"?"hn-terminal-status-warn":void 0,children:I==="loading"?"Memuat layout server…":I==="recovering"?a.jsxs(a.Fragment,{children:[a.jsx("span",{children:"Layout server belum tersambung"})," ",a.jsx("button",{type:"button",onClick:()=>void V(),children:"Coba lagi"})]}):D??"Layout berubah di perangkat lain"}),M.length>0&&a.jsx("span",{"data-testid":"worktree-cleanups",title:M.map(t=>`${t.sessionId}${t.error?` — ${t.error}`:""}`).join(`
1
+ import{h as F,i as Q,j as a,M as te,f as St,g as ee,a3 as xn,a4 as ja,m as ze,n as vt,I as De,a2 as vn,Z as yn,B as L,a5 as jn,C as Qe,a6 as ta,a7 as aa,a8 as na,e as we,a9 as wn,aa as Sn,ab as Nn,ac as In,ad as Cn,ae as Rn,af as Fe,ag as wa,ah as Me,ai as Tn,r as En,a1 as An,Y as ge,O as Ne,aj as zn,ak as Dn,al as yt,am as Mn,q as fe,an as Sa,b as Fn,ao as $n,d as Pn,ap as Ln,p as On,aq as Bn,ar as ia,as as Kn,o as gt,at as _n,au as Gn,c as Wn,av as qn,aw as sa,ax as Un,ay as Hn,V as Vn,az as Yn,aA as Jn,aB as Je,aC as Nt,aD as Xn,aE as Zn,D as Qn,aF as ei,aG as ra,aH as ti}from"./index-C5P4ykKO.js";import{R as d,r as P}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import{A as ai}from"./fields-of8G961J.js";import"./xterm-3VOAfa_q.js";function It(e){return e.endedAt?e.endedReason==="reconciled"?"interrupted":e.exitCode===null||e.exitCode===0?"completed":"failed":"running"}const Xe=new Set;let Ae;function ni(e){return Xe.add(e),Ae||(Ae=setInterval(()=>{for(const n of[...Xe])n()},1e3)),()=>{Xe.delete(e),Xe.size===0&&Ae&&(clearInterval(Ae),Ae=void 0)}}const la=20;function ii(e,n){if(!n)return"—";const s=new Date(n).getTime()-new Date(e).getTime();if(!Number.isFinite(s)||s<0)return"—";const r=Math.round(s/1e3);if(r<60)return`${r} dtk`;const l=Math.round(r/60);return l<60?`${l} mnt`:`${Math.floor(l/60)} jam ${l%60} mnt`}function si(e){switch(It(e)){case"running":return{label:"berjalan",tone:"neutral"};case"interrupted":return{label:"terputus",tone:"warn"};case"failed":return{label:`exit ${e.exitCode}`,tone:"err"};default:return{label:"selesai",tone:"ok"}}}const Na=e=>It(e)==="interrupted"?"—":ii(e.startedAt,e.endedAt),Ia=e=>ja[e]??e;function ri({projects:e,onClose:n,onRestart:s}){const[r,l]=d.useState([]),[u,x]=d.useState(0),[g,N]=d.useState(1),[h,k]=d.useState(!1),[p,b]=d.useState(""),[j,C]=d.useState(""),[E,A]=d.useState(""),[R,y]=d.useState(""),[f,M]=d.useState(null),[K,W]=d.useState(null),[v,I]=d.useState(0);d.useEffect(()=>{const o=setTimeout(()=>y(E.trim()),250);return()=>clearTimeout(o)},[E]),d.useEffect(()=>{N(1)},[p,j,R]),d.useEffect(()=>{let o=!0;return k(!0),F.listSessionHistory({projectId:p||void 0,kind:j||void 0,q:R||void 0,page:g,limit:la}).then(T=>{o&&(W(null),x(T.total),l(T.items))}).catch(T=>{o&&(l([]),x(0),W(Q("memuat riwayat sesi",T)))}).finally(()=>{o&&k(!1)}),()=>{o=!1}},[p,j,R,g,v]);const D=yn(u,g,la),w=o=>{var T;return((T=e.find(V=>V.id===o))==null?void 0:T.name)??o};return a.jsxs(te,{open:!0,title:"Riwayat sesi",icon:"history",onClose:n,width:900,children:[a.jsxs("div",{className:"hn-terminal-hist-toolbar",children:[a.jsx(St,{size:"sm",leftIcon:"search",placeholder:"mis. spec-412 atau reverse","aria-label":"Cari riwayat sesi",value:E,onChange:o=>A(o.target.value),className:"hn-terminal-hist-search"}),a.jsx(ee,{size:"sm","aria-label":"Filter project",value:p,onChange:o=>b(o.target.value),options:[{value:"",label:"Semua project"}].concat(e.map(o=>({value:o.id,label:o.name})))}),a.jsx(ee,{size:"sm","aria-label":"Filter jenis",value:j,onChange:o=>C(o.target.value),options:[{value:"",label:"Semua jenis"}].concat(xn.map(o=>({value:o,label:ja[o]})))})]}),K?a.jsx(ze,{kind:"error",icon:"history",title:"Riwayat belum bisa dimuat",hint:K,action:()=>I(o=>o+1),actionLabel:"Coba lagi"}):r.length===0&&!h?a.jsx(ze,{kind:"empty",icon:"history",title:"Belum ada riwayat sesi",hint:"Riwayat terisi sendiri saat sesi terminal dibuka lalu ditutup — termasuk sesi backlog, terminal biasa, dan sesi project-level."}):a.jsxs("div",{className:"hn-terminal-hist-list",children:[r.map(o=>{const T=si(o);return a.jsx("button",{onClick:()=>M(o),className:"hn-terminal-hist-row",children:a.jsxs("span",{className:"hn-dense-row hn-picker-row hn-terminal-hist-main",children:[a.jsx("span",{className:"hn-terminal-hist-when",children:new Date(o.startedAt).toLocaleString("id-ID")}),a.jsx(vt,{size:"sm",tone:"neutral",children:Ia(o.kind)}),a.jsx("span",{className:"hn-picker-title hn-terminal-hist-title",children:o.title??o.specId??w(o.projectId)}),o.transcriptBytes!==null&&a.jsx(De,{name:"file-text",size:12,color:"var(--text-subtle)"}),a.jsx("span",{className:"hn-terminal-hist-duration",children:Na(o)}),a.jsx(vt,{size:"sm",tone:T.tone,children:T.label})]})},o.id)}),h&&a.jsx("div",{className:"hn-terminal-hist-loading",children:"memuat…"})]}),a.jsx(vn,{page:D.page,pageCount:D.pageCount,total:u,from:D.from,to:D.to,onPage:N,unit:"sesi"}),f&&a.jsx(li,{row:f,projectName:w(f.projectId),onBack:()=>M(null),onRestart:s})]})}function li({row:e,projectName:n,onBack:s,onRestart:r}){const[l,u]=d.useState(null),[x,g]=d.useState("idle"),[N,h]=d.useState(null);async function k(j){try{if(!navigator.clipboard)throw new Error("clipboard tidak tersedia di browser ini");await navigator.clipboard.writeText(j),h({tone:"ok",text:"Transkrip disalin."})}catch(C){h({tone:"err",text:Q("menyalin transkrip",C)})}}d.useEffect(()=>{if(e.transcriptBytes===null){g("none"),u(null);return}let j=!0;return g("loading"),F.sessionTranscript(e.id).then(C=>{j&&(u(C.text),g("idle"))}).catch(()=>{j&&(u(null),g("error"))}),()=>{j=!1}},[e.id,e.transcriptBytes]);const p=It(e)==="interrupted",b=[["Project",n],["Sesi",e.sessionId],["Jenis",Ia(e.kind)],["Agen",[e.agent,e.model,e.effort].filter(Boolean).join(" · ")],["Mulai",new Date(e.startedAt).toLocaleString("id-ID")],[p?"Terakhir terlihat hidup":"Selesai",e.endedAt?new Date(e.endedAt).toLocaleString("id-ID"):"berjalan"],...p&&e.reconciledAt?[["Terdeteksi mati",new Date(e.reconciledAt).toLocaleString("id-ID")]]:[],["Durasi",Na(e)],["Direktori",e.cwd]];return e.specId&&b.splice(1,0,["Backlog",`${e.specId}${e.title?` · ${e.title}`:""}`]),e.branch&&b.push(["Branch",e.branch]),a.jsxs(te,{open:!0,title:e.title??e.specId??e.sessionId,icon:"history",onClose:s,width:1e3,children:[a.jsxs("div",{className:"hn-terminal-hist-actions",children:[a.jsx(L,{size:"sm",variant:"ghost",leftIcon:"arrow-left",onClick:s,children:"Kembali"}),a.jsx("div",{className:"hn-terminal-hist-spacer"}),l&&a.jsx(L,{size:"sm",variant:"secondary",leftIcon:"copy",onClick:()=>void k(l),children:"Salin transkrip"}),jn(e.kind)&&a.jsx(L,{size:"sm",leftIcon:"play",onClick:()=>r(e),children:"Mulai lagi"})]}),p&&a.jsxs(Qe,{tone:"warn",title:"Sesi terputus — hasilnya tak diketahui",className:"hn-terminal-notice",children:["Panenya sudah lenyap saat hanoman menyala lagi (reboot, ",a.jsx("code",{children:"tmux kill-server"}),", atau host mati), jadi sesi ini tak meninggalkan exit code dan transkripnya kemungkinan besar tak sempat diambil — capture berjalan tepat sebelum pane dibunuh, dan di jalur ini sudah tak ada pane untuk dibaca. Periksa worktree & branch sesi ini sebelum menganggapnya selesai, lalu mulai lagi bila pekerjaannya belum tuntas."]}),a.jsx("div",{className:"hn-terminal-hist-meta",children:b.map(([j,C])=>a.jsxs(d.Fragment,{children:[a.jsx("span",{className:"hn-terminal-hist-key",children:j}),a.jsx("span",{className:"hn-terminal-hist-val",children:C})]},j))}),x==="loading"&&a.jsx("div",{className:"hn-terminal-hist-note",children:"memuat transkrip…"}),x==="none"&&a.jsx("div",{className:"hn-terminal-hist-note",children:p?"Tanpa transkrip — panenya sudah lenyap sebelum hanoman sempat mengambilnya.":"Tanpa transkrip — sesi ini ditutup sebelum fitur riwayat ada, atau panenya tak menyisakan keluaran."}),N&&a.jsx("div",{role:"status",className:N.tone==="err"?"hn-terminal-hist-copy is-err":"hn-terminal-hist-copy",children:N.text}),x==="error"&&a.jsx("div",{className:"hn-terminal-hist-error",children:"Transkrip tak terbaca lagi di server."}),l!==null&&a.jsx("pre",{className:"hn-terminal-hist-pre",children:l})]})}function oi({open:e,projectId:n,projectName:s,projects:r,onProjectChange:l,onClose:u,onCreated:x}){var w;const[g,N]=d.useState("claude"),[h,k]=d.useState("sonnet"),[p,b]=d.useState("medium"),[j,C]=d.useState({claude:{model:"sonnet",effort:"medium"},codex:{...aa},antigravity:{...ta}}),[E,A]=d.useState(!1),[R,y]=d.useState(null),[f,M]=d.useState(null),[K,W]=d.useState(null);d.useEffect(()=>{e&&(y(null),M(null),F.getSettings().then(o=>{const T={claude:{model:o.model,effort:o.effort},codex:{...aa,...o.codex??{}},antigravity:{...ta,...o.antigravity??{}}},V=o.agent??"claude",O=na(T,V);C(T),N(V),k(O.model),b(O.effort)}).catch(o=>{y(`${Q("memuat pengaturan",o)} · memakai default bawaan`)}),F.getCodexVersion().then(o=>W(o.version)).catch(o=>{y(T=>(T?`${T} · `:"")+Q("membaca versi Codex CLI",o))}))},[e]);const v=o=>{N(o);const T=na(j,o);k(T.model),b(T.effort)},I=o=>{k(o),b(T=>Rn(g,o,T))};async function D(){A(!0),M(null);try{const{id:o}=await F.createTerminal(n,{agent:g,model:h,effort:p});x(o),u()}catch(o){M(Q("membuka sesi",o))}finally{A(!1)}}return a.jsxs(te,{open:e,onClose:u,icon:"plus",eyebrow:s,title:"Sesi baru",footer:a.jsxs(a.Fragment,{children:[a.jsx(L,{variant:"ghost",onClick:u,children:"Batal"}),a.jsx(L,{leftIcon:"play",disabled:E,onClick:()=>void D(),children:"Buka sesi"})]}),children:[R&&a.jsx(Qe,{tone:"warn",title:"Pengaturan belum terbaca",className:"hn-terminal-notice",children:R}),f&&a.jsx(Qe,{tone:"err",title:"Sesi belum terbuka",className:"hn-terminal-notice",children:f}),a.jsxs("div",{className:"hn-terminal-intro",children:["Runtime untuk sesi ini. Default dari setelan global; ubah bila perlu. Sesi lahir dengan pilihan ini untuk seluruh hidupnya — ",a.jsx("code",{children:"/model"})," di terminal tetap bisa mengubahnya."]}),r&&l&&r.length>1&&a.jsx(we,{label:"Project",hint:"Direktori repo tempat sesi dibuka.",children:a.jsx(ee,{"aria-label":"Project",value:n,className:"hn-terminal-field-full",options:r.map(o=>({value:o.id,label:o.name})),onChange:o=>l(o.target.value)})}),a.jsx(we,{label:"Agen",hint:"Mesin yang menjalankan sesi ini. Perilaku sesi sama; hanya CLI-nya berbeda.",children:a.jsx(ee,{"aria-label":"Agen",value:g,className:"hn-terminal-field-full",options:wn,onChange:o=>v(o.target.value)})}),a.jsx(we,{label:"Model",children:a.jsx(ee,{"aria-label":"Model",value:h,className:"hn-terminal-field-full",options:Sn(g,h),onChange:o=>I(o.target.value)})}),a.jsx(we,{label:"Effort",children:a.jsx(ee,{"aria-label":"Effort",value:p,className:"hn-terminal-field-full",options:Nn(g,h).map(o=>({value:o,label:o})),onChange:o=>b(o.target.value)})}),g==="antigravity"&&a.jsx(ai,{}),g==="codex"&&In(h,K)&&a.jsxs("div",{"data-testid":"codex-version-note",className:"hn-terminal-codex-note",children:["Codex CLI terpasang ",a.jsx("b",{children:K}),", sedangkan ",a.jsx("b",{children:h})," butuh ",a.jsx("b",{children:(w=Cn(h))==null?void 0:w.minClient}),". Sesi tetap boleh dijalankan, tapi modelnya belum tentu dikenali CLI ini."]})]})}function ci({projectId:e,projects:n,onProjectChange:s,onClose:r,onConfirm:l}){return a.jsx(te,{open:!0,onClose:r,icon:"terminal",title:"Terminal biasa",footer:a.jsxs(a.Fragment,{children:[a.jsx(L,{variant:"ghost",onClick:r,children:"Batal"}),a.jsx(L,{leftIcon:"play",disabled:!e,onClick:()=>l(e),children:"Buka terminal"})]}),children:a.jsx(we,{label:"Project",hint:"Shell dibuka di direktori repo project ini.",children:a.jsx(ee,{"aria-label":"Project",value:e,className:"hn-terminal-field-full",options:n.map(u=>({value:u.id,label:u.name})),onChange:u=>s(u.target.value)})})})}const Ca=()=>({rows:1,cols:1,cells:[null]}),Ra=(e,n)=>[...e.slice(0,n),...e.slice(n+1)],oa=e=>({...e,rows:e.rows+1,cells:[...e.cells,...Array(e.cols).fill(null)],...e.rowSizes?{rowSizes:[...e.rowSizes,1]}:{}});function ca(e){const n=e.cols+1,s=[];for(let r=0;r<e.rows;r++)for(let l=0;l<n;l++)s.push(l<e.cols?e.cells[r*e.cols+l]??null:null);return{...e,cols:n,cells:s,...e.colSizes?{colSizes:[...e.colSizes,1]}:{}}}function ua(e,n){if(e.rows===1||n<0||n>=e.rows)return e;const s=[...e.cells];return s.splice(n*e.cols,e.cols),{...e,rows:e.rows-1,cells:s,...e.rowSizes?{rowSizes:Ra(e.rowSizes,n)}:{}}}function da(e,n){if(e.cols===1||n<0||n>=e.cols)return e;const s=e.cols-1,r=[];for(let l=0;l<e.rows;l++)for(let u=0;u<e.cols;u++)u!==n&&r.push(e.cells[l*e.cols+u]??null);return{...e,cols:s,cells:r,...e.colSizes?{colSizes:Ra(e.colSizes,n)}:{}}}const Ta=.3,ui=(e,n,s)=>Math.min(s,Math.max(n,e));function Ct(e,n,s){if(n<0||n+1>=e.length||s===0)return e;const l=e.reduce((N,h)=>N+h,0)/e.length*Ta,u=e[n]+e[n+1],x=ui(e[n]+s,l,u-l);if(x===e[n])return e;const g=[...e];return g[n]=x,g[n+1]=u-x,g}function Ea(e,n,s){const r=e.colSizes??Array(e.cols).fill(1),l=Ct(r,n,s);return l===r?e:{...e,colSizes:l}}function Aa(e,n,s){const r=e.rowSizes??Array(e.rows).fill(1),l=Ct(r,n,s);return l===r?e:{...e,rowSizes:l}}const di=.05,mi=.15,za=(e,n)=>e.reduce((s,r)=>s+r,0)*(n?mi:di);function hi(e,n,s,r=!1){const l=e.colSizes??Array(e.cols).fill(1);return Ea(e,n,s*za(l,r))}function pi(e,n,s,r=!1){const l=e.rowSizes??Array(e.rows).fill(1);return Aa(e,n,s*za(l,r))}function ma(e,n){const r=e.reduce((x,g)=>x+g,0)/e.length*Ta,l=e[n]+e[n+1],u=Math.round(r/l*100);return{now:Math.round(e[n]/l*100),min:u,max:100-u}}function jt(e,n,s){if(n<0||n>=e.cells.length)return e;const r=e.cells.map(l=>s!==null&&l===s?null:l);return r[n]=s,{...e,cells:r}}const fi=(e,n)=>({...e,cells:e.cells.map(s=>s&&n.has(s)?s:null)}),Da=e=>({id:crypto.randomUUID(),name:e,layout:Ca()});function ha(){const e=Da("Utama");return{groups:[e],active:e.id}}const $e=e=>e.groups.find(n=>n.id===e.active)??e.groups[0];function gi(e,n){const s=Da(n);return{groups:[...e.groups,s],active:s.id}}const bi=(e,n,s)=>({...e,groups:e.groups.map(r=>r.id===n?{...r,name:s}:r)});function ki(e,n){if(e.groups.length===1)return e;const s=e.groups.filter(r=>r.id!==n);return s.length===e.groups.length?e:{groups:s,active:e.active===n?s[0].id:e.active}}const xi=(e,n)=>e.groups.some(s=>s.id===n)?{...e,active:n}:e;function H(e,n){const s=$e(e);return{...e,groups:e.groups.map(r=>r.id===s.id?{...r,layout:n(r.layout)}:r)}}function wt(e,n,s){const r=$e(e),l=s===null?e.groups:e.groups.map(u=>u.id===r.id?u:{...u,layout:jt(u.layout,u.layout.cells.indexOf(s),null)});return{...e,groups:l.map(u=>u.id===r.id?{...u,layout:jt(u.layout,n,s)}:u)}}function je(e,n){const s=$e(e).layout.cells.indexOf(null);return s===-1?e:wt(e,s,n)}const vi=(e,n)=>({...e,groups:e.groups.map(s=>({...s,layout:jt(s.layout,s.layout.cells.indexOf(n),null)}))}),pa=e=>new Set(e.groups.flatMap(n=>n.layout.cells.filter(s=>s!==null))),fa=(e,n)=>({...e,groups:e.groups.map(s=>({...s,layout:fi(s.layout,n)}))}),Ma="hanoman.terminal.workspace",Fa="hanoman.terminal.layout",Se=e=>Fe.parse({version:1,groups:e.groups});function Ze(e,n){const s=e.groups,r=n&&s.some(l=>l.id===n)?n:s[0].id;return{groups:s,active:r}}function yi(e){try{const n=JSON.parse(e);if(!n||typeof n!="object")return null;const s=n,r=Fe.parse({version:1,groups:s.groups});return{workspace:r,active:typeof s.active=="string"&&r.groups.some(l=>l.id===s.active)?s.active:r.groups[0].id}}catch{return null}}function ji(){try{const e=localStorage.getItem(Ma);if(e)return yi(e);const n=localStorage.getItem(Fa);if(!n)return null;const s=JSON.parse(n),r={id:crypto.randomUUID(),name:"Utama",layout:s};return{workspace:Fe.parse({version:1,groups:[r]}),active:r.id}}catch{return null}}function bt(){try{localStorage.removeItem(Ma),localStorage.removeItem(Fa)}catch{}}const $a=e=>`hanoman.terminal.workspace.v2.${encodeURIComponent(e)}`;function wi(e){try{const n=localStorage.getItem($a(e));if(!n)return null;const s=JSON.parse(n),r=Fe.parse(s.workspace);if(!Number.isInteger(s.revision)||(s.revision??-1)<0)return null;const l=typeof s.active=="string"&&r.groups.some(u=>u.id===s.active)?s.active:r.groups[0].id;return{workspace:r,revision:s.revision,active:l}}catch{return null}}function kt(e,n){try{const s=Fe.parse(n.workspace);if(!Number.isInteger(n.revision)||n.revision<0)return;const r=s.groups.some(l=>l.id===n.active)?n.active:s.groups[0].id;localStorage.setItem($a(e),JSON.stringify({workspace:s,revision:n.revision,active:r}))}catch{}}function xt(e){if(!(e instanceof Me)||e.status!==409)return null;const n=e.detail;if((n==null?void 0:n.code)!=="revision-conflict")return null;const s=Tn.safeParse(n.current);return s.success?s.data:null}function Si(e){const n=P.useRef(null);n.current||(n.current=ha());const[s,r]=P.useState(n.current),[l,u]=P.useState("loading"),[x,g]=P.useState(null),[N,h]=P.useState(!1),k=P.useRef(s),p=P.useRef(0),b=P.useRef(!1),j=P.useRef(Promise.resolve()),C=P.useRef(0),E=P.useCallback(v=>{k.current=v,r(v)},[]),A=P.useCallback(v=>{b.current=v,h(v)},[]),R=P.useCallback(v=>{const I=j.current.then(v,v);return j.current=I.then(()=>{},()=>{}),I},[]),y=P.useCallback((v,I="ready",D=null,w=k.current.active)=>{const o=v.workspace?Ze(v.workspace,w):ha();p.current=v.revision,E(o),u(I),g(D),A(!0),v.workspace&&kt(e,{workspace:v.workspace,revision:v.revision,active:o.active})},[E,A,e]),f=P.useCallback(v=>{const I=wi(e);I&&(p.current=I.revision,E(Ze(I.workspace,I.active))),A(!1),u("recovering"),g(v instanceof Error?v.message:"Layout server belum tersambung")},[E,A,e]),M=P.useCallback(()=>R(async()=>{try{y(await F.getTerminalWorkspace())}catch(v){f(v)}}),[y,R,f]);P.useEffect(()=>{const v=++C.current;return u("loading"),g(null),A(!1),R(async()=>{try{const I=await F.getTerminalWorkspace();if(v!==C.current)return;if(I.workspace){y(I),bt();return}const D=ji();if(!D){y(I);return}try{const w=await F.putTerminalWorkspace({baseRevision:I.revision,workspace:D.workspace});if(v!==C.current)return;E(Ze(w.workspace,D.active)),p.current=w.revision,kt(e,{workspace:w.workspace,revision:w.revision,active:D.active}),bt(),u("ready"),g(null),A(!0)}catch(w){const o=xt(w);o!=null&&o.workspace?(y(o,"conflict","Layout server lebih baru; layout lokal lama tidak diunggah"),bt()):f(w)}}catch(I){v===C.current&&f(I)}}),()=>{C.current+=1}},[y,R,f,E,A,e]),P.useEffect(()=>{const v=()=>{M()},I=()=>{document.visibilityState==="visible"&&M()};return window.addEventListener("focus",v),document.addEventListener("visibilitychange",I),()=>{window.removeEventListener("focus",v),document.removeEventListener("visibilitychange",I)}},[M]);const K=P.useCallback(v=>R(async()=>{if(!b.current)return!1;const I=v(k.current);let D,w;try{D=Se(I),w=Se(k.current)}catch{return u("conflict"),g("Layout tidak valid dan tidak disimpan"),!1}if(wa(D,w))return!0;try{return y(await F.putTerminalWorkspace({baseRevision:p.current,workspace:D}),"ready",null,I.active),!0}catch(o){const T=xt(o);if(!(T!=null&&T.workspace))return f(o),!1;const V=v(Ze(T.workspace,k.current.active));try{const O=await F.putTerminalWorkspace({baseRevision:T.revision,workspace:Se(V)});return y(O,"conflict","Layout berubah di perangkat lain; perubahan ini diterapkan ulang",V.active),!0}catch(O){if(!xt(O)&&!(O instanceof Me&&O.status===409))return f(O),!1;try{y(await F.getTerminalWorkspace(),"conflict","Layout berubah lagi di perangkat lain; state terbaru dimuat")}catch(ue){f(ue)}return!1}}}),[y,R,f]),W=P.useCallback(v=>{const I=xi(k.current,v);E(I);const D=Se(I);kt(e,{workspace:D,revision:p.current,active:I.active})},[E,e]);return{workspace:s,status:l,message:x,writable:N,mutate:K,setActive:W,refresh:M}}const Ni=En("focus","grid"),ga={attention:0,running:1,open:1,failed:2,done:3};function Pa(e,n){return e.exited?e.exitCode?{tone:"failed",label:`Gagal · exit ${e.exitCode}`}:{tone:"done",label:"Selesai"}:n?{tone:"done",label:"Selesai"}:e.deciding?{tone:"attention",label:"Lead memutuskan"}:e.decision?{tone:"attention",label:"Menunggu keputusan"}:e.specId?{tone:"running",label:"Berjalan"}:{tone:"open",label:"Terbuka"}}function Ii(e){const n=e.startedAt;return typeof n=="number"&&Number.isFinite(n)&&n>0?n*1e3:null}function Ci(e,n){const s=e.map((r,l)=>({session:r,index:l,rank:ga[Pa(r,n.has(r.id)).tone]}));return s.sort((r,l)=>{if(r.rank!==l.rank)return r.rank-l.rank;if(r.rank===ga.attention){const u=r.session.decisionAt?Date.parse(r.session.decisionAt):Number.NaN,x=l.session.decisionAt?Date.parse(l.session.decisionAt):Number.NaN,g=Number.isNaN(u)?Number.POSITIVE_INFINITY:u,N=Number.isNaN(x)?Number.POSITIVE_INFINITY:x;if(g!==N)return g<N?-1:1}return r.index-l.index}),s.map(r=>r.session)}function Ri(e){const n=new Map;for(const s of e){const r=n.get(s.projectId);r?r.push(s):n.set(s.projectId,[s])}return[...n.values()].flat()}function Ti(e,n){if(n){const s=e.find(r=>r.id===n);if(s)return s}return e[0]??null}function Ei(e,n,s){if(s<=0)return null;const r=e<0?0:e;switch(n){case"ArrowDown":return Math.min(r+1,s-1);case"ArrowUp":return Math.max(r-1,0);case"Home":return 0;case"End":return s-1;default:return null}}const La={attention:"awaiting",running:"running",open:"idle",failed:"failed",done:"done"};function Ai(e){const[n,s]=d.useState(()=>Date.now());return d.useEffect(()=>{const r=setInterval(()=>s(Date.now()),e);return()=>clearInterval(r)},[e]),n}function ba({items:e,focusedId:n,onFocus:s,menuFor:r,label:l="Daftar sesi"}){const u=Ai(3e4),x=d.useRef([]),g=new Set(e.map(k=>k.session.projectId)).size>1,N=e.findIndex(k=>k.session.id===n),h=k=>{var C;const p=x.current.indexOf(k.target);if(p<0)return;const b=Ei(p,k.key,e.length);if(b===null)return;k.preventDefault();const j=e[b];j&&(s(j.session.id),(C=x.current[b])==null||C.focus())};return a.jsx("ul",{role:"list","aria-label":l,className:"hn-terminal-rail-list",onKeyDown:h,children:e.map((k,p)=>{var R;const{session:b,status:j}=k,C=b.id===n,E=C||N<0&&p===0,A=k.startedMs!==null?An(k.startedMs,u):"";return a.jsxs(d.Fragment,{children:[g&&k.session.projectId!==((R=e[p-1])==null?void 0:R.session.projectId)&&a.jsx("li",{role:"presentation",className:"hn-terminal-rail-group",children:k.projectName}),a.jsx("li",{className:"hn-terminal-rail-item",children:a.jsxs("div",{className:`hn-terminal-rail-row${C?" is-focused":""}`,"data-tone":j.tone,children:[a.jsxs("button",{type:"button",className:"hn-terminal-rail-main",ref:y=>{x.current[p]=y},tabIndex:E?0:-1,"aria-current":C?"true":void 0,title:k.label,onClick:()=>s(b.id),children:[a.jsx("span",{className:"hn-terminal-rail-name",children:k.label}),a.jsxs("span",{className:"hn-terminal-rail-meta",children:[a.jsx(ge,{status:La[j.tone],variant:"dot",size:"sm",children:j.label}),A&&a.jsx("span",{className:"hn-terminal-rail-time",children:A})]})]}),a.jsx(Ne,{label:`Aksi sesi ${b.id} di daftar`,items:r(b)})]})})]},b.id)})})}const zi=[],Di=e=>!!(e.binding??e.repoDir),Mi=e=>{var n;return((n=e.find(Di)??e[0])==null?void 0:n.id)??""},Fi=e=>e instanceof Me&&e.status===400&&typeof e.detail=="object"&&e.detail!==null&&e.detail.needsBind===!0;function Xi({userId:e="test-user",projects:n,backlog:s=zi,focusSession:r,startedSession:l,onStartedSessionHandled:u,onStartBacklog:x,onOpenReview:g,onOpenSessionReview:N,titleOf:h,onIntegrate:k,onIntegrateSession:p,specOf:b,sessions:j,setSessions:C,onOpenProject:E}){const[A,R]=d.useState([]),y=j??A,f=C??R,[M,K]=d.useState([]),W=Si(e),{workspace:v,status:I,message:D,writable:w,mutate:o,setActive:T,refresh:V}=W,[O,ue]=fe("terminal","project",Mi(n),Qn),Ie=Sa(),ke=Fn(),re=ke==="mobile",[J,de]=fe("terminal","fontSize",Ie?Yn:Jn,Vn),[le,Pe]=fe("terminal","keys",Ie&&!re,Je),[q,xe]=fe("terminal","predict",!0,Je),[ae,Le]=fe("terminal","diag",!1,Je),[ne,Ka]=fe("terminal","sr",!1,Je),Tt=t=>de(i=>Hn(i+t)),[me,Et]=d.useState(!1),[ie,et]=d.useState(null),[_a,Oe]=d.useState(!1),[Ga,Be]=d.useState(null),[Wa,At]=d.useState(!1),[qa,tt]=d.useState(!1),[Ua,Ke]=d.useState(!1),[Ha,at]=fe("terminal","view","focus",Ni),U=Ha==="focus",[nt,Ce]=d.useState(null),[it,Va]=d.useState(()=>new Set),[Ya,Ja]=d.useState(null),[zt,Dt]=d.useState(!1),[Xa,Mt]=d.useState(!1),[he,Re]=d.useState(null),[_e,Ft]=d.useState(!1),[Ge,$t]=d.useState(null),st=$n(),{confirm:Za,dialog:Qa}=Pn(),z=$e(v).layout,rt=z.rows===1&&z.cols===1&&!z.cells[0]&&y.length===0,lt=d.useRef(null),[en,tn]=d.useState(Number.POSITIVE_INFINITY);d.useEffect(()=>{const t=lt.current;if(!t||typeof ResizeObserver!="function")return;const i=new ResizeObserver(c=>{var S;const m=((S=c[0])==null?void 0:S.contentRect.width)??t.getBoundingClientRect().width;m>0&&tn(m)});return i.observe(t),()=>i.disconnect()},[rt]);const an=ke==="tablet"&&Ln(z.cols,en,Un),B=re||an,[X,We]=d.useState(0),[se,qe]=d.useState(null),ot=d.useRef(null),Te=t=>{Ce(t),qe(t)},nn=d.useCallback((t,i)=>{Va(c=>{if(c.has(t)===i)return c;const m=new Set(c);return i?m.add(t):m.delete(t),m})},[]),Pt=d.useMemo(()=>Ri(Ci(y,it)),[y,it]),Ue=Ti(Pt,nt),He=(Ue==null?void 0:Ue.id)??null;d.useEffect(()=>{He&&He!==nt&&Ce(He)},[He,nt]);const[ve,sn]=d.useState(!1),[Ve,Lt]=d.useState(null),[rn,ln]=d.useState(0);d.useEffect(()=>{let t=!0;return F.listTerminals().then(i=>{t&&(Lt(null),f(i),sn(!0))}).catch(i=>{t&&Lt(Q("memuat daftar sesi",i))}),()=>{t=!1}},[rn]);const[on,oe]=On();d.useEffect(()=>Bn(t=>{t.t==="sessions"&&!j?f(t.sessions):t.t==="cleanups"&&K(t.cleanups)}),[]),d.useEffect(()=>{if(!ve||!w)return;const t=new Set(y.map(c=>c.id)),i=fa(v,t);wa(Se(i),Se(v))||o(c=>fa(c,t))},[o,y,ve,w,v]),d.useEffect(()=>{!l||l.specId==null||!ve||(f(t=>t.some(i=>i.id===l.id)?t:[...t,{...l,cwd:"",exited:!1}]),Ce(l.id),qe(l.id),u==null||u())},[u,ve,l]);const ct=d.useRef(null);d.useEffect(()=>{if(!r){ot.current=null,ct.current=null;return}if(!(!ve||ot.current===r)){if(!y.some(t=>t.id===r&&!t.exited)){if(ct.current===r)return;ct.current=r,F.listSessionHistory({q:r,limit:1}).then(t=>oe(ia,"warn","history",t.total>0?{action:{label:Kn,onAction:()=>Ke(!0)},duration:7e3}:void 0)).catch(()=>{oe(ia,"warn","history")});return}ot.current=r,Ce(r),qe(r)}},[r,y,ve,oe]),d.useEffect(()=>{if(!se)return;const t=v.groups.find(i=>i.layout.cells.includes(se));if(t){t.id!==v.active&&T(t.id);return}w&&o(i=>{if(pa(i).has(se))return i;const c=je(i,se);return c!==i||!B?c:wt(i,X,se)})},[X,B,o,se,T,w,v]),d.useEffect(()=>{ie&&!y.some(t=>t.id===ie)&&et(null)},[ie,y]);const ut=M.filter(t=>t.error),Z=t=>y.find(i=>i.id===t)??null,Y=d.useCallback(t=>{var i;return((i=n.find(c=>c.id===t))==null?void 0:i.name)??t},[n]);function cn(t){f(i=>i.some(c=>c.id===t)?i:[...i,{id:t,projectId:O,cwd:"",exited:!1}]),o(i=>je(i,t)),Te(t)}async function Ot(t){if(!t)return;tt(!1);let i;try{({id:i}=await F.createShell(t))}catch(c){Fi(c)?oe(`Project ${Y(t)} belum terhubung ke folder repo — hubungkan dulu.`,"err","folder-git-2",E?{action:{label:"Buka project",onAction:()=>E(t)}}:void 0):oe(Q("membuka terminal biasa",c),"err","x-circle");return}f(c=>[...c,{id:i,projectId:t,cwd:"",exited:!1}]),o(c=>je(c,i)),Te(i)}async function Bt(t,i){if(x&&!i){Oe(!1),Be(null),x(t);return}const c=Zn(t.source);try{const{id:m}=await F.startSession({spec:t.id,flow:c,...i?{force:i}:{}});f(S=>S.some($=>$.id===m)?S:[...S,{id:m,projectId:t.projectId,specId:t.id,flow:c,cwd:"",exited:!1}]),o(S=>je(S,m)),Te(m),Oe(!1),Be(null)}catch(m){if(st.offerRetry(m,t.id,$=>Bt(t,$)))return;const S=m instanceof Me&&(m.status===400||m.status===422);Be(`${t.id} · gagal mulai${S?" · project belum punya repoDir":""}`)}}async function Kt(t,i){try{const c=t.specId?await F.startSession({spec:t.specId,flow:t.flow??"feature",agent:t.agent==="antigravity"?"antigravity":t.agent==="codex"?"codex":"claude",...t.model?{model:t.model}:{},...t.effort?{effort:t.effort}:{},...i?{force:i}:{}}):t.kind==="shell"?await F.createShell(t.projectId):t.kind==="terminal"?await F.createTerminal(t.projectId,{agent:t.agent==="antigravity"?"antigravity":t.agent==="codex"?"codex":"claude",...t.model?{model:t.model}:{},...t.effort?{effort:t.effort}:{}}):await(i?F.createTerminalFlow(t.projectId,t.kind,{force:i}):F.createTerminalFlow(t.projectId,t.kind));f(m=>m.some(S=>S.id===c.id)?m:[...m,{id:c.id,projectId:t.projectId,specId:t.specId??void 0,cwd:"",exited:!1}]),o(m=>je(m,c.id)),Te(c.id),Ke(!1)}catch(c){if((t.specId||t.kind!=="shell"&&t.kind!=="terminal")&&st.offerRetry(c,`${t.projectId} · ${t.title??t.specId??t.kind}`,m=>Kt(t,m)))return}}const _t=new Set(y.filter(t=>t.specId&&!t.exited).map(t=>t.specId)),un=s.filter(t=>t.stage!=="done"&&!_t.has(t.id));function Gt(t){f(i=>i.filter(c=>c.id!==t)),F.deleteTerminal(t).catch(i=>{i instanceof Me&&i.status===404||oe(Q(`menutup sesi ${t.slice(0,6)}`,i),"err","x-circle")})}async function Wt(){if(!he||_e)return;const{id:t,value:i}=he;Ft(!0);try{const c=await F.renameTerminal(t,i);f(m=>m.map(S=>{if(S.id!==t)return S;const{name:$,...G}=S;return c.name?{...G,name:c.name}:G})),Re(null),oe(c.name?"Nama sesi disimpan":"Nama kustom dihapus","ok")}catch(c){oe(Q("mengganti nama sesi",c),"err","x-circle")}finally{Ft(!1)}}async function dt(t){const i=Z(t),c=`${i?be(i,Y,h):t} · ${t.slice(0,6)}`,m=!!i&&!i.exited;await Za({title:`Tutup sesi "${c}"?`,impact:[m?"Agen yang sedang berjalan di sesi ini akan dihentikan.":"Sesi ini sudah berhenti, jadi tidak ada agen yang perlu dihentikan.","Worktree sesi ini ikut dibersihkan dari disk."],confirmLabel:"Tutup sesi",icon:"square",tone:"danger"})&&Gt(t)}const dn=d.useCallback((t,i)=>{f(c=>c.map(m=>m.id===t?{...m,exited:!0,exitCode:i}:m))},[]),qt={killSession:Gt,requestKill:dt,detach:t=>{o(i=>vi(i,t))},markExited:dn,setFullId:et,openDialog:(t,i)=>$t({kind:t,sessionId:i}),openRename:t=>{var i;return Re({id:t,value:((i=Z(t))==null?void 0:i.name)??""})},props:{onOpenReview:g,onOpenSessionReview:N,titleOf:h,onIntegrate:k,onIntegrateSession:p,specOf:b}},_=d.useRef(qt);_.current=qt;const Ut=d.useRef(new Map),pe=t=>{let i=Ut.current.get(t);return i||(i={onClose:()=>void _.current.requestKill(t),onForget:()=>_.current.killSession(t),onDetach:()=>_.current.detach(t),onExit:c=>_.current.markExited(t,c),onFullscreen:()=>_.current.setFullId(t),onDialog:c=>_.current.openDialog(c,t),onRename:()=>_.current.openRename(t)},Ut.current.set(t,i)),i},Ht=d.useRef(new Map),mn=t=>{let i=Ht.current.get(t);return i||(i=(c,m)=>{Ja({sessionId:t,phases:c}),nn(t,m)},Ht.current.set(t,i)),i},hn=t=>Ba(t,{label:be(t,Y,h),canArrange:w,specOf:b,onReview:g,onSessionReview:N,onIntegrate:k,onIntegrateSession:p,onDialog:pe(t.id).onDialog,onDetach:pe(t.id).onDetach,onFullscreen:pe(t.id).onFullscreen,onKill:()=>void dt(t.id),onRename:pe(t.id).onRename}),ye=d.useRef({onOpenReview:t=>{var i,c;return(c=(i=_.current.props).onOpenReview)==null?void 0:c.call(i,t)},onOpenSessionReview:(t,i)=>{var c,m;return(m=(c=_.current.props).onOpenSessionReview)==null?void 0:m.call(c,t,i)},titleOf:t=>{var i,c;return(c=(i=_.current.props).titleOf)==null?void 0:c.call(i,t)},onIntegrate:(t,i,c)=>{var m,S;return(S=(m=_.current.props).onIntegrate)==null?void 0:S.call(m,t,i,c)},onIntegrateSession:(t,i,c)=>{var m,S;return(S=(m=_.current.props).onIntegrateSession)==null?void 0:S.call(m,t,i,c)},specOf:t=>{var i,c;return(c=(i=_.current.props).specOf)==null?void 0:c.call(i,t)}}).current,pn=(t,i)=>{We(t),o(c=>wt(c,t,i))},fn=t=>{Te(t),o(i=>je(i,t))},gn=pa(v),mt=y.filter(t=>!gn.has(t.id));d.useEffect(()=>{if(!se)return;const t=z.cells.indexOf(se);t<0||(We(t),qe(null))},[z.cells,se]),d.useEffect(()=>{X>=z.cells.length&&We(Math.max(0,z.cells.length-1))},[X,z.cells.length]);const Ye=d.useRef(null),[ce,ht]=d.useState(null),pt=(ce==null?void 0:ce.axis)==="col"?ce.sizes:z.colSizes??Array(z.cols).fill(1),ft=(ce==null?void 0:ce.axis)==="row"?ce.sizes:z.rowSizes??Array(z.rows).fill(1);function Vt(t,i,c){var $,G,Ee;if(!w)return;const m=($=lt.current)==null?void 0:$.getBoundingClientRect();if(!m)return;(Ee=(G=c.currentTarget).setPointerCapture)==null||Ee.call(G,c.pointerId);const S=t==="col"?pt:ft;Ye.current={axis:t,index:i,pointerId:c.pointerId,start:t==="col"?c.clientX:c.clientY,extent:t==="col"?m.width:m.height,startSizes:S,latest:S},ht({axis:t,sizes:S})}function Yt(t){const i=Ye.current;if(!i||i.pointerId!==t.pointerId)return;const c=i.axis==="col"?t.clientX:t.clientY,m=i.startSizes.reduce(($,G)=>$+G,0),S=(c-i.start)/i.extent*m;i.latest=Ct(i.startSizes,i.index,S),ht({axis:i.axis,sizes:i.latest})}function Jt(t){var c,m;const i=Ye.current;!i||i.pointerId!==t.pointerId||(Ye.current=null,(m=(c=t.currentTarget).releasePointerCapture)==null||m.call(c,t.pointerId),ht(null),i.latest!==i.startSizes&&o(S=>H(S,$=>i.axis==="col"?{...$,colSizes:i.latest}:{...$,rowSizes:i.latest})))}function Xt(t,i,c){if(!w)return;const m=t==="col"?"ArrowRight":"ArrowDown",S=t==="col"?"ArrowLeft":"ArrowUp",$=c.key===m?1:c.key===S?-1:0;$!==0&&(c.preventDefault(),o(G=>H(G,Ee=>t==="col"?hi(Ee,i,$,c.shiftKey):pi(Ee,i,$,c.shiftKey))))}function Zt(t,i){w&&o(c=>H(c,m=>{const S=t==="col"?m.colSizes??Array(m.cols).fill(1):m.rowSizes??Array(m.rows).fill(1),G=(S[i]+S[i+1])/2-S[i];return t==="col"?Ea(m,i,G):Aa(m,i,G)}))}const Qt=a.jsxs("div",{className:"hn-terminal-display",children:[a.jsxs("div",{className:"hn-dense-row hn-terminal-display-row",children:[a.jsx("span",{className:"hn-terminal-display-label",children:"Ukuran teks terminal"}),a.jsx(gt,{size:"sm",icon:"minus",label:"Perkecil teks terminal",disabled:J<=_n,onClick:()=>Tt(-1)}),a.jsxs("span",{className:"hn-terminal-display-value",children:[J,"px"]}),a.jsx(gt,{size:"sm",icon:"plus",label:"Perbesar teks terminal",disabled:J>=Gn,onClick:()=>Tt(1)})]}),a.jsxs("div",{className:"hn-dense-row hn-terminal-display-row",children:[a.jsx("span",{className:"hn-terminal-display-label",children:"Papan tombol layar (Esc · panah · Enter)"}),a.jsx(L,{size:"sm",variant:"secondary","aria-pressed":le,onClick:()=>Pe(t=>!t),children:le?"Sembunyikan":"Tampilkan"})]}),a.jsxs("div",{className:"hn-dense-row hn-terminal-display-row",children:[a.jsx("span",{className:"hn-terminal-display-label",children:"Ketik responsif (huruf tampil sebelum echo server)"}),a.jsx(L,{size:"sm",variant:"secondary","aria-pressed":q,"aria-label":`${q?"Matikan":"Nyalakan"} ketik responsif`,onClick:()=>xe(t=>!t),children:q?"Matikan":"Nyalakan"})]}),a.jsxs("div",{className:"hn-dense-row hn-terminal-display-row",children:[a.jsx("span",{id:"terminal-sr-label",className:"hn-terminal-display-label",children:"Mode pembaca layar"}),a.jsx(L,{size:"sm",variant:"secondary","aria-pressed":ne,"aria-describedby":"terminal-sr-hint","aria-label":`${ne?"Matikan":"Nyalakan"} mode pembaca layar`,onClick:()=>Ka(t=>!t),children:ne?"Matikan":"Nyalakan"})]}),a.jsx("p",{id:"terminal-sr-hint",className:"hn-terminal-sr-hint",children:"Untuk pembaca layar: teks terminal tersedia di DOM; kecepatan lebih rendah. Tab dikirim ke sesi (tidak memindahkan fokus). Untuk keluar dari terminal tekan Ctrl+Shift+Esc."}),!U&&a.jsxs("div",{className:"hn-dense-row hn-terminal-display-row",children:[a.jsx("span",{id:"terminal-reset-grid-hint",className:"hn-terminal-display-label",children:'Kembalikan grid ke 1 kolom × 1 baris (sesi lain pindah ke "belum di grid")'}),a.jsx(L,{size:"sm",variant:"secondary","aria-describedby":"terminal-reset-grid-hint",disabled:!w||z.cols===1&&z.rows===1,onClick:()=>void o(t=>H(t,()=>Ca())),children:"Reset grid"})]}),a.jsxs("details",{className:"hn-terminal-diag",children:[a.jsxs("summary",{className:"hn-terminal-diag-summary",children:["Diagnostik",ae?" · perekaman aktif":""]}),a.jsxs("div",{className:"hn-dense-row hn-terminal-display-row hn-terminal-diag-row",children:[a.jsx("span",{className:"hn-terminal-display-label",children:"Rekam jalur ketik — mencatat setiap tombol yang ditekan di pane. Nyalakan hanya saat menyelidiki masalah ketik."}),a.jsx(L,{size:"sm",variant:"secondary","aria-pressed":ae,"aria-label":`${ae?"Matikan":"Nyalakan"} rekam jalur ketik`,onClick:()=>Le(t=>!t),children:ae?"Matikan":"Nyalakan"})]})]})]}),ea=[{key:"backlog",label:"Ambil backlog",icon:"inbox",onSelect:()=>{Be(null),Oe(!0)}},{key:"history",label:"Riwayat sesi",icon:"history",onSelect:()=>Ke(!0)},{key:"shell",label:"Terminal biasa",icon:"terminal",onSelect:()=>n.length>1?tt(!0):void Ot(O)}],bn=[{key:"col+",label:"+ Kolom",icon:"columns-2",disabled:!w,onSelect:()=>void o(t=>H(t,ca))},{key:"row+",label:"+ Baris",icon:"rows-2",disabled:!w,onSelect:()=>void o(t=>H(t,oa))},{key:"col-",label:"Hapus kolom aktif",icon:"columns-2",disabled:!w||z.cols===1,onSelect:()=>void o(t=>H(t,i=>da(i,X%i.cols)))},{key:"row-",label:"Hapus baris aktif",icon:"rows-2",disabled:!w||z.rows===1,onSelect:()=>void o(t=>H(t,i=>ua(i,Math.floor(X/i.cols))))}],kn=[{key:"mode",label:U?"Pakai mode Grid":"Pakai mode Fokus",icon:U?"columns-2":"terminal",onSelect:()=>at(U?"grid":"focus")},{key:"full",label:me?"Keluar layar penuh":"Layar penuh",icon:me?"minimize-2":"maximize-2",onSelect:()=>Et(t=>!t)},{key:"display",label:"Tampilan terminal",icon:"sliders",onSelect:()=>Mt(!0)}];return a.jsxs("div",{"data-testid":"terminal-root",className:me?"hn-terminal-screen is-maxed":"hn-terminal-screen",children:[a.jsxs("div",{className:"hn-terminal-toolbar",role:"group","aria-label":"Terminal",children:[a.jsx(L,{size:"sm",leftIcon:"plus",title:"Pilih runtime lalu buka sesi agen di direktori project. Agen berjalan dengan izin penuh (claude --dangerously-skip-permissions).",onClick:()=>At(!0),children:"Sesi baru"}),re?a.jsxs(a.Fragment,{children:[a.jsx(ya,{compact:!0,items:ea}),U&&y.length>0&&a.jsxs("button",{type:"button",className:"hn-terminal-rail-toggle","aria-haspopup":"dialog","aria-expanded":zt,onClick:()=>Dt(!0),children:["Sesi · ",y.length]}),a.jsx(Ne,{label:"Menu terminal",title:"Terminal",items:kn})]}):a.jsxs(a.Fragment,{children:[a.jsx(ya,{items:ea}),a.jsxs("div",{className:"hn-terminal-seg",role:"group","aria-label":"Mode tampilan terminal",children:[a.jsx("button",{type:"button",className:"hn-terminal-seg-btn","aria-pressed":U,title:"Satu terminal fokus dengan daftar sesi di samping",onClick:()=>at("focus"),children:"Fokus"}),a.jsx("button",{type:"button",className:"hn-terminal-seg-btn","aria-pressed":!U,title:"Beberapa terminal sekaligus dalam grid",onClick:()=>at("grid"),children:"Grid"})]}),a.jsx(Ne,{label:"Tampilan terminal",icon:"sliders",items:[],children:Qt}),a.jsx(gt,{size:"sm",icon:me?"minimize-2":"maximize-2",label:me?"Keluar layar penuh":"Layar penuh","aria-pressed":me,onClick:()=>Et(t=>!t)})]})]}),(I!=="ready"||M.length>0)&&a.jsxs("div",{className:"hn-terminal-status",children:[I!=="ready"&&a.jsx("span",{"data-testid":"terminal-workspace-status",title:D??void 0,className:I==="conflict"?"hn-terminal-status-warn":void 0,children:I==="loading"?"Memuat layout server…":I==="recovering"?a.jsxs(a.Fragment,{children:[a.jsx("span",{children:"Layout server belum tersambung"})," ",a.jsx("button",{type:"button",onClick:()=>void V(),children:"Coba lagi"})]}):D??"Layout berubah di perangkat lain"}),M.length>0&&a.jsx("span",{"data-testid":"worktree-cleanups",title:M.map(t=>`${t.sessionId}${t.error?` — ${t.error}`:""}`).join(`
2
2
  `),className:ut.length?"hn-terminal-status-err":void 0,children:ut.length?`${ut.length} worktree gagal dibersihkan`:`membersihkan ${M.length} worktree…`})]}),!U&&a.jsxs("div",{className:"hn-terminal-grid-bar",children:[a.jsx(Pi,{compact:me,ws:v,writable:w,onSelect:T,onAdd:()=>void o(t=>gi(t,`Grup ${t.groups.length+1}`)),onRename:(t,i)=>void o(c=>bi(c,t,i)),onRemove:t=>void o(i=>ki(i,t))}),!B&&a.jsxs(a.Fragment,{children:[a.jsx(L,{size:"sm",variant:"ghost",disabled:!w,onClick:()=>void o(t=>H(t,ca)),children:"+ Kolom"}),a.jsx(L,{size:"sm",variant:"ghost",disabled:!w,onClick:()=>void o(t=>H(t,oa)),children:"+ Baris"})]}),B&&a.jsx(Ne,{label:"Atur grid",icon:"sliders",items:bn})]}),Ve&&a.jsxs(Qe,{tone:"err",title:"Daftar sesi belum bisa dimuat",className:"hn-terminal-notice--tight",children:[a.jsxs("span",{children:[Ve," "]}),a.jsx("button",{type:"button",className:"hn-terminal-action hn-terminal-action--text",onClick:()=>ln(t=>t+1),children:"Coba lagi"})]}),!U&&mt.length>0&&a.jsxs("div",{className:"hn-terminal-unplaced",children:[a.jsx("span",{className:"hn-terminal-unplaced-label",children:"Belum di grid:"}),mt.map(t=>a.jsxs("span",{className:"hn-terminal-unplaced-chip",children:[a.jsxs("button",{className:"hn-terminal-unplaced-action",disabled:!w,onClick:()=>fn(t.id),title:"Taruh di sel kosong pertama grup ini",children:[t.specId??Y(t.projectId)," · ",t.id.slice(0,6)]}),a.jsx("button",{type:"button",className:"hn-terminal-action","aria-label":`Tutup sesi ${t.id}`,onClick:()=>void dt(t.id),children:"×"})]},t.id))]}),!U&&B&&!rt&&a.jsx("div",{className:"hn-stack-mobile hn-terminal-tabs-row",children:a.jsx(Wn,{"aria-label":"Panel terminal",variant:"pill",value:String(X),onChange:t=>We(Number(t)),tabs:z.cells.map((t,i)=>({value:String(i),label:`Panel ${i+1}${t?` · ${t.slice(0,6)}`:" · kosong"}`}))})}),!U&&(rt?Ve?null:a.jsx(ze,{kind:"empty",icon:"terminal",title:"Belum ada sesi terminal",hint:"Tekan Sesi baru untuk memulai agen di project terpilih, atau Terminal biasa untuk shell."}):a.jsxs("div",{ref:lt,"data-testid":"terminal-grid",className:"hn-terminal-grid",style:{"--grid-cols":B?"minmax(0, 1fr)":`18px ${pt.map(t=>`minmax(0, ${t}fr)`).join(" ")}`,"--grid-rows":B?"minmax(0, 1fr)":`16px ${ft.map(t=>`minmax(0, ${t}fr)`).join(" ")}`},children:[!B&&a.jsx("div",{className:"hn-terminal-grid-corner"}),!B&&Array.from({length:z.cols},(t,i)=>a.jsx(ka,{axis:"col",label:`Tutup kolom ${i+1}`,disabled:!w||z.cols===1,gridColumn:i+2,gridRow:1,onClick:()=>void o(c=>H(c,m=>da(m,i)))},`col-${i}`)),!B&&Array.from({length:z.rows},(t,i)=>a.jsx(ka,{axis:"row",label:`Tutup baris ${i+1}`,disabled:!w||z.rows===1,gridColumn:1,gridRow:i+2,onClick:()=>void o(c=>H(c,m=>ua(m,i)))},`row-${i}`)),!B&&Array.from({length:z.cols-1},(t,i)=>{const c=ma(pt,i);return a.jsx(xa,{orientation:"col",label:`Ubah lebar kolom ${i+1}/${i+2}`,now:c.now,min:c.min,max:c.max,disabled:!w,gridColumn:i+3,gridRow:"1 / -1",onPointerDown:m=>Vt("col",i,m),onPointerMove:Yt,onPointerUp:Jt,onKeyDown:m=>Xt("col",i,m),onDoubleClick:()=>Zt("col",i)},`col-div-${i}`)}),!B&&Array.from({length:z.rows-1},(t,i)=>{const c=ma(ft,i);return a.jsx(xa,{orientation:"row",label:`Ubah tinggi baris ${i+1}/${i+2}`,now:c.now,min:c.min,max:c.max,disabled:!w,gridColumn:"1 / -1",gridRow:i+3,onPointerDown:m=>Vt("row",i,m),onPointerMove:Yt,onPointerUp:Jt,onKeyDown:m=>Xt("row",i,m),onDoubleClick:()=>Zt("row",i)},`row-div-${i}`)}),Array.from({length:z.rows},(t,i)=>i).flatMap(t=>Array.from({length:z.cols},(i,c)=>{const m=t*z.cols+c,S=z.cells[m]??null,$=S?Z(S):null;return a.jsx("div",{"data-terminal-cell-index":m,"aria-hidden":B&&X!==m?"true":"false",className:B&&X!==m?"hn-terminal-cell-slot is-hidden":"hn-terminal-cell-slot",style:{"--cell-col":B?"auto":c+2,"--cell-row":B?"auto":t+2},children:$?a.jsx(Bi,{session:$,nameOf:Y,...pe($.id),canArrange:w,onReview:g&&ye.onOpenReview,onSessionReview:N&&ye.onOpenSessionReview,titleOf:h&&ye.titleOf,onIntegrate:k&&ye.onIntegrate,onIntegrateSession:p&&ye.onIntegrateSession,specOf:b&&ye.specOf,backlog:s,fontSize:J,showKeys:le,predict:q,diag:ae,screenReader:ne,fullscreen:ie===$.id,paneHidden:B&&X!==m}):a.jsx(qi,{disabled:!w,unplaced:mt,nameOf:Y,onPick:G=>pn(m,G)})},S??`empty-${m}`)}))]})),U&&a.jsx(Gi,{sessionCount:y.length,focused:Ue,mobile:re,railItems:Pt.map(t=>({session:t,label:be(t,Y,h),projectName:Y(t.projectId),status:Pa(t,it.has(t.id)),startedMs:Ii(t)})),listError:!!Ve,menuFor:hn,onFocus:Ce,drawerOpen:zt,onDrawer:Dt,fullId:ie,focusPhases:Ya,paneHandlers:t=>({onExit:pe(t).onExit,onPhases:mn(t),onForget:pe(t).onForget}),fontSize:J,showKeys:le,onToggleKeys:()=>Pe(t=>!t),predict:q,diag:ae,screenReader:ne}),_a&&a.jsx($i,{seed:un,activeIds:_t,error:Ga,onPick:t=>void Bt(t),onClose:()=>Oe(!1)}),Wa&&a.jsx(oi,{open:!0,projectId:O,projectName:Y(O),projects:n,onProjectChange:ue,onClose:()=>At(!1),onCreated:cn}),qa&&a.jsx(ci,{projectId:O,projects:n,onProjectChange:ue,onClose:()=>tt(!1),onConfirm:t=>void Ot(t)}),Ua&&a.jsx(ri,{projects:n,onClose:()=>Ke(!1),onRestart:t=>void Kt(t)}),st.dialog,Ge&&Z(Ge.sessionId)&&a.jsx(_i,{kind:Ge.kind,session:Z(Ge.sessionId),specOf:b,onIntegrate:k,onIntegrateSession:p,onClose:()=>$t(null)}),he&&a.jsx(te,{open:!0,title:"Ganti nama sesi",eyebrow:"terminal",width:420,onClose:()=>{_e||Re(null)},footer:a.jsxs(a.Fragment,{children:[a.jsx(L,{size:"sm",variant:"ghost",disabled:_e,onClick:()=>Re(null),children:"Batal"}),a.jsx(L,{size:"sm",leftIcon:"save",disabled:_e,onClick:()=>void Wt(),children:"Simpan"})]}),children:a.jsx(we,{label:"Nama sesi",hint:"Maksimal 80 karakter. Kosongkan untuk kembali ke nama otomatis.",children:a.jsx(St,{"aria-label":"Nama sesi",autoFocus:!0,maxLength:80,value:he.value,placeholder:Z(he.id)?be({...Z(he.id),name:void 0},Y,h):void 0,onChange:t=>Re({id:he.id,value:t.target.value}),onKeyDown:t=>{t.key==="Enter"&&Wt()}})})}),ie&&Z(ie)&&a.jsx(Wi,{session:Z(ie),label:be(Z(ie),Y,h),fontSize:J,showKeys:le,predict:q,diag:ae,screenReader:ne,onClose:()=>et(null)}),re&&Xa&&a.jsx(te,{open:!0,title:"Tampilan terminal",icon:"sliders",width:420,onClose:()=>Mt(!1),children:Qt}),Qa,a.jsx(qn,{toast:on})]})}function be(e,n,s){if(e.name)return e.name;const r=n(e.projectId),l=e.specId?s==null?void 0:s(e.specId):void 0;return e.specId?`${r} · ${e.specId}${l?` · ${l}`:""}`:e.id.startsWith("xaudit-")?`${r} · audit lintas`:r}function $i({seed:e,activeIds:n,error:s,onPick:r,onClose:l}){const[u,x]=d.useState(""),[g,N]=d.useState("all"),[h,k]=d.useState("all"),[p,b]=d.useState(e),[j,C]=d.useState(""),[E,A]=d.useState(null);d.useEffect(()=>{const f=setTimeout(()=>C(u.trim()),250);return()=>clearTimeout(f)},[u]),d.useEffect(()=>{var K,W;let f=!0;const M=(W=(K=F).listSpecs)==null?void 0:W.call(K,{startable:!0,q:j||void 0,stage:g==="all"?void 0:g,priority:h==="all"?void 0:h});return M==null||M.then(v=>{f&&(b(v.items),A(null))}).catch(v=>{f&&A(Q("memuat backlog",v))}),()=>{f=!1}},[j,g,h]);const R=p.filter(f=>!n.has(f.id)),y=s??E;return a.jsxs(te,{open:!0,title:"Ambil backlog",icon:"inbox",onClose:l,width:760,children:[y&&a.jsx("div",{role:"alert",className:"hn-terminal-pick-notice",children:y}),a.jsxs("div",{className:"hn-terminal-pick-filters",children:[a.jsx(St,{size:"sm",leftIcon:"search",placeholder:"mis. invoice atau SPEC-412","aria-label":"Cari backlog",value:u,onChange:f=>x(f.target.value),className:"hn-terminal-pick-search"}),a.jsx(ee,{size:"sm","aria-label":"Filter stage",value:g,onChange:f=>N(f.target.value),options:[{value:"all",label:"Semua stage"}].concat(Xn.filter(f=>f.key!=="done").map(f=>({value:f.key,label:f.label})))}),a.jsx(ee,{size:"sm","aria-label":"Filter prioritas",value:h,onChange:f=>k(f.target.value),options:[{value:"all",label:"Semua prioritas"},{value:"tinggi",label:"Tinggi"},{value:"sedang",label:"Sedang"},{value:"rendah",label:"Rendah"}]})]}),R.length===0?a.jsx(ze,{kind:"empty",icon:"inbox",title:"Tak ada backlog untuk diambil",hint:"Semua item sudah selesai/aktif atau tak cocok filter — buat brief baru di halaman Backlog."}):a.jsx("div",{className:"hn-terminal-pick-list",children:R.map(f=>a.jsx("button",{onClick:()=>r(f),className:"hn-terminal-pick-row",children:a.jsxs("span",{className:"hn-dense-row hn-picker-row hn-terminal-pick-main",children:[a.jsx(De,{name:f.source==="qa"?"bug":f.source==="audit"?"search":"lightbulb",size:14,color:f.source==="qa"?"var(--clay-500)":f.source==="audit"?"var(--wind-600)":"var(--brass-500)"}),a.jsx("span",{className:"hn-terminal-pick-id",children:f.id}),a.jsx("span",{className:"hn-picker-title hn-terminal-pick-title",children:f.title}),a.jsx(vt,{tone:f.priority==="tinggi"?"err":"neutral",size:"sm",children:f.priority}),a.jsx("span",{className:"hn-terminal-pick-project",children:f.projectId})]})},f.id))})]})}function Pi({ws:e,compact:n=!1,writable:s,onSelect:r,onAdd:l,onRename:u,onRemove:x}){const[g,N]=d.useState(null),h=$e(e),k=e.groups.length===1,b=Sa()?44:24;return a.jsxs("div",{className:n?"hn-terminal-groups":"hn-terminal-groups is-bordered",style:{"--group-box":`${b}px`},children:[a.jsx("div",{role:"tablist","aria-label":"Grup terminal",className:"hn-terminal-groups-tabs",children:e.groups.map((j,C)=>{const E=j.id===h.id;return a.jsx("button",{type:"button",role:"tab","aria-selected":E,tabIndex:E?0:-1,className:"hn-terminal-group-control hn-terminal-group-tab",onClick:()=>r(j.id),onKeyDown:A=>{var y,f;let R=null;A.key==="ArrowRight"?R=(C+1)%e.groups.length:A.key==="ArrowLeft"?R=(C-1+e.groups.length)%e.groups.length:A.key==="Home"?R=0:A.key==="End"&&(R=e.groups.length-1),R!==null&&(A.preventDefault(),r(e.groups[R].id),(f=(y=A.currentTarget.closest('[role="tablist"]'))==null?void 0:y.querySelectorAll('[role="tab"]')[R])==null||f.focus())},children:j.name},j.id)})}),s&&(g===h.id?a.jsx(Li,{initial:h.name,onCommit:j=>{j.trim()&&u(h.id,j.trim()),N(null)},onCancel:()=>N(null)},h.id):a.jsxs("span",{role:"group","aria-label":`Kelola grup ${h.name}`,className:"hn-terminal-groups-actions",children:[a.jsx("button",{type:"button",className:"hn-terminal-group-control hn-terminal-group-action","aria-label":`Ganti nama grup ${h.name}`,title:"Ganti nama",onClick:()=>N(h.id),children:"✎"}),a.jsx("button",{type:"button",className:"hn-terminal-group-control hn-terminal-group-action hn-terminal-group-remove","aria-label":`Hapus grup ${h.name}`,title:k?"Grup terakhir tak bisa dihapus":"Hapus grup (sesi tetap hidup)",disabled:k,onClick:()=>x(h.id),children:"×"})]})),a.jsx("button",{type:"button",className:"hn-terminal-group-control hn-terminal-group-action hn-terminal-group-add","aria-label":"Grup baru",title:"Grup baru",disabled:!s,onClick:l,children:"+"})]})}function ka({label:e,disabled:n,onClick:s,axis:r,gridColumn:l,gridRow:u}){return a.jsx("button",{type:"button","aria-label":e,title:n?"Grid tak boleh menyusut ke nol":e,disabled:n,onClick:s,className:`hn-terminal-gutter hn-terminal-gutter--${r}`,style:{"--grid-col":l,"--grid-row":u},children:"×"})}function xa({orientation:e,label:n,now:s,min:r,max:l,disabled:u,gridColumn:x,gridRow:g,onPointerDown:N,onPointerMove:h,onPointerUp:k,onKeyDown:p,onDoubleClick:b}){return a.jsx("div",{role:"separator","aria-label":n,"aria-disabled":u,"aria-orientation":e==="col"?"vertical":"horizontal","aria-valuenow":s,"aria-valuemin":r,"aria-valuemax":l,tabIndex:u?-1:0,className:`hn-terminal-divider hn-terminal-divider--${e}`,title:u?void 0:"Seret untuk ubah ukuran — panah untuk langkah kecil, Shift+panah langkah besar, klik dua kali menyamakan",style:{"--grid-col":x,"--grid-row":g},onPointerDown:u?void 0:N,onPointerMove:u?void 0:h,onPointerUp:u?void 0:k,onPointerCancel:u?void 0:k,onKeyDown:u?void 0:p,onDoubleClick:u?void 0:b})}function Li({initial:e,onCommit:n,onCancel:s}){const[r,l]=d.useState(e);return a.jsx("input",{autoFocus:!0,"aria-label":"Nama grup",value:r,placeholder:"mis. Rilis",onChange:u=>l(u.target.value),onBlur:()=>n(r),onKeyDown:u=>{u.key==="Enter"?n(r):u.key==="Escape"&&s()},className:"hn-terminal-rename"})}const Oi={done:"✓",running:"●",pending:"○",skipped:"–",failed:"✕",abandoned:"⨯"};function Oa({phases:e,compact:n=!1,now:s}){const[r,l]=d.useState(null),u=zn(r!==null,()=>l(null),"dialog"),[,x]=d.useState(0),g=!!(e!=null&&e.some(p=>{var b;return((b=p.agent)==null?void 0:b.status)==="running"}));if(d.useEffect(()=>{if(!(!g||s!==void 0))return ni(()=>x(p=>p+1))},[g,s]),!(e!=null&&e.length))return null;const N=s??Date.now(),h=e.find(p=>p.name===r&&p.agent),k=p=>{const b=p.agent;return b?typeof b.durationMs=="number"?sa(b.durationMs):b.status==="running"&&b.startedAt?sa(N-Date.parse(b.startedAt)):"":""};return a.jsxs("div",{"data-testid":"phase-strip",className:"hn-terminal-phase",children:[a.jsx("div",{"data-testid":"phase-strip-scroller",className:"hn-terminal-phase-scroller",children:e.map(p=>{if(!p.agent)return a.jsx("span",{"data-state":p.state,title:p.state,className:"hn-terminal-phase-name",children:p.name},p.name);const b=p.agent,j=Dn(p),C=!n||p.state==="active",E=k(p);return a.jsxs("button",{type:"button","data-tone":j,"aria-expanded":r===p.name,ref:r===p.name?u.triggerRef:void 0,"aria-haspopup":"dialog","aria-controls":r===p.name?u.panelId:void 0,"aria-label":Mn(p,E),onClick:()=>l(r===p.name?null:p.name),className:"hn-terminal-phase-chip",children:[a.jsx("span",{"aria-hidden":!0,children:Oi[j]}),a.jsx("span",{"data-state":p.state,title:p.state,className:"hn-terminal-phase-name",children:p.name}),p.state==="skipped"&&a.jsx("span",{children:"dilewati"}),C&&b.model&&a.jsxs("span",{children:["· ",yt(b.model)]}),C&&b.effort&&a.jsxs("span",{children:["· ",b.effort]}),C&&E&&a.jsxs("span",{children:["· ",E]}),(b.attempts??0)>1&&a.jsxs("span",{children:["↻",b.attempts]}),b.evidence==="missing"&&a.jsx("span",{role:"img","aria-label":"bukti subagent tak diterima",title:"bukti subagent tak diterima",className:"hn-terminal-phase-warn",children:"⚠"})]},p.name)})}),(h==null?void 0:h.agent)&&a.jsxs("div",{ref:u.panelRef,id:u.panelId,role:"dialog","aria-label":`Detail fase ${h.name}`,tabIndex:-1,onKeyDown:u.onKeyDown,className:"hn-terminal-phase-panel",children:[a.jsx("div",{children:a.jsx("b",{children:h.agent.name})}),a.jsx("div",{children:[yt(h.agent.model)||(h.agent.evidence==="unknown"?"model tidak diketahui":""),h.agent.effort??(h.agent.evidence==="unknown"?"effort tidak diketahui":""),h.agent.status??"belum mulai"].filter(Boolean).join(" · ")}),a.jsxs("div",{children:["durasi ",k(h)||(h.agent.evidence==="unknown"?"tidak diketahui":"—")," · percobaan ",h.agent.attempts??"tidak diketahui"]}),a.jsxs("div",{children:["token in ",h.agent.inputTokens??"tidak diketahui"," · out ",h.agent.outputTokens??"tidak diketahui"," · cache ",h.agent.cachedTokens??"tidak diketahui"]}),h.agent.resultExcerpt&&a.jsx("pre",{className:"hn-terminal-phase-excerpt",children:h.agent.resultExcerpt})]})]})}const Bi=d.memo(Ki);function Ki({session:e,nameOf:n,onClose:s,onForget:r,canArrange:l,onDetach:u,onExit:x,onReview:g,onSessionReview:N,titleOf:h,onIntegrate:k,onIntegrateSession:p,specOf:b,fontSize:j,showKeys:C,predict:E,diag:A,screenReader:R,fullscreen:y,onFullscreen:f,onDialog:M,onRename:K,paneHidden:W}){const[v,I]=d.useState(null),D=d.useRef(null),[w,o]=d.useState(Number.POSITIVE_INFINITY);d.useEffect(()=>{const q=D.current;if(!q||typeof ResizeObserver!="function")return;const xe=new ResizeObserver(ae=>{var ne;const Le=((ne=ae[0])==null?void 0:ne.contentRect.width)??q.getBoundingClientRect().width;Le>0&&o(Le)});return xe.observe(q),()=>xe.disconnect()},[]);const[T,V]=d.useState(!1),O=d.useCallback((q,xe)=>{I(q),V(xe)},[]),ue=be(e,n,h),Ie=!e.exited&&!!e.decision,ke=!e.exited&&!!e.deciding,re=Ie||ke,J=e.exited&&!!e.exitCode,de=!e.exited&&T,le=J?null:e.exited||de?"PST-005":re?"PST-004":"PST-003",Pe=Ba(e,{label:ue,canArrange:l,specOf:b,onReview:g,onSessionReview:N,onIntegrate:k,onIntegrateSession:p,onDialog:M,onDetach:u,onFullscreen:f,onRename:K});return a.jsxs(a.Fragment,{children:[a.jsxs("div",{className:e.exited?"hn-terminal-cell-header is-exited":"hn-terminal-cell-header","data-cell-tone":J?"failed":e.exited||de?"done":re?"attention":"idle",children:[le&&a.jsx("span",{className:"hn-terminal-cell-illus",children:a.jsx(ti,{id:le,decorative:!0})}),a.jsxs("span",{className:"hn-terminal-cell-title",children:[ue," · ",e.id.slice(0,6)]}),e.orchestrated&&e.model&&a.jsxs("span",{"data-testid":"orchestrator-chip",title:"Model & effort orchestrator",className:"hn-terminal-orch",children:["orch ",yt(e.model),e.effort?` · ${e.effort}`:""]}),e.exited&&(J?a.jsx(ge,{status:"failed",size:"sm",children:`Gagal · exit ${e.exitCode}`}):a.jsx(ge,{status:"done",size:"sm",children:"Selesai"})),de&&a.jsx(ge,{status:"done",size:"sm",children:"Selesai"}),ke&&!de&&a.jsx(ge,{status:"running",size:"sm",children:"Lead memutuskan"}),Ie&&!ke&&!de&&a.jsx(ge,{status:"awaiting",size:"sm"}),a.jsxs("span",{className:"hn-terminal-actions",children:[a.jsx(Ne,{label:`Aksi sesi ${e.id}`,items:Pe}),a.jsx("button",{type:"button",className:"hn-terminal-action","aria-label":`Tutup sesi ${e.id}`,title:"Tutup sesi (dikonfirmasi dulu)",onClick:s,children:a.jsx(De,{name:"x",size:12})})]})]}),a.jsxs("div",{ref:D,className:"hn-terminal-cell-body",children:[e.exited&&a.jsx(Rt,{}),a.jsx(Oa,{phases:v,compact:w<480}),a.jsx("div",{className:"hn-terminal-cell-pane",children:y?a.jsx("div",{className:"hn-terminal-cell-fullscreen",children:"Terbuka di layar penuh"}):a.jsx(Nt,{sessionId:e.id,onExit:x,onPhases:O,fontSize:j,showKeys:C,predict:E,diag:A,screenReader:R,hidden:W,onForget:r,label:be(e,n,h)},e.id)})]})]})}function Ba(e,n){var x;const s=[],r=e.specId?(x=n.specOf)==null?void 0:x.call(n,e.specId):void 0,l=!e.specId&&!!e.branch;e.specId&&s.push({key:"docs",label:"Lihat dokumen",icon:"file-text",title:"Lihat dokumen (audit/spec/plan)",onSelect:()=>n.onDialog("docs")});const u=e.specId;if(u&&n.onReview){const g=n.onReview;s.push({key:"review",label:"Review perubahan",icon:"git-compare",title:"Review perubahan (diff worktree)",onSelect:()=>g(u)})}if(l&&n.onSessionReview){const g=n.onSessionReview;s.push({key:"review-session",label:"Review perubahan",icon:"git-compare",title:"Review perubahan (diff worktree sesi)",onSelect:()=>g(e.id,n.label)})}return r&&n.onIntegrate&&s.push({key:"integrate",label:"Rebase / Merge branch",icon:"git-merge",title:"Rebase / Merge branch spec",onSelect:()=>n.onDialog("integrate")}),l&&n.onIntegrateSession&&s.push({key:"integrate-session",label:"Rebase / Merge branch",icon:"git-merge",title:"Rebase / Merge branch sesi",onSelect:()=>n.onDialog("sessIntegrate")}),n.onRename&&s.push({key:"rename",label:"Ganti nama",icon:"pencil",title:"Beri nama kustom pada sesi ini",onSelect:n.onRename}),s.push({key:"detach",label:"Lepas dari grid",icon:"unlink",disabled:!n.canArrange,title:"Lepas dari grid (sesi tetap hidup)",onSelect:n.onDetach}),s.push({key:"fullscreen",label:"Layar penuh",icon:"fullscreen",title:"Layar penuh — fokus 1 terminal",onSelect:n.onFullscreen}),n.onKill&&s.push({key:"close",label:"Tutup sesi",icon:"square",tone:"danger",title:"Tutup sesi (dikonfirmasi dulu)",onSelect:n.onKill}),s}function _i({kind:e,session:n,specOf:s,onIntegrate:r,onIntegrateSession:l,onClose:u}){if(e==="docs")return n.specId?a.jsx(ei,{specId:n.specId,onClose:u}):null;if(e==="integrate"){const x=n.specId?s==null?void 0:s(n.specId):void 0;return!x||!r?null:a.jsx(ra,{projectId:x.projectId,ownBranch:`hanoman/${x.id.toLowerCase().replace(/[^a-z0-9_-]/g,"_")}`,eyebrow:x.id,onClose:u,onIntegrate:(g,N)=>{u(),r(x,g,N)}})}return!n.branch||n.specId||!l?null:a.jsx(ra,{projectId:n.projectId,ownBranch:n.branch,eyebrow:n.id.slice(0,16),onClose:u,onIntegrate:(x,g)=>{u(),l(n,x,g)}})}const va="Buka sesi lain: ambil backlog, riwayat sesi, atau terminal biasa";function ya({items:e,compact:n=!1}){const[s,r]=d.useState(!1);return a.jsxs(a.Fragment,{children:[n?a.jsxs("button",{type:"button",className:"hn-terminal-open-compact","aria-label":"Buka…",title:va,"aria-haspopup":"dialog","aria-expanded":s,onClick:()=>r(!0),children:[a.jsx(De,{name:"folder-open",size:16}),a.jsx("span",{className:"hn-terminal-open-text",children:"Buka…"})]}):a.jsx(L,{size:"sm",variant:"ghost","aria-haspopup":"dialog","aria-expanded":s,title:va,onClick:()=>r(!0),children:"Buka…"}),s&&a.jsx(te,{open:!0,title:"Buka sesi",icon:"terminal",width:420,onClose:()=>r(!1),children:a.jsx("div",{className:"hn-terminal-menu-list",children:e.map(l=>a.jsxs("button",{type:"button",disabled:l.disabled,title:l.title,className:"hn-overflow-item",onClick:()=>{r(!1),l.onSelect()},children:[l.icon&&a.jsx(De,{name:l.icon,size:15}),l.label]},l.key))})})]})}function Gi({sessionCount:e,focused:n,railItems:s,mobile:r,listError:l,menuFor:u,onFocus:x,drawerOpen:g,onDrawer:N,fullId:h,focusPhases:k,paneHandlers:p,fontSize:b,showKeys:j,onToggleKeys:C,predict:E,diag:A,screenReader:R}){const y=n?s.find(f=>f.session.id===n.id):void 0;return a.jsxs("div",{className:"hn-terminal-focus","data-testid":"terminal-focus",children:[!r&&e>0&&a.jsxs("aside",{className:"hn-terminal-rail","aria-label":"Sesi terminal",children:[a.jsxs("div",{className:"hn-terminal-rail-head",children:[a.jsx("span",{children:"Sesi"}),a.jsx("span",{children:e})]}),a.jsx("div",{className:"hn-terminal-rail-scroll",children:a.jsx(ba,{items:s,focusedId:(n==null?void 0:n.id)??null,onFocus:x,menuFor:u})})]}),a.jsx("section",{className:"hn-terminal-focus-main","aria-label":"Terminal fokus",children:n&&y?a.jsxs(a.Fragment,{children:[a.jsxs("header",{className:"hn-terminal-focus-head",children:[a.jsxs("span",{className:"hn-terminal-focus-title",title:y.label,children:[y.label," · ",n.id.slice(0,6)]}),a.jsx(ge,{status:La[y.status.tone],size:"sm",variant:"dot",children:y.status.label}),a.jsx(Ne,{label:`Aksi sesi ${n.id}`,items:u(n)})]}),n.exited&&a.jsx(Rt,{}),a.jsx(Oa,{compact:r,phases:(k==null?void 0:k.sessionId)===n.id?k.phases:null}),a.jsx("div",{className:"hn-terminal-focus-body",children:h===n.id?a.jsx("div",{className:"hn-terminal-focus-placeholder",children:"Terbuka di layar penuh"}):a.jsx(Nt,{sessionId:n.id,...p(n.id),fontSize:b,showKeys:j,predict:E,diag:A,screenReader:R,composer:!0,compact:r,onToggleKeys:C,label:y.label},n.id)})]}):l?null:a.jsx(ze,{kind:"empty",icon:"terminal",title:"Belum ada sesi terminal",hint:"Tekan Sesi baru untuk memulai agen di project terpilih, atau Terminal biasa untuk shell."})}),r&&g&&a.jsx(te,{open:!0,title:"Sesi terminal",icon:"terminal",width:460,onClose:()=>N(!1),children:a.jsx(ba,{items:s,focusedId:(n==null?void 0:n.id)??null,onFocus:f=>{x(f),N(!1)},menuFor:u})})]})}function Rt(){return a.jsxs("div",{role:"status","data-testid":"terminal-ended",className:"hn-terminal-ended",children:[a.jsx("strong",{className:"hn-terminal-ended-title",children:"Berakhir"}),a.jsx("span",{className:"hn-terminal-ended-body",children:"Agen sudah berhenti. Output tetap bisa dibaca; tutup sel bila tak diperlukan lagi."})]})}function Wi({session:e,label:n,fontSize:s,showKeys:r,predict:l,diag:u,screenReader:x,onClose:g}){return a.jsx(te,{open:!0,icon:"terminal",title:n,onClose:g,closeOnEscape:!1,width:1600,children:a.jsxs("div",{className:"hn-terminal-fullscreen-body",children:[e.exited&&a.jsx(Rt,{}),a.jsx(Nt,{sessionId:e.id,onExit:()=>{},fontSize:s,showKeys:r,predict:l,diag:u,screenReader:x},e.id)]})})}function qi({unplaced:e,nameOf:n,onPick:s,disabled:r}){return a.jsx("div",{className:"hn-terminal-empty-cell",children:a.jsx(ee,{size:"sm",value:"","aria-label":"Pilih sesi untuk sel",disabled:r||!e.length,onChange:l=>l.target.value&&s(l.target.value),options:[{value:"",label:e.length?"Pilih sesi…":"tidak ada sesi bebas"}].concat(e.map(l=>({value:l.id,label:`${l.specId??n(l.projectId)} · ${l.id.slice(0,6)}`})))})})}export{Oa as PhaseStrip,Xi as TerminalScreen,Ba as sessionMenuItems};
@@ -1 +1 @@
1
- import{q as X,r as De,J as dt,d as Ke,p as ht,h as p,K as mt,G as kt,j as e,w as _e,e as Z,g as ce,L as pt,m as _,N as gt,R as bt,C as Ae,B as f,n as qe,x as ft,y as jt,Q as xt,U as yt,z as vt,D as ze,V as wt,i as St,W as Ct,X as It,Y as Tt,Z as we,_ as ke,O as Me,f as Nt,H as Pt,$ as Ge,a0 as $t,a1 as Lt,a2 as Et,b as Bt}from"./index-BQw6xQI4.js";import{R as l}from"./react-DfGhg7ZW.js";import{L as Rt}from"./live-CONO0GTu.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";function Dt(a,r){return a==="rejected"?"Ditutup":a!=="accepted"?"Sedang ditinjau":r==="done"?"Selesai":r==="executing"?"Sedang dikerjakan":"Diterima"}const At=5e3,Y=20,zt=400,Gt=6e3,Ht=[{key:"new",label:"Belum ditinjau"},{key:"accepted",label:"Diterima"},{key:"rejected",label:"Ditutup"}],Kt={new:"drift",accepted:"ok",rejected:"idle"},oe=gt,me={semua:"Semua sumber",tiket:"Help Center",issue:"GitHub"},Oe=a=>{var d;const r=(d=a==null?void 0:a.detail)==null?void 0:d.error;if(typeof r=="string"&&r.trim())return r;const h=a==null?void 0:a.status;return typeof h=="number"?`server menolak permintaan (HTTP ${h})`:a instanceof Error?a.message:""},w=(a,r)=>St(a,new Error(Oe(r))),pe=(a,r=Date.now())=>Lt(a,r)||"—",Se=(a,r)=>`${a==="tiket"?"t":"i"}:${r}`;function _t(a,r){return{key:Se("tiket",a.id),kind:"tiket",id:a.id,number:a.number,title:a.title,status:a.status,specId:a.specId,at:a.createdAt,meta:[`#${a.number}`,a.category,r(a.projectId),a.reporterEmail,pe(a.createdAt),...a.attachmentCount>0?[`${a.attachmentCount} lampiran`]:[],...a.specId?[`→ ${a.specId}`]:[]]}}function qt(a,r){return{key:Se("issue",a.id),kind:"issue",id:a.id,number:a.number,title:a.title,status:a.status,specId:a.specId,at:a.issueCreatedAt,meta:[`#${a.number}`,`@${a.authorLogin}`,...a.labels,r(a.projectId),pe(a.issueCreatedAt),...a.specId?[`→ ${a.specId}`]:[]]}}function Mt({page:a,pageCount:r,onPage:h}){return r<=1?null:e.jsxs("div",{className:"hn-triage-footer",children:[e.jsxs("span",{children:["Halaman ",a," dari ",r," · tiket dan issue"]}),e.jsxs("span",{className:"hn-triage-acts",children:[e.jsx(f,{size:"sm",variant:"ghost","aria-label":"Sebelumnya",disabled:a<=1,onClick:()=>h(a-1),children:"Sebelumnya"}),e.jsx(f,{size:"sm",variant:"ghost","aria-label":"Berikutnya",disabled:a>=r,onClick:()=>h(a+1),children:"Berikutnya"})]})]})}function He({total:a,page:r,onPage:h,unit:d="tiket"}){const j=we(a,r,Y);return e.jsx(Et,{page:j.page,pageCount:j.pageCount,total:a,from:j.from,to:j.to,onPage:h,unit:d})}function Ot({row:a,selected:r,picked:h,busy:d,onOpen:j,onPick:R,onAccept:g,onReject:N}){const D=a.status==="new",S=a.kind==="tiket"?"tiket":"issue";return e.jsxs(It,{selected:r,onClick:j,actions:e.jsxs(e.Fragment,{children:[D&&e.jsx("label",{className:"hn-triage-check hn-touch-target",children:e.jsx("input",{type:"checkbox","aria-label":`Pilih ${S} ${a.number}`,checked:h,onChange:R})}),e.jsx(qe,{tone:"neutral",size:"sm",children:a.kind==="tiket"?"Help Center":"GitHub"}),D&&e.jsxs(e.Fragment,{children:[e.jsx(f,{size:"sm","aria-label":`Terima ${S} ${a.number}`,disabled:d,onClick:g,children:"Terima"}),e.jsx(f,{size:"sm",variant:"ghost","aria-label":`Tolak ${S} ${a.number}`,disabled:d,onClick:N,children:"Tolak"})]})]}),children:[e.jsxs("span",{className:"hn-triage-title-line",children:[e.jsx(Tt,{variant:"dot",status:Kt[a.status],children:oe[a.status]}),e.jsx("span",{className:"hn-triage-title",children:a.title})]}),e.jsx("span",{className:"hn-triage-meta",children:a.meta.join(" · ")})]})}function Fe(a,r){const h=Bt();l.useEffect(()=>{if(h!=="mobile"||!a)return;const d=j=>{j.key!=="Escape"||document.querySelector('[role="dialog"]')||r()};return window.addEventListener("keydown",d),()=>window.removeEventListener("keydown",d)},[h,a,r])}function Ft({id:a,projectName:r,onBack:h,onAccepted:d,onDeleted:j,onReject:R,onToast:g}){var E;const[N,D]=l.useState(null),[S,z]=l.useState("loading"),[y,x]=l.useState(!1),[C,ge]=l.useState("sedang"),[V,J]=l.useState(!1),[q,M]=l.useState(!1),{confirm:ee,dialog:O}=Ke(),[u,P]=l.useState({title:"",detail:"",category:"bug",status:"new"}),I=l.useCallback(()=>{p.getTicket(a).then(o=>{D(o),z("ready")}).catch(()=>z("error"))},[a]);if(l.useEffect(()=>{I()},[I]),Fe(!V,h),S==="loading")return e.jsx(_,{kind:"loading"});if(S==="error"||!N)return e.jsx(_,{kind:"error",hint:"Gagal memuat tiket.",action:I,actionLabel:"Coba lagi"});const c=N,Q=!!c.specId,te=c.status!=="new",ue=u.title!==c.title||u.detail!==c.detail||u.category!==c.category||u.status!==c.status;async function ae(){x(!0);try{const o=await p.acceptTicket(a,C);d(o.spec,!!o.alreadyPromoted)}catch(o){g(w("menerima tiket",o),"err","x-circle")}finally{x(!1)}}async function F(){x(!0);try{await R(a),I()}finally{x(!1)}}async function de(o,k){try{await navigator.clipboard.writeText(o),g(k,"ok","copy")}catch(U){g(w("menyalin link",U),"err","x-circle")}}async function be(){x(!0);try{const o=await p.unlinkTicket(a);D({...c,specId:o.specId,spec:null,status:o.status}),g("Tautan backlog dilepas","ok","unlink")}catch(o){g(w("melepas tautan",o),"err","x-circle")}finally{x(!1)}}function A(){P({title:c.title,detail:c.detail,category:c.category,status:c.status}),J(!0)}async function fe(){ue&&!await ee({title:"Buang perubahan?",message:"Perubahan pada tiket ini belum disimpan.",impact:["Judul, detail, kategori, dan status kembali ke nilai tersimpan."],confirmLabel:"Buang perubahan",tone:"danger"})||J(!1)}async function L(){if(u.title.trim()){x(!0);try{const o=await p.editTicket(a,{title:u.title,detail:u.detail,category:u.category,status:u.status});D(o),J(!1),g("Tiket diperbarui","ok")}catch(o){g(w("menyimpan tiket",o),"err","x-circle")}finally{x(!1)}}}async function ie(){x(!0);try{await p.deleteTicket(a),g("Tiket dihapus","ok","trash-2"),j()}catch(o){g(w("menghapus tiket",o),"err","x-circle"),x(!1)}}if(V){const o=!u.title.trim();return e.jsxs("div",{className:"hn-triage-detail",children:[e.jsx("div",{className:"hn-triage-detail-scroll",children:e.jsxs(_e,{gap:4,children:[e.jsxs("div",{className:"hn-triage-status-row",children:[e.jsx(f,{size:"sm",variant:"ghost",leftIcon:"arrow-left",onClick:()=>void fe(),disabled:y,children:"Batal"}),e.jsx(f,{size:"sm",variant:"primary",leftIcon:"check",onClick:L,disabled:y||o,children:"Simpan"})]}),e.jsx(Z,{label:"Judul",error:o?"Judul tiket wajib diisi.":void 0,children:e.jsx(Nt,{value:u.title,invalid:o,placeholder:"mis. Tombol Simpan tak berfungsi di HP",onChange:k=>P({...u,title:k.target.value})})}),e.jsxs("div",{className:"hn-triage-status-row",children:[e.jsx(Z,{label:"Kategori",children:e.jsx(ce,{value:u.category,onChange:k=>P({...u,category:k.target.value}),options:[{value:"bug",label:"bug"},{value:"fitur",label:"fitur"},{value:"pertanyaan",label:"pertanyaan"},{value:"lainnya",label:"lainnya"}]})}),e.jsx(Z,{label:"Status",children:e.jsx(ce,{value:u.status,onChange:k=>P({...u,status:k.target.value}),options:[{value:"new",label:oe.new},{value:"accepted",label:oe.accepted},{value:"rejected",label:oe.rejected}]})})]}),e.jsx(Z,{label:"Detail keluhan",children:e.jsx(Pt,{value:u.detail,rows:6,placeholder:"mis. Buka halaman Pesanan di HP, tekan Simpan — layar diam dan datanya tak tersimpan.",onChange:k=>P({...u,detail:k.target.value})})})]})}),O]})}const m=c.publicStatusUrl,se=[{key:"edit",label:"Edit",icon:"pencil",onSelect:A,disabled:y},...m?[{key:"public-open",label:"Buka status publik",icon:"share-2",onSelect:()=>window.open(m,"_blank","noreferrer")},{key:"public-copy",label:"Salin link publik",icon:"link-2",onSelect:()=>void de(m,"Link publik disalin")}]:[],...Q?[{key:"spec-copy",label:"Salin link backlog",icon:"copy",onSelect:()=>void de(ke(c.specId),"Link backlog disalin")},{key:"unlink",label:"Lepas tautan",icon:"unlink",onSelect:()=>void be(),disabled:y}]:[],{key:"delete",label:"Hapus",icon:"trash-2",onSelect:()=>M(!0),disabled:y}];return e.jsxs("div",{className:"hn-triage-detail",children:[e.jsx("div",{className:"hn-triage-detail-scroll",children:e.jsxs("div",{className:"hn-triage-detail-body",children:[e.jsxs("div",{children:[e.jsxs("span",{className:"hn-triage-meta",children:["#",c.number," · ",c.category]}),e.jsx("h2",{className:"hn-triage-detail-title",children:c.title})]}),e.jsxs("ul",{className:"hn-triage-facts",children:[e.jsxs("li",{children:["pelapor: ",e.jsx("b",{children:c.reporterEmail})]}),e.jsxs("li",{children:["project: ",e.jsx("b",{children:r(c.projectId)})]}),e.jsxs("li",{children:["masuk ",pe(c.createdAt)]}),Q&&e.jsxs("li",{children:["backlog: ",e.jsx("b",{children:c.specId})," · ",e.jsx("span",{children:Dt(c.status,(E=c.spec)==null?void 0:E.stage)})]})]}),e.jsxs("div",{children:[e.jsx("h3",{className:"hn-eyebrow hn-triage-section-title",children:"Detail keluhan"}),e.jsx("div",{className:"hn-triage-body-text",children:c.detail})]}),c.attachments.length>0&&e.jsxs("details",{className:"hn-triage-disclosure",open:!0,children:[e.jsxs("summary",{children:["Lampiran (",c.attachments.length,")"]}),e.jsx("ul",{className:"hn-triage-attachments",children:c.attachments.map(o=>e.jsx("li",{children:e.jsx("a",{href:Ge.ticketAttachment(c.id,o.id),target:"_blank",rel:"noreferrer",className:"hn-triage-attachment-link",children:e.jsx("img",{src:Ge.ticketAttachment(c.id,o.id),alt:o.filename})})},o.id))})]})]})}),e.jsxs("div",{className:"hn-triage-decision",role:"group","aria-label":"Keputusan",children:[Q?e.jsx(f,{size:"sm",leftIcon:"external-link",onClick:()=>window.open(ke(c.specId),"_blank","noreferrer"),children:"Buka backlog"}):!te&&e.jsxs(e.Fragment,{children:[e.jsx(f,{size:"sm",leftIcon:"arrow-up-right",onClick:ae,disabled:y,children:"Terima → backlog"}),e.jsx(f,{size:"sm",variant:"secondary",leftIcon:"ban",onClick:F,disabled:y,children:"Tolak"}),e.jsx(ce,{size:"sm",value:C,"aria-label":"Prioritas tiket",onChange:o=>ge(o.target.value),options:[{value:"tinggi",label:"Prioritas tinggi"},{value:"sedang",label:"Prioritas sedang"},{value:"rendah",label:"Prioritas rendah"}]})]}),e.jsx("span",{className:"hn-triage-decision-spacer"}),e.jsx(Me,{label:"Aksi lainnya",items:se})]}),e.jsx($t,{open:q,title:"Hapus tiket?",eyebrow:`#${c.number}`,confirmLabel:"Hapus tiket",message:`Tiket "${c.title}" dan seluruh lampirannya akan dihapus permanen. Tindakan ini tak bisa dibatalkan.`,busy:y,onCancel:()=>M(!1),onConfirm:ie}),O]})}function Ut({issue:a,projectName:r,onBack:h,onAccepted:d,onReject:j,onToast:R}){const[g,N]=l.useState(!1);Fe(!0,h);const D=a.status==="new",S=!!a.specId;async function z(){N(!0);try{const C=await p.acceptGithubIssue(a.id);d(C.spec,!!C.alreadyPromoted)}catch(C){R(w("menerima issue",C),"err","x-circle")}finally{N(!1)}}async function y(){N(!0);try{await j(a)}finally{N(!1)}}const x=[{key:"gh",label:"Buka di GitHub",icon:"external-link",onSelect:()=>window.open(a.url,"_blank","noreferrer")},...S?[{key:"spec-copy",label:"Salin link backlog",icon:"copy",onSelect:()=>{navigator.clipboard.writeText(ke(a.specId)).then(()=>R("Link backlog disalin","ok","copy"),C=>R(w("menyalin link",C),"err","x-circle"))}}]:[]];return e.jsxs("div",{className:"hn-triage-detail",children:[e.jsx("div",{className:"hn-triage-detail-scroll",children:e.jsxs("div",{className:"hn-triage-detail-body",children:[e.jsxs("div",{children:[e.jsxs("span",{className:"hn-triage-meta",children:["#",a.number," · @",a.authorLogin]}),e.jsx("h2",{className:"hn-triage-detail-title",children:a.title})]}),e.jsxs("ul",{className:"hn-triage-facts",children:[e.jsxs("li",{children:["project: ",e.jsx("b",{children:r(a.projectId)})]}),e.jsxs("li",{children:["repo: ",e.jsx("b",{children:a.repoSlug})]}),e.jsxs("li",{children:["dibuat ",pe(a.issueCreatedAt)]}),a.labels.length>0&&e.jsxs("li",{children:["label: ",e.jsx("b",{children:a.labels.join(", ")})]}),S&&e.jsxs("li",{children:["backlog: ",e.jsx("b",{children:a.specId})]})]}),e.jsxs("div",{children:[e.jsx("h3",{className:"hn-eyebrow hn-triage-section-title",children:"Isi issue"}),e.jsx("div",{className:"hn-triage-body-text",children:a.body||"Tanpa isi."})]})]})}),e.jsxs("div",{className:"hn-triage-decision",role:"group","aria-label":"Keputusan",children:[D&&e.jsxs(e.Fragment,{children:[e.jsx(f,{size:"sm",leftIcon:"arrow-up-right",onClick:z,disabled:g,children:"Terima → backlog"}),e.jsx(f,{size:"sm",variant:"secondary",leftIcon:"ban",onClick:y,disabled:g,children:"Tolak"})]}),S&&e.jsx(f,{size:"sm",leftIcon:"external-link",onClick:()=>window.open(ke(a.specId),"_blank","noreferrer"),children:"Buka backlog"}),e.jsx("span",{className:"hn-triage-decision-spacer"}),e.jsx(Me,{label:"Aksi lainnya",items:x})]})]})}function Zt({projects:a,onAccepted:r,onToast:h}){const d=l.useCallback(t=>{var s;return((s=a.find(n=>n.id===t))==null?void 0:s.name)??t},[a]),[j,R]=l.useState([]),[g,N]=l.useState(0),[D,S]=l.useState(0),[z,y]=l.useState([]),[x,C]=l.useState(0),[ge,V]=l.useState(0),[J,q]=l.useState(!1),[M,ee]=l.useState(null),[O,u]=l.useState(null),[P,I]=l.useState(!1),[c,Q]=l.useState(null),[te,ue]=l.useState(null),[ae,F]=l.useState([]),[de,be]=l.useState(0),[A,fe]=X("triage","status","new",De("new","accepted","rejected")),[L,ie]=X("triage","source","semua",De("semua","tiket","issue")),[m,se]=X("triage","project","",ze),[E,o]=X("triage","q","",ze),[k,U]=X("triage","page",1,wt),[$,G]=X("triage","openId",null,Ct),Ce=[m!=="",L!=="semua",E.trim()!==""].filter(Boolean).length,H=L!=="issue",W=L!=="tiket"&&m!=="",Ie=dt("triage","scroll",J),Te=l.useRef(null),Ue=l.useCallback(t=>{Te.current=t,Ie(t)},[Ie]),{confirm:Ne,dialog:Ve}=Ke(),[Je,B]=ht(),[je,Qe]=l.useState(E);l.useEffect(()=>{const t=setTimeout(()=>Qe(E),zt);return()=>clearTimeout(t)},[E]);const he=l.useRef(0),ne=l.useRef(0),T=l.useCallback((t=!1)=>{const s=++he.current,n=++ne.current;if(p.listTickets({project:m||void 0,status:A,q:je||void 0,page:String(k),limit:String(H?Y:1)}).then(i=>{s===he.current&&(R(H?i.items:[]),N(H?i.total:0),S(i.unreviewed),ee(null),q(!0))},i=>{s===he.current&&(t||ee(w("memuat tiket",i)),q(!0))}),!m){y([]),C(0),V(0),u(null);return}W?p.listGithubIssues(m,{status:A,page:k,limit:Y}).then(i=>{n===ne.current&&(y(i.items),C(i.total),u(null),q(!0))},i=>{n===ne.current&&(t||u(w("memuat issue",i)),q(!0))}):(y([]),C(0),u(null)),p.listGithubIssues(m,{status:"new",limit:1}).then(i=>{n===ne.current&&V(i.total)},()=>{n===ne.current&&V(null)})},[m,A,je,k,H,W]);l.useEffect(()=>{T()},[T]),mt(JSON.stringify([m,L,A,E]),()=>{U(1),F([])});const Pe=()=>{se(""),ie("semua"),o(""),U(1)};kt({topic:"tickets",params:{project:m||void 0,status:A,q:je||void 0,page:k,limit:Y},apply:t=>{he.current++,R(t.data.items),N(t.data.total),S(t.data.unreviewed),ee(null),q(!0)},refetch:()=>T(!0),pollMs:At});const v=l.useMemo(()=>{const t=E.trim().toLowerCase(),s=H?j.map(i=>_t(i,d)):[],n=W?z.filter(i=>!t||`${i.number} ${i.title} ${i.authorLogin} ${i.labels.join(" ")}`.toLowerCase().includes(t)).map(i=>qt(i,d)):[];return[...s,...n].sort((i,b)=>Date.parse(b.at)-Date.parse(i.at))},[j,z,H,W,E,d]),We=l.useMemo(()=>new Map(v.map(t=>[t.key,t])),[v]),le=$?We.get($):void 0,xe=new Set(ae),$e=D+(ge??0);async function ye(t){const s=await Promise.allSettled(t.map(b=>p.rejectTicket(b))),n=t.filter((b,K)=>s[K].status==="fulfilled"),i=s.find(b=>b.status==="rejected");n.length>0&&B(n.length===1?"Tiket ditolak":`${n.length} tiket ditolak`,"ok","ban",{action:{label:"Urungkan",onAction:()=>void Xe(n)},duration:Gt}),i&&B(w("menolak tiket",i.reason),"err","x-circle"),T(!0)}async function Xe(t){const n=(await Promise.allSettled(t.map(i=>p.editTicket(i,{status:"new"})))).filter(i=>i.status==="fulfilled").length;be(i=>i+1),T(!0),n===t.length?B("Penolakan dibatalkan","ok","check"):B(`${n} dari ${t.length} penolakan dibatalkan`,"err","x-circle")}async function Le(t){I(!0);try{const s=t.kind==="tiket"?await p.acceptTicket(t.id,"sedang"):await p.acceptGithubIssue(t.id),n=s.spec.id;B(s.alreadyPromoted?`Sudah jadi ${n}`:`Diterima → ${n}`,"ok","arrow-up-right"),T(!0)}catch(s){B(w("menerima "+(t.kind==="tiket"?"tiket":"issue"),s),"err","x-circle")}finally{I(!1)}}async function Ee(t){await Ne({title:`Tolak issue #${t.number}?`,message:t.title,impact:["Issue ditandai ditutup di hanoman.","Issue di GitHub tidak diubah."],confirmLabel:"Tolak issue",tone:"danger",icon:"x-circle",run:async()=>{await p.rejectGithubIssue(t.id),T(!0)}}).catch(s=>B(w("menolak issue",s),"err","x-circle"))}async function Be(t){if(t.kind==="tiket"){I(!0);try{await ye([t.id])}finally{I(!1)}return}const s=z.find(n=>n.id===t.id);s&&await Ee(s)}async function Ye(){const t=v.filter(i=>xe.has(i.key)&&i.status==="new"),s=t.filter(i=>i.kind==="tiket"),n=t.filter(i=>i.kind==="issue");I(!0);try{const i=await Promise.allSettled(s.map(re=>p.acceptTicket(re.id,"sedang"))),b=n.length?await p.acceptGithubIssues(n.map(re=>re.id),void 0):null,K=i.filter(re=>re.status==="fulfilled").length,ut=(b==null?void 0:b.created.length)??0,ve=i.length-K+((b==null?void 0:b.failed.length)??0);B(`${K+ut} diterima${ve?` · ${ve} gagal`:""}`,ve?"err":"ok","arrow-up-right"),F([]),T(!0)}catch(i){B(w("menerima yang dipilih",i),"err","x-circle")}finally{I(!1)}}async function Ze(){const t=v.filter(s=>xe.has(s.key)&&s.status==="new");t.length!==0&&await Ne({title:`Tolak ${t.length} item?`,message:"Item berikut ditandai ditutup di hanoman. Issue di GitHub tidak diubah.",impact:t.map(s=>`${s.kind==="tiket"?"Tiket":"Issue"} #${s.number}: ${s.title}`),confirmLabel:`Tolak ${t.length} item`,tone:"danger",icon:"x-circle",run:async()=>{const s=t.filter(i=>i.kind==="tiket").map(i=>i.id),n=t.filter(i=>i.kind==="issue").map(i=>i.id);if(s.length&&await ye(s),n.length){const b=(await Promise.allSettled(n.map(K=>p.rejectGithubIssue(K)))).filter(K=>K.status==="fulfilled").length;B(`${b} issue ditolak`,"ok","ban")}F([]),T(!0)}}).catch(s=>B(w("menolak yang dipilih",s),"err","x-circle"))}async function et(){if(m){I(!0),ue(null),Q(null);try{const t=await p.pullGithubIssues(m);Q(`${t.repo}: ${t.created} baru, ${t.updated} diperbarui`+(t.skippedPullRequests?` · ${t.skippedPullRequests} pull request dilewati`:"")),T(!0)}catch(t){ue(`Gagal menarik issue: ${Oe(t)}`)}finally{I(!1)}}}const tt=t=>F(s=>s.includes(t)?s.filter(n=>n!==t):[...s,t]),at=t=>{var n,i;const s=v.findIndex(b=>b.key===t);(i=(n=Te.current)==null?void 0:n.querySelectorAll("button.hn-row-main")[s])==null||i.focus()},it=t=>{if(v.length===0)return;const s=v.findIndex(i=>i.key===$),n=v[s<0?t>0?0:v.length-1:Math.min(v.length-1,Math.max(0,s+t))];n&&(G(n.key),at(n.key))},st=t=>{if(t.defaultPrevented||t.ctrlKey||t.metaKey||t.altKey||t.target.closest("input, textarea, select, [contenteditable='true']")||document.querySelector('[role="dialog"]'))return;if(t.key==="Escape"){$&&(t.preventDefault(),G(null));return}const n=t.key.toLowerCase();if(n==="j"||n==="k"){t.preventDefault(),it(n==="j"?1:-1);return}!le||le.status!=="new"||P||(n==="a"?(t.preventDefault(),Le(le)):n==="r"&&(t.preventDefault(),Be(le)))},nt=[...m?[{key:"project",label:`Project: ${d(m)}`,onRemove:()=>se("")}]:[],...L!=="semua"?[{key:"source",label:`Sumber: ${me[L]}`,onRemove:()=>ie("semua")}]:[]],lt=e.jsxs(_e,{gap:3,children:[e.jsx(Z,{label:"Project",children:e.jsx(ce,{size:"sm",value:m,"aria-label":"Project triase",onChange:t=>se(t.target.value),options:[{value:"",label:"Semua project"},...a.map(t=>({value:t.id,label:t.name}))]})}),e.jsx(Z,{label:"Sumber",children:e.jsx(ce,{size:"sm",value:L,"aria-label":"Sumber triase",onChange:t=>ie(t.target.value),options:[{value:"semua",label:me.semua},{value:"tiket",label:me.tiket},{value:"issue",label:me.issue}]})})]}),rt=H&&W?e.jsx(Mt,{page:k,pageCount:Math.max(we(g,k,Y).pageCount,we(x,k,Y).pageCount),onPage:U}):H?e.jsx(He,{total:g,page:k,onPage:U}):W?e.jsx(He,{total:x,page:k,onPage:U,unit:"issue"}):null,ct=J?v.length===0&&(M||O)?e.jsx(_,{kind:"error",hint:M??O??"Gagal memuat.",action:()=>T(),actionLabel:"Coba lagi"}):v.length===0?L==="issue"&&!m?e.jsx(_,{kind:"empty",icon:"inbox",title:"Pilih satu project",hint:"Issue GitHub milik satu repo, jadi pilih project-nya lebih dulu di penyaring."}):Ce>0?e.jsx(_,{kind:"empty",icon:"filter",title:"Tak ada yang cocok",hint:"Tidak ada tiket atau issue yang cocok dengan penyaring atau kata kunci saat ini.",action:Pe,actionLabel:"Reset penyaring"}):A==="new"?e.jsx(_,{kind:"empty",icon:"inbox",title:"Belum ada keluhan",hint:"Aktifkan Help Center di detail project, lalu sebar link publiknya agar keluhan mulai masuk."}):e.jsx(_,{kind:"empty",icon:"inbox",title:`Belum ada yang ${oe[A].toLowerCase()}`}):e.jsx(bt,{label:"Keluhan dan issue",children:v.map(t=>e.jsx(Ot,{row:t,selected:t.key===$,picked:xe.has(t.key),busy:P,onOpen:()=>G(t.key),onPick:()=>tt(t.key),onAccept:()=>void Le(t),onReject:()=>void Be(t)},t.key))}):e.jsx(pt,{rows:4,label:"Memuat keluhan dan issue…"}),ot=e.jsxs("div",{className:"hn-triage-list-panel",children:[(M||O)&&v.length>0&&e.jsx(Ae,{tone:"err",title:"Sebagian data gagal dimuat",children:M??O}),ae.length>0&&e.jsxs("div",{className:"hn-triage-bulk",role:"region","aria-label":"Aksi massal",children:[e.jsxs("span",{className:"hn-triage-bulk-count",children:[ae.length," dipilih"]}),e.jsx(f,{size:"sm",leftIcon:"arrow-up-right",onClick:()=>void Ye(),disabled:P,children:"Terima terpilih"}),e.jsx(f,{size:"sm",variant:"secondary",leftIcon:"ban",onClick:()=>void Ze(),disabled:P,children:"Tolak terpilih"}),e.jsx(f,{size:"sm",variant:"ghost",onClick:()=>F([]),disabled:P,children:"Batal pilih"})]}),e.jsx("div",{ref:Ue,"data-testid":"triage-scroll",className:"hn-triage-scroll",children:ct}),rt]}),Re=$&&($.startsWith("i:")?le?e.jsx(Ut,{issue:z.find(t=>Se("issue",t.id)===$),projectName:d,onBack:()=>G(null),onAccepted:r,onReject:Ee,onToast:h}):e.jsx(_,{kind:"empty",icon:"inbox",title:"Issue ini tak ada di daftar",hint:"Pilih ulang dari daftar di sebelahnya.",action:()=>G(null),actionLabel:"Kembali ke daftar"}):e.jsx(Ft,{id:$.slice(2),projectName:d,onBack:()=>G(null),onAccepted:r,onDeleted:()=>{G(null),T(!0)},onReject:t=>ye([t]),onToast:h},`${$}-${de}`));return e.jsxs("div",{className:"hn-triage",onKeyDown:st,children:[e.jsxs("div",{className:"hn-triage-status-row",children:[e.jsx("div",{className:"hn-triage-segment",role:"group","aria-label":"Status keluhan dan issue",children:Ht.map(t=>e.jsxs("button",{type:"button",className:"hn-triage-segment-btn","aria-pressed":A===t.key,onClick:()=>fe(t.key),children:[t.label,t.key==="new"&&$e>0&&e.jsx(qe,{tone:"warn",size:"sm",children:$e})]},t.key))}),m&&L!=="tiket"&&e.jsx(f,{size:"sm",variant:"secondary",onClick:()=>void et(),disabled:P,children:"Tarik issue"})]}),(c||te)&&(te?e.jsx(Ae,{tone:"err",role:"alert",children:te}):e.jsx("span",{className:"hn-triage-meta",children:c})),e.jsx(ft,{label:"Filter keluhan dan issue",search:{value:E,onChange:o,label:"Cari tiket",placeholder:"mis. gagal login atau budi@contoh.id"},chips:nt,filters:lt,filtersLabel:"Filter",onReset:Pe,resetLabel:"Hapus semua filter",actions:e.jsxs(e.Fragment,{children:[e.jsx(jt,{onDone:()=>T(!0),onToast:h}),e.jsx(xt,{screen:"triage",active:Ce}),e.jsx(Rt,{})]})}),e.jsx(yt,{ariaLabel:"Panel triase",active:$?"detail":"list",onActiveChange:t=>{t==="list"&&G(null)},splitAt:"tablet",masterWidth:360,panels:[{id:"list",label:"Daftar",content:ot,className:"hn-panel-flex"},...$&&Re?[{id:"detail",label:"Detail",className:"hn-panel-flex",content:Re}]:[]]}),e.jsx(vt,{toast:Je}),Ve]})}export{Zt as TriageScreen};
1
+ import{q as X,r as De,J as dt,d as Ke,p as ht,h as p,K as mt,G as kt,j as e,w as _e,e as Z,g as ce,L as pt,m as _,N as gt,R as bt,C as Ae,B as f,n as qe,x as ft,y as jt,Q as xt,U as yt,z as vt,D as ze,V as wt,i as St,W as Ct,X as It,Y as Tt,Z as we,_ as ke,O as Me,f as Nt,H as Pt,$ as Ge,a0 as $t,a1 as Lt,a2 as Et,b as Bt}from"./index-C5P4ykKO.js";import{R as l}from"./react-DfGhg7ZW.js";import{L as Rt}from"./live-DQen7wLm.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";function Dt(a,r){return a==="rejected"?"Ditutup":a!=="accepted"?"Sedang ditinjau":r==="done"?"Selesai":r==="executing"?"Sedang dikerjakan":"Diterima"}const At=5e3,Y=20,zt=400,Gt=6e3,Ht=[{key:"new",label:"Belum ditinjau"},{key:"accepted",label:"Diterima"},{key:"rejected",label:"Ditutup"}],Kt={new:"drift",accepted:"ok",rejected:"idle"},oe=gt,me={semua:"Semua sumber",tiket:"Help Center",issue:"GitHub"},Oe=a=>{var d;const r=(d=a==null?void 0:a.detail)==null?void 0:d.error;if(typeof r=="string"&&r.trim())return r;const h=a==null?void 0:a.status;return typeof h=="number"?`server menolak permintaan (HTTP ${h})`:a instanceof Error?a.message:""},w=(a,r)=>St(a,new Error(Oe(r))),pe=(a,r=Date.now())=>Lt(a,r)||"—",Se=(a,r)=>`${a==="tiket"?"t":"i"}:${r}`;function _t(a,r){return{key:Se("tiket",a.id),kind:"tiket",id:a.id,number:a.number,title:a.title,status:a.status,specId:a.specId,at:a.createdAt,meta:[`#${a.number}`,a.category,r(a.projectId),a.reporterEmail,pe(a.createdAt),...a.attachmentCount>0?[`${a.attachmentCount} lampiran`]:[],...a.specId?[`→ ${a.specId}`]:[]]}}function qt(a,r){return{key:Se("issue",a.id),kind:"issue",id:a.id,number:a.number,title:a.title,status:a.status,specId:a.specId,at:a.issueCreatedAt,meta:[`#${a.number}`,`@${a.authorLogin}`,...a.labels,r(a.projectId),pe(a.issueCreatedAt),...a.specId?[`→ ${a.specId}`]:[]]}}function Mt({page:a,pageCount:r,onPage:h}){return r<=1?null:e.jsxs("div",{className:"hn-triage-footer",children:[e.jsxs("span",{children:["Halaman ",a," dari ",r," · tiket dan issue"]}),e.jsxs("span",{className:"hn-triage-acts",children:[e.jsx(f,{size:"sm",variant:"ghost","aria-label":"Sebelumnya",disabled:a<=1,onClick:()=>h(a-1),children:"Sebelumnya"}),e.jsx(f,{size:"sm",variant:"ghost","aria-label":"Berikutnya",disabled:a>=r,onClick:()=>h(a+1),children:"Berikutnya"})]})]})}function He({total:a,page:r,onPage:h,unit:d="tiket"}){const j=we(a,r,Y);return e.jsx(Et,{page:j.page,pageCount:j.pageCount,total:a,from:j.from,to:j.to,onPage:h,unit:d})}function Ot({row:a,selected:r,picked:h,busy:d,onOpen:j,onPick:R,onAccept:g,onReject:N}){const D=a.status==="new",S=a.kind==="tiket"?"tiket":"issue";return e.jsxs(It,{selected:r,onClick:j,actions:e.jsxs(e.Fragment,{children:[D&&e.jsx("label",{className:"hn-triage-check hn-touch-target",children:e.jsx("input",{type:"checkbox","aria-label":`Pilih ${S} ${a.number}`,checked:h,onChange:R})}),e.jsx(qe,{tone:"neutral",size:"sm",children:a.kind==="tiket"?"Help Center":"GitHub"}),D&&e.jsxs(e.Fragment,{children:[e.jsx(f,{size:"sm","aria-label":`Terima ${S} ${a.number}`,disabled:d,onClick:g,children:"Terima"}),e.jsx(f,{size:"sm",variant:"ghost","aria-label":`Tolak ${S} ${a.number}`,disabled:d,onClick:N,children:"Tolak"})]})]}),children:[e.jsxs("span",{className:"hn-triage-title-line",children:[e.jsx(Tt,{variant:"dot",status:Kt[a.status],children:oe[a.status]}),e.jsx("span",{className:"hn-triage-title",children:a.title})]}),e.jsx("span",{className:"hn-triage-meta",children:a.meta.join(" · ")})]})}function Fe(a,r){const h=Bt();l.useEffect(()=>{if(h!=="mobile"||!a)return;const d=j=>{j.key!=="Escape"||document.querySelector('[role="dialog"]')||r()};return window.addEventListener("keydown",d),()=>window.removeEventListener("keydown",d)},[h,a,r])}function Ft({id:a,projectName:r,onBack:h,onAccepted:d,onDeleted:j,onReject:R,onToast:g}){var E;const[N,D]=l.useState(null),[S,z]=l.useState("loading"),[y,x]=l.useState(!1),[C,ge]=l.useState("sedang"),[V,J]=l.useState(!1),[q,M]=l.useState(!1),{confirm:ee,dialog:O}=Ke(),[u,P]=l.useState({title:"",detail:"",category:"bug",status:"new"}),I=l.useCallback(()=>{p.getTicket(a).then(o=>{D(o),z("ready")}).catch(()=>z("error"))},[a]);if(l.useEffect(()=>{I()},[I]),Fe(!V,h),S==="loading")return e.jsx(_,{kind:"loading"});if(S==="error"||!N)return e.jsx(_,{kind:"error",hint:"Gagal memuat tiket.",action:I,actionLabel:"Coba lagi"});const c=N,Q=!!c.specId,te=c.status!=="new",ue=u.title!==c.title||u.detail!==c.detail||u.category!==c.category||u.status!==c.status;async function ae(){x(!0);try{const o=await p.acceptTicket(a,C);d(o.spec,!!o.alreadyPromoted)}catch(o){g(w("menerima tiket",o),"err","x-circle")}finally{x(!1)}}async function F(){x(!0);try{await R(a),I()}finally{x(!1)}}async function de(o,k){try{await navigator.clipboard.writeText(o),g(k,"ok","copy")}catch(U){g(w("menyalin link",U),"err","x-circle")}}async function be(){x(!0);try{const o=await p.unlinkTicket(a);D({...c,specId:o.specId,spec:null,status:o.status}),g("Tautan backlog dilepas","ok","unlink")}catch(o){g(w("melepas tautan",o),"err","x-circle")}finally{x(!1)}}function A(){P({title:c.title,detail:c.detail,category:c.category,status:c.status}),J(!0)}async function fe(){ue&&!await ee({title:"Buang perubahan?",message:"Perubahan pada tiket ini belum disimpan.",impact:["Judul, detail, kategori, dan status kembali ke nilai tersimpan."],confirmLabel:"Buang perubahan",tone:"danger"})||J(!1)}async function L(){if(u.title.trim()){x(!0);try{const o=await p.editTicket(a,{title:u.title,detail:u.detail,category:u.category,status:u.status});D(o),J(!1),g("Tiket diperbarui","ok")}catch(o){g(w("menyimpan tiket",o),"err","x-circle")}finally{x(!1)}}}async function ie(){x(!0);try{await p.deleteTicket(a),g("Tiket dihapus","ok","trash-2"),j()}catch(o){g(w("menghapus tiket",o),"err","x-circle"),x(!1)}}if(V){const o=!u.title.trim();return e.jsxs("div",{className:"hn-triage-detail",children:[e.jsx("div",{className:"hn-triage-detail-scroll",children:e.jsxs(_e,{gap:4,children:[e.jsxs("div",{className:"hn-triage-status-row",children:[e.jsx(f,{size:"sm",variant:"ghost",leftIcon:"arrow-left",onClick:()=>void fe(),disabled:y,children:"Batal"}),e.jsx(f,{size:"sm",variant:"primary",leftIcon:"check",onClick:L,disabled:y||o,children:"Simpan"})]}),e.jsx(Z,{label:"Judul",error:o?"Judul tiket wajib diisi.":void 0,children:e.jsx(Nt,{value:u.title,invalid:o,placeholder:"mis. Tombol Simpan tak berfungsi di HP",onChange:k=>P({...u,title:k.target.value})})}),e.jsxs("div",{className:"hn-triage-status-row",children:[e.jsx(Z,{label:"Kategori",children:e.jsx(ce,{value:u.category,onChange:k=>P({...u,category:k.target.value}),options:[{value:"bug",label:"bug"},{value:"fitur",label:"fitur"},{value:"pertanyaan",label:"pertanyaan"},{value:"lainnya",label:"lainnya"}]})}),e.jsx(Z,{label:"Status",children:e.jsx(ce,{value:u.status,onChange:k=>P({...u,status:k.target.value}),options:[{value:"new",label:oe.new},{value:"accepted",label:oe.accepted},{value:"rejected",label:oe.rejected}]})})]}),e.jsx(Z,{label:"Detail keluhan",children:e.jsx(Pt,{value:u.detail,rows:6,placeholder:"mis. Buka halaman Pesanan di HP, tekan Simpan — layar diam dan datanya tak tersimpan.",onChange:k=>P({...u,detail:k.target.value})})})]})}),O]})}const m=c.publicStatusUrl,se=[{key:"edit",label:"Edit",icon:"pencil",onSelect:A,disabled:y},...m?[{key:"public-open",label:"Buka status publik",icon:"share-2",onSelect:()=>window.open(m,"_blank","noreferrer")},{key:"public-copy",label:"Salin link publik",icon:"link-2",onSelect:()=>void de(m,"Link publik disalin")}]:[],...Q?[{key:"spec-copy",label:"Salin link backlog",icon:"copy",onSelect:()=>void de(ke(c.specId),"Link backlog disalin")},{key:"unlink",label:"Lepas tautan",icon:"unlink",onSelect:()=>void be(),disabled:y}]:[],{key:"delete",label:"Hapus",icon:"trash-2",onSelect:()=>M(!0),disabled:y}];return e.jsxs("div",{className:"hn-triage-detail",children:[e.jsx("div",{className:"hn-triage-detail-scroll",children:e.jsxs("div",{className:"hn-triage-detail-body",children:[e.jsxs("div",{children:[e.jsxs("span",{className:"hn-triage-meta",children:["#",c.number," · ",c.category]}),e.jsx("h2",{className:"hn-triage-detail-title",children:c.title})]}),e.jsxs("ul",{className:"hn-triage-facts",children:[e.jsxs("li",{children:["pelapor: ",e.jsx("b",{children:c.reporterEmail})]}),e.jsxs("li",{children:["project: ",e.jsx("b",{children:r(c.projectId)})]}),e.jsxs("li",{children:["masuk ",pe(c.createdAt)]}),Q&&e.jsxs("li",{children:["backlog: ",e.jsx("b",{children:c.specId})," · ",e.jsx("span",{children:Dt(c.status,(E=c.spec)==null?void 0:E.stage)})]})]}),e.jsxs("div",{children:[e.jsx("h3",{className:"hn-eyebrow hn-triage-section-title",children:"Detail keluhan"}),e.jsx("div",{className:"hn-triage-body-text",children:c.detail})]}),c.attachments.length>0&&e.jsxs("details",{className:"hn-triage-disclosure",open:!0,children:[e.jsxs("summary",{children:["Lampiran (",c.attachments.length,")"]}),e.jsx("ul",{className:"hn-triage-attachments",children:c.attachments.map(o=>e.jsx("li",{children:e.jsx("a",{href:Ge.ticketAttachment(c.id,o.id),target:"_blank",rel:"noreferrer",className:"hn-triage-attachment-link",children:e.jsx("img",{src:Ge.ticketAttachment(c.id,o.id),alt:o.filename})})},o.id))})]})]})}),e.jsxs("div",{className:"hn-triage-decision",role:"group","aria-label":"Keputusan",children:[Q?e.jsx(f,{size:"sm",leftIcon:"external-link",onClick:()=>window.open(ke(c.specId),"_blank","noreferrer"),children:"Buka backlog"}):!te&&e.jsxs(e.Fragment,{children:[e.jsx(f,{size:"sm",leftIcon:"arrow-up-right",onClick:ae,disabled:y,children:"Terima → backlog"}),e.jsx(f,{size:"sm",variant:"secondary",leftIcon:"ban",onClick:F,disabled:y,children:"Tolak"}),e.jsx(ce,{size:"sm",value:C,"aria-label":"Prioritas tiket",onChange:o=>ge(o.target.value),options:[{value:"tinggi",label:"Prioritas tinggi"},{value:"sedang",label:"Prioritas sedang"},{value:"rendah",label:"Prioritas rendah"}]})]}),e.jsx("span",{className:"hn-triage-decision-spacer"}),e.jsx(Me,{label:"Aksi lainnya",items:se})]}),e.jsx($t,{open:q,title:"Hapus tiket?",eyebrow:`#${c.number}`,confirmLabel:"Hapus tiket",message:`Tiket "${c.title}" dan seluruh lampirannya akan dihapus permanen. Tindakan ini tak bisa dibatalkan.`,busy:y,onCancel:()=>M(!1),onConfirm:ie}),O]})}function Ut({issue:a,projectName:r,onBack:h,onAccepted:d,onReject:j,onToast:R}){const[g,N]=l.useState(!1);Fe(!0,h);const D=a.status==="new",S=!!a.specId;async function z(){N(!0);try{const C=await p.acceptGithubIssue(a.id);d(C.spec,!!C.alreadyPromoted)}catch(C){R(w("menerima issue",C),"err","x-circle")}finally{N(!1)}}async function y(){N(!0);try{await j(a)}finally{N(!1)}}const x=[{key:"gh",label:"Buka di GitHub",icon:"external-link",onSelect:()=>window.open(a.url,"_blank","noreferrer")},...S?[{key:"spec-copy",label:"Salin link backlog",icon:"copy",onSelect:()=>{navigator.clipboard.writeText(ke(a.specId)).then(()=>R("Link backlog disalin","ok","copy"),C=>R(w("menyalin link",C),"err","x-circle"))}}]:[]];return e.jsxs("div",{className:"hn-triage-detail",children:[e.jsx("div",{className:"hn-triage-detail-scroll",children:e.jsxs("div",{className:"hn-triage-detail-body",children:[e.jsxs("div",{children:[e.jsxs("span",{className:"hn-triage-meta",children:["#",a.number," · @",a.authorLogin]}),e.jsx("h2",{className:"hn-triage-detail-title",children:a.title})]}),e.jsxs("ul",{className:"hn-triage-facts",children:[e.jsxs("li",{children:["project: ",e.jsx("b",{children:r(a.projectId)})]}),e.jsxs("li",{children:["repo: ",e.jsx("b",{children:a.repoSlug})]}),e.jsxs("li",{children:["dibuat ",pe(a.issueCreatedAt)]}),a.labels.length>0&&e.jsxs("li",{children:["label: ",e.jsx("b",{children:a.labels.join(", ")})]}),S&&e.jsxs("li",{children:["backlog: ",e.jsx("b",{children:a.specId})]})]}),e.jsxs("div",{children:[e.jsx("h3",{className:"hn-eyebrow hn-triage-section-title",children:"Isi issue"}),e.jsx("div",{className:"hn-triage-body-text",children:a.body||"Tanpa isi."})]})]})}),e.jsxs("div",{className:"hn-triage-decision",role:"group","aria-label":"Keputusan",children:[D&&e.jsxs(e.Fragment,{children:[e.jsx(f,{size:"sm",leftIcon:"arrow-up-right",onClick:z,disabled:g,children:"Terima → backlog"}),e.jsx(f,{size:"sm",variant:"secondary",leftIcon:"ban",onClick:y,disabled:g,children:"Tolak"})]}),S&&e.jsx(f,{size:"sm",leftIcon:"external-link",onClick:()=>window.open(ke(a.specId),"_blank","noreferrer"),children:"Buka backlog"}),e.jsx("span",{className:"hn-triage-decision-spacer"}),e.jsx(Me,{label:"Aksi lainnya",items:x})]})]})}function Zt({projects:a,onAccepted:r,onToast:h}){const d=l.useCallback(t=>{var s;return((s=a.find(n=>n.id===t))==null?void 0:s.name)??t},[a]),[j,R]=l.useState([]),[g,N]=l.useState(0),[D,S]=l.useState(0),[z,y]=l.useState([]),[x,C]=l.useState(0),[ge,V]=l.useState(0),[J,q]=l.useState(!1),[M,ee]=l.useState(null),[O,u]=l.useState(null),[P,I]=l.useState(!1),[c,Q]=l.useState(null),[te,ue]=l.useState(null),[ae,F]=l.useState([]),[de,be]=l.useState(0),[A,fe]=X("triage","status","new",De("new","accepted","rejected")),[L,ie]=X("triage","source","semua",De("semua","tiket","issue")),[m,se]=X("triage","project","",ze),[E,o]=X("triage","q","",ze),[k,U]=X("triage","page",1,wt),[$,G]=X("triage","openId",null,Ct),Ce=[m!=="",L!=="semua",E.trim()!==""].filter(Boolean).length,H=L!=="issue",W=L!=="tiket"&&m!=="",Ie=dt("triage","scroll",J),Te=l.useRef(null),Ue=l.useCallback(t=>{Te.current=t,Ie(t)},[Ie]),{confirm:Ne,dialog:Ve}=Ke(),[Je,B]=ht(),[je,Qe]=l.useState(E);l.useEffect(()=>{const t=setTimeout(()=>Qe(E),zt);return()=>clearTimeout(t)},[E]);const he=l.useRef(0),ne=l.useRef(0),T=l.useCallback((t=!1)=>{const s=++he.current,n=++ne.current;if(p.listTickets({project:m||void 0,status:A,q:je||void 0,page:String(k),limit:String(H?Y:1)}).then(i=>{s===he.current&&(R(H?i.items:[]),N(H?i.total:0),S(i.unreviewed),ee(null),q(!0))},i=>{s===he.current&&(t||ee(w("memuat tiket",i)),q(!0))}),!m){y([]),C(0),V(0),u(null);return}W?p.listGithubIssues(m,{status:A,page:k,limit:Y}).then(i=>{n===ne.current&&(y(i.items),C(i.total),u(null),q(!0))},i=>{n===ne.current&&(t||u(w("memuat issue",i)),q(!0))}):(y([]),C(0),u(null)),p.listGithubIssues(m,{status:"new",limit:1}).then(i=>{n===ne.current&&V(i.total)},()=>{n===ne.current&&V(null)})},[m,A,je,k,H,W]);l.useEffect(()=>{T()},[T]),mt(JSON.stringify([m,L,A,E]),()=>{U(1),F([])});const Pe=()=>{se(""),ie("semua"),o(""),U(1)};kt({topic:"tickets",params:{project:m||void 0,status:A,q:je||void 0,page:k,limit:Y},apply:t=>{he.current++,R(t.data.items),N(t.data.total),S(t.data.unreviewed),ee(null),q(!0)},refetch:()=>T(!0),pollMs:At});const v=l.useMemo(()=>{const t=E.trim().toLowerCase(),s=H?j.map(i=>_t(i,d)):[],n=W?z.filter(i=>!t||`${i.number} ${i.title} ${i.authorLogin} ${i.labels.join(" ")}`.toLowerCase().includes(t)).map(i=>qt(i,d)):[];return[...s,...n].sort((i,b)=>Date.parse(b.at)-Date.parse(i.at))},[j,z,H,W,E,d]),We=l.useMemo(()=>new Map(v.map(t=>[t.key,t])),[v]),le=$?We.get($):void 0,xe=new Set(ae),$e=D+(ge??0);async function ye(t){const s=await Promise.allSettled(t.map(b=>p.rejectTicket(b))),n=t.filter((b,K)=>s[K].status==="fulfilled"),i=s.find(b=>b.status==="rejected");n.length>0&&B(n.length===1?"Tiket ditolak":`${n.length} tiket ditolak`,"ok","ban",{action:{label:"Urungkan",onAction:()=>void Xe(n)},duration:Gt}),i&&B(w("menolak tiket",i.reason),"err","x-circle"),T(!0)}async function Xe(t){const n=(await Promise.allSettled(t.map(i=>p.editTicket(i,{status:"new"})))).filter(i=>i.status==="fulfilled").length;be(i=>i+1),T(!0),n===t.length?B("Penolakan dibatalkan","ok","check"):B(`${n} dari ${t.length} penolakan dibatalkan`,"err","x-circle")}async function Le(t){I(!0);try{const s=t.kind==="tiket"?await p.acceptTicket(t.id,"sedang"):await p.acceptGithubIssue(t.id),n=s.spec.id;B(s.alreadyPromoted?`Sudah jadi ${n}`:`Diterima → ${n}`,"ok","arrow-up-right"),T(!0)}catch(s){B(w("menerima "+(t.kind==="tiket"?"tiket":"issue"),s),"err","x-circle")}finally{I(!1)}}async function Ee(t){await Ne({title:`Tolak issue #${t.number}?`,message:t.title,impact:["Issue ditandai ditutup di hanoman.","Issue di GitHub tidak diubah."],confirmLabel:"Tolak issue",tone:"danger",icon:"x-circle",run:async()=>{await p.rejectGithubIssue(t.id),T(!0)}}).catch(s=>B(w("menolak issue",s),"err","x-circle"))}async function Be(t){if(t.kind==="tiket"){I(!0);try{await ye([t.id])}finally{I(!1)}return}const s=z.find(n=>n.id===t.id);s&&await Ee(s)}async function Ye(){const t=v.filter(i=>xe.has(i.key)&&i.status==="new"),s=t.filter(i=>i.kind==="tiket"),n=t.filter(i=>i.kind==="issue");I(!0);try{const i=await Promise.allSettled(s.map(re=>p.acceptTicket(re.id,"sedang"))),b=n.length?await p.acceptGithubIssues(n.map(re=>re.id),void 0):null,K=i.filter(re=>re.status==="fulfilled").length,ut=(b==null?void 0:b.created.length)??0,ve=i.length-K+((b==null?void 0:b.failed.length)??0);B(`${K+ut} diterima${ve?` · ${ve} gagal`:""}`,ve?"err":"ok","arrow-up-right"),F([]),T(!0)}catch(i){B(w("menerima yang dipilih",i),"err","x-circle")}finally{I(!1)}}async function Ze(){const t=v.filter(s=>xe.has(s.key)&&s.status==="new");t.length!==0&&await Ne({title:`Tolak ${t.length} item?`,message:"Item berikut ditandai ditutup di hanoman. Issue di GitHub tidak diubah.",impact:t.map(s=>`${s.kind==="tiket"?"Tiket":"Issue"} #${s.number}: ${s.title}`),confirmLabel:`Tolak ${t.length} item`,tone:"danger",icon:"x-circle",run:async()=>{const s=t.filter(i=>i.kind==="tiket").map(i=>i.id),n=t.filter(i=>i.kind==="issue").map(i=>i.id);if(s.length&&await ye(s),n.length){const b=(await Promise.allSettled(n.map(K=>p.rejectGithubIssue(K)))).filter(K=>K.status==="fulfilled").length;B(`${b} issue ditolak`,"ok","ban")}F([]),T(!0)}}).catch(s=>B(w("menolak yang dipilih",s),"err","x-circle"))}async function et(){if(m){I(!0),ue(null),Q(null);try{const t=await p.pullGithubIssues(m);Q(`${t.repo}: ${t.created} baru, ${t.updated} diperbarui`+(t.skippedPullRequests?` · ${t.skippedPullRequests} pull request dilewati`:"")),T(!0)}catch(t){ue(`Gagal menarik issue: ${Oe(t)}`)}finally{I(!1)}}}const tt=t=>F(s=>s.includes(t)?s.filter(n=>n!==t):[...s,t]),at=t=>{var n,i;const s=v.findIndex(b=>b.key===t);(i=(n=Te.current)==null?void 0:n.querySelectorAll("button.hn-row-main")[s])==null||i.focus()},it=t=>{if(v.length===0)return;const s=v.findIndex(i=>i.key===$),n=v[s<0?t>0?0:v.length-1:Math.min(v.length-1,Math.max(0,s+t))];n&&(G(n.key),at(n.key))},st=t=>{if(t.defaultPrevented||t.ctrlKey||t.metaKey||t.altKey||t.target.closest("input, textarea, select, [contenteditable='true']")||document.querySelector('[role="dialog"]'))return;if(t.key==="Escape"){$&&(t.preventDefault(),G(null));return}const n=t.key.toLowerCase();if(n==="j"||n==="k"){t.preventDefault(),it(n==="j"?1:-1);return}!le||le.status!=="new"||P||(n==="a"?(t.preventDefault(),Le(le)):n==="r"&&(t.preventDefault(),Be(le)))},nt=[...m?[{key:"project",label:`Project: ${d(m)}`,onRemove:()=>se("")}]:[],...L!=="semua"?[{key:"source",label:`Sumber: ${me[L]}`,onRemove:()=>ie("semua")}]:[]],lt=e.jsxs(_e,{gap:3,children:[e.jsx(Z,{label:"Project",children:e.jsx(ce,{size:"sm",value:m,"aria-label":"Project triase",onChange:t=>se(t.target.value),options:[{value:"",label:"Semua project"},...a.map(t=>({value:t.id,label:t.name}))]})}),e.jsx(Z,{label:"Sumber",children:e.jsx(ce,{size:"sm",value:L,"aria-label":"Sumber triase",onChange:t=>ie(t.target.value),options:[{value:"semua",label:me.semua},{value:"tiket",label:me.tiket},{value:"issue",label:me.issue}]})})]}),rt=H&&W?e.jsx(Mt,{page:k,pageCount:Math.max(we(g,k,Y).pageCount,we(x,k,Y).pageCount),onPage:U}):H?e.jsx(He,{total:g,page:k,onPage:U}):W?e.jsx(He,{total:x,page:k,onPage:U,unit:"issue"}):null,ct=J?v.length===0&&(M||O)?e.jsx(_,{kind:"error",hint:M??O??"Gagal memuat.",action:()=>T(),actionLabel:"Coba lagi"}):v.length===0?L==="issue"&&!m?e.jsx(_,{kind:"empty",icon:"inbox",title:"Pilih satu project",hint:"Issue GitHub milik satu repo, jadi pilih project-nya lebih dulu di penyaring."}):Ce>0?e.jsx(_,{kind:"empty",icon:"filter",title:"Tak ada yang cocok",hint:"Tidak ada tiket atau issue yang cocok dengan penyaring atau kata kunci saat ini.",action:Pe,actionLabel:"Reset penyaring"}):A==="new"?e.jsx(_,{kind:"empty",icon:"inbox",title:"Belum ada keluhan",hint:"Aktifkan Help Center di detail project, lalu sebar link publiknya agar keluhan mulai masuk."}):e.jsx(_,{kind:"empty",icon:"inbox",title:`Belum ada yang ${oe[A].toLowerCase()}`}):e.jsx(bt,{label:"Keluhan dan issue",children:v.map(t=>e.jsx(Ot,{row:t,selected:t.key===$,picked:xe.has(t.key),busy:P,onOpen:()=>G(t.key),onPick:()=>tt(t.key),onAccept:()=>void Le(t),onReject:()=>void Be(t)},t.key))}):e.jsx(pt,{rows:4,label:"Memuat keluhan dan issue…"}),ot=e.jsxs("div",{className:"hn-triage-list-panel",children:[(M||O)&&v.length>0&&e.jsx(Ae,{tone:"err",title:"Sebagian data gagal dimuat",children:M??O}),ae.length>0&&e.jsxs("div",{className:"hn-triage-bulk",role:"region","aria-label":"Aksi massal",children:[e.jsxs("span",{className:"hn-triage-bulk-count",children:[ae.length," dipilih"]}),e.jsx(f,{size:"sm",leftIcon:"arrow-up-right",onClick:()=>void Ye(),disabled:P,children:"Terima terpilih"}),e.jsx(f,{size:"sm",variant:"secondary",leftIcon:"ban",onClick:()=>void Ze(),disabled:P,children:"Tolak terpilih"}),e.jsx(f,{size:"sm",variant:"ghost",onClick:()=>F([]),disabled:P,children:"Batal pilih"})]}),e.jsx("div",{ref:Ue,"data-testid":"triage-scroll",className:"hn-triage-scroll",children:ct}),rt]}),Re=$&&($.startsWith("i:")?le?e.jsx(Ut,{issue:z.find(t=>Se("issue",t.id)===$),projectName:d,onBack:()=>G(null),onAccepted:r,onReject:Ee,onToast:h}):e.jsx(_,{kind:"empty",icon:"inbox",title:"Issue ini tak ada di daftar",hint:"Pilih ulang dari daftar di sebelahnya.",action:()=>G(null),actionLabel:"Kembali ke daftar"}):e.jsx(Ft,{id:$.slice(2),projectName:d,onBack:()=>G(null),onAccepted:r,onDeleted:()=>{G(null),T(!0)},onReject:t=>ye([t]),onToast:h},`${$}-${de}`));return e.jsxs("div",{className:"hn-triage",onKeyDown:st,children:[e.jsxs("div",{className:"hn-triage-status-row",children:[e.jsx("div",{className:"hn-triage-segment",role:"group","aria-label":"Status keluhan dan issue",children:Ht.map(t=>e.jsxs("button",{type:"button",className:"hn-triage-segment-btn","aria-pressed":A===t.key,onClick:()=>fe(t.key),children:[t.label,t.key==="new"&&$e>0&&e.jsx(qe,{tone:"warn",size:"sm",children:$e})]},t.key))}),m&&L!=="tiket"&&e.jsx(f,{size:"sm",variant:"secondary",onClick:()=>void et(),disabled:P,children:"Tarik issue"})]}),(c||te)&&(te?e.jsx(Ae,{tone:"err",role:"alert",children:te}):e.jsx("span",{className:"hn-triage-meta",children:c})),e.jsx(ft,{label:"Filter keluhan dan issue",search:{value:E,onChange:o,label:"Cari tiket",placeholder:"mis. gagal login atau budi@contoh.id"},chips:nt,filters:lt,filtersLabel:"Filter",onReset:Pe,resetLabel:"Hapus semua filter",actions:e.jsxs(e.Fragment,{children:[e.jsx(jt,{onDone:()=>T(!0),onToast:h}),e.jsx(xt,{screen:"triage",active:Ce}),e.jsx(Rt,{})]})}),e.jsx(yt,{ariaLabel:"Panel triase",active:$?"detail":"list",onActiveChange:t=>{t==="list"&&G(null)},splitAt:"tablet",masterWidth:360,panels:[{id:"list",label:"Daftar",content:ot,className:"hn-panel-flex"},...$&&Re?[{id:"detail",label:"Detail",className:"hn-panel-flex",content:Re}]:[]]}),e.jsx(vt,{toast:Je}),Ve]})}export{Zt as TriageScreen};
@@ -1,2 +1,2 @@
1
- import{a1 as be,h as g,v as fe,d as me,aV as E,aW as Y,j as e,M as ye,c as Oe,aX as ie,aT as ue,m as F,I as ne,x as Re,B as y,i as T,q as Se,r as Me,aY as Ue,aJ as _e,e as G,f as X,aZ as He,l as Fe,aq as Ke,R as We,X as qe,O as Ge,W as Xe}from"./index-BQw6xQI4.js";import{R as c}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";const Ye=10*6e4,we=(s,t)=>!!s.lastSeenAt&&t-new Date(s.lastSeenAt).getTime()<Ye;function he(s,t=Date.now()){const l=s.lastSeenAt?we(s,t)?{state:"done",text:"terhubung"}:{state:"gagal",text:"tidak terjangkau"}:{state:"todo",text:"belum terhubung"},o=s.lastAuditAt?{state:"done",text:`diaudit ${be(s.lastAuditAt,t)||"—"}`}:{state:"todo",text:"belum diaudit"},m=s.lastAuditAt&&s.hardened?{state:"done",text:"diperkuat"}:{state:"todo",text:"belum diperkuat"};return[{key:"terhubung",label:"Terhubung",...l},{key:"diaudit",label:"Diaudit",...o},{key:"diperkuat",label:"Diperkuat",...m}]}const Je=(s,t)=>{const l=new Set(s);return l.size===new Set(t).size&&t.every(o=>l.has(o))};function ke(s,t){return s.length>0&&t!==null&&Je(s,t)}const Qe=s=>s==null?"Skor —":`Skor ${s}%`,Ze={pass:"check",fail:"x",warn:"alert-triangle",na:"minus",unknown:"circle"},es={pass:"var(--leaf-600)",fail:"var(--clay-600)",warn:"var(--status-warn)",na:"var(--text-subtle)",unknown:"var(--text-subtle)"},ss={critical:"var(--clay-600)",high:"var(--status-warn)",medium:"var(--text-subtle)",low:"var(--text-subtle)"},te={AUTO:"Otomatis",AUDIT:"Audit",INFO:"Info"};function re({text:s,color:t}){return e.jsx("span",{className:"vps-badge",style:{color:t,borderColor:t},children:s})}function Ne({score:s}){const t=s>=90?"vps-tone-ok":s>=50?"vps-tone-warn":"vps-tone-bad";return e.jsxs("div",{className:"vps-bar-wrap",children:[e.jsx("div",{className:"vps-bar",children:e.jsx("div",{className:`vps-bar-fill ${t}`,style:{width:`${s}%`}})}),e.jsxs("span",{className:"vps-bar-num",children:[s,"%"]})]})}function as({item:s,busy:t,selected:l,onToggle:o,onNa:m,onAttest:h}){const u=s.mode==="AUTO"&&!s.na,x=s.status==="fail"||s.status==="warn"||!!s.drifted;return e.jsxs("div",{"data-testid":`item-${s.id}`,title:`${te[s.mode]} · ${Y[s.severity]}`,className:`vps-item${s.na?" vps-item-na":""}`,children:[u?e.jsx("span",{className:"vps-touch",children:e.jsx("input",{type:"checkbox","aria-label":`Pilih ${s.title}`,checked:l,onChange:()=>o(s)})}):e.jsx("span",{className:"vps-item-gap"}),e.jsx(ne,{name:Ze[s.status],size:14,color:es[s.status]}),e.jsx("span",{className:"vps-item-title",children:s.title}),s.drifted&&e.jsx(re,{text:"drift",color:"var(--clay-600)"}),x&&e.jsx(re,{text:Y[s.severity],color:ss[s.severity]}),s.mode==="INFO"&&!s.attested&&e.jsx(y,{size:"sm",variant:"ghost",leftIcon:"check-circle",loading:t,onClick:()=>h(s),children:"Tandai terpenuhi"}),e.jsx(y,{size:"sm",variant:"ghost",leftIcon:s.na?"rotate-ccw":"minus-circle",loading:t,onClick:()=>m(s,!s.na),children:s.na?"Batal N/A":"N/A"})]})}const ce={section:"",mode:"",status:"",severity:""};function le({value:s,onChange:t,options:l,label:o}){return e.jsxs("select",{"aria-label":o,value:s,onChange:m=>t(m.target.value),className:"vps-select vps-touch-select",children:[e.jsxs("option",{value:"",children:[o,": semua"]}),l.map(([m,h])=>e.jsx("option",{value:m,children:h},m))]})}function ts(s){let t=0,l=0,o=0,m=0;for(const x of s)x.status==="fail"?t++:x.status==="warn"?l++:x.status==="unknown"&&o++,x.drifted&&m++;const h=x=>x.charAt(0).toLowerCase()+x.slice(1),u=[t&&`${t} ${h(E.fail)}`,l&&`${l} ${h(E.warn)}`,o&&`${o} ${h(E.unknown)}`].filter(Boolean);return{text:u.length?u.join(" · "):`semua ${h(E.pass)}`,drift:m}}function ns({section:s,items:t,expanded:l,onToggle:o,busy:m,selected:h,onToggleItem:u,onNa:x,onAttest:b,onSectionNa:j}){const p=ts(s.items),f=!!s.suggestion&&!s.suggestion.applicable;return e.jsxs("div",{className:"vps-section",children:[e.jsxs("button",{"data-testid":`section-${s.id}`,"aria-expanded":l,onClick:()=>o(s.id),className:`vps-section-head${l?" vps-section-open":""}`,children:[e.jsx(ne,{name:l?"chevron-down":"chevron-right",size:15,color:"var(--text-subtle)"}),e.jsx("span",{className:"vps-section-icon",children:s.icon}),e.jsx("span",{className:"vps-section-title",children:s.title}),e.jsx("span",{className:"vps-section-sum",children:p.text}),p.drift>0&&e.jsx(re,{text:"drift",color:"var(--clay-600)"}),f&&e.jsx(re,{text:"saran N/A",color:"var(--brass-700)"}),e.jsx(Ne,{score:s.score})]}),l&&e.jsxs("div",{className:"vps-section-body",children:[f&&e.jsxs("div",{"data-testid":`suggestion-${s.id}`,className:"vps-suggest",children:[e.jsx(ne,{name:"info",size:13,color:"var(--brass-700)"}),e.jsxs("span",{className:"vps-suggest-text",children:["Stack tak terdeteksi (",s.suggestion.detail,") — kemungkinan N/A. Cek Docker manual bila ragu."]}),e.jsx(y,{size:"sm",variant:"ghost",leftIcon:"minus-circle",loading:m===`section:${s.id}`,onClick:()=>j(s),children:"Tandai seksi N/A"})]}),t.map(S=>e.jsx(as,{item:S,busy:m===S.id,selected:h.has(S.id),onToggle:u,onNa:x,onAttest:b},S.id))]})]})}function is({vpsId:s,vpsName:t,lastAuditAt:l,health:o,summary:m,provisioning:h,access:u,onScore:x,onClose:b,onToast:j}){const[p,f]=c.useState(null),[S,L]=c.useState("loading"),[A,B]=c.useState(""),[N,R]=c.useState("ringkasan"),[d,z]=c.useState(ce),[K,W]=c.useState(""),[J,q]=c.useState(new Set),[M,$]=c.useState(null),[C,O]=c.useState(new Set),[D,U]=c.useState(null),[Q,a]=c.useState(""),v=c.useRef(x);v.current=x;const I=c.useCallback(()=>{L("loading"),g.vpsChecklist(s).then(i=>{var k;f(i),L("ready"),(k=v.current)==null||k.call(v,i.scoreTotal)}).catch(i=>{B(fe(i,"tak diketahui")),L("error")})},[s]);c.useEffect(()=>{I(),O(new Set),U(null),q(new Set),W(""),z(ce)},[I]);const Z=i=>{U(null),O(k=>{const r=new Set(k);return r.has(i.id)?r.delete(i.id):r.add(i.id),r})},_=()=>{O(new Set),U(null)},ee=i=>q(k=>{const r=new Set(k);return r.has(i)?r.delete(i):r.add(i),r}),{confirm:se,dialog:n}=me(),w=(D==null?void 0:D.forIds)??null,V=ke([...C],w);async function Ce(){const i=[...C];a("preview");try{U({steps:(await g.remediatePreview(s,i)).steps,forIds:i})}catch(k){j(T("membuat pratinjau remediasi",k),"err","x-circle")}finally{a("")}}async function Pe(){const i=[...C];if(!ke(i,w))return;const r=((p==null?void 0:p.sections.flatMap(P=>P.items))??[]).filter(P=>C.has(P.id));if(await se({title:`Terapkan ${i.length} item AUTO ke VPS ini?`,message:"Remediasi dijalankan langsung di server yang terdaftar.",impact:[...r.map(P=>`${P.id} · ${P.title}`),"Langkahnya idempoten dan anti-lockout.","Checklist diaudit ulang setelah selesai."],confirmLabel:"Terapkan",icon:"shield"})){a("apply");try{await g.remediate(s,i),_(),I(),j("Remediasi diterapkan · audit ulang","ok","shield")}catch(P){j(T("menerapkan remediasi",P),"err","x-circle")}finally{a("")}}}async function pe(i,k,r){$(i.id);try{await k(),I(),j(r,"ok","shield")}catch(P){j(T(`memperbarui ${i.id}`,P),"err","x-circle")}finally{$(null)}}const Ae=(i,k)=>pe(i,()=>g.markNa(s,i.id,k,k?"ditandai dari checklist":void 0),k?`${i.id} ditandai N/A`:`${i.id} kembali applicable`),Ie=i=>pe(i,()=>g.attestItem(s,i.id),`${i.id} ditandai terpenuhi`);async function Le(i){const k=i.items.map(r=>r.id);if(await se({title:`Tandai ${k.length} item seksi "${i.title}" sebagai N/A?`,message:"Stack-nya tak terdeteksi — cek Docker manual bila ragu.",confirmLabel:"Tandai N/A",icon:"shield"})){$(`section:${i.id}`);try{await g.markNaBulk(s,k,!0,"app-layer: stack tak terdeteksi"),I(),j(`Seksi ${i.title} ditandai N/A`,"ok","shield")}catch(r){j(T(`menandai seksi ${i.title} sebagai N/A`,r),"err","x-circle")}finally{$(null)}}}const ae=K.trim().toLowerCase(),oe=!!(d.section||d.mode||d.status||d.severity)||ae!=="",Ve=i=>(!d.section||i.section===d.section)&&(!d.mode||i.mode===d.mode)&&(!d.status||i.status===d.status)&&(!d.severity||i.severity===d.severity)&&(!ae||i.title.toLowerCase().includes(ae)||i.id.toLowerCase().includes(ae)||(i.code??"").toLowerCase().includes(ae)),H=i=>k=>z(r=>({...r,[i]:k})),Te=i=>{var k;return((k=p==null?void 0:p.sections.find(r=>r.id===i))==null?void 0:k.title)??i},De=[...d.section?[{key:"section",label:`Seksi: ${Te(d.section)}`,onRemove:()=>H("section")("")}]:[],...d.mode?[{key:"mode",label:`Mode: ${te[d.mode]}`,onRemove:()=>H("mode")("")}]:[],...d.status?[{key:"status",label:`Status: ${E[d.status]}`,onRemove:()=>H("status")("")}]:[],...d.severity?[{key:"severity",label:`Severity: ${Y[d.severity]}`,onRemove:()=>H("severity")("")}]:[]],Be=()=>{z(ce),W("")};function ze(){if(S==="loading")return e.jsx(F,{kind:"loading",compact:!0,title:"Memuat checklist…"});if(S==="error"||!p)return e.jsx(F,{kind:"error",compact:!0,title:"Gagal memuat checklist",hint:A,action:I});const i=p.sections.reduce((r,P)=>r+P.items.filter(Ee=>Ee.drifted).length,0),k=p.sections.map(r=>({section:r,matched:r.items.filter(Ve)})).filter(r=>!oe||r.matched.length>0);return e.jsxs("div",{children:[e.jsxs("div",{className:"vps-check-head",children:[e.jsxs("div",{className:"vps-check-score",children:[e.jsxs("span",{"data-testid":"score-total",className:"vps-check-score-num",children:[p.scoreTotal,"%"]}),e.jsx("div",{className:"vps-check-score-bar",children:e.jsx(Ne,{score:p.scoreTotal})}),e.jsx(ue,{size:11,tone:"subtle",children:"skor kepatuhan"})]}),i>0&&e.jsxs("div",{"data-testid":"drift-summary",className:"vps-drift",children:[e.jsx(ne,{name:"alert-triangle",size:14,color:"var(--clay-600)"}),i," item drift (regresi) sejak audit sebelumnya"]}),e.jsx(Re,{label:"Filter checklist",search:{value:K,onChange:W,label:"cari item",placeholder:"mis. ssh atau 5.2.1"},chips:De,filtersLabel:"Filter",onReset:Be,filters:e.jsxs("div",{className:"vps-filter-fields",children:[e.jsx(le,{label:"seksi",value:d.section,onChange:H("section"),options:p.sections.map(r=>[r.id,r.title])}),e.jsx(le,{label:"mode",value:d.mode,onChange:H("mode"),options:[["AUTO",te.AUTO],["AUDIT",te.AUDIT],["INFO",te.INFO]]}),e.jsx(le,{label:"status",value:d.status,onChange:H("status"),options:[["pass",E.pass],["fail",E.fail],["warn",E.warn],["na",E.na],["unknown",E.unknown]]}),e.jsx(le,{label:"severity",value:d.severity,onChange:H("severity"),options:[["critical",Y.critical],["high",Y.high],["medium",Y.medium],["low",Y.low]]})]})}),C.size>0&&e.jsxs("div",{className:"vps-remedi",role:"group","aria-label":"Alur perbaikan",children:[e.jsxs("ol",{className:"vps-remedi-steps",children:[e.jsxs("li",{"data-state":"done",children:["1 Pilih · ",C.size," item AUTO"]}),e.jsx("li",{"data-state":D?"done":"active",children:"2 Pratinjau"}),e.jsx("li",{"data-state":V?"active":"todo",children:"3 Terapkan"})]}),e.jsxs("div",{className:"vps-remedi-actions",children:[e.jsx(y,{size:"sm",variant:"secondary",leftIcon:"eye",loading:Q==="preview",onClick:Ce,children:"Pratinjau"}),e.jsx(y,{size:"sm",leftIcon:"shield",loading:Q==="apply",disabled:!V,onClick:Pe,children:"Terapkan"}),e.jsx(y,{size:"sm",variant:"ghost",onClick:_,children:"Batal"})]}),!V&&e.jsx("div",{className:"vps-remedi-hint",children:"Buat pratinjau dulu. Terapkan hanya memakai pratinjau untuk pilihan ini."})]}),D&&e.jsxs("div",{"data-testid":"remediate-preview",className:"vps-preview",children:[e.jsx("div",{className:"vps-preview-title",children:"Pratinjau (dry-run) — belum diterapkan. Mengubah pilihan membatalkannya."}),D.steps.map(r=>e.jsxs("div",{className:"vps-preview-line",children:[r.item," · ",r.status," ",r.detail]},r.item))]})]}),k.length===0?e.jsx(F,{kind:"empty",compact:!0,title:"Tidak ada item cocok",hint:"Ubah kata kunci atau reset filter."}):k.map(({section:r,matched:P})=>e.jsx(ns,{section:r,items:oe?P:r.items,expanded:oe?!0:J.has(r.id),onToggle:ee,busy:M,selected:C,onToggleItem:Z,onNa:Ae,onAttest:Ie,onSectionNa:Le},r.id))]})}return e.jsxs(ye,{open:!0,width:960,icon:"clipboard-list",eyebrow:"Detail server",title:t??"VPS",onClose:b,children:[e.jsxs(Oe,{"aria-label":"Bagian detail VPS",value:N,className:"vps-tabs",tabs:[{value:"ringkasan",label:"Ringkasan"},{value:"checklist",label:"Checklist"},{value:"pemasangan",label:"Pemasangan"},{value:"akses",label:"Akses"}],onChange:i=>R(i),children:[e.jsx(ie,{value:"ringkasan",children:e.jsxs("div",{className:"vps-summary",children:[e.jsxs("div",{"data-testid":"vps-detail",className:"vps-detail-meta",children:[l?`Audit terakhir ${be(l)||"—"}`:"Belum pernah diaudit",o&&` · disk ${o.disk} · mem ${o.mem} · load ${o.load}`]}),p&&e.jsxs("div",{className:"vps-summary-score",children:[e.jsx(ue,{size:12,tone:"muted",children:"Skor kepatuhan"}),e.jsxs("span",{"data-testid":"ringkasan-score",className:"vps-summary-score-num",children:[p.scoreTotal,"%"]})]}),m]})}),e.jsx(ie,{value:"checklist",children:ze()}),e.jsx(ie,{value:"pemasangan",children:e.jsx("div",{"data-testid":"vps-provisioning",children:h??e.jsx(F,{kind:"empty",compact:!0,title:"Pemasangan belum tersedia"})})}),e.jsx(ie,{value:"akses",children:u??e.jsx(F,{kind:"empty",compact:!0,title:"Akses belum tersedia"})})]}),n]})}const xe=He;function ls(s,t){if(t.status==="partial"&&t.detail.startsWith("not-logged-in"))return`${s} · belum login`;if(t.status==="partial")return`${s} · ${t.detail||xe.partial}`;const l=t.status==="ok"&&t.detail?` ${t.detail}`:"";return`${s} · ${Fe(xe,t.status)}${l}`}const rs={lab:"Uji coba: komponen dipasang langsung di host ini.",production:"Produksi: agen dipasang ke dalam image terisolasi; sebagian komponen tak tersedia di profil ini."};function os({status:s,children:t,title:l}){return e.jsxs("span",{title:l,className:"vps-prov-chip",children:[e.jsx("span",{"aria-hidden":!0,className:"vps-prov-dot","data-status":s}),t]})}function $e({components:s,checkedAt:t}){return!s||!t?e.jsx("span",{className:"vps-prov-hint",children:"Komponen belum diperiksa"}):e.jsxs("div",{className:"vps-prov-badges",children:[Object.entries(s).map(([l,o])=>e.jsx(os,{status:o.status,children:ls(l,o)},l)),e.jsxs("span",{className:"vps-prov-hint",children:["diperiksa ",new Date(t).toLocaleString("id-ID")]})]})}function cs(s,t,l){const o=new Map(t.map(u=>[u.id,u])),m=new Set,h=u=>{var x;if(!m.has(u)){m.add(u);for(const b of((x=o.get(u))==null?void 0:x.requires[l])??[])h(b)}};for(const u of s)h(u);return m}function ds({vps:s,onToast:t,onGotoTerminal:l}){const[o,m]=c.useState([]),[h,u]=Se("vps",`provisionProfile@${s.id}`,"lab",Me("lab","production")),[x,b]=c.useState(new Set),[j,p]=c.useState(""),[f,S]=c.useState(null),[L,A]=c.useState(null),[B,N]=c.useState(null),[R,d]=c.useState(null),[z,K]=c.useState(!1),{confirm:W,dialog:J}=me();c.useEffect(()=>{g.listVpsComponents().then(n=>m(n.components)).catch(()=>m([]))},[]);const q=o.filter(n=>n.profiles.includes(h)),M=cs(x,o,h),$=[...M],C=$.some(n=>{var w;return(w=o.find(V=>V.id===n))==null?void 0:w.needsDomain}),O=$.length>0&&(!C||j.trim().length>0),D=$.length===0?"Pilih minimal satu komponen.":C&&!j.trim()?"Isi domain dulu — komponen yang dipilih membutuhkannya.":null;function U(n){b(w=>{const V=new Set(w);return V.has(n)?V.delete(n):V.add(n),V})}async function Q(){d("probe");try{A(await g.probeVps(s.id)),t("Komponen diperiksa","ok","server")}catch(n){t(T("memeriksa komponen",n),"err","x-circle")}finally{d(null)}}async function a(){d("preview");try{S((await g.provisionPreview(s.id,{items:$,profile:h,domain:j||void 0})).steps)}catch(n){t(T("membuat pratinjau",n),"err","x-circle")}finally{d(null)}}async function v(){if(await W({title:`Pasang ${$.length} komponen di "${s.name}"?`,message:`Profil ${h}. Langkah dijalankan lewat SSH dan bisa memakan beberapa menit.`,impact:$.map(n=>{var w;return((w=o.find(V=>V.id===n))==null?void 0:w.label)??n}),confirmLabel:"Pasang",icon:"server"})){d("apply");try{const n=await g.provisionVps(s.id,{items:$,profile:h,domain:j||void 0,confirm:!0});S(n.steps),A({components:n.components,checkedAt:n.checkedAt}),N(n.setup),t("Provisioning selesai","ok","server")}catch(n){t(T("memasang komponen",n),"err","x-circle")}finally{d(null)}}}const I=async()=>{try{const{id:n}=await g.vpsConsole(s.id);l(n)}catch(n){t(T("membuka console",n),"err","x-circle")}},Z=async n=>{if(!navigator.clipboard){t("Salin tak tersedia di browser ini. Pilih tautannya lalu salin manual.","err","x-circle");return}try{await navigator.clipboard.writeText(n),K(!0),window.setTimeout(()=>K(!1),2e3)}catch(w){t(T("menyalin tautan",w),"err","x-circle")}},_=L?Object.fromEntries(L.components.map(n=>[n.id,{status:n.status,detail:n.detail}])):s.components??null,ee=(L==null?void 0:L.checkedAt)??s.componentsCheckedAt??null,se=_?Object.entries(_).filter(([,n])=>n.status==="partial"&&n.detail.startsWith("not-logged-in")):[];return e.jsxs("div",{className:"vps-prov",children:[e.jsxs("div",{className:"vps-prov-row",children:[e.jsx($e,{components:_,checkedAt:ee}),e.jsx(y,{size:"sm",variant:"ghost",onClick:Q,disabled:R!==null,children:"Periksa"})]}),e.jsxs("fieldset",{className:"vps-prov-fieldset",children:[e.jsx("legend",{className:"vps-prov-legend",children:"Profil"}),e.jsx("div",{className:"vps-prov-profiles",children:["lab","production"].map(n=>e.jsxs("div",{children:[e.jsx(Ue,{"aria-label":n,label:n,checked:h===n,onChange:()=>u(n)}),e.jsx("div",{className:"vps-prov-profile-hint",children:rs[n]})]},n))})]}),e.jsx("div",{className:"vps-prov-items",children:q.map(n=>{const w=M.has(n.id)&&!x.has(n.id);return e.jsxs("div",{className:"vps-prov-item",children:[e.jsx(_e,{"aria-label":n.label,label:n.label,checked:M.has(n.id),disabled:w,onChange:()=>U(n.id)}),w&&e.jsx("span",{className:"vps-prov-tag",children:"prasyarat"})]},n.id)})}),C&&e.jsx(G,{label:"Domain",hint:"A record harus sudah menunjuk ke IP VPS ini",children:e.jsx(X,{"aria-label":"Domain",value:j,onChange:n=>p(n.currentTarget.value),placeholder:"hanoman.contoh.id"})}),e.jsxs("div",{className:"vps-prov-row",children:[e.jsx(y,{variant:"ghost",onClick:a,disabled:!O||R!==null,children:"Pratinjau"}),e.jsx(y,{onClick:v,disabled:!O||R!==null,children:"Pasang"}),!O&&D&&e.jsx("span",{className:"vps-prov-reason",children:D})]}),e.jsx("div",{"aria-live":"polite",children:f&&e.jsx("pre",{tabIndex:0,"aria-label":"Hasil langkah provisioning",className:"vps-prov-steps",children:f.map(n=>`${n.item.padEnd(14)} ${n.status.padEnd(6)} ${n.detail}`).join(`
1
+ import{a1 as be,h as g,v as fe,d as me,aV as E,aW as Y,j as e,M as ye,c as Oe,aX as ie,aT as ue,m as F,I as ne,x as Re,B as y,i as T,q as Se,r as Me,aY as Ue,aJ as _e,e as G,f as X,aZ as He,l as Fe,aq as Ke,R as We,X as qe,O as Ge,W as Xe}from"./index-C5P4ykKO.js";import{R as c}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";const Ye=10*6e4,we=(s,t)=>!!s.lastSeenAt&&t-new Date(s.lastSeenAt).getTime()<Ye;function he(s,t=Date.now()){const l=s.lastSeenAt?we(s,t)?{state:"done",text:"terhubung"}:{state:"gagal",text:"tidak terjangkau"}:{state:"todo",text:"belum terhubung"},o=s.lastAuditAt?{state:"done",text:`diaudit ${be(s.lastAuditAt,t)||"—"}`}:{state:"todo",text:"belum diaudit"},m=s.lastAuditAt&&s.hardened?{state:"done",text:"diperkuat"}:{state:"todo",text:"belum diperkuat"};return[{key:"terhubung",label:"Terhubung",...l},{key:"diaudit",label:"Diaudit",...o},{key:"diperkuat",label:"Diperkuat",...m}]}const Je=(s,t)=>{const l=new Set(s);return l.size===new Set(t).size&&t.every(o=>l.has(o))};function ke(s,t){return s.length>0&&t!==null&&Je(s,t)}const Qe=s=>s==null?"Skor —":`Skor ${s}%`,Ze={pass:"check",fail:"x",warn:"alert-triangle",na:"minus",unknown:"circle"},es={pass:"var(--leaf-600)",fail:"var(--clay-600)",warn:"var(--status-warn)",na:"var(--text-subtle)",unknown:"var(--text-subtle)"},ss={critical:"var(--clay-600)",high:"var(--status-warn)",medium:"var(--text-subtle)",low:"var(--text-subtle)"},te={AUTO:"Otomatis",AUDIT:"Audit",INFO:"Info"};function re({text:s,color:t}){return e.jsx("span",{className:"vps-badge",style:{color:t,borderColor:t},children:s})}function Ne({score:s}){const t=s>=90?"vps-tone-ok":s>=50?"vps-tone-warn":"vps-tone-bad";return e.jsxs("div",{className:"vps-bar-wrap",children:[e.jsx("div",{className:"vps-bar",children:e.jsx("div",{className:`vps-bar-fill ${t}`,style:{width:`${s}%`}})}),e.jsxs("span",{className:"vps-bar-num",children:[s,"%"]})]})}function as({item:s,busy:t,selected:l,onToggle:o,onNa:m,onAttest:h}){const u=s.mode==="AUTO"&&!s.na,x=s.status==="fail"||s.status==="warn"||!!s.drifted;return e.jsxs("div",{"data-testid":`item-${s.id}`,title:`${te[s.mode]} · ${Y[s.severity]}`,className:`vps-item${s.na?" vps-item-na":""}`,children:[u?e.jsx("span",{className:"vps-touch",children:e.jsx("input",{type:"checkbox","aria-label":`Pilih ${s.title}`,checked:l,onChange:()=>o(s)})}):e.jsx("span",{className:"vps-item-gap"}),e.jsx(ne,{name:Ze[s.status],size:14,color:es[s.status]}),e.jsx("span",{className:"vps-item-title",children:s.title}),s.drifted&&e.jsx(re,{text:"drift",color:"var(--clay-600)"}),x&&e.jsx(re,{text:Y[s.severity],color:ss[s.severity]}),s.mode==="INFO"&&!s.attested&&e.jsx(y,{size:"sm",variant:"ghost",leftIcon:"check-circle",loading:t,onClick:()=>h(s),children:"Tandai terpenuhi"}),e.jsx(y,{size:"sm",variant:"ghost",leftIcon:s.na?"rotate-ccw":"minus-circle",loading:t,onClick:()=>m(s,!s.na),children:s.na?"Batal N/A":"N/A"})]})}const ce={section:"",mode:"",status:"",severity:""};function le({value:s,onChange:t,options:l,label:o}){return e.jsxs("select",{"aria-label":o,value:s,onChange:m=>t(m.target.value),className:"vps-select vps-touch-select",children:[e.jsxs("option",{value:"",children:[o,": semua"]}),l.map(([m,h])=>e.jsx("option",{value:m,children:h},m))]})}function ts(s){let t=0,l=0,o=0,m=0;for(const x of s)x.status==="fail"?t++:x.status==="warn"?l++:x.status==="unknown"&&o++,x.drifted&&m++;const h=x=>x.charAt(0).toLowerCase()+x.slice(1),u=[t&&`${t} ${h(E.fail)}`,l&&`${l} ${h(E.warn)}`,o&&`${o} ${h(E.unknown)}`].filter(Boolean);return{text:u.length?u.join(" · "):`semua ${h(E.pass)}`,drift:m}}function ns({section:s,items:t,expanded:l,onToggle:o,busy:m,selected:h,onToggleItem:u,onNa:x,onAttest:b,onSectionNa:j}){const p=ts(s.items),f=!!s.suggestion&&!s.suggestion.applicable;return e.jsxs("div",{className:"vps-section",children:[e.jsxs("button",{"data-testid":`section-${s.id}`,"aria-expanded":l,onClick:()=>o(s.id),className:`vps-section-head${l?" vps-section-open":""}`,children:[e.jsx(ne,{name:l?"chevron-down":"chevron-right",size:15,color:"var(--text-subtle)"}),e.jsx("span",{className:"vps-section-icon",children:s.icon}),e.jsx("span",{className:"vps-section-title",children:s.title}),e.jsx("span",{className:"vps-section-sum",children:p.text}),p.drift>0&&e.jsx(re,{text:"drift",color:"var(--clay-600)"}),f&&e.jsx(re,{text:"saran N/A",color:"var(--brass-700)"}),e.jsx(Ne,{score:s.score})]}),l&&e.jsxs("div",{className:"vps-section-body",children:[f&&e.jsxs("div",{"data-testid":`suggestion-${s.id}`,className:"vps-suggest",children:[e.jsx(ne,{name:"info",size:13,color:"var(--brass-700)"}),e.jsxs("span",{className:"vps-suggest-text",children:["Stack tak terdeteksi (",s.suggestion.detail,") — kemungkinan N/A. Cek Docker manual bila ragu."]}),e.jsx(y,{size:"sm",variant:"ghost",leftIcon:"minus-circle",loading:m===`section:${s.id}`,onClick:()=>j(s),children:"Tandai seksi N/A"})]}),t.map(S=>e.jsx(as,{item:S,busy:m===S.id,selected:h.has(S.id),onToggle:u,onNa:x,onAttest:b},S.id))]})]})}function is({vpsId:s,vpsName:t,lastAuditAt:l,health:o,summary:m,provisioning:h,access:u,onScore:x,onClose:b,onToast:j}){const[p,f]=c.useState(null),[S,L]=c.useState("loading"),[A,B]=c.useState(""),[N,R]=c.useState("ringkasan"),[d,z]=c.useState(ce),[K,W]=c.useState(""),[J,q]=c.useState(new Set),[M,$]=c.useState(null),[C,O]=c.useState(new Set),[D,U]=c.useState(null),[Q,a]=c.useState(""),v=c.useRef(x);v.current=x;const I=c.useCallback(()=>{L("loading"),g.vpsChecklist(s).then(i=>{var k;f(i),L("ready"),(k=v.current)==null||k.call(v,i.scoreTotal)}).catch(i=>{B(fe(i,"tak diketahui")),L("error")})},[s]);c.useEffect(()=>{I(),O(new Set),U(null),q(new Set),W(""),z(ce)},[I]);const Z=i=>{U(null),O(k=>{const r=new Set(k);return r.has(i.id)?r.delete(i.id):r.add(i.id),r})},_=()=>{O(new Set),U(null)},ee=i=>q(k=>{const r=new Set(k);return r.has(i)?r.delete(i):r.add(i),r}),{confirm:se,dialog:n}=me(),w=(D==null?void 0:D.forIds)??null,V=ke([...C],w);async function Ce(){const i=[...C];a("preview");try{U({steps:(await g.remediatePreview(s,i)).steps,forIds:i})}catch(k){j(T("membuat pratinjau remediasi",k),"err","x-circle")}finally{a("")}}async function Pe(){const i=[...C];if(!ke(i,w))return;const r=((p==null?void 0:p.sections.flatMap(P=>P.items))??[]).filter(P=>C.has(P.id));if(await se({title:`Terapkan ${i.length} item AUTO ke VPS ini?`,message:"Remediasi dijalankan langsung di server yang terdaftar.",impact:[...r.map(P=>`${P.id} · ${P.title}`),"Langkahnya idempoten dan anti-lockout.","Checklist diaudit ulang setelah selesai."],confirmLabel:"Terapkan",icon:"shield"})){a("apply");try{await g.remediate(s,i),_(),I(),j("Remediasi diterapkan · audit ulang","ok","shield")}catch(P){j(T("menerapkan remediasi",P),"err","x-circle")}finally{a("")}}}async function pe(i,k,r){$(i.id);try{await k(),I(),j(r,"ok","shield")}catch(P){j(T(`memperbarui ${i.id}`,P),"err","x-circle")}finally{$(null)}}const Ae=(i,k)=>pe(i,()=>g.markNa(s,i.id,k,k?"ditandai dari checklist":void 0),k?`${i.id} ditandai N/A`:`${i.id} kembali applicable`),Ie=i=>pe(i,()=>g.attestItem(s,i.id),`${i.id} ditandai terpenuhi`);async function Le(i){const k=i.items.map(r=>r.id);if(await se({title:`Tandai ${k.length} item seksi "${i.title}" sebagai N/A?`,message:"Stack-nya tak terdeteksi — cek Docker manual bila ragu.",confirmLabel:"Tandai N/A",icon:"shield"})){$(`section:${i.id}`);try{await g.markNaBulk(s,k,!0,"app-layer: stack tak terdeteksi"),I(),j(`Seksi ${i.title} ditandai N/A`,"ok","shield")}catch(r){j(T(`menandai seksi ${i.title} sebagai N/A`,r),"err","x-circle")}finally{$(null)}}}const ae=K.trim().toLowerCase(),oe=!!(d.section||d.mode||d.status||d.severity)||ae!=="",Ve=i=>(!d.section||i.section===d.section)&&(!d.mode||i.mode===d.mode)&&(!d.status||i.status===d.status)&&(!d.severity||i.severity===d.severity)&&(!ae||i.title.toLowerCase().includes(ae)||i.id.toLowerCase().includes(ae)||(i.code??"").toLowerCase().includes(ae)),H=i=>k=>z(r=>({...r,[i]:k})),Te=i=>{var k;return((k=p==null?void 0:p.sections.find(r=>r.id===i))==null?void 0:k.title)??i},De=[...d.section?[{key:"section",label:`Seksi: ${Te(d.section)}`,onRemove:()=>H("section")("")}]:[],...d.mode?[{key:"mode",label:`Mode: ${te[d.mode]}`,onRemove:()=>H("mode")("")}]:[],...d.status?[{key:"status",label:`Status: ${E[d.status]}`,onRemove:()=>H("status")("")}]:[],...d.severity?[{key:"severity",label:`Severity: ${Y[d.severity]}`,onRemove:()=>H("severity")("")}]:[]],Be=()=>{z(ce),W("")};function ze(){if(S==="loading")return e.jsx(F,{kind:"loading",compact:!0,title:"Memuat checklist…"});if(S==="error"||!p)return e.jsx(F,{kind:"error",compact:!0,title:"Gagal memuat checklist",hint:A,action:I});const i=p.sections.reduce((r,P)=>r+P.items.filter(Ee=>Ee.drifted).length,0),k=p.sections.map(r=>({section:r,matched:r.items.filter(Ve)})).filter(r=>!oe||r.matched.length>0);return e.jsxs("div",{children:[e.jsxs("div",{className:"vps-check-head",children:[e.jsxs("div",{className:"vps-check-score",children:[e.jsxs("span",{"data-testid":"score-total",className:"vps-check-score-num",children:[p.scoreTotal,"%"]}),e.jsx("div",{className:"vps-check-score-bar",children:e.jsx(Ne,{score:p.scoreTotal})}),e.jsx(ue,{size:11,tone:"subtle",children:"skor kepatuhan"})]}),i>0&&e.jsxs("div",{"data-testid":"drift-summary",className:"vps-drift",children:[e.jsx(ne,{name:"alert-triangle",size:14,color:"var(--clay-600)"}),i," item drift (regresi) sejak audit sebelumnya"]}),e.jsx(Re,{label:"Filter checklist",search:{value:K,onChange:W,label:"cari item",placeholder:"mis. ssh atau 5.2.1"},chips:De,filtersLabel:"Filter",onReset:Be,filters:e.jsxs("div",{className:"vps-filter-fields",children:[e.jsx(le,{label:"seksi",value:d.section,onChange:H("section"),options:p.sections.map(r=>[r.id,r.title])}),e.jsx(le,{label:"mode",value:d.mode,onChange:H("mode"),options:[["AUTO",te.AUTO],["AUDIT",te.AUDIT],["INFO",te.INFO]]}),e.jsx(le,{label:"status",value:d.status,onChange:H("status"),options:[["pass",E.pass],["fail",E.fail],["warn",E.warn],["na",E.na],["unknown",E.unknown]]}),e.jsx(le,{label:"severity",value:d.severity,onChange:H("severity"),options:[["critical",Y.critical],["high",Y.high],["medium",Y.medium],["low",Y.low]]})]})}),C.size>0&&e.jsxs("div",{className:"vps-remedi",role:"group","aria-label":"Alur perbaikan",children:[e.jsxs("ol",{className:"vps-remedi-steps",children:[e.jsxs("li",{"data-state":"done",children:["1 Pilih · ",C.size," item AUTO"]}),e.jsx("li",{"data-state":D?"done":"active",children:"2 Pratinjau"}),e.jsx("li",{"data-state":V?"active":"todo",children:"3 Terapkan"})]}),e.jsxs("div",{className:"vps-remedi-actions",children:[e.jsx(y,{size:"sm",variant:"secondary",leftIcon:"eye",loading:Q==="preview",onClick:Ce,children:"Pratinjau"}),e.jsx(y,{size:"sm",leftIcon:"shield",loading:Q==="apply",disabled:!V,onClick:Pe,children:"Terapkan"}),e.jsx(y,{size:"sm",variant:"ghost",onClick:_,children:"Batal"})]}),!V&&e.jsx("div",{className:"vps-remedi-hint",children:"Buat pratinjau dulu. Terapkan hanya memakai pratinjau untuk pilihan ini."})]}),D&&e.jsxs("div",{"data-testid":"remediate-preview",className:"vps-preview",children:[e.jsx("div",{className:"vps-preview-title",children:"Pratinjau (dry-run) — belum diterapkan. Mengubah pilihan membatalkannya."}),D.steps.map(r=>e.jsxs("div",{className:"vps-preview-line",children:[r.item," · ",r.status," ",r.detail]},r.item))]})]}),k.length===0?e.jsx(F,{kind:"empty",compact:!0,title:"Tidak ada item cocok",hint:"Ubah kata kunci atau reset filter."}):k.map(({section:r,matched:P})=>e.jsx(ns,{section:r,items:oe?P:r.items,expanded:oe?!0:J.has(r.id),onToggle:ee,busy:M,selected:C,onToggleItem:Z,onNa:Ae,onAttest:Ie,onSectionNa:Le},r.id))]})}return e.jsxs(ye,{open:!0,width:960,icon:"clipboard-list",eyebrow:"Detail server",title:t??"VPS",onClose:b,children:[e.jsxs(Oe,{"aria-label":"Bagian detail VPS",value:N,className:"vps-tabs",tabs:[{value:"ringkasan",label:"Ringkasan"},{value:"checklist",label:"Checklist"},{value:"pemasangan",label:"Pemasangan"},{value:"akses",label:"Akses"}],onChange:i=>R(i),children:[e.jsx(ie,{value:"ringkasan",children:e.jsxs("div",{className:"vps-summary",children:[e.jsxs("div",{"data-testid":"vps-detail",className:"vps-detail-meta",children:[l?`Audit terakhir ${be(l)||"—"}`:"Belum pernah diaudit",o&&` · disk ${o.disk} · mem ${o.mem} · load ${o.load}`]}),p&&e.jsxs("div",{className:"vps-summary-score",children:[e.jsx(ue,{size:12,tone:"muted",children:"Skor kepatuhan"}),e.jsxs("span",{"data-testid":"ringkasan-score",className:"vps-summary-score-num",children:[p.scoreTotal,"%"]})]}),m]})}),e.jsx(ie,{value:"checklist",children:ze()}),e.jsx(ie,{value:"pemasangan",children:e.jsx("div",{"data-testid":"vps-provisioning",children:h??e.jsx(F,{kind:"empty",compact:!0,title:"Pemasangan belum tersedia"})})}),e.jsx(ie,{value:"akses",children:u??e.jsx(F,{kind:"empty",compact:!0,title:"Akses belum tersedia"})})]}),n]})}const xe=He;function ls(s,t){if(t.status==="partial"&&t.detail.startsWith("not-logged-in"))return`${s} · belum login`;if(t.status==="partial")return`${s} · ${t.detail||xe.partial}`;const l=t.status==="ok"&&t.detail?` ${t.detail}`:"";return`${s} · ${Fe(xe,t.status)}${l}`}const rs={lab:"Uji coba: komponen dipasang langsung di host ini.",production:"Produksi: agen dipasang ke dalam image terisolasi; sebagian komponen tak tersedia di profil ini."};function os({status:s,children:t,title:l}){return e.jsxs("span",{title:l,className:"vps-prov-chip",children:[e.jsx("span",{"aria-hidden":!0,className:"vps-prov-dot","data-status":s}),t]})}function $e({components:s,checkedAt:t}){return!s||!t?e.jsx("span",{className:"vps-prov-hint",children:"Komponen belum diperiksa"}):e.jsxs("div",{className:"vps-prov-badges",children:[Object.entries(s).map(([l,o])=>e.jsx(os,{status:o.status,children:ls(l,o)},l)),e.jsxs("span",{className:"vps-prov-hint",children:["diperiksa ",new Date(t).toLocaleString("id-ID")]})]})}function cs(s,t,l){const o=new Map(t.map(u=>[u.id,u])),m=new Set,h=u=>{var x;if(!m.has(u)){m.add(u);for(const b of((x=o.get(u))==null?void 0:x.requires[l])??[])h(b)}};for(const u of s)h(u);return m}function ds({vps:s,onToast:t,onGotoTerminal:l}){const[o,m]=c.useState([]),[h,u]=Se("vps",`provisionProfile@${s.id}`,"lab",Me("lab","production")),[x,b]=c.useState(new Set),[j,p]=c.useState(""),[f,S]=c.useState(null),[L,A]=c.useState(null),[B,N]=c.useState(null),[R,d]=c.useState(null),[z,K]=c.useState(!1),{confirm:W,dialog:J}=me();c.useEffect(()=>{g.listVpsComponents().then(n=>m(n.components)).catch(()=>m([]))},[]);const q=o.filter(n=>n.profiles.includes(h)),M=cs(x,o,h),$=[...M],C=$.some(n=>{var w;return(w=o.find(V=>V.id===n))==null?void 0:w.needsDomain}),O=$.length>0&&(!C||j.trim().length>0),D=$.length===0?"Pilih minimal satu komponen.":C&&!j.trim()?"Isi domain dulu — komponen yang dipilih membutuhkannya.":null;function U(n){b(w=>{const V=new Set(w);return V.has(n)?V.delete(n):V.add(n),V})}async function Q(){d("probe");try{A(await g.probeVps(s.id)),t("Komponen diperiksa","ok","server")}catch(n){t(T("memeriksa komponen",n),"err","x-circle")}finally{d(null)}}async function a(){d("preview");try{S((await g.provisionPreview(s.id,{items:$,profile:h,domain:j||void 0})).steps)}catch(n){t(T("membuat pratinjau",n),"err","x-circle")}finally{d(null)}}async function v(){if(await W({title:`Pasang ${$.length} komponen di "${s.name}"?`,message:`Profil ${h}. Langkah dijalankan lewat SSH dan bisa memakan beberapa menit.`,impact:$.map(n=>{var w;return((w=o.find(V=>V.id===n))==null?void 0:w.label)??n}),confirmLabel:"Pasang",icon:"server"})){d("apply");try{const n=await g.provisionVps(s.id,{items:$,profile:h,domain:j||void 0,confirm:!0});S(n.steps),A({components:n.components,checkedAt:n.checkedAt}),N(n.setup),t("Provisioning selesai","ok","server")}catch(n){t(T("memasang komponen",n),"err","x-circle")}finally{d(null)}}}const I=async()=>{try{const{id:n}=await g.vpsConsole(s.id);l(n)}catch(n){t(T("membuka console",n),"err","x-circle")}},Z=async n=>{if(!navigator.clipboard){t("Salin tak tersedia di browser ini. Pilih tautannya lalu salin manual.","err","x-circle");return}try{await navigator.clipboard.writeText(n),K(!0),window.setTimeout(()=>K(!1),2e3)}catch(w){t(T("menyalin tautan",w),"err","x-circle")}},_=L?Object.fromEntries(L.components.map(n=>[n.id,{status:n.status,detail:n.detail}])):s.components??null,ee=(L==null?void 0:L.checkedAt)??s.componentsCheckedAt??null,se=_?Object.entries(_).filter(([,n])=>n.status==="partial"&&n.detail.startsWith("not-logged-in")):[];return e.jsxs("div",{className:"vps-prov",children:[e.jsxs("div",{className:"vps-prov-row",children:[e.jsx($e,{components:_,checkedAt:ee}),e.jsx(y,{size:"sm",variant:"ghost",onClick:Q,disabled:R!==null,children:"Periksa"})]}),e.jsxs("fieldset",{className:"vps-prov-fieldset",children:[e.jsx("legend",{className:"vps-prov-legend",children:"Profil"}),e.jsx("div",{className:"vps-prov-profiles",children:["lab","production"].map(n=>e.jsxs("div",{children:[e.jsx(Ue,{"aria-label":n,label:n,checked:h===n,onChange:()=>u(n)}),e.jsx("div",{className:"vps-prov-profile-hint",children:rs[n]})]},n))})]}),e.jsx("div",{className:"vps-prov-items",children:q.map(n=>{const w=M.has(n.id)&&!x.has(n.id);return e.jsxs("div",{className:"vps-prov-item",children:[e.jsx(_e,{"aria-label":n.label,label:n.label,checked:M.has(n.id),disabled:w,onChange:()=>U(n.id)}),w&&e.jsx("span",{className:"vps-prov-tag",children:"prasyarat"})]},n.id)})}),C&&e.jsx(G,{label:"Domain",hint:"A record harus sudah menunjuk ke IP VPS ini",children:e.jsx(X,{"aria-label":"Domain",value:j,onChange:n=>p(n.currentTarget.value),placeholder:"hanoman.contoh.id"})}),e.jsxs("div",{className:"vps-prov-row",children:[e.jsx(y,{variant:"ghost",onClick:a,disabled:!O||R!==null,children:"Pratinjau"}),e.jsx(y,{onClick:v,disabled:!O||R!==null,children:"Pasang"}),!O&&D&&e.jsx("span",{className:"vps-prov-reason",children:D})]}),e.jsx("div",{"aria-live":"polite",children:f&&e.jsx("pre",{tabIndex:0,"aria-label":"Hasil langkah provisioning",className:"vps-prov-steps",children:f.map(n=>`${n.item.padEnd(14)} ${n.status.padEnd(6)} ${n.detail}`).join(`
2
2
  `)})}),B&&e.jsxs("div",{className:"vps-prov-setup",children:[e.jsx("strong",{className:"vps-prov-setup-title",children:"Buat admin pertama"}),e.jsx("a",{href:B.url,target:"_blank",rel:"noreferrer",className:"vps-prov-setup-link",children:B.url}),e.jsxs("span",{className:"vps-prov-hint",children:["berlaku sampai ",new Date(B.expiresAt).toLocaleTimeString("id-ID")]}),e.jsx("div",{children:e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>void Z(B.url),children:z?"Tersalin":"Salin"})})]}),se.length>0&&e.jsxs("div",{className:"vps-prov-pending",children:[e.jsx(ne,{name:"alert-triangle"}),e.jsxs("span",{children:[se.map(([n])=>n).join(", ")," terpasang tapi belum login."]}),e.jsx(y,{size:"sm",variant:"ghost",onClick:I,children:"Login lewat Console"})]}),J]})}const js=(s,t=Date.now())=>we(s,t),gs=s=>s.lastAuditAt?s.hardened?"hardened":"belum":"unknown";function ve(s){const t={name:s.name.trim(),host:s.host.trim(),user:s.user.trim(),port:Number(s.port)||22};return s.keyPath.trim()&&(t.keyPath=s.keyPath.trim()),s.password&&(t.password=s.password),t}const us="opsional — dipakai sekali untuk memasang key hanoman, tidak disimpan";function de({open:s,title:t,submitLabel:l,initial:o,onClose:m,onSubmit:h}){const[u,x]=c.useState(o);c.useEffect(()=>{s&&x(o)},[s,o]);const b=p=>f=>x(S=>({...S,[p]:f.target.value})),j=!!(u.name.trim()&&u.host.trim()&&u.user.trim());return e.jsxs(ye,{open:s,onClose:m,icon:"server",eyebrow:"infra",title:t,footer:e.jsxs(e.Fragment,{children:[e.jsx(y,{variant:"ghost",size:"sm",onClick:m,children:"Batal"}),e.jsx(y,{size:"sm",leftIcon:"check",onClick:()=>j&&h(u),children:l})]}),children:[e.jsx(G,{label:"Nama",children:e.jsx(X,{value:u.name,onChange:b("name"),placeholder:"mis. web-1",style:{width:"100%"}})}),e.jsx(G,{label:"Host",hint:"hostname atau IP — tanpa user@",children:e.jsx(X,{value:u.host,onChange:b("host"),mono:!0,placeholder:"203.0.113.10",style:{width:"100%"}})}),e.jsxs("div",{className:"hn-grid-mobile vps-form-pair",children:[e.jsx(G,{label:"User SSH",hint:"root atau user ber-passwordless-sudo",children:e.jsx(X,{value:u.user,onChange:b("user"),mono:!0,placeholder:"deploy",style:{width:"100%"}})}),e.jsx(G,{label:"Port",children:e.jsx(X,{value:u.port,onChange:b("port"),mono:!0,placeholder:"22",style:{width:"100%"}})})]}),e.jsx(G,{label:"Password SSH",hint:us,children:e.jsx(X,{type:"password",value:u.password,onChange:b("password"),placeholder:"••••••••",style:{width:"100%"}})}),e.jsx(G,{label:"Key path",hint:"kosongkan bila memakai password di atas, atau key default mesin server",children:e.jsx(X,{value:u.keyPath,onChange:b("keyPath"),mono:!0,placeholder:"~/.ssh/id_ed25519",style:{width:"100%"}})})]})}const je={name:"",host:"",user:"",port:"22",keyPath:"",password:""},ms=s=>({name:s.name,host:s.host,user:s.user,port:String(s.port),keyPath:s.keyPath??"",password:""});function ge({steps:s,name:t}){return e.jsx("ol",{className:"vps-stepper","aria-label":`Kemajuan ${t}`,children:s.map(l=>e.jsxs("li",{className:`vps-step vps-step-${l.state}`,children:[e.jsx("span",{className:"vps-step-label",children:l.label}),e.jsx("span",{className:"vps-step-text",children:l.text})]},l.key))})}function bs({onToast:s,onGotoTerminal:t}){const[l,o]=c.useState([]),[m,h]=c.useState("loading"),[u,x]=c.useState(""),[b,j]=c.useState(null),[p,f]=c.useState(null),[S,L]=Se("vps","detailId",null,Xe),A=c.useMemo(()=>l.find(a=>a.id===S)??null,[l,S]),B=c.useCallback(a=>L(a?a.id:null),[L]),N=c.useCallback(()=>{g.listVps().then(a=>{o(a),h("ready")}).catch(a=>{x(fe(a,"tak diketahui")),h("error")})},[]);c.useEffect(()=>(N(),Ke(a=>{a.t==="vps"&&(o(a.vps),h("ready"))})),[N]);const{confirm:R,dialog:d}=me();async function z(a,v,I,Z,_){j(`${a}:${v}`);try{await I(),N(),s(Z,"ok","server")}catch(ee){s(T(_,ee),"err","x-circle")}finally{j(null)}}const K=async a=>{j(`audit:${a.id}`);try{await g.auditVps(a.id),N(),s(`${a.name} · audit selesai`,"ok","server")}catch(v){s(T("menjalankan audit",v),"err","x-circle")}finally{j(null)}};async function W(a){await R({title:`Harden "${a.name}"?`,message:"Pastikan akses key SSH non-password kamu sudah bekerja sebelum melanjutkan.",impact:[`Firewall: izinkan ${a.port}/80/443.`,"fail2ban & auto security update dipasang.","PermitRootLogin & PasswordAuthentication dimatikan.","NTP disinkronkan."],confirmLabel:"Harden",icon:"shield"})&&z("harden",a.id,()=>g.hardenVps(a.id),`${a.name} · harden selesai`,"menjalankan harden")}const J=a=>z("sesi",a.id,async()=>{const{id:v}=await g.vpsSession(a.id);t(v)},`${a.name} · sesi Claude dibuka`,"membuka sesi Claude"),q=a=>z("test",a.id,async()=>{const v=await g.testVps(a.id);if(!v.ok)throw new Error(v.out)},`${a.name} · koneksi ok`,"tes koneksi"),M=a=>z("console",a.id,async()=>{const{id:v}=await g.vpsConsole(a.id);t(v)},`${a.name} · console dibuka`,"membuka console");async function $(a){try{if(!await R({title:`Hapus registrasi VPS "${a.name}"?`,message:"Server-nya sendiri tak disentuh — hanya pendaftarannya di dashboard ini yang dihapus.",confirmLabel:"Hapus registrasi",run:()=>g.deleteVps(a.id)}))return;N(),s(`${a.name} dihapus dari daftar`,"ok","check")}catch(v){s(T("menghapus registrasi VPS",v),"err","x-circle")}}async function C(a){try{const v=await g.createVps(ve(a));f(null),N(),s(a.password?`${v.name} terdaftar · key hanoman terpasang · password dibuang`:`${v.name} terdaftar · jalankan audit`,"ok","server")}catch{s("Gagal mendaftarkan VPS — cek host/user, atau password SSH-nya","err","x-circle")}}async function O(a,v){try{const I=await g.updateVps(a.id,ve(v));f(null),N(),s(v.password?`${I.name} diperbarui · key hanoman terpasang · password dibuang`:`${I.name} diperbarui`,"ok","server")}catch{s("Gagal memperbarui VPS","err","x-circle")}}const D=a=>[{key:"tes",label:"Tes koneksi",icon:"plug-zap",onSelect:()=>void q(a)},{key:"console",label:"Buka console",icon:"terminal-square",onSelect:()=>void M(a)},{key:"sesi",label:"Sesi Claude",icon:"terminal",onSelect:()=>void J(a)},{key:"edit",label:"Edit",icon:"pencil",onSelect:()=>f(a)},{key:"harden",label:"Harden",icon:"shield",tone:"danger",onSelect:()=>void W(a)},{key:"hapus",label:"Hapus registrasi",icon:"trash-2",tone:"danger",onSelect:()=>void $(a)}],U=a=>e.jsxs(e.Fragment,{children:[e.jsx(ge,{steps:he(a),name:a.name}),e.jsx("div",{className:"vps-summary-comp",children:e.jsx($e,{components:a.components??null,checkedAt:a.componentsCheckedAt??null})})]}),Q=a=>e.jsxs("div",{className:"vps-access",children:[e.jsxs("dl",{className:"vps-access-list",children:[e.jsxs("div",{children:[e.jsx("dt",{children:"Host"}),e.jsx("dd",{children:a.host})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"User SSH"}),e.jsx("dd",{children:a.user})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"Port"}),e.jsx("dd",{children:a.port})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"Key"}),e.jsx("dd",{children:a.keyPath??"key default mesin server"})]})]}),e.jsxs("div",{className:"vps-access-actions",children:[e.jsx(y,{size:"sm",variant:"secondary",leftIcon:"plug-zap",loading:b===`test:${a.id}`,onClick:()=>void q(a),children:"Tes koneksi"}),e.jsx(y,{size:"sm",variant:"secondary",leftIcon:"terminal-square",loading:b===`console:${a.id}`,onClick:()=>void M(a),children:"Buka console"}),e.jsx(y,{size:"sm",variant:"secondary",leftIcon:"terminal",loading:b===`sesi:${a.id}`,onClick:()=>void J(a),children:"Sesi Claude"}),e.jsx(y,{size:"sm",variant:"ghost",leftIcon:"pencil",onClick:()=>f(a),children:"Edit"})]})]});return m==="loading"?e.jsx(F,{kind:"loading",title:"Memuat daftar VPS…"}):m==="error"?e.jsx(F,{kind:"error",title:"Gagal memuat daftar VPS",hint:`Alasan: ${u}. Pastikan server hanoman berjalan.`,action:N}):l.length===0?e.jsxs(e.Fragment,{children:[e.jsx(F,{kind:"empty",icon:"server",title:"Belum ada VPS",hint:"Daftarkan VPS untuk mulai audit & hardening.",action:()=>f("new"),actionLabel:"Daftarkan VPS"}),e.jsx(de,{open:p==="new",title:"Daftarkan VPS",submitLabel:"Daftarkan",initial:je,onClose:()=>f(null),onSubmit:C})]}):e.jsxs("div",{className:"vps-screen",children:[e.jsxs("div",{className:"vps-toolbar",children:[e.jsxs(ue,{size:12,tone:"muted",children:[l.length," VPS terdaftar"]}),e.jsx(y,{size:"sm",leftIcon:"plus",onClick:()=>f("new"),children:"Daftarkan VPS"})]}),e.jsx(We,{label:"Daftar VPS",children:l.map(a=>e.jsx(qe,{actions:e.jsxs(e.Fragment,{children:[e.jsx(y,{size:"sm",leftIcon:"radar",loading:b===`audit:${a.id}`,onClick:()=>void K(a),children:"Periksa"}),e.jsx(Ge,{label:`Aksi lain untuk ${a.name}`,title:a.name,items:D(a)})]}),children:e.jsxs("div",{className:"vps-row",children:[e.jsxs("button",{type:"button","aria-label":`Buka detail ${a.name}`,className:"vps-row-open",onClick:()=>B(a),children:[e.jsx("span",{className:"vps-row-name",children:a.name}),e.jsxs("span",{className:"vps-row-addr",children:[a.user,"@",a.host,a.port!==22?`:${a.port}`:""]})]}),e.jsx(ge,{steps:he(a),name:a.name}),e.jsx("span",{className:"vps-row-score",children:Qe(a.scoreTotal)})]})},a.id))}),A&&e.jsx(is,{vpsId:A.id,vpsName:A.name,lastAuditAt:A.lastAuditAt,health:A.health,summary:U(A),provisioning:e.jsx(ds,{vps:A,onToast:s,onGotoTerminal:t}),access:Q(A),onScore:()=>N(),onClose:()=>{B(null),N()},onToast:s}),e.jsx(de,{open:p==="new",title:"Daftarkan VPS",submitLabel:"Daftarkan",initial:je,onClose:()=>f(null),onSubmit:C}),p&&p!=="new"&&e.jsx(de,{open:!0,title:`Edit ${p.name}`,submitLabel:"Simpan",initial:ms(p),onClose:()=>f(null),onSubmit:a=>O(p,a)}),d]})}export{bs as VpsScreen,ge as VpsStepper,gs as hardenedLabel,js as isReachable,ve as vpsFormToBody};
@@ -0,0 +1 @@
1
+ import{cg as R,ch as F,ci as I,cj as O,ck as M,cl as U,bZ as $,bW as P,bX as B,bY as G,cm as z,a6 as H,a7 as K,cn as V,bc as Y,co as q,bR as W,cp as X,cq as Z,j as a,B as J,h as Q,aI as ee,b2 as te,ae as T,g as A,a9 as ae,aa as se,ab as ne,ac as re,ad as ie,f as le}from"./index-C5P4ykKO.js";import{R as f}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";const xe=R,S=[{key:"sesi",label:"Sesi harian",icon:"bell",sections:[{key:"sesi",label:"Sesi harian",icon:"bell",keywords:"notifikasi suara selesai keputusan gagal full-auto scaffold agen model default effort goal kondisi verifikasi scope metode workflow"}]},{key:"model",label:"Agen & model",icon:"cpu",sections:[{key:"model",label:"Agen & model",icon:"cpu",keywords:"override konflik rebase merge lead operator obrolan portal jatah orkestrasi fase effort model runtime"}]},{key:"integrasi",label:"Integrasi & akses",icon:"webhook",sections:[{key:"agent",label:"Akses AI Agent",icon:"bot",keywords:"token agent capability mcp master switch"},{key:"telegram",label:"Telegram",icon:"send",keywords:"bot token chat allowlist gateway operator agen progress uji koneksi"},{key:"webhook",label:"Webhook",icon:"webhook",keywords:"endpoint secret peristiwa pengiriman dokumentasi"},{key:"akses-klien",label:"Akses klien",icon:"user-check",keywords:"portal klien grant lihat tulis mulai sesi"},{key:"perangkat",label:"Perangkat",icon:"key-round",keywords:"token perangkat sinkron server pusat"},{key:"kendali-jarak-jauh",label:"Kendali jarak jauh",icon:"shield",keywords:"izin server pusat perangkat kendali"}]},{key:"lanjutan",label:"Lanjutan",icon:"sliders-horizontal",collapsible:!0,sections:[{key:"akun",label:"Akun",icon:"user-round",keywords:"password email logout ganti masuk"},{key:"users",label:"Pengguna",icon:"users",keywords:"undang hapus pengguna email password"},{key:"setup",label:"Setup awal",icon:"shield",keywords:"peruntukan hardening setup ulang"},{key:"konfigurasi",label:"Konfigurasi",icon:"sliders-horizontal",keywords:"env rahasia bootstrap sinkron runtime variabel"},{key:"aktivitas",label:"Log aktivitas",icon:"activity",keywords:"log sesi project hasil commit pr hapus"},{key:"custom-agent",label:"Custom agent",icon:"bot",keywords:"persona agen mention katalog"},{key:"zona-bahaya",label:"Zona bahaya",icon:"alert-triangle",keywords:"reset default kembalikan semua setelan"}]}],L="sesi",oe=S.flatMap(e=>e.sections.map(t=>t.key)),D=e=>oe.includes(e),ue=new Map([["umum","sesi"],["orkestrasi","model"]]);function je(e){if(typeof e!="string")return L;const t=ue.get(e)??e;return D(t)?t:L}function ce(e){return S.find(t=>t.sections.some(n=>n.key===e))??S[0]}function de(e){return S.flatMap(n=>n.sections).find(n=>n.key===e)??S[0].sections[0]}function Ne(e){const t=ce(e);return t.sections.length>1?`${t.label} · ${de(e).label}`:t.label}function Ae(e){const t=new URLSearchParams(e.replace(/^#/,"")).get("bagian");return t&&D(t)?t:null}const we=e=>Z(e).map(t=>({value:t,label:t==="xhigh"?"x-high":t})),Te=e=>W(X,e),fe=(e,t)=>{const n=q(e,t);return n===t?{}:{effort:n}},Le=[{value:"blip",label:"Blip · 0.1s"},{value:"pop",label:"Pop · 0.1s"},{value:"short",label:"Short · 0.15s"},{value:"ping",label:"Ping · 0.2s"},{value:"coin",label:"Coin · 0.3s"},{value:"alert",label:"Alert · 0.3s"},{value:"medium",label:"Medium · 0.4s"},{value:"chime",label:"Chime · 0.4s"},{value:"success",label:"Success · 0.4s"},{value:"bell",label:"Bell · 0.5s"},{value:"marimba",label:"Marimba · 0.6s"},{value:"long",label:"Long · 0.8s"},{value:"fanfare",label:"Fanfare · 0.9s"},{value:"off",label:"Senyap"}],De={model:"sonnet",effort:"medium",autoDefault:!0,autoScaffold:!0,notifyFail:!0,notifyDone:!0,notifySound:"short",notifyDecision:!0,notifyDecisionSound:"alert",notifyDecisionTelegram:!0,agentAccessEnabled:!1,scheduler:Y,goal:V,agent:"claude",codex:K,antigravity:H,verifyScope:"changed",method:z,conflict:G,lead:B,telegram:P,portalChat:$,orchestration:U,remoteControl:M,logShipping:O,logRetention:I,builtinAgents:{},builtinAgentPolicies:{},builtinRuntimeDefaults:F};function ge({save:e}){if(e.status==="idle")return null;if(e.status==="error")return a.jsxs("span",{className:"hn-set-save hn-set-save--err",role:"status","data-testid":"save-status",children:["Gagal — coba lagi",a.jsx(J,{size:"sm",variant:"ghost",leftIcon:"refresh-cw",onClick:e.retry,children:"Coba lagi"})]});const t=e.status==="saved"?"Tersimpan":"Menyimpan…",n=e.status==="saved"?"hn-set-save--ok":"hn-set-save--pending";return a.jsx("span",{className:`hn-set-save ${n}`,role:"status","data-testid":"save-status",children:t})}function he({text:e}){return a.jsx(a.Fragment,{children:e.split(/`([^`]+)`/).map((t,n)=>n%2===1?a.jsx("code",{className:"hn-set-mono hn-set-codeinline",children:t},n):t)})}function x({title:e,desc:t,children:n,last:r,save:c,search:o}){return a.jsxs("div",{className:`hn-setting-row hn-set-row${r?" hn-set-row--last":""}`,"data-setting-row":!0,"data-search":`${e} ${t??""} ${o??""}`,children:[a.jsxs("div",{className:"hn-set-row-text",children:[a.jsx("div",{className:"hn-set-row-title",children:e}),t&&a.jsx("div",{className:"hn-set-row-desc",children:a.jsx(he,{text:t})}),c&&a.jsx(ge,{save:c})]}),a.jsx("div",{className:"hn-setting-control hn-set-row-control",children:n})]})}function Ce({id:e,text:t}){return t?a.jsx("div",{id:e,className:"hn-set-hint",children:t}):null}function _e({children:e}){return a.jsx("div",{className:"hn-set-note",children:e})}function me({children:e}){return a.jsx("div",{className:"hn-set-prose",children:e})}const ke=400,ve=1800;function y(e){const t=f.useRef(e);t.current=e;const[n,r]=f.useState(null),c=f.useRef(e.value),[o,l]=f.useState("idle"),u=f.useRef(0),g=f.useRef(null),s=f.useRef(null),h=f.useRef(null),m=f.useRef(null),d=f.useRef(!1),k=f.useRef(0),v=()=>{s.current&&(clearTimeout(s.current),s.current=null)},j=()=>{h.current&&(clearTimeout(h.current),h.current=null)},N=(i,p)=>{if(v(),k.current===0&&Object.is(i,t.current.value)){p===u.current&&(g.current=null,r(null),l("idle"));return}k.current++,l("saving"),Promise.resolve(t.current.save(i)).then(E=>{k.current--,!(!d.current||p!==u.current)&&(g.current=null,E?(m.current=null,r({v:i,settled:!0}),l("saved"),j(),h.current=setTimeout(()=>{h.current=null,d.current&&l(b=>b==="saved"?"idle":b)},ve)):(m.current={v:i},r(null),l("error")))})},w=i=>{const p=++u.current;g.current={v:i,id:p},m.current=null,j(),r({v:i,settled:!1}),v();const E=t.current.delayMs??ke;if(E<=0){N(i,p);return}l("pending"),s.current=setTimeout(()=>{s.current=null;const b=g.current;b&&N(b.v,b.id)},E)};f.useEffect(()=>{Object.is(c.current,e.value)||(c.current=e.value,r(i=>i&&i.settled?null:i))},[e.value]);const C=()=>{const i=g.current;!s.current||!i||N(i.v,i.id)},_=()=>{const i=m.current;i&&w(i.v)};return f.useEffect(()=>(d.current=!0,()=>{d.current=!1;const i=g.current;s.current&&i&&(v(),Promise.resolve(t.current.save(i.v))),j()}),[]),{value:n?n.v:e.value,set:w,flush:C,status:o,retry:_}}function be({model:e,codexVer:t}){var r;const n=(t==null?void 0:t.version)??null;return re(e,n)?a.jsxs("div",{"data-testid":"codex-version-note",className:"hn-set-codex-note",children:["Codex CLI terpasang ",a.jsx("b",{children:n}),", sedangkan ",a.jsx("b",{children:e})," butuh ",a.jsx("b",{children:(r=ie(e))==null?void 0:r.minClient}),". Sesi tetap boleh dijalankan, tapi modelnya belum tentu dikenali CLI ini. Perbarui dengan ",a.jsx("code",{children:"npm i -g @openai/codex@latest"}),"."]}):null}function Re({id:e,label:t,active:n}){return a.jsxs("div",{className:"hn-set-agent-head",children:[a.jsx("div",{className:"hn-set-agent-name",children:t}),a.jsx("span",{"data-testid":`agent-badge-${e}`,className:`hn-set-agent-badge${n?" hn-set-agent-badge--on":""}`,children:n?"dipakai sesi baru":"tidak dipakai sekarang"})]})}function Fe({engine:e,labels:t,defaults:n,codexVer:r,save:c}){const o=y({value:e.agent,delayMs:0,save:s=>{const h=n[s];return c({agent:s,model:h.model,effort:s==="claude"?h.effort:T(s,h.model,h.effort)},`${t.msg.agent} → ${s}`)}}),l=y({value:e.model,delayMs:0,save:s=>c({model:s,...e.agent==="claude"?fe(s,e.effort):{effort:T(e.agent,s,e.effort)}},`${t.msg.model} → ${s}`)}),u=y({value:e.effort,delayMs:0,save:s=>c({effort:s},`${t.msg.effort} → ${s}`)}),g=o.value==="codex";return a.jsxs(a.Fragment,{children:[a.jsx(x,{title:t.agentTitle,desc:t.agentDesc,save:o,children:a.jsx(A,{size:"sm","aria-label":t.aria.agent,value:o.value,className:"hn-set-w-sm",options:ae,onChange:s=>o.set(s.target.value)})}),g&&a.jsx(be,{model:l.value,codexVer:r}),o.value==="antigravity"&&a.jsx(pe,{}),a.jsx(x,{title:"Model",save:l,children:a.jsx(A,{size:"sm","aria-label":t.aria.model,value:l.value,className:"hn-set-w-sm",options:se(o.value,l.value),onChange:s=>l.set(s.target.value)})}),a.jsx(x,{title:"Effort",desc:t.effortDesc,last:!0,save:u,children:a.jsx(A,{size:"sm","aria-label":t.aria.effort,value:u.value,className:"hn-set-w-xs",options:ne(o.value,l.value).map(s=>({value:s,label:s==="xhigh"?"x-high":s})),onChange:s=>u.set(s.target.value)})})]})}function Ie({eyebrow:e,title:t,desc:n,toggleTitle:r="Pakai setelan sendiri",toggleDesc:c,toggleAria:o,enabled:l,onToggle:u,inherited:g,inheritedTestId:s,children:h}){const m=y({value:l,delayMs:0,save:d=>u(d)});return a.jsxs(ee,{eyebrow:e,title:t,"data-setting-card":!0,"data-search":`${t} ${e}`,children:[a.jsx(me,{children:n}),a.jsx(x,{title:r,desc:c,save:m,last:!m.value,children:a.jsx(te,{"aria-label":o,checked:m.value,onChange:d=>m.set(d)})}),m.value?h:g?a.jsx("div",{"data-testid":s,className:"hn-set-inherited",children:g}):null]})}function Oe({label:e,value:t,min:n,max:r,placeholder:c,width:o,onCommit:l,onToast:u}){const[g,s]=f.useState(String(t));f.useEffect(()=>s(String(t)),[t]);const h=y({value:t,delayMs:0,save:d=>l(d)}),m=()=>{const d=g.trim(),k=d===""?NaN:Math.floor(Number(d));if(!Number.isFinite(k)||k<n){u==null||u(`${e}: isi angka ${n} atau lebih. Nilai sebelumnya dipertahankan.`,"warn","alert-triangle"),s(String(t));return}const v=Math.min(k,r);v!==k&&(u==null||u(`${e} dibatasi ke ${r}.`,"warn","alert-triangle"),s(String(v))),v!==t&&h.set(v)};return a.jsx(le,{"aria-label":e,type:"number",min:n,max:r,placeholder:c,className:o??"hn-set-w-xs",value:g,onChange:d=>s(d.target.value),onBlur:m,onKeyDown:d=>{d.key==="Enter"&&m()}})}function pe({info:e}){const[t,n]=f.useState(null);f.useEffect(()=>{var o,l;if(e!==void 0)return;let c=!0;return(l=(o=Q).getAntigravityVersion)==null||l.call(o).then(u=>{c&&n(u)}).catch(()=>{c&&n({version:null,error:"Versi Antigravity tidak dapat diperiksa."})}),()=>{c=!1}},[e]);const r=e===void 0?t:e;return a.jsxs("div",{role:"status","data-testid":"antigravity-version-note",className:"hn-set-codex-note",children:["Antigravity CLI · versi ",(r==null?void 0:r.version)??"tak terdeteksi",". ",r==null?void 0:r.error,a.jsx("p",{children:"Host/lab saja; sandbox belum didukung. Mode goal native belum didukung. Telemetri native tidak diketahui."}),a.jsx("a",{href:"https://antigravity.google/docs/cli",target:"_blank",rel:"noreferrer",children:"Panduan pemasangan dan login resmi"})]})}export{pe as A,Ce as B,be as C,L as D,Fe as E,Ie as F,Oe as N,me as P,S,x as a,Le as b,fe as c,Re as d,xe as e,Te as f,we as g,_e as h,De as i,ce as j,je as n,Ae as r,Ne as s,y as u};