hanoman 0.9.11 → 0.9.13
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 +358 -37
- package/dist/server.js +20667 -17844
- package/package.json +1 -1
- package/prisma/migrations/20261001081455_qa_workspace/migration.sql +85 -0
- package/prisma/migrations/20261001093314_qa_attachment_sync/migration.sql +31 -0
- package/prisma/schema.prisma +97 -0
- package/web/assets/{ChangelogScreen-CYHlMkuo.js → ChangelogScreen-Ceqp0J6L.js} +1 -1
- package/web/assets/{DalangHanomanScreen-BIREPQkt.js → DalangHanomanScreen-CPJtZxV3.js} +1 -1
- package/web/assets/{DocPreviewModal-Dy5PZX3L.js → DocPreviewModal-C_vQOOHV.js} +1 -1
- package/web/assets/{DocsWorkspace-sstV_mwF.js → DocsWorkspace-D4P_5t9b.js} +2 -2
- package/web/assets/{IdeScreen-BoZ21X0r.js → IdeScreen-bD4qiBDt.js} +1 -1
- package/web/assets/{LeadScreen-B8j5AbCq.js → LeadScreen-Db9PHjdT.js} +1 -1
- package/web/assets/{ReviewScreen-9jkwgxsp.js → ReviewScreen-DLlDOQod.js} +1 -1
- package/web/assets/{SchedulerScreen-BmeeP6iC.js → SchedulerScreen-D6ffDlTM.js} +1 -1
- package/web/assets/{SettingsScreen-BpjqRvvn.js → SettingsScreen-72EvmiY4.js} +4 -4
- package/web/assets/{TeamScreen-ftIlQ3wy.js → TeamScreen-CY-5tnPa.js} +1 -1
- package/web/assets/TerminalScreen-CKac8Ti6.js +2 -0
- package/web/assets/{TriageScreen-CMJajN4R.js → TriageScreen-BEb2vxPb.js} +1 -1
- package/web/assets/{VpsScreen-B1tHTxXY.js → VpsScreen-DTJd5Gks.js} +1 -1
- package/web/assets/index-BsjfXxQM.css +32 -0
- package/web/assets/index-DYNYB1Nj.js +1039 -0
- package/web/assets/{live-DZWDT8yU.js → live-nMnpVkPn.js} +1 -1
- package/web/index.html +2 -2
- package/web/assets/TerminalScreen-CQuR2PLL.js +0 -2
- package/web/assets/index-C0hF6fPX.js +0 -1017
- package/web/assets/index-ezlZRsLF.css +0 -32
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{aO as i,j as u,B as f}from"./index-DYNYB1Nj.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,11 +5,11 @@
|
|
|
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-DYNYB1Nj.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">
|
|
12
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
12
|
+
<link rel="stylesheet" crossorigin href="/assets/index-BsjfXxQM.css">
|
|
13
13
|
</head>
|
|
14
14
|
<body>
|
|
15
15
|
<div id="root"></div>
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{e as L,j as t,M as ke,d as yt,S as J,G as _t,J as kt,f as Ye,B as _e,I as ie,w as qt,D as Ut,a as G,K as Vt,N as Yt,O as lt,Q as ot,c as Pe,U as Jt,V as Xt,W as Qt,X as Zt,Y as ea,Z as ta,_ as je,$ as jt,a0 as Je,a1 as aa,a2 as na,a3 as ia,a4 as qe,a5 as ra,h as be,a6 as wt,a7 as sa,a8 as la,a9 as oa,g as We,aa as ca,ab as da,ac as St,l as ua,ad as ct,ae as pa,x as ma,af as fa,ag as ha,ah as Me,p as xa,ai as ga,aj as ba,ak as It,al as va,am as ve,an as ya,ao as dt,ap as ka}from"./index-C0hF6fPX.js";import{R as o,r as $}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";function Xe(e){return e.endedAt?e.endedReason==="reconciled"?"interrupted":e.exitCode===null||e.exitCode===0?"completed":"failed":"running"}const Ae=new Set;let ye;function ja(e){return Ae.add(e),ye||(ye=setInterval(()=>{for(const i of[...Ae])i()},1e3)),()=>{Ae.delete(e),Ae.size===0&&ye&&(clearInterval(ye),ye=void 0)}}const ut=20;function wa(e,i){if(!i)return"—";const n=new Date(i).getTime()-new Date(e).getTime();if(!Number.isFinite(n)||n<0)return"—";const s=Math.round(n/1e3);if(s<60)return`${s} dtk`;const c=Math.round(s/60);return c<60?`${c} mnt`:`${Math.floor(c/60)} jam ${c%60} mnt`}function Sa(e){switch(Xe(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 Ct=e=>Xe(e)==="interrupted"?"—":wa(e.startedAt,e.endedAt),zt=e=>kt[e]??e;function Ia({projects:e,onClose:i,onRestart:n}){const[s,c]=o.useState([]),[d,R]=o.useState(0),[v,T]=o.useState(1),[h,g]=o.useState(!1),[b,u]=o.useState(""),[x,C]=o.useState(""),[w,p]=o.useState(""),[S,z]=o.useState(""),[N,D]=o.useState(null);o.useEffect(()=>{const l=setTimeout(()=>z(w.trim()),250);return()=>clearTimeout(l)},[w]),o.useEffect(()=>{T(1)},[b,x,S]),o.useEffect(()=>{let l=!0;return g(!0),L.listSessionHistory({projectId:b||void 0,kind:x||void 0,q:S||void 0,page:v,limit:ut}).then(f=>{l&&(R(f.total),c(f.items))}).catch(()=>{l&&(c([]),R(0))}).finally(()=>{l&&g(!1)}),()=>{l=!1}},[b,x,S,v]);const k=Ut(d,v,ut),E=l=>{var f;return((f=e.find(I=>I.id===l))==null?void 0:f.name)??l};return t.jsxs(ke,{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(yt,{size:"sm",leftIcon:"search",placeholder:"mis. spec-412 atau reverse","aria-label":"Cari riwayat sesi",value:w,onChange:l=>p(l.target.value),style:{flex:"1 1 200px"}}),t.jsx(J,{size:"sm","aria-label":"Filter project",value:b,onChange:l=>u(l.target.value),options:[{value:"",label:"Semua project"}].concat(e.map(l=>({value:l.id,label:l.name})))}),t.jsx(J,{size:"sm","aria-label":"Filter jenis",value:x,onChange:l=>C(l.target.value),options:[{value:"",label:"Semua jenis"}].concat(_t.map(l=>({value:l,label:kt[l]})))})]}),s.length===0&&!h?t.jsx(Ye,{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:[s.map(l=>{const f=Sa(l);return t.jsx("button",{onClick:()=>D(l),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(l.startedAt).toLocaleString("id-ID")}),t.jsx(_e,{size:"sm",tone:"neutral",children:zt(l.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:l.title??l.specId??E(l.projectId)}),l.transcriptBytes!==null&&t.jsx(ie,{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:Ct(l)}),t.jsx(_e,{size:"sm",tone:f.tone,children:f.label})]})},l.id)}),h&&t.jsx("div",{style:{padding:"10px 8px",textAlign:"center",fontSize:11,color:"var(--text-subtle)"},children:"memuat…"})]}),t.jsx(qt,{page:k.page,pageCount:k.pageCount,total:d,from:k.from,to:k.to,onPage:T,unit:"sesi"}),N&&t.jsx(Ca,{row:N,projectName:E(N.projectId),onBack:()=>D(null),onRestart:n})]})}function Ca({row:e,projectName:i,onBack:n,onRestart:s}){const[c,d]=o.useState(null),[R,v]=o.useState("idle");o.useEffect(()=>{if(e.transcriptBytes===null){v("none"),d(null);return}let g=!0;return v("loading"),L.sessionTranscript(e.id).then(b=>{g&&(d(b.text),v("idle"))}).catch(()=>{g&&(d(null),v("error"))}),()=>{g=!1}},[e.id,e.transcriptBytes]);const T=Xe(e)==="interrupted",h=[["Project",i],["Sesi",e.sessionId],["Jenis",zt(e.kind)],["Agen",[e.agent,e.model,e.effort].filter(Boolean).join(" · ")],["Mulai",new Date(e.startedAt).toLocaleString("id-ID")],[T?"Terakhir terlihat hidup":"Selesai",e.endedAt?new Date(e.endedAt).toLocaleString("id-ID"):"berjalan"],...T&&e.reconciledAt?[["Terdeteksi mati",new Date(e.reconciledAt).toLocaleString("id-ID")]]:[],["Durasi",Ct(e)],["Direktori",e.cwd]];return e.specId&&h.splice(1,0,["Backlog",`${e.specId}${e.title?` · ${e.title}`:""}`]),e.branch&&h.push(["Branch",e.branch]),t.jsxs(ke,{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(G,{size:"sm",variant:"ghost",leftIcon:"arrow-left",onClick:n,children:"Kembali"}),t.jsx("div",{style:{flex:1}}),c&&t.jsx(G,{size:"sm",variant:"secondary",leftIcon:"copy",onClick:()=>{var g;return void((g=navigator.clipboard)==null?void 0:g.writeText(c))},children:"Salin transkrip"}),Vt(e.kind)&&t.jsx(G,{size:"sm",leftIcon:"play",onClick:()=>s(e),children:"Mulai lagi"})]}),T&&t.jsxs(Yt,{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:h.map(([g,b])=>t.jsxs(o.Fragment,{children:[t.jsx("span",{style:{color:"var(--text-subtle)"},children:g}),t.jsx("span",{style:{fontFamily:"var(--font-mono)",color:"var(--text-body)",wordBreak:"break-all"},children:b})]},g))}),R==="loading"&&t.jsx("div",{style:{fontSize:12,color:"var(--text-subtle)"},children:"memuat transkrip…"}),R==="none"&&t.jsx("div",{style:{fontSize:12,color:"var(--text-subtle)"},children:T?"Tanpa transkrip — panenya sudah lenyap sebelum hanoman sempat mengambilnya.":"Tanpa transkrip — sesi ini ditutup sebelum fitur riwayat ada, atau panenya tak menyisakan keluaran."}),R==="error"&&t.jsx("div",{style:{fontSize:12,color:"var(--clay-600)"},children:"Transkrip tak terbaca lagi di server."}),c!==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:c})]})}function za({open:e,projectId:i,projectName:n,onClose:s,onCreated:c}){var D;const[d,R]=o.useState("claude"),[v,T]=o.useState("sonnet"),[h,g]=o.useState("medium"),[b,u]=o.useState({claude:{model:"sonnet",effort:"medium"},codex:{...lt}}),[x,C]=o.useState(!1),[w,p]=o.useState(null);o.useEffect(()=>{e&&(L.getSettings().then(k=>{const E={claude:{model:k.model,effort:k.effort},codex:{...lt,...k.codex??{}}},l=k.agent==="codex"?"codex":"claude",f=ot(E,l);u(E),R(l),T(f.model),g(f.effort)}).catch(()=>{}),L.getCodexVersion().then(k=>p(k.version)).catch(()=>{}))},[e]);const S=k=>{R(k);const E=ot(b,k);T(E.model),g(E.effort)},z=k=>{T(k),g(E=>d==="codex"?ea(k,E):ta(k,E))};async function N(){C(!0);try{const{id:k}=await L.createTerminal(i,{agent:d,model:v,effort:h});c(k),s()}catch{}finally{C(!1)}}return t.jsxs(ke,{open:e,onClose:s,icon:"plus",eyebrow:n,title:"Sesi baru",footer:t.jsxs(t.Fragment,{children:[t.jsx(G,{variant:"ghost",onClick:s,children:"Batal"}),t.jsx(G,{leftIcon:"play",disabled:x,onClick:()=>void N(),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(Pe,{label:"Agen",hint:"Mesin yang menjalankan sesi ini. Perilaku sesi sama; hanya CLI-nya berbeda.",children:t.jsx(J,{"aria-label":"Agen",value:d,style:{width:"100%"},options:[{value:"claude",label:"Claude Code"},{value:"codex",label:"Codex CLI"}],onChange:k=>S(k.target.value)})}),t.jsx(Pe,{label:"Model",children:t.jsx(J,{"aria-label":"Model",value:v,style:{width:"100%"},options:Jt(d,v),onChange:k=>z(k.target.value)})}),t.jsx(Pe,{label:"Effort",children:t.jsx(J,{"aria-label":"Effort",value:h,style:{width:"100%"},options:Xt(d,v).map(k=>({value:k,label:k})),onChange:k=>g(k.target.value)})}),d==="codex"&&Qt(v,w)&&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:w}),", sedangkan ",t.jsx("b",{children:v})," butuh ",t.jsx("b",{children:(D=Zt(v))==null?void 0:D.minClient}),". Sesi tetap boleh dijalankan, tapi modelnya belum tentu dikenali CLI ini."]})]})}const Ra=()=>({rows:1,cols:1,cells:[null]}),pt=e=>({...e,rows:e.rows+1,cells:[...e.cells,...Array(e.cols).fill(null)]});function mt(e){const i=e.cols+1,n=[];for(let s=0;s<e.rows;s++)for(let c=0;c<i;c++)n.push(c<e.cols?e.cells[s*e.cols+c]??null:null);return{rows:e.rows,cols:i,cells:n}}function ft(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 ht(e,i){if(e.cols===1||i<0||i>=e.cols)return e;const n=e.cols-1,s=[];for(let c=0;c<e.rows;c++)for(let d=0;d<e.cols;d++)d!==i&&s.push(e.cells[c*e.cols+d]??null);return{rows:e.rows,cols:n,cells:s}}function Ue(e,i,n){if(i<0||i>=e.cells.length)return e;const s=e.cells.map(c=>n!==null&&c===n?null:c);return s[i]=n,{...e,cells:s}}const Ta=(e,i)=>({...e,cells:e.cells.map(n=>n&&i.has(n)?n:null)}),Rt=e=>({id:crypto.randomUUID(),name:e,layout:Ra()});function xt(){const e=Rt("Utama");return{groups:[e],active:e.id}}const we=e=>e.groups.find(i=>i.id===e.active)??e.groups[0];function Ea(e,i){const n=Rt(i);return{groups:[...e.groups,n],active:n.id}}const Na=(e,i,n)=>({...e,groups:e.groups.map(s=>s.id===i?{...s,name:n}:s)});function Aa(e,i){if(e.groups.length===1)return e;const n=e.groups.filter(s=>s.id!==i);return n.length===e.groups.length?e:{groups:n,active:e.active===i?n[0].id:e.active}}const La=(e,i)=>e.groups.some(n=>n.id===i)?{...e,active:i}:e;function ne(e,i){const n=we(e);return{...e,groups:e.groups.map(s=>s.id===n.id?{...s,layout:i(s.layout)}:s)}}function Ve(e,i,n){const s=we(e),c=n===null?e.groups:e.groups.map(d=>d.id===s.id?d:{...d,layout:Ue(d.layout,d.layout.cells.indexOf(n),null)});return{...e,groups:c.map(d=>d.id===s.id?{...d,layout:Ue(d.layout,i,n)}:d)}}function ue(e,i){const n=we(e).layout.cells.indexOf(null);return n===-1?e:Ve(e,n,i)}const Fa=(e,i)=>({...e,groups:e.groups.map(n=>({...n,layout:Ue(n.layout,n.layout.cells.indexOf(i),null)}))}),gt=e=>new Set(e.groups.flatMap(i=>i.layout.cells.filter(n=>n!==null))),bt=(e,i)=>({...e,groups:e.groups.map(n=>({...n,layout:Ta(n.layout,i)}))}),Tt="hanoman.terminal.workspace",Et="hanoman.terminal.layout",pe=e=>je.parse({version:1,groups:e.groups});function Le(e,i){const n=e.groups,s=i&&n.some(c=>c.id===i)?i:n[0].id;return{groups:n,active:s}}function $a(e){try{const i=JSON.parse(e);if(!i||typeof i!="object")return null;const n=i,s=je.parse({version:1,groups:n.groups});return{workspace:s,active:typeof n.active=="string"&&s.groups.some(c=>c.id===n.active)?n.active:s.groups[0].id}}catch{return null}}function Ba(){try{const e=localStorage.getItem(Tt);if(e)return $a(e);const i=localStorage.getItem(Et);if(!i)return null;const n=JSON.parse(i),s={id:crypto.randomUUID(),name:"Utama",layout:n};return{workspace:je.parse({version:1,groups:[s]}),active:s.id}}catch{return null}}function He(){try{localStorage.removeItem(Tt),localStorage.removeItem(Et)}catch{}}const Nt=e=>`hanoman.terminal.workspace.v2.${encodeURIComponent(e)}`;function Da(e){try{const i=localStorage.getItem(Nt(e));if(!i)return null;const n=JSON.parse(i),s=je.parse(n.workspace);if(!Number.isInteger(n.revision)||(n.revision??-1)<0)return null;const c=typeof n.active=="string"&&s.groups.some(d=>d.id===n.active)?n.active:s.groups[0].id;return{workspace:s,revision:n.revision,active:c}}catch{return null}}function Ge(e,i){try{const n=je.parse(i.workspace);if(!Number.isInteger(i.revision)||i.revision<0)return;const s=n.groups.some(c=>c.id===i.active)?i.active:n.groups[0].id;localStorage.setItem(Nt(e),JSON.stringify({workspace:n,revision:i.revision,active:s}))}catch{}}function Ke(e){if(!(e instanceof Je)||e.status!==409)return null;const i=e.detail;if((i==null?void 0:i.code)!=="revision-conflict")return null;const n=aa.safeParse(i.current);return n.success?n.data:null}function Oa(e){const i=$.useRef(null);i.current||(i.current=xt());const[n,s]=$.useState(i.current),[c,d]=$.useState("loading"),[R,v]=$.useState(null),[T,h]=$.useState(!1),g=$.useRef(n),b=$.useRef(0),u=$.useRef(!1),x=$.useRef(Promise.resolve()),C=$.useRef(0),w=$.useCallback(l=>{g.current=l,s(l)},[]),p=$.useCallback(l=>{u.current=l,h(l)},[]),S=$.useCallback(l=>{const f=x.current.then(l,l);return x.current=f.then(()=>{},()=>{}),f},[]),z=$.useCallback((l,f="ready",I=null,y=g.current.active)=>{const O=l.workspace?Le(l.workspace,y):xt();b.current=l.revision,w(O),d(f),v(I),p(!0),l.workspace&&Ge(e,{workspace:l.workspace,revision:l.revision,active:O.active})},[w,p,e]),N=$.useCallback(l=>{const f=Da(e);f&&(b.current=f.revision,w(Le(f.workspace,f.active))),p(!1),d("recovering"),v(l instanceof Error?l.message:"Layout server belum tersambung")},[w,p,e]),D=$.useCallback(()=>S(async()=>{try{z(await L.getTerminalWorkspace())}catch(l){N(l)}}),[z,S,N]);$.useEffect(()=>{const l=++C.current;return d("loading"),v(null),p(!1),S(async()=>{try{const f=await L.getTerminalWorkspace();if(l!==C.current)return;if(f.workspace){z(f),He();return}const I=Ba();if(!I){z(f);return}try{const y=await L.putTerminalWorkspace({baseRevision:f.revision,workspace:I.workspace});if(l!==C.current)return;w(Le(y.workspace,I.active)),b.current=y.revision,Ge(e,{workspace:y.workspace,revision:y.revision,active:I.active}),He(),d("ready"),v(null),p(!0)}catch(y){const O=Ke(y);O!=null&&O.workspace?(z(O,"conflict","Layout server lebih baru; layout lokal lama tidak diunggah"),He()):N(y)}}catch(f){l===C.current&&N(f)}}),()=>{C.current+=1}},[z,S,N,w,p,e]),$.useEffect(()=>{const l=()=>{D()},f=()=>{document.visibilityState==="visible"&&D()};return window.addEventListener("focus",l),document.addEventListener("visibilitychange",f),()=>{window.removeEventListener("focus",l),document.removeEventListener("visibilitychange",f)}},[D]);const k=$.useCallback(l=>S(async()=>{if(!u.current)return!1;const f=l(g.current);let I,y;try{I=pe(f),y=pe(g.current)}catch{return d("conflict"),v("Layout tidak valid dan tidak disimpan"),!1}if(jt(I,y))return!0;try{return z(await L.putTerminalWorkspace({baseRevision:b.current,workspace:I}),"ready",null,f.active),!0}catch(O){const X=Ke(O);if(!(X!=null&&X.workspace))return N(O),!1;const M=l(Le(X.workspace,g.current.active));try{const _=await L.putTerminalWorkspace({baseRevision:X.revision,workspace:pe(M)});return z(_,"conflict","Layout berubah di perangkat lain; perubahan ini diterapkan ulang",M.active),!0}catch(_){if(!Ke(_)&&!(_ instanceof Je&&_.status===409))return N(_),!1;try{z(await L.getTerminalWorkspace(),"conflict","Layout berubah lagi di perangkat lain; state terbaru dimuat")}catch(Q){N(Q)}return!1}}}),[z,S,N]),E=$.useCallback(l=>{const f=La(g.current,l);w(f);const I=pe(f);Ge(e,{workspace:I,revision:b.current,active:f.active})},[w,e]);return{workspace:n,status:c,message:R,writable:T,mutate:k,setActive:E,refresh:D}}const Pa=[];function tn({userId:e="test-user",projects:i,backlog:n=Pa,focusSession:s,startedSession:c,onStartedSessionHandled:d,onStartBacklog:R,onOpenReview:v,onOpenSessionReview:T,titleOf:h,onIntegrate:g,onIntegrateSession:b,specOf:u,sessions:x,setSessions:C}){var st;const[w,p]=o.useState([]),S=x??w,z=C??p,[N,D]=o.useState([]),k=Oa(e),{workspace:E,status:l,message:f,writable:I,mutate:y,setActive:O,refresh:X}=k,[M,_]=be("terminal","project",((st=i[0])==null?void 0:st.id)??"",xa),Q=wt(),[re,le]=be("terminal","fontSize",Q?fa:ha,ma),[q,me]=be("terminal","keys",Q,Me),[Z,fe]=be("terminal","predict",!0,Me),[V,Se]=be("terminal","diag",!1,Me),oe=a=>le(r=>pa(r+a)),[B,Ie]=o.useState(!1),[K,he]=o.useState(null),[Ce,te]=o.useState(!1),[H,P]=o.useState(null),[Fe,xe]=o.useState(!1),[ze,Re]=o.useState(!1),$e=sa(),W=la()==="mobile",[Y,Te]=o.useState(0),[ee,ae]=o.useState(null),Be=o.useRef(null),[ce,Lt]=o.useState(!1);o.useEffect(()=>{L.listTerminals().then(a=>{z(a),Lt(!0)}).catch(()=>{})},[]),o.useEffect(()=>oa(a=>{a.t==="sessions"&&!x?z(a.sessions):a.t==="cleanups"&&D(a.cleanups)}),[]),o.useEffect(()=>{if(!ce||!I)return;const a=new Set(S.map(m=>m.id)),r=bt(E,a);jt(pe(r),pe(E))||y(m=>bt(m,a))},[y,S,ce,I,E]),o.useEffect(()=>{!c||c.specId==null||!ce||(z(a=>a.some(r=>r.id===c.id)?a:[...a,{...c,cwd:"",exited:!1}]),ae(c.id),d==null||d())},[d,ce,c]),o.useEffect(()=>{if(!s){Be.current=null;return}!ce||Be.current===s||S.some(a=>a.id===s&&!a.exited)&&(Be.current=s,ae(s))},[s,S,ce]),o.useEffect(()=>{if(!ee)return;const a=E.groups.find(r=>r.layout.cells.includes(ee));if(a){a.id!==E.active&&O(a.id);return}I&&y(r=>{if(gt(r).has(ee))return r;const m=ue(r,ee);return m!==r||!W?m:Ve(r,Y,ee)})},[Y,W,y,ee,O,I,E]),o.useEffect(()=>{K&&!S.some(a=>a.id===K)&&he(null)},[K,S]);const De=N.filter(a=>a.error),Ee=a=>S.find(r=>r.id===a)??null,ge=o.useCallback(a=>{var r;return((r=i.find(m=>m.id===a))==null?void 0:r.name)??a},[i]);function Ft(a){z(r=>r.some(m=>m.id===a)?r:[...r,{id:a,projectId:M,cwd:"",exited:!1}]),y(r=>ue(r,a)),ae(a)}async function Qe(){if(!M)return;const{id:a}=await L.createShell(M);z(r=>[...r,{id:a,projectId:M,cwd:"",exited:!1}]),y(r=>ue(r,a)),ae(a)}async function Ze(a,r){if(R&&!r){te(!1),P(null),R(a);return}const m=ba(a.source);try{const{id:j}=await L.startSession({spec:a.id,flow:m,...r?{force:r}:{}});z(A=>A.some(se=>se.id===j)?A:[...A,{id:j,projectId:a.projectId,specId:a.id,flow:m,cwd:"",exited:!1}]),y(A=>ue(A,j)),ae(j),te(!1),P(null)}catch(j){if($e.offerRetry(j,a.id,se=>Ze(a,se)))return;const A=j instanceof Je&&(j.status===400||j.status===422);P(`${a.id} · gagal mulai${A?" · project belum punya repoDir":""}`)}}async function et(a,r){try{const m=a.specId?await L.startSession({spec:a.specId,flow:a.flow??"feature",agent:a.agent==="codex"?"codex":"claude",...a.model?{model:a.model}:{},...a.effort?{effort:a.effort}:{},...r?{force:r}:{}}):a.kind==="shell"?await L.createShell(a.projectId):a.kind==="terminal"?await L.createTerminal(a.projectId,{agent:a.agent==="codex"?"codex":"claude",...a.model?{model:a.model}:{},...a.effort?{effort:a.effort}:{}}):await(r?L.createTerminalFlow(a.projectId,a.kind,{force:r}):L.createTerminalFlow(a.projectId,a.kind));z(j=>j.some(A=>A.id===m.id)?j:[...j,{id:m.id,projectId:a.projectId,specId:a.specId??void 0,cwd:"",exited:!1}]),y(j=>ue(j,m.id)),ae(m.id),Re(!1)}catch(m){if((a.specId||a.kind!=="shell"&&a.kind!=="terminal")&&$e.offerRetry(m,`${a.projectId} · ${a.title??a.specId??a.kind}`,j=>et(a,j)))return}}const tt=new Set(S.filter(a=>a.specId&&!a.exited).map(a=>a.specId)),$t=n.filter(a=>a.stage!=="done"&&!tt.has(a.id));function at(a){z(r=>r.filter(m=>m.id!==a)),L.deleteTerminal(a).catch(()=>{})}const Bt=o.useCallback((a,r)=>{z(m=>m.map(j=>j.id===a?{...j,exited:!0,exitCode:r}:j))},[]),nt={close:at,detach:a=>{y(r=>Fa(r,a))},markExited:Bt,setFullId:he,props:{onOpenReview:v,onOpenSessionReview:T,titleOf:h,onIntegrate:g,onIntegrateSession:b,specOf:u}},U=o.useRef(nt);U.current=nt;const it=o.useRef(new Map),Dt=a=>{let r=it.current.get(a);return r||(r={onClose:()=>void U.current.close(a),onDetach:()=>U.current.detach(a),onExit:m=>U.current.markExited(a,m),onFullscreen:()=>U.current.setFullId(a)},it.current.set(a,r)),r},de=o.useRef({onOpenReview:a=>{var r,m;return(m=(r=U.current.props).onOpenReview)==null?void 0:m.call(r,a)},onOpenSessionReview:(a,r)=>{var m,j;return(j=(m=U.current.props).onOpenSessionReview)==null?void 0:j.call(m,a,r)},titleOf:a=>{var r,m;return(m=(r=U.current.props).titleOf)==null?void 0:m.call(r,a)},onIntegrate:(a,r,m)=>{var j,A;return(A=(j=U.current.props).onIntegrate)==null?void 0:A.call(j,a,r,m)},onIntegrateSession:(a,r,m)=>{var j,A;return(A=(j=U.current.props).onIntegrateSession)==null?void 0:A.call(j,a,r,m)},specOf:a=>{var r,m;return(m=(r=U.current.props).specOf)==null?void 0:m.call(r,a)}}).current,Ot=(a,r)=>{Te(a),y(m=>Ve(m,a,r))},Pt=a=>{ae(a),y(r=>ue(r,a))},Wt=gt(E),Oe=S.filter(a=>!Wt.has(a.id)),F=we(E).layout;o.useEffect(()=>{if(!ee)return;const a=F.cells.indexOf(ee);a<0||(Te(a),ae(null))},[F.cells,ee]),o.useEffect(()=>{Y>=F.cells.length&&Te(Math.max(0,F.cells.length-1))},[Y,F.cells.length]);const rt=F.rows===1&&F.cols===1&&!F.cells[0]&&S.length===0,Mt=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(We,{size:"sm",icon:"minus",label:"Perkecil teks terminal",disabled:re<=ca,onClick:()=>oe(-1)}),t.jsxs("span",{style:{fontFamily:"var(--font-mono)",fontSize:12,minWidth:44,textAlign:"center"},children:[re,"px"]}),t.jsx(We,{size:"sm",icon:"plus",label:"Perbesar teks terminal",disabled:re>=da,onClick:()=>oe(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(G,{size:"sm",variant:"secondary","aria-pressed":q,onClick:()=>me(a=>!a),children:q?"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(G,{size:"sm",variant:"secondary","aria-pressed":Z,"aria-label":`${Z?"Matikan":"Nyalakan"} ketik responsif`,onClick:()=>fe(a=>!a),children:Z?"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(G,{size:"sm",variant:"secondary","aria-pressed":V,"aria-label":`${V?"Matikan":"Nyalakan"} rekam jalur ketik`,onClick:()=>Se(a=>!a),children:V?"Matikan":"Nyalakan"})]}),W&&t.jsx(J,{size:"sm","aria-label":"Project sesi baru",value:M,onChange:a=>_(a.target.value),options:i.map(a=>({value:a.id,label:a.name}))})]}),Ht=[{key:"backlog",label:"Ambil backlog",icon:"inbox",onSelect:()=>{P(null),te(!0)}},{key:"history",label:"Riwayat sesi",icon:"history",onSelect:()=>Re(!0)},{key:"shell",label:"Terminal biasa",icon:"terminal",onSelect:()=>void Qe()},{key:"col+",label:"+ Kolom",icon:"columns-2",disabled:!I,onSelect:()=>void y(a=>ne(a,mt))},{key:"row+",label:"+ Baris",icon:"rows-2",disabled:!I,onSelect:()=>void y(a=>ne(a,pt))},{key:"col-",label:"Hapus kolom aktif",icon:"columns-2",disabled:!I||F.cols===1,onSelect:()=>void y(a=>ne(a,r=>ht(r,Y%r.cols)))},{key:"row-",label:"Hapus baris aktif",icon:"rows-2",disabled:!I||F.rows===1,onSelect:()=>void y(a=>ne(a,r=>ft(r,Math.floor(Y/r.cols))))}],Gt={display:"flex",flexDirection:"column",gap:B?8:12,...B?{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:Gt,children:[t.jsxs("div",{style:{display:"flex",gap:8,flexDirection:B?"row":"column",alignItems:B?"center":"stretch"},children:[t.jsx(Ma,{compact:B,ws:E,writable:I,onSelect:O,onAdd:()=>void y(a=>Ea(a,`Grup ${a.groups.length+1}`)),onRename:(a,r)=>void y(m=>Na(m,a,r)),onRemove:a=>void y(r=>Aa(r,a))}),t.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,flexWrap:"wrap",...B?{flex:1,minWidth:0}:{}},children:[!W&&t.jsxs(t.Fragment,{children:[t.jsx(G,{size:"sm",variant:"ghost",disabled:!I,onClick:()=>void y(a=>ne(a,mt)),children:"+ Kolom"}),t.jsx(G,{size:"sm",variant:"ghost",disabled:!I,onClick:()=>void y(a=>ne(a,pt)),children:"+ Baris"})]}),t.jsx("div",{style:{flex:1,minWidth:0}}),l!=="ready"&&t.jsx("span",{"data-testid":"terminal-workspace-status",title:f??void 0,style:{fontSize:12,color:l==="conflict"?"var(--status-warn)":"var(--text-muted)"},children:l==="loading"?"Memuat layout server…":l==="recovering"?t.jsxs(t.Fragment,{children:[t.jsx("span",{children:"Layout server belum tersambung"})," ",t.jsx("button",{type:"button",onClick:()=>void X(),children:"Retry"})]}):f??"Layout berubah di perangkat lain"}),N.length>0&&t.jsx("span",{"data-testid":"worktree-cleanups",title:N.map(a=>`${a.sessionId}${a.error?` — ${a.error}`:""}`).join(`
|
|
2
|
-
`),style:{fontSize:12,color:De.length?"var(--status-err)":"var(--text-muted)"},children:De.length?`${De.length} worktree gagal dibersihkan`:`membersihkan ${N.length} worktree…`}),!W&&t.jsxs(t.Fragment,{children:[t.jsx(J,{size:"sm",value:M,onChange:a=>_(a.target.value),options:i.map(a=>({value:a.id,label:a.name}))}),t.jsx(G,{size:"sm",variant:"secondary",leftIcon:"inbox",onClick:()=>{P(null),te(!0)},children:"Ambil backlog"}),t.jsx(G,{size:"sm",variant:"secondary",leftIcon:"history",title:"Riwayat sesi yang sudah berlalu — buka kembali atau baca transkripnya",onClick:()=>Re(!0),children:"Riwayat"}),t.jsx(G,{size:"sm",variant:"secondary",leftIcon:"terminal",title:"Buka shell tmux tanpa Claude di project terpilih — jalankan command di project",onClick:()=>void Qe(),children:"Terminal biasa"})]}),t.jsx(G,{size:"sm",leftIcon:"plus",onClick:()=>xe(!0),children:"Sesi baru"}),t.jsx(St,{label:W?"Aksi terminal lain":"Tampilan terminal",items:W?Ht:[],children:Mt}),t.jsx(We,{size:"sm",icon:B?"minimize-2":"maximize-2",label:B?"Keluar layar penuh":"Layar penuh","aria-pressed":B,onClick:()=>Ie(a=>!a)})]})]}),Oe.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:"}),Oe.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:!I,onClick:()=>Pt(a.id),title:"Taruh di sel kosong pertama grup ini",style:{all:"unset",cursor:"pointer"},children:[a.specId??ge(a.projectId)," · ",a.id.slice(0,6)]}),t.jsx("button",{type:"button",className:"hn-terminal-action","aria-label":`Tutup sesi ${a.id}`,onClick:()=>void at(a.id),children:"×"})]},a.id))]}),W&&!rt&&t.jsx("div",{className:"hn-stack-mobile",style:{display:"flex",alignItems:"center",gap:8},children:t.jsx(ua,{"aria-label":"Panel terminal",variant:"pill",value:String(Y),onChange:a=>Te(Number(a)),tabs:F.cells.map((a,r)=>({value:String(r),label:`Panel ${r+1}${a?` · ${a.slice(0,6)}`:" · kosong"}`}))})}),rt?t.jsx(Ye,{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:W?"minmax(0, 1fr)":`18px repeat(${F.cols}, minmax(0, 1fr))`,gridTemplateRows:W?"minmax(0, 1fr)":`16px repeat(${F.rows}, minmax(0, 1fr))`},children:[!W&&t.jsx("div",{}),!W&&Array.from({length:F.cols},(a,r)=>t.jsx(vt,{label:`Tutup kolom ${r+1}`,disabled:!I||F.cols===1,onClick:()=>void y(m=>ne(m,j=>ht(j,r)))},`col-${r}`)),Array.from({length:F.rows},(a,r)=>t.jsxs(o.Fragment,{children:[!W&&t.jsx(vt,{label:`Tutup baris ${r+1}`,disabled:!I||F.rows===1,onClick:()=>void y(m=>ne(m,j=>ft(j,r)))}),Array.from({length:F.cols},(m,j)=>{const A=r*F.cols+j,se=F.cells[A]??null,Ne=se?Ee(se):null;return t.jsx("div",{"data-terminal-cell-index":A,"aria-hidden":W&&Y!==A?"true":"false",style:{minHeight:0,minWidth:0,display:W&&Y!==A?"none":"flex",flexDirection:"column",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",overflow:"hidden"},children:Ne?t.jsx(qa,{session:Ne,nameOf:ge,...Dt(Ne.id),canArrange:I,onReview:v&&de.onOpenReview,onSessionReview:T&&de.onOpenSessionReview,titleOf:h&&de.titleOf,onIntegrate:g&&de.onIntegrate,onIntegrateSession:b&&de.onIntegrateSession,specOf:u&&de.specOf,backlog:n,fontSize:re,showKeys:q,predict:Z,diag:V,fullscreen:K===Ne.id,paneHidden:W&&Y!==A}):t.jsx(Ya,{disabled:!I,unplaced:Oe,nameOf:ge,onPick:Kt=>Ot(A,Kt)})},se??`empty-${A}`)})]},`row-${r}`))]}),Ce&&t.jsx(Wa,{seed:$t,activeIds:tt,error:H,onPick:a=>void Ze(a),onClose:()=>te(!1)}),Fe&&t.jsx(za,{open:!0,projectId:M,projectName:ge(M),onClose:()=>xe(!1),onCreated:Ft}),ze&&t.jsx(Ia,{projects:i,onClose:()=>Re(!1),onRestart:a=>void et(a)}),$e.dialog,K&&Ee(K)&&t.jsx(Va,{session:Ee(K),label:At(Ee(K),ge,h),fontSize:re,showKeys:q,predict:Z,diag:V,onClose:()=>he(null)})]})}function At(e,i,n){const s=i(e.projectId),c=e.specId?n==null?void 0:n(e.specId):void 0;return e.specId?`${s} · ${e.specId}${c?` · ${c}`:""}`:e.id.startsWith("xaudit-")?`${s} · audit lintas`:s}function Wa({seed:e,activeIds:i,error:n,onPick:s,onClose:c}){const[d,R]=o.useState(""),[v,T]=o.useState("all"),[h,g]=o.useState("all"),[b,u]=o.useState(e),[x,C]=o.useState("");o.useEffect(()=>{const p=setTimeout(()=>C(d.trim()),250);return()=>clearTimeout(p)},[d]),o.useEffect(()=>{var z,N;let p=!0;const S=(N=(z=L).listSpecs)==null?void 0:N.call(z,{startable:!0,q:x||void 0,stage:v==="all"?void 0:v,priority:h==="all"?void 0:h});return S==null||S.then(D=>{p&&u(D.items)}).catch(()=>{}),()=>{p=!1}},[x,v,h]);const w=b.filter(p=>!i.has(p.id));return t.jsxs(ke,{open:!0,title:"Ambil backlog",icon:"inbox",onClose:c,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(yt,{size:"sm",leftIcon:"search",placeholder:"mis. invoice atau SPEC-412","aria-label":"Cari backlog",value:d,onChange:p=>R(p.target.value),style:{flex:"1 1 220px"}}),t.jsx(J,{size:"sm","aria-label":"Filter stage",value:v,onChange:p=>T(p.target.value),options:[{value:"all",label:"Semua stage"}].concat(ga.filter(p=>p.key!=="done").map(p=>({value:p.key,label:p.label})))}),t.jsx(J,{size:"sm","aria-label":"Filter prioritas",value:h,onChange:p=>g(p.target.value),options:[{value:"all",label:"Semua prioritas"},{value:"tinggi",label:"Tinggi"},{value:"sedang",label:"Sedang"},{value:"rendah",label:"Rendah"}]})]}),w.length===0?t.jsx(Ye,{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:w.map(p=>t.jsx("button",{onClick:()=>s(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(ie,{name:p.source==="qa"?"bug":p.source==="audit"?"search":"lightbulb",size:14,color:p.source==="qa"?"var(--clay-500)":p.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:p.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:p.title}),t.jsx(_e,{tone:p.priority==="tinggi"?"err":"neutral",size:"sm",children:p.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:p.projectId})]})},p.id))})]})}function Ma({ws:e,compact:i=!1,writable:n,onSelect:s,onAdd:c,onRename:d,onRemove:R}){const[v,T]=o.useState(null),h=we(e),g=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((b,u)=>{const x=b.id===h.id;return v===b.id?t.jsx(Ha,{initial:b.name,onCommit:C=>{C.trim()&&d(b.id,C.trim()),T(null)},onCancel:()=>T(null)},b.id):t.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:4,padding:"3px 6px",borderRadius:"var(--radius-sm)",fontSize:12,background:x?"var(--bone-200)":"transparent",border:`1px solid ${x?"var(--border-hair)":"transparent"}`},children:[t.jsx("button",{className:"hn-terminal-group-control",role:"tab","aria-selected":x,tabIndex:x?0:-1,onClick:()=>s(b.id),onKeyDown:C=>{var p,S;let w=null;C.key==="ArrowRight"?w=(u+1)%e.groups.length:C.key==="ArrowLeft"?w=(u-1+e.groups.length)%e.groups.length:C.key==="Home"?w=0:C.key==="End"&&(w=e.groups.length-1),w!==null&&(C.preventDefault(),s(e.groups[w].id),(S=(p=C.currentTarget.closest('[role="tablist"]'))==null?void 0:p.querySelectorAll('[role="tab"]')[w])==null||S.focus())},style:{border:0,padding:0,background:"transparent",font:"inherit",cursor:"pointer",color:x?"var(--text-strong)":"var(--text-muted)"},children:b.name}),x&&n&&t.jsxs(t.Fragment,{children:[t.jsx("button",{className:"hn-terminal-group-control","aria-label":`Ganti nama grup ${b.name}`,title:"Ganti nama",onClick:()=>T(b.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 ${b.name}`,title:g?"Grup terakhir tak bisa dihapus":"Hapus grup (sesi tetap hidup)",disabled:g,onClick:()=>R(b.id),style:{border:0,padding:0,background:"transparent",cursor:g?"not-allowed":"pointer",color:"var(--text-subtle)",opacity:g?.35:1},children:"×"})]})]},b.id)}),t.jsx("button",{className:"hn-terminal-group-control","aria-label":"Grup baru",title:"Grup baru",disabled:!n,onClick:c,style:{border:0,background:"transparent",cursor:"pointer",padding:"3px 8px",color:"var(--text-subtle)",fontSize:12},children:"+"})]})}function vt({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 Ha({initial:e,onCommit:i,onCancel:n}){const[s,c]=o.useState(e);return t.jsx("input",{autoFocus:!0,"aria-label":"Nama grup",value:s,placeholder:"mis. Rilis",onChange:d=>c(d.target.value),onBlur:()=>i(s),onKeyDown:d=>{d.key==="Enter"?i(s):d.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 Ga={done:"var(--brass)",active:"var(--text-strong)",skipped:"var(--text-subtle)",pending:"var(--text-subtle)"},Ka={done:"✓",running:"●",pending:"○",skipped:"–",failed:"✕",abandoned:"⨯"};function _a({phases:e,compact:i=!1,now:n}){const[s,c]=o.useState(null),d=na(s!==null,()=>c(null),"dialog"),[,R]=o.useState(0),v=!!(e!=null&&e.some(u=>{var x;return((x=u.agent)==null?void 0:x.status)==="running"}));if(o.useEffect(()=>{if(!(!v||n!==void 0))return ja(()=>R(u=>u+1))},[v,n]),!(e!=null&&e.length))return null;const T=n??Date.now(),h=e.find(u=>u.name===s&&u.agent),g=u=>({color:Ga[u.state],fontWeight:u.state==="active"?600:400,textDecoration:u.state==="skipped"?"line-through":"none",opacity:u.state==="pending"?.5:1}),b=u=>{const x=u.agent;return x?typeof x.durationMs=="number"?ct(x.durationMs):x.status==="running"&&x.startedAt?ct(T-Date.parse(x.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(u=>{if(!u.agent)return t.jsx("span",{"data-state":u.state,title:u.state,style:g(u),children:u.name},u.name);const x=u.agent,C=ia(u),w=!i||u.state==="active",p=b(u);return t.jsxs("button",{type:"button","data-tone":C,"aria-expanded":s===u.name,ref:s===u.name?d.triggerRef:void 0,"aria-haspopup":"dialog","aria-controls":s===u.name?d.panelId:void 0,"aria-label":ra(u,p),onClick:()=>c(s===u.name?null:u.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:Ka[C]}),t.jsx("span",{"data-state":u.state,title:u.state,style:g(u),children:u.name}),u.state==="skipped"&&t.jsx("span",{children:"dilewati"}),w&&x.model&&t.jsxs("span",{children:["· ",qe(x.model)]}),w&&x.effort&&t.jsxs("span",{children:["· ",x.effort]}),w&&p&&t.jsxs("span",{children:["· ",p]}),x.attempts>1&&t.jsxs("span",{children:["↻",x.attempts]}),x.evidence==="missing"&&t.jsx("span",{role:"img","aria-label":"bukti subagent tak diterima",title:"bukti subagent tak diterima",style:{color:"var(--status-warn)"},children:"⚠"})]},u.name)})}),(h==null?void 0:h.agent)&&t.jsxs("div",{ref:d.panelRef,id:d.panelId,role:"dialog","aria-label":`Detail fase ${h.name}`,tabIndex:-1,onKeyDown:d.onKeyDown,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:h.agent.name})}),t.jsx("div",{children:[qe(h.agent.model),h.agent.effort,h.agent.status??"belum mulai"].filter(Boolean).join(" · ")}),t.jsxs("div",{children:["durasi ",b(h)||"—"," · percobaan ",h.agent.attempts]}),t.jsxs("div",{children:["token in ",h.agent.inputTokens??"—"," · out ",h.agent.outputTokens??"—"," · cache ",h.agent.cachedTokens??"—"]}),h.agent.resultExcerpt&&t.jsx("pre",{style:{margin:"6px 0 0",whiteSpace:"pre-wrap",maxHeight:160,overflow:"auto"},children:h.agent.resultExcerpt})]})]})}const qa=o.memo(Ua);function Ua({session:e,nameOf:i,onClose:n,canArrange:s,onDetach:c,onExit:d,onReview:R,onSessionReview:v,titleOf:T,onIntegrate:h,onIntegrateSession:g,specOf:b,fontSize:u,showKeys:x,predict:C,diag:w,fullscreen:p,onFullscreen:S,paneHidden:z}){const[N,D]=o.useState(null),k=o.useRef(null),[E,l]=o.useState(Number.POSITIVE_INFINITY),f=wt();o.useEffect(()=>{const H=k.current;if(!H||typeof ResizeObserver!="function")return;const P=new ResizeObserver(Fe=>{var ze;const xe=((ze=Fe[0])==null?void 0:ze.contentRect.width)??H.getBoundingClientRect().width;xe>0&&l(xe)});return P.observe(H),()=>P.disconnect()},[]);const[I,y]=o.useState(!1),O=o.useCallback((H,P)=>{D(H),y(P)},[]),[X,M]=o.useState(!1),[_,Q]=o.useState(!1),[re,le]=o.useState(!1),q=e.specId?b==null?void 0:b(e.specId):void 0,me=!e.specId&&!!e.branch,Z=At(e,i,T),fe=!e.exited&&!!e.decision,V=!e.exited&&!!e.deciding,Se=fe||V,oe=e.exited&&!!e.exitCode,B=!e.exited&&I,Ie=oe?null:e.exited||B?"PST-005":Se?"PST-004":"PST-003",K=[...e.specId?[{key:"docs",label:"Lihat dokumen",icon:"file-text",title:"Lihat dokumen (audit/spec/plan)",onSelect:()=>M(!0),render:t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:()=>M(!0),"aria-label":`Lihat dokumen sesi ${e.id}`,title:"Lihat dokumen (audit/spec/plan)",children:t.jsx(ie,{name:"file-text",size:12})},"docs")}]:[],...e.specId&&R?[{key:"review",label:"Review perubahan",icon:"git-compare",title:"Review perubahan (diff worktree)",onSelect:()=>R(e.specId),render:t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:()=>R(e.specId),"aria-label":`Review sesi ${e.id}`,title:"Review perubahan (diff worktree)",children:t.jsx(ie,{name:"git-compare",size:12})},"review")}]:[],...me&&v?[{key:"review-session",label:"Review perubahan",icon:"git-compare",title:"Review perubahan (diff worktree sesi)",onSelect:()=>v(e.id,Z),render:t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:()=>v(e.id,Z),"aria-label":`Review sesi ${e.id}`,title:"Review perubahan (diff worktree sesi)",children:t.jsx(ie,{name:"git-compare",size:12})},"review-session")}]:[],...q&&h?[{key:"integrate",label:"Rebase / Merge branch",icon:"git-merge",title:"Rebase / Merge branch spec",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 spec",children:t.jsx(ie,{name:"git-merge",size:12})},"integrate")}]:[],...me&&g?[{key:"integrate-session",label:"Rebase / Merge branch",icon:"git-merge",title:"Rebase / Merge branch sesi",onSelect:()=>le(!0),render:t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:()=>le(!0),"aria-label":`Integrasikan sesi ${e.id}`,title:"Rebase / Merge branch sesi",children:t.jsx(ie,{name:"git-merge",size:12})},"integrate-session")}]:[],{key:"detach",label:"Lepas dari grid",icon:"unlink",disabled:!s,title:"Lepas dari grid (sesi tetap hidup)",onSelect:c,render:t.jsx("button",{type:"button",className:"hn-terminal-action hn-terminal-action--text",onClick:c,disabled:!s,title:"Lepas dari grid (sesi tetap hidup)",children:"lepas"},"detach")},{key:"fullscreen",label:"Layar penuh",icon:"fullscreen",title:"Layar penuh — fokus 1 terminal",onSelect:S,render:t.jsx("button",{type:"button",className:"hn-terminal-action",onClick:S,title:"Layar penuh — fokus 1 terminal","aria-label":`Layar penuh sesi ${e.id}`,children:t.jsx(ie,{name:"fullscreen",size:12})},"fullscreen")},{key:"close",label:"Tutup",icon:"x",title:"Tutup sesi",onSelect:n,render:t.jsx("button",{type:"button",className:"hn-terminal-action","aria-label":`Tutup sesi ${e.id}`,onClick:n,children:"×"},"close")}],he=40+(e.orchestrated&&e.model?110:0)+(e.exited||B?110:0)+(V||fe&&!B?130:0),Ce=ka(E,K.length,f?44:28,he),te=K.slice(Ce);return t.jsxs(t.Fragment,{children:[t.jsxs("div",{ref:k,className:"hn-terminal-cell-header",style:{display:"flex",alignItems:"center",gap:8,padding:"4px 8px",flex:"0 0 auto",background:oe?"var(--status-err-tint)":e.exited||B?"var(--status-ok-tint)":Se?"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:[Ie&&t.jsx(va,{id:Ie,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:[Z," · ",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 ",qe(e.model),e.effort?` · ${e.effort}`:""]}),e.exited&&(oe?t.jsx(ve,{status:"failed",size:"sm",children:`Gagal · exit ${e.exitCode}`}):t.jsx(ve,{status:"done",size:"sm",children:"Selesai"})),B&&t.jsx(ve,{status:"done",size:"sm",children:"Selesai"}),V&&!B&&t.jsx(ve,{status:"running",size:"sm",children:"Lead memutuskan"}),fe&&!V&&!B&&t.jsx(ve,{status:"awaiting",size:"sm"}),t.jsxs("span",{className:"hn-terminal-actions",children:[K.slice(0,Ce).map(H=>H.render),te.length>0&&t.jsx(St,{label:`Aksi lain sesi ${e.id}`,items:te.map(({render:H,...P})=>P)})]})]}),t.jsxs("div",{style:{display:"flex",flexDirection:"column",flex:1,minHeight:0,position:"relative",opacity:e.exited?.6:1},children:[t.jsx(_a,{phases:N,compact:E<480}),t.jsx("div",{style:{flex:1,minHeight:0},children:p?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(It,{sessionId:e.id,onExit:d,onPhases:O,fontSize:u,showKeys:x,predict:C,diag:w,hidden:z},e.id)})]}),X&&e.specId&&t.jsx(ya,{specId:e.specId,onClose:()=>M(!1)}),_&&q&&h&&t.jsx(dt,{projectId:q.projectId,ownBranch:`hanoman/${q.id.toLowerCase().replace(/[^a-z0-9_-]/g,"_")}`,eyebrow:q.id,onClose:()=>Q(!1),onIntegrate:(H,P)=>{Q(!1),h(q,H,P)}}),re&&me&&g&&t.jsx(dt,{projectId:e.projectId,ownBranch:e.branch,eyebrow:e.id.slice(0,16),onClose:()=>le(!1),onIntegrate:(H,P)=>{le(!1),g(e,H,P)}})]})}function Va({session:e,label:i,fontSize:n,showKeys:s,predict:c,diag:d,onClose:R}){return t.jsx(ke,{open:!0,icon:"terminal",title:i,onClose:R,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(It,{sessionId:e.id,onExit:()=>{},fontSize:n,showKeys:s,predict:c,diag:d},e.id)})})}function Ya({unplaced:e,nameOf:i,onPick:n,disabled:s}){return t.jsx("div",{style:{flex:1,display:"grid",placeItems:"center",padding:12},children:t.jsx(J,{size:"sm",value:"","aria-label":"Pilih sesi untuk sel",disabled:s||!e.length,onChange:c=>c.target.value&&n(c.target.value),options:[{value:"",label:e.length?"Pilih sesi…":"tidak ada sesi bebas"}].concat(e.map(c=>({value:c.id,label:`${c.specId??i(c.projectId)} · ${c.id.slice(0,6)}`})))})})}export{_a as PhaseStrip,tn as TerminalScreen};
|