hanoman 0.9.29 → 0.9.30
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 +23 -0
- package/dist/server.js +266 -68
- package/package.json +1 -1
- package/web/assets/{DalangHanomanScreen-BMrikKnt.js → DalangHanomanScreen-Fd7_DcSP.js} +1 -1
- package/web/assets/{DocPreviewModal-5j31WUwI.js → DocPreviewModal-SMRN2K98.js} +1 -1
- package/web/assets/{DocsWorkspace-GkTrniF3.js → DocsWorkspace-pxj0N6QW.js} +1 -1
- package/web/assets/{IdeScreen-CAQfv1_e.js → IdeScreen-Cr9Vqdrc.js} +1 -1
- package/web/assets/{LeadScreen-Da5-1FLe.js → LeadScreen-CQXpJy0y.js} +1 -1
- package/web/assets/{ReviewScreen-B8KHzQpd.js → ReviewScreen-B7NNEjxk.js} +1 -1
- package/web/assets/SchedulerScreen-D3rPdS-F.js +1 -0
- package/web/assets/{SettingsScreen-BxQ3CH2D.js → SettingsScreen-Bx13PWKQ.js} +1 -1
- package/web/assets/{TeamScreen-P6vz88Pp.js → TeamScreen-BBAsYLpT.js} +1 -1
- package/web/assets/{TerminalScreen-B_cagBZd.js → TerminalScreen-DpVp4h1n.js} +1 -1
- package/web/assets/{TriageScreen-IYkxyhdm.js → TriageScreen-wAPnttRe.js} +1 -1
- package/web/assets/{VpsScreen-DFGT5S8Y.js → VpsScreen-DeQVx9Jy.js} +1 -1
- package/web/assets/{fields-CmVwp6QK.js → fields-qnBoIMR_.js} +1 -1
- package/web/assets/{index-C-iSWHn3.js → index-BQw6xQI4.js} +207 -207
- package/web/assets/{index-0T3s-I82.css → index-C3KwOJxI.css} +1 -1
- package/web/assets/{live-lSo-u7M6.js → live-CONO0GTu.js} +1 -1
- package/web/assets/{sched-lead-shared-BTz6aILx.js → sched-lead-shared-CDR0pOqs.js} +1 -1
- package/web/assets/{settings-rebase-CPawFVpp.js → settings-rebase-CpaFw0Tm.js} +1 -1
- package/web/index.html +2 -2
- package/web/assets/SchedulerScreen-CBd4O5kw.js +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{h as N,i as E,j as e,L as G,R as ee,X as H,n as F,B as C,a2 as le,aR as Je,Z as ie,d as Le,q as J,D as Ge,V as ke,W as Ke,a_ as Qe,a$ as Ye,g as O,I as We,aK as Ze,b0 as Ve,O as Xe,M as qe,c as Re,aX as T,e as R,f as $,b1 as ea,H as aa,b2 as xe,b3 as we,ab as na,b4 as sa,b5 as re,l as X,b6 as ta,r as Ee,G as Be,m as ra,Y as la,b7 as ia,b8 as oa,b9 as ca,P as da,ba as q,F as ua,bb as Ae,_ as ha}from"./index-C-iSWHn3.js";import{R as i}from"./react-DfGhg7ZW.js";import{L as ma}from"./live-lSo-u7M6.js";import"./markdown-CWEY34jk.js";import{I as W,b as pa,c as _,f as ja,u as ba,a as Me,d as xa}from"./sched-lead-shared-BTz6aILx.js";/* empty css */import{r as ka,O as ga}from"./settings-rebase-CPawFVpp.js";import"./xterm-3VOAfa_q.js";const Se=10,fa=a=>a<1024?`${a} B`:`${(a/1024).toFixed(1)} KiB`;function va(a){const s=URL.createObjectURL(new Blob([a.body],{type:"text/markdown;charset=utf-8"})),t=document.createElement("a");t.href=s,t.download=a.filename,t.click(),URL.revokeObjectURL(s)}function ya({id:a}){const[s,t]=i.useState(null),[r,x]=i.useState(null),m=i.useCallback(()=>{let p=!0;return N.getCronReport(a).then(o=>{p&&(t(o),x(null))}).catch(o=>{p&&x(E("memuat laporan",o))}),()=>{p=!1}},[a]);return i.useEffect(()=>m(),[m]),r?e.jsx(W,{message:r,onRetry:()=>{m()}}):s?e.jsxs("div",{className:"hn-sched-report-body",children:[e.jsxs("div",{className:"hn-sched-report-actions",children:[e.jsx("span",{className:"hn-sched-row-meta",children:s.filename}),e.jsx(C,{size:"sm",variant:"ghost",leftIcon:"download",onClick:()=>va(s),children:"Unduh .md"})]}),e.jsx(Je,{text:s.body,name:s.filename})]}):e.jsx(G,{rows:2,label:"Memuat laporan…"})}function wa({projectId:a,projectName:s}){const[t,r]=i.useState([]),[x,m]=i.useState(0),[p,o]=i.useState(1),[w,g]=i.useState(!1),[h,S]=i.useState(null),[u,l]=i.useState(null),c=i.useCallback(()=>{let b=!0;return N.listCronReports({projectId:a,page:p,limit:Se}).then(P=>{b&&(r(P.items),m(P.total),g(!0),S(null))}).catch(P=>{b&&(S(E("memuat laporan cron",P)),g(!0))}),()=>{b=!1}},[a,p]);if(i.useEffect(()=>{o(1),l(null)},[a]),i.useEffect(()=>(g(!1),c()),[c]),h)return e.jsx(W,{message:h,onRetry:()=>{c()}});if(!w)return e.jsx(G,{rows:2,label:"Memuat laporan cron…"});if(x===0)return e.jsx("p",{className:"hn-sched-empty",children:"Belum ada laporan. Laporan tersimpan otomatis dari pesan akhir tiap run cron."});const k=ie(x,p,Se),B=!a&&s,I=B?[...t].sort((b,P)=>t.findIndex(A=>A.projectId===b.projectId)-t.findIndex(A=>A.projectId===P.projectId)):t;return e.jsxs(e.Fragment,{children:[e.jsx(ee,{label:"Laporan run cron",children:I.map((b,P)=>{var A;return e.jsxs(i.Fragment,{children:[B&&b.projectId!==((A=I[P-1])==null?void 0:A.projectId)&&e.jsx("h4",{className:"hn-sched-group-title hn-sched-group-sub",children:s(b.projectId)}),e.jsx(H,{children:e.jsxs("span",{className:"hn-sched-row-text",children:[e.jsxs("span",{className:"hn-sched-row-head",children:[e.jsx("span",{className:"hn-sched-row-title",children:b.cronName}),e.jsx(F,{tone:"neutral",size:"sm",children:b.runDate}),e.jsx(C,{size:"sm",variant:"ghost","aria-expanded":u===b.id,onClick:()=>l(u===b.id?null:b.id),children:u===b.id?"Sembunyikan":"Baca"})]}),e.jsxs("span",{className:"hn-sched-row-meta",children:[fa(b.bytes)," · ",b.filename]}),u===b.id&&e.jsx(ya,{id:b.id})]})})]},b.id)})}),e.jsx(le,{page:k.page,pageCount:k.pageCount,total:x,from:k.from,to:k.to,onPage:o,unit:"laporan"})]})}const Y=10,Sa=500,me=a=>{var s;return(s=a.detail)==null?void 0:s.error},pe=a=>String(a).padStart(2,"0"),Ce=a=>{const s={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)??""},t=a?sa(a.expr):{kind:"harian",hour:7,minute:0};if(!t)return s;if(t.kind==="tiap-n-jam")return{...s,kind:t.kind,everyHours:String(t.everyHours),time:`00:${pe(t.minute)}`};const r=`${pe(t.hour)}:${pe(t.minute)}`;return t.kind==="mingguan"?{...s,kind:t.kind,time:r,weekday:t.weekday}:{...s,kind:t.kind,time:r}},Ca=a=>{if(a.kind==="lanjutan")return a.expr.trim();const[s,t]=a.time.split(":").map(Number);switch(a.kind){case"harian":return re({kind:"harian",hour:s,minute:t});case"hari-kerja":return re({kind:"hari-kerja",hour:s,minute:t});case"mingguan":return re({kind:"mingguan",hour:s,minute:t,weekday:a.weekday});case"tiap-n-jam":return re({kind:"tiap-n-jam",everyHours:_(a.everyHours,1,23,6),minute:t})}},Na={launched:"ok",queued:"neutral",skipped:"warn",failed:"err"};function Ia({cronId:a,at:s}){const[t,r]=i.useState([]),[x,m]=i.useState(0),[p,o]=i.useState(!1),[w,g]=i.useState(null),[h,S]=J("scheduler","cronRunsPage",1,ke),u=i.useCallback(()=>{let c=!0;return N.listCronRuns(a,{page:h,limit:Y}).then(k=>{c&&(r(k.items),m(k.total),o(!0),g(null))}).catch(k=>{c&&(g(E("memuat riwayat",k)),o(!0))}),()=>{c=!1}},[a,h]);if(i.useEffect(()=>u(),[u]),w)return e.jsx(W,{message:w,onRetry:()=>{u()}});if(!p)return e.jsx(G,{rows:2,label:"Memuat riwayat…"});if(x===0)return e.jsx("p",{className:"hn-sched-empty",children:"Belum ada eksekusi."});const l=ie(x,h,Y);return e.jsxs(e.Fragment,{children:[e.jsx(ee,{label:"Riwayat eksekusi",children:t.map(c=>e.jsx(H,{children:e.jsxs("span",{className:"hn-sched-row-text",children:[e.jsx("span",{className:"hn-sched-row-head",children:e.jsx(F,{tone:Na[c.status]??"neutral",size:"sm",children:X(ta,c.status)})}),e.jsxs("span",{className:"hn-sched-row-meta",children:["jatuh tempo ",s(c.dueAt),c.startedAt?` · mulai ${s(c.startedAt)}`:"",c.manual?" · uji coba":"",c.note?` · ${c.note}`:""]})]})},c.id))}),e.jsx(le,{page:l.page,pageCount:l.pageCount,total:x,from:l.from,to:l.to,onPage:S,unit:"run"})]})}function Pa({projects:a,onProjectChanged:s,onToast:t,timeZone:r}){const{confirm:x,dialog:m}=Le(),p=r??pa(),o=n=>ja(n,p),[w,g]=J("scheduler","cronProject","",Ge),h=a.some(n=>n.id===w)?w:"",[S,u]=J("scheduler","cronListPage",1,ke),[l,c]=i.useState(""),[k,B]=i.useState([]),[I,b]=i.useState(!1),[P,A]=i.useState(null),[D,U]=i.useState(void 0),[j,L]=i.useState(Ce()),[M,ne]=i.useState("dasar"),[Z,f]=J("scheduler","cronOpenRuns",null,Ke),[y,v]=i.useState(!1),se=a.find(n=>n.id===h),K=i.useCallback(()=>{if(a.length===0){B([]),A(null),b(!0);return}N.listCrons({projectId:h||void 0,page:1,limit:Sa}).then(n=>{B(n.items),A(null),b(!0)}).catch(n=>{A(E("memuat daftar cron",n)),b(!0)})},[h,a.length]);i.useEffect(()=>{B([]),b(!1),K()},[K]);const oe=n=>{var d;return((d=a.find(z=>z.id===n))==null?void 0:d.name)??"Project lain"},V=i.useMemo(()=>{const n=new Map(a.map((d,z)=>[d.id,z]));return[...k].sort((d,z)=>(n.get(d.projectId)??1e9)-(n.get(z.projectId)??1e9))},[k,a]),Q=ie(V.length,S,Y),ge=V.slice((Q.page-1)*Y,Q.page*Y),fe=n=>{var d;U(n??null),L(Ce(n)),ne("dasar"),c(h||((d=a[0])==null?void 0:d.id)||"")},te=Ca(j),ce=Qe(te)!==null,de=ce?Ye(te,new Date,p):null,$e=async()=>{if(!ce){t("Ekspresi cron tidak sah","err","x-circle");return}v(!0);try{D?await N.patchCron(D.id,{name:j.name,expr:te,prompt:j.prompt,enabled:j.enabled,agent:j.agent||null,model:j.model||null,effort:j.effort||null}):await N.createCron({project:l,name:j.name,expr:te,prompt:j.prompt,enabled:j.enabled,agent:j.agent||void 0,model:j.model||void 0,effort:j.effort||void 0}),t("Cron tersimpan","ok","save"),U(void 0),K()}catch(n){t(me(n)??E("menyimpan cron",n),"err","x-circle")}finally{v(!1)}},Fe=async n=>{v(!0);try{await N.runCronNow(n),t("Uji coba masuk antrean; sesi dibuka pada siklus berikutnya","ok","play")}catch(d){t(me(d)??E("menjalankan cron",d),"err","x-circle")}finally{v(!1),K()}},He=async n=>{v(!0);try{await N.deleteCron(n),t("Cron dihapus","ok","trash")}catch(d){t(me(d)??E("menghapus cron",d),"err","x-circle")}finally{v(!1),K()}},De=n=>{x({title:"Hapus cron ini?",eyebrow:"scheduler · cronjob",impact:[`Cron "${n.name}" di project ${oe(n.projectId)} dihapus permanen.`,"Jadwalnya berhenti dan tidak akan dijalankan lagi.","Tindakan ini tidak bisa dibatalkan."],confirmLabel:"Hapus cron",icon:"trash-2",tone:"danger",run:()=>He(n.id)})},Ue=async()=>{if(h)try{await N.updateProject(h,{schedulerOptIn:!0}),await s(h),t("Project diizinkan untuk scheduler","ok")}catch(n){t(E("mengizinkan project",n),"err","x-circle")}},Te=n=>[{key:"edit",label:"Ubah",icon:"pencil",onSelect:()=>fe(n)},{key:"run",label:"Jalankan sekarang",icon:"play",disabled:y,onSelect:()=>void Fe(n.id)},{key:"runs",label:Z===n.id?"Sembunyikan riwayat":"Riwayat",icon:"list",onSelect:()=>f(Z===n.id?null:n.id)},{key:"remove",label:"Hapus",icon:"trash",tone:"danger",disabled:y,onSelect:()=>De(n)}],ue=j.agent||"claude",ve=()=>L(n=>({...n,everyHours:String(_(n.everyHours,1,23,6))})),_e=ce?de?`Perkiraan jalan berikutnya: ${o(de.toISOString())}`:`Preview belum bisa dihitung untuk zona ${p}. Jam jalan berikutnya tampil di daftar cron.`:"Jadwal tidak sah, jadi tidak ada jalan berikutnya.";return e.jsxs("div",{className:"hn-sched-panel",children:[e.jsxs("div",{className:"hn-sched-toolbar",children:[e.jsx(O,{value:h,"aria-label":"Project",onChange:n=>{g(n.target.value),u(1)},options:[{value:"",label:"Semua project"},...a.map(n=>({value:n.id,label:n.name}))]}),e.jsx(C,{size:"sm",leftIcon:"plus",disabled:a.length===0,onClick:()=>fe(),children:"Cron baru"})]}),e.jsxs("p",{className:"hn-sched-caption",children:["Jam ditampilkan dalam zona server ",e.jsx("b",{children:p}),r===void 0?" (server belum melaporkan zonanya, jadi zona browser yang dipakai)":"","."]}),se&&!se.schedulerOptIn&&e.jsx("div",{className:"hn-sched-notice",children:e.jsxs("div",{className:"hn-dense-row",role:"note",children:[e.jsx(We,{name:"alert-triangle",size:16,color:"var(--clay-600)"}),e.jsx("span",{className:"hn-grow hn-sched-notice-text",children:"Project ini belum diizinkan untuk scheduler, jadi cron-nya tidak akan pernah dijalankan."}),e.jsx(C,{size:"sm",leftIcon:"check",onClick:()=>void Ue(),children:"Aktifkan scheduler di project ini"})]})}),P?e.jsx(W,{message:P,onRetry:K,busy:y}):I?k.length===0?e.jsx("p",{className:"hn-sched-empty",children:h?"Belum ada cron di project ini.":"Belum ada cron di project mana pun."}):e.jsx(Ze,{children:e.jsxs("table",{className:"hn-sched-table",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{scope:"col",children:"Cron"}),e.jsx("th",{scope:"col",children:"Jadwal"}),e.jsx("th",{scope:"col",children:"Terakhir"}),e.jsx("th",{scope:"col",children:"Berikutnya"}),e.jsx("th",{scope:"col",children:e.jsx("span",{className:"hn-sr-only",children:"Aksi"})})]})}),e.jsx("tbody",{children:ge.map((n,d)=>{var z,ye;return e.jsxs(i.Fragment,{children:[!h&&n.projectId!==((z=ge[d-1])==null?void 0:z.projectId)&&e.jsx("tr",{className:"hn-sched-group-row",children:e.jsx("th",{scope:"colgroup",colSpan:5,children:e.jsxs("span",{className:"hn-sched-row-head",children:[e.jsx("span",{className:"hn-sched-group-title",children:oe(n.projectId)}),e.jsxs(F,{tone:"neutral",size:"sm",children:[V.filter(he=>he.projectId===n.projectId).length," cron"]}),((ye=a.find(he=>he.id===n.projectId))==null?void 0:ye.schedulerOptIn)===!1&&e.jsx(F,{tone:"warn",size:"sm",children:"belum diizinkan"})]})})}),e.jsxs("tr",{children:[e.jsx("td",{"data-label":"Cron",children:e.jsxs("span",{className:"hn-sched-row-head",children:[e.jsx("span",{className:"hn-sched-row-title",children:n.name}),e.jsx(F,{tone:n.enabled?"ok":"neutral",size:"sm",children:n.enabled?"aktif":"nonaktif"})]})}),e.jsx("td",{"data-label":"Jadwal",children:Ve(n.expr)}),e.jsx("td",{"data-label":"Terakhir",children:o(n.lastRunAt)}),e.jsx("td",{"data-label":"Berikutnya",children:o(n.nextRunAt)}),e.jsx("td",{className:"hn-sched-cell-actions",children:e.jsx(Xe,{label:`Aksi untuk cron ${n.name}`,title:n.name,items:Te(n)})})]}),Z===n.id&&e.jsx("tr",{className:"hn-sched-runs",children:e.jsx("td",{colSpan:5,children:e.jsx("div",{id:`cron-runs-${n.id}`,children:e.jsx(Ia,{cronId:n.id,at:o})})})})]},n.id)})})]})}):e.jsx(G,{rows:3,label:"Memuat daftar cron…"}),!P&&I&&V.length>Y&&e.jsx(le,{page:Q.page,pageCount:Q.pageCount,total:V.length,from:Q.from,to:Q.to,onPage:u,unit:"cron"}),a.length>0&&e.jsxs("section",{className:"hn-sched-reports","aria-label":"Laporan run cron",children:[e.jsx("h3",{children:"Laporan run cron"}),e.jsx(wa,{projectId:h||void 0,projectName:oe})]}),e.jsx(qe,{open:D!==void 0,title:D?"Ubah cron":"Cron baru",eyebrow:"scheduler",onClose:()=>U(void 0),width:640,footer:e.jsxs("div",{className:"hn-sched-savebar",children:[e.jsx(C,{size:"sm",variant:"ghost",onClick:()=>U(void 0),children:"Batal"}),e.jsx(C,{size:"sm",leftIcon:"save",disabled:y,onClick:()=>void $e(),children:"Simpan"})]}),children:e.jsxs(Re,{tabs:[{value:"dasar",label:"Dasar"},{value:"lanjutan",label:"Lanjutan"}],value:M,onChange:n=>ne(n),children:[e.jsxs(T,{value:"dasar",className:"hn-sched-panel",children:[!D&&!h&&e.jsx(R,{label:"Project",children:e.jsx(O,{"aria-label":"Project cron baru",value:l,onChange:n=>c(n.target.value),options:a.map(n=>({value:n.id,label:n.name}))})}),e.jsx(R,{label:"Nama cron",children:e.jsx($,{"aria-label":"Nama cron",placeholder:"mis. Cek error produksi pagi",value:j.name,onChange:n=>L(d=>({...d,name:n.target.value}))})}),e.jsxs("div",{className:"hn-sched-form-grid",children:[e.jsx(R,{label:"Preset jadwal",children:e.jsx(O,{"aria-label":"Preset jadwal",value:j.kind,onChange:n=>L(d=>({...d,kind:n.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:"Ekspresi cron (lanjutan)"}]})}),j.kind!=="lanjutan"&&e.jsx(R,{label:j.kind==="tiap-n-jam"?"Menit pada setiap jam":"Jam",children:e.jsx($,{type:"time","aria-label":"Jam",value:j.time,onChange:n=>L(d=>({...d,time:n.target.value}))})}),j.kind==="mingguan"&&e.jsx(R,{label:"Hari",children:e.jsx(O,{"aria-label":"Hari",value:String(j.weekday),onChange:n=>L(d=>({...d,weekday:Number(n.target.value)})),options:ea.map((n,d)=>({value:String(d),label:n}))})}),j.kind==="tiap-n-jam"&&e.jsx(R,{label:"Tiap berapa jam",children:e.jsx($,{type:"number",min:1,max:23,"aria-label":"Tiap berapa jam",placeholder:"mis. 6",value:j.everyHours,onChange:n=>L(d=>({...d,everyHours:n.target.value})),onBlur:ve,onKeyDown:n=>{n.key==="Enter"&&(n.preventDefault(),ve())}})})]}),j.kind==="lanjutan"&&e.jsx(R,{label:"Ekspresi cron",hint:"Lima bagian: menit, jam, tanggal, bulan, hari dalam minggu.",children:e.jsx($,{"aria-label":"Ekspresi cron",placeholder:"mis. 0 7 * * 1-5",value:j.expr,onChange:n=>L(d=>({...d,expr:n.target.value}))})}),e.jsx("p",{"data-testid":"cron-next-preview",className:`hn-sched-note${de?"":" hn-sched-preview-warn"}`,children:_e}),e.jsxs("p",{className:"hn-sched-note",children:["Jadwal berlaku menurut zona waktu server ",e.jsx("b",{children:p}),"."]}),e.jsx(R,{label:"Prompt",hint:"Instruksi bebas untuk agen. Temuan sebaiknya dicatat sebagai item backlog baru.",children:e.jsx(aa,{"aria-label":"Prompt",rows:6,placeholder:"mis. Periksa error 5xx sejak kemarin, lalu catat temuannya sebagai QA finding.",value:j.prompt,onChange:n=>L(d=>({...d,prompt:n.target.value}))})}),e.jsx(xe,{label:"Aktif",checked:j.enabled,onChange:n=>L(d=>({...d,enabled:n}))})]}),e.jsxs(T,{value:"lanjutan",className:"hn-sched-panel",children:[e.jsx("p",{className:"hn-sched-group-hint",children:"Kosongkan untuk mengikuti default sesi. Model dan effort baru tersedia setelah runtime dipilih."}),e.jsxs("div",{className:"hn-sched-form-grid",children:[e.jsx(R,{label:"Runtime",children:e.jsx(O,{"aria-label":"Runtime",value:j.agent,onChange:n=>L(d=>({...d,agent:n.target.value,model:"",effort:""})),options:[{value:"",label:"Ikuti default sesi"},{value:"claude",label:"Claude Code"},{value:"codex",label:"Codex CLI"}]})}),e.jsx(R,{label:"Model",children:e.jsx(O,{"aria-label":"Model",value:j.model,disabled:!j.agent,onChange:n=>L(d=>({...d,model:n.target.value,effort:""})),options:[{value:"",label:"Ikuti default"},...we(ue).map(n=>({value:n.id,label:n.label}))]})}),e.jsx(R,{label:"Effort",children:e.jsx(O,{"aria-label":"Effort",value:j.effort,disabled:!j.agent,onChange:n=>L(d=>({...d,effort:n.target.value})),options:[{value:"",label:"Ikuti default"},...na(ue,j.model||we(ue)[0].id).map(n=>({value:n,label:n}))]})})]})]})]})}),m]})}const ze=5e3,je=10,La=["antre","berjalan","riwayat","cron","setelan"],Ra=["done","failed","canceled"],Ne={done:"Selesai",failed:"Gagal",canceled:"Dibatalkan"},Ea={tinggi:"err",sedang:"warn",rendah:"neutral"},Ba=[{value:"butuh-keputusan",label:"Berhenti dan minta keputusan dulu"},{value:"full-control",label:"Jalan sampai selesai tanpa berhenti"}],Ie=a=>{var s;return(s=a.detail)==null?void 0:s.error};function Aa(a,s){var t;return((t=s.find(r=>r.id===a))==null?void 0:t.title)??a}function ae({specId:a,ctx:s}){return e.jsx("span",{className:"hn-sched-row-title",children:Aa(a,s.backlog)})}function Ma({q:a,ctx:s,busy:t,onCancel:r}){return e.jsx(H,{actions:e.jsx(C,{size:"sm",variant:"ghost",leftIcon:"ban",disabled:t,onClick:()=>r(a.id),children:"Batalkan"}),children:e.jsxs("span",{className:"hn-sched-row-text",children:[e.jsxs("span",{className:"hn-sched-row-head",children:[e.jsx(ae,{specId:a.specId,ctx:s}),e.jsx(F,{tone:Ea[a.priority]??"neutral",size:"sm",children:X(da,a.priority)})]}),e.jsxs("span",{className:"hn-sched-row-meta",children:[s.projectName(a.projectId)," · ",X(q,a.source),a.note?` · ${a.note}`:""]})]})})}function za({s:a,ctx:s,onGotoTerminal:t}){const r=a.flow?ua[a.flow]??a.flow:"";return e.jsx(H,{actions:e.jsx(C,{size:"sm",variant:"ghost",leftIcon:"terminal",onClick:()=>t(a.id),children:"Buka terminal"}),children:e.jsxs("span",{className:"hn-sched-row-text",children:[e.jsxs("span",{className:"hn-sched-row-head",children:[e.jsx(ae,{specId:a.specId,ctx:s}),a.decision&&e.jsx(F,{tone:"warn",icon:"bell",size:"sm",children:"menunggu kamu"})]}),e.jsxs("span",{className:"hn-sched-row-meta",children:[s.projectName(a.projectId),r?` · ${r}`:""]})]})})}function Oa({q:a,ctx:s,onToast:t}){const r=ha(a.specId);return e.jsx(H,{actions:e.jsxs(e.Fragment,{children:[e.jsx(C,{size:"sm",variant:"ghost",leftIcon:"external-link",onClick:()=>window.open(r,"_blank","noreferrer"),children:"Buka review"}),e.jsx(C,{size:"sm",variant:"ghost",leftIcon:"copy",onClick:()=>{var x;(x=navigator.clipboard)==null||x.writeText(r),t("Link review disalin","ok","copy")},children:"Salin"})]}),children:e.jsxs("span",{className:"hn-sched-row-text",children:[e.jsx(ae,{specId:a.specId,ctx:s}),e.jsxs("span",{className:"hn-sched-row-meta",children:[s.projectName(a.projectId)," · ",X(q,a.source)," · ",a.launchedAt?`selesai ${Me(a.launchedAt)}`:a.note??"tidak diluncurkan"]})]})})}function $a({q:a,ctx:s,onRequeue:t,busy:r}){return e.jsx(H,{actions:e.jsx(C,{size:"sm",variant:"secondary",leftIcon:"rotate-ccw",disabled:r,onClick:()=>t(a.id),children:"Antre ulang"}),children:e.jsxs("span",{className:"hn-sched-row-text",children:[e.jsx(ae,{specId:a.specId,ctx:s}),e.jsxs("span",{className:"hn-sched-row-meta",children:[s.projectName(a.projectId)," · ",a.note??"gagal tanpa alasan tercatat"]})]})})}function Fa({q:a,ctx:s,onRequeue:t,busy:r}){return e.jsx(H,{actions:e.jsx(C,{size:"sm",variant:"ghost",leftIcon:"rotate-ccw",disabled:r,onClick:()=>t(a.id),children:"Antre lagi"}),children:e.jsxs("span",{className:"hn-sched-row-text",children:[e.jsx(ae,{specId:a.specId,ctx:s}),e.jsxs("span",{className:"hn-sched-row-meta",children:[s.projectName(a.projectId)," · ",X(q,a.source)," · ",a.note??"dibatalkan"]})]})})}function Oe({what:a,status:s,count:t,empty:r,render:x}){const[m,p]=i.useState([]),[o,w]=i.useState(0),[g,h]=i.useState(!1),[S,u]=i.useState(null),[l,c]=J("scheduler",`queue-${s}-page`,1,ke),k=i.useCallback(()=>{N.getSchedulerQueue({status:s,page:l,limit:je}).then(I=>{p(I.items),w(I.total),u(null),h(!0)}).catch(I=>{u(E(`memuat ${a}`,I)),h(!0)})},[s,l,a]);if(i.useEffect(()=>{k()},[k]),Be({topic:"schedulerQueue",params:{status:s,page:l,limit:je},apply:I=>{p(I.data.items),w(I.data.total),u(null),h(!0)},refetch:()=>{k()},pollMs:ze}),S)return e.jsx(W,{message:S,onRetry:k});if(t===0)return e.jsx("p",{className:"hn-sched-empty",children:r});if(!g)return e.jsx(G,{rows:3,label:`Memuat ${a}…`});const B=ie(o,l,je);return e.jsxs(e.Fragment,{children:[e.jsx(ee,{label:a,children:m.map(I=>x(I))}),e.jsx(le,{page:B.page,pageCount:B.pageCount,total:o,from:B.from,to:B.to,onPage:c,unit:"item"})]})}function Ha({counts:a,ctx:s,busyId:t,onRowAction:r,onToast:x}){const m=Ra.filter(u=>(a[u]??0)>0),p=(a.failed??0)>0?"failed":(a.done??0)>0?"done":"canceled",[o,w]=J("scheduler","riwayatStatus",p,Ee("done","failed","canceled"));if(m.length===0)return e.jsx("p",{className:"hn-sched-empty",children:"Belum ada riwayat."});const g=m.includes(o)?o:m[0],h=u=>void r(u,"requeue"),S=u=>{const l=t===u.id;return g==="done"?e.jsx(Oa,{q:u,ctx:s,onToast:x},u.id):g==="failed"?e.jsx($a,{q:u,ctx:s,onRequeue:h,busy:l},u.id):e.jsx(Fa,{q:u,ctx:s,onRequeue:h,busy:l},u.id)};return e.jsxs(e.Fragment,{children:[e.jsx("div",{role:"group","aria-label":"Filter riwayat",className:"hn-sched-chips",children:m.map(u=>e.jsxs("button",{type:"button",className:"hn-sched-chip hn-touch-target","aria-pressed":u===g,onClick:()=>w(u),children:[Ne[u],e.jsx("span",{className:"hn-sched-chip-count",children:a[u]})]},u))}),e.jsx(Oe,{what:`item ${Ne[g].toLowerCase()}`,status:g,count:a[g]??0,empty:"Belum ada riwayat.",render:S},g)]})}function Da({cfg:a,cap:s,liveCount:t,onWrite:r,onAsk:x,busy:m}){const p=a.enabled?a.paused?{status:"paused",label:"Dijeda"}:{status:"running",label:"Berjalan"}:{status:"stopped",label:"Berhenti"},o=t>=s;return e.jsxs("section",{"aria-label":"Status scheduler",className:"hn-sched-strip",children:[e.jsx(la,{status:p.status,variant:"dot",children:p.label}),e.jsx("div",{className:"hn-sched-capacity",children:e.jsx(ia,{value:t,max:Math.max(s,1),size:"sm",tone:o?"warn":"brass",label:`${t} dari ${s} sesi`})}),e.jsxs("div",{className:"hn-sched-limits",children:[e.jsx(oa,{}),e.jsx(ca,{})]}),e.jsx(ma,{}),e.jsxs("div",{className:"hn-sched-strip-actions",children:[a.enabled?a.paused?e.jsx(C,{size:"sm",leftIcon:"play",disabled:m,onClick:()=>r({...a,paused:!1},"Scheduler dilanjutkan"),children:"Lanjutkan"}):e.jsx(C,{size:"sm",variant:"secondary",leftIcon:"pause",disabled:m,onClick:()=>x({...a,paused:!0},"jeda"),children:"Jeda"}):e.jsx(C,{size:"sm",leftIcon:"play",disabled:m,onClick:()=>r({...a,enabled:!0},"Scheduler diaktifkan"),children:"Aktifkan"}),a.enabled&&e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"hn-sched-strip-divider","aria-hidden":"true"}),e.jsx(C,{size:"sm",variant:"danger",leftIcon:"square",disabled:m,onClick:()=>x({...a,enabled:!1},"hentikan"),children:"Hentikan"})]})]})]})}function Ua({status:a}){return e.jsxs("div",{"aria-label":"Status pemeriksaan peluncuran",className:"hn-sched-guard-status",children:[e.jsxs("div",{children:["Pemeriksaan ",a.enabled?"aktif":"nonaktif"," · ",a.liveCount," dari batas ",a.maxConcurrent," sesi berjalan (",a.liveAgentCount," di antaranya agen)"]}),e.jsxs("div",{children:["Beban CPU per inti: ",a.loadStatus==="available"&&a.loadPerCore!==null?a.loadPerCore.toFixed(2):"tidak tersedia",a.loadStatus==="unsupported"?" (tidak didukung platform)":""," · batas ",a.maxLoadPerCore]}),e.jsxs("div",{children:["Memori bebas: ",a.memStatus==="available"&&a.memAvailablePct!==null?`${a.memAvailablePct.toFixed(0)}%`:"tidak tersedia"," · minimal ",a.minMemAvailablePct,"%"]}),e.jsx("div",{className:"hn-sched-note",children:"Berlaku juga saat scheduler berhenti. Terminal dan shell tetap bisa dibuka, dan keduanya ikut dihitung dalam batas sesi."})]})}const be=a=>{const s=a.launchGuard??Ae.launchGuard;return{maxConcurrent:String(a.maxConcurrent),autonomy:a.autonomy,guardOn:s.enabled,maxLoad:String(s.maxLoadPerCore),minMem:String(s.minMemAvailablePct),sources:{backlog:{enabled:a.sources.backlog.enabled,everyMin:String(a.sources.backlog.everyMin)},triase:{enabled:a.sources.triase.enabled,everyMin:String(a.sources.triase.everyMin)}}}},Pe=(a,s)=>{const t=s.launchGuard??Ae.launchGuard,r=s.sources.backlog,x=s.sources.triase;return{...s,maxConcurrent:_(a.maxConcurrent,1,1/0,s.maxConcurrent),autonomy:a.autonomy,launchGuard:{...t,enabled:a.guardOn,maxLoadPerCore:_(a.maxLoad,.1,1/0,t.maxLoadPerCore,!1),minMemAvailablePct:_(a.minMem,0,100,t.minMemAvailablePct,!1)},sources:{...s.sources,backlog:{...r,enabled:a.sources.backlog.enabled,everyMin:_(a.sources.backlog.everyMin,1,1/0,r.everyMin)},triase:{...x,enabled:a.sources.triase.enabled,everyMin:_(a.sources.triase.everyMin,1,1/0,x.everyMin)}}}},Ta=a=>`${a.lastRunAt?`terakhir ${Me(a.lastRunAt)}`:"belum pernah dicek"} · ${a.nextRunAt?`berikutnya ${xa(a.nextRunAt)}`:"belum dijadwalkan"}`;function _a({cfg:a,sources:s,admission:t,onWrite:r,busy:x}){const{draft:m,setDraft:p,dirty:o}=ba(be(a)),w=l=>be(Pe(l,a)),g=()=>p(l=>w(l)),h=()=>{const l=Pe(m,a);p(be(l)),r(l)},S=l=>{l.key==="Enter"&&(l.preventDefault(),h())},u=(l,c)=>p(k=>({...k,sources:{...k.sources,[l]:{...k.sources[l],...c}}}));return e.jsxs("div",{className:"hn-sched-panel",children:[e.jsxs("section",{className:"hn-sched-group","aria-labelledby":"sched-set-sesi",children:[e.jsx("h3",{id:"sched-set-sesi",className:"hn-sched-group-title",children:"Sesi"}),e.jsxs("div",{className:"hn-sched-grid",children:[e.jsx(R,{label:"Batas sesi bersamaan",hint:"Termasuk terminal dan shell yang kamu buka sendiri.",children:e.jsx($,{type:"number",min:1,value:m.maxConcurrent,"aria-label":"Batas sesi bersamaan",placeholder:"mis. 6",onChange:l=>p(c=>({...c,maxConcurrent:l.target.value})),onBlur:g,onKeyDown:S})}),e.jsx(R,{label:"Saat ada keputusan yang belum jelas",hint:"Keputusan yang ambigu tetap ditanyakan ke lead atau kamu.",children:e.jsx(O,{value:m.autonomy,"aria-label":"Mode otonomi",onChange:l=>p(c=>({...c,autonomy:l.target.value})),options:Ba})})]})]}),e.jsxs("section",{className:"hn-sched-group","aria-labelledby":"sched-set-peluncuran",children:[e.jsx("h3",{id:"sched-set-peluncuran",className:"hn-sched-group-title",children:"Peluncuran"}),e.jsx(xe,{label:"Tahan peluncuran saat server sibuk",checked:m.guardOn,onChange:l=>p(c=>({...c,guardOn:l}))}),e.jsx("p",{className:"hn-sched-group-hint",children:"Mencegah sesi baru diluncurkan saat batas sesi penuh, beban CPU per inti terlalu tinggi, atau memori bebas terlalu sedikit. Berlaku juga untuk peluncuran manual. Mematikannya melewati ketiga pemeriksaan itu. Terpisah dari saklar scheduler dan sumber."}),e.jsxs("div",{className:"hn-sched-grid",children:[e.jsx(R,{label:"Batas beban CPU per inti",hint:"Di atas angka ini, sesi baru tidak diluncurkan.",children:e.jsx($,{type:"number",min:.1,step:"any",value:m.maxLoad,"aria-label":"Batas beban CPU per inti",placeholder:"mis. 2.5",onChange:l=>p(c=>({...c,maxLoad:l.target.value})),onBlur:g,onKeyDown:S})}),e.jsx(R,{label:"Memori bebas minimal (%)",hint:"Di bawah angka ini, sesi baru tidak diluncurkan.",children:e.jsx($,{type:"number",min:0,max:100,step:"any",value:m.minMem,"aria-label":"Memori bebas minimal (%)",placeholder:"mis. 15",onChange:l=>p(c=>({...c,minMem:l.target.value})),onBlur:g,onKeyDown:S})})]}),t&&e.jsx(Ua,{status:t})]}),e.jsxs("section",{className:"hn-sched-group","aria-labelledby":"sched-set-sumber",children:[e.jsx("h3",{id:"sched-set-sumber",className:"hn-sched-group-title",children:"Sumber otomatis"}),["backlog","triase"].map(l=>{const c=s.find(k=>k.id===l);return e.jsxs("div",{className:"hn-sched-source",children:[e.jsx(xe,{label:q[l],checked:m.sources[l].enabled,onChange:k=>u(l,{enabled:k})}),e.jsx("span",{className:"hn-sched-spacer"}),e.jsxs("label",{className:"hn-sched-inline-field",children:["cek tiap",e.jsx($,{type:"number",min:1,"aria-label":`Interval cek ${q[l]}`,placeholder:"mis. 30",value:m.sources[l].everyMin,onChange:k=>u(l,{everyMin:k.target.value}),onBlur:g,onKeyDown:S}),"menit"]}),c&&e.jsx("span",{className:"hn-sched-source-facts",children:Ta(c)})]},l)})]}),e.jsxs("div",{className:"hn-sched-savebar",children:[o&&e.jsx("span",{role:"status",className:"hn-sched-note",children:"Ada perubahan yang belum disimpan."}),e.jsx(C,{leftIcon:"save",disabled:x,onClick:h,children:"Simpan setelan"})]})]})}function Ja({projects:a,onToggle:s,busyId:t}){return e.jsxs("section",{className:"hn-sched-group","aria-labelledby":"sched-set-project",children:[e.jsx("h3",{id:"sched-set-project",className:"hn-sched-group-title",children:"Project yang diizinkan"}),e.jsx("p",{className:"hn-sched-group-hint",children:"Scheduler hanya menyentuh project yang diizinkan. Default: tidak diizinkan."}),a.length===0?e.jsx("p",{className:"hn-sched-empty",children:"Belum ada project."}):e.jsx(ee,{label:"Project yang diizinkan",children:a.map(r=>e.jsx(H,{actions:r.schedulerOptIn?e.jsx(C,{size:"sm",variant:"ghost",leftIcon:"ban",disabled:t===r.id,onClick:()=>s(r.id,!1),children:"Cabut izin"}):e.jsx(C,{size:"sm",leftIcon:"check",disabled:t===r.id,onClick:()=>s(r.id,!0),children:"Izinkan"}),children:e.jsx("span",{className:"hn-sched-row-text",children:e.jsxs("span",{className:"hn-sched-row-head",children:[e.jsx("span",{className:"hn-sched-row-title",children:r.name}),e.jsx(F,{tone:r.schedulerOptIn?"ok":"neutral",size:"sm",children:r.schedulerOptIn?"diizinkan":"tidak diizinkan"})]})})},r.id))})]})}function Ga(a){const[s,t]=i.useState(null),[r,x]=i.useState(null),m=i.useCallback(()=>{N.getSettings().then(o=>{t(o),x(null)}).catch(o=>x(E("memuat orkestrasi",o)))},[]);i.useEffect(()=>{m()},[m]);const p=i.useCallback(async(o,w)=>{if(!s)return;const g=s;t({...g,orchestration:o});try{const h=await N.getSettings().catch(()=>{});await N.putSettings(ka(g,{...g,orchestration:o},h)),a(w,"ok","check-circle-2")}catch(h){t(g),a(E("menyimpan orkestrasi",h),"err","alert-triangle")}},[s,a]);return{setting:s,error:r,load:m,writeOrchestration:p}}function Ka({snap:a}){return e.jsxs("section",{className:"hn-sched-group","aria-labelledby":"sched-set-orkestrasi",children:[e.jsx("h3",{id:"sched-set-orkestrasi",className:"hn-sched-group-title",children:"Orkestrasi subagen per fase"}),e.jsx("p",{className:"hn-sched-group-hint",children:"Perubahan tersimpan saat diubah. Buka satu flow untuk mengatur model dan effort per fase."}),a.error?e.jsx(W,{message:a.error,onRetry:a.load}):a.setting?e.jsx(ga,{variant:"accordion",orchestration:a.setting.orchestration,onChange:(s,t)=>void a.writeOrchestration(s,t)}):e.jsx(G,{rows:2,label:"Memuat orkestrasi…"})]})}function an({projects:a,backlog:s,onProjectChanged:t,onToast:r,onGotoTerminal:x}){const{confirm:m,dialog:p}=Le(),[o,w]=i.useState(null),[g,h]=i.useState("loading"),[S,u]=i.useState(!1),[l,c]=i.useState(null),[k,B]=J("scheduler","tab","antre",Ee(...La)),I=Ga(r),b=i.useCallback((f=!1)=>{f||h("loading"),N.getSchedulerState().then(y=>{w(y),h("ready")}).catch(()=>{f||h("error")})},[]);i.useEffect(()=>{b()},[b]),Be({topic:"schedulerState",params:{},apply:f=>{w(f.state),h("ready")},refetch:()=>b(!0),pollMs:ze});const P=i.useCallback(async(f,y="Setelan scheduler tersimpan")=>{u(!0);try{await N.putSchedulerConfig(f),r(y,"ok","save"),b(!0)}catch(v){r(Ie(v)??E("menyimpan setelan",v),"err","x-circle")}finally{u(!1)}},[b,r]),A=i.useCallback((f,y)=>{const v=y==="jeda";m({title:v?"Jeda scheduler?":"Hentikan scheduler?",eyebrow:"scheduler · rem darurat",message:v?"Scheduler berhenti meluncurkan sesi baru dari antrean sampai kamu melanjutkannya. Sesi yang sudah berjalan tidak dihentikan.":void 0,impact:v?void 0:["Sumber backlog dan triase tidak lagi diperiksa sampai diaktifkan lagi.","Antrean tetap tersimpan dan tidak diproses selama berhenti.","Sesi yang sudah berjalan tetap berjalan."],confirmLabel:v?"Jeda scheduler":"Hentikan scheduler",icon:v?"pause":"square",tone:v?"default":"danger",run:()=>P(f,v?"Scheduler dijeda":"Scheduler dihentikan")})},[m,P]),D=i.useCallback(async(f,y)=>{c(f);try{await N.updateProject(f,{schedulerOptIn:y}),await t(f),r(y?"Project diizinkan untuk scheduler":"Izin scheduler dicabut","ok")}catch(v){r(E("mengubah izin project",v),"err","x-circle")}finally{c(null)}},[t,r]),U=i.useCallback(async(f,y)=>{c(f);try{y==="cancel"?(await N.cancelSchedulerQueueItem(f),r("Item antrean dibatalkan","ok","ban")):(await N.requeueSchedulerQueueItem(f),r("Item dikembalikan ke antrean","ok","rotate-ccw"))}catch(v){const se=y==="cancel"?"membatalkan item antrean":"mengembalikan item ke antrean";r(Ie(v)??E(se,v),"err","x-circle")}finally{c(null),b(!0)}},[b,r]);if(g==="loading")return e.jsx(G,{rows:4,label:"Memuat scheduler…"});if(g==="error"||!o)return e.jsx(ra,{kind:"error",hint:"Gagal memuat state scheduler.",action:()=>b(),actionLabel:"Coba lagi"});const L={backlog:s,projectName:f=>{var y;return((y=a.find(v=>v.id===f))==null?void 0:y.name)??"Project lain"}},M=o.queueCounts,ne=(M.done??0)+(M.failed??0)+(M.canceled??0),Z=[{value:"antre",label:"Antre",count:M.queued||void 0},{value:"berjalan",label:"Berjalan",count:o.sessions.length||void 0},{value:"riwayat",label:"Riwayat",count:ne||void 0},{value:"cron",label:"Cron"},{value:"setelan",label:"Setelan"}];return e.jsxs("div",{className:"hn-sched",children:[e.jsx(Da,{cfg:o.config,cap:o.cap,liveCount:o.liveCount,onWrite:P,onAsk:A,busy:S}),e.jsxs(Re,{tabs:Z,value:k,onChange:f=>B(f),children:[e.jsx(T,{value:"antre",className:"hn-sched-panel",children:e.jsx(Oe,{what:"antrean",status:"queued",count:M.queued,empty:"Antrean kosong.",render:f=>e.jsx(Ma,{q:f,ctx:L,busy:l===f.id,onCancel:y=>void U(y,"cancel")},f.id)})}),e.jsx(T,{value:"berjalan",className:"hn-sched-panel",children:o.sessions.length===0?e.jsx("p",{className:"hn-sched-empty",children:"Tidak ada sesi dari scheduler yang sedang berjalan."}):e.jsx(ee,{label:"Sesi berjalan",children:o.sessions.map(f=>e.jsx(za,{s:f,ctx:L,onGotoTerminal:x},f.id))})}),e.jsx(T,{value:"riwayat",className:"hn-sched-panel",children:k==="riwayat"&&e.jsx(Ha,{counts:M,ctx:L,busyId:l,onRowAction:U,onToast:r})}),e.jsx(T,{value:"cron",className:"hn-sched-panel",children:k==="cron"&&e.jsx(Pa,{projects:a,onProjectChanged:t,onToast:r,timeZone:o.serverTimeZone})}),e.jsxs(T,{value:"setelan",className:"hn-sched-panel",children:[e.jsx(_a,{cfg:o.config,sources:o.sources,admission:o.admission,onWrite:f=>void P(f),busy:S}),e.jsx(Ja,{projects:a,onToggle:D,busyId:l}),e.jsx(Ka,{snap:I})]})]}),p]})}export{an as SchedulerScreen};
|