kaizen-agent 1.47.0 → 1.49.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +111 -84
- package/cli/build-web.ts +4 -2
- package/cli/hermes.ts +65 -0
- package/cli/install.ts +24 -10
- package/cli/localsend.test.ts +84 -0
- package/cli/localsend.ts +131 -0
- package/cli/notes.test.ts +6 -4
- package/cli/settings.ts +1 -0
- package/cli/state.test.ts +37 -0
- package/cli/state.ts +35 -20
- package/cli/video.test.ts +479 -0
- package/cli/video.ts +507 -0
- package/cli/web.ts +127 -1
- package/cli/worktree.test.ts +3 -1
- package/package.json +1 -1
- package/skills/kaizen/config.default.yml +4 -0
- package/skills/media/kaizen-book/SKILL.md +107 -0
- package/skills/media/kaizen-book/assets/reader.html +440 -0
- package/skills/media/kaizen-book/assets/styles.json +45 -0
- package/skills/media/kaizen-book/examples/book.json +14 -0
- package/skills/media/kaizen-book/examples/images/reach.svg +1 -0
- package/skills/media/kaizen-book/examples/manuscript.md +127 -0
- package/skills/media/kaizen-book/references/interview.md +85 -0
- package/skills/media/kaizen-book/references/proofread.md +47 -0
- package/skills/media/kaizen-book/references/writing.md +53 -0
- package/skills/media/kaizen-book/scripts/build_book.py +279 -0
- package/skills/media/kaizen-book/scripts/check.sh +10 -0
- package/skills/media/kaizen-book/scripts/check_book.py +128 -0
- package/skills/media/kaizen-book/scripts/deploy.py +58 -0
- package/skills/media/kaizen-book/scripts/pdf.mjs +99 -0
- package/skills/media/kaizen-book/scripts/setup.sh +9 -0
- package/skills/media/kaizen-book/scripts/verify.mjs +95 -0
- package/skills/{story-deck → media/kaizen-deck}/SKILL.md +1 -1
- package/skills/{story-deck → media/kaizen-deck}/scripts/check.sh +1 -1
- package/skills/{story-deck → media/kaizen-deck}/scripts/install_fonts.py +2 -2
- package/skills/media/kaizen-video/SKILL.md +112 -0
- package/skills/media/kaizen-video/assets/CREDITS.txt +16 -0
- package/skills/media/kaizen-video/assets/film-fonts/Fraunces.ttf +0 -0
- package/skills/media/kaizen-video/assets/film-fonts/Inter.ttf +0 -0
- package/skills/media/kaizen-video/assets/film-fonts/PlayfairDisplay-Italic.ttf +0 -0
- package/skills/media/kaizen-video/assets/film-fonts/PlayfairDisplay.ttf +0 -0
- package/skills/media/kaizen-video/assets/fonts/Fredoka.ttf +0 -0
- package/skills/media/kaizen-video/assets/fonts/Montserrat.ttf +0 -0
- package/skills/media/kaizen-video/assets/fonts/SpecialElite.ttf +0 -0
- package/skills/media/kaizen-video/assets/music/investigations.mp3 +0 -0
- package/skills/media/kaizen-video/assets/music/lights.mp3 +0 -0
- package/skills/media/kaizen-video/assets/music/sunny.mp3 +0 -0
- package/skills/media/kaizen-video/examples/config.json +152 -0
- package/skills/media/kaizen-video/examples/sample-film/README.md +10 -0
- package/skills/media/kaizen-video/examples/sample-film/film.json +63 -0
- package/skills/media/kaizen-video/film.html +246 -0
- package/skills/media/kaizen-video/hyperframes.json +12 -0
- package/skills/media/kaizen-video/presets/educational-warning/CREDITS.txt +3 -0
- package/skills/media/kaizen-video/presets/educational-warning/README.md +26 -0
- package/skills/media/kaizen-video/presets/educational-warning/assets/sfx/ending.wav +0 -0
- package/skills/media/kaizen-video/presets/educational-warning/assets/sfx/reveal.wav +0 -0
- package/skills/media/kaizen-video/presets/educational-warning/assets/sfx/shutter.wav +0 -0
- package/skills/media/kaizen-video/presets/educational-warning/assets/sfx/stamp.wav +0 -0
- package/skills/media/kaizen-video/presets/educational-warning/index.html +236 -0
- package/skills/media/kaizen-video/presets/educational-warning/package.json +10 -0
- package/skills/media/kaizen-video/presets/film-cinematic-drama/CREDITS.txt +1 -0
- package/skills/media/kaizen-video/presets/film-cinematic-drama/README.md +2 -0
- package/skills/media/kaizen-video/presets/film-cinematic-drama/style.json +39 -0
- package/skills/media/kaizen-video/presets/film-fun-energetic/CREDITS.txt +1 -0
- package/skills/media/kaizen-video/presets/film-fun-energetic/README.md +2 -0
- package/skills/media/kaizen-video/presets/film-fun-energetic/style.json +39 -0
- package/skills/media/kaizen-video/presets/film-promo-booth/CREDITS.txt +1 -0
- package/skills/media/kaizen-video/presets/film-promo-booth/README.md +2 -0
- package/skills/media/kaizen-video/presets/film-promo-booth/style.json +39 -0
- package/skills/media/kaizen-video/presets/film-viral-social/CREDITS.txt +1 -0
- package/skills/media/kaizen-video/presets/film-viral-social/README.md +2 -0
- package/skills/media/kaizen-video/presets/film-viral-social/style.json +39 -0
- package/skills/media/kaizen-video/presets/tiktok-cheerful/CREDITS.txt +3 -0
- package/skills/media/kaizen-video/presets/tiktok-cheerful/README.md +35 -0
- package/skills/media/kaizen-video/presets/tiktok-cheerful/assets/sfx/boing.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-cheerful/assets/sfx/chime.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-cheerful/assets/sfx/ding.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-cheerful/assets/sfx/ending.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-cheerful/assets/sfx/pop.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-cheerful/assets/sfx/reveal.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-cheerful/assets/sfx/shutter.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-cheerful/assets/sfx/stamp.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-cheerful/assets/sfx/whoosh.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-cheerful/index.html +260 -0
- package/skills/media/kaizen-video/presets/tiktok-cheerful/package.json +10 -0
- package/skills/media/kaizen-video/presets/tiktok-explainer/CREDITS.txt +3 -0
- package/skills/media/kaizen-video/presets/tiktok-explainer/README.md +52 -0
- package/skills/media/kaizen-video/presets/tiktok-explainer/assets/fonts/InstrumentSerif.ttf +0 -0
- package/skills/media/kaizen-video/presets/tiktok-explainer/assets/fonts/SpaceMono.ttf +0 -0
- package/skills/media/kaizen-video/presets/tiktok-explainer/assets/sfx/boing.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-explainer/assets/sfx/ding.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-explainer/assets/sfx/ending.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-explainer/assets/sfx/pop.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-explainer/assets/sfx/reveal.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-explainer/assets/sfx/shutter.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-explainer/assets/sfx/stamp.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-explainer/assets/sfx/tick.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-explainer/assets/sfx/whoosh.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-explainer/index.html +272 -0
- package/skills/media/kaizen-video/presets/tiktok-explainer/package.json +10 -0
- package/skills/media/kaizen-video/presets/tiktok-mystery/CREDITS.txt +12 -0
- package/skills/media/kaizen-video/presets/tiktok-mystery/README.md +51 -0
- package/skills/media/kaizen-video/presets/tiktok-mystery/assets/sfx/clock.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-mystery/assets/sfx/ding.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-mystery/assets/sfx/ending.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-mystery/assets/sfx/heart.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-mystery/assets/sfx/projector.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-mystery/assets/sfx/reveal.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-mystery/assets/sfx/shutter.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-mystery/assets/sfx/stamp.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-mystery/assets/sfx/whoosh.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-mystery/index.html +260 -0
- package/skills/media/kaizen-video/presets/tiktok-mystery/package.json +10 -0
- package/skills/media/kaizen-video/presets/tiktok-scam-alert/CREDITS.txt +8 -0
- package/skills/media/kaizen-video/presets/tiktok-scam-alert/README.md +24 -0
- package/skills/media/kaizen-video/presets/tiktok-scam-alert/assets/sfx/clock.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-scam-alert/assets/sfx/ding.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-scam-alert/assets/sfx/ending.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-scam-alert/assets/sfx/heart.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-scam-alert/assets/sfx/reveal.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-scam-alert/assets/sfx/shutter.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-scam-alert/assets/sfx/stamp.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-scam-alert/assets/sfx/whoosh.wav +0 -0
- package/skills/media/kaizen-video/presets/tiktok-scam-alert/index.html +266 -0
- package/skills/media/kaizen-video/presets/tiktok-scam-alert/package.json +10 -0
- package/skills/media/kaizen-video/references/presets.md +76 -0
- package/skills/{story-video → media/kaizen-video}/references/production.md +2 -2
- package/skills/{story-video → media/kaizen-video}/references/revisions.md +9 -9
- package/skills/media/kaizen-video/scripts/__pycache__/intake.cpython-314.pyc +0 -0
- package/skills/media/kaizen-video/scripts/__pycache__/make_film.cpython-314.pyc +0 -0
- package/skills/media/kaizen-video/scripts/__pycache__/make_tiktok.cpython-314.pyc +0 -0
- package/skills/media/kaizen-video/scripts/__pycache__/render_cut.cpython-314.pyc +0 -0
- package/skills/media/kaizen-video/scripts/__pycache__/sfx.cpython-314.pyc +0 -0
- package/skills/media/kaizen-video/scripts/__pycache__/srt.cpython-314.pyc +0 -0
- package/skills/media/kaizen-video/scripts/__pycache__/transcribe.cpython-314.pyc +0 -0
- package/skills/media/kaizen-video/scripts/__pycache__/vo.cpython-314.pyc +0 -0
- package/skills/media/kaizen-video/scripts/check.sh +22 -0
- package/skills/{story-video → media/kaizen-video}/scripts/intake.py +2 -2
- package/skills/media/kaizen-video/scripts/make_film.py +263 -0
- package/skills/media/kaizen-video/scripts/make_tiktok.py +213 -0
- package/skills/{story-video → media/kaizen-video}/scripts/master.sh +12 -11
- package/skills/media/kaizen-video/scripts/render_cut.py +88 -0
- package/skills/media/kaizen-video/scripts/setup.sh +14 -0
- package/skills/{story-video → media/kaizen-video}/scripts/sfx.py +3 -3
- package/skills/media/kaizen-video/scripts/srt.py +9 -0
- package/skills/media/kaizen-video/scripts/still.sh +7 -0
- package/skills/media/kaizen-video/scripts/transcribe.py +45 -0
- package/skills/media/kaizen-video/tools/carve.mjs +560 -0
- package/skills/media/kaizen-video/tools/lib/main-module.mjs +13 -0
- package/web/board/views.ts +1 -1
- package/web/board.html +3 -1
- package/web/board.js +2 -2
- package/web/notebook.js +1 -1
- package/web/notes.html +2 -0
- package/web/term.js +38 -36
- package/web/term.ts +43 -10
- package/web/video.html +298 -0
- package/web/video.js +81 -0
- package/web/video.ts +610 -0
- package/skills/story-video/SKILL.md +0 -108
- package/skills/story-video/engine/package.json +0 -12
- package/skills/story-video/engine/src/Root.tsx +0 -24
- package/skills/story-video/engine/src/engine/Film.tsx +0 -405
- package/skills/story-video/engine/src/engine/presets.json +0 -58
- package/skills/story-video/engine/src/index.ts +0 -3
- package/skills/story-video/engine/tsconfig.json +0 -1
- package/skills/story-video/examples/sample-film/README.md +0 -12
- package/skills/story-video/examples/sample-film/film.json +0 -16
- package/skills/story-video/references/presets.md +0 -21
- package/skills/story-video/scripts/check.sh +0 -19
- package/skills/story-video/scripts/setup.sh +0 -25
- package/skills/story-video/scripts/srt.py +0 -30
- package/skills/story-video/scripts/still.sh +0 -10
- /package/skills/{story-deck → media/kaizen-deck}/examples/build-example.js +0 -0
- /package/skills/{story-deck → media/kaizen-deck}/references/rules.md +0 -0
- /package/skills/{story-deck → media/kaizen-deck}/references/story-arc.md +0 -0
- /package/skills/{story-deck → media/kaizen-deck}/scripts/kit.js +0 -0
- /package/skills/{story-deck → media/kaizen-deck}/scripts/prep_images.py +0 -0
- /package/skills/{story-deck → media/kaizen-deck}/scripts/qa.sh +0 -0
- /package/skills/{story-video → media/kaizen-video}/examples/sample-film/lines.json +0 -0
- /package/skills/{story-video → media/kaizen-video}/references/licensing.md +0 -0
- /package/skills/{story-video → media/kaizen-video}/references/script.md +0 -0
- /package/skills/{story-video → media/kaizen-video}/scripts/music.sh +0 -0
- /package/skills/{story-video → media/kaizen-video}/scripts/vo.py +0 -0
package/web/board.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* kaizen board
|
|
1
|
+
/* kaizen board c24cf970db99487d -- generated by bun run build:web from web/board/main.ts; do not edit */
|
|
2
2
|
(()=>{var a={S:{project:null,projects:[],cards:[],now:Date.now(),all:!1},all:new URLSearchParams(location.search).get("all")!=="0",dir:null,openKey:null,mode:null,modeKey:null,menuKey:null,flash:new Set,tab:"request",lastTab:"request",runDoc:null,clearMenu:!1,sevMenu:!1,wantTerm:null,setQ:"",pageGen:0,PL:[],shown:new Set((()=>{try{return JSON.parse(localStorage.getItem("kz-show"))||[]}catch(e){return[]}})())};var s=(e)=>document.getElementById(e),Fe=(e)=>String(e).replace(/[&<>"]/g,(t)=>({"&":"&","<":"<",">":">",'"':"""})[t]);class sn{s;constructor(e){this.s=e}toString(){return this.s}}var B=(e)=>new sn(String(e)),Qn=(e)=>e instanceof sn?e.s:Array.isArray(e)?e.map(Qn).join(""):e==null||e===!1?"":Fe(e),h=(e,...t)=>B(e.reduce((n,i,r)=>n+Qn(t[r-1])+i)),E=(e)=>B(`<svg><use href="#i-${e}"/></svg>`),Mt=B('<div aria-busy="true" aria-label="Loading"><span class="skel" style="height:16px;width:35%;margin:20px 0 14px"></span>'+'<span class="skel" style="height:44px;margin-bottom:10px"></span>'.repeat(4)+"</div>"),jt=(e)=>Promise.all(e.map((t)=>new Promise((n)=>{let i=new FileReader;i.onload=()=>n({name:t.name,data:i.result}),i.readAsDataURL(t)})));function _e(e){let t=document.createElement("dialog");return t.className="kz",t.innerHTML=`<form class="inl" method="dialog">${e}</form>`,t.onclose=()=>t.remove(),t.onclick=(n)=>{if(n.target===t)t.close()},document.body.appendChild(t),t.showModal(),t}var Zs=()=>{let e=document.documentElement.dataset.motion;return e?e==="full":!matchMedia("(prefers-reduced-motion: reduce)").matches},Ye=(e)=>Zs()&&document.startViewTransition?document.startViewTransition(e).updateCallbackDone:(e(),Promise.resolve());var Jn;function C(e,t){let n=s("toast");if(n.textContent=e,n.classList.toggle("rep",!!t),t){let i=document.createElement("a");i.href="/issue?"+new URLSearchParams(t),i.target="_blank",i.rel="noopener",i.textContent="Report",n.append(" ",i)}n.classList.add("on"),clearTimeout(Jn),Jn=setTimeout(()=>n.classList.remove("on"),t?8000:4000)}function Le(){try{if(typeof Notification<"u"&&Notification.permission==="default")Notification.requestPermission()}catch(e){}}function on(e,t){try{if(typeof Notification<"u"&&Notification.permission==="granted")new Notification("kaizen",{body:e,icon:"/logo.png",tag:t})}catch(n){}}var Xs="https://cdn.jsdelivr.net/npm/@huggingface/transformers@4.3.0",Yn={tiny:"onnx-community/whisper-tiny",base:"onnx-community/whisper-base",small:"onnx-community/whisper-small","large-v3-turbo":"onnx-community/whisper-large-v3-turbo"},an=null,eo=`import{pipeline}from"${Xs}";let asr=null;
|
|
3
3
|
onmessage=async e=>{const m=e.data;try{
|
|
4
4
|
if(m.type==="load"){const prog=p=>{if(p.status==="progress")postMessage({type:"progress",file:p.file,pct:p.progress||0})};
|
|
@@ -22,7 +22,7 @@ onmessage=async e=>{const m=e.data;try{
|
|
|
22
22
|
${d("Motion",r("mo",["system","full","reduce"],document.documentElement.dataset.motion||"system"),"Animations on the board and notes. System follows the device's reduce-motion setting.","mo","motion animation reduce reduced browser")}
|
|
23
23
|
${d("Notifications",h`<button class="chk${c==="granted"?" on":""}" id="nt" role="switch" aria-checked="${String(c==="granted")}"${c&&c!=="denied"?"":" disabled"}></button>`,m,"nt","notifications "+m+" browser")}</div>
|
|
24
24
|
<p class="snone" id="snone" hidden></p>`,ln();let f=[...s("pbody").querySelectorAll(".sg")],g=()=>{let p=a.setQ.trim().toLowerCase(),v=!1;f.forEach((k)=>{let A=!1;for(let q of k.nextElementSibling.children)q.hidden=!!p&&!q.dataset.q.includes(p),A||=!q.hidden;k.hidden=!A,v||=A}),s("snone").hidden=v,s("snone").textContent=`No setting matches “${a.setQ.trim()}”.`};if(s("sq").oninput=(p)=>{a.setQ=p.target.value,g()},s("sq").onkeydown=(p)=>{if(p.key!=="Escape")return;if(p.preventDefault(),a.setQ)a.setQ="",p.target.value="",g();else ne()},g(),u){let p=s("sq");p.focus(),p.setSelectionRange(p.value.length,p.value.length)}s("gg-save").onclick=async()=>{let p=await T("/google",{op:"client",id:s("gg-id").value,secret:s("gg-secret").value});if(p.ok)C("Saved");else C(p.error||"Enter both the client id and the secret");Ce()},s("gg-conn").onclick=async()=>{if(i.connected)return await T("/google",{op:"disconnect"}),Ce();let p=window.open("","_blank"),v=await T("/google",{op:"connect"});if(v.ok&&p)p.location=v.url;else p?.close(),C(v.error||"Could not start Google sign-in")};let b=(p,v,k,A)=>{let q=Math.max(v.indexOf(k),0),G=(x)=>{q=(q+x+v.length)%v.length,p.querySelector("output").textContent=v[q]===""?"—":v[q],A(v[q])};s(p.id+"-prev").onclick=()=>G(-1),s(p.id+"-next").onclick=()=>G(1),p.onkeydown=(x)=>{if(x.key!=="ArrowLeft"&&x.key!=="ArrowRight")return;x.preventDefault();let I=s(p.id+(x.key==="ArrowLeft"?"-prev":"-next"));I.focus(),I.click()}},w=async(p)=>{if(await Ce(),p&&/^s-preset-|-(prev|next)$/.test(p))s(p)?.focus()};if(b(s("th"),["system","light","dark"],t,setTheme),b(s("mo"),["system","full","reduce"],document.documentElement.dataset.motion||"system",setMotion),s("nt").onclick=()=>{Le(),setTimeout(Ce,300)},n)n.rows.forEach((p)=>{let v=s("s-"+p.key.replace(/\./g,"-")),k=async(q)=>{let G=document.activeElement?.id;if((await T("/settings",{key:p.key,value:q})).ok)C("Saved");await w(G)};if(v.tagName==="INPUT")v.onchange=async()=>{await k(v.value.trim()),N()};else v.querySelectorAll("[data-v]").forEach((q)=>q.onclick=()=>k(q.dataset.v));if(v.matches(".chk"))v.onclick=()=>k(v.dataset.v);let A;if(v.matches(".step"))b(v,p.values,p.value,(q)=>{clearTimeout(A),A=setTimeout(()=>k(q),300)});if(p.folder)s(v.id+"-pick").onclick=async()=>{let q=await T("/pick-folder",{});if(q.path)await k(q.path),N()}})}var Nt=(e)=>e.status==="stalled"||!!(e.pty&&!e.pty.alive);async function tt(e,t){t.disabled=!0,Le();let n=await T("/resume",{dir:e.state,id:e.id});if(!n.ok){t.disabled=!1;return}if(C("Resumed, "+Ve(n)+": "+Ie(n.agent)),n.pty)a.wantTerm=D(e);if(a.openKey===D(e))s("pfoot").innerHTML="",se(e,!0)}var cn={"approvals.plan":"The plan is ready. Read it in the Plan tab, then approve or send it back.","approvals.review":"The work is ready to check. Approve to finish it, or revise with what to change.",findings:"The review has open findings. Approve as-is to accept them and finish, or fix selected findings first."},nt=new Set,st=(e)=>D(e)+":"+e.awaiting+":"+e.moved;async function Kt(e,t,n,i){t.disabled=!0,Le();let r=await T("/decide",{dir:e.state,id:e.id,awaiting:e.awaiting,...n===void 0?{}:{why:n},...i?{answers:i}:{}});if(!r.ok){t.disabled=!1;return}if(nt.add(st(e)),C((n===void 0?"Approved":"Sent back")+", "+Ve(r)+": "+Ie(r.agent)),r.pty)a.wantTerm=D(e);if(a.openKey===D(e))s("pfoot").innerHTML="",se(e,!0)}function ds(e){let t=s("pfoot"),n=e.awaiting==="approvals.plan";t.innerHTML=h`<div class="inl" style="flex:1"><div class="q">${n?"What should the plan do differently?":"What should change in the work?"}</div><div class="q dim">Opens your agent on this run with your comment.${n?" It revises the plan and comes back here for approval.":" It changes the work, rechecks it and comes back here."}</div><textarea aria-label="Revise comment"></textarea><div class="row"><button class="btn ghost" data-a="c">Cancel</button><button class="btn pri" data-a="s">Send back</button></div></div>`;let i=t.querySelector("textarea");i.focus(),t.querySelector("[data-a=c]").onclick=()=>{t.innerHTML="",se(e,!0)},t.querySelector("[data-a=s]").onclick=(r)=>{let d=i.value.trim();if(!d){C("Say what should change"),i.focus();return}Kt(e,r.target,d)}}function us(e,t){let n=s("pfoot");n.innerHTML=h`<div class="inl qa" style="flex:1"><div class="q">The plan asks ${t.length===1?"one question":t.length+" questions"}.</div><div class="q dim">Your answers go to your agent with the approval. It records them and builds the plan.</div>${t.map((i,r)=>h`<fieldset><legend>${i.q}</legend>${i.options.map((d,u)=>h`<label><input type="${i.multi?"checkbox":"radio"}" name="q${r}" value="${u}"${d.rec||!i.multi&&!u&&!i.options.some((c)=>c.rec)?" checked":""}> ${d.text}</label>`)}<input type="text" data-n="${r}" placeholder="Note (optional)" aria-label="Note: ${i.q}"></fieldset>`)}<div class="row"><button class="btn ghost" data-a="c">Cancel</button><button class="btn pri" data-a="s">Approve with these answers</button></div></div>`,n.querySelector("[data-a=c]").onclick=()=>{n.innerHTML="",se(e,!0)},n.querySelector("[data-a=s]").onclick=(i)=>Kt(e,i.target,void 0,t.map((r,d)=>{let u=[...n.querySelectorAll(`[name=q${d}]:checked`)].map((m)=>`"${r.options[+m.value].label}"`).join(", ")||"none of the options",c=n.querySelector(`[data-n="${d}"]`).value.trim();return`${r.q} — ${u}${c?"; "+c:""}`}))}var io=[["grid","Grid","lgrid"],["cols","Side by side","lcols"],["rows","Stacked","lrows"]],yt=6,j={mode:"grid",order:[],hidden:[],max:null,sizes:{}};try{j={...j,...JSON.parse(localStorage.getItem("kz-terms")||"{}")}}catch(e){}var Oe=()=>{j.order=j.order.slice(-100),j.hidden=j.hidden.slice(-100);try{localStorage.setItem("kz-terms",JSON.stringify(j))}catch(e){}},Me=new Map,ot=!1,Te=null,bt=null,dn=(e)=>e.kind==="run"?String(e.id||e.text).replace(/^\d{4}-\d\d-\d\d-/,"").replace(/-/g," "):String(e.text).split(`
|
|
25
|
-
`)[0].slice(0,80),ps=(e)=>!e.pty.alive?"ended":e.pty.asking?"asking":"running",un=(e)=>String(e.where||"").split(/[\\/]/).filter(Boolean).pop()||e.where||"";function It(){let e=new Map;for(let t of a.S.cards)if(t.pty&&!t.archived)e.set(t.pty.key,t);return e}function fn(){let e=It(),t=j.hidden.filter((i)=>e.get(i)?.pty.alive).length,n=document.querySelector('.rail a[data-view="terminal"]');if(!n)return;if(t)n.dataset.n=String(t);else delete n.dataset.n;n.title="Terminal: every agent running in its card"+(t?` (${t} hidden)`:"")}function fs(){ot=!1,document.body.classList.remove("tmax");for(let e of Me.values())e.off?.();Me.clear(),s("terms").innerHTML=""}var Ot=(e)=>Me.get(e)?.el.querySelector(".xterm-helper-textarea")?.focus({preventScroll:!0});if(typeof window<"u")addEventListener("keydown",(e)=>{if(!ot||!e.ctrlKey||!e.shiftKey||e.altKey||e.metaKey||e.code!=="KeyM"||Te?.matches)return;let t=e.target.closest?.(".tile")?.dataset.k||j.max;if(!t)return;e.preventDefault(),e.stopPropagation(),j.max=j.max===t?null:t,Oe(),pe(),Ot(t)},!0);if(typeof window<"u")addEventListener("keydown",(e)=>{let t=/^Digit([1-9])$/.exec(e.code)?.[1];if(!ot||!t||!e.altKey||e.ctrlKey||e.shiftKey||e.metaKey)return;let n=[...s("terms").querySelectorAll(".tile")][+t-1]?.dataset.k;if(!n)return;if(e.preventDefault(),e.stopPropagation(),Te?.matches)bt=n;else if(j.max&&j.max!==n)j.max=n,Oe();pe(),Ot(n)},!0);function pe(){if(ot=!0,!Te)(Te=matchMedia("(max-width:640px)")).onchange=()=>ot&&pe();if(document.body.classList.contains("tdrag"))return;let e=s("terms"),t=It();for(let[x,I]of Me)if(!t.has(x)||j.hidden.includes(x))I.off?.(),I.el.remove(),Me.delete(x);let n=(x)=>j.order.includes(x)?j.order.indexOf(x):1e9,i=(x)=>t.get(x).pty.alive?0:1,r=[...t.keys()].filter((x)=>!j.hidden.includes(x)).sort((x,I)=>i(x)-i(I)||n(x)-n(I));for(let x of r)if(!j.order.includes(x))j.order.push(x);if(j.max&&!r.includes(j.max))j.max=null;let d=Te.matches?bt&&r.includes(bt)?bt:r[0]:j.max,u=e.querySelector(".tgrid"),c=e.querySelector(".tbar");if(!u)e.innerHTML='<div class="tbar"></div><div class="tgrid"></div>',u=e.querySelector(".tgrid"),c=e.querySelector(".tbar");let m=[...t.keys()].filter((x)=>j.hidden.includes(x)&&t.get(x).pty.alive);if(s("tmodes").innerHTML=h`${io.map(([x,I,V])=>h`<button data-mode="${x}" class="${j.mode===x?"on":""}" aria-pressed="${String(j.mode===x)}" title="${I}" aria-label="${I}">${E(V)}</button>`)}`.s,c.innerHTML=h`${m.length?h`<span class="dim">Hidden</span>${m.map((x)=>h`<button class="chip" data-show="${x}" title="Show this terminal">${E("plus")}${dn(t.get(x))} - ${un(t.get(x))}</button>`)}`:""}${Te.matches&&r.length>1?h`<span class="ttabs" role="group" aria-label="Terminals">${r.map((x)=>h`<button class="${x===d?"on":""}" data-pick="${x}" aria-pressed="${String(x===d)}"><span class="tdot ${ps(t.get(x))}"></span>${dn(t.get(x))} - ${un(t.get(x))}</button>`)}</span>`:""}`.s,fn(),c.querySelectorAll("[data-pick]").forEach((x)=>x.onclick=()=>{bt=x.dataset.pick,pe()}),c.querySelector(".ttabs .on")?.scrollIntoView({block:"nearest",inline:"nearest"}),s("tmodes").querySelectorAll("[data-mode]").forEach((x)=>x.onclick=()=>{j.mode=x.dataset.mode,j.max=null,Oe(),pe()}),c.querySelectorAll("[data-show]").forEach((x)=>x.onclick=()=>{j.hidden=j.hidden.filter((I)=>I!==x.dataset.show),Oe(),pe()}),u.querySelector(".tempty")?.remove(),!r.length){u.style.cssText="",u.querySelectorAll(".tsplit").forEach((x)=>x.remove()),u.insertAdjacentHTML("beforeend",h`<div class="empty tempty"><div class="mascot"></div><b>${m.length?"Every terminal is hidden":"No terminals running"}</b><p>Runs started with the agent in its card show here, from Ideas to Done.</p></div>`.s);return}let f=document.activeElement,g=0;for(let x of r){let I=t.get(x),V=Me.get(x);if(!V){let Y=document.createElement("section");Y.className="tile",Y.dataset.k=x,Y.innerHTML='<header draggable="true"></header><div class="term" aria-label="Agent terminal"></div>',V={el:Y,off:null},Me.set(x,V),ro(x,V),lo(Y)}let ye=ps(I),J=ye==="ended",fe=V.el.querySelector("header");if(fe.title=(I.kind==="run"?I.id:I.text)+" · "+I.where+(g<9?` · Alt+${g+1}`:""),fe.innerHTML=h`<span class="tdot ${ye}" role="img" title="${ye}" aria-label="${ye}"></span><b>${dn(I)} - ${un(I)}</b>${J?h`<span class="tend">ended</span>`:""}<span class="sp"></span>${J&&I.kind==="run"?h`<button class="btn sm" data-a="resume" title="Continue this run's agent">Resume</button>`:""}<button class="ib sm" data-a="card" title="Open card" aria-label="Open card">${E("open")}</button><button class="ib sm" data-a="max" title="${j.max===x?"Restore":"Maximise"} (Ctrl+Shift+M)" aria-label="${j.max===x?"Restore":"Maximise"}">${E(j.max===x?"min":"max")}</button>${J?"":h`<button class="ib sm" data-a="hide" title="Hide" aria-label="Hide">${E("dash")}</button>`}<button class="ib sm" data-a="${J?"hide":"exit"}" title="${J?"Close":"Exit session"}" aria-label="${J?"Close":"Exit session"}">${E("close")}</button>`.s,V.el.classList.toggle("ended",J),V.el.classList.toggle("asking",ye==="asking"),V.el.classList.toggle("off",!!d&&d!==x),V.el.classList.toggle("max",!Te.matches&&j.max===x),V.el.style.gridColumn="",u.children[g]!==V.el)u.insertBefore(V.el,u.children[g]||null);g++}if(f instanceof HTMLElement&&f!==document.activeElement&&f.isConnected)f.focus({preventScroll:!0});document.body.classList.toggle("tmax",!!j.max&&!Te.matches);let b=d?1:r.length,w=j.mode==="cols"?b:j.mode==="rows"?1:Math.ceil(Math.sqrt(b)),p=Math.ceil(b/w),v=w;if(!d&&w*p>b)Me.get(r[r.length-1]).el.style.gridColumn=`span ${w*p-b+1}`,v=b-(p-1)*w-1;let k=`${j.mode}:${w}x${p}`,A=j.sizes[k],q=A?.c?.length===w?A.c:Array(w).fill(1),G=A?.r?.length===p?A.r:Array(p).fill(1);co(u,q,G,k,v,!d)}function ro(e,t){mn().then((n)=>{if(Me.get(e)!==t)return;t.off=n(t.el.querySelector(".term"),e,()=>N(!0))}).catch(()=>t.el.querySelector(".term").textContent="The terminal could not load.")}function lo(e){let t=e.dataset.k;e.querySelector("header").onclick=(n)=>{let i=n.target.closest("[data-a]")?.dataset.a;if(i==="max")j.max=j.max===t?null:t;else if(i==="hide"){if(j.hidden.push(t),j.max===t)j.max=null}else if(i==="exit"){if(confirm("End this agent session? A run can be resumed from its tile or card."))T("/pty/exit",{key:t}).then(()=>N(!0));return}else if(i==="card"){let r=It().get(t);if(r)xe(r);return}else if(i==="resume"){let r=It().get(t);if(r)tt(r,n.target.closest("button")).then(()=>a.wantTerm=null);return}else return;Oe(),pe(),Ot(t)},e.querySelector("header").ondblclick=(n)=>{if(n.target.closest("button")||Te?.matches)return;j.max=j.max===t?null:t,Oe(),pe(),Ot(t)},e.querySelector("header").ondragstart=(n)=>{n.dataTransfer.setData("text/kz-term",t),n.dataTransfer.effectAllowed="move"},e.ondragover=(n)=>{if(!n.dataTransfer.types.includes("text/kz-term"))return;n.preventDefault(),e.classList.add("drop")},e.ondragleave=()=>e.classList.remove("drop"),e.ondrop=(n)=>{e.classList.remove("drop");let i=n.dataTransfer.getData("text/kz-term");if(!i||i===t)return;n.preventDefault();let r=j.order.indexOf(i),d=j.order.indexOf(t);if(r<0||d<0)return;[j.order[r],j.order[d]]=[j.order[d],j.order[r]],Oe(),pe()}}var pn=(e,t)=>{let n=e.reduce((r,d)=>r+d,0),i=e.slice(0,t+1).reduce((r,d)=>r+d,0);return`calc((100% - ${(e.length-1)*yt}px) * ${i/n} + ${t*yt+yt/2}px)`};function co(e,t,n,i,r,d){e.querySelectorAll(".tsplit").forEach((c)=>c.remove());let u=()=>{e.style.gridTemplateColumns=t.map((c)=>c+"fr").join(" "),e.style.gridTemplateRows=n.map((c)=>c+"fr").join(" "),e.querySelectorAll(".tsplit").forEach((c)=>{let m=+c.dataset.i;if(c.dataset.axis==="r")return void(c.style.top=pn(n,m));c.style.left=pn(t,m),c.style.bottom=m>=r?`calc(100% - ${pn(n,n.length-2)} + ${yt/2}px)`:"0px"})};if(d)for(let[c,m]of[["c",t],["r",n]])for(let f=0;f<m.length-1;f++){let g=document.createElement("div");g.className="tsplit "+c,g.dataset.axis=c,g.dataset.i=String(f),g.setAttribute("role","separator"),g.setAttribute("aria-orientation",c==="c"?"vertical":"horizontal"),g.title="Drag to resize, double-click to even out",uo(g,e,c,m,f,u,()=>{j.sizes[i]={c:[...t],r:[...n]},Oe()}),e.append(g)}u()}function uo(e,t,n,i,r,d,u){e.ondblclick=()=>{i.fill(1),u(),d()},e.onpointerdown=(c)=>{c.preventDefault(),e.setPointerCapture(c.pointerId),document.body.classList.add("tdrag");let m=i.reduce((v,k)=>v+k,0),f=(n==="c"?t.clientWidth:t.clientHeight)-(i.length-1)*yt,g=m*0.1,b=n==="c"?c.clientX:c.clientY,w=i[r],p=i[r+1];e.onpointermove=(v)=>{let k=Math.max(g-w,Math.min(p-g,((n==="c"?v.clientX:v.clientY)-b)/f*m));i[r]=w+k,i[r+1]=p-k,d()},e.onpointerup=e.onpointercancel=()=>{e.onpointermove=e.onpointerup=e.onpointercancel=null,document.body.classList.remove("tdrag"),u()}}}var ms=()=>ot;var W="board",hn=(e)=>{document.querySelectorAll(".rail a.it").forEach((t)=>t.dataset.view===e?t.setAttribute("aria-current","page"):t.removeAttribute("aria-current")),document.querySelector(".hdr h1").textContent=e==="sources"?"Icebox":e==="terminal"?"Terminal":"Board"};function he(e,t){if(a.pageGen++,e==="icebox")e="sources";if(!["settings","sources","terminal"].includes(e))e="board";let n=W;if(W=e,hn(e),document.body.classList.toggle("paged",e!=="board"),document.body.classList.toggle("ice",e==="sources"),document.body.classList.toggle("termv",e==="terminal"),t&&e!==n)history.pushState(null,"",e==="board"?location.pathname:"?view="+(e==="sources"?"icebox":e));let i=s("panel");if(e==="terminal")pe();else fs();if(e==="board"||e==="terminal"){if(n==="board"||n==="terminal"){if(e==="terminal"&&n==="board")W="board",ne(),W=e;return}i.style.transition="none",i.classList.remove("open","docked"),i.offsetWidth,i.style.transition="",W="board",ne(),W=e;return}if(i.classList.add("docked"),e==="settings")Ce();else z()}function hs(){document.querySelectorAll(".rail a[data-view]").forEach((e)=>{if(e.dataset.view==="notes")return;e.onclick=(t)=>{if(t.ctrlKey||t.metaKey||t.shiftKey||t.button)return;if(t.preventDefault(),e.dataset.view==="settings")a.setQ="";Ye(()=>he(e.dataset.view,!0))}}),document.querySelector(".rail .home").onclick=(e)=>{if(e.ctrlKey||e.metaKey||e.shiftKey||e.button)return;e.preventDefault(),Ye(()=>he("board",!0))},addEventListener("popstate",()=>Ye(()=>he(new URLSearchParams(location.search).get("view")))),addEventListener("kz-theme",()=>{if(W==="settings")Ce()})}var bs="Icebox",re=null,wt={},gn=(e)=>{if(!wt[e])try{wt[e]=localStorage.getItem("kz-reply-style:"+e)}catch(t){}return wt[e]||"casual"},po={casual:"Casual",fun:"Fun",helpful:"Helpful",promo:"Promo"},le=null,je=null,ge=null,be="",oe="",at="link",vt=null,it=!1,zt=!1,Gt=null,X=new Set,kt={x:"X",tiktok:"TikTok",instagram:"Instagram",threads:"Threads"},ee=()=>s("panel").classList.contains("open")&&s("ptitle").textContent===bs,Qe=(e)=>{let t=Math.round((Date.now()-Date.parse(e))/60000);return t<1?"just now":t<60?t+" min ago":t<1440?Math.round(t/60)+" h ago":Math.round(t/1440)+" d ago"};function gs(e,t){let n=s(e);if(!n)return;let i=n.querySelector("button.sel"),r=n.querySelector(".menu-pop"),d=r.querySelector("input"),u=r.querySelector(".pick-list"),c=(f)=>{if(r.hidden=!f,i.setAttribute("aria-expanded",f),f)d.value="",m(),d.focus()},m=()=>{let f=d.value.trim().toLowerCase(),g=null,b=!1;for(let w of u.children)if(w.classList.contains("grp")){if(g)g.hidden=!b;g=w,b=!1}else{let p=!f||w.dataset.q.includes(f)||g&&g.dataset.g.includes(f);w.hidden=!p,b||=p}if(g)g.hidden=!b};i.onclick=()=>c(r.hidden),d.oninput=m,d.onkeydown=(f)=>{if(f.key==="Escape")f.stopPropagation(),c(!1),i.focus();else if(f.key==="Enter")f.preventDefault(),u.querySelector("button:not([hidden])")?.click()},u.onclick=(f)=>{let g=f.target.closest("button[data-v]");if(!g)return;c(!1),t(g.dataset.v)}}async function z(){if(W!=="sources")return;let e=++a.pageGen;de(!0);let t=ee()?[s("src-url")?.value||"",s("src-label")?.value||"",document.activeElement?.id,s("src-dir")?.value,s("src-cat")?.value||"",s("src-plat")?.value,s("src-q")?.value||""]:["",""],n=new Map(ee()?[...s("pbody").querySelectorAll("[data-mv]")].map((o)=>[o.dataset.k,o.value]):[]),i=ee()&&document.activeElement?.closest?.(".ice-row"),r=i?[i.dataset.k,document.activeElement.id.replace(/-\d+$/,"")]:null,d=ee()&&s("ice-title")?[s("ice-title").dataset.k,s("ice-title").value,s("ice-details").value]:null,u=new Map(ee()?[...s("pbody").querySelectorAll("[data-ct]")].map((o)=>[o.dataset.k,o.value]):[]);if(!ee())s("pbody").innerHTML=Mt;Ae(),a.openKey=null,a.runDoc=null,s("pterm").hidden=!0,s("panel").classList.add("open"),s("scrim").classList.add("on"),s("ptitle").textContent=bs,s("ptabs").innerHTML="",s("pfoot").innerHTML="",s("psub").textContent="",s("psub").title="";let c=a.all?null:a.S.dir,m=c?"?dir="+encodeURIComponent(c):"",f=await fetch("/sources"+m).then((o)=>o.json()).catch(()=>null);if(e!==a.pageGen||!ee())return;let g=(o)=>{try{return new URL(o).hostname}catch{return o}},b=(o,l,y)=>{if(kt[y])return h`<span class="fav">${E("b-"+y)}</span>`;let S;try{let U=new URL(o);if(/^https?:$/.test(U.protocol))S=U.origin}catch{}let P=!S?"":o.includes("docs.google.com/spreadsheets")?"https://ssl.gstatic.com/docs/spreadsheets/favicon3.ico":o.includes("docs.google.com/document")?"https://ssl.gstatic.com/docs/documents/images/kix-favicon7.ico":S+"/favicon.ico";return h`<span class="fav">${P?h`<img src="${P}" alt="" loading="lazy" referrerpolicy="no-referrer" onerror="this.remove()">`:""}${E(l)}</span>`},w=(o)=>kt[o?.social]||(o?g(o.url).replace(/^www\./,""):"")||"Other",p=(o)=>{if(o.social)return"social";let l=o.url;if(l.includes("docs.google.com/spreadsheets")||l.endsWith(".csv")||l.endsWith(".tsv"))return"sheet";if(l.includes("docs.google.com/document"))return"doc";return"link"},v=f&&f.sources||[],k=[...f&&f.icebox||[],...f&&f.dismissed||[]],A=(f&&f.icebox||[]).length,q=f&&f.gatherer||{},G=q.use==="chatgpt"&&q.connected,x=(o,l)=>h`${o&&!a.S.projects.some((y)=>y.dir===o)?h`<option value="${o}" title="${l||o}" selected>${De(l||o)}</option>`:""}${a.S.projects.map((y)=>h`<option value="${y.dir}" title="${y.label}"${y.dir===o?" selected":""}>${De(y.label)}</option>`)}`,I=v.map((o,l)=>{let y=p(o),S=o.label||g(o.url),P=o.social&&(!o.last||!o.last.ok&&/gathered by your agent/i.test(o.last.note))?h`<span class="src-badge dim">${E("at")}${G?"Gathered with ChatGPT":"Gathered by your agent"}</span>`:!o.last?h`<span class="src-badge dim">Not gathered yet</span>`:o.last.ok?h`<span class="src-badge ok"><svg viewBox="0 0 16 16"><path d="M3.5 8.5l3 3 6-6" stroke="currentColor" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>${o.last.note}</span><span class="hint" style="margin:0">${Qe(o.last.at)}</span>`:h`<span class="src-badge warn"><svg viewBox="0 0 16 16"><circle cx="8" cy="8" r="6" stroke="currentColor" fill="none" stroke-width="1.8"/><path d="M8 5v3.5M8 11v.1" stroke="currentColor" fill="none" stroke-width="2" stroke-linecap="round"/></svg>Failed: ${o.last.note}</span><span class="hint" style="margin:0">${Qe(o.last.at)}</span>`,U=y==="sheet"?"sheet":y==="doc"?"doc":y==="social"?"at":"link",F=o.url.replace(/^https?:\/\/(www\.)?/,"");return h`<div class="src-card" id="src-card-${l}"><div class="src-hd"><span class="src-ico" title="${y==="social"?kt[o.social]||"social":y}">${b(o.url,U,o.social)}</span><div class="src-info"><span class="src-title" title="${S}">${S}</span><a class="src-url" href="${o.url}" target="_blank" rel="noopener noreferrer" title="${o.url}"><span>${F}</span>${E("ext")}</a></div><div class="src-acts">${o.social?h`<button class="ib sm" id="src-ag-${l}" data-ag="${l}" aria-label="Gather ${S} with your agent" title="${G?"Gather with your ChatGPT plan":"Gather: opens your agent on /kaizen gather"}">${E("refresh")}</button>`:h`<button class="ib sm" id="src-chk-${l}" data-chk="${l}" aria-label="Check ${S} now" title="Check now">${E("refresh")}</button>`}<button class="ib sm danger" id="src-rm-${l}" data-rm="${l}" aria-label="Remove ${S}" title="Remove source">${E("trash")}</button></div></div><div class="src-status">${P}</div><div class="src-fields"><label class="src-f" title="Category"><span>Category</span><input class="sel" id="src-ct-${l}" data-ct="${l}" data-k="${o.dir+" "+o.url}" value="${o.category||""}" placeholder="${w(o)}" maxlength="40" aria-label="Category of ${S}"><button class="btn sm pri" id="src-cs-${l}" aria-label="Save the category of ${S}" disabled>Save</button></label><label class="src-f" title="Project"><span>Project</span>${rt(o.dir,o.project||"")}<select class="sel" id="src-mv-${l}" data-mv="${l}" data-k="${o.dir+" "+o.url}" aria-label="Project of ${S}">${x(o.dir,o.project)}</select><button class="btn sm pri" id="src-mb-${l}" aria-label="Move ${S} to the chosen project" disabled>Move</button></label>${y==="sheet"||/github\.com/.test(o.url)?h`<label class="src-wb"><input type="checkbox" id="src-wb-${l}" data-wb="${l}"${o.writeback?" checked":""}> Write back</label>`:""}</div></div>`}),V=(f&&f.failed||[]).map((o)=>h`<p style="color:var(--dim)">The sources of ${o} could not be read.</p>`),ye=h`<div class="src-empty"><div class="src-empty-ico">${E("link")}</div><h4>No sources yet</h4></div>`,J=at==="social",fe=!v.length||it||[t[0],t[1],t[4],t[6]].some(Boolean),Y=h`<div class="src-add" id="src-addbox"${fe?"":" hidden"}><div class="hd"><h4>Add a source</h4><div class="src-kind" role="group" aria-label="Kind of source"><button id="src-k-link" data-kind="link" aria-pressed="${String(!J)}">Link</button><button id="src-k-social" data-kind="social" aria-pressed="${String(J)}">Social</button></div></div><label for="src-url"${J?" hidden":""}><span>Link</span><input class="sel" id="src-url" placeholder="Link" spellcheck="false" autocomplete="off"></label><div class="two plat"${J?"":" hidden"}><label for="src-plat"><span>Platform</span><select class="sel" id="src-plat">${Object.entries(kt).map(([o,l])=>h`<option value="${o}">${l}</option>`)}</select></label><label for="src-q"><span>Follow</span><input class="sel" id="src-q" placeholder="keyword, #hashtag or @account" maxlength="100" spellcheck="false" autocomplete="off"></label></div><div class="two"><label for="src-label"><span>Label <i>optional</i></span><input class="sel" id="src-label" placeholder="${J?"e.g. Mentions on X":"e.g. Feedback Q4"}"></label><label for="src-cat"><span>Category <i>optional</i></span><input class="sel" id="src-cat" placeholder="${J?"e.g. Social":"e.g. Bugs"}" maxlength="40"></label></div><label for="src-dir"><span>Project</span><select class="sel" id="src-dir">${c?"":h`<option value="">Choose project…</option>`}${x(c)}</select></label><div class="acts"><span class="end"></span><button class="btn pri" id="src-add">Add source</button></div></div>`,ae=(o)=>{let l=v.find((y)=>y.dir===o.dir&&y.url===o.source);return l?l.label||g(l.url):g(o.source)},L=(o)=>o.dir+" "+o.id,R=(o)=>o.dir+" "+o.source,M=(o)=>v.find((l)=>l.dir===o.dir&&l.url===o.source),O=(o)=>o.status==="dismissed"?"Dismissed":o.status==="done"?"Done":o.category||M(o)?.category||w(M(o)||{url:o.source}),K=(o,l)=>{let y=new Map;return o.forEach((S)=>{let P=l(S);y.set(P,{it:S,n:(y.get(P)?.n||0)+1})}),y},Z=c?new Map:K(k,(o)=>o.dir);if(!c){for(let o of a.shown)if(!Z.has(o)){let l=ze().find((y)=>y.dir===o);if(l)Z.set(o,{it:{dir:o,project:l.label},n:0})}}let we=(o)=>c||!a.shown.size||a.shown.has(o.dir),In=k.filter(we),ut=K(In,O);if(oe&&!ut.has(oe))oe="";let Os=In.filter((o)=>!oe||O(o)===oe),pt=K(Os,R);if(be&&!pt.has(be))be="";let zs=new Set(k.map(L));if(le&&!zs.has(le))le=null;if(je!==le)je=null;let ft=new Map;k.forEach((o,l)=>{if(!we(o)||(oe?O(o)!==oe:o.status==="dismissed"||o.status==="done")||be&&R(o)!==be)return;let y=O(o);ft.has(y)||ft.set(y,[]),ft.get(y).push(l)});let Q=[...ft.values()].flat();{let o=new Set(Q.map((l)=>L(k[l])));[...X].forEach((l)=>o.has(l)||X.delete(l))}if(!Q.some((o)=>L(k[o])===ge))ge=Q.length?L(k[Q[0]]):null;let mt=Q.filter((o)=>X.has(L(k[o]))).length,Gs=Z.size>1,On=(o,l,y,S)=>h`<div class="combo ice-combo" id="${o}"><button class="sel" aria-label="${l}" aria-haspopup="listbox" aria-expanded="false">${y}</button><div class="menu-pop" hidden><input class="sel" aria-label="Search ${l.toLowerCase()}" placeholder="Search…" spellcheck="false" autocomplete="off"><div class="pick-list" role="listbox">${S}</div></div></div>`,qt=(o,l,y,S,P="")=>h`<button type="button" role="option" data-v="${o}" data-q="${S.toLowerCase()}" class="${l?"on":""}${P}" aria-selected="${String(l)}">${y}</button>`,Et=new Map;for(let[o,{it:l}]of pt){let y=w(M(l)||{url:l.source});Et.has(y)||Et.set(y,[]),Et.get(y).push([o,l])}let Xt=(o)=>b(o.source,"link",M(o)?.social),en=be&&[...pt].find(([o])=>o===be)?.[1].it,zn=h`${ut.size>1||ut.has("Dismissed")||ut.has("Done")?On("ice-fc","Category",h`<span>${oe||"All categories"}</span>`,h`${qt("",!oe,h`<span>All categories</span>`,"all categories")}${[...ut].map(([o,{n:l}])=>qt(o,oe===o,h`<span>${o}</span><i>${l}</i>`,o))}`):""}${pt.size>1?On("ice-fs","Source",en?h`${Xt(en)}<span>${ae(en)}</span>`:h`<span>All sources</span>`,h`${qt("",!be,h`<span>All sources</span>`,"all sources")}${[...Et].map(([o,l])=>h`<div class="grp" data-g="${o.toLowerCase()}">${Xt(l[0][1])}${o}</div>${l.map(([y,S])=>qt(y,be===y,h`${Xt(S)}<span>${ae(S).toLowerCase().startsWith(o.toLowerCase()+":")?ae(S).slice(o.length+1).trim():ae(S)}</span><i>${pt.get(y).n}</i>`,o+" "+ae(S)," sub"))}`)}`):""}`,Us=h`<div class="ice-bar">${Q.length?h`<input type="checkbox" id="ice-all" aria-label="Select every request shown"${mt&&mt===Q.length?" checked":""}>`:""}<span class="count">${oe==="Dismissed"||oe==="Done"?`${Q.length} ${oe.toLowerCase()}`:`${Q.length<A?`${Q.length} of ${A}`:A} waiting`}</span><span class="end"></span>${String(zn)?h`<details class="ice-filt"><summary class="ib${oe||be?" on":""}" aria-label="Filter requests" title="Filter requests">${E("filter")}</summary><div class="ice-fpop">${zn}</div></details>`:""}<button class="btn ghost sm" id="ice-new" title="Add a request by hand">${E("plus")} Add</button><button class="btn sm" id="src-go"${v.length?"":" disabled"}>${E("refresh")} Gather all</button><button class="btn ghost sm" id="src-tog" aria-expanded="${String(vt??!v.length)}" aria-controls="src-sec">${E("link")} Sources · ${v.length}</button></div>`,Gn=X.size?h`<div class="ice-bulk" role="toolbar" aria-label="Selected requests"><span>${X.size} selected</span><span class="end"></span><button class="btn sm" id="ice-bp" title="Promote (p)">${E("plus")} Promote</button><button class="btn ghost sm" id="ice-bd" title="Dismiss (d)">${E("x")} Dismiss</button><button class="btn ghost sm" id="ice-bc" title="Clear selection (Esc)">Clear</button></div>`:"",Fs=(o)=>h`<div class="ice-form"><label for="ice-title" class="hint" style="margin:0">Idea title</label><input class="sel" id="ice-title" data-k="${L(o)}" maxlength="200" value="${o.text}" aria-label="Idea title"><label for="ice-details" class="hint" style="margin:0">Details</label><textarea class="sel" id="ice-details" rows="3" aria-label="Details"></textarea><div class="ice-form-acts"><span class="end"></span><button class="btn ghost sm" id="ice-cancel">Cancel</button><button class="btn pri sm" id="ice-ok">Promote</button></div></div>`,_s=(o)=>{if(!o.post)return"";if(o.replied)return h`<span class="hint" style="margin:0">You replied to this post ${Qe(o.replied)}.</span>`;let l=re&&re.k===L(o)?re:null,y=(S)=>h`<select class="sel" id="ice-rst" aria-label="Reply style"${S?" disabled":""}>${Object.entries(po).map(([P,U])=>h`<option value="${P}"${P===gn(o.dir)?" selected":""}>${U}</option>`)}</select>`;if(!l)return h`<div class="ice-form-acts"><span class="hint">You review it before it posts.</span>${q.connected?y(!1):""}<button class="btn sm" id="ice-rp">Reply</button></div>`;if(l.wait)return h`<div class="ice-form-acts"><span class="hint">Drafting…</span></div>`;return h`<div class="ice-form"><label for="ice-reply" class="hint" style="margin:0">Your reply${l.note?` · ${l.note}`:""}</label><textarea class="sel" id="ice-reply" rows="3" maxlength="2000" aria-label="Your reply"${l.busy||l.again?" disabled":""}>${l.text}</textarea><span class="hint" id="ice-rn" style="margin:0">${l.again?"Writing another…":`${l.text.length} chars`}</span><div class="ice-form-acts"><span class="end"></span>${q.connected?h`${y(l.busy||l.again)}<button class="btn ghost sm" id="ice-rg"${l.busy||l.again?" disabled":""}>Regenerate</button>`:""}<button class="btn ghost sm" id="ice-rc"${l.busy?" disabled":""}>Cancel</button><button class="btn pri sm" id="ice-rs"${l.busy||l.again||!l.text.trim()?" disabled":""}>${l.busy?"Sending…":"Send reply"}</button></div></div>`},Bs=(o)=>{let l=k[o],y=L(l),S=le===y,P=h`<div class="ice-row${ge===y?" cur":""}${X.has(y)?" sel":""}" data-i="${o}" data-k="${y}"><input type="checkbox" id="ice-ck-${o}" data-ck="${o}"${X.has(y)?" checked":""} aria-label="Select: ${l.text}"><span class="ice-src" title="${ae(l)}">${b(l.source,"link",v.find((F)=>F.dir===l.dir&&F.url===l.source)?.social)}</span><button class="ice-t" id="ice-o-${o}" data-o="${o}" aria-expanded="${String(S)}" title="${l.text}">${l.text}</button><span class="ice-meta">${Gs?h`<span class="nm" title="${l.project||""}">${rt(l.dir,l.project||"")}${De(l.project||"")}</span>`:""}${l.status==="done"&&l.written?h`<span title="Written back ${Qe(l.written)}">written back</span>`:""}${l.status==="done"&&l.writeError?h`<span title="${l.writeError}">write-back failed</span>`:""}${l.status==="promoted"?h`<span title="Promoted to Ideas: ${l.idea||""}">promoted</span>`:""}${l.replied?h`<span title="Replied ${Qe(l.replied)}">replied</span>`:""}<span class="ice-age">${Qe(l.at)}</span><span class="ice-ra">${l.status==="promoted"||l.status==="done"?"":h`<button class="btn ghost sm" id="ice-pr-${o}" data-pr="${o}" title="Promote to Ideas (p)" aria-label="Promote to Ideas: ${l.text}">${E("plus")}</button>`}${l.status==="promoted"||l.status==="done"?"":l.status==="dismissed"?h`<button class="btn ghost sm" id="ice-rs-${o}" data-rs="${o}" title="Restore to waiting" aria-label="Restore: ${l.text}">Restore</button>`:h`<button class="btn ghost sm" id="ice-ds-${o}" data-ds="${o}" title="Dismiss (d)" aria-label="Dismiss: ${l.text}">${E("x")}</button>`}</span></span></div>`,U=S?h`<div class="ice-open">${l.notes?h`<div class="ice-notes">${l.notes}</div>`:""}${(l.images||[]).filter((F)=>/^https:\/\//.test(F)).length?h`<details class="ice-imgs"><summary>Show images (${l.images.filter((F)=>/^https:\/\//.test(F)).length}) — loads them from the source's site</summary>${l.images.filter((F)=>/^https:\/\//.test(F)).map((F,_)=>{let ce=`/ice-image?dir=${encodeURIComponent(l.dir)}&id=${encodeURIComponent(l.id)}&i=${_}`;return h`<a href="${ce}" target="_blank" rel="noopener noreferrer"><img data-src="${ce}" alt="" referrerpolicy="no-referrer"></a>`})}</details>`:""}<span class="hint" style="margin:0">From ${ae(l)} · ${Qe(l.at)}${l.post?h` · <a href="${l.post}" target="_blank" rel="noopener">open post</a>`:""}</span>${_s(l)}${je===y?Fs(l):""}</div>`:"";return h`${P}${U}`},Ws=A&&!Q.length?h`<div class="ice-zero"><h4>No matches</h4><p style="margin-top:10px"><button class="btn sm" id="ice-unf">Clear filters</button></p></div>`:Q.length?h`<div class="ice-list">${[...ft].map(([o,l])=>h`<div class="ice-cat">${o}<i>${l.length}</i></div>${l.map(Bs)}`)}</div>`:h`<div class="ice-zero"><h4>Nothing waiting</h4></div>`,Ct=vt??!v.length,tn=Ct&&!s("src-sec")?.classList.contains("open"),Vs=h`<div class="src-scrim${Ct&&!tn?" on":""}" id="src-scrim"></div><aside class="src-sec${Ct&&!tn?" open":""}" id="src-sec" aria-label="Sources"${Ct?"":" inert"}><header><div class="t"><b>Sources</b><div class="src-chips"><a id="src-to-settings" class="schip" role="button" tabindex="0" title="${f&&f.every&&f.every!=="off"?`Checked every ${f.every}`:"Auto-check off"}: change in Settings">${E("clock")}${f&&f.every&&f.every!=="off"?f.every:"Off"}</a>${q.connected?h`<span class="schip on" title="ChatGPT${q.email?": "+q.email:""}">${E("ai")}ChatGPT<a id="cg-out" role="button" tabindex="0" aria-label="Disconnect ChatGPT" title="Disconnect">${E("x")}</a></span>`:h`<a id="cg-in" class="schip" role="button" tabindex="0" title="Connect ChatGPT">${E("ai")}ChatGPT</a>`}${(f.google||{}).connected?h`<span class="schip on" title="Google connected">${E("google")}Google<a id="gg-out" role="button" tabindex="0" aria-label="Disconnect Google" title="Disconnect">${E("x")}</a></span>`:h`<a id="gg-in" class="schip" role="button" tabindex="0" title="Connect Google">${E("google")}Google</a>`}</div></div><div class="src-hda">${v.length?h`<button class="btn sm" id="src-new" aria-expanded="${String(fe)}" aria-controls="src-addbox">${E("plus")} Add</button>`:""}<button class="ib" id="src-x" aria-label="Close sources" title="Close">${E("close")}</button></div></header><div class="body">${Y}${v.length?h`<div class="src-list">${I}</div>`:ye}</div></aside>`,Qs=q.use==="ask"&&!q.connected?h`<div class="cg-onb"><div class="acts"><b>Gather social posts with ChatGPT?</b><span class="end"></span><button class="btn ghost" id="cg-skip">Skip</button><button class="btn pri" id="cg-go">Connect</button></div></div>`:"",Js=s("src-sec")?.querySelector(".body")?.scrollTop??0;if(s("pbody").innerHTML=f&&f.error?h`<p style="color:var(--dim)">${f.error}</p>`:!f?h`<p style="color:var(--dim)">The icebox could not be read.</p>`:h`${Qs}${Us}${Gn}${V}${Ws}${Vs}`,!f||f.error)return;let Un=s("src-sec")?.querySelector(".body");if(Un)Un.scrollTop=Js;if(d&&d[0]===le&&s("ice-title"))s("ice-title").value=d[1],s("ice-details").value=d[2];if(s("src-add")){if(t[5])s("src-plat").value=t[5];if(s("src-q").value=t[6]||"",s("src-url").value=t[0],s("src-label").value=t[1],s("src-cat").value=t[4]||"",t[3]!==void 0&&s("src-dir"))s("src-dir").value=t[3]}if(s("src-to-settings"))s("src-to-settings").onclick=()=>{a.setQ="sources",he("settings",!0)};let Ys=async()=>{let o=window.open("","_blank"),l=await T("/chatgpt",{op:"connect"});if(l.ok&&o)o.location=l.url;else if(o?.close(),l.ok)location.href=l.url};for(let o of["cg-go","cg-in"])if(s(o))s(o).onclick=Ys;if(s("gg-in"))s("gg-in").onclick=async()=>{if(!(f.google||{}).hasClient){C("Add your Google client in Settings first"),a.setQ="google",he("settings",!0);return}let o=window.open("","_blank"),l=await T("/google",{op:"connect"});if(l.ok&&o)o.location=l.url;else if(o?.close(),l.ok)location.href=l.url;else C(l.error||"Could not start Google sign-in")};if(s("gg-out"))s("gg-out").onclick=async()=>{if(!confirm("Disconnect Google? Done requests stop being written to sheets."))return;if((await T("/google",{op:"disconnect"})).ok)C("Google disconnected"),z()};if(s("cg-skip"))s("cg-skip").onclick=async()=>{if((await T("/chatgpt",{op:"skip"})).ok)z()};if(s("cg-out"))s("cg-out").onclick=async()=>{if(!confirm("Disconnect ChatGPT? Gather goes back to your agent."))return;if((await T("/chatgpt",{op:"disconnect"})).ok)C("ChatGPT disconnected"),z()};if(tn)s("src-sec").offsetWidth,s("src-sec").classList.add("open"),s("src-scrim").classList.add("on");let At=()=>{vt=!1,s("src-sec").classList.remove("open"),s("src-scrim").classList.remove("on"),s("src-sec").inert=!0,s("src-tog").setAttribute("aria-expanded","false"),s("src-tog").focus()};if(s("src-x").onclick=s("src-scrim").onclick=At,s("src-new"))s("src-new").onclick=()=>{let o=s("src-addbox");if(it=o.hidden,o.hidden=!it,s("src-new").setAttribute("aria-expanded",it),it)s(at==="social"?"src-q":"src-url").focus()};if(s("src-sec").onkeydown=(o)=>{if(o.key==="Escape")o.stopPropagation(),At()},s("src-tog").onclick=()=>{if(s("src-sec").classList.contains("open"))return At();vt=!0,z().then(()=>vt&&s("src-url")?.focus())},gs("ice-fs",(o)=>{be=o,z()}),gs("ice-fc",(o)=>{oe=o,z()}),s("ice-unf"))s("ice-unf").onclick=()=>{if(oe=be="",!c)a.shown.clear();Ft(),z()};s("pbody").querySelectorAll("[data-kind]").forEach((o)=>o.onclick=()=>{if(at===o.dataset.kind)return;at=o.dataset.kind,z().then(()=>s(at==="social"?"src-q":"src-url")?.focus())});let Ue=async(o,l)=>{let y=await T("/sources",o);if(y.ok)l(y),N();if(ee())z()};s("pbody").querySelectorAll("[data-mv]").forEach((o)=>{let l=v[+o.dataset.mv],y=s("src-mb-"+o.dataset.mv),S=n.get(o.dataset.k);if(S&&[...o.options].some((P)=>P.value===S))o.value=S;(o.onchange=()=>{y.disabled=o.value===l.dir})(),y.onclick=()=>Ue({op:"move",dir:l.dir,to:o.value,url:l.url},()=>C("Source moved"))}),s("pbody").querySelectorAll("[data-wb]").forEach((o)=>{let l=v[+o.dataset.wb];o.onchange=()=>{if(o.checked&&l.social===void 0&&/docs\.google\.com/.test(l.url)&&!(f.google||{}).connected){alert("Connect Google first (Sources header), so kaizen can write to the sheet."),o.checked=!1;return}if(o.checked&&!confirm("When a promoted request's run is done, kaizen will write that back to this source. A closed issue or a changed cell is visible to others. Turn on?")){o.checked=!1;return}Ue({op:"writeback",dir:l.dir,url:l.url,on:o.checked},()=>C(o.checked?"Write back on":"Write back off"))}}),s("pbody").querySelectorAll("[data-ct]").forEach((o)=>{let l=v[+o.dataset.ct],y=s("src-cs-"+o.dataset.ct),S=u.get(o.dataset.k);if(S!==void 0)o.value=S;(o.oninput=()=>{y.disabled=o.value.trim()===(l.category||"")})(),o.onkeydown=(P)=>{if(P.key==="Enter"&&!y.disabled)y.click()},y.onclick=()=>{y.disabled=!0,Ue({op:"category",dir:l.dir,url:l.url,category:o.value.trim()},()=>C(o.value.trim()?`New requests from ${l.label||g(l.url)} go under ${o.value.trim()}`:"Category cleared"))}});let Fn=()=>{if(!document.activeElement||document.activeElement===document.body)s("pbody").querySelector(".ice-row.cur .ice-t")?.focus()},_n=(o)=>{let l=Q.findIndex((P)=>L(k[P])===ge);if(l<0||!o.has(ge))return;let y=(P)=>!o.has(L(k[P])),S=Q.slice(l+1).find(y)??Q.slice(0,l).reverse().find(y);ge=S===void 0?null:L(k[S])},nn=(o,l,y,S={})=>(async()=>{if(_n(new Set([L(l)])),(await T("/icebox",{op:o,dir:l.dir,ids:[l.id],...S})).ok){if(o==="promote"&&le===L(l))le=je=null;C(y),N()}if(ee())z().then(Fn)})(),Bn=async(o)=>{let l=k.filter((S)=>X.has(L(S)));if(!l.length)return;_n(new Set(l.map(L))),zt=!0,s("ice-bp").disabled=s("ice-bd").disabled=!0;let y=0;try{if(o==="dismiss")for(let S of new Set(l.map((P)=>P.dir))){let P=l.filter((U)=>U.dir===S).map((U)=>U.id);if((await T("/icebox",{op:o,dir:S,ids:P})).ok)y+=P.length}else for(let S of l)if((await T("/icebox",{op:o,dir:S.dir,ids:[S.id]})).ok)y++}finally{zt=!1}if(X.clear(),y)C(`${y} ${o==="promote"?"promoted to Ideas":"dismissed"}${y<l.length?`, ${l.length-y} not`:""}`);if(N(),ee())z().then(Fn)};if(Gn)s("ice-bp").onclick=()=>Bn("promote"),s("ice-bd").onclick=()=>Bn("dismiss"),s("ice-bc").onclick=()=>{X.clear(),z()};if(s("ice-all"))s("ice-all").onchange=()=>{let o=Q.map((l)=>L(k[l]));if(mt===Q.length)o.forEach((l)=>X.delete(l));else o.forEach((l)=>X.add(l));z()};if(s("ice-all"))s("ice-all").indeterminate=mt>0&&mt<Q.length;s("pbody").querySelectorAll("[data-ck]").forEach((o)=>o.onchange=()=>{let l=L(k[+o.dataset.ck]);ge=l,o.checked?X.add(l):X.delete(l),z()});let Wn=(o)=>{let l=L(k[o]);ge=l,le=le===l?null:l,je=null,z().then(()=>s("ice-o-"+o)?.focus())};s("pbody").querySelectorAll(".ice-row").forEach((o)=>o.onclick=(l)=>{if(!l.target.closest("input,button"))Wn(+o.dataset.i)}),s("pbody").querySelectorAll("[data-o]").forEach((o)=>o.onclick=()=>Wn(+o.dataset.o)),s("pbody").querySelectorAll("details.ice-imgs").forEach((o)=>o.ontoggle=()=>o.open&&o.querySelectorAll("img[data-src]").forEach((l)=>l.src=l.dataset.src)),s("pbody").querySelectorAll("[data-pr]").forEach((o)=>o.onclick=()=>{ge=le=je=L(k[+o.dataset.pr]),z().then(()=>{s("ice-title")?.focus(),s("ice-title")?.select()})}),s("pbody").querySelectorAll("[data-ds]").forEach((o)=>o.onclick=()=>{o.disabled=!0,nn("dismiss",k[+o.dataset.ds],"Dismissed")}),s("pbody").querySelectorAll("[data-rs]").forEach((o)=>o.onclick=()=>{o.disabled=!0,nn("restore",k[+o.dataset.rs],"Restored")});let ht=k.find((o)=>L(o)===le);if(s("ice-rp"))s("ice-rp").onclick=async()=>{let o=ht,l=L(o);re={k:l,text:"",wait:!0},z();let y=await T("/reply",{op:"draft",dir:o.dir,id:o.id,style:gn(o.dir)});if(!re||re.k!==l)return;re={k:l,text:y.text||"",note:y.ok?y.note||"":"",wait:!1},z().then(()=>s("ice-reply")?.focus())};if(s("ice-rst"))s("ice-rst").onchange=(o)=>{let l=ht.dir;wt[l]=o.target.value;try{localStorage.setItem("kz-reply-style:"+l,wt[l])}catch(y){}};if(s("ice-rg"))s("ice-rg").onclick=async()=>{let o=ht,l=re;l.again=!0,z();let y=await T("/reply",{op:"draft",dir:o.dir,id:o.id,style:gn(o.dir),avoid:l.text});if(re!==l)return;if(l.again=!1,y.text)l.text=y.text;l.note=y.ok?y.note||"":"",z().then(()=>s("ice-reply")?.focus())};if(s("ice-reply")){let o=s("ice-reply");o.oninput=()=>{re.text=o.value,s("ice-rn").textContent=`${o.value.length} chars`,s("ice-rs").disabled=!o.value.trim()},o.onkeydown=(l)=>{if(l.key==="Escape")l.stopPropagation(),s("ice-rc").click()},s("ice-rc").onclick=()=>{re=null,z()},s("ice-rs").onclick=async()=>{let l=ht,y=re;y.busy=!0,z();let S=await T("/reply",{op:"send",dir:l.dir,id:l.id,text:y.text});if(S.ok)re=null,C("Reply posted");else if(S.sent)re=null;else y.busy=!1;if(N(),ee())z()}}if(s("ice-ok")){let o=()=>{let l=s("ice-title").value.trim();if(!l){s("ice-title").focus();return}s("ice-ok").disabled=!0,nn("promote",ht,"Promoted to Ideas",{text:l,details:s("ice-details").value})};s("ice-ok").onclick=o,s("ice-cancel").onclick=()=>{je=null,z()},s("ice-title").onkeydown=(l)=>{if(l.key==="Enter")o();if(l.key==="Escape")s("ice-cancel").click()},s("ice-details").onkeydown=(l)=>{if(l.key==="Enter"&&(l.ctrlKey||l.metaKey))o();if(l.key==="Escape")s("ice-cancel").click()}}Gt=(o)=>{if(o.altKey||o.ctrlKey||o.metaKey)return!1;let l=o.key,y=Q.findIndex((U)=>L(k[U])===ge),S=Q[y];if(l==="Escape"){if(s("src-sec")?.classList.contains("open"))return At(),!0;if(le){if(je)je=null;else le=null;return z(),!0}if(X.size)return X.clear(),z(),!0;return!1}if(y<0)return!1;if(l==="j"||l==="k"){o.preventDefault();let U=Q[Math.max(0,Math.min(Q.length-1,y+(l==="j"?1:-1)))];return ge=L(k[U]),s("pbody").querySelectorAll(".ice-row").forEach((F)=>F.classList.toggle("cur",+F.dataset.i===U)),s("pbody").querySelector(`.ice-row[data-i="${U}"]`)?.scrollIntoView({block:"nearest"}),!0}let P=l==="o"?s("ice-o-"+S):l==="x"?s("ice-ck-"+S):l==="p"?X.size?s("ice-bp"):s("ice-pr-"+S):l==="d"?X.size?s("ice-bd"):s("ice-ds-"+S):null;if(!P||P.disabled)return!1;return o.preventDefault(),P.click(),!0},s("pbody").querySelectorAll("[data-chk]").forEach((o)=>{let l=v[+o.dataset.chk];o.onclick=()=>{o.disabled=!0,o.innerHTML=E("refresh")+" Checking…",Ue({op:"gather",dir:l.dir,url:l.url},(y)=>{let S=y.results&&y.results[0];C(S?S.ok?`${l.label||g(l.url)}: ${S.note}${S.added?" in the icebox":""}`:`Failed: ${S.note}`:"Checked")})}}),s("pbody").querySelectorAll("[data-ag]").forEach((o)=>{let l=v[+o.dataset.ag];o.onclick=()=>{if(o.disabled=!0,G)o.innerHTML=E("refresh")+" Gathering…";Ue({op:"agent",dir:l.dir,url:l.url},(y)=>{let S=y.results&&y.results[0];C(y.via==="chatgpt"?S&&S.ok?`${l.label||g(l.url)}: ${S.note}${S.added?" in the icebox":""}`:`Failed: ${S?S.note:"no answer"}`:"/kaizen gather opened in your terminal: "+Ie(y.agent))})}}),s("pbody").querySelectorAll("[data-rm]").forEach((o)=>{let l=v[+o.dataset.rm];o.onclick=()=>{if(!confirm(`Remove ${l.label||g(l.url)}? What it gathered stays; added again later, it may bring back ones you deleted or dismissed.`))return;Ue({op:"remove",dir:v[+o.dataset.rm].dir,url:v[+o.dataset.rm].url},()=>C("Source removed"))}});let Vn=k.findIndex((o)=>L(o)===ge);if(r){let o=k.findIndex((l)=>L(l)===r[0]);(o>=0?s(r[1]+"-"+o):Vn>=0?s("ice-o-"+Vn):null)?.focus()}let Tt=!r&&t[2]&&s(t[2]);if(Tt)(Tt.disabled?s(Tt.id.replace("src-mb-","src-mv-").replace("src-cs-","src-ct-")):Tt)?.focus();if(s("src-add"))s("src-add").onclick=()=>{let o=at==="social",l=s("src-url").value.trim(),y=s("src-q").value.trim(),S=s("src-plat").value;if(o?!y:!l){s(o?"src-q":"src-url").focus();return}let P=s("src-dir").value;if(!P){s("src-dir").focus();return}s("src-add").disabled=!0,s("src-add").textContent="Adding…",(async()=>{let U=s("src-label").value.trim()||(o?`${kt[S]}: ${y}`:""),F=s("src-cat").value.trim(),_=await T("/sources",o?{op:"add",dir:P,platform:S,query:y,label:U,category:F}:{op:"add",dir:P,url:l,label:U,category:F});if(_.ok&&o)s("src-q").value=s("src-label").value=s("src-cat").value="",C("Source added"),N();else if(_.ok){s("src-url").value=s("src-label").value=s("src-cat").value="";let ce=await T("/sources",{op:"gather",dir:P,url:l}),me=ce.results&&ce.results[0];C(me?me.ok?`Source added: ${me.note} in the icebox`:`Source added, but: ${me.note}`:"Source added"),N()}else C(_.error||"Could not add source");if(_.ok)it=!1;if(ee())z()})()},s("src-url").onkeydown=s("src-q").onkeydown=s("src-label").onkeydown=s("src-cat").onkeydown=(o)=>{if(o.key==="Enter")s("src-add").click()};if(s("ice-new"))s("ice-new").onclick=()=>{let o=!c;if(!c&&!ze().length)return C("Pick a project first");let l=_e(`${o?'<div class="combo" id="ndc"><button type="button" class="sel" id="newdir" aria-label="Project for this request" aria-haspopup="listbox" aria-expanded="false"></button><div class="menu-pop" hidden><input class="sel" aria-label="Search projects" placeholder="Search projects…" spellcheck="false" autocomplete="off"><div id="nds" role="listbox"></div></div></div>':""}<textarea id="newidea" placeholder="What did someone ask for?" aria-label="Request"></textarea><div class="att"></div><input type="file" multiple hidden><div class="row"><button type="button" class="ib" id="newpick" aria-label="Attach files" title="Attach files">${E("clip")}</button><button type="button" class="btn ghost" value="">Cancel</button><button class="btn pri">Add</button></div>`),y=l.querySelector("form"),S=y.querySelector("textarea"),P=[],U=(_)=>{P.push(_),y.querySelector(".att").textContent=P.map((ce)=>ce.name).join(" · ")};if(y.querySelector("#newpick").onclick=()=>y.querySelector("input[type=file]").click(),y.querySelector("input[type=file]").onchange=(_)=>{[..._.target.files].forEach(U),_.target.value=""},S.onpaste=(_)=>{for(let ce of _.clipboardData.items)if(ce.kind==="file"){let me=ce.getAsFile();U(new File([me],me.name==="image.png"?`paste-${Date.now()}.png`:me.name,{type:me.type})),_.preventDefault()}},y.querySelector(".btn.ghost").onclick=()=>l.close(),o)Ut(y);let F=Be([S]);if(F)y.querySelector(".row").prepend(F);l.addEventListener("close",()=>de(!1)),S.onkeydown=(_)=>{if(_.key==="Enter"&&!_.shiftKey)_.preventDefault(),y.requestSubmit()},y.onsubmit=async(_)=>{_.preventDefault();let ce=S.value.trim(),me=c||Pe;if(!ce)return S.focus();if(!me)return C("Pick a project first");if((await T("/icebox",{op:"add",dir:me,text:ce,files:await jt(P)})).ok)C("Added to the icebox"),l.close()},S.focus()};if(s("src-go"))s("src-go").onclick=()=>{s("src-go").disabled=!0,s("src-go").innerHTML=E("refresh")+" Gathering…",Ue({op:"gather",dir:c||void 0},(o)=>{let l=o.results||[],y=(F)=>v.some((_)=>_.url===F.url&&_.social),S=l.reduce((F,_)=>F+_.added,0),P=l.filter((F)=>!F.ok&&!y(F)).length,U=l.filter(y).length;C((S?`${S} new in the icebox`:"Nothing new")+(P?`, ${P} source${P===1?"":"s"} could not be read`:"")+(U?`; ${U} social for /kaizen gather`:""))})}}var bn=new URLSearchParams(location.search).has("all");function Ge(e){if(bn)return;try{e?localStorage.setItem("kz-proj",e):localStorage.removeItem("kz-proj")}catch(t){}}var De=(e)=>e.split(/[\\/]/).pop()||e,rt=(e,t="")=>{let n=h`<span class="plogo" aria-hidden="true">${(De(t)||"?").charAt(0).toUpperCase()}</span>`;return a.S?.projects?.some((i)=>i.dir===e&&i.logo)?h`<img class="plogo" src="/project-logo?dir=${encodeURIComponent(e)}" alt="" loading="lazy" onerror="this.outerHTML=this.dataset.f" data-f="${String(n)}">`:n},Bt=(e,t)=>h`${rt(e,t)}<span>${De(t)}</span>`;function Vt(){let e=s("projq").value.trim().toLowerCase(),t=0;s("projs").innerHTML=a.PL.map((i,r)=>i[0].toLowerCase().includes(e)?h`${i[2]&&!t++?h`<div class="grp">In your projects folder</div>`:""}<button role="option" data-i="${r}" title="${i[0]}">${i[1]==="all"?h`<span class="plogo" aria-hidden="true">${E("board")}</span><span>${i[0]}</span>`:i[1]==="__new"||i[1]==="__find"||i[1]==="__clone"?h`<span class="plogo" aria-hidden="true">${E("plus")}</span><span>${i[0]}</span>`:Bt(i[1],i[0])}</button>`:"").join("")||'<div class="grp">No match</div>';let n=s("projs").querySelector("button");if(n)n.classList.add("on")}function _t(e){if(s("projpop").hidden=!e,s("proj").setAttribute("aria-expanded",e),e)s("projq").value="",Vt(),s("projq").focus()}async function fo(e){if(e==="__find"){C("Searching…");let t=await T("/find",{});if(t.ok)C(t.added?`Found ${t.added} new project${t.added===1?"":"s"}`:"No new projects found")}else if(e==="__new"){let t=_e('<b>New project</b><input name="name" placeholder="Project name" aria-label="Project name" spellcheck="false" autocomplete="off"><div class="row"><input name="to" placeholder="Folder to create" aria-label="Create in" spellcheck="false" autocomplete="off"><button type="button" class="btn ghost" data-a="pick">Pick…</button></div><div class="row"><button type="button" class="btn ghost" data-a="x">Cancel</button><button class="btn pri">Create</button></div>'),n=t.querySelector("form"),i=n.querySelector("[name=name]"),r=n.querySelector("[name=to]"),d="";i.oninput=async()=>{let c=i.value.trim();if(!c||/[\\/:*?"<>|]/.test(c)||r.value.trim()&&r.value!==d)return;let m=await T("/new-project",{name:c,check:!0});if(m.ok&&i.value.trim()===c)r.value=d=m.to},n.querySelector("[data-a=x]").onclick=()=>t.close(),n.querySelector("[data-a=pick]").onclick=async()=>{let c=await T("/pick-folder",{});if(c.path)r.value=c.path.replace(/[\\/]+$/,"")+(c.path.includes("\\")?"\\":"/")+(i.value.trim()||"")},i.focus();let u=await new Promise((c)=>{t.addEventListener("close",()=>c(null)),n.onsubmit=async(m)=>{if(m.preventDefault(),!i.value.trim())return i.focus();let f=await T("/new-project",{name:i.value.trim(),to:r.value.trim()||void 0});if(!f.ok)return;c(f.dir),t.close()}});if(!u)return;await T("/cd",{dir:u}),a.all=!1,a.dir=u,Ge(u),C("Project created")}else if(e==="__clone"){let t=_e('<b>Clone from GitHub</b><input name="url" placeholder="https://github.com/owner/repo" aria-label="GitHub link (https or ssh)" spellcheck="false" autocomplete="off"><div class="row"><input name="to" placeholder="Folder to clone into" aria-label="Clone into" spellcheck="false" autocomplete="off"><button type="button" class="btn ghost" data-a="pick">Pick…</button></div><div class="row"><button type="button" class="btn ghost" data-a="x">Cancel</button><button class="btn pri">Clone</button></div>'),n=t.querySelector("form"),i=n.querySelector("[name=url]"),r=n.querySelector("[name=to]"),d="",u="",c=async()=>{let f=i.value.trim();if(!f)return null;let g=await T("/clone",{url:f,check:!0});if(!g.ok)return null;if(d=g.name,!r.value.trim()||r.value===u)r.value=u=g.to;return g};i.onchange=c,n.querySelector("[data-a=x]").onclick=()=>t.close(),n.querySelector("[data-a=pick]").onclick=async()=>{if(!await c())return i.focus();let f=await T("/pick-folder",{});if(f.path)r.value=f.path.replace(/[\\/]+$/,"")+(f.path.includes("\\")?"\\":"/")+d},i.focus();let m=await new Promise((f)=>{t.addEventListener("close",()=>f(null)),n.onsubmit=async(g)=>{if(g.preventDefault(),!await c())return i.focus();C("Cloning…");let b=await T("/clone",{url:i.value.trim(),to:r.value.trim()||void 0});if(!b.ok)return;f(b.dir),t.close()}});if(!m)return;await T("/cd",{dir:m}),a.all=!1,a.dir=m,Ge(m),C("Cloned")}else if(e==="all")a.all=!0,Ge();else if((await T("/cd",{dir:e})).ok)a.all=!1,a.dir=e,Ge(e);if(await N(),W==="sources")z()}var Pe=null;function Ut(e){let t=mo(),n=e.querySelector("#newdir"),i=e.querySelector("#ndc .menu-pop"),r=i.querySelector("input"),d=e.querySelector("#nds");if(!t.some((f)=>f.dir===Pe))Pe=t[0]?.dir??null;let u=()=>{let f=t.find((g)=>g.dir===Pe);n.innerHTML=f?Bt(f.dir,f.label):"Choose project"},c=()=>{let f=r.value.trim().toLowerCase();d.innerHTML=t.filter((g)=>g.label.toLowerCase().includes(f)).map((g)=>h`<button type="button" role="option" data-d="${g.dir}" title="${g.label}" class="${g.dir===Pe?"on":""}">${Bt(g.dir,g.label)}</button>`).join("")||'<div class="grp">No match</div>',d.querySelectorAll("button").forEach((g)=>g.onclick=()=>{Pe=g.dataset.d,u(),m(!1),e.querySelector("#newidea").focus()})},m=(f)=>{if(i.hidden=!f,n.setAttribute("aria-expanded",f),f)r.value="",c(),r.focus()};n.onclick=(f)=>{f.preventDefault(),m(i.hidden)},r.oninput=c,r.onkeydown=(f)=>{if(f.key==="Escape")f.stopPropagation(),m(!1);if(f.key==="Enter")f.preventDefault(),d.querySelector("button")?.click()},u()}function mo(){let e=ze(),t=e.filter((n)=>a.shown.has(n.dir));return t.length?t:e}function ze(){let e=[...a.S.projects];for(let t of a.S.cards)if(!e.some((n)=>n.dir===t.state))e.push({dir:t.state,label:t.where});return e}var lt=[];function Wt(){let e=s("showq").value.trim().toLowerCase();lt=ze(),s("shows").innerHTML=lt.map((n,i)=>n.label.toLowerCase().includes(e)?h`<button type="button" role="menuitemcheckbox" data-i="${i}" aria-checked="${String(a.shown.has(n.dir))}" title="${n.label}">${Bt(n.dir,n.label)}<svg class="ck"><use href="#i-check"/></svg></button>`:"").join("")||'<div class="grp">No match</div>';let t=lt.filter((n)=>a.shown.has(n.dir)).length;s("showcount").textContent=t?`${t} of ${lt.length} shown`:`All ${lt.length} shown`}function Ft(){try{localStorage.setItem("kz-show",JSON.stringify([...a.shown]))}catch(e){}if(H(),ee())z()}function ys(){s("proj").onclick=()=>_t(s("projpop").hidden),s("projq").oninput=Vt,s("projq").onkeydown=(e)=>{let t=[...s("projs").querySelectorAll("button")],n=t.findIndex((i)=>i.classList.contains("on"));if(e.key==="Escape")_t(!1),s("proj").focus();else if(e.key==="Enter"){if(t[n])t[n].click()}else if((e.key==="ArrowDown"||e.key==="ArrowUp")&&t[n]){e.preventDefault();let i=t[(n+(e.key==="ArrowDown"?1:t.length-1))%t.length];t[n].classList.remove("on"),i.classList.add("on"),i.scrollIntoView({block:"nearest"})}},s("projs").onclick=(e)=>{let t=e.target.closest("button");if(t)_t(!1),fo(a.PL[t.dataset.i][1])},document.addEventListener("click",(e)=>{if(!e.target.closest("#combo"))_t(!1)}),s("show").onclick=()=>{let e=s("showpop").hidden;if(s("showpop").hidden=!e,s("show").setAttribute("aria-expanded",e),e)s("showq").value="",Wt(),s("showq").focus()},s("showq").oninput=Wt,s("showq").onkeydown=(e)=>{if(e.key==="Escape")s("showpop").hidden=!0,s("show").setAttribute("aria-expanded",!1),s("show").focus()},s("shows").onclick=(e)=>{let t=e.target.closest("button[data-i]"),n=t?.dataset.i,i=lt[n]?.dir;if(!i)return;a.shown.has(i)?a.shown.delete(i):a.shown.add(i),Ft(),s("shows").querySelector(`[data-i="${n}"]`)?.focus()},s("showall").onclick=()=>{a.shown.clear(),Ft()},document.addEventListener("click",(e)=>{if(!e.target.closest("#showc"))s("showpop").hidden=!0,s("show").setAttribute("aria-expanded",!1)}),s("newtop").onclick=$t}var Se=null,xn="",yn=6,Qt=new Set,xt=(()=>{try{return JSON.parse(localStorage.getItem("kz-order"))||{}}catch(e){return{}}})(),te=!1,St=(()=>{try{return localStorage.getItem("kz-ideas-tab")==="backlog"?"backlog":"ideas"}catch(e){return"ideas"}})(),He=null,vn=[["high","High+",(e)=>e==="critical"||e==="high"],["medium","Medium",(e)=>e==="medium"],["low","Low",(e)=>e==="low"],["none","No severity",(e)=>!e]],kn=()=>(a.S.backlog||[]).map((e)=>({...e,kind:"backlog",status:e.starting?"starting":"idea",title:e.text,column:0,archived:!1,_k:"backlog:"+e.state+":"+e.source+"#"+e.n})),wn=(e)=>{if(e.kind!=="backlog")return xe(e);let t=a.S.cards.find((n)=>n.kind==="run"&&n.id===e.source&&n.state===e.state);if(!t)return C(e.source==="orphan"?"Kept from a run that was pruned":"That run is not on this board");Ss(t,"backlog",e.n)},Lt=!1,ke=new Set,D=(e)=>e._k||(e.kind==="idea"?"idea:"+e.state+":"+e.text:"run:"+e.state+":"+e.id),ho=(e)=>e.kind==="run"?a.S.cards.filter((t)=>t.parent===e.id&&t.state===e.state):[],go=(e)=>!!e.parent&&a.S.cards.some((t)=>t.kind==="run"&&t.id===e.parent&&t.state===e.state&&!t.archived&&t.column!==4),$n=new Set,vs=(e)=>nt.has(st(e))?"Sent to agent":e.status!=="waiting"?"Open":{"approvals.plan":"Review plan",findings:"See findings","approvals.review":"Review work"}[e.awaiting]||"Open";function bo(e){let t=D(e),n=document.createElement("div");n.className="card"+(t===a.openKey?" open":"")+(t===a.menuKey?" menu":"")+(a.flash.has(t)?" flash":"")+(e.archived?" archived":""),n.tabIndex=0,n.dataset.k=t,n.setAttribute("role","button");let i=Ke[e.status]||"idea",r=e.kind==="run"?e.text.replace(/-/g," "):"",d=e.status==="waiting"?gt(e.awaiting)||"needs you":e.status||"idea",u=[],c=[],m=(p,v,k="")=>h`<span class="mk${k}" role="img" title="${v}" aria-label="${v}"><svg><use href="#${p}"/></svg></span>`;if(a.all){let p=e.where.split("/").filter(Boolean).pop()||e.where;u.push(h`<span class="chip proj" title="${e.where}">${p}</span>`)}for(let p of e.tags||[])if(ns[p])c.push(m("c-"+p,p==="full"?"Full run: separate reviewer":p==="lite"?"Lite run: one session":rn[p]||p,p==="full"||p==="lite"?" accent":""));else if(p==="yolo")c.push(h`<span class="mk warn" title="Started in Yolo: the agent runs commands without asking">yolo</span>`);else u.push(h`<span class="chip">${rn[p]||p}</span>`);if(e.pty&&e.pty.alive&&e.pty.asking)c.push(m("i-ask","The agent is asking you something: open it, terminal button at the top"," warn ask"));else if(e.pty&&e.pty.alive)c.push(m("i-term","The agent is running in this card: open it, terminal button at the top"," run"));let f=e.notes&&/^\[[^\]]*\] (?:Gathered from|Promoted from the icebox:) (.+?)\. Outside text/.exec(e.notes);if(e.parent)u.push(h`<span class="chip link" title="Filed by ${e.parent}">${e.parent.replace(/^\d{4}-\d\d-\d\d-/,"").replace(/-/g," ")}</span>`);if(e.kind==="backlog"){if(e.severity)u.push(h`<span class="chip${e.severity==="critical"||e.severity==="high"?" warn":""}"><i></i>${e.severity}</span>`);u.push(e.source==="orphan"?h`<span class="chip" title="Kept from a pruned run">orphaned</span>`:h`<span class="chip link" title="Left by ${e.source}${e.at?" · "+e.at:""}">${e.source.replace(/^\d{4}-\d\d-\d\d-/,"").replace(/-/g," ")}</span>`)}if(e.branch)u.push(h`<span class="chip" title="Built on its own branch, ${e.branch}">branch</span>`);if(f)u.push(h`<span class="chip" title="From ${f[1]}">gathered</span>`);else if(e.notes)u.push(h`<span class="chip">notes</span>`);if(e.git)c.push(m("c-git",e.git==="pushed"?"Committed & pushed":"Not committed & pushed yet",e.git==="pushed"?" ok":" warn"));if(e.open)c.push(m("i-bug",`${e.open} open finding${e.open===1?"":"s"} to fix`," warn"));let g=Lt&&!te&&e.column===4;if(e.column===4&&!te)n.classList.add("compact");let b=e.kind==="run"&&!te&&!g?e.status==="waiting"?h`<button class="btn sm${nt.has(st(e))?"":" pri"} act" data-a="open">${vs(e)}</button>`:e.status==="stalled"&&Nt(e)?h`<button class="btn sm act" data-a="resume">Resume</button>`:"":"";n.innerHTML=(g?h`<input type="checkbox" class="pick" ${B(ke.has(t)?"checked":"")} aria-label="Select">`:"")+h`<div class="c-id"><span class="st d-${i}" role="img" title="${d}" aria-label="${d}"><svg><use href="#s-${i}"/></svg></span><span class="idt">${r}</span><span class="age">${e.kind==="run"?ts(e.moved||a.S.now,a.S.now):""}</span><button class="ib sm more" data-a="menu" title="Actions" aria-label="Actions" aria-haspopup="menu" aria-expanded="${String(t===a.menuKey)}">${E("more")}</button></div>
|
|
25
|
+
`)[0].slice(0,80),ps=(e)=>!e.pty.alive?"ended":e.pty.asking?"asking":"running",un=(e)=>String(e.where||"").split(/[\\/]/).filter(Boolean).pop()||e.where||"";function It(){let e=new Map;for(let t of a.S.cards)if(t.pty&&!t.archived)e.set(t.pty.key,t);return e}function fn(){let e=It(),t=j.hidden.filter((i)=>e.get(i)?.pty.alive).length,n=document.querySelector('.rail a[data-view="terminal"]');if(!n)return;if(t)n.dataset.n=String(t);else delete n.dataset.n;n.title="Terminal: every agent running in its card"+(t?` (${t} hidden)`:"")}function fs(){ot=!1,document.body.classList.remove("tmax");for(let e of Me.values())e.off?.();Me.clear(),s("terms").innerHTML=""}var Ot=(e)=>Me.get(e)?.el.querySelector(".xterm-helper-textarea")?.focus({preventScroll:!0});if(typeof window<"u")addEventListener("keydown",(e)=>{if(!ot||!e.ctrlKey||!e.shiftKey||e.altKey||e.metaKey||e.code!=="KeyM"||Te?.matches)return;let t=e.target.closest?.(".tile")?.dataset.k||j.max;if(!t)return;e.preventDefault(),e.stopPropagation(),j.max=j.max===t?null:t,Oe(),pe(),Ot(t)},!0);if(typeof window<"u")addEventListener("keydown",(e)=>{let t=/^Digit([1-9])$/.exec(e.code)?.[1];if(!ot||!t||!e.altKey||e.ctrlKey||e.shiftKey||e.metaKey)return;let n=[...s("terms").querySelectorAll(".tile")][+t-1]?.dataset.k;if(!n)return;if(e.preventDefault(),e.stopPropagation(),Te?.matches)bt=n;else if(j.max&&j.max!==n)j.max=n,Oe();pe(),Ot(n)},!0);function pe(){if(ot=!0,!Te)(Te=matchMedia("(max-width:640px)")).onchange=()=>ot&&pe();if(document.body.classList.contains("tdrag"))return;let e=s("terms"),t=It();for(let[x,I]of Me)if(!t.has(x)||j.hidden.includes(x))I.off?.(),I.el.remove(),Me.delete(x);let n=(x)=>j.order.includes(x)?j.order.indexOf(x):1e9,i=(x)=>t.get(x).pty.alive?0:1,r=[...t.keys()].filter((x)=>!j.hidden.includes(x)).sort((x,I)=>i(x)-i(I)||n(x)-n(I));for(let x of r)if(!j.order.includes(x))j.order.push(x);if(j.max&&!r.includes(j.max))j.max=null;let d=Te.matches?bt&&r.includes(bt)?bt:r[0]:j.max,u=e.querySelector(".tgrid"),c=e.querySelector(".tbar");if(!u)e.innerHTML='<div class="tbar"></div><div class="tgrid"></div>',u=e.querySelector(".tgrid"),c=e.querySelector(".tbar");let m=[...t.keys()].filter((x)=>j.hidden.includes(x)&&t.get(x).pty.alive);if(s("tmodes").innerHTML=h`${io.map(([x,I,V])=>h`<button data-mode="${x}" class="${j.mode===x?"on":""}" aria-pressed="${String(j.mode===x)}" title="${I}" aria-label="${I}">${E(V)}</button>`)}`.s,c.innerHTML=h`${m.length?h`<span class="dim">Hidden</span>${m.map((x)=>h`<button class="chip" data-show="${x}" title="Show this terminal">${E("plus")}${dn(t.get(x))} - ${un(t.get(x))}</button>`)}`:""}${Te.matches&&r.length>1?h`<span class="ttabs" role="group" aria-label="Terminals">${r.map((x)=>h`<button class="${x===d?"on":""}" data-pick="${x}" aria-pressed="${String(x===d)}"><span class="tdot ${ps(t.get(x))}"></span>${dn(t.get(x))} - ${un(t.get(x))}</button>`)}</span>`:""}`.s,fn(),c.querySelectorAll("[data-pick]").forEach((x)=>x.onclick=()=>{bt=x.dataset.pick,pe()}),c.querySelector(".ttabs .on")?.scrollIntoView({block:"nearest",inline:"nearest"}),s("tmodes").querySelectorAll("[data-mode]").forEach((x)=>x.onclick=()=>{j.mode=x.dataset.mode,j.max=null,Oe(),pe()}),c.querySelectorAll("[data-show]").forEach((x)=>x.onclick=()=>{j.hidden=j.hidden.filter((I)=>I!==x.dataset.show),Oe(),pe()}),u.querySelector(".tempty")?.remove(),!r.length){u.style.cssText="",u.querySelectorAll(".tsplit").forEach((x)=>x.remove()),u.insertAdjacentHTML("beforeend",h`<div class="empty tempty"><div class="mascot"></div><b>${m.length?"Every terminal is hidden":"No terminals running"}</b><p>Runs started with the agent in its card show here, from Ideas to Done.</p></div>`.s);return}let f=document.activeElement,g=0;for(let x of r){let I=t.get(x),V=Me.get(x);if(!V){let Y=document.createElement("section");Y.className="tile",Y.dataset.k=x,Y.innerHTML='<header draggable="true"></header><div class="term" aria-label="Agent terminal"></div>',V={el:Y,off:null},Me.set(x,V),ro(x,V),lo(Y)}let ye=ps(I),J=ye==="ended",fe=V.el.querySelector("header");if(fe.title=(I.kind==="run"?I.id:I.text)+" · "+I.where+(g<9?` · Alt+${g+1}`:""),fe.innerHTML=h`<span class="tdot ${ye}" role="img" title="${ye}" aria-label="${ye}"></span><b>${dn(I)} - ${un(I)}</b>${J?h`<span class="tend">ended</span>`:""}<span class="sp"></span>${J&&I.kind==="run"?h`<button class="btn sm" data-a="resume" title="Continue this run's agent">Resume</button>`:""}<button class="ib sm" data-a="card" title="Open card" aria-label="Open card">${E("open")}</button><button class="ib sm" data-a="max" title="${j.max===x?"Restore":"Maximise"} (Ctrl+Shift+M)" aria-label="${j.max===x?"Restore":"Maximise"}">${E(j.max===x?"min":"max")}</button>${J?"":h`<button class="ib sm" data-a="hide" title="Hide" aria-label="Hide">${E("dash")}</button>`}<button class="ib sm" data-a="${J?"hide":"exit"}" title="${J?"Close":"Exit session"}" aria-label="${J?"Close":"Exit session"}">${E("close")}</button>`.s,V.el.classList.toggle("ended",J),V.el.classList.toggle("asking",ye==="asking"),V.el.classList.toggle("off",!!d&&d!==x),V.el.classList.toggle("max",!Te.matches&&j.max===x),V.el.style.gridColumn="",u.children[g]!==V.el)u.insertBefore(V.el,u.children[g]||null);g++}if(f instanceof HTMLElement&&f!==document.activeElement&&f.isConnected)f.focus({preventScroll:!0});document.body.classList.toggle("tmax",!!j.max&&!Te.matches);let b=d?1:r.length,w=j.mode==="cols"?b:j.mode==="rows"?1:Math.ceil(Math.sqrt(b)),p=Math.ceil(b/w),v=w;if(!d&&w*p>b)Me.get(r[r.length-1]).el.style.gridColumn=`span ${w*p-b+1}`,v=b-(p-1)*w-1;let k=`${j.mode}:${w}x${p}`,A=j.sizes[k],q=A?.c?.length===w?A.c:Array(w).fill(1),G=A?.r?.length===p?A.r:Array(p).fill(1);co(u,q,G,k,v,!d)}function ro(e,t){mn().then((n)=>{if(Me.get(e)!==t)return;t.off=n(t.el.querySelector(".term"),e,()=>N(!0))}).catch(()=>t.el.querySelector(".term").textContent="The terminal could not load.")}function lo(e){let t=e.dataset.k;e.querySelector("header").onclick=(n)=>{let i=n.target.closest("[data-a]")?.dataset.a;if(i==="max")j.max=j.max===t?null:t;else if(i==="hide"){if(j.hidden.push(t),j.max===t)j.max=null}else if(i==="exit"){if(confirm("End this agent session? A run can be resumed from its tile or card."))T("/pty/exit",{key:t}).then(()=>N(!0));return}else if(i==="card"){let r=It().get(t);if(r)xe(r);return}else if(i==="resume"){let r=It().get(t);if(r)tt(r,n.target.closest("button")).then(()=>a.wantTerm=null);return}else return;Oe(),pe(),Ot(t)},e.querySelector("header").ondblclick=(n)=>{if(n.target.closest("button")||Te?.matches)return;j.max=j.max===t?null:t,Oe(),pe(),Ot(t)},e.querySelector("header").ondragstart=(n)=>{n.dataTransfer.setData("text/kz-term",t),n.dataTransfer.effectAllowed="move"},e.ondragover=(n)=>{if(!n.dataTransfer.types.includes("text/kz-term"))return;n.preventDefault(),e.classList.add("drop")},e.ondragleave=()=>e.classList.remove("drop"),e.ondrop=(n)=>{e.classList.remove("drop");let i=n.dataTransfer.getData("text/kz-term");if(!i||i===t)return;n.preventDefault();let r=j.order.indexOf(i),d=j.order.indexOf(t);if(r<0||d<0)return;[j.order[r],j.order[d]]=[j.order[d],j.order[r]],Oe(),pe()}}var pn=(e,t)=>{let n=e.reduce((r,d)=>r+d,0),i=e.slice(0,t+1).reduce((r,d)=>r+d,0);return`calc((100% - ${(e.length-1)*yt}px) * ${i/n} + ${t*yt+yt/2}px)`};function co(e,t,n,i,r,d){e.querySelectorAll(".tsplit").forEach((c)=>c.remove());let u=()=>{e.style.gridTemplateColumns=t.map((c)=>c+"fr").join(" "),e.style.gridTemplateRows=n.map((c)=>c+"fr").join(" "),e.querySelectorAll(".tsplit").forEach((c)=>{let m=+c.dataset.i;if(c.dataset.axis==="r")return void(c.style.top=pn(n,m));c.style.left=pn(t,m),c.style.bottom=m>=r?`calc(100% - ${pn(n,n.length-2)} + ${yt/2}px)`:"0px"})};if(d)for(let[c,m]of[["c",t],["r",n]])for(let f=0;f<m.length-1;f++){let g=document.createElement("div");g.className="tsplit "+c,g.dataset.axis=c,g.dataset.i=String(f),g.setAttribute("role","separator"),g.setAttribute("aria-orientation",c==="c"?"vertical":"horizontal"),g.title="Drag to resize, double-click to even out",uo(g,e,c,m,f,u,()=>{j.sizes[i]={c:[...t],r:[...n]},Oe()}),e.append(g)}u()}function uo(e,t,n,i,r,d,u){e.ondblclick=()=>{i.fill(1),u(),d()},e.onpointerdown=(c)=>{c.preventDefault(),e.setPointerCapture(c.pointerId),document.body.classList.add("tdrag");let m=i.reduce((v,k)=>v+k,0),f=(n==="c"?t.clientWidth:t.clientHeight)-(i.length-1)*yt,g=m*0.1,b=n==="c"?c.clientX:c.clientY,w=i[r],p=i[r+1];e.onpointermove=(v)=>{let k=Math.max(g-w,Math.min(p-g,((n==="c"?v.clientX:v.clientY)-b)/f*m));i[r]=w+k,i[r+1]=p-k,d()},e.onpointerup=e.onpointercancel=()=>{e.onpointermove=e.onpointerup=e.onpointercancel=null,document.body.classList.remove("tdrag"),u()}}}var ms=()=>ot;var W="board",hn=(e)=>{document.querySelectorAll(".rail a.it").forEach((t)=>t.dataset.view===e?t.setAttribute("aria-current","page"):t.removeAttribute("aria-current")),document.querySelector(".hdr h1").textContent=e==="sources"?"Icebox":e==="terminal"?"Terminal":"Board"};function he(e,t){if(a.pageGen++,e==="icebox")e="sources";if(!["settings","sources","terminal"].includes(e))e="board";let n=W;if(W=e,hn(e),document.body.classList.toggle("paged",e!=="board"),document.body.classList.toggle("ice",e==="sources"),document.body.classList.toggle("termv",e==="terminal"),t&&e!==n)history.pushState(null,"",e==="board"?location.pathname:"?view="+(e==="sources"?"icebox":e));let i=s("panel");if(e==="terminal")pe();else fs();if(e==="board"||e==="terminal"){if(n==="board"||n==="terminal"){if(e==="terminal"&&n==="board")W="board",ne(),W=e;return}i.style.transition="none",i.classList.remove("open","docked"),i.offsetWidth,i.style.transition="",W="board",ne(),W=e;return}if(i.classList.add("docked"),e==="settings")Ce();else z()}function hs(){document.querySelectorAll(".rail a[data-view]").forEach((e)=>{if(e.dataset.view==="notes"||e.dataset.view==="video")return;e.onclick=(t)=>{if(t.ctrlKey||t.metaKey||t.shiftKey||t.button)return;if(t.preventDefault(),e.dataset.view==="settings")a.setQ="";Ye(()=>he(e.dataset.view,!0))}}),document.querySelector(".rail .home").onclick=(e)=>{if(e.ctrlKey||e.metaKey||e.shiftKey||e.button)return;e.preventDefault(),Ye(()=>he("board",!0))},addEventListener("popstate",()=>Ye(()=>he(new URLSearchParams(location.search).get("view")))),addEventListener("kz-theme",()=>{if(W==="settings")Ce()})}var bs="Icebox",re=null,wt={},gn=(e)=>{if(!wt[e])try{wt[e]=localStorage.getItem("kz-reply-style:"+e)}catch(t){}return wt[e]||"casual"},po={casual:"Casual",fun:"Fun",helpful:"Helpful",promo:"Promo"},le=null,je=null,ge=null,be="",oe="",at="link",vt=null,it=!1,zt=!1,Gt=null,X=new Set,kt={x:"X",tiktok:"TikTok",instagram:"Instagram",threads:"Threads"},ee=()=>s("panel").classList.contains("open")&&s("ptitle").textContent===bs,Qe=(e)=>{let t=Math.round((Date.now()-Date.parse(e))/60000);return t<1?"just now":t<60?t+" min ago":t<1440?Math.round(t/60)+" h ago":Math.round(t/1440)+" d ago"};function gs(e,t){let n=s(e);if(!n)return;let i=n.querySelector("button.sel"),r=n.querySelector(".menu-pop"),d=r.querySelector("input"),u=r.querySelector(".pick-list"),c=(f)=>{if(r.hidden=!f,i.setAttribute("aria-expanded",f),f)d.value="",m(),d.focus()},m=()=>{let f=d.value.trim().toLowerCase(),g=null,b=!1;for(let w of u.children)if(w.classList.contains("grp")){if(g)g.hidden=!b;g=w,b=!1}else{let p=!f||w.dataset.q.includes(f)||g&&g.dataset.g.includes(f);w.hidden=!p,b||=p}if(g)g.hidden=!b};i.onclick=()=>c(r.hidden),d.oninput=m,d.onkeydown=(f)=>{if(f.key==="Escape")f.stopPropagation(),c(!1),i.focus();else if(f.key==="Enter")f.preventDefault(),u.querySelector("button:not([hidden])")?.click()},u.onclick=(f)=>{let g=f.target.closest("button[data-v]");if(!g)return;c(!1),t(g.dataset.v)}}async function z(){if(W!=="sources")return;let e=++a.pageGen;de(!0);let t=ee()?[s("src-url")?.value||"",s("src-label")?.value||"",document.activeElement?.id,s("src-dir")?.value,s("src-cat")?.value||"",s("src-plat")?.value,s("src-q")?.value||""]:["",""],n=new Map(ee()?[...s("pbody").querySelectorAll("[data-mv]")].map((o)=>[o.dataset.k,o.value]):[]),i=ee()&&document.activeElement?.closest?.(".ice-row"),r=i?[i.dataset.k,document.activeElement.id.replace(/-\d+$/,"")]:null,d=ee()&&s("ice-title")?[s("ice-title").dataset.k,s("ice-title").value,s("ice-details").value]:null,u=new Map(ee()?[...s("pbody").querySelectorAll("[data-ct]")].map((o)=>[o.dataset.k,o.value]):[]);if(!ee())s("pbody").innerHTML=Mt;Ae(),a.openKey=null,a.runDoc=null,s("pterm").hidden=!0,s("panel").classList.add("open"),s("scrim").classList.add("on"),s("ptitle").textContent=bs,s("ptabs").innerHTML="",s("pfoot").innerHTML="",s("psub").textContent="",s("psub").title="";let c=a.all?null:a.S.dir,m=c?"?dir="+encodeURIComponent(c):"",f=await fetch("/sources"+m).then((o)=>o.json()).catch(()=>null);if(e!==a.pageGen||!ee())return;let g=(o)=>{try{return new URL(o).hostname}catch{return o}},b=(o,l,y)=>{if(kt[y])return h`<span class="fav">${E("b-"+y)}</span>`;let S;try{let U=new URL(o);if(/^https?:$/.test(U.protocol))S=U.origin}catch{}let P=!S?"":o.includes("docs.google.com/spreadsheets")?"https://ssl.gstatic.com/docs/spreadsheets/favicon3.ico":o.includes("docs.google.com/document")?"https://ssl.gstatic.com/docs/documents/images/kix-favicon7.ico":S+"/favicon.ico";return h`<span class="fav">${P?h`<img src="${P}" alt="" loading="lazy" referrerpolicy="no-referrer" onerror="this.remove()">`:""}${E(l)}</span>`},w=(o)=>kt[o?.social]||(o?g(o.url).replace(/^www\./,""):"")||"Other",p=(o)=>{if(o.social)return"social";let l=o.url;if(l.includes("docs.google.com/spreadsheets")||l.endsWith(".csv")||l.endsWith(".tsv"))return"sheet";if(l.includes("docs.google.com/document"))return"doc";return"link"},v=f&&f.sources||[],k=[...f&&f.icebox||[],...f&&f.dismissed||[]],A=(f&&f.icebox||[]).length,q=f&&f.gatherer||{},G=q.use==="chatgpt"&&q.connected,x=(o,l)=>h`${o&&!a.S.projects.some((y)=>y.dir===o)?h`<option value="${o}" title="${l||o}" selected>${De(l||o)}</option>`:""}${a.S.projects.map((y)=>h`<option value="${y.dir}" title="${y.label}"${y.dir===o?" selected":""}>${De(y.label)}</option>`)}`,I=v.map((o,l)=>{let y=p(o),S=o.label||g(o.url),P=o.social&&(!o.last||!o.last.ok&&/gathered by your agent/i.test(o.last.note))?h`<span class="src-badge dim">${E("at")}${G?"Gathered with ChatGPT":"Gathered by your agent"}</span>`:!o.last?h`<span class="src-badge dim">Not gathered yet</span>`:o.last.ok?h`<span class="src-badge ok"><svg viewBox="0 0 16 16"><path d="M3.5 8.5l3 3 6-6" stroke="currentColor" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>${o.last.note}</span><span class="hint" style="margin:0">${Qe(o.last.at)}</span>`:h`<span class="src-badge warn"><svg viewBox="0 0 16 16"><circle cx="8" cy="8" r="6" stroke="currentColor" fill="none" stroke-width="1.8"/><path d="M8 5v3.5M8 11v.1" stroke="currentColor" fill="none" stroke-width="2" stroke-linecap="round"/></svg>Failed: ${o.last.note}</span><span class="hint" style="margin:0">${Qe(o.last.at)}</span>`,U=y==="sheet"?"sheet":y==="doc"?"doc":y==="social"?"at":"link",F=o.url.replace(/^https?:\/\/(www\.)?/,"");return h`<div class="src-card" id="src-card-${l}"><div class="src-hd"><span class="src-ico" title="${y==="social"?kt[o.social]||"social":y}">${b(o.url,U,o.social)}</span><div class="src-info"><span class="src-title" title="${S}">${S}</span><a class="src-url" href="${o.url}" target="_blank" rel="noopener noreferrer" title="${o.url}"><span>${F}</span>${E("ext")}</a></div><div class="src-acts">${o.social?h`<button class="ib sm" id="src-ag-${l}" data-ag="${l}" aria-label="Gather ${S} with your agent" title="${G?"Gather with your ChatGPT plan":"Gather: opens your agent on /kaizen gather"}">${E("refresh")}</button>`:h`<button class="ib sm" id="src-chk-${l}" data-chk="${l}" aria-label="Check ${S} now" title="Check now">${E("refresh")}</button>`}<button class="ib sm danger" id="src-rm-${l}" data-rm="${l}" aria-label="Remove ${S}" title="Remove source">${E("trash")}</button></div></div><div class="src-status">${P}</div><div class="src-fields"><label class="src-f" title="Category"><span>Category</span><input class="sel" id="src-ct-${l}" data-ct="${l}" data-k="${o.dir+" "+o.url}" value="${o.category||""}" placeholder="${w(o)}" maxlength="40" aria-label="Category of ${S}"><button class="btn sm pri" id="src-cs-${l}" aria-label="Save the category of ${S}" disabled>Save</button></label><label class="src-f" title="Project"><span>Project</span>${rt(o.dir,o.project||"")}<select class="sel" id="src-mv-${l}" data-mv="${l}" data-k="${o.dir+" "+o.url}" aria-label="Project of ${S}">${x(o.dir,o.project)}</select><button class="btn sm pri" id="src-mb-${l}" aria-label="Move ${S} to the chosen project" disabled>Move</button></label>${y==="sheet"||/github\.com/.test(o.url)?h`<label class="src-wb"><input type="checkbox" id="src-wb-${l}" data-wb="${l}"${o.writeback?" checked":""}> Write back</label>`:""}</div></div>`}),V=(f&&f.failed||[]).map((o)=>h`<p style="color:var(--dim)">The sources of ${o} could not be read.</p>`),ye=h`<div class="src-empty"><div class="src-empty-ico">${E("link")}</div><h4>No sources yet</h4></div>`,J=at==="social",fe=!v.length||it||[t[0],t[1],t[4],t[6]].some(Boolean),Y=h`<div class="src-add" id="src-addbox"${fe?"":" hidden"}><div class="hd"><h4>Add a source</h4><div class="src-kind" role="group" aria-label="Kind of source"><button id="src-k-link" data-kind="link" aria-pressed="${String(!J)}">Link</button><button id="src-k-social" data-kind="social" aria-pressed="${String(J)}">Social</button></div></div><label for="src-url"${J?" hidden":""}><span>Link</span><input class="sel" id="src-url" placeholder="Link" spellcheck="false" autocomplete="off"></label><div class="two plat"${J?"":" hidden"}><label for="src-plat"><span>Platform</span><select class="sel" id="src-plat">${Object.entries(kt).map(([o,l])=>h`<option value="${o}">${l}</option>`)}</select></label><label for="src-q"><span>Follow</span><input class="sel" id="src-q" placeholder="keyword, #hashtag or @account" maxlength="100" spellcheck="false" autocomplete="off"></label></div><div class="two"><label for="src-label"><span>Label <i>optional</i></span><input class="sel" id="src-label" placeholder="${J?"e.g. Mentions on X":"e.g. Feedback Q4"}"></label><label for="src-cat"><span>Category <i>optional</i></span><input class="sel" id="src-cat" placeholder="${J?"e.g. Social":"e.g. Bugs"}" maxlength="40"></label></div><label for="src-dir"><span>Project</span><select class="sel" id="src-dir">${c?"":h`<option value="">Choose project…</option>`}${x(c)}</select></label><div class="acts"><span class="end"></span><button class="btn pri" id="src-add">Add source</button></div></div>`,ae=(o)=>{let l=v.find((y)=>y.dir===o.dir&&y.url===o.source);return l?l.label||g(l.url):g(o.source)},L=(o)=>o.dir+" "+o.id,R=(o)=>o.dir+" "+o.source,M=(o)=>v.find((l)=>l.dir===o.dir&&l.url===o.source),O=(o)=>o.status==="dismissed"?"Dismissed":o.status==="done"?"Done":o.category||M(o)?.category||w(M(o)||{url:o.source}),K=(o,l)=>{let y=new Map;return o.forEach((S)=>{let P=l(S);y.set(P,{it:S,n:(y.get(P)?.n||0)+1})}),y},Z=c?new Map:K(k,(o)=>o.dir);if(!c){for(let o of a.shown)if(!Z.has(o)){let l=ze().find((y)=>y.dir===o);if(l)Z.set(o,{it:{dir:o,project:l.label},n:0})}}let we=(o)=>c||!a.shown.size||a.shown.has(o.dir),In=k.filter(we),ut=K(In,O);if(oe&&!ut.has(oe))oe="";let Os=In.filter((o)=>!oe||O(o)===oe),pt=K(Os,R);if(be&&!pt.has(be))be="";let zs=new Set(k.map(L));if(le&&!zs.has(le))le=null;if(je!==le)je=null;let ft=new Map;k.forEach((o,l)=>{if(!we(o)||(oe?O(o)!==oe:o.status==="dismissed"||o.status==="done")||be&&R(o)!==be)return;let y=O(o);ft.has(y)||ft.set(y,[]),ft.get(y).push(l)});let Q=[...ft.values()].flat();{let o=new Set(Q.map((l)=>L(k[l])));[...X].forEach((l)=>o.has(l)||X.delete(l))}if(!Q.some((o)=>L(k[o])===ge))ge=Q.length?L(k[Q[0]]):null;let mt=Q.filter((o)=>X.has(L(k[o]))).length,Gs=Z.size>1,On=(o,l,y,S)=>h`<div class="combo ice-combo" id="${o}"><button class="sel" aria-label="${l}" aria-haspopup="listbox" aria-expanded="false">${y}</button><div class="menu-pop" hidden><input class="sel" aria-label="Search ${l.toLowerCase()}" placeholder="Search…" spellcheck="false" autocomplete="off"><div class="pick-list" role="listbox">${S}</div></div></div>`,qt=(o,l,y,S,P="")=>h`<button type="button" role="option" data-v="${o}" data-q="${S.toLowerCase()}" class="${l?"on":""}${P}" aria-selected="${String(l)}">${y}</button>`,Et=new Map;for(let[o,{it:l}]of pt){let y=w(M(l)||{url:l.source});Et.has(y)||Et.set(y,[]),Et.get(y).push([o,l])}let Xt=(o)=>b(o.source,"link",M(o)?.social),en=be&&[...pt].find(([o])=>o===be)?.[1].it,zn=h`${ut.size>1||ut.has("Dismissed")||ut.has("Done")?On("ice-fc","Category",h`<span>${oe||"All categories"}</span>`,h`${qt("",!oe,h`<span>All categories</span>`,"all categories")}${[...ut].map(([o,{n:l}])=>qt(o,oe===o,h`<span>${o}</span><i>${l}</i>`,o))}`):""}${pt.size>1?On("ice-fs","Source",en?h`${Xt(en)}<span>${ae(en)}</span>`:h`<span>All sources</span>`,h`${qt("",!be,h`<span>All sources</span>`,"all sources")}${[...Et].map(([o,l])=>h`<div class="grp" data-g="${o.toLowerCase()}">${Xt(l[0][1])}${o}</div>${l.map(([y,S])=>qt(y,be===y,h`${Xt(S)}<span>${ae(S).toLowerCase().startsWith(o.toLowerCase()+":")?ae(S).slice(o.length+1).trim():ae(S)}</span><i>${pt.get(y).n}</i>`,o+" "+ae(S)," sub"))}`)}`):""}`,Us=h`<div class="ice-bar">${Q.length?h`<input type="checkbox" id="ice-all" aria-label="Select every request shown"${mt&&mt===Q.length?" checked":""}>`:""}<span class="count">${oe==="Dismissed"||oe==="Done"?`${Q.length} ${oe.toLowerCase()}`:`${Q.length<A?`${Q.length} of ${A}`:A} waiting`}</span><span class="end"></span>${String(zn)?h`<details class="ice-filt"><summary class="ib${oe||be?" on":""}" aria-label="Filter requests" title="Filter requests">${E("filter")}</summary><div class="ice-fpop">${zn}</div></details>`:""}<button class="btn ghost sm" id="ice-new" title="Add a request by hand">${E("plus")} Add</button><button class="btn sm" id="src-go"${v.length?"":" disabled"}>${E("refresh")} Gather all</button><button class="btn ghost sm" id="src-tog" aria-expanded="${String(vt??!v.length)}" aria-controls="src-sec">${E("link")} Sources · ${v.length}</button></div>`,Gn=X.size?h`<div class="ice-bulk" role="toolbar" aria-label="Selected requests"><span>${X.size} selected</span><span class="end"></span><button class="btn sm" id="ice-bp" title="Promote (p)">${E("plus")} Promote</button><button class="btn ghost sm" id="ice-bd" title="Dismiss (d)">${E("x")} Dismiss</button><button class="btn ghost sm" id="ice-bc" title="Clear selection (Esc)">Clear</button></div>`:"",Fs=(o)=>h`<div class="ice-form"><label for="ice-title" class="hint" style="margin:0">Idea title</label><input class="sel" id="ice-title" data-k="${L(o)}" maxlength="200" value="${o.text}" aria-label="Idea title"><label for="ice-details" class="hint" style="margin:0">Details</label><textarea class="sel" id="ice-details" rows="3" aria-label="Details"></textarea><div class="ice-form-acts"><span class="end"></span><button class="btn ghost sm" id="ice-cancel">Cancel</button><button class="btn pri sm" id="ice-ok">Promote</button></div></div>`,_s=(o)=>{if(!o.post)return"";if(o.replied)return h`<span class="hint" style="margin:0">You replied to this post ${Qe(o.replied)}.</span>`;let l=re&&re.k===L(o)?re:null,y=(S)=>h`<select class="sel" id="ice-rst" aria-label="Reply style"${S?" disabled":""}>${Object.entries(po).map(([P,U])=>h`<option value="${P}"${P===gn(o.dir)?" selected":""}>${U}</option>`)}</select>`;if(!l)return h`<div class="ice-form-acts"><span class="hint">You review it before it posts.</span>${q.connected?y(!1):""}<button class="btn sm" id="ice-rp">Reply</button></div>`;if(l.wait)return h`<div class="ice-form-acts"><span class="hint">Drafting…</span></div>`;return h`<div class="ice-form"><label for="ice-reply" class="hint" style="margin:0">Your reply${l.note?` · ${l.note}`:""}</label><textarea class="sel" id="ice-reply" rows="3" maxlength="2000" aria-label="Your reply"${l.busy||l.again?" disabled":""}>${l.text}</textarea><span class="hint" id="ice-rn" style="margin:0">${l.again?"Writing another…":`${l.text.length} chars`}</span><div class="ice-form-acts"><span class="end"></span>${q.connected?h`${y(l.busy||l.again)}<button class="btn ghost sm" id="ice-rg"${l.busy||l.again?" disabled":""}>Regenerate</button>`:""}<button class="btn ghost sm" id="ice-rc"${l.busy?" disabled":""}>Cancel</button><button class="btn pri sm" id="ice-rs"${l.busy||l.again||!l.text.trim()?" disabled":""}>${l.busy?"Sending…":"Send reply"}</button></div></div>`},Bs=(o)=>{let l=k[o],y=L(l),S=le===y,P=h`<div class="ice-row${ge===y?" cur":""}${X.has(y)?" sel":""}" data-i="${o}" data-k="${y}"><input type="checkbox" id="ice-ck-${o}" data-ck="${o}"${X.has(y)?" checked":""} aria-label="Select: ${l.text}"><span class="ice-src" title="${ae(l)}">${b(l.source,"link",v.find((F)=>F.dir===l.dir&&F.url===l.source)?.social)}</span><button class="ice-t" id="ice-o-${o}" data-o="${o}" aria-expanded="${String(S)}" title="${l.text}">${l.text}</button><span class="ice-meta">${Gs?h`<span class="nm" title="${l.project||""}">${rt(l.dir,l.project||"")}${De(l.project||"")}</span>`:""}${l.status==="done"&&l.written?h`<span title="Written back ${Qe(l.written)}">written back</span>`:""}${l.status==="done"&&l.writeError?h`<span title="${l.writeError}">write-back failed</span>`:""}${l.status==="promoted"?h`<span title="Promoted to Ideas: ${l.idea||""}">promoted</span>`:""}${l.replied?h`<span title="Replied ${Qe(l.replied)}">replied</span>`:""}<span class="ice-age">${Qe(l.at)}</span><span class="ice-ra">${l.status==="promoted"||l.status==="done"?"":h`<button class="btn ghost sm" id="ice-pr-${o}" data-pr="${o}" title="Promote to Ideas (p)" aria-label="Promote to Ideas: ${l.text}">${E("plus")}</button>`}${l.status==="promoted"||l.status==="done"?"":l.status==="dismissed"?h`<button class="btn ghost sm" id="ice-rs-${o}" data-rs="${o}" title="Restore to waiting" aria-label="Restore: ${l.text}">Restore</button>`:h`<button class="btn ghost sm" id="ice-ds-${o}" data-ds="${o}" title="Dismiss (d)" aria-label="Dismiss: ${l.text}">${E("x")}</button>`}</span></span></div>`,U=S?h`<div class="ice-open">${l.notes?h`<div class="ice-notes">${l.notes}</div>`:""}${(l.images||[]).filter((F)=>/^https:\/\//.test(F)).length?h`<details class="ice-imgs"><summary>Show images (${l.images.filter((F)=>/^https:\/\//.test(F)).length}) — loads them from the source's site</summary>${l.images.filter((F)=>/^https:\/\//.test(F)).map((F,_)=>{let ce=`/ice-image?dir=${encodeURIComponent(l.dir)}&id=${encodeURIComponent(l.id)}&i=${_}`;return h`<a href="${ce}" target="_blank" rel="noopener noreferrer"><img data-src="${ce}" alt="" referrerpolicy="no-referrer"></a>`})}</details>`:""}<span class="hint" style="margin:0">From ${ae(l)} · ${Qe(l.at)}${l.post?h` · <a href="${l.post}" target="_blank" rel="noopener">open post</a>`:""}</span>${_s(l)}${je===y?Fs(l):""}</div>`:"";return h`${P}${U}`},Ws=A&&!Q.length?h`<div class="ice-zero"><h4>No matches</h4><p style="margin-top:10px"><button class="btn sm" id="ice-unf">Clear filters</button></p></div>`:Q.length?h`<div class="ice-list">${[...ft].map(([o,l])=>h`<div class="ice-cat">${o}<i>${l.length}</i></div>${l.map(Bs)}`)}</div>`:h`<div class="ice-zero"><h4>Nothing waiting</h4></div>`,Ct=vt??!v.length,tn=Ct&&!s("src-sec")?.classList.contains("open"),Vs=h`<div class="src-scrim${Ct&&!tn?" on":""}" id="src-scrim"></div><aside class="src-sec${Ct&&!tn?" open":""}" id="src-sec" aria-label="Sources"${Ct?"":" inert"}><header><div class="t"><b>Sources</b><div class="src-chips"><a id="src-to-settings" class="schip" role="button" tabindex="0" title="${f&&f.every&&f.every!=="off"?`Checked every ${f.every}`:"Auto-check off"}: change in Settings">${E("clock")}${f&&f.every&&f.every!=="off"?f.every:"Off"}</a>${q.connected?h`<span class="schip on" title="ChatGPT${q.email?": "+q.email:""}">${E("ai")}ChatGPT<a id="cg-out" role="button" tabindex="0" aria-label="Disconnect ChatGPT" title="Disconnect">${E("x")}</a></span>`:h`<a id="cg-in" class="schip" role="button" tabindex="0" title="Connect ChatGPT">${E("ai")}ChatGPT</a>`}${(f.google||{}).connected?h`<span class="schip on" title="Google connected">${E("google")}Google<a id="gg-out" role="button" tabindex="0" aria-label="Disconnect Google" title="Disconnect">${E("x")}</a></span>`:h`<a id="gg-in" class="schip" role="button" tabindex="0" title="Connect Google">${E("google")}Google</a>`}</div></div><div class="src-hda">${v.length?h`<button class="btn sm" id="src-new" aria-expanded="${String(fe)}" aria-controls="src-addbox">${E("plus")} Add</button>`:""}<button class="ib" id="src-x" aria-label="Close sources" title="Close">${E("close")}</button></div></header><div class="body">${Y}${v.length?h`<div class="src-list">${I}</div>`:ye}</div></aside>`,Qs=q.use==="ask"&&!q.connected?h`<div class="cg-onb"><div class="acts"><b>Gather social posts with ChatGPT?</b><span class="end"></span><button class="btn ghost" id="cg-skip">Skip</button><button class="btn pri" id="cg-go">Connect</button></div></div>`:"",Js=s("src-sec")?.querySelector(".body")?.scrollTop??0;if(s("pbody").innerHTML=f&&f.error?h`<p style="color:var(--dim)">${f.error}</p>`:!f?h`<p style="color:var(--dim)">The icebox could not be read.</p>`:h`${Qs}${Us}${Gn}${V}${Ws}${Vs}`,!f||f.error)return;let Un=s("src-sec")?.querySelector(".body");if(Un)Un.scrollTop=Js;if(d&&d[0]===le&&s("ice-title"))s("ice-title").value=d[1],s("ice-details").value=d[2];if(s("src-add")){if(t[5])s("src-plat").value=t[5];if(s("src-q").value=t[6]||"",s("src-url").value=t[0],s("src-label").value=t[1],s("src-cat").value=t[4]||"",t[3]!==void 0&&s("src-dir"))s("src-dir").value=t[3]}if(s("src-to-settings"))s("src-to-settings").onclick=()=>{a.setQ="sources",he("settings",!0)};let Ys=async()=>{let o=window.open("","_blank"),l=await T("/chatgpt",{op:"connect"});if(l.ok&&o)o.location=l.url;else if(o?.close(),l.ok)location.href=l.url};for(let o of["cg-go","cg-in"])if(s(o))s(o).onclick=Ys;if(s("gg-in"))s("gg-in").onclick=async()=>{if(!(f.google||{}).hasClient){C("Add your Google client in Settings first"),a.setQ="google",he("settings",!0);return}let o=window.open("","_blank"),l=await T("/google",{op:"connect"});if(l.ok&&o)o.location=l.url;else if(o?.close(),l.ok)location.href=l.url;else C(l.error||"Could not start Google sign-in")};if(s("gg-out"))s("gg-out").onclick=async()=>{if(!confirm("Disconnect Google? Done requests stop being written to sheets."))return;if((await T("/google",{op:"disconnect"})).ok)C("Google disconnected"),z()};if(s("cg-skip"))s("cg-skip").onclick=async()=>{if((await T("/chatgpt",{op:"skip"})).ok)z()};if(s("cg-out"))s("cg-out").onclick=async()=>{if(!confirm("Disconnect ChatGPT? Gather goes back to your agent."))return;if((await T("/chatgpt",{op:"disconnect"})).ok)C("ChatGPT disconnected"),z()};if(tn)s("src-sec").offsetWidth,s("src-sec").classList.add("open"),s("src-scrim").classList.add("on");let At=()=>{vt=!1,s("src-sec").classList.remove("open"),s("src-scrim").classList.remove("on"),s("src-sec").inert=!0,s("src-tog").setAttribute("aria-expanded","false"),s("src-tog").focus()};if(s("src-x").onclick=s("src-scrim").onclick=At,s("src-new"))s("src-new").onclick=()=>{let o=s("src-addbox");if(it=o.hidden,o.hidden=!it,s("src-new").setAttribute("aria-expanded",it),it)s(at==="social"?"src-q":"src-url").focus()};if(s("src-sec").onkeydown=(o)=>{if(o.key==="Escape")o.stopPropagation(),At()},s("src-tog").onclick=()=>{if(s("src-sec").classList.contains("open"))return At();vt=!0,z().then(()=>vt&&s("src-url")?.focus())},gs("ice-fs",(o)=>{be=o,z()}),gs("ice-fc",(o)=>{oe=o,z()}),s("ice-unf"))s("ice-unf").onclick=()=>{if(oe=be="",!c)a.shown.clear();Ft(),z()};s("pbody").querySelectorAll("[data-kind]").forEach((o)=>o.onclick=()=>{if(at===o.dataset.kind)return;at=o.dataset.kind,z().then(()=>s(at==="social"?"src-q":"src-url")?.focus())});let Ue=async(o,l)=>{let y=await T("/sources",o);if(y.ok)l(y),N();if(ee())z()};s("pbody").querySelectorAll("[data-mv]").forEach((o)=>{let l=v[+o.dataset.mv],y=s("src-mb-"+o.dataset.mv),S=n.get(o.dataset.k);if(S&&[...o.options].some((P)=>P.value===S))o.value=S;(o.onchange=()=>{y.disabled=o.value===l.dir})(),y.onclick=()=>Ue({op:"move",dir:l.dir,to:o.value,url:l.url},()=>C("Source moved"))}),s("pbody").querySelectorAll("[data-wb]").forEach((o)=>{let l=v[+o.dataset.wb];o.onchange=()=>{if(o.checked&&l.social===void 0&&/docs\.google\.com/.test(l.url)&&!(f.google||{}).connected){alert("Connect Google first (Sources header), so kaizen can write to the sheet."),o.checked=!1;return}if(o.checked&&!confirm("When a promoted request's run is done, kaizen will write that back to this source. A closed issue or a changed cell is visible to others. Turn on?")){o.checked=!1;return}Ue({op:"writeback",dir:l.dir,url:l.url,on:o.checked},()=>C(o.checked?"Write back on":"Write back off"))}}),s("pbody").querySelectorAll("[data-ct]").forEach((o)=>{let l=v[+o.dataset.ct],y=s("src-cs-"+o.dataset.ct),S=u.get(o.dataset.k);if(S!==void 0)o.value=S;(o.oninput=()=>{y.disabled=o.value.trim()===(l.category||"")})(),o.onkeydown=(P)=>{if(P.key==="Enter"&&!y.disabled)y.click()},y.onclick=()=>{y.disabled=!0,Ue({op:"category",dir:l.dir,url:l.url,category:o.value.trim()},()=>C(o.value.trim()?`New requests from ${l.label||g(l.url)} go under ${o.value.trim()}`:"Category cleared"))}});let Fn=()=>{if(!document.activeElement||document.activeElement===document.body)s("pbody").querySelector(".ice-row.cur .ice-t")?.focus()},_n=(o)=>{let l=Q.findIndex((P)=>L(k[P])===ge);if(l<0||!o.has(ge))return;let y=(P)=>!o.has(L(k[P])),S=Q.slice(l+1).find(y)??Q.slice(0,l).reverse().find(y);ge=S===void 0?null:L(k[S])},nn=(o,l,y,S={})=>(async()=>{if(_n(new Set([L(l)])),(await T("/icebox",{op:o,dir:l.dir,ids:[l.id],...S})).ok){if(o==="promote"&&le===L(l))le=je=null;C(y),N()}if(ee())z().then(Fn)})(),Bn=async(o)=>{let l=k.filter((S)=>X.has(L(S)));if(!l.length)return;_n(new Set(l.map(L))),zt=!0,s("ice-bp").disabled=s("ice-bd").disabled=!0;let y=0;try{if(o==="dismiss")for(let S of new Set(l.map((P)=>P.dir))){let P=l.filter((U)=>U.dir===S).map((U)=>U.id);if((await T("/icebox",{op:o,dir:S,ids:P})).ok)y+=P.length}else for(let S of l)if((await T("/icebox",{op:o,dir:S.dir,ids:[S.id]})).ok)y++}finally{zt=!1}if(X.clear(),y)C(`${y} ${o==="promote"?"promoted to Ideas":"dismissed"}${y<l.length?`, ${l.length-y} not`:""}`);if(N(),ee())z().then(Fn)};if(Gn)s("ice-bp").onclick=()=>Bn("promote"),s("ice-bd").onclick=()=>Bn("dismiss"),s("ice-bc").onclick=()=>{X.clear(),z()};if(s("ice-all"))s("ice-all").onchange=()=>{let o=Q.map((l)=>L(k[l]));if(mt===Q.length)o.forEach((l)=>X.delete(l));else o.forEach((l)=>X.add(l));z()};if(s("ice-all"))s("ice-all").indeterminate=mt>0&&mt<Q.length;s("pbody").querySelectorAll("[data-ck]").forEach((o)=>o.onchange=()=>{let l=L(k[+o.dataset.ck]);ge=l,o.checked?X.add(l):X.delete(l),z()});let Wn=(o)=>{let l=L(k[o]);ge=l,le=le===l?null:l,je=null,z().then(()=>s("ice-o-"+o)?.focus())};s("pbody").querySelectorAll(".ice-row").forEach((o)=>o.onclick=(l)=>{if(!l.target.closest("input,button"))Wn(+o.dataset.i)}),s("pbody").querySelectorAll("[data-o]").forEach((o)=>o.onclick=()=>Wn(+o.dataset.o)),s("pbody").querySelectorAll("details.ice-imgs").forEach((o)=>o.ontoggle=()=>o.open&&o.querySelectorAll("img[data-src]").forEach((l)=>l.src=l.dataset.src)),s("pbody").querySelectorAll("[data-pr]").forEach((o)=>o.onclick=()=>{ge=le=je=L(k[+o.dataset.pr]),z().then(()=>{s("ice-title")?.focus(),s("ice-title")?.select()})}),s("pbody").querySelectorAll("[data-ds]").forEach((o)=>o.onclick=()=>{o.disabled=!0,nn("dismiss",k[+o.dataset.ds],"Dismissed")}),s("pbody").querySelectorAll("[data-rs]").forEach((o)=>o.onclick=()=>{o.disabled=!0,nn("restore",k[+o.dataset.rs],"Restored")});let ht=k.find((o)=>L(o)===le);if(s("ice-rp"))s("ice-rp").onclick=async()=>{let o=ht,l=L(o);re={k:l,text:"",wait:!0},z();let y=await T("/reply",{op:"draft",dir:o.dir,id:o.id,style:gn(o.dir)});if(!re||re.k!==l)return;re={k:l,text:y.text||"",note:y.ok?y.note||"":"",wait:!1},z().then(()=>s("ice-reply")?.focus())};if(s("ice-rst"))s("ice-rst").onchange=(o)=>{let l=ht.dir;wt[l]=o.target.value;try{localStorage.setItem("kz-reply-style:"+l,wt[l])}catch(y){}};if(s("ice-rg"))s("ice-rg").onclick=async()=>{let o=ht,l=re;l.again=!0,z();let y=await T("/reply",{op:"draft",dir:o.dir,id:o.id,style:gn(o.dir),avoid:l.text});if(re!==l)return;if(l.again=!1,y.text)l.text=y.text;l.note=y.ok?y.note||"":"",z().then(()=>s("ice-reply")?.focus())};if(s("ice-reply")){let o=s("ice-reply");o.oninput=()=>{re.text=o.value,s("ice-rn").textContent=`${o.value.length} chars`,s("ice-rs").disabled=!o.value.trim()},o.onkeydown=(l)=>{if(l.key==="Escape")l.stopPropagation(),s("ice-rc").click()},s("ice-rc").onclick=()=>{re=null,z()},s("ice-rs").onclick=async()=>{let l=ht,y=re;y.busy=!0,z();let S=await T("/reply",{op:"send",dir:l.dir,id:l.id,text:y.text});if(S.ok)re=null,C("Reply posted");else if(S.sent)re=null;else y.busy=!1;if(N(),ee())z()}}if(s("ice-ok")){let o=()=>{let l=s("ice-title").value.trim();if(!l){s("ice-title").focus();return}s("ice-ok").disabled=!0,nn("promote",ht,"Promoted to Ideas",{text:l,details:s("ice-details").value})};s("ice-ok").onclick=o,s("ice-cancel").onclick=()=>{je=null,z()},s("ice-title").onkeydown=(l)=>{if(l.key==="Enter")o();if(l.key==="Escape")s("ice-cancel").click()},s("ice-details").onkeydown=(l)=>{if(l.key==="Enter"&&(l.ctrlKey||l.metaKey))o();if(l.key==="Escape")s("ice-cancel").click()}}Gt=(o)=>{if(o.altKey||o.ctrlKey||o.metaKey)return!1;let l=o.key,y=Q.findIndex((U)=>L(k[U])===ge),S=Q[y];if(l==="Escape"){if(s("src-sec")?.classList.contains("open"))return At(),!0;if(le){if(je)je=null;else le=null;return z(),!0}if(X.size)return X.clear(),z(),!0;return!1}if(y<0)return!1;if(l==="j"||l==="k"){o.preventDefault();let U=Q[Math.max(0,Math.min(Q.length-1,y+(l==="j"?1:-1)))];return ge=L(k[U]),s("pbody").querySelectorAll(".ice-row").forEach((F)=>F.classList.toggle("cur",+F.dataset.i===U)),s("pbody").querySelector(`.ice-row[data-i="${U}"]`)?.scrollIntoView({block:"nearest"}),!0}let P=l==="o"?s("ice-o-"+S):l==="x"?s("ice-ck-"+S):l==="p"?X.size?s("ice-bp"):s("ice-pr-"+S):l==="d"?X.size?s("ice-bd"):s("ice-ds-"+S):null;if(!P||P.disabled)return!1;return o.preventDefault(),P.click(),!0},s("pbody").querySelectorAll("[data-chk]").forEach((o)=>{let l=v[+o.dataset.chk];o.onclick=()=>{o.disabled=!0,o.innerHTML=E("refresh")+" Checking…",Ue({op:"gather",dir:l.dir,url:l.url},(y)=>{let S=y.results&&y.results[0];C(S?S.ok?`${l.label||g(l.url)}: ${S.note}${S.added?" in the icebox":""}`:`Failed: ${S.note}`:"Checked")})}}),s("pbody").querySelectorAll("[data-ag]").forEach((o)=>{let l=v[+o.dataset.ag];o.onclick=()=>{if(o.disabled=!0,G)o.innerHTML=E("refresh")+" Gathering…";Ue({op:"agent",dir:l.dir,url:l.url},(y)=>{let S=y.results&&y.results[0];C(y.via==="chatgpt"?S&&S.ok?`${l.label||g(l.url)}: ${S.note}${S.added?" in the icebox":""}`:`Failed: ${S?S.note:"no answer"}`:"/kaizen gather opened in your terminal: "+Ie(y.agent))})}}),s("pbody").querySelectorAll("[data-rm]").forEach((o)=>{let l=v[+o.dataset.rm];o.onclick=()=>{if(!confirm(`Remove ${l.label||g(l.url)}? What it gathered stays; added again later, it may bring back ones you deleted or dismissed.`))return;Ue({op:"remove",dir:v[+o.dataset.rm].dir,url:v[+o.dataset.rm].url},()=>C("Source removed"))}});let Vn=k.findIndex((o)=>L(o)===ge);if(r){let o=k.findIndex((l)=>L(l)===r[0]);(o>=0?s(r[1]+"-"+o):Vn>=0?s("ice-o-"+Vn):null)?.focus()}let Tt=!r&&t[2]&&s(t[2]);if(Tt)(Tt.disabled?s(Tt.id.replace("src-mb-","src-mv-").replace("src-cs-","src-ct-")):Tt)?.focus();if(s("src-add"))s("src-add").onclick=()=>{let o=at==="social",l=s("src-url").value.trim(),y=s("src-q").value.trim(),S=s("src-plat").value;if(o?!y:!l){s(o?"src-q":"src-url").focus();return}let P=s("src-dir").value;if(!P){s("src-dir").focus();return}s("src-add").disabled=!0,s("src-add").textContent="Adding…",(async()=>{let U=s("src-label").value.trim()||(o?`${kt[S]}: ${y}`:""),F=s("src-cat").value.trim(),_=await T("/sources",o?{op:"add",dir:P,platform:S,query:y,label:U,category:F}:{op:"add",dir:P,url:l,label:U,category:F});if(_.ok&&o)s("src-q").value=s("src-label").value=s("src-cat").value="",C("Source added"),N();else if(_.ok){s("src-url").value=s("src-label").value=s("src-cat").value="";let ce=await T("/sources",{op:"gather",dir:P,url:l}),me=ce.results&&ce.results[0];C(me?me.ok?`Source added: ${me.note} in the icebox`:`Source added, but: ${me.note}`:"Source added"),N()}else C(_.error||"Could not add source");if(_.ok)it=!1;if(ee())z()})()},s("src-url").onkeydown=s("src-q").onkeydown=s("src-label").onkeydown=s("src-cat").onkeydown=(o)=>{if(o.key==="Enter")s("src-add").click()};if(s("ice-new"))s("ice-new").onclick=()=>{let o=!c;if(!c&&!ze().length)return C("Pick a project first");let l=_e(`${o?'<div class="combo" id="ndc"><button type="button" class="sel" id="newdir" aria-label="Project for this request" aria-haspopup="listbox" aria-expanded="false"></button><div class="menu-pop" hidden><input class="sel" aria-label="Search projects" placeholder="Search projects…" spellcheck="false" autocomplete="off"><div id="nds" role="listbox"></div></div></div>':""}<textarea id="newidea" placeholder="What did someone ask for?" aria-label="Request"></textarea><div class="att"></div><input type="file" multiple hidden><div class="row"><button type="button" class="ib" id="newpick" aria-label="Attach files" title="Attach files">${E("clip")}</button><button type="button" class="btn ghost" value="">Cancel</button><button class="btn pri">Add</button></div>`),y=l.querySelector("form"),S=y.querySelector("textarea"),P=[],U=(_)=>{P.push(_),y.querySelector(".att").textContent=P.map((ce)=>ce.name).join(" · ")};if(y.querySelector("#newpick").onclick=()=>y.querySelector("input[type=file]").click(),y.querySelector("input[type=file]").onchange=(_)=>{[..._.target.files].forEach(U),_.target.value=""},S.onpaste=(_)=>{for(let ce of _.clipboardData.items)if(ce.kind==="file"){let me=ce.getAsFile();U(new File([me],me.name==="image.png"?`paste-${Date.now()}.png`:me.name,{type:me.type})),_.preventDefault()}},y.querySelector(".btn.ghost").onclick=()=>l.close(),o)Ut(y);let F=Be([S]);if(F)y.querySelector(".row").prepend(F);l.addEventListener("close",()=>de(!1)),S.onkeydown=(_)=>{if(_.key==="Enter"&&!_.shiftKey)_.preventDefault(),y.requestSubmit()},y.onsubmit=async(_)=>{_.preventDefault();let ce=S.value.trim(),me=c||Pe;if(!ce)return S.focus();if(!me)return C("Pick a project first");if((await T("/icebox",{op:"add",dir:me,text:ce,files:await jt(P)})).ok)C("Added to the icebox"),l.close()},S.focus()};if(s("src-go"))s("src-go").onclick=()=>{s("src-go").disabled=!0,s("src-go").innerHTML=E("refresh")+" Gathering…",Ue({op:"gather",dir:c||void 0},(o)=>{let l=o.results||[],y=(F)=>v.some((_)=>_.url===F.url&&_.social),S=l.reduce((F,_)=>F+_.added,0),P=l.filter((F)=>!F.ok&&!y(F)).length,U=l.filter(y).length;C((S?`${S} new in the icebox`:"Nothing new")+(P?`, ${P} source${P===1?"":"s"} could not be read`:"")+(U?`; ${U} social for /kaizen gather`:""))})}}var bn=new URLSearchParams(location.search).has("all");function Ge(e){if(bn)return;try{e?localStorage.setItem("kz-proj",e):localStorage.removeItem("kz-proj")}catch(t){}}var De=(e)=>e.split(/[\\/]/).pop()||e,rt=(e,t="")=>{let n=h`<span class="plogo" aria-hidden="true">${(De(t)||"?").charAt(0).toUpperCase()}</span>`;return a.S?.projects?.some((i)=>i.dir===e&&i.logo)?h`<img class="plogo" src="/project-logo?dir=${encodeURIComponent(e)}" alt="" loading="lazy" onerror="this.outerHTML=this.dataset.f" data-f="${String(n)}">`:n},Bt=(e,t)=>h`${rt(e,t)}<span>${De(t)}</span>`;function Vt(){let e=s("projq").value.trim().toLowerCase(),t=0;s("projs").innerHTML=a.PL.map((i,r)=>i[0].toLowerCase().includes(e)?h`${i[2]&&!t++?h`<div class="grp">In your projects folder</div>`:""}<button role="option" data-i="${r}" title="${i[0]}">${i[1]==="all"?h`<span class="plogo" aria-hidden="true">${E("board")}</span><span>${i[0]}</span>`:i[1]==="__new"||i[1]==="__find"||i[1]==="__clone"?h`<span class="plogo" aria-hidden="true">${E("plus")}</span><span>${i[0]}</span>`:Bt(i[1],i[0])}</button>`:"").join("")||'<div class="grp">No match</div>';let n=s("projs").querySelector("button");if(n)n.classList.add("on")}function _t(e){if(s("projpop").hidden=!e,s("proj").setAttribute("aria-expanded",e),e)s("projq").value="",Vt(),s("projq").focus()}async function fo(e){if(e==="__find"){C("Searching…");let t=await T("/find",{});if(t.ok)C(t.added?`Found ${t.added} new project${t.added===1?"":"s"}`:"No new projects found")}else if(e==="__new"){let t=_e('<b>New project</b><input name="name" placeholder="Project name" aria-label="Project name" spellcheck="false" autocomplete="off"><div class="row"><input name="to" placeholder="Folder to create" aria-label="Create in" spellcheck="false" autocomplete="off"><button type="button" class="btn ghost" data-a="pick">Pick…</button></div><div class="row"><button type="button" class="btn ghost" data-a="x">Cancel</button><button class="btn pri">Create</button></div>'),n=t.querySelector("form"),i=n.querySelector("[name=name]"),r=n.querySelector("[name=to]"),d="";i.oninput=async()=>{let c=i.value.trim();if(!c||/[\\/:*?"<>|]/.test(c)||r.value.trim()&&r.value!==d)return;let m=await T("/new-project",{name:c,check:!0});if(m.ok&&i.value.trim()===c)r.value=d=m.to},n.querySelector("[data-a=x]").onclick=()=>t.close(),n.querySelector("[data-a=pick]").onclick=async()=>{let c=await T("/pick-folder",{});if(c.path)r.value=c.path.replace(/[\\/]+$/,"")+(c.path.includes("\\")?"\\":"/")+(i.value.trim()||"")},i.focus();let u=await new Promise((c)=>{t.addEventListener("close",()=>c(null)),n.onsubmit=async(m)=>{if(m.preventDefault(),!i.value.trim())return i.focus();let f=await T("/new-project",{name:i.value.trim(),to:r.value.trim()||void 0});if(!f.ok)return;c(f.dir),t.close()}});if(!u)return;await T("/cd",{dir:u}),a.all=!1,a.dir=u,Ge(u),C("Project created")}else if(e==="__clone"){let t=_e('<b>Clone from GitHub</b><input name="url" placeholder="https://github.com/owner/repo" aria-label="GitHub link (https or ssh)" spellcheck="false" autocomplete="off"><div class="row"><input name="to" placeholder="Folder to clone into" aria-label="Clone into" spellcheck="false" autocomplete="off"><button type="button" class="btn ghost" data-a="pick">Pick…</button></div><div class="row"><button type="button" class="btn ghost" data-a="x">Cancel</button><button class="btn pri">Clone</button></div>'),n=t.querySelector("form"),i=n.querySelector("[name=url]"),r=n.querySelector("[name=to]"),d="",u="",c=async()=>{let f=i.value.trim();if(!f)return null;let g=await T("/clone",{url:f,check:!0});if(!g.ok)return null;if(d=g.name,!r.value.trim()||r.value===u)r.value=u=g.to;return g};i.onchange=c,n.querySelector("[data-a=x]").onclick=()=>t.close(),n.querySelector("[data-a=pick]").onclick=async()=>{if(!await c())return i.focus();let f=await T("/pick-folder",{});if(f.path)r.value=f.path.replace(/[\\/]+$/,"")+(f.path.includes("\\")?"\\":"/")+d},i.focus();let m=await new Promise((f)=>{t.addEventListener("close",()=>f(null)),n.onsubmit=async(g)=>{if(g.preventDefault(),!await c())return i.focus();C("Cloning…");let b=await T("/clone",{url:i.value.trim(),to:r.value.trim()||void 0});if(!b.ok)return;f(b.dir),t.close()}});if(!m)return;await T("/cd",{dir:m}),a.all=!1,a.dir=m,Ge(m),C("Cloned")}else if(e==="all")a.all=!0,Ge();else if((await T("/cd",{dir:e})).ok)a.all=!1,a.dir=e,Ge(e);if(await N(),W==="sources")z()}var Pe=null;function Ut(e){let t=mo(),n=e.querySelector("#newdir"),i=e.querySelector("#ndc .menu-pop"),r=i.querySelector("input"),d=e.querySelector("#nds");if(!t.some((f)=>f.dir===Pe))Pe=t[0]?.dir??null;let u=()=>{let f=t.find((g)=>g.dir===Pe);n.innerHTML=f?Bt(f.dir,f.label):"Choose project"},c=()=>{let f=r.value.trim().toLowerCase();d.innerHTML=t.filter((g)=>g.label.toLowerCase().includes(f)).map((g)=>h`<button type="button" role="option" data-d="${g.dir}" title="${g.label}" class="${g.dir===Pe?"on":""}">${Bt(g.dir,g.label)}</button>`).join("")||'<div class="grp">No match</div>',d.querySelectorAll("button").forEach((g)=>g.onclick=()=>{Pe=g.dataset.d,u(),m(!1),e.querySelector("#newidea").focus()})},m=(f)=>{if(i.hidden=!f,n.setAttribute("aria-expanded",f),f)r.value="",c(),r.focus()};n.onclick=(f)=>{f.preventDefault(),m(i.hidden)},r.oninput=c,r.onkeydown=(f)=>{if(f.key==="Escape")f.stopPropagation(),m(!1);if(f.key==="Enter")f.preventDefault(),d.querySelector("button")?.click()},u()}function mo(){let e=ze(),t=e.filter((n)=>a.shown.has(n.dir));return t.length?t:e}function ze(){let e=[...a.S.projects];for(let t of a.S.cards)if(!e.some((n)=>n.dir===t.state))e.push({dir:t.state,label:t.where});return e}var lt=[];function Wt(){let e=s("showq").value.trim().toLowerCase();lt=ze(),s("shows").innerHTML=lt.map((n,i)=>n.label.toLowerCase().includes(e)?h`<button type="button" role="menuitemcheckbox" data-i="${i}" aria-checked="${String(a.shown.has(n.dir))}" title="${n.label}">${Bt(n.dir,n.label)}<svg class="ck"><use href="#i-check"/></svg></button>`:"").join("")||'<div class="grp">No match</div>';let t=lt.filter((n)=>a.shown.has(n.dir)).length;s("showcount").textContent=t?`${t} of ${lt.length} shown`:`All ${lt.length} shown`}function Ft(){try{localStorage.setItem("kz-show",JSON.stringify([...a.shown]))}catch(e){}if(H(),ee())z()}function ys(){s("proj").onclick=()=>_t(s("projpop").hidden),s("projq").oninput=Vt,s("projq").onkeydown=(e)=>{let t=[...s("projs").querySelectorAll("button")],n=t.findIndex((i)=>i.classList.contains("on"));if(e.key==="Escape")_t(!1),s("proj").focus();else if(e.key==="Enter"){if(t[n])t[n].click()}else if((e.key==="ArrowDown"||e.key==="ArrowUp")&&t[n]){e.preventDefault();let i=t[(n+(e.key==="ArrowDown"?1:t.length-1))%t.length];t[n].classList.remove("on"),i.classList.add("on"),i.scrollIntoView({block:"nearest"})}},s("projs").onclick=(e)=>{let t=e.target.closest("button");if(t)_t(!1),fo(a.PL[t.dataset.i][1])},document.addEventListener("click",(e)=>{if(!e.target.closest("#combo"))_t(!1)}),s("show").onclick=()=>{let e=s("showpop").hidden;if(s("showpop").hidden=!e,s("show").setAttribute("aria-expanded",e),e)s("showq").value="",Wt(),s("showq").focus()},s("showq").oninput=Wt,s("showq").onkeydown=(e)=>{if(e.key==="Escape")s("showpop").hidden=!0,s("show").setAttribute("aria-expanded",!1),s("show").focus()},s("shows").onclick=(e)=>{let t=e.target.closest("button[data-i]"),n=t?.dataset.i,i=lt[n]?.dir;if(!i)return;a.shown.has(i)?a.shown.delete(i):a.shown.add(i),Ft(),s("shows").querySelector(`[data-i="${n}"]`)?.focus()},s("showall").onclick=()=>{a.shown.clear(),Ft()},document.addEventListener("click",(e)=>{if(!e.target.closest("#showc"))s("showpop").hidden=!0,s("show").setAttribute("aria-expanded",!1)}),s("newtop").onclick=$t}var Se=null,xn="",yn=6,Qt=new Set,xt=(()=>{try{return JSON.parse(localStorage.getItem("kz-order"))||{}}catch(e){return{}}})(),te=!1,St=(()=>{try{return localStorage.getItem("kz-ideas-tab")==="backlog"?"backlog":"ideas"}catch(e){return"ideas"}})(),He=null,vn=[["high","High+",(e)=>e==="critical"||e==="high"],["medium","Medium",(e)=>e==="medium"],["low","Low",(e)=>e==="low"],["none","No severity",(e)=>!e]],kn=()=>(a.S.backlog||[]).map((e)=>({...e,kind:"backlog",status:e.starting?"starting":"idea",title:e.text,column:0,archived:!1,_k:"backlog:"+e.state+":"+e.source+"#"+e.n})),wn=(e)=>{if(e.kind!=="backlog")return xe(e);let t=a.S.cards.find((n)=>n.kind==="run"&&n.id===e.source&&n.state===e.state);if(!t)return C(e.source==="orphan"?"Kept from a run that was pruned":"That run is not on this board");Ss(t,"backlog",e.n)},Lt=!1,ke=new Set,D=(e)=>e._k||(e.kind==="idea"?"idea:"+e.state+":"+e.text:"run:"+e.state+":"+e.id),ho=(e)=>e.kind==="run"?a.S.cards.filter((t)=>t.parent===e.id&&t.state===e.state):[],go=(e)=>!!e.parent&&a.S.cards.some((t)=>t.kind==="run"&&t.id===e.parent&&t.state===e.state&&!t.archived&&t.column!==4),$n=new Set,vs=(e)=>nt.has(st(e))?"Sent to agent":e.status!=="waiting"?"Open":{"approvals.plan":"Review plan",findings:"See findings","approvals.review":"Review work"}[e.awaiting]||"Open";function bo(e){let t=D(e),n=document.createElement("div");n.className="card"+(t===a.openKey?" open":"")+(t===a.menuKey?" menu":"")+(a.flash.has(t)?" flash":"")+(e.archived?" archived":""),n.tabIndex=0,n.dataset.k=t,n.setAttribute("role","button");let i=Ke[e.status]||"idea",r=e.kind==="run"?e.text.replace(/-/g," "):"",d=e.status==="waiting"?gt(e.awaiting)||"needs you":e.status||"idea",u=[],c=[],m=(p,v,k="")=>h`<span class="mk${k}" role="img" title="${v}" aria-label="${v}"><svg><use href="#${p}"/></svg></span>`;if(a.all){let p=e.where.split("/").filter(Boolean).pop()||e.where;u.push(h`<span class="chip proj" title="${e.where}">${p}</span>`)}for(let p of e.tags||[])if(ns[p])c.push(m("c-"+p,p==="full"?"Full run: separate reviewer":p==="lite"?"Lite run: one session":rn[p]||p,p==="full"||p==="lite"?" accent":""));else if(p==="yolo")c.push(h`<span class="mk warn" title="Started in Yolo: the agent runs commands without asking">yolo</span>`);else u.push(h`<span class="chip">${rn[p]||p}</span>`);if(e.pty&&e.pty.alive&&e.pty.asking)c.push(m("i-ask","The agent is asking you something: open it, terminal button at the top"," warn ask"));else if(e.pty&&e.pty.alive)c.push(m("i-term","The agent is running in this card: open it, terminal button at the top"," run"));let f=e.notes&&/^\[[^\]]*\] (?:Gathered from|Promoted from the icebox:) (.+?)\. Outside text/.exec(e.notes);if(e.parent)u.push(h`<span class="chip link" title="Filed by ${e.parent}">${e.parent.replace(/^\d{4}-\d\d-\d\d-/,"").replace(/-/g," ")}</span>`);if(e.kind==="backlog"){if(e.severity)u.push(h`<span class="chip${e.severity==="critical"||e.severity==="high"?" warn":""}"><i></i>${e.severity}</span>`);u.push(e.source==="orphan"?h`<span class="chip" title="Kept from a pruned run">orphaned</span>`:h`<span class="chip link" title="Left by ${e.source}${e.at?" · "+e.at:""}">${e.source.replace(/^\d{4}-\d\d-\d\d-/,"").replace(/-/g," ")}</span>`)}if(e.branch)u.push(h`<span class="chip" title="Built on its own branch, ${e.branch}">branch</span>`);if(f)u.push(h`<span class="chip" title="From ${f[1]}">gathered</span>`);else if(e.notes)u.push(h`<span class="chip">notes</span>`);if(e.git)c.push(m("c-git",e.git==="pushed"?"Committed & pushed":"Not committed & pushed yet",e.git==="pushed"?" ok":" warn"));if(e.open)c.push(m("i-bug",`${e.open} open finding${e.open===1?"":"s"} to fix`," warn"));let g=Lt&&!te&&e.column===4;if(e.column===4&&!te)n.classList.add("compact");let b=e.kind==="run"&&!te&&!g?e.status==="waiting"?h`<button class="btn sm${nt.has(st(e))?"":" pri"} act" data-a="open">${vs(e)}</button>`:e.status==="stalled"&&Nt(e)?h`<button class="btn sm act" data-a="resume">Resume</button>`:"":"";n.innerHTML=(g?h`<input type="checkbox" class="pick" ${B(ke.has(t)?"checked":"")} aria-label="Select">`:"")+h`<div class="c-id"><span class="st d-${i}" role="img" title="${d}" aria-label="${d}"><svg><use href="#s-${i}"/></svg></span><span class="idt">${r}</span><span class="age">${e.kind==="run"?ts(e.moved||a.S.now,a.S.now):""}</span><button class="ib sm more" data-a="menu" title="Actions" aria-label="Actions" aria-haspopup="menu" aria-expanded="${String(t===a.menuKey)}">${E("more")}</button></div>
|
|
26
26
|
<div class="c-title"${e.kind==="idea"&&Ee(e.text).parts.length?h` title="${e.text}"`:""}>${e.kind==="idea"?Ee(e.text).head:e.title||e.id}</div>
|
|
27
27
|
${b}
|
|
28
28
|
${u.length||c.length?h`<div class="c-foot"><span class="c-chips">${u}</span><span class="c-marks">${c}</span></div>`:""}`;let w=ho(e);if(w.length){let p=$n.has(t),v=w.filter((q)=>q.status==="done").length,k=w.some((q)=>q.status==="waiting"),A=document.createElement("div");A.className="kids",A.innerHTML=h`<button class="kids-t" aria-expanded="${String(p)}">${p?"▾":"▸"} ${w.length} ${w.length===1?"child":"children"}${v?` · ${v} done`:""}${k?h`<span class="kids-w" title="A child is waiting on you"></span>`:""}</button>`+(p?h`<ul>${w.map((q,G)=>{let x=Ke[q.status]||"idea";return h`<li data-i="${G}" tabindex="0" role="button" title="Open"><span class="st d-${x}"><svg><use href="#s-${x}"/></svg></span><span class="kids-s">${Xe[q.status]||q.status}</span><span class="kids-n" title="${q.title||q.text||q.id}">${q.kind==="idea"?Ee(q.text).head:(q.text||q.id||"").replace(/-/g," ")}</span></li>`})}</ul>`:""),A.querySelector(".kids-t").onclick=(q)=>{q.stopPropagation(),p?$n.delete(t):$n.add(t),H()},A.querySelectorAll("li").forEach((q)=>{let G=(x)=>{x.stopPropagation(),xe(w[+q.dataset.i])};q.onclick=G,q.onkeydown=(x)=>(x.key==="Enter"||x.key===" ")&&(x.preventDefault(),G(x))}),n.appendChild(A)}if(t===a.menuKey){let p=[];if(te){if(p.push(["restore","Restore",E("restore")]),p.push(["open","Open",E("open")]),e.kind==="idea")p.push(null,["delete","Delete",E("trash"),"danger"])}else if(e.kind==="backlog")p.push(["run",e.status==="starting"?"Run again":"Run",E("play")],["open","Open its run",E("open")],null,["reject","Reject",E("x"),"danger"]);else if(e.kind==="idea"&&e.status==="idea")p.push(["run","Run",E("play")],["edit","Edit",E("pen")],...a.S.projects.some((v)=>v.dir!==e.state)?[["move","Move to project",E("ext")]]:[],["archive","Archive",E("archive")],null,["reject","Reject",E("x")],["delete","Delete",E("trash"),"danger"]);else if(e.kind==="idea")p.push(["open","Open",E("open")],["run","Run again",E("play")],["archive","Archive",E("archive")],null,["delete","Remove",E("trash"),"danger"]);else{if(p.push(["open",vs(e),E("open")]),p.push(["archive","Archive",E("archive")]),e.column===1&&e.status!=="abandoned")p.push(["toidea","Back to idea",E("restore")]);if(e.status==="waiting"||e.status==="running"||e.status==="stalled")p.push(null,["reject","Abandon",E("x"),"danger"])}n.innerHTML+=h`<div class="menu-pop" role="menu">${p.map((v)=>v?h`<button role="menuitem" data-a="${v[0]}" class="${v[3]||""}">${v[2]}${v[1]}</button>`:B("<hr>"))}</div>`}if(n.querySelectorAll("[data-a]").forEach((p)=>p.onclick=async(v)=>{v.stopPropagation();let k=p.dataset.a,A=a.menuKey;if(a.menuKey=null,k==="menu"){a.menuKey=A===t?null:t,H();return}if(k==="open"){wn(e);return}if(k==="resume"){tt(e,p);return}if(k==="archive"||k==="restore"){Jt(e,k==="archive");return}if(k==="toidea"){if((await T("/to-idea",{dir:e.state,id:e.id})).ok)C("Back in Ideas");N();return}a.mode=k,a.modeKey=t,H()}),g)return n.classList.toggle("picked",ke.has(t)),n.onclick=()=>{ke.has(t)?ke.delete(t):ke.add(t),H()},n;return n.onclick=()=>{if(a.menuKey){a.menuKey=null,H();return}wn(e)},n.onkeydown=(p)=>{if(p.key==="Enter"||p.key===" ")p.preventDefault(),wn(e)},n}function yo(e){let t=document.createElement("li");t.className="inl";let n=e.state;if(a.mode==="edit")t.innerHTML=h`<input value="${e.text}"><textarea placeholder="Anything the planner should know">${e.notes||""}</textarea><div class="q dim" id="clong" hidden>The first line is over 72 characters; logs will cut it short.</div><div class="row"><button class="btn ghost" data-a="c">Cancel</button><button class="btn pri" data-a="s">Save</button></div>`,t.querySelector("[data-a=s]").onclick=async()=>{let r=t.querySelector("input").value.trim(),d=t.querySelector("textarea").value.trim();if(a.mode=null,r&&(r!==e.text||d!==(e.notes||"")))await T("/inbox",{op:"edit",dir:n,text:e.text,next:r,notes:d});N()};if(a.mode==="reject"){let r=e.kind!=="run";t.innerHTML=h`<div class="q">${e.kind==="backlog"?"Not doing this backlog item?":r?"Reject this idea?":"Abandon this run?"} The reason is recorded.</div><input placeholder="Why not?"><div class="row"><button class="btn ghost" data-a="c">Keep it</button><button class="btn warn" data-a="s">${r?"Reject":"Abandon"}</button></div>`,t.querySelector("[data-a=s]").onclick=async()=>{let d=t.querySelector("input").value.trim();if(!d){C("A reason is required");return}if(a.mode=null,(e.kind==="backlog"?await T("/backlog",{op:"reject",dir:n,source:e.source,n:e.n,reason:d}):r?await T("/inbox",{op:"reject",dir:n,text:e.text,reason:d}):await T("/abort",{dir:n,id:e.id,why:d})).ok)C(r?"Rejected":"Abandoned, reason recorded");N()}}if(a.mode==="delete")t.innerHTML=h`<div class="q">Delete "${e.text}"?</div><div class="q dim">Not recorded anywhere.</div><div class="row"><button class="btn ghost" data-a="c">Keep it</button><button class="btn danger" data-a="s">Delete</button></div>`,t.querySelector("[data-a=s]").onclick=async()=>{if(a.mode=null,(await T("/inbox",{op:"delete",dir:n,text:e.text})).ok)C("Deleted");N()};if(a.mode==="move"){let r=a.S.projects.filter((d)=>d.dir!==n);t.innerHTML=h`<div class="q">Move "${e.text}" to</div><select class="sel" aria-label="Project">${r.map((d)=>h`<option value="${d.dir}" title="${d.label}">${De(d.label)}</option>`)}</select><div class="row"><button class="btn ghost" data-a="c">Cancel</button><button class="btn pri" data-a="s">Move</button></div>`,t.querySelector("[data-a=s]").onclick=async()=>{let d=t.querySelector("select"),u=d.value,c=d.selectedOptions[0]?.textContent;if(a.mode=null,(await T("/inbox",{op:"move",dir:n,to:u,text:e.text})).ok)C(`Moved to ${c}`);N()}}if(a.mode==="run")t.innerHTML=h`<div class="q">Run "${e.text}"</div><div class="q dim">Opens your agent with this request in a terminal.</div><div class="q dim">Full plans, builds, and checks with a separate reviewer. Lite does it in one session.</div><div id="run-pick" style="display:grid;gap:6px"><div id="run-agent" class="agents" role="radiogroup" aria-label="Agent"></div></div><div class="run-actions"><label class="yolo" id="run-yolo" title="Yolo: the agent runs every command and edit without asking" hidden><button type="button" class="chk" role="switch" aria-checked="false"></button>Yolo</label><div class="row"><button class="btn ghost" data-a="c">Cancel</button><button class="btn" data-a="l">Lite</button><button class="btn pri" data-a="s">Full run</button></div></div>`,t.querySelector("[data-a=s]").onclick=()=>Sn(e,"full"),t.querySelector("[data-a=l]").onclick=()=>Sn(e,"lite"),vo(t,e);if(t.querySelector("[data-a=c]").onclick=()=>{a.mode=null,H()},t.querySelectorAll("input,textarea").forEach((r,d)=>We(r,"f:"+a.mode+":"+a.modeKey+":"+d)),a.mode!=="run"){let r=Be([...t.querySelectorAll("input,textarea")]);if(r)t.querySelector(".row").prepend(r)}let i=t.querySelector("input");if(i)i.onkeydown=(r)=>{if(r.key==="Enter")t.querySelector("[data-a=s]").click();if(r.key==="Escape")a.mode=null,H()},setTimeout(()=>i.focus());return t}var ie=null,Ie=(e)=>e.name+(e.note?". "+e.note:"");async function vo(e,t){let n=D(t),i=e.querySelector("#run-agent"),r=await fetch("/agents?dir="+encodeURIComponent(t.state)).then((m)=>m.json()).catch(()=>null);if(!r||!r.agents||!r.agents.length){e.querySelector("#run-pick").hidden=!0;return}if(r.agents.some((m)=>m.cmd==="agy"))r.agents=r.agents.filter((m)=>m.cmd!=="gemini");if(!ie||ie.k!==n)ie={k:n,agent:r.agents.some((m)=>m.cmd===r.default)?r.default:r.agents[0].cmd};i.innerHTML=r.agents.map((m)=>h`<button type="button" class="agent" role="radio" aria-checked="${String(m.cmd===ie.agent)}" data-cmd="${m.cmd}"><svg><use href="#c-${m.cmd}"/></svg>${m.name}</button>`).join("");let d=e.querySelector("#run-yolo"),u=d.querySelector(".chk"),c=()=>{let m=!!r.agents.find((g)=>g.cmd===ie.agent)?.yolo,f=!!ie.yolo;d.hidden=!m,u.classList.toggle("on",f),u.setAttribute("aria-checked",f)};i.querySelectorAll(".agent").forEach((m)=>m.onclick=()=>{ie.agent=m.dataset.cmd,i.querySelectorAll(".agent").forEach((f)=>f.setAttribute("aria-checked",f===m)),c()}),u.onclick=()=>{ie.yolo=!ie.yolo,c()},c(),i.onkeydown=u.onkeydown=(m)=>{if(m.key==="Escape")a.mode=null,H()}}async function Sn(e,t){a.mode=null,Le();let n=ie&&ie.k===D(e)?ie:null;ie=null;let i=!!(n&&n.yolo&&!s("run-yolo")?.hidden),r=e.kind==="backlog"?{source:e.source,n:e.n}:void 0,d=await T("/run",{dir:e.state,text:e.text,backlog:r,kind:t,agent:n?n.agent:void 0,yolo:i});if(d.ok){if(C((t==="full"?"Full":t==="lite"?"Lite":"Started")+(i?" yolo":"")+" run "+Ve(d)+": "+Ie(d.agent)),d.pty&&!r)a.wantTerm=D(e)}N()}var ko={1:"Ideas you run are planned here",2:"Approved plans are built here",3:"Finished builds are checked here"};function ks(e,t){e.innerHTML=h`${a.all?h`<div class="combo" id="ndc"><button type="button" class="sel" id="newdir" aria-label="Project for this idea" aria-haspopup="listbox" aria-expanded="false"></button><div class="menu-pop" hidden><input class="sel" aria-label="Search projects" placeholder="Search projects…" spellcheck="false" autocomplete="off"><div id="nds" role="listbox"></div></div></div>`:""}<input id="newidea" placeholder="What do you want to build?"><textarea id="newnotes" placeholder="Anything the planner should know (optional)"></textarea><div class="att" id="newatt"></div><input type="file" id="newfile" multiple hidden><div class="row"><button type="button" class="ib" id="newpick" aria-label="Attach files" title="Attach files">${E("clip")}</button><button type="button" class="btn ghost" id="nc">Cancel</button><div class="split"><button type="button" class="btn pri" id="ns">Add</button><button type="button" class="btn pri" id="nm" aria-label="More ways to add" aria-haspopup="menu" aria-expanded="false">${E("chev")}</button><div class="menu-pop" role="menu" hidden><button type="button" role="menuitem" id="nr" title="Add the idea and run it now">${E("play")}Start run</button></div></div></div>`;let n=e.querySelector("#newidea"),i=[];We(n,"f:new:0"),We(e.querySelector("textarea"),"f:new:1");let r=async(u)=>{let c=n.value.trim();if(!c)return;let m=e.querySelector("textarea").value.trim();t();let f=a.all?Pe:null;if((await T("/inbox",f?{op:"add",dir:f,text:c,notes:m}:{op:"add",text:c,notes:m})).ok){if(C("Idea added"),i.length){let b=await jt(i);if(!(await T("/note",{dir:f,for:c,text:"",files:b})).ok)C("Idea added, files not attached")}if(u){await N();let b=a.S.cards.find((w)=>w.kind==="idea"&&w.text===c&&(!f||w.state===f));if(b)return Sn(b)}}N()},d=(u)=>{i.push(u),e.querySelector("#newatt").textContent=i.map((c)=>c.name).join(" · ")};e.querySelector("#newpick").onclick=()=>e.querySelector("#newfile").click(),e.querySelector("#newfile").onchange=(u)=>{[...u.target.files].forEach(d),u.target.value=""};for(let u of[n,e.querySelector("textarea")])u.onpaste=(c)=>{for(let m of c.clipboardData.items)if(m.kind==="file"){let f=m.getAsFile();d(new File([f],f.name==="image.png"?`paste-${Date.now()}.png`:f.name,{type:f.type})),c.preventDefault()}};if(a.all)Ut(e);e.querySelector("#ns").onclick=()=>r(!1),e.querySelector("#nr").onclick=()=>r(!0);{let u=e.querySelector("#nm"),c=e.querySelector(".split .menu-pop"),m=(g,b)=>{if(c.hidden=!g,u.setAttribute("aria-expanded",String(g)),g&&b)setTimeout(()=>c.querySelector("button").focus())};u.onclick=(g)=>{g.stopPropagation(),m(c.hidden,g.detail===0)},c.onkeydown=(g)=>{if(g.key==="Escape")g.preventDefault(),g.stopPropagation(),m(!1),u.focus()},e.addEventListener("click",(g)=>{if(!c.hidden&&!g.target.closest(".split"))m(!1)});let f=e.querySelector(".split");f.addEventListener("focusout",(g)=>{if(!f.contains(g.relatedTarget))m(!1)})}e.querySelector("#nc").onclick=t;{let u=Be([n,e.querySelector("textarea")]);if(u)e.querySelector(".row").prepend(u)}n.onkeydown=(u)=>{if(u.key==="Enter")u.preventDefault(),r(!1);if(u.key==="Escape")u.preventDefault(),t()},setTimeout(()=>n.focus())}function $t(){if(a.mode==="new")a.mode=null,H();let e=_e(""),t=e.querySelector("form");t.onsubmit=(n)=>n.preventDefault(),e.addEventListener("close",()=>de(!1)),ks(t,()=>e.close())}function H(){if(a.mode&&a.mode!=="new"&&![...a.S.cards,...kn()].some((b)=>D(b)===a.modeKey))a.mode=null;if(a.mode!=="run"&&ie)ie.yolo=!1;if(!a.mode)Xn("f:");try{sessionStorage.setItem("kz-form",JSON.stringify(["new","edit","reject"].includes(a.mode)?[a.mode,a.modeKey]:null))}catch(b){}let e=Ln(),t=a.all&&a.shown.size&&ze().some((b)=>a.shown.has(b.dir)),n=a.S.cards.filter((b)=>b.archived===te&&(!t||a.shown.has(b.state))),i=s("board");i.innerHTML="",i.removeAttribute("aria-busy");let r=a.S.cards.filter((b)=>b.archived).length,d=(b)=>n.filter((w)=>w.status===b).length,u=[];for(let b of["waiting","running","stalled","starting","idea","done","abandoned"]){let w=d(b);if(!w&&b!=="running")continue;let p=b==="running"?'<span class="d-run"><span class="pulse"></span></span>':`<span class="st d-${Ke[b]}"><svg><use href="#s-${Ke[b]}"/></svg></span>`;u.push(`<button class="${b==="waiting"?"attn ":""}${Se===b?"on":""}" data-f="${b}" title="Show only ${Xe[b]}">${p}${w} ${Xe[b]}${b==="idea"&&w!==1?"s":""}</button>`)}u.push(`<button class="${te?"on":""}" data-f="__archive" title="${n.filter((b)=>b.kind==="idea").length} ideas · ${n.filter((b)=>b.kind==="run").length} runs on the board">${te?"Back to board":"Archive "+r}</button>`),s("strip").innerHTML=u.join(""),s("fbtn").hidden=!1,s("fbtn").classList.toggle("on",!!Se||te),s("fbtn").classList.toggle("wait",!Se&&!te&&d("waiting")>0),s("strip").querySelectorAll("button").forEach((b)=>b.onclick=()=>{if(b.dataset.f==="__archive"){te=!te,Se=null,H();return}Se=Se===b.dataset.f?null:b.dataset.f,H()}),a.PL=[["All projects","all"],...a.S.projects.map((b)=>[b.label,b.dir]),...a.S.fresh.map((b)=>[b.label,b.dir,1]),["New project…","__new"],["Find projects on this PC…","__find"],["Clone from GitHub…","__clone"]];let c=a.all||!a.S.dir?"All projects":(a.PL.find((b)=>b[1]===a.S.dir)||["All projects"])[0];if(s("proj").innerHTML=a.all||!a.S.dir?h`<span class="plogo" aria-hidden="true">${E("board")}</span><span>${c}</span>`:h`${rt(a.S.dir,c)}<span>${De(c)}</span>`,s("proj").title=c,!s("projpop").hidden)Vt();s("showc").hidden=!a.all;let m=ze(),f=m.filter((b)=>a.shown.has(b.dir)).length;if(s("show").textContent=f?`Showing ${f} of ${m.length}`:"Showing all",!s("showpop").hidden)Wt();if(!n.length&&a.mode!=="new"){if(i.innerHTML=te?'<div class="empty"><div class="mascot"></div><b>Nothing archived</b></div>':'<div class="empty"><div class="mascot"></div><b>Nothing here yet</b><p>Add an idea and kaizen will plan it, build it, and check the result.</p><button class="btn pri" id="newempty">New idea</button></div>',!te)s("newempty").onclick=$t}ss.forEach((b,w)=>{let p=document.createElement("section"),v=xn.trim().toLowerCase(),k=w===0&&!te&&St==="backlog",q=(k?kn().filter((L)=>!t||a.shown.has(L.state)):n).filter((L)=>L.column===w&&(!k||!He||vn.find((R)=>R[0]===He)[2](L.severity))&&(!Se||L.status===Se)&&(te||!go(L))&&(!v||`${L.title||""} ${L.text||""} ${L.id||""}`.toLowerCase().includes(v)));if(w<4&&!k){let L=(K)=>K.kind==="run"?K.moved||0:K.added||0,R=xt[w]==="old",M=(K)=>a.S.cards.indexOf(K),O=(K)=>K.status==="waiting"?1:0;q.sort((K,Z)=>O(Z)-O(K)||(R?L(K)-L(Z)||M(K)-M(Z):L(Z)-L(K)||M(Z)-M(K)))}let G=w===4&&!te&&q.length,x=(L)=>q.filter((R)=>a.S.now-(R.moved||a.S.now)>L*es),I=w===0&&!te,V=I?kn().filter((L)=>!t||a.shown.has(L.state)):[],ye=I?`<span class="itabs" role="tablist" aria-label="Ideas column">${[["ideas","Ideas",'<svg><use href="#s-idea"/></svg>',n.filter((L)=>L.column===0).length],["backlog","Backlog: what finished runs left undone",E("clock"),V.length]].map(([L,R,M,O])=>`<button role="tab" aria-selected="${String(St===L)}" data-t="${L}" title="${R}" aria-label="${R}, ${O}">${M}<i>${O}</i></button>`).join("")}</span>`:`${b}<i>${q.length||""}</i>`,J=k?`<button class="ib sm sevf${He?" on":""}" data-sv="1" title="${He?"Severity: "+vn.find((L)=>L[0]===He)[1]:"Filter by severity"}" aria-label="Filter by severity" aria-haspopup="menu" aria-expanded="${String(a.sevMenu)}">${E("filter")}</button>`+(a.sevMenu?`<div class="menu-pop sev-pop" role="menu"><button role="menuitemradio" aria-checked="${String(!He)}" data-s="">All severities <i>${V.length}</i></button><hr>${vn.map(([L,R,M])=>`<button role="menuitemradio" aria-checked="${String(He===L)}" data-s="${L}">${R} <i>${V.filter((O)=>M(O.severity)).length}</i></button>`).join("")}</div>`:""):"",fe=`<h2>${ye}${w<4&&!k&&q.length>1?`<button class="btn sm ghost ord" title="Sort order">${xt[w]==="old"?"Oldest":"Newest"}</button>`:""}${J}${I?`<button class="ib sm newi" title="New idea" aria-label="New idea">${E("plus")}</button>`:""}`;if(G&&Lt)fe+=`<span class="pickbar"><button class="btn sm ghost" data-p="cancel">Cancel</button><button class="btn sm pri" data-p="go" ${ke.size?"":"disabled"}>Archive ${ke.size||""}</button></span>`;else if(G)fe+='<button class="btn sm ghost clear" title="Archive finished runs">Clear ▾</button>';if(G&&a.clearMenu)fe+=`<div class="menu-pop clear-pop"><button data-c="7">Older than a week <i>${x(7).length}</i></button><button data-c="3">Older than 3 days <i>${x(3).length}</i></button><button data-c="0">Everything <i>${q.length}</i></button><hr><button data-c="pick">Pick which…</button></div>`;if(p.innerHTML=fe+"</h2>",I){p.querySelectorAll("[data-t]").forEach((R)=>R.onclick=()=>{St=R.dataset.t,a.sevMenu=!1;try{localStorage.setItem("kz-ideas-tab",St)}catch(M){}H()});let L=p.querySelector("[data-sv]");if(L)L.onclick=(R)=>{R.stopPropagation(),a.sevMenu=!a.sevMenu,H()};p.querySelectorAll("[data-s]").forEach((R)=>R.onclick=(M)=>{M.stopPropagation(),He=R.dataset.s||null,a.sevMenu=!1,H()})}{let L=p.querySelector(".ord");if(L)L.onclick=(R)=>{R.stopPropagation(),xt[w]=xt[w]==="old"?"new":"old";try{localStorage.setItem("kz-order",JSON.stringify(xt))}catch(M){}H()}}if(I)p.querySelector(".newi").onclick=()=>{a.mode="new",St="ideas",H()};if(G){let L=p.querySelector(".clear");if(L)L.onclick=(R)=>{R.stopPropagation(),a.clearMenu=!a.clearMenu,H()};p.querySelectorAll("[data-c]").forEach((R)=>R.onclick=async(M)=>{M.stopPropagation(),a.clearMenu=!1;let O=R.dataset.c;if(O==="pick"){Lt=!0,ke.clear(),H();return}let K=x(+O);if(!K.length){C("Nothing that old"),H();return}for(let Z of K)await T("/archive",{dir:Z.state,id:Z.id});C("Archived "+K.length),N()}),p.querySelectorAll("[data-p]").forEach((R)=>R.onclick=async(M)=>{if(M.stopPropagation(),R.dataset.p==="cancel"){Lt=!1,ke.clear(),H();return}let O=q.filter((K)=>ke.has(D(K)));Lt=!1,ke.clear();for(let K of O)await T("/archive",{dir:K.state,id:K.id});C("Archived "+O.length),N()})}let Y=document.createElement("ul");if(w===0&&a.mode==="new"){let L=document.createElement("li");L.className="inl",Y.appendChild(L),ks(L,()=>{a.mode=null,H()})}let ae=Qt.has(w)||q.length<=yn+1?q:q.slice(0,yn);if(ae.forEach((L)=>{if(a.modeKey===D(L)&&a.mode&&a.mode!=="new"){Y.appendChild(yo(L));return}let R=document.createElement("li");R.appendChild(bo(L)),Y.appendChild(R)}),ae.length<q.length){let L=document.createElement("li");L.innerHTML=`<button class="more-btn">Show ${q.length-ae.length} more</button>`,L.firstChild.onclick=()=>{Qt.add(w),H()},Y.appendChild(L)}else if(Qt.has(w)&&q.length>yn+1){let L=document.createElement("li");L.innerHTML='<button class="more-btn">Show less</button>',L.firstChild.onclick=()=>{Qt.delete(w),H()},Y.appendChild(L)}if(!q.length&&w>=1&&w<=3&&n.length&&!Se&&!v&&!te)Y.innerHTML=`<li class="hint">${ko[w]}</li>`;if(k&&!q.length&&!Se&&!v)Y.innerHTML=`<li class="hint">${He?"Nothing at this severity":"What finished runs left undone shows here"}</li>`;p.appendChild(Y),i.appendChild(p)});let g=a.S.cards.filter((b)=>!b.archived&&(b.kind==="run"&&b.status==="waiting"||b.pty?.alive&&b.pty.asking)).length;if(document.title=g?`(${g}) kaizen`:"kaizen",fn(),de(!1),e&&document.activeElement===document.body)qn(e)?.focus({preventScroll:!0})}function ws(){let e=s("bq");We(e,"bq"),xn=e.value,e.addEventListener("input",()=>{xn=e.value,H()}),e.addEventListener("keydown",(t)=>{if(t.key==="Escape")t.stopPropagation(),e.value="",e.dispatchEvent(new Event("input")),e.blur()})}function $s(){let e=s("fbtn"),t=document.querySelector(".ftr"),n=(i)=>{if(t.classList.toggle("on",i),e.setAttribute("aria-expanded",i),i)t.style.top=e.getBoundingClientRect().bottom+6+"px"};e.onclick=()=>n(!t.classList.contains("on")),document.addEventListener("pointerdown",(i)=>{if(t.classList.contains("on")&&!t.contains(i.target)&&!e.contains(i.target))n(!1)}),document.addEventListener("keydown",(i)=>i.key==="Escape"&&t.classList.contains("on")&&n(!1))}var Ln=()=>document.activeElement?.closest?.("#board .card")?.dataset.k,qn=(e)=>e&&s("board").querySelector('.card[data-k="'+CSS.escape(e)+'"]');function xs(e,t){let n=[...s("board").querySelectorAll("section")].map((c)=>[...c.querySelectorAll(".card")]).filter((c)=>c.length);if(!n.length)return;let i=document.activeElement.closest(".card"),r=n.findIndex((c)=>c.includes(i)),d=0;if(r<0)r=0;else if(d=n[r].indexOf(i),t)d=Math.max(0,Math.min(n[r].length-1,d+t));else r=Math.max(0,Math.min(n.length-1,r+e)),d=Math.min(d,n[r].length-1);let u=n[r][d];u.focus({preventScroll:!0}),u.scrollIntoView({block:"nearest",inline:"nearest"})}var En=null,Cn=null,Ls=()=>a.dir?{"x-kz-dir":a.dir}:{};async function N(e){let t;try{t=await fetch("/state"+(a.all?"?all=1":""),{headers:Ls()})}catch{C(qs);return}let n=a.openKey&&a.S.cards.find((u)=>D(u)===a.openKey);a.S=await t.json();{let u=new Map;for(let c of a.S.cards){let m=D(c),f=u.get(m)||0;u.set(m,f+1),c._k=f?m+"#"+f:m}}for(let u of a.S.cards){if(u.kind!=="run"||u.archived)continue;if(due(D(u),u.notice,u.status==="done",a.S.now))on(u.notice)}{let u=new Map(a.S.cards.filter((c)=>!c.archived&&c.pty?.alive&&c.pty.asking).map((c)=>[c.pty.key,c]));if(En&&document.hidden){for(let[c,m]of u)if(!En.has(c))on(`${m.kind==="run"?m.id:String(m.text).split(`
|
package/web/notebook.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* kaizen notebook
|
|
1
|
+
/* kaizen notebook c24cf970db99487d -- generated by bun run build:web from web/notebook.ts; do not edit */
|
|
2
2
|
var Ss=[],ua=[];(()=>{let e="lc,34,7n,7,7b,19,,,,2,,2,,,20,b,1c,l,g,,2t,7,2,6,2,2,,4,z,,u,r,2j,b,1m,9,9,,o,4,,9,,3,,5,17,3,1n,9,16,o,,x,1i,3,,i,,7,a,2,t,3,1k,,,7,2,2,2,3,9,,a,2,q,,2,3,1k,,,5,4,2,2,3,3,,u,2,3,,b,3,1k,,,8,,3,,3,k,2,m,6,,3,1k,,,7,2,2,2,3,7,3,a,2,u,,1n,5,3,3,,4,9,,14,5,1j,,,7,,3,,4,7,2,b,2,t,3,1k,,,7,,3,,4,7,2,b,2,f,,c,4,1j,2,,7,,3,,4,9,,a,2,t,3,1y,,4,6,,,,8,i,2,1p,,,8,c,8,2q,,,a,b,7,21,2,r,,,,,,4,2,1d,k,,2,5,b,,10,9,,2u,b,,6,n,4,4,3,g,4,d,,,3,6,,f,,jj,3,qa,4,s,3,t,2,u,2,1s,w,9,,19,3,,,39,2,y,,3a,c,4,c,63,5,1l,a,,,,,2,o,2,,1c,1a,2,c,k,5,1b,h,12,9,c,3,u,d,1k,e,1c,k,48,3,,l,4,,6,,2,3,5i,1s,ek,,5f,x,2da,3,3x,,2o,w,fe,6,2x,2,n9w,4,,a,w,2,28,2,7k,,3,,4,,n,5,4,,2b,2,1e,i,q,i,d,,12,8,p,d,18,4,1b,e,10,,1v,e,c,,8,2,1a,,1f,,,3,2,2,5,2,,,15,5,5,2,6k,8,,2,fn4,,kh,g,g,g,a6,2,gt,,6a,,45,5,1ae,3,,2,5,4,14,3,4,,4l,2,fx,4,1t,5,8t,2,25,6,1y,b,1d,4,3e,3,1h,f,15,,2,2,a,4,19,b,7,,1p,3,10,e,g,2,18,,c,3,1c,e,8,4,,2,2k,c,6,,2,,4d,c,l,4,1j,2,,7,2,2,2,3,9,,a,2,2,7,3,5,1v,9,,,2,,,4,,5,,,e,2,2a,i,n,,29,k,6j,7,2,9,r,2,2a,h,2y,d,2t,3,2,a,74,f,6t,6,,2,2,4,,,,2,3x,7,2,7,3,,s,a,14,7,,4,8,,9,b,1a,g,5i,8,5j,8,,8,2a,m,,e,3e,6,3,,,2,,7,,,1u,5,,2,,5,9n,4,9,2,,,1c,7,3,5,n,,44l,,6,f,8ug,i,1xc,5,1n,7,t4,,,1j,7,4,29,,b,2,f57,2,3mp,1a,2,n,f2,5,3,6,8,8,2,7,u,4,44,3,1iz,1j,4,1e,8,,e,,m,5,,f,11s,7,,h,2,7,,2,,5,2s,,4g,7,af,,1p,4,e4,4,72,2,6r,,2,,7,2,5,,d6,7,31,7,240,5".split(",").map((t)=>t?parseInt(t,36):1);for(let t=0,i=0;t<e.length;t++)(t%2?ua:Ss).push(i=i+e[t])})();function op(e){if(e<768)return!1;for(let t=0,i=Ss.length;;){let n=t+i>>1;if(e<Ss[n])i=n;else if(e>=ua[n])t=n+1;else return!0;if(t==i)return!1}}function ha(e){return e>=127462&&e<=127487}var fa=8205;function da(e,t,i=!0,n=!0){return(i?Oa:lp)(e,t,n)}function Oa(e,t,i){if(t==e.length)return t;if(t&&pa(e.charCodeAt(t))&&ma(e.charCodeAt(t-1)))t--;let n=bs(e,t);t+=ca(n);while(t<e.length){let r=bs(e,t);if(n==fa||r==fa||i&&op(r))t+=ca(r),n=r;else if(ha(r)){let s=0,o=t-2;while(o>=0&&ha(bs(e,o)))s++,o-=2;if(s%2==0)break;else t+=2}else break}return t}function lp(e,t,i){while(t>1){let n=Oa(e,t-2,i);if(n<t)return n;t--}return 0}function bs(e,t){let i=e.charCodeAt(t);if(!ma(i)||t+1==e.length)return i;let n=e.charCodeAt(t+1);if(!pa(n))return i;return(i-55296<<10)+(n-56320)+65536}function pa(e){return e>=56320&&e<57344}function ma(e){return e>=55296&&e<56320}function ca(e){return e<65536?1:2}class _{lineAt(e){if(e<0||e>this.length)throw RangeError(`Invalid position ${e} in document of length ${this.length}`);return this.lineInner(e,!1,1,0)}line(e){if(e<1||e>this.lines)throw RangeError(`Invalid line number ${e} in ${this.lines}-line document`);return this.lineInner(e,!0,1,0)}replace(e,t,i){[e,t]=vi(this,e,t);let n=[];if(this.decompose(0,e,n,2),i.length)i.decompose(0,i.length,n,3);return this.decompose(t,this.length,n,1),ft.from(n,this.length-(t-e)+i.length)}append(e){return this.replace(this.length,this.length,e)}slice(e,t=this.length){[e,t]=vi(this,e,t);let i=[];return this.decompose(e,t,i,0),ft.from(i,t-e)}eq(e){if(e==this)return!0;if(e.length!=this.length||e.lines!=this.lines)return!1;let t=this.scanIdentical(e,1),i=this.length-this.scanIdentical(e,-1),n=new wi(this),r=new wi(e);for(let s=t,o=t;;){if(n.next(s),r.next(s),s=0,n.lineBreak!=r.lineBreak||n.done!=r.done||n.value!=r.value)return!1;if(o+=n.value.length,n.done||o>=i)return!0}}iter(e=1){return new wi(this,e)}iterRange(e,t=this.length){return new Ts(this,e,t)}iterLines(e,t){let i;if(e==null)i=this.iter();else{if(t==null)t=this.lines+1;let n=this.line(e).from;i=this.iterRange(n,Math.max(n,t==this.lines+1?this.length:t<=1?0:this.line(t-1).to))}return new As(i)}toString(){return this.sliceString(0)}toJSON(){let e=[];return this.flatten(e),e}constructor(){}static of(e){if(e.length==0)throw RangeError("A document must have at least one line");if(e.length==1&&!e[0])return _.empty;return e.length<=32?new oe(e):ft.from(oe.split(e,[]))}}class oe extends _{constructor(e,t=ap(e)){super();this.text=e,this.length=t}get lines(){return this.text.length}get children(){return null}lineInner(e,t,i,n){for(let r=0;;r++){let s=this.text[r],o=n+s.length;if((t?i:o)>=e)return new ka(n,o,i,s);n=o+1,i++}}decompose(e,t,i,n){let r=e<=0&&t>=this.length?this:new oe(ga(this.text,e,t),Math.min(t,this.length)-Math.max(0,e));if(n&1){let s=i.pop(),o=cr(r.text,s.text.slice(),0,r.length);if(o.length<=32)i.push(new oe(o,s.length+r.length));else{let l=o.length>>1;i.push(new oe(o.slice(0,l)),new oe(o.slice(l)))}}else i.push(r)}replace(e,t,i){if(!(i instanceof oe))return super.replace(e,t,i);[e,t]=vi(this,e,t);let n=cr(this.text,cr(i.text,ga(this.text,0,e)),t),r=this.length+i.length-(t-e);if(n.length<=32)return new oe(n,r);return ft.from(oe.split(n,[]),r)}sliceString(e,t=this.length,i=`
|
|
3
3
|
`){[e,t]=vi(this,e,t);let n="";for(let r=0,s=0;r<=t&&s<this.text.length;s++){let o=this.text[s],l=r+o.length;if(r>e&&s)n+=i;if(e<l&&t>r)n+=o.slice(Math.max(0,e-r),t-r);r=l+1}return n}flatten(e){for(let t of this.text)e.push(t)}scanIdentical(){return 0}static split(e,t){let i=[],n=-1;for(let r of e)if(i.push(r),n+=r.length+1,i.length==32)t.push(new oe(i,n)),i=[],n=-1;if(n>-1)t.push(new oe(i,n));return t}}class ft extends _{constructor(e,t){super();this.children=e,this.length=t,this.lines=0;for(let i of e)this.lines+=i.lines}lineInner(e,t,i,n){for(let r=0;;r++){let s=this.children[r],o=n+s.length,l=i+s.lines-1;if((t?l:o)>=e)return s.lineInner(e,t,i,n);n=o+1,i=l+1}}decompose(e,t,i,n){for(let r=0,s=0;s<=t&&r<this.children.length;r++){let o=this.children[r],l=s+o.length;if(e<=l&&t>=s){let a=n&((s<=e?1:0)|(l>=t?2:0));if(s>=e&&l<=t&&!a)i.push(o);else o.decompose(e-s,t-s,i,a)}s=l+1}}replace(e,t,i){if([e,t]=vi(this,e,t),i.lines<this.lines)for(let n=0,r=0;n<this.children.length;n++){let s=this.children[n],o=r+s.length;if(e>=r&&t<=o){let l=s.replace(e-r,t-r,i),a=this.lines-s.lines+l.lines;if(l.lines<a>>4&&l.lines>a>>6){let h=this.children.slice();return h[n]=l,new ft(h,this.length-(t-e)+i.length)}return super.replace(r,o,l)}r=o+1}return super.replace(e,t,i)}sliceString(e,t=this.length,i=`
|
|
4
4
|
`){[e,t]=vi(this,e,t);let n="";for(let r=0,s=0;r<this.children.length&&s<=t;r++){let o=this.children[r],l=s+o.length;if(s>e&&r)n+=i;if(e<l&&t>s)n+=o.sliceString(e-s,t-s,i);s=l+1}return n}flatten(e){for(let t of this.children)t.flatten(e)}scanIdentical(e,t){if(!(e instanceof ft))return 0;let i=0,[n,r,s,o]=t>0?[0,0,this.children.length,e.children.length]:[this.children.length-1,e.children.length-1,-1,-1];for(;;n+=t,r+=t){if(n==s||r==o)return i;let l=this.children[n],a=e.children[r];if(l!=a)return i+l.scanIdentical(a,t);i+=l.length+1}}static from(e,t=e.reduce((i,n)=>i+n.length+1,-1)){let i=0;for(let u of e)i+=u.lines;if(i<32){let u=[];for(let d of e)d.flatten(u);return new oe(u,t)}let n=Math.max(32,i>>5),r=n<<1,s=n>>1,o=[],l=0,a=-1,h=[];function f(u){let d;if(u.lines>r&&u instanceof ft)for(let O of u.children)f(O);else if(u.lines>s&&(l>s||!l))c(),o.push(u);else if(u instanceof oe&&l&&(d=h[h.length-1])instanceof oe&&u.lines+d.lines<=32)l+=u.lines,a+=u.length+1,h[h.length-1]=new oe(d.text.concat(u.text),d.length+1+u.length);else{if(l+u.lines>n)c();l+=u.lines,a+=u.length+1,h.push(u)}}function c(){if(l==0)return;o.push(h.length==1?h[0]:ft.from(h,a)),a=-1,l=h.length=0}for(let u of e)f(u);return c(),o.length==1?o[0]:new ft(o,t)}}_.empty=new oe([""],0);function ap(e){let t=-1;for(let i of e)t+=i.length+1;return t}function cr(e,t,i=0,n=1e9){for(let r=0,s=0,o=!0;s<e.length&&r<=n;s++){let l=e[s],a=r+l.length;if(a>=i){if(a>n)l=l.slice(0,n-r);if(r<i)l=l.slice(i-r);if(o)t[t.length-1]+=l,o=!1;else t.push(l)}r=a+1}return t}function ga(e,t,i){return cr(e,[""],t,i)}class wi{constructor(e,t=1){this.dir=t,this.done=!1,this.lineBreak=!1,this.value="",this.nodes=[e],this.offsets=[t>0?1:(e instanceof oe?e.text.length:e.children.length)<<1]}nextInner(e,t){this.done=this.lineBreak=!1;for(;;){let i=this.nodes.length-1,n=this.nodes[i],r=this.offsets[i],s=r>>1,o=n instanceof oe?n.text.length:n.children.length;if(s==(t>0?o:0)){if(i==0)return this.done=!0,this.value="",this;if(t>0)this.offsets[i-1]++;this.nodes.pop(),this.offsets.pop()}else if((r&1)==(t>0?0:1)){if(this.offsets[i]+=t,e==0)return this.lineBreak=!0,this.value=`
|
package/web/notes.html
CHANGED
|
@@ -220,6 +220,7 @@ select.sel{cursor:pointer;appearance:none;padding-right:30px;max-width:min(320px
|
|
|
220
220
|
<symbol id="i-inbox" viewBox="0 0 24 24"><path d="M22 12h-6l-2 3h-4l-2-3H2"/><path d="M5.5 5.1L2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.5-6.9A2 2 0 0 0 16.8 4H7.2a2 2 0 0 0-1.7 1.1z"/></symbol>
|
|
221
221
|
<symbol id="i-link" viewBox="0 0 24 24"><path d="M10 13a5 5 0 0 0 7.1.4l3-3a5 5 0 0 0-7.1-7.1l-1.7 1.7M14 11a5 5 0 0 0-7.1-.4l-3 3a5 5 0 0 0 7.1 7.1l1.7-1.7"/></symbol>
|
|
222
222
|
<symbol id="i-note" viewBox="0 0 24 24"><path d="M6 3h9l4 4v14H6z"/><path d="M14 3v5h5M9 13h6M9 17h6"/></symbol>
|
|
223
|
+
<symbol id="i-video" viewBox="0 0 24 24"><rect x="3" y="6" width="13" height="12" rx="2"/><path d="M16 10.5l5-3v9l-5-3z"/></symbol>
|
|
223
224
|
<symbol id="i-board" viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="16" rx="2"/><path d="M9 4v16M15 4v16"/></symbol>
|
|
224
225
|
<symbol id="i-side" viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="16" rx="2"/><path d="M9 4v16"/></symbol>
|
|
225
226
|
<symbol id="i-sun" viewBox="0 0 24 24"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"/></symbol>
|
|
@@ -242,6 +243,7 @@ select.sel{cursor:pointer;appearance:none;padding-right:30px;max-width:min(320px
|
|
|
242
243
|
<a class="it" href="/?view=icebox" data-view="sources" title="Icebox: requests gathered from your sources"><svg><use href="#i-inbox"/></svg><span class="lbl">Icebox</span></a>
|
|
243
244
|
<a class="it" href="/" data-view="board" title="Board"><svg><use href="#i-board"/></svg><span class="lbl">Board</span></a>
|
|
244
245
|
<a class="it" href="/notebook" data-view="notes" title="Notes"><svg><use href="#i-note"/></svg><span class="lbl">Notes</span></a>
|
|
246
|
+
<a class="it" href="/video" data-view="video" title="Video: make and edit videos"><svg><use href="#i-video"/></svg><span class="lbl">Video</span></a>
|
|
245
247
|
<a class="it" href="/?view=terminal" data-view="terminal" title="Terminal: every agent running in its card"><svg><use href="#i-term"/></svg><span class="lbl">Terminal</span></a>
|
|
246
248
|
<a class="it" href="/?view=settings" data-view="settings" title="Settings"><svg><use href="#i-gear"/></svg><span class="lbl">Settings</span></a>
|
|
247
249
|
<span class="end"></span>
|