hanoman 0.3.2 → 0.4.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 (25) hide show
  1. package/dist/build-info.json +3 -3
  2. package/dist/cli.js +120 -8
  3. package/dist/server.js +1435 -797
  4. package/package.json +1 -1
  5. package/prisma/migrations/20260914120000_agent_invocation_phase/migration.sql +3 -0
  6. package/prisma/schema.prisma +3 -0
  7. package/web/assets/{ChangelogScreen-D_-RmJkz.js → ChangelogScreen-aqsJmmfe.js} +1 -1
  8. package/web/assets/{DalangHanomanScreen-pVfnLx9z.js → DalangHanomanScreen-D3rNURz7.js} +1 -1
  9. package/web/assets/{DocPreviewModal-ZFjISCL0.js → DocPreviewModal-B7r_7p8N.js} +1 -1
  10. package/web/assets/{DocsWorkspace-Vp_vik3v.js → DocsWorkspace-_w6pncu9.js} +1 -1
  11. package/web/assets/{IdeScreen-DQSRs3fr.js → IdeScreen-etZ2QyO-.js} +1 -1
  12. package/web/assets/{LeadScreen-Bv5LiudD.js → LeadScreen-Bo0K2-ML.js} +1 -1
  13. package/web/assets/{ReviewScreen-Cime4Tci.js → ReviewScreen-lRf2FW30.js} +1 -1
  14. package/web/assets/{SchedulerScreen-DKmRNbTs.js → SchedulerScreen-D75twy4J.js} +1 -1
  15. package/web/assets/SettingsScreen-rMIR22vv.js +62 -0
  16. package/web/assets/{TeamScreen-5ugoXsOv.js → TeamScreen-nsttkE2J.js} +1 -1
  17. package/web/assets/TerminalScreen-BG9vRE1-.js +9 -0
  18. package/web/assets/{TriageScreen-BajACF5K.js → TriageScreen-7eM8gjr_.js} +1 -1
  19. package/web/assets/{VpsScreen-C7muNRX5.js → VpsScreen-C29j52Tu.js} +1 -1
  20. package/web/assets/{diff-view-CsZPBznT.js → diff-view-RZNZ9Nz6.js} +1 -1
  21. package/web/assets/{index-DI7G_sit.js → index-BHI_f9DD.js} +192 -192
  22. package/web/assets/{live-DVDstDzi.js → live-CniaVDeP.js} +1 -1
  23. package/web/index.html +1 -1
  24. package/web/assets/SettingsScreen-Bh8XhyVQ.js +0 -62
  25. package/web/assets/TerminalScreen-DsAn5dlH.js +0 -9
@@ -0,0 +1,9 @@
1
+ import{j as t,d as st,e as _,A as Jt,M as Be,S as pe,G as Qt,J as Lt,f as ot,B as tt,I as ve,w as Zt,D as en,a as re,K as tn,N as nn,O as ht,Q as gt,c as Xe,U as rn,V as an,W as sn,X as on,Y as ln,Z as cn,_ as $e,$ as Nt,a0 as lt,a1 as un,a2 as dn,a3 as nt,h as Ne,a4 as Dt,a5 as pn,a6 as fn,a7 as mn,g as Ve,a8 as Bt,l as hn,a9 as xt,x as gn,aa as Je,p as xn,ab as bn,ac as De,ad as vn,ae as bt,af as yn,ag as kn}from"./index-BHI_f9DD.js";import{R as l,r as K}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import{D as jn,o as wn}from"./xterm-3VOAfa_q.js";function ct(e){return e.endedAt?e.endedReason==="reconciled"?"interrupted":e.exitCode===null||e.exitCode===0?"completed":"failed":"running"}const Sn=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"),Cn=e=>e.length>0&&e.replace(Sn,"")==="";function In(e,n){if(e.type!=="keydown")return null;const a=e.key.toLowerCase();return e.metaKey||e.ctrlKey&&e.shiftKey?a==="c"?n?"copy":null:a==="v"?"paste":null:null}const En=new Set(["image/png","image/jpeg","image/webp"]);function vt(e){return(e!=null&&e.files?Array.from(e.files):[]).filter(a=>En.has(a.type))}function Tn(e){return e!=null&&e.types?Array.from(e.types).includes("Files"):!1}const Rn=96,zn=50,An=2,Ln=2;function Nn(e,n,a){if(!Number.isFinite(e)||e<=0)return n;const i=a+An,s=Math.floor((e-Rn-zn-Ln*i)/i);return s>=n?n:Math.max(0,s-1)}const Dn=/enter to select/i,Bn=/to navigate/i,$n=/^\s*[❯>*]?\s*(\d)\.\s/;function Mn(e,n){var s;const a=e.join(`
2
+ `);if(!Dn.test(a)||!Bn.test(a))return null;const i=e[n];return i?((s=$n.exec(i))==null?void 0:s[1])??null:null}const $t=10,Mt=24,ut=13,Fn=15;function rt(e){return Number.isFinite(e)?Math.min(Mt,Math.max($t,Math.round(e))):ut}const Pn=[{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"}],On=/[\x00-\x1f\x7f]/;function dt(e){return!e||On.test(e)?"control":[...e].length>1?"bulk":"text"}function Ft(e){return e?`\x1B[4m${e}\x1B[24m`:""}function Ue(e){return e>0?`\x1B[${e}D\x1B[K`:""}const Wn=500,_n=5e3,Hn=64,Kn=2;function Pt(){return{pending:"",since:null,altScreen:!1,suspendedUntil:0,typed:"",unechoed:"",gen:0,parsed:0}}const qn=e=>e.gen!==e.parsed;function Gn(e,n){return{...e,altScreen:n}}const Un=/(password|passphrase|pass|pin)\s*(?:for\s+\S+\s*)?:\s*$/i;function Yn(e){return Un.test(e)}function Ot(e,n,a,i,s){return!s||!a.deliverable||e.altScreen||i<e.suspendedUntil||dt(n)!=="text"||a.cursorX+Kn+1>a.cols||a.line.slice(a.cursorX).trim().length>0?!1:!Yn(a.line.trimEnd())}function Xn(e,n){for(let a=n.length;a>0;a-=1)if(e.endsWith(n.slice(0,a)))return a;return 0}function Vn(e,n,a,i,s){const d=dt(n);if(d==="text"&&qn(e)&&s&&a.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(!Ot(e,n,a,i,s)){const g=i<e.suspendedUntil&&d==="text"?(e.typed+n).slice(-32):"";return g===e.typed&&!e.unechoed?{state:e,write:""}:{state:{...e,typed:g,unechoed:""},write:""}}return{state:{...e,pending:e.pending+n,unechoed:e.unechoed+n,since:null,typed:""},write:Ft(n)}}function Jn(e,n){if(!n)return!1;const a=n.slice(-Math.min(2,n.length));return e.endsWith(a)}function Qn(e,n,a){return a>=e.suspendedUntil?e.typed?{...e,typed:""}:e:Jn(n,e.typed)?{...e,suspendedUntil:0,typed:""}:e}function Zn(e,n,a){return{state:{...e,pending:"",since:null,gen:e.gen+1},write:Ue(e.pending.length)+n}}function er(e,n,a,i,s){if(n!==e.gen)return{state:e,write:""};const d=a.line.slice(0,a.cursorX),y=Qn({...e,parsed:n},d,i);if(!y.unechoed)return{state:y,write:""};const g=y.unechoed.slice(Xn(d,y.unechoed));if(!g)return{state:{...y,unechoed:""},write:""};const v=nr({...y,pending:""},g,a,i,s);return v.write?{state:{...v.state,unechoed:g},write:v.write}:{state:{...y,pending:"",unechoed:""},write:""}}function tr(e,n){return!e.pending||e.since!==null?e:{...e,since:n}}function nr(e,n,a,i,s){if(!n)return{state:e,write:""};const d=[...n];for(let y=0;y<d.length;y+=1){const g={...a,cursorX:a.cursorX+y};if(!Ot({...e},d[y],g,i,s))return{state:e,write:""}}return{state:{...e,pending:n,since:null},write:Ft(n)}}function rr(e,n){return!e.pending||e.since===null||n<e.since+Wn?{state:e,write:"",missed:!1}:{state:{...e,pending:"",since:null,suspendedUntil:n+_n,typed:"",unechoed:""},write:Ue(e.pending.length),missed:!0}}function yt(e){const n=((e==null?void 0:e.gen)??0)+1;return{...Pt(),gen:n,parsed:n}}const ar=16;function ir(e){let n="",a;const i=()=>{if(a&&(clearTimeout(a),a=void 0),!n)return;const s=n;n="",e(s)};return{push(s,d){if(!d||dt(s)!=="text"){i(),s&&e(s);return}n+=s,a||(a=setTimeout(i,ar))},flush:i,dispose(){i()}}}const sr=250,or=512,lr={"\x1B":"\\e","\r":"\\r","\n":"\\n"," ":"\\t","\b":"\\b","":"\\x7f"};function kt(e){let n="";for(const a of e){const i=lr[a];if(i){n+=i;continue}const s=a.codePointAt(0);n+=s<32||s===127?`\\x${s.toString(16).padStart(2,"0")}`:a}return n}function cr(e){const n=e.batchMs??sr,a=e.max??or;let i=null,s=[],d,y=!1;const g=()=>{if(d&&(clearTimeout(d),d=void 0),!s.length)return;const v=s;s=[],e.send(v)};return{record(v,R,x){if(y)return;const c=e.now();i===null&&(i=c);const j={t:c-i,k:v,v:R};x!==void 0&&(j.n=x),s.push(j),s.length>a&&(s=s.slice(s.length-a)),d||(d=setTimeout(g,n))},flush:g,dispose(){g(),y=!0}}}const ur="",dr=350,pr=1e3;function pt(){return{text:"",sentPrefix:""}}function fr(e,n){const a=[...e],i=[...n];let s=0;for(;s<a.length&&s<i.length&&a[s]===i[s];)s+=1;return s}function ft(e,n){const a=fr(e,n);return ur.repeat([...e].length-a)+[...n].slice(a).join("")}function mr(e,n){return{...e,text:n}}function hr(e){return{state:{...e,sentPrefix:e.text},send:ft(e.sentPrefix,e.text)}}function gr(e){return{state:pt(),send:ft(e.sentPrefix,e.text)+"\r"}}function xr(e){return{state:pt(),send:ft(e.sentPrefix,e.text)}}function br(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 vr({sessionId:e,send:n,external:a,linkState:i,queue:s}){const[d,y]=l.useState(""),g=l.useRef(pt()),v=l.useRef(n);v.current=n;const R=l.useRef(void 0),x=l.useRef(void 0),c=()=>{clearTimeout(R.current),R.current=void 0,clearTimeout(x.current),x.current=void 0},j=T=>{c(),g.current=T.state,T.send&&v.current(T.send)},A=()=>j(hr(g.current));a.current=()=>{j(xr(g.current)),y("")},l.useEffect(()=>()=>{a.current=()=>{}},[a]),l.useEffect(()=>c,[]);const C=T=>{g.current=mr(g.current,T),y(T),clearTimeout(R.current),R.current=setTimeout(A,dr),x.current||(x.current=setTimeout(A,pr))},k=()=>{j(gr(g.current)),y("")},m=br(i,s);return t.jsxs("div",{className:"hn-terminal-composer",children:[t.jsx(st,{size:"lg",mono:!0,value:d,"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:T=>C(T.target.value),onBlur:()=>A(),onKeyDown:T=>{T.key!=="Enter"||T.nativeEvent.isComposing||(T.preventDefault(),k())}}),m&&t.jsx("span",{"data-testid":"terminal-composer-status",className:`hn-terminal-composer-status hn-terminal-composer-status--${m.kind}`,children:m.text})]})}const Wt=[500,1e3,2e3,4e3,8e3,8e3,8e3,8e3,8e3,8e3,8e3,8e3],jt=Wt.length,yr=4096,kr=/[\r\n]/;function _t({sessionId:e,onExit:n,onPhases:a,fontSize:i=ut,showKeys:s=!1,predict:d=!0,diag:y=!1}){const g=l.useRef(null),v=l.useRef(i);v.current=i;const R=l.useRef(d);R.current=d;const x=l.useRef(y);x.current=y;const c=l.useRef(null),j=l.useRef(n);j.current=n;const A=l.useRef(a);A.current=a;const[C,k]=l.useState({state:"connecting"}),[m,T]=l.useState({n:0,held:!1,full:!1}),E=l.useRef(()=>{}),w=l.useRef(()=>{}),P=l.useRef(()=>{}),S=l.useRef(()=>{}),B=l.useRef(()=>{}),p=l.useRef(()=>{});return l.useEffect(()=>{const u=g.current;if(!u)return;const D=getComputedStyle(document.documentElement),M=(f,z)=>D.getPropertyValue(f).trim()||z,b=new jn({fontFamily:M("--font-mono","monospace"),fontSize:rt(v.current),cursorBlink:!0,macOptionClickForcesSelection:!0,theme:{background:M("--term-bg","#1c1810"),foreground:M("--term-fg","#e9e0cd")}}),G=new wn;b.loadAddon(G),b.open(u);const U=()=>{const f=u.getBoundingClientRect();return f.width>0&&f.height>0?f:null};U()&&G.fit();let N,Y=!1,ae=0,ie,X=!1;const le=f=>{(N==null?void 0:N.readyState)===WebSocket.OPEN&&N.send(JSON.stringify(f))};c.current={term:b,fit:G,send:le};const Q=cr({now:()=>Date.now(),send:f=>le({t:"diag",ev:f})}),Z=(f,z,r)=>{x.current&&Q.record(f,z,r)};let V="",J=!1,ee=!1,se=0,ce=0,fe=!1;const ue=new Map,H=f=>{if(se+=1,ce+=1,x.current){if(ue.size>256)for(const z of[...ue.keys()].slice(0,128))ue.delete(z);ue.set(se,Date.now())}le({t:"in",d:f,seq:se})},O=()=>T({n:V.length,held:J,full:ee}),Fe=f=>{if(!J&&!V&&(N==null?void 0:N.readyState)===WebSocket.OPEN){H(f);return}if(!(fe||Cn(f))){if(V.length+f.length>yr){ee=!0,O();return}V+=f,O()}};let I=Pt();const q=ir(Fe),ye=f=>q.push(f,!1);w.current=ye;const te=f=>{B.current(),ye(f)};p.current=te;const de=()=>{var z;const f=b.buffer.active;return{cursorX:f.cursorX,cols:b.cols,deliverable:!fe&&!ee,line:((z=f.getLine(f.viewportY+f.cursorY))==null?void 0:z.translateToString(!0))??""}},ke=()=>{ce===0&&(N==null?void 0:N.readyState)===WebSocket.OPEN&&(I=tr(I,Date.now()))},je=()=>{if(!V||(N==null?void 0:N.readyState)!==WebSocket.OPEN){O();return}const f=V;V="",ee=!1,O(),H(f)},Ye=()=>{if(q.flush(),!V){O();return}if(kr.test(V)){J=!0,O();return}je()};P.current=()=>{J=!1,je()},S.current=()=>{V="",J=!1,ee=!1,O()};const ze=f=>{B.current();const z=I.pending.length>0;Z("data",kt(f));const r=de(),o=Vn(I,f,r,Date.now(),R.current);I=o.state,o.write?b.write(o.write):o.deferred?Z("pred","tangguh: frame server in flight"):Z("pred",`tolak cx=${r.cursorX}/${r.cols} alt=${I.altScreen?1:0} deliverable=${r.deliverable?1:0} suspend=${Math.max(0,I.suspendedUntil-Date.now())}`),q.push(f,z||o.write.length>0||o.deferred===!0)},Se=setInterval(()=>{const f=rr(I,Date.now());I=f.state,f.write&&b.write(f.write)},100),me=()=>{_.issueWsTicket(`terminal:${e}`).then(({ticket:f})=>{if(Y)return;const z=location.protocol==="https:"?"wss:":"ws:",r=new WebSocket(`${z}//${location.host}${Jt.terminalWs(e)}`,[`hanoman-ticket.${f}`]);N=r,r.onopen=()=>{ae=0,se=0,ce=0;const o=Ue(I.pending.length);o&&b.write(o),I=yt(I),k({state:"open"}),U()&&((typeof window.matchMedia!="function"||window.matchMedia("(hover: hover) and (pointer: fine)").matches)&&b.focus(),le({t:"resize",cols:b.cols,rows:b.rows})),Ye()},r.onmessage=o=>{var L;const h=JSON.parse(o.data);if(h.t==="data"){const F=Zn(I,h.d??"");I=F.state;const oe=I.gen;b.write(F.write,()=>{if(Y)return;const ne=er(I,oe,de(),Date.now(),R.current);I=ne.state,ne.write&&b.write(ne.write),ke()}),ke()}else if(h.t==="ack"){if(ce=Math.max(0,ce-1),typeof h.seq=="number"){const F=ue.get(h.seq);F!==void 0&&(ue.delete(h.seq),Z("ack",String(h.seq),Date.now()-F))}ke()}else h.t==="phase"?(L=A.current)==null||L.call(A,h.phases??[],h.complete===!0):h.t==="alt"?I=Gn(I,h.on===!0):h.t==="exit"&&(X=!0,b.write(`\r
3
+ \x1B[33m— sesi berakhir (exit ${h.code}) —\x1B[0m\r
4
+ `),j.current(h.code??0))},r.onclose=o=>{if(!(Y||X)){if(o.code===4004){fe=!0;const h=Ue(I.pending.length);h&&b.write(h),I=yt(I),V="",J=!1,ee=!1,O(),k({state:"gone"});return}Pe()}},r.onerror=()=>{}}).catch(()=>{Y||(b.write(`\r
5
+ \x1B[31mWebSocket admission gagal\x1B[0m\r
6
+ `),Pe())})},Pe=()=>{if(ae>=jt){k({state:"lost"});return}const f=Wt[ae];ae+=1,k({state:"retrying",attempt:ae}),ie=setTimeout(me,f)};E.current=()=>{Y||(clearTimeout(ie),ae=0,k({state:"retrying",attempt:1}),me())},me(),b.attachCustomKeyEventHandler(f=>{var r,o;const z=In(f,b.hasSelection());return z==="copy"?((r=navigator.clipboard)==null||r.writeText(b.getSelection()),!1):z==="paste"?((o=navigator.clipboard)==null||o.readText().then(h=>{h&&te(h)}),!1):!0}),b.attachCustomWheelEventHandler(f=>{if(!f.shiftKey)return!0;const z=U();if(!z||b.rows<=0)return!0;const r=z.height/b.rows,o=Math.trunc(f.deltaY/r)||Math.sign(f.deltaY);return o&&b.scrollLines(o),!1});const Oe=b.onData(ze),$=b.textarea,Ae=f=>Z("key",f.key,f.keyCode),he=f=>Z("comp",`${f.type}:${kt(f.data??"")}`);$==null||$.addEventListener("keydown",Ae),$==null||$.addEventListener("compositionstart",he),$==null||$.addEventListener("compositionupdate",he),$==null||$.addEventListener("compositionend",he);let ge=null,xe=0,Ce=!1;const we=()=>{ge=null,xe=0,Ce=!1},We=f=>{if(f.touches.length!==1){we();return}ge=f.touches[0].clientY,xe=0,Ce=!1},_e=f=>{if(ge===null||f.touches.length!==1){we();return}const z=U();if(!z||b.rows<=0)return;const r=f.touches[0].clientY;xe+=ge-r,ge=r;const o=z.height/b.rows,h=Math.trunc(xe/o);h!==0&&(b.scrollLines(h),xe-=h*o,Ce=!0),f.preventDefault()},He=f=>{var ne,Ee;const z=ge!==null&&!Ce,r=((Ee=(ne=f.changedTouches)==null?void 0:ne[0])==null?void 0:Ee.clientY)??ge;if(we(),!z||r===null||r===void 0)return;const o=U();if(!o||b.rows<=0)return;const h=Math.floor((r-o.top)/(o.height/b.rows)),L=b.buffer.active,F=Array.from({length:b.rows},(Yr,Vt)=>{var mt;return((mt=L.getLine(L.viewportY+Vt))==null?void 0:mt.translateToString(!0))??""}),oe=Mn(F,h);oe&&te(oe)},Ie=async f=>{for(const z of f)try{const{path:r}=await _.uploadTerminalAttachment(e,z);te(`${r} `)}catch(r){b.write(`\r
7
+ \x1B[31mlampiran gagal: ${r.message}\x1B[0m\r
8
+ `)}},W=f=>{const z=vt(f.clipboardData);z.length&&(f.preventDefault(),Ie(z))},Le=f=>{Tn(f.dataTransfer)&&f.preventDefault()},Ke=f=>{const z=vt(f.dataTransfer);z.length&&(f.preventDefault(),Ie(z))};u.addEventListener("paste",W),u.addEventListener("dragover",Le),u.addEventListener("drop",Ke),u.addEventListener("touchstart",We,{passive:!0}),u.addEventListener("touchmove",_e,{passive:!1}),u.addEventListener("touchend",He,{passive:!0}),u.addEventListener("touchcancel",we,{passive:!0});const qe=new ResizeObserver(f=>{var r;const z=((r=f[0])==null?void 0:r.contentRect)??u.getBoundingClientRect();z.width<=0||z.height<=0||(G.fit(),le({t:"resize",cols:b.cols,rows:b.rows}))});return qe.observe(u),()=>{Y=!0,clearTimeout(ie),E.current=()=>{},w.current=()=>{},p.current=()=>{},P.current=()=>{},S.current=()=>{},c.current=null,u.removeEventListener("paste",W),u.removeEventListener("dragover",Le),u.removeEventListener("drop",Ke),u.removeEventListener("touchstart",We),u.removeEventListener("touchmove",_e),u.removeEventListener("touchend",He),u.removeEventListener("touchcancel",we),qe.disconnect(),clearInterval(Se),q.dispose(),Q.dispose(),$==null||$.removeEventListener("keydown",Ae),$==null||$.removeEventListener("compositionstart",he),$==null||$.removeEventListener("compositionupdate",he),$==null||$.removeEventListener("compositionend",he),Oe.dispose(),N==null||N.close(),b.dispose()}},[e]),l.useEffect(()=>{const u=c.current,D=g.current;if(!u||!D)return;const M=rt(i);if(u.term.options.fontSize===M)return;u.term.options.fontSize=M;const b=D.getBoundingClientRect();b.width<=0||b.height<=0||(u.fit.fit(),u.send({t:"resize",cols:u.term.cols,rows:u.term.rows}))},[i]),l.useEffect(()=>{const u=c.current,D=g.current;if(!u||!D)return;const M=D.getBoundingClientRect();M.width<=0||M.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:[(C.state!=="open"&&C.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:C.state==="retrying"||m.held?"var(--status-warn-tint)":"var(--status-err-tint)",color:"var(--text-body)"},children:[C.state==="retrying"&&t.jsxs("span",{children:["menyambung ulang… (",C.attempt,"/",jt,")"]}),C.state==="gone"&&t.jsx("span",{children:"sesi tidak ditemukan di tmux"}),C.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:()=>E.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:()=>P.current(),children:"Kirim"}),t.jsx("button",{type:"button",className:"hn-terminal-action hn-terminal-action--text",onClick:()=>S.current(),children:"Buang"})]}),m.full&&t.jsx("span",{"data-testid":"terminal-queue-full",children:"antrean penuh"})]}),t.jsx("div",{ref:g,"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(vr,{sessionId:e,send:u=>w.current(u),external:B,linkState:C.state,queue:m}),s&&t.jsx(jr,{onKey:u=>p.current(u)})]})}function jr({onKey:e}){return t.jsx("div",{className:"hn-terminal-keys",role:"group","aria-label":"Tombol terminal",children:Pn.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 wt=20;function wr(e,n){if(!n)return"—";const a=new Date(n).getTime()-new Date(e).getTime();if(!Number.isFinite(a)||a<0)return"—";const i=Math.round(a/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 Sr(e){switch(ct(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 Ht=e=>ct(e)==="interrupted"?"—":wr(e.startedAt,e.endedAt),Kt=e=>Lt[e]??e;function Cr({projects:e,onClose:n,onRestart:a}){const[i,s]=l.useState([]),[d,y]=l.useState(0),[g,v]=l.useState(1),[R,x]=l.useState(!1),[c,j]=l.useState(""),[A,C]=l.useState(""),[k,m]=l.useState(""),[T,E]=l.useState(""),[w,P]=l.useState(null);l.useEffect(()=>{const p=setTimeout(()=>E(k.trim()),250);return()=>clearTimeout(p)},[k]),l.useEffect(()=>{v(1)},[c,A,T]),l.useEffect(()=>{let p=!0;return x(!0),_.listSessionHistory({projectId:c||void 0,kind:A||void 0,q:T||void 0,page:g,limit:wt}).then(u=>{p&&(y(u.total),s(u.items))}).catch(()=>{p&&(s([]),y(0))}).finally(()=>{p&&x(!1)}),()=>{p=!1}},[c,A,T,g]);const S=en(d,g,wt),B=p=>{var u;return((u=e.find(D=>D.id===p))==null?void 0:u.name)??p};return t.jsxs(Be,{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(st,{size:"sm",leftIcon:"search",placeholder:"mis. spec-412 atau reverse","aria-label":"Cari riwayat sesi",value:k,onChange:p=>m(p.target.value),style:{flex:"1 1 200px"}}),t.jsx(pe,{size:"sm","aria-label":"Filter project",value:c,onChange:p=>j(p.target.value),options:[{value:"",label:"Semua project"}].concat(e.map(p=>({value:p.id,label:p.name})))}),t.jsx(pe,{size:"sm","aria-label":"Filter jenis",value:A,onChange:p=>C(p.target.value),options:[{value:"",label:"Semua jenis"}].concat(Qt.map(p=>({value:p,label:Lt[p]})))})]}),i.length===0&&!R?t.jsx(ot,{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(p=>{const u=Sr(p);return t.jsx("button",{onClick:()=>P(p),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(p.startedAt).toLocaleString("id-ID")}),t.jsx(tt,{size:"sm",tone:"neutral",children:Kt(p.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:p.title??p.specId??B(p.projectId)}),p.transcriptBytes!==null&&t.jsx(ve,{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:Ht(p)}),t.jsx(tt,{size:"sm",tone:u.tone,children:u.label})]})},p.id)}),R&&t.jsx("div",{style:{padding:"10px 8px",textAlign:"center",fontSize:11,color:"var(--text-subtle)"},children:"memuat…"})]}),t.jsx(Zt,{page:S.page,pageCount:S.pageCount,total:d,from:S.from,to:S.to,onPage:v,unit:"sesi"}),w&&t.jsx(Ir,{row:w,projectName:B(w.projectId),onBack:()=>P(null),onRestart:a})]})}function Ir({row:e,projectName:n,onBack:a,onRestart:i}){const[s,d]=l.useState(null),[y,g]=l.useState("idle");l.useEffect(()=>{if(e.transcriptBytes===null){g("none"),d(null);return}let x=!0;return g("loading"),_.sessionTranscript(e.id).then(c=>{x&&(d(c.text),g("idle"))}).catch(()=>{x&&(d(null),g("error"))}),()=>{x=!1}},[e.id,e.transcriptBytes]);const v=ct(e)==="interrupted",R=[["Project",n],["Sesi",e.sessionId],["Jenis",Kt(e.kind)],["Agen",[e.agent,e.model,e.effort].filter(Boolean).join(" · ")],["Mulai",new Date(e.startedAt).toLocaleString("id-ID")],[v?"Terakhir terlihat hidup":"Selesai",e.endedAt?new Date(e.endedAt).toLocaleString("id-ID"):"berjalan"],...v&&e.reconciledAt?[["Terdeteksi mati",new Date(e.reconciledAt).toLocaleString("id-ID")]]:[],["Durasi",Ht(e)],["Direktori",e.cwd]];return e.specId&&R.splice(1,0,["Backlog",`${e.specId}${e.title?` · ${e.title}`:""}`]),e.branch&&R.push(["Branch",e.branch]),t.jsxs(Be,{open:!0,title:e.title??e.specId??e.sessionId,icon:"history",onClose:a,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:a,children:"Kembali"}),t.jsx("div",{style:{flex:1}}),s&&t.jsx(re,{size:"sm",variant:"secondary",leftIcon:"copy",onClick:()=>{var x;return void((x=navigator.clipboard)==null?void 0:x.writeText(s))},children:"Salin transkrip"}),tn(e.kind)&&t.jsx(re,{size:"sm",leftIcon:"play",onClick:()=>i(e),children:"Mulai lagi"})]}),v&&t.jsxs(nn,{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:R.map(([x,c])=>t.jsxs(l.Fragment,{children:[t.jsx("span",{style:{color:"var(--text-subtle)"},children:x}),t.jsx("span",{style:{fontFamily:"var(--font-mono)",color:"var(--text-body)",wordBreak:"break-all"},children:c})]},x))}),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:v?"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 Er({open:e,projectId:n,projectName:a,onClose:i,onCreated:s}){var P;const[d,y]=l.useState("claude"),[g,v]=l.useState("claude-opus-5"),[R,x]=l.useState("xhigh"),[c,j]=l.useState({claude:{model:"claude-opus-5",effort:"xhigh"},codex:{...ht}}),[A,C]=l.useState(!1),[k,m]=l.useState(null);l.useEffect(()=>{e&&(_.getSettings().then(S=>{const B={claude:{model:S.model,effort:S.effort},codex:{...ht,...S.codex??{}}},p=S.agent==="codex"?"codex":"claude",u=gt(B,p);j(B),y(p),v(u.model),x(u.effort)}).catch(()=>{}),_.getCodexVersion().then(S=>m(S.version)).catch(()=>{}))},[e]);const T=S=>{y(S);const B=gt(c,S);v(B.model),x(B.effort)},E=S=>{v(S),x(B=>d==="codex"?ln(S,B):cn(S,B))};async function w(){C(!0);try{const{id:S}=await _.createTerminal(n,{agent:d,model:g,effort:R});s(S),i()}catch{}finally{C(!1)}}return t.jsxs(Be,{open:e,onClose:i,icon:"plus",eyebrow:a,title:"Sesi baru",footer:t.jsxs(t.Fragment,{children:[t.jsx(re,{variant:"ghost",onClick:i,children:"Batal"}),t.jsx(re,{leftIcon:"play",disabled:A,onClick:()=>void w(),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(Xe,{label:"Agen",hint:"Mesin yang menjalankan sesi ini. Perilaku sesi sama; hanya CLI-nya berbeda.",children:t.jsx(pe,{"aria-label":"Agen",value:d,style:{width:"100%"},options:[{value:"claude",label:"Claude Code"},{value:"codex",label:"Codex CLI"}],onChange:S=>T(S.target.value)})}),t.jsx(Xe,{label:"Model",children:t.jsx(pe,{"aria-label":"Model",value:g,style:{width:"100%"},options:rn(d).map(S=>({value:S.id,label:S.label})),onChange:S=>E(S.target.value)})}),t.jsx(Xe,{label:"Effort",children:t.jsx(pe,{"aria-label":"Effort",value:R,style:{width:"100%"},options:an(d,g).map(S=>({value:S,label:S})),onChange:S=>x(S.target.value)})}),d==="codex"&&sn(g,k)&&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:k}),", sedangkan ",t.jsx("b",{children:g})," butuh ",t.jsx("b",{children:(P=on(g))==null?void 0:P.minClient}),". Sesi tetap boleh dijalankan, tapi modelnya belum tentu dikenali CLI ini."]})]})}const Tr=()=>({rows:1,cols:1,cells:[null]}),St=e=>({...e,rows:e.rows+1,cells:[...e.cells,...Array(e.cols).fill(null)]});function Ct(e){const n=e.cols+1,a=[];for(let i=0;i<e.rows;i++)for(let s=0;s<n;s++)a.push(s<e.cols?e.cells[i*e.cols+s]??null:null);return{rows:e.rows,cols:n,cells:a}}function It(e,n){if(e.rows===1||n<0||n>=e.rows)return e;const a=[...e.cells];return a.splice(n*e.cols,e.cols),{...e,rows:e.rows-1,cells:a}}function Et(e,n){if(e.cols===1||n<0||n>=e.cols)return e;const a=e.cols-1,i=[];for(let s=0;s<e.rows;s++)for(let d=0;d<e.cols;d++)d!==n&&i.push(e.cells[s*e.cols+d]??null);return{rows:e.rows,cols:a,cells:i}}function at(e,n,a){if(n<0||n>=e.cells.length)return e;const i=e.cells.map(s=>a!==null&&s===a?null:s);return i[n]=a,{...e,cells:i}}const Rr=(e,n)=>({...e,cells:e.cells.map(a=>a&&n.has(a)?a:null)}),qt=e=>({id:crypto.randomUUID(),name:e,layout:Tr()});function Tt(){const e=qt("Utama");return{groups:[e],active:e.id}}const Me=e=>e.groups.find(n=>n.id===e.active)??e.groups[0];function zr(e,n){const a=qt(n);return{groups:[...e.groups,a],active:a.id}}const Ar=(e,n,a)=>({...e,groups:e.groups.map(i=>i.id===n?{...i,name:a}:i)});function Lr(e,n){if(e.groups.length===1)return e;const a=e.groups.filter(i=>i.id!==n);return a.length===e.groups.length?e:{groups:a,active:e.active===n?a[0].id:e.active}}const Nr=(e,n)=>e.groups.some(a=>a.id===n)?{...e,active:n}:e;function be(e,n){const a=Me(e);return{...e,groups:e.groups.map(i=>i.id===a.id?{...i,layout:n(i.layout)}:i)}}function it(e,n,a){const i=Me(e),s=a===null?e.groups:e.groups.map(d=>d.id===i.id?d:{...d,layout:at(d.layout,d.layout.cells.indexOf(a),null)});return{...e,groups:s.map(d=>d.id===i.id?{...d,layout:at(d.layout,n,a)}:d)}}function Te(e,n){const a=Me(e).layout.cells.indexOf(null);return a===-1?e:it(e,a,n)}const Dr=(e,n)=>({...e,groups:e.groups.map(a=>({...a,layout:at(a.layout,a.layout.cells.indexOf(n),null)}))}),Rt=e=>new Set(e.groups.flatMap(n=>n.layout.cells.filter(a=>a!==null))),zt=(e,n)=>({...e,groups:e.groups.map(a=>({...a,layout:Rr(a.layout,n)}))}),Gt="hanoman.terminal.workspace",Ut="hanoman.terminal.layout",Re=e=>$e.parse({version:1,groups:e.groups});function Ge(e,n){const a=e.groups,i=n&&a.some(s=>s.id===n)?n:a[0].id;return{groups:a,active:i}}function Br(e){try{const n=JSON.parse(e);if(!n||typeof n!="object")return null;const a=n,i=$e.parse({version:1,groups:a.groups});return{workspace:i,active:typeof a.active=="string"&&i.groups.some(s=>s.id===a.active)?a.active:i.groups[0].id}}catch{return null}}function $r(){try{const e=localStorage.getItem(Gt);if(e)return Br(e);const n=localStorage.getItem(Ut);if(!n)return null;const a=JSON.parse(n),i={id:crypto.randomUUID(),name:"Utama",layout:a};return{workspace:$e.parse({version:1,groups:[i]}),active:i.id}}catch{return null}}function Qe(){try{localStorage.removeItem(Gt),localStorage.removeItem(Ut)}catch{}}const Yt=e=>`hanoman.terminal.workspace.v2.${encodeURIComponent(e)}`;function Mr(e){try{const n=localStorage.getItem(Yt(e));if(!n)return null;const a=JSON.parse(n),i=$e.parse(a.workspace);if(!Number.isInteger(a.revision)||(a.revision??-1)<0)return null;const s=typeof a.active=="string"&&i.groups.some(d=>d.id===a.active)?a.active:i.groups[0].id;return{workspace:i,revision:a.revision,active:s}}catch{return null}}function Ze(e,n){try{const a=$e.parse(n.workspace);if(!Number.isInteger(n.revision)||n.revision<0)return;const i=a.groups.some(s=>s.id===n.active)?n.active:a.groups[0].id;localStorage.setItem(Yt(e),JSON.stringify({workspace:a,revision:n.revision,active:i}))}catch{}}function et(e){if(!(e instanceof lt)||e.status!==409)return null;const n=e.detail;if((n==null?void 0:n.code)!=="revision-conflict")return null;const a=un.safeParse(n.current);return a.success?a.data:null}function Fr(e){const n=K.useRef(null);n.current||(n.current=Tt());const[a,i]=K.useState(n.current),[s,d]=K.useState("loading"),[y,g]=K.useState(null),[v,R]=K.useState(!1),x=K.useRef(a),c=K.useRef(0),j=K.useRef(!1),A=K.useRef(Promise.resolve()),C=K.useRef(0),k=K.useCallback(p=>{x.current=p,i(p)},[]),m=K.useCallback(p=>{j.current=p,R(p)},[]),T=K.useCallback(p=>{const u=A.current.then(p,p);return A.current=u.then(()=>{},()=>{}),u},[]),E=K.useCallback((p,u="ready",D=null,M=x.current.active)=>{const b=p.workspace?Ge(p.workspace,M):Tt();c.current=p.revision,k(b),d(u),g(D),m(!0),p.workspace&&Ze(e,{workspace:p.workspace,revision:p.revision,active:b.active})},[k,m,e]),w=K.useCallback(p=>{const u=Mr(e);u&&(c.current=u.revision,k(Ge(u.workspace,u.active))),m(!1),d("recovering"),g(p instanceof Error?p.message:"Layout server belum tersambung")},[k,m,e]),P=K.useCallback(()=>T(async()=>{try{E(await _.getTerminalWorkspace())}catch(p){w(p)}}),[E,T,w]);K.useEffect(()=>{const p=++C.current;return d("loading"),g(null),m(!1),T(async()=>{try{const u=await _.getTerminalWorkspace();if(p!==C.current)return;if(u.workspace){E(u),Qe();return}const D=$r();if(!D){E(u);return}try{const M=await _.putTerminalWorkspace({baseRevision:u.revision,workspace:D.workspace});if(p!==C.current)return;k(Ge(M.workspace,D.active)),c.current=M.revision,Ze(e,{workspace:M.workspace,revision:M.revision,active:D.active}),Qe(),d("ready"),g(null),m(!0)}catch(M){const b=et(M);b!=null&&b.workspace?(E(b,"conflict","Layout server lebih baru; layout lokal lama tidak diunggah"),Qe()):w(M)}}catch(u){p===C.current&&w(u)}}),()=>{C.current+=1}},[E,T,w,k,m,e]),K.useEffect(()=>{const p=()=>{P()},u=()=>{document.visibilityState==="visible"&&P()};return window.addEventListener("focus",p),document.addEventListener("visibilitychange",u),()=>{window.removeEventListener("focus",p),document.removeEventListener("visibilitychange",u)}},[P]);const S=K.useCallback(p=>T(async()=>{if(!j.current)return!1;const u=p(x.current);let D,M;try{D=Re(u),M=Re(x.current)}catch{return d("conflict"),g("Layout tidak valid dan tidak disimpan"),!1}if(Nt(D,M))return!0;try{return E(await _.putTerminalWorkspace({baseRevision:c.current,workspace:D}),"ready",null,u.active),!0}catch(b){const G=et(b);if(!(G!=null&&G.workspace))return w(b),!1;const U=p(Ge(G.workspace,x.current.active));try{const N=await _.putTerminalWorkspace({baseRevision:G.revision,workspace:Re(U)});return E(N,"conflict","Layout berubah di perangkat lain; perubahan ini diterapkan ulang",U.active),!0}catch(N){if(!et(N)&&!(N instanceof lt&&N.status===409))return w(N),!1;try{E(await _.getTerminalWorkspace(),"conflict","Layout berubah lagi di perangkat lain; state terbaru dimuat")}catch(Y){w(Y)}return!1}}}),[E,T,w]),B=K.useCallback(p=>{const u=Nr(x.current,p);k(u);const D=Re(u);Ze(e,{workspace:D,revision:c.current,active:u.active})},[k,e]);return{workspace:a,status:s,message:y,writable:v,mutate:S,setActive:B,refresh:P}}function Zr({userId:e="test-user",projects:n,backlog:a=[],focusSession:i,onOpenReview:s,onOpenSessionReview:d,titleOf:y,onIntegrate:g,onIntegrateSession:v,specOf:R}){var z;const[x,c]=l.useState([]),[j,A]=l.useState([]),C=Fr(e),{workspace:k,status:m,message:T,writable:E,mutate:w,setActive:P,refresh:S}=C,[B,p]=Ne("terminal","project",((z=n[0])==null?void 0:z.id)??"",xn),u=Dt(),[D,M]=Ne("terminal","fontSize",u?Fn:ut,gn),[b,G]=Ne("terminal","keys",u,Je),[U,N]=Ne("terminal","predict",!0,Je),[Y,ae]=Ne("terminal","diag",!1,Je),ie=r=>M(o=>rt(o+r)),[X,le]=l.useState(!1),[Q,Z]=l.useState(null),[V,J]=l.useState(!1),[ee,se]=l.useState(null),[ce,fe]=l.useState(!1),[ue,H]=l.useState(!1),O=pn(),I=fn()==="mobile",[q,ye]=l.useState(0),[te,de]=l.useState(null),ke=l.useRef(null),[je,Ye]=l.useState(!1);l.useEffect(()=>{_.listTerminals().then(r=>{c(r),Ye(!0)}).catch(()=>{})},[]),l.useEffect(()=>mn(r=>{r.t==="sessions"?c(r.sessions):r.t==="cleanups"&&A(r.cleanups)}),[]),l.useEffect(()=>{if(!je||!E)return;const r=new Set(x.map(h=>h.id)),o=zt(k,r);Nt(Re(o),Re(k))||w(h=>zt(h,r))},[w,x,je,E,k]),l.useEffect(()=>{if(!i){ke.current=null;return}!je||ke.current===i||x.some(r=>r.id===i&&!r.exited)&&(ke.current=i,de(i))},[i,x,je]),l.useEffect(()=>{if(!te)return;const r=k.groups.find(o=>o.layout.cells.includes(te));if(r){r.id!==k.active&&P(r.id);return}E&&w(o=>{if(Rt(o).has(te))return o;const h=Te(o,te);return h!==o||!I?h:it(o,q,te)})},[q,I,w,te,P,E,k]),l.useEffect(()=>{Q&&!x.some(r=>r.id===Q)&&Z(null)},[Q,x]);const ze=j.filter(r=>r.error),Se=r=>x.find(o=>o.id===r)??null,me=r=>{var o;return((o=n.find(h=>h.id===r))==null?void 0:o.name)??r};function Pe(r){c(o=>o.some(h=>h.id===r)?o:[...o,{id:r,projectId:B,cwd:"",exited:!1}]),w(o=>Te(o,r)),de(r)}async function Oe(){if(!B)return;const{id:r}=await _.createShell(B);c(o=>[...o,{id:r,projectId:B,cwd:"",exited:!1}]),w(o=>Te(o,r)),de(r)}async function $(r,o){const h=kn(r.source);try{const{id:L}=await _.startSession({spec:r.id,flow:h,...o?{force:o}:{}});c(F=>F.some(oe=>oe.id===L)?F:[...F,{id:L,projectId:r.projectId,specId:r.id,flow:h,cwd:"",exited:!1}]),w(F=>Te(F,L)),de(L),J(!1),se(null)}catch(L){if(O.offerRetry(L,r.id,oe=>$(r,oe)))return;const F=L instanceof lt&&(L.status===400||L.status===422);se(`${r.id} · gagal mulai${F?" · project belum punya repoDir":""}`)}}async function Ae(r,o){try{const h=r.specId?await _.startSession({spec:r.specId,flow:r.flow??"feature",...o?{force:o}:{}}):r.kind==="shell"?await _.createShell(r.projectId):r.kind==="terminal"?await _.createTerminal(r.projectId,{agent:r.agent==="codex"?"codex":"claude",...r.model?{model:r.model}:{},...r.effort?{effort:r.effort}:{}}):await(o?_.createTerminalFlow(r.projectId,r.kind,{force:o}):_.createTerminalFlow(r.projectId,r.kind));c(L=>L.some(F=>F.id===h.id)?L:[...L,{id:h.id,projectId:r.projectId,specId:r.specId??void 0,cwd:"",exited:!1}]),w(L=>Te(L,h.id)),de(h.id),H(!1)}catch(h){if((r.specId||r.kind!=="shell"&&r.kind!=="terminal")&&O.offerRetry(h,`${r.projectId} · ${r.title??r.specId??r.kind}`,L=>Ae(r,L)))return}}const he=new Set(x.filter(r=>r.specId&&!r.exited).map(r=>r.specId)),ge=a.filter(r=>r.stage!=="done"&&!he.has(r.id));function xe(r){c(o=>o.filter(h=>h.id!==r)),_.deleteTerminal(r).catch(()=>{})}const Ce=l.useCallback((r,o)=>{c(h=>h.map(L=>L.id===r?{...L,exited:!0,exitCode:o}:L))},[]),we=(r,o)=>{ye(r),w(h=>it(h,r,o))},We=r=>{de(r),w(o=>Te(o,r))},_e=r=>{w(o=>Dr(o,r))},He=Rt(k),Ie=x.filter(r=>!He.has(r.id)),W=Me(k).layout;l.useEffect(()=>{if(!te)return;const r=W.cells.indexOf(te);r<0||(ye(r),de(null))},[W.cells,te]),l.useEffect(()=>{q>=W.cells.length&&ye(Math.max(0,W.cells.length-1))},[q,W.cells.length]);const Le=W.rows===1&&W.cols===1&&!W.cells[0]&&x.length===0,Ke=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(Ve,{size:"sm",icon:"minus",label:"Perkecil teks terminal",disabled:D<=$t,onClick:()=>ie(-1)}),t.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontSize:12,minWidth:44,textAlign:"center"},children:[D,"px"]}),t.jsx(Ve,{size:"sm",icon:"plus",label:"Perbesar teks terminal",disabled:D>=Mt,onClick:()=>ie(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":b,onClick:()=>G(r=>!r),children:b?"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":U,"aria-label":`${U?"Matikan":"Nyalakan"} ketik responsif`,onClick:()=>N(r=>!r),children:U?"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":Y,"aria-label":`${Y?"Matikan":"Nyalakan"} rekam jalur ketik`,onClick:()=>ae(r=>!r),children:Y?"Matikan":"Nyalakan"})]}),I&&t.jsx(pe,{size:"sm","aria-label":"Project sesi baru",value:B,onChange:r=>p(r.target.value),options:n.map(r=>({value:r.id,label:r.name}))})]}),qe=[{key:"backlog",label:"Ambil backlog",icon:"inbox",onSelect:()=>{se(null),J(!0)}},{key:"history",label:"Riwayat sesi",icon:"history",onSelect:()=>H(!0)},{key:"shell",label:"Terminal biasa",icon:"terminal",onSelect:()=>void Oe()},{key:"col+",label:"+ Kolom",icon:"columns-2",disabled:!E,onSelect:()=>void w(r=>be(r,Ct))},{key:"row+",label:"+ Baris",icon:"rows-2",disabled:!E,onSelect:()=>void w(r=>be(r,St))},{key:"col-",label:"Hapus kolom aktif",icon:"columns-2",disabled:!E||W.cols===1,onSelect:()=>void w(r=>be(r,o=>Et(o,q%o.cols)))},{key:"row-",label:"Hapus baris aktif",icon:"rows-2",disabled:!E||W.rows===1,onSelect:()=>void w(r=>be(r,o=>It(o,Math.floor(q/o.cols))))}],f={display:"flex",flexDirection:"column",gap:X?8:12,...X?{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:f,children:[t.jsxs("div",{style:{display:"flex",gap:8,flexDirection:X?"row":"column",alignItems:X?"center":"stretch"},children:[t.jsx(Or,{compact:X,ws:k,writable:E,onSelect:P,onAdd:()=>void w(r=>zr(r,`Grup ${r.groups.length+1}`)),onRename:(r,o)=>void w(h=>Ar(h,r,o)),onRemove:r=>void w(o=>Lr(o,r))}),t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,flexWrap:"wrap",...X?{flex:1,minWidth:0}:{}},children:[!I&&t.jsxs(t.Fragment,{children:[t.jsx(re,{size:"sm",variant:"ghost",disabled:!E,onClick:()=>void w(r=>be(r,Ct)),children:"+ Kolom"}),t.jsx(re,{size:"sm",variant:"ghost",disabled:!E,onClick:()=>void w(r=>be(r,St)),children:"+ Baris"})]}),t.jsx("div",{style:{flex:1,minWidth:0}}),m!=="ready"&&t.jsx("span",{"data-testid":"terminal-workspace-status",title:T??void 0,style:{fontSize:12,color:m==="conflict"?"var(--status-warn)":"var(--text-muted)"},children:m==="loading"?"Memuat layout server…":m==="recovering"?t.jsxs(t.Fragment,{children:[t.jsx("span",{children:"Layout server belum tersambung"})," ",t.jsx("button",{type:"button",onClick:()=>void S(),children:"Retry"})]}):T??"Layout berubah di perangkat lain"}),j.length>0&&t.jsx("span",{"data-testid":"worktree-cleanups",title:j.map(r=>`${r.sessionId}${r.error?` — ${r.error}`:""}`).join(`
9
+ `),style:{fontSize:12,color:ze.length?"var(--status-err)":"var(--text-muted)"},children:ze.length?`${ze.length} worktree gagal dibersihkan`:`membersihkan ${j.length} worktree…`}),!I&&t.jsxs(t.Fragment,{children:[t.jsx(pe,{size:"sm",value:B,onChange:r=>p(r.target.value),options:n.map(r=>({value:r.id,label:r.name}))}),t.jsx(re,{size:"sm",variant:"secondary",leftIcon:"inbox",onClick:()=>{se(null),J(!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:()=>H(!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 Oe(),children:"Terminal biasa"})]}),t.jsx(re,{size:"sm",leftIcon:"plus",onClick:()=>fe(!0),children:"Sesi baru"}),t.jsx(Bt,{label:I?"Aksi terminal lain":"Tampilan terminal",items:I?qe:[],children:Ke}),t.jsx(Ve,{size:"sm",icon:X?"minimize-2":"maximize-2",label:X?"Keluar layar penuh":"Layar penuh","aria-pressed":X,onClick:()=>le(r=>!r)})]})]}),Ie.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:"}),Ie.map(r=>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:!E,onClick:()=>We(r.id),title:"Taruh di sel kosong pertama grup ini",style:{all:"unset",cursor:"pointer"},children:[r.specId??me(r.projectId)," · ",r.id.slice(0,6)]}),t.jsx("button",{type:"button",className:"hn-terminal-action","aria-label":`Tutup sesi ${r.id}`,onClick:()=>void xe(r.id),children:"×"})]},r.id))]}),I&&!Le&&t.jsx("div",{className:"hn-stack-mobile",style:{display:"flex",alignItems:"center",gap:8},children:t.jsx(hn,{"aria-label":"Panel terminal",variant:"pill",value:String(q),onChange:r=>ye(Number(r)),tabs:W.cells.map((r,o)=>({value:String(o),label:`Panel ${o+1}${r?` · ${r.slice(0,6)}`:" · kosong"}`}))})}),Le?t.jsx(ot,{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:I?"minmax(0, 1fr)":`18px repeat(${W.cols}, minmax(0, 1fr))`,gridTemplateRows:I?"minmax(0, 1fr)":`16px repeat(${W.rows}, minmax(0, 1fr))`},children:[!I&&t.jsx("div",{}),!I&&Array.from({length:W.cols},(r,o)=>t.jsx(At,{label:`Tutup kolom ${o+1}`,disabled:!E||W.cols===1,onClick:()=>void w(h=>be(h,L=>Et(L,o)))},`col-${o}`)),Array.from({length:W.rows},(r,o)=>t.jsxs(l.Fragment,{children:[!I&&t.jsx(At,{label:`Tutup baris ${o+1}`,disabled:!E||W.rows===1,onClick:()=>void w(h=>be(h,L=>It(L,o)))}),Array.from({length:W.cols},(h,L)=>{const F=o*W.cols+L,oe=W.cells[F]??null,ne=oe?Se(oe):null;return t.jsx("div",{"data-terminal-cell-index":F,"aria-hidden":I&&q!==F?"true":"false",style:{minHeight:0,minWidth:0,display:I&&q!==F?"none":"flex",flexDirection:"column",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",overflow:"hidden"},children:ne?t.jsx(qr,{session:ne,nameOf:me,onClose:()=>void xe(ne.id),canArrange:E,onDetach:()=>_e(ne.id),onExit:Ee=>Ce(ne.id,Ee),onReview:s,onSessionReview:d,titleOf:y,onIntegrate:g,onIntegrateSession:v,specOf:R,fontSize:D,showKeys:b,predict:U,diag:Y,fullscreen:Q===ne.id,onFullscreen:()=>Z(ne.id)}):t.jsx(Ur,{disabled:!E,unplaced:Ie,nameOf:me,onPick:Ee=>we(F,Ee)})},oe??`empty-${F}`)})]},`row-${o}`))]}),V&&t.jsx(Pr,{seed:ge,activeIds:he,error:ee,onPick:r=>void $(r),onClose:()=>J(!1)}),ce&&t.jsx(Er,{open:!0,projectId:B,projectName:me(B),onClose:()=>fe(!1),onCreated:Pe}),ue&&t.jsx(Cr,{projects:n,onClose:()=>H(!1),onRestart:r=>void Ae(r)}),O.dialog,Q&&Se(Q)&&t.jsx(Gr,{session:Se(Q),label:Xt(Se(Q),me,y),fontSize:D,showKeys:b,predict:U,diag:Y,onClose:()=>Z(null)})]})}function Xt(e,n,a){const i=n(e.projectId),s=e.specId?a==null?void 0:a(e.specId):void 0;return e.specId?`${i} · ${e.specId}${s?` · ${s}`:""}`:e.id.startsWith("xaudit-")?`${i} · audit lintas`:i}function Pr({seed:e,activeIds:n,error:a,onPick:i,onClose:s}){const[d,y]=l.useState(""),[g,v]=l.useState("all"),[R,x]=l.useState("all"),[c,j]=l.useState(e),[A,C]=l.useState("");l.useEffect(()=>{const m=setTimeout(()=>C(d.trim()),250);return()=>clearTimeout(m)},[d]),l.useEffect(()=>{var E,w;let m=!0;const T=(w=(E=_).listSpecs)==null?void 0:w.call(E,{startable:!0,q:A||void 0,stage:g==="all"?void 0:g,priority:R==="all"?void 0:R});return T==null||T.then(P=>{m&&j(P.items)}).catch(()=>{}),()=>{m=!1}},[A,g,R]);const k=c.filter(m=>!n.has(m.id));return t.jsxs(Be,{open:!0,title:"Ambil backlog",icon:"inbox",onClose:s,width:760,children:[a&&t.jsx("div",{style:{marginBottom:10,padding:"8px 10px",borderRadius:"var(--radius-sm)",background:"var(--clay-100)",color:"var(--clay-600)",fontSize:12},children:a}),t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,flexWrap:"wrap",marginBottom:10},children:[t.jsx(st,{size:"sm",leftIcon:"search",placeholder:"mis. invoice atau SPEC-412","aria-label":"Cari backlog",value:d,onChange:m=>y(m.target.value),style:{flex:"1 1 220px"}}),t.jsx(pe,{size:"sm","aria-label":"Filter stage",value:g,onChange:m=>v(m.target.value),options:[{value:"all",label:"Semua stage"}].concat(yn.filter(m=>m.key!=="done").map(m=>({value:m.key,label:m.label})))}),t.jsx(pe,{size:"sm","aria-label":"Filter prioritas",value:R,onChange:m=>x(m.target.value),options:[{value:"all",label:"Semua prioritas"},{value:"tinggi",label:"Tinggi"},{value:"sedang",label:"Sedang"},{value:"rendah",label:"Rendah"}]})]}),k.length===0?t.jsx(ot,{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:k.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(ve,{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(tt,{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 Or({ws:e,compact:n=!1,writable:a,onSelect:i,onAdd:s,onRename:d,onRemove:y}){const[g,v]=l.useState(null),R=Me(e),x=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((c,j)=>{const A=c.id===R.id;return g===c.id?t.jsx(Wr,{initial:c.name,onCommit:C=>{C.trim()&&d(c.id,C.trim()),v(null)},onCancel:()=>v(null)},c.id):t.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:4,padding:"3px 6px",borderRadius:"var(--radius-sm)",fontSize:12,background:A?"var(--bone-200)":"transparent",border:`1px solid ${A?"var(--border-hair)":"transparent"}`},children:[t.jsx("button",{className:"hn-terminal-group-control",role:"tab","aria-selected":A,tabIndex:A?0:-1,onClick:()=>i(c.id),onKeyDown:C=>{var m,T;let k=null;C.key==="ArrowRight"?k=(j+1)%e.groups.length:C.key==="ArrowLeft"?k=(j-1+e.groups.length)%e.groups.length:C.key==="Home"?k=0:C.key==="End"&&(k=e.groups.length-1),k!==null&&(C.preventDefault(),i(e.groups[k].id),(T=(m=C.currentTarget.closest('[role="tablist"]'))==null?void 0:m.querySelectorAll('[role="tab"]')[k])==null||T.focus())},style:{border:0,padding:0,background:"transparent",font:"inherit",cursor:"pointer",color:A?"var(--text-strong)":"var(--text-muted)"},children:c.name}),A&&a&&t.jsxs(t.Fragment,{children:[t.jsx("button",{className:"hn-terminal-group-control","aria-label":`Ganti nama grup ${c.name}`,title:"Ganti nama",onClick:()=>v(c.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 ${c.name}`,title:x?"Grup terakhir tak bisa dihapus":"Hapus grup (sesi tetap hidup)",disabled:x,onClick:()=>y(c.id),style:{border:0,padding:0,background:"transparent",cursor:x?"not-allowed":"pointer",color:"var(--text-subtle)",opacity:x?.35:1},children:"×"})]})]},c.id)}),t.jsx("button",{className:"hn-terminal-group-control","aria-label":"Grup baru",title:"Grup baru",disabled:!a,onClick:s,style:{border:0,background:"transparent",cursor:"pointer",padding:"3px 8px",color:"var(--text-subtle)",fontSize:12},children:"+"})]})}function At({label:e,disabled:n,onClick:a}){return t.jsx("button",{type:"button","aria-label":e,title:n?"Grid tak boleh menyusut ke nol":e,disabled:n,onClick:a,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 Wr({initial:e,onCommit:n,onCancel:a}){const[i,s]=l.useState(e);return t.jsx("input",{autoFocus:!0,"aria-label":"Nama grup",value:i,placeholder:"mis. Rilis",onChange:d=>s(d.target.value),onBlur:()=>n(i),onKeyDown:d=>{d.key==="Enter"?n(i):d.key==="Escape"&&a()},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 _r={done:"var(--brass)",active:"var(--text-strong)",skipped:"var(--text-subtle)",pending:"var(--text-subtle)"},Hr={done:"✓",running:"●",pending:"○",skipped:"–",failed:"✕",abandoned:"⨯"};function Kr({phases:e,compact:n=!1,now:a}){const[i,s]=l.useState(null),[,d]=l.useState(0),y=!!(e!=null&&e.some(c=>{var j;return((j=c.agent)==null?void 0:j.status)==="running"}));if(l.useEffect(()=>{if(!y||a!==void 0)return;const c=setInterval(()=>d(j=>j+1),1e3);return()=>clearInterval(c)},[y,a]),!(e!=null&&e.length))return null;const g=a??Date.now(),v=e.find(c=>c.name===i&&c.agent),R=c=>({color:_r[c.state],fontWeight:c.state==="active"?600:400,textDecoration:c.state==="skipped"?"line-through":"none",opacity:c.state==="pending"?.5:1}),x=c=>{const j=c.agent;return j?typeof j.durationMs=="number"?xt(j.durationMs):j.status==="running"&&j.startedAt?xt(g-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(c=>{if(!c.agent)return t.jsx("span",{"data-state":c.state,title:c.state,style:R(c),children:c.name},c.name);const j=c.agent,A=dn(c),C=!n||c.state==="active",k=x(c);return t.jsxs("button",{type:"button","data-tone":A,"aria-expanded":i===c.name,"aria-label":`Detail fase ${c.name}`,onClick:()=>s(i===c.name?null:c.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[A]}),t.jsx("span",{"data-state":c.state,title:c.state,style:R(c),children:c.name}),c.state==="skipped"&&t.jsx("span",{children:"dilewati"}),C&&j.model&&t.jsxs("span",{children:["· ",nt(j.model)]}),C&&j.effort&&t.jsxs("span",{children:["· ",j.effort]}),C&&k&&t.jsxs("span",{children:["· ",k]}),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:"⚠"})]},c.name)})}),(v==null?void 0:v.agent)&&t.jsxs("div",{role:"dialog","aria-label":`Detail fase ${v.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:v.agent.name})}),t.jsx("div",{children:[nt(v.agent.model),v.agent.effort,v.agent.status??"belum mulai"].filter(Boolean).join(" · ")}),t.jsxs("div",{children:["durasi ",x(v)||"—"," · percobaan ",v.agent.attempts]}),t.jsxs("div",{children:["token in ",v.agent.inputTokens??"—"," · out ",v.agent.outputTokens??"—"," · cache ",v.agent.cachedTokens??"—"]}),v.agent.resultExcerpt&&t.jsx("pre",{style:{margin:"6px 0 0",whiteSpace:"pre-wrap",maxHeight:160,overflow:"auto"},children:v.agent.resultExcerpt})]})]})}function qr({session:e,nameOf:n,onClose:a,canArrange:i,onDetach:s,onExit:d,onReview:y,onSessionReview:g,titleOf:v,onIntegrate:R,onIntegrateSession:x,specOf:c,fontSize:j,showKeys:A,predict:C,diag:k,fullscreen:m,onFullscreen:T}){const[E,w]=l.useState(null),P=l.useRef(null),[S,B]=l.useState(Number.POSITIVE_INFINITY),p=Dt();l.useEffect(()=>{const H=P.current;if(!H||typeof ResizeObserver!="function")return;const O=new ResizeObserver(Fe=>{var q;const I=((q=Fe[0])==null?void 0:q.contentRect.width)??H.getBoundingClientRect().width;I>0&&B(I)});return O.observe(H),()=>O.disconnect()},[]);const[u,D]=l.useState(!1),M=l.useCallback((H,O)=>{w(H),D(O)},[]),[b,G]=l.useState(!1),[U,N]=l.useState(!1),[Y,ae]=l.useState(!1),ie=e.specId?c==null?void 0:c(e.specId):void 0,X=!e.specId&&!!e.branch,le=Xt(e,n,v),Q=!e.exited&&!!e.decision,Z=!e.exited&&!!e.deciding,V=Q||Z,J=e.exited&&!!e.exitCode,ee=!e.exited&&u,se=J?null:e.exited||ee?"PST-005":V?"PST-004":"PST-003",ce=[...e.specId?[{key:"docs",label:"Lihat dokumen",icon:"file-text",title:"Lihat dokumen (audit/spec/plan)",onSelect:()=>G(!0),render:t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:()=>G(!0),"aria-label":`Lihat dokumen sesi ${e.id}`,title:"Lihat dokumen (audit/spec/plan)",children:t.jsx(ve,{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(ve,{name:"git-compare",size:12})},"review")}]:[],...X&&g?[{key:"review-session",label:"Review perubahan",icon:"git-compare",title:"Review perubahan (diff worktree sesi)",onSelect:()=>g(e.id,le),render:t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:()=>g(e.id,le),"aria-label":`Review sesi ${e.id}`,title:"Review perubahan (diff worktree sesi)",children:t.jsx(ve,{name:"git-compare",size:12})},"review-session")}]:[],...ie&&R?[{key:"integrate",label:"Rebase / Merge branch",icon:"git-merge",title:"Rebase / Merge branch spec",onSelect:()=>N(!0),render:t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:()=>N(!0),"aria-label":`Integrasikan sesi ${e.id}`,title:"Rebase / Merge branch spec",children:t.jsx(ve,{name:"git-merge",size:12})},"integrate")}]:[],...X&&x?[{key:"integrate-session",label:"Rebase / Merge branch",icon:"git-merge",title:"Rebase / Merge branch sesi",onSelect:()=>ae(!0),render:t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:()=>ae(!0),"aria-label":`Integrasikan sesi ${e.id}`,title:"Rebase / Merge branch sesi",children:t.jsx(ve,{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")}],fe=Nn(S,ce.length,p?44:28),ue=ce.slice(fe);return t.jsxs(t.Fragment,{children:[t.jsxs("div",{ref:P,className:"hn-terminal-cell-header",style:{display:"flex",alignItems:"center",gap:8,padding:"4px 8px",flex:"0 0 auto",background:J?"var(--status-err-tint)":e.exited||ee?"var(--status-ok-tint)":V?"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:[se&&t.jsx(bn,{id:se,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:[le," · ",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 ",nt(e.model),e.effort?` · ${e.effort}`:""]}),e.exited&&(J?t.jsx(De,{status:"failed",size:"sm",children:`Gagal · exit ${e.exitCode}`}):t.jsx(De,{status:"done",size:"sm",children:"Selesai"})),ee&&t.jsx(De,{status:"done",size:"sm",children:"Selesai"}),Z&&!ee&&t.jsx(De,{status:"running",size:"sm",children:"Lead memutuskan"}),Q&&!Z&&!ee&&t.jsx(De,{status:"awaiting",size:"sm"}),t.jsxs("span",{className:"hn-terminal-actions",children:[ce.slice(0,fe).map(H=>H.render),ue.length>0&&t.jsx(Bt,{label:`Aksi lain sesi ${e.id}`,items:ue.map(({render:H,...O})=>O)}),t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:T,title:"Layar penuh — fokus 1 terminal","aria-label":`Layar penuh sesi ${e.id}`,children:t.jsx(ve,{name:"fullscreen",size:12})}),t.jsx("button",{type:"button",className:"hn-terminal-action","aria-label":`Tutup sesi ${e.id}`,onClick:a,children:"×"})]})]}),t.jsxs("div",{style:{display:"flex",flexDirection:"column",flex:1,minHeight:0,position:"relative",opacity:e.exited?.6:1},children:[t.jsx(Kr,{phases:E,compact:S<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(_t,{sessionId:e.id,onExit:d,onPhases:M,fontSize:j,showKeys:A,predict:C,diag:k},e.id)})]}),b&&e.specId&&t.jsx(vn,{specId:e.specId,onClose:()=>G(!1)}),U&&ie&&R&&t.jsx(bt,{projectId:ie.projectId,ownBranch:`hanoman/${ie.id.toLowerCase().replace(/[^a-z0-9_-]/g,"_")}`,eyebrow:ie.id,onClose:()=>N(!1),onIntegrate:(H,O)=>{N(!1),R(ie,H,O)}}),Y&&X&&x&&t.jsx(bt,{projectId:e.projectId,ownBranch:e.branch,eyebrow:e.id.slice(0,16),onClose:()=>ae(!1),onIntegrate:(H,O)=>{ae(!1),x(e,H,O)}})]})}function Gr({session:e,label:n,fontSize:a,showKeys:i,predict:s,diag:d,onClose:y}){return t.jsx(Be,{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(_t,{sessionId:e.id,onExit:()=>{},fontSize:a,showKeys:i,predict:s,diag:d},e.id)})})}function Ur({unplaced:e,nameOf:n,onPick:a,disabled:i}){return t.jsx("div",{style:{flex:1,display:"grid",placeItems:"center",padding:12},children:t.jsx(pe,{size:"sm",value:"","aria-label":"Pilih sesi untuk sel",disabled:i||!e.length,onChange:s=>s.target.value&&a(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{Kr 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-DI7G_sit.js";import{R as l}from"./react-DfGhg7ZW.js";import{L as ue}from"./live-DVDstDzi.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-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,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,am as be,af as ke,c as O,d as T,a5 as ye,a9 as se,y as ve}from"./index-DI7G_sit.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-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(`
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-DI7G_sit.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-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(`
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};