hanoman 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/README.md +2 -0
  2. package/dist/build-info.json +3 -3
  3. package/dist/cli.js +362 -28
  4. package/dist/server.js +2521 -1070
  5. package/docs/agent-integration.md +4 -0
  6. package/package.json +1 -1
  7. package/prisma/migrations/20260915120000_log_terpusat/migration.sql +34 -0
  8. package/prisma/schema.prisma +39 -0
  9. package/web/assets/{ChangelogScreen-aqsJmmfe.js → ChangelogScreen-DVMpzy2Y.js} +1 -1
  10. package/web/assets/{DalangHanomanScreen-D3rNURz7.js → DalangHanomanScreen-aY89PmaJ.js} +1 -1
  11. package/web/assets/{DocPreviewModal-B7r_7p8N.js → DocPreviewModal-BTwj2rmX.js} +1 -1
  12. package/web/assets/{DocsWorkspace-_w6pncu9.js → DocsWorkspace-CgM5rgcr.js} +1 -1
  13. package/web/assets/{IdeScreen-etZ2QyO-.js → IdeScreen-B7oDlNQ0.js} +1 -1
  14. package/web/assets/{LeadScreen-Bo0K2-ML.js → LeadScreen-BzNU_kBC.js} +1 -1
  15. package/web/assets/{ReviewScreen-lRf2FW30.js → ReviewScreen-Dk0Zy4jJ.js} +1 -1
  16. package/web/assets/{SchedulerScreen-D75twy4J.js → SchedulerScreen-CxYqEqnw.js} +1 -1
  17. package/web/assets/SettingsScreen-D1Fop_V6.js +62 -0
  18. package/web/assets/{TeamScreen-nsttkE2J.js → TeamScreen-DwtrDuZG.js} +1 -1
  19. package/web/assets/TerminalScreen-CViC7rot.js +9 -0
  20. package/web/assets/{TriageScreen-7eM8gjr_.js → TriageScreen-DjCXx0F4.js} +1 -1
  21. package/web/assets/{VpsScreen-C29j52Tu.js → VpsScreen-C2WoJQ_j.js} +1 -1
  22. package/web/assets/{diff-view-RZNZ9Nz6.js → diff-view-Bep86yt6.js} +1 -1
  23. package/web/assets/index-Bd9gXx1g.js +923 -0
  24. package/web/assets/{live-CniaVDeP.js → live-BlNZnTbo.js} +1 -1
  25. package/web/index.html +1 -1
  26. package/web/assets/SettingsScreen-rMIR22vv.js +0 -62
  27. package/web/assets/TerminalScreen-BG9vRE1-.js +0 -9
  28. package/web/assets/index-BHI_f9DD.js +0 -923
@@ -0,0 +1,9 @@
1
+ import{j as t,d as ct,e as _,A as Qt,M as Oe,S as me,G as Zt,J as Dt,f as ut,B as at,I as Ce,w as en,D as tn,a as re,K as nn,N as rn,O as xt,Q as bt,c as Qe,U as an,V as sn,W as on,X as ln,Y as cn,Z as un,_ as We,$ as Bt,a0 as dt,a1 as dn,a2 as pn,a3 as it,h as Fe,a4 as $t,a5 as fn,a6 as mn,a7 as hn,g as Ze,a8 as Mt,l as gn,a9 as vt,x as xn,aa as et,p as bn,ab as vn,ac as Pe,ad as yn,ae as yt,af as kn,ag as jn}from"./index-Bd9gXx1g.js";import{R as o,r as Y}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import{D as wn,o as Sn}from"./xterm-3VOAfa_q.js";function pt(e){return e.endedAt?e.endedReason==="reconciled"?"interrupted":e.exitCode===null||e.exitCode===0?"completed":"failed":"running"}const Cn=new RegExp(["\\x1b\\[[?>][0-9;]*c","\\x1b\\[\\??[0-9]+;[0-9]+R","\\x1b\\[\\??[0-9;]*n","\\x1b\\[\\??[0-9;]*\\$y","\\x1b\\][0-9][0-9;]*;[^\\x07\\x1b]*(?:\\x07|\\x1b\\\\)","\\x1bP[0-9]*[$+>][a-z|][^\\x1b]*\\x1b\\\\"].join("|"),"g"),In=e=>e.length>0&&e.replace(Cn,"")==="";function En(e,n){if(e.type!=="keydown")return null;const r=e.key.toLowerCase();return e.metaKey||e.ctrlKey&&e.shiftKey?r==="c"?n?"copy":null:r==="v"?"paste":null:null}const Tn=new Set(["image/png","image/jpeg","image/webp"]);function kt(e){return(e!=null&&e.files?Array.from(e.files):[]).filter(r=>Tn.has(r.type))}function Rn(e){return e!=null&&e.types?Array.from(e.types).includes("Files"):!1}const zn=96,An=50,Ln=2,Nn=2;function Dn(e,n,r){if(!Number.isFinite(e)||e<=0)return n;const i=r+Ln,s=Math.floor((e-zn-An-Nn*i)/i);return s>=n?n:Math.max(0,s-1)}const Bn=/enter to select/i,$n=/to navigate/i,Mn=/^\s*[❯>*]?\s*(\d)\.\s/;function Fn(e,n){var s;const r=e.join(`
2
+ `);if(!Bn.test(r)||!$n.test(r))return null;const i=e[n];return i?((s=Mn.exec(i))==null?void 0:s[1])??null:null}const Ft=10,Pt=24,ft=13,Pn=15;function st(e){return Number.isFinite(e)?Math.min(Pt,Math.max(Ft,Math.round(e))):ft}const On=[{id:"esc",label:"Esc",seq:"\x1B",aria:"Kirim Escape ke terminal"},{id:"tab",label:"Tab",seq:" ",aria:"Kirim Tab ke terminal"},{id:"up",label:"↑",seq:"\x1B[A",aria:"Kirim panah atas ke terminal"},{id:"down",label:"↓",seq:"\x1B[B",aria:"Kirim panah bawah ke terminal"},{id:"left",label:"←",seq:"\x1B[D",aria:"Kirim panah kiri ke terminal"},{id:"right",label:"→",seq:"\x1B[C",aria:"Kirim panah kanan ke terminal"},{id:"enter",label:"Enter",seq:"\r",aria:"Kirim Enter ke terminal"}],Wn=/[\x00-\x1f\x7f]/;function mt(e){return!e||Wn.test(e)?"control":[...e].length>1?"bulk":"text"}function Ot(e){return e?`\x1B[4m${e}\x1B[24m`:""}function Ve(e){return e>0?`\x1B[${e}D\x1B[K`:""}const _n=500,Kn=5e3,Hn=64,qn=2;function Wt(){return{pending:"",since:null,altScreen:!1,suspendedUntil:0,typed:"",unechoed:"",gen:0,parsed:0}}const Gn=e=>e.gen!==e.parsed;function Un(e,n){return{...e,altScreen:n}}const Yn=/(password|passphrase|pass|pin)\s*(?:for\s+\S+\s*)?:\s*$/i;function Xn(e){return Yn.test(e)}function _t(e,n,r,i,s){return!s||!r.deliverable||e.altScreen||i<e.suspendedUntil||mt(n)!=="text"||r.cursorX+qn+1>r.cols||r.line.slice(r.cursorX).trim().length>0?!1:!Xn(r.line.trimEnd())}function Vn(e,n){for(let r=n.length;r>0;r-=1)if(e.endsWith(n.slice(0,r)))return r;return 0}function Jn(e,n,r,i,s){const c=mt(n);if(c==="text"&&Gn(e)&&s&&r.deliverable&&!e.altScreen&&i>=e.suspendedUntil)return e.unechoed.length>=Hn?{state:e,write:""}:{state:{...e,unechoed:e.unechoed+n,typed:""},write:"",deferred:!0};if(!_t(e,n,r,i,s)){const h=i<e.suspendedUntil&&c==="text"?(e.typed+n).slice(-32):"";return h===e.typed&&!e.unechoed?{state:e,write:""}:{state:{...e,typed:h,unechoed:""},write:""}}return{state:{...e,pending:e.pending+n,unechoed:e.unechoed+n,since:null,typed:""},write:Ot(n)}}function Qn(e,n){if(!n)return!1;const r=n.slice(-Math.min(2,n.length));return e.endsWith(r)}function Zn(e,n,r){return r>=e.suspendedUntil?e.typed?{...e,typed:""}:e:Qn(n,e.typed)?{...e,suspendedUntil:0,typed:""}:e}function er(e,n,r){return{state:{...e,pending:"",since:null,gen:e.gen+1},write:Ve(e.pending.length)+n}}function tr(e,n,r,i,s){if(n!==e.gen)return{state:e,write:""};const c=r.line.slice(0,r.cursorX),y=Zn({...e,parsed:n},c,i);if(!y.unechoed)return{state:y,write:""};const h=y.unechoed.slice(Vn(c,y.unechoed));if(!h)return{state:{...y,unechoed:""},write:""};const b=rr({...y,pending:""},h,r,i,s);return b.write?{state:{...b.state,unechoed:h},write:b.write}:{state:{...y,pending:"",unechoed:""},write:""}}function nr(e,n){return!e.pending||e.since!==null?e:{...e,since:n}}function rr(e,n,r,i,s){if(!n)return{state:e,write:""};const c=[...n];for(let y=0;y<c.length;y+=1){const h={...r,cursorX:r.cursorX+y};if(!_t({...e},c[y],h,i,s))return{state:e,write:""}}return{state:{...e,pending:n,since:null},write:Ot(n)}}function ar(e,n){return!e.pending||e.since===null||n<e.since+_n?{state:e,write:"",missed:!1}:{state:{...e,pending:"",since:null,suspendedUntil:n+Kn,typed:"",unechoed:""},write:Ve(e.pending.length),missed:!0}}function jt(e){const n=((e==null?void 0:e.gen)??0)+1;return{...Wt(),gen:n,parsed:n}}const ir=16;function sr(e){let n="",r;const i=()=>{if(r&&(clearTimeout(r),r=void 0),!n)return;const s=n;n="",e(s)};return{push(s,c){if(!c||mt(s)!=="text"){i(),s&&e(s);return}n+=s,r||(r=setTimeout(i,ir))},flush:i,dispose(){i()}}}const or=250,lr=512,cr={"\x1B":"\\e","\r":"\\r","\n":"\\n"," ":"\\t","\b":"\\b","":"\\x7f"};function wt(e){let n="";for(const r of e){const i=cr[r];if(i){n+=i;continue}const s=r.codePointAt(0);n+=s<32||s===127?`\\x${s.toString(16).padStart(2,"0")}`:r}return n}function ur(e){const n=e.batchMs??or,r=e.max??lr;let i=null,s=[],c,y=!1;const h=()=>{if(c&&(clearTimeout(c),c=void 0),!s.length)return;const b=s;s=[],e.send(b)};return{record(b,I,v){if(y)return;const l=e.now();i===null&&(i=l);const j={t:l-i,k:b,v:I};v!==void 0&&(j.n=v),s.push(j),s.length>r&&(s=s.slice(s.length-r)),c||(c=setTimeout(h,n))},flush:h,dispose(){h(),y=!0}}}const dr="",pr=350,fr=1e3;function ht(){return{text:"",sentPrefix:""}}function mr(e,n){const r=[...e],i=[...n];let s=0;for(;s<r.length&&s<i.length&&r[s]===i[s];)s+=1;return s}function gt(e,n){const r=mr(e,n);return dr.repeat([...e].length-r)+[...n].slice(r).join("")}function hr(e,n){return{...e,text:n}}function gr(e){return{state:{...e,sentPrefix:e.text},send:gt(e.sentPrefix,e.text)}}function xr(e){return{state:ht(),send:gt(e.sentPrefix,e.text)+"\r"}}function br(e){return{state:ht(),send:gt(e.sentPrefix,e.text)}}function vr(e,n){return n.held?{kind:"held",text:"tertahan — Kirim di atas"}:n.n>0?{kind:"queued",text:`diantre ${n.n}`}:e==="open"?{kind:"sent",text:"terkirim"}:null}function yr({sessionId:e,send:n,external:r,linkState:i,queue:s}){const[c,y]=o.useState(""),h=o.useRef(ht()),b=o.useRef(n);b.current=n;const I=o.useRef(void 0),v=o.useRef(void 0),l=()=>{clearTimeout(I.current),I.current=void 0,clearTimeout(v.current),v.current=void 0},j=E=>{l(),h.current=E.state,E.send&&b.current(E.send)},w=()=>j(gr(h.current));r.current=()=>{j(br(h.current)),y("")},o.useEffect(()=>()=>{r.current=()=>{}},[r]),o.useEffect(()=>l,[]);const k=E=>{h.current=hr(h.current,E),y(E),clearTimeout(I.current),I.current=setTimeout(w,pr),v.current||(v.current=setTimeout(w,fr))},S=()=>{j(xr(h.current)),y("")},m=vr(i,s);return t.jsxs("div",{className:"hn-terminal-composer",children:[t.jsx(ct,{size:"lg",mono:!0,value:c,"data-testid":"terminal-composer","aria-label":`Ketik untuk sesi ${e}`,placeholder:"mis. pnpm vitest --run",autoCapitalize:"off",autoCorrect:"off",spellCheck:!1,autoComplete:"off",enterKeyHint:"send",style:{flex:"1 1 160px",minWidth:0},onChange:E=>k(E.target.value),onBlur:()=>w(),onKeyDown:E=>{E.key!=="Enter"||E.nativeEvent.isComposing||(E.preventDefault(),S())}}),m&&t.jsx("span",{"data-testid":"terminal-composer-status",className:`hn-terminal-composer-status hn-terminal-composer-status--${m.kind}`,children:m.text})]})}const Kt=[500,1e3,2e3,4e3,8e3,8e3,8e3,8e3,8e3,8e3,8e3,8e3],St=Kt.length,kr=4096,jr=/[\r\n]/;function Ht({sessionId:e,onExit:n,onPhases:r,fontSize:i=ft,showKeys:s=!1,predict:c=!0,diag:y=!1}){const h=o.useRef(null),b=o.useRef(i);b.current=i;const I=o.useRef(c);I.current=c;const v=o.useRef(y);v.current=y;const l=o.useRef(null),j=o.useRef(n);j.current=n;const w=o.useRef(r);w.current=r;const[k,S]=o.useState({state:"connecting"}),[m,E]=o.useState({n:0,held:!1,full:!1}),L=o.useRef(()=>{}),F=o.useRef(()=>{}),K=o.useRef(()=>{}),g=o.useRef(()=>{}),C=o.useRef(()=>{}),d=o.useRef(()=>{});return o.useEffect(()=>{const u=h.current;if(!u)return;const N=getComputedStyle(document.documentElement),O=(p,R)=>N.getPropertyValue(p).trim()||R,x=new wn({fontFamily:O("--font-mono","monospace"),fontSize:st(b.current),cursorBlink:!0,macOptionClickForcesSelection:!0,theme:{background:O("--term-bg","#1c1810"),foreground:O("--term-fg","#e9e0cd")}}),q=new Sn;x.loadAddon(q),x.open(u);const ae=()=>{const p=u.getBoundingClientRect();return p.width>0&&p.height>0?p:null};ae()&&q.fit();let z,ie=!1,J=0,se,oe=!1;const ue=p=>{(z==null?void 0:z.readyState)===WebSocket.OPEN&&z.send(JSON.stringify(p))};l.current={term:x,fit:q,send:ue};const be=ur({now:()=>Date.now(),send:p=>ue({t:"diag",ev:p})}),G=(p,R,D)=>{v.current&&be.record(p,R,D)};let Z="",X=!1,ee=!1,he=0,te=0,ve=!1;const ne=new Map,Q=p=>{if(he+=1,te+=1,v.current){if(ne.size>256)for(const R of[...ne.keys()].slice(0,128))ne.delete(R);ne.set(he,Date.now())}ue({t:"in",d:p,seq:he})},H=()=>E({n:Z.length,held:X,full:ee}),De=p=>{if(!X&&!Z&&(z==null?void 0:z.readyState)===WebSocket.OPEN){Q(p);return}if(!(ve||In(p))){if(Z.length+p.length>kr){ee=!0,H();return}Z+=p,H()}};let $=Wt();const de=sr(De),Je=p=>de.push(p,!1);F.current=Je;const U=p=>{C.current(),Je(p)};d.current=U;const le=()=>{var R;const p=x.buffer.active;return{cursorX:p.cursorX,cols:x.cols,deliverable:!ve&&!ee,line:((R=p.getLine(p.viewportY+p.cursorY))==null?void 0:R.translateToString(!0))??""}},ye=()=>{te===0&&(z==null?void 0:z.readyState)===WebSocket.OPEN&&($=nr($,Date.now()))},ce=()=>{if(!Z||(z==null?void 0:z.readyState)!==WebSocket.OPEN){H();return}const p=Z;Z="",ee=!1,H(),Q(p)},pe=()=>{if(de.flush(),!Z){H();return}if(jr.test(Z)){X=!0,H();return}ce()};K.current=()=>{X=!1,ce()},g.current=()=>{Z="",X=!1,ee=!1,H()};const Be=p=>{C.current();const R=$.pending.length>0;G("data",wt(p));const D=le(),P=Jn($,p,D,Date.now(),I.current);$=P.state,P.write?x.write(P.write):P.deferred?G("pred","tangguh: frame server in flight"):G("pred",`tolak cx=${D.cursorX}/${D.cols} alt=${$.altScreen?1:0} deliverable=${D.deliverable?1:0} suspend=${Math.max(0,$.suspendedUntil-Date.now())}`),de.push(p,R||P.write.length>0||P.deferred===!0)},ke=setInterval(()=>{const p=ar($,Date.now());$=p.state,p.write&&x.write(p.write)},100),$e=()=>{_.issueWsTicket(`terminal:${e}`).then(({ticket:p})=>{if(ie)return;const R=location.protocol==="https:"?"wss:":"ws:",D=new WebSocket(`${R}//${location.host}${Qt.terminalWs(e)}`,[`hanoman-ticket.${p}`]);z=D,D.onopen=()=>{J=0,he=0,te=0;const P=Ve($.pending.length);P&&x.write(P),$=jt($),S({state:"open"}),ae()&&((typeof window.matchMedia!="function"||window.matchMedia("(hover: hover) and (pointer: fine)").matches)&&x.focus(),ue({t:"resize",cols:x.cols,rows:x.rows})),pe()},D.onmessage=P=>{var a;const B=JSON.parse(P.data);if(B.t==="data"){const f=er($,B.d??"");$=f.state;const T=$.gen;x.write(f.write,()=>{if(ie)return;const A=tr($,T,le(),Date.now(),I.current);$=A.state,A.write&&x.write(A.write),ye()}),ye()}else if(B.t==="ack"){if(te=Math.max(0,te-1),typeof B.seq=="number"){const f=ne.get(B.seq);f!==void 0&&(ne.delete(B.seq),G("ack",String(B.seq),Date.now()-f))}ye()}else B.t==="phase"?(a=w.current)==null||a.call(w,B.phases??[],B.complete===!0):B.t==="alt"?$=Un($,B.on===!0):B.t==="exit"&&(oe=!0,x.write(`\r
3
+ \x1B[33m— sesi berakhir (exit ${B.code}) —\x1B[0m\r
4
+ `),j.current(B.code??0))},D.onclose=P=>{if(!(ie||oe)){if(P.code===4004){ve=!0;const B=Ve($.pending.length);B&&x.write(B),$=jt($),Z="",X=!1,ee=!1,H(),S({state:"gone"});return}Te()}},D.onerror=()=>{}}).catch(()=>{ie||(x.write(`\r
5
+ \x1B[31mWebSocket admission gagal\x1B[0m\r
6
+ `),Te())})},Te=()=>{if(J>=St){S({state:"lost"});return}const p=Kt[J];J+=1,S({state:"retrying",attempt:J}),se=setTimeout($e,p)};L.current=()=>{ie||(clearTimeout(se),J=0,S({state:"retrying",attempt:1}),$e())},$e(),x.attachCustomKeyEventHandler(p=>{var D,P;const R=En(p,x.hasSelection());return R==="copy"?((D=navigator.clipboard)==null||D.writeText(x.getSelection()),!1):R==="paste"?((P=navigator.clipboard)==null||P.readText().then(B=>{B&&U(B)}),!1):!0}),x.attachCustomWheelEventHandler(p=>{if(!p.shiftKey)return!0;const R=ae();if(!R||x.rows<=0)return!0;const D=R.height/x.rows,P=Math.trunc(p.deltaY/D)||Math.sign(p.deltaY);return P&&x.scrollLines(P),!1});const Re=x.onData(Be),M=x.textarea,Ke=p=>G("key",p.key,p.keyCode),ge=p=>G("comp",`${p.type}:${wt(p.data??"")}`);M==null||M.addEventListener("keydown",Ke),M==null||M.addEventListener("compositionstart",ge),M==null||M.addEventListener("compositionupdate",ge),M==null||M.addEventListener("compositionend",ge);let fe=null,je=0,Ie=!1;const Ee=()=>{fe=null,je=0,Ie=!1},Me=p=>{if(p.touches.length!==1){Ee();return}fe=p.touches[0].clientY,je=0,Ie=!1},He=p=>{if(fe===null||p.touches.length!==1){Ee();return}const R=ae();if(!R||x.rows<=0)return;const D=p.touches[0].clientY;je+=fe-D,fe=D;const P=R.height/x.rows,B=Math.trunc(je/P);B!==0&&(x.scrollLines(B),je-=B*P,Ie=!0),p.preventDefault()},qe=p=>{var A,V;const R=fe!==null&&!Ie,D=((V=(A=p.changedTouches)==null?void 0:A[0])==null?void 0:V.clientY)??fe;if(Ee(),!R||D===null||D===void 0)return;const P=ae();if(!P||x.rows<=0)return;const B=Math.floor((D-P.top)/(P.height/x.rows)),a=x.buffer.active,f=Array.from({length:x.rows},(we,xe)=>{var Ae;return((Ae=a.getLine(a.viewportY+xe))==null?void 0:Ae.translateToString(!0))??""}),T=Fn(f,B);T&&U(T)},Ge=async p=>{for(const R of p)try{const{path:D}=await _.uploadTerminalAttachment(e,R);U(`${D} `)}catch(D){x.write(`\r
7
+ \x1B[31mlampiran gagal: ${D.message}\x1B[0m\r
8
+ `)}},Ue=p=>{const R=kt(p.clipboardData);R.length&&(p.preventDefault(),Ge(R))},Ye=p=>{Rn(p.dataTransfer)&&p.preventDefault()},ze=p=>{const R=kt(p.dataTransfer);R.length&&(p.preventDefault(),Ge(R))};u.addEventListener("paste",Ue),u.addEventListener("dragover",Ye),u.addEventListener("drop",ze),u.addEventListener("touchstart",Me,{passive:!0}),u.addEventListener("touchmove",He,{passive:!1}),u.addEventListener("touchend",qe,{passive:!0}),u.addEventListener("touchcancel",Ee,{passive:!0});const W=new ResizeObserver(p=>{var D;const R=((D=p[0])==null?void 0:D.contentRect)??u.getBoundingClientRect();R.width<=0||R.height<=0||(q.fit(),ue({t:"resize",cols:x.cols,rows:x.rows}))});return W.observe(u),()=>{ie=!0,clearTimeout(se),L.current=()=>{},F.current=()=>{},d.current=()=>{},K.current=()=>{},g.current=()=>{},l.current=null,u.removeEventListener("paste",Ue),u.removeEventListener("dragover",Ye),u.removeEventListener("drop",ze),u.removeEventListener("touchstart",Me),u.removeEventListener("touchmove",He),u.removeEventListener("touchend",qe),u.removeEventListener("touchcancel",Ee),W.disconnect(),clearInterval(ke),de.dispose(),be.dispose(),M==null||M.removeEventListener("keydown",Ke),M==null||M.removeEventListener("compositionstart",ge),M==null||M.removeEventListener("compositionupdate",ge),M==null||M.removeEventListener("compositionend",ge),Re.dispose(),z==null||z.close(),x.dispose()}},[e]),o.useEffect(()=>{const u=l.current,N=h.current;if(!u||!N)return;const O=st(i);if(u.term.options.fontSize===O)return;u.term.options.fontSize=O;const x=N.getBoundingClientRect();x.width<=0||x.height<=0||(u.fit.fit(),u.send({t:"resize",cols:u.term.cols,rows:u.term.rows}))},[i]),o.useEffect(()=>{const u=l.current,N=h.current;if(!u||!N)return;const O=N.getBoundingClientRect();O.width<=0||O.height<=0||(u.fit.fit(),u.send({t:"resize",cols:u.term.cols,rows:u.term.rows}))},[s]),t.jsxs("div",{style:{display:"flex",flexDirection:"column",height:"100%",minHeight:0},children:[(k.state!=="open"&&k.state!=="connecting"||m.held||m.full)&&t.jsxs("div",{"data-testid":"terminal-link",style:{display:"flex",alignItems:"center",gap:8,flex:"0 0 auto",flexWrap:"wrap",padding:"3px 8px",fontFamily:"var(--font-mono)",fontSize:11,background:k.state==="retrying"||m.held?"var(--status-warn-tint)":"var(--status-err-tint)",color:"var(--text-body)"},children:[k.state==="retrying"&&t.jsxs("span",{children:["menyambung ulang… (",k.attempt,"/",St,")"]}),k.state==="gone"&&t.jsx("span",{children:"sesi tidak ditemukan di tmux"}),k.state==="lost"&&t.jsxs(t.Fragment,{children:[t.jsx("span",{children:"terputus"}),t.jsx("button",{type:"button",className:"hn-terminal-action hn-terminal-action--text",onClick:()=>L.current(),children:"Sambungkan lagi"})]}),m.n>0&&!m.held&&t.jsxs("span",{"data-testid":"terminal-queue",children:[m.n," ketikan diantre"]}),m.held&&t.jsxs(t.Fragment,{children:[t.jsxs("span",{"data-testid":"terminal-held",children:[m.n," ketikan tertahan — belum dikirim"]}),t.jsx("button",{type:"button",className:"hn-terminal-action hn-terminal-action--text",onClick:()=>K.current(),children:"Kirim"}),t.jsx("button",{type:"button",className:"hn-terminal-action hn-terminal-action--text",onClick:()=>g.current(),children:"Buang"})]}),m.full&&t.jsx("span",{"data-testid":"terminal-queue-full",children:"antrean penuh"})]}),t.jsx("div",{ref:h,"data-testid":"terminal-host",style:{flex:1,minHeight:0,width:"100%",background:"var(--term-bg)",padding:8,borderRadius:"var(--radius-sm)",touchAction:"pan-x pinch-zoom",overscrollBehavior:"contain"}}),s&&t.jsx(yr,{sessionId:e,send:u=>F.current(u),external:C,linkState:k.state,queue:m}),s&&t.jsx(wr,{onKey:u=>d.current(u)})]})}function wr({onKey:e}){return t.jsx("div",{className:"hn-terminal-keys",role:"group","aria-label":"Tombol terminal",children:On.map(n=>t.jsx("button",{type:"button",className:"hn-terminal-key","aria-label":n.aria,title:n.aria,onClick:()=>e(n.seq),children:n.label},n.id))})}const Ct=20;function Sr(e,n){if(!n)return"—";const r=new Date(n).getTime()-new Date(e).getTime();if(!Number.isFinite(r)||r<0)return"—";const i=Math.round(r/1e3);if(i<60)return`${i} dtk`;const s=Math.round(i/60);return s<60?`${s} mnt`:`${Math.floor(s/60)} jam ${s%60} mnt`}function Cr(e){switch(pt(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 qt=e=>pt(e)==="interrupted"?"—":Sr(e.startedAt,e.endedAt),Gt=e=>Dt[e]??e;function Ir({projects:e,onClose:n,onRestart:r}){const[i,s]=o.useState([]),[c,y]=o.useState(0),[h,b]=o.useState(1),[I,v]=o.useState(!1),[l,j]=o.useState(""),[w,k]=o.useState(""),[S,m]=o.useState(""),[E,L]=o.useState(""),[F,K]=o.useState(null);o.useEffect(()=>{const d=setTimeout(()=>L(S.trim()),250);return()=>clearTimeout(d)},[S]),o.useEffect(()=>{b(1)},[l,w,E]),o.useEffect(()=>{let d=!0;return v(!0),_.listSessionHistory({projectId:l||void 0,kind:w||void 0,q:E||void 0,page:h,limit:Ct}).then(u=>{d&&(y(u.total),s(u.items))}).catch(()=>{d&&(s([]),y(0))}).finally(()=>{d&&v(!1)}),()=>{d=!1}},[l,w,E,h]);const g=tn(c,h,Ct),C=d=>{var u;return((u=e.find(N=>N.id===d))==null?void 0:u.name)??d};return t.jsxs(Oe,{open:!0,title:"Riwayat sesi",icon:"history",onClose:n,width:900,children:[t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,flexWrap:"wrap",marginBottom:10},children:[t.jsx(ct,{size:"sm",leftIcon:"search",placeholder:"mis. spec-412 atau reverse","aria-label":"Cari riwayat sesi",value:S,onChange:d=>m(d.target.value),style:{flex:"1 1 200px"}}),t.jsx(me,{size:"sm","aria-label":"Filter project",value:l,onChange:d=>j(d.target.value),options:[{value:"",label:"Semua project"}].concat(e.map(d=>({value:d.id,label:d.name})))}),t.jsx(me,{size:"sm","aria-label":"Filter jenis",value:w,onChange:d=>k(d.target.value),options:[{value:"",label:"Semua jenis"}].concat(Zt.map(d=>({value:d,label:Dt[d]})))})]}),i.length===0&&!I?t.jsx(ut,{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."}):t.jsxs("div",{style:{display:"flex",flexDirection:"column",maxHeight:"60vh",overflowY:"auto"},children:[i.map(d=>{const u=Cr(d);return t.jsx("button",{onClick:()=>K(d),style:{cursor:"pointer",display:"block",width:"100%",flex:"0 0 auto",font:"inherit",color:"inherit",textAlign:"left",background:"transparent",padding:"9px 8px",border:"none",borderBottom:"1px solid var(--border-hair)"},children:t.jsxs("span",{className:"hn-dense-row hn-picker-row",style:{display:"flex",alignItems:"center",gap:10,width:"100%"},children:[t.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:11,color:"var(--text-subtle)",flex:"0 0 132px"},children:new Date(d.startedAt).toLocaleString("id-ID")}),t.jsx(at,{size:"sm",tone:"neutral",children:Gt(d.kind)}),t.jsx("span",{className:"hn-picker-title",style:{flex:1,minWidth:0,fontSize:13,color:"var(--text-strong)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:d.title??d.specId??C(d.projectId)}),d.transcriptBytes!==null&&t.jsx(Ce,{name:"file-text",size:12,color:"var(--text-subtle)"}),t.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:11,color:"var(--text-muted)",flex:"0 0 72px"},children:qt(d)}),t.jsx(at,{size:"sm",tone:u.tone,children:u.label})]})},d.id)}),I&&t.jsx("div",{style:{padding:"10px 8px",textAlign:"center",fontSize:11,color:"var(--text-subtle)"},children:"memuat…"})]}),t.jsx(en,{page:g.page,pageCount:g.pageCount,total:c,from:g.from,to:g.to,onPage:b,unit:"sesi"}),F&&t.jsx(Er,{row:F,projectName:C(F.projectId),onBack:()=>K(null),onRestart:r})]})}function Er({row:e,projectName:n,onBack:r,onRestart:i}){const[s,c]=o.useState(null),[y,h]=o.useState("idle");o.useEffect(()=>{if(e.transcriptBytes===null){h("none"),c(null);return}let v=!0;return h("loading"),_.sessionTranscript(e.id).then(l=>{v&&(c(l.text),h("idle"))}).catch(()=>{v&&(c(null),h("error"))}),()=>{v=!1}},[e.id,e.transcriptBytes]);const b=pt(e)==="interrupted",I=[["Project",n],["Sesi",e.sessionId],["Jenis",Gt(e.kind)],["Agen",[e.agent,e.model,e.effort].filter(Boolean).join(" · ")],["Mulai",new Date(e.startedAt).toLocaleString("id-ID")],[b?"Terakhir terlihat hidup":"Selesai",e.endedAt?new Date(e.endedAt).toLocaleString("id-ID"):"berjalan"],...b&&e.reconciledAt?[["Terdeteksi mati",new Date(e.reconciledAt).toLocaleString("id-ID")]]:[],["Durasi",qt(e)],["Direktori",e.cwd]];return e.specId&&I.splice(1,0,["Backlog",`${e.specId}${e.title?` · ${e.title}`:""}`]),e.branch&&I.push(["Branch",e.branch]),t.jsxs(Oe,{open:!0,title:e.title??e.specId??e.sessionId,icon:"history",onClose:r,width:1e3,children:[t.jsxs("div",{style:{display:"flex",gap:8,alignItems:"center",marginBottom:10},children:[t.jsx(re,{size:"sm",variant:"ghost",leftIcon:"arrow-left",onClick:r,children:"Kembali"}),t.jsx("div",{style:{flex:1}}),s&&t.jsx(re,{size:"sm",variant:"secondary",leftIcon:"copy",onClick:()=>{var v;return void((v=navigator.clipboard)==null?void 0:v.writeText(s))},children:"Salin transkrip"}),nn(e.kind)&&t.jsx(re,{size:"sm",leftIcon:"play",onClick:()=>i(e),children:"Mulai lagi"})]}),b&&t.jsxs(rn,{tone:"warn",title:"Sesi terputus — hasilnya tak diketahui",style:{marginBottom:12},children:["Panenya sudah lenyap saat hanoman menyala lagi (reboot, ",t.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."]}),t.jsx("div",{style:{display:"grid",gridTemplateColumns:"auto 1fr",gap:"4px 12px",marginBottom:12,fontSize:12},children:I.map(([v,l])=>t.jsxs(o.Fragment,{children:[t.jsx("span",{style:{color:"var(--text-subtle)"},children:v}),t.jsx("span",{style:{fontFamily:"var(--font-mono)",color:"var(--text-body)",wordBreak:"break-all"},children:l})]},v))}),y==="loading"&&t.jsx("div",{style:{fontSize:12,color:"var(--text-subtle)"},children:"memuat transkrip…"}),y==="none"&&t.jsx("div",{style:{fontSize:12,color:"var(--text-subtle)"},children:b?"Tanpa transkrip — panenya sudah lenyap sebelum hanoman sempat mengambilnya.":"Tanpa transkrip — sesi ini ditutup sebelum fitur riwayat ada, atau panenya tak menyisakan keluaran."}),y==="error"&&t.jsx("div",{style:{fontSize:12,color:"var(--clay-600)"},children:"Transkrip tak terbaca lagi di server."}),s!==null&&t.jsx("pre",{style:{maxHeight:"52vh",overflow:"auto",margin:0,padding:10,background:"var(--bone-200)",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",fontFamily:"var(--font-mono)",fontSize:11,whiteSpace:"pre-wrap",wordBreak:"break-word",color:"var(--text-body)"},children:s})]})}function Tr({open:e,projectId:n,projectName:r,onClose:i,onCreated:s}){var K;const[c,y]=o.useState("claude"),[h,b]=o.useState("claude-opus-5"),[I,v]=o.useState("xhigh"),[l,j]=o.useState({claude:{model:"claude-sonnet-5",effort:"medium"},codex:{...xt}}),[w,k]=o.useState(!1),[S,m]=o.useState(null);o.useEffect(()=>{e&&(_.getSettings().then(g=>{const C={claude:{model:g.model,effort:g.effort},codex:{...xt,...g.codex??{}}},d=g.agent==="codex"?"codex":"claude",u=bt(C,d);j(C),y(d),b(u.model),v(u.effort)}).catch(()=>{}),_.getCodexVersion().then(g=>m(g.version)).catch(()=>{}))},[e]);const E=g=>{y(g);const C=bt(l,g);b(C.model),v(C.effort)},L=g=>{b(g),v(C=>c==="codex"?cn(g,C):un(g,C))};async function F(){k(!0);try{const{id:g}=await _.createTerminal(n,{agent:c,model:h,effort:I});s(g),i()}catch{}finally{k(!1)}}return t.jsxs(Oe,{open:e,onClose:i,icon:"plus",eyebrow:r,title:"Sesi baru",footer:t.jsxs(t.Fragment,{children:[t.jsx(re,{variant:"ghost",onClick:i,children:"Batal"}),t.jsx(re,{leftIcon:"play",disabled:w,onClick:()=>void F(),children:"Buka sesi"})]}),children:[t.jsxs("div",{style:{fontSize:12.5,color:"var(--text-muted)",marginBottom:12,lineHeight:1.5},children:["Runtime untuk sesi ini. Default dari setelan global; ubah bila perlu. Sesi lahir dengan pilihan ini untuk seluruh hidupnya — ",t.jsx("code",{children:"/model"})," di terminal tetap bisa mengubahnya."]}),t.jsx(Qe,{label:"Agen",hint:"Mesin yang menjalankan sesi ini. Perilaku sesi sama; hanya CLI-nya berbeda.",children:t.jsx(me,{"aria-label":"Agen",value:c,style:{width:"100%"},options:[{value:"claude",label:"Claude Code"},{value:"codex",label:"Codex CLI"}],onChange:g=>E(g.target.value)})}),t.jsx(Qe,{label:"Model",children:t.jsx(me,{"aria-label":"Model",value:h,style:{width:"100%"},options:an(c).map(g=>({value:g.id,label:g.label})),onChange:g=>L(g.target.value)})}),t.jsx(Qe,{label:"Effort",children:t.jsx(me,{"aria-label":"Effort",value:I,style:{width:"100%"},options:sn(c,h).map(g=>({value:g,label:g})),onChange:g=>v(g.target.value)})}),c==="codex"&&on(h,S)&&t.jsxs("div",{"data-testid":"codex-version-note",style:{fontSize:12,lineHeight:1.5,marginBottom:12,padding:"8px 10px",borderRadius:8,background:"var(--warn-bg, #fdf6e3)",color:"var(--text-muted)"},children:["Codex CLI terpasang ",t.jsx("b",{children:S}),", sedangkan ",t.jsx("b",{children:h})," butuh ",t.jsx("b",{children:(K=ln(h))==null?void 0:K.minClient}),". Sesi tetap boleh dijalankan, tapi modelnya belum tentu dikenali CLI ini."]})]})}const Rr=()=>({rows:1,cols:1,cells:[null]}),It=e=>({...e,rows:e.rows+1,cells:[...e.cells,...Array(e.cols).fill(null)]});function Et(e){const n=e.cols+1,r=[];for(let i=0;i<e.rows;i++)for(let s=0;s<n;s++)r.push(s<e.cols?e.cells[i*e.cols+s]??null:null);return{rows:e.rows,cols:n,cells:r}}function Tt(e,n){if(e.rows===1||n<0||n>=e.rows)return e;const r=[...e.cells];return r.splice(n*e.cols,e.cols),{...e,rows:e.rows-1,cells:r}}function Rt(e,n){if(e.cols===1||n<0||n>=e.cols)return e;const r=e.cols-1,i=[];for(let s=0;s<e.rows;s++)for(let c=0;c<e.cols;c++)c!==n&&i.push(e.cells[s*e.cols+c]??null);return{rows:e.rows,cols:r,cells:i}}function ot(e,n,r){if(n<0||n>=e.cells.length)return e;const i=e.cells.map(s=>r!==null&&s===r?null:s);return i[n]=r,{...e,cells:i}}const zr=(e,n)=>({...e,cells:e.cells.map(r=>r&&n.has(r)?r:null)}),Ut=e=>({id:crypto.randomUUID(),name:e,layout:Rr()});function zt(){const e=Ut("Utama");return{groups:[e],active:e.id}}const _e=e=>e.groups.find(n=>n.id===e.active)??e.groups[0];function Ar(e,n){const r=Ut(n);return{groups:[...e.groups,r],active:r.id}}const Lr=(e,n,r)=>({...e,groups:e.groups.map(i=>i.id===n?{...i,name:r}:i)});function Nr(e,n){if(e.groups.length===1)return e;const r=e.groups.filter(i=>i.id!==n);return r.length===e.groups.length?e:{groups:r,active:e.active===n?r[0].id:e.active}}const Dr=(e,n)=>e.groups.some(r=>r.id===n)?{...e,active:n}:e;function Se(e,n){const r=_e(e);return{...e,groups:e.groups.map(i=>i.id===r.id?{...i,layout:n(i.layout)}:i)}}function lt(e,n,r){const i=_e(e),s=r===null?e.groups:e.groups.map(c=>c.id===i.id?c:{...c,layout:ot(c.layout,c.layout.cells.indexOf(r),null)});return{...e,groups:s.map(c=>c.id===i.id?{...c,layout:ot(c.layout,n,r)}:c)}}function Le(e,n){const r=_e(e).layout.cells.indexOf(null);return r===-1?e:lt(e,r,n)}const Br=(e,n)=>({...e,groups:e.groups.map(r=>({...r,layout:ot(r.layout,r.layout.cells.indexOf(n),null)}))}),At=e=>new Set(e.groups.flatMap(n=>n.layout.cells.filter(r=>r!==null))),Lt=(e,n)=>({...e,groups:e.groups.map(r=>({...r,layout:zr(r.layout,n)}))}),Yt="hanoman.terminal.workspace",Xt="hanoman.terminal.layout",Ne=e=>We.parse({version:1,groups:e.groups});function Xe(e,n){const r=e.groups,i=n&&r.some(s=>s.id===n)?n:r[0].id;return{groups:r,active:i}}function $r(e){try{const n=JSON.parse(e);if(!n||typeof n!="object")return null;const r=n,i=We.parse({version:1,groups:r.groups});return{workspace:i,active:typeof r.active=="string"&&i.groups.some(s=>s.id===r.active)?r.active:i.groups[0].id}}catch{return null}}function Mr(){try{const e=localStorage.getItem(Yt);if(e)return $r(e);const n=localStorage.getItem(Xt);if(!n)return null;const r=JSON.parse(n),i={id:crypto.randomUUID(),name:"Utama",layout:r};return{workspace:We.parse({version:1,groups:[i]}),active:i.id}}catch{return null}}function tt(){try{localStorage.removeItem(Yt),localStorage.removeItem(Xt)}catch{}}const Vt=e=>`hanoman.terminal.workspace.v2.${encodeURIComponent(e)}`;function Fr(e){try{const n=localStorage.getItem(Vt(e));if(!n)return null;const r=JSON.parse(n),i=We.parse(r.workspace);if(!Number.isInteger(r.revision)||(r.revision??-1)<0)return null;const s=typeof r.active=="string"&&i.groups.some(c=>c.id===r.active)?r.active:i.groups[0].id;return{workspace:i,revision:r.revision,active:s}}catch{return null}}function nt(e,n){try{const r=We.parse(n.workspace);if(!Number.isInteger(n.revision)||n.revision<0)return;const i=r.groups.some(s=>s.id===n.active)?n.active:r.groups[0].id;localStorage.setItem(Vt(e),JSON.stringify({workspace:r,revision:n.revision,active:i}))}catch{}}function rt(e){if(!(e instanceof dt)||e.status!==409)return null;const n=e.detail;if((n==null?void 0:n.code)!=="revision-conflict")return null;const r=dn.safeParse(n.current);return r.success?r.data:null}function Pr(e){const n=Y.useRef(null);n.current||(n.current=zt());const[r,i]=Y.useState(n.current),[s,c]=Y.useState("loading"),[y,h]=Y.useState(null),[b,I]=Y.useState(!1),v=Y.useRef(r),l=Y.useRef(0),j=Y.useRef(!1),w=Y.useRef(Promise.resolve()),k=Y.useRef(0),S=Y.useCallback(d=>{v.current=d,i(d)},[]),m=Y.useCallback(d=>{j.current=d,I(d)},[]),E=Y.useCallback(d=>{const u=w.current.then(d,d);return w.current=u.then(()=>{},()=>{}),u},[]),L=Y.useCallback((d,u="ready",N=null,O=v.current.active)=>{const x=d.workspace?Xe(d.workspace,O):zt();l.current=d.revision,S(x),c(u),h(N),m(!0),d.workspace&&nt(e,{workspace:d.workspace,revision:d.revision,active:x.active})},[S,m,e]),F=Y.useCallback(d=>{const u=Fr(e);u&&(l.current=u.revision,S(Xe(u.workspace,u.active))),m(!1),c("recovering"),h(d instanceof Error?d.message:"Layout server belum tersambung")},[S,m,e]),K=Y.useCallback(()=>E(async()=>{try{L(await _.getTerminalWorkspace())}catch(d){F(d)}}),[L,E,F]);Y.useEffect(()=>{const d=++k.current;return c("loading"),h(null),m(!1),E(async()=>{try{const u=await _.getTerminalWorkspace();if(d!==k.current)return;if(u.workspace){L(u),tt();return}const N=Mr();if(!N){L(u);return}try{const O=await _.putTerminalWorkspace({baseRevision:u.revision,workspace:N.workspace});if(d!==k.current)return;S(Xe(O.workspace,N.active)),l.current=O.revision,nt(e,{workspace:O.workspace,revision:O.revision,active:N.active}),tt(),c("ready"),h(null),m(!0)}catch(O){const x=rt(O);x!=null&&x.workspace?(L(x,"conflict","Layout server lebih baru; layout lokal lama tidak diunggah"),tt()):F(O)}}catch(u){d===k.current&&F(u)}}),()=>{k.current+=1}},[L,E,F,S,m,e]),Y.useEffect(()=>{const d=()=>{K()},u=()=>{document.visibilityState==="visible"&&K()};return window.addEventListener("focus",d),document.addEventListener("visibilitychange",u),()=>{window.removeEventListener("focus",d),document.removeEventListener("visibilitychange",u)}},[K]);const g=Y.useCallback(d=>E(async()=>{if(!j.current)return!1;const u=d(v.current);let N,O;try{N=Ne(u),O=Ne(v.current)}catch{return c("conflict"),h("Layout tidak valid dan tidak disimpan"),!1}if(Bt(N,O))return!0;try{return L(await _.putTerminalWorkspace({baseRevision:l.current,workspace:N}),"ready",null,u.active),!0}catch(x){const q=rt(x);if(!(q!=null&&q.workspace))return F(x),!1;const ae=d(Xe(q.workspace,v.current.active));try{const z=await _.putTerminalWorkspace({baseRevision:q.revision,workspace:Ne(ae)});return L(z,"conflict","Layout berubah di perangkat lain; perubahan ini diterapkan ulang",ae.active),!0}catch(z){if(!rt(z)&&!(z instanceof dt&&z.status===409))return F(z),!1;try{L(await _.getTerminalWorkspace(),"conflict","Layout berubah lagi di perangkat lain; state terbaru dimuat")}catch(ie){F(ie)}return!1}}}),[L,E,F]),C=Y.useCallback(d=>{const u=Dr(v.current,d);S(u);const N=Ne(u);nt(e,{workspace:N,revision:l.current,active:u.active})},[S,e]);return{workspace:r,status:s,message:y,writable:b,mutate:g,setActive:C,refresh:K}}function Zr({userId:e="test-user",projects:n,backlog:r=[],focusSession:i,startedSession:s,onStartedSessionHandled:c,onStartBacklog:y,onOpenReview:h,onOpenSessionReview:b,titleOf:I,onIntegrate:v,onIntegrateSession:l,specOf:j}){var B;const[w,k]=o.useState([]),[S,m]=o.useState([]),E=Pr(e),{workspace:L,status:F,message:K,writable:g,mutate:C,setActive:d,refresh:u}=E,[N,O]=Fe("terminal","project",((B=n[0])==null?void 0:B.id)??"",bn),x=$t(),[q,ae]=Fe("terminal","fontSize",x?Pn:ft,xn),[z,ie]=Fe("terminal","keys",x,et),[J,se]=Fe("terminal","predict",!0,et),[oe,ue]=Fe("terminal","diag",!1,et),be=a=>ae(f=>st(f+a)),[G,Z]=o.useState(!1),[X,ee]=o.useState(null),[he,te]=o.useState(!1),[ve,ne]=o.useState(null),[Q,H]=o.useState(!1),[De,$]=o.useState(!1),de=fn(),U=mn()==="mobile",[le,ye]=o.useState(0),[ce,pe]=o.useState(null),Be=o.useRef(null),[ke,$e]=o.useState(!1);o.useEffect(()=>{_.listTerminals().then(a=>{k(a),$e(!0)}).catch(()=>{})},[]),o.useEffect(()=>hn(a=>{a.t==="sessions"?k(a.sessions):a.t==="cleanups"&&m(a.cleanups)}),[]),o.useEffect(()=>{if(!ke||!g)return;const a=new Set(w.map(T=>T.id)),f=Lt(L,a);Bt(Ne(f),Ne(L))||C(T=>Lt(T,a))},[C,w,ke,g,L]),o.useEffect(()=>{!s||s.specId==null||!ke||(k(a=>a.some(f=>f.id===s.id)?a:[...a,{...s,cwd:"",exited:!1}]),pe(s.id),c==null||c())},[c,ke,s]),o.useEffect(()=>{if(!i){Be.current=null;return}!ke||Be.current===i||w.some(a=>a.id===i&&!a.exited)&&(Be.current=i,pe(i))},[i,w,ke]),o.useEffect(()=>{if(!ce)return;const a=L.groups.find(f=>f.layout.cells.includes(ce));if(a){a.id!==L.active&&d(a.id);return}g&&C(f=>{if(At(f).has(ce))return f;const T=Le(f,ce);return T!==f||!U?T:lt(f,le,ce)})},[le,U,C,ce,d,g,L]),o.useEffect(()=>{X&&!w.some(a=>a.id===X)&&ee(null)},[X,w]);const Te=S.filter(a=>a.error),Re=a=>w.find(f=>f.id===a)??null,M=a=>{var f;return((f=n.find(T=>T.id===a))==null?void 0:f.name)??a};function Ke(a){k(f=>f.some(T=>T.id===a)?f:[...f,{id:a,projectId:N,cwd:"",exited:!1}]),C(f=>Le(f,a)),pe(a)}async function ge(){if(!N)return;const{id:a}=await _.createShell(N);k(f=>[...f,{id:a,projectId:N,cwd:"",exited:!1}]),C(f=>Le(f,a)),pe(a)}async function fe(a,f){if(y&&!f){te(!1),ne(null),y(a);return}const T=jn(a.source);try{const{id:A}=await _.startSession({spec:a.id,flow:T,...f?{force:f}:{}});k(V=>V.some(we=>we.id===A)?V:[...V,{id:A,projectId:a.projectId,specId:a.id,flow:T,cwd:"",exited:!1}]),C(V=>Le(V,A)),pe(A),te(!1),ne(null)}catch(A){if(de.offerRetry(A,a.id,we=>fe(a,we)))return;const V=A instanceof dt&&(A.status===400||A.status===422);ne(`${a.id} · gagal mulai${V?" · project belum punya repoDir":""}`)}}async function je(a,f){try{const T=a.specId?await _.startSession({spec:a.specId,flow:a.flow??"feature",...f?{force:f}:{}}):a.kind==="shell"?await _.createShell(a.projectId):a.kind==="terminal"?await _.createTerminal(a.projectId,{agent:a.agent==="codex"?"codex":"claude",...a.model?{model:a.model}:{},...a.effort?{effort:a.effort}:{}}):await(f?_.createTerminalFlow(a.projectId,a.kind,{force:f}):_.createTerminalFlow(a.projectId,a.kind));k(A=>A.some(V=>V.id===T.id)?A:[...A,{id:T.id,projectId:a.projectId,specId:a.specId??void 0,cwd:"",exited:!1}]),C(A=>Le(A,T.id)),pe(T.id),$(!1)}catch(T){if((a.specId||a.kind!=="shell"&&a.kind!=="terminal")&&de.offerRetry(T,`${a.projectId} · ${a.title??a.specId??a.kind}`,A=>je(a,A)))return}}const Ie=new Set(w.filter(a=>a.specId&&!a.exited).map(a=>a.specId)),Ee=r.filter(a=>a.stage!=="done"&&!Ie.has(a.id));function Me(a){k(f=>f.filter(T=>T.id!==a)),_.deleteTerminal(a).catch(()=>{})}const He=o.useCallback((a,f)=>{k(T=>T.map(A=>A.id===a?{...A,exited:!0,exitCode:f}:A))},[]),qe=(a,f)=>{ye(a),C(T=>lt(T,a,f))},Ge=a=>{pe(a),C(f=>Le(f,a))},Ue=a=>{C(f=>Br(f,a))},Ye=At(L),ze=w.filter(a=>!Ye.has(a.id)),W=_e(L).layout;o.useEffect(()=>{if(!ce)return;const a=W.cells.indexOf(ce);a<0||(ye(a),pe(null))},[W.cells,ce]),o.useEffect(()=>{le>=W.cells.length&&ye(Math.max(0,W.cells.length-1))},[le,W.cells.length]);const p=W.rows===1&&W.cols===1&&!W.cells[0]&&w.length===0,R=t.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:10,marginBottom:10},children:[t.jsxs("div",{className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:8},children:[t.jsx("span",{style:{flex:1,minWidth:0,fontSize:12,color:"var(--text-muted)"},children:"Ukuran teks terminal"}),t.jsx(Ze,{size:"sm",icon:"minus",label:"Perkecil teks terminal",disabled:q<=Ft,onClick:()=>be(-1)}),t.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontSize:12,minWidth:44,textAlign:"center"},children:[q,"px"]}),t.jsx(Ze,{size:"sm",icon:"plus",label:"Perbesar teks terminal",disabled:q>=Pt,onClick:()=>be(1)})]}),t.jsxs("div",{className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:8},children:[t.jsx("span",{style:{flex:1,minWidth:0,fontSize:12,color:"var(--text-muted)"},children:"Papan tombol layar (Esc · panah · Enter)"}),t.jsx(re,{size:"sm",variant:"secondary","aria-pressed":z,onClick:()=>ie(a=>!a),children:z?"Sembunyikan":"Tampilkan"})]}),t.jsxs("div",{className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:8},children:[t.jsx("span",{style:{flex:1,minWidth:0,fontSize:12,color:"var(--text-muted)"},children:"Ketik responsif (huruf tampil sebelum echo server)"}),t.jsx(re,{size:"sm",variant:"secondary","aria-pressed":J,"aria-label":`${J?"Matikan":"Nyalakan"} ketik responsif`,onClick:()=>se(a=>!a),children:J?"Matikan":"Nyalakan"})]}),t.jsxs("div",{className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:8},children:[t.jsx("span",{style:{flex:1,minWidth:0,fontSize:12,color:"var(--text-muted)"},children:"Rekam jalur ketik (diagnostik — merekam setiap tombol)"}),t.jsx(re,{size:"sm",variant:"secondary","aria-pressed":oe,"aria-label":`${oe?"Matikan":"Nyalakan"} rekam jalur ketik`,onClick:()=>ue(a=>!a),children:oe?"Matikan":"Nyalakan"})]}),U&&t.jsx(me,{size:"sm","aria-label":"Project sesi baru",value:N,onChange:a=>O(a.target.value),options:n.map(a=>({value:a.id,label:a.name}))})]}),D=[{key:"backlog",label:"Ambil backlog",icon:"inbox",onSelect:()=>{ne(null),te(!0)}},{key:"history",label:"Riwayat sesi",icon:"history",onSelect:()=>$(!0)},{key:"shell",label:"Terminal biasa",icon:"terminal",onSelect:()=>void ge()},{key:"col+",label:"+ Kolom",icon:"columns-2",disabled:!g,onSelect:()=>void C(a=>Se(a,Et))},{key:"row+",label:"+ Baris",icon:"rows-2",disabled:!g,onSelect:()=>void C(a=>Se(a,It))},{key:"col-",label:"Hapus kolom aktif",icon:"columns-2",disabled:!g||W.cols===1,onSelect:()=>void C(a=>Se(a,f=>Rt(f,le%f.cols)))},{key:"row-",label:"Hapus baris aktif",icon:"rows-2",disabled:!g||W.rows===1,onSelect:()=>void C(a=>Se(a,f=>Tt(f,Math.floor(le/f.cols))))}],P={display:"flex",flexDirection:"column",gap:G?8:12,...G?{position:"fixed",inset:0,zIndex:100,background:"var(--surface-page)",paddingTop:"max(12px, var(--safe-top))",paddingRight:"max(12px, var(--safe-right))",paddingBottom:"max(12px, var(--safe-bottom))",paddingLeft:"max(12px, var(--safe-left))"}:{flex:"1 1 0",minHeight:640}};return t.jsxs("div",{"data-testid":"terminal-root",style:P,children:[t.jsxs("div",{style:{display:"flex",gap:8,flexDirection:G?"row":"column",alignItems:G?"center":"stretch"},children:[t.jsx(Wr,{compact:G,ws:L,writable:g,onSelect:d,onAdd:()=>void C(a=>Ar(a,`Grup ${a.groups.length+1}`)),onRename:(a,f)=>void C(T=>Lr(T,a,f)),onRemove:a=>void C(f=>Nr(f,a))}),t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,flexWrap:"wrap",...G?{flex:1,minWidth:0}:{}},children:[!U&&t.jsxs(t.Fragment,{children:[t.jsx(re,{size:"sm",variant:"ghost",disabled:!g,onClick:()=>void C(a=>Se(a,Et)),children:"+ Kolom"}),t.jsx(re,{size:"sm",variant:"ghost",disabled:!g,onClick:()=>void C(a=>Se(a,It)),children:"+ Baris"})]}),t.jsx("div",{style:{flex:1,minWidth:0}}),F!=="ready"&&t.jsx("span",{"data-testid":"terminal-workspace-status",title:K??void 0,style:{fontSize:12,color:F==="conflict"?"var(--status-warn)":"var(--text-muted)"},children:F==="loading"?"Memuat layout server…":F==="recovering"?t.jsxs(t.Fragment,{children:[t.jsx("span",{children:"Layout server belum tersambung"})," ",t.jsx("button",{type:"button",onClick:()=>void u(),children:"Retry"})]}):K??"Layout berubah di perangkat lain"}),S.length>0&&t.jsx("span",{"data-testid":"worktree-cleanups",title:S.map(a=>`${a.sessionId}${a.error?` — ${a.error}`:""}`).join(`
9
+ `),style:{fontSize:12,color:Te.length?"var(--status-err)":"var(--text-muted)"},children:Te.length?`${Te.length} worktree gagal dibersihkan`:`membersihkan ${S.length} worktree…`}),!U&&t.jsxs(t.Fragment,{children:[t.jsx(me,{size:"sm",value:N,onChange:a=>O(a.target.value),options:n.map(a=>({value:a.id,label:a.name}))}),t.jsx(re,{size:"sm",variant:"secondary",leftIcon:"inbox",onClick:()=>{ne(null),te(!0)},children:"Ambil backlog"}),t.jsx(re,{size:"sm",variant:"secondary",leftIcon:"history",title:"Riwayat sesi yang sudah berlalu — buka kembali atau baca transkripnya",onClick:()=>$(!0),children:"Riwayat"}),t.jsx(re,{size:"sm",variant:"secondary",leftIcon:"terminal",title:"Buka shell tmux tanpa Claude di project terpilih — jalankan command di project",onClick:()=>void ge(),children:"Terminal biasa"})]}),t.jsx(re,{size:"sm",leftIcon:"plus",onClick:()=>H(!0),children:"Sesi baru"}),t.jsx(Mt,{label:U?"Aksi terminal lain":"Tampilan terminal",items:U?D:[],children:R}),t.jsx(Ze,{size:"sm",icon:G?"minimize-2":"maximize-2",label:G?"Keluar layar penuh":"Layar penuh","aria-pressed":G,onClick:()=>Z(a=>!a)})]})]}),ze.length>0&&t.jsxs("div",{style:{display:"flex",gap:6,flexWrap:"wrap",alignItems:"center"},children:[t.jsx("span",{style:{fontSize:11,color:"var(--text-subtle)"},children:"Belum di grid:"}),ze.map(a=>t.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:6,padding:"4px 8px",borderRadius:"var(--radius-sm)",background:"var(--bone-200)",border:"1px solid var(--border-hair)",fontFamily:"var(--font-mono)",fontSize:11},children:[t.jsxs("button",{className:"hn-terminal-unplaced-action",disabled:!g,onClick:()=>Ge(a.id),title:"Taruh di sel kosong pertama grup ini",style:{all:"unset",cursor:"pointer"},children:[a.specId??M(a.projectId)," · ",a.id.slice(0,6)]}),t.jsx("button",{type:"button",className:"hn-terminal-action","aria-label":`Tutup sesi ${a.id}`,onClick:()=>void Me(a.id),children:"×"})]},a.id))]}),U&&!p&&t.jsx("div",{className:"hn-stack-mobile",style:{display:"flex",alignItems:"center",gap:8},children:t.jsx(gn,{"aria-label":"Panel terminal",variant:"pill",value:String(le),onChange:a=>ye(Number(a)),tabs:W.cells.map((a,f)=>({value:String(f),label:`Panel ${f+1}${a?` · ${a.slice(0,6)}`:" · kosong"}`}))})}),p?t.jsx(ut,{kind:"empty",icon:"terminal",title:"Belum ada sesi terminal",hint:"Pilih project lalu buka sesi — 'Sesi baru' menjalankan claude --dangerously-skip-permissions di direktori project; 'Terminal biasa' membuka shell tmux polos untuk menjalankan command."}):t.jsxs("div",{style:{flex:1,minHeight:0,display:"grid",gap:8,gridTemplateColumns:U?"minmax(0, 1fr)":`18px repeat(${W.cols}, minmax(0, 1fr))`,gridTemplateRows:U?"minmax(0, 1fr)":`16px repeat(${W.rows}, minmax(0, 1fr))`},children:[!U&&t.jsx("div",{}),!U&&Array.from({length:W.cols},(a,f)=>t.jsx(Nt,{label:`Tutup kolom ${f+1}`,disabled:!g||W.cols===1,onClick:()=>void C(T=>Se(T,A=>Rt(A,f)))},`col-${f}`)),Array.from({length:W.rows},(a,f)=>t.jsxs(o.Fragment,{children:[!U&&t.jsx(Nt,{label:`Tutup baris ${f+1}`,disabled:!g||W.rows===1,onClick:()=>void C(T=>Se(T,A=>Tt(A,f)))}),Array.from({length:W.cols},(T,A)=>{const V=f*W.cols+A,we=W.cells[V]??null,xe=we?Re(we):null;return t.jsx("div",{"data-terminal-cell-index":V,"aria-hidden":U&&le!==V?"true":"false",style:{minHeight:0,minWidth:0,display:U&&le!==V?"none":"flex",flexDirection:"column",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",overflow:"hidden"},children:xe?t.jsx(Gr,{session:xe,nameOf:M,onClose:()=>void Me(xe.id),canArrange:g,onDetach:()=>Ue(xe.id),onExit:Ae=>He(xe.id,Ae),onReview:h,onSessionReview:b,titleOf:I,onIntegrate:v,onIntegrateSession:l,specOf:j,fontSize:q,showKeys:z,predict:J,diag:oe,fullscreen:X===xe.id,onFullscreen:()=>ee(xe.id)}):t.jsx(Yr,{disabled:!g,unplaced:ze,nameOf:M,onPick:Ae=>qe(V,Ae)})},we??`empty-${V}`)})]},`row-${f}`))]}),he&&t.jsx(Or,{seed:Ee,activeIds:Ie,error:ve,onPick:a=>void fe(a),onClose:()=>te(!1)}),Q&&t.jsx(Tr,{open:!0,projectId:N,projectName:M(N),onClose:()=>H(!1),onCreated:Ke}),De&&t.jsx(Ir,{projects:n,onClose:()=>$(!1),onRestart:a=>void je(a)}),de.dialog,X&&Re(X)&&t.jsx(Ur,{session:Re(X),label:Jt(Re(X),M,I),fontSize:q,showKeys:z,predict:J,diag:oe,onClose:()=>ee(null)})]})}function Jt(e,n,r){const i=n(e.projectId),s=e.specId?r==null?void 0:r(e.specId):void 0;return e.specId?`${i} · ${e.specId}${s?` · ${s}`:""}`:e.id.startsWith("xaudit-")?`${i} · audit lintas`:i}function Or({seed:e,activeIds:n,error:r,onPick:i,onClose:s}){const[c,y]=o.useState(""),[h,b]=o.useState("all"),[I,v]=o.useState("all"),[l,j]=o.useState(e),[w,k]=o.useState("");o.useEffect(()=>{const m=setTimeout(()=>k(c.trim()),250);return()=>clearTimeout(m)},[c]),o.useEffect(()=>{var L,F;let m=!0;const E=(F=(L=_).listSpecs)==null?void 0:F.call(L,{startable:!0,q:w||void 0,stage:h==="all"?void 0:h,priority:I==="all"?void 0:I});return E==null||E.then(K=>{m&&j(K.items)}).catch(()=>{}),()=>{m=!1}},[w,h,I]);const S=l.filter(m=>!n.has(m.id));return t.jsxs(Oe,{open:!0,title:"Ambil backlog",icon:"inbox",onClose:s,width:760,children:[r&&t.jsx("div",{style:{marginBottom:10,padding:"8px 10px",borderRadius:"var(--radius-sm)",background:"var(--clay-100)",color:"var(--clay-600)",fontSize:12},children:r}),t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,flexWrap:"wrap",marginBottom:10},children:[t.jsx(ct,{size:"sm",leftIcon:"search",placeholder:"mis. invoice atau SPEC-412","aria-label":"Cari backlog",value:c,onChange:m=>y(m.target.value),style:{flex:"1 1 220px"}}),t.jsx(me,{size:"sm","aria-label":"Filter stage",value:h,onChange:m=>b(m.target.value),options:[{value:"all",label:"Semua stage"}].concat(kn.filter(m=>m.key!=="done").map(m=>({value:m.key,label:m.label})))}),t.jsx(me,{size:"sm","aria-label":"Filter prioritas",value:I,onChange:m=>v(m.target.value),options:[{value:"all",label:"Semua prioritas"},{value:"tinggi",label:"Tinggi"},{value:"sedang",label:"Sedang"},{value:"rendah",label:"Rendah"}]})]}),S.length===0?t.jsx(ut,{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."}):t.jsx("div",{style:{display:"flex",flexDirection:"column",maxHeight:"62vh",overflowY:"auto"},children:S.map(m=>t.jsx("button",{onClick:()=>i(m),style:{cursor:"pointer",display:"block",width:"100%",flex:"0 0 auto",font:"inherit",color:"inherit",textAlign:"left",background:"transparent",padding:"9px 8px",border:"none",borderBottom:"1px solid var(--border-hair)"},children:t.jsxs("span",{className:"hn-dense-row hn-picker-row",style:{display:"flex",alignItems:"center",gap:10,width:"100%"},children:[t.jsx(Ce,{name:m.source==="qa"?"bug":m.source==="audit"?"search":"lightbulb",size:14,color:m.source==="qa"?"var(--clay-500)":m.source==="audit"?"var(--wind-600)":"var(--brass-500)"}),t.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:12,color:"var(--text-subtle)",flex:"0 0 78px"},children:m.id}),t.jsx("span",{className:"hn-picker-title",style:{flex:1,minWidth:0,fontSize:13,color:"var(--text-strong)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:m.title}),t.jsx(at,{tone:m.priority==="tinggi"?"err":"neutral",size:"sm",children:m.priority}),t.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:11,flex:"0 1 auto",minWidth:0,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",color:"var(--text-muted)"},children:m.projectId})]})},m.id))})]})}function Wr({ws:e,compact:n=!1,writable:r,onSelect:i,onAdd:s,onRename:c,onRemove:y}){const[h,b]=o.useState(null),I=_e(e),v=e.groups.length===1;return t.jsxs("div",{role:"tablist","aria-label":"Grup terminal",style:{display:"flex",alignItems:"center",gap:4,flexWrap:"wrap",...n?{}:{borderBottom:"1px solid var(--border-hair)",paddingBottom:4}},children:[e.groups.map((l,j)=>{const w=l.id===I.id;return h===l.id?t.jsx(_r,{initial:l.name,onCommit:k=>{k.trim()&&c(l.id,k.trim()),b(null)},onCancel:()=>b(null)},l.id):t.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:4,padding:"3px 6px",borderRadius:"var(--radius-sm)",fontSize:12,background:w?"var(--bone-200)":"transparent",border:`1px solid ${w?"var(--border-hair)":"transparent"}`},children:[t.jsx("button",{className:"hn-terminal-group-control",role:"tab","aria-selected":w,tabIndex:w?0:-1,onClick:()=>i(l.id),onKeyDown:k=>{var m,E;let S=null;k.key==="ArrowRight"?S=(j+1)%e.groups.length:k.key==="ArrowLeft"?S=(j-1+e.groups.length)%e.groups.length:k.key==="Home"?S=0:k.key==="End"&&(S=e.groups.length-1),S!==null&&(k.preventDefault(),i(e.groups[S].id),(E=(m=k.currentTarget.closest('[role="tablist"]'))==null?void 0:m.querySelectorAll('[role="tab"]')[S])==null||E.focus())},style:{border:0,padding:0,background:"transparent",font:"inherit",cursor:"pointer",color:w?"var(--text-strong)":"var(--text-muted)"},children:l.name}),w&&r&&t.jsxs(t.Fragment,{children:[t.jsx("button",{className:"hn-terminal-group-control","aria-label":`Ganti nama grup ${l.name}`,title:"Ganti nama",onClick:()=>b(l.id),style:{border:0,padding:0,background:"transparent",cursor:"pointer",color:"var(--text-subtle)",fontSize:10},children:"✎"}),t.jsx("button",{className:"hn-terminal-group-control","aria-label":`Hapus grup ${l.name}`,title:v?"Grup terakhir tak bisa dihapus":"Hapus grup (sesi tetap hidup)",disabled:v,onClick:()=>y(l.id),style:{border:0,padding:0,background:"transparent",cursor:v?"not-allowed":"pointer",color:"var(--text-subtle)",opacity:v?.35:1},children:"×"})]})]},l.id)}),t.jsx("button",{className:"hn-terminal-group-control","aria-label":"Grup baru",title:"Grup baru",disabled:!r,onClick:s,style:{border:0,background:"transparent",cursor:"pointer",padding:"3px 8px",color:"var(--text-subtle)",fontSize:12},children:"+"})]})}function Nt({label:e,disabled:n,onClick:r}){return t.jsx("button",{type:"button","aria-label":e,title:n?"Grid tak boleh menyusut ke nol":e,disabled:n,onClick:r,style:{all:"unset",display:"grid",placeItems:"center",fontSize:11,lineHeight:1,color:"var(--text-subtle)",opacity:n?.3:1,cursor:n?"not-allowed":"pointer"},children:"×"})}function _r({initial:e,onCommit:n,onCancel:r}){const[i,s]=o.useState(e);return t.jsx("input",{autoFocus:!0,"aria-label":"Nama grup",value:i,placeholder:"mis. Rilis",onChange:c=>s(c.target.value),onBlur:()=>n(i),onKeyDown:c=>{c.key==="Enter"?n(i):c.key==="Escape"&&r()},style:{width:100,padding:"3px 6px",fontSize:12,fontFamily:"var(--font-ui)",border:"1px solid var(--border-strong)",borderRadius:"var(--radius-sm)",background:"var(--surface-card)",color:"var(--text-strong)"}})}const Kr={done:"var(--brass)",active:"var(--text-strong)",skipped:"var(--text-subtle)",pending:"var(--text-subtle)"},Hr={done:"✓",running:"●",pending:"○",skipped:"–",failed:"✕",abandoned:"⨯"};function qr({phases:e,compact:n=!1,now:r}){const[i,s]=o.useState(null),[,c]=o.useState(0),y=!!(e!=null&&e.some(l=>{var j;return((j=l.agent)==null?void 0:j.status)==="running"}));if(o.useEffect(()=>{if(!y||r!==void 0)return;const l=setInterval(()=>c(j=>j+1),1e3);return()=>clearInterval(l)},[y,r]),!(e!=null&&e.length))return null;const h=r??Date.now(),b=e.find(l=>l.name===i&&l.agent),I=l=>({color:Kr[l.state],fontWeight:l.state==="active"?600:400,textDecoration:l.state==="skipped"?"line-through":"none",opacity:l.state==="pending"?.5:1}),v=l=>{const j=l.agent;return j?typeof j.durationMs=="number"?vt(j.durationMs):j.status==="running"&&j.startedAt?vt(h-Date.parse(j.startedAt)):"":""};return t.jsxs("div",{"data-testid":"phase-strip",style:{flex:"0 0 auto",borderBottom:"1px solid var(--border-hair)"},children:[t.jsx("div",{"data-testid":"phase-strip-scroller",style:{display:"flex",alignItems:"center",gap:8,padding:"3px 8px",fontSize:10,fontFamily:"var(--font-mono)",overflowX:"auto",whiteSpace:"nowrap"},children:e.map(l=>{if(!l.agent)return t.jsx("span",{"data-state":l.state,title:l.state,style:I(l),children:l.name},l.name);const j=l.agent,w=pn(l),k=!n||l.state==="active",S=v(l);return t.jsxs("button",{type:"button","data-tone":w,"aria-expanded":i===l.name,"aria-label":`Detail fase ${l.name}`,onClick:()=>s(i===l.name?null:l.name),style:{display:"inline-flex",alignItems:"center",gap:4,flex:"0 0 auto",padding:"1px 6px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",background:"transparent",font:"inherit",color:"var(--text-body)",cursor:"pointer"},children:[t.jsx("span",{"aria-hidden":!0,children:Hr[w]}),t.jsx("span",{"data-state":l.state,title:l.state,style:I(l),children:l.name}),l.state==="skipped"&&t.jsx("span",{children:"dilewati"}),k&&j.model&&t.jsxs("span",{children:["· ",it(j.model)]}),k&&j.effort&&t.jsxs("span",{children:["· ",j.effort]}),k&&S&&t.jsxs("span",{children:["· ",S]}),j.attempts>1&&t.jsxs("span",{children:["↻",j.attempts]}),j.evidence==="missing"&&t.jsx("span",{role:"img","aria-label":"bukti subagent tak diterima",title:"bukti subagent tak diterima",style:{color:"var(--status-warn)"},children:"⚠"})]},l.name)})}),(b==null?void 0:b.agent)&&t.jsxs("div",{role:"dialog","aria-label":`Detail fase ${b.name}`,style:{position:"absolute",marginLeft:8,zIndex:5,minWidth:220,maxWidth:"min(420px, calc(100% - 16px))",maxHeight:"calc(100% - 48px)",overflowY:"auto",boxSizing:"border-box",padding:"8px 10px",background:"var(--surface-card)",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",whiteSpace:"normal",lineHeight:1.5,fontSize:10,fontFamily:"var(--font-mono)"},children:[t.jsx("div",{children:t.jsx("b",{children:b.agent.name})}),t.jsx("div",{children:[it(b.agent.model),b.agent.effort,b.agent.status??"belum mulai"].filter(Boolean).join(" · ")}),t.jsxs("div",{children:["durasi ",v(b)||"—"," · percobaan ",b.agent.attempts]}),t.jsxs("div",{children:["token in ",b.agent.inputTokens??"—"," · out ",b.agent.outputTokens??"—"," · cache ",b.agent.cachedTokens??"—"]}),b.agent.resultExcerpt&&t.jsx("pre",{style:{margin:"6px 0 0",whiteSpace:"pre-wrap",maxHeight:160,overflow:"auto"},children:b.agent.resultExcerpt})]})]})}function Gr({session:e,nameOf:n,onClose:r,canArrange:i,onDetach:s,onExit:c,onReview:y,onSessionReview:h,titleOf:b,onIntegrate:I,onIntegrateSession:v,specOf:l,fontSize:j,showKeys:w,predict:k,diag:S,fullscreen:m,onFullscreen:E}){const[L,F]=o.useState(null),K=o.useRef(null),[g,C]=o.useState(Number.POSITIVE_INFINITY),d=$t();o.useEffect(()=>{const Q=K.current;if(!Q||typeof ResizeObserver!="function")return;const H=new ResizeObserver(De=>{var de;const $=((de=De[0])==null?void 0:de.contentRect.width)??Q.getBoundingClientRect().width;$>0&&C($)});return H.observe(Q),()=>H.disconnect()},[]);const[u,N]=o.useState(!1),O=o.useCallback((Q,H)=>{F(Q),N(H)},[]),[x,q]=o.useState(!1),[ae,z]=o.useState(!1),[ie,J]=o.useState(!1),se=e.specId?l==null?void 0:l(e.specId):void 0,oe=!e.specId&&!!e.branch,ue=Jt(e,n,b),be=!e.exited&&!!e.decision,G=!e.exited&&!!e.deciding,Z=be||G,X=e.exited&&!!e.exitCode,ee=!e.exited&&u,he=X?null:e.exited||ee?"PST-005":Z?"PST-004":"PST-003",te=[...e.specId?[{key:"docs",label:"Lihat dokumen",icon:"file-text",title:"Lihat dokumen (audit/spec/plan)",onSelect:()=>q(!0),render:t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:()=>q(!0),"aria-label":`Lihat dokumen sesi ${e.id}`,title:"Lihat dokumen (audit/spec/plan)",children:t.jsx(Ce,{name:"file-text",size:12})},"docs")}]:[],...e.specId&&y?[{key:"review",label:"Review perubahan",icon:"git-compare",title:"Review perubahan (diff worktree)",onSelect:()=>y(e.specId),render:t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:()=>y(e.specId),"aria-label":`Review sesi ${e.id}`,title:"Review perubahan (diff worktree)",children:t.jsx(Ce,{name:"git-compare",size:12})},"review")}]:[],...oe&&h?[{key:"review-session",label:"Review perubahan",icon:"git-compare",title:"Review perubahan (diff worktree sesi)",onSelect:()=>h(e.id,ue),render:t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:()=>h(e.id,ue),"aria-label":`Review sesi ${e.id}`,title:"Review perubahan (diff worktree sesi)",children:t.jsx(Ce,{name:"git-compare",size:12})},"review-session")}]:[],...se&&I?[{key:"integrate",label:"Rebase / Merge branch",icon:"git-merge",title:"Rebase / Merge branch spec",onSelect:()=>z(!0),render:t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:()=>z(!0),"aria-label":`Integrasikan sesi ${e.id}`,title:"Rebase / Merge branch spec",children:t.jsx(Ce,{name:"git-merge",size:12})},"integrate")}]:[],...oe&&v?[{key:"integrate-session",label:"Rebase / Merge branch",icon:"git-merge",title:"Rebase / Merge branch sesi",onSelect:()=>J(!0),render:t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:()=>J(!0),"aria-label":`Integrasikan sesi ${e.id}`,title:"Rebase / Merge branch sesi",children:t.jsx(Ce,{name:"git-merge",size:12})},"integrate-session")}]:[],{key:"detach",label:"Lepas dari grid",icon:"unlink",disabled:!i,title:"Lepas dari grid (sesi tetap hidup)",onSelect:s,render:t.jsx("button",{type:"button",className:"hn-terminal-action hn-terminal-action--text",onClick:s,disabled:!i,title:"Lepas dari grid (sesi tetap hidup)",children:"lepas"},"detach")}],ve=Dn(g,te.length,d?44:28),ne=te.slice(ve);return t.jsxs(t.Fragment,{children:[t.jsxs("div",{ref:K,className:"hn-terminal-cell-header",style:{display:"flex",alignItems:"center",gap:8,padding:"4px 8px",flex:"0 0 auto",background:X?"var(--status-err-tint)":e.exited||ee?"var(--status-ok-tint)":Z?"var(--status-warn-tint)":"var(--bone-200)",borderBottom:"1px solid var(--border-hair)",fontFamily:"var(--font-mono)",fontSize:11,color:e.exited?"var(--text-muted)":"var(--text-body)"},children:[he&&t.jsx(vn,{id:he,decorative:!0,style:{width:34,flex:"0 0 auto",borderRadius:"var(--radius-sm)"}}),t.jsxs("span",{style:{flex:1,minWidth:0,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:[ue," · ",e.id.slice(0,6)]}),e.orchestrated&&e.model&&t.jsxs("span",{"data-testid":"orchestrator-chip",title:"Model & effort orchestrator",style:{flex:"0 0 auto",fontSize:10,color:"var(--text-muted)"},children:["orch ",it(e.model),e.effort?` · ${e.effort}`:""]}),e.exited&&(X?t.jsx(Pe,{status:"failed",size:"sm",children:`Gagal · exit ${e.exitCode}`}):t.jsx(Pe,{status:"done",size:"sm",children:"Selesai"})),ee&&t.jsx(Pe,{status:"done",size:"sm",children:"Selesai"}),G&&!ee&&t.jsx(Pe,{status:"running",size:"sm",children:"Lead memutuskan"}),be&&!G&&!ee&&t.jsx(Pe,{status:"awaiting",size:"sm"}),t.jsxs("span",{className:"hn-terminal-actions",children:[te.slice(0,ve).map(Q=>Q.render),ne.length>0&&t.jsx(Mt,{label:`Aksi lain sesi ${e.id}`,items:ne.map(({render:Q,...H})=>H)}),t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:E,title:"Layar penuh — fokus 1 terminal","aria-label":`Layar penuh sesi ${e.id}`,children:t.jsx(Ce,{name:"fullscreen",size:12})}),t.jsx("button",{type:"button",className:"hn-terminal-action","aria-label":`Tutup sesi ${e.id}`,onClick:r,children:"×"})]})]}),t.jsxs("div",{style:{display:"flex",flexDirection:"column",flex:1,minHeight:0,position:"relative",opacity:e.exited?.6:1},children:[t.jsx(qr,{phases:L,compact:g<480}),t.jsx("div",{style:{flex:1,minHeight:0},children:m?t.jsx("div",{style:{height:"100%",display:"grid",placeItems:"center",padding:12,color:"var(--text-subtle)",fontSize:12,textAlign:"center"},children:"Terbuka di layar penuh"}):t.jsx(Ht,{sessionId:e.id,onExit:c,onPhases:O,fontSize:j,showKeys:w,predict:k,diag:S},e.id)})]}),x&&e.specId&&t.jsx(yn,{specId:e.specId,onClose:()=>q(!1)}),ae&&se&&I&&t.jsx(yt,{projectId:se.projectId,ownBranch:`hanoman/${se.id.toLowerCase().replace(/[^a-z0-9_-]/g,"_")}`,eyebrow:se.id,onClose:()=>z(!1),onIntegrate:(Q,H)=>{z(!1),I(se,Q,H)}}),ie&&oe&&v&&t.jsx(yt,{projectId:e.projectId,ownBranch:e.branch,eyebrow:e.id.slice(0,16),onClose:()=>J(!1),onIntegrate:(Q,H)=>{J(!1),v(e,Q,H)}})]})}function Ur({session:e,label:n,fontSize:r,showKeys:i,predict:s,diag:c,onClose:y}){return t.jsx(Oe,{open:!0,icon:"terminal",title:n,onClose:y,closeOnEscape:!1,width:1600,children:t.jsx("div",{style:{height:"min(72vh, calc(100dvh - 180px))",minHeight:0,display:"flex",flexDirection:"column",opacity:e.exited?.6:1},children:t.jsx(Ht,{sessionId:e.id,onExit:()=>{},fontSize:r,showKeys:i,predict:s,diag:c},e.id)})})}function Yr({unplaced:e,nameOf:n,onPick:r,disabled:i}){return t.jsx("div",{style:{flex:1,display:"grid",placeItems:"center",padding:12},children:t.jsx(me,{size:"sm",value:"","aria-label":"Pilih sesi untuk sel",disabled:i||!e.length,onChange:s=>s.target.value&&r(s.target.value),options:[{value:"",label:e.length?"Pilih sesi…":"tidak ada sesi bebas"}].concat(e.map(s=>({value:s.id,label:`${s.specId??n(s.projectId)} · ${s.id.slice(0,6)}`})))})})}export{qr as PhaseStrip,Zr as TerminalScreen};
@@ -1 +1 @@
1
- import{e as y,j as e,a as d,f as T,B as C,h as H,o as V,r as Y,t as X,q as Z,S as F,d as U,m as ee,R as te,v as ae,w as ie,p as A,x as se,I as le,y as ne,u as re,c as W,H as oe,z as O,A as q,C as ce,D as de}from"./index-BHI_f9DD.js";import{R as l}from"./react-DfGhg7ZW.js";import{L as ue}from"./live-CniaVDeP.js";import"./markdown-CWEY34jk.js";function pe(s,c){return s==="rejected"?"Ditutup":s!=="accepted"?"Sedang ditinjau":c==="done"?"Selesai":c==="executing"?"Sedang dikerjakan":"Diterima"}const he=5e3,$=20,me=400;function M({total:s,page:c,onPage:j,unit:p="tiket"}){const n=de(s,c,$);return e.jsx(ie,{page:n.page,pageCount:n.pageCount,total:s,from:n.from,to:n.to,onPage:j,unit:p})}function Q(s,c=Date.now()){const j=Math.max(0,c-new Date(s).getTime()),p=Math.floor(j/6e4);if(p<1)return"baru saja";if(p<60)return`${p}m`;const n=Math.floor(p/60);return n<24?`${n}j`:`${Math.floor(n/24)}h`}const K={new:"warn",accepted:"ok",rejected:"neutral"},J={new:"belum ditinjau",accepted:"diterima",rejected:"ditutup"};function ge({t:s,onOpen:c}){return e.jsxs("button",{onClick:()=>c(s.id),className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:12,width:"100%",textAlign:"left",padding:"12px 14px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-md)",background:"var(--surface-card)",cursor:"pointer",marginBottom:8},children:[e.jsxs("span",{style:{flex:1,minWidth:0},children:[e.jsxs("span",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontWeight:600,color:"var(--text-strong)"},children:["#",s.number]}),e.jsx(C,{tone:"neutral",size:"sm",children:s.category}),e.jsx(C,{tone:K[s.status]??"neutral",size:"sm",children:J[s.status]??s.status})]}),e.jsx("span",{style:{display:"block",color:"var(--text-body)",fontSize:"var(--text-sm)",marginTop:2,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:s.title}),e.jsxs("span",{style:{fontSize:"var(--text-xs)",color:"var(--text-subtle)",marginTop:2,display:"block"},children:[s.projectId," · ",s.reporterEmail," · ",Q(s.createdAt)," lalu",s.attachmentCount>0?` · ${s.attachmentCount} lampiran`:""]})]}),s.specId&&e.jsxs(C,{tone:"ok",icon:"link",children:["→ ",s.specId]}),e.jsx(le,{name:"chevron-right",size:16,color:"var(--text-subtle)"})]})}function xe({id:s,onBack:c,onAccepted:j,onDeleted:p,onToast:n}){var R;const[i,k]=l.useState(null),[h,z]=l.useState("loading"),[m,u]=l.useState(!1),[g,x]=l.useState("sedang"),[P,b]=l.useState(!1),[f,B]=l.useState(!1),{confirm:v,dialog:S}=re(),[r,I]=l.useState({title:"",detail:"",category:"bug",status:"new"}),w=l.useCallback(()=>{y.getTicket(s).then(t=>{k(t),z("ready")}).catch(()=>z("error"))},[s]);if(l.useEffect(()=>{w()},[w]),h==="loading")return e.jsx(T,{kind:"loading"});if(h==="error"||!i)return e.jsx(T,{kind:"error",hint:"Gagal memuat tiket.",action:w,actionLabel:"Coba lagi"});async function L(){u(!0);try{const t=await y.acceptTicket(s,g);j(t.spec,!!t.alreadyPromoted)}catch{n("Gagal menerima tiket","err","x-circle")}finally{u(!1)}}async function E(){if(await v({title:`Tolak & tutup tiket #${i.number}?`,message:`"${i.title}" ditutup tanpa membuat backlog item.`,confirmLabel:"Tolak tiket",icon:"x-circle"})){u(!0);try{await y.rejectTicket(s),k({...i,status:"rejected"}),n("Tiket ditutup","ok","check")}catch{n("Gagal menolak tiket","err","x-circle")}finally{u(!1)}}}async function a(){u(!0);try{const t=await y.unlinkTicket(s);k({...i,specId:t.specId,spec:null,status:t.status}),n("Tautan backlog dilepas","ok","unlink")}catch{n("Gagal melepas tautan","err","x-circle")}finally{u(!1)}}function o(){I({title:i.title,detail:i.detail,category:i.category,status:i.status}),b(!0)}async function D(){u(!0);try{const t=await y.editTicket(s,{title:r.title,detail:r.detail,category:r.category,status:r.status});k(t),b(!1),n("Tiket diperbarui","ok")}catch{n("Gagal menyimpan","err","x-circle")}finally{u(!1)}}async function N(){u(!0);try{await y.deleteTicket(s),n("Tiket dihapus","ok","trash-2"),p()}catch{n("Gagal menghapus","err","x-circle"),u(!1)}}if(P)return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:14},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10},children:[e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"arrow-left",onClick:()=>b(!1),disabled:m,children:"Batal"}),e.jsx("span",{style:{flex:1}}),e.jsx(d,{size:"sm",variant:"primary",leftIcon:"check",onClick:D,disabled:m,children:"Simpan"})]}),e.jsx(W,{label:"Judul",children:e.jsx(U,{value:r.title,placeholder:"mis. Tombol Simpan tak berfungsi di HP",onChange:t=>I({...r,title:t.target.value})})}),e.jsxs("div",{style:{display:"flex",gap:10,flexWrap:"wrap"},children:[e.jsx(W,{label:"Kategori",children:e.jsx(F,{value:r.category,onChange:t=>I({...r,category:t.target.value}),options:[{value:"bug",label:"bug"},{value:"fitur",label:"fitur"},{value:"pertanyaan",label:"pertanyaan"},{value:"lainnya",label:"lainnya"}]})}),e.jsx(W,{label:"Status",children:e.jsx(F,{value:r.status,onChange:t=>I({...r,status:t.target.value}),options:[{value:"new",label:"belum ditinjau"},{value:"accepted",label:"diterima"},{value:"rejected",label:"ditutup"}]})})]}),e.jsx(W,{label:"Detail keluhan",children:e.jsx(oe,{value:r.detail,rows:6,placeholder:"mis. Buka halaman Pesanan di HP, tekan Simpan — layar diam dan datanya tak tersimpan.",onChange:t=>I({...r,detail:t.target.value})})})]});const _=i.status!=="new";return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:14},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,flexWrap:"wrap"},children:[e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"arrow-left",onClick:c,children:"Kembali"}),e.jsx(C,{tone:K[i.status]??"neutral",children:J[i.status]??i.status}),e.jsx("span",{style:{flex:1}}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"pencil",onClick:o,disabled:m,children:"Ubah"}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"trash-2",onClick:()=>B(!0),disabled:m,children:"Hapus"}),i.publicStatusUrl&&e.jsxs(e.Fragment,{children:[e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"share-2",onClick:()=>window.open(i.publicStatusUrl,"_blank","noreferrer"),children:"Buka status publik"}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"link-2",onClick:()=>{var t;(t=navigator.clipboard)==null||t.writeText(i.publicStatusUrl),n("Link publik disalin","ok","copy")},children:"Salin link publik"})]}),i.specId?e.jsxs(e.Fragment,{children:[e.jsxs(C,{tone:"ok",icon:"link",children:["→ ",i.specId]}),e.jsx(C,{tone:"neutral",size:"sm",children:pe(i.status,(R=i.spec)==null?void 0:R.stage)}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"external-link",onClick:()=>window.open(O(i.specId),"_blank","noreferrer"),children:"Buka backlog"}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"copy",onClick:()=>{var t;(t=navigator.clipboard)==null||t.writeText(O(i.specId)),n("Link backlog disalin","ok","copy")},children:"Salin link"}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"unlink",onClick:a,disabled:m,children:"Lepas tautan"})]}):!_&&e.jsxs(e.Fragment,{children:[e.jsx(F,{size:"sm",value:g,onChange:t=>x(t.target.value),options:[{value:"tinggi",label:"Prioritas tinggi"},{value:"sedang",label:"Prioritas sedang"},{value:"rendah",label:"Prioritas rendah"}]}),e.jsx(d,{size:"sm",leftIcon:"arrow-up-right",onClick:L,disabled:m,children:"Terima → backlog"}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"ban",onClick:E,disabled:m,children:"Tolak"})]})]}),e.jsxs("div",{children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontWeight:600,color:"var(--text-strong)"},children:["#",i.number]}),e.jsx(C,{tone:"neutral",size:"sm",children:i.category})]}),e.jsx("div",{style:{fontWeight:600,fontSize:"var(--text-lg)",color:"var(--text-strong)",marginTop:4},children:i.title})]}),e.jsxs("div",{style:{display:"flex",gap:18,flexWrap:"wrap",fontSize:"var(--text-sm)",color:"var(--text-muted)"},children:[e.jsxs("span",{children:["pelapor: ",e.jsx("b",{style:{color:"var(--text-body)"},children:i.reporterEmail})]}),e.jsxs("span",{children:["project: ",e.jsx("b",{style:{color:"var(--text-body)"},children:i.projectId})]}),e.jsxs("span",{children:["masuk: ",Q(i.createdAt)," lalu"]})]}),e.jsxs("div",{children:[e.jsx("div",{className:"hn-eyebrow",style:{marginBottom:6},children:"Detail keluhan"}),e.jsx("div",{style:{whiteSpace:"pre-wrap",color:"var(--text-body)",fontSize:"var(--text-sm)",lineHeight:1.55},children:i.detail})]}),i.attachments.length>0&&e.jsxs("div",{children:[e.jsx("div",{className:"hn-eyebrow",style:{marginBottom:6},children:"Lampiran"}),e.jsx("div",{style:{display:"flex",gap:10,flexWrap:"wrap"},children:i.attachments.map(t=>e.jsx("a",{href:q.ticketAttachment(i.id,t.id),target:"_blank",rel:"noreferrer",style:{display:"block",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",overflow:"hidden"},children:e.jsx("img",{src:q.ticketAttachment(i.id,t.id),alt:t.filename,style:{display:"block",maxWidth:180,maxHeight:140,objectFit:"cover"}})},t.id))})]}),e.jsx(ce,{open:f,title:"Hapus tiket?",eyebrow:`#${i.number}`,message:`Tiket "${i.title}" dan seluruh lampirannya akan dihapus permanen. Tindakan ini tak bisa dibatalkan.`,busy:m,onCancel:()=>B(!1),onConfirm:N}),S]})}function fe({projectId:s,onAccepted:c}){const[j,p]=l.useState([]),[n,i]=l.useState("loading"),[k,h]=l.useState(!1),[z,m]=l.useState(null),[u,g]=l.useState(null),[x,P]=l.useState([]),[b,f]=l.useState(0),[B,v]=l.useState(1),S=l.useCallback(async()=>{try{const a=await y.listGithubIssues(s,{page:B,limit:$});p(a.items),f(a.total),i("ready")}catch{i("error")}},[s,B]);l.useEffect(()=>{S()},[S]);const r=a=>{var D;const o=(D=a.detail)==null?void 0:D.error;return typeof o=="string"?o:a.message};async function I(){h(!0),g(null),m(null);try{const a=await y.pullGithubIssues(s);m(`${a.repo}: ${a.created} baru, ${a.updated} diperbarui`+(a.skippedPullRequests?` · ${a.skippedPullRequests} pull request dilewati`:"")),await S()}catch(a){g(r(a))}finally{h(!1)}}async function w(){h(!0),g(null);try{const a=await y.acceptGithubIssues(x,void 0);P([]),c==null||c(a.created),await S()}catch(a){g(r(a))}finally{h(!1)}}async function L(a){h(!0),g(null);try{await y.rejectGithubIssue(a),await S()}catch(o){g(r(o))}finally{h(!1)}}const E=a=>P(o=>o.includes(a)?o.filter(D=>D!==a):[...o,a]);return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:12,minHeight:0,flex:1},children:[e.jsxs("div",{style:{display:"flex",gap:8,alignItems:"center",flexWrap:"wrap"},children:[e.jsx(d,{size:"sm",onClick:I,disabled:k,children:"Tarik issue"}),e.jsxs(d,{size:"sm",variant:"primary",onClick:w,disabled:k||x.length===0,children:["Terima terpilih",x.length?` (${x.length})`:""]}),z&&e.jsx("span",{style:{fontSize:12,color:"var(--text-muted)"},children:z})]}),u&&e.jsx("div",{role:"alert",style:{fontSize:12,color:"var(--danger, #b00)"},children:u}),n==="loading"?e.jsx(T,{kind:"loading"}):n==="error"?e.jsx(T,{kind:"error",hint:"Gagal memuat daftar issue.",action:()=>void S(),actionLabel:"Coba lagi"}):j.length===0?e.jsx(T,{kind:"empty",icon:"inbox",title:"Belum ada issue tertarik",hint:"Tekan “Tarik issue” untuk menariknya dari repo GitHub project ini."}):e.jsxs(e.Fragment,{children:[e.jsx("div",{style:{overflowY:"auto",minHeight:0},children:j.map(a=>e.jsxs("div",{className:"hn-dense-row",style:{display:"flex",gap:8,alignItems:"baseline",padding:"8px 0",borderBottom:"1px solid var(--border-hair)"},children:[a.status==="new"&&e.jsx("input",{type:"checkbox","aria-label":`Pilih issue ${a.number}`,checked:x.includes(a.id),onChange:()=>E(a.id)}),e.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontSize:12,color:"var(--text-muted)"},children:["#",a.number]}),e.jsx("a",{href:a.url,target:"_blank",rel:"noreferrer",style:{flex:1,minWidth:0},children:a.title}),e.jsxs("span",{style:{fontSize:12,color:"var(--text-muted)"},children:["@",a.authorLogin]}),a.labels.map(o=>e.jsx(C,{children:o},o)),a.status==="rejected"&&e.jsx(C,{tone:"neutral",children:"ditutup"}),a.specId&&e.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:12},children:a.specId}),a.status==="new"&&e.jsx(d,{size:"sm",variant:"ghost",onClick:()=>L(a.id),disabled:k,children:"Tolak"})]},a.id))}),e.jsx(M,{total:b,page:B,onPage:v,unit:"issue"})]})]})}function ve({projects:s,onAccepted:c,onToast:j}){const[p,n]=l.useState([]),[i,k]=l.useState(0),[h,z]=H("triage","page",1,se),[m,u]=l.useState(0),[g,x]=l.useState("loading"),[P,b]=H("triage","openId",null,ne),[f,B]=H("triage","project","",A),[v,S]=H("triage","status","",A),[r,I]=H("triage","q","",A),[w,L]=H("triage","tab","tiket",V("tiket","issue")),E=[f!=="",v!=="",r.trim()!==""].filter(Boolean).length,a=Y("triage","scroll",p.length>0),o=l.useCallback((t=!1)=>{t||x("loading"),y.listTickets({project:f||void 0,status:v||void 0,q:r||void 0,page:String(h),limit:String($)}).then(G=>{n(G.items),k(G.total),u(G.unreviewed),x("ready")}).catch(()=>{t||x("error")})},[f,v,r,h]);l.useEffect(()=>{o()},[o]),X(JSON.stringify([f,v,r]),()=>z(1));const[D,N]=l.useState(r);l.useEffect(()=>{const t=setTimeout(()=>N(r),me);return()=>clearTimeout(t)},[r]),Z({topic:"tickets",params:{project:f||void 0,status:v||void 0,q:D||void 0,page:h,limit:$},apply:t=>{n(t.data.items),k(t.data.total),u(t.data.unreviewed),x("ready")},refetch:()=>o(!0),pollMs:he});const _=e.jsx("div",{style:{display:"flex",flexDirection:"column",gap:12,minHeight:0,flex:1},children:f?e.jsx(fe,{projectId:f,onAccepted:t=>t.forEach(G=>c(G,!1))}):e.jsx(T,{kind:"empty",icon:"inbox",title:"Pilih satu project",hint:"Issue GitHub milik satu repo, jadi pilih project-nya lebih dulu di penyaring di atas."})}),R=e.jsx("div",{style:{display:"flex",flexDirection:"column",flex:1,minHeight:0},children:g==="loading"?e.jsx(T,{kind:"loading"}):g==="error"?e.jsx(T,{kind:"error",hint:"Gagal memuat tiket.",action:()=>o(),actionLabel:"Coba lagi"}):p.length===0?e.jsx(T,{kind:"empty",icon:"inbox",title:"Belum ada keluhan",hint:"Aktifkan Help Center di detail project, lalu sebar link publiknya agar keluhan mulai masuk."}):e.jsxs(e.Fragment,{children:[e.jsx("div",{ref:a,"data-testid":"triage-scroll",style:{overflowY:"auto",minHeight:0,flex:"1 1 auto"},children:p.map(t=>e.jsx(ge,{t,onOpen:b},t.id))}),e.jsx(M,{total:i,page:h,onPage:z})]})});return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:14,minHeight:0,flex:1},children:[e.jsxs("div",{className:"hn-wrap-mobile",style:{display:"flex",gap:8,alignItems:"center"},children:[e.jsx(d,{size:"sm",variant:w==="tiket"?"primary":"ghost",onClick:()=>L("tiket"),children:"Tiket Help Center"}),e.jsx(d,{size:"sm",variant:w==="issue"?"primary":"ghost",onClick:()=>L("issue"),children:"Issue GitHub"})]}),e.jsxs("div",{style:{display:"flex",gap:10,flexWrap:"wrap",alignItems:"center"},children:[e.jsx(F,{size:"sm",value:f,"aria-label":"Project triase",onChange:t=>B(t.target.value),options:[{value:"",label:"Semua project"},...s.map(t=>({value:t.id,label:t.name}))]}),w==="tiket"&&e.jsxs(e.Fragment,{children:[e.jsx(F,{size:"sm",value:v,"aria-label":"Status tiket",onChange:t=>S(t.target.value),options:[{value:"",label:"Semua status"},{value:"new",label:"belum ditinjau"},{value:"accepted",label:"diterima"},{value:"rejected",label:"ditutup"}]}),e.jsx(U,{size:"sm",value:r,"aria-label":"Cari tiket",onChange:t=>I(t.target.value),placeholder:"mis. gagal login atau budi@contoh.id",style:{flex:1,minWidth:160}}),m>0&&e.jsxs(C,{tone:"warn",children:[m," belum ditinjau"]}),e.jsx(ee,{onDone:()=>o(!0),onToast:j}),e.jsx(te,{screen:"triage",active:E}),e.jsx(ue,{})]})]}),w==="issue"?_:e.jsx(ae,{ariaLabel:"Panel triase",active:P?"detail":"list",onActiveChange:t=>{t==="list"&&b(null)},splitAt:"tablet",masterWidth:360,panels:[{id:"list",label:"Daftar",content:R,className:"hn-panel-flex"},...P?[{id:"detail",label:"Detail",className:"hn-panel-flex",content:e.jsx(xe,{id:P,onBack:()=>{b(null),o(!0)},onAccepted:c,onDeleted:()=>{b(null),o(!0)},onToast:j})}]:[]]})]})}export{fe as GithubIssuesPanel,ve as TriageScreen};
1
+ import{e as y,j as e,a as d,f as T,B as C,h as H,o as V,r as Y,t as X,q as Z,S as F,d as U,m as ee,R as te,v as ae,w as ie,p as A,x as se,I as le,y as ne,u as re,c as W,H as oe,z as O,A as q,C as ce,D as de}from"./index-Bd9gXx1g.js";import{R as l}from"./react-DfGhg7ZW.js";import{L as ue}from"./live-BlNZnTbo.js";import"./markdown-CWEY34jk.js";function pe(s,c){return s==="rejected"?"Ditutup":s!=="accepted"?"Sedang ditinjau":c==="done"?"Selesai":c==="executing"?"Sedang dikerjakan":"Diterima"}const he=5e3,$=20,me=400;function M({total:s,page:c,onPage:j,unit:p="tiket"}){const n=de(s,c,$);return e.jsx(ie,{page:n.page,pageCount:n.pageCount,total:s,from:n.from,to:n.to,onPage:j,unit:p})}function Q(s,c=Date.now()){const j=Math.max(0,c-new Date(s).getTime()),p=Math.floor(j/6e4);if(p<1)return"baru saja";if(p<60)return`${p}m`;const n=Math.floor(p/60);return n<24?`${n}j`:`${Math.floor(n/24)}h`}const K={new:"warn",accepted:"ok",rejected:"neutral"},J={new:"belum ditinjau",accepted:"diterima",rejected:"ditutup"};function ge({t:s,onOpen:c}){return e.jsxs("button",{onClick:()=>c(s.id),className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:12,width:"100%",textAlign:"left",padding:"12px 14px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-md)",background:"var(--surface-card)",cursor:"pointer",marginBottom:8},children:[e.jsxs("span",{style:{flex:1,minWidth:0},children:[e.jsxs("span",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontWeight:600,color:"var(--text-strong)"},children:["#",s.number]}),e.jsx(C,{tone:"neutral",size:"sm",children:s.category}),e.jsx(C,{tone:K[s.status]??"neutral",size:"sm",children:J[s.status]??s.status})]}),e.jsx("span",{style:{display:"block",color:"var(--text-body)",fontSize:"var(--text-sm)",marginTop:2,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:s.title}),e.jsxs("span",{style:{fontSize:"var(--text-xs)",color:"var(--text-subtle)",marginTop:2,display:"block"},children:[s.projectId," · ",s.reporterEmail," · ",Q(s.createdAt)," lalu",s.attachmentCount>0?` · ${s.attachmentCount} lampiran`:""]})]}),s.specId&&e.jsxs(C,{tone:"ok",icon:"link",children:["→ ",s.specId]}),e.jsx(le,{name:"chevron-right",size:16,color:"var(--text-subtle)"})]})}function xe({id:s,onBack:c,onAccepted:j,onDeleted:p,onToast:n}){var R;const[i,k]=l.useState(null),[h,z]=l.useState("loading"),[m,u]=l.useState(!1),[g,x]=l.useState("sedang"),[P,b]=l.useState(!1),[f,B]=l.useState(!1),{confirm:v,dialog:S}=re(),[r,I]=l.useState({title:"",detail:"",category:"bug",status:"new"}),w=l.useCallback(()=>{y.getTicket(s).then(t=>{k(t),z("ready")}).catch(()=>z("error"))},[s]);if(l.useEffect(()=>{w()},[w]),h==="loading")return e.jsx(T,{kind:"loading"});if(h==="error"||!i)return e.jsx(T,{kind:"error",hint:"Gagal memuat tiket.",action:w,actionLabel:"Coba lagi"});async function L(){u(!0);try{const t=await y.acceptTicket(s,g);j(t.spec,!!t.alreadyPromoted)}catch{n("Gagal menerima tiket","err","x-circle")}finally{u(!1)}}async function E(){if(await v({title:`Tolak & tutup tiket #${i.number}?`,message:`"${i.title}" ditutup tanpa membuat backlog item.`,confirmLabel:"Tolak tiket",icon:"x-circle"})){u(!0);try{await y.rejectTicket(s),k({...i,status:"rejected"}),n("Tiket ditutup","ok","check")}catch{n("Gagal menolak tiket","err","x-circle")}finally{u(!1)}}}async function a(){u(!0);try{const t=await y.unlinkTicket(s);k({...i,specId:t.specId,spec:null,status:t.status}),n("Tautan backlog dilepas","ok","unlink")}catch{n("Gagal melepas tautan","err","x-circle")}finally{u(!1)}}function o(){I({title:i.title,detail:i.detail,category:i.category,status:i.status}),b(!0)}async function D(){u(!0);try{const t=await y.editTicket(s,{title:r.title,detail:r.detail,category:r.category,status:r.status});k(t),b(!1),n("Tiket diperbarui","ok")}catch{n("Gagal menyimpan","err","x-circle")}finally{u(!1)}}async function N(){u(!0);try{await y.deleteTicket(s),n("Tiket dihapus","ok","trash-2"),p()}catch{n("Gagal menghapus","err","x-circle"),u(!1)}}if(P)return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:14},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10},children:[e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"arrow-left",onClick:()=>b(!1),disabled:m,children:"Batal"}),e.jsx("span",{style:{flex:1}}),e.jsx(d,{size:"sm",variant:"primary",leftIcon:"check",onClick:D,disabled:m,children:"Simpan"})]}),e.jsx(W,{label:"Judul",children:e.jsx(U,{value:r.title,placeholder:"mis. Tombol Simpan tak berfungsi di HP",onChange:t=>I({...r,title:t.target.value})})}),e.jsxs("div",{style:{display:"flex",gap:10,flexWrap:"wrap"},children:[e.jsx(W,{label:"Kategori",children:e.jsx(F,{value:r.category,onChange:t=>I({...r,category:t.target.value}),options:[{value:"bug",label:"bug"},{value:"fitur",label:"fitur"},{value:"pertanyaan",label:"pertanyaan"},{value:"lainnya",label:"lainnya"}]})}),e.jsx(W,{label:"Status",children:e.jsx(F,{value:r.status,onChange:t=>I({...r,status:t.target.value}),options:[{value:"new",label:"belum ditinjau"},{value:"accepted",label:"diterima"},{value:"rejected",label:"ditutup"}]})})]}),e.jsx(W,{label:"Detail keluhan",children:e.jsx(oe,{value:r.detail,rows:6,placeholder:"mis. Buka halaman Pesanan di HP, tekan Simpan — layar diam dan datanya tak tersimpan.",onChange:t=>I({...r,detail:t.target.value})})})]});const _=i.status!=="new";return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:14},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,flexWrap:"wrap"},children:[e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"arrow-left",onClick:c,children:"Kembali"}),e.jsx(C,{tone:K[i.status]??"neutral",children:J[i.status]??i.status}),e.jsx("span",{style:{flex:1}}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"pencil",onClick:o,disabled:m,children:"Ubah"}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"trash-2",onClick:()=>B(!0),disabled:m,children:"Hapus"}),i.publicStatusUrl&&e.jsxs(e.Fragment,{children:[e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"share-2",onClick:()=>window.open(i.publicStatusUrl,"_blank","noreferrer"),children:"Buka status publik"}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"link-2",onClick:()=>{var t;(t=navigator.clipboard)==null||t.writeText(i.publicStatusUrl),n("Link publik disalin","ok","copy")},children:"Salin link publik"})]}),i.specId?e.jsxs(e.Fragment,{children:[e.jsxs(C,{tone:"ok",icon:"link",children:["→ ",i.specId]}),e.jsx(C,{tone:"neutral",size:"sm",children:pe(i.status,(R=i.spec)==null?void 0:R.stage)}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"external-link",onClick:()=>window.open(O(i.specId),"_blank","noreferrer"),children:"Buka backlog"}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"copy",onClick:()=>{var t;(t=navigator.clipboard)==null||t.writeText(O(i.specId)),n("Link backlog disalin","ok","copy")},children:"Salin link"}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"unlink",onClick:a,disabled:m,children:"Lepas tautan"})]}):!_&&e.jsxs(e.Fragment,{children:[e.jsx(F,{size:"sm",value:g,onChange:t=>x(t.target.value),options:[{value:"tinggi",label:"Prioritas tinggi"},{value:"sedang",label:"Prioritas sedang"},{value:"rendah",label:"Prioritas rendah"}]}),e.jsx(d,{size:"sm",leftIcon:"arrow-up-right",onClick:L,disabled:m,children:"Terima → backlog"}),e.jsx(d,{size:"sm",variant:"ghost",leftIcon:"ban",onClick:E,disabled:m,children:"Tolak"})]})]}),e.jsxs("div",{children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontWeight:600,color:"var(--text-strong)"},children:["#",i.number]}),e.jsx(C,{tone:"neutral",size:"sm",children:i.category})]}),e.jsx("div",{style:{fontWeight:600,fontSize:"var(--text-lg)",color:"var(--text-strong)",marginTop:4},children:i.title})]}),e.jsxs("div",{style:{display:"flex",gap:18,flexWrap:"wrap",fontSize:"var(--text-sm)",color:"var(--text-muted)"},children:[e.jsxs("span",{children:["pelapor: ",e.jsx("b",{style:{color:"var(--text-body)"},children:i.reporterEmail})]}),e.jsxs("span",{children:["project: ",e.jsx("b",{style:{color:"var(--text-body)"},children:i.projectId})]}),e.jsxs("span",{children:["masuk: ",Q(i.createdAt)," lalu"]})]}),e.jsxs("div",{children:[e.jsx("div",{className:"hn-eyebrow",style:{marginBottom:6},children:"Detail keluhan"}),e.jsx("div",{style:{whiteSpace:"pre-wrap",color:"var(--text-body)",fontSize:"var(--text-sm)",lineHeight:1.55},children:i.detail})]}),i.attachments.length>0&&e.jsxs("div",{children:[e.jsx("div",{className:"hn-eyebrow",style:{marginBottom:6},children:"Lampiran"}),e.jsx("div",{style:{display:"flex",gap:10,flexWrap:"wrap"},children:i.attachments.map(t=>e.jsx("a",{href:q.ticketAttachment(i.id,t.id),target:"_blank",rel:"noreferrer",style:{display:"block",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",overflow:"hidden"},children:e.jsx("img",{src:q.ticketAttachment(i.id,t.id),alt:t.filename,style:{display:"block",maxWidth:180,maxHeight:140,objectFit:"cover"}})},t.id))})]}),e.jsx(ce,{open:f,title:"Hapus tiket?",eyebrow:`#${i.number}`,message:`Tiket "${i.title}" dan seluruh lampirannya akan dihapus permanen. Tindakan ini tak bisa dibatalkan.`,busy:m,onCancel:()=>B(!1),onConfirm:N}),S]})}function fe({projectId:s,onAccepted:c}){const[j,p]=l.useState([]),[n,i]=l.useState("loading"),[k,h]=l.useState(!1),[z,m]=l.useState(null),[u,g]=l.useState(null),[x,P]=l.useState([]),[b,f]=l.useState(0),[B,v]=l.useState(1),S=l.useCallback(async()=>{try{const a=await y.listGithubIssues(s,{page:B,limit:$});p(a.items),f(a.total),i("ready")}catch{i("error")}},[s,B]);l.useEffect(()=>{S()},[S]);const r=a=>{var D;const o=(D=a.detail)==null?void 0:D.error;return typeof o=="string"?o:a.message};async function I(){h(!0),g(null),m(null);try{const a=await y.pullGithubIssues(s);m(`${a.repo}: ${a.created} baru, ${a.updated} diperbarui`+(a.skippedPullRequests?` · ${a.skippedPullRequests} pull request dilewati`:"")),await S()}catch(a){g(r(a))}finally{h(!1)}}async function w(){h(!0),g(null);try{const a=await y.acceptGithubIssues(x,void 0);P([]),c==null||c(a.created),await S()}catch(a){g(r(a))}finally{h(!1)}}async function L(a){h(!0),g(null);try{await y.rejectGithubIssue(a),await S()}catch(o){g(r(o))}finally{h(!1)}}const E=a=>P(o=>o.includes(a)?o.filter(D=>D!==a):[...o,a]);return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:12,minHeight:0,flex:1},children:[e.jsxs("div",{style:{display:"flex",gap:8,alignItems:"center",flexWrap:"wrap"},children:[e.jsx(d,{size:"sm",onClick:I,disabled:k,children:"Tarik issue"}),e.jsxs(d,{size:"sm",variant:"primary",onClick:w,disabled:k||x.length===0,children:["Terima terpilih",x.length?` (${x.length})`:""]}),z&&e.jsx("span",{style:{fontSize:12,color:"var(--text-muted)"},children:z})]}),u&&e.jsx("div",{role:"alert",style:{fontSize:12,color:"var(--danger, #b00)"},children:u}),n==="loading"?e.jsx(T,{kind:"loading"}):n==="error"?e.jsx(T,{kind:"error",hint:"Gagal memuat daftar issue.",action:()=>void S(),actionLabel:"Coba lagi"}):j.length===0?e.jsx(T,{kind:"empty",icon:"inbox",title:"Belum ada issue tertarik",hint:"Tekan “Tarik issue” untuk menariknya dari repo GitHub project ini."}):e.jsxs(e.Fragment,{children:[e.jsx("div",{style:{overflowY:"auto",minHeight:0},children:j.map(a=>e.jsxs("div",{className:"hn-dense-row",style:{display:"flex",gap:8,alignItems:"baseline",padding:"8px 0",borderBottom:"1px solid var(--border-hair)"},children:[a.status==="new"&&e.jsx("input",{type:"checkbox","aria-label":`Pilih issue ${a.number}`,checked:x.includes(a.id),onChange:()=>E(a.id)}),e.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontSize:12,color:"var(--text-muted)"},children:["#",a.number]}),e.jsx("a",{href:a.url,target:"_blank",rel:"noreferrer",style:{flex:1,minWidth:0},children:a.title}),e.jsxs("span",{style:{fontSize:12,color:"var(--text-muted)"},children:["@",a.authorLogin]}),a.labels.map(o=>e.jsx(C,{children:o},o)),a.status==="rejected"&&e.jsx(C,{tone:"neutral",children:"ditutup"}),a.specId&&e.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:12},children:a.specId}),a.status==="new"&&e.jsx(d,{size:"sm",variant:"ghost",onClick:()=>L(a.id),disabled:k,children:"Tolak"})]},a.id))}),e.jsx(M,{total:b,page:B,onPage:v,unit:"issue"})]})]})}function ve({projects:s,onAccepted:c,onToast:j}){const[p,n]=l.useState([]),[i,k]=l.useState(0),[h,z]=H("triage","page",1,se),[m,u]=l.useState(0),[g,x]=l.useState("loading"),[P,b]=H("triage","openId",null,ne),[f,B]=H("triage","project","",A),[v,S]=H("triage","status","",A),[r,I]=H("triage","q","",A),[w,L]=H("triage","tab","tiket",V("tiket","issue")),E=[f!=="",v!=="",r.trim()!==""].filter(Boolean).length,a=Y("triage","scroll",p.length>0),o=l.useCallback((t=!1)=>{t||x("loading"),y.listTickets({project:f||void 0,status:v||void 0,q:r||void 0,page:String(h),limit:String($)}).then(G=>{n(G.items),k(G.total),u(G.unreviewed),x("ready")}).catch(()=>{t||x("error")})},[f,v,r,h]);l.useEffect(()=>{o()},[o]),X(JSON.stringify([f,v,r]),()=>z(1));const[D,N]=l.useState(r);l.useEffect(()=>{const t=setTimeout(()=>N(r),me);return()=>clearTimeout(t)},[r]),Z({topic:"tickets",params:{project:f||void 0,status:v||void 0,q:D||void 0,page:h,limit:$},apply:t=>{n(t.data.items),k(t.data.total),u(t.data.unreviewed),x("ready")},refetch:()=>o(!0),pollMs:he});const _=e.jsx("div",{style:{display:"flex",flexDirection:"column",gap:12,minHeight:0,flex:1},children:f?e.jsx(fe,{projectId:f,onAccepted:t=>t.forEach(G=>c(G,!1))}):e.jsx(T,{kind:"empty",icon:"inbox",title:"Pilih satu project",hint:"Issue GitHub milik satu repo, jadi pilih project-nya lebih dulu di penyaring di atas."})}),R=e.jsx("div",{style:{display:"flex",flexDirection:"column",flex:1,minHeight:0},children:g==="loading"?e.jsx(T,{kind:"loading"}):g==="error"?e.jsx(T,{kind:"error",hint:"Gagal memuat tiket.",action:()=>o(),actionLabel:"Coba lagi"}):p.length===0?e.jsx(T,{kind:"empty",icon:"inbox",title:"Belum ada keluhan",hint:"Aktifkan Help Center di detail project, lalu sebar link publiknya agar keluhan mulai masuk."}):e.jsxs(e.Fragment,{children:[e.jsx("div",{ref:a,"data-testid":"triage-scroll",style:{overflowY:"auto",minHeight:0,flex:"1 1 auto"},children:p.map(t=>e.jsx(ge,{t,onOpen:b},t.id))}),e.jsx(M,{total:i,page:h,onPage:z})]})});return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:14,minHeight:0,flex:1},children:[e.jsxs("div",{className:"hn-wrap-mobile",style:{display:"flex",gap:8,alignItems:"center"},children:[e.jsx(d,{size:"sm",variant:w==="tiket"?"primary":"ghost",onClick:()=>L("tiket"),children:"Tiket Help Center"}),e.jsx(d,{size:"sm",variant:w==="issue"?"primary":"ghost",onClick:()=>L("issue"),children:"Issue GitHub"})]}),e.jsxs("div",{style:{display:"flex",gap:10,flexWrap:"wrap",alignItems:"center"},children:[e.jsx(F,{size:"sm",value:f,"aria-label":"Project triase",onChange:t=>B(t.target.value),options:[{value:"",label:"Semua project"},...s.map(t=>({value:t.id,label:t.name}))]}),w==="tiket"&&e.jsxs(e.Fragment,{children:[e.jsx(F,{size:"sm",value:v,"aria-label":"Status tiket",onChange:t=>S(t.target.value),options:[{value:"",label:"Semua status"},{value:"new",label:"belum ditinjau"},{value:"accepted",label:"diterima"},{value:"rejected",label:"ditutup"}]}),e.jsx(U,{size:"sm",value:r,"aria-label":"Cari tiket",onChange:t=>I(t.target.value),placeholder:"mis. gagal login atau budi@contoh.id",style:{flex:1,minWidth:160}}),m>0&&e.jsxs(C,{tone:"warn",children:[m," belum ditinjau"]}),e.jsx(ee,{onDone:()=>o(!0),onToast:j}),e.jsx(te,{screen:"triage",active:E}),e.jsx(ue,{})]})]}),w==="issue"?_:e.jsx(ae,{ariaLabel:"Panel triase",active:P?"detail":"list",onActiveChange:t=>{t==="list"&&b(null)},splitAt:"tablet",masterWidth:360,panels:[{id:"list",label:"Daftar",content:R,className:"hn-panel-flex"},...P?[{id:"detail",label:"Detail",className:"hn-panel-flex",content:e.jsx(xe,{id:P,onBack:()=>{b(null),o(!0)},onAccepted:c,onDeleted:()=>{b(null),o(!0)},onToast:j})}]:[]]})]})}export{fe as GithubIssuesPanel,ve as TriageScreen};
@@ -1,2 +1,2 @@
1
- import{e as v,u as te,j as e,M as oe,f as U,I as W,a as f,h as de,o as fe,ap as be,ai as ke,c as O,d as T,a7 as ye,ac as se,y as ve}from"./index-BHI_f9DD.js";import{R as p}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";const je={pass:"check",fail:"x",warn:"alert-triangle",na:"minus",unknown:"circle"},we={pass:"var(--leaf-600)",fail:"var(--clay-600)",warn:"var(--amber-600)",na:"var(--text-subtle)",unknown:"var(--text-subtle)"},Se={AUTO:"var(--brass-700)",AUDIT:"var(--amber-600)",INFO:"var(--text-subtle)"},Ce={critical:"var(--clay-600)",high:"var(--amber-600)",medium:"var(--text-subtle)",low:"var(--text-subtle)"};function K({text:a,color:s}){return e.jsx("span",{style:{fontSize:10,textTransform:"uppercase",letterSpacing:"0.04em",color:s,border:`1px solid ${s}`,borderRadius:3,padding:"0 4px",whiteSpace:"nowrap"},children:a})}function ce({score:a}){const s=a>=90?"var(--leaf-600)":a>=50?"var(--amber-600)":"var(--clay-600)";return e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6,minWidth:90},children:[e.jsx("div",{style:{flex:1,height:6,background:"var(--bone-200)",borderRadius:3,overflow:"hidden"},children:e.jsx("div",{style:{width:`${a}%`,height:"100%",background:s}})}),e.jsxs("span",{style:{fontSize:11,fontFamily:"var(--font-mono)",color:"var(--text-subtle)",minWidth:28,textAlign:"right"},children:[a,"%"]})]})}function Pe({item:a,busy:s,selected:l,onToggle:o,onNa:u,onAttest:c}){const n=a.mode==="AUTO"&&!a.na;return e.jsxs("div",{"data-testid":`item-${a.id}`,style:{display:"flex",alignItems:"center",gap:8,padding:"5px 0",borderBottom:"1px solid var(--border-hair)",fontSize:13,opacity:a.na?.55:1},children:[n?e.jsx("input",{type:"checkbox","aria-label":`pilih ${a.id}`,checked:l,onChange:()=>o(a)}):e.jsx("span",{style:{display:"inline-block",width:13}}),e.jsx(W,{name:je[a.status],size:14,color:we[a.status]}),e.jsx("span",{style:{flex:1,minWidth:0},children:a.title}),a.drifted&&e.jsx(K,{text:"drift",color:"var(--clay-600)"}),e.jsx(K,{text:a.mode,color:Se[a.mode]}),e.jsx(K,{text:a.severity,color:Ce[a.severity]}),a.mode==="INFO"&&!a.attested&&e.jsx(f,{size:"sm",variant:"ghost",leftIcon:"check-circle",loading:s,onClick:()=>c(a),children:"Attest"}),e.jsx(f,{size:"sm",variant:"ghost",leftIcon:a.na?"rotate-ccw":"minus-circle",loading:s,onClick:()=>u(a,!a.na),children:a.na?"Batal N/A":"N/A"})]})}const ee={section:"",mode:"",status:"",severity:""};function J({value:a,onChange:s,options:l,label:o}){return e.jsxs("select",{"aria-label":o,value:a,onChange:u=>s(u.target.value),style:{fontSize:12,padding:"3px 6px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",background:"var(--bone-50)",color:"var(--text)"},children:[e.jsxs("option",{value:"",children:[o,": semua"]}),l.map(([u,c])=>e.jsx("option",{value:u,children:c},u))]})}function ze(a){let s=0,l=0,o=0,u=0;for(const n of a)n.status==="fail"?s++:n.status==="warn"?l++:n.status==="unknown"&&o++,n.drifted&&u++;const c=[s&&`${s} fail`,l&&`${l} warn`,o&&`${o} unknown`].filter(Boolean);return{text:c.length?c.join(" "):"semua pass",drift:u}}function $e({section:a,items:s,expanded:l,onToggle:o,busy:u,selected:c,onToggleItem:n,onNa:b,onAttest:g,onSectionNa:k}){const S=ze(a.items),h=!!a.suggestion&&!a.suggestion.applicable;return e.jsxs("div",{style:{marginBottom:8,border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",overflow:"hidden"},children:[e.jsxs("button",{"data-testid":`section-${a.id}`,"aria-expanded":l,onClick:()=>o(a.id),style:{display:"flex",alignItems:"center",gap:8,width:"100%",padding:"8px 10px",textAlign:"left",background:l?"var(--bone-100)":"transparent",border:"none",cursor:"pointer"},children:[e.jsx(W,{name:l?"chevron-down":"chevron-right",size:15,color:"var(--text-subtle)"}),e.jsx("span",{style:{fontSize:14},children:a.icon}),e.jsx("span",{style:{fontSize:13,fontWeight:600,flex:1,minWidth:0},children:a.title}),e.jsx("span",{style:{fontSize:11,color:"var(--text-subtle)",whiteSpace:"nowrap"},children:S.text}),S.drift>0&&e.jsx(K,{text:"drift",color:"var(--clay-600)"}),h&&e.jsx(K,{text:"saran N/A",color:"var(--brass-700)"}),e.jsx(ce,{score:a.score})]}),l&&e.jsxs("div",{style:{padding:"2px 10px 8px"},children:[h&&e.jsxs("div",{"data-testid":`suggestion-${a.id}`,style:{display:"flex",alignItems:"center",gap:8,margin:"6px 0",padding:"6px 10px",fontSize:12,color:"var(--text-subtle)",background:"var(--bone-50)",border:"1px dashed var(--border-hair)",borderRadius:"var(--radius-sm)"},children:[e.jsx(W,{name:"info",size:13,color:"var(--brass-700)"}),e.jsxs("span",{style:{flex:1},children:["Stack tak terdeteksi (",a.suggestion.detail,") — kemungkinan N/A. Cek Docker manual bila ragu."]}),e.jsx(f,{size:"sm",variant:"ghost",leftIcon:"minus-circle",loading:u===`section:${a.id}`,onClick:()=>k(a),children:"Tandai seksi N/A"})]}),s.map(y=>e.jsx(Pe,{item:y,busy:u===y.id,selected:c.has(y.id),onToggle:n,onNa:b,onAttest:g},y.id))]})]})}function Ae({vpsId:a,vpsName:s,lastAuditAt:l,health:o,provisioning:u,onClose:c,onToast:n}){const[b,g]=p.useState(null),[k,S]=p.useState("loading"),[h,y]=p.useState(ee),[P,w]=p.useState(""),[B,E]=p.useState(new Set),[$,C]=p.useState(null),[R,V]=p.useState(new Set),[F,D]=p.useState(null),[A,L]=p.useState(""),I=p.useCallback(()=>{S("loading"),v.vpsChecklist(a).then(r=>{g(r),S("ready")}).catch(()=>S("error"))},[a]);p.useEffect(()=>{I(),V(new Set),D(null),E(new Set),w(""),y(ee)},[I]);const t=r=>V(j=>{const d=new Set(j);return d.has(r.id)?d.delete(r.id):d.add(r.id),d}),x=()=>{V(new Set),D(null)},m=r=>E(j=>{const d=new Set(j);return d.has(r)?d.delete(r):d.add(r),d}),{confirm:H,dialog:X}=te();async function M(){L("preview");try{D((await v.remediatePreview(a,[...R])).steps)}catch{n("Preview remediasi gagal","err","x-circle")}finally{L("")}}async function Y(){if(await H({title:`Terapkan ${R.size} item AUTO ke VPS ini?`,message:"Remediasi dijalankan langsung di server yang terdaftar.",impact:["Langkahnya idempoten dan anti-lockout.","Checklist diaudit ulang setelah selesai."],confirmLabel:"Terapkan",icon:"shield"})){L("apply");try{await v.remediate(a,[...R]),x(),I(),n("Remediasi diterapkan · audit ulang","ok","shield")}catch{n("Remediasi gagal","err","x-circle")}finally{L("")}}}async function _(r,j,d){C(r.id);try{await j(),I(),n(d,"ok","shield")}catch{n(`Gagal memperbarui ${r.id}`,"err","x-circle")}finally{C(null)}}const i=(r,j)=>_(r,()=>v.markNa(a,r.id,j,j?"ditandai dari checklist":void 0),j?`${r.id} ditandai N/A`:`${r.id} kembali applicable`),z=r=>_(r,()=>v.attestItem(a,r.id),`${r.id} di-attest`);async function N(r){const j=r.items.map(d=>d.id);if(await H({title:`Tandai ${j.length} item seksi "${r.title}" sebagai N/A?`,message:"Stack-nya tak terdeteksi — cek Docker manual bila ragu.",confirmLabel:"Tandai N/A",icon:"shield"})){C(`section:${r.id}`);try{await v.markNaBulk(a,j,!0,"app-layer: stack tak terdeteksi"),I(),n(`Seksi ${r.title} ditandai N/A`,"ok","shield")}catch{n("Gagal tandai seksi N/A","err","x-circle")}finally{C(null)}}}const G=P.trim().toLowerCase(),q=!!(h.section||h.mode||h.status||h.severity)||G!=="",me=r=>(!h.section||r.section===h.section)&&(!h.mode||r.mode===h.mode)&&(!h.status||r.status===h.status)&&(!h.severity||r.severity===h.severity)&&(!G||r.title.toLowerCase().includes(G)||r.id.toLowerCase().includes(G)||(r.code??"").toLowerCase().includes(G)),Q=r=>j=>y(d=>({...d,[r]:j}));function ge(){if(k==="loading")return e.jsx(U,{kind:"loading",compact:!0,title:"Memuat checklist…"});if(k==="error"||!b)return e.jsx(U,{kind:"error",compact:!0,title:"Gagal memuat checklist",action:I});const r=b.sections.reduce((d,Z)=>d+Z.items.filter(xe=>xe.drifted).length,0),j=b.sections.map(d=>({section:d,matched:d.items.filter(me)})).filter(d=>!q||d.matched.length>0);return e.jsxs("div",{children:[e.jsxs("div",{style:{position:"sticky",top:0,zIndex:1,background:"var(--surface-card)",paddingBottom:10},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,marginBottom:10},children:[e.jsxs("div",{"data-testid":"score-total",style:{fontSize:22,fontWeight:700,fontFamily:"var(--font-mono)"},children:[b.scoreTotal,"%"]}),e.jsx("div",{style:{flex:1},children:e.jsx(ce,{score:b.scoreTotal})}),e.jsx("span",{style:{fontSize:11,color:"var(--text-subtle)"},children:"skor kepatuhan"})]}),r>0&&e.jsxs("div",{"data-testid":"drift-summary",style:{display:"flex",alignItems:"center",gap:6,marginBottom:10,padding:"6px 10px",fontSize:12,color:"var(--clay-700)",background:"var(--clay-50, var(--bone-100))",border:"1px solid var(--clay-600)",borderRadius:"var(--radius-sm)"},children:[e.jsx(W,{name:"alert-triangle",size:14,color:"var(--clay-600)"}),r," item drift (regresi) sejak audit sebelumnya"]}),e.jsxs("div",{style:{display:"flex",flexWrap:"wrap",gap:6,alignItems:"center"},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:4,flex:"1 1 180px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",padding:"2px 8px",background:"var(--bone-50)"},children:[e.jsx(W,{name:"search",size:13,color:"var(--text-subtle)"}),e.jsx("input",{"aria-label":"cari item",value:P,onChange:d=>w(d.target.value),placeholder:"mis. ssh atau 5.2.1",style:{flex:1,border:"none",background:"transparent",fontSize:12,color:"var(--text)",outline:"none"}})]}),e.jsx(J,{label:"seksi",value:h.section,onChange:Q("section"),options:b.sections.map(d=>[d.id,d.title])}),e.jsx(J,{label:"mode",value:h.mode,onChange:Q("mode"),options:[["AUTO","AUTO"],["AUDIT","AUDIT"],["INFO","INFO"]]}),e.jsx(J,{label:"status",value:h.status,onChange:Q("status"),options:[["pass","pass"],["fail","fail"],["warn","warn"],["na","na"],["unknown","unknown"]]}),e.jsx(J,{label:"severity",value:h.severity,onChange:Q("severity"),options:[["critical","critical"],["high","high"],["medium","medium"],["low","low"]]}),q&&e.jsx(f,{size:"sm",variant:"ghost",onClick:()=>{y(ee),w("")},children:"Reset"})]}),R.size>0&&e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,marginTop:10,padding:"8px 10px",background:"var(--bone-100)",border:"1px solid var(--brass-300)",borderRadius:"var(--radius-sm)"},children:[e.jsxs("span",{style:{fontSize:12,flex:1},children:[R.size," item AUTO dipilih"]}),e.jsx(f,{size:"sm",variant:"secondary",leftIcon:"eye",loading:A==="preview",onClick:M,children:"Preview"}),e.jsx(f,{size:"sm",leftIcon:"shield",loading:A==="apply",onClick:Y,children:"Apply"}),e.jsx(f,{size:"sm",variant:"ghost",onClick:x,children:"Batal"})]}),F&&e.jsxs("div",{"data-testid":"remediate-preview",style:{marginTop:10,padding:"8px 10px",fontSize:12,fontFamily:"var(--font-mono)",background:"var(--bone-50)",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)"},children:[e.jsx("div",{style:{fontWeight:600,marginBottom:4},children:"Pratinjau (dry-run) — belum diterapkan:"}),F.map(d=>e.jsxs("div",{style:{color:"var(--text-subtle)"},children:[d.item," · ",d.status," ",d.detail]},d.item))]})]}),j.length===0?e.jsx(U,{kind:"empty",compact:!0,title:"Tak ada item cocok",hint:"Ubah kata kunci atau reset filter."}):j.map(({section:d,matched:Z})=>e.jsx($e,{section:d,items:q?Z:d.items,expanded:q?!0:B.has(d.id),onToggle:m,busy:$,selected:R,onToggleItem:t,onNa:i,onAttest:z,onSectionNa:N},d.id))]})}return e.jsxs(oe,{open:!0,width:960,icon:"clipboard-list",eyebrow:s??"VPS",title:"Checklist kepatuhan",onClose:c,children:[e.jsxs("div",{"data-testid":"vps-detail",style:{fontSize:12,color:"var(--text-subtle)",marginBottom:12,paddingBottom:10,borderBottom:"1px solid var(--border-hair)"},children:[l?`Audit terakhir ${new Date(l).toLocaleString()}`:"Belum pernah diaudit",o&&` · disk ${o.disk} · mem ${o.mem} · load ${o.load}`]}),u&&e.jsx("div",{"data-testid":"vps-provisioning",style:{marginBottom:12,paddingBottom:10,borderBottom:"1px solid var(--border-hair)"},children:u}),ge(),X]})}const ne={ok:"terpasang",partial:"belum siap",absent:"belum ada"},ue={ok:"var(--leaf-600)",partial:"var(--amber-600)",absent:"var(--text-subtle)"};function pe(a,s){if(s.status==="partial"&&s.detail.startsWith("not-logged-in"))return`${a} · belum login`;if(s.status==="partial")return`${a} · ${s.detail||ne.partial}`;const l=s.status==="ok"&&s.detail?` ${s.detail}`:"";return`${a} · ${ne[s.status]??s.status}${l}`}const Ie={ok:"terpasang",partial:"belum siap",absent:"belum ada"};function he({status:a,children:s,title:l}){const o=ue[a]??"var(--text-subtle)";return e.jsxs("span",{title:l,style:{display:"inline-flex",alignItems:"center",gap:5,fontSize:11,lineHeight:"18px",color:"var(--text-primary)",background:"var(--surface-sunken)",border:"1px solid var(--border-hair)",borderRadius:999,padding:"0 8px",whiteSpace:"nowrap"},children:[e.jsx("span",{"aria-hidden":!0,style:{width:6,height:6,borderRadius:"50%",background:o,flex:"0 0 auto"}}),s]})}function Be({components:a,checkedAt:s}){return!a||!s?e.jsx("span",{style:{fontSize:11,color:"var(--text-subtle)"},children:"Komponen belum diperiksa"}):e.jsxs("div",{style:{display:"flex",flexWrap:"wrap",gap:6,alignItems:"center"},children:[Object.entries(a).map(([l,o])=>e.jsx(he,{status:o.status,children:pe(l,o)},l)),e.jsxs("span",{style:{fontSize:11,color:"var(--text-subtle)"},children:["diperiksa ",new Date(s).toLocaleString("id-ID")]})]})}const Re=a=>new Date(a).toLocaleString("id-ID",{day:"numeric",month:"short",hour:"2-digit",minute:"2-digit"});function Le({components:a,checkedAt:s}){if(!a||!s)return e.jsx("span",{style:{fontSize:11,color:"var(--text-subtle)"},children:"Komponen belum diperiksa — buka detail untuk memeriksa"});const l=Object.entries(a),o=l.filter(([,c])=>c.status!=="ok"),u=l.length-o.length;return e.jsxs("div",{style:{display:"flex",flexWrap:"wrap",gap:8,alignItems:"center",minWidth:0},children:[e.jsx("span",{"aria-hidden":!0,style:{display:"flex",gap:2,alignItems:"center"},children:l.map(([c,n])=>e.jsx("span",{style:{width:12,height:4,borderRadius:2,background:n.status==="absent"?"var(--border-strong)":ue[n.status]}},c))}),e.jsxs("span",{style:{fontSize:11,color:"var(--text-subtle)",whiteSpace:"nowrap"},children:[e.jsxs("strong",{style:{color:"var(--text-primary)",fontWeight:600},children:[u,"/",l.length]})," terpasang"]}),o.map(([c,n])=>e.jsxs(he,{status:n.status,title:pe(c,n),children:[c," · ",n.status==="partial"&&n.detail.startsWith("not-logged-in")?"belum login":Ie[n.status]??n.status]},c)),e.jsxs("span",{style:{fontSize:11,color:"var(--text-subtle)",whiteSpace:"nowrap"},children:["diperiksa ",Re(s)]})]})}function Ne(a,s,l){const o=new Map(s.map(n=>[n.id,n])),u=new Set,c=n=>{var b;if(!u.has(n)){u.add(n);for(const g of((b=o.get(n))==null?void 0:b.requires[l])??[])c(g)}};for(const n of a)c(n);return u}function De({vps:a,onToast:s,onGotoTerminal:l}){const[o,u]=p.useState([]),[c,n]=de("vps",`provisionProfile@${a.id}`,"lab",fe("lab","production")),[b,g]=p.useState(new Set),[k,S]=p.useState(""),[h,y]=p.useState(null),[P,w]=p.useState(null),[B,E]=p.useState(null),[$,C]=p.useState(null),{confirm:R,dialog:V}=te();p.useEffect(()=>{v.listVpsComponents().then(i=>u(i.components)).catch(()=>u([]))},[]);const F=o.filter(i=>i.profiles.includes(c)),D=Ne(b,o,c),A=[...D],L=A.some(i=>{var z;return(z=o.find(N=>N.id===i))==null?void 0:z.needsDomain}),I=A.length>0&&(!L||k.trim().length>0);function t(i){g(z=>{const N=new Set(z);return N.has(i)?N.delete(i):N.add(i),N})}async function x(){C("probe");try{w(await v.probeVps(a.id)),s("Komponen diperiksa","ok","server")}catch{s("Probe gagal","err","x-circle")}finally{C(null)}}async function m(){C("preview");try{y((await v.provisionPreview(a.id,{items:A,profile:c,domain:k||void 0})).steps)}catch{s("Pratinjau gagal","err","x-circle")}finally{C(null)}}async function H(){if(await R({title:`Pasang ${A.length} komponen di "${a.name}"?`,message:`Profil ${c}. Langkah dijalankan lewat SSH dan bisa memakan beberapa menit.`,impact:A.map(i=>{var z;return((z=o.find(N=>N.id===i))==null?void 0:z.label)??i}),confirmLabel:"Pasang",icon:"server"})){C("apply");try{const i=await v.provisionVps(a.id,{items:A,profile:c,domain:k||void 0,confirm:!0});y(i.steps),w({components:i.components,checkedAt:i.checkedAt}),E(i.setup),s("Provisioning selesai","ok","server")}catch{s("Provisioning gagal","err","x-circle")}finally{C(null)}}}const X=async()=>{try{const{id:i}=await v.vpsConsole(a.id);l(i)}catch{s("Gagal membuka console","err","x-circle")}},M=P?Object.fromEntries(P.components.map(i=>[i.id,{status:i.status,detail:i.detail}])):a.components??null,Y=(P==null?void 0:P.checkedAt)??a.componentsCheckedAt??null,_=M?Object.entries(M).filter(([,i])=>i.status==="partial"&&i.detail.startsWith("not-logged-in")):[];return e.jsxs("div",{style:{display:"grid",gap:12},children:[e.jsxs("div",{style:{display:"flex",gap:8,alignItems:"center",flexWrap:"wrap"},children:[e.jsx(Be,{components:M,checkedAt:Y}),e.jsx(f,{size:"sm",variant:"ghost",onClick:x,disabled:$!==null,children:"Periksa"})]}),e.jsx("div",{style:{display:"flex",gap:16},children:["lab","production"].map(i=>e.jsx(be,{"aria-label":i,label:i,checked:c===i,onChange:()=>n(i)},i))}),e.jsx("div",{style:{display:"grid",gap:6},children:F.map(i=>{const z=D.has(i.id)&&!b.has(i.id);return e.jsxs("div",{style:{display:"flex",gap:6,alignItems:"center"},children:[e.jsx(ke,{"aria-label":i.label,label:i.label,checked:D.has(i.id),disabled:z,onChange:()=>t(i.id)}),z&&e.jsx("span",{style:{fontSize:10,color:"var(--text-subtle)"},children:"prasyarat"})]},i.id)})}),L&&e.jsx(O,{label:"Domain",hint:"A record harus sudah menunjuk ke IP VPS ini",children:e.jsx(T,{"aria-label":"Domain",value:k,onChange:i=>S(i.currentTarget.value),placeholder:"hanoman.contoh.id"})}),e.jsxs("div",{style:{display:"flex",gap:8},children:[e.jsx(f,{variant:"ghost",onClick:m,disabled:!I||$!==null,children:"Pratinjau"}),e.jsx(f,{onClick:H,disabled:!I||$!==null,children:"Pasang"})]}),h&&e.jsx("pre",{style:{fontSize:11,fontFamily:"var(--font-mono)",maxHeight:220,overflow:"auto",background:"var(--surface-sunken)",padding:8,borderRadius:4},children:h.map(i=>`${i.item.padEnd(14)} ${i.status.padEnd(6)} ${i.detail}`).join(`
1
+ import{e as v,u as te,j as e,M as oe,f as U,I as W,a as f,h as de,o as fe,ap as be,ai as ke,c as O,d as T,a7 as ye,ac as se,y as ve}from"./index-Bd9gXx1g.js";import{R as p}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";const je={pass:"check",fail:"x",warn:"alert-triangle",na:"minus",unknown:"circle"},we={pass:"var(--leaf-600)",fail:"var(--clay-600)",warn:"var(--amber-600)",na:"var(--text-subtle)",unknown:"var(--text-subtle)"},Se={AUTO:"var(--brass-700)",AUDIT:"var(--amber-600)",INFO:"var(--text-subtle)"},Ce={critical:"var(--clay-600)",high:"var(--amber-600)",medium:"var(--text-subtle)",low:"var(--text-subtle)"};function K({text:a,color:s}){return e.jsx("span",{style:{fontSize:10,textTransform:"uppercase",letterSpacing:"0.04em",color:s,border:`1px solid ${s}`,borderRadius:3,padding:"0 4px",whiteSpace:"nowrap"},children:a})}function ce({score:a}){const s=a>=90?"var(--leaf-600)":a>=50?"var(--amber-600)":"var(--clay-600)";return e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6,minWidth:90},children:[e.jsx("div",{style:{flex:1,height:6,background:"var(--bone-200)",borderRadius:3,overflow:"hidden"},children:e.jsx("div",{style:{width:`${a}%`,height:"100%",background:s}})}),e.jsxs("span",{style:{fontSize:11,fontFamily:"var(--font-mono)",color:"var(--text-subtle)",minWidth:28,textAlign:"right"},children:[a,"%"]})]})}function Pe({item:a,busy:s,selected:l,onToggle:o,onNa:u,onAttest:c}){const n=a.mode==="AUTO"&&!a.na;return e.jsxs("div",{"data-testid":`item-${a.id}`,style:{display:"flex",alignItems:"center",gap:8,padding:"5px 0",borderBottom:"1px solid var(--border-hair)",fontSize:13,opacity:a.na?.55:1},children:[n?e.jsx("input",{type:"checkbox","aria-label":`pilih ${a.id}`,checked:l,onChange:()=>o(a)}):e.jsx("span",{style:{display:"inline-block",width:13}}),e.jsx(W,{name:je[a.status],size:14,color:we[a.status]}),e.jsx("span",{style:{flex:1,minWidth:0},children:a.title}),a.drifted&&e.jsx(K,{text:"drift",color:"var(--clay-600)"}),e.jsx(K,{text:a.mode,color:Se[a.mode]}),e.jsx(K,{text:a.severity,color:Ce[a.severity]}),a.mode==="INFO"&&!a.attested&&e.jsx(f,{size:"sm",variant:"ghost",leftIcon:"check-circle",loading:s,onClick:()=>c(a),children:"Attest"}),e.jsx(f,{size:"sm",variant:"ghost",leftIcon:a.na?"rotate-ccw":"minus-circle",loading:s,onClick:()=>u(a,!a.na),children:a.na?"Batal N/A":"N/A"})]})}const ee={section:"",mode:"",status:"",severity:""};function J({value:a,onChange:s,options:l,label:o}){return e.jsxs("select",{"aria-label":o,value:a,onChange:u=>s(u.target.value),style:{fontSize:12,padding:"3px 6px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",background:"var(--bone-50)",color:"var(--text)"},children:[e.jsxs("option",{value:"",children:[o,": semua"]}),l.map(([u,c])=>e.jsx("option",{value:u,children:c},u))]})}function ze(a){let s=0,l=0,o=0,u=0;for(const n of a)n.status==="fail"?s++:n.status==="warn"?l++:n.status==="unknown"&&o++,n.drifted&&u++;const c=[s&&`${s} fail`,l&&`${l} warn`,o&&`${o} unknown`].filter(Boolean);return{text:c.length?c.join(" "):"semua pass",drift:u}}function $e({section:a,items:s,expanded:l,onToggle:o,busy:u,selected:c,onToggleItem:n,onNa:b,onAttest:g,onSectionNa:k}){const S=ze(a.items),h=!!a.suggestion&&!a.suggestion.applicable;return e.jsxs("div",{style:{marginBottom:8,border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",overflow:"hidden"},children:[e.jsxs("button",{"data-testid":`section-${a.id}`,"aria-expanded":l,onClick:()=>o(a.id),style:{display:"flex",alignItems:"center",gap:8,width:"100%",padding:"8px 10px",textAlign:"left",background:l?"var(--bone-100)":"transparent",border:"none",cursor:"pointer"},children:[e.jsx(W,{name:l?"chevron-down":"chevron-right",size:15,color:"var(--text-subtle)"}),e.jsx("span",{style:{fontSize:14},children:a.icon}),e.jsx("span",{style:{fontSize:13,fontWeight:600,flex:1,minWidth:0},children:a.title}),e.jsx("span",{style:{fontSize:11,color:"var(--text-subtle)",whiteSpace:"nowrap"},children:S.text}),S.drift>0&&e.jsx(K,{text:"drift",color:"var(--clay-600)"}),h&&e.jsx(K,{text:"saran N/A",color:"var(--brass-700)"}),e.jsx(ce,{score:a.score})]}),l&&e.jsxs("div",{style:{padding:"2px 10px 8px"},children:[h&&e.jsxs("div",{"data-testid":`suggestion-${a.id}`,style:{display:"flex",alignItems:"center",gap:8,margin:"6px 0",padding:"6px 10px",fontSize:12,color:"var(--text-subtle)",background:"var(--bone-50)",border:"1px dashed var(--border-hair)",borderRadius:"var(--radius-sm)"},children:[e.jsx(W,{name:"info",size:13,color:"var(--brass-700)"}),e.jsxs("span",{style:{flex:1},children:["Stack tak terdeteksi (",a.suggestion.detail,") — kemungkinan N/A. Cek Docker manual bila ragu."]}),e.jsx(f,{size:"sm",variant:"ghost",leftIcon:"minus-circle",loading:u===`section:${a.id}`,onClick:()=>k(a),children:"Tandai seksi N/A"})]}),s.map(y=>e.jsx(Pe,{item:y,busy:u===y.id,selected:c.has(y.id),onToggle:n,onNa:b,onAttest:g},y.id))]})]})}function Ae({vpsId:a,vpsName:s,lastAuditAt:l,health:o,provisioning:u,onClose:c,onToast:n}){const[b,g]=p.useState(null),[k,S]=p.useState("loading"),[h,y]=p.useState(ee),[P,w]=p.useState(""),[B,E]=p.useState(new Set),[$,C]=p.useState(null),[R,V]=p.useState(new Set),[F,D]=p.useState(null),[A,L]=p.useState(""),I=p.useCallback(()=>{S("loading"),v.vpsChecklist(a).then(r=>{g(r),S("ready")}).catch(()=>S("error"))},[a]);p.useEffect(()=>{I(),V(new Set),D(null),E(new Set),w(""),y(ee)},[I]);const t=r=>V(j=>{const d=new Set(j);return d.has(r.id)?d.delete(r.id):d.add(r.id),d}),x=()=>{V(new Set),D(null)},m=r=>E(j=>{const d=new Set(j);return d.has(r)?d.delete(r):d.add(r),d}),{confirm:H,dialog:X}=te();async function M(){L("preview");try{D((await v.remediatePreview(a,[...R])).steps)}catch{n("Preview remediasi gagal","err","x-circle")}finally{L("")}}async function Y(){if(await H({title:`Terapkan ${R.size} item AUTO ke VPS ini?`,message:"Remediasi dijalankan langsung di server yang terdaftar.",impact:["Langkahnya idempoten dan anti-lockout.","Checklist diaudit ulang setelah selesai."],confirmLabel:"Terapkan",icon:"shield"})){L("apply");try{await v.remediate(a,[...R]),x(),I(),n("Remediasi diterapkan · audit ulang","ok","shield")}catch{n("Remediasi gagal","err","x-circle")}finally{L("")}}}async function _(r,j,d){C(r.id);try{await j(),I(),n(d,"ok","shield")}catch{n(`Gagal memperbarui ${r.id}`,"err","x-circle")}finally{C(null)}}const i=(r,j)=>_(r,()=>v.markNa(a,r.id,j,j?"ditandai dari checklist":void 0),j?`${r.id} ditandai N/A`:`${r.id} kembali applicable`),z=r=>_(r,()=>v.attestItem(a,r.id),`${r.id} di-attest`);async function N(r){const j=r.items.map(d=>d.id);if(await H({title:`Tandai ${j.length} item seksi "${r.title}" sebagai N/A?`,message:"Stack-nya tak terdeteksi — cek Docker manual bila ragu.",confirmLabel:"Tandai N/A",icon:"shield"})){C(`section:${r.id}`);try{await v.markNaBulk(a,j,!0,"app-layer: stack tak terdeteksi"),I(),n(`Seksi ${r.title} ditandai N/A`,"ok","shield")}catch{n("Gagal tandai seksi N/A","err","x-circle")}finally{C(null)}}}const G=P.trim().toLowerCase(),q=!!(h.section||h.mode||h.status||h.severity)||G!=="",me=r=>(!h.section||r.section===h.section)&&(!h.mode||r.mode===h.mode)&&(!h.status||r.status===h.status)&&(!h.severity||r.severity===h.severity)&&(!G||r.title.toLowerCase().includes(G)||r.id.toLowerCase().includes(G)||(r.code??"").toLowerCase().includes(G)),Q=r=>j=>y(d=>({...d,[r]:j}));function ge(){if(k==="loading")return e.jsx(U,{kind:"loading",compact:!0,title:"Memuat checklist…"});if(k==="error"||!b)return e.jsx(U,{kind:"error",compact:!0,title:"Gagal memuat checklist",action:I});const r=b.sections.reduce((d,Z)=>d+Z.items.filter(xe=>xe.drifted).length,0),j=b.sections.map(d=>({section:d,matched:d.items.filter(me)})).filter(d=>!q||d.matched.length>0);return e.jsxs("div",{children:[e.jsxs("div",{style:{position:"sticky",top:0,zIndex:1,background:"var(--surface-card)",paddingBottom:10},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,marginBottom:10},children:[e.jsxs("div",{"data-testid":"score-total",style:{fontSize:22,fontWeight:700,fontFamily:"var(--font-mono)"},children:[b.scoreTotal,"%"]}),e.jsx("div",{style:{flex:1},children:e.jsx(ce,{score:b.scoreTotal})}),e.jsx("span",{style:{fontSize:11,color:"var(--text-subtle)"},children:"skor kepatuhan"})]}),r>0&&e.jsxs("div",{"data-testid":"drift-summary",style:{display:"flex",alignItems:"center",gap:6,marginBottom:10,padding:"6px 10px",fontSize:12,color:"var(--clay-700)",background:"var(--clay-50, var(--bone-100))",border:"1px solid var(--clay-600)",borderRadius:"var(--radius-sm)"},children:[e.jsx(W,{name:"alert-triangle",size:14,color:"var(--clay-600)"}),r," item drift (regresi) sejak audit sebelumnya"]}),e.jsxs("div",{style:{display:"flex",flexWrap:"wrap",gap:6,alignItems:"center"},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:4,flex:"1 1 180px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",padding:"2px 8px",background:"var(--bone-50)"},children:[e.jsx(W,{name:"search",size:13,color:"var(--text-subtle)"}),e.jsx("input",{"aria-label":"cari item",value:P,onChange:d=>w(d.target.value),placeholder:"mis. ssh atau 5.2.1",style:{flex:1,border:"none",background:"transparent",fontSize:12,color:"var(--text)",outline:"none"}})]}),e.jsx(J,{label:"seksi",value:h.section,onChange:Q("section"),options:b.sections.map(d=>[d.id,d.title])}),e.jsx(J,{label:"mode",value:h.mode,onChange:Q("mode"),options:[["AUTO","AUTO"],["AUDIT","AUDIT"],["INFO","INFO"]]}),e.jsx(J,{label:"status",value:h.status,onChange:Q("status"),options:[["pass","pass"],["fail","fail"],["warn","warn"],["na","na"],["unknown","unknown"]]}),e.jsx(J,{label:"severity",value:h.severity,onChange:Q("severity"),options:[["critical","critical"],["high","high"],["medium","medium"],["low","low"]]}),q&&e.jsx(f,{size:"sm",variant:"ghost",onClick:()=>{y(ee),w("")},children:"Reset"})]}),R.size>0&&e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,marginTop:10,padding:"8px 10px",background:"var(--bone-100)",border:"1px solid var(--brass-300)",borderRadius:"var(--radius-sm)"},children:[e.jsxs("span",{style:{fontSize:12,flex:1},children:[R.size," item AUTO dipilih"]}),e.jsx(f,{size:"sm",variant:"secondary",leftIcon:"eye",loading:A==="preview",onClick:M,children:"Preview"}),e.jsx(f,{size:"sm",leftIcon:"shield",loading:A==="apply",onClick:Y,children:"Apply"}),e.jsx(f,{size:"sm",variant:"ghost",onClick:x,children:"Batal"})]}),F&&e.jsxs("div",{"data-testid":"remediate-preview",style:{marginTop:10,padding:"8px 10px",fontSize:12,fontFamily:"var(--font-mono)",background:"var(--bone-50)",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)"},children:[e.jsx("div",{style:{fontWeight:600,marginBottom:4},children:"Pratinjau (dry-run) — belum diterapkan:"}),F.map(d=>e.jsxs("div",{style:{color:"var(--text-subtle)"},children:[d.item," · ",d.status," ",d.detail]},d.item))]})]}),j.length===0?e.jsx(U,{kind:"empty",compact:!0,title:"Tak ada item cocok",hint:"Ubah kata kunci atau reset filter."}):j.map(({section:d,matched:Z})=>e.jsx($e,{section:d,items:q?Z:d.items,expanded:q?!0:B.has(d.id),onToggle:m,busy:$,selected:R,onToggleItem:t,onNa:i,onAttest:z,onSectionNa:N},d.id))]})}return e.jsxs(oe,{open:!0,width:960,icon:"clipboard-list",eyebrow:s??"VPS",title:"Checklist kepatuhan",onClose:c,children:[e.jsxs("div",{"data-testid":"vps-detail",style:{fontSize:12,color:"var(--text-subtle)",marginBottom:12,paddingBottom:10,borderBottom:"1px solid var(--border-hair)"},children:[l?`Audit terakhir ${new Date(l).toLocaleString()}`:"Belum pernah diaudit",o&&` · disk ${o.disk} · mem ${o.mem} · load ${o.load}`]}),u&&e.jsx("div",{"data-testid":"vps-provisioning",style:{marginBottom:12,paddingBottom:10,borderBottom:"1px solid var(--border-hair)"},children:u}),ge(),X]})}const ne={ok:"terpasang",partial:"belum siap",absent:"belum ada"},ue={ok:"var(--leaf-600)",partial:"var(--amber-600)",absent:"var(--text-subtle)"};function pe(a,s){if(s.status==="partial"&&s.detail.startsWith("not-logged-in"))return`${a} · belum login`;if(s.status==="partial")return`${a} · ${s.detail||ne.partial}`;const l=s.status==="ok"&&s.detail?` ${s.detail}`:"";return`${a} · ${ne[s.status]??s.status}${l}`}const Ie={ok:"terpasang",partial:"belum siap",absent:"belum ada"};function he({status:a,children:s,title:l}){const o=ue[a]??"var(--text-subtle)";return e.jsxs("span",{title:l,style:{display:"inline-flex",alignItems:"center",gap:5,fontSize:11,lineHeight:"18px",color:"var(--text-primary)",background:"var(--surface-sunken)",border:"1px solid var(--border-hair)",borderRadius:999,padding:"0 8px",whiteSpace:"nowrap"},children:[e.jsx("span",{"aria-hidden":!0,style:{width:6,height:6,borderRadius:"50%",background:o,flex:"0 0 auto"}}),s]})}function Be({components:a,checkedAt:s}){return!a||!s?e.jsx("span",{style:{fontSize:11,color:"var(--text-subtle)"},children:"Komponen belum diperiksa"}):e.jsxs("div",{style:{display:"flex",flexWrap:"wrap",gap:6,alignItems:"center"},children:[Object.entries(a).map(([l,o])=>e.jsx(he,{status:o.status,children:pe(l,o)},l)),e.jsxs("span",{style:{fontSize:11,color:"var(--text-subtle)"},children:["diperiksa ",new Date(s).toLocaleString("id-ID")]})]})}const Re=a=>new Date(a).toLocaleString("id-ID",{day:"numeric",month:"short",hour:"2-digit",minute:"2-digit"});function Le({components:a,checkedAt:s}){if(!a||!s)return e.jsx("span",{style:{fontSize:11,color:"var(--text-subtle)"},children:"Komponen belum diperiksa — buka detail untuk memeriksa"});const l=Object.entries(a),o=l.filter(([,c])=>c.status!=="ok"),u=l.length-o.length;return e.jsxs("div",{style:{display:"flex",flexWrap:"wrap",gap:8,alignItems:"center",minWidth:0},children:[e.jsx("span",{"aria-hidden":!0,style:{display:"flex",gap:2,alignItems:"center"},children:l.map(([c,n])=>e.jsx("span",{style:{width:12,height:4,borderRadius:2,background:n.status==="absent"?"var(--border-strong)":ue[n.status]}},c))}),e.jsxs("span",{style:{fontSize:11,color:"var(--text-subtle)",whiteSpace:"nowrap"},children:[e.jsxs("strong",{style:{color:"var(--text-primary)",fontWeight:600},children:[u,"/",l.length]})," terpasang"]}),o.map(([c,n])=>e.jsxs(he,{status:n.status,title:pe(c,n),children:[c," · ",n.status==="partial"&&n.detail.startsWith("not-logged-in")?"belum login":Ie[n.status]??n.status]},c)),e.jsxs("span",{style:{fontSize:11,color:"var(--text-subtle)",whiteSpace:"nowrap"},children:["diperiksa ",Re(s)]})]})}function Ne(a,s,l){const o=new Map(s.map(n=>[n.id,n])),u=new Set,c=n=>{var b;if(!u.has(n)){u.add(n);for(const g of((b=o.get(n))==null?void 0:b.requires[l])??[])c(g)}};for(const n of a)c(n);return u}function De({vps:a,onToast:s,onGotoTerminal:l}){const[o,u]=p.useState([]),[c,n]=de("vps",`provisionProfile@${a.id}`,"lab",fe("lab","production")),[b,g]=p.useState(new Set),[k,S]=p.useState(""),[h,y]=p.useState(null),[P,w]=p.useState(null),[B,E]=p.useState(null),[$,C]=p.useState(null),{confirm:R,dialog:V}=te();p.useEffect(()=>{v.listVpsComponents().then(i=>u(i.components)).catch(()=>u([]))},[]);const F=o.filter(i=>i.profiles.includes(c)),D=Ne(b,o,c),A=[...D],L=A.some(i=>{var z;return(z=o.find(N=>N.id===i))==null?void 0:z.needsDomain}),I=A.length>0&&(!L||k.trim().length>0);function t(i){g(z=>{const N=new Set(z);return N.has(i)?N.delete(i):N.add(i),N})}async function x(){C("probe");try{w(await v.probeVps(a.id)),s("Komponen diperiksa","ok","server")}catch{s("Probe gagal","err","x-circle")}finally{C(null)}}async function m(){C("preview");try{y((await v.provisionPreview(a.id,{items:A,profile:c,domain:k||void 0})).steps)}catch{s("Pratinjau gagal","err","x-circle")}finally{C(null)}}async function H(){if(await R({title:`Pasang ${A.length} komponen di "${a.name}"?`,message:`Profil ${c}. Langkah dijalankan lewat SSH dan bisa memakan beberapa menit.`,impact:A.map(i=>{var z;return((z=o.find(N=>N.id===i))==null?void 0:z.label)??i}),confirmLabel:"Pasang",icon:"server"})){C("apply");try{const i=await v.provisionVps(a.id,{items:A,profile:c,domain:k||void 0,confirm:!0});y(i.steps),w({components:i.components,checkedAt:i.checkedAt}),E(i.setup),s("Provisioning selesai","ok","server")}catch{s("Provisioning gagal","err","x-circle")}finally{C(null)}}}const X=async()=>{try{const{id:i}=await v.vpsConsole(a.id);l(i)}catch{s("Gagal membuka console","err","x-circle")}},M=P?Object.fromEntries(P.components.map(i=>[i.id,{status:i.status,detail:i.detail}])):a.components??null,Y=(P==null?void 0:P.checkedAt)??a.componentsCheckedAt??null,_=M?Object.entries(M).filter(([,i])=>i.status==="partial"&&i.detail.startsWith("not-logged-in")):[];return e.jsxs("div",{style:{display:"grid",gap:12},children:[e.jsxs("div",{style:{display:"flex",gap:8,alignItems:"center",flexWrap:"wrap"},children:[e.jsx(Be,{components:M,checkedAt:Y}),e.jsx(f,{size:"sm",variant:"ghost",onClick:x,disabled:$!==null,children:"Periksa"})]}),e.jsx("div",{style:{display:"flex",gap:16},children:["lab","production"].map(i=>e.jsx(be,{"aria-label":i,label:i,checked:c===i,onChange:()=>n(i)},i))}),e.jsx("div",{style:{display:"grid",gap:6},children:F.map(i=>{const z=D.has(i.id)&&!b.has(i.id);return e.jsxs("div",{style:{display:"flex",gap:6,alignItems:"center"},children:[e.jsx(ke,{"aria-label":i.label,label:i.label,checked:D.has(i.id),disabled:z,onChange:()=>t(i.id)}),z&&e.jsx("span",{style:{fontSize:10,color:"var(--text-subtle)"},children:"prasyarat"})]},i.id)})}),L&&e.jsx(O,{label:"Domain",hint:"A record harus sudah menunjuk ke IP VPS ini",children:e.jsx(T,{"aria-label":"Domain",value:k,onChange:i=>S(i.currentTarget.value),placeholder:"hanoman.contoh.id"})}),e.jsxs("div",{style:{display:"flex",gap:8},children:[e.jsx(f,{variant:"ghost",onClick:m,disabled:!I||$!==null,children:"Pratinjau"}),e.jsx(f,{onClick:H,disabled:!I||$!==null,children:"Pasang"})]}),h&&e.jsx("pre",{style:{fontSize:11,fontFamily:"var(--font-mono)",maxHeight:220,overflow:"auto",background:"var(--surface-sunken)",padding:8,borderRadius:4},children:h.map(i=>`${i.item.padEnd(14)} ${i.status.padEnd(6)} ${i.detail}`).join(`
2
2
  `)}),B&&e.jsxs("div",{style:{display:"grid",gap:4,border:"1px solid var(--border-strong)",borderRadius:4,padding:8},children:[e.jsx("strong",{style:{fontSize:12},children:"Buat admin pertama"}),e.jsx("a",{href:B.url,target:"_blank",rel:"noreferrer",style:{fontSize:12,wordBreak:"break-all"},children:B.url}),e.jsxs("span",{style:{fontSize:11,color:"var(--text-subtle)"},children:["berlaku sampai ",new Date(B.expiresAt).toLocaleTimeString("id-ID")]}),e.jsx("div",{children:e.jsx(f,{size:"sm",variant:"ghost",onClick:()=>{var i;return void((i=navigator.clipboard)==null?void 0:i.writeText(B.url))},children:"Salin"})})]}),_.length>0&&e.jsxs("div",{style:{display:"flex",gap:8,alignItems:"center",fontSize:12},children:[e.jsx(W,{name:"alert-triangle"}),e.jsxs("span",{children:[_.map(([i])=>i).join(", ")," terpasang tapi belum login."]}),e.jsx(f,{size:"sm",variant:"ghost",onClick:X,children:"Login lewat Console"})]}),V]})}const ie=(a,s=Date.now())=>!!a.lastSeenAt&&s-new Date(a.lastSeenAt).getTime()<10*6e4,Ve=a=>a.lastAuditAt?a.hardened?"hardened":"belum":"unknown",Oe={hardened:{status:"ok",label:"hardened"},belum:{status:"broken",label:"belum hardened"},unknown:{status:"idle",label:"belum diaudit"}};function re(a){const s={name:a.name.trim(),host:a.host.trim(),user:a.user.trim(),port:Number(a.port)||22};return a.keyPath.trim()&&(s.keyPath=a.keyPath.trim()),a.password&&(s.password=a.password),s}const Te="opsional — dipakai sekali untuk memasang key hanoman, tidak disimpan";function ae({open:a,title:s,submitLabel:l,initial:o,onClose:u,onSubmit:c}){const[n,b]=p.useState(o);p.useEffect(()=>{a&&b(o)},[a,o]);const g=S=>h=>b(y=>({...y,[S]:h.target.value})),k=!!(n.name.trim()&&n.host.trim()&&n.user.trim());return e.jsxs(oe,{open:a,onClose:u,icon:"server",eyebrow:"infra",title:s,footer:e.jsxs(e.Fragment,{children:[e.jsx(f,{variant:"ghost",size:"sm",onClick:u,children:"Batal"}),e.jsx(f,{size:"sm",leftIcon:"check",onClick:()=>k&&c(n),children:l})]}),children:[e.jsx(O,{label:"Nama",children:e.jsx(T,{value:n.name,onChange:g("name"),placeholder:"mis. web-1",style:{width:"100%"}})}),e.jsx(O,{label:"Host",hint:"hostname atau IP — tanpa user@",children:e.jsx(T,{value:n.host,onChange:g("host"),mono:!0,placeholder:"203.0.113.10",style:{width:"100%"}})}),e.jsxs("div",{className:"hn-grid-mobile",style:{display:"grid",gridTemplateColumns:"1.4fr 1fr",gap:12},children:[e.jsx(O,{label:"User SSH",hint:"root atau user ber-passwordless-sudo",children:e.jsx(T,{value:n.user,onChange:g("user"),mono:!0,placeholder:"deploy",style:{width:"100%"}})}),e.jsx(O,{label:"Port",children:e.jsx(T,{value:n.port,onChange:g("port"),mono:!0,placeholder:"22",style:{width:"100%"}})})]}),e.jsx(O,{label:"Password SSH",hint:Te,children:e.jsx(T,{type:"password",value:n.password,onChange:g("password"),placeholder:"••••••••",style:{width:"100%"}})}),e.jsx(O,{label:"Key path",hint:"kosongkan bila memakai password di atas, atau key default mesin server",children:e.jsx(T,{value:n.keyPath,onChange:g("keyPath"),mono:!0,placeholder:"~/.ssh/id_ed25519",style:{width:"100%"}})})]})}const le={name:"",host:"",user:"",port:"22",keyPath:"",password:""},We=a=>({name:a.name,host:a.host,user:a.user,port:String(a.port),keyPath:a.keyPath??"",password:""});function Me({onToast:a,onGotoTerminal:s}){const[l,o]=p.useState([]),[u,c]=p.useState("loading"),[n,b]=p.useState(null),[g,k]=p.useState(null),[S,h]=de("vps","detailId",null,ve),y=p.useMemo(()=>l.find(t=>t.id===S)??null,[l,S]),P=p.useCallback(t=>h(t?t.id:null),[h]),w=p.useCallback(()=>{v.listVps().then(t=>{o(t),c("ready")}).catch(()=>c("error"))},[]);p.useEffect(()=>(w(),ye(t=>{t.t==="vps"&&(o(t.vps),c("ready"))})),[w]);const{confirm:B,dialog:E}=te();async function $(t,x,m,H){b(`${t}:${x}`);try{await m(),w(),a(H,"ok","server")}catch{a(`Gagal ${t}`,"err","x-circle")}finally{b(null)}}const C=t=>$("audit",t.id,()=>v.auditVps(t.id),`${t.name} · audit selesai`);async function R(t){await B({title:`Harden "${t.name}"?`,message:"Pastikan akses key SSH non-password kamu sudah bekerja sebelum melanjutkan.",impact:[`Firewall: izinkan ${t.port}/80/443.`,"fail2ban & auto security update dipasang.","PermitRootLogin & PasswordAuthentication dimatikan.","NTP disinkronkan."],confirmLabel:"Harden",icon:"shield"})&&$("harden",t.id,()=>v.hardenVps(t.id),`${t.name} · harden selesai`)}const V=t=>$("sesi",t.id,async()=>{const{id:x}=await v.vpsSession(t.id);s(x)},`${t.name} · sesi Claude dibuka`),F=t=>$("test",t.id,async()=>{const x=await v.testVps(t.id);if(!x.ok)throw new Error(x.out)},`${t.name} · koneksi ok`),D=t=>$("console",t.id,async()=>{const{id:x}=await v.vpsConsole(t.id);s(x)},`${t.name} · console dibuka`);async function A(t){try{if(!await B({title:`Hapus registrasi VPS "${t.name}"?`,message:"Server-nya sendiri tak disentuh — hanya pendaftarannya di dashboard ini yang dihapus.",confirmLabel:"Hapus registrasi",run:()=>v.deleteVps(t.id)}))return;w()}catch{a("Gagal hapus","err","x-circle")}}async function L(t){try{const x=await v.createVps(re(t));k(null),w(),a(t.password?`${x.name} terdaftar · key hanoman terpasang · password dibuang`:`${x.name} terdaftar · jalankan audit`,"ok","server")}catch{a("Gagal mendaftarkan VPS — cek host/user, atau password SSH-nya","err","x-circle")}}async function I(t,x){try{const m=await v.updateVps(t.id,re(x));k(null),w(),a(x.password?`${m.name} diperbarui · key hanoman terpasang · password dibuang`:`${m.name} diperbarui`,"ok","server")}catch{a("Gagal memperbarui VPS","err","x-circle")}}return u==="loading"?e.jsx(U,{kind:"loading",title:"Memuat daftar VPS…"}):u==="error"?e.jsx(U,{kind:"error",title:"Gagal memuat daftar VPS",hint:"Pastikan server hanoman berjalan.",action:w}):l.length===0?e.jsxs(e.Fragment,{children:[e.jsx(U,{kind:"empty",icon:"server",title:"Belum ada VPS",hint:"Daftarkan VPS untuk mulai audit & hardening.",action:()=>k("new"),actionLabel:"Daftarkan VPS"}),e.jsx(ae,{open:g==="new",title:"Daftarkan VPS",submitLabel:"Daftarkan",initial:le,onClose:()=>k(null),onSubmit:L})]}):e.jsxs("div",{children:[e.jsxs("div",{children:[e.jsx("div",{style:{display:"flex",justifyContent:"flex-end",marginBottom:10},children:e.jsx(f,{size:"sm",leftIcon:"plus",onClick:()=>k("new"),children:"Daftarkan VPS"})}),l.map(t=>{const x=Oe[Ve(t)];return e.jsxs("div",{className:"hn-vps-row",onClick:()=>P(t),style:{padding:"10px 12px",cursor:"pointer",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",marginBottom:8},children:[e.jsxs("div",{className:"hn-vps-main",children:[e.jsxs("button",{type:"button","aria-label":`Buka detail ${t.name}`,onClick:m=>{m.stopPropagation(),P(t)},style:{display:"flex",alignItems:"center",gap:10,flex:"1 1 220px",minWidth:0,cursor:"pointer",font:"inherit",color:"inherit",textAlign:"left",background:"transparent",padding:0,border:"none"},children:[e.jsx(W,{name:"server",size:16,color:"var(--brass-700)"}),e.jsxs("span",{style:{minWidth:0},children:[e.jsx("span",{style:{display:"block",fontSize:13,fontWeight:600,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:t.name}),e.jsxs("span",{style:{display:"block",fontSize:12,fontFamily:"var(--font-mono)",color:"var(--text-subtle)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:[t.user,"@",t.host,t.port!==22?`:${t.port}`:""]})]})]}),e.jsxs("div",{className:"hn-vps-pills",style:{display:"flex",gap:6,alignItems:"center",flexShrink:0},children:[e.jsx(se,{size:"sm",status:ie(t)?"ok":"broken",children:ie(t)?"reachable":"unreachable"}),e.jsx(se,{size:"sm",status:x.status,children:x.label})]}),e.jsxs("div",{className:"hn-vps-actions",children:[e.jsx(f,{size:"sm",variant:"ghost",leftIcon:"plug-zap",loading:n===`test:${t.id}`,onClick:m=>{m.stopPropagation(),F(t)},children:"Test"}),e.jsx(f,{size:"sm",variant:"ghost",leftIcon:"terminal-square",loading:n===`console:${t.id}`,onClick:m=>{m.stopPropagation(),D(t)},children:"Console"}),e.jsx(f,{size:"sm",variant:"ghost",leftIcon:"terminal",loading:n===`sesi:${t.id}`,onClick:m=>{m.stopPropagation(),V(t)},children:"Sesi Claude"}),e.jsx(f,{size:"sm",variant:"secondary",leftIcon:"radar",loading:n===`audit:${t.id}`,onClick:m=>{m.stopPropagation(),C(t)},children:"Audit"}),e.jsx(f,{size:"sm",leftIcon:"shield",loading:n===`harden:${t.id}`,onClick:m=>{m.stopPropagation(),R(t)},children:"Harden"}),e.jsx("span",{"aria-hidden":!0,className:"hn-vps-sep"}),e.jsx(f,{size:"sm",variant:"ghost",leftIcon:"pencil",title:`Edit ${t.name}`,onClick:m=>{m.stopPropagation(),k(t)}}),e.jsx(f,{size:"sm",variant:"ghost",leftIcon:"trash-2",title:`Hapus ${t.name}`,onClick:m=>{m.stopPropagation(),A(t)}})]})]}),e.jsx("div",{style:{marginTop:8,paddingTop:8,borderTop:"1px solid var(--border-hair)"},children:e.jsx(Le,{components:t.components??null,checkedAt:t.componentsCheckedAt??null})})]},t.id)})]}),y&&e.jsx(Ae,{vpsId:y.id,vpsName:y.name,lastAuditAt:y.lastAuditAt,health:y.health,provisioning:e.jsx(De,{vps:y,onToast:a,onGotoTerminal:s}),onClose:()=>{P(null),w()},onToast:a}),e.jsx(ae,{open:g==="new",title:"Daftarkan VPS",submitLabel:"Daftarkan",initial:le,onClose:()=>k(null),onSubmit:L}),g&&g!=="new"&&e.jsx(ae,{open:!0,title:`Edit ${g.name}`,submitLabel:"Simpan",initial:We(g),onClose:()=>k(null),onSubmit:t=>I(g,t)}),E]})}export{Me as VpsScreen,Ve as hardenedLabel,ie as isReachable,re as vpsFormToBody};
@@ -1,2 +1,2 @@
1
- import{j as t,I as v,f as W}from"./index-BHI_f9DD.js";import{R as g}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";function F(s,n=[]){const i={path:"",kids:[]},r=(o,p)=>{let e=i;const c=o.split("/").filter(Boolean);c.forEach((a,x)=>{const y=p&&x===c.length-1,m=e.path?e.path+"/"+a:a;let d=e.kids.find(u=>u.name===a&&u.leaf===y);d||(d={name:a,path:m,kids:[],leaf:y},e.kids.push(d)),e=d})};for(const o of s)r(o,!0);for(const o of n)r(o,!1);const l=o=>{o.kids.sort((p,e)=>p.leaf===e.leaf?p.name.localeCompare(e.name):p.leaf?1:-1),o.kids.forEach(l)};return l(i),i.kids}const j={A:"var(--leaf-600)",M:"var(--brass-600)",D:"var(--clay-500)"};function k({node:s,selected:n,onSelect:i,depth:r=0,meta:l,defaultOpen:o=!1,dirSelected:p,onSelectDir:e,ignored:c,onExpand:a}){const[x,y]=g.useState(o),[m,d]=g.useState(!1),u=c!=null&&c.has(s.path)?.62:1;if(s.leaf){const f=s.path===n,h=l==null?void 0:l[s.path];return t.jsxs("button",{onClick:()=>i(s.path),style:{display:"flex",alignItems:"center",gap:8,width:"100%",padding:"5px 8px",paddingLeft:22+r*12,border:"none",cursor:"pointer",textAlign:"left",background:f?"var(--brass-100)":"transparent",opacity:u},children:[h?t.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:12,fontWeight:700,color:j[h.status]},children:h.status}):t.jsx(v,{name:"file-text",size:13,color:f?"var(--brass-700)":"var(--text-subtle)"}),t.jsx("span",{style:{flex:1,minWidth:0,fontFamily:"var(--font-mono)",fontSize:12,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",color:f?"var(--brass-700)":"var(--text-body)",fontWeight:f?600:400},children:s.name}),h&&!h.binary&&t.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontSize:11},children:[t.jsxs("span",{style:{color:"var(--leaf-600)"},children:["+",h.add]})," ",t.jsxs("span",{style:{color:"var(--clay-500)"},children:["−",h.del]})]})]})}const b=!!e&&s.path===p,w=!!a&&s.kids.length===0;async function z(){e==null||e(s.path);const f=!x;if(y(f),f&&w&&!m){d(!0);try{await(a==null?void 0:a(s.path))}finally{d(!1)}}}return t.jsxs("div",{children:[t.jsxs("button",{onClick:()=>void z(),style:{display:"flex",alignItems:"center",gap:8,width:"100%",padding:"5px 6px",paddingLeft:6+r*12,border:"none",background:b?"var(--brass-100)":"transparent",cursor:"pointer",textAlign:"left",opacity:u},children:[t.jsx(v,{name:x?"chevron-down":"chevron-right",size:14,color:"var(--text-subtle)"}),t.jsx(v,{name:"folder",size:15,color:b?"var(--brass-700)":"var(--brass-500)"}),t.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontSize:12.5,color:b?"var(--brass-700)":"var(--text-strong)",fontWeight:b?700:500},children:[s.name,"/"]}),m&&t.jsx("span",{style:{fontSize:11,color:"var(--text-subtle)"},children:"memuat…"})]}),x&&s.kids.map(f=>t.jsx(k,{node:f,selected:n,onSelect:i,depth:r+1,meta:l,defaultOpen:o,dirSelected:p,onSelectDir:e,ignored:c,onExpand:a},f.path)),x&&!m&&s.kids.length===0&&t.jsx("div",{style:{padding:"4px 8px",paddingLeft:28+r*12,fontSize:11.5,color:"var(--text-subtle)"},children:"kosong"})]})}function S({cf:s,selected:n,onSelect:i}){const r=s.path===n;return t.jsxs("button",{onClick:()=>i(s.path),style:{display:"flex",alignItems:"center",gap:8,width:"100%",padding:"5px 10px",border:"none",cursor:"pointer",textAlign:"left",background:r?"var(--brass-100)":"transparent"},children:[t.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:12,fontWeight:700,color:j[s.status]},children:s.status}),t.jsx("span",{style:{flex:1,minWidth:0,fontFamily:"var(--font-mono)",fontSize:12,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",color:r?"var(--brass-700)":"var(--text-body)"},children:s.path}),!s.binary&&t.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontSize:11},children:[t.jsxs("span",{style:{color:"var(--leaf-600)"},children:["+",s.add]})," ",t.jsxs("span",{style:{color:"var(--clay-500)"},children:["−",s.del]})]})]})}function T({label:s,changed:n,selected:i,onSelect:r,view:l,onView:o,emptyText:p="Tak ada file berubah."}){const e=g.useMemo(()=>F(n.map(a=>a.path)),[n]),c=g.useMemo(()=>Object.fromEntries(n.map(a=>[a.path,a])),[n]);return t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"hn-eyebrow",style:{display:"flex",alignItems:"center",gap:6,padding:"6px 8px"},children:[t.jsxs("span",{style:{flex:1},children:[s," · ",n.length]}),n.length>0&&["list","tree"].map(a=>t.jsx("button",{"aria-label":`${a==="list"?"List":"Tree"} ${s}`,onClick:()=>o(a),style:{display:"flex",padding:3,border:"none",cursor:"pointer",borderRadius:4,background:l===a?"var(--brass-100)":"transparent"},children:t.jsx(v,{name:a==="list"?"list":"folder-tree",size:14,color:l===a?"var(--brass-700)":"var(--text-subtle)"})},a))]}),n.length===0?t.jsx("div",{style:{padding:"4px 10px",fontSize:12,color:"var(--text-subtle)"},children:p}):l==="tree"?e.map(a=>t.jsx(k,{node:a,selected:i,onSelect:r,meta:c,defaultOpen:!0},a.path)):n.map(a=>t.jsx(S,{cf:a,selected:i,onSelect:r},a.path))]})}function I({diff:s,emptyTitle:n="Tidak ada perubahan pada file ini",emptyHint:i}){return s?t.jsx("pre",{style:{margin:0,fontFamily:"var(--font-mono)",fontSize:12.5,lineHeight:1.6},children:s.split(`
1
+ import{j as t,I as v,f as W}from"./index-Bd9gXx1g.js";import{R as g}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";function F(s,n=[]){const i={path:"",kids:[]},r=(o,p)=>{let e=i;const c=o.split("/").filter(Boolean);c.forEach((a,x)=>{const y=p&&x===c.length-1,m=e.path?e.path+"/"+a:a;let d=e.kids.find(u=>u.name===a&&u.leaf===y);d||(d={name:a,path:m,kids:[],leaf:y},e.kids.push(d)),e=d})};for(const o of s)r(o,!0);for(const o of n)r(o,!1);const l=o=>{o.kids.sort((p,e)=>p.leaf===e.leaf?p.name.localeCompare(e.name):p.leaf?1:-1),o.kids.forEach(l)};return l(i),i.kids}const j={A:"var(--leaf-600)",M:"var(--brass-600)",D:"var(--clay-500)"};function k({node:s,selected:n,onSelect:i,depth:r=0,meta:l,defaultOpen:o=!1,dirSelected:p,onSelectDir:e,ignored:c,onExpand:a}){const[x,y]=g.useState(o),[m,d]=g.useState(!1),u=c!=null&&c.has(s.path)?.62:1;if(s.leaf){const f=s.path===n,h=l==null?void 0:l[s.path];return t.jsxs("button",{onClick:()=>i(s.path),style:{display:"flex",alignItems:"center",gap:8,width:"100%",padding:"5px 8px",paddingLeft:22+r*12,border:"none",cursor:"pointer",textAlign:"left",background:f?"var(--brass-100)":"transparent",opacity:u},children:[h?t.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:12,fontWeight:700,color:j[h.status]},children:h.status}):t.jsx(v,{name:"file-text",size:13,color:f?"var(--brass-700)":"var(--text-subtle)"}),t.jsx("span",{style:{flex:1,minWidth:0,fontFamily:"var(--font-mono)",fontSize:12,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",color:f?"var(--brass-700)":"var(--text-body)",fontWeight:f?600:400},children:s.name}),h&&!h.binary&&t.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontSize:11},children:[t.jsxs("span",{style:{color:"var(--leaf-600)"},children:["+",h.add]})," ",t.jsxs("span",{style:{color:"var(--clay-500)"},children:["−",h.del]})]})]})}const b=!!e&&s.path===p,w=!!a&&s.kids.length===0;async function z(){e==null||e(s.path);const f=!x;if(y(f),f&&w&&!m){d(!0);try{await(a==null?void 0:a(s.path))}finally{d(!1)}}}return t.jsxs("div",{children:[t.jsxs("button",{onClick:()=>void z(),style:{display:"flex",alignItems:"center",gap:8,width:"100%",padding:"5px 6px",paddingLeft:6+r*12,border:"none",background:b?"var(--brass-100)":"transparent",cursor:"pointer",textAlign:"left",opacity:u},children:[t.jsx(v,{name:x?"chevron-down":"chevron-right",size:14,color:"var(--text-subtle)"}),t.jsx(v,{name:"folder",size:15,color:b?"var(--brass-700)":"var(--brass-500)"}),t.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontSize:12.5,color:b?"var(--brass-700)":"var(--text-strong)",fontWeight:b?700:500},children:[s.name,"/"]}),m&&t.jsx("span",{style:{fontSize:11,color:"var(--text-subtle)"},children:"memuat…"})]}),x&&s.kids.map(f=>t.jsx(k,{node:f,selected:n,onSelect:i,depth:r+1,meta:l,defaultOpen:o,dirSelected:p,onSelectDir:e,ignored:c,onExpand:a},f.path)),x&&!m&&s.kids.length===0&&t.jsx("div",{style:{padding:"4px 8px",paddingLeft:28+r*12,fontSize:11.5,color:"var(--text-subtle)"},children:"kosong"})]})}function S({cf:s,selected:n,onSelect:i}){const r=s.path===n;return t.jsxs("button",{onClick:()=>i(s.path),style:{display:"flex",alignItems:"center",gap:8,width:"100%",padding:"5px 10px",border:"none",cursor:"pointer",textAlign:"left",background:r?"var(--brass-100)":"transparent"},children:[t.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:12,fontWeight:700,color:j[s.status]},children:s.status}),t.jsx("span",{style:{flex:1,minWidth:0,fontFamily:"var(--font-mono)",fontSize:12,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",color:r?"var(--brass-700)":"var(--text-body)"},children:s.path}),!s.binary&&t.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontSize:11},children:[t.jsxs("span",{style:{color:"var(--leaf-600)"},children:["+",s.add]})," ",t.jsxs("span",{style:{color:"var(--clay-500)"},children:["−",s.del]})]})]})}function T({label:s,changed:n,selected:i,onSelect:r,view:l,onView:o,emptyText:p="Tak ada file berubah."}){const e=g.useMemo(()=>F(n.map(a=>a.path)),[n]),c=g.useMemo(()=>Object.fromEntries(n.map(a=>[a.path,a])),[n]);return t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"hn-eyebrow",style:{display:"flex",alignItems:"center",gap:6,padding:"6px 8px"},children:[t.jsxs("span",{style:{flex:1},children:[s," · ",n.length]}),n.length>0&&["list","tree"].map(a=>t.jsx("button",{"aria-label":`${a==="list"?"List":"Tree"} ${s}`,onClick:()=>o(a),style:{display:"flex",padding:3,border:"none",cursor:"pointer",borderRadius:4,background:l===a?"var(--brass-100)":"transparent"},children:t.jsx(v,{name:a==="list"?"list":"folder-tree",size:14,color:l===a?"var(--brass-700)":"var(--text-subtle)"})},a))]}),n.length===0?t.jsx("div",{style:{padding:"4px 10px",fontSize:12,color:"var(--text-subtle)"},children:p}):l==="tree"?e.map(a=>t.jsx(k,{node:a,selected:i,onSelect:r,meta:c,defaultOpen:!0},a.path)):n.map(a=>t.jsx(S,{cf:a,selected:i,onSelect:r},a.path))]})}function I({diff:s,emptyTitle:n="Tidak ada perubahan pada file ini",emptyHint:i}){return s?t.jsx("pre",{style:{margin:0,fontFamily:"var(--font-mono)",fontSize:12.5,lineHeight:1.6},children:s.split(`
2
2
  `).map((r,l)=>{const o=r.startsWith("+")&&!r.startsWith("+++"),p=r.startsWith("-")&&!r.startsWith("---"),e=r.startsWith("@@"),c=o?"var(--leaf-600)":p?"var(--clay-600)":e?"var(--brass-700)":"var(--text-body)",a=o?"color-mix(in srgb, var(--leaf-500) 10%, transparent)":p?"color-mix(in srgb, var(--clay-500) 10%, transparent)":"transparent";return t.jsx("div",{style:{color:c,background:a,padding:"0 12px",whiteSpace:"pre-wrap",wordBreak:"break-word"},children:r||" "},l)})}):t.jsx(W,{kind:"empty",icon:"check",title:n,hint:i})}export{T as C,I as D,k as T,F as b};