hanoman 0.9.21 → 0.9.23

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 (38) hide show
  1. package/dist/build-info.json +3 -3
  2. package/dist/cli.js +9 -6
  3. package/dist/server.js +19 -15
  4. package/package.json +1 -1
  5. package/web/assets/DalangHanomanScreen--M-xLwH5.js +16 -0
  6. package/web/assets/DalangHanomanScreen-DhDPV6e8.css +1 -0
  7. package/web/assets/{DocPreviewModal-CJP6d0Hx.js → DocPreviewModal-CYdmHEb_.js} +1 -1
  8. package/web/assets/{DocsWorkspace-zGpPd7u3.js → DocsWorkspace-BFzb87Ye.js} +1 -1
  9. package/web/assets/{IdeScreen-DTvfuR2n.js → IdeScreen-CDMJaERU.js} +1 -1
  10. package/web/assets/{LeadScreen-DWbunLkQ.js → LeadScreen-DJjFTkyZ.js} +1 -1
  11. package/web/assets/{ReviewScreen-Ch9UiKlx.js → ReviewScreen-DG0xSBou.js} +1 -1
  12. package/web/assets/{SchedulerScreen-zIUh-Vbe.js → SchedulerScreen-ChEZ01CH.js} +1 -1
  13. package/web/assets/{SettingsScreen-CLMuCJ6R.js → SettingsScreen-BnINOj5X.js} +1 -1
  14. package/web/assets/{TeamScreen-CV1R5Ekk.js → TeamScreen-5cFDPm3o.js} +1 -1
  15. package/web/assets/{TerminalScreen-QVjhjrxx.js → TerminalScreen-CIROrYjO.js} +1 -1
  16. package/web/assets/TerminalScreen-D0NdFmR-.css +1 -0
  17. package/web/assets/{TriageScreen-Dpj4YrBQ.js → TriageScreen-BWnuGOmQ.js} +1 -1
  18. package/web/assets/{VpsScreen-DX_HEquM.js → VpsScreen-PqOkFriA.js} +1 -1
  19. package/web/assets/hnm-blencong-v01-CBBfchr0.webp +0 -0
  20. package/web/assets/hnm-hero-rig-arm-ml-v01-Kts3pjTf.webp +0 -0
  21. package/web/assets/hnm-hero-rig-arm-mr-v01-DQgnE6bD.webp +0 -0
  22. package/web/assets/hnm-hero-rig-arm-ul-v01-CIAWAxFe.webp +0 -0
  23. package/web/assets/hnm-hero-rig-arm-ur-v01-C0R0CZnp.webp +0 -0
  24. package/web/assets/hnm-hero-rig-body-v01-DmbKJJHB.webp +0 -0
  25. package/web/assets/hnm-wayang-panakawan-v01-1LGv-V8N.webp +0 -0
  26. package/web/assets/hnm-wayang-putri-v01-F6p69kHq.webp +0 -0
  27. package/web/assets/hnm-wayang-satria-alus-v01-CpfoXKTy.webp +0 -0
  28. package/web/assets/hnm-wayang-satria-gagah-v01-bLfIYAsv.webp +0 -0
  29. package/web/assets/{index-DmnwLncG.js → index-DYWU10xI.js} +3 -3
  30. package/web/assets/index-T4aiSGoI.css +32 -0
  31. package/web/assets/{live-B193WtZm.js → live-C90Zx0h6.js} +1 -1
  32. package/web/assets/{sched-lead-shared-BjMO8Q_k.js → sched-lead-shared-Qn3NA7WO.js} +1 -1
  33. package/web/assets/{settings-rebase-BI7-Bk98.js → settings-rebase-3Z15zUKI.js} +1 -1
  34. package/web/index.html +2 -2
  35. package/web/assets/DalangHanomanScreen-Us_5qG25.js +0 -13
  36. package/web/assets/DalangHanomanScreen-gk7fa9dl.css +0 -1
  37. package/web/assets/TerminalScreen-DrgZKlw2.css +0 -1
  38. package/web/assets/index-CL0_zz87.css +0 -32
@@ -1,4 +1,4 @@
1
- import{bm as ra,bn as da,bo as ca,bp as oa,bq as ua,br as ha,bs as ma,bt as ga,bu as ka,bv as pa,bw as ba,bx as fa,by as ja,bz as xa,bA as va,bB as ya,bC as wa,bD as Sa,bE as Na,bF as Ca,bG as Ea,bH as Aa,bI as Oa,bJ as Pa,bK as Ma,bL as Ia,bM as Da,bN as La,bO as _a,bP as ke,bQ as Z,bR as te,bS as Je,bT as Ra,a6 as be,bU as Ba,ba as Ha,ad as Fa,bV as Ee,bW as za,bX as $a,h as N,i as $,j as e,f as J,B as y,aH as I,b1 as q,ac as we,g as K,bY as qe,aa as Ua,ab as Ka,bZ as Ve,b_ as Ta,b$ as Ga,c0 as Wa,c1 as De,bb as Ja,aX as fe,c2 as Le,c3 as _e,n as ee,H as qa,d as le,I as re,m as W,C as se,e as ae,aI as de,c4 as Va,c5 as Ye,c6 as me,c7 as Qe,c8 as Ya,c9 as oe,ca as Ae,cb as Qa,cc as Re,cd as Xa,ce as Za,cf as en,cg as pe,$ as an,b as Xe,ch as nn,ci as tn,cj as sn,ag as Se,q as ln,D as rn,ck as dn,cl as cn}from"./index-DmnwLncG.js";import{R as d}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import{r as Ze,O as on}from"./settings-rebase-BI7-Bk98.js";import{D as un}from"./DocPreviewModal-CJP6d0Hx.js";import"./xterm-3VOAfa_q.js";/* empty css */const hn=[...ra,...da,...ca,...oa,...ua,...ha,...ma,...ga,...ka,...pa,...ba,...fa,...ja,...xa,...va,...ya,...wa,...Sa,...Na,...Ca,...Ea,...Aa,...Oa],mn=2,Y=Pa,ie=[{key:"sesi",label:"Sesi harian",icon:"bell",sections:[{key:"sesi",label:"Sesi harian",icon:"bell",keywords:"notifikasi suara selesai keputusan gagal full-auto scaffold agen model default effort goal kondisi verifikasi scope metode workflow"}]},{key:"model",label:"Agen & model",icon:"cpu",sections:[{key:"model",label:"Agen & model",icon:"cpu",keywords:"override konflik rebase merge lead operator obrolan portal jatah orkestrasi fase effort model runtime"}]},{key:"integrasi",label:"Integrasi & akses",icon:"webhook",sections:[{key:"agent",label:"Akses AI Agent",icon:"bot",keywords:"token agent capability mcp master switch"},{key:"telegram",label:"Telegram",icon:"send",keywords:"bot token chat allowlist gateway operator agen progress uji koneksi"},{key:"webhook",label:"Webhook",icon:"webhook",keywords:"endpoint secret peristiwa pengiriman dokumentasi"},{key:"akses-klien",label:"Akses klien",icon:"user-check",keywords:"portal klien grant lihat tulis mulai sesi"},{key:"perangkat",label:"Perangkat",icon:"key-round",keywords:"token perangkat sinkron server pusat"},{key:"kendali-jarak-jauh",label:"Kendali jarak jauh",icon:"shield",keywords:"izin server pusat perangkat kendali"}]},{key:"lanjutan",label:"Lanjutan",icon:"sliders-horizontal",collapsible:!0,sections:[{key:"akun",label:"Akun",icon:"user-round",keywords:"password email logout ganti masuk"},{key:"users",label:"Pengguna",icon:"users",keywords:"undang hapus pengguna email password"},{key:"setup",label:"Setup awal",icon:"shield",keywords:"peruntukan hardening setup ulang"},{key:"konfigurasi",label:"Konfigurasi",icon:"sliders-horizontal",keywords:"env rahasia bootstrap sinkron runtime variabel"},{key:"aktivitas",label:"Log aktivitas",icon:"activity",keywords:"log sesi project hasil commit pr hapus"},{key:"custom-agent",label:"Custom agent",icon:"bot",keywords:"persona agen mention katalog"},{key:"zona-bahaya",label:"Zona bahaya",icon:"alert-triangle",keywords:"reset default kembalikan semua setelan"}]}],Ne="sesi",gn=ie.flatMap(a=>a.sections.map(n=>n.key)),ea=a=>gn.includes(a),kn=new Map([["umum","sesi"],["orkestrasi","model"]]);function Be(a){if(typeof a!="string")return Ne;const n=kn.get(a)??a;return ea(n)?n:Ne}function aa(a){return ie.find(n=>n.sections.some(t=>t.key===a))??ie[0]}function pn(a){return ie.flatMap(t=>t.sections).find(t=>t.key===a)??ie[0].sections[0]}function na(a){const n=aa(a);return n.sections.length>1?`${n.label} · ${pn(a).label}`:n.label}function bn(a){const n=new URLSearchParams(a.replace(/^#/,"")).get("bagian");return n&&ea(n)?n:null}const Oe=a=>$a(a).map(n=>({value:n,label:n==="xhigh"?"x-high":n})),Pe=a=>Ee(za,a),Me=(a,n)=>{const t=Fa(a,n);return t===n?{}:{effort:t}},He=[{value:"blip",label:"Blip · 0.1s"},{value:"pop",label:"Pop · 0.1s"},{value:"short",label:"Short · 0.15s"},{value:"ping",label:"Ping · 0.2s"},{value:"coin",label:"Coin · 0.3s"},{value:"alert",label:"Alert · 0.3s"},{value:"medium",label:"Medium · 0.4s"},{value:"chime",label:"Chime · 0.4s"},{value:"success",label:"Success · 0.4s"},{value:"bell",label:"Bell · 0.5s"},{value:"marimba",label:"Marimba · 0.6s"},{value:"long",label:"Long · 0.8s"},{value:"fanfare",label:"Fanfare · 0.9s"},{value:"off",label:"Senyap"}],fn={model:"sonnet",effort:"medium",autoDefault:!0,autoScaffold:!0,notifyFail:!0,notifyDone:!0,notifySound:"short",notifyDecision:!0,notifyDecisionSound:"alert",agentAccessEnabled:!1,scheduler:Ha,goal:Ba,agent:"claude",codex:be,verifyScope:"changed",method:Ra,conflict:Je,lead:te,telegram:Z,portalChat:ke,orchestration:_a,remoteControl:La,logShipping:Da,logRetention:Ia,builtinAgents:{},builtinAgentPolicies:{},builtinRuntimeDefaults:Ma},Fe=()=>{};function jn(a){const[n,t]=d.useState(null),[l,r]=d.useState(!1),m=d.useRef(null),i=d.useRef(a);i.current=a;const s=d.useRef(Promise.resolve()),u=d.useCallback(k=>{m.current=k,t(k)},[]),h=d.useCallback(()=>{r(!1),u(null),N.getSettings().then(k=>u(k),()=>r(!0))},[u]);d.useEffect(()=>{h()},[h]);const b=d.useCallback((k,w,O,S)=>{const D=m.current;if(!D)return Promise.resolve(!1);const A=Object.keys(k).filter(M=>JSON.stringify(k[M])!==JSON.stringify(D[M]));u(k);const x=s.current.then(async()=>{const M=await N.getSettings().catch(()=>{});await N.putSettings(Ze(D,k,M))});return s.current=x.then(Fe,Fe),x.then(()=>{var M;return w&&((M=i.current)==null||M.call(i,w,O||"ok",S||"check-circle-2")),!0},M=>{var C;const L=Object.fromEntries(A.map(R=>[R,D[R]]));return u({...m.current??D,...L}),(C=i.current)==null||C.call(i,$("menyimpan pengaturan",M),"err","alert-triangle"),!1})},[u]),f=d.useCallback((k,w)=>{const O=m.current;return O?b({...O,...k},w):Promise.resolve(!1)},[b]),g=d.useCallback(k=>{const w=m.current;w&&u(k(w))},[u]),j=d.useCallback(()=>m.current,[]);return{s:n,failed:l,load:h,persist:b,save:f,update:g,current:j}}function xn(a){const n=a.trim().toLowerCase();return n?ie.flatMap(t=>t.sections).filter(t=>`${t.label} ${t.keywords}`.toLowerCase().includes(n)).map(t=>({key:t.key,path:na(t.key)})):[]}const je=(a,n)=>(a??"").toLowerCase().includes(n);function vn(a,n){if(!a)return 0;const t=n.trim().toLowerCase(),l=Array.from(a.querySelectorAll("[data-setting-row]")),r=Array.from(a.querySelectorAll("[data-setting-card]")),m=s=>{var u;return((u=s.parentElement)==null?void 0:u.closest("[data-setting-card]"))??null};let i=0;return t?(r.forEach(s=>{const u=je(s.getAttribute("data-search"),t),h=Array.from(s.querySelectorAll("[data-setting-row]")).filter(f=>m(f)===s);if(h.length===0){s.hidden=!u,u&&i++;return}let b=!1;h.forEach(f=>{const g=u||je(f.getAttribute("data-search"),t);f.hidden=!g,g&&(b=!0,i++)}),s.hidden=!(u||b)}),l.forEach(s=>{if(m(s))return;const u=je(s.getAttribute("data-search"),t);s.hidden=!u,u&&i++}),i):(l.forEach(s=>{s.hidden=!1}),r.forEach(s=>{s.hidden=!1}),l.length+r.filter(s=>!s.querySelector("[data-setting-row]")).length)}function yn(a,n,t){const[l,r]=d.useState(0);return d.useLayoutEffect(()=>{const m=a.current,i=()=>r(vn(m,n));if(i(),!m||typeof MutationObserver>"u")return;const s=new MutationObserver(i);return s.observe(m,{childList:!0,subtree:!0}),()=>s.disconnect()},[n,t,a]),l}function wn({value:a,onChange:n,hits:t,onPick:l}){return e.jsxs("div",{className:"hn-set-search",role:"search",children:[e.jsx(J,{type:"search","aria-label":"Cari pengaturan",placeholder:"mis. notifikasi, telegram, token",value:a,leftIcon:"search",className:"hn-set-full",onChange:r=>n(r.target.value),onKeyDown:r=>{r.key==="Escape"&&a&&n("")}}),a.trim()!==""&&t.length>0&&e.jsx("ul",{className:"hn-set-search-hits","aria-label":"Bagian yang cocok",children:t.map(r=>e.jsx("li",{children:e.jsx("button",{type:"button",className:"hn-set-search-hit",onClick:()=>l(r.key),children:r.path})},r.key))})]})}function Sn({save:a}){if(a.status==="idle")return null;if(a.status==="error")return e.jsxs("span",{className:"hn-set-save hn-set-save--err",role:"status","data-testid":"save-status",children:["Gagal — coba lagi",e.jsx(y,{size:"sm",variant:"ghost",leftIcon:"refresh-cw",onClick:a.retry,children:"Coba lagi"})]});const n=a.status==="saved"?"Tersimpan":"Menyimpan…",t=a.status==="saved"?"hn-set-save--ok":"hn-set-save--pending";return e.jsx("span",{className:`hn-set-save ${t}`,role:"status","data-testid":"save-status",children:n})}function Nn({text:a}){return e.jsx(e.Fragment,{children:a.split(/`([^`]+)`/).map((n,t)=>t%2===1?e.jsx("code",{className:"hn-set-mono hn-set-codeinline",children:n},t):n)})}function E({title:a,desc:n,children:t,last:l,save:r,search:m}){return e.jsxs("div",{className:`hn-setting-row hn-set-row${l?" hn-set-row--last":""}`,"data-setting-row":!0,"data-search":`${a} ${n??""} ${m??""}`,children:[e.jsxs("div",{className:"hn-set-row-text",children:[e.jsx("div",{className:"hn-set-row-title",children:a}),n&&e.jsx("div",{className:"hn-set-row-desc",children:e.jsx(Nn,{text:n})}),r&&e.jsx(Sn,{save:r})]}),e.jsx("div",{className:"hn-setting-control hn-set-row-control",children:t})]})}function ue({id:a,text:n}){return n?e.jsx("div",{id:a,className:"hn-set-hint",children:n}):null}function Cn({children:a}){return e.jsx("div",{className:"hn-set-note",children:a})}function T({children:a}){return e.jsx("div",{className:"hn-set-prose",children:a})}const En=400,An=1800;function H(a){const n=d.useRef(a);n.current=a;const[t,l]=d.useState(null),r=d.useRef(a.value),[m,i]=d.useState("idle"),s=d.useRef(0),u=d.useRef(null),h=d.useRef(null),b=d.useRef(null),f=d.useRef(null),g=d.useRef(!1),j=d.useRef(0),k=()=>{h.current&&(clearTimeout(h.current),h.current=null)},w=()=>{b.current&&(clearTimeout(b.current),b.current=null)},O=(x,M)=>{if(k(),j.current===0&&Object.is(x,n.current.value)){M===s.current&&(u.current=null,l(null),i("idle"));return}j.current++,i("saving"),Promise.resolve(n.current.save(x)).then(L=>{j.current--,!(!g.current||M!==s.current)&&(u.current=null,L?(f.current=null,l({v:x,settled:!0}),i("saved"),w(),b.current=setTimeout(()=>{b.current=null,g.current&&i(C=>C==="saved"?"idle":C)},An)):(f.current={v:x},l(null),i("error")))})},S=x=>{const M=++s.current;u.current={v:x,id:M},f.current=null,w(),l({v:x,settled:!1}),k();const L=n.current.delayMs??En;if(L<=0){O(x,M);return}i("pending"),h.current=setTimeout(()=>{h.current=null;const C=u.current;C&&O(C.v,C.id)},L)};d.useEffect(()=>{Object.is(r.current,a.value)||(r.current=a.value,l(x=>x&&x.settled?null:x))},[a.value]);const D=()=>{const x=u.current;!h.current||!x||O(x.v,x.id)},A=()=>{const x=f.current;x&&S(x.v)};return d.useEffect(()=>(g.current=!0,()=>{g.current=!1;const x=u.current;h.current&&x&&(k(),Promise.resolve(n.current.save(x.v))),w()}),[]),{value:t?t.v:a.value,set:S,flush:D,status:m,retry:A}}const On=a=>Ee(Ve,a);function ta({model:a,codexVer:n}){var l;const t=(n==null?void 0:n.version)??null;return Ua(a,t)?e.jsxs("div",{"data-testid":"codex-version-note",className:"hn-set-codex-note",children:["Codex CLI terpasang ",e.jsx("b",{children:t}),", sedangkan ",e.jsx("b",{children:a})," butuh ",e.jsx("b",{children:(l=Ka(a))==null?void 0:l.minClient}),". Sesi tetap boleh dijalankan, tapi modelnya belum tentu dikenali CLI ini. Perbarui dengan ",e.jsx("code",{children:"npm i -g @openai/codex@latest"}),"."]}):null}function ze({id:a,label:n,active:t}){return e.jsxs("div",{className:"hn-set-agent-head",children:[e.jsx("div",{className:"hn-set-agent-name",children:n}),e.jsx("span",{"data-testid":`agent-badge-${a}`,className:`hn-set-agent-badge${t?" hn-set-agent-badge--on":""}`,children:t?"dipakai sesi baru":"tidak dipakai sekarang"})]})}function Ce({engine:a,labels:n,defaults:t,codexVer:l,save:r}){const m=H({value:a.agent,delayMs:0,save:h=>{const b=h==="codex"?t.codex:t.claude;return r({agent:h,model:b.model,effort:h==="codex"?we(b.model,b.effort):b.effort},`${n.msg.agent} → ${h}`)}}),i=H({value:a.model,delayMs:0,save:h=>r({model:h,...a.agent==="codex"?{effort:we(h,a.effort)}:Me(h,a.effort)},`${n.msg.model} → ${h}`)}),s=H({value:a.effort,delayMs:0,save:h=>r({effort:h},`${n.msg.effort} → ${h}`)}),u=m.value==="codex";return e.jsxs(e.Fragment,{children:[e.jsx(E,{title:n.agentTitle,desc:n.agentDesc,save:m,children:e.jsx(K,{size:"sm","aria-label":n.aria.agent,value:m.value,className:"hn-set-w-sm",options:[{value:"claude",label:Y.claude},{value:"codex",label:Y.codex}],onChange:h=>m.set(h.target.value)})}),u&&e.jsx(ta,{model:i.value,codexVer:l}),e.jsx(E,{title:"Model",save:i,children:e.jsx(K,{size:"sm","aria-label":n.aria.model,value:i.value,className:"hn-set-w-sm",options:u?On(i.value):Pe(i.value),onChange:h=>i.set(h.target.value)})}),e.jsx(E,{title:"Effort",desc:n.effortDesc,last:!0,save:s,children:e.jsx(K,{size:"sm","aria-label":n.aria.effort,value:s.value,className:"hn-set-w-xs",options:u?qe(i.value).map(h=>({value:h,label:h})):Oe(i.value),onChange:h=>s.set(h.target.value)})})]})}function ge({eyebrow:a,title:n,desc:t,toggleTitle:l="Pakai setelan sendiri",toggleDesc:r,toggleAria:m,enabled:i,onToggle:s,inherited:u,inheritedTestId:h,children:b}){const f=H({value:i,delayMs:0,save:g=>s(g)});return e.jsxs(I,{eyebrow:a,title:n,"data-setting-card":!0,"data-search":`${n} ${a}`,children:[e.jsx(T,{children:t}),e.jsx(E,{title:l,desc:r,save:f,last:!f.value,children:e.jsx(q,{"aria-label":m,checked:f.value,onChange:g=>f.set(g)})}),f.value?b:u?e.jsx("div",{"data-testid":h,className:"hn-set-inherited",children:u}):null]})}function xe({label:a,value:n,min:t,max:l,placeholder:r,width:m,onCommit:i,onToast:s}){const[u,h]=d.useState(String(n));d.useEffect(()=>h(String(n)),[n]);const b=H({value:n,delayMs:0,save:g=>i(g)}),f=()=>{const g=u.trim(),j=g===""?NaN:Math.floor(Number(g));if(!Number.isFinite(j)||j<t){s==null||s(`${a}: isi angka ${t} atau lebih. Nilai sebelumnya dipertahankan.`,"warn","alert-triangle"),h(String(n));return}const k=Math.min(j,l);k!==j&&(s==null||s(`${a} dibatasi ke ${l}.`,"warn","alert-triangle"),h(String(k))),k!==n&&b.set(k)};return e.jsx(J,{"aria-label":a,type:"number",min:t,max:l,placeholder:r,className:m??"hn-set-w-xs",value:u,onChange:g=>h(g.target.value),onBlur:f,onKeyDown:g=>{g.key==="Enter"&&f()}})}const Pn={default:null,tampil:!0,sembunyi:!1};function ce(a,n,t,l){return H({value:t,delayMs:0,save:r=>a.save({[n]:r},l+(r?" · aktif":" · nonaktif"))})}function Mn({s:a,store:n,onToast:t,codexVer:l}){const r=Ta(),[m,i]=d.useState(null),[s,u]=d.useState("");d.useEffect(()=>{N.getMethodStatus().then(i).catch(()=>i(null)),N.listProjects({limit:100}).then(o=>u(c=>{var _;return c||(((_=o.items.find(z=>z.binding??z.repoDir))==null?void 0:_.id)??"")})).catch(o=>t==null?void 0:t($("memuat daftar project",o),"err","alert-triangle"))},[]);const[h,b]=Ga(),f=h===null?"default":h?"tampil":"sembunyi",g=ce(n,"notifyDone",a.notifyDone,"Notifikasi backlog selesai"),j=H({value:a.notifySound,delayMs:0,save:o=>n.save({notifySound:o},"Sound → "+o)}),k=ce(n,"notifyDecision",a.notifyDecision,"Notifikasi keputusan"),w=H({value:a.notifyDecisionSound,delayMs:0,save:o=>n.save({notifyDecisionSound:o},"Sound keputusan → "+o)}),O=ce(n,"notifyFail",a.notifyFail,"Notifikasi gagal"),S=ce(n,"autoDefault",a.autoDefault,"Full-auto default"),D=ce(n,"autoScaffold",a.autoScaffold,"Auto-scaffold"),A=a.agent??"claude",x=a.codex??be,M=H({value:A,delayMs:0,save:o=>n.save({agent:o},"Agen → "+o)}),L=H({value:a.model,delayMs:0,save:o=>n.save({model:o,...Me(o,a.effort)},"Model claude → "+o)}),C=H({value:a.effort,delayMs:0,save:o=>n.save({effort:o},"Effort claude → "+o)}),R=H({value:x.model,delayMs:0,save:o=>n.save({codex:{model:o,effort:we(o,x.effort)}},"Model codex → "+o)}),B=H({value:x.effort,delayMs:0,save:o=>n.save({codex:{...x,effort:o}},"Effort codex → "+o)}),Q=H({value:a.goal.enabled,delayMs:0,save:o=>n.save({goal:{...a.goal,enabled:o}},"Mode goal"+(o?" · aktif":" · nonaktif"))}),V=H({value:a.goal.condition,save:o=>n.save({goal:{...a.goal,condition:o}},"Kondisi mode goal disimpan")}),X=H({value:a.verifyScope??"changed",delayMs:0,save:o=>n.save({verifyScope:o},"Scope verifikasi → "+o)}),G=H({value:Wa(a.method).id,delayMs:0,save:o=>n.save({method:o},"Metode → "+o)}),p=async o=>{if(s)try{await N.createShell(s,{method:o.method,agent:o.agent}),t==null||t(`Pemasangan ${o.label} · ${Y[o.agent]} berjalan di Terminal`,"ok","terminal")}catch{t==null||t("Gagal membuka sesi terminal pemasangan","err","alert-triangle")}},P=A==="codex"?{agent:"codex",model:x.model,effort:x.effort}:{agent:"claude",model:a.model,effort:a.effort};return e.jsxs(e.Fragment,{children:[e.jsxs(I,{eyebrow:"sesi",title:"Sesi & notifikasi","data-setting-card":!0,"data-search":"sesi notifikasi suara",children:[e.jsx(E,{title:"Notifikasi backlog selesai",desc:"Toast + sound saat sebuah backlog mencapai stage done. Daftar lonceng tetap terisi meski dimatikan.",save:g,children:e.jsx(q,{"aria-label":"Notifikasi backlog selesai",checked:g.value,onChange:o=>g.set(o)})}),e.jsx(E,{title:"Sound notifikasi",desc:"Durasi nada saat backlog selesai.",save:j,children:e.jsxs("div",{className:"hn-set-inline",children:[e.jsx(K,{size:"sm","aria-label":"Sound notifikasi",value:j.value,options:He,className:"hn-set-w-sm",onChange:o=>j.set(o.target.value)}),e.jsx(y,{size:"sm",variant:"ghost",leftIcon:"volume-2",disabled:j.value==="off",onClick:()=>De(j.value),children:"Preview"})]})}),e.jsx(E,{title:"Notifikasi butuh keputusan",desc:"Toast + sound saat sesi Claude berhenti menunggu keputusanmu. Nada sengaja beda dari selesai.",save:k,children:e.jsx(q,{"aria-label":"Notifikasi keputusan",checked:k.value,onChange:o=>k.set(o)})}),e.jsx(E,{title:"Sound keputusan",desc:"Nada saat sebuah sesi menunggu keputusan.",save:w,children:e.jsxs("div",{className:"hn-set-inline",children:[e.jsx(K,{size:"sm","aria-label":"Sound keputusan",value:w.value,options:He,className:"hn-set-w-sm",onChange:o=>w.set(o.target.value)}),e.jsx(y,{size:"sm",variant:"ghost",leftIcon:"volume-2",disabled:w.value==="off",onClick:()=>De(w.value),children:"Preview"})]})}),e.jsx(E,{title:"Notifikasi saat sesi gagal",last:!0,desc:"Kirim notifikasi ketika sesi Claude Code berakhir dengan error.",save:O,children:e.jsx(q,{"aria-label":"Notifikasi gagal",checked:O.value,onChange:o=>O.set(o)})})]}),e.jsxs(I,{eyebrow:"umum",title:"Perilaku sesi","data-setting-card":!0,"data-search":"perilaku sesi full-auto scaffold doc index",children:[e.jsx(E,{title:"Full-auto sebagai default",desc:"Run baru jalan sendiri sampai selesai. Manusia tetap bisa steer / interupsi kapan pun.",save:S,children:e.jsx(q,{"aria-label":"Full-auto sebagai default",checked:S.value,onChange:o=>S.set(o)})}),e.jsx(E,{title:"Auto-scaffold doc index",desc:"Project yang dibuat dari nol otomatis disiapkan indeks dokumennya setelah tujuannya terkunci.",save:D,children:e.jsx(q,{"aria-label":"Auto-scaffold",checked:D.value,onChange:o=>D.set(o)})}),e.jsx(E,{title:"Tampilkan Hanoman (pet)",last:!0,search:"pet hanoman maskot tampil sembunyi",desc:"Pendamping kecil di sudut layar. Pilihan ini hanya berlaku di browser ini. Default: aktif di desktop, mati di tablet & ponsel.",children:e.jsxs(Ja,{"aria-label":"Tampilkan Hanoman (pet)",direction:"row",value:f,onChange:o=>b(Pn[o]??null),children:[e.jsx(fe,{value:"default",label:"Default"}),e.jsx(fe,{value:"tampil",label:"Tampilkan"}),e.jsx(fe,{value:"sembunyi",label:"Sembunyikan"})]})})]}),e.jsxs(I,{eyebrow:"model",title:"Agen & model — default global","data-setting-card":!0,"data-search":"agen model default effort claude codex agen sesi baru",children:[e.jsxs(T,{children:["Default untuk sesi baru; bisa di-override per sesi saat ",e.jsx("b",{children:"Start"}),". Di terminal, ",e.jsx("code",{children:"/model"})," ","mengubahnya kapan saja. Dengan orkestrasi aktif, model ini menjadi model ",e.jsx("b",{children:"orchestrator"}),"; model & effort tiap fase diatur di bagian ",e.jsx("b",{children:"Orkestrasi"})," pada Agen & model. Yang benar-benar dipakai adalah blok milik agen terpilih di bawah — yang satunya tersimpan, menunggu giliran."]}),e.jsx(E,{title:"Agen default",desc:"Sesi backlog masih bisa memilih agen lain saat Start.",save:M,children:e.jsx(K,{size:"sm","aria-label":"Agen default",value:M.value,className:"hn-set-w-sm",options:[{value:"claude",label:Y.claude},{value:"codex",label:Y.codex}],onChange:o=>M.set(o.target.value)})}),e.jsxs("div",{"data-testid":"agent-group-claude",className:"hn-set-group",children:[e.jsxs("div",{className:"hn-set-catalog",children:["Katalog model diperiksa otomatis setiap 5 menit.",Object.entries(r.providers).map(([o,c])=>e.jsxs("div",{children:[o,": ",c.source==="bundled"?"daftar bawaan":c.source==="cache"?"cache terakhir":"dari CLI",c.checkedAt?" · diperiksa "+new Date(c.checkedAt).toLocaleTimeString():"",c.error?" · "+c.error:""]},o))]}),e.jsx(ze,{id:"claude",label:Y.claude,active:A==="claude"}),e.jsx(E,{title:"Model",desc:"Diteruskan apa adanya ke `claude --model`.",save:L,children:e.jsx(K,{size:"sm","aria-label":"Model claude",value:L.value,options:Pe(L.value),className:"hn-set-w-sm",onChange:o=>L.set(o.target.value)})}),e.jsx(E,{title:"Effort",last:!0,desc:"Anggaran berpikir per giliran (`claude --effort`).",save:C,children:e.jsx(K,{size:"sm","aria-label":"Effort claude",value:C.value,options:Oe(L.value),className:"hn-set-w-xs",onChange:o=>C.set(o.target.value)})})]}),e.jsxs("div",{"data-testid":"agent-group-codex",className:"hn-set-group hn-set-group--codex",children:[e.jsx(ze,{id:"codex",label:Y.codex,active:A==="codex"}),e.jsx(ta,{model:R.value,codexVer:l}),e.jsx(E,{title:"Model",desc:"Diteruskan apa adanya ke `codex -m`.",save:R,children:e.jsx(K,{size:"sm","aria-label":"Model codex",value:R.value,className:"hn-set-w-sm",options:Ee(Ve,R.value),onChange:o=>R.set(o.target.value)})}),e.jsx(E,{title:"Effort",last:!0,desc:"Diteruskan ke `codex -c model_reasoning_effort`.",save:B,children:e.jsx(K,{size:"sm","aria-label":"Effort codex",value:B.value,className:"hn-set-w-xs",options:qe(R.value).map(o=>({value:o,label:o})),onChange:o=>B.set(o.target.value)})})]}),e.jsxs("div",{className:"hn-set-inherited-note","data-testid":"session-default-summary",children:["Sesi baru memakai ",e.jsx("b",{children:Y[P.agent]})," · ",e.jsx("code",{children:P.model})," · ",e.jsx("code",{children:P.effort}),"."]})]}),e.jsxs(I,{eyebrow:"goal",title:"Mode goal — sesi backlog","data-setting-card":!0,"data-search":"mode goal kondisi template gate stop",children:[e.jsxs(T,{children:["Sesi backlog lahir dengan gate ",e.jsx("code",{children:"Stop"}),": ia menolak berhenti sampai kondisinya terbukti di transkrip. Interupsi manusia (",e.jsx("code",{children:"Esc"}),") tetap bekerja; melepas gate sepenuhnya = hentikan sesinya. Sesi scheduler mengikuti setelan ini."]}),e.jsx(E,{title:"Aktif sebagai default",desc:"Sesi backlog baru lahir dengan mode goal. Masih bisa dimatikan per sesi saat Start.",save:Q,children:e.jsx(q,{"aria-label":"Mode goal default",checked:Q.value,onChange:o=>Q.set(o)})}),e.jsx(E,{title:"Kondisi (template global)",last:!0,desc:"Kosong = kondisi bawaan hanoman: semua fase tercatat di phase file, plan tak menyisakan task, push sukses.",save:V,children:e.jsx("div",{className:"hn-set-w-field",children:e.jsx(In,{value:V.value,onSet:V.set,onFlush:V.flush})})})]}),e.jsxs(I,{eyebrow:"verifikasi",title:"Scope verifikasi — sesi backlog","data-setting-card":!0,"data-search":"scope verifikasi hanya yang berubah seluruh project uji",children:[e.jsxs(T,{children:["Beberapa sesi berjalan bersamaan di perangkat ini. ",e.jsx("b",{children:"Hanya yang berubah"})," menyuruh sesi menguji hanya berkas yang ia ubah — misalnya dengan ",e.jsx("code",{children:"vitest --changed"})," (uji) dan typecheck per paket — alih-alih seluruh project. Dengan begitu RAM dan CPU tetap tersisa untuk sesi lain. Uji penuh, lint penuh, dan build penuh tetap dijalankan manusia sebelum merge."]}),e.jsx(E,{title:"Scope default",last:!0,desc:"Sesi backlog baru lahir dengan scope ini. Masih bisa diubah per sesi saat Start.",save:X,children:e.jsx(K,{size:"sm","aria-label":"Scope verifikasi default",value:X.value,className:"hn-set-w-md",options:[{value:"changed",label:"Hanya yang berubah"},{value:"full",label:"Seluruh project"}],onChange:o=>X.set(o.target.value)})})]}),e.jsxs(I,{eyebrow:"metode",title:"Metode workflow — sesi backlog","data-setting-card":!0,"data-search":"metode workflow skill direktori plan spec pemasangan",children:[e.jsxs(T,{children:["Metode menentukan ",e.jsx("b",{children:"skill mana yang dimuat di tiap fase"})," dan ",e.jsx("b",{children:"di direktori mana plan & spec ditulis"}),". Fase-fasenya sendiri tak berubah. Gerbang plan memindai direktori SEMUA metode, jadi item yang berpindah metode tak pernah lolos lewat direktori kosong."]}),e.jsx(E,{title:"Metode default",last:!0,desc:"Sesi backlog baru lahir dengan metode ini. Masih bisa diubah per sesi saat Start.",save:G,children:e.jsx(K,{size:"sm","aria-label":"Metode default",className:"hn-set-w-md",value:G.value,options:Le.map(o=>({value:o,label:_e[o].label})),onChange:o=>G.set(o.target.value)})}),m&&e.jsxs("div",{"data-testid":"method-status",className:"hn-set-method-status",children:[Le.map(o=>e.jsxs("div",{className:"hn-set-method",children:[e.jsx("div",{className:"hn-set-method-name",children:_e[o].label}),m.methods.filter(c=>c.method===o).map(c=>e.jsxs("div",{"data-testid":`method-status-${c.method}-${c.agent}`,className:"hn-set-method-row",children:[e.jsx(ee,{tone:c.ready?"ok":"warn",children:c.ready?"siap":"belum siap"}),e.jsxs("div",{className:"hn-set-method-text",children:[e.jsx("b",{children:Y[c.agent]}),!c.ready&&e.jsxs("div",{className:"hn-set-method-missing",children:[c.missingPackages.length>0&&e.jsxs("div",{children:["paket kurang: ",e.jsx("code",{children:c.missingPackages.join(" · ")})]}),c.missingSkills.length>0&&e.jsxs("div",{children:["skill kurang: ",e.jsx("code",{children:c.missingSkills.join(" · ")})]})]})]}),!c.ready&&e.jsx(y,{size:"sm",variant:"ghost",leftIcon:"download",disabled:!s,onClick:()=>p(c),children:"Pasang"})]},c.agent))]},o)),e.jsx(Cn,{children:s?e.jsxs(e.Fragment,{children:["Pemasangan berjalan di ",e.jsx("b",{children:"sesi terminal"})," project ",e.jsx("code",{children:s})," — outputnya bisa ditonton di Terminal. hanoman sendiri tak pernah memasang apa pun."]}):e.jsx(e.Fragment,{children:"Pemasangan butuh satu project yang sudah di-bind ke checkout lokal: perintahnya dijalankan di sesi terminal project itu."})})]})]})]})}function In({value:a,onSet:n,onFlush:t}){return e.jsx("div",{onBlur:()=>t(),children:e.jsx(qa,{value:a,rows:4,mono:!0,"aria-label":"Kondisi mode goal",placeholder:"mis. semua fase tercatat & plan tanpa - [ ]",onChange:l=>n(l.target.value)})})}async function $e(a,n,t,l){var i;const r=((i=a.current())==null?void 0:i.lead)??te,m=s=>(s??te).engine??te.engine;a.update(s=>({...s,lead:{...s.lead??te,engine:{...m(s.lead),...t}}}));try{const s=await N.getLeadConfig(),u=await N.putLeadConfig({...s,engine:{...s.engine??te.engine,...t}});return a.update(h=>({...h,lead:u})),n==null||n(l,"ok","check-circle-2"),!0}catch{return a.update(s=>({...s,lead:r})),n==null||n("Gagal menyimpan setelan lead","err","alert-triangle"),!1}}async function Ue(a,n,t,l){var i;const r=((i=a.current())==null?void 0:i.telegram)??Z,m=s=>s.engine??Z.engine;a.update(s=>({...s,telegram:{...s.telegram??Z,engine:{...m(s.telegram??Z),...t}}}));try{const s=await N.getSettings(),u=s.telegram??Z,h={...s,telegram:{...u,engine:{...u.engine??Z.engine,...t}}},b=await N.putSettings(h);return a.update(f=>({...f,telegram:(b??h).telegram??f.telegram})),n==null||n(l,"ok","check-circle-2"),!0}catch{return a.update(s=>({...s,telegram:r})),n==null||n("Gagal menyimpan setelan operator Telegram","err","alert-triangle"),!1}}function Dn({s:a,store:n,onToast:t,codexVer:l,onNavigate:r}){const m=a.codex??be,i=a.agent??"claude",s={claude:{model:a.model,effort:a.effort},codex:{model:m.model,effort:m.effort}},u=i==="codex"?{agent:"codex",model:m.model,effort:m.effort}:{agent:"claude",model:a.model,effort:a.effort},h=k=>e.jsxs(e.Fragment,{children:[k," ",e.jsx("b",{children:Y[u.agent]})," · ",e.jsx("code",{children:u.model})," · ",e.jsx("code",{children:u.effort}),"."]}),b=a.conflict??Je,f=(k,w)=>n.save({conflict:{...b,...k}},w),j=(a.lead??te).engine??te.engine;return e.jsxs(e.Fragment,{children:[e.jsxs(I,{eyebrow:"override",title:"Override per fungsi","data-setting-card":!0,"data-search":"override per fungsi",children:[e.jsxs(T,{children:["Default global diatur di ",e.jsx("b",{children:"Sesi harian"}),". Tiap fungsi di bawah bisa memakai setelan sendiri; bila sakelarnya mati, ia ikut default global. Agen operator Telegram juga override, tetapi diatur di satu tempat bersama kredensial Telegram."]}),e.jsx("div",{className:"hn-set-inline",children:e.jsx(y,{size:"sm",variant:"ghost",leftIcon:"send",onClick:()=>r("telegram"),children:"Buka Telegram"})})]}),e.jsx(ge,{eyebrow:"konflik",title:"Konflik rebase & merge",desc:"Saat rebase/merge berkonflik, hanoman menyerahkan worktree-nya ke satu sesi agen untuk dibereskan. Pekerjaannya sempit dan tak berfase, jadi ia boleh memakai model & effort yang berbeda dari sesi kerja. Berlaku untuk ketiga pintu integrasi: backlog, git graph, dan PRD.",toggleDesc:"Mati = ikut default global. Hidup = sesi konflik memakai pilihan di bawah.",toggleAria:"Override agen konflik",enabled:b.enabled,onToggle:k=>f({enabled:k},"Setelan konflik"+(k?" · aktif":" · ikut default global")),inheritedTestId:"conflict-inherited",inherited:h("Sesi konflik memakai default global:"),children:e.jsx(Ce,{engine:{enabled:b.enabled,agent:b.agent,model:b.model,effort:b.effort},labels:{agentTitle:"Agen",agentDesc:"Mesin yang membereskan konflik. Bisa beda dari agen sesi kerja.",effortDesc:"Konflik biasanya mekanis — effort rendah sering cukup.",aria:{agent:"Agen konflik",model:"Model konflik",effort:"Effort konflik"},msg:{agent:"Agen konflik",model:"Model konflik",effort:"Effort konflik"}},defaults:s,codexVer:l,save:(k,w)=>f(k,w)})}),e.jsx(ge,{eyebrow:"lead",title:"Agen hanoman-lead",desc:e.jsxs(e.Fragment,{children:["Mesin yang menjalankan agen pemimpin — panggilan sekali-jalan non-interaktif yang membaca docs, plan, kode, dan riwayat git sebelum memutuskan. Berlaku untuk ketiga pintu lead (kontrak, deteksi otomatis, denyut) dan dipakai putusan berikutnya, tanpa restart. Rem darurat, denyut, dan opt-in per project tetap diurus di layar ",e.jsx("b",{children:"Lead"}),"."]}),toggleDesc:"Mati = ikut default global. Hidup = lead memakai pilihan di bawah.",toggleAria:"Override agen lead",enabled:j.enabled,onToggle:k=>$e(n,t,{enabled:k},"Setelan lead"+(k?" · aktif":" · ikut default global")),inheritedTestId:"lead-engine-inherited",inherited:h("hanoman-lead memakai default global:"),children:e.jsx(Ce,{engine:j,labels:{agentTitle:"Runtime",agentDesc:"Mesin yang menjalankan lead. Bisa beda dari agen sesi kerja.",effortDesc:"Putusan lead menuntut membaca bukti — dokumen proyek, ADR, plan, kode, riwayat git. Effort rendah memangkas kedalamannya.",aria:{agent:"Runtime lead",model:"Model lead",effort:"Effort lead"},msg:{agent:"Runtime lead",model:"Model lead",effort:"Effort lead"}},defaults:s,codexVer:l,save:(k,w)=>$e(n,t,k,w)})}),e.jsx(ge,{eyebrow:"portal",title:"Obrolan portal klien",desc:"Permukaan obrolan di portal klien: klien memilih Brainstorming (digali sampai jelas, keluarannya PRD draft untuk Anda review) atau Bertanya (dijawab langsung dari dokumen project). Jatah berlaku per project dan dihitung bulanan; brainstorming dan pertanyaan punya jatah masing-masing.",toggleTitle:"Aktifkan obrolan",toggleDesc:"Mati = klien hanya punya Pekerjaan & Help desk, persis seperti sebelumnya.",toggleAria:"Aktifkan obrolan portal",enabled:(a.portalChat??ke).enabled,onToggle:k=>n.save({portalChat:{...a.portalChat??ke,enabled:k}},"Obrolan portal"+(k?" · aktif":" · mati")),children:e.jsx(Ln,{s:a,store:n,onToast:t})}),e.jsx(on,{orchestration:a.orchestration,onChange:(k,w)=>{n.save({orchestration:k},w)}})]})}function Ln({s:a,store:n,onToast:t}){const l=a.portalChat??ke,r=(s,u)=>n.save({portalChat:{...l,...s}},u),m=H({value:l.model,delayMs:0,save:s=>r({model:s,...Me(s,l.effort)},"Model obrolan portal → "+s)}),i=H({value:l.effort,delayMs:0,save:s=>r({effort:s},"Effort obrolan portal → "+s)});return e.jsxs(e.Fragment,{children:[e.jsx(E,{title:"Jatah brainstorming",desc:"Berapa sesi brainstorming per project tiap bulan. 0 = tertutup.",children:e.jsx(xe,{label:"Jatah brainstorming",value:l.brainstormPerMonth,min:0,max:1e3,placeholder:"mis. 3",onToast:t,onCommit:s=>r({brainstormPerMonth:s},"Jatah brainstorming → "+s)})}),e.jsx(E,{title:"Jatah pertanyaan",desc:"Berapa sesi tanya-jawab per project tiap bulan. 0 = tertutup.",children:e.jsx(xe,{label:"Jatah pertanyaan",value:l.askPerMonth,min:0,max:1e4,placeholder:"mis. 30",onToast:t,onCommit:s=>r({askPerMonth:s},"Jatah pertanyaan → "+s)})}),e.jsx(E,{title:"Model",desc:"Mesin obrolan selalu Claude — gerbang tool yang menjaganya tak ada di runtime lain.",children:e.jsx(K,{size:"sm","aria-label":"Model obrolan portal",value:m.value,className:"hn-set-w-sm",options:Pe(m.value),onChange:s=>m.set(s.target.value)})}),e.jsx(E,{title:"Effort",children:e.jsx(K,{size:"sm","aria-label":"Effort obrolan portal",value:i.value,className:"hn-set-w-xs",options:Oe(m.value),onChange:s=>i.set(s.target.value)})}),e.jsx(E,{title:"Batas waktu satu jawaban",last:!0,desc:"Detik. Lewat dari ini klien menerima kalimat 'coba lagi sebentar', bukan layar menggantung.",children:e.jsx(xe,{label:"Batas waktu obrolan portal",value:l.timeoutSec,min:10,max:900,placeholder:"mis. 120",onToast:t,onCommit:s=>r({timeoutSec:s},"Batas waktu obrolan → "+s)})})]})}const _n={name:"",url:"",events:["*"],enabled:!0,allowPrivate:!1},Rn=Ye.map(a=>({entity:a.entity,label:a.label,types:me.filter(n=>n.entity===a.entity).map(n=>n.type)})),Ke=a=>a?new Date(a).toLocaleString("id-ID",{dateStyle:"short",timeStyle:"medium"}):"—";function Bn({e:a}){return a.enabled?e.jsx(ee,{tone:"ok",children:"aktif"}):a.disabledAt?e.jsx(ee,{tone:"err",children:"dinonaktifkan otomatis"}):e.jsx(ee,{children:"nonaktif"})}function Hn({onToast:a,onOpenDocs:n}={}){const[t,l]=d.useState(null),[r,m]=d.useState(!1),[i,s]=d.useState(null),[u,h]=d.useState(null),[b,f]=d.useState(!1),[g,j]=d.useState({}),[k,w]=d.useState(null),[O,S]=d.useState([]),{confirm:D,dialog:A}=le(),x=d.useCallback(async()=>{try{l((await N.listWebhooks()).endpoints),m(!1)}catch{m(!0)}},[]);d.useEffect(()=>{x()},[x]);const M=async p=>{w(p);try{S((await N.listWebhookDeliveries(p)).items)}catch{S([])}},L=async()=>{if(i){f(!0);try{if(i.id)await N.updateWebhook(i.id,{name:i.name,url:i.url,events:i.events,enabled:i.enabled,allowPrivate:i.allowPrivate}),a==null||a("Endpoint webhook diperbarui");else{const p=await N.createWebhook({name:i.name,url:i.url,events:i.events,enabled:i.enabled,allowPrivate:i.allowPrivate});h(p.secret??null),a==null||a("Endpoint webhook dibuat")}s(null),await x()}catch(p){a==null||a($("menyimpan endpoint",p),"err")}finally{f(!1)}}},C=async p=>{f(!0);try{const P=await N.updateWebhook(p,{rotateSecret:!0});h(P.secret??null),await x()}catch(P){a==null||a(`Gagal merotasi secret: ${P.message}`,"err")}finally{f(!1)}},R=async(p,P)=>{try{await N.updateWebhook(p.id,{enabled:P}),await x()}catch(o){a==null||a($("mengubah status endpoint",o),"err")}},B=async p=>{f(!0);try{const P=await N.testWebhook(p);j(o=>({...o,[p]:P})),await x()}catch(P){j(o=>({...o,[p]:{ok:!1,httpStatus:null,durationMs:0,error:P.message}}))}finally{f(!1)}},Q=async p=>{try{await D({title:`Hapus endpoint "${p.name}"?`,message:"Endpoint ini tak lagi menerima peristiwa dari hanoman.",impact:["Riwayat pengiriman endpoint ini ikut dihapus.","Tindakan ini tak bisa dibatalkan."],confirmLabel:"Hapus endpoint",tone:"danger",icon:"trash-2",run:()=>N.deleteWebhook(p.id)})&&(a==null||a("Endpoint webhook dihapus"),await x())}catch(P){a==null||a($("menghapus endpoint",P),"err")}},V=async p=>{try{await N.retryWebhookDelivery(p),k&&await M(k),await x()}catch(P){a==null||a(`Gagal antre ulang: ${P.message}`,"err")}},X=(p,P)=>s(o=>o&&{...o,events:P?[...new Set([...o.events.filter(c=>c!=="*"),...p])]:o.events.filter(c=>c!=="*"&&!p.includes(c))}),G=(i==null?void 0:i.events.includes("*"))??!1;return e.jsxs(e.Fragment,{children:[e.jsxs(I,{eyebrow:"integrasi",title:"Webhook keluar",children:[e.jsxs("div",{className:"hn-wh-muted hn-wh-mb12",children:["hanoman mengirim ",e.jsx("b",{children:"HTTP POST"})," bertanda tangan ke endpoint yang Anda daftarkan setiap kali sesuatu berubah — backlog dibuat atau berpindah stage, sesi mulai dan selesai, putusan lead terbit, tiket masuk, notifikasi. Pengiriman berjalan di antrean: penerima yang lambat atau mati ",e.jsx("b",{children:"tidak"})," memperlambat hanoman."]}),e.jsxs("div",{className:"hn-wh-actions",children:[e.jsxs(y,{size:"sm",onClick:()=>{s({..._n}),h(null)},children:[e.jsx(re,{name:"plus",size:14})," Tambah endpoint"]}),n&&e.jsxs(y,{size:"sm",variant:"ghost",onClick:n,children:[e.jsx(re,{name:"book-open",size:14})," Dokumentasi webhook"]})]}),r?e.jsx(W,{kind:"error",compact:!0,title:"Gagal memuat endpoint webhook",hint:"Coba muat ulang.",action:()=>void x(),actionLabel:"Coba lagi"}):t===null?e.jsx("div",{className:"hn-wh-muted",children:"Memuat…"}):t.length===0?e.jsx(W,{kind:"empty",compact:!0,title:"Belum ada endpoint webhook",hint:"Daftarkan URL penerima pertama untuk mulai berlangganan peristiwa hanoman."}):e.jsx("div",{className:"hn-wh-col-10",children:t.map(p=>e.jsxs("div",{"data-testid":`webhook-${p.id}`,className:"hn-wh-endpoint",children:[e.jsxs("div",{className:"hn-wh-endpoint-head",children:[e.jsx("div",{className:"hn-wh-name",children:p.name}),e.jsx(Bn,{e:p}),p.pending>0?e.jsxs(ee,{children:[p.pending," mengantre"]}):null,e.jsxs("div",{className:"hn-wh-endpoint-actions",children:[e.jsx(q,{checked:p.enabled,"aria-label":`Aktifkan ${p.name}`,onChange:P=>void R(p,P)}),e.jsx(y,{size:"sm",variant:"ghost",disabled:b,onClick:()=>void B(p.id),children:"Test"}),e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>void M(p.id),children:"Riwayat"}),e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>{h(null),s({id:p.id,name:p.name,url:p.url,events:p.events,enabled:p.enabled,allowPrivate:p.allowPrivate})},children:"Ubah"}),e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>void Q(p),children:"Hapus"})]})]}),e.jsx("div",{className:"hn-wh-url",children:p.url}),e.jsxs("div",{className:"hn-wh-muted hn-wh-mt6",children:["Peristiwa: ",e.jsx("code",{children:p.events.join(", ")})," · secret …",p.secretHint," ·"," ","sukses terakhir ",Ke(p.lastSuccessAt),p.failureStreak>0?` · ${p.failureStreak} gagal beruntun`:""]}),p.disabledReason?e.jsx("div",{className:"hn-wh-muted hn-wh-mt6 hn-wh-err",children:p.disabledReason}):null,g[p.id]?e.jsx("div",{className:"hn-wh-muted hn-wh-mt6",children:g[p.id].ok?`Test berhasil — HTTP ${g[p.id].httpStatus} · ${g[p.id].durationMs} ms`:`Test gagal — ${g[p.id].error}`}):null]},p.id))})]}),u?e.jsxs(I,{eyebrow:"secret",title:"Salin sekarang — secret tak ditampilkan lagi",children:[e.jsx(se,{tone:"brass",children:e.jsx("div",{className:"hn-wh-secret",children:u})}),e.jsxs("div",{className:"hn-wh-row hn-wh-mt10",children:[e.jsx(y,{size:"sm",onClick:()=>{var p;return void((p=navigator.clipboard)==null?void 0:p.writeText(u))},children:"Salin secret"}),e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>h(null),children:"Tutup"})]})]}):null,i?e.jsx(I,{eyebrow:i.id?"ubah":"tambah",title:i.id?"Ubah endpoint":"Endpoint baru",children:e.jsxs("div",{className:"hn-wh-col-12",children:[e.jsx(ae,{label:"Nama",children:e.jsx(J,{value:i.name,placeholder:"mis. Dashboard internal",onChange:p=>s({...i,name:p.target.value})})}),e.jsx(ae,{label:"URL tujuan",children:e.jsx(J,{value:i.url,placeholder:"https://contoh.id/hanoman-webhook",onChange:p=>s({...i,url:p.target.value})})}),e.jsxs("div",{children:[e.jsx("div",{className:"hn-wh-label",children:"Peristiwa yang dikirim"}),e.jsx(de,{checked:G,label:"Semua peristiwa",onChange:p=>s({...i,events:p?["*"]:[]})}),G?null:e.jsxs("div",{className:"hn-wh-tree",children:[Rn.map(p=>e.jsxs("div",{children:[e.jsx(de,{checked:p.types.every(P=>i.events.includes(P)),label:p.label,onChange:P=>X(p.types,P)}),e.jsx("div",{className:"hn-wh-family-types",children:p.types.map(P=>e.jsx(de,{checked:i.events.includes(P),label:P,onChange:o=>s({...i,events:o?[...new Set([...i.events.filter(c=>c!=="*"),P])]:i.events.filter(c=>c!==P&&c!=="*")})},P))})]},p.entity)),e.jsxs("div",{className:"hn-wh-muted",children:[e.jsx("code",{children:Va})," selalu terkirim saat tombol Test ditekan, apa pun langganannya."]})]})]}),e.jsx(de,{checked:i.allowPrivate,label:"Izinkan alamat internal / loopback",onChange:p=>s({...i,allowPrivate:p})}),e.jsx("div",{className:"hn-wh-muted",children:"Biarkan mati kecuali penerima memang berjalan di mesin/jaringan yang sama. Menyalakannya membuka jalan ke layanan internal yang tak pernah dimaksudkan terekspos."}),e.jsx(de,{checked:i.enabled,label:"Aktif",onChange:p=>s({...i,enabled:p})}),e.jsxs("div",{className:"hn-wh-row",children:[e.jsx(y,{size:"sm",disabled:b||!i.name||!i.url||i.events.length===0,onClick:()=>void L(),children:"Simpan"}),e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>s(null),children:"Batal"}),i.id?e.jsx(y,{size:"sm",variant:"ghost",disabled:b,onClick:()=>void C(i.id),children:"Rotasi secret"}):null]})]})}):null,k?e.jsxs(I,{eyebrow:"riwayat",title:"Riwayat pengiriman",children:[e.jsx("div",{className:"hn-wh-history-head",children:e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>w(null),children:"Tutup riwayat"})}),O.length===0?e.jsx("div",{className:"hn-wh-muted",children:"Belum ada pengiriman."}):e.jsx("div",{className:"hn-local-overflow",children:e.jsxs("table",{className:"hn-wh-table hn-wh-table--full",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"hn-wh-thead",children:[e.jsx("th",{className:"hn-wh-cell",children:"Waktu"}),e.jsx("th",{className:"hn-wh-cell",children:"Jenis"}),e.jsx("th",{className:"hn-wh-cell",children:"Status"}),e.jsx("th",{className:"hn-wh-cell",children:"HTTP"}),e.jsx("th",{className:"hn-wh-cell",children:"Percobaan"}),e.jsx("th",{className:"hn-wh-cell",children:"Galat"}),e.jsx("th",{})]})}),e.jsx("tbody",{children:O.map(p=>e.jsxs("tr",{className:"hn-wh-tr",children:[e.jsx("td",{className:"hn-wh-cell hn-wh-cell--nowrap",children:Ke(p.createdAt)}),e.jsx("td",{className:"hn-wh-cell hn-wh-cell--mono12",children:p.eventType}),e.jsx("td",{className:"hn-wh-cell",children:p.status}),e.jsx("td",{className:"hn-wh-cell",children:p.httpStatus??"—"}),e.jsx("td",{className:"hn-wh-cell",children:`${p.attempt} / ${p.maxAttempts}`}),e.jsx("td",{className:"hn-wh-cell hn-wh-cell--muted",children:p.error??"—"}),e.jsx("td",{className:"hn-wh-cell",children:p.status==="failed"||p.status==="dropped"?e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>void V(p.id),children:"Antre ulang"}):null})]},p.id))})]})})]}):null,A]})}function ve({text:a,label:n="Salin"}){const[t,l]=d.useState(!1);return e.jsxs("div",{className:"hn-wh-copy",children:[e.jsx("pre",{className:"hn-wh-code",children:a}),e.jsx("div",{className:"hn-wh-mt6",children:e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>{var r;(r=navigator.clipboard)==null||r.writeText(a),l(!0),setTimeout(()=>l(!1),1500)},children:t?"Tersalin":n})})]})}const Fn=`// Node.js (Express) — verifikasi tanda tangan webhook hanoman
1
+ import{bm as ra,bn as da,bo as ca,bp as oa,bq as ua,br as ha,bs as ma,bt as ga,bu as ka,bv as pa,bw as ba,bx as fa,by as ja,bz as xa,bA as va,bB as ya,bC as wa,bD as Sa,bE as Na,bF as Ca,bG as Ea,bH as Aa,bI as Oa,bJ as Pa,bK as Ma,bL as Ia,bM as Da,bN as La,bO as _a,bP as ke,bQ as Z,bR as te,bS as Je,bT as Ra,a6 as be,bU as Ba,ba as Ha,ad as Fa,bV as Ee,bW as za,bX as $a,h as N,i as $,j as e,f as J,B as y,aH as I,b1 as q,ac as we,g as K,bY as qe,aa as Ua,ab as Ka,bZ as Ve,b_ as Ta,b$ as Ga,c0 as Wa,c1 as De,bb as Ja,aX as fe,c2 as Le,c3 as _e,n as ee,H as qa,d as le,I as re,m as W,C as se,e as ae,aI as de,c4 as Va,c5 as Ye,c6 as me,c7 as Qe,c8 as Ya,c9 as oe,ca as Ae,cb as Qa,cc as Re,cd as Xa,ce as Za,cf as en,cg as pe,$ as an,b as Xe,ch as nn,ci as tn,cj as sn,ag as Se,q as ln,D as rn,ck as dn,cl as cn}from"./index-DYWU10xI.js";import{R as d}from"./react-DfGhg7ZW.js";import"./markdown-CWEY34jk.js";import{r as Ze,O as on}from"./settings-rebase-3Z15zUKI.js";import{D as un}from"./DocPreviewModal-CYdmHEb_.js";import"./xterm-3VOAfa_q.js";/* empty css */const hn=[...ra,...da,...ca,...oa,...ua,...ha,...ma,...ga,...ka,...pa,...ba,...fa,...ja,...xa,...va,...ya,...wa,...Sa,...Na,...Ca,...Ea,...Aa,...Oa],mn=2,Y=Pa,ie=[{key:"sesi",label:"Sesi harian",icon:"bell",sections:[{key:"sesi",label:"Sesi harian",icon:"bell",keywords:"notifikasi suara selesai keputusan gagal full-auto scaffold agen model default effort goal kondisi verifikasi scope metode workflow"}]},{key:"model",label:"Agen & model",icon:"cpu",sections:[{key:"model",label:"Agen & model",icon:"cpu",keywords:"override konflik rebase merge lead operator obrolan portal jatah orkestrasi fase effort model runtime"}]},{key:"integrasi",label:"Integrasi & akses",icon:"webhook",sections:[{key:"agent",label:"Akses AI Agent",icon:"bot",keywords:"token agent capability mcp master switch"},{key:"telegram",label:"Telegram",icon:"send",keywords:"bot token chat allowlist gateway operator agen progress uji koneksi"},{key:"webhook",label:"Webhook",icon:"webhook",keywords:"endpoint secret peristiwa pengiriman dokumentasi"},{key:"akses-klien",label:"Akses klien",icon:"user-check",keywords:"portal klien grant lihat tulis mulai sesi"},{key:"perangkat",label:"Perangkat",icon:"key-round",keywords:"token perangkat sinkron server pusat"},{key:"kendali-jarak-jauh",label:"Kendali jarak jauh",icon:"shield",keywords:"izin server pusat perangkat kendali"}]},{key:"lanjutan",label:"Lanjutan",icon:"sliders-horizontal",collapsible:!0,sections:[{key:"akun",label:"Akun",icon:"user-round",keywords:"password email logout ganti masuk"},{key:"users",label:"Pengguna",icon:"users",keywords:"undang hapus pengguna email password"},{key:"setup",label:"Setup awal",icon:"shield",keywords:"peruntukan hardening setup ulang"},{key:"konfigurasi",label:"Konfigurasi",icon:"sliders-horizontal",keywords:"env rahasia bootstrap sinkron runtime variabel"},{key:"aktivitas",label:"Log aktivitas",icon:"activity",keywords:"log sesi project hasil commit pr hapus"},{key:"custom-agent",label:"Custom agent",icon:"bot",keywords:"persona agen mention katalog"},{key:"zona-bahaya",label:"Zona bahaya",icon:"alert-triangle",keywords:"reset default kembalikan semua setelan"}]}],Ne="sesi",gn=ie.flatMap(a=>a.sections.map(n=>n.key)),ea=a=>gn.includes(a),kn=new Map([["umum","sesi"],["orkestrasi","model"]]);function Be(a){if(typeof a!="string")return Ne;const n=kn.get(a)??a;return ea(n)?n:Ne}function aa(a){return ie.find(n=>n.sections.some(t=>t.key===a))??ie[0]}function pn(a){return ie.flatMap(t=>t.sections).find(t=>t.key===a)??ie[0].sections[0]}function na(a){const n=aa(a);return n.sections.length>1?`${n.label} · ${pn(a).label}`:n.label}function bn(a){const n=new URLSearchParams(a.replace(/^#/,"")).get("bagian");return n&&ea(n)?n:null}const Oe=a=>$a(a).map(n=>({value:n,label:n==="xhigh"?"x-high":n})),Pe=a=>Ee(za,a),Me=(a,n)=>{const t=Fa(a,n);return t===n?{}:{effort:t}},He=[{value:"blip",label:"Blip · 0.1s"},{value:"pop",label:"Pop · 0.1s"},{value:"short",label:"Short · 0.15s"},{value:"ping",label:"Ping · 0.2s"},{value:"coin",label:"Coin · 0.3s"},{value:"alert",label:"Alert · 0.3s"},{value:"medium",label:"Medium · 0.4s"},{value:"chime",label:"Chime · 0.4s"},{value:"success",label:"Success · 0.4s"},{value:"bell",label:"Bell · 0.5s"},{value:"marimba",label:"Marimba · 0.6s"},{value:"long",label:"Long · 0.8s"},{value:"fanfare",label:"Fanfare · 0.9s"},{value:"off",label:"Senyap"}],fn={model:"sonnet",effort:"medium",autoDefault:!0,autoScaffold:!0,notifyFail:!0,notifyDone:!0,notifySound:"short",notifyDecision:!0,notifyDecisionSound:"alert",agentAccessEnabled:!1,scheduler:Ha,goal:Ba,agent:"claude",codex:be,verifyScope:"changed",method:Ra,conflict:Je,lead:te,telegram:Z,portalChat:ke,orchestration:_a,remoteControl:La,logShipping:Da,logRetention:Ia,builtinAgents:{},builtinAgentPolicies:{},builtinRuntimeDefaults:Ma},Fe=()=>{};function jn(a){const[n,t]=d.useState(null),[l,r]=d.useState(!1),m=d.useRef(null),i=d.useRef(a);i.current=a;const s=d.useRef(Promise.resolve()),u=d.useCallback(k=>{m.current=k,t(k)},[]),h=d.useCallback(()=>{r(!1),u(null),N.getSettings().then(k=>u(k),()=>r(!0))},[u]);d.useEffect(()=>{h()},[h]);const b=d.useCallback((k,w,O,S)=>{const D=m.current;if(!D)return Promise.resolve(!1);const A=Object.keys(k).filter(M=>JSON.stringify(k[M])!==JSON.stringify(D[M]));u(k);const x=s.current.then(async()=>{const M=await N.getSettings().catch(()=>{});await N.putSettings(Ze(D,k,M))});return s.current=x.then(Fe,Fe),x.then(()=>{var M;return w&&((M=i.current)==null||M.call(i,w,O||"ok",S||"check-circle-2")),!0},M=>{var C;const L=Object.fromEntries(A.map(R=>[R,D[R]]));return u({...m.current??D,...L}),(C=i.current)==null||C.call(i,$("menyimpan pengaturan",M),"err","alert-triangle"),!1})},[u]),f=d.useCallback((k,w)=>{const O=m.current;return O?b({...O,...k},w):Promise.resolve(!1)},[b]),g=d.useCallback(k=>{const w=m.current;w&&u(k(w))},[u]),j=d.useCallback(()=>m.current,[]);return{s:n,failed:l,load:h,persist:b,save:f,update:g,current:j}}function xn(a){const n=a.trim().toLowerCase();return n?ie.flatMap(t=>t.sections).filter(t=>`${t.label} ${t.keywords}`.toLowerCase().includes(n)).map(t=>({key:t.key,path:na(t.key)})):[]}const je=(a,n)=>(a??"").toLowerCase().includes(n);function vn(a,n){if(!a)return 0;const t=n.trim().toLowerCase(),l=Array.from(a.querySelectorAll("[data-setting-row]")),r=Array.from(a.querySelectorAll("[data-setting-card]")),m=s=>{var u;return((u=s.parentElement)==null?void 0:u.closest("[data-setting-card]"))??null};let i=0;return t?(r.forEach(s=>{const u=je(s.getAttribute("data-search"),t),h=Array.from(s.querySelectorAll("[data-setting-row]")).filter(f=>m(f)===s);if(h.length===0){s.hidden=!u,u&&i++;return}let b=!1;h.forEach(f=>{const g=u||je(f.getAttribute("data-search"),t);f.hidden=!g,g&&(b=!0,i++)}),s.hidden=!(u||b)}),l.forEach(s=>{if(m(s))return;const u=je(s.getAttribute("data-search"),t);s.hidden=!u,u&&i++}),i):(l.forEach(s=>{s.hidden=!1}),r.forEach(s=>{s.hidden=!1}),l.length+r.filter(s=>!s.querySelector("[data-setting-row]")).length)}function yn(a,n,t){const[l,r]=d.useState(0);return d.useLayoutEffect(()=>{const m=a.current,i=()=>r(vn(m,n));if(i(),!m||typeof MutationObserver>"u")return;const s=new MutationObserver(i);return s.observe(m,{childList:!0,subtree:!0}),()=>s.disconnect()},[n,t,a]),l}function wn({value:a,onChange:n,hits:t,onPick:l}){return e.jsxs("div",{className:"hn-set-search",role:"search",children:[e.jsx(J,{type:"search","aria-label":"Cari pengaturan",placeholder:"mis. notifikasi, telegram, token",value:a,leftIcon:"search",className:"hn-set-full",onChange:r=>n(r.target.value),onKeyDown:r=>{r.key==="Escape"&&a&&n("")}}),a.trim()!==""&&t.length>0&&e.jsx("ul",{className:"hn-set-search-hits","aria-label":"Bagian yang cocok",children:t.map(r=>e.jsx("li",{children:e.jsx("button",{type:"button",className:"hn-set-search-hit",onClick:()=>l(r.key),children:r.path})},r.key))})]})}function Sn({save:a}){if(a.status==="idle")return null;if(a.status==="error")return e.jsxs("span",{className:"hn-set-save hn-set-save--err",role:"status","data-testid":"save-status",children:["Gagal — coba lagi",e.jsx(y,{size:"sm",variant:"ghost",leftIcon:"refresh-cw",onClick:a.retry,children:"Coba lagi"})]});const n=a.status==="saved"?"Tersimpan":"Menyimpan…",t=a.status==="saved"?"hn-set-save--ok":"hn-set-save--pending";return e.jsx("span",{className:`hn-set-save ${t}`,role:"status","data-testid":"save-status",children:n})}function Nn({text:a}){return e.jsx(e.Fragment,{children:a.split(/`([^`]+)`/).map((n,t)=>t%2===1?e.jsx("code",{className:"hn-set-mono hn-set-codeinline",children:n},t):n)})}function E({title:a,desc:n,children:t,last:l,save:r,search:m}){return e.jsxs("div",{className:`hn-setting-row hn-set-row${l?" hn-set-row--last":""}`,"data-setting-row":!0,"data-search":`${a} ${n??""} ${m??""}`,children:[e.jsxs("div",{className:"hn-set-row-text",children:[e.jsx("div",{className:"hn-set-row-title",children:a}),n&&e.jsx("div",{className:"hn-set-row-desc",children:e.jsx(Nn,{text:n})}),r&&e.jsx(Sn,{save:r})]}),e.jsx("div",{className:"hn-setting-control hn-set-row-control",children:t})]})}function ue({id:a,text:n}){return n?e.jsx("div",{id:a,className:"hn-set-hint",children:n}):null}function Cn({children:a}){return e.jsx("div",{className:"hn-set-note",children:a})}function T({children:a}){return e.jsx("div",{className:"hn-set-prose",children:a})}const En=400,An=1800;function H(a){const n=d.useRef(a);n.current=a;const[t,l]=d.useState(null),r=d.useRef(a.value),[m,i]=d.useState("idle"),s=d.useRef(0),u=d.useRef(null),h=d.useRef(null),b=d.useRef(null),f=d.useRef(null),g=d.useRef(!1),j=d.useRef(0),k=()=>{h.current&&(clearTimeout(h.current),h.current=null)},w=()=>{b.current&&(clearTimeout(b.current),b.current=null)},O=(x,M)=>{if(k(),j.current===0&&Object.is(x,n.current.value)){M===s.current&&(u.current=null,l(null),i("idle"));return}j.current++,i("saving"),Promise.resolve(n.current.save(x)).then(L=>{j.current--,!(!g.current||M!==s.current)&&(u.current=null,L?(f.current=null,l({v:x,settled:!0}),i("saved"),w(),b.current=setTimeout(()=>{b.current=null,g.current&&i(C=>C==="saved"?"idle":C)},An)):(f.current={v:x},l(null),i("error")))})},S=x=>{const M=++s.current;u.current={v:x,id:M},f.current=null,w(),l({v:x,settled:!1}),k();const L=n.current.delayMs??En;if(L<=0){O(x,M);return}i("pending"),h.current=setTimeout(()=>{h.current=null;const C=u.current;C&&O(C.v,C.id)},L)};d.useEffect(()=>{Object.is(r.current,a.value)||(r.current=a.value,l(x=>x&&x.settled?null:x))},[a.value]);const D=()=>{const x=u.current;!h.current||!x||O(x.v,x.id)},A=()=>{const x=f.current;x&&S(x.v)};return d.useEffect(()=>(g.current=!0,()=>{g.current=!1;const x=u.current;h.current&&x&&(k(),Promise.resolve(n.current.save(x.v))),w()}),[]),{value:t?t.v:a.value,set:S,flush:D,status:m,retry:A}}const On=a=>Ee(Ve,a);function ta({model:a,codexVer:n}){var l;const t=(n==null?void 0:n.version)??null;return Ua(a,t)?e.jsxs("div",{"data-testid":"codex-version-note",className:"hn-set-codex-note",children:["Codex CLI terpasang ",e.jsx("b",{children:t}),", sedangkan ",e.jsx("b",{children:a})," butuh ",e.jsx("b",{children:(l=Ka(a))==null?void 0:l.minClient}),". Sesi tetap boleh dijalankan, tapi modelnya belum tentu dikenali CLI ini. Perbarui dengan ",e.jsx("code",{children:"npm i -g @openai/codex@latest"}),"."]}):null}function ze({id:a,label:n,active:t}){return e.jsxs("div",{className:"hn-set-agent-head",children:[e.jsx("div",{className:"hn-set-agent-name",children:n}),e.jsx("span",{"data-testid":`agent-badge-${a}`,className:`hn-set-agent-badge${t?" hn-set-agent-badge--on":""}`,children:t?"dipakai sesi baru":"tidak dipakai sekarang"})]})}function Ce({engine:a,labels:n,defaults:t,codexVer:l,save:r}){const m=H({value:a.agent,delayMs:0,save:h=>{const b=h==="codex"?t.codex:t.claude;return r({agent:h,model:b.model,effort:h==="codex"?we(b.model,b.effort):b.effort},`${n.msg.agent} → ${h}`)}}),i=H({value:a.model,delayMs:0,save:h=>r({model:h,...a.agent==="codex"?{effort:we(h,a.effort)}:Me(h,a.effort)},`${n.msg.model} → ${h}`)}),s=H({value:a.effort,delayMs:0,save:h=>r({effort:h},`${n.msg.effort} → ${h}`)}),u=m.value==="codex";return e.jsxs(e.Fragment,{children:[e.jsx(E,{title:n.agentTitle,desc:n.agentDesc,save:m,children:e.jsx(K,{size:"sm","aria-label":n.aria.agent,value:m.value,className:"hn-set-w-sm",options:[{value:"claude",label:Y.claude},{value:"codex",label:Y.codex}],onChange:h=>m.set(h.target.value)})}),u&&e.jsx(ta,{model:i.value,codexVer:l}),e.jsx(E,{title:"Model",save:i,children:e.jsx(K,{size:"sm","aria-label":n.aria.model,value:i.value,className:"hn-set-w-sm",options:u?On(i.value):Pe(i.value),onChange:h=>i.set(h.target.value)})}),e.jsx(E,{title:"Effort",desc:n.effortDesc,last:!0,save:s,children:e.jsx(K,{size:"sm","aria-label":n.aria.effort,value:s.value,className:"hn-set-w-xs",options:u?qe(i.value).map(h=>({value:h,label:h})):Oe(i.value),onChange:h=>s.set(h.target.value)})})]})}function ge({eyebrow:a,title:n,desc:t,toggleTitle:l="Pakai setelan sendiri",toggleDesc:r,toggleAria:m,enabled:i,onToggle:s,inherited:u,inheritedTestId:h,children:b}){const f=H({value:i,delayMs:0,save:g=>s(g)});return e.jsxs(I,{eyebrow:a,title:n,"data-setting-card":!0,"data-search":`${n} ${a}`,children:[e.jsx(T,{children:t}),e.jsx(E,{title:l,desc:r,save:f,last:!f.value,children:e.jsx(q,{"aria-label":m,checked:f.value,onChange:g=>f.set(g)})}),f.value?b:u?e.jsx("div",{"data-testid":h,className:"hn-set-inherited",children:u}):null]})}function xe({label:a,value:n,min:t,max:l,placeholder:r,width:m,onCommit:i,onToast:s}){const[u,h]=d.useState(String(n));d.useEffect(()=>h(String(n)),[n]);const b=H({value:n,delayMs:0,save:g=>i(g)}),f=()=>{const g=u.trim(),j=g===""?NaN:Math.floor(Number(g));if(!Number.isFinite(j)||j<t){s==null||s(`${a}: isi angka ${t} atau lebih. Nilai sebelumnya dipertahankan.`,"warn","alert-triangle"),h(String(n));return}const k=Math.min(j,l);k!==j&&(s==null||s(`${a} dibatasi ke ${l}.`,"warn","alert-triangle"),h(String(k))),k!==n&&b.set(k)};return e.jsx(J,{"aria-label":a,type:"number",min:t,max:l,placeholder:r,className:m??"hn-set-w-xs",value:u,onChange:g=>h(g.target.value),onBlur:f,onKeyDown:g=>{g.key==="Enter"&&f()}})}const Pn={default:null,tampil:!0,sembunyi:!1};function ce(a,n,t,l){return H({value:t,delayMs:0,save:r=>a.save({[n]:r},l+(r?" · aktif":" · nonaktif"))})}function Mn({s:a,store:n,onToast:t,codexVer:l}){const r=Ta(),[m,i]=d.useState(null),[s,u]=d.useState("");d.useEffect(()=>{N.getMethodStatus().then(i).catch(()=>i(null)),N.listProjects({limit:100}).then(o=>u(c=>{var _;return c||(((_=o.items.find(z=>z.binding??z.repoDir))==null?void 0:_.id)??"")})).catch(o=>t==null?void 0:t($("memuat daftar project",o),"err","alert-triangle"))},[]);const[h,b]=Ga(),f=h===null?"default":h?"tampil":"sembunyi",g=ce(n,"notifyDone",a.notifyDone,"Notifikasi backlog selesai"),j=H({value:a.notifySound,delayMs:0,save:o=>n.save({notifySound:o},"Sound → "+o)}),k=ce(n,"notifyDecision",a.notifyDecision,"Notifikasi keputusan"),w=H({value:a.notifyDecisionSound,delayMs:0,save:o=>n.save({notifyDecisionSound:o},"Sound keputusan → "+o)}),O=ce(n,"notifyFail",a.notifyFail,"Notifikasi gagal"),S=ce(n,"autoDefault",a.autoDefault,"Full-auto default"),D=ce(n,"autoScaffold",a.autoScaffold,"Auto-scaffold"),A=a.agent??"claude",x=a.codex??be,M=H({value:A,delayMs:0,save:o=>n.save({agent:o},"Agen → "+o)}),L=H({value:a.model,delayMs:0,save:o=>n.save({model:o,...Me(o,a.effort)},"Model claude → "+o)}),C=H({value:a.effort,delayMs:0,save:o=>n.save({effort:o},"Effort claude → "+o)}),R=H({value:x.model,delayMs:0,save:o=>n.save({codex:{model:o,effort:we(o,x.effort)}},"Model codex → "+o)}),B=H({value:x.effort,delayMs:0,save:o=>n.save({codex:{...x,effort:o}},"Effort codex → "+o)}),Q=H({value:a.goal.enabled,delayMs:0,save:o=>n.save({goal:{...a.goal,enabled:o}},"Mode goal"+(o?" · aktif":" · nonaktif"))}),V=H({value:a.goal.condition,save:o=>n.save({goal:{...a.goal,condition:o}},"Kondisi mode goal disimpan")}),X=H({value:a.verifyScope??"changed",delayMs:0,save:o=>n.save({verifyScope:o},"Scope verifikasi → "+o)}),G=H({value:Wa(a.method).id,delayMs:0,save:o=>n.save({method:o},"Metode → "+o)}),p=async o=>{if(s)try{await N.createShell(s,{method:o.method,agent:o.agent}),t==null||t(`Pemasangan ${o.label} · ${Y[o.agent]} berjalan di Terminal`,"ok","terminal")}catch{t==null||t("Gagal membuka sesi terminal pemasangan","err","alert-triangle")}},P=A==="codex"?{agent:"codex",model:x.model,effort:x.effort}:{agent:"claude",model:a.model,effort:a.effort};return e.jsxs(e.Fragment,{children:[e.jsxs(I,{eyebrow:"sesi",title:"Sesi & notifikasi","data-setting-card":!0,"data-search":"sesi notifikasi suara",children:[e.jsx(E,{title:"Notifikasi backlog selesai",desc:"Toast + sound saat sebuah backlog mencapai stage done. Daftar lonceng tetap terisi meski dimatikan.",save:g,children:e.jsx(q,{"aria-label":"Notifikasi backlog selesai",checked:g.value,onChange:o=>g.set(o)})}),e.jsx(E,{title:"Sound notifikasi",desc:"Durasi nada saat backlog selesai.",save:j,children:e.jsxs("div",{className:"hn-set-inline",children:[e.jsx(K,{size:"sm","aria-label":"Sound notifikasi",value:j.value,options:He,className:"hn-set-w-sm",onChange:o=>j.set(o.target.value)}),e.jsx(y,{size:"sm",variant:"ghost",leftIcon:"volume-2",disabled:j.value==="off",onClick:()=>De(j.value),children:"Preview"})]})}),e.jsx(E,{title:"Notifikasi butuh keputusan",desc:"Toast + sound saat sesi Claude berhenti menunggu keputusanmu. Nada sengaja beda dari selesai.",save:k,children:e.jsx(q,{"aria-label":"Notifikasi keputusan",checked:k.value,onChange:o=>k.set(o)})}),e.jsx(E,{title:"Sound keputusan",desc:"Nada saat sebuah sesi menunggu keputusan.",save:w,children:e.jsxs("div",{className:"hn-set-inline",children:[e.jsx(K,{size:"sm","aria-label":"Sound keputusan",value:w.value,options:He,className:"hn-set-w-sm",onChange:o=>w.set(o.target.value)}),e.jsx(y,{size:"sm",variant:"ghost",leftIcon:"volume-2",disabled:w.value==="off",onClick:()=>De(w.value),children:"Preview"})]})}),e.jsx(E,{title:"Notifikasi saat sesi gagal",last:!0,desc:"Kirim notifikasi ketika sesi Claude Code berakhir dengan error.",save:O,children:e.jsx(q,{"aria-label":"Notifikasi gagal",checked:O.value,onChange:o=>O.set(o)})})]}),e.jsxs(I,{eyebrow:"umum",title:"Perilaku sesi","data-setting-card":!0,"data-search":"perilaku sesi full-auto scaffold doc index",children:[e.jsx(E,{title:"Full-auto sebagai default",desc:"Run baru jalan sendiri sampai selesai. Manusia tetap bisa steer / interupsi kapan pun.",save:S,children:e.jsx(q,{"aria-label":"Full-auto sebagai default",checked:S.value,onChange:o=>S.set(o)})}),e.jsx(E,{title:"Auto-scaffold doc index",desc:"Project yang dibuat dari nol otomatis disiapkan indeks dokumennya setelah tujuannya terkunci.",save:D,children:e.jsx(q,{"aria-label":"Auto-scaffold",checked:D.value,onChange:o=>D.set(o)})}),e.jsx(E,{title:"Tampilkan Hanoman (pet)",last:!0,search:"pet hanoman maskot tampil sembunyi",desc:"Pendamping kecil di sudut layar. Pilihan ini hanya berlaku di browser ini. Default: aktif di desktop, mati di tablet & ponsel.",children:e.jsxs(Ja,{"aria-label":"Tampilkan Hanoman (pet)",direction:"row",value:f,onChange:o=>b(Pn[o]??null),children:[e.jsx(fe,{value:"default",label:"Default"}),e.jsx(fe,{value:"tampil",label:"Tampilkan"}),e.jsx(fe,{value:"sembunyi",label:"Sembunyikan"})]})})]}),e.jsxs(I,{eyebrow:"model",title:"Agen & model — default global","data-setting-card":!0,"data-search":"agen model default effort claude codex agen sesi baru",children:[e.jsxs(T,{children:["Default untuk sesi baru; bisa di-override per sesi saat ",e.jsx("b",{children:"Start"}),". Di terminal, ",e.jsx("code",{children:"/model"})," ","mengubahnya kapan saja. Dengan orkestrasi aktif, model ini menjadi model ",e.jsx("b",{children:"orchestrator"}),"; model & effort tiap fase diatur di bagian ",e.jsx("b",{children:"Orkestrasi"})," pada Agen & model. Yang benar-benar dipakai adalah blok milik agen terpilih di bawah — yang satunya tersimpan, menunggu giliran."]}),e.jsx(E,{title:"Agen default",desc:"Sesi backlog masih bisa memilih agen lain saat Start.",save:M,children:e.jsx(K,{size:"sm","aria-label":"Agen default",value:M.value,className:"hn-set-w-sm",options:[{value:"claude",label:Y.claude},{value:"codex",label:Y.codex}],onChange:o=>M.set(o.target.value)})}),e.jsxs("div",{"data-testid":"agent-group-claude",className:"hn-set-group",children:[e.jsxs("div",{className:"hn-set-catalog",children:["Katalog model diperiksa otomatis setiap 5 menit.",Object.entries(r.providers).map(([o,c])=>e.jsxs("div",{children:[o,": ",c.source==="bundled"?"daftar bawaan":c.source==="cache"?"cache terakhir":"dari CLI",c.checkedAt?" · diperiksa "+new Date(c.checkedAt).toLocaleTimeString():"",c.error?" · "+c.error:""]},o))]}),e.jsx(ze,{id:"claude",label:Y.claude,active:A==="claude"}),e.jsx(E,{title:"Model",desc:"Diteruskan apa adanya ke `claude --model`.",save:L,children:e.jsx(K,{size:"sm","aria-label":"Model claude",value:L.value,options:Pe(L.value),className:"hn-set-w-sm",onChange:o=>L.set(o.target.value)})}),e.jsx(E,{title:"Effort",last:!0,desc:"Anggaran berpikir per giliran (`claude --effort`).",save:C,children:e.jsx(K,{size:"sm","aria-label":"Effort claude",value:C.value,options:Oe(L.value),className:"hn-set-w-xs",onChange:o=>C.set(o.target.value)})})]}),e.jsxs("div",{"data-testid":"agent-group-codex",className:"hn-set-group hn-set-group--codex",children:[e.jsx(ze,{id:"codex",label:Y.codex,active:A==="codex"}),e.jsx(ta,{model:R.value,codexVer:l}),e.jsx(E,{title:"Model",desc:"Diteruskan apa adanya ke `codex -m`.",save:R,children:e.jsx(K,{size:"sm","aria-label":"Model codex",value:R.value,className:"hn-set-w-sm",options:Ee(Ve,R.value),onChange:o=>R.set(o.target.value)})}),e.jsx(E,{title:"Effort",last:!0,desc:"Diteruskan ke `codex -c model_reasoning_effort`.",save:B,children:e.jsx(K,{size:"sm","aria-label":"Effort codex",value:B.value,className:"hn-set-w-xs",options:qe(R.value).map(o=>({value:o,label:o})),onChange:o=>B.set(o.target.value)})})]}),e.jsxs("div",{className:"hn-set-inherited-note","data-testid":"session-default-summary",children:["Sesi baru memakai ",e.jsx("b",{children:Y[P.agent]})," · ",e.jsx("code",{children:P.model})," · ",e.jsx("code",{children:P.effort}),"."]})]}),e.jsxs(I,{eyebrow:"goal",title:"Mode goal — sesi backlog","data-setting-card":!0,"data-search":"mode goal kondisi template gate stop",children:[e.jsxs(T,{children:["Sesi backlog lahir dengan gate ",e.jsx("code",{children:"Stop"}),": ia menolak berhenti sampai kondisinya terbukti di transkrip. Interupsi manusia (",e.jsx("code",{children:"Esc"}),") tetap bekerja; melepas gate sepenuhnya = hentikan sesinya. Sesi scheduler mengikuti setelan ini."]}),e.jsx(E,{title:"Aktif sebagai default",desc:"Sesi backlog baru lahir dengan mode goal. Masih bisa dimatikan per sesi saat Start.",save:Q,children:e.jsx(q,{"aria-label":"Mode goal default",checked:Q.value,onChange:o=>Q.set(o)})}),e.jsx(E,{title:"Kondisi (template global)",last:!0,desc:"Kosong = kondisi bawaan hanoman: semua fase tercatat di phase file, plan tak menyisakan task, push sukses.",save:V,children:e.jsx("div",{className:"hn-set-w-field",children:e.jsx(In,{value:V.value,onSet:V.set,onFlush:V.flush})})})]}),e.jsxs(I,{eyebrow:"verifikasi",title:"Scope verifikasi — sesi backlog","data-setting-card":!0,"data-search":"scope verifikasi hanya yang berubah seluruh project uji",children:[e.jsxs(T,{children:["Beberapa sesi berjalan bersamaan di perangkat ini. ",e.jsx("b",{children:"Hanya yang berubah"})," menyuruh sesi menguji hanya berkas yang ia ubah — misalnya dengan ",e.jsx("code",{children:"vitest --changed"})," (uji) dan typecheck per paket — alih-alih seluruh project. Dengan begitu RAM dan CPU tetap tersisa untuk sesi lain. Uji penuh, lint penuh, dan build penuh tetap dijalankan manusia sebelum merge."]}),e.jsx(E,{title:"Scope default",last:!0,desc:"Sesi backlog baru lahir dengan scope ini. Masih bisa diubah per sesi saat Start.",save:X,children:e.jsx(K,{size:"sm","aria-label":"Scope verifikasi default",value:X.value,className:"hn-set-w-md",options:[{value:"changed",label:"Hanya yang berubah"},{value:"full",label:"Seluruh project"}],onChange:o=>X.set(o.target.value)})})]}),e.jsxs(I,{eyebrow:"metode",title:"Metode workflow — sesi backlog","data-setting-card":!0,"data-search":"metode workflow skill direktori plan spec pemasangan",children:[e.jsxs(T,{children:["Metode menentukan ",e.jsx("b",{children:"skill mana yang dimuat di tiap fase"})," dan ",e.jsx("b",{children:"di direktori mana plan & spec ditulis"}),". Fase-fasenya sendiri tak berubah. Gerbang plan memindai direktori SEMUA metode, jadi item yang berpindah metode tak pernah lolos lewat direktori kosong."]}),e.jsx(E,{title:"Metode default",last:!0,desc:"Sesi backlog baru lahir dengan metode ini. Masih bisa diubah per sesi saat Start.",save:G,children:e.jsx(K,{size:"sm","aria-label":"Metode default",className:"hn-set-w-md",value:G.value,options:Le.map(o=>({value:o,label:_e[o].label})),onChange:o=>G.set(o.target.value)})}),m&&e.jsxs("div",{"data-testid":"method-status",className:"hn-set-method-status",children:[Le.map(o=>e.jsxs("div",{className:"hn-set-method",children:[e.jsx("div",{className:"hn-set-method-name",children:_e[o].label}),m.methods.filter(c=>c.method===o).map(c=>e.jsxs("div",{"data-testid":`method-status-${c.method}-${c.agent}`,className:"hn-set-method-row",children:[e.jsx(ee,{tone:c.ready?"ok":"warn",children:c.ready?"siap":"belum siap"}),e.jsxs("div",{className:"hn-set-method-text",children:[e.jsx("b",{children:Y[c.agent]}),!c.ready&&e.jsxs("div",{className:"hn-set-method-missing",children:[c.missingPackages.length>0&&e.jsxs("div",{children:["paket kurang: ",e.jsx("code",{children:c.missingPackages.join(" · ")})]}),c.missingSkills.length>0&&e.jsxs("div",{children:["skill kurang: ",e.jsx("code",{children:c.missingSkills.join(" · ")})]})]})]}),!c.ready&&e.jsx(y,{size:"sm",variant:"ghost",leftIcon:"download",disabled:!s,onClick:()=>p(c),children:"Pasang"})]},c.agent))]},o)),e.jsx(Cn,{children:s?e.jsxs(e.Fragment,{children:["Pemasangan berjalan di ",e.jsx("b",{children:"sesi terminal"})," project ",e.jsx("code",{children:s})," — outputnya bisa ditonton di Terminal. hanoman sendiri tak pernah memasang apa pun."]}):e.jsx(e.Fragment,{children:"Pemasangan butuh satu project yang sudah di-bind ke checkout lokal: perintahnya dijalankan di sesi terminal project itu."})})]})]})]})}function In({value:a,onSet:n,onFlush:t}){return e.jsx("div",{onBlur:()=>t(),children:e.jsx(qa,{value:a,rows:4,mono:!0,"aria-label":"Kondisi mode goal",placeholder:"mis. semua fase tercatat & plan tanpa - [ ]",onChange:l=>n(l.target.value)})})}async function $e(a,n,t,l){var i;const r=((i=a.current())==null?void 0:i.lead)??te,m=s=>(s??te).engine??te.engine;a.update(s=>({...s,lead:{...s.lead??te,engine:{...m(s.lead),...t}}}));try{const s=await N.getLeadConfig(),u=await N.putLeadConfig({...s,engine:{...s.engine??te.engine,...t}});return a.update(h=>({...h,lead:u})),n==null||n(l,"ok","check-circle-2"),!0}catch{return a.update(s=>({...s,lead:r})),n==null||n("Gagal menyimpan setelan lead","err","alert-triangle"),!1}}async function Ue(a,n,t,l){var i;const r=((i=a.current())==null?void 0:i.telegram)??Z,m=s=>s.engine??Z.engine;a.update(s=>({...s,telegram:{...s.telegram??Z,engine:{...m(s.telegram??Z),...t}}}));try{const s=await N.getSettings(),u=s.telegram??Z,h={...s,telegram:{...u,engine:{...u.engine??Z.engine,...t}}},b=await N.putSettings(h);return a.update(f=>({...f,telegram:(b??h).telegram??f.telegram})),n==null||n(l,"ok","check-circle-2"),!0}catch{return a.update(s=>({...s,telegram:r})),n==null||n("Gagal menyimpan setelan operator Telegram","err","alert-triangle"),!1}}function Dn({s:a,store:n,onToast:t,codexVer:l,onNavigate:r}){const m=a.codex??be,i=a.agent??"claude",s={claude:{model:a.model,effort:a.effort},codex:{model:m.model,effort:m.effort}},u=i==="codex"?{agent:"codex",model:m.model,effort:m.effort}:{agent:"claude",model:a.model,effort:a.effort},h=k=>e.jsxs(e.Fragment,{children:[k," ",e.jsx("b",{children:Y[u.agent]})," · ",e.jsx("code",{children:u.model})," · ",e.jsx("code",{children:u.effort}),"."]}),b=a.conflict??Je,f=(k,w)=>n.save({conflict:{...b,...k}},w),j=(a.lead??te).engine??te.engine;return e.jsxs(e.Fragment,{children:[e.jsxs(I,{eyebrow:"override",title:"Override per fungsi","data-setting-card":!0,"data-search":"override per fungsi",children:[e.jsxs(T,{children:["Default global diatur di ",e.jsx("b",{children:"Sesi harian"}),". Tiap fungsi di bawah bisa memakai setelan sendiri; bila sakelarnya mati, ia ikut default global. Agen operator Telegram juga override, tetapi diatur di satu tempat bersama kredensial Telegram."]}),e.jsx("div",{className:"hn-set-inline",children:e.jsx(y,{size:"sm",variant:"ghost",leftIcon:"send",onClick:()=>r("telegram"),children:"Buka Telegram"})})]}),e.jsx(ge,{eyebrow:"konflik",title:"Konflik rebase & merge",desc:"Saat rebase/merge berkonflik, hanoman menyerahkan worktree-nya ke satu sesi agen untuk dibereskan. Pekerjaannya sempit dan tak berfase, jadi ia boleh memakai model & effort yang berbeda dari sesi kerja. Berlaku untuk ketiga pintu integrasi: backlog, git graph, dan PRD.",toggleDesc:"Mati = ikut default global. Hidup = sesi konflik memakai pilihan di bawah.",toggleAria:"Override agen konflik",enabled:b.enabled,onToggle:k=>f({enabled:k},"Setelan konflik"+(k?" · aktif":" · ikut default global")),inheritedTestId:"conflict-inherited",inherited:h("Sesi konflik memakai default global:"),children:e.jsx(Ce,{engine:{enabled:b.enabled,agent:b.agent,model:b.model,effort:b.effort},labels:{agentTitle:"Agen",agentDesc:"Mesin yang membereskan konflik. Bisa beda dari agen sesi kerja.",effortDesc:"Konflik biasanya mekanis — effort rendah sering cukup.",aria:{agent:"Agen konflik",model:"Model konflik",effort:"Effort konflik"},msg:{agent:"Agen konflik",model:"Model konflik",effort:"Effort konflik"}},defaults:s,codexVer:l,save:(k,w)=>f(k,w)})}),e.jsx(ge,{eyebrow:"lead",title:"Agen hanoman-lead",desc:e.jsxs(e.Fragment,{children:["Mesin yang menjalankan agen pemimpin — panggilan sekali-jalan non-interaktif yang membaca docs, plan, kode, dan riwayat git sebelum memutuskan. Berlaku untuk ketiga pintu lead (kontrak, deteksi otomatis, denyut) dan dipakai putusan berikutnya, tanpa restart. Rem darurat, denyut, dan opt-in per project tetap diurus di layar ",e.jsx("b",{children:"Lead"}),"."]}),toggleDesc:"Mati = ikut default global. Hidup = lead memakai pilihan di bawah.",toggleAria:"Override agen lead",enabled:j.enabled,onToggle:k=>$e(n,t,{enabled:k},"Setelan lead"+(k?" · aktif":" · ikut default global")),inheritedTestId:"lead-engine-inherited",inherited:h("hanoman-lead memakai default global:"),children:e.jsx(Ce,{engine:j,labels:{agentTitle:"Runtime",agentDesc:"Mesin yang menjalankan lead. Bisa beda dari agen sesi kerja.",effortDesc:"Putusan lead menuntut membaca bukti — dokumen proyek, ADR, plan, kode, riwayat git. Effort rendah memangkas kedalamannya.",aria:{agent:"Runtime lead",model:"Model lead",effort:"Effort lead"},msg:{agent:"Runtime lead",model:"Model lead",effort:"Effort lead"}},defaults:s,codexVer:l,save:(k,w)=>$e(n,t,k,w)})}),e.jsx(ge,{eyebrow:"portal",title:"Obrolan portal klien",desc:"Permukaan obrolan di portal klien: klien memilih Brainstorming (digali sampai jelas, keluarannya PRD draft untuk Anda review) atau Bertanya (dijawab langsung dari dokumen project). Jatah berlaku per project dan dihitung bulanan; brainstorming dan pertanyaan punya jatah masing-masing.",toggleTitle:"Aktifkan obrolan",toggleDesc:"Mati = klien hanya punya Pekerjaan & Help desk, persis seperti sebelumnya.",toggleAria:"Aktifkan obrolan portal",enabled:(a.portalChat??ke).enabled,onToggle:k=>n.save({portalChat:{...a.portalChat??ke,enabled:k}},"Obrolan portal"+(k?" · aktif":" · mati")),children:e.jsx(Ln,{s:a,store:n,onToast:t})}),e.jsx(on,{orchestration:a.orchestration,onChange:(k,w)=>{n.save({orchestration:k},w)}})]})}function Ln({s:a,store:n,onToast:t}){const l=a.portalChat??ke,r=(s,u)=>n.save({portalChat:{...l,...s}},u),m=H({value:l.model,delayMs:0,save:s=>r({model:s,...Me(s,l.effort)},"Model obrolan portal → "+s)}),i=H({value:l.effort,delayMs:0,save:s=>r({effort:s},"Effort obrolan portal → "+s)});return e.jsxs(e.Fragment,{children:[e.jsx(E,{title:"Jatah brainstorming",desc:"Berapa sesi brainstorming per project tiap bulan. 0 = tertutup.",children:e.jsx(xe,{label:"Jatah brainstorming",value:l.brainstormPerMonth,min:0,max:1e3,placeholder:"mis. 3",onToast:t,onCommit:s=>r({brainstormPerMonth:s},"Jatah brainstorming → "+s)})}),e.jsx(E,{title:"Jatah pertanyaan",desc:"Berapa sesi tanya-jawab per project tiap bulan. 0 = tertutup.",children:e.jsx(xe,{label:"Jatah pertanyaan",value:l.askPerMonth,min:0,max:1e4,placeholder:"mis. 30",onToast:t,onCommit:s=>r({askPerMonth:s},"Jatah pertanyaan → "+s)})}),e.jsx(E,{title:"Model",desc:"Mesin obrolan selalu Claude — gerbang tool yang menjaganya tak ada di runtime lain.",children:e.jsx(K,{size:"sm","aria-label":"Model obrolan portal",value:m.value,className:"hn-set-w-sm",options:Pe(m.value),onChange:s=>m.set(s.target.value)})}),e.jsx(E,{title:"Effort",children:e.jsx(K,{size:"sm","aria-label":"Effort obrolan portal",value:i.value,className:"hn-set-w-xs",options:Oe(m.value),onChange:s=>i.set(s.target.value)})}),e.jsx(E,{title:"Batas waktu satu jawaban",last:!0,desc:"Detik. Lewat dari ini klien menerima kalimat 'coba lagi sebentar', bukan layar menggantung.",children:e.jsx(xe,{label:"Batas waktu obrolan portal",value:l.timeoutSec,min:10,max:900,placeholder:"mis. 120",onToast:t,onCommit:s=>r({timeoutSec:s},"Batas waktu obrolan → "+s)})})]})}const _n={name:"",url:"",events:["*"],enabled:!0,allowPrivate:!1},Rn=Ye.map(a=>({entity:a.entity,label:a.label,types:me.filter(n=>n.entity===a.entity).map(n=>n.type)})),Ke=a=>a?new Date(a).toLocaleString("id-ID",{dateStyle:"short",timeStyle:"medium"}):"—";function Bn({e:a}){return a.enabled?e.jsx(ee,{tone:"ok",children:"aktif"}):a.disabledAt?e.jsx(ee,{tone:"err",children:"dinonaktifkan otomatis"}):e.jsx(ee,{children:"nonaktif"})}function Hn({onToast:a,onOpenDocs:n}={}){const[t,l]=d.useState(null),[r,m]=d.useState(!1),[i,s]=d.useState(null),[u,h]=d.useState(null),[b,f]=d.useState(!1),[g,j]=d.useState({}),[k,w]=d.useState(null),[O,S]=d.useState([]),{confirm:D,dialog:A}=le(),x=d.useCallback(async()=>{try{l((await N.listWebhooks()).endpoints),m(!1)}catch{m(!0)}},[]);d.useEffect(()=>{x()},[x]);const M=async p=>{w(p);try{S((await N.listWebhookDeliveries(p)).items)}catch{S([])}},L=async()=>{if(i){f(!0);try{if(i.id)await N.updateWebhook(i.id,{name:i.name,url:i.url,events:i.events,enabled:i.enabled,allowPrivate:i.allowPrivate}),a==null||a("Endpoint webhook diperbarui");else{const p=await N.createWebhook({name:i.name,url:i.url,events:i.events,enabled:i.enabled,allowPrivate:i.allowPrivate});h(p.secret??null),a==null||a("Endpoint webhook dibuat")}s(null),await x()}catch(p){a==null||a($("menyimpan endpoint",p),"err")}finally{f(!1)}}},C=async p=>{f(!0);try{const P=await N.updateWebhook(p,{rotateSecret:!0});h(P.secret??null),await x()}catch(P){a==null||a(`Gagal merotasi secret: ${P.message}`,"err")}finally{f(!1)}},R=async(p,P)=>{try{await N.updateWebhook(p.id,{enabled:P}),await x()}catch(o){a==null||a($("mengubah status endpoint",o),"err")}},B=async p=>{f(!0);try{const P=await N.testWebhook(p);j(o=>({...o,[p]:P})),await x()}catch(P){j(o=>({...o,[p]:{ok:!1,httpStatus:null,durationMs:0,error:P.message}}))}finally{f(!1)}},Q=async p=>{try{await D({title:`Hapus endpoint "${p.name}"?`,message:"Endpoint ini tak lagi menerima peristiwa dari hanoman.",impact:["Riwayat pengiriman endpoint ini ikut dihapus.","Tindakan ini tak bisa dibatalkan."],confirmLabel:"Hapus endpoint",tone:"danger",icon:"trash-2",run:()=>N.deleteWebhook(p.id)})&&(a==null||a("Endpoint webhook dihapus"),await x())}catch(P){a==null||a($("menghapus endpoint",P),"err")}},V=async p=>{try{await N.retryWebhookDelivery(p),k&&await M(k),await x()}catch(P){a==null||a(`Gagal antre ulang: ${P.message}`,"err")}},X=(p,P)=>s(o=>o&&{...o,events:P?[...new Set([...o.events.filter(c=>c!=="*"),...p])]:o.events.filter(c=>c!=="*"&&!p.includes(c))}),G=(i==null?void 0:i.events.includes("*"))??!1;return e.jsxs(e.Fragment,{children:[e.jsxs(I,{eyebrow:"integrasi",title:"Webhook keluar",children:[e.jsxs("div",{className:"hn-wh-muted hn-wh-mb12",children:["hanoman mengirim ",e.jsx("b",{children:"HTTP POST"})," bertanda tangan ke endpoint yang Anda daftarkan setiap kali sesuatu berubah — backlog dibuat atau berpindah stage, sesi mulai dan selesai, putusan lead terbit, tiket masuk, notifikasi. Pengiriman berjalan di antrean: penerima yang lambat atau mati ",e.jsx("b",{children:"tidak"})," memperlambat hanoman."]}),e.jsxs("div",{className:"hn-wh-actions",children:[e.jsxs(y,{size:"sm",onClick:()=>{s({..._n}),h(null)},children:[e.jsx(re,{name:"plus",size:14})," Tambah endpoint"]}),n&&e.jsxs(y,{size:"sm",variant:"ghost",onClick:n,children:[e.jsx(re,{name:"book-open",size:14})," Dokumentasi webhook"]})]}),r?e.jsx(W,{kind:"error",compact:!0,title:"Gagal memuat endpoint webhook",hint:"Coba muat ulang.",action:()=>void x(),actionLabel:"Coba lagi"}):t===null?e.jsx("div",{className:"hn-wh-muted",children:"Memuat…"}):t.length===0?e.jsx(W,{kind:"empty",compact:!0,title:"Belum ada endpoint webhook",hint:"Daftarkan URL penerima pertama untuk mulai berlangganan peristiwa hanoman."}):e.jsx("div",{className:"hn-wh-col-10",children:t.map(p=>e.jsxs("div",{"data-testid":`webhook-${p.id}`,className:"hn-wh-endpoint",children:[e.jsxs("div",{className:"hn-wh-endpoint-head",children:[e.jsx("div",{className:"hn-wh-name",children:p.name}),e.jsx(Bn,{e:p}),p.pending>0?e.jsxs(ee,{children:[p.pending," mengantre"]}):null,e.jsxs("div",{className:"hn-wh-endpoint-actions",children:[e.jsx(q,{checked:p.enabled,"aria-label":`Aktifkan ${p.name}`,onChange:P=>void R(p,P)}),e.jsx(y,{size:"sm",variant:"ghost",disabled:b,onClick:()=>void B(p.id),children:"Test"}),e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>void M(p.id),children:"Riwayat"}),e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>{h(null),s({id:p.id,name:p.name,url:p.url,events:p.events,enabled:p.enabled,allowPrivate:p.allowPrivate})},children:"Ubah"}),e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>void Q(p),children:"Hapus"})]})]}),e.jsx("div",{className:"hn-wh-url",children:p.url}),e.jsxs("div",{className:"hn-wh-muted hn-wh-mt6",children:["Peristiwa: ",e.jsx("code",{children:p.events.join(", ")})," · secret …",p.secretHint," ·"," ","sukses terakhir ",Ke(p.lastSuccessAt),p.failureStreak>0?` · ${p.failureStreak} gagal beruntun`:""]}),p.disabledReason?e.jsx("div",{className:"hn-wh-muted hn-wh-mt6 hn-wh-err",children:p.disabledReason}):null,g[p.id]?e.jsx("div",{className:"hn-wh-muted hn-wh-mt6",children:g[p.id].ok?`Test berhasil — HTTP ${g[p.id].httpStatus} · ${g[p.id].durationMs} ms`:`Test gagal — ${g[p.id].error}`}):null]},p.id))})]}),u?e.jsxs(I,{eyebrow:"secret",title:"Salin sekarang — secret tak ditampilkan lagi",children:[e.jsx(se,{tone:"brass",children:e.jsx("div",{className:"hn-wh-secret",children:u})}),e.jsxs("div",{className:"hn-wh-row hn-wh-mt10",children:[e.jsx(y,{size:"sm",onClick:()=>{var p;return void((p=navigator.clipboard)==null?void 0:p.writeText(u))},children:"Salin secret"}),e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>h(null),children:"Tutup"})]})]}):null,i?e.jsx(I,{eyebrow:i.id?"ubah":"tambah",title:i.id?"Ubah endpoint":"Endpoint baru",children:e.jsxs("div",{className:"hn-wh-col-12",children:[e.jsx(ae,{label:"Nama",children:e.jsx(J,{value:i.name,placeholder:"mis. Dashboard internal",onChange:p=>s({...i,name:p.target.value})})}),e.jsx(ae,{label:"URL tujuan",children:e.jsx(J,{value:i.url,placeholder:"https://contoh.id/hanoman-webhook",onChange:p=>s({...i,url:p.target.value})})}),e.jsxs("div",{children:[e.jsx("div",{className:"hn-wh-label",children:"Peristiwa yang dikirim"}),e.jsx(de,{checked:G,label:"Semua peristiwa",onChange:p=>s({...i,events:p?["*"]:[]})}),G?null:e.jsxs("div",{className:"hn-wh-tree",children:[Rn.map(p=>e.jsxs("div",{children:[e.jsx(de,{checked:p.types.every(P=>i.events.includes(P)),label:p.label,onChange:P=>X(p.types,P)}),e.jsx("div",{className:"hn-wh-family-types",children:p.types.map(P=>e.jsx(de,{checked:i.events.includes(P),label:P,onChange:o=>s({...i,events:o?[...new Set([...i.events.filter(c=>c!=="*"),P])]:i.events.filter(c=>c!==P&&c!=="*")})},P))})]},p.entity)),e.jsxs("div",{className:"hn-wh-muted",children:[e.jsx("code",{children:Va})," selalu terkirim saat tombol Test ditekan, apa pun langganannya."]})]})]}),e.jsx(de,{checked:i.allowPrivate,label:"Izinkan alamat internal / loopback",onChange:p=>s({...i,allowPrivate:p})}),e.jsx("div",{className:"hn-wh-muted",children:"Biarkan mati kecuali penerima memang berjalan di mesin/jaringan yang sama. Menyalakannya membuka jalan ke layanan internal yang tak pernah dimaksudkan terekspos."}),e.jsx(de,{checked:i.enabled,label:"Aktif",onChange:p=>s({...i,enabled:p})}),e.jsxs("div",{className:"hn-wh-row",children:[e.jsx(y,{size:"sm",disabled:b||!i.name||!i.url||i.events.length===0,onClick:()=>void L(),children:"Simpan"}),e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>s(null),children:"Batal"}),i.id?e.jsx(y,{size:"sm",variant:"ghost",disabled:b,onClick:()=>void C(i.id),children:"Rotasi secret"}):null]})]})}):null,k?e.jsxs(I,{eyebrow:"riwayat",title:"Riwayat pengiriman",children:[e.jsx("div",{className:"hn-wh-history-head",children:e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>w(null),children:"Tutup riwayat"})}),O.length===0?e.jsx("div",{className:"hn-wh-muted",children:"Belum ada pengiriman."}):e.jsx("div",{className:"hn-local-overflow",children:e.jsxs("table",{className:"hn-wh-table hn-wh-table--full",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"hn-wh-thead",children:[e.jsx("th",{className:"hn-wh-cell",children:"Waktu"}),e.jsx("th",{className:"hn-wh-cell",children:"Jenis"}),e.jsx("th",{className:"hn-wh-cell",children:"Status"}),e.jsx("th",{className:"hn-wh-cell",children:"HTTP"}),e.jsx("th",{className:"hn-wh-cell",children:"Percobaan"}),e.jsx("th",{className:"hn-wh-cell",children:"Galat"}),e.jsx("th",{})]})}),e.jsx("tbody",{children:O.map(p=>e.jsxs("tr",{className:"hn-wh-tr",children:[e.jsx("td",{className:"hn-wh-cell hn-wh-cell--nowrap",children:Ke(p.createdAt)}),e.jsx("td",{className:"hn-wh-cell hn-wh-cell--mono12",children:p.eventType}),e.jsx("td",{className:"hn-wh-cell",children:p.status}),e.jsx("td",{className:"hn-wh-cell",children:p.httpStatus??"—"}),e.jsx("td",{className:"hn-wh-cell",children:`${p.attempt} / ${p.maxAttempts}`}),e.jsx("td",{className:"hn-wh-cell hn-wh-cell--muted",children:p.error??"—"}),e.jsx("td",{className:"hn-wh-cell",children:p.status==="failed"||p.status==="dropped"?e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>void V(p.id),children:"Antre ulang"}):null})]},p.id))})]})})]}):null,A]})}function ve({text:a,label:n="Salin"}){const[t,l]=d.useState(!1);return e.jsxs("div",{className:"hn-wh-copy",children:[e.jsx("pre",{className:"hn-wh-code",children:a}),e.jsx("div",{className:"hn-wh-mt6",children:e.jsx(y,{size:"sm",variant:"ghost",onClick:()=>{var r;(r=navigator.clipboard)==null||r.writeText(a),l(!0),setTimeout(()=>l(!1),1500)},children:t?"Tersalin":n})})]})}const Fn=`// Node.js (Express) — verifikasi tanda tangan webhook hanoman
2
2
  import express from "express";
3
3
  import { createHmac, timingSafeEqual } from "node:crypto";
4
4
 
@@ -1 +1 @@
1
- import{T as ra,a as Pa,b as Ba,j as a,c as Se,O as oa,P as me,I as q,d as ca,M as we,e as $,f as Y,g as B,H as Aa,B as U,h as D,i as Ce,k as He,E as Ra,s as _a,C as Ua,m as W,n as Ze,o as ke,p as Fa,q as X,r as Ye,t as Ka,v as za,w as Ga,x as Ha,y as Za,z as Ya,A as Va,D as xe,G as Wa}from"./index-DmnwLncG.js";import{R as d}from"./react-DfGhg7ZW.js";import{L as qa}from"./live-B193WtZm.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";const Ja=Pa,Z=ra.map(e=>({key:e,label:Ja[e]})),Qa=()=>Object.fromEntries(ra.map(e=>[e,[]])),Ne=(e,t)=>e!==t,da=e=>e.length===0?0:e.reduce((t,n)=>n.order>t?n.order:t,-1/0)+1;function Xa(e,t,n,l){if(!Ne(n,l))return null;const r=e[n].find(f=>f.id===t);if(!r)return null;const o={status:l,order:da(e[l])},u={...e};return u[n]=e[n].filter(f=>f.id!==t),u[l]=[...e[l],{...r,...o}],{board:u,patch:o}}function ye(e,t){const n={...e};return n[t.status]=e[t.status].map(l=>l.id===t.id?t:l),n}const Ve=e=>e?e.slice(0,10):"",We=e=>/^\d{4}-\d{2}-\d{2}$/.test(e)?`${e}T12:00:00.000Z`:null,J=864e5,se=e=>Math.floor(e/J)*J,qe=e=>{if(!e)return null;const t=new Date(e).getTime();return Number.isFinite(t)?t:null};function ee(e){const t=qe(e.startDate),n=qe(e.dueDate);if(t===null&&n===null)return null;const l=t??n,r=n??t;return{start:se(Math.min(l,r)),end:se(Math.max(l,r))+J,invalid:r<l}}const et=new Intl.DateTimeFormat("id-ID",{day:"numeric",month:"short",timeZone:"UTC"}),Je=e=>e?et.format(new Date(e)):null;function ue(e){const t=Je(e.startDate),n=Je(e.dueDate);return t&&n?`${t} → ${n}`:n?`→ ${n}`:t}const Qe=["day","week","month"],ua={day:{cell:34,minTicks:14},week:{cell:56,minTicks:8},month:{cell:84,minTicks:6}},at=e=>ua[e].cell,tt=120,nt=(e,t)=>{const n=se(e);if(t==="day")return n;if(t==="week")return n-(new Date(n).getUTCDay()+6)%7*J;const l=new Date(n);return Date.UTC(l.getUTCFullYear(),l.getUTCMonth(),1)},st=(e,t)=>{if(t==="day")return e+J;if(t==="week")return e+7*J;const n=new Date(e);return Date.UTC(n.getUTCFullYear(),n.getUTCMonth()+1,1)},lt=new Intl.DateTimeFormat("id-ID",{day:"numeric",timeZone:"UTC"}),Xe=new Intl.DateTimeFormat("id-ID",{day:"numeric",month:"short",timeZone:"UTC"}),it=new Intl.DateTimeFormat("id-ID",{month:"short",timeZone:"UTC"}),rt=new Intl.DateTimeFormat("id-ID",{month:"short",year:"2-digit",timeZone:"UTC"}),ot=(e,t)=>{const n=new Date(e);return t==="day"?n.getUTCDate()===1:t==="week"?n.getUTCDate()<=7:n.getUTCMonth()===0},ct=(e,t,n)=>{const l=new Date(e);return t==="day"?(n?Xe:lt).format(l):t==="week"?Xe.format(l):(n?rt:it).format(l)};function ma(e,t,n){const l=se(n);let r=l,o=l+J;for(const b of e)b.start<r&&(r=b.start),b.end>o&&(o=b.end);const u=nt(r,t),{minTicks:f}=ua[t],p=[];let i=u;for(;p.length<tt&&(i<o||p.length<f);){const b=ot(i,t);p.push({start:i,label:ct(i,t,b),major:b}),i=st(i,t)}return{from:u,to:i,zoom:t,ticks:p}}function ha(e,t){const n=t.to-t.from;if(n<=0||e.end<=t.from||e.start>=t.to)return null;const l=Math.max(e.start,t.from),r=Math.min(e.end,t.to);return{left:(l-t.from)/n*100,width:(r-l)/n*100,clippedStart:e.start<t.from,clippedEnd:e.end>t.to,invalid:e.invalid}}function Ie(e,t){const n=ee(e);return n?ha(n,t):null}function dt(e){let t=1/0,n=-1/0,l=!1;for(const r of e){const o=ee(r);o&&(o.start<t&&(t=o.start),o.end>n&&(n=o.end),o.invalid&&(l=!0))}return t===1/0?null:{start:t,end:n,invalid:l}}function ut(e,t){const n=se(t);return n<e.from||n>=e.to?null:(n-e.from)/(e.to-e.from)*100}function mt(e,t){const n=[],l=[],r=[];for(const o of e){const u=ee(o);if(!u){l.push(o);continue}const f=Ie(o,t);if(!f){r.push(o);continue}n.push({task:o,geometry:f,start:u.start})}return n.sort((o,u)=>o.start-u.start||o.task.title.localeCompare(u.task.title,"id")||o.task.id.localeCompare(u.task.id)),{rows:n.map(({task:o,geometry:u})=>({task:o,geometry:u})),unscheduled:l,outside:r}}const ea=(e,t)=>e.title.localeCompare(t.title,"id")||e.id.localeCompare(t.id);function ht(e,t,n){const l=Symbol("no-project"),r=new Map;for(const p of e){const i=p.projectId??l,b=r.get(i);b?b.tasks.push(p):r.set(i,{projectId:p.projectId,tasks:[p]})}const o=[...r.values()].map(({projectId:p,tasks:i})=>{const b=dt(i),m=[],k=[];for(const S of i){const j=ee(S);j?m.push({task:S,start:j.start}):k.push(S)}return m.sort((S,j)=>S.start-j.start||ea(S.task,j.task)),k.sort(ea),{projectId:p,span:b,geometry:b?ha(b,t):null,tasks:[...m.map(S=>S.task),...k]}}),u=p=>p.geometry?0:p.span?1:2,f=p=>p.projectId===null?[1,""]:[0,p.projectId];return o.sort((p,i)=>{const[b,m]=f(p),[k,S]=f(i);return u(p)-u(i)||(p.span&&i.span?p.span.start-i.span.start:0)||n(p.projectId).localeCompare(n(i.projectId),"id")||b-k||m.localeCompare(S)}),o}const pt={tinggi:"high",sedang:"mid",rendah:"low"};function gt({priority:e}){const t=pt[e]??"mid",n=me[e]??e;return a.jsx("span",{className:`hn-tm-prio hn-tm-prio-${t}`,title:`Prioritas ${n}`,children:a.jsxs("span",{className:"hn-sr-only",children:["Prioritas ",n]})})}function bt({name:e}){if(!e)return a.jsx("span",{className:"hn-tm-avatar hn-tm-avatar-empty","aria-hidden":"true",children:a.jsx(q,{name:"user",size:12})});const t=e.split(/\s+/).filter(Boolean).slice(0,2).map(n=>n[0].toUpperCase()).join("");return a.jsx("span",{className:"hn-tm-avatar","aria-hidden":"true",children:t||"?"})}function ft(e,t,n){const l=[...Z.filter(r=>r.key!==e.status).map(r=>({key:`move-${r.key}`,label:`Pindah ke ${r.label}`,onSelect:()=>n.onMove(e,r.key)})),...t.map(r=>({key:`assign-${r.id}`,label:`Tugaskan ke ${r.name}`,disabled:e.memberId===r.id,onSelect:()=>n.onAssign(e,r.id)})),{key:"assign-none",label:"Kosongkan penugasan",disabled:!e.memberId,onSelect:()=>n.onAssign(e,null)}];if(e.specId){if(e.spec&&n.onOpenSpec){const r=e.specId;l.push({key:"open-spec",label:`Buka ${e.spec.id} di Backlog`,onSelect:()=>{var o;return(o=n.onOpenSpec)==null?void 0:o.call(n,r)}})}l.push({key:"unlink",label:e.spec?"Lepas tautan":"Lepas tautan (spec tak ditemukan)",onSelect:()=>n.onUnlink(e)})}else l.push({key:"escalate",label:"Kirim ke Backlog",onSelect:()=>n.onEscalate(e)});return l}function jt({task:e,members:t,projectName:n,dragging:l,onDragStart:r,onDragEnd:o,onOpen:u,onMove:f,onAssign:p,onEscalate:i,onUnlink:b,onOpenSpec:m}){var C;const k=((C=t.find(h=>h.id===e.memberId))==null?void 0:C.name)??null,S=ft(e,t,{onMove:f,onAssign:p,onEscalate:i,onUnlink:b,onOpenSpec:m}),j=e.projectId===null?"tanpa project":n??"project tak dikenal";return a.jsxs("div",{draggable:!0,"data-testid":`team-card-${e.id}`,className:"hn-tm-card","data-dragging":l||void 0,title:`Project: ${j}`,onDragStart:h=>{h.dataTransfer.effectAllowed="move",h.dataTransfer.setData("text/plain",e.id),r()},onDragEnd:o,children:[a.jsxs("div",{className:"hn-tm-card-head",children:[a.jsx(gt,{priority:e.priority}),a.jsx("button",{type:"button",className:"hn-tm-title",onClick:()=>u(e),children:e.title})]}),a.jsxs("div",{className:"hn-tm-card-foot",children:[a.jsxs("span",{className:"hn-tm-assignee-wrap",children:[a.jsx(bt,{name:k}),a.jsx("span",{className:"hn-tm-assignee",children:k??"belum ditugaskan"})]}),a.jsx(oa,{label:`Ubah tugas: ${e.title}`,icon:"ellipsis",items:S})]})]})}function kt({board:e,totals:t,columns:n,members:l,projects:r=[],onMove:o,onAssign:u,onOpen:f,onEscalate:p,onUnlink:i,onOpenSpec:b}){var T;const[m,k]=d.useState(null),[S,j]=d.useState(null),C=Ba(),[h,N]=d.useState(((T=n[0])==null?void 0:T.key)??"backlog"),M=d.useMemo(()=>{const c=new Map(r.map(y=>[y.id,y.name]));return y=>y===null?null:c.get(y)??null},[r]),A=c=>{m&&Ne(m.from,c)&&o(m.task,c),k(null),j(null)},g=(c,y)=>a.jsx(jt,{task:c,members:l,projectName:M(c.projectId),dragging:(m==null?void 0:m.task.id)===c.id,onDragStart:()=>k({task:c,from:y}),onDragEnd:()=>{k(null),j(null)},onOpen:f,onMove:o,onAssign:u,onEscalate:p,onUnlink:i,onOpenSpec:b},c.id);if(C==="mobile"){const c=n.find(I=>I.key===h)??n[0];if(!c)return null;const y=e[c.key],L=Math.max(0,(t[c.key]??0)-y.length);return a.jsxs("div",{"data-testid":"team-board","data-layout":"mobile",className:"hn-tm-mobile",children:[a.jsx(Se,{variant:"pill","aria-label":"Kolom papan tim",value:c.key,onChange:I=>N(I),tabs:n.map(I=>({value:I.key,label:`${I.label} · ${e[I.key].length}`}))}),a.jsxs("div",{"data-testid":`team-col-${c.key}`,className:"hn-tm-col-stack",children:[y.map(I=>g(I,c.key)),y.length===0&&a.jsxs("div",{className:"hn-tm-empty-col",children:["Tak ada tugas di ",c.label,"."]}),L>0&&a.jsxs("div",{className:"hn-tm-hidden-note",children:["menampilkan ",y.length," dari ",t[c.key]," — persempit penyaring"]})]})]})}return a.jsx("div",{"data-testid":"team-board",className:"hn-board-local-overflow hn-tm-board",children:n.map(c=>{const y=e[c.key],L=!!m&&Ne(m.from,c.key),I=L&&S===c.key,K=Math.max(0,(t[c.key]??0)-y.length);return a.jsxs("div",{"data-testid":`team-col-${c.key}`,className:"hn-tm-col","data-active":L||void 0,"data-hot":I||void 0,"data-dimmed":m&&!L||void 0,onDragOver:v=>{L&&(v.preventDefault(),v.dataTransfer.dropEffect="move",j(c.key))},onDragLeave:()=>j(v=>v===c.key?null:v),onDrop:v=>{v.preventDefault(),A(c.key)},children:[a.jsxs("div",{className:"hn-tm-col-head",children:[a.jsx("span",{className:"hn-eyebrow",children:c.label}),a.jsx("span",{className:"hn-tm-col-count",children:y.length})]}),a.jsx("div",{className:"hn-tm-col-body",children:y.map(v=>g(v,c.key))}),K>0&&a.jsxs("div",{className:"hn-tm-hidden-note",children:["menampilkan ",y.length," dari ",t[c.key]," — persempit penyaring"]})]},c.key)})})}const ve=232,xt={brass:"var(--brass-500)",err:"var(--status-err)",muted:"var(--border-strong)",envelope:"var(--border-hair)"},Te=e=>e;function yt({spec:e}){const t=e.geometry,n=xt[e.tone],l=!!e.onClick,r={"data-testid":`timeline-bar-${e.key}`,"data-tone":e.tone,"data-invalid":t.invalid?"true":"false","data-clipped-start":t.clippedStart?"true":"false","data-clipped-end":t.clippedEnd?"true":"false",title:e.title,"aria-label":e.title,onClick:e.onClick,className:"hn-tl-bar",style:Te({"--tl-left":`${t.left}%`,"--tl-width":`${t.width}%`})},o=a.jsxs(a.Fragment,{children:[t.invalid&&a.jsx(q,{name:"triangle-alert",size:11,color:n}),t.clippedStart&&a.jsx(q,{name:"chevron-left",size:11,color:n}),a.jsx("span",{className:"hn-grow"}),t.clippedEnd&&a.jsx(q,{name:"chevron-right",size:11,color:n})]});return l?a.jsx("button",{type:"button",...r,children:o}):a.jsx("div",{role:"img",...r,children:o})}function pa({envelope:e=!1}){const t=n=>a.jsx("span",{"aria-hidden":"true",className:"hn-tl-swatch","data-tone":n});return a.jsxs("ul",{"aria-label":"Legenda linimasa",className:"hn-tl-legend",children:[a.jsxs("li",{className:"hn-tl-legend-item",children:[t("brass"),"Rencana"]}),a.jsxs("li",{className:"hn-tl-legend-item",children:[t("muted"),"Selesai"]}),a.jsxs("li",{className:"hn-tl-legend-item",children:[t("err"),a.jsx(q,{name:"triangle-alert",size:11,color:"var(--status-err)"}),"Tenggat mendahului mulai"]}),e&&a.jsxs("li",{className:"hn-tl-legend-item",children:[t("envelope"),"Rentang project (buka lewat namanya)"]})]})}function ga({window:e,rows:t,today:n,emptyHint:l,testId:r,labelHead:o}){const u=at(e.zoom),f=e.ticks.length*u,p=ut(e,n);return a.jsx("div",{"data-testid":r??"team-timeline",className:"hn-timeline-scroll hn-tl-scroll",children:a.jsxs("div",{"data-testid":"timeline-canvas",className:"hn-tl",style:Te({"--tl-label-w":`${ve}px`,"--tl-cell":`${u}px`,"--tl-ticks":String(e.ticks.length),"--tl-track-w":`${f}px`,"--tl-canvas-w":`${ve+f}px`}),children:[a.jsxs("div",{className:"hn-tl-head",children:[a.jsx("div",{className:"hn-tl-label",children:a.jsx("span",{className:"hn-eyebrow",children:o??"Tugas"})}),a.jsx("div",{className:"hn-tl-ticks",children:e.ticks.map(i=>a.jsx("div",{"data-testid":"timeline-tick","data-major":i.major?"true":"false",className:"hn-tl-tick",children:i.label},i.start))})]}),t.length===0?a.jsx("div",{"data-testid":"timeline-empty",className:"hn-tl-empty",children:l??"Tak ada yang bisa dihamparkan di jendela ini."}):t.map(i=>a.jsxs("div",{"data-testid":`timeline-row-${i.key}`,className:"hn-tl-row",children:[a.jsxs("div",{className:"hn-tl-label",children:[a.jsx("div",{className:"hn-tl-label-text",children:i.label}),i.meta&&a.jsx("div",{className:"hn-tl-label-meta",children:i.meta})]}),a.jsx("div",{className:"hn-tl-track",children:i.bars.map(b=>a.jsx(yt,{spec:b},b.key))})]},i.key)),p!==null&&a.jsx("div",{"data-testid":"timeline-today","aria-hidden":"true",className:"hn-tl-today",style:Te({"--tl-today-x":`${ve+p/100*f}px`})})]})})}function aa({testId:e,icon:t,title:n,hint:l,tasks:r,onOpen:o}){return r.length===0?null:a.jsxs("div",{"data-testid":e,className:"hn-tl-aside",children:[a.jsxs("div",{className:"hn-tl-aside-head",children:[a.jsx(q,{name:t,size:13,color:"var(--text-subtle)"}),a.jsxs("span",{className:"hn-eyebrow",children:[n," · ",r.length]}),l&&a.jsx("span",{className:"hn-tl-aside-hint",children:l})]}),a.jsx("div",{className:"hn-tl-aside-list",children:r.map(u=>a.jsx("button",{type:"button",onClick:()=>o(u),className:"hn-tl-chip",children:u.title},u.id))})]})}function vt({tasks:e,members:t,zoom:n,today:l,hidden:r,onOpen:o}){const u=d.useMemo(()=>{const m=e.map(ee).filter(k=>k!==null);return ma(m,n,l)},[e,n,l]),{rows:f,unscheduled:p,outside:i}=d.useMemo(()=>mt(e,u),[e,u]),b=d.useMemo(()=>f.map(({task:m,geometry:k})=>{var h;const S=((h=t.find(N=>N.id===m.memberId))==null?void 0:h.name)??"belum ditugaskan",j=ue(m),C=[k.invalid?"tenggat mendahului mulai":null,k.clippedStart||k.clippedEnd?"melewati tepi jendela":null].filter(Boolean);return{key:m.id,label:m.title,meta:j?`${S} · ${j}`:S,bars:[{key:m.id,geometry:k,tone:k.invalid?"err":m.status==="done"?"muted":"brass",title:[m.title,j,...C].filter(Boolean).join(" · "),onClick:()=>o(m)}]}}),[f,t,o]);return a.jsxs(a.Fragment,{children:[a.jsx(pa,{}),a.jsx(ga,{window:u,rows:b,today:l,emptyHint:"Belum ada tugas bertanggal — isi mulai atau tenggat di kartunya."}),r>0&&a.jsxs("div",{"data-testid":"timeline-truncated",className:"hn-tl-note",children:[r," tugas tak termuat karena plafon 200 per kolom — persempit penyaring"]}),a.jsx(aa,{testId:"timeline-unscheduled",icon:"calendar-off",title:"Belum dijadwalkan",tasks:p,onOpen:o}),a.jsx(aa,{testId:"timeline-outside",icon:"chevrons-left-right",title:"Di luar jendela",hint:"pilih zoom yang lebih lebar",tasks:i,onOpen:o})]})}const St="__none__",ta=(e,t)=>t.invalid?"err":e.status==="done"?"muted":"brass",na=(e,t,n)=>[e.title,n,t.invalid?"tenggat mendahului mulai":null,t.clippedStart||t.clippedEnd?"melewati tepi jendela":null].filter(Boolean).join(" · ");function Ct({testId:e,open:t,name:n,count:l,onClick:r}){return a.jsxs("button",{type:"button",onClick:r,"data-testid":e,"aria-expanded":t,className:"hn-tl-expand",children:[a.jsx(q,{name:t?"chevron-down":"chevron-right",size:12,color:"var(--text-subtle)"}),a.jsx("span",{className:"hn-tl-expand-name",children:n}),a.jsx("span",{className:"hn-tl-expand-count",children:l})]})}function Nt({tasks:e,projects:t,members:n,zoom:l,today:r,hidden:o,expanded:u,onToggle:f,onOpen:p}){const i=d.useMemo(()=>{const j=e.map(ee).filter(C=>C!==null);return ma(j,l,r)},[e,l,r]),b=d.useCallback(j=>{var C;return j===null?"Tanpa project":((C=t.find(h=>h.id===j))==null?void 0:C.name)??j},[t]),m=d.useMemo(()=>ht(e,i,b),[e,i,b]),k=d.useMemo(()=>new Set(u),[u]),S=d.useMemo(()=>{var C;const j=[];for(const h of m){const N=h.projectId??St,M=k.has(N),A=b(h.projectId),g=h.geometry?ue({startDate:new Date(h.span.start).toISOString(),dueDate:new Date(h.span.end-1).toISOString()}):h.span?"di luar jendela · pilih zoom yang lebih lebar":"belum dijadwalkan",T=[];if(h.geometry){T.push({key:`span:${N}`,geometry:h.geometry,tone:h.geometry.invalid?"err":"envelope",title:`${A} · ${g??""}`.trim()});for(const c of h.tasks){const y=Ie(c,i);y&&T.push({key:`seg:${c.id}`,geometry:y,tone:ta(c,y),title:na(c,y,ue(c)),onClick:()=>p(c)})}}if(j.push({key:`p:${N}`,meta:g,bars:T,label:a.jsx(Ct,{testId:`expand-${N}`,open:M,name:A,count:h.tasks.length,onClick:()=>f(N)})}),!!M)for(const c of h.tasks){const y=Ie(c,i),L=((C=n.find(K=>K.id===c.memberId))==null?void 0:C.name)??"belum ditugaskan",I=ue(c);j.push({key:`t:${c.id}`,label:a.jsx("span",{className:"hn-tl-child",children:c.title}),meta:I?`${L} · ${I}`:L,bars:y?[{key:`t:${c.id}`,geometry:y,tone:ta(c,y),title:na(c,y,I),onClick:()=>p(c)}]:[]})}}return j},[m,k,b,i,n,f,p]);return a.jsxs(a.Fragment,{children:[a.jsx(pa,{envelope:!0}),a.jsx(ga,{window:i,rows:S,today:r,testId:"team-projects",labelHead:"Project",emptyHint:"Belum ada project bertanggal — isi mulai atau tenggat di kartunya."}),o>0&&a.jsxs("div",{"data-testid":"projects-truncated",className:"hn-tl-note",children:[o," tugas tak termuat karena plafon 200 per kolom — amplop project bisa lebih pendek dari rentang sebenarnya; persempit kolom, anggota, atau pencarian"]})]})}const It=Object.keys(me).map(e=>({value:e,label:me[e]})),sa=(e,t)=>({title:(e==null?void 0:e.title)??"",detail:(e==null?void 0:e.detail)??"",projectId:e?e.projectId??"":t??"",status:(e==null?void 0:e.status)??"backlog",priority:e&&e.priority in me?e.priority:"sedang",memberId:(e==null?void 0:e.memberId)??"",startDate:Ve((e==null?void 0:e.startDate)??null),dueDate:Ve((e==null?void 0:e.dueDate)??null)});function Tt({open:e,task:t,projects:n,members:l,defaultProjectId:r,orderFor:o,onClose:u,onSaved:f,onToast:p}){const[i,b]=d.useState(()=>sa(t,r)),[m,k]=d.useState(!1),{confirm:S,dialog:j}=ca(),C=`${e?"1":"0"}:${(t==null?void 0:t.id)??""}`,h=d.useRef(C);if(h.current!==C&&(h.current=C,e&&b(sa(t,r))),!e)return null;const N=g=>b(T=>({...T,...g}));async function M(){if(!i.title.trim()){p("Judul tugas wajib diisi","err","x-circle");return}k(!0);const g=!t||t.status!==i.status,T={title:i.title.trim(),detail:i.detail.trim()||null,projectId:i.projectId||null,status:i.status,priority:i.priority,memberId:i.memberId||null,startDate:We(i.startDate),dueDate:We(i.dueDate),...g?{order:o(i.status)}:{}};try{t?await D.patchTask(t.id,T):await D.createTask(T),p(t?"Tugas diperbarui":"Tugas dibuat","ok","check"),f(),u()}catch(c){p(Ce("menyimpan tugas",c),"err","x-circle")}finally{k(!1)}}async function A(){if(t){try{if(!await S({title:`Hapus "${t.title}"?`,impact:["Kartu ini hilang dari papan di semua device yang tersinkron."],confirmLabel:"Hapus tugas",tone:"danger",icon:"trash-2",run:async()=>{k(!0);try{await D.deleteTask(t.id)}finally{k(!1)}}}))return}catch(g){p(Ce("menghapus tugas",g),"err","x-circle");return}p("Tugas dihapus","ok","trash-2"),f(),u()}}return a.jsxs(a.Fragment,{children:[a.jsxs(we,{open:e,onClose:m?void 0:u,icon:"clipboard-list",eyebrow:"Papan tim",title:t?"Ubah tugas":"Tugas baru",footer:a.jsxs("div",{style:{display:"flex",gap:8,width:"100%",alignItems:"center"},children:[t&&a.jsx(U,{variant:"ghost",leftIcon:"trash-2",onClick:A,disabled:m,children:"Hapus"}),a.jsx("span",{style:{flex:1}}),a.jsx(U,{variant:"secondary",onClick:u,disabled:m,children:"Batal"}),a.jsx(U,{onClick:M,loading:m,children:t?"Simpan":"Buat tugas"})]}),children:[a.jsx($,{label:"Judul",children:a.jsx(Y,{value:i.title,"aria-label":"Judul tugas",placeholder:"mis. Rapikan halaman harga",onChange:g=>N({title:g.target.value}),style:{width:"100%"}})}),a.jsxs("div",{style:{display:"flex",gap:10,flexWrap:"wrap"},children:[a.jsx($,{label:"Project",children:a.jsx(B,{value:i.projectId,"aria-label":"Project tugas",onChange:g=>N({projectId:g.target.value}),options:[{value:"",label:"Tanpa project"},...n.map(g=>({value:g.id,label:g.name}))]})}),a.jsx($,{label:"Kolom",children:a.jsx(B,{value:i.status,"aria-label":"Kolom tugas",onChange:g=>N({status:g.target.value}),options:Z.map(g=>({value:g.key,label:g.label}))})}),a.jsx($,{label:"Prioritas",children:a.jsx(B,{value:i.priority,"aria-label":"Prioritas tugas",onChange:g=>N({priority:g.target.value}),options:It})})]}),a.jsx($,{label:"Ditugaskan ke",children:a.jsx(B,{value:i.memberId,"aria-label":"Anggota tugas",onChange:g=>N({memberId:g.target.value}),options:[{value:"",label:"Belum ditugaskan"},...l.map(g=>({value:g.id,label:g.role?`${g.name} · ${g.role}`:g.name}))],style:{width:"100%"}})}),a.jsxs("div",{style:{display:"flex",gap:10,flexWrap:"wrap"},children:[a.jsx($,{label:"Mulai",children:a.jsx(Y,{type:"date",value:i.startDate,"aria-label":"Tanggal mulai",onChange:g=>N({startDate:g.target.value})})}),a.jsx($,{label:"Tenggat",children:a.jsx(Y,{type:"date",value:i.dueDate,"aria-label":"Tanggal tenggat",onChange:g=>N({dueDate:g.target.value})})})]}),a.jsx($,{label:"Detail",hint:"Opsional — konteks yang tak muat di judul.",children:a.jsx(Aa,{value:i.detail,"aria-label":"Detail tugas",rows:4,placeholder:"mis. tunggu aset dari klien, deadline ikut jadwal kampanye",onChange:g=>N({detail:g.target.value})})})]}),j]})}const wt=Ra.map(e=>({value:e,label:_a(e).label}));function Dt({task:e,projects:t,onClose:n,onDone:l,onToast:r}){const[o,u]=d.useState("brief"),[f,p]=d.useState(()=>He.some(h=>h.value===e.priority)?e.priority:"sedang"),[i,b]=d.useState(""),[m,k]=d.useState(!1),S=e.projectId===null,j=e.projectId??i;async function C(){if(!(!j||m)){k(!0);try{const h=await D.escalateTask(e.id,{source:o,priority:f,...e.projectId?{}:{projectId:i}});r(h.created?`Dieskalasi jadi ${h.spec.id}`:`Sudah tertaut ke ${h.spec.id}`,"ok","link"),l(h.task),n()}catch(h){r(Ce("mengeskalasi kartu",h),"err","x-circle")}finally{k(!1)}}}return a.jsxs(we,{open:!0,onClose:m?void 0:n,icon:"git-branch",eyebrow:"Papan tim",title:"Kirim ke Backlog",footer:a.jsxs("div",{className:"hn-dia-foot-split",children:[a.jsx("span",{className:"hn-grow"}),a.jsx(U,{variant:"secondary",onClick:n,disabled:m,children:"Batal"}),a.jsx(U,{onClick:C,loading:m,disabled:!j,leftIcon:"git-branch",children:"Kirim ke Backlog"})]}),children:[a.jsxs("div",{className:"hn-dia-lead",children:["Kartu ",a.jsx("strong",{children:e.title})," tetap di papan. Yang lahir adalah backlog item baru yang bisa dikerjakan sesi agen, dan kartu ini menampilkan stage-nya."]}),S&&a.jsxs($,{label:"Project",children:[a.jsx(B,{"aria-label":"Project",value:i,className:"hn-dia-full",onChange:h=>b(h.target.value),options:[{value:"",label:"Pilih project…"},...t.map(h=>({value:h.id,label:h.name}))]}),a.jsx("div",{className:"hn-dia-hint",children:"Nomor SPEC diambil dari repo project, jadi kartu tanpa project belum bisa dieskalasi."})]}),a.jsx($,{label:"Source",hint:"Jenis item backlog yang lahir dari kartu ini, mis. feature brief atau Finding QA.",children:a.jsx(B,{"aria-label":"Source",value:o,className:"hn-dia-full",onChange:h=>u(h.target.value),options:wt})}),a.jsx($,{label:"Prioritas",children:a.jsx(B,{"aria-label":"Prioritas",value:f,className:"hn-dia-full",onChange:h=>p(h.target.value),options:He})})]})}function Mt({m:e,busy:t,onSave:n,onToggle:l,onDelete:r}){const[o,u]=d.useState(!1),[f,p]=d.useState(e.name),[i,b]=d.useState(e.role??"");return o?a.jsxs("div",{className:"hn-mem-edit",children:[a.jsx(Y,{size:"sm",value:f,"aria-label":`Nama ${e.name}`,placeholder:"mis. Dena Meidina",onChange:m=>p(m.target.value)}),a.jsx(Y,{size:"sm",value:i,"aria-label":`Peran ${e.name}`,placeholder:"mis. desainer",onChange:m=>b(m.target.value)}),a.jsxs("div",{className:"hn-mem-note",children:[e.email," — ganti email berarti hapus lalu buat baru."]}),a.jsxs("div",{className:"hn-mem-actions",children:[a.jsx(U,{size:"sm",disabled:t,onClick:()=>{n(e.id,{name:f.trim(),role:i.trim()||null}),u(!1)},children:"Simpan"}),a.jsx(U,{size:"sm",variant:"ghost",onClick:()=>u(!1),children:"Batal"})]})]}):a.jsxs("div",{className:`hn-dense-row hn-mem-row${e.active?"":" hn-mem-row--off"}`,children:[a.jsxs("span",{className:"hn-mem-main",children:[a.jsxs("span",{className:"hn-mem-name-row",children:[a.jsx("span",{className:"hn-mem-name",children:e.name}),e.role&&a.jsx(Ze,{tone:"neutral",size:"sm",children:e.role}),!e.active&&a.jsx(Ze,{tone:"warn",size:"sm",children:"nonaktif"})]}),a.jsx("span",{className:"hn-mem-email",children:e.email})]}),a.jsx(ke,{icon:"pencil",label:`Ubah ${e.name}`,size:"sm",onClick:()=>u(!0)}),a.jsx(ke,{icon:e.active?"user-minus":"user-check",size:"sm",label:`${e.active?"Nonaktifkan":"Aktifkan"} ${e.name}`,onClick:()=>l(e)}),a.jsx(ke,{icon:"trash-2",label:`Hapus ${e.name}`,size:"sm",onClick:()=>r(e)})]})}function Et({open:e,onClose:t,onChanged:n,onToast:l}){const[r,o]=d.useState([]),[u,f]=d.useState("loading"),[p,i]=d.useState(!1),[b,m]=d.useState(!1),[k,S]=d.useState(""),[j,C]=d.useState(""),[h,N]=d.useState(""),{confirm:M,dialog:A}=ca(),g=d.useRef(n);g.current=n;const T=d.useRef(!1),c=d.useCallback(()=>{T.current||f("loading"),D.listMembers().then(v=>{T.current=!0,o(v.items),f("ready"),i(!1),g.current(v.items)}).catch(()=>{T.current?i(!0):f("error")})},[]);if(d.useEffect(()=>{e&&c()},[e,c]),!e)return null;async function y(){if(!k.trim()||!j.trim()){l("Nama & email wajib diisi","err","x-circle");return}m(!0);try{await D.createMember({name:k.trim(),email:j.trim(),role:h.trim()||null}),S(""),C(""),N(""),l("Anggota ditambahkan","ok","user-plus"),c()}catch{l("Gagal menambah anggota — email mungkin sudah terdaftar","err","x-circle")}finally{m(!1)}}async function L(v,le){m(!0);try{await D.patchMember(v,le),c()}catch{l("Gagal menyimpan anggota","err","x-circle")}finally{m(!1)}}async function I(v){m(!0);try{await D.patchMember(v.id,{active:!v.active}),c()}catch{l("Gagal mengubah status anggota","err","x-circle")}finally{m(!1)}}async function K(v){await M({title:`Hapus ${v.name} dari direktori?`,message:"Tugasnya tidak ikut terhapus — kartu yang ditugaskan padanya jadi 'belum ditugaskan'.",confirmLabel:"Hapus anggota",tone:"danger",icon:"trash-2",run:()=>D.deleteMember(v.id)})&&(l("Anggota dihapus","ok","trash-2"),c())}return a.jsxs(a.Fragment,{children:[a.jsxs(we,{open:e,onClose:t,icon:"users",eyebrow:"Papan tim",title:"Anggota",width:620,children:[a.jsxs("div",{className:"hn-mem-add",children:[a.jsx(Y,{size:"sm",value:k,"aria-label":"Nama anggota baru",placeholder:"Nama",onChange:v=>S(v.target.value),className:"hn-mem-in-name"}),a.jsx(Y,{size:"sm",value:j,"aria-label":"Email anggota baru",placeholder:"email@nafanesia.id",onChange:v=>C(v.target.value),className:"hn-mem-in-email"}),a.jsx(Y,{size:"sm",value:h,"aria-label":"Peran anggota baru",placeholder:"Peran (opsional)",onChange:v=>N(v.target.value),className:"hn-mem-in-role"}),a.jsx(U,{size:"sm",leftIcon:"user-plus",onClick:y,loading:b,children:"Tambah anggota"})]}),p&&a.jsx(Ua,{tone:"err",title:"Gagal memuat ulang anggota",className:"hn-mem-alert",action:a.jsx(U,{size:"sm",variant:"ghost",onClick:c,children:"Coba lagi"}),children:"Yang tampil di bawah adalah data lama. Coba lagi untuk memuat yang terbaru."}),u==="loading"?a.jsx(W,{kind:"loading",compact:!0}):u==="error"?a.jsx(W,{kind:"error",compact:!0,hint:"Gagal memuat anggota.",action:c,actionLabel:"Coba lagi"}):r.length===0?a.jsx(W,{kind:"empty",compact:!0,icon:"users",title:"Belum ada anggota",hint:"Tambahkan orang di atas agar kartu papan bisa ditugaskan."}):r.map(v=>a.jsx(Mt,{m:v,busy:b,onSave:L,onToggle:I,onDelete:K},v.id))]}),A]})}const $t=5e3,la=200,Lt=400,_="me",H="all",ia=[{value:"board",label:"Papan",icon:"kanban"},{value:"timeline",label:"Linimasa",icon:"gantt-chart"},{value:"projects",label:"Lintas project",icon:"layers"}],Ot={day:"Hari",week:"Minggu",month:"Bulan"},Pt=()=>Object.fromEntries(Z.map(e=>[e.key,0]));function Bt({status:e,params:t,onData:n,refetch:l}){return Wa({topic:"tasks",params:{...t,status:e},apply:r=>n(e,r.data.items,r.data.total),refetch:l,pollMs:$t}),null}function Kt({projects:e,projectFilter:t,onProjectFilter:n,onToast:l,onOpenSpec:r}){var Ke,ze,Ge;const[o,u]=d.useState(Qa),[f,p]=d.useState(Pt),[i,b]=d.useState([]),[m,k]=d.useState(""),[S,j]=d.useState("loading"),[C,h]=d.useState(!1),[N,M]=d.useState(null),[A,g]=d.useState(!1),[T,c]=d.useState(!1),[y,L]=d.useState(null),[I,K]=d.useState(null),[v,le]=Fa(),[he,ba]=X("team","view","board",Ye(...ia.map(s=>s.value))),[V,pe]=X("team","q","",xe),[z,ie]=X("team","col","all",xe),[P,ae]=X("team","member",_,xe),[ge,fa]=X("team","zoom","week",Ye(...Qe)),[ja,De]=X("team","expanded",[],Va),ka=d.useCallback(s=>{De(x=>x.includes(s)?x.filter(w=>w!==s):[...x,s])},[De]),Me=he==="timeline",F=he==="projects",Ee=d.useRef(Date.now()).current;d.useEffect(()=>{var w,E;let s=!0;const x=(E=(w=D).authStatus)==null?void 0:E.call(w);return x==null||x.then(O=>{var R;s&&K(((R=O.user)==null?void 0:R.email)??null)}).catch(()=>{s&&K(null)}),()=>{s=!1}},[]);const G=d.useMemo(()=>z==="all"?Z:Z.filter(s=>s.key===z),[z]),be=G.map(s=>s.key).join(","),fe=F||t==="all"?void 0:t,re=d.useMemo(()=>{if(!I)return null;const s=Ka(I);return i.some(x=>x.id===s)?s:null},[I,i]),oe=P===_?re??void 0:P===H?void 0:P,$e=P!==_&&P!==H,Q=d.useMemo(()=>({projectId:fe,memberId:oe,q:V.trim()||void 0}),[fe,oe,V]),ce=d.useRef(!1),te=d.useCallback((s=!1)=>{!s&&!ce.current&&j("loading");const x=be?be.split(","):[];Promise.all(x.map(w=>D.listTasks({...Q,status:w,page:1,limit:la}))).then(w=>{u(E=>{const O={...E};return x.forEach((R,ne)=>{O[R]=w[ne].items}),O}),p(E=>{const O={...E};return x.forEach((R,ne)=>{O[R]=w[ne].total}),O}),ce.current=!0,h(!1),j("ready")}).catch(()=>{if(!ce.current){j("error");return}h(!0)})},[Q,be]);d.useEffect(()=>{te()},[te]);const Le=d.useCallback(()=>{D.listMembers().then(s=>{b(s.items),k("")}).catch(s=>k(za(s,"tidak diketahui")))},[]);d.useEffect(()=>{Le()},[Le]);const[Oe,xa]=d.useState(()=>V.trim());d.useEffect(()=>{const s=setTimeout(()=>xa(V.trim()),Lt);return()=>clearTimeout(s)},[V]);const ya=d.useCallback((s,x,w)=>{u(E=>({...E,[s]:x})),p(E=>({...E,[s]:w})),ce.current=!0,h(!1),j("ready")},[]),va=d.useMemo(()=>({projectId:Q.projectId,memberId:Q.memberId,q:Oe||void 0,page:1,limit:la}),[Q.projectId,Q.memberId,Oe]),de=d.useCallback(()=>te(!0),[te]);async function Sa(s,x){var O;const w=Xa(o,s.id,s.status,x);if(!w)return;const E=o;u(w.board);try{await D.patchTask(s.id,w.patch);const R=((O=Z.find(ne=>ne.key===x))==null?void 0:O.label)??x;le(`Tugas dipindah ke ${R}`,"ok",void 0,{action:{label:"Urungkan",onAction:()=>{Pe(s.id,{status:s.status})}}})}catch{u(E),l("Gagal memindahkan tugas","err","x-circle")}}async function Ca(s,x){var E;const w=o;u(ye(o,{...s,memberId:x}));try{await D.patchTask(s.id,{memberId:x});const O=x?((E=i.find(R=>R.id===x))==null?void 0:E.name)??"anggota":null;le(O?`Ditugaskan ke ${O}`:"Penugasan dikosongkan","ok",void 0,{action:{label:"Urungkan",onAction:()=>{Pe(s.id,{memberId:s.memberId})}}})}catch{u(w),l("Gagal menugaskan","err","x-circle")}}async function Pe(s,x){try{await D.patchTask(s,x),de()}catch{l("Gagal mengurungkan perubahan","err","x-circle")}}async function Na(s){const x=o;u(ye(o,{...s,specId:null,spec:null}));try{await D.unlinkTaskSpec(s.id),l("Tautan backlog dilepas","ok","unlink")}catch{u(x),l("Gagal melepas tautan","err","x-circle")}}const Be=G.every(s=>o[s.key].length===0),je=V.trim()!=="",Ae=(!F&&t!=="all"?1:0)+(z!=="all"?1:0)+($e?1:0),Re=Ae>0||je||oe!==void 0,Ia=((Ke=e.find(s=>s.id===t))==null?void 0:Ke.name)??t,Ta=((ze=i.find(s=>s.id===P))==null?void 0:ze.name)??P,wa=((Ge=Z.find(s=>s.key===z))==null?void 0:Ge.label)??z,Da=()=>{F||n("all"),ie("all"),ae(_),pe("")},Ma=()=>{F||n("all"),ie("all"),ae(H),pe("")},_e=d.useMemo(()=>G.flatMap(s=>o[s.key]),[o,G]),Ue=G.reduce((s,x)=>s+Math.max(0,(f[x.key]??0)-o[x.key].length),0),Ea=G.reduce((s,x)=>s+(f[x.key]??0),0),Fe=[...!F&&t!=="all"?[{key:"project",label:`Project: ${Ia}`,onRemove:()=>n("all")}]:[],...z!=="all"?[{key:"col",label:`Kolom: ${wa}`,onRemove:()=>ie("all")}]:[],...$e?[{key:"member",label:`Anggota: ${Ta}`,onRemove:()=>ae(_)}]:[]],$a=[...re?[{value:_,label:"Saya"}]:[],{value:H,label:"Semua anggota"},...i.map(s=>({value:s.id,label:s.name}))],La=P===_&&!re?H:P,Oa=a.jsxs(Ga,{gap:3,children:[a.jsx($,{label:"Project",children:a.jsx(B,{size:"sm","aria-label":"Filter project",value:t,disabled:F,onChange:s=>n(s.target.value),options:[{value:"all",label:"Semua project"},...e.map(s=>({value:s.id,label:s.name}))]})}),F&&a.jsx("p",{"data-testid":"project-filter-note",className:"hn-tm-hint",children:"Mode ini melintasi semua project"}),a.jsx($,{label:"Anggota",children:a.jsx(B,{size:"sm","aria-label":"Filter anggota",value:La,disabled:!!m,onChange:s=>ae(s.target.value),options:$a})}),m&&a.jsxs("p",{role:"alert",className:"hn-tm-hint hn-tm-alert",children:["Anggota gagal dimuat: ",m]}),a.jsx($,{label:"Kolom",children:a.jsx(B,{size:"sm","aria-label":"Filter kolom",value:z,onChange:s=>ie(s.target.value),options:[{value:"all",label:"Semua kolom"},...Z.map(s=>({value:s.key,label:s.label}))]})}),(Me||F)&&a.jsx($,{label:"Zoom",children:a.jsx(B,{size:"sm","aria-label":"Zoom linimasa",value:ge,onChange:s=>fa(s.target.value),options:Qe.map(s=>({value:s,label:Ot[s]}))})})]});return a.jsxs("div",{className:"hn-tm-screen",children:[a.jsxs("section",{className:"hn-tm-toolbar",role:"region","aria-label":"Kontrol papan tim",children:[a.jsxs("div",{className:"hn-tm-switches",children:[a.jsx(Se,{variant:"pill",value:he,onChange:ba,tabs:ia,"aria-label":"Mode tampilan"}),re&&a.jsx(Se,{variant:"pill","aria-label":"Lensa tugas",value:P===H?H:P===_?_:"",onChange:s=>ae(s),tabs:[{value:_,label:"Saya"},{value:H,label:"Semua"}]}),a.jsxs("span",{className:"hn-tm-count",role:"status",title:C?"Server tak menjawab saat menyegarkan — angka ini dari muatan terakhir yang berhasil":void 0,children:[Ea," tugas",C?" · data lama":""]}),a.jsx(qa,{})]}),a.jsx(Ha,{label:"Penyaring tim",search:{value:V,onChange:pe,label:"Cari tugas",placeholder:"mis. halaman harga atau deploy"},chips:Fe,filters:Oa,filtersLabel:"Filter",onReset:Fe.length>0||je?Da:void 0,resetLabel:"Reset filter",actions:a.jsxs(a.Fragment,{children:[a.jsx(U,{size:"sm",leftIcon:"plus",onClick:()=>{M(null),g(!0)},children:"Tugas baru"}),a.jsx(Za,{onDone:de,onToast:l}),a.jsx(oa,{label:"Lainnya",items:[{key:"members",label:"Anggota tim",icon:"users",onSelect:()=>c(!0)}]})]})})]}),G.map(s=>a.jsx(Bt,{status:s.key,params:va,onData:ya,refetch:de},s.key)),S==="loading"?a.jsx(W,{kind:"loading"}):S==="error"?a.jsx(W,{kind:"error",hint:"Gagal memuat papan tim.",action:()=>te(),actionLabel:"Coba lagi"}):Be&&!Re?a.jsx(W,{kind:"empty",icon:"users",title:"Papan tim masih kosong",hint:"Catat pekerjaan manusia di sekitar sesi agen — desain, meeting klien, deploy, nego.",action:()=>{M(null),g(!0)},actionLabel:"Tugas baru",actionIcon:"plus"}):a.jsxs(a.Fragment,{children:[Be&&Re&&a.jsx(W,{kind:"empty",compact:!0,icon:"filter",title:oe!==void 0&&Ae===0&&!je?"Tak ada tugas untuk kamu":"Tak ada tugas yang cocok dengan filter",hint:"Penyaring yang aktif menyembunyikan semua tugas di papan ini.",action:Ma,actionLabel:"Tampilkan semua",actionIcon:"x"}),F?a.jsx(Nt,{tasks:_e,projects:e,members:i,zoom:ge,today:Ee,hidden:Ue,expanded:ja,onToggle:ka,onOpen:s=>{M(s),g(!0)}}):Me?a.jsx(vt,{tasks:_e,members:i,zoom:ge,today:Ee,hidden:Ue,onOpen:s=>{M(s),g(!0)}}):a.jsx(kt,{board:o,totals:f,columns:G,members:i,projects:e,onOpenSpec:r,onMove:Sa,onAssign:Ca,onEscalate:L,onUnlink:Na,onOpen:s=>{M(s),g(!0)}})]}),a.jsx(Tt,{open:A,task:N,projects:e,members:i,defaultProjectId:fe??null,orderFor:s=>da(o[s]),onClose:()=>{g(!1),M(null)},onSaved:de,onToast:l}),y&&a.jsx(Dt,{task:y,projects:e,onClose:()=>L(null),onDone:s=>u(x=>ye(x,s)),onToast:l}),a.jsx(Et,{open:T,onClose:()=>c(!1),onChanged:b,onToast:l}),a.jsx(Ya,{toast:v})]})}export{ia as TEAM_VIEWS,Kt as TeamScreen};
1
+ import{T as ra,a as Pa,b as Ba,j as a,c as Se,O as oa,P as me,I as q,d as ca,M as we,e as $,f as Y,g as B,H as Aa,B as U,h as D,i as Ce,k as He,E as Ra,s as _a,C as Ua,m as W,n as Ze,o as ke,p as Fa,q as X,r as Ye,t as Ka,v as za,w as Ga,x as Ha,y as Za,z as Ya,A as Va,D as xe,G as Wa}from"./index-DYWU10xI.js";import{R as d}from"./react-DfGhg7ZW.js";import{L as qa}from"./live-C90Zx0h6.js";import"./markdown-CWEY34jk.js";import"./xterm-3VOAfa_q.js";const Ja=Pa,Z=ra.map(e=>({key:e,label:Ja[e]})),Qa=()=>Object.fromEntries(ra.map(e=>[e,[]])),Ne=(e,t)=>e!==t,da=e=>e.length===0?0:e.reduce((t,n)=>n.order>t?n.order:t,-1/0)+1;function Xa(e,t,n,l){if(!Ne(n,l))return null;const r=e[n].find(f=>f.id===t);if(!r)return null;const o={status:l,order:da(e[l])},u={...e};return u[n]=e[n].filter(f=>f.id!==t),u[l]=[...e[l],{...r,...o}],{board:u,patch:o}}function ye(e,t){const n={...e};return n[t.status]=e[t.status].map(l=>l.id===t.id?t:l),n}const Ve=e=>e?e.slice(0,10):"",We=e=>/^\d{4}-\d{2}-\d{2}$/.test(e)?`${e}T12:00:00.000Z`:null,J=864e5,se=e=>Math.floor(e/J)*J,qe=e=>{if(!e)return null;const t=new Date(e).getTime();return Number.isFinite(t)?t:null};function ee(e){const t=qe(e.startDate),n=qe(e.dueDate);if(t===null&&n===null)return null;const l=t??n,r=n??t;return{start:se(Math.min(l,r)),end:se(Math.max(l,r))+J,invalid:r<l}}const et=new Intl.DateTimeFormat("id-ID",{day:"numeric",month:"short",timeZone:"UTC"}),Je=e=>e?et.format(new Date(e)):null;function ue(e){const t=Je(e.startDate),n=Je(e.dueDate);return t&&n?`${t} → ${n}`:n?`→ ${n}`:t}const Qe=["day","week","month"],ua={day:{cell:34,minTicks:14},week:{cell:56,minTicks:8},month:{cell:84,minTicks:6}},at=e=>ua[e].cell,tt=120,nt=(e,t)=>{const n=se(e);if(t==="day")return n;if(t==="week")return n-(new Date(n).getUTCDay()+6)%7*J;const l=new Date(n);return Date.UTC(l.getUTCFullYear(),l.getUTCMonth(),1)},st=(e,t)=>{if(t==="day")return e+J;if(t==="week")return e+7*J;const n=new Date(e);return Date.UTC(n.getUTCFullYear(),n.getUTCMonth()+1,1)},lt=new Intl.DateTimeFormat("id-ID",{day:"numeric",timeZone:"UTC"}),Xe=new Intl.DateTimeFormat("id-ID",{day:"numeric",month:"short",timeZone:"UTC"}),it=new Intl.DateTimeFormat("id-ID",{month:"short",timeZone:"UTC"}),rt=new Intl.DateTimeFormat("id-ID",{month:"short",year:"2-digit",timeZone:"UTC"}),ot=(e,t)=>{const n=new Date(e);return t==="day"?n.getUTCDate()===1:t==="week"?n.getUTCDate()<=7:n.getUTCMonth()===0},ct=(e,t,n)=>{const l=new Date(e);return t==="day"?(n?Xe:lt).format(l):t==="week"?Xe.format(l):(n?rt:it).format(l)};function ma(e,t,n){const l=se(n);let r=l,o=l+J;for(const b of e)b.start<r&&(r=b.start),b.end>o&&(o=b.end);const u=nt(r,t),{minTicks:f}=ua[t],p=[];let i=u;for(;p.length<tt&&(i<o||p.length<f);){const b=ot(i,t);p.push({start:i,label:ct(i,t,b),major:b}),i=st(i,t)}return{from:u,to:i,zoom:t,ticks:p}}function ha(e,t){const n=t.to-t.from;if(n<=0||e.end<=t.from||e.start>=t.to)return null;const l=Math.max(e.start,t.from),r=Math.min(e.end,t.to);return{left:(l-t.from)/n*100,width:(r-l)/n*100,clippedStart:e.start<t.from,clippedEnd:e.end>t.to,invalid:e.invalid}}function Ie(e,t){const n=ee(e);return n?ha(n,t):null}function dt(e){let t=1/0,n=-1/0,l=!1;for(const r of e){const o=ee(r);o&&(o.start<t&&(t=o.start),o.end>n&&(n=o.end),o.invalid&&(l=!0))}return t===1/0?null:{start:t,end:n,invalid:l}}function ut(e,t){const n=se(t);return n<e.from||n>=e.to?null:(n-e.from)/(e.to-e.from)*100}function mt(e,t){const n=[],l=[],r=[];for(const o of e){const u=ee(o);if(!u){l.push(o);continue}const f=Ie(o,t);if(!f){r.push(o);continue}n.push({task:o,geometry:f,start:u.start})}return n.sort((o,u)=>o.start-u.start||o.task.title.localeCompare(u.task.title,"id")||o.task.id.localeCompare(u.task.id)),{rows:n.map(({task:o,geometry:u})=>({task:o,geometry:u})),unscheduled:l,outside:r}}const ea=(e,t)=>e.title.localeCompare(t.title,"id")||e.id.localeCompare(t.id);function ht(e,t,n){const l=Symbol("no-project"),r=new Map;for(const p of e){const i=p.projectId??l,b=r.get(i);b?b.tasks.push(p):r.set(i,{projectId:p.projectId,tasks:[p]})}const o=[...r.values()].map(({projectId:p,tasks:i})=>{const b=dt(i),m=[],k=[];for(const S of i){const j=ee(S);j?m.push({task:S,start:j.start}):k.push(S)}return m.sort((S,j)=>S.start-j.start||ea(S.task,j.task)),k.sort(ea),{projectId:p,span:b,geometry:b?ha(b,t):null,tasks:[...m.map(S=>S.task),...k]}}),u=p=>p.geometry?0:p.span?1:2,f=p=>p.projectId===null?[1,""]:[0,p.projectId];return o.sort((p,i)=>{const[b,m]=f(p),[k,S]=f(i);return u(p)-u(i)||(p.span&&i.span?p.span.start-i.span.start:0)||n(p.projectId).localeCompare(n(i.projectId),"id")||b-k||m.localeCompare(S)}),o}const pt={tinggi:"high",sedang:"mid",rendah:"low"};function gt({priority:e}){const t=pt[e]??"mid",n=me[e]??e;return a.jsx("span",{className:`hn-tm-prio hn-tm-prio-${t}`,title:`Prioritas ${n}`,children:a.jsxs("span",{className:"hn-sr-only",children:["Prioritas ",n]})})}function bt({name:e}){if(!e)return a.jsx("span",{className:"hn-tm-avatar hn-tm-avatar-empty","aria-hidden":"true",children:a.jsx(q,{name:"user",size:12})});const t=e.split(/\s+/).filter(Boolean).slice(0,2).map(n=>n[0].toUpperCase()).join("");return a.jsx("span",{className:"hn-tm-avatar","aria-hidden":"true",children:t||"?"})}function ft(e,t,n){const l=[...Z.filter(r=>r.key!==e.status).map(r=>({key:`move-${r.key}`,label:`Pindah ke ${r.label}`,onSelect:()=>n.onMove(e,r.key)})),...t.map(r=>({key:`assign-${r.id}`,label:`Tugaskan ke ${r.name}`,disabled:e.memberId===r.id,onSelect:()=>n.onAssign(e,r.id)})),{key:"assign-none",label:"Kosongkan penugasan",disabled:!e.memberId,onSelect:()=>n.onAssign(e,null)}];if(e.specId){if(e.spec&&n.onOpenSpec){const r=e.specId;l.push({key:"open-spec",label:`Buka ${e.spec.id} di Backlog`,onSelect:()=>{var o;return(o=n.onOpenSpec)==null?void 0:o.call(n,r)}})}l.push({key:"unlink",label:e.spec?"Lepas tautan":"Lepas tautan (spec tak ditemukan)",onSelect:()=>n.onUnlink(e)})}else l.push({key:"escalate",label:"Kirim ke Backlog",onSelect:()=>n.onEscalate(e)});return l}function jt({task:e,members:t,projectName:n,dragging:l,onDragStart:r,onDragEnd:o,onOpen:u,onMove:f,onAssign:p,onEscalate:i,onUnlink:b,onOpenSpec:m}){var C;const k=((C=t.find(h=>h.id===e.memberId))==null?void 0:C.name)??null,S=ft(e,t,{onMove:f,onAssign:p,onEscalate:i,onUnlink:b,onOpenSpec:m}),j=e.projectId===null?"tanpa project":n??"project tak dikenal";return a.jsxs("div",{draggable:!0,"data-testid":`team-card-${e.id}`,className:"hn-tm-card","data-dragging":l||void 0,title:`Project: ${j}`,onDragStart:h=>{h.dataTransfer.effectAllowed="move",h.dataTransfer.setData("text/plain",e.id),r()},onDragEnd:o,children:[a.jsxs("div",{className:"hn-tm-card-head",children:[a.jsx(gt,{priority:e.priority}),a.jsx("button",{type:"button",className:"hn-tm-title",onClick:()=>u(e),children:e.title})]}),a.jsxs("div",{className:"hn-tm-card-foot",children:[a.jsxs("span",{className:"hn-tm-assignee-wrap",children:[a.jsx(bt,{name:k}),a.jsx("span",{className:"hn-tm-assignee",children:k??"belum ditugaskan"})]}),a.jsx(oa,{label:`Ubah tugas: ${e.title}`,icon:"ellipsis",items:S})]})]})}function kt({board:e,totals:t,columns:n,members:l,projects:r=[],onMove:o,onAssign:u,onOpen:f,onEscalate:p,onUnlink:i,onOpenSpec:b}){var T;const[m,k]=d.useState(null),[S,j]=d.useState(null),C=Ba(),[h,N]=d.useState(((T=n[0])==null?void 0:T.key)??"backlog"),M=d.useMemo(()=>{const c=new Map(r.map(y=>[y.id,y.name]));return y=>y===null?null:c.get(y)??null},[r]),A=c=>{m&&Ne(m.from,c)&&o(m.task,c),k(null),j(null)},g=(c,y)=>a.jsx(jt,{task:c,members:l,projectName:M(c.projectId),dragging:(m==null?void 0:m.task.id)===c.id,onDragStart:()=>k({task:c,from:y}),onDragEnd:()=>{k(null),j(null)},onOpen:f,onMove:o,onAssign:u,onEscalate:p,onUnlink:i,onOpenSpec:b},c.id);if(C==="mobile"){const c=n.find(I=>I.key===h)??n[0];if(!c)return null;const y=e[c.key],L=Math.max(0,(t[c.key]??0)-y.length);return a.jsxs("div",{"data-testid":"team-board","data-layout":"mobile",className:"hn-tm-mobile",children:[a.jsx(Se,{variant:"pill","aria-label":"Kolom papan tim",value:c.key,onChange:I=>N(I),tabs:n.map(I=>({value:I.key,label:`${I.label} · ${e[I.key].length}`}))}),a.jsxs("div",{"data-testid":`team-col-${c.key}`,className:"hn-tm-col-stack",children:[y.map(I=>g(I,c.key)),y.length===0&&a.jsxs("div",{className:"hn-tm-empty-col",children:["Tak ada tugas di ",c.label,"."]}),L>0&&a.jsxs("div",{className:"hn-tm-hidden-note",children:["menampilkan ",y.length," dari ",t[c.key]," — persempit penyaring"]})]})]})}return a.jsx("div",{"data-testid":"team-board",className:"hn-board-local-overflow hn-tm-board",children:n.map(c=>{const y=e[c.key],L=!!m&&Ne(m.from,c.key),I=L&&S===c.key,K=Math.max(0,(t[c.key]??0)-y.length);return a.jsxs("div",{"data-testid":`team-col-${c.key}`,className:"hn-tm-col","data-active":L||void 0,"data-hot":I||void 0,"data-dimmed":m&&!L||void 0,onDragOver:v=>{L&&(v.preventDefault(),v.dataTransfer.dropEffect="move",j(c.key))},onDragLeave:()=>j(v=>v===c.key?null:v),onDrop:v=>{v.preventDefault(),A(c.key)},children:[a.jsxs("div",{className:"hn-tm-col-head",children:[a.jsx("span",{className:"hn-eyebrow",children:c.label}),a.jsx("span",{className:"hn-tm-col-count",children:y.length})]}),a.jsx("div",{className:"hn-tm-col-body",children:y.map(v=>g(v,c.key))}),K>0&&a.jsxs("div",{className:"hn-tm-hidden-note",children:["menampilkan ",y.length," dari ",t[c.key]," — persempit penyaring"]})]},c.key)})})}const ve=232,xt={brass:"var(--brass-500)",err:"var(--status-err)",muted:"var(--border-strong)",envelope:"var(--border-hair)"},Te=e=>e;function yt({spec:e}){const t=e.geometry,n=xt[e.tone],l=!!e.onClick,r={"data-testid":`timeline-bar-${e.key}`,"data-tone":e.tone,"data-invalid":t.invalid?"true":"false","data-clipped-start":t.clippedStart?"true":"false","data-clipped-end":t.clippedEnd?"true":"false",title:e.title,"aria-label":e.title,onClick:e.onClick,className:"hn-tl-bar",style:Te({"--tl-left":`${t.left}%`,"--tl-width":`${t.width}%`})},o=a.jsxs(a.Fragment,{children:[t.invalid&&a.jsx(q,{name:"triangle-alert",size:11,color:n}),t.clippedStart&&a.jsx(q,{name:"chevron-left",size:11,color:n}),a.jsx("span",{className:"hn-grow"}),t.clippedEnd&&a.jsx(q,{name:"chevron-right",size:11,color:n})]});return l?a.jsx("button",{type:"button",...r,children:o}):a.jsx("div",{role:"img",...r,children:o})}function pa({envelope:e=!1}){const t=n=>a.jsx("span",{"aria-hidden":"true",className:"hn-tl-swatch","data-tone":n});return a.jsxs("ul",{"aria-label":"Legenda linimasa",className:"hn-tl-legend",children:[a.jsxs("li",{className:"hn-tl-legend-item",children:[t("brass"),"Rencana"]}),a.jsxs("li",{className:"hn-tl-legend-item",children:[t("muted"),"Selesai"]}),a.jsxs("li",{className:"hn-tl-legend-item",children:[t("err"),a.jsx(q,{name:"triangle-alert",size:11,color:"var(--status-err)"}),"Tenggat mendahului mulai"]}),e&&a.jsxs("li",{className:"hn-tl-legend-item",children:[t("envelope"),"Rentang project (buka lewat namanya)"]})]})}function ga({window:e,rows:t,today:n,emptyHint:l,testId:r,labelHead:o}){const u=at(e.zoom),f=e.ticks.length*u,p=ut(e,n);return a.jsx("div",{"data-testid":r??"team-timeline",className:"hn-timeline-scroll hn-tl-scroll",children:a.jsxs("div",{"data-testid":"timeline-canvas",className:"hn-tl",style:Te({"--tl-label-w":`${ve}px`,"--tl-cell":`${u}px`,"--tl-ticks":String(e.ticks.length),"--tl-track-w":`${f}px`,"--tl-canvas-w":`${ve+f}px`}),children:[a.jsxs("div",{className:"hn-tl-head",children:[a.jsx("div",{className:"hn-tl-label",children:a.jsx("span",{className:"hn-eyebrow",children:o??"Tugas"})}),a.jsx("div",{className:"hn-tl-ticks",children:e.ticks.map(i=>a.jsx("div",{"data-testid":"timeline-tick","data-major":i.major?"true":"false",className:"hn-tl-tick",children:i.label},i.start))})]}),t.length===0?a.jsx("div",{"data-testid":"timeline-empty",className:"hn-tl-empty",children:l??"Tak ada yang bisa dihamparkan di jendela ini."}):t.map(i=>a.jsxs("div",{"data-testid":`timeline-row-${i.key}`,className:"hn-tl-row",children:[a.jsxs("div",{className:"hn-tl-label",children:[a.jsx("div",{className:"hn-tl-label-text",children:i.label}),i.meta&&a.jsx("div",{className:"hn-tl-label-meta",children:i.meta})]}),a.jsx("div",{className:"hn-tl-track",children:i.bars.map(b=>a.jsx(yt,{spec:b},b.key))})]},i.key)),p!==null&&a.jsx("div",{"data-testid":"timeline-today","aria-hidden":"true",className:"hn-tl-today",style:Te({"--tl-today-x":`${ve+p/100*f}px`})})]})})}function aa({testId:e,icon:t,title:n,hint:l,tasks:r,onOpen:o}){return r.length===0?null:a.jsxs("div",{"data-testid":e,className:"hn-tl-aside",children:[a.jsxs("div",{className:"hn-tl-aside-head",children:[a.jsx(q,{name:t,size:13,color:"var(--text-subtle)"}),a.jsxs("span",{className:"hn-eyebrow",children:[n," · ",r.length]}),l&&a.jsx("span",{className:"hn-tl-aside-hint",children:l})]}),a.jsx("div",{className:"hn-tl-aside-list",children:r.map(u=>a.jsx("button",{type:"button",onClick:()=>o(u),className:"hn-tl-chip",children:u.title},u.id))})]})}function vt({tasks:e,members:t,zoom:n,today:l,hidden:r,onOpen:o}){const u=d.useMemo(()=>{const m=e.map(ee).filter(k=>k!==null);return ma(m,n,l)},[e,n,l]),{rows:f,unscheduled:p,outside:i}=d.useMemo(()=>mt(e,u),[e,u]),b=d.useMemo(()=>f.map(({task:m,geometry:k})=>{var h;const S=((h=t.find(N=>N.id===m.memberId))==null?void 0:h.name)??"belum ditugaskan",j=ue(m),C=[k.invalid?"tenggat mendahului mulai":null,k.clippedStart||k.clippedEnd?"melewati tepi jendela":null].filter(Boolean);return{key:m.id,label:m.title,meta:j?`${S} · ${j}`:S,bars:[{key:m.id,geometry:k,tone:k.invalid?"err":m.status==="done"?"muted":"brass",title:[m.title,j,...C].filter(Boolean).join(" · "),onClick:()=>o(m)}]}}),[f,t,o]);return a.jsxs(a.Fragment,{children:[a.jsx(pa,{}),a.jsx(ga,{window:u,rows:b,today:l,emptyHint:"Belum ada tugas bertanggal — isi mulai atau tenggat di kartunya."}),r>0&&a.jsxs("div",{"data-testid":"timeline-truncated",className:"hn-tl-note",children:[r," tugas tak termuat karena plafon 200 per kolom — persempit penyaring"]}),a.jsx(aa,{testId:"timeline-unscheduled",icon:"calendar-off",title:"Belum dijadwalkan",tasks:p,onOpen:o}),a.jsx(aa,{testId:"timeline-outside",icon:"chevrons-left-right",title:"Di luar jendela",hint:"pilih zoom yang lebih lebar",tasks:i,onOpen:o})]})}const St="__none__",ta=(e,t)=>t.invalid?"err":e.status==="done"?"muted":"brass",na=(e,t,n)=>[e.title,n,t.invalid?"tenggat mendahului mulai":null,t.clippedStart||t.clippedEnd?"melewati tepi jendela":null].filter(Boolean).join(" · ");function Ct({testId:e,open:t,name:n,count:l,onClick:r}){return a.jsxs("button",{type:"button",onClick:r,"data-testid":e,"aria-expanded":t,className:"hn-tl-expand",children:[a.jsx(q,{name:t?"chevron-down":"chevron-right",size:12,color:"var(--text-subtle)"}),a.jsx("span",{className:"hn-tl-expand-name",children:n}),a.jsx("span",{className:"hn-tl-expand-count",children:l})]})}function Nt({tasks:e,projects:t,members:n,zoom:l,today:r,hidden:o,expanded:u,onToggle:f,onOpen:p}){const i=d.useMemo(()=>{const j=e.map(ee).filter(C=>C!==null);return ma(j,l,r)},[e,l,r]),b=d.useCallback(j=>{var C;return j===null?"Tanpa project":((C=t.find(h=>h.id===j))==null?void 0:C.name)??j},[t]),m=d.useMemo(()=>ht(e,i,b),[e,i,b]),k=d.useMemo(()=>new Set(u),[u]),S=d.useMemo(()=>{var C;const j=[];for(const h of m){const N=h.projectId??St,M=k.has(N),A=b(h.projectId),g=h.geometry?ue({startDate:new Date(h.span.start).toISOString(),dueDate:new Date(h.span.end-1).toISOString()}):h.span?"di luar jendela · pilih zoom yang lebih lebar":"belum dijadwalkan",T=[];if(h.geometry){T.push({key:`span:${N}`,geometry:h.geometry,tone:h.geometry.invalid?"err":"envelope",title:`${A} · ${g??""}`.trim()});for(const c of h.tasks){const y=Ie(c,i);y&&T.push({key:`seg:${c.id}`,geometry:y,tone:ta(c,y),title:na(c,y,ue(c)),onClick:()=>p(c)})}}if(j.push({key:`p:${N}`,meta:g,bars:T,label:a.jsx(Ct,{testId:`expand-${N}`,open:M,name:A,count:h.tasks.length,onClick:()=>f(N)})}),!!M)for(const c of h.tasks){const y=Ie(c,i),L=((C=n.find(K=>K.id===c.memberId))==null?void 0:C.name)??"belum ditugaskan",I=ue(c);j.push({key:`t:${c.id}`,label:a.jsx("span",{className:"hn-tl-child",children:c.title}),meta:I?`${L} · ${I}`:L,bars:y?[{key:`t:${c.id}`,geometry:y,tone:ta(c,y),title:na(c,y,I),onClick:()=>p(c)}]:[]})}}return j},[m,k,b,i,n,f,p]);return a.jsxs(a.Fragment,{children:[a.jsx(pa,{envelope:!0}),a.jsx(ga,{window:i,rows:S,today:r,testId:"team-projects",labelHead:"Project",emptyHint:"Belum ada project bertanggal — isi mulai atau tenggat di kartunya."}),o>0&&a.jsxs("div",{"data-testid":"projects-truncated",className:"hn-tl-note",children:[o," tugas tak termuat karena plafon 200 per kolom — amplop project bisa lebih pendek dari rentang sebenarnya; persempit kolom, anggota, atau pencarian"]})]})}const It=Object.keys(me).map(e=>({value:e,label:me[e]})),sa=(e,t)=>({title:(e==null?void 0:e.title)??"",detail:(e==null?void 0:e.detail)??"",projectId:e?e.projectId??"":t??"",status:(e==null?void 0:e.status)??"backlog",priority:e&&e.priority in me?e.priority:"sedang",memberId:(e==null?void 0:e.memberId)??"",startDate:Ve((e==null?void 0:e.startDate)??null),dueDate:Ve((e==null?void 0:e.dueDate)??null)});function Tt({open:e,task:t,projects:n,members:l,defaultProjectId:r,orderFor:o,onClose:u,onSaved:f,onToast:p}){const[i,b]=d.useState(()=>sa(t,r)),[m,k]=d.useState(!1),{confirm:S,dialog:j}=ca(),C=`${e?"1":"0"}:${(t==null?void 0:t.id)??""}`,h=d.useRef(C);if(h.current!==C&&(h.current=C,e&&b(sa(t,r))),!e)return null;const N=g=>b(T=>({...T,...g}));async function M(){if(!i.title.trim()){p("Judul tugas wajib diisi","err","x-circle");return}k(!0);const g=!t||t.status!==i.status,T={title:i.title.trim(),detail:i.detail.trim()||null,projectId:i.projectId||null,status:i.status,priority:i.priority,memberId:i.memberId||null,startDate:We(i.startDate),dueDate:We(i.dueDate),...g?{order:o(i.status)}:{}};try{t?await D.patchTask(t.id,T):await D.createTask(T),p(t?"Tugas diperbarui":"Tugas dibuat","ok","check"),f(),u()}catch(c){p(Ce("menyimpan tugas",c),"err","x-circle")}finally{k(!1)}}async function A(){if(t){try{if(!await S({title:`Hapus "${t.title}"?`,impact:["Kartu ini hilang dari papan di semua device yang tersinkron."],confirmLabel:"Hapus tugas",tone:"danger",icon:"trash-2",run:async()=>{k(!0);try{await D.deleteTask(t.id)}finally{k(!1)}}}))return}catch(g){p(Ce("menghapus tugas",g),"err","x-circle");return}p("Tugas dihapus","ok","trash-2"),f(),u()}}return a.jsxs(a.Fragment,{children:[a.jsxs(we,{open:e,onClose:m?void 0:u,icon:"clipboard-list",eyebrow:"Papan tim",title:t?"Ubah tugas":"Tugas baru",footer:a.jsxs("div",{style:{display:"flex",gap:8,width:"100%",alignItems:"center"},children:[t&&a.jsx(U,{variant:"ghost",leftIcon:"trash-2",onClick:A,disabled:m,children:"Hapus"}),a.jsx("span",{style:{flex:1}}),a.jsx(U,{variant:"secondary",onClick:u,disabled:m,children:"Batal"}),a.jsx(U,{onClick:M,loading:m,children:t?"Simpan":"Buat tugas"})]}),children:[a.jsx($,{label:"Judul",children:a.jsx(Y,{value:i.title,"aria-label":"Judul tugas",placeholder:"mis. Rapikan halaman harga",onChange:g=>N({title:g.target.value}),style:{width:"100%"}})}),a.jsxs("div",{style:{display:"flex",gap:10,flexWrap:"wrap"},children:[a.jsx($,{label:"Project",children:a.jsx(B,{value:i.projectId,"aria-label":"Project tugas",onChange:g=>N({projectId:g.target.value}),options:[{value:"",label:"Tanpa project"},...n.map(g=>({value:g.id,label:g.name}))]})}),a.jsx($,{label:"Kolom",children:a.jsx(B,{value:i.status,"aria-label":"Kolom tugas",onChange:g=>N({status:g.target.value}),options:Z.map(g=>({value:g.key,label:g.label}))})}),a.jsx($,{label:"Prioritas",children:a.jsx(B,{value:i.priority,"aria-label":"Prioritas tugas",onChange:g=>N({priority:g.target.value}),options:It})})]}),a.jsx($,{label:"Ditugaskan ke",children:a.jsx(B,{value:i.memberId,"aria-label":"Anggota tugas",onChange:g=>N({memberId:g.target.value}),options:[{value:"",label:"Belum ditugaskan"},...l.map(g=>({value:g.id,label:g.role?`${g.name} · ${g.role}`:g.name}))],style:{width:"100%"}})}),a.jsxs("div",{style:{display:"flex",gap:10,flexWrap:"wrap"},children:[a.jsx($,{label:"Mulai",children:a.jsx(Y,{type:"date",value:i.startDate,"aria-label":"Tanggal mulai",onChange:g=>N({startDate:g.target.value})})}),a.jsx($,{label:"Tenggat",children:a.jsx(Y,{type:"date",value:i.dueDate,"aria-label":"Tanggal tenggat",onChange:g=>N({dueDate:g.target.value})})})]}),a.jsx($,{label:"Detail",hint:"Opsional — konteks yang tak muat di judul.",children:a.jsx(Aa,{value:i.detail,"aria-label":"Detail tugas",rows:4,placeholder:"mis. tunggu aset dari klien, deadline ikut jadwal kampanye",onChange:g=>N({detail:g.target.value})})})]}),j]})}const wt=Ra.map(e=>({value:e,label:_a(e).label}));function Dt({task:e,projects:t,onClose:n,onDone:l,onToast:r}){const[o,u]=d.useState("brief"),[f,p]=d.useState(()=>He.some(h=>h.value===e.priority)?e.priority:"sedang"),[i,b]=d.useState(""),[m,k]=d.useState(!1),S=e.projectId===null,j=e.projectId??i;async function C(){if(!(!j||m)){k(!0);try{const h=await D.escalateTask(e.id,{source:o,priority:f,...e.projectId?{}:{projectId:i}});r(h.created?`Dieskalasi jadi ${h.spec.id}`:`Sudah tertaut ke ${h.spec.id}`,"ok","link"),l(h.task),n()}catch(h){r(Ce("mengeskalasi kartu",h),"err","x-circle")}finally{k(!1)}}}return a.jsxs(we,{open:!0,onClose:m?void 0:n,icon:"git-branch",eyebrow:"Papan tim",title:"Kirim ke Backlog",footer:a.jsxs("div",{className:"hn-dia-foot-split",children:[a.jsx("span",{className:"hn-grow"}),a.jsx(U,{variant:"secondary",onClick:n,disabled:m,children:"Batal"}),a.jsx(U,{onClick:C,loading:m,disabled:!j,leftIcon:"git-branch",children:"Kirim ke Backlog"})]}),children:[a.jsxs("div",{className:"hn-dia-lead",children:["Kartu ",a.jsx("strong",{children:e.title})," tetap di papan. Yang lahir adalah backlog item baru yang bisa dikerjakan sesi agen, dan kartu ini menampilkan stage-nya."]}),S&&a.jsxs($,{label:"Project",children:[a.jsx(B,{"aria-label":"Project",value:i,className:"hn-dia-full",onChange:h=>b(h.target.value),options:[{value:"",label:"Pilih project…"},...t.map(h=>({value:h.id,label:h.name}))]}),a.jsx("div",{className:"hn-dia-hint",children:"Nomor SPEC diambil dari repo project, jadi kartu tanpa project belum bisa dieskalasi."})]}),a.jsx($,{label:"Source",hint:"Jenis item backlog yang lahir dari kartu ini, mis. feature brief atau Finding QA.",children:a.jsx(B,{"aria-label":"Source",value:o,className:"hn-dia-full",onChange:h=>u(h.target.value),options:wt})}),a.jsx($,{label:"Prioritas",children:a.jsx(B,{"aria-label":"Prioritas",value:f,className:"hn-dia-full",onChange:h=>p(h.target.value),options:He})})]})}function Mt({m:e,busy:t,onSave:n,onToggle:l,onDelete:r}){const[o,u]=d.useState(!1),[f,p]=d.useState(e.name),[i,b]=d.useState(e.role??"");return o?a.jsxs("div",{className:"hn-mem-edit",children:[a.jsx(Y,{size:"sm",value:f,"aria-label":`Nama ${e.name}`,placeholder:"mis. Dena Meidina",onChange:m=>p(m.target.value)}),a.jsx(Y,{size:"sm",value:i,"aria-label":`Peran ${e.name}`,placeholder:"mis. desainer",onChange:m=>b(m.target.value)}),a.jsxs("div",{className:"hn-mem-note",children:[e.email," — ganti email berarti hapus lalu buat baru."]}),a.jsxs("div",{className:"hn-mem-actions",children:[a.jsx(U,{size:"sm",disabled:t,onClick:()=>{n(e.id,{name:f.trim(),role:i.trim()||null}),u(!1)},children:"Simpan"}),a.jsx(U,{size:"sm",variant:"ghost",onClick:()=>u(!1),children:"Batal"})]})]}):a.jsxs("div",{className:`hn-dense-row hn-mem-row${e.active?"":" hn-mem-row--off"}`,children:[a.jsxs("span",{className:"hn-mem-main",children:[a.jsxs("span",{className:"hn-mem-name-row",children:[a.jsx("span",{className:"hn-mem-name",children:e.name}),e.role&&a.jsx(Ze,{tone:"neutral",size:"sm",children:e.role}),!e.active&&a.jsx(Ze,{tone:"warn",size:"sm",children:"nonaktif"})]}),a.jsx("span",{className:"hn-mem-email",children:e.email})]}),a.jsx(ke,{icon:"pencil",label:`Ubah ${e.name}`,size:"sm",onClick:()=>u(!0)}),a.jsx(ke,{icon:e.active?"user-minus":"user-check",size:"sm",label:`${e.active?"Nonaktifkan":"Aktifkan"} ${e.name}`,onClick:()=>l(e)}),a.jsx(ke,{icon:"trash-2",label:`Hapus ${e.name}`,size:"sm",onClick:()=>r(e)})]})}function Et({open:e,onClose:t,onChanged:n,onToast:l}){const[r,o]=d.useState([]),[u,f]=d.useState("loading"),[p,i]=d.useState(!1),[b,m]=d.useState(!1),[k,S]=d.useState(""),[j,C]=d.useState(""),[h,N]=d.useState(""),{confirm:M,dialog:A}=ca(),g=d.useRef(n);g.current=n;const T=d.useRef(!1),c=d.useCallback(()=>{T.current||f("loading"),D.listMembers().then(v=>{T.current=!0,o(v.items),f("ready"),i(!1),g.current(v.items)}).catch(()=>{T.current?i(!0):f("error")})},[]);if(d.useEffect(()=>{e&&c()},[e,c]),!e)return null;async function y(){if(!k.trim()||!j.trim()){l("Nama & email wajib diisi","err","x-circle");return}m(!0);try{await D.createMember({name:k.trim(),email:j.trim(),role:h.trim()||null}),S(""),C(""),N(""),l("Anggota ditambahkan","ok","user-plus"),c()}catch{l("Gagal menambah anggota — email mungkin sudah terdaftar","err","x-circle")}finally{m(!1)}}async function L(v,le){m(!0);try{await D.patchMember(v,le),c()}catch{l("Gagal menyimpan anggota","err","x-circle")}finally{m(!1)}}async function I(v){m(!0);try{await D.patchMember(v.id,{active:!v.active}),c()}catch{l("Gagal mengubah status anggota","err","x-circle")}finally{m(!1)}}async function K(v){await M({title:`Hapus ${v.name} dari direktori?`,message:"Tugasnya tidak ikut terhapus — kartu yang ditugaskan padanya jadi 'belum ditugaskan'.",confirmLabel:"Hapus anggota",tone:"danger",icon:"trash-2",run:()=>D.deleteMember(v.id)})&&(l("Anggota dihapus","ok","trash-2"),c())}return a.jsxs(a.Fragment,{children:[a.jsxs(we,{open:e,onClose:t,icon:"users",eyebrow:"Papan tim",title:"Anggota",width:620,children:[a.jsxs("div",{className:"hn-mem-add",children:[a.jsx(Y,{size:"sm",value:k,"aria-label":"Nama anggota baru",placeholder:"Nama",onChange:v=>S(v.target.value),className:"hn-mem-in-name"}),a.jsx(Y,{size:"sm",value:j,"aria-label":"Email anggota baru",placeholder:"email@nafanesia.id",onChange:v=>C(v.target.value),className:"hn-mem-in-email"}),a.jsx(Y,{size:"sm",value:h,"aria-label":"Peran anggota baru",placeholder:"Peran (opsional)",onChange:v=>N(v.target.value),className:"hn-mem-in-role"}),a.jsx(U,{size:"sm",leftIcon:"user-plus",onClick:y,loading:b,children:"Tambah anggota"})]}),p&&a.jsx(Ua,{tone:"err",title:"Gagal memuat ulang anggota",className:"hn-mem-alert",action:a.jsx(U,{size:"sm",variant:"ghost",onClick:c,children:"Coba lagi"}),children:"Yang tampil di bawah adalah data lama. Coba lagi untuk memuat yang terbaru."}),u==="loading"?a.jsx(W,{kind:"loading",compact:!0}):u==="error"?a.jsx(W,{kind:"error",compact:!0,hint:"Gagal memuat anggota.",action:c,actionLabel:"Coba lagi"}):r.length===0?a.jsx(W,{kind:"empty",compact:!0,icon:"users",title:"Belum ada anggota",hint:"Tambahkan orang di atas agar kartu papan bisa ditugaskan."}):r.map(v=>a.jsx(Mt,{m:v,busy:b,onSave:L,onToggle:I,onDelete:K},v.id))]}),A]})}const $t=5e3,la=200,Lt=400,_="me",H="all",ia=[{value:"board",label:"Papan",icon:"kanban"},{value:"timeline",label:"Linimasa",icon:"gantt-chart"},{value:"projects",label:"Lintas project",icon:"layers"}],Ot={day:"Hari",week:"Minggu",month:"Bulan"},Pt=()=>Object.fromEntries(Z.map(e=>[e.key,0]));function Bt({status:e,params:t,onData:n,refetch:l}){return Wa({topic:"tasks",params:{...t,status:e},apply:r=>n(e,r.data.items,r.data.total),refetch:l,pollMs:$t}),null}function Kt({projects:e,projectFilter:t,onProjectFilter:n,onToast:l,onOpenSpec:r}){var Ke,ze,Ge;const[o,u]=d.useState(Qa),[f,p]=d.useState(Pt),[i,b]=d.useState([]),[m,k]=d.useState(""),[S,j]=d.useState("loading"),[C,h]=d.useState(!1),[N,M]=d.useState(null),[A,g]=d.useState(!1),[T,c]=d.useState(!1),[y,L]=d.useState(null),[I,K]=d.useState(null),[v,le]=Fa(),[he,ba]=X("team","view","board",Ye(...ia.map(s=>s.value))),[V,pe]=X("team","q","",xe),[z,ie]=X("team","col","all",xe),[P,ae]=X("team","member",_,xe),[ge,fa]=X("team","zoom","week",Ye(...Qe)),[ja,De]=X("team","expanded",[],Va),ka=d.useCallback(s=>{De(x=>x.includes(s)?x.filter(w=>w!==s):[...x,s])},[De]),Me=he==="timeline",F=he==="projects",Ee=d.useRef(Date.now()).current;d.useEffect(()=>{var w,E;let s=!0;const x=(E=(w=D).authStatus)==null?void 0:E.call(w);return x==null||x.then(O=>{var R;s&&K(((R=O.user)==null?void 0:R.email)??null)}).catch(()=>{s&&K(null)}),()=>{s=!1}},[]);const G=d.useMemo(()=>z==="all"?Z:Z.filter(s=>s.key===z),[z]),be=G.map(s=>s.key).join(","),fe=F||t==="all"?void 0:t,re=d.useMemo(()=>{if(!I)return null;const s=Ka(I);return i.some(x=>x.id===s)?s:null},[I,i]),oe=P===_?re??void 0:P===H?void 0:P,$e=P!==_&&P!==H,Q=d.useMemo(()=>({projectId:fe,memberId:oe,q:V.trim()||void 0}),[fe,oe,V]),ce=d.useRef(!1),te=d.useCallback((s=!1)=>{!s&&!ce.current&&j("loading");const x=be?be.split(","):[];Promise.all(x.map(w=>D.listTasks({...Q,status:w,page:1,limit:la}))).then(w=>{u(E=>{const O={...E};return x.forEach((R,ne)=>{O[R]=w[ne].items}),O}),p(E=>{const O={...E};return x.forEach((R,ne)=>{O[R]=w[ne].total}),O}),ce.current=!0,h(!1),j("ready")}).catch(()=>{if(!ce.current){j("error");return}h(!0)})},[Q,be]);d.useEffect(()=>{te()},[te]);const Le=d.useCallback(()=>{D.listMembers().then(s=>{b(s.items),k("")}).catch(s=>k(za(s,"tidak diketahui")))},[]);d.useEffect(()=>{Le()},[Le]);const[Oe,xa]=d.useState(()=>V.trim());d.useEffect(()=>{const s=setTimeout(()=>xa(V.trim()),Lt);return()=>clearTimeout(s)},[V]);const ya=d.useCallback((s,x,w)=>{u(E=>({...E,[s]:x})),p(E=>({...E,[s]:w})),ce.current=!0,h(!1),j("ready")},[]),va=d.useMemo(()=>({projectId:Q.projectId,memberId:Q.memberId,q:Oe||void 0,page:1,limit:la}),[Q.projectId,Q.memberId,Oe]),de=d.useCallback(()=>te(!0),[te]);async function Sa(s,x){var O;const w=Xa(o,s.id,s.status,x);if(!w)return;const E=o;u(w.board);try{await D.patchTask(s.id,w.patch);const R=((O=Z.find(ne=>ne.key===x))==null?void 0:O.label)??x;le(`Tugas dipindah ke ${R}`,"ok",void 0,{action:{label:"Urungkan",onAction:()=>{Pe(s.id,{status:s.status})}}})}catch{u(E),l("Gagal memindahkan tugas","err","x-circle")}}async function Ca(s,x){var E;const w=o;u(ye(o,{...s,memberId:x}));try{await D.patchTask(s.id,{memberId:x});const O=x?((E=i.find(R=>R.id===x))==null?void 0:E.name)??"anggota":null;le(O?`Ditugaskan ke ${O}`:"Penugasan dikosongkan","ok",void 0,{action:{label:"Urungkan",onAction:()=>{Pe(s.id,{memberId:s.memberId})}}})}catch{u(w),l("Gagal menugaskan","err","x-circle")}}async function Pe(s,x){try{await D.patchTask(s,x),de()}catch{l("Gagal mengurungkan perubahan","err","x-circle")}}async function Na(s){const x=o;u(ye(o,{...s,specId:null,spec:null}));try{await D.unlinkTaskSpec(s.id),l("Tautan backlog dilepas","ok","unlink")}catch{u(x),l("Gagal melepas tautan","err","x-circle")}}const Be=G.every(s=>o[s.key].length===0),je=V.trim()!=="",Ae=(!F&&t!=="all"?1:0)+(z!=="all"?1:0)+($e?1:0),Re=Ae>0||je||oe!==void 0,Ia=((Ke=e.find(s=>s.id===t))==null?void 0:Ke.name)??t,Ta=((ze=i.find(s=>s.id===P))==null?void 0:ze.name)??P,wa=((Ge=Z.find(s=>s.key===z))==null?void 0:Ge.label)??z,Da=()=>{F||n("all"),ie("all"),ae(_),pe("")},Ma=()=>{F||n("all"),ie("all"),ae(H),pe("")},_e=d.useMemo(()=>G.flatMap(s=>o[s.key]),[o,G]),Ue=G.reduce((s,x)=>s+Math.max(0,(f[x.key]??0)-o[x.key].length),0),Ea=G.reduce((s,x)=>s+(f[x.key]??0),0),Fe=[...!F&&t!=="all"?[{key:"project",label:`Project: ${Ia}`,onRemove:()=>n("all")}]:[],...z!=="all"?[{key:"col",label:`Kolom: ${wa}`,onRemove:()=>ie("all")}]:[],...$e?[{key:"member",label:`Anggota: ${Ta}`,onRemove:()=>ae(_)}]:[]],$a=[...re?[{value:_,label:"Saya"}]:[],{value:H,label:"Semua anggota"},...i.map(s=>({value:s.id,label:s.name}))],La=P===_&&!re?H:P,Oa=a.jsxs(Ga,{gap:3,children:[a.jsx($,{label:"Project",children:a.jsx(B,{size:"sm","aria-label":"Filter project",value:t,disabled:F,onChange:s=>n(s.target.value),options:[{value:"all",label:"Semua project"},...e.map(s=>({value:s.id,label:s.name}))]})}),F&&a.jsx("p",{"data-testid":"project-filter-note",className:"hn-tm-hint",children:"Mode ini melintasi semua project"}),a.jsx($,{label:"Anggota",children:a.jsx(B,{size:"sm","aria-label":"Filter anggota",value:La,disabled:!!m,onChange:s=>ae(s.target.value),options:$a})}),m&&a.jsxs("p",{role:"alert",className:"hn-tm-hint hn-tm-alert",children:["Anggota gagal dimuat: ",m]}),a.jsx($,{label:"Kolom",children:a.jsx(B,{size:"sm","aria-label":"Filter kolom",value:z,onChange:s=>ie(s.target.value),options:[{value:"all",label:"Semua kolom"},...Z.map(s=>({value:s.key,label:s.label}))]})}),(Me||F)&&a.jsx($,{label:"Zoom",children:a.jsx(B,{size:"sm","aria-label":"Zoom linimasa",value:ge,onChange:s=>fa(s.target.value),options:Qe.map(s=>({value:s,label:Ot[s]}))})})]});return a.jsxs("div",{className:"hn-tm-screen",children:[a.jsxs("section",{className:"hn-tm-toolbar",role:"region","aria-label":"Kontrol papan tim",children:[a.jsxs("div",{className:"hn-tm-switches",children:[a.jsx(Se,{variant:"pill",value:he,onChange:ba,tabs:ia,"aria-label":"Mode tampilan"}),re&&a.jsx(Se,{variant:"pill","aria-label":"Lensa tugas",value:P===H?H:P===_?_:"",onChange:s=>ae(s),tabs:[{value:_,label:"Saya"},{value:H,label:"Semua"}]}),a.jsxs("span",{className:"hn-tm-count",role:"status",title:C?"Server tak menjawab saat menyegarkan — angka ini dari muatan terakhir yang berhasil":void 0,children:[Ea," tugas",C?" · data lama":""]}),a.jsx(qa,{})]}),a.jsx(Ha,{label:"Penyaring tim",search:{value:V,onChange:pe,label:"Cari tugas",placeholder:"mis. halaman harga atau deploy"},chips:Fe,filters:Oa,filtersLabel:"Filter",onReset:Fe.length>0||je?Da:void 0,resetLabel:"Reset filter",actions:a.jsxs(a.Fragment,{children:[a.jsx(U,{size:"sm",leftIcon:"plus",onClick:()=>{M(null),g(!0)},children:"Tugas baru"}),a.jsx(Za,{onDone:de,onToast:l}),a.jsx(oa,{label:"Lainnya",items:[{key:"members",label:"Anggota tim",icon:"users",onSelect:()=>c(!0)}]})]})})]}),G.map(s=>a.jsx(Bt,{status:s.key,params:va,onData:ya,refetch:de},s.key)),S==="loading"?a.jsx(W,{kind:"loading"}):S==="error"?a.jsx(W,{kind:"error",hint:"Gagal memuat papan tim.",action:()=>te(),actionLabel:"Coba lagi"}):Be&&!Re?a.jsx(W,{kind:"empty",icon:"users",title:"Papan tim masih kosong",hint:"Catat pekerjaan manusia di sekitar sesi agen — desain, meeting klien, deploy, nego.",action:()=>{M(null),g(!0)},actionLabel:"Tugas baru",actionIcon:"plus"}):a.jsxs(a.Fragment,{children:[Be&&Re&&a.jsx(W,{kind:"empty",compact:!0,icon:"filter",title:oe!==void 0&&Ae===0&&!je?"Tak ada tugas untuk kamu":"Tak ada tugas yang cocok dengan filter",hint:"Penyaring yang aktif menyembunyikan semua tugas di papan ini.",action:Ma,actionLabel:"Tampilkan semua",actionIcon:"x"}),F?a.jsx(Nt,{tasks:_e,projects:e,members:i,zoom:ge,today:Ee,hidden:Ue,expanded:ja,onToggle:ka,onOpen:s=>{M(s),g(!0)}}):Me?a.jsx(vt,{tasks:_e,members:i,zoom:ge,today:Ee,hidden:Ue,onOpen:s=>{M(s),g(!0)}}):a.jsx(kt,{board:o,totals:f,columns:G,members:i,projects:e,onOpenSpec:r,onMove:Sa,onAssign:Ca,onEscalate:L,onUnlink:Na,onOpen:s=>{M(s),g(!0)}})]}),a.jsx(Tt,{open:A,task:N,projects:e,members:i,defaultProjectId:fe??null,orderFor:s=>da(o[s]),onClose:()=>{g(!1),M(null)},onSaved:de,onToast:l}),y&&a.jsx(Dt,{task:y,projects:e,onClose:()=>L(null),onDone:s=>u(x=>ye(x,s)),onToast:l}),a.jsx(Et,{open:T,onClose:()=>c(!1),onChanged:b,onToast:l}),a.jsx(Ya,{toast:v})]})}export{ia as TEAM_VIEWS,Kt as TeamScreen};