hanoman 0.7.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build-info.json +3 -3
- package/dist/cli.js +11 -11
- package/dist/server.js +786 -441
- package/package.json +1 -1
- package/web/assets/{ChangelogScreen-D6brfukI.js → ChangelogScreen-_gDN94cU.js} +1 -1
- package/web/assets/{DalangHanomanScreen-C8GIJv8X.js → DalangHanomanScreen-DYgYsjHL.js} +1 -1
- package/web/assets/{DocPreviewModal-4m5Afjx2.js → DocPreviewModal-BmiV6G97.js} +1 -1
- package/web/assets/{DocsWorkspace-8U-UYo4-.js → DocsWorkspace-B235YOee.js} +1 -1
- package/web/assets/{IdeScreen-8QAVPotm.js → IdeScreen-CKtV6kQg.js} +1 -1
- package/web/assets/{LeadScreen-CRs2p9QY.js → LeadScreen-CCbmOwDK.js} +1 -1
- package/web/assets/{ReviewScreen-CBmaRAHG.js → ReviewScreen-Cjn2UblA.js} +1 -1
- package/web/assets/{SchedulerScreen-C1dPfo1w.js → SchedulerScreen-CgWbTZRW.js} +1 -1
- package/web/assets/{SettingsScreen-rE_jbjMw.js → SettingsScreen-CgKsiBYb.js} +2 -2
- package/web/assets/{TeamScreen-Dz0rA4Tk.js → TeamScreen-BQaDdG1N.js} +1 -1
- package/web/assets/TerminalScreen-XuGax_Pi.js +2 -0
- package/web/assets/{TriageScreen-BZQvccje.js → TriageScreen-Dwb-RSdX.js} +1 -1
- package/web/assets/{VpsScreen-CPlPXExd.js → VpsScreen-B98EElUN.js} +1 -1
- package/web/assets/index-B5A1QnO4.js +1005 -0
- package/web/assets/{live-BWD2sDTC.js → live-DanRrGMa.js} +1 -1
- package/web/index.html +1 -1
- package/web/assets/TerminalScreen-Ca7K60wq.js +0 -2
- package/web/assets/index-C_btxEiC.js +0 -931
|
@@ -1 +1 @@
|
|
|
1
|
-
import{aJ as i,j as u,B as f}from"./index-
|
|
1
|
+
import{aJ as i,j as u,B as f}from"./index-B5A1QnO4.js";import{R as s}from"./react-DfGhg7ZW.js";const w=6e3;function d({className:o="",style:a={}}){const e=i(),n=!e.connected&&!e.paused,[r,t]=s.useState(()=>Date.now());return s.useEffect(()=>{if(!n)return;t(Date.now());const c=setInterval(()=>t(Date.now()),1e3);return()=>clearInterval(c)},[n,e.since]),!n||r-e.since<w?null:u.jsx(f,{tone:"warn",variant:"soft",icon:"wifi-off",className:o,style:a,children:"koneksi terputus · menyambung ulang…"})}export{d as L};
|
package/web/index.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
7
7
|
<title>hanoman</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-B5A1QnO4.js"></script>
|
|
9
9
|
<link rel="modulepreload" crossorigin href="/assets/react-DfGhg7ZW.js">
|
|
10
10
|
<link rel="modulepreload" crossorigin href="/assets/markdown-CWEY34jk.js">
|
|
11
11
|
<link rel="modulepreload" crossorigin href="/assets/xterm-3VOAfa_q.js">
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{e as N,j as t,M as be,d as ut,S as U,G as Lt,J as pt,f as He,B as Pe,I as ne,w as Bt,D as Dt,a as H,K as Pt,N as Wt,O as Qe,Q as Ze,c as $e,U as Mt,V as Ot,W as Ht,X as Gt,Y as _t,Z as Kt,_ as ve,$ as mt,a0 as Ge,a1 as qt,a2 as Ut,a3 as We,h as xe,a4 as ft,a5 as Vt,a6 as Yt,a7 as Jt,g as Ae,a8 as Xt,a9 as Qt,aa as ht,l as Zt,ab as et,ac as ea,x as ta,ad as aa,ae as na,af as Fe,p as ia,ag as ra,ah as ge,ai as xt,aj as sa,ak as tt,al as la,am as oa,an as ca}from"./index-C_btxEiC.js";import{R as d,r as A}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";function _e(e){return e.endedAt?e.endedReason==="reconciled"?"interrupted":e.exitCode===null||e.exitCode===0?"completed":"failed":"running"}const at=20;function da(e,i){if(!i)return"—";const n=new Date(i).getTime()-new Date(e).getTime();if(!Number.isFinite(n)||n<0)return"—";const r=Math.round(n/1e3);if(r<60)return`${r} dtk`;const o=Math.round(r/60);return o<60?`${o} mnt`:`${Math.floor(o/60)} jam ${o%60} mnt`}function ua(e){switch(_e(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 gt=e=>_e(e)==="interrupted"?"—":da(e.startedAt,e.endedAt),bt=e=>pt[e]??e;function pa({projects:e,onClose:i,onRestart:n}){const[r,o]=d.useState([]),[u,C]=d.useState(0),[v,x]=d.useState(1),[I,h]=d.useState(!1),[l,k]=d.useState(""),[j,g]=d.useState(""),[y,m]=d.useState(""),[E,S]=d.useState(""),[T,F]=d.useState(null);d.useEffect(()=>{const s=setTimeout(()=>S(y.trim()),250);return()=>clearTimeout(s)},[y]),d.useEffect(()=>{x(1)},[l,j,E]),d.useEffect(()=>{let s=!0;return h(!0),N.listSessionHistory({projectId:l||void 0,kind:j||void 0,q:E||void 0,page:v,limit:at}).then(f=>{s&&(C(f.total),o(f.items))}).catch(()=>{s&&(o([]),C(0))}).finally(()=>{s&&h(!1)}),()=>{s=!1}},[l,j,E,v]);const p=Dt(u,v,at),b=s=>{var f;return((f=e.find(R=>R.id===s))==null?void 0:f.name)??s};return t.jsxs(be,{open:!0,title:"Riwayat sesi",icon:"history",onClose:i,width:900,children:[t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,flexWrap:"wrap",marginBottom:10},children:[t.jsx(ut,{size:"sm",leftIcon:"search",placeholder:"mis. spec-412 atau reverse","aria-label":"Cari riwayat sesi",value:y,onChange:s=>m(s.target.value),style:{flex:"1 1 200px"}}),t.jsx(U,{size:"sm","aria-label":"Filter project",value:l,onChange:s=>k(s.target.value),options:[{value:"",label:"Semua project"}].concat(e.map(s=>({value:s.id,label:s.name})))}),t.jsx(U,{size:"sm","aria-label":"Filter jenis",value:j,onChange:s=>g(s.target.value),options:[{value:"",label:"Semua jenis"}].concat(Lt.map(s=>({value:s,label:pt[s]})))})]}),r.length===0&&!I?t.jsx(He,{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:[r.map(s=>{const f=ua(s);return t.jsx("button",{onClick:()=>F(s),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(s.startedAt).toLocaleString("id-ID")}),t.jsx(Pe,{size:"sm",tone:"neutral",children:bt(s.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:s.title??s.specId??b(s.projectId)}),s.transcriptBytes!==null&&t.jsx(ne,{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:gt(s)}),t.jsx(Pe,{size:"sm",tone:f.tone,children:f.label})]})},s.id)}),I&&t.jsx("div",{style:{padding:"10px 8px",textAlign:"center",fontSize:11,color:"var(--text-subtle)"},children:"memuat…"})]}),t.jsx(Bt,{page:p.page,pageCount:p.pageCount,total:u,from:p.from,to:p.to,onPage:x,unit:"sesi"}),T&&t.jsx(ma,{row:T,projectName:b(T.projectId),onBack:()=>F(null),onRestart:n})]})}function ma({row:e,projectName:i,onBack:n,onRestart:r}){const[o,u]=d.useState(null),[C,v]=d.useState("idle");d.useEffect(()=>{if(e.transcriptBytes===null){v("none"),u(null);return}let h=!0;return v("loading"),N.sessionTranscript(e.id).then(l=>{h&&(u(l.text),v("idle"))}).catch(()=>{h&&(u(null),v("error"))}),()=>{h=!1}},[e.id,e.transcriptBytes]);const x=_e(e)==="interrupted",I=[["Project",i],["Sesi",e.sessionId],["Jenis",bt(e.kind)],["Agen",[e.agent,e.model,e.effort].filter(Boolean).join(" · ")],["Mulai",new Date(e.startedAt).toLocaleString("id-ID")],[x?"Terakhir terlihat hidup":"Selesai",e.endedAt?new Date(e.endedAt).toLocaleString("id-ID"):"berjalan"],...x&&e.reconciledAt?[["Terdeteksi mati",new Date(e.reconciledAt).toLocaleString("id-ID")]]:[],["Durasi",gt(e)],["Direktori",e.cwd]];return e.specId&&I.splice(1,0,["Backlog",`${e.specId}${e.title?` · ${e.title}`:""}`]),e.branch&&I.push(["Branch",e.branch]),t.jsxs(be,{open:!0,title:e.title??e.specId??e.sessionId,icon:"history",onClose:n,width:1e3,children:[t.jsxs("div",{style:{display:"flex",gap:8,alignItems:"center",marginBottom:10},children:[t.jsx(H,{size:"sm",variant:"ghost",leftIcon:"arrow-left",onClick:n,children:"Kembali"}),t.jsx("div",{style:{flex:1}}),o&&t.jsx(H,{size:"sm",variant:"secondary",leftIcon:"copy",onClick:()=>{var h;return void((h=navigator.clipboard)==null?void 0:h.writeText(o))},children:"Salin transkrip"}),Pt(e.kind)&&t.jsx(H,{size:"sm",leftIcon:"play",onClick:()=>r(e),children:"Mulai lagi"})]}),x&&t.jsxs(Wt,{tone:"warn",title:"Sesi terputus — hasilnya tak diketahui",style:{marginBottom:12},children:["Panenya sudah lenyap saat hanoman menyala lagi (reboot, ",t.jsx("code",{children:"tmux kill-server"}),", atau host mati), jadi sesi ini tak meninggalkan exit code dan transkripnya kemungkinan besar tak sempat diambil — capture berjalan tepat sebelum pane dibunuh, dan di jalur ini sudah tak ada pane untuk dibaca. Periksa worktree & branch sesi ini sebelum menganggapnya selesai, lalu mulai lagi bila pekerjaannya belum tuntas."]}),t.jsx("div",{style:{display:"grid",gridTemplateColumns:"auto 1fr",gap:"4px 12px",marginBottom:12,fontSize:12},children:I.map(([h,l])=>t.jsxs(d.Fragment,{children:[t.jsx("span",{style:{color:"var(--text-subtle)"},children:h}),t.jsx("span",{style:{fontFamily:"var(--font-mono)",color:"var(--text-body)",wordBreak:"break-all"},children:l})]},h))}),C==="loading"&&t.jsx("div",{style:{fontSize:12,color:"var(--text-subtle)"},children:"memuat transkrip…"}),C==="none"&&t.jsx("div",{style:{fontSize:12,color:"var(--text-subtle)"},children:x?"Tanpa transkrip — panenya sudah lenyap sebelum hanoman sempat mengambilnya.":"Tanpa transkrip — sesi ini ditutup sebelum fitur riwayat ada, atau panenya tak menyisakan keluaran."}),C==="error"&&t.jsx("div",{style:{fontSize:12,color:"var(--clay-600)"},children:"Transkrip tak terbaca lagi di server."}),o!==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:o})]})}function fa({open:e,projectId:i,projectName:n,onClose:r,onCreated:o}){var F;const[u,C]=d.useState("claude"),[v,x]=d.useState("claude-opus-5"),[I,h]=d.useState("xhigh"),[l,k]=d.useState({claude:{model:"claude-sonnet-5",effort:"medium"},codex:{...Qe}}),[j,g]=d.useState(!1),[y,m]=d.useState(null);d.useEffect(()=>{e&&(N.getSettings().then(p=>{const b={claude:{model:p.model,effort:p.effort},codex:{...Qe,...p.codex??{}}},s=p.agent==="codex"?"codex":"claude",f=Ze(b,s);k(b),C(s),x(f.model),h(f.effort)}).catch(()=>{}),N.getCodexVersion().then(p=>m(p.version)).catch(()=>{}))},[e]);const E=p=>{C(p);const b=Ze(l,p);x(b.model),h(b.effort)},S=p=>{x(p),h(b=>u==="codex"?_t(p,b):Kt(p,b))};async function T(){g(!0);try{const{id:p}=await N.createTerminal(i,{agent:u,model:v,effort:I});o(p),r()}catch{}finally{g(!1)}}return t.jsxs(be,{open:e,onClose:r,icon:"plus",eyebrow:n,title:"Sesi baru",footer:t.jsxs(t.Fragment,{children:[t.jsx(H,{variant:"ghost",onClick:r,children:"Batal"}),t.jsx(H,{leftIcon:"play",disabled:j,onClick:()=>void T(),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($e,{label:"Agen",hint:"Mesin yang menjalankan sesi ini. Perilaku sesi sama; hanya CLI-nya berbeda.",children:t.jsx(U,{"aria-label":"Agen",value:u,style:{width:"100%"},options:[{value:"claude",label:"Claude Code"},{value:"codex",label:"Codex CLI"}],onChange:p=>E(p.target.value)})}),t.jsx($e,{label:"Model",children:t.jsx(U,{"aria-label":"Model",value:v,style:{width:"100%"},options:Mt(u).map(p=>({value:p.id,label:p.label})),onChange:p=>S(p.target.value)})}),t.jsx($e,{label:"Effort",children:t.jsx(U,{"aria-label":"Effort",value:I,style:{width:"100%"},options:Ot(u,v).map(p=>({value:p,label:p})),onChange:p=>h(p.target.value)})}),u==="codex"&&Ht(v,y)&&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:y}),", sedangkan ",t.jsx("b",{children:v})," butuh ",t.jsx("b",{children:(F=Gt(v))==null?void 0:F.minClient}),". Sesi tetap boleh dijalankan, tapi modelnya belum tentu dikenali CLI ini."]})]})}const ha=()=>({rows:1,cols:1,cells:[null]}),nt=e=>({...e,rows:e.rows+1,cells:[...e.cells,...Array(e.cols).fill(null)]});function it(e){const i=e.cols+1,n=[];for(let r=0;r<e.rows;r++)for(let o=0;o<i;o++)n.push(o<e.cols?e.cells[r*e.cols+o]??null:null);return{rows:e.rows,cols:i,cells:n}}function rt(e,i){if(e.rows===1||i<0||i>=e.rows)return e;const n=[...e.cells];return n.splice(i*e.cols,e.cols),{...e,rows:e.rows-1,cells:n}}function st(e,i){if(e.cols===1||i<0||i>=e.cols)return e;const n=e.cols-1,r=[];for(let o=0;o<e.rows;o++)for(let u=0;u<e.cols;u++)u!==i&&r.push(e.cells[o*e.cols+u]??null);return{rows:e.rows,cols:n,cells:r}}function Me(e,i,n){if(i<0||i>=e.cells.length)return e;const r=e.cells.map(o=>n!==null&&o===n?null:o);return r[i]=n,{...e,cells:r}}const xa=(e,i)=>({...e,cells:e.cells.map(n=>n&&i.has(n)?n:null)}),vt=e=>({id:crypto.randomUUID(),name:e,layout:ha()});function lt(){const e=vt("Utama");return{groups:[e],active:e.id}}const ye=e=>e.groups.find(i=>i.id===e.active)??e.groups[0];function ga(e,i){const n=vt(i);return{groups:[...e.groups,n],active:n.id}}const ba=(e,i,n)=>({...e,groups:e.groups.map(r=>r.id===i?{...r,name:n}:r)});function va(e,i){if(e.groups.length===1)return e;const n=e.groups.filter(r=>r.id!==i);return n.length===e.groups.length?e:{groups:n,active:e.active===i?n[0].id:e.active}}const ya=(e,i)=>e.groups.some(n=>n.id===i)?{...e,active:i}:e;function ae(e,i){const n=ye(e);return{...e,groups:e.groups.map(r=>r.id===n.id?{...r,layout:i(r.layout)}:r)}}function Oe(e,i,n){const r=ye(e),o=n===null?e.groups:e.groups.map(u=>u.id===r.id?u:{...u,layout:Me(u.layout,u.layout.cells.indexOf(n),null)});return{...e,groups:o.map(u=>u.id===r.id?{...u,layout:Me(u.layout,i,n)}:u)}}function de(e,i){const n=ye(e).layout.cells.indexOf(null);return n===-1?e:Oe(e,n,i)}const ka=(e,i)=>({...e,groups:e.groups.map(n=>({...n,layout:Me(n.layout,n.layout.cells.indexOf(i),null)}))}),ot=e=>new Set(e.groups.flatMap(i=>i.layout.cells.filter(n=>n!==null))),ct=(e,i)=>({...e,groups:e.groups.map(n=>({...n,layout:xa(n.layout,i)}))}),yt="hanoman.terminal.workspace",kt="hanoman.terminal.layout",ue=e=>ve.parse({version:1,groups:e.groups});function Ce(e,i){const n=e.groups,r=i&&n.some(o=>o.id===i)?i:n[0].id;return{groups:n,active:r}}function ja(e){try{const i=JSON.parse(e);if(!i||typeof i!="object")return null;const n=i,r=ve.parse({version:1,groups:n.groups});return{workspace:r,active:typeof n.active=="string"&&r.groups.some(o=>o.id===n.active)?n.active:r.groups[0].id}}catch{return null}}function wa(){try{const e=localStorage.getItem(yt);if(e)return ja(e);const i=localStorage.getItem(kt);if(!i)return null;const n=JSON.parse(i),r={id:crypto.randomUUID(),name:"Utama",layout:n};return{workspace:ve.parse({version:1,groups:[r]}),active:r.id}}catch{return null}}function Le(){try{localStorage.removeItem(yt),localStorage.removeItem(kt)}catch{}}const jt=e=>`hanoman.terminal.workspace.v2.${encodeURIComponent(e)}`;function Sa(e){try{const i=localStorage.getItem(jt(e));if(!i)return null;const n=JSON.parse(i),r=ve.parse(n.workspace);if(!Number.isInteger(n.revision)||(n.revision??-1)<0)return null;const o=typeof n.active=="string"&&r.groups.some(u=>u.id===n.active)?n.active:r.groups[0].id;return{workspace:r,revision:n.revision,active:o}}catch{return null}}function Be(e,i){try{const n=ve.parse(i.workspace);if(!Number.isInteger(i.revision)||i.revision<0)return;const r=n.groups.some(o=>o.id===i.active)?i.active:n.groups[0].id;localStorage.setItem(jt(e),JSON.stringify({workspace:n,revision:i.revision,active:r}))}catch{}}function De(e){if(!(e instanceof Ge)||e.status!==409)return null;const i=e.detail;if((i==null?void 0:i.code)!=="revision-conflict")return null;const n=qt.safeParse(i.current);return n.success?n.data:null}function Ia(e){const i=A.useRef(null);i.current||(i.current=lt());const[n,r]=A.useState(i.current),[o,u]=A.useState("loading"),[C,v]=A.useState(null),[x,I]=A.useState(!1),h=A.useRef(n),l=A.useRef(0),k=A.useRef(!1),j=A.useRef(Promise.resolve()),g=A.useRef(0),y=A.useCallback(s=>{h.current=s,r(s)},[]),m=A.useCallback(s=>{k.current=s,I(s)},[]),E=A.useCallback(s=>{const f=j.current.then(s,s);return j.current=f.then(()=>{},()=>{}),f},[]),S=A.useCallback((s,f="ready",R=null,L=h.current.active)=>{const P=s.workspace?Ce(s.workspace,L):lt();l.current=s.revision,y(P),u(f),v(R),m(!0),s.workspace&&Be(e,{workspace:s.workspace,revision:s.revision,active:P.active})},[y,m,e]),T=A.useCallback(s=>{const f=Sa(e);f&&(l.current=f.revision,y(Ce(f.workspace,f.active))),m(!1),u("recovering"),v(s instanceof Error?s.message:"Layout server belum tersambung")},[y,m,e]),F=A.useCallback(()=>E(async()=>{try{S(await N.getTerminalWorkspace())}catch(s){T(s)}}),[S,E,T]);A.useEffect(()=>{const s=++g.current;return u("loading"),v(null),m(!1),E(async()=>{try{const f=await N.getTerminalWorkspace();if(s!==g.current)return;if(f.workspace){S(f),Le();return}const R=wa();if(!R){S(f);return}try{const L=await N.putTerminalWorkspace({baseRevision:f.revision,workspace:R.workspace});if(s!==g.current)return;y(Ce(L.workspace,R.active)),l.current=L.revision,Be(e,{workspace:L.workspace,revision:L.revision,active:R.active}),Le(),u("ready"),v(null),m(!0)}catch(L){const P=De(L);P!=null&&P.workspace?(S(P,"conflict","Layout server lebih baru; layout lokal lama tidak diunggah"),Le()):T(L)}}catch(f){s===g.current&&T(f)}}),()=>{g.current+=1}},[S,E,T,y,m,e]),A.useEffect(()=>{const s=()=>{F()},f=()=>{document.visibilityState==="visible"&&F()};return window.addEventListener("focus",s),document.addEventListener("visibilitychange",f),()=>{window.removeEventListener("focus",s),document.removeEventListener("visibilitychange",f)}},[F]);const p=A.useCallback(s=>E(async()=>{if(!k.current)return!1;const f=s(h.current);let R,L;try{R=ue(f),L=ue(h.current)}catch{return u("conflict"),v("Layout tidak valid dan tidak disimpan"),!1}if(mt(R,L))return!0;try{return S(await N.putTerminalWorkspace({baseRevision:l.current,workspace:R}),"ready",null,f.active),!0}catch(P){const W=De(P);if(!(W!=null&&W.workspace))return T(P),!1;const le=s(Ce(W.workspace,h.current.active));try{const B=await N.putTerminalWorkspace({baseRevision:W.revision,workspace:ue(le)});return S(B,"conflict","Layout berubah di perangkat lain; perubahan ini diterapkan ulang",le.active),!0}catch(B){if(!De(B)&&!(B instanceof Ge&&B.status===409))return T(B),!1;try{S(await N.getTerminalWorkspace(),"conflict","Layout berubah lagi di perangkat lain; state terbaru dimuat")}catch(pe){T(pe)}return!1}}}),[S,E,T]),b=A.useCallback(s=>{const f=ya(h.current,s);y(f);const R=ue(f);Be(e,{workspace:R,revision:l.current,active:f.active})},[y,e]);return{workspace:n,status:o,message:C,writable:x,mutate:p,setActive:b,refresh:F}}function Ma({userId:e="test-user",projects:i,backlog:n=[],focusSession:r,startedSession:o,onStartedSessionHandled:u,onStartBacklog:C,onOpenReview:v,onOpenSessionReview:x,titleOf:I,onIntegrate:h,onIntegrateSession:l,specOf:k}){var Xe;const[j,g]=d.useState([]),[y,m]=d.useState([]),E=Ia(e),{workspace:S,status:T,message:F,writable:p,mutate:b,setActive:s,refresh:f}=E,[R,L]=xe("terminal","project",((Xe=i[0])==null?void 0:Xe.id)??"",ia),P=ft(),[W,le]=xe("terminal","fontSize",P?aa:na,ta),[B,pe]=xe("terminal","keys",P,Fe),[q,Z]=xe("terminal","predict",!0,Fe),[V,me]=xe("terminal","diag",!1,Fe),fe=a=>le(c=>ea(c+a)),[G,ke]=d.useState(!1),[K,Y]=d.useState(null),[je,J]=d.useState(!1),[we,ee]=d.useState(null),[O,_]=d.useState(!1),[ze,ie]=d.useState(!1),oe=Vt(),M=Yt()==="mobile",[X,Se]=d.useState(0),[Q,te]=d.useState(null),Te=d.useRef(null),[ce,St]=d.useState(!1);d.useEffect(()=>{N.listTerminals().then(a=>{g(a),St(!0)}).catch(()=>{})},[]),d.useEffect(()=>Jt(a=>{a.t==="sessions"?g(a.sessions):a.t==="cleanups"&&m(a.cleanups)}),[]),d.useEffect(()=>{if(!ce||!p)return;const a=new Set(j.map(w=>w.id)),c=ct(S,a);mt(ue(c),ue(S))||b(w=>ct(w,a))},[b,j,ce,p,S]),d.useEffect(()=>{!o||o.specId==null||!ce||(g(a=>a.some(c=>c.id===o.id)?a:[...a,{...o,cwd:"",exited:!1}]),te(o.id),u==null||u())},[u,ce,o]),d.useEffect(()=>{if(!r){Te.current=null;return}!ce||Te.current===r||j.some(a=>a.id===r&&!a.exited)&&(Te.current=r,te(r))},[r,j,ce]),d.useEffect(()=>{if(!Q)return;const a=S.groups.find(c=>c.layout.cells.includes(Q));if(a){a.id!==S.active&&s(a.id);return}p&&b(c=>{if(ot(c).has(Q))return c;const w=de(c,Q);return w!==c||!M?w:Oe(c,X,Q)})},[X,M,b,Q,s,p,S]),d.useEffect(()=>{K&&!j.some(a=>a.id===K)&&Y(null)},[K,j]);const Re=y.filter(a=>a.error),Ie=a=>j.find(c=>c.id===a)??null,he=a=>{var c;return((c=i.find(w=>w.id===a))==null?void 0:c.name)??a};function It(a){g(c=>c.some(w=>w.id===a)?c:[...c,{id:a,projectId:R,cwd:"",exited:!1}]),b(c=>de(c,a)),te(a)}async function Ke(){if(!R)return;const{id:a}=await N.createShell(R);g(c=>[...c,{id:a,projectId:R,cwd:"",exited:!1}]),b(c=>de(c,a)),te(a)}async function qe(a,c){if(C&&!c){J(!1),ee(null),C(a);return}const w=oa(a.source);try{const{id:z}=await N.startSession({spec:a.id,flow:w,...c?{force:c}:{}});g(D=>D.some(re=>re.id===z)?D:[...D,{id:z,projectId:a.projectId,specId:a.id,flow:w,cwd:"",exited:!1}]),b(D=>de(D,z)),te(z),J(!1),ee(null)}catch(z){if(oe.offerRetry(z,a.id,re=>qe(a,re)))return;const D=z instanceof Ge&&(z.status===400||z.status===422);ee(`${a.id} · gagal mulai${D?" · project belum punya repoDir":""}`)}}async function Ue(a,c){try{const w=a.specId?await N.startSession({spec:a.specId,flow:a.flow??"feature",...c?{force:c}:{}}):a.kind==="shell"?await N.createShell(a.projectId):a.kind==="terminal"?await N.createTerminal(a.projectId,{agent:a.agent==="codex"?"codex":"claude",...a.model?{model:a.model}:{},...a.effort?{effort:a.effort}:{}}):await(c?N.createTerminalFlow(a.projectId,a.kind,{force:c}):N.createTerminalFlow(a.projectId,a.kind));g(z=>z.some(D=>D.id===w.id)?z:[...z,{id:w.id,projectId:a.projectId,specId:a.specId??void 0,cwd:"",exited:!1}]),b(z=>de(z,w.id)),te(w.id),ie(!1)}catch(w){if((a.specId||a.kind!=="shell"&&a.kind!=="terminal")&&oe.offerRetry(w,`${a.projectId} · ${a.title??a.specId??a.kind}`,z=>Ue(a,z)))return}}const Ve=new Set(j.filter(a=>a.specId&&!a.exited).map(a=>a.specId)),Ct=n.filter(a=>a.stage!=="done"&&!Ve.has(a.id));function Ye(a){g(c=>c.filter(w=>w.id!==a)),N.deleteTerminal(a).catch(()=>{})}const zt=d.useCallback((a,c)=>{g(w=>w.map(z=>z.id===a?{...z,exited:!0,exitCode:c}:z))},[]),Tt=(a,c)=>{Se(a),b(w=>Oe(w,a,c))},Rt=a=>{te(a),b(c=>de(c,a))},Et=a=>{b(c=>ka(c,a))},Nt=ot(S),Ee=j.filter(a=>!Nt.has(a.id)),$=ye(S).layout;d.useEffect(()=>{if(!Q)return;const a=$.cells.indexOf(Q);a<0||(Se(a),te(null))},[$.cells,Q]),d.useEffect(()=>{X>=$.cells.length&&Se(Math.max(0,$.cells.length-1))},[X,$.cells.length]);const Je=$.rows===1&&$.cols===1&&!$.cells[0]&&j.length===0,$t=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(Ae,{size:"sm",icon:"minus",label:"Perkecil teks terminal",disabled:W<=Xt,onClick:()=>fe(-1)}),t.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontSize:12,minWidth:44,textAlign:"center"},children:[W,"px"]}),t.jsx(Ae,{size:"sm",icon:"plus",label:"Perbesar teks terminal",disabled:W>=Qt,onClick:()=>fe(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(H,{size:"sm",variant:"secondary","aria-pressed":B,onClick:()=>pe(a=>!a),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(H,{size:"sm",variant:"secondary","aria-pressed":q,"aria-label":`${q?"Matikan":"Nyalakan"} ketik responsif`,onClick:()=>Z(a=>!a),children:q?"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(H,{size:"sm",variant:"secondary","aria-pressed":V,"aria-label":`${V?"Matikan":"Nyalakan"} rekam jalur ketik`,onClick:()=>me(a=>!a),children:V?"Matikan":"Nyalakan"})]}),M&&t.jsx(U,{size:"sm","aria-label":"Project sesi baru",value:R,onChange:a=>L(a.target.value),options:i.map(a=>({value:a.id,label:a.name}))})]}),At=[{key:"backlog",label:"Ambil backlog",icon:"inbox",onSelect:()=>{ee(null),J(!0)}},{key:"history",label:"Riwayat sesi",icon:"history",onSelect:()=>ie(!0)},{key:"shell",label:"Terminal biasa",icon:"terminal",onSelect:()=>void Ke()},{key:"col+",label:"+ Kolom",icon:"columns-2",disabled:!p,onSelect:()=>void b(a=>ae(a,it))},{key:"row+",label:"+ Baris",icon:"rows-2",disabled:!p,onSelect:()=>void b(a=>ae(a,nt))},{key:"col-",label:"Hapus kolom aktif",icon:"columns-2",disabled:!p||$.cols===1,onSelect:()=>void b(a=>ae(a,c=>st(c,X%c.cols)))},{key:"row-",label:"Hapus baris aktif",icon:"rows-2",disabled:!p||$.rows===1,onSelect:()=>void b(a=>ae(a,c=>rt(c,Math.floor(X/c.cols))))}],Ft={display:"flex",flexDirection:"column",gap:G?8:12,...G?{position:"fixed",inset:0,zIndex:100,background:"var(--surface-page)",paddingTop:"max(12px, var(--safe-top))",paddingRight:"max(12px, var(--safe-right))",paddingBottom:"max(12px, var(--safe-bottom))",paddingLeft:"max(12px, var(--safe-left))"}:{flex:"1 1 0",minHeight:640}};return t.jsxs("div",{"data-testid":"terminal-root",style:Ft,children:[t.jsxs("div",{style:{display:"flex",gap:8,flexDirection:G?"row":"column",alignItems:G?"center":"stretch"},children:[t.jsx(za,{compact:G,ws:S,writable:p,onSelect:s,onAdd:()=>void b(a=>ga(a,`Grup ${a.groups.length+1}`)),onRename:(a,c)=>void b(w=>ba(w,a,c)),onRemove:a=>void b(c=>va(c,a))}),t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,flexWrap:"wrap",...G?{flex:1,minWidth:0}:{}},children:[!M&&t.jsxs(t.Fragment,{children:[t.jsx(H,{size:"sm",variant:"ghost",disabled:!p,onClick:()=>void b(a=>ae(a,it)),children:"+ Kolom"}),t.jsx(H,{size:"sm",variant:"ghost",disabled:!p,onClick:()=>void b(a=>ae(a,nt)),children:"+ Baris"})]}),t.jsx("div",{style:{flex:1,minWidth:0}}),T!=="ready"&&t.jsx("span",{"data-testid":"terminal-workspace-status",title:F??void 0,style:{fontSize:12,color:T==="conflict"?"var(--status-warn)":"var(--text-muted)"},children:T==="loading"?"Memuat layout server…":T==="recovering"?t.jsxs(t.Fragment,{children:[t.jsx("span",{children:"Layout server belum tersambung"})," ",t.jsx("button",{type:"button",onClick:()=>void f(),children:"Retry"})]}):F??"Layout berubah di perangkat lain"}),y.length>0&&t.jsx("span",{"data-testid":"worktree-cleanups",title:y.map(a=>`${a.sessionId}${a.error?` — ${a.error}`:""}`).join(`
|
|
2
|
-
`),style:{fontSize:12,color:Re.length?"var(--status-err)":"var(--text-muted)"},children:Re.length?`${Re.length} worktree gagal dibersihkan`:`membersihkan ${y.length} worktree…`}),!M&&t.jsxs(t.Fragment,{children:[t.jsx(U,{size:"sm",value:R,onChange:a=>L(a.target.value),options:i.map(a=>({value:a.id,label:a.name}))}),t.jsx(H,{size:"sm",variant:"secondary",leftIcon:"inbox",onClick:()=>{ee(null),J(!0)},children:"Ambil backlog"}),t.jsx(H,{size:"sm",variant:"secondary",leftIcon:"history",title:"Riwayat sesi yang sudah berlalu — buka kembali atau baca transkripnya",onClick:()=>ie(!0),children:"Riwayat"}),t.jsx(H,{size:"sm",variant:"secondary",leftIcon:"terminal",title:"Buka shell tmux tanpa Claude di project terpilih — jalankan command di project",onClick:()=>void Ke(),children:"Terminal biasa"})]}),t.jsx(H,{size:"sm",leftIcon:"plus",onClick:()=>_(!0),children:"Sesi baru"}),t.jsx(ht,{label:M?"Aksi terminal lain":"Tampilan terminal",items:M?At:[],children:$t}),t.jsx(Ae,{size:"sm",icon:G?"minimize-2":"maximize-2",label:G?"Keluar layar penuh":"Layar penuh","aria-pressed":G,onClick:()=>ke(a=>!a)})]})]}),Ee.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:"}),Ee.map(a=>t.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:6,padding:"4px 8px",borderRadius:"var(--radius-sm)",background:"var(--bone-200)",border:"1px solid var(--border-hair)",fontFamily:"var(--font-mono)",fontSize:11},children:[t.jsxs("button",{className:"hn-terminal-unplaced-action",disabled:!p,onClick:()=>Rt(a.id),title:"Taruh di sel kosong pertama grup ini",style:{all:"unset",cursor:"pointer"},children:[a.specId??he(a.projectId)," · ",a.id.slice(0,6)]}),t.jsx("button",{type:"button",className:"hn-terminal-action","aria-label":`Tutup sesi ${a.id}`,onClick:()=>void Ye(a.id),children:"×"})]},a.id))]}),M&&!Je&&t.jsx("div",{className:"hn-stack-mobile",style:{display:"flex",alignItems:"center",gap:8},children:t.jsx(Zt,{"aria-label":"Panel terminal",variant:"pill",value:String(X),onChange:a=>Se(Number(a)),tabs:$.cells.map((a,c)=>({value:String(c),label:`Panel ${c+1}${a?` · ${a.slice(0,6)}`:" · kosong"}`}))})}),Je?t.jsx(He,{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:M?"minmax(0, 1fr)":`18px repeat(${$.cols}, minmax(0, 1fr))`,gridTemplateRows:M?"minmax(0, 1fr)":`16px repeat(${$.rows}, minmax(0, 1fr))`},children:[!M&&t.jsx("div",{}),!M&&Array.from({length:$.cols},(a,c)=>t.jsx(dt,{label:`Tutup kolom ${c+1}`,disabled:!p||$.cols===1,onClick:()=>void b(w=>ae(w,z=>st(z,c)))},`col-${c}`)),Array.from({length:$.rows},(a,c)=>t.jsxs(d.Fragment,{children:[!M&&t.jsx(dt,{label:`Tutup baris ${c+1}`,disabled:!p||$.rows===1,onClick:()=>void b(w=>ae(w,z=>rt(z,c)))}),Array.from({length:$.cols},(w,z)=>{const D=c*$.cols+z,re=$.cells[D]??null,se=re?Ie(re):null;return t.jsx("div",{"data-terminal-cell-index":D,"aria-hidden":M&&X!==D?"true":"false",style:{minHeight:0,minWidth:0,display:M&&X!==D?"none":"flex",flexDirection:"column",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",overflow:"hidden"},children:se?t.jsx($a,{session:se,nameOf:he,onClose:()=>void Ye(se.id),canArrange:p,onDetach:()=>Et(se.id),onExit:Ne=>zt(se.id,Ne),onReview:v,onSessionReview:x,titleOf:I,onIntegrate:h,onIntegrateSession:l,specOf:k,fontSize:W,showKeys:B,predict:q,diag:V,fullscreen:K===se.id,onFullscreen:()=>Y(se.id)}):t.jsx(Fa,{disabled:!p,unplaced:Ee,nameOf:he,onPick:Ne=>Tt(D,Ne)})},re??`empty-${D}`)})]},`row-${c}`))]}),je&&t.jsx(Ca,{seed:Ct,activeIds:Ve,error:we,onPick:a=>void qe(a),onClose:()=>J(!1)}),O&&t.jsx(fa,{open:!0,projectId:R,projectName:he(R),onClose:()=>_(!1),onCreated:It}),ze&&t.jsx(pa,{projects:i,onClose:()=>ie(!1),onRestart:a=>void Ue(a)}),oe.dialog,K&&Ie(K)&&t.jsx(Aa,{session:Ie(K),label:wt(Ie(K),he,I),fontSize:W,showKeys:B,predict:q,diag:V,onClose:()=>Y(null)})]})}function wt(e,i,n){const r=i(e.projectId),o=e.specId?n==null?void 0:n(e.specId):void 0;return e.specId?`${r} · ${e.specId}${o?` · ${o}`:""}`:e.id.startsWith("xaudit-")?`${r} · audit lintas`:r}function Ca({seed:e,activeIds:i,error:n,onPick:r,onClose:o}){const[u,C]=d.useState(""),[v,x]=d.useState("all"),[I,h]=d.useState("all"),[l,k]=d.useState(e),[j,g]=d.useState("");d.useEffect(()=>{const m=setTimeout(()=>g(u.trim()),250);return()=>clearTimeout(m)},[u]),d.useEffect(()=>{var S,T;let m=!0;const E=(T=(S=N).listSpecs)==null?void 0:T.call(S,{startable:!0,q:j||void 0,stage:v==="all"?void 0:v,priority:I==="all"?void 0:I});return E==null||E.then(F=>{m&&k(F.items)}).catch(()=>{}),()=>{m=!1}},[j,v,I]);const y=l.filter(m=>!i.has(m.id));return t.jsxs(be,{open:!0,title:"Ambil backlog",icon:"inbox",onClose:o,width:760,children:[n&&t.jsx("div",{style:{marginBottom:10,padding:"8px 10px",borderRadius:"var(--radius-sm)",background:"var(--clay-100)",color:"var(--clay-600)",fontSize:12},children:n}),t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,flexWrap:"wrap",marginBottom:10},children:[t.jsx(ut,{size:"sm",leftIcon:"search",placeholder:"mis. invoice atau SPEC-412","aria-label":"Cari backlog",value:u,onChange:m=>C(m.target.value),style:{flex:"1 1 220px"}}),t.jsx(U,{size:"sm","aria-label":"Filter stage",value:v,onChange:m=>x(m.target.value),options:[{value:"all",label:"Semua stage"}].concat(la.filter(m=>m.key!=="done").map(m=>({value:m.key,label:m.label})))}),t.jsx(U,{size:"sm","aria-label":"Filter prioritas",value:I,onChange:m=>h(m.target.value),options:[{value:"all",label:"Semua prioritas"},{value:"tinggi",label:"Tinggi"},{value:"sedang",label:"Sedang"},{value:"rendah",label:"Rendah"}]})]}),y.length===0?t.jsx(He,{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:y.map(m=>t.jsx("button",{onClick:()=>r(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(ne,{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(Pe,{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 za({ws:e,compact:i=!1,writable:n,onSelect:r,onAdd:o,onRename:u,onRemove:C}){const[v,x]=d.useState(null),I=ye(e),h=e.groups.length===1;return t.jsxs("div",{role:"tablist","aria-label":"Grup terminal",style:{display:"flex",alignItems:"center",gap:4,flexWrap:"wrap",...i?{}:{borderBottom:"1px solid var(--border-hair)",paddingBottom:4}},children:[e.groups.map((l,k)=>{const j=l.id===I.id;return v===l.id?t.jsx(Ta,{initial:l.name,onCommit:g=>{g.trim()&&u(l.id,g.trim()),x(null)},onCancel:()=>x(null)},l.id):t.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:4,padding:"3px 6px",borderRadius:"var(--radius-sm)",fontSize:12,background:j?"var(--bone-200)":"transparent",border:`1px solid ${j?"var(--border-hair)":"transparent"}`},children:[t.jsx("button",{className:"hn-terminal-group-control",role:"tab","aria-selected":j,tabIndex:j?0:-1,onClick:()=>r(l.id),onKeyDown:g=>{var m,E;let y=null;g.key==="ArrowRight"?y=(k+1)%e.groups.length:g.key==="ArrowLeft"?y=(k-1+e.groups.length)%e.groups.length:g.key==="Home"?y=0:g.key==="End"&&(y=e.groups.length-1),y!==null&&(g.preventDefault(),r(e.groups[y].id),(E=(m=g.currentTarget.closest('[role="tablist"]'))==null?void 0:m.querySelectorAll('[role="tab"]')[y])==null||E.focus())},style:{border:0,padding:0,background:"transparent",font:"inherit",cursor:"pointer",color:j?"var(--text-strong)":"var(--text-muted)"},children:l.name}),j&&n&&t.jsxs(t.Fragment,{children:[t.jsx("button",{className:"hn-terminal-group-control","aria-label":`Ganti nama grup ${l.name}`,title:"Ganti nama",onClick:()=>x(l.id),style:{border:0,padding:0,background:"transparent",cursor:"pointer",color:"var(--text-subtle)",fontSize:10},children:"✎"}),t.jsx("button",{className:"hn-terminal-group-control","aria-label":`Hapus grup ${l.name}`,title:h?"Grup terakhir tak bisa dihapus":"Hapus grup (sesi tetap hidup)",disabled:h,onClick:()=>C(l.id),style:{border:0,padding:0,background:"transparent",cursor:h?"not-allowed":"pointer",color:"var(--text-subtle)",opacity:h?.35:1},children:"×"})]})]},l.id)}),t.jsx("button",{className:"hn-terminal-group-control","aria-label":"Grup baru",title:"Grup baru",disabled:!n,onClick:o,style:{border:0,background:"transparent",cursor:"pointer",padding:"3px 8px",color:"var(--text-subtle)",fontSize:12},children:"+"})]})}function dt({label:e,disabled:i,onClick:n}){return t.jsx("button",{type:"button","aria-label":e,title:i?"Grid tak boleh menyusut ke nol":e,disabled:i,onClick:n,style:{all:"unset",display:"grid",placeItems:"center",fontSize:11,lineHeight:1,color:"var(--text-subtle)",opacity:i?.3:1,cursor:i?"not-allowed":"pointer"},children:"×"})}function Ta({initial:e,onCommit:i,onCancel:n}){const[r,o]=d.useState(e);return t.jsx("input",{autoFocus:!0,"aria-label":"Nama grup",value:r,placeholder:"mis. Rilis",onChange:u=>o(u.target.value),onBlur:()=>i(r),onKeyDown:u=>{u.key==="Enter"?i(r):u.key==="Escape"&&n()},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 Ra={done:"var(--brass)",active:"var(--text-strong)",skipped:"var(--text-subtle)",pending:"var(--text-subtle)"},Ea={done:"✓",running:"●",pending:"○",skipped:"–",failed:"✕",abandoned:"⨯"};function Na({phases:e,compact:i=!1,now:n}){const[r,o]=d.useState(null),[,u]=d.useState(0),C=!!(e!=null&&e.some(l=>{var k;return((k=l.agent)==null?void 0:k.status)==="running"}));if(d.useEffect(()=>{if(!C||n!==void 0)return;const l=setInterval(()=>u(k=>k+1),1e3);return()=>clearInterval(l)},[C,n]),!(e!=null&&e.length))return null;const v=n??Date.now(),x=e.find(l=>l.name===r&&l.agent),I=l=>({color:Ra[l.state],fontWeight:l.state==="active"?600:400,textDecoration:l.state==="skipped"?"line-through":"none",opacity:l.state==="pending"?.5:1}),h=l=>{const k=l.agent;return k?typeof k.durationMs=="number"?et(k.durationMs):k.status==="running"&&k.startedAt?et(v-Date.parse(k.startedAt)):"":""};return t.jsxs("div",{"data-testid":"phase-strip",style:{flex:"0 0 auto",borderBottom:"1px solid var(--border-hair)"},children:[t.jsx("div",{"data-testid":"phase-strip-scroller",style:{display:"flex",alignItems:"center",gap:8,padding:"3px 8px",fontSize:10,fontFamily:"var(--font-mono)",overflowX:"auto",whiteSpace:"nowrap"},children:e.map(l=>{if(!l.agent)return t.jsx("span",{"data-state":l.state,title:l.state,style:I(l),children:l.name},l.name);const k=l.agent,j=Ut(l),g=!i||l.state==="active",y=h(l);return t.jsxs("button",{type:"button","data-tone":j,"aria-expanded":r===l.name,"aria-label":`Detail fase ${l.name}`,onClick:()=>o(r===l.name?null:l.name),style:{display:"inline-flex",alignItems:"center",gap:4,flex:"0 0 auto",padding:"1px 6px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",background:"transparent",font:"inherit",color:"var(--text-body)",cursor:"pointer"},children:[t.jsx("span",{"aria-hidden":!0,children:Ea[j]}),t.jsx("span",{"data-state":l.state,title:l.state,style:I(l),children:l.name}),l.state==="skipped"&&t.jsx("span",{children:"dilewati"}),g&&k.model&&t.jsxs("span",{children:["· ",We(k.model)]}),g&&k.effort&&t.jsxs("span",{children:["· ",k.effort]}),g&&y&&t.jsxs("span",{children:["· ",y]}),k.attempts>1&&t.jsxs("span",{children:["↻",k.attempts]}),k.evidence==="missing"&&t.jsx("span",{role:"img","aria-label":"bukti subagent tak diterima",title:"bukti subagent tak diterima",style:{color:"var(--status-warn)"},children:"⚠"})]},l.name)})}),(x==null?void 0:x.agent)&&t.jsxs("div",{role:"dialog","aria-label":`Detail fase ${x.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:x.agent.name})}),t.jsx("div",{children:[We(x.agent.model),x.agent.effort,x.agent.status??"belum mulai"].filter(Boolean).join(" · ")}),t.jsxs("div",{children:["durasi ",h(x)||"—"," · percobaan ",x.agent.attempts]}),t.jsxs("div",{children:["token in ",x.agent.inputTokens??"—"," · out ",x.agent.outputTokens??"—"," · cache ",x.agent.cachedTokens??"—"]}),x.agent.resultExcerpt&&t.jsx("pre",{style:{margin:"6px 0 0",whiteSpace:"pre-wrap",maxHeight:160,overflow:"auto"},children:x.agent.resultExcerpt})]})]})}function $a({session:e,nameOf:i,onClose:n,canArrange:r,onDetach:o,onExit:u,onReview:C,onSessionReview:v,titleOf:x,onIntegrate:I,onIntegrateSession:h,specOf:l,fontSize:k,showKeys:j,predict:g,diag:y,fullscreen:m,onFullscreen:E}){const[S,T]=d.useState(null),F=d.useRef(null),[p,b]=d.useState(Number.POSITIVE_INFINITY),s=ft();d.useEffect(()=>{const O=F.current;if(!O||typeof ResizeObserver!="function")return;const _=new ResizeObserver(ze=>{var oe;const ie=((oe=ze[0])==null?void 0:oe.contentRect.width)??O.getBoundingClientRect().width;ie>0&&b(ie)});return _.observe(O),()=>_.disconnect()},[]);const[f,R]=d.useState(!1),L=d.useCallback((O,_)=>{T(O),R(_)},[]),[P,W]=d.useState(!1),[le,B]=d.useState(!1),[pe,q]=d.useState(!1),Z=e.specId?l==null?void 0:l(e.specId):void 0,V=!e.specId&&!!e.branch,me=wt(e,i,x),fe=!e.exited&&!!e.decision,G=!e.exited&&!!e.deciding,ke=fe||G,K=e.exited&&!!e.exitCode,Y=!e.exited&&f,je=K?null:e.exited||Y?"PST-005":ke?"PST-004":"PST-003",J=[...e.specId?[{key:"docs",label:"Lihat dokumen",icon:"file-text",title:"Lihat dokumen (audit/spec/plan)",onSelect:()=>W(!0),render:t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:()=>W(!0),"aria-label":`Lihat dokumen sesi ${e.id}`,title:"Lihat dokumen (audit/spec/plan)",children:t.jsx(ne,{name:"file-text",size:12})},"docs")}]:[],...e.specId&&C?[{key:"review",label:"Review perubahan",icon:"git-compare",title:"Review perubahan (diff worktree)",onSelect:()=>C(e.specId),render:t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:()=>C(e.specId),"aria-label":`Review sesi ${e.id}`,title:"Review perubahan (diff worktree)",children:t.jsx(ne,{name:"git-compare",size:12})},"review")}]:[],...V&&v?[{key:"review-session",label:"Review perubahan",icon:"git-compare",title:"Review perubahan (diff worktree sesi)",onSelect:()=>v(e.id,me),render:t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:()=>v(e.id,me),"aria-label":`Review sesi ${e.id}`,title:"Review perubahan (diff worktree sesi)",children:t.jsx(ne,{name:"git-compare",size:12})},"review-session")}]:[],...Z&&I?[{key:"integrate",label:"Rebase / Merge branch",icon:"git-merge",title:"Rebase / Merge branch spec",onSelect:()=>B(!0),render:t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:()=>B(!0),"aria-label":`Integrasikan sesi ${e.id}`,title:"Rebase / Merge branch spec",children:t.jsx(ne,{name:"git-merge",size:12})},"integrate")}]:[],...V&&h?[{key:"integrate-session",label:"Rebase / Merge branch",icon:"git-merge",title:"Rebase / Merge branch sesi",onSelect:()=>q(!0),render:t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:()=>q(!0),"aria-label":`Integrasikan sesi ${e.id}`,title:"Rebase / Merge branch sesi",children:t.jsx(ne,{name:"git-merge",size:12})},"integrate-session")}]:[],{key:"detach",label:"Lepas dari grid",icon:"unlink",disabled:!r,title:"Lepas dari grid (sesi tetap hidup)",onSelect:o,render:t.jsx("button",{type:"button",className:"hn-terminal-action hn-terminal-action--text",onClick:o,disabled:!r,title:"Lepas dari grid (sesi tetap hidup)",children:"lepas"},"detach")}],we=ca(p,J.length,s?44:28),ee=J.slice(we);return t.jsxs(t.Fragment,{children:[t.jsxs("div",{ref:F,className:"hn-terminal-cell-header",style:{display:"flex",alignItems:"center",gap:8,padding:"4px 8px",flex:"0 0 auto",background:K?"var(--status-err-tint)":e.exited||Y?"var(--status-ok-tint)":ke?"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:[je&&t.jsx(ra,{id:je,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:[me," · ",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 ",We(e.model),e.effort?` · ${e.effort}`:""]}),e.exited&&(K?t.jsx(ge,{status:"failed",size:"sm",children:`Gagal · exit ${e.exitCode}`}):t.jsx(ge,{status:"done",size:"sm",children:"Selesai"})),Y&&t.jsx(ge,{status:"done",size:"sm",children:"Selesai"}),G&&!Y&&t.jsx(ge,{status:"running",size:"sm",children:"Lead memutuskan"}),fe&&!G&&!Y&&t.jsx(ge,{status:"awaiting",size:"sm"}),t.jsxs("span",{className:"hn-terminal-actions",children:[J.slice(0,we).map(O=>O.render),ee.length>0&&t.jsx(ht,{label:`Aksi lain sesi ${e.id}`,items:ee.map(({render:O,..._})=>_)}),t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:E,title:"Layar penuh — fokus 1 terminal","aria-label":`Layar penuh sesi ${e.id}`,children:t.jsx(ne,{name:"fullscreen",size:12})}),t.jsx("button",{type:"button",className:"hn-terminal-action","aria-label":`Tutup sesi ${e.id}`,onClick:n,children:"×"})]})]}),t.jsxs("div",{style:{display:"flex",flexDirection:"column",flex:1,minHeight:0,position:"relative",opacity:e.exited?.6:1},children:[t.jsx(Na,{phases:S,compact:p<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(xt,{sessionId:e.id,onExit:u,onPhases:L,fontSize:k,showKeys:j,predict:g,diag:y},e.id)})]}),P&&e.specId&&t.jsx(sa,{specId:e.specId,onClose:()=>W(!1)}),le&&Z&&I&&t.jsx(tt,{projectId:Z.projectId,ownBranch:`hanoman/${Z.id.toLowerCase().replace(/[^a-z0-9_-]/g,"_")}`,eyebrow:Z.id,onClose:()=>B(!1),onIntegrate:(O,_)=>{B(!1),I(Z,O,_)}}),pe&&V&&h&&t.jsx(tt,{projectId:e.projectId,ownBranch:e.branch,eyebrow:e.id.slice(0,16),onClose:()=>q(!1),onIntegrate:(O,_)=>{q(!1),h(e,O,_)}})]})}function Aa({session:e,label:i,fontSize:n,showKeys:r,predict:o,diag:u,onClose:C}){return t.jsx(be,{open:!0,icon:"terminal",title:i,onClose:C,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(xt,{sessionId:e.id,onExit:()=>{},fontSize:n,showKeys:r,predict:o,diag:u},e.id)})})}function Fa({unplaced:e,nameOf:i,onPick:n,disabled:r}){return t.jsx("div",{style:{flex:1,display:"grid",placeItems:"center",padding:12},children:t.jsx(U,{size:"sm",value:"","aria-label":"Pilih sesi untuk sel",disabled:r||!e.length,onChange:o=>o.target.value&&n(o.target.value),options:[{value:"",label:e.length?"Pilih sesi…":"tidak ada sesi bebas"}].concat(e.map(o=>({value:o.id,label:`${o.specId??i(o.projectId)} · ${o.id.slice(0,6)}`})))})})}export{Na as PhaseStrip,Ma as TerminalScreen};
|