hanoman 0.3.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. package/dist/build-info.json +3 -3
  2. package/dist/cli.js +120 -8
  3. package/dist/server.js +1435 -797
  4. package/package.json +1 -1
  5. package/prisma/migrations/20260914120000_agent_invocation_phase/migration.sql +3 -0
  6. package/prisma/schema.prisma +3 -0
  7. package/web/assets/{ChangelogScreen-D_-RmJkz.js → ChangelogScreen-aqsJmmfe.js} +1 -1
  8. package/web/assets/{DalangHanomanScreen-pVfnLx9z.js → DalangHanomanScreen-D3rNURz7.js} +1 -1
  9. package/web/assets/{DocPreviewModal-ZFjISCL0.js → DocPreviewModal-B7r_7p8N.js} +1 -1
  10. package/web/assets/{DocsWorkspace-Vp_vik3v.js → DocsWorkspace-_w6pncu9.js} +1 -1
  11. package/web/assets/{IdeScreen-DQSRs3fr.js → IdeScreen-etZ2QyO-.js} +1 -1
  12. package/web/assets/{LeadScreen-Bv5LiudD.js → LeadScreen-Bo0K2-ML.js} +1 -1
  13. package/web/assets/{ReviewScreen-Cime4Tci.js → ReviewScreen-lRf2FW30.js} +1 -1
  14. package/web/assets/{SchedulerScreen-DKmRNbTs.js → SchedulerScreen-D75twy4J.js} +1 -1
  15. package/web/assets/SettingsScreen-rMIR22vv.js +62 -0
  16. package/web/assets/{TeamScreen-5ugoXsOv.js → TeamScreen-nsttkE2J.js} +1 -1
  17. package/web/assets/TerminalScreen-BG9vRE1-.js +9 -0
  18. package/web/assets/{TriageScreen-BajACF5K.js → TriageScreen-7eM8gjr_.js} +1 -1
  19. package/web/assets/{VpsScreen-C7muNRX5.js → VpsScreen-C29j52Tu.js} +1 -1
  20. package/web/assets/{diff-view-CsZPBznT.js → diff-view-RZNZ9Nz6.js} +1 -1
  21. package/web/assets/{index-DI7G_sit.js → index-BHI_f9DD.js} +192 -192
  22. package/web/assets/{live-DVDstDzi.js → live-CniaVDeP.js} +1 -1
  23. package/web/index.html +1 -1
  24. package/web/assets/SettingsScreen-Bh8XhyVQ.js +0 -62
  25. package/web/assets/TerminalScreen-DsAn5dlH.js +0 -9
@@ -1 +1 @@
1
- import{h as E,e as b,t as se,q as ne,j as e,f as H,ae as L,B as m,a as u,I as ie,S as Y,R as le,x as J,p as re,d as $,w as oe,D as ce,af as de,am as ue}from"./index-DI7G_sit.js";import{R as c}from"./react-DfGhg7ZW.js";import{L as pe}from"./live-DVDstDzi.js";import"./markdown-CWEY34jk.js";const me=5e3,z=20;function U({total:a,page:r,onPage:s,unit:o}){const n=ce(a,r,z);return e.jsx(oe,{page:n.page,pageCount:n.pageCount,total:a,from:n.from,to:n.to,onPage:s,unit:o})}function Q(a,r=Date.now()){if(!a)return"—";const s=Math.max(0,r-new Date(a).getTime()),o=Math.floor(s/6e4);if(o<1)return"baru saja";if(o<60)return`${o}m`;const n=Math.floor(o/60);return n<24?`${n}j`:`${Math.floor(n/24)}h`}const xe={tinggi:"ok",sedang:"neutral",ragu:"warn"},ge={berlaku:"ok",ditimpa:"warn",dibatalkan:"neutral",gagal:"err"},he={answer:"jawaban",order:"urutan kerja",collision:"tabrakan area",quality:"mutu hasil",refusal:"tindakan ditolak"},je={contract:"kontrak",detected:"deteksi otomatis",pulse:"denyut"},be={menunggu:"warn",sebagian:"info",selesai:"ok",dibatalkan:"neutral"},fe=new Set(["menunggu","sebagian"]),ke={tunggal:"sekali jalan",submit:"di-submit",operator:"dibatalkan operator",kedaluwarsa:"kedaluwarsa"};function G({children:a}){return e.jsx("div",{className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:10,padding:"10px 12px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",background:"var(--surface-card)",marginBottom:6},children:a})}function ve({title:a,count:r,empty:s,children:o}){return e.jsx(L,{eyebrow:`lead · ${a.toLowerCase()}`,title:`${a} (${r})`,children:r===0?e.jsx("div",{style:{fontSize:"var(--text-sm)",color:"var(--text-subtle)"},children:s}):o})}function ye({cfg:a,onWrite:r,busy:s}){var n;const o=(i,p)=>Math.max(p,Number(i)||p);return e.jsxs(L,{eyebrow:"lead · kendali",title:"hanoman-lead",children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,flexWrap:"wrap",marginBottom:12},children:[e.jsx(m,{tone:a.enabled?a.paused?"warn":"ok":"neutral",children:a.enabled?a.paused?"dijeda":"aktif":"mati"}),a.enabled?e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"ban",disabled:s,onClick:()=>r({...a,enabled:!1,paused:!1}),children:"Matikan"}):e.jsx(u,{size:"sm",leftIcon:"play",disabled:s,onClick:()=>r({...a,enabled:!0}),children:"Nyalakan"}),a.enabled&&(a.paused?e.jsx(u,{size:"sm",leftIcon:"play",disabled:s,onClick:()=>r({...a,paused:!1}),children:"Lanjutkan"}):e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"pause",disabled:s,onClick:()=>r({...a,paused:!0}),children:"Pause"}))]}),e.jsxs("div",{style:{display:"flex",gap:14,flexWrap:"wrap",alignItems:"center"},children:[e.jsxs("label",{style:{display:"flex",alignItems:"center",gap:6,fontSize:"var(--text-xs)"},children:["denyut tiap",e.jsx($,{type:"number",min:1,style:{width:76},"aria-label":"denyut lead (menit)",placeholder:"5",value:String(a.everyMin),disabled:s,onChange:i=>r({...a,everyMin:o(i.target.value,1)})}),"menit"]}),e.jsxs("label",{style:{display:"flex",alignItems:"center",gap:6,fontSize:"var(--text-xs)"},children:["batas waktu putusan",e.jsx($,{type:"number",min:10,style:{width:84},"aria-label":"batas waktu putusan (detik)",placeholder:"600",value:String(a.timeoutSec),disabled:s,onChange:i=>r({...a,timeoutSec:o(i.target.value,10)})}),"detik"]}),e.jsxs("label",{style:{display:"flex",alignItems:"center",gap:6,fontSize:"var(--text-xs)"},children:["maks jawaban otomatis/sesi",e.jsx($,{type:"number",min:1,style:{width:76},"aria-label":"maksimum jawaban otomatis per sesi",placeholder:"3",value:String(a.maxAutoAnswers),disabled:s,onChange:i=>r({...a,maxAutoAnswers:o(i.target.value,1)})})]}),e.jsxs("label",{style:{display:"flex",alignItems:"center",gap:6,fontSize:"var(--text-xs)"},children:["syarat sebelum integrasi ke main",e.jsx(Y,{size:"sm","aria-label":"syarat sebelum integrasi ke main",value:a.requireGreenBeforeIntegrate?"wajib":"bebas",disabled:s,onChange:i=>r({...a,requireGreenBeforeIntegrate:i.target.value==="wajib"}),options:[{value:"wajib",label:"plan tuntas"},{value:"bebas",label:"tanpa syarat"}]})]})]}),e.jsxs("div",{"data-testid":"lead-engine-line",style:{fontSize:"var(--text-xs)",color:"var(--text-subtle)",marginTop:10},children:["mesin: ",(n=a.engine)!=null&&n.enabled?e.jsxs(e.Fragment,{children:[a.engine.agent==="codex"?"Codex CLI":"Claude Code"," · ",e.jsx("code",{children:a.engine.model})," · ",e.jsx("code",{children:a.engine.effort})]}):e.jsx(e.Fragment,{children:"ikut default global · atur di Settings → Model sesi"})]}),e.jsx("div",{style:{fontSize:"var(--text-xs)",color:"var(--text-subtle)",marginTop:6},children:"Lead memutuskan lalu melapor. Produksi/VPS dan penghapusan data terkunci secara teknis — apa pun setelannya."})]})}function we({options:a,multi:r,value:s,onChange:o}){const n=i=>{if(!r){o([i]);return}o(s.includes(i)?s.filter(p=>p!==i):[...s,i])};return e.jsx("div",{style:{display:"flex",flexDirection:"column",gap:6},children:a.map(i=>r?e.jsx(de,{checked:s.includes(i),label:i,onChange:()=>n(i)},i):e.jsx(ue,{checked:s.includes(i),label:i,onChange:()=>n(i)},i))})}function Se({d:a,onOverride:r,onCancel:s,busyId:o}){var C;const[n,i]=c.useState(!1),[p,w]=c.useState(""),[v,S]=c.useState([]),h=(a.choices??[]).length>0?a.choices:a.choiceIndex!=null&&a.choice?[{index:a.choiceIndex,option:a.choice}]:[],f=a.options??[],y=((C=a.select)==null?void 0:C.mode)==="multi";return e.jsxs("div",{style:{padding:"10px 12px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",background:"var(--surface-card)",marginBottom:6},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,flexWrap:"wrap"},children:[e.jsx(m,{tone:ge[a.status]??"neutral",size:"sm",children:a.status}),e.jsx(m,{tone:xe[a.confidence]??"neutral",size:"sm",children:a.confidence}),e.jsx(m,{tone:"neutral",size:"sm",children:he[a.kind]??a.kind}),e.jsx(m,{tone:"neutral",size:"sm",children:je[a.gate]??a.gate}),a.weighty&&e.jsx(m,{tone:"warn",size:"sm",children:"berbobot"}),h.length>0&&f.length>0&&e.jsx(m,{tone:"brass",size:"sm",children:h.length>1?`${h.length} dari ${f.length} opsi`:`opsi ${h[0].index}/${f.length}`}),(a.missing??[]).length>0&&e.jsx(m,{tone:"warn",size:"sm",children:"kurang konteks"}),e.jsx("span",{style:{flex:1}}),e.jsx("span",{style:{fontSize:"var(--text-xs)",color:"var(--text-muted)"},children:Q(a.createdAt)})]}),e.jsx("div",{style:{marginTop:6,fontSize:"var(--text-sm)",color:"var(--text-subtle)",whiteSpace:"pre-wrap"},children:a.question.slice(0,400)}),e.jsx("div",{style:{marginTop:4,color:"var(--text-strong)",fontWeight:500,whiteSpace:"pre-wrap"},children:h.length?h.map(j=>j.option).join(" · "):a.answer||e.jsx("em",{style:{fontWeight:400,color:"var(--text-muted)"},children:"tak ada jawaban"})}),e.jsx("div",{style:{marginTop:4,fontSize:"var(--text-xs)",color:"var(--text-subtle)",whiteSpace:"pre-wrap"},children:a.reason}),a.refs.length>0&&e.jsx("div",{style:{marginTop:6,display:"flex",gap:6,flexWrap:"wrap"},children:a.refs.map(j=>e.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:"var(--text-xs)",color:"var(--text-muted)",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",padding:"1px 6px"},children:j},j))}),(a.missing??[]).length>0&&e.jsxs("div",{style:{marginTop:6,fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:["Yang kurang: ",a.missing.join(" · ")]}),e.jsxs("div",{style:{marginTop:8,display:"flex",gap:8,alignItems:"center",flexWrap:"wrap"},children:[e.jsxs("span",{style:{fontSize:"var(--text-xs)",color:"var(--text-muted)",fontFamily:"var(--font-mono)"},children:[a.projectId,a.specId?` · ${a.specId}`:"",a.sessionId?` · ${a.sessionId}`:"",a.action!=="none"?` · ${a.action}`:""]}),e.jsx("span",{style:{flex:1}}),a.status==="berlaku"&&!n&&e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"edit-3",onClick:()=>i(!0),children:"Timpa"}),a.status==="berlaku"&&e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"x-circle",disabled:o===a.id,onClick:()=>s(a.id),children:"Batalkan"})]}),n&&e.jsxs("div",{style:{marginTop:8,display:"flex",flexDirection:"column",gap:8},children:[f.length>0&&e.jsx(we,{options:f,multi:y,value:v,onChange:S}),e.jsxs("div",{style:{display:"flex",gap:8},children:[e.jsx($,{style:{flex:1},"aria-label":`jawaban operator untuk ${a.id}`,placeholder:"mis. pilih opsi 2, pakai Node 22",value:p,onChange:j=>w(j.target.value)}),e.jsx(u,{size:"sm",leftIcon:"check",disabled:!p.trim()&&v.length===0||o===a.id,onClick:()=>{r(a.id,p.trim()||v.join("; "),v),i(!1),w(""),S([])},children:"Simpan"})]})]})]})}function Pe({projects:a,onProjectChanged:r,onToast:s,onGotoTerminal:o}){const[n,i]=c.useState(null),[p,w]=c.useState([]),[v,S]=c.useState([]),[h,f]=c.useState(0),[y,C]=E("lead","decPage",1,J),[j,M]=c.useState(0),[P,N]=E("lead","flowPage",1,J),[q,B]=c.useState("loading"),[O,T]=c.useState(!1),[I,k]=c.useState(null),[x,X]=E("lead","filter","all",re),d=c.useCallback((t=!1)=>{t||B("loading"),Promise.all([b.getLeadStatus(),b.getLeadDecisions({projectId:x==="all"?void 0:x,page:y,limit:z}),b.getLeadFlows({projectId:x==="all"?void 0:x,page:P,limit:z}).catch(()=>({items:[],total:0,page:1,pageSize:z}))]).then(([l,g,D])=>{i(l),w(g.items??[]),f(g.total??0),S(D.items??[]),M(D.total??0),B("ready")}).catch(()=>{t||B("error")})},[x,y,P]);c.useEffect(()=>{d()},[d]),se(x,()=>{C(1),N(1)}),ne({topic:"lead",params:{projectId:x==="all"?void 0:x,decPage:y,flowPage:P,limit:z},apply:t=>{i(t.status),w(t.decisions.items),f(t.decisions.total),S(t.flows.items),M(t.flows.total),B("ready")},refetch:()=>d(!0),pollMs:me});const A=c.useCallback(async t=>{T(!0);try{await b.putLeadConfig(t),s("Setelan lead tersimpan","ok","save"),d(!0)}catch{s("Gagal menyimpan setelan lead","err","x-circle")}finally{T(!1)}},[d,s]),_=c.useCallback(async(t,l)=>{k(t);try{await b.updateProject(t,{leadOptIn:l}),await r(t),d(!0),s(l?"Project dipimpin lead":"Project dilepas dari lead","ok")}catch{s("Gagal mengubah opt-in","err","x-circle")}finally{k(null)}},[d,r,s]),W=c.useCallback(async(t,l)=>{if(!n)return;const g=new Set(n.config.pausedProjects);l?g.add(t):g.delete(t),await A({...n.config,pausedProjects:[...g]})},[n,A]),Z=c.useCallback(async(t,l,g=[])=>{k(t);try{const D=await b.overrideLeadDecision(t,l,"",g);s(D.delivered?"Jawaban kamu dikirim ke sesi":"Keputusan ditimpa","ok","check"),d(!0)}catch{s("Gagal menimpa keputusan","err","x-circle")}finally{k(null)}},[d,s]),K=c.useCallback(async(t,l)=>{k(t);try{await(l==="submit"?b.submitLeadFlow(t):b.cancelLeadFlow(t)),s(l==="submit"?"Rantai di-submit":"Rantai dibatalkan","ok","check"),d(!0)}catch{s("Gagal menutup rantai","err","x-circle")}finally{k(null)}},[d,s]),ee=c.useCallback(async t=>{k(t);try{await b.cancelLeadDecision(t),s("Keputusan dibatalkan","ok"),d(!0)}catch{s("Gagal membatalkan keputusan","err","x-circle")}finally{k(null)}},[d,s]);if(q==="loading")return e.jsx(H,{kind:"loading"});if(q==="error"||!n)return e.jsx(H,{kind:"error",hint:"Gagal memuat status lead.",action:()=>d(),actionLabel:"Coba lagi"});const F=new Set(n.projects.map(t=>t.projectId)),V=n.waiting,ae=new Set(n.deciding),te=new Set(n.queued??[]),R=n.gate??{inFlight:0,queued:0,capacity:1};return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:16,minHeight:0},children:[e.jsx(ye,{cfg:n.config,onWrite:A,busy:O}),e.jsxs(L,{eyebrow:"lead · project",title:"Project yang dipimpin",children:[e.jsx("div",{style:{fontSize:"var(--text-xs)",color:"var(--text-subtle)",marginBottom:10},children:"Lead hanya menyentuh project yang di-opt-in. Default mati."}),a.length===0?e.jsx("div",{style:{fontSize:"var(--text-sm)",color:"var(--text-subtle)"},children:"Belum ada project."}):a.map(t=>{const l=n.projects.find(g=>g.projectId===t.id);return e.jsxs(G,{children:[e.jsx("span",{style:{flex:1,minWidth:0,color:"var(--text-strong)",fontWeight:500},children:t.name}),l&&e.jsxs("span",{style:{fontSize:"var(--text-xs)",color:"var(--text-muted)"},children:[l.decisions24h," keputusan/24j · ",l.openSessions," sesi"]}),e.jsx(m,{tone:F.has(t.id)?l!=null&&l.paused?"warn":"ok":"neutral",size:"sm",children:F.has(t.id)?l!=null&&l.paused?"dijeda":"dipimpin":"mati"}),F.has(t.id)&&(l!=null&&l.paused?e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"play",disabled:O,onClick:()=>W(t.id,!1),children:"Lanjutkan"}):e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"pause",disabled:O,onClick:()=>W(t.id,!0),children:"Pause"})),F.has(t.id)?e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"ban",disabled:I===t.id,onClick:()=>_(t.id,!1),children:"Lepas"}):e.jsx(u,{size:"sm",leftIcon:"check",disabled:I===t.id,onClick:()=>_(t.id,!0),children:"Pimpin"})]},t.id)})]}),e.jsxs(ve,{title:"Sesi menunggu keputusan",count:V.length,empty:"Tak ada sesi yang menunggu keputusan.",children:[R.queued>0&&e.jsxs("div",{style:{fontSize:"var(--text-xs)",color:"var(--text-muted)",marginBottom:8},children:["Gerbang lead: ",R.inFlight,"/",R.capacity," diputuskan · ",R.queued," antre menunggu slot."]}),V.map(t=>{const l=ae.has(t)?"sedang diputuskan":te.has(t)?"antre":"menunggu";return e.jsxs(G,{children:[e.jsx(ie,{name:l==="sedang diputuskan"?"loader":l==="antre"?"clock":"help-circle"}),e.jsx("span",{style:{flex:1,fontFamily:"var(--font-mono)",color:"var(--text-strong)"},children:t}),e.jsx(m,{tone:l==="menunggu"?"warn":"ok",size:"sm",children:l}),e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"terminal",onClick:()=>o(t),children:"Ambil alih"})]},t)})]}),e.jsxs(L,{eyebrow:"lead · rantai keputusan",title:`Rantai (${j})`,children:[v.length===0?e.jsx("div",{style:{fontSize:"var(--text-sm)",color:"var(--text-subtle)"},children:"Belum ada rantai. Satu rantai adalah satu urusan — beberapa pertanyaan berurutan sampai di-submit."}):v.map(t=>e.jsxs(G,{children:[e.jsx(m,{tone:be[t.status]??"neutral",size:"sm",children:t.status}),e.jsx("span",{style:{flex:1,minWidth:0,color:"var(--text-strong)"},children:t.title}),e.jsxs("span",{style:{fontSize:"var(--text-xs)",color:"var(--text-muted)"},children:[t.steps," langkah · ",Q(t.openedAt),t.closeReason?` · ${ke[t.closeReason]??t.closeReason}`:""]}),fe.has(t.status)&&e.jsxs(e.Fragment,{children:[e.jsx(u,{size:"sm",leftIcon:"check",disabled:I===t.id,onClick:()=>K(t.id,"submit"),children:"Submit"}),e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"x-circle",disabled:I===t.id,onClick:()=>K(t.id,"cancel"),children:"Batalkan"})]})]},t.id)),e.jsx(U,{total:j,page:P,onPage:N,unit:"rantai"})]}),e.jsxs(L,{eyebrow:"lead · jejak keputusan",title:`Keputusan (${h})`,actions:e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsx(Y,{size:"sm",value:x,"aria-label":"saring project",onChange:t=>X(t.target.value),options:[{value:"all",label:"semua project"},...a.map(t=>({value:t.id,label:t.name}))]}),e.jsx(le,{screen:"lead",active:x==="all"?0:1}),e.jsx(pe,{})]}),children:[p.length===0?e.jsx("div",{style:{fontSize:"var(--text-sm)",color:"var(--text-subtle)"},children:"Belum ada keputusan. Lead menulis satu baris di sini setiap kali ia memutuskan."}):p.map(t=>e.jsx(Se,{d:t,onOverride:Z,onCancel:ee,busyId:I},t.id)),e.jsx(U,{total:h,page:y,onPage:C,unit:"keputusan"})]})]})}export{Pe as LeadScreen};
1
+ import{h as E,e as b,t as se,q as ne,j as e,f as H,ah as L,B as m,a as u,I as ie,S as Y,R as le,x as J,p as re,d as $,w as oe,D as ce,ai as de,ap as ue}from"./index-BHI_f9DD.js";import{R as c}from"./react-DfGhg7ZW.js";import{L as pe}from"./live-CniaVDeP.js";import"./markdown-CWEY34jk.js";const me=5e3,z=20;function U({total:a,page:r,onPage:s,unit:o}){const n=ce(a,r,z);return e.jsx(oe,{page:n.page,pageCount:n.pageCount,total:a,from:n.from,to:n.to,onPage:s,unit:o})}function Q(a,r=Date.now()){if(!a)return"—";const s=Math.max(0,r-new Date(a).getTime()),o=Math.floor(s/6e4);if(o<1)return"baru saja";if(o<60)return`${o}m`;const n=Math.floor(o/60);return n<24?`${n}j`:`${Math.floor(n/24)}h`}const xe={tinggi:"ok",sedang:"neutral",ragu:"warn"},ge={berlaku:"ok",ditimpa:"warn",dibatalkan:"neutral",gagal:"err"},he={answer:"jawaban",order:"urutan kerja",collision:"tabrakan area",quality:"mutu hasil",refusal:"tindakan ditolak"},je={contract:"kontrak",detected:"deteksi otomatis",pulse:"denyut"},be={menunggu:"warn",sebagian:"info",selesai:"ok",dibatalkan:"neutral"},ke=new Set(["menunggu","sebagian"]),fe={tunggal:"sekali jalan",submit:"di-submit",operator:"dibatalkan operator",kedaluwarsa:"kedaluwarsa"};function G({children:a}){return e.jsx("div",{className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:10,padding:"10px 12px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",background:"var(--surface-card)",marginBottom:6},children:a})}function ve({title:a,count:r,empty:s,children:o}){return e.jsx(L,{eyebrow:`lead · ${a.toLowerCase()}`,title:`${a} (${r})`,children:r===0?e.jsx("div",{style:{fontSize:"var(--text-sm)",color:"var(--text-subtle)"},children:s}):o})}function ye({cfg:a,onWrite:r,busy:s}){var n;const o=(i,p)=>Math.max(p,Number(i)||p);return e.jsxs(L,{eyebrow:"lead · kendali",title:"hanoman-lead",children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,flexWrap:"wrap",marginBottom:12},children:[e.jsx(m,{tone:a.enabled?a.paused?"warn":"ok":"neutral",children:a.enabled?a.paused?"dijeda":"aktif":"mati"}),a.enabled?e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"ban",disabled:s,onClick:()=>r({...a,enabled:!1,paused:!1}),children:"Matikan"}):e.jsx(u,{size:"sm",leftIcon:"play",disabled:s,onClick:()=>r({...a,enabled:!0}),children:"Nyalakan"}),a.enabled&&(a.paused?e.jsx(u,{size:"sm",leftIcon:"play",disabled:s,onClick:()=>r({...a,paused:!1}),children:"Lanjutkan"}):e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"pause",disabled:s,onClick:()=>r({...a,paused:!0}),children:"Pause"}))]}),e.jsxs("div",{style:{display:"flex",gap:14,flexWrap:"wrap",alignItems:"center"},children:[e.jsxs("label",{style:{display:"flex",alignItems:"center",gap:6,fontSize:"var(--text-xs)"},children:["denyut tiap",e.jsx($,{type:"number",min:1,style:{width:76},"aria-label":"denyut lead (menit)",placeholder:"5",value:String(a.everyMin),disabled:s,onChange:i=>r({...a,everyMin:o(i.target.value,1)})}),"menit"]}),e.jsxs("label",{style:{display:"flex",alignItems:"center",gap:6,fontSize:"var(--text-xs)"},children:["batas waktu putusan",e.jsx($,{type:"number",min:10,style:{width:84},"aria-label":"batas waktu putusan (detik)",placeholder:"600",value:String(a.timeoutSec),disabled:s,onChange:i=>r({...a,timeoutSec:o(i.target.value,10)})}),"detik"]}),e.jsxs("label",{style:{display:"flex",alignItems:"center",gap:6,fontSize:"var(--text-xs)"},children:["maks jawaban otomatis/sesi",e.jsx($,{type:"number",min:1,style:{width:76},"aria-label":"maksimum jawaban otomatis per sesi",placeholder:"3",value:String(a.maxAutoAnswers),disabled:s,onChange:i=>r({...a,maxAutoAnswers:o(i.target.value,1)})})]}),e.jsxs("label",{style:{display:"flex",alignItems:"center",gap:6,fontSize:"var(--text-xs)"},children:["syarat sebelum integrasi ke main",e.jsx(Y,{size:"sm","aria-label":"syarat sebelum integrasi ke main",value:a.requireGreenBeforeIntegrate?"wajib":"bebas",disabled:s,onChange:i=>r({...a,requireGreenBeforeIntegrate:i.target.value==="wajib"}),options:[{value:"wajib",label:"plan tuntas"},{value:"bebas",label:"tanpa syarat"}]})]})]}),e.jsxs("div",{"data-testid":"lead-engine-line",style:{fontSize:"var(--text-xs)",color:"var(--text-subtle)",marginTop:10},children:["mesin: ",(n=a.engine)!=null&&n.enabled?e.jsxs(e.Fragment,{children:[a.engine.agent==="codex"?"Codex CLI":"Claude Code"," · ",e.jsx("code",{children:a.engine.model})," · ",e.jsx("code",{children:a.engine.effort})]}):e.jsx(e.Fragment,{children:"ikut default global · atur di Settings → Model sesi"})]}),e.jsx("div",{style:{fontSize:"var(--text-xs)",color:"var(--text-subtle)",marginTop:6},children:"Lead memutuskan lalu melapor. Produksi/VPS dan penghapusan data terkunci secara teknis — apa pun setelannya."})]})}function we({options:a,multi:r,value:s,onChange:o}){const n=i=>{if(!r){o([i]);return}o(s.includes(i)?s.filter(p=>p!==i):[...s,i])};return e.jsx("div",{style:{display:"flex",flexDirection:"column",gap:6},children:a.map(i=>r?e.jsx(de,{checked:s.includes(i),label:i,onChange:()=>n(i)},i):e.jsx(ue,{checked:s.includes(i),label:i,onChange:()=>n(i)},i))})}function Se({d:a,onOverride:r,onCancel:s,busyId:o}){var C;const[n,i]=c.useState(!1),[p,w]=c.useState(""),[v,S]=c.useState([]),h=(a.choices??[]).length>0?a.choices:a.choiceIndex!=null&&a.choice?[{index:a.choiceIndex,option:a.choice}]:[],k=a.options??[],y=((C=a.select)==null?void 0:C.mode)==="multi";return e.jsxs("div",{style:{padding:"10px 12px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",background:"var(--surface-card)",marginBottom:6},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8,flexWrap:"wrap"},children:[e.jsx(m,{tone:ge[a.status]??"neutral",size:"sm",children:a.status}),e.jsx(m,{tone:xe[a.confidence]??"neutral",size:"sm",children:a.confidence}),e.jsx(m,{tone:"neutral",size:"sm",children:he[a.kind]??a.kind}),e.jsx(m,{tone:"neutral",size:"sm",children:je[a.gate]??a.gate}),a.weighty&&e.jsx(m,{tone:"warn",size:"sm",children:"berbobot"}),h.length>0&&k.length>0&&e.jsx(m,{tone:"brass",size:"sm",children:h.length>1?`${h.length} dari ${k.length} opsi`:`opsi ${h[0].index}/${k.length}`}),(a.missing??[]).length>0&&e.jsx(m,{tone:"warn",size:"sm",children:"kurang konteks"}),e.jsx("span",{style:{flex:1}}),e.jsx("span",{style:{fontSize:"var(--text-xs)",color:"var(--text-muted)"},children:Q(a.createdAt)})]}),e.jsx("div",{style:{marginTop:6,fontSize:"var(--text-sm)",color:"var(--text-subtle)",whiteSpace:"pre-wrap"},children:a.question.slice(0,400)}),e.jsx("div",{style:{marginTop:4,color:"var(--text-strong)",fontWeight:500,whiteSpace:"pre-wrap"},children:h.length?h.map(j=>j.option).join(" · "):a.answer||e.jsx("em",{style:{fontWeight:400,color:"var(--text-muted)"},children:"tak ada jawaban"})}),e.jsx("div",{style:{marginTop:4,fontSize:"var(--text-xs)",color:"var(--text-subtle)",whiteSpace:"pre-wrap"},children:a.reason}),a.refs.length>0&&e.jsx("div",{style:{marginTop:6,display:"flex",gap:6,flexWrap:"wrap"},children:a.refs.map(j=>e.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:"var(--text-xs)",color:"var(--text-muted)",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",padding:"1px 6px"},children:j},j))}),(a.missing??[]).length>0&&e.jsxs("div",{style:{marginTop:6,fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:["Yang kurang: ",a.missing.join(" · ")]}),e.jsxs("div",{style:{marginTop:8,display:"flex",gap:8,alignItems:"center",flexWrap:"wrap"},children:[e.jsxs("span",{style:{fontSize:"var(--text-xs)",color:"var(--text-muted)",fontFamily:"var(--font-mono)"},children:[a.projectId,a.specId?` · ${a.specId}`:"",a.sessionId?` · ${a.sessionId}`:"",a.action!=="none"?` · ${a.action}`:""]}),e.jsx("span",{style:{flex:1}}),a.status==="berlaku"&&!n&&e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"edit-3",onClick:()=>i(!0),children:"Timpa"}),a.status==="berlaku"&&e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"x-circle",disabled:o===a.id,onClick:()=>s(a.id),children:"Batalkan"})]}),n&&e.jsxs("div",{style:{marginTop:8,display:"flex",flexDirection:"column",gap:8},children:[k.length>0&&e.jsx(we,{options:k,multi:y,value:v,onChange:S}),e.jsxs("div",{style:{display:"flex",gap:8},children:[e.jsx($,{style:{flex:1},"aria-label":`jawaban operator untuk ${a.id}`,placeholder:"mis. pilih opsi 2, pakai Node 22",value:p,onChange:j=>w(j.target.value)}),e.jsx(u,{size:"sm",leftIcon:"check",disabled:!p.trim()&&v.length===0||o===a.id,onClick:()=>{r(a.id,p.trim()||v.join("; "),v),i(!1),w(""),S([])},children:"Simpan"})]})]})]})}function Pe({projects:a,onProjectChanged:r,onToast:s,onGotoTerminal:o}){const[n,i]=c.useState(null),[p,w]=c.useState([]),[v,S]=c.useState([]),[h,k]=c.useState(0),[y,C]=E("lead","decPage",1,J),[j,M]=c.useState(0),[P,N]=E("lead","flowPage",1,J),[q,B]=c.useState("loading"),[O,T]=c.useState(!1),[I,f]=c.useState(null),[x,X]=E("lead","filter","all",re),d=c.useCallback((t=!1)=>{t||B("loading"),Promise.all([b.getLeadStatus(),b.getLeadDecisions({projectId:x==="all"?void 0:x,page:y,limit:z}),b.getLeadFlows({projectId:x==="all"?void 0:x,page:P,limit:z}).catch(()=>({items:[],total:0,page:1,pageSize:z}))]).then(([l,g,D])=>{i(l),w(g.items??[]),k(g.total??0),S(D.items??[]),M(D.total??0),B("ready")}).catch(()=>{t||B("error")})},[x,y,P]);c.useEffect(()=>{d()},[d]),se(x,()=>{C(1),N(1)}),ne({topic:"lead",params:{projectId:x==="all"?void 0:x,decPage:y,flowPage:P,limit:z},apply:t=>{i(t.status),w(t.decisions.items),k(t.decisions.total),S(t.flows.items),M(t.flows.total),B("ready")},refetch:()=>d(!0),pollMs:me});const A=c.useCallback(async t=>{T(!0);try{await b.putLeadConfig(t),s("Setelan lead tersimpan","ok","save"),d(!0)}catch{s("Gagal menyimpan setelan lead","err","x-circle")}finally{T(!1)}},[d,s]),_=c.useCallback(async(t,l)=>{f(t);try{await b.updateProject(t,{leadOptIn:l}),await r(t),d(!0),s(l?"Project dipimpin lead":"Project dilepas dari lead","ok")}catch{s("Gagal mengubah opt-in","err","x-circle")}finally{f(null)}},[d,r,s]),W=c.useCallback(async(t,l)=>{if(!n)return;const g=new Set(n.config.pausedProjects);l?g.add(t):g.delete(t),await A({...n.config,pausedProjects:[...g]})},[n,A]),Z=c.useCallback(async(t,l,g=[])=>{f(t);try{const D=await b.overrideLeadDecision(t,l,"",g);s(D.delivered?"Jawaban kamu dikirim ke sesi":"Keputusan ditimpa","ok","check"),d(!0)}catch{s("Gagal menimpa keputusan","err","x-circle")}finally{f(null)}},[d,s]),K=c.useCallback(async(t,l)=>{f(t);try{await(l==="submit"?b.submitLeadFlow(t):b.cancelLeadFlow(t)),s(l==="submit"?"Rantai di-submit":"Rantai dibatalkan","ok","check"),d(!0)}catch{s("Gagal menutup rantai","err","x-circle")}finally{f(null)}},[d,s]),ee=c.useCallback(async t=>{f(t);try{await b.cancelLeadDecision(t),s("Keputusan dibatalkan","ok"),d(!0)}catch{s("Gagal membatalkan keputusan","err","x-circle")}finally{f(null)}},[d,s]);if(q==="loading")return e.jsx(H,{kind:"loading"});if(q==="error"||!n)return e.jsx(H,{kind:"error",hint:"Gagal memuat status lead.",action:()=>d(),actionLabel:"Coba lagi"});const F=new Set(n.projects.map(t=>t.projectId)),V=n.waiting,ae=new Set(n.deciding),te=new Set(n.queued??[]),R=n.gate??{inFlight:0,queued:0,capacity:1};return e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:16,minHeight:0},children:[e.jsx(ye,{cfg:n.config,onWrite:A,busy:O}),e.jsxs(L,{eyebrow:"lead · project",title:"Project yang dipimpin",children:[e.jsx("div",{style:{fontSize:"var(--text-xs)",color:"var(--text-subtle)",marginBottom:10},children:"Lead hanya menyentuh project yang di-opt-in. Default mati."}),a.length===0?e.jsx("div",{style:{fontSize:"var(--text-sm)",color:"var(--text-subtle)"},children:"Belum ada project."}):a.map(t=>{const l=n.projects.find(g=>g.projectId===t.id);return e.jsxs(G,{children:[e.jsx("span",{style:{flex:1,minWidth:0,color:"var(--text-strong)",fontWeight:500},children:t.name}),l&&e.jsxs("span",{style:{fontSize:"var(--text-xs)",color:"var(--text-muted)"},children:[l.decisions24h," keputusan/24j · ",l.openSessions," sesi"]}),e.jsx(m,{tone:F.has(t.id)?l!=null&&l.paused?"warn":"ok":"neutral",size:"sm",children:F.has(t.id)?l!=null&&l.paused?"dijeda":"dipimpin":"mati"}),F.has(t.id)&&(l!=null&&l.paused?e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"play",disabled:O,onClick:()=>W(t.id,!1),children:"Lanjutkan"}):e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"pause",disabled:O,onClick:()=>W(t.id,!0),children:"Pause"})),F.has(t.id)?e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"ban",disabled:I===t.id,onClick:()=>_(t.id,!1),children:"Lepas"}):e.jsx(u,{size:"sm",leftIcon:"check",disabled:I===t.id,onClick:()=>_(t.id,!0),children:"Pimpin"})]},t.id)})]}),e.jsxs(ve,{title:"Sesi menunggu keputusan",count:V.length,empty:"Tak ada sesi yang menunggu keputusan.",children:[R.queued>0&&e.jsxs("div",{style:{fontSize:"var(--text-xs)",color:"var(--text-muted)",marginBottom:8},children:["Gerbang lead: ",R.inFlight,"/",R.capacity," diputuskan · ",R.queued," antre menunggu slot."]}),V.map(t=>{const l=ae.has(t)?"sedang diputuskan":te.has(t)?"antre":"menunggu";return e.jsxs(G,{children:[e.jsx(ie,{name:l==="sedang diputuskan"?"loader":l==="antre"?"clock":"help-circle"}),e.jsx("span",{style:{flex:1,fontFamily:"var(--font-mono)",color:"var(--text-strong)"},children:t}),e.jsx(m,{tone:l==="menunggu"?"warn":"ok",size:"sm",children:l}),e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"terminal",onClick:()=>o(t),children:"Ambil alih"})]},t)})]}),e.jsxs(L,{eyebrow:"lead · rantai keputusan",title:`Rantai (${j})`,children:[v.length===0?e.jsx("div",{style:{fontSize:"var(--text-sm)",color:"var(--text-subtle)"},children:"Belum ada rantai. Satu rantai adalah satu urusan — beberapa pertanyaan berurutan sampai di-submit."}):v.map(t=>e.jsxs(G,{children:[e.jsx(m,{tone:be[t.status]??"neutral",size:"sm",children:t.status}),e.jsx("span",{style:{flex:1,minWidth:0,color:"var(--text-strong)"},children:t.title}),e.jsxs("span",{style:{fontSize:"var(--text-xs)",color:"var(--text-muted)"},children:[t.steps," langkah · ",Q(t.openedAt),t.closeReason?` · ${fe[t.closeReason]??t.closeReason}`:""]}),ke.has(t.status)&&e.jsxs(e.Fragment,{children:[e.jsx(u,{size:"sm",leftIcon:"check",disabled:I===t.id,onClick:()=>K(t.id,"submit"),children:"Submit"}),e.jsx(u,{size:"sm",variant:"ghost",leftIcon:"x-circle",disabled:I===t.id,onClick:()=>K(t.id,"cancel"),children:"Batalkan"})]})]},t.id)),e.jsx(U,{total:j,page:P,onPage:N,unit:"rantai"})]}),e.jsxs(L,{eyebrow:"lead · jejak keputusan",title:`Keputusan (${h})`,actions:e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsx(Y,{size:"sm",value:x,"aria-label":"saring project",onChange:t=>X(t.target.value),options:[{value:"all",label:"semua project"},...a.map(t=>({value:t.id,label:t.name}))]}),e.jsx(le,{screen:"lead",active:x==="all"?0:1}),e.jsx(pe,{})]}),children:[p.length===0?e.jsx("div",{style:{fontSize:"var(--text-sm)",color:"var(--text-subtle)"},children:"Belum ada keputusan. Lead menulis satu baris di sini setiap kali ia memutuskan."}):p.map(t=>e.jsx(Se,{d:t,onOverride:Z,onCancel:ee,busyId:I},t.id)),e.jsx(U,{total:h,page:y,onPage:C,unit:"keputusan"})]})]})}export{Pe as LeadScreen};
@@ -1 +1 @@
1
- import{ah as A,j as e,f as l,v as K,ae as y,a as k,I as L,B as N,e as d}from"./index-DI7G_sit.js";import{R as a}from"./react-DfGhg7ZW.js";import{D as G}from"./DocPreviewModal-ZFjISCL0.js";import{b as J,C as q,T as O,D as Q}from"./diff-view-CsZPBznT.js";import"./markdown-CWEY34jk.js";function ee({specId:r,title:X,onBack:S,kind:f="spec"}){const R=f==="session"?d.sessionReview:d.specReview,F=f==="session"?d.sessionReviewFile:d.specReviewFile,[o,C]=a.useState(null),[x,c]=a.useState("loading"),[B,P]=a.useState(""),[s,g]=a.useState(""),[i,p]=a.useState(null),[u,T]=a.useState("diff"),[z,v]=a.useState(0),[M,D]=a.useState("list"),[V,h]=a.useState(!1),[E,m]=a.useState("files");a.useEffect(()=>{let t=!0;return c("loading"),R(r).then(n=>{var j;t&&(C(n),c("ready"),g(((j=n.changed[0])==null?void 0:j.path)??n.files[0]??""))}).catch(n=>{t&&((n==null?void 0:n.status)===409?(c("empty"),P(String((n==null?void 0:n.message)??""))):c("error"))}),()=>{t=!1}},[r,z]),a.useEffect(()=>{if(!s){p(null);return}let t=!0;return p(null),h(!1),F(r,s).then(n=>{t&&p(n)}).catch(()=>{t&&p(null)}),()=>{t=!1}},[r,s]);const H=a.useMemo(()=>J((o==null?void 0:o.files)??[]),[o]),W=(o==null?void 0:o.changed)??[],b=!!i&&!i.binary&&i.content!==null&&A(s),U=f==="session"?d.sessionReviewFileDownloadUrl:d.specReviewFileDownloadUrl,w=t=>{g(t),m("viewer")};return x==="loading"?e.jsx(l,{kind:"loading",title:"Memuat review…",hint:r}):x==="error"?e.jsx(l,{kind:"error",title:"Gagal memuat review",hint:r,action:()=>v(t=>t+1)}):x==="empty"?e.jsx(l,{kind:"empty",icon:"git-branch",title:"Belum ada worktree untuk di-review",hint:B||"Jalankan atau lanjutkan sesi backlog item ini dulu.",action:S,actionLabel:"Kembali ke backlog"}):e.jsxs(e.Fragment,{children:[e.jsx(K,{ariaLabel:"Panel Review",active:E,onActiveChange:t=>m(t),masterWidth:300,panels:[{id:"files",label:"Files",content:e.jsxs(y,{padding:0,children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:8,padding:"10px 12px",borderBottom:"1px solid var(--border-hair)"},children:[e.jsx("span",{className:"hn-eyebrow",children:r}),e.jsx(k,{size:"sm",variant:"ghost",leftIcon:"rotate-ccw",onClick:()=>v(t=>t+1),children:"Muat ulang"})]}),e.jsxs("div",{style:{maxHeight:640,overflow:"auto",padding:"6px 4px"},children:[e.jsx(q,{label:"Changed",changed:W,selected:s,onSelect:w,view:M,onView:D}),e.jsx("div",{className:"hn-eyebrow",style:{padding:"6px 8px",marginTop:8,borderTop:"1px solid var(--border-hair)"},children:"Files"}),H.map(t=>e.jsx(O,{node:t,selected:s,onSelect:w},t.path))]})]})},{id:"viewer",label:"Viewer",content:e.jsxs(y,{padding:0,children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:12,padding:"10px 16px",borderBottom:"1px solid var(--border-hair)",flexWrap:"wrap"},children:[e.jsx(L,{name:"file-text",size:15,color:"var(--text-muted)"}),e.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:13,color:"var(--text-strong)",fontWeight:500},children:s||"—"}),(i==null?void 0:i.status)&&e.jsx(N,{tone:i.status==="D"?"err":i.status==="A"?"ok":"brass",size:"sm",children:i.status}),e.jsx("span",{style:{flex:1}}),b&&e.jsx(k,{size:"sm",variant:"secondary",leftIcon:"book-open",onClick:()=>h(!0),children:"Preview"}),e.jsx("div",{style:{display:"flex",gap:2,background:"var(--bone-100)",borderRadius:"var(--radius-pill)",padding:2},children:["diff","source"].map(t=>e.jsx("button",{onClick:()=>T(t),style:{padding:"4px 12px",border:"none",cursor:"pointer",borderRadius:"var(--radius-pill)",fontSize:12,textTransform:"capitalize",background:u===t?"var(--surface-card)":"transparent",color:u===t?"var(--text-strong)":"var(--text-muted)",fontWeight:u===t?600:400},children:t},t))})]}),e.jsx("div",{style:{maxHeight:640,overflow:"auto",background:"var(--surface-card)"},children:s?i?i.binary?e.jsx(l,{kind:"empty",icon:"file",title:"Berkas biner",hint:"Tak dapat di-review dari dashboard."}):u==="diff"?e.jsxs("div",{style:{padding:"10px 0"},children:[e.jsx(Q,{diff:i.diff??"",emptyHint:"File ini bagian dari project tapi tak diubah backlog ini."}),i.truncated&&e.jsx("div",{style:{padding:"8px 12px",fontSize:11,color:"var(--text-subtle)"},children:"… dipotong pada 256 KB."})]}):i.content===null?e.jsx(l,{kind:"empty",icon:"trash-2",title:"File dihapus",hint:"Tak ada isi untuk ditampilkan."}):e.jsx("pre",{style:{margin:0,padding:"12px 16px",fontFamily:"var(--font-mono)",fontSize:12.5,lineHeight:1.6,whiteSpace:"pre-wrap",wordBreak:"break-word",color:"var(--text-body)"},children:i.content}):e.jsx(l,{kind:"loading",title:"Memuat file…",hint:s}):e.jsx(l,{kind:"empty",icon:"file-text",title:"Pilih file",hint:"Pilih file dari changed atau tree."})})]})}]}),V&&b&&e.jsx(G,{path:s,text:i.content??"",eyebrow:r,download:t=>U(r,s,t),onClose:()=>h(!1)})]})}export{ee as ReviewScreen};
1
+ import{ak as A,j as e,f as l,v as K,ah as y,a as k,I as L,B as N,e as d}from"./index-BHI_f9DD.js";import{R as a}from"./react-DfGhg7ZW.js";import{D as G}from"./DocPreviewModal-B7r_7p8N.js";import{b as J,C as q,T as O,D as Q}from"./diff-view-RZNZ9Nz6.js";import"./markdown-CWEY34jk.js";function ee({specId:r,title:X,onBack:S,kind:f="spec"}){const R=f==="session"?d.sessionReview:d.specReview,F=f==="session"?d.sessionReviewFile:d.specReviewFile,[o,C]=a.useState(null),[x,c]=a.useState("loading"),[B,P]=a.useState(""),[s,g]=a.useState(""),[i,p]=a.useState(null),[u,T]=a.useState("diff"),[z,v]=a.useState(0),[M,D]=a.useState("list"),[V,h]=a.useState(!1),[E,m]=a.useState("files");a.useEffect(()=>{let t=!0;return c("loading"),R(r).then(n=>{var j;t&&(C(n),c("ready"),g(((j=n.changed[0])==null?void 0:j.path)??n.files[0]??""))}).catch(n=>{t&&((n==null?void 0:n.status)===409?(c("empty"),P(String((n==null?void 0:n.message)??""))):c("error"))}),()=>{t=!1}},[r,z]),a.useEffect(()=>{if(!s){p(null);return}let t=!0;return p(null),h(!1),F(r,s).then(n=>{t&&p(n)}).catch(()=>{t&&p(null)}),()=>{t=!1}},[r,s]);const H=a.useMemo(()=>J((o==null?void 0:o.files)??[]),[o]),W=(o==null?void 0:o.changed)??[],b=!!i&&!i.binary&&i.content!==null&&A(s),U=f==="session"?d.sessionReviewFileDownloadUrl:d.specReviewFileDownloadUrl,w=t=>{g(t),m("viewer")};return x==="loading"?e.jsx(l,{kind:"loading",title:"Memuat review…",hint:r}):x==="error"?e.jsx(l,{kind:"error",title:"Gagal memuat review",hint:r,action:()=>v(t=>t+1)}):x==="empty"?e.jsx(l,{kind:"empty",icon:"git-branch",title:"Belum ada worktree untuk di-review",hint:B||"Jalankan atau lanjutkan sesi backlog item ini dulu.",action:S,actionLabel:"Kembali ke backlog"}):e.jsxs(e.Fragment,{children:[e.jsx(K,{ariaLabel:"Panel Review",active:E,onActiveChange:t=>m(t),masterWidth:300,panels:[{id:"files",label:"Files",content:e.jsxs(y,{padding:0,children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:8,padding:"10px 12px",borderBottom:"1px solid var(--border-hair)"},children:[e.jsx("span",{className:"hn-eyebrow",children:r}),e.jsx(k,{size:"sm",variant:"ghost",leftIcon:"rotate-ccw",onClick:()=>v(t=>t+1),children:"Muat ulang"})]}),e.jsxs("div",{style:{maxHeight:640,overflow:"auto",padding:"6px 4px"},children:[e.jsx(q,{label:"Changed",changed:W,selected:s,onSelect:w,view:M,onView:D}),e.jsx("div",{className:"hn-eyebrow",style:{padding:"6px 8px",marginTop:8,borderTop:"1px solid var(--border-hair)"},children:"Files"}),H.map(t=>e.jsx(O,{node:t,selected:s,onSelect:w},t.path))]})]})},{id:"viewer",label:"Viewer",content:e.jsxs(y,{padding:0,children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:12,padding:"10px 16px",borderBottom:"1px solid var(--border-hair)",flexWrap:"wrap"},children:[e.jsx(L,{name:"file-text",size:15,color:"var(--text-muted)"}),e.jsx("span",{style:{fontFamily:"var(--font-mono)",fontSize:13,color:"var(--text-strong)",fontWeight:500},children:s||"—"}),(i==null?void 0:i.status)&&e.jsx(N,{tone:i.status==="D"?"err":i.status==="A"?"ok":"brass",size:"sm",children:i.status}),e.jsx("span",{style:{flex:1}}),b&&e.jsx(k,{size:"sm",variant:"secondary",leftIcon:"book-open",onClick:()=>h(!0),children:"Preview"}),e.jsx("div",{style:{display:"flex",gap:2,background:"var(--bone-100)",borderRadius:"var(--radius-pill)",padding:2},children:["diff","source"].map(t=>e.jsx("button",{onClick:()=>T(t),style:{padding:"4px 12px",border:"none",cursor:"pointer",borderRadius:"var(--radius-pill)",fontSize:12,textTransform:"capitalize",background:u===t?"var(--surface-card)":"transparent",color:u===t?"var(--text-strong)":"var(--text-muted)",fontWeight:u===t?600:400},children:t},t))})]}),e.jsx("div",{style:{maxHeight:640,overflow:"auto",background:"var(--surface-card)"},children:s?i?i.binary?e.jsx(l,{kind:"empty",icon:"file",title:"Berkas biner",hint:"Tak dapat di-review dari dashboard."}):u==="diff"?e.jsxs("div",{style:{padding:"10px 0"},children:[e.jsx(Q,{diff:i.diff??"",emptyHint:"File ini bagian dari project tapi tak diubah backlog ini."}),i.truncated&&e.jsx("div",{style:{padding:"8px 12px",fontSize:11,color:"var(--text-subtle)"},children:"… dipotong pada 256 KB."})]}):i.content===null?e.jsx(l,{kind:"empty",icon:"trash-2",title:"File dihapus",hint:"Tak ada isi untuk ditampilkan."}):e.jsx("pre",{style:{margin:0,padding:"12px 16px",fontFamily:"var(--font-mono)",fontSize:12.5,lineHeight:1.6,whiteSpace:"pre-wrap",wordBreak:"break-word",color:"var(--text-body)"},children:i.content}):e.jsx(l,{kind:"loading",title:"Memuat file…",hint:s}):e.jsx(l,{kind:"empty",icon:"file-text",title:"Pilih file",hint:"Pilih file dari changed atau tree."})})]})}]}),V&&b&&e.jsx(G,{path:s,text:i.content??"",eyebrow:r,download:t=>U(r,s,t),onClose:()=>h(!1)})]})}export{ee as ReviewScreen};
@@ -1 +1 @@
1
- import{h as D,p as le,y as ie,e as v,an as U,ao as se,j as e,ae as w,I as T,a as g,B as P,ap as oe,M as de,c as C,d as z,S as I,aq as ue,H as ce,U as Q,V as pe,ar as H,as as xe,at as W,x as V,w as Y,D as X,q as Z,f as _,z as me,au as he}from"./index-DI7G_sit.js";import{R as m}from"./react-DfGhg7ZW.js";import{L as ge}from"./live-DVDstDzi.js";import"./markdown-CWEY34jk.js";const J=10,G=a=>String(a).padStart(2,"0"),B=a=>a?new Date(a).toLocaleString("id-ID",{dateStyle:"medium",timeStyle:"short"}):"—",K=a=>{const i={name:(a==null?void 0:a.name)??"",prompt:(a==null?void 0:a.prompt)??"",enabled:(a==null?void 0:a.enabled)??!1,kind:"lanjutan",time:"07:00",weekday:1,everyHours:6,expr:(a==null?void 0:a.expr)??"0 7 * * *",agent:(a==null?void 0:a.agent)??"",model:(a==null?void 0:a.model)??"",effort:(a==null?void 0:a.effort)??""},l=a?xe(a.expr):{kind:"harian",hour:7,minute:0};if(!l)return i;if(l.kind==="tiap-n-jam")return{...i,kind:l.kind,everyHours:l.everyHours,time:`00:${G(l.minute)}`};const t=`${G(l.hour)}:${G(l.minute)}`;return l.kind==="mingguan"?{...i,kind:l.kind,time:t,weekday:l.weekday}:{...i,kind:l.kind,time:t}},fe=a=>{if(a.kind==="lanjutan")return a.expr.trim();const[i,l]=a.time.split(":").map(Number);switch(a.kind){case"harian":return W({kind:"harian",hour:i,minute:l});case"hari-kerja":return W({kind:"hari-kerja",hour:i,minute:l});case"mingguan":return W({kind:"mingguan",hour:i,minute:l,weekday:a.weekday});case"tiap-n-jam":return W({kind:"tiap-n-jam",everyHours:a.everyHours,minute:l})}},be={launched:"ok",queued:"neutral",skipped:"warn",failed:"err"},je={launched:"berjalan",queued:"menunggu",skipped:"dilewati",failed:"gagal"};function ve({cronId:a}){const[i,l]=m.useState([]),[t,p]=m.useState(0),[u,f]=D("scheduler","cronRunsPage",1,V);m.useEffect(()=>{let o=!0;return v.listCronRuns(a,{page:u,limit:J}).then(n=>{o&&(l(n.items),p(n.total))}).catch(()=>{o&&(l([]),p(0))}),()=>{o=!1}},[a,u]);const x=X(t,u,J);return t===0?e.jsx("div",{style:{fontSize:"var(--text-sm)",color:"var(--text-subtle)"},children:"Belum ada eksekusi."}):e.jsxs(e.Fragment,{children:[i.map(o=>e.jsxs("div",{className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:10,padding:"8px 10px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",marginBottom:6},children:[e.jsx(P,{tone:be[o.status]??"neutral",size:"sm",children:je[o.status]??o.status}),e.jsxs("span",{style:{flex:1,minWidth:0,fontSize:"var(--text-xs)",color:"var(--text-muted)"},children:["jatuh tempo ",B(o.dueAt),o.startedAt?` · mulai ${B(o.startedAt)}`:"",o.sessionId?` · sesi ${o.sessionId}`:"",o.manual?" · uji coba":"",o.note?` · ${o.note}`:""]})]},o.id)),e.jsx(Y,{page:x.page,pageCount:x.pageCount,total:t,from:x.from,to:x.to,onPage:f,unit:"run"})]})}function ye({projects:a,onProjectChanged:i,onToast:l}){var F;const[t,p]=D("scheduler","cronProject",((F=a[0])==null?void 0:F.id)??"",le),[u,f]=m.useState([]),[x,o]=m.useState(void 0),[n,d]=m.useState(K()),[j,k]=D("scheduler","cronOpenRuns",null,ie),[h,y]=m.useState(!1),M=a.find(r=>r.id===t),S=m.useCallback(()=>{if(!t){f([]);return}v.listCrons({projectId:t,page:1,limit:100}).then(r=>f(r.items)).catch(()=>f([]))},[t]);m.useEffect(()=>{S()},[S]);const s=r=>{o(r??null),d(K(r))},b=fe(n),A=U(b)?se(b,new Date):null,L=async()=>{var r;if(!U(b)){l("Cron expression tak sah","err","x-circle");return}y(!0);try{x?await v.patchCron(x.id,{name:n.name,expr:b,prompt:n.prompt,enabled:n.enabled,agent:n.agent||null,model:n.model||null,effort:n.effort||null}):await v.createCron({project:t,name:n.name,expr:b,prompt:n.prompt,enabled:n.enabled,agent:n.agent||void 0,model:n.model||void 0,effort:n.effort||void 0}),l("Cron tersimpan","ok","save"),o(void 0),S()}catch(c){l(((r=c.detail)==null?void 0:r.error)??"Gagal menyimpan cron","err","x-circle")}finally{y(!1)}},ae=async r=>{var c;y(!0);try{await v.runCronNow(r),l("Uji coba diantrekan — sesi terbuka di tick berikutnya","ok","play")}catch(re){l(((c=re.detail)==null?void 0:c.error)??"Gagal menjalankan cron","err","x-circle")}finally{y(!1),S()}},te=async r=>{y(!0);try{await v.deleteCron(r),l("Cron dihapus","ok","trash")}catch{l("Gagal menghapus cron","err","x-circle")}finally{y(!1),S()}},ne=async()=>{if(t)try{await v.updateProject(t,{schedulerOptIn:!0}),await i(t),l("Project di-opt-in","ok")}catch{l("Gagal mengubah opt-in","err","x-circle")}},N=n.agent||"claude";return e.jsxs(w,{eyebrow:"scheduler · cronjob",title:"Pengecekan rutin per project",actions:e.jsxs("div",{style:{display:"flex",gap:8,alignItems:"center"},children:[e.jsx(I,{value:t,"aria-label":"Project",onChange:r=>p(r.target.value),options:a.map(r=>({value:r.id,label:r.name}))}),e.jsx(g,{size:"sm",leftIcon:"plus",disabled:!t,onClick:()=>s(),children:"Cron baru"})]}),children:[M&&!M.schedulerOptIn&&e.jsxs("div",{className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:10,marginBottom:12,padding:"10px 12px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",background:"var(--surface-sunken)"},children:[e.jsx(T,{name:"alert-triangle",size:16,color:"var(--clay-500)"}),e.jsx("span",{style:{flex:1,fontSize:"var(--text-xs)",color:"var(--text-muted)"},children:"Project ini belum di-opt-in scheduler — cron-nya tak akan pernah dijalankan."}),e.jsx(g,{size:"sm",leftIcon:"check",onClick:()=>void ne(),children:"Aktifkan scheduler di project ini"})]}),u.length===0?e.jsx("div",{style:{fontSize:"var(--text-sm)",color:"var(--text-subtle)"},children:"Belum ada cron di project ini."}):u.map(r=>e.jsxs("div",{style:{padding:"10px 12px",marginBottom:6,border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",background:"var(--surface-card)"},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,flexWrap:"wrap"},children:[e.jsx("span",{style:{color:"var(--text-strong)",fontWeight:500},children:r.name}),e.jsx(P,{tone:r.enabled?"ok":"neutral",size:"sm",children:r.enabled?"aktif":"nonaktif"}),e.jsx("span",{style:{flex:1}}),e.jsx(g,{size:"sm",variant:"ghost",leftIcon:"play",disabled:h,onClick:()=>void ae(r.id),children:"Jalankan sekarang"}),e.jsx(g,{size:"sm",variant:"ghost",leftIcon:"list",onClick:()=>k(j===r.id?null:r.id),children:"Riwayat"}),e.jsx(g,{size:"sm",variant:"ghost",leftIcon:"pencil",onClick:()=>s(r),children:"Ubah"}),e.jsx(g,{size:"sm",variant:"ghost",leftIcon:"trash",disabled:h,onClick:()=>void te(r.id),children:"Hapus"})]}),e.jsxs("div",{style:{marginTop:4,fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:[oe(r.expr)," · terakhir ",B(r.lastRunAt)," · berikutnya ",B(r.nextRunAt)]}),j===r.id&&e.jsx("div",{style:{marginTop:10},children:e.jsx(ve,{cronId:r.id})})]},r.id)),e.jsxs(de,{open:x!==void 0,title:x?"Ubah cron":"Cron baru",eyebrow:"scheduler",onClose:()=>o(void 0),width:620,footer:e.jsxs("div",{style:{display:"flex",gap:8,justifyContent:"flex-end"},children:[e.jsx(g,{size:"sm",variant:"ghost",onClick:()=>o(void 0),children:"Batal"}),e.jsx(g,{size:"sm",leftIcon:"save",disabled:h,onClick:()=>void L(),children:"Simpan"})]}),children:[e.jsx(C,{label:"Nama cron",children:e.jsx(z,{"aria-label":"Nama cron",placeholder:"Cek error produksi pagi",value:n.name,onChange:r=>d(c=>({...c,name:r.target.value}))})}),e.jsxs("div",{className:"hn-grid-mobile",style:{display:"grid",gridTemplateColumns:"repeat(3, minmax(0,1fr))",gap:10},children:[e.jsx(C,{label:"Preset jadwal",children:e.jsx(I,{"aria-label":"Preset jadwal",value:n.kind,onChange:r=>d(c=>({...c,kind:r.target.value})),options:[{value:"harian",label:"Setiap hari"},{value:"hari-kerja",label:"Hari kerja"},{value:"mingguan",label:"Mingguan"},{value:"tiap-n-jam",label:"Tiap N jam"},{value:"lanjutan",label:"Lanjutan (cron expression)"}]})}),n.kind!=="lanjutan"&&e.jsx(C,{label:n.kind==="tiap-n-jam"?"Menit (dari jam)":"Jam",children:e.jsx(z,{type:"time","aria-label":"Jam",value:n.time,onChange:r=>d(c=>({...c,time:r.target.value}))})}),n.kind==="mingguan"&&e.jsx(C,{label:"Hari",children:e.jsx(I,{"aria-label":"Hari",value:String(n.weekday),onChange:r=>d(c=>({...c,weekday:Number(r.target.value)})),options:ue.map((r,c)=>({value:String(c),label:r}))})}),n.kind==="tiap-n-jam"&&e.jsx(C,{label:"Tiap berapa jam",children:e.jsx(z,{type:"number",min:1,max:23,"aria-label":"Tiap berapa jam",placeholder:"mis. 6",value:String(n.everyHours),onChange:r=>d(c=>({...c,everyHours:Math.min(23,Math.max(1,Number(r.target.value)||1))}))})})]}),n.kind==="lanjutan"&&e.jsx(C,{label:"Cron expression",hint:"Lima field: menit jam tanggal bulan hari-pekan — zona waktu server.",children:e.jsx(z,{"aria-label":"Cron expression",placeholder:"0 7 * * 1-5",value:n.expr,onChange:r=>d(c=>({...c,expr:r.target.value}))})}),e.jsx("div",{"data-testid":"cron-next-preview",style:{marginBottom:14,fontSize:"var(--text-xs)",color:A?"var(--text-muted)":"var(--clay-500)"},children:A?`Jalan berikutnya: ${B(A.toISOString())} (waktu lokal)`:"Jadwal tak sah — tak ada jalan berikutnya"}),e.jsx(C,{label:"Prompt",hint:"Instruksi bebas untuk agen. Temuan sebaiknya difilekan sebagai backlog lewat POST /api/specs.",children:e.jsx(ce,{"aria-label":"Prompt",rows:6,placeholder:"mis. Periksa error 5xx sejak kemarin, lalu filekan temuannya sebagai QA finding.",value:n.prompt,onChange:r=>d(c=>({...c,prompt:r.target.value}))})}),e.jsxs("div",{className:"hn-grid-mobile",style:{display:"grid",gridTemplateColumns:"repeat(3, minmax(0,1fr))",gap:10},children:[e.jsx(C,{label:"Runtime",children:e.jsx(I,{"aria-label":"Runtime",value:n.agent,onChange:r=>d(c=>({...c,agent:r.target.value,model:"",effort:""})),options:[{value:"",label:"Warisi default sesi"},{value:"claude",label:"Claude Code"},{value:"codex",label:"Codex CLI"}]})}),e.jsx(C,{label:"Model",children:e.jsx(I,{"aria-label":"Model",value:n.model,disabled:!n.agent,onChange:r=>d(c=>({...c,model:r.target.value,effort:""})),options:[{value:"",label:"Warisi"},...Q(N).map(r=>({value:r.id,label:r.label}))]})}),e.jsx(C,{label:"Effort",children:e.jsx(I,{"aria-label":"Effort",value:n.effort,disabled:!n.agent,onChange:r=>d(c=>({...c,effort:r.target.value})),options:[{value:"",label:"Warisi"},...pe(N,n.model||Q(N)[0].id).map(r=>({value:r,label:r}))]})})]}),e.jsx(H,{label:"Aktif",checked:n.enabled,onChange:r=>d(c=>({...c,enabled:r}))})]})]})}const q=5e3,O=10;function ee(a,i=Date.now()){if(!a)return"—";const l=Math.max(0,i-new Date(a).getTime()),t=Math.floor(l/6e4);if(t<1)return"baru saja";if(t<60)return`${t}m`;const p=Math.floor(t/60);return p<24?`${p}j`:`${Math.floor(p/24)}h`}function ke(a,i=Date.now()){if(!a)return"—";const l=new Date(a).getTime()-i;if(l<=0)return"jatuh tempo";const t=Math.ceil(l/6e4);return t<60?`${t}m lagi`:`${Math.ceil(t/60)}j lagi`}const Ce={tinggi:"err",sedang:"warn",rendah:"neutral"};function E(a,i){var l;return((l=i.find(t=>t.id===a))==null?void 0:l.title)??a}function Se({s:a}){return e.jsxs("div",{style:{padding:"12px 14px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-md)",background:"var(--surface-card)",display:"flex",flexDirection:"column",gap:6,flex:1,minWidth:180},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsx("span",{style:{fontFamily:"var(--font-mono)",fontWeight:600,color:"var(--text-strong)"},children:a.id}),e.jsx(P,{tone:a.enabled?"ok":"neutral",size:"sm",children:a.enabled?"aktif":"nonaktif"})]}),e.jsxs("div",{style:{fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:["tiap ",a.everyMin,"m"]}),e.jsxs("div",{style:{fontSize:"var(--text-xs)",color:"var(--text-muted)"},children:["terakhir ",ee(a.lastRunAt)," · berikutnya ",ke(a.nextRunAt)]})]})}function R({children:a}){return e.jsx("div",{className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:10,padding:"10px 12px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",background:"var(--surface-card)",marginBottom:6},children:a})}function we({q:a,backlog:i,onCancel:l,busy:t}){return e.jsxs(R,{children:[e.jsxs("span",{style:{flex:1,minWidth:0},children:[e.jsx("span",{style:{color:"var(--text-strong)",fontWeight:500},children:E(a.specId,i)}),e.jsxs("span",{style:{display:"block",fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:[a.projectId," · ",a.source,a.note?` · ${a.note}`:""]})]}),e.jsx(P,{tone:Ce[a.priority]??"neutral",size:"sm",children:a.priority}),e.jsx(g,{size:"sm",variant:"ghost",leftIcon:"ban",disabled:t,onClick:()=>l(a.id),children:"Batalkan"})]})}function Ie({q:a,backlog:i,onRequeue:l,busy:t}){return e.jsxs(R,{children:[e.jsx(T,{name:"ban",size:16,color:"var(--text-subtle)"}),e.jsxs("span",{style:{flex:1,minWidth:0},children:[e.jsx("span",{style:{color:"var(--text-strong)",fontWeight:500},children:E(a.specId,i)}),e.jsxs("span",{style:{display:"block",fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:[a.projectId," · ",a.source," · ",a.note??"dibatalkan"]})]}),e.jsx(g,{size:"sm",variant:"ghost",leftIcon:"rotate-ccw",disabled:t,onClick:()=>l(a.id),children:"Antre lagi"})]})}function ze({s:a,backlog:i,onGotoTerminal:l}){return e.jsxs(R,{children:[e.jsxs("span",{style:{flex:1,minWidth:0},children:[e.jsx("span",{style:{color:"var(--text-strong)",fontWeight:500},children:E(a.specId,i)}),e.jsxs("span",{style:{display:"block",fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:[a.projectId,a.flow?` · ${a.flow}`:""]})]}),a.decision&&e.jsx(P,{tone:"warn",icon:"bell",size:"sm",children:"menunggu keputusan"}),e.jsx(g,{size:"sm",variant:"ghost",leftIcon:"terminal",onClick:()=>l(a.id),children:"Buka terminal"})]})}function Pe({q:a,backlog:i,onToast:l}){const t=me(a.specId);return e.jsxs(R,{children:[e.jsxs("span",{style:{flex:1,minWidth:0},children:[e.jsx("span",{style:{color:"var(--text-strong)",fontWeight:500},children:E(a.specId,i)}),e.jsxs("span",{style:{display:"block",fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:[a.projectId," · ",a.source," · ",a.launchedAt?`selesai ${ee(a.launchedAt)}`:a.note??"tak diluncurkan",a.sessionId?` · hanoman/${a.sessionId}`:""]})]}),e.jsx(g,{size:"sm",variant:"ghost",leftIcon:"external-link",onClick:()=>window.open(t,"_blank","noreferrer"),children:"Buka review"}),e.jsx(g,{size:"sm",variant:"ghost",leftIcon:"copy",onClick:()=>{var p;(p=navigator.clipboard)==null||p.writeText(t),l("Link review disalin","ok","copy")},children:"Salin"})]})}function Re({q:a,backlog:i}){return e.jsxs(R,{children:[e.jsx(T,{name:"x-circle",size:16,color:"var(--clay-500)"}),e.jsxs("span",{style:{flex:1,minWidth:0},children:[e.jsx("span",{style:{color:"var(--text-strong)",fontWeight:500},children:E(a.specId,i)}),e.jsxs("span",{style:{display:"block",fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:[a.projectId," · ",a.note??"gagal tanpa alasan tercatat"]})]})]})}function Ae({title:a,count:i,empty:l,children:t}){return e.jsx(w,{eyebrow:"scheduler",title:`${a}${i?` · ${i}`:""}`,children:i===0?e.jsx("div",{style:{fontSize:"var(--text-sm)",color:"var(--text-subtle)"},children:l}):t})}function $({title:a,status:i,count:l,empty:t,render:p}){const[u,f]=m.useState([]),[x,o]=m.useState(0),[n,d]=D("scheduler",`queue-${i}-page`,1,V),j=m.useCallback(()=>{let h=!0;return v.getSchedulerQueue({status:i,page:n,limit:O}).then(y=>{h&&(f(y.items),o(y.total))}).catch(()=>{h&&(f([]),o(0))}),()=>{h=!1}},[i,n]);m.useEffect(()=>j(),[j]),Z({topic:"schedulerQueue",params:{status:i,page:n,limit:O},apply:h=>{f(h.data.items),o(h.data.total)},refetch:()=>{j()},pollMs:q});const k=X(x,n,O);return e.jsx(w,{eyebrow:"scheduler",title:`${a}${l?` · ${l}`:""}`,children:l===0?e.jsx("div",{style:{fontSize:"var(--text-sm)",color:"var(--text-subtle)"},children:t}):e.jsxs(e.Fragment,{children:[u.map(h=>p(h)),e.jsx(Y,{page:k.page,pageCount:k.pageCount,total:x,from:k.from,to:k.to,onPage:d,unit:"item"})]})})}function Le({cfg:a,cap:i,liveCount:l,onWrite:t,busy:p}){const u=!a.enabled,f=u?"neutral":a.paused?"warn":"ok",x=u?"berhenti":a.paused?"dijeda":"aktif";return e.jsx(w,{eyebrow:"scheduler · rem darurat",title:"Kendali",children:e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:12,flexWrap:"wrap"},children:[e.jsx(P,{tone:f,children:x}),e.jsxs("span",{style:{fontSize:"var(--text-sm)",color:"var(--text-muted)"},children:[l," / ",i," sesi hidup"]}),e.jsx(ge,{}),e.jsx("span",{style:{flex:1}}),a.enabled&&e.jsx(g,{size:"sm",variant:"secondary",leftIcon:a.paused?"play":"pause",disabled:p,onClick:()=>t({...a,paused:!a.paused}),children:a.paused?"Lanjutkan":"Pause"}),a.enabled?e.jsx(g,{size:"sm",variant:"ghost",leftIcon:"square",disabled:p,onClick:()=>t({...a,enabled:!1}),children:"Stop"}):e.jsx(g,{size:"sm",leftIcon:"play",disabled:p,onClick:()=>t({...a,enabled:!0}),children:"Aktifkan"})]})})}function Be({status:a}){return e.jsx(w,{eyebrow:"host · peluncuran agen",title:"Gerbang peluncuran",children:e.jsxs("div",{"aria-label":"Status gerbang peluncuran",style:{fontSize:"var(--text-sm)",color:"var(--text-muted)",lineHeight:1.6},children:[e.jsxs("div",{children:["Gerbang ",a.enabled?"aktif":"nonaktif"," · ",a.liveCount," sesi hidup · ",a.liveAgentCount," agen terstruktur · cap ",a.maxConcurrent]}),e.jsxs("div",{children:["Load per core: ",a.loadStatus==="available"&&a.loadPerCore!==null?a.loadPerCore.toFixed(2):"tidak tersedia",a.loadStatus==="unsupported"?" (tidak didukung platform)":""," · ambang ",a.maxLoadPerCore]}),e.jsx("div",{style:{fontSize:"var(--text-xs)",marginTop:6},children:"Berlaku juga saat scheduler berhenti. Terminal dan shell tetap bisa dibuka; keduanya ikut mengisi cap."})]})})}function Ee({cfg:a,onWrite:i,busy:l}){const[t,p]=m.useState(a);m.useEffect(()=>{p(a)},[a]);const u=(n,d)=>p(j=>({...j,sources:{...j.sources,[n]:{...j.sources[n],...d}}})),f=(n,d=1)=>Math.max(d,Number(n)||d),x=t.launchGuard??he.launchGuard,o=Number.isFinite(x.maxLoadPerCore)&&x.maxLoadPerCore>0;return e.jsxs(w,{eyebrow:"scheduler · setelan",title:"Konfigurasi",actions:e.jsx(g,{size:"sm",leftIcon:"save",disabled:l||!o,onClick:()=>i({...t,launchGuard:x}),children:"Simpan setelan"}),children:[e.jsxs("div",{className:"hn-grid-mobile",style:{display:"grid",gridTemplateColumns:"repeat(2, minmax(0,1fr))",gap:14},children:[e.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:4},children:[e.jsx("span",{className:"hn-eyebrow",children:"Cap concurrent"}),e.jsx(z,{type:"number",min:1,value:String(t.maxConcurrent),"aria-label":"Cap concurrent",placeholder:"6",onChange:n=>p(d=>({...d,maxConcurrent:f(n.target.value)}))})]}),e.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:4},children:[e.jsx("span",{className:"hn-eyebrow",children:"Autonomy"}),e.jsx(I,{value:t.autonomy,"aria-label":"Autonomy",onChange:n=>p(d=>({...d,autonomy:n.target.value})),options:[{value:"butuh-keputusan",label:"butuh-keputusan"},{value:"full-control",label:"full-control"}]})]})]}),e.jsxs("div",{style:{marginTop:14,padding:"10px 12px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)"},children:[e.jsx(H,{label:"Gerbang peluncuran",checked:x.enabled,onChange:n=>p(d=>({...d,launchGuard:{...x,enabled:n}}))}),e.jsx("p",{style:{fontSize:"var(--text-xs)",color:"var(--text-muted)",lineHeight:1.5},children:"Membatasi peluncuran agen menurut cap sesi dan beban host, termasuk peluncuran manual. Mematikannya melewati kedua pemeriksaan. Terpisah dari sakelar scheduler dan source."}),e.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:4},children:[e.jsx("span",{className:"hn-eyebrow",children:"Ambang load per core"}),e.jsx(z,{type:"number",min:0,step:"any",value:String(x.maxLoadPerCore),"aria-label":"Ambang load per core","aria-invalid":!o,placeholder:"2.5",onChange:n=>p(d=>({...d,launchGuard:{...x,maxLoadPerCore:Number(n.target.value)}}))}),!o&&e.jsx("span",{style:{fontSize:"var(--text-xs)",color:"var(--clay-500)"},children:"Isi angka lebih besar dari nol."})]})]}),e.jsx("div",{style:{marginTop:14,display:"flex",flexDirection:"column",gap:10},children:["backlog","triase"].map(n=>e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:12,flexWrap:"wrap",padding:"10px 12px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)"},children:[e.jsx(H,{label:n,checked:t.sources[n].enabled,onChange:d=>u(n,{enabled:d})}),e.jsx("span",{style:{flex:1}}),e.jsxs("label",{style:{display:"flex",alignItems:"center",gap:6,fontSize:"var(--text-xs)"},children:["tiap",e.jsx(z,{type:"number",min:1,style:{width:84},"aria-label":`cadence ${n}`,placeholder:"30",value:String(t.sources[n].everyMin),onChange:d=>u(n,{everyMin:f(d.target.value)})}),"menit"]})]},n))})]})}function Me({projects:a,onToggle:i,busyId:l}){return e.jsxs(w,{eyebrow:"scheduler · opt-in project",title:"Project yang diizinkan",children:[e.jsx("div",{style:{fontSize:"var(--text-xs)",color:"var(--text-subtle)",marginBottom:10},children:"Scheduler hanya menyentuh project yang di-opt-in. Default mati."}),a.length===0?e.jsx("div",{style:{fontSize:"var(--text-sm)",color:"var(--text-subtle)"},children:"Belum ada project."}):a.map(t=>e.jsxs(R,{children:[e.jsx("span",{style:{flex:1,minWidth:0,color:"var(--text-strong)",fontWeight:500},children:t.name}),e.jsx(P,{tone:t.schedulerOptIn?"ok":"neutral",size:"sm",children:t.schedulerOptIn?"opt-in":"mati"}),t.schedulerOptIn?e.jsx(g,{size:"sm",variant:"ghost",leftIcon:"ban",disabled:l===t.id,onClick:()=>i(t.id,!1),children:"Cabut opt-in"}):e.jsx(g,{size:"sm",leftIcon:"check",disabled:l===t.id,onClick:()=>i(t.id,!0),children:"Opt-in"})]},t.id))]})}function Ge({projects:a,backlog:i,onProjectChanged:l,onToast:t,onGotoTerminal:p}){const[u,f]=m.useState(null),[x,o]=m.useState("loading"),[n,d]=m.useState(!1),[j,k]=m.useState(null),h=m.useCallback((s=!1)=>{s||o("loading"),v.getSchedulerState().then(b=>{f(b),o("ready")}).catch(()=>{s||o("error")})},[]);m.useEffect(()=>{h()},[h]),Z({topic:"schedulerState",params:{},apply:s=>{f(s.state),o("ready")},refetch:()=>h(!0),pollMs:q});const y=m.useCallback(async s=>{d(!0);try{await v.putSchedulerConfig(s),t("Setelan scheduler tersimpan","ok","save"),h(!0)}catch{t("Gagal menyimpan setelan","err","x-circle")}finally{d(!1)}},[h,t]),M=m.useCallback(async(s,b)=>{k(s);try{await v.updateProject(s,{schedulerOptIn:b}),await l(s),t(b?"Project di-opt-in":"Opt-in dicabut","ok")}catch{t("Gagal mengubah opt-in","err","x-circle")}finally{k(null)}},[l,t]),S=m.useCallback(async(s,b)=>{k(s);try{b==="cancel"?(await v.cancelSchedulerQueueItem(s),t("Item antrean dibatalkan","ok","ban")):(await v.requeueSchedulerQueueItem(s),t("Item dikembalikan ke antrean","ok","rotate-ccw"))}catch(A){const L=A.detail;t((L==null?void 0:L.error)??"Gagal mengubah item antrean","err","x-circle")}finally{k(null),h(!0)}},[h,t]);return x==="loading"?e.jsx(_,{kind:"loading"}):x==="error"||!u?e.jsx(_,{kind:"error",hint:"Gagal memuat state scheduler.",action:()=>h(),actionLabel:"Coba lagi"}):e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:16,minHeight:0},children:[e.jsx(Le,{cfg:u.config,cap:u.cap,liveCount:u.liveCount,onWrite:y,busy:n}),u.admission&&e.jsx(Be,{status:u.admission}),e.jsx(w,{eyebrow:"scheduler · observabilitas",title:"Status per source",children:e.jsx("div",{style:{display:"flex",gap:10,flexWrap:"wrap"},children:u.sources.map(s=>e.jsx(Se,{s},s.id))})}),e.jsx(ye,{projects:a,onProjectChanged:l,onToast:t}),e.jsx($,{title:"Antrean",status:"queued",count:u.queueCounts.queued,empty:"Antrean kosong.",render:s=>e.jsx(we,{q:s,backlog:i,onCancel:b=>void S(b,"cancel"),busy:j===s.id},s.id)}),e.jsx($,{title:"Dibatalkan",status:"canceled",count:u.queueCounts.canceled,empty:"Tak ada item yang dibatalkan.",render:s=>e.jsx(Ie,{q:s,backlog:i,onRequeue:b=>void S(b,"requeue"),busy:j===s.id},s.id)}),e.jsx(Ae,{title:"Sesi berjalan",count:u.sessions.length,empty:"Tak ada sesi scheduler berjalan.",children:u.sessions.map(s=>e.jsx(ze,{s,backlog:i,onGotoTerminal:p},s.id))}),e.jsx($,{title:"Selesai (done)",status:"done",count:u.queueCounts.done,empty:"Belum ada hasil selesai.",render:s=>e.jsx(Pe,{q:s,backlog:i,onToast:t},s.id)}),e.jsx($,{title:"Gagal",status:"failed",count:u.queueCounts.failed,empty:"Tak ada sesi gagal.",render:s=>e.jsx(Re,{q:s,backlog:i},s.id)}),e.jsx(Ee,{cfg:u.config,onWrite:y,busy:n}),e.jsx(Me,{projects:a,onToggle:M,busyId:j})]})}export{Ge as SchedulerScreen};
1
+ import{h as D,p as le,y as ie,e as v,aq as U,ar as se,j as e,ah as w,I as T,a as g,B as P,as as oe,M as de,c as C,d as z,S as I,at as ue,H as ce,U as Q,V as pe,au as H,av as xe,aw as W,x as V,w as Y,D as X,q as Z,f as _,z as me,ax as he}from"./index-BHI_f9DD.js";import{R as m}from"./react-DfGhg7ZW.js";import{L as ge}from"./live-CniaVDeP.js";import"./markdown-CWEY34jk.js";const J=10,G=a=>String(a).padStart(2,"0"),B=a=>a?new Date(a).toLocaleString("id-ID",{dateStyle:"medium",timeStyle:"short"}):"—",K=a=>{const i={name:(a==null?void 0:a.name)??"",prompt:(a==null?void 0:a.prompt)??"",enabled:(a==null?void 0:a.enabled)??!1,kind:"lanjutan",time:"07:00",weekday:1,everyHours:6,expr:(a==null?void 0:a.expr)??"0 7 * * *",agent:(a==null?void 0:a.agent)??"",model:(a==null?void 0:a.model)??"",effort:(a==null?void 0:a.effort)??""},l=a?xe(a.expr):{kind:"harian",hour:7,minute:0};if(!l)return i;if(l.kind==="tiap-n-jam")return{...i,kind:l.kind,everyHours:l.everyHours,time:`00:${G(l.minute)}`};const t=`${G(l.hour)}:${G(l.minute)}`;return l.kind==="mingguan"?{...i,kind:l.kind,time:t,weekday:l.weekday}:{...i,kind:l.kind,time:t}},fe=a=>{if(a.kind==="lanjutan")return a.expr.trim();const[i,l]=a.time.split(":").map(Number);switch(a.kind){case"harian":return W({kind:"harian",hour:i,minute:l});case"hari-kerja":return W({kind:"hari-kerja",hour:i,minute:l});case"mingguan":return W({kind:"mingguan",hour:i,minute:l,weekday:a.weekday});case"tiap-n-jam":return W({kind:"tiap-n-jam",everyHours:a.everyHours,minute:l})}},be={launched:"ok",queued:"neutral",skipped:"warn",failed:"err"},je={launched:"berjalan",queued:"menunggu",skipped:"dilewati",failed:"gagal"};function ve({cronId:a}){const[i,l]=m.useState([]),[t,p]=m.useState(0),[u,f]=D("scheduler","cronRunsPage",1,V);m.useEffect(()=>{let o=!0;return v.listCronRuns(a,{page:u,limit:J}).then(n=>{o&&(l(n.items),p(n.total))}).catch(()=>{o&&(l([]),p(0))}),()=>{o=!1}},[a,u]);const x=X(t,u,J);return t===0?e.jsx("div",{style:{fontSize:"var(--text-sm)",color:"var(--text-subtle)"},children:"Belum ada eksekusi."}):e.jsxs(e.Fragment,{children:[i.map(o=>e.jsxs("div",{className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:10,padding:"8px 10px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",marginBottom:6},children:[e.jsx(P,{tone:be[o.status]??"neutral",size:"sm",children:je[o.status]??o.status}),e.jsxs("span",{style:{flex:1,minWidth:0,fontSize:"var(--text-xs)",color:"var(--text-muted)"},children:["jatuh tempo ",B(o.dueAt),o.startedAt?` · mulai ${B(o.startedAt)}`:"",o.sessionId?` · sesi ${o.sessionId}`:"",o.manual?" · uji coba":"",o.note?` · ${o.note}`:""]})]},o.id)),e.jsx(Y,{page:x.page,pageCount:x.pageCount,total:t,from:x.from,to:x.to,onPage:f,unit:"run"})]})}function ye({projects:a,onProjectChanged:i,onToast:l}){var F;const[t,p]=D("scheduler","cronProject",((F=a[0])==null?void 0:F.id)??"",le),[u,f]=m.useState([]),[x,o]=m.useState(void 0),[n,d]=m.useState(K()),[j,k]=D("scheduler","cronOpenRuns",null,ie),[h,y]=m.useState(!1),M=a.find(r=>r.id===t),S=m.useCallback(()=>{if(!t){f([]);return}v.listCrons({projectId:t,page:1,limit:100}).then(r=>f(r.items)).catch(()=>f([]))},[t]);m.useEffect(()=>{S()},[S]);const s=r=>{o(r??null),d(K(r))},b=fe(n),A=U(b)?se(b,new Date):null,L=async()=>{var r;if(!U(b)){l("Cron expression tak sah","err","x-circle");return}y(!0);try{x?await v.patchCron(x.id,{name:n.name,expr:b,prompt:n.prompt,enabled:n.enabled,agent:n.agent||null,model:n.model||null,effort:n.effort||null}):await v.createCron({project:t,name:n.name,expr:b,prompt:n.prompt,enabled:n.enabled,agent:n.agent||void 0,model:n.model||void 0,effort:n.effort||void 0}),l("Cron tersimpan","ok","save"),o(void 0),S()}catch(c){l(((r=c.detail)==null?void 0:r.error)??"Gagal menyimpan cron","err","x-circle")}finally{y(!1)}},ae=async r=>{var c;y(!0);try{await v.runCronNow(r),l("Uji coba diantrekan — sesi terbuka di tick berikutnya","ok","play")}catch(re){l(((c=re.detail)==null?void 0:c.error)??"Gagal menjalankan cron","err","x-circle")}finally{y(!1),S()}},te=async r=>{y(!0);try{await v.deleteCron(r),l("Cron dihapus","ok","trash")}catch{l("Gagal menghapus cron","err","x-circle")}finally{y(!1),S()}},ne=async()=>{if(t)try{await v.updateProject(t,{schedulerOptIn:!0}),await i(t),l("Project di-opt-in","ok")}catch{l("Gagal mengubah opt-in","err","x-circle")}},N=n.agent||"claude";return e.jsxs(w,{eyebrow:"scheduler · cronjob",title:"Pengecekan rutin per project",actions:e.jsxs("div",{style:{display:"flex",gap:8,alignItems:"center"},children:[e.jsx(I,{value:t,"aria-label":"Project",onChange:r=>p(r.target.value),options:a.map(r=>({value:r.id,label:r.name}))}),e.jsx(g,{size:"sm",leftIcon:"plus",disabled:!t,onClick:()=>s(),children:"Cron baru"})]}),children:[M&&!M.schedulerOptIn&&e.jsxs("div",{className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:10,marginBottom:12,padding:"10px 12px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",background:"var(--surface-sunken)"},children:[e.jsx(T,{name:"alert-triangle",size:16,color:"var(--clay-500)"}),e.jsx("span",{style:{flex:1,fontSize:"var(--text-xs)",color:"var(--text-muted)"},children:"Project ini belum di-opt-in scheduler — cron-nya tak akan pernah dijalankan."}),e.jsx(g,{size:"sm",leftIcon:"check",onClick:()=>void ne(),children:"Aktifkan scheduler di project ini"})]}),u.length===0?e.jsx("div",{style:{fontSize:"var(--text-sm)",color:"var(--text-subtle)"},children:"Belum ada cron di project ini."}):u.map(r=>e.jsxs("div",{style:{padding:"10px 12px",marginBottom:6,border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",background:"var(--surface-card)"},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:10,flexWrap:"wrap"},children:[e.jsx("span",{style:{color:"var(--text-strong)",fontWeight:500},children:r.name}),e.jsx(P,{tone:r.enabled?"ok":"neutral",size:"sm",children:r.enabled?"aktif":"nonaktif"}),e.jsx("span",{style:{flex:1}}),e.jsx(g,{size:"sm",variant:"ghost",leftIcon:"play",disabled:h,onClick:()=>void ae(r.id),children:"Jalankan sekarang"}),e.jsx(g,{size:"sm",variant:"ghost",leftIcon:"list",onClick:()=>k(j===r.id?null:r.id),children:"Riwayat"}),e.jsx(g,{size:"sm",variant:"ghost",leftIcon:"pencil",onClick:()=>s(r),children:"Ubah"}),e.jsx(g,{size:"sm",variant:"ghost",leftIcon:"trash",disabled:h,onClick:()=>void te(r.id),children:"Hapus"})]}),e.jsxs("div",{style:{marginTop:4,fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:[oe(r.expr)," · terakhir ",B(r.lastRunAt)," · berikutnya ",B(r.nextRunAt)]}),j===r.id&&e.jsx("div",{style:{marginTop:10},children:e.jsx(ve,{cronId:r.id})})]},r.id)),e.jsxs(de,{open:x!==void 0,title:x?"Ubah cron":"Cron baru",eyebrow:"scheduler",onClose:()=>o(void 0),width:620,footer:e.jsxs("div",{style:{display:"flex",gap:8,justifyContent:"flex-end"},children:[e.jsx(g,{size:"sm",variant:"ghost",onClick:()=>o(void 0),children:"Batal"}),e.jsx(g,{size:"sm",leftIcon:"save",disabled:h,onClick:()=>void L(),children:"Simpan"})]}),children:[e.jsx(C,{label:"Nama cron",children:e.jsx(z,{"aria-label":"Nama cron",placeholder:"Cek error produksi pagi",value:n.name,onChange:r=>d(c=>({...c,name:r.target.value}))})}),e.jsxs("div",{className:"hn-grid-mobile",style:{display:"grid",gridTemplateColumns:"repeat(3, minmax(0,1fr))",gap:10},children:[e.jsx(C,{label:"Preset jadwal",children:e.jsx(I,{"aria-label":"Preset jadwal",value:n.kind,onChange:r=>d(c=>({...c,kind:r.target.value})),options:[{value:"harian",label:"Setiap hari"},{value:"hari-kerja",label:"Hari kerja"},{value:"mingguan",label:"Mingguan"},{value:"tiap-n-jam",label:"Tiap N jam"},{value:"lanjutan",label:"Lanjutan (cron expression)"}]})}),n.kind!=="lanjutan"&&e.jsx(C,{label:n.kind==="tiap-n-jam"?"Menit (dari jam)":"Jam",children:e.jsx(z,{type:"time","aria-label":"Jam",value:n.time,onChange:r=>d(c=>({...c,time:r.target.value}))})}),n.kind==="mingguan"&&e.jsx(C,{label:"Hari",children:e.jsx(I,{"aria-label":"Hari",value:String(n.weekday),onChange:r=>d(c=>({...c,weekday:Number(r.target.value)})),options:ue.map((r,c)=>({value:String(c),label:r}))})}),n.kind==="tiap-n-jam"&&e.jsx(C,{label:"Tiap berapa jam",children:e.jsx(z,{type:"number",min:1,max:23,"aria-label":"Tiap berapa jam",placeholder:"mis. 6",value:String(n.everyHours),onChange:r=>d(c=>({...c,everyHours:Math.min(23,Math.max(1,Number(r.target.value)||1))}))})})]}),n.kind==="lanjutan"&&e.jsx(C,{label:"Cron expression",hint:"Lima field: menit jam tanggal bulan hari-pekan — zona waktu server.",children:e.jsx(z,{"aria-label":"Cron expression",placeholder:"0 7 * * 1-5",value:n.expr,onChange:r=>d(c=>({...c,expr:r.target.value}))})}),e.jsx("div",{"data-testid":"cron-next-preview",style:{marginBottom:14,fontSize:"var(--text-xs)",color:A?"var(--text-muted)":"var(--clay-500)"},children:A?`Jalan berikutnya: ${B(A.toISOString())} (waktu lokal)`:"Jadwal tak sah — tak ada jalan berikutnya"}),e.jsx(C,{label:"Prompt",hint:"Instruksi bebas untuk agen. Temuan sebaiknya difilekan sebagai backlog lewat POST /api/specs.",children:e.jsx(ce,{"aria-label":"Prompt",rows:6,placeholder:"mis. Periksa error 5xx sejak kemarin, lalu filekan temuannya sebagai QA finding.",value:n.prompt,onChange:r=>d(c=>({...c,prompt:r.target.value}))})}),e.jsxs("div",{className:"hn-grid-mobile",style:{display:"grid",gridTemplateColumns:"repeat(3, minmax(0,1fr))",gap:10},children:[e.jsx(C,{label:"Runtime",children:e.jsx(I,{"aria-label":"Runtime",value:n.agent,onChange:r=>d(c=>({...c,agent:r.target.value,model:"",effort:""})),options:[{value:"",label:"Warisi default sesi"},{value:"claude",label:"Claude Code"},{value:"codex",label:"Codex CLI"}]})}),e.jsx(C,{label:"Model",children:e.jsx(I,{"aria-label":"Model",value:n.model,disabled:!n.agent,onChange:r=>d(c=>({...c,model:r.target.value,effort:""})),options:[{value:"",label:"Warisi"},...Q(N).map(r=>({value:r.id,label:r.label}))]})}),e.jsx(C,{label:"Effort",children:e.jsx(I,{"aria-label":"Effort",value:n.effort,disabled:!n.agent,onChange:r=>d(c=>({...c,effort:r.target.value})),options:[{value:"",label:"Warisi"},...pe(N,n.model||Q(N)[0].id).map(r=>({value:r,label:r}))]})})]}),e.jsx(H,{label:"Aktif",checked:n.enabled,onChange:r=>d(c=>({...c,enabled:r}))})]})]})}const q=5e3,O=10;function ee(a,i=Date.now()){if(!a)return"—";const l=Math.max(0,i-new Date(a).getTime()),t=Math.floor(l/6e4);if(t<1)return"baru saja";if(t<60)return`${t}m`;const p=Math.floor(t/60);return p<24?`${p}j`:`${Math.floor(p/24)}h`}function ke(a,i=Date.now()){if(!a)return"—";const l=new Date(a).getTime()-i;if(l<=0)return"jatuh tempo";const t=Math.ceil(l/6e4);return t<60?`${t}m lagi`:`${Math.ceil(t/60)}j lagi`}const Ce={tinggi:"err",sedang:"warn",rendah:"neutral"};function E(a,i){var l;return((l=i.find(t=>t.id===a))==null?void 0:l.title)??a}function Se({s:a}){return e.jsxs("div",{style:{padding:"12px 14px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-md)",background:"var(--surface-card)",display:"flex",flexDirection:"column",gap:6,flex:1,minWidth:180},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsx("span",{style:{fontFamily:"var(--font-mono)",fontWeight:600,color:"var(--text-strong)"},children:a.id}),e.jsx(P,{tone:a.enabled?"ok":"neutral",size:"sm",children:a.enabled?"aktif":"nonaktif"})]}),e.jsxs("div",{style:{fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:["tiap ",a.everyMin,"m"]}),e.jsxs("div",{style:{fontSize:"var(--text-xs)",color:"var(--text-muted)"},children:["terakhir ",ee(a.lastRunAt)," · berikutnya ",ke(a.nextRunAt)]})]})}function R({children:a}){return e.jsx("div",{className:"hn-dense-row",style:{display:"flex",alignItems:"center",gap:10,padding:"10px 12px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)",background:"var(--surface-card)",marginBottom:6},children:a})}function we({q:a,backlog:i,onCancel:l,busy:t}){return e.jsxs(R,{children:[e.jsxs("span",{style:{flex:1,minWidth:0},children:[e.jsx("span",{style:{color:"var(--text-strong)",fontWeight:500},children:E(a.specId,i)}),e.jsxs("span",{style:{display:"block",fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:[a.projectId," · ",a.source,a.note?` · ${a.note}`:""]})]}),e.jsx(P,{tone:Ce[a.priority]??"neutral",size:"sm",children:a.priority}),e.jsx(g,{size:"sm",variant:"ghost",leftIcon:"ban",disabled:t,onClick:()=>l(a.id),children:"Batalkan"})]})}function Ie({q:a,backlog:i,onRequeue:l,busy:t}){return e.jsxs(R,{children:[e.jsx(T,{name:"ban",size:16,color:"var(--text-subtle)"}),e.jsxs("span",{style:{flex:1,minWidth:0},children:[e.jsx("span",{style:{color:"var(--text-strong)",fontWeight:500},children:E(a.specId,i)}),e.jsxs("span",{style:{display:"block",fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:[a.projectId," · ",a.source," · ",a.note??"dibatalkan"]})]}),e.jsx(g,{size:"sm",variant:"ghost",leftIcon:"rotate-ccw",disabled:t,onClick:()=>l(a.id),children:"Antre lagi"})]})}function ze({s:a,backlog:i,onGotoTerminal:l}){return e.jsxs(R,{children:[e.jsxs("span",{style:{flex:1,minWidth:0},children:[e.jsx("span",{style:{color:"var(--text-strong)",fontWeight:500},children:E(a.specId,i)}),e.jsxs("span",{style:{display:"block",fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:[a.projectId,a.flow?` · ${a.flow}`:""]})]}),a.decision&&e.jsx(P,{tone:"warn",icon:"bell",size:"sm",children:"menunggu keputusan"}),e.jsx(g,{size:"sm",variant:"ghost",leftIcon:"terminal",onClick:()=>l(a.id),children:"Buka terminal"})]})}function Pe({q:a,backlog:i,onToast:l}){const t=me(a.specId);return e.jsxs(R,{children:[e.jsxs("span",{style:{flex:1,minWidth:0},children:[e.jsx("span",{style:{color:"var(--text-strong)",fontWeight:500},children:E(a.specId,i)}),e.jsxs("span",{style:{display:"block",fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:[a.projectId," · ",a.source," · ",a.launchedAt?`selesai ${ee(a.launchedAt)}`:a.note??"tak diluncurkan",a.sessionId?` · hanoman/${a.sessionId}`:""]})]}),e.jsx(g,{size:"sm",variant:"ghost",leftIcon:"external-link",onClick:()=>window.open(t,"_blank","noreferrer"),children:"Buka review"}),e.jsx(g,{size:"sm",variant:"ghost",leftIcon:"copy",onClick:()=>{var p;(p=navigator.clipboard)==null||p.writeText(t),l("Link review disalin","ok","copy")},children:"Salin"})]})}function Re({q:a,backlog:i}){return e.jsxs(R,{children:[e.jsx(T,{name:"x-circle",size:16,color:"var(--clay-500)"}),e.jsxs("span",{style:{flex:1,minWidth:0},children:[e.jsx("span",{style:{color:"var(--text-strong)",fontWeight:500},children:E(a.specId,i)}),e.jsxs("span",{style:{display:"block",fontSize:"var(--text-xs)",color:"var(--text-subtle)"},children:[a.projectId," · ",a.note??"gagal tanpa alasan tercatat"]})]})]})}function Ae({title:a,count:i,empty:l,children:t}){return e.jsx(w,{eyebrow:"scheduler",title:`${a}${i?` · ${i}`:""}`,children:i===0?e.jsx("div",{style:{fontSize:"var(--text-sm)",color:"var(--text-subtle)"},children:l}):t})}function $({title:a,status:i,count:l,empty:t,render:p}){const[u,f]=m.useState([]),[x,o]=m.useState(0),[n,d]=D("scheduler",`queue-${i}-page`,1,V),j=m.useCallback(()=>{let h=!0;return v.getSchedulerQueue({status:i,page:n,limit:O}).then(y=>{h&&(f(y.items),o(y.total))}).catch(()=>{h&&(f([]),o(0))}),()=>{h=!1}},[i,n]);m.useEffect(()=>j(),[j]),Z({topic:"schedulerQueue",params:{status:i,page:n,limit:O},apply:h=>{f(h.data.items),o(h.data.total)},refetch:()=>{j()},pollMs:q});const k=X(x,n,O);return e.jsx(w,{eyebrow:"scheduler",title:`${a}${l?` · ${l}`:""}`,children:l===0?e.jsx("div",{style:{fontSize:"var(--text-sm)",color:"var(--text-subtle)"},children:t}):e.jsxs(e.Fragment,{children:[u.map(h=>p(h)),e.jsx(Y,{page:k.page,pageCount:k.pageCount,total:x,from:k.from,to:k.to,onPage:d,unit:"item"})]})})}function Le({cfg:a,cap:i,liveCount:l,onWrite:t,busy:p}){const u=!a.enabled,f=u?"neutral":a.paused?"warn":"ok",x=u?"berhenti":a.paused?"dijeda":"aktif";return e.jsx(w,{eyebrow:"scheduler · rem darurat",title:"Kendali",children:e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:12,flexWrap:"wrap"},children:[e.jsx(P,{tone:f,children:x}),e.jsxs("span",{style:{fontSize:"var(--text-sm)",color:"var(--text-muted)"},children:[l," / ",i," sesi hidup"]}),e.jsx(ge,{}),e.jsx("span",{style:{flex:1}}),a.enabled&&e.jsx(g,{size:"sm",variant:"secondary",leftIcon:a.paused?"play":"pause",disabled:p,onClick:()=>t({...a,paused:!a.paused}),children:a.paused?"Lanjutkan":"Pause"}),a.enabled?e.jsx(g,{size:"sm",variant:"ghost",leftIcon:"square",disabled:p,onClick:()=>t({...a,enabled:!1}),children:"Stop"}):e.jsx(g,{size:"sm",leftIcon:"play",disabled:p,onClick:()=>t({...a,enabled:!0}),children:"Aktifkan"})]})})}function Be({status:a}){return e.jsx(w,{eyebrow:"host · peluncuran agen",title:"Gerbang peluncuran",children:e.jsxs("div",{"aria-label":"Status gerbang peluncuran",style:{fontSize:"var(--text-sm)",color:"var(--text-muted)",lineHeight:1.6},children:[e.jsxs("div",{children:["Gerbang ",a.enabled?"aktif":"nonaktif"," · ",a.liveCount," sesi hidup · ",a.liveAgentCount," agen terstruktur · cap ",a.maxConcurrent]}),e.jsxs("div",{children:["Load per core: ",a.loadStatus==="available"&&a.loadPerCore!==null?a.loadPerCore.toFixed(2):"tidak tersedia",a.loadStatus==="unsupported"?" (tidak didukung platform)":""," · ambang ",a.maxLoadPerCore]}),e.jsx("div",{style:{fontSize:"var(--text-xs)",marginTop:6},children:"Berlaku juga saat scheduler berhenti. Terminal dan shell tetap bisa dibuka; keduanya ikut mengisi cap."})]})})}function Ee({cfg:a,onWrite:i,busy:l}){const[t,p]=m.useState(a);m.useEffect(()=>{p(a)},[a]);const u=(n,d)=>p(j=>({...j,sources:{...j.sources,[n]:{...j.sources[n],...d}}})),f=(n,d=1)=>Math.max(d,Number(n)||d),x=t.launchGuard??he.launchGuard,o=Number.isFinite(x.maxLoadPerCore)&&x.maxLoadPerCore>0;return e.jsxs(w,{eyebrow:"scheduler · setelan",title:"Konfigurasi",actions:e.jsx(g,{size:"sm",leftIcon:"save",disabled:l||!o,onClick:()=>i({...t,launchGuard:x}),children:"Simpan setelan"}),children:[e.jsxs("div",{className:"hn-grid-mobile",style:{display:"grid",gridTemplateColumns:"repeat(2, minmax(0,1fr))",gap:14},children:[e.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:4},children:[e.jsx("span",{className:"hn-eyebrow",children:"Cap concurrent"}),e.jsx(z,{type:"number",min:1,value:String(t.maxConcurrent),"aria-label":"Cap concurrent",placeholder:"6",onChange:n=>p(d=>({...d,maxConcurrent:f(n.target.value)}))})]}),e.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:4},children:[e.jsx("span",{className:"hn-eyebrow",children:"Autonomy"}),e.jsx(I,{value:t.autonomy,"aria-label":"Autonomy",onChange:n=>p(d=>({...d,autonomy:n.target.value})),options:[{value:"butuh-keputusan",label:"butuh-keputusan"},{value:"full-control",label:"full-control"}]})]})]}),e.jsxs("div",{style:{marginTop:14,padding:"10px 12px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)"},children:[e.jsx(H,{label:"Gerbang peluncuran",checked:x.enabled,onChange:n=>p(d=>({...d,launchGuard:{...x,enabled:n}}))}),e.jsx("p",{style:{fontSize:"var(--text-xs)",color:"var(--text-muted)",lineHeight:1.5},children:"Membatasi peluncuran agen menurut cap sesi dan beban host, termasuk peluncuran manual. Mematikannya melewati kedua pemeriksaan. Terpisah dari sakelar scheduler dan source."}),e.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:4},children:[e.jsx("span",{className:"hn-eyebrow",children:"Ambang load per core"}),e.jsx(z,{type:"number",min:0,step:"any",value:String(x.maxLoadPerCore),"aria-label":"Ambang load per core","aria-invalid":!o,placeholder:"2.5",onChange:n=>p(d=>({...d,launchGuard:{...x,maxLoadPerCore:Number(n.target.value)}}))}),!o&&e.jsx("span",{style:{fontSize:"var(--text-xs)",color:"var(--clay-500)"},children:"Isi angka lebih besar dari nol."})]})]}),e.jsx("div",{style:{marginTop:14,display:"flex",flexDirection:"column",gap:10},children:["backlog","triase"].map(n=>e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:12,flexWrap:"wrap",padding:"10px 12px",border:"1px solid var(--border-hair)",borderRadius:"var(--radius-sm)"},children:[e.jsx(H,{label:n,checked:t.sources[n].enabled,onChange:d=>u(n,{enabled:d})}),e.jsx("span",{style:{flex:1}}),e.jsxs("label",{style:{display:"flex",alignItems:"center",gap:6,fontSize:"var(--text-xs)"},children:["tiap",e.jsx(z,{type:"number",min:1,style:{width:84},"aria-label":`cadence ${n}`,placeholder:"30",value:String(t.sources[n].everyMin),onChange:d=>u(n,{everyMin:f(d.target.value)})}),"menit"]})]},n))})]})}function Me({projects:a,onToggle:i,busyId:l}){return e.jsxs(w,{eyebrow:"scheduler · opt-in project",title:"Project yang diizinkan",children:[e.jsx("div",{style:{fontSize:"var(--text-xs)",color:"var(--text-subtle)",marginBottom:10},children:"Scheduler hanya menyentuh project yang di-opt-in. Default mati."}),a.length===0?e.jsx("div",{style:{fontSize:"var(--text-sm)",color:"var(--text-subtle)"},children:"Belum ada project."}):a.map(t=>e.jsxs(R,{children:[e.jsx("span",{style:{flex:1,minWidth:0,color:"var(--text-strong)",fontWeight:500},children:t.name}),e.jsx(P,{tone:t.schedulerOptIn?"ok":"neutral",size:"sm",children:t.schedulerOptIn?"opt-in":"mati"}),t.schedulerOptIn?e.jsx(g,{size:"sm",variant:"ghost",leftIcon:"ban",disabled:l===t.id,onClick:()=>i(t.id,!1),children:"Cabut opt-in"}):e.jsx(g,{size:"sm",leftIcon:"check",disabled:l===t.id,onClick:()=>i(t.id,!0),children:"Opt-in"})]},t.id))]})}function Ge({projects:a,backlog:i,onProjectChanged:l,onToast:t,onGotoTerminal:p}){const[u,f]=m.useState(null),[x,o]=m.useState("loading"),[n,d]=m.useState(!1),[j,k]=m.useState(null),h=m.useCallback((s=!1)=>{s||o("loading"),v.getSchedulerState().then(b=>{f(b),o("ready")}).catch(()=>{s||o("error")})},[]);m.useEffect(()=>{h()},[h]),Z({topic:"schedulerState",params:{},apply:s=>{f(s.state),o("ready")},refetch:()=>h(!0),pollMs:q});const y=m.useCallback(async s=>{d(!0);try{await v.putSchedulerConfig(s),t("Setelan scheduler tersimpan","ok","save"),h(!0)}catch{t("Gagal menyimpan setelan","err","x-circle")}finally{d(!1)}},[h,t]),M=m.useCallback(async(s,b)=>{k(s);try{await v.updateProject(s,{schedulerOptIn:b}),await l(s),t(b?"Project di-opt-in":"Opt-in dicabut","ok")}catch{t("Gagal mengubah opt-in","err","x-circle")}finally{k(null)}},[l,t]),S=m.useCallback(async(s,b)=>{k(s);try{b==="cancel"?(await v.cancelSchedulerQueueItem(s),t("Item antrean dibatalkan","ok","ban")):(await v.requeueSchedulerQueueItem(s),t("Item dikembalikan ke antrean","ok","rotate-ccw"))}catch(A){const L=A.detail;t((L==null?void 0:L.error)??"Gagal mengubah item antrean","err","x-circle")}finally{k(null),h(!0)}},[h,t]);return x==="loading"?e.jsx(_,{kind:"loading"}):x==="error"||!u?e.jsx(_,{kind:"error",hint:"Gagal memuat state scheduler.",action:()=>h(),actionLabel:"Coba lagi"}):e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:16,minHeight:0},children:[e.jsx(Le,{cfg:u.config,cap:u.cap,liveCount:u.liveCount,onWrite:y,busy:n}),u.admission&&e.jsx(Be,{status:u.admission}),e.jsx(w,{eyebrow:"scheduler · observabilitas",title:"Status per source",children:e.jsx("div",{style:{display:"flex",gap:10,flexWrap:"wrap"},children:u.sources.map(s=>e.jsx(Se,{s},s.id))})}),e.jsx(ye,{projects:a,onProjectChanged:l,onToast:t}),e.jsx($,{title:"Antrean",status:"queued",count:u.queueCounts.queued,empty:"Antrean kosong.",render:s=>e.jsx(we,{q:s,backlog:i,onCancel:b=>void S(b,"cancel"),busy:j===s.id},s.id)}),e.jsx($,{title:"Dibatalkan",status:"canceled",count:u.queueCounts.canceled,empty:"Tak ada item yang dibatalkan.",render:s=>e.jsx(Ie,{q:s,backlog:i,onRequeue:b=>void S(b,"requeue"),busy:j===s.id},s.id)}),e.jsx(Ae,{title:"Sesi berjalan",count:u.sessions.length,empty:"Tak ada sesi scheduler berjalan.",children:u.sessions.map(s=>e.jsx(ze,{s,backlog:i,onGotoTerminal:p},s.id))}),e.jsx($,{title:"Selesai (done)",status:"done",count:u.queueCounts.done,empty:"Belum ada hasil selesai.",render:s=>e.jsx(Pe,{q:s,backlog:i,onToast:t},s.id)}),e.jsx($,{title:"Gagal",status:"failed",count:u.queueCounts.failed,empty:"Tak ada sesi gagal.",render:s=>e.jsx(Re,{q:s,backlog:i},s.id)}),e.jsx(Ee,{cfg:u.config,onWrite:y,busy:n}),e.jsx(Me,{projects:a,onToggle:M,busyId:j})]})}export{Ge as SchedulerScreen};