@sma1lboy/rove 0.9.253 → 0.9.256
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/{chunk-xmf4053m.js → chunk-09v8w5jq.js} +1 -1
- package/dist/cli/{chunk-sncjkw3g.js → chunk-0yyvfpcg.js} +3 -3
- package/dist/cli/{chunk-t6j3pmpp.js → chunk-18dpws0y.js} +1 -1
- package/dist/cli/{chunk-19h18xca.js → chunk-1e6jbj70.js} +1 -1
- package/dist/cli/{chunk-avdg2rrh.js → chunk-1s8ctwmv.js} +1 -1
- package/dist/cli/{chunk-97vsqj97.js → chunk-372yekdz.js} +1 -1
- package/dist/cli/{chunk-g3wdrhxk.js → chunk-3aecx6za.js} +2 -2
- package/dist/cli/{chunk-yq99x0r6.js → chunk-3r8v2gza.js} +1 -1
- package/dist/cli/chunk-3vq0ywzf.js +3 -0
- package/dist/cli/{chunk-rm2wy5hf.js → chunk-3x0hyz6y.js} +3 -3
- package/dist/cli/{chunk-mrtfvgb2.js → chunk-4mxn5jg6.js} +1 -1
- package/dist/cli/{chunk-zy20hzvh.js → chunk-5a6b4kv9.js} +1 -1
- package/dist/cli/{chunk-bdvqjzwh.js → chunk-5csm9ffj.js} +9 -7
- package/dist/cli/{chunk-3j1x55tc.js → chunk-5d0vb6v9.js} +1 -1
- package/dist/cli/{chunk-c3d36ryd.js → chunk-5j6z32fh.js} +1 -1
- package/dist/cli/{chunk-8je3dmzq.js → chunk-5s4g1bkx.js} +1 -1
- package/dist/cli/{chunk-34vpdm19.js → chunk-6d5csfp4.js} +1 -1
- package/dist/cli/{chunk-vcq9hb2a.js → chunk-73chbrb4.js} +1 -1
- package/dist/cli/chunk-7wga6bet.js +8 -0
- package/dist/cli/{chunk-nhpadsbv.js → chunk-7yb48mar.js} +1 -1
- package/dist/cli/{chunk-2nfz06mq.js → chunk-7zpkyrxy.js} +1 -1
- package/dist/cli/{chunk-ffjwgbck.js → chunk-80zzjcvp.js} +1 -1
- package/dist/cli/{chunk-wq6pfbek.js → chunk-8vh57pq0.js} +2 -2
- package/dist/cli/{chunk-3r4ekafa.js → chunk-8wf3p9er.js} +1 -1
- package/dist/cli/chunk-9g0vz9dk.js +209 -0
- package/dist/cli/{chunk-6e54q8g5.js → chunk-9qny0zke.js} +1 -1
- package/dist/cli/{chunk-epyw87gt.js → chunk-adkk89dp.js} +1 -1
- package/dist/cli/{chunk-ad5gbdcf.js → chunk-ant4k6dm.js} +1 -1
- package/dist/cli/{chunk-6k424rbf.js → chunk-bampejxv.js} +1 -1
- package/dist/cli/{chunk-76adkzyf.js → chunk-btpp4geb.js} +1 -1
- package/dist/cli/chunk-c9xg9dn0.js +3 -0
- package/dist/cli/{chunk-pcyatg4b.js → chunk-ccqs21dj.js} +1 -1
- package/dist/cli/{chunk-814ktvx2.js → chunk-cqdebtbr.js} +1 -1
- package/dist/cli/{chunk-2bmebw8q.js → chunk-d4mvprvq.js} +1 -1
- package/dist/cli/{chunk-dk0hffvd.js → chunk-dqprpnd6.js} +1 -1
- package/dist/cli/chunk-edsm15ht.js +4 -0
- package/dist/cli/{chunk-rpm771v5.js → chunk-ekre1aps.js} +8 -8
- package/dist/cli/chunk-em6vwq07.js +2 -0
- package/dist/cli/{chunk-vjvkkrzc.js → chunk-f5n0tgky.js} +1 -1
- package/dist/cli/chunk-fhrs8ja3.js +2 -0
- package/dist/cli/{chunk-y33j54yr.js → chunk-fnsch8kr.js} +2 -2
- package/dist/cli/{chunk-mw35vd6g.js → chunk-fvksjtsk.js} +1 -1
- package/dist/cli/{chunk-tq1hrd9n.js → chunk-ggzfard0.js} +1 -1
- package/dist/cli/{chunk-x2c8f2qz.js → chunk-gpcxqdmq.js} +1 -1
- package/dist/cli/{chunk-hbq7nqnp.js → chunk-h0h51emh.js} +1 -1
- package/dist/cli/{chunk-0x7zcw52.js → chunk-hkyn3kme.js} +1 -1
- package/dist/cli/{chunk-p8d9va1w.js → chunk-hqp8b49k.js} +2 -2
- package/dist/cli/{chunk-yjk0465m.js → chunk-hzzq6pdb.js} +1 -1
- package/dist/cli/{chunk-s21t29qn.js → chunk-j7831wcj.js} +1 -1
- package/dist/cli/{chunk-67q0qw7z.js → chunk-jetsx9zr.js} +1 -1
- package/dist/cli/{chunk-q349ydch.js → chunk-jtpjdmb6.js} +1 -1
- package/dist/cli/{chunk-c4e149yb.js → chunk-jwtqe209.js} +1 -1
- package/dist/cli/{chunk-gt1vbz3f.js → chunk-k7ke95vy.js} +1 -1
- package/dist/cli/{chunk-6r84zkcz.js → chunk-ksk3j88n.js} +1 -1
- package/dist/cli/{chunk-mwm63vz3.js → chunk-m3pn99w9.js} +8 -8
- package/dist/cli/{chunk-xgq5ycyn.js → chunk-mk1xzp2k.js} +1 -1
- package/dist/cli/{chunk-02h0488p.js → chunk-mvsvmfsf.js} +1 -1
- package/dist/cli/{chunk-hqzgejfj.js → chunk-p5902z3e.js} +1 -1
- package/dist/cli/{chunk-q1e0qqmd.js → chunk-pahcf9td.js} +1 -1
- package/dist/cli/{chunk-9wkf17yd.js → chunk-pfx1tg6q.js} +1 -1
- package/dist/cli/{chunk-8wze6dnr.js → chunk-ptaj848y.js} +1 -1
- package/dist/cli/chunk-pw10r9fk.js +2 -0
- package/dist/cli/{chunk-b1mk33gy.js → chunk-pw1twn8f.js} +1 -1
- package/dist/cli/{chunk-k8dm013e.js → chunk-q800jxzk.js} +1 -1
- package/dist/cli/{chunk-v9avfsxq.js → chunk-q9f24pkx.js} +1 -1
- package/dist/cli/{chunk-6ygwq4w5.js → chunk-rc2nwsdd.js} +1 -1
- package/dist/cli/{chunk-zmw0v18d.js → chunk-rf4z7b6g.js} +1 -1
- package/dist/cli/{chunk-jbqpyp76.js → chunk-rnxk3587.js} +1 -1
- package/dist/cli/chunk-rzd7xpx2.js +30 -0
- package/dist/cli/{chunk-pwybgztt.js → chunk-s96qnht3.js} +1 -1
- package/dist/cli/{chunk-jk9b9ztf.js → chunk-se20ckc5.js} +1 -1
- package/dist/cli/chunk-sma961wh.js +3 -0
- package/dist/cli/{chunk-b18pnmsv.js → chunk-stcvcsfm.js} +1 -1
- package/dist/cli/{chunk-hm7t9gkb.js → chunk-tewt7vre.js} +1 -1
- package/dist/cli/{chunk-b3j5s2jb.js → chunk-tq6pq1ws.js} +1 -1
- package/dist/cli/{chunk-3dgghmjv.js → chunk-v7prawj1.js} +1 -1
- package/dist/cli/chunk-vbv6v4hs.js +52 -0
- package/dist/cli/chunk-vfwbgx85.js +2 -0
- package/dist/cli/{chunk-qc06psqb.js → chunk-vvw1njx5.js} +1 -1
- package/dist/cli/{chunk-7hkkjx6g.js → chunk-vydwyjz2.js} +1 -1
- package/dist/cli/{chunk-sk3h2pzj.js → chunk-w9grtqm8.js} +2 -2
- package/dist/cli/{chunk-dkb8nj75.js → chunk-wy5xx1ez.js} +1 -1
- package/dist/cli/{chunk-65tbvcjj.js → chunk-xd4qfcm6.js} +1 -1
- package/dist/cli/{chunk-p98w5ffk.js → chunk-y330t2bt.js} +2 -2
- package/dist/cli/{chunk-bq0xsdqx.js → chunk-y4vxge6s.js} +1 -1
- package/dist/cli/{chunk-bk4pfjs0.js → chunk-ypzac0kj.js} +1 -1
- package/dist/cli/{chunk-mt8vtz20.js → chunk-z41s748k.js} +2 -2
- package/dist/cli/index.js +4 -4
- package/dist/cli/pty-host-node.mjs +5 -2
- package/dist/cli/rove.js +4 -4
- package/dist/completions/rove.bash +1 -1
- package/dist/completions/rove.fish +1 -1
- package/dist/completions/rove.zsh +1 -1
- package/dist/skills/rove/SKILL.md +14 -3
- package/dist/skills/rove/references/api-flags.md +47 -32
- package/dist/web/assets/{index-DmRZRttZ.js → index-BydepNFM.js} +1 -1
- package/dist/web/index.html +1 -1
- package/dist/web-ui/assets/{harness-BHiciz5A.js → harness-dYkQBfYz.js} +3 -3
- package/dist/web-ui/assets/{index-BkxJISAI.js → index-ByMdqeTv.js} +2 -2
- package/dist/web-ui/index.html +1 -1
- package/package.json +6 -4
- package/dist/cli/chunk-75zg2k73.js +0 -3
- package/dist/cli/chunk-9g7gneek.js +0 -30
- package/dist/cli/chunk-9jbcfrse.js +0 -2
- package/dist/cli/chunk-9r6x8mh4.js +0 -8
- package/dist/cli/chunk-admwmjjy.js +0 -4
- package/dist/cli/chunk-cgy92ks5.js +0 -2
- package/dist/cli/chunk-n7dtvega.js +0 -2
- package/dist/cli/chunk-parvvj8h.js +0 -2
- package/dist/cli/chunk-r2pd9tv9.js +0 -3
- package/dist/cli/chunk-sb2xg6py.js +0 -5
- package/dist/cli/chunk-vx4e787s.js +0 -3
- package/dist/cli/chunk-zfjqy7hp.js +0 -52
|
@@ -10,7 +10,7 @@ Error generating stack: `+e.message+`
|
|
|
10
10
|
`)}`}async function Qn(e){let t=new Uint8Array(await e.arrayBuffer()),n=``;for(let e=0;e<t.length;e+=32768)n+=String.fromCharCode(...t.subarray(e,e+32768));return btoa(n)}function $n(e,t){let[n,r]=(0,m.useState)([]);return{attachments:n,attach:async n=>{for(let i of n)if(Xn.includes(i.type))try{let t=await e.client.request(`attachment.put`,{mime:i.type,data:await Qn(i)});r(e=>[...e,{path:t.path,kind:t.kind,name:i.name||t.path}])}catch(e){t(e instanceof Error?e.message:String(e))}},remove:e=>r(t=>t.filter(t=>t.path!==e))}}function er(e){return e.attachments.length===0?null:(0,z.jsx)(`div`,{className:`chips-row`,"data-field":`attachments`,children:e.attachments.map((t,n)=>(0,z.jsxs)(`button`,{type:`button`,className:`chip-button is-active`,title:t.path,onClick:()=>e.onRemove(t.path),children:[t.kind===`pdf`?`pdf`:`images`,`[`,n,`] ×`]},t.path))})}function tr(e){let t=(0,m.useRef)(null),n=(0,m.useRef)(e.value);n.current=e.value;let r=(r,i)=>{r.preventDefault();let a=e.choices.findIndex(e=>e.id===n.current),o=e.choices[(a+i+e.choices.length)%e.choices.length];o&&(n.current=o.id,e.onChange(o.id),requestAnimationFrame(()=>t.current?.querySelector(`[aria-pressed=true]`)?.focus()))};return(0,z.jsx)(`div`,{ref:t,className:`chips-row`,"aria-label":e.label,"data-field":e.field,onKeyDown:t=>{t.ctrlKey||t.metaKey||t.altKey||e.choices.length===0||(t.key===`ArrowRight`||t.key===`l`?r(t,1):(t.key===`ArrowLeft`||t.key===`h`)&&r(t,-1))},children:e.choices.map(t=>(0,z.jsxs)(`button`,{type:`button`,"aria-pressed":t.id===e.value,tabIndex:t.id===e.value||!e.choices.some(t=>t.id===e.value)?0:-1,className:`chip-button ${t.id===e.value?`is-active`:``}`,title:t.title,onClick:()=>e.onChange(t.id),children:[t.label,t.dim&&(0,z.jsx)(`span`,{className:`muted`,children:` ·`})]},t.id))})}function nr(e,t){let n=e.querySelector(`[data-field="${t}"]`);(n?.matches(`input, textarea`)?n:n?.querySelector(`[tabindex='0']`))?.focus()}function rr(e,t,n){let r=document.activeElement?.closest(`[data-field]`)?.getAttribute(`data-field`),i=t.findIndex(e=>e===r),a=t[i<0?0:(i+n+t.length)%t.length];a&&nr(e,a)}var ir=[`1`,`2`,`3`,`4`,`5`],ar=[`message`,`attempts`,`engine`,`base`];function or(e){let{model:t,start:n,engines:r}=e,[i,a]=(0,m.useState)(``),[o,s]=(0,m.useState)(`1`),[c,l]=(0,m.useState)(n.engine),[u,d]=(0,m.useState)(n.baseRef),{busy:f,error:p,setError:h,submit:g}=ae(),{attachments:_,attach:v,remove:y}=$n(t,h),b=()=>{let e=r.findIndex(e=>e.id===c),t=r[(e+1)%r.length];t&&l(t.id)},x=()=>g(async()=>{if(i.trim().length===0)throw document.querySelector(`[data-field=message]`)?.focus(),Error(V(`quickTask`,`promptPlaceholder`));let e=Number(o),r=await t.client.request(`task.spawn`,{repo:n.repo,engine:c,baseBranch:u.trim()||n.baseRef,prompt:Zn(i.trim(),_),...e>1?{count:e}:{}});e>1&&L(V(`quickTask`,`startedRound`,{count:r.taskIds.length}));let a=r.taskIds[0];a&&t.selectWhenListed(a)});return(0,z.jsx)(ie,{title:V(`quickTask`,`title`,{repoLabel:n.label}),wide:!0,children:(0,z.jsxs)(`form`,{className:`dialog-body`,onKeyDown:e=>{if(e.key===`Tab`&&!e.ctrlKey&&!e.metaKey&&!e.altKey)e.preventDefault(),rr(e.currentTarget,ar,e.shiftKey?-1:1);else if(e.ctrlKey&&!e.metaKey&&!e.altKey&&e.key.toLowerCase()===`e`)e.preventDefault(),e.stopPropagation(),b();else if(e.ctrlKey&&!e.metaKey&&!e.altKey&&e.key.toLowerCase()===`x`){e.preventDefault();let t=_.at(-1);t&&y(t.path)}else e.key===`Enter`&&!e.shiftKey&&e.target.closest(`[data-field=attempts], [data-field=engine]`)&&(e.preventDefault(),e.currentTarget.requestSubmit())},onSubmit:e=>{e.preventDefault(),x()},onDragOver:e=>e.preventDefault(),onDrop:e=>{e.preventDefault(),v(Array.from(e.dataTransfer.files))},children:[(0,z.jsx)(`p`,{className:`muted`,children:V(`onboarding`,`quickIntent`,{key:$e(`task.new.global`)})}),(0,z.jsxs)(`label`,{className:`field`,children:[(0,z.jsx)(`span`,{className:`kicker`,children:V(`quickTask`,`promptLabel`)}),(0,z.jsx)(`textarea`,{className:`input textarea`,"data-field":`message`,autoFocus:!0,rows:3,placeholder:V(`quickTask`,`promptPlaceholder`),value:i,onChange:e=>a(e.target.value),onPaste:e=>{let t=Array.from(e.clipboardData.files);t.length!==0&&(e.preventDefault(),v(t))},onKeyDown:e=>{e.key===`Enter`&&!e.shiftKey&&(e.preventDefault(),e.currentTarget.form?.requestSubmit())}})]}),(0,z.jsxs)(`div`,{className:`field`,children:[(0,z.jsx)(`span`,{className:`kicker`,children:V(`quickTask`,`attemptsLabel`)}),(0,z.jsx)(tr,{label:V(`quickTask`,`attemptsLabel`),field:`attempts`,value:o,onChange:s,choices:ir.map(e=>({id:e,label:e}))})]}),(0,z.jsxs)(`div`,{className:`field`,children:[(0,z.jsx)(`span`,{className:`kicker`,children:V(`quickTask`,`engineLabel`)}),(0,z.jsx)(tr,{label:V(`quickTask`,`engineLabel`),field:`engine`,value:c,onChange:l,choices:r.map(e=>({id:e.id,label:e.name}))})]}),(0,z.jsxs)(`label`,{className:`field`,children:[(0,z.jsx)(`span`,{className:`kicker`,children:V(`quickTask`,`branchLabel`)}),(0,z.jsx)(`input`,{className:`input`,"data-field":`base`,spellCheck:!1,value:u,onChange:e=>d(e.target.value)})]}),(0,z.jsx)(er,{attachments:_,onRemove:y}),(0,z.jsx)(`p`,{className:`muted newtask-legend`,children:V(`quickTask`,`legend`)}),p&&(0,z.jsx)(`p`,{className:`error`,children:p}),(0,z.jsx)(le,{busy:f,submitLabel:T(`newChat.start`)})]})})}function sr(e){let[t,n]=(0,m.useState)([]),[r,i]=(0,m.useState)(``);return(0,m.useEffect)(()=>{e.client.request(`engines.list`).then(e=>{n(e.engines),i((e.engines.find(e=>e.ready!==!1)??e.engines[0])?.id??``)}).catch(()=>n([]))},[e]),{engines:t,engine:r,setEngine:i}}var cr=`shell`,lr=`pane:`,ur=e=>e.startsWith(lr),dr=e=>e.slice(5);function fr(e){let[t,n]=(0,m.useState)([]);return(0,m.useEffect)(()=>{e.client.request(`plugin.panes`).then(e=>n(e.panes)).catch(()=>n([]))},[e]),t}function pr(e){let t=[...e.engines,...e.withShell?[{id:cr,name:T(`tab.shell`)}]:[],...(e.panes??[]).map(e=>({id:lr+e.id,name:e.title}))];return(0,z.jsx)(tr,{label:T(`newTask.engine`),field:`engine`,value:e.value,onChange:e.onChange,choices:t.map(e=>({id:e.id,label:e.name,dim:`ready`in e&&e.ready===!1,title:`ready`in e&&e.ready===!1?T(`newTask.notReady`):void 0}))})}async function mr(e,t,n){let{tabId:r}=await e.client.request(`tab.new`,{taskId:t,kind:n.kind,...n.engine?{engine:n.engine}:{},...n.prompt?{prompt:n.prompt}:{}});await e.refreshTabsNow(),e.select(t,r)}var hr=[`tab`,`fork`,`scratch`],gr=[`message`,`attempts`,`engine`,`fork-base`,`destination`];function _r(e){D();let{model:t,taskId:n}=e,r=sr(t),[i,a]=(0,m.useState)(e.destination??`tab`),[o,s]=(0,m.useState)(e.context??`fresh`),[c,l]=(0,m.useState)(``),[u,d]=(0,m.useState)(`1`),f=t.tasks.get()?.tasks.find(e=>e.id===n),[p,h]=(0,m.useState)(f?.branch??`main`),{busy:g,error:_,setError:v,submit:y}=ae(),{attachments:b,attach:x,remove:S}=$n(t,v),C=o===`fresh`&&i!==`fork`,w=i===`tab`&&o===`fresh`,E=fr(t),O=r.engine===`shell`&&!C||ur(r.engine)&&!w?``:r.engine,k=O===cr,ee=ur(O),A=i===`fork`,j=(e,t)=>{let n=e===`scratch`&&t===`continue`&&i===`scratch`?`tab`:e;a(n),s(n===`scratch`?`fresh`:t)},M=async()=>{let e=await t.client.request(`tab.handoff`,{taskId:n,tabId:t.selection.get().tabId??void 0});if(e.kind===`handoff`&&e.prompt)return e.prompt;throw Error(e.kind===`no-transcript`?V(`terminal`,`tab.noTranscriptToHandOff`,{engine:e.engine??``}):V(`terminal`,`tab.nothingToFork`))},N=()=>y(async()=>{let e=[o===`continue`?await M():``,Zn(c.trim(),b)].filter(Boolean).join(`
|
|
11
11
|
|
|
12
12
|
`);if(i===`scratch`){let e=await t.client.request(`task.openScratch`,k?{}:{engine:O});k?await mr(t,e.taskId,{kind:`shell`}):t.selectWhenListed(e.taskId)}else if(A){if(!f)throw Error(V(`terminal`,`tab.tabGone`));if(!c.trim())throw Error(T(`taskops.forkNeedsMessage`));let n=(await t.client.request(`tab.forkTask`,{repo:f.repo,baseBranch:p.trim()||f.branch,prompt:e,...O?{engine:O}:{},...Number(u)>1?{count:Number(u)}:{}})).taskIds[0];n&&t.selectWhenListed(n)}else if(k)await mr(t,n,{kind:`shell`});else if(ee){let{selection:e}=t,r=e.get().taskId===n?e.get().tabId:null,i=await t.client.request(`plugin.paneOpen`,{taskId:n,pane:dr(O),...r?{tabId:r}:{}});await t.refreshTabsNow(),t.select(n,i.tabId)}else await mr(t,n,{kind:`engine`,engine:O,prompt:e})});return(0,z.jsx)(ie,{title:V(`terminal`,`tab.newChat.title`),wide:!0,children:(0,z.jsxs)(`form`,{className:`dialog-body`,onKeyDown:e=>{if(e.key===`Tab`&&!e.ctrlKey&&!e.metaKey&&!e.altKey&&(A||!e.shiftKey))e.preventDefault(),e.stopPropagation(),A?rr(e.currentTarget,gr,e.shiftKey?-1:1):j(hr[(hr.indexOf(i)+1)%hr.length]??`tab`,o);else if(e.ctrlKey&&!e.metaKey&&!e.altKey&&e.key.toLowerCase()===`e`){e.preventDefault(),e.stopPropagation();let t=r.engines.filter(e=>e.ready!==!1),n=t[(t.findIndex(e=>e.id===r.engine)+1)%t.length];n&&r.setEngine(n.id)}else e.ctrlKey&&!e.metaKey&&!e.altKey&&e.key.toLowerCase()===`f`?(e.preventDefault(),e.stopPropagation(),j(i,o===`fresh`?`continue`:`fresh`)):e.key===`Enter`&&A&&e.target.closest(`[data-field=attempts], [data-field=engine]`)&&(e.preventDefault(),e.currentTarget.requestSubmit())},onSubmit:e=>{e.preventDefault(),N()},onDragOver:e=>e.preventDefault(),onDrop:e=>{e.preventDefault(),x(Array.from(e.dataTransfer.files))},children:[(0,z.jsxs)(`div`,{className:`field`,children:[(0,z.jsx)(`span`,{className:`kicker`,children:V(`terminal`,`tab.newChat.engine`)}),(0,z.jsx)(pr,{engines:r.engines,value:O,onChange:r.setEngine,withShell:C,panes:w?E:[]})]}),(0,z.jsxs)(`div`,{className:`field`,children:[(0,z.jsx)(`span`,{className:`kicker`,children:V(`terminal`,`tab.newChat.destLabel`)}),(0,z.jsx)(tr,{label:V(`terminal`,`tab.newChat.destLabel`),field:`destination`,value:i,onChange:e=>j(e,o),choices:hr.map(e=>({id:e,label:V(`terminal`,`tab.newChat.dest${e===`tab`?`Tab`:e===`fork`?`Fork`:`Scratch`}`)}))})]}),(0,z.jsxs)(`div`,{className:`field`,children:[(0,z.jsxs)(`span`,{className:`kicker`,children:[V(`terminal`,`tab.newChat.ctxLabel`),` · ctrl+f`]}),(0,z.jsx)(tr,{label:V(`terminal`,`tab.newChat.ctxLabel`),field:`context`,value:o,onChange:e=>j(i,e===`continue`?`continue`:`fresh`),choices:[`fresh`,`continue`].map(e=>({id:e,label:V(`terminal`,`tab.newChat.ctx${e===`fresh`?`Fresh`:`Continue`}`)}))})]}),A&&(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`div`,{className:`field`,children:[(0,z.jsx)(`span`,{className:`kicker`,children:V(`quickTask`,`attemptsLabel`)}),(0,z.jsx)(tr,{label:V(`quickTask`,`attemptsLabel`),field:`attempts`,value:u,onChange:d,choices:ir.map(e=>({id:e,label:e}))})]}),(0,z.jsxs)(`label`,{className:`field`,children:[(0,z.jsx)(`span`,{className:`kicker`,children:T(`taskops.forkBranch`)}),(0,z.jsx)(`input`,{className:`input`,"data-field":`fork-base`,spellCheck:!1,value:p,onChange:e=>h(e.target.value)})]})]}),!k&&!ee&&i!==`scratch`&&(0,z.jsxs)(`label`,{className:`field`,children:[(0,z.jsx)(`span`,{className:`kicker`,children:T(`newChat.prompt`)}),(0,z.jsx)(`textarea`,{className:`input textarea`,"data-field":`message`,autoFocus:!0,rows:4,placeholder:T(`newChat.promptPlaceholder`),value:c,onChange:e=>l(e.target.value),onPaste:e=>{let t=Array.from(e.clipboardData.files);t.length!==0&&(e.preventDefault(),x(t))},onKeyDown:e=>{e.key===`Enter`&&(e.metaKey||e.ctrlKey)&&e.currentTarget.form?.requestSubmit()}})]}),(0,z.jsx)(er,{attachments:b,onRemove:S}),(0,z.jsx)(`p`,{className:`muted newtask-legend`,children:V(`quickTask`,`legend`)}),_&&(0,z.jsx)(`p`,{className:`error`,children:_}),(0,z.jsx)(le,{busy:g,submitLabel:T(`newChat.start`)})]})})}function vr(e){let t=e.lastIndexOf(`/`);return t<0||t===e.length-1?{base:e,dir:``}:{base:e.slice(t+1),dir:e.slice(0,t+1)}}function yr(e,t){let n=t.trim().toLowerCase();return n?e.filter(e=>e.toLowerCase().includes(n)):e}function br(e){return e.startsWith(`~`)||e.includes(`/`)}function xr(e,t){return t?e===`~`?t:e.startsWith(`~/`)?t+e.slice(1):e:e}function Sr(e,t){return t?e===t?`~`:e.startsWith(`${t}/`)?`~${e.slice(t.length)}`:e:e}function Cr(e,t,n,r){let i=t+n;return e.startsWith(`~`)?Sr(i,r):i}function wr(e,t,n,r){return`${Cr(e,t,n,r)}/`}function Tr(e,t){let n=e.trim();if(!n||br(n))return{kind:`path`,path:n};let r=t.filter(e=>vr(e).base===n);return r.length===1?{kind:`path`,path:r[0]}:r.length>1?{kind:`ambiguous`,name:n}:{kind:`path`,path:n}}function Er(e,t){let n=vr(e).base,r=Tr(n,t);return r.kind===`path`&&r.path===e?n:e}function Dr(e){let t=e.trim().replace(/\/+$/,``),n=Math.max(t.lastIndexOf(`/`),t.lastIndexOf(`:`));return(n>=0?t.slice(n+1):t).replace(/\.git$/i,``)}function Or(e,t){let n=``;for(let t=0;t<e.length;t++){let r=e[t];r===`*`?e[t+1]===`*`?(n+=`.*`,t++):n+=`[^/]*`:n+=r===`?`?`[^/]`:r.replace(/[.+^${}()|[\]\\]/g,`\\$&`)}let r=RegExp(`^${n}$`);return r.test(t)||r.test(t.slice(t.lastIndexOf(`/`)+1))}function kr(e,t){let n=t.trim();return n?e.filter(e=>Or(n,e.path)):e}var Ar=class extends Error{code;constructor(e,t){super(t),this.code=e}},jr=[500,1e3,2e3,4e3,8e3,15e3],Mr=class{url;token;conn=_({state:`connecting`,hello:null,failures:0});ws=null;nextId=1;pending=new Map;listeners=new Map;openHooks=new Set;retryTimer=null;constructor(e,t){this.url=e,this.token=t}start(){this.connect()}onOpen(e){return this.openHooks.add(e),this.conn.get().state===`open`&&e(),()=>this.openHooks.delete(e)}on(e,t){let n=this.listeners.get(e);return n||(n=new Set,this.listeners.set(e,n)),n.add(t),()=>n.delete(t)}request(e,t={},n){let r=this.ws;if(!r||r.readyState!==WebSocket.OPEN)return Promise.reject(new Ar(`NOT_CONNECTED`,`not connected to rove`));let i=this.nextId++;return new Promise((a,o)=>{this.pending.set(i,{resolve:e=>a(e),reject:o,progress:n}),r.send(JSON.stringify({id:i,op:e,args:t}))})}connect(){this.retryTimer=null;let e=new WebSocket(this.url,[`rove.v1`,`rove.bearer.${this.token}`]);this.ws=e,e.onmessage=e=>this.receive(String(e.data)),e.onopen=()=>{this.request(`hello`).then(e=>{this.conn.set({state:`open`,hello:e,failures:0});for(let e of this.openHooks)e()},()=>e.close())},e.onclose=()=>{if(this.ws!==e)return;this.ws=null;for(let e of this.pending.values())e.reject(new Ar(`NOT_CONNECTED`,`connection lost`));this.pending.clear();let t=this.conn.get().failures+1;this.conn.set({state:`retrying`,hello:this.conn.get().hello,failures:t});let n=jr[Math.min(t-1,jr.length-1)];this.retryTimer=window.setTimeout(()=>this.connect(),n)}}receive(e){let t;try{t=JSON.parse(e)}catch{return}if(!t||typeof t!=`object`)return;if(`event`in t&&typeof t.event==`string`){let e=`data`in t?t.data:void 0;if(t.event===`op.progress`){let t=e;typeof t?.id==`number`&&typeof t.line==`string`&&this.pending.get(t.id)?.progress?.(t.line);return}for(let n of this.listeners.get(t.event)??[])n(e);return}if(!(`id`in t)||typeof t.id!=`number`)return;let n=this.pending.get(t.id);if(!n)return;if(this.pending.delete(t.id),`ok`in t&&t.ok===!0){n.resolve(`result`in t?t.result:void 0);return}let r=`error`in t&&t.error&&typeof t.error==`object`?t.error:{},i=`code`in r&&typeof r.code==`string`?r.code:`INTERNAL`,a=`message`in r&&typeof r.message==`string`?r.message:i;n.reject(new Ar(i,a))}retryNow(){this.retryTimer!==null&&(window.clearTimeout(this.retryTimer),this.connect())}};function Nr(){return`${window.location.protocol===`https:`?`wss:`:`ws:`}//${window.location.host}/ws`}function Pr(e){document.querySelector(`.dialog [data-field="${e}"]:not([hidden] *)`)?.focus()}function Fr(e){let[t,n]=(0,m.useState)(0),r=e.open&&e.items.length>0,i=Math.min(t,Math.max(0,e.items.length-1)),a=(0,m.useRef)(null),{onCursor:o}=e;return(0,m.useEffect)(()=>o?.(i),[i,o]),(0,m.useEffect)(()=>a.current?.scrollIntoView({block:`nearest`}),[i,e.items]),(0,z.jsxs)(`div`,{className:`suggest`,children:[(0,z.jsx)(`input`,{className:`input`,"data-field":e.field,spellCheck:!1,autoComplete:`off`,autoFocus:e.autoFocus,placeholder:e.placeholder,value:e.value,onChange:t=>{n(0),e.onChange(t.target.value.replace(/[\r\n]+/g,``))},onKeyDown:t=>{if(!t.nativeEvent.isComposing){if(t.key===`ArrowDown`||t.key===`ArrowUp`){if(!r)return;t.preventDefault(),n(Math.max(0,Math.min(e.items.length-1,i+(t.key===`ArrowDown`?1:-1))))}else t.key===`Tab`&&!t.shiftKey&&r&&e.onComplete?.(i)?(t.preventDefault(),n(0)):t.key===`Enter`&&!t.ctrlKey&&!t.metaKey&&(t.preventDefault(),r?((e.onEnterRow??e.onPick)(i),n(0)):e.onEnter?.())}}}),r&&(0,z.jsx)(`ul`,{className:`suggest-list`,children:e.items.map((t,n)=>(0,z.jsx)(`li`,{ref:n===i?a:void 0,children:(0,z.jsxs)(`button`,{type:`button`,tabIndex:-1,"aria-pressed":n===i,className:`suggest-row ${n===i?`is-cursor`:``} ${t.accent?`is-accent`:``}`,onMouseDown:t=>{t.preventDefault(),e.onPick(n)},children:[(0,z.jsx)(`span`,{children:t.text}),t.dim&&(0,z.jsxs)(`span`,{className:`muted`,children:[` `,t.dim]})]})},t.key))})]})}var Ir=`rove.web.cloneParent`;function Lr({model:e,engine:t,busy:n,error:r,run:i}){let[a,o]=(0,m.useState)(``),[s,c]=(0,m.useState)(()=>localStorage.getItem(Ir)||`~/`),[l,u]=(0,m.useState)(null),[d,f]=(0,m.useState)(`main`),[p,h]=(0,m.useState)(``),[g,_]=(0,m.useState)(!1),[v,y]=(0,m.useState)({base:``,home:``,names:[]});(0,m.useEffect)(()=>{let t=!1,n=setTimeout(()=>{e.client.request(`fs.subdirs`,{path:s}).then(e=>!t&&y(e)).catch(()=>{})},60);return()=>{t=!0,clearTimeout(n)}},[e,s]);let b=l??Dr(a),x=xr(s.trim(),v.home),S=()=>i(async()=>{if(!a.trim())throw Pr(`url`),Error(V(`newTask`,`error.gitUrlRequired`));let n;try{h(``),n=await e.client.request(`repo.clone`,{url:a.trim(),parentDir:x,...l?.trim()?{folder:l.trim()}:{}},h)}catch(e){throw e instanceof Ar&&e.code===`CLONE_FAILED`?Error(V(`newTask`,`error.cloneFailed`,{error:e.message})):e}localStorage.setItem(Ir,s.trim());let r=(await e.client.request(`task.spawn`,{repo:n.path,...t?{engine:t}:{},...d.trim()?{baseBranch:d.trim()}:{}})).taskIds[0];r&&e.selectWhenListed(r)});return(0,z.jsxs)(`form`,{className:`dialog-body`,onSubmit:e=>{e.preventDefault(),S()},children:[(0,z.jsxs)(`div`,{className:`field`,children:[(0,z.jsx)(`span`,{className:`kicker`,children:V(`newTask`,`field.gitUrl`)}),(0,z.jsx)(`input`,{className:`input`,"data-field":`url`,spellCheck:!1,placeholder:`https://github.com/user/repo.git`,value:a,onChange:e=>o(e.target.value.replace(/[\r\n]+/g,``)),onKeyDown:e=>{e.key!==`Enter`||e.ctrlKey||e.metaKey||(e.preventDefault(),a.trim()&&Pr(`parent`))}})]}),(0,z.jsxs)(`div`,{className:`field`,children:[(0,z.jsx)(`span`,{className:`kicker`,children:V(`newTask`,`field.parentDir`)}),(0,z.jsx)(Fr,{field:`parent`,value:s,placeholder:`~/`,onChange:e=>{_(!0),c(e)},items:v.names.map(e=>({key:e,text:`${e}/`})),open:g,onPick:e=>{let t=v.names[e];t!==void 0&&c(Cr(s,v.base,t,v.home)),_(!1),Pr(`folder`)},onComplete:e=>{let t=v.names[e];if(t===void 0)return!1;let n=`${Cr(s,v.base,t,v.home)}/`;return n!==s&&(c(n),!0)},onEnter:()=>Pr(`folder`)}),(0,z.jsx)(`span`,{className:`muted`,children:V(`newTask`,`hint.remembered`)})]}),(0,z.jsxs)(`div`,{className:`field`,children:[(0,z.jsx)(`span`,{className:`kicker`,children:V(`newTask`,`field.folderName`)}),(0,z.jsx)(`input`,{className:`input`,"data-field":`folder`,spellCheck:!1,placeholder:V(`newTask`,`placeholder.folderName`),value:b,onChange:e=>u(e.target.value.replace(/[\r\n]+/g,``)),onKeyDown:e=>{e.key!==`Enter`||e.ctrlKey||e.metaKey||(e.preventDefault(),Pr(`clone-base`))}})]}),(0,z.jsxs)(`div`,{className:`field`,children:[(0,z.jsx)(`span`,{className:`kicker`,children:V(`newTask`,`field.baseBranch`)}),(0,z.jsx)(`input`,{className:`input`,"data-field":`clone-base`,spellCheck:!1,placeholder:`main`,value:d,onChange:e=>f(e.target.value.replace(/[\r\n]+/g,``))})]}),n&&(0,z.jsx)(`p`,{className:`muted`,"data-field":`clone-progress`,children:p||V(`newTask`,`clone.progressInto`,{target:`${x}/${b}`})}),r&&(0,z.jsxs)(`p`,{className:`error`,children:[`※ `,r]}),(0,z.jsx)(le,{busy:n,submitLabel:V(`newTask`,n?`button.cloning`:`button.create`)})]})}function Rr({model:e,engine:t,busy:n,error:r,run:i,repo:a,active:o}){let[s,c]=(0,m.useState)(``),[l,u]=(0,m.useState)(null),[d,f]=(0,m.useState)(new Set),[p,h]=(0,m.useState)(0),g=a.expanded;(0,m.useEffect)(()=>{if(!o||!g)return;let t=!1;return u(null),f(new Set),e.client.request(`repo.probe`,{path:g,adoptable:!0}).then(e=>!t&&u(e.worktrees??[])).catch(()=>!t&&u([])),()=>{t=!0}},[e,o,g]);let _=kr(l??[],s),v=e=>f(t=>{let n=new Set(t);return n.delete(e)||n.add(e),n}),y=()=>i(async()=>{let n=d.size>0?_.filter(e=>d.has(e.path)):_.slice(p,p+1);if(n.length===0)throw Error(V(`newTask`,`error.noAdoptable`));let r=0,i,a;for(let o of n){let n={repo:g,worktreePath:o.path,branch:o.branch,...t?{engine:t}:{}};try{let t;try{t=await e.client.request(`worktree.adopt`,n)}catch(r){if(!(r instanceof Ar&&r.code===`UNKNOWN_REPO`))throw r;await e.client.request(`task.openMain`,{repo:g}),t=await e.client.request(`worktree.adopt`,n)}a=t.taskId,r++}catch(e){i??=e instanceof Error?e.message:String(e)}}if(r===0)throw Error(V(`newTask`,`adopt.summaryNone`,{error:i??``}));L(r<n.length?V(`newTask`,`adopt.summaryPartial`,{done:r,total:n.length}):V(`newTask`,`adopt.summaryAll`,{count:r})),a&&e.selectWhenListed(a)}),b=d.size>0?V(`newTask`,`adopt.hintSelected`,{count:d.size}):V(`newTask`,`adopt.hintDefault`);return(0,z.jsxs)(`form`,{className:`dialog-body`,onSubmit:e=>{e.preventDefault(),y()},onKeyDown:e=>{e.ctrlKey&&!e.shiftKey&&!e.metaKey&&e.key.toLowerCase()===`a`&&(e.preventDefault(),e.stopPropagation(),f(e=>_.every(t=>e.has(t.path))?new Set:new Set(_.map(e=>e.path))))},children:[(0,z.jsxs)(`div`,{className:`field`,children:[(0,z.jsx)(`span`,{className:`kicker`,children:V(`newTask`,`field.adoptFilter`)}),(0,z.jsx)(Fr,{field:`filter`,value:s,placeholder:V(`newTask`,`placeholder.adoptFilter`),onChange:c,items:_.map(e=>{let t=[e.dirty===!0?`dirty`:e.dirty===null?`dirty?`:``,e.roveManaged?``:`external`].filter(Boolean).join(`,`);return{key:e.path,text:`${d.has(e.path)?`[x]`:`[ ]`} ${e.branch}${t?` (${t})`:``}`,dim:e.path,accent:d.has(e.path)}}),open:!0,onPick:e=>{let t=_[e];t&&v(t.path)},onCursor:h,onEnter:()=>{}}),(0,z.jsx)(`span`,{className:`muted`,children:V(`newTask`,`adopt.repoLine`,{path:g||V(`newTask`,`adopt.repoNone`)})}),l===null&&g&&(0,z.jsx)(`span`,{className:`muted`,children:V(`newTask`,`hint.scanningWorktrees`)}),l!==null&&_.length===0&&(0,z.jsx)(`span`,{className:`muted`,children:V(`newTask`,l.length===0?`adopt.noUnlinked`:`adopt.noMatch`)}),_.length>0&&(0,z.jsx)(`span`,{className:`muted`,children:b})]}),r&&(0,z.jsxs)(`p`,{className:`error`,children:[`※ `,r]}),(0,z.jsx)(le,{busy:n,submitLabel:V(`newTask`,`button.create`)})]})}var zr=[`existing`,`clone`,`adopt`];function Br(e,t){let[n,r]=(0,m.useState)([]),[i,a]=(0,m.useState)(``),[o,s]=(0,m.useState)(``),[c,l]=(0,m.useState)(!1),[u,d]=(0,m.useState)(null),[f,p]=(0,m.useState)(null);(0,m.useEffect)(()=>{Promise.all([e.client.request(`repos.list`),e.client.request(`fs.subdirs`,{path:`~/`})]).then(([e,n])=>{r(e.repos),a(n.home);let i=t??e.repos[0]??``;s(t=>t||Er(i,e.repos))}).catch(()=>{})},[e,t]);let h=br(o.trim())&&!n.includes(o.trim());(0,m.useEffect)(()=>{if(!h)return;let t=!1,n=setTimeout(()=>{e.client.request(`fs.subdirs`,{path:o}).then(e=>!t&&d({base:e.base,names:e.names})).catch(()=>!t&&d({base:``,names:[]}))},60);return()=>{t=!0,clearTimeout(n)}},[e,h,o]);let g=Tr(o,n),_=g.kind===`path`?g.path:``,v=_.startsWith(`~`)&&!i?``:_.replace(/^~(?=\/|$)/,i).replace(/(.)\/+$/,`$1`);(0,m.useEffect)(()=>{if(p(null),!v)return;let t=!1,n=setTimeout(()=>{e.client.request(`repo.probe`,{path:v}).then(e=>!t&&p(e)).catch(()=>{})},150);return()=>{t=!0,clearTimeout(n)}},[e,v]);let y=new Set((e.tasks.get()?.tasks??[]).filter(e=>e.kind===`main`).map(e=>e.repo.replace(/\/+$/,``))),b=h?u?.names??[]:[],x=yr(n,o),S=h?b.map(e=>({key:e,text:`${e}/`})):x.map(e=>{let{base:t,dir:n}=vr(e);return{key:e,text:t,dim:n,accent:e===v}});return{text:o,saved:n,home:i,expanded:v,ambiguous:g.kind===`ambiguous`?g.name:null,mainRepos:y,open:!c,items:S,probe:f,setText:e=>{l(!1),s(e)},pick:e=>{if(h){let t=b[e];t!==void 0&&s(Cr(o,u?.base??``,t,i))}else{let t=x[e];t!==void 0&&s(Er(t,n))}l(!0),Pr(`branch`)},complete:e=>{if(c)return!1;if(h){let t=b[e];if(t===void 0)return!1;let n=wr(o,u?.base??``,t,i);return n!==o&&(s(n),!0)}let t=x[e];if(t===void 0)return!1;let r=Er(t,n);return r!==o.trim()&&(s(r),l(!0),!0)},reopen:()=>l(!1)}}function Vr(e){let{model:t,repo:n}=e,[r,i]=(0,m.useState)(``),[a,o]=(0,m.useState)(!1),[s,c]=(0,m.useState)(!0),[l,u]=(0,m.useState)(`task`),d=n.mainRepos.has(n.expanded),f=n.probe?.ok?n.probe:null,p=f?.branches??[];(0,m.useEffect)(()=>{!a&&f?.current&&i(f.current)},[a,f]),(0,m.useEffect)(()=>u(`task`),[n.expanded]);let h=yr(p,r),g=i=>e.run(async()=>{if(n.ambiguous)throw n.reopen(),Pr(`repo`),Error(V(`newTask`,`error.repoAmbiguous`,{name:n.ambiguous}));if(!n.expanded)throw Pr(`repo`),Error(T(`newTask.needRepo`));let a=await t.client.request(`repo.probe`,{path:n.expanded});if(!a.ok)throw Pr(`repo`),Error(a.reason??n.expanded);if(l===`project`&&d){let e=await t.client.request(`task.openMain`,{repo:a.repo});t.selectWhenListed(e.taskId);return}let o=(i??r).trim(),s=(await t.client.request(`task.spawn`,{repo:a.repo,...e.engine?{engine:e.engine}:{},...o?{baseBranch:o}:{}})).taskIds[0];s&&t.selectWhenListed(s)});return(0,z.jsxs)(`form`,{className:`dialog-body`,onSubmit:e=>{e.preventDefault(),g()},children:[(0,z.jsxs)(`div`,{className:`field`,children:[(0,z.jsx)(`span`,{className:`kicker`,children:V(`newTask`,`field.repo`)}),(0,z.jsx)(Fr,{field:`repo`,value:n.text,onChange:n.setText,items:n.items,open:n.open,onPick:n.pick,onComplete:n.complete,onEnter:()=>Pr(`branch`)})]}),d&&(0,z.jsxs)(`div`,{className:`field`,children:[(0,z.jsx)(`span`,{className:`kicker`,children:V(`newTask`,`field.opens`)}),(0,z.jsx)(tr,{label:V(`newTask`,`field.opens`),field:`intent`,value:l,onChange:e=>u(e===`project`?`project`:`task`),choices:[{id:`task`,label:V(`newTask`,`intent.task`)},{id:`project`,label:V(`newTask`,`intent.project`)}]})]}),!(l===`project`&&d)&&(0,z.jsxs)(`div`,{className:`field`,children:[(0,z.jsx)(`span`,{className:`kicker`,children:V(`newTask`,`field.fromBranch`)}),(0,z.jsx)(Fr,{field:`branch`,value:r,placeholder:`main`,onChange:e=>{o(!0),c(!0),i(e)},items:h.map(e=>({key:e,text:e,accent:e===r.trim()})),open:s,onPick:e=>{let t=h[e];t!==void 0&&(i(t),o(!0),c(!1),Pr(`create`))},onEnterRow:e=>{let t=r.trim(),n=t?h.find(e=>e.toLowerCase()===t.toLowerCase()):void 0;g(n??h[e]??t)},onEnter:()=>void g()}),h.length===0&&e.error==null&&(0,z.jsx)(`span`,{className:`muted`,children:V(`newTask`,p.length===0?`hint.noBranchesFound`:`hint.noMatchBranch`)})]}),e.error&&(0,z.jsxs)(`p`,{className:`error`,children:[`※ `,e.error]}),(0,z.jsx)(le,{busy:e.busy,submitLabel:V(`newTask`,`button.create`)})]})}function Hr({model:e,repo:t}){D();let n=sr(e),[r,i]=(0,m.useState)(`existing`),{busy:a,error:o,setError:s,submit:c}=ae(),l=e.selection.get().taskId,u=e.tasks.get()?.tasks.find(e=>e.id===l)?.repo,d=Br(e,t??u),f=(0,m.useRef)(null),p=(0,m.useRef)(!0);(0,m.useEffect)(()=>{if(s(null),p.current){p.current=!1,f.current?.querySelector(`[data-field=mode] [aria-pressed=true]`)?.focus();return}Pr(r===`existing`?`repo`:r===`clone`?`url`:`filter`)},[r]);let h=n.engines.filter(e=>e.ready!==!1),g=()=>{let e=h.length>0?h:n.engines,t=e[(e.findIndex(e=>e.id===n.engine)+1)%e.length];t&&n.setEngine(t.id)},_=e=>i(t=>zr[(zr.indexOf(t)+e+zr.length)%zr.length]),v={model:e,engine:n.engine,busy:a,error:o,setError:s,run:c};return(0,z.jsx)(ie,{title:V(`newTask`,`title`),wide:!0,children:(0,z.jsxs)(`div`,{ref:f,onKeyDown:e=>{if(!(!e.ctrlKey||e.metaKey||e.altKey)){if(e.key===`]`||e.key===`[`)_(e.key===`]`?1:-1);else if(e.key.toLowerCase()===`e`&&!e.shiftKey)g();else return;e.preventDefault(),e.stopPropagation()}},children:[(0,z.jsxs)(`div`,{className:`dialog-body`,children:[(0,z.jsxs)(`div`,{className:`field`,children:[(0,z.jsx)(`span`,{className:`kicker`,children:V(`newTask`,`field.mode`)}),(0,z.jsx)(tr,{label:V(`newTask`,`field.mode`),field:`mode`,value:r,onChange:e=>i(e),choices:zr.map(e=>({id:e,label:V(`newTask`,`tabs.${e}`)}))})]}),(0,z.jsxs)(`div`,{className:`field`,children:[(0,z.jsx)(`span`,{className:`kicker`,children:V(`newTask`,`field.engine`)}),(0,z.jsx)(pr,{engines:n.engines,value:n.engine,onChange:n.setEngine})]})]}),(0,z.jsx)(`div`,{hidden:r!==`existing`,children:(0,z.jsx)(Vr,{...v,repo:d})}),(0,z.jsx)(`div`,{hidden:r!==`clone`,children:(0,z.jsx)(Lr,{...v})}),(0,z.jsx)(`div`,{hidden:r!==`adopt`,children:(0,z.jsx)(Rr,{...v,repo:d,active:r===`adopt`})}),(0,z.jsx)(`p`,{className:`muted newtask-legend`,children:V(`newTask`,`legend`,{enter:V(`newTask`,`enterNext`)})})]})})}var Ur=10;function Wr(e,t){let n=e=>e.surface===t?0:e.surface?1:2,r=Mt().filter(n=>Nt(n,t)&&n.live?.(e)!==!1).map((e,t)=>({command:e,index:t})).sort((e,t)=>n(e.command)-n(t.command)||Number(e.command.prefix)-Number(t.command.prefix)||e.index-t.index),i=new Set,a=[];for(let{command:e}of r){let t=e.chords[0];!t||e.id===`palette.open`||i.has(e.id)||(i.add(e.id),a.push({command:e,name:Xt(e.id),chord:e.prefix?`${Xe()} + ${Ue(t)}`:Ue(t),raw:e.prefix?`${Ye()} + ${t}`:t}))}return a}function Gr(e){let t=document.activeElement instanceof HTMLElement?document.activeElement:null;k.set((0,z.jsx)(Kr,{model:e,surface:Ft(),origin:t}))}function Kr({model:e,surface:t,origin:n}){D();let[r,i]=(0,m.useState)(``),[a,o]=(0,m.useState)(0),s=(0,m.useRef)(null),c=v(We),l=(0,m.useMemo)(()=>Wr(e,t),[e,t,c]).filter(e=>Tt(r,e.name,e.raw)),u=Math.min(a,Math.max(0,l.length-1));(0,m.useEffect)(()=>()=>n?.focus(),[n]),(0,m.useEffect)(()=>{s.current?.querySelector(`.is-selected`)?.scrollIntoView({block:`nearest`})},[u]);let d=t=>{R(),n?.focus(),t.command.live?.(e)===!1?L(qt(`unavailable`),`error`):t.command.run(e)};return(0,z.jsx)(ie,{title:qt(`palette`),wide:!0,children:(0,z.jsxs)(`div`,{className:`dialog-body palette`,onKeyDown:e=>{if(e.key===`ArrowDown`)o(Math.min(l.length-1,u+1));else if(e.key===`ArrowUp`)o(Math.max(0,u-1));else if(e.key===`Enter`){let e=l[u];e&&d(e)}else return;e.preventDefault()},children:[(0,z.jsx)(`input`,{className:`input`,autoFocus:!0,spellCheck:!1,value:r,placeholder:qt(`search`),onChange:e=>{i(e.target.value),o(0)}}),(0,z.jsxs)(`div`,{className:`palette-list`,ref:s,style:{maxHeight:`${Ur*1.9}em`},children:[l.length===0&&(0,z.jsx)(`p`,{className:`muted`,children:qt(`noResults`)}),l.map((e,t)=>(0,z.jsxs)(`button`,{type:`button`,className:`palette-row ${t===u?`is-selected`:``}`,onMouseEnter:()=>o(t),onClick:()=>d(e),children:[(0,z.jsx)(`span`,{children:`${t===u?`› `:` `}${e.name}`}),(0,z.jsx)(`span`,{className:`palette-chord mono`,children:e.chord})]},e.command.id))]}),(0,z.jsx)(`p`,{className:`muted`,children:qt(`run`)})]})})}var qr=[`sidebar`,`workspace`,`files`];function Jr(e,t,n){let r=qr.filter(e=>e!==`files`||n.filesVisible),i=r.indexOf(e);if(i<0)return(t>0?r[r.length-1]:r[0])??null;let a=Math.min(Math.max(i+t,0),r.length-1);return a===i?null:r[a]??null}var Yr={sidebar:[`.rail`,`.rail`],workspace:[`.workspace`,`.preview, .term-slot:not(.is-hidden) .split-leaf.is-active textarea`],files:[`.files`,`.files`]};function Xr(e){let t=Jr(Object.keys(Yr).find(e=>document.activeElement?.closest(Yr[e][0]))??`sidebar`,e,{filesVisible:document.querySelector(Yr.files[0])!==null});t&&document.querySelector(Yr[t][1])?.focus()}var Zr=_(null);function Qr(e){let t=(document.activeElement?.closest(`.rail`)==null?null:Zr.get())??e.selection.get().taskId;return e.tasks.get()?.tasks.find(e=>e.id===t)??null}var $r={autoRouting:{title:`Auto routing`,hint:"Routing by depth: a task says how deep the work is — swift, standard, deep — and this table says which engine, model and reasoning effort that depth runs on. Pick a depth in the new-task dialog (or `rove api add --tier`) and Rove fills those three fields from the row; you still see them and can change them before the task starts. enter (or click) a row to point it somewhere else, with the same picker a task uses. A row whose target cannot start says why here, not at launch.",unconfigured:`Auto routing is off: a depth has nowhere to route — its engine is blank. Point it somewhere below, or remove the empty autoRouting.<tier>.engine from state.json.`,engineDefault:`engine default`,ready:`● ready`,unavailable:`! unavailable — {reason}`,classifierTitle:`Classifier`,classifierHint:"The rows above say what each depth RUNS. This says who CHOOSES one: switch it on and `rove api add --tier auto` reads the task's first message and picks the depth for you. It is off by default, it is never required, and it can never fail a create — no key, no network, a timeout, or an answer it is not confident enough about all leave you on the depth you would have had.",classifierDataFlow:"! Turning the classifier on sends the task's first message to a third party that is NOT the engine vendor you picked — TypeSafe System One for `jev`, or whatever address you point `custom` at. It reads the text before your engine does. Nothing leaves this machine while it is off.",classifierLabel:`Choose with`,classifierOff:`off`,classifierCustomLabel:`custom`,classifierOffHint:`— nothing is sent anywhere`,classifierJevHint:`— TypeSafe System One, billed to your own key`,classifierCustomHint:`— your endpoint: POST the text, answer with a depth and a confidence`,endpointLabel:`Endpoint`,endpointUnset:`(none — enter one, then set Choose with to custom)`,endpointTitle:`Custom classifier endpoint`,endpointField:`URL`,endpointInvalidTitle:`Not a URL`,endpointInvalidBody:`The endpoint has to start with https://, or http:// for a loopback address (127.0.0.1, localhost, ::1) — over a network, plain http would carry the task's first 1,200 characters in cleartext. Leave it empty to clear it.`,thresholdLabel:`Confidence floor`,thresholdHint:`— below this, the depth is left alone`,thresholdTitle:`Confidence floor`,thresholdField:`0 to 1`,thresholdInvalidTitle:`Not a confidence`,thresholdInvalidBody:`The floor is a number between 0 and 1. 0.5 is the shipped default.`,keyLabel:`API key`,keyStored:`stored {hint} — enter to replace, empty to clear`,keyFromEnv:"from ${env} — the environment wins over a stored key",keyNone:`not set — enter to paste one`,keyTitle:`{env}`,keyPlaceholder:`paste the key; leave empty to clear the stored one`,keySaved:`● key stored in ~/.rove/secrets.json (owner-only, never in state.json)`,keyCustomUnused:`● no Authorization header is sent to a custom endpoint — set autoRouting.classifierCustomKeyEnv to the variable holding its key if it needs one`,keyNoVariableTitle:`No key variable for this endpoint`,keyNoVariableBody:`A custom classifier endpoint is sent no Authorization header until autoRouting.classifierCustomKeyEnv names the variable its key lives in. Set that first — a key stored under a name nothing reads is a key at rest for no purpose.`,keyWriteFailedTitle:`Key not saved`,keyWriteFailedBody:`~/.rove/secrets.json could not be written: {reason}. Check directory permissions and disk space, then save again.`,keyMissing:`! no key — nothing is chosen and tasks keep their usual depth`,keyPresentEnv:"● key read from ${env} in this process's environment"}},ei={autoRouting:{title:`自动路由`,hint:"按深度路由:任务说明这活有多深——轻快、标准、深入——这张表说明那一档跑在哪个引擎、哪个模型、哪个推理强度上。在新建任务对话框里选一档(或 `rove api add --tier`),Rove 就照那一行填进这三个字段;任务启动前你仍然看得见、改得了。enter(或点击)某一行,用和任务一样的选择器把它指到别处。目标起不来的行会在这里说明原因,而不是等到启动时才炸。",unconfigured:`自动路由已关闭:有一档无处可去——它的引擎是空的。在下面把它指到某个引擎,或从 state.json 里删掉空的 autoRouting.<tier>.engine。`,engineDefault:`引擎默认`,ready:`● 可用`,unavailable:`! 不可用——{reason}`,classifierTitle:`分类器`,classifierHint:"上面几行说的是每一档**跑什么**,这里决定**由谁来选**:打开之后,`rove api add --tier auto` 会读任务的第一句话替你选档。默认关着,从来不是必需的,也永远不会让建 task 失败——没 key、断网、超时、或者它自己没把握,都只是让你停在本来就会用的那一档上。",classifierDataFlow:"! 打开分类器,任务的第一句话会发给一个**不是你选的那个引擎厂商**的第三方——`jev` 是 TypeSafe System One,`custom` 是你自己填的地址。它比你的引擎更早读到这段文字。关着的时候什么都不发。",classifierLabel:`选档方式`,classifierOff:`关`,classifierCustomLabel:`自定义`,classifierOffHint:`——不向任何地方发送`,classifierJevHint:`——TypeSafe System One,走你自己的 key 计费`,classifierCustomHint:`——你自己的接口:POST 那段文本,返回一个档位加一个置信度`,endpointLabel:`接口地址`,endpointUnset:`(未填——先填一个,再把「选档方式」切到自定义)`,endpointTitle:`自定义分类器接口`,endpointField:`URL`,endpointInvalidTitle:`不是一个 URL`,endpointInvalidBody:`接口地址要以 https:// 开头;http:// 只在回环地址(127.0.0.1、localhost、::1)上接受——发到网络上的话,明文 http 会把任务的前 1200 个字符原样带走。留空则清除。`,thresholdLabel:`置信度下限`,thresholdHint:`——低于这个值就不动档位`,thresholdTitle:`置信度下限`,thresholdField:`0 到 1`,thresholdInvalidTitle:`不是一个置信度`,thresholdInvalidBody:`下限是 0 到 1 之间的数。出厂默认 0.5。`,keyLabel:`API key`,keyStored:`已存 {hint}——enter 可替换,留空清除`,keyFromEnv:"来自环境变量 ${env}——环境变量优先于存起来的那个",keyNone:`未设置——enter 粘贴一个`,keyTitle:`{env}`,keyPlaceholder:`粘贴 key;留空则清除已存的那个`,keySaved:`● key 存在 ~/.rove/secrets.json(仅本人可读,不会进 state.json)`,keyCustomUnused:`● 自定义接口不会收到 Authorization 头——它若需要凭据,把 autoRouting.classifierCustomKeyEnv 指向存它的变量`,keyNoVariableTitle:`这个接口还没有 key 变量`,keyNoVariableBody:`在 autoRouting.classifierCustomKeyEnv 指定存 key 的变量之前,自定义分类器接口不会收到任何 Authorization 头。先设那个——存在一个没人读的名字下面的 key,只是白白落在盘上。`,keyWriteFailedTitle:`key 没存下`,keyWriteFailedBody:`写不了 ~/.rove/secrets.json:{reason}。请检查目录权限和磁盘空间,再次保存。`,keyMissing:`! 没有 key——不会替你选档,任务保持原来的档位`,keyPresentEnv:"● key 来自本进程环境变量 ${env}"}},ti={dev:{reset:`Reset UI state`,resetHint:`Clears ~/.config/rove/state.json and ~/.rove/tasks.json, then quits Rove — relaunch to start fresh. Working session list, pane sizes, theme, model picks all reset. Worktrees on disk and engine session history are not touched.`,resetButton:`[enter] Reset`,restart:`Restart backend`,restartHint:`Stops the Rove daemon and relaunches this window on the installed build — picks up daemon / orchestrator / engine edits without quitting by hand. Running engine sessions live in the PTY host and survive it; other attached Rove windows reconnect on their own.`,restartButton:`[enter] Restart`,reload:`Reload settings`,reloadHint:"Applies hand edits to ~/.config/rove/state.json (from `rove config`) to this window without a restart.",reloadButton:`[enter] Reload`,reloadDone:`Reloaded: {count} changed.`,reloadUnchanged:`Already matches state.json; nothing changed.`,reloadFailed:`state.json could not be read, nothing changed: {error}`,doctorHint:"Daemon wedged or unresponsive? Restart backend above does it from here; from a shell it is `rove daemon restart`. Hosted engine sessions stay alive across a daemon restart.",experimental:`Experimental`,remoteHint:"Remote projects (SSH): register a project whose git worktrees live on another host, driven from this local Rove. Unfinished — Hosted PTY engine launch over SSH is not implemented, and file/diff panes still degrade. Enables `rove add --remote`.",remote:`Remote projects`,autoStatusHint:`Auto status flow: a backlog task moves to in_progress when its engine starts a turn, and new sessions get a system-prompt note telling the agent to set in_review itself when the work is done. Never touches done/canceled.`,autoStatus:`Auto status flow`,dispatcherHint:"Field-notes dispatcher: task sessions file one-line gotchas (`rove api note`), the daemon forwards each to the repo's main session, and that session relays them to the in-flight tasks that benefit (`rove api dispatch`). Web-hosted sessions receive the relays today.",dispatcher:`Field-notes dispatcher`}},ni={dev:{reset:`重置 UI 状态`,resetHint:`清空 ~/.config/rove/state.json 和 ~/.rove/tasks.json,然后退出 Rove——重新启动即可从头开始。工作会话列表、面板尺寸、主题、模型选择都会重置。磁盘上的 worktree 和引擎会话历史不受影响。`,resetButton:`[enter] 重置`,restart:`重启后端`,restartHint:`停止 Rove daemon,并以已安装的版本重新启动当前窗口——无需手动退出即可应用 daemon / orchestrator / engine 的改动。正在运行的引擎会话由 PTY host 托管,不受影响;其他已连接的 Rove 窗口会自行重连。`,restartButton:`[enter] 重启`,reload:`重新加载设置`,reloadHint:"把对 ~/.config/rove/state.json 的手动修改(来自 `rove config`)应用到当前窗口,无需重启。",reloadButton:`[enter] 重新加载`,reloadDone:`已重新加载:{count} 项有变化。`,reloadUnchanged:`已与 state.json 一致,没有变化。`,reloadFailed:`无法读取 state.json,未做任何改动:{error}`,doctorHint:"daemon 卡住或无响应?上面的「重启后端」就能在这里完成;在 shell 里则是 `rove daemon restart`。Hosted PTY 引擎会话不会因 daemon 重启而退出。",experimental:`实验性`,remoteHint:"远程项目(SSH):注册一个 git worktree + 引擎都通过 SSH 跑在另一台主机上、由本地 Rove 驱动的项目。尚未完成——文件/diff 面板对远程仍会降级。启用 `rove add --remote`。",remote:`远程项目`,autoStatusHint:`自动状态流转:backlog 任务在其引擎开始一轮时移到 in_progress,新会话会拿到一条系统提示,告诉 agent 完成后自行设为 in_review。绝不触碰 done/canceled。`,autoStatus:`自动状态流转`,dispatcherHint:"现场笔记调度器:任务会话提交一行经验(`rove api note`),daemon 将每条转发给仓库的主会话,主会话再把它们转达给能受益的进行中任务(`rove api dispatch`)。目前由 Web 托管的会话会收到转达。",dispatcher:`现场笔记调度器`}},ri={engines:{title:`Engines`,hint:`Every engine Rove can launch, with what detection found under each one: where its binary is, and for the engines with an account detector whether you are logged in. [x] = offered when picking an engine for a task; (●) = the global default (per-project picks, e.g. Ctrl+Shift+T, override it) — click either, or use the keys below. Override a launch command when the binary isn't on PATH or to pass default flags. space on/off · enter edit command · r rename · x reset/remove · d set default. The third line under each engine names which of Rove's reporting layers it uses — hooks it installs, completion markers it reads, screen rules it falls back to. A missing layer is not a fault: an engine whose hooks report everything needs no screen rules.`,customTag:` (custom)`,addEngine:`+ Add engine`,launchCommandTitle:`{name} launch command`,displayNameTitle:`{name} display name (blank = default)`,addTitle:`Add engine`,addStepTitle:`Add engine · {id}`,protocolTitle:`Add engine · {id} — protocol`,protocolNone:`None — generic adapter`,protocolFooter:`↑↓ choose · enter pick · esc cancel`,protocolRow:`protocol {protocol}`,protocolGeneric:`generic`,idPlaceholder:`lowercase slug, e.g. aider`,commandPlaceholder:`e.g. aider --model sonnet`,hookInstalled:`hooks written`,hookTrustHint:`Open {command} in the engine and approve hooks yourself. Written hooks are not proof of trust.`,readiness:`CLI: {cli} · login: {login} · hooks: {hooks}`,cliReady:`available`,cliMissing:`missing; install the engine CLI`,loginReady:`detected`,loginMissing:`sign in with the engine CLI`,readinessUnknown:`not observable`,hooksWritten:`written`,hooksMissing:`not written; Settings → Engines`,hooksOutdated:`outdated; Settings → Engines`,hookWaiting:`No hook event received yet. After approval, send a short prompt to verify activity.`,hookReceived:`Hook event recorded for this tab. Send a short prompt to check current reporting; current trust is not inferred.`,readinessFailed:`Readiness check unavailable; run rove doctor. No authorization is inferred.`,hookOutdated:`hooks outdated`,hookMissing:`hooks not installed`,hookNone:`no hooks`,hookUnavailable:`engine not installed`,markersYes:`markers`,markersNo:`no markers`,screenYes:`screen rules`,screenNo:`no screen rules`,hookRefused:`! {file} rejected: {reason}`,installHooks:`→ Install engine integrations ({count})`,installHooksDone:`· Engine integrations up to date`,uninstallHooks:`← Remove engine integrations ({count})`,uninstallHooksDone:`· No engine integrations installed`},accounts:{checking:`Checking…`,notLoggedIn:`○ Not logged in`,loggedIn:`● Logged in: {email}`,apiKeyConfigured:`● API key configured`,chatgptLogin:`● ChatGPT login: {email}`,tokenConfigured:`● Token configured ({source})`,detected:`● Login detected`}},ii={engines:{title:`引擎`,hint:`Rove 能启动的所有引擎,每个下面跟着本地探测到的情况:二进制在哪,以及对有账户探测器的引擎是否已登录。[x] = 为任务选引擎时会列出它;(●) = 全局默认引擎(各项目自己的选择会覆盖它,如 Ctrl+Shift+T)——两者都可直接点,也可用下面的按键。二进制不在 PATH 上、或要传默认参数时,覆盖它的启动命令。space 开/关 · enter 编辑命令 · r 重命名 · x 重置/移除 · d 设为默认。每个引擎下方第三行说明它的状态由哪几层负责——Rove 安装的钩子、可读回的完成标记、兜底的读屏规则。缺某一层不算故障:钩子已经报全的引擎不需要读屏规则。`,customTag:` (自定义)`,addEngine:`+ 添加引擎`,launchCommandTitle:`{name} 的启动命令`,displayNameTitle:`{name} 的显示名称(留空 = 默认)`,addTitle:`添加引擎`,addStepTitle:`添加引擎 · {id}`,protocolTitle:`添加引擎 · {id} —— 协议`,protocolNone:`无 —— 通用适配器`,protocolFooter:`↑↓ 选择 · enter 确认 · esc 取消`,protocolRow:`协议 {protocol}`,protocolGeneric:`通用`,idPlaceholder:`小写短名,如 aider`,commandPlaceholder:`如 aider --model sonnet`,hookInstalled:`hooks 已写入`,hookTrustHint:`在引擎中打开 {command},由你自行批准 hooks。写入不代表已授权。`,readiness:`CLI:{cli} · 登录:{login} · hooks:{hooks}`,cliReady:`可用`,cliMissing:`缺失;请安装引擎 CLI`,loginReady:`已检测到`,loginMissing:`请通过引擎 CLI 登录`,readinessUnknown:`无法观测`,hooksWritten:`已写入`,hooksMissing:`未写入;设置 → 引擎`,hooksOutdated:`已过时;设置 → 引擎`,hookWaiting:`尚未收到 hook 事件。授权后发送一条简短提示,验证活动状态。`,hookReceived:`已记录此标签页的 hook 事件。发送简短提示以检查当前上报;不据此推断当前授权。`,readinessFailed:`无法检查就绪状态;请运行 rove doctor。不会据此推断已授权。`,hookOutdated:`钩子已过期`,hookMissing:`未装钩子`,hookNone:`无钩子`,hookUnavailable:`引擎未安装`,markersYes:`有完成标记`,markersNo:`无完成标记`,screenYes:`有读屏规则`,screenNo:`无读屏规则`,hookRefused:`! {file} 被拒绝:{reason}`,installHooks:`→ 安装引擎接入({count})`,installHooksDone:`· 引擎接入已是最新`,uninstallHooks:`← 移除引擎接入({count})`,uninstallHooksDone:`· 未安装任何引擎接入`},accounts:{checking:`检查中…`,notLoggedIn:`○ 未登录`,loggedIn:`● 已登录: {email}`,apiKeyConfigured:`● 已配置 API key`,chatgptLogin:`● ChatGPT 登录: {email}`,tokenConfigured:`● 已配置 Token ({source})`,detected:`● 检测到登录`}},ai={plugins:{title:`Plugins`,hint:"Rove's built-in plugins first, then those registered in ~/.rove/plugins.json. enter (or click) toggles one on or off — the daemon watches the file, so the change applies live. Rows indented under a plugin are the settings it declares; enter edits one, and the value reaches the plugin on its next run. Install and remove them from the shell: `rove plugin install <owner/repo>`, `rove plugin link <dir>`.",empty:"No plugins registered. Install one with `rove plugin install <owner/repo>` — browse the `rove-plugin` topic on GitHub.",sourceLink:`linked {path}`,sourceGithub:`{spec}`,sourceBuiltIn:`built into Rove`,updateAvailable:`update available — rove plugin update`,declares:`{actions} actions · {events} events · {panes} panes`,declaresWithEngines:`{actions} actions · {events} events · {panes} panes · {engines} engines`,declaresPages:`· {pages} pages`,pageFailed:`page {detail}`,manifestUnreadable:`manifest unreadable; check the rove-plugin.toml path and TOML syntax`,unsupportedPlatform:`· not supported on this platform`,noHooks:`· no hooks declared`,lastRun:`· last run {label} {status} {ago} ago`,neverRun:`· never run`,runOk:`ok`,runRunning:`still running`,runFailed:"failed to start; inspect `rove plugin log <id>`",runExit:`exit {code}`,settingUnset:`(unset — enter to edit)`,settingInvalidTitle:`Not a number`,settingInvalidBody:`{label} only accepts a number. Keeping the previous value.`},marketplace:{title:`Marketplace`,hint:"Plugins published under the `rove-plugin` topic on GitHub, most-starred first. enter (or click) shows what the install would run and asks before running any of it. The listing is re-queried each time you open this section.",loading:`Searching GitHub…`,empty:`No plugins listed.`,offline:`GitHub is unreachable — showing first-party plugins only. Re-open this section to retry.`,installedTag:`installed`,firstParty:`first-party`,preparing:`cloning {ref}…`,installing:`building and registering {name}…`,installed:`installed {id} v{version} — it is enabled, and appears under Plugins.`,cancelled:`install cancelled; nothing was run.`,failed:`install failed: {error}. Check the build output and retry from Marketplace.`,alreadyInstalled:`already installed as {id} — manage it under Plugins.`,confirmTitle:`Install {name}?`,confirmInstall:`install`,previewSource:`source: {source}`,previewCommands:`Commands this plugin declares:`,previewNoCommands:`This plugin declares no commands.`,previewWarning:`warning: {warning}`,previewTrust:`Installing runs the build commands above, and the rest run later on the events they declare. They run as you, with your environment, and nothing is sandboxed.`}},oi={plugins:{title:`插件`,hint:"先列 Rove 内置插件,再列在 ~/.rove/plugins.json 里注册的插件。enter(或点击)切换启用/禁用——daemon 监听该文件,改动实时生效。插件下方缩进的行是它声明的设置项,enter 编辑,新值在插件下次运行时生效。安装与移除在 shell 里做:`rove plugin install <owner/repo>`、`rove plugin link <dir>`。",empty:"尚未注册任何插件。用 `rove plugin install <owner/repo>` 安装一个——可在 GitHub 的 `rove-plugin` 话题下浏览。",sourceLink:`本地链接 {path}`,sourceGithub:`{spec}`,sourceBuiltIn:`Rove 内置`,updateAvailable:`有新版本 — rove plugin update`,declares:`{actions} 个动作 · {events} 个事件 · {panes} 个面板`,declaresWithEngines:`{actions} 个动作 · {events} 个事件 · {panes} 个面板 · {engines} 个引擎`,declaresPages:`· {pages} 个页面`,pageFailed:`页面 {detail}`,manifestUnreadable:`manifest 无法解析;请检查rove-plugin.toml 的路径和 TOML 语法`,unsupportedPlatform:`· 不支持当前平台`,noHooks:`· 未声明钩子`,lastRun:`· 上次运行 {label} {status} {ago}前`,neverRun:`· 尚未运行过`,runOk:`成功`,runRunning:`仍在运行`,runFailed:"启动失败;请查看 `rove plugin log <id>`",runExit:`退出码 {code}`,settingUnset:`(未设置 — enter 编辑)`,settingInvalidTitle:`不是数字`,settingInvalidBody:`{label} 只接受数字,保留原值。`},marketplace:{title:`插件市场`,hint:"GitHub 上 `rove-plugin` 话题下发布的插件,按 star 数排序。enter(或点击)会先列出安装会执行的命令,确认后才真正执行。每次进入本区块都会重新查询列表。",loading:`正在搜索 GitHub…`,empty:`列表为空。`,offline:`GitHub 不可达——只显示首方插件。重新进入本区块可再试一次。`,installedTag:`已安装`,firstParty:`首方`,preparing:`正在克隆 {ref}…`,installing:`正在构建并注册 {name}…`,installed:`已安装 {id} v{version}——已启用,可在「插件」区块管理。`,cancelled:`已取消安装,没有执行任何命令。`,failed:`安装失败:{error}。请检查构建输出,再从插件市场重试。`,alreadyInstalled:`已安装为 {id}——在「插件」区块管理。`,confirmTitle:`安装 {name}?`,confirmInstall:`安装`,previewSource:`来源:{source}`,previewCommands:`该插件声明的命令:`,previewNoCommands:`该插件未声明任何命令。`,previewWarning:`警告:{warning}`,previewTrust:`安装会执行上面的 build 命令,其余命令会在它们声明的事件发生时执行。它们以你的身份、带你的环境变量运行,没有任何沙箱。`}},si={en:{appearance:{enabled:`On`,disabled:`Off`,singleRow:`Single row`,doubleRow:`Two rows`,borderFlow:`Flowing gradient`,borderStill:`Still`,glyphsBraille:`Braille`,glyphsStarburst:`Starburst (needs a font with the Dingbats block)`,glyphsAscii:`ASCII`,titleShimmer:`Shimmer`,titleStill:`Still`,preview:`Workspace preview`,tasks:`Tasks`,terminal:`Terminal`,files:`Files`,testsPassed:`Tests passed`,modelDetail:`model · effort`,transparent:`Transparent background`,opaque:`Opaque background`,modeDark:`Dark`,modeLight:`Light`,modeAuto:`Auto (follow the terminal)`,openHint:`Enter to choose an option and preview it.`,chooseHint:`↑/↓ or j/k preview · enter apply · esc cancel`},title:`Settings`,esc:`esc`,nav:{default:`j/k pick · h/l switch level · enter activate · esc close`,feedback:`tab next field · enter sends on Send · esc close`},sections:{general:`General`,engines:`Engines`,autoRouting:`Auto routing`,plugins:`Plugins`,marketplace:`Marketplace`,keys:`Keybindings`,feedback:`Feedback`,dev:`Dev`},general:{usage:`USAGE`,theme:`Theme`,themeMode:`Mode`,themeHint:`l to enter list · j/k to highlight · enter to apply`,language:`Language`,languageHint:`Display language for Rove's UI. l to enter list · j/k to highlight · enter to apply.`,transparent:`Transparent background`,transparentHint:`Drops the renderer's bg fill so the host terminal shows through. enter toggles.`,on:`[x] on`,off:`[ ] off`,focusAccent:`Focus accent`,focusAccentHint:`Color of focused pane title, ▌ marker, and split borders.`,accentPrimary:`Primary (brand accent)`,accentSuccess:`Success (legacy green)`,accentInfo:`Info (cool blue)`,appearance:`Appearance`,appearanceHint:`How split panes draw.`,splitStyle:`Split panes`,tabRowHeight:`Tab row height`,tabRowHeightHint:`Two cells adds the model and reasoning level under an agent tab, and halves how many rows fit.`,tabRowHeightRow:`{cells}-cell agent tab rows`,tabRowHeightRowHint:`enter cycles`,workingBorder:`Working border`,taskColors:`Task colors`,glyphSet:`State glyphs`,colorblind:`Colorblind diff colours`,runningTitle:`Running title`,splitBox:`Box frames`,splitLine:`Divider line`,splitRail:`Accent rail`,splitRule:`Top rule`,notifications:`Notifications`,notificationsHint:`When a background tab finishes or pauses on an approval.`,toast:`Toast`,toastHint:`bottom-right popup`,sound:`Sound`,soundHint:`bell + chime + an OSC 9 desktop notification (rides SSH)`,soundVolume:`Chime volume — {percent}%`,soundVolumeHint:`enter cycles; applies to the next chime`,crossTask:`Cross-task`,crossTaskHint:`also for a task you switched away from`,keyHints:`Keyboard hints`,keyHintsHint:`The status-bar reminder and the first-use hints in the sidebar and files panes.`,keyHintsShow:`Show keyboard hints`,keyHintsShowHint:`re-enabling relights hints dismissed by use`,zen:`Zen mode`,zenHint:"The `zen` chip and `prefix`+z hide Files, keeping the Tasks rail and workspace.",zenDefaultOn:`Start in zen mode`,updates:`Updates`,updatesHint:`Stable releases are cut by hand; the nightly preview is built from main every day.`,updateChannel:`Channel: {channel}`,updateChannelHint:"enter switches; `rove update` follows it",updateChannelName:{latest:`stable`,nightly:`nightly preview`},updateTry:{latest:`[ Back to stable ]`,nightly:`[ Try the nightly preview ]`},updateTryHint:`installs it now and follows that channel`,updateTryTitle:{latest:`Go back to stable?`,nightly:`Install the nightly preview?`},updateTryBody:{latest:`Rove installs the latest stable release, which can be older than this nightly, then quits.`,nightly:"Rove installs today's nightly build of main, then quits. It is newer and less tested; `rove update --stable` goes back."},railFold:`Folded task rail`,railFoldHint:`What the rail shows once folded away from its corner control.`,railFoldRow:`Folded rail shows: {style}`,railFoldRowHint:`enter cycles`,railFoldGlyphs:`status glyphs`,railFoldInitials:`glyph + initials`,railFoldHairline:`colour band only`,editor:`Editor`,editorHint:`What enter opens a file with in the file tree — diff mode when the editor supports it, the read-only preview when it isn't installed.`,editorRow:`editor: < {kind} >`,editorRowHint:`auto follows $VISUAL / $EDITOR, else nvim / vim / emacs / nano`,editorCustom:`custom: {cmd}`,editorCustomUnset:`(unset — enter to edit)`,worktree:`Worktree location`,worktreeHint:`Where new task worktrees are created. New tasks only.`,worktreeBase:`location: < {kind} >`,worktreeBaseHint:"custom takes `~`, a relative path, or a leading `$project_dir`",worktreeKindDefault:`default ~/.rove/worktrees`,worktreeKindNext:`next to project`,worktreeKindCustom:`custom`,worktreeCustom:`custom: {path}`,worktreeCustomUnset:`(unset — enter to edit)`,worktreeBaseTitle:`Custom worktree location (blank = default; $project_dir = project root)`,worktreeBaseField:`PATH`,editorCustomTitle:`Custom editor command (use {file} for the path)`,worktreeBaseInvalidTitle:`Can't use that worktree location`,worktreeBaseTokenBody:`{token} only expands as the leading path segment (e.g. {token}/../rove-worktrees). Keeping the previous setting.`,worktreeBaseUnusableBody:`{path} isn't usable ({error}). Keeping the previous setting — pick a writable directory.`,terminal:`Terminal`,terminalHint:`Applies to terminals opened after the change.`,scrollbackRow:`scrollback: {rows} rows`,scrollbackRowHint:`100–100000 · larger costs proportionally more CPU per redraw`,scrollbackTitle:`Terminal scrollback rows (100–100000)`,scrollbackField:`ROWS`,scrollbackInvalidTitle:`Not a number`,scrollbackInvalidBody:`Scrollback must be a number of rows (e.g. 1000). Keeping the previous setting.`,tabStripRow:`tab strip: {mode}`,tabStripMode:{never:`off — the sidebar tree lists tabs`,multipleOnly:`only with 2+ tabs`,always:`always`}},field:{command:`COMMAND`,name:`NAME`,id:`ID`},action:{save:`save`,next:`next`,add:`add`},reset:{title:`Reset UI state?`,body:`Wipes ~/.config/rove/state.json and ~/.rove/tasks.json, then quits Rove — relaunch for a fresh start with an empty working session list. Worktrees on disk and engine session history are NOT touched.`,done:`Rove: UI state reset. Relaunch Rove to start fresh.`,failedTitle:`UI state was not reset`,failedBody:`Could not write the settings file. Your settings and tasks have been kept. Try resetting again.`},restart:{title:`Restart backend?`,body:`Stops the daemon and relaunches this Rove on the installed build, so daemon / orchestrator / engine edits take effect. Running engine sessions live in the PTY host and keep going; open tabs come back. Any other attached windows reconnect on their own.`,done:`Rove: restarting the backend...`},stateWrite:{failedTitle:`Settings were not saved`,failedBody:`{file} could not be written ({keys}). Check its directory permissions and free disk space, then save again.`},...$r,...ri,...ai,keybindings:{title:`Keybindings`,hint:`Rebind direct and prefix chords in your own YAML file; changes reload live. Press F1 anywhere for the live keymap with every binding id.`,configFile:`Config file`,notCreated:` (not created yet)`,prefixTitle:`Command layer ({prefix})`,prefixHint:`Bare keys act in the focused pane; a small one-press set covers frequent Rove actions; {prefix} opens the command layer ({timeout}ms second-stroke window). Prefix bindings keep their pane scope and modal rules.`,tapPresentation:`Prefix tap`,tapPresentationHint:`Choose whether the complete guide also marks controls already on screen.`,tapPresentationLocal:`On-screen entries + complete guide (default)`,tapPresentationGuide:`Complete guide only`,prefixDisabled:`disabled`,fixed:`Fixed (not rebindable): {ids}.`,createHint:`No overrides file yet. Rove can write one for you, fully commented — nothing is rebound until you uncomment a line.`,createFile:`[enter] Create keybindings.yaml`,overridesApplied:`Overrides applied`,none:`none`,unbound:`(unbound)`,defaultKeys:`default: {keys}`,warnings:`Warnings`},feedback:{title:`Feedback`,hint:"Sends a GitHub Discussion to the Rove repo through `gh`. Requires `gh auth login`; category defaults to Feedback.",titleLabel:`title`,titlePlaceholder:`Short summary`,descriptionLabel:`description`,descriptionPlaceholder:`What happened? (enter for a new line · tab to Send)`,send:`[enter] Send to GitHub Discussions`},...ti},zh:{appearance:{enabled:`开启`,disabled:`关闭`,singleRow:`单行`,doubleRow:`双行`,borderFlow:`流动渐变`,borderStill:`静止`,glyphsBraille:`盲文点`,glyphsStarburst:`星芒(需要含 Dingbats 符号区的字体)`,glyphsAscii:`ASCII`,titleShimmer:`流光`,titleStill:`静止`,preview:`工作区预览`,tasks:`任务`,terminal:`终端`,files:`文件`,testsPassed:`测试通过`,modelDetail:`模型 · 推理强度`,transparent:`透明背景`,opaque:`不透明背景`,modeDark:`深色`,modeLight:`浅色`,modeAuto:`自动(跟随终端)`,openHint:`按 Enter 打开选项和预览。`,chooseHint:`↑/↓ 或 j/k 预览 · enter 应用 · esc 取消`},title:`设置`,esc:`esc`,nav:{default:`j/k 选择 · h/l 切换层级 · enter 确认 · esc 关闭`,feedback:`tab 下一项 · enter 在发送项发送 · esc 关闭`},sections:{general:`通用`,autoRouting:`自动路由`,engines:`引擎`,plugins:`插件`,marketplace:`插件市场`,keys:`快捷键`,feedback:`反馈`,dev:`开发`},general:{usage:`用量`,theme:`主题`,themeMode:`明暗`,themeHint:`l 进入列表 · j/k 高亮 · enter 应用`,language:`语言`,languageHint:`Rove 界面的显示语言。l 进入列表 · j/k 高亮 · enter 应用。`,transparent:`透明背景`,transparentHint:`去掉渲染器的背景填充,让宿主终端透出来。按 enter 切换。`,on:`[x] 开`,off:`[ ] 关`,focusAccent:`聚焦强调色`,focusAccentHint:`聚焦面板标题、▌ 标记和分隔边框的颜色。`,accentPrimary:`主色(品牌强调色)`,accentSuccess:`成功色(传统绿)`,accentInfo:`信息色(冷蓝)`,appearance:`外观`,appearanceHint:`分屏面板怎么画边。`,splitStyle:`分屏面板`,tabRowHeight:`Tab 行高`,tabRowHeightHint:`两格会在引擎 tab 下面加一行模型和推理档位,可见行数减半。`,tabRowHeightRow:`引擎 tab 行占 {cells} 格`,tabRowHeightRowHint:`enter 切换`,workingBorder:`运行中边框`,taskColors:`任务配色`,glyphSet:`状态符号`,colorblind:`色盲友好的增删配色`,runningTitle:`运行中标题`,splitBox:`方框边框`,splitLine:`单线分隔`,splitRail:`左侧强调条`,splitRule:`顶部横线`,notifications:`通知`,notificationsHint:`后台标签完成或在审批处暂停时触发。`,toast:`Toast 弹窗`,toastHint:`右下角弹窗`,sound:`声音`,soundHint:`响铃 + 提示音 + OSC 9 桌面通知(经 SSH 直达本地)`,soundVolume:`提示音音量 — {percent}%`,soundVolumeHint:`回车循环切换;下一声提示音生效`,crossTask:`跨任务`,crossTaskHint:`你已切走的任务也通知`,keyHints:`键盘提示`,keyHintsHint:`状态栏提醒,以及侧栏和文件面板的首用提示。`,keyHintsShow:`显示键盘提示`,keyHintsShowHint:`重新开启会点亮已因使用而熄灭的提示`,zen:`禅模式`,zenHint:"`zen` 标记和 `prefix`+z 隐藏 Files,保留 Tasks 侧栏与 workspace。",zenDefaultOn:`启动即进入禅模式`,updates:`更新`,updatesHint:`稳定版手动发布;nightly 预览版每天从 main 自动构建。`,updateChannel:`渠道:{channel}`,updateChannelHint:"enter 切换;`rove update` 跟随它",updateChannelName:{latest:`稳定版`,nightly:`nightly 预览版`},updateTry:{latest:`[ 回到稳定版 ]`,nightly:`[ 试用 nightly 预览版 ]`},updateTryHint:`立即安装并改为跟随该渠道`,updateTryTitle:{latest:`回到稳定版?`,nightly:`安装 nightly 预览版?`},updateTryBody:{latest:`Rove 会安装最新稳定版(可能比当前 nightly 旧),然后退出。`,nightly:"Rove 会安装今天从 main 构建的 nightly,然后退出。它更新、但测试更少;`rove update --stable` 可回到稳定版。"},railFold:`折叠后的任务栏`,railFoldHint:`任务栏从角标折叠之后显示什么。`,railFoldRow:`折叠后显示:{style}`,railFoldRowHint:`enter 切换`,railFoldGlyphs:`状态字形`,railFoldInitials:`字形 + 首字母`,railFoldHairline:`仅色带`,editor:`编辑器`,editorHint:`文件树里按 enter 用什么打开文件——支持时走编辑器 diff 模式,未安装时回退到只读预览。`,editorRow:`编辑器: < {kind} >`,editorRowHint:`auto 跟随 $VISUAL / $EDITOR,否则 nvim / vim / emacs / nano`,editorCustom:`自定义: {cmd}`,editorCustomUnset:`(未设置 — enter 编辑)`,worktree:`工作树位置`,worktreeHint:`新任务工作树的创建位置。仅对新任务生效。`,worktreeBase:`位置: < {kind} >`,worktreeBaseHint:"自定义可填 `~`、相对路径或以 `$project_dir` 开头",worktreeKindDefault:`默认 ~/.rove/worktrees`,worktreeKindNext:`项目旁边`,worktreeKindCustom:`自定义`,worktreeCustom:`自定义: {path}`,worktreeCustomUnset:`(未设置 — enter 编辑)`,worktreeBaseTitle:`自定义工作树位置(留空 = 默认;$project_dir = 项目根目录)`,worktreeBaseField:`路径`,editorCustomTitle:`自定义编辑器命令(用 {file} 代表文件路径)`,worktreeBaseInvalidTitle:`无法使用该工作树位置`,worktreeBaseTokenBody:`{token} 只能作为路径的第一段展开(如 {token}/../rove-worktrees)。保留原设置。`,worktreeBaseUnusableBody:`{path} 不可用({error})。保留原设置 —— 请选择一个可写目录。`,terminal:`终端`,terminalHint:`对修改后新打开的终端生效。`,scrollbackRow:`回滚行数: {rows} 行`,scrollbackRowHint:`100–100000 · 调大会按比例增加每次重绘的 CPU`,scrollbackTitle:`终端回滚行数(100–100000)`,scrollbackField:`行数`,scrollbackInvalidTitle:`不是数字`,scrollbackInvalidBody:`回滚行数必须是数字(如 1000)。保留原设置。`,tabStripRow:`标签栏: {mode}`,tabStripMode:{never:`关闭 — 标签在左侧树里`,multipleOnly:`仅 2 个以上标签时显示`,always:`始终显示`}},field:{command:`命令`,name:`名称`,id:`标识`},action:{save:`保存`,next:`下一步`,add:`添加`},reset:{title:`重置界面状态?`,body:`将清除 ~/.config/rove/state.json 和 ~/.rove/tasks.json 并退出 Rove —— 重新启动后会是一个干净的开始,工作会话列表为空。磁盘上的工作树和引擎会话历史不受影响。`,done:`Rove:界面状态已重置。重新启动 Rove 即可从头开始。`,failedTitle:`UI 状态未能重置`,failedBody:`无法写入设置文件。设置和任务均已保留,请稍后重新尝试重置。`},restart:{title:`重启后端?`,body:`会停掉 daemon,并以已安装的版本重新启动当前 Rove 窗口,从而让 daemon / orchestrator / 引擎的改动生效。正在运行的引擎会话由 PTY host 托管,不会中断;已打开的标签页会恢复。其他已连接的窗口会自行重连。`,done:`Rove:正在重启后端……`},stateWrite:{failedTitle:`设置未能保存`,failedBody:`{file} 写入失败({keys})。请检查目录权限和磁盘空间,再次保存。`},...ei,...ii,...oi,keybindings:{title:`快捷键`,hint:`在你自己的 YAML 文件里重绑定直接按键和 prefix 组合;修改会实时加载。任意位置按 F1 查看带每个绑定 id 的实时键位表。`,configFile:`配置文件`,notCreated:` (尚未创建)`,prefixTitle:`命令层({prefix})`,prefixHint:`裸键作用于当前聚焦面板;少量单次快捷键覆盖高频 Rove 操作;{prefix} 打开命令层(第二击窗口 {timeout}ms)。Prefix 绑定保持原有的面板作用域和 modal 规则。`,tapPresentation:`点按 Prefix`,tapPresentationHint:`选择完整指南是否同时标记当前屏幕上的入口。`,tapPresentationLocal:`屏幕入口 + 完整指南(默认)`,tapPresentationGuide:`仅完整指南`,prefixDisabled:`已禁用`,fixed:`固定(不可重绑定):{ids}。`,createHint:`还没有覆盖文件。Rove 可以帮你写一份带完整注释的——在你取消注释之前不会改动任何按键。`,createFile:`[enter] 创建 keybindings.yaml`,overridesApplied:`已应用的覆盖`,none:`无`,unbound:`(已解绑)`,defaultKeys:`默认: {keys}`,warnings:`警告`},feedback:{title:`反馈`,hint:"通过 `gh` 向 Rove 仓库发一条 GitHub Discussion。需要 `gh auth login`;分类默认为 Feedback。",titleLabel:`标题`,titlePlaceholder:`简短概括`,descriptionLabel:`描述`,descriptionPlaceholder:`发生了什么?(enter 换行 · tab 跳到发送)`,send:`[enter] 发送到 GitHub Discussions`},...ni}},ci={en:we,zh:Te};function H(e,t){return E(si,e,t)}function li(e,t){return E(ci,e,t)}var ui=`rove.prefs`,di={locale:`en`,theme:`claude`,themeMode:`dark`,transparent:!0,focusAccent:`primary`,splitStyle:`line`,railFold:`glyphs`,tabRowHeight:1,workingBorder:`flow`,taskColors:`on`,glyphSet:`braille`,colorblind:`off`,runningTitle:`shimmer`,toast:!0,sound:!0,soundVolume:.4,crossTask:!0,keyHints:!0,zen:!0,editorKind:`auto`,worktreeBase:`default`,scrollbackRows:1e3,tabStrip:`never`,prefixTap:`local`,remoteProjects:!1,autoStatus:!1,dispatcher:!1};function fi(){try{let e=JSON.parse(localStorage.getItem(ui)??`null`);if(e&&typeof e==`object`&&`prefs`in e&&`themes`in e)return{...e,loaded:!0}}catch{}return{loaded:!1,prefs:di,options:{},info:{editorCustomSet:!1,worktreeCustomPath:``},themes:[],glyphSets:{}}}var pi=_(fi());function mi(e){(e.locale===`en`||e.locale===`zh`)&&S.set(e.locale)}mi(pi.get().prefs);function hi(e){let t={loaded:!0,prefs:e.prefs,options:e.options,info:e.info,themes:e.themes,glyphSets:e.glyphSets};pi.set(t),mi(t.prefs),localStorage.setItem(ui,JSON.stringify(t))}async function gi(e){hi(await e.request(`prefs.get`))}async function _i(e,t,n){let r=pi.get();pi.set({...r,prefs:{...r.prefs,[t]:n}}),mi(pi.get().prefs);try{let r=await e.request(`prefs.set`,{key:t,value:n});hi({...pi.get(),prefs:r.prefs})}catch(e){pi.set(r),mi(r.prefs),L(e instanceof Error?e.message:String(e),`error`)}}function vi(){return v(pi)}function yi(e,t){let n=e.options[t];return Array.isArray(n)?n:[]}function bi(e,t){return e[(e.indexOf(t)+1)%e.length]??t}function xi(e){return(0,z.jsxs)(`section`,{className:`settings-group`,children:[(0,z.jsx)(`h2`,{className:`kicker`,children:e.title}),e.hint&&(0,z.jsx)(`p`,{className:`muted`,children:e.hint}),e.children]})}function Si(e){return(0,z.jsxs)(`label`,{className:`pref-row`,children:[(0,z.jsx)(`input`,{type:`checkbox`,checked:e.checked,disabled:e.disabled,onChange:t=>e.onChange(t.target.checked)}),(0,z.jsx)(`span`,{className:`pref-label`,children:e.label}),e.hint&&(0,z.jsx)(`span`,{className:`pref-hint muted`,children:e.hint})]})}function Ci(e){return(0,z.jsxs)(`fieldset`,{className:`pref-field`,children:[(0,z.jsx)(`legend`,{className:`pref-label`,children:e.label}),(0,z.jsx)(`div`,{className:`chips-row`,children:e.picks.map(t=>(0,z.jsx)(`button`,{type:`button`,"aria-pressed":t.value===e.value,className:`chip-button ${t.value===e.value?`is-active`:``}`,onClick:()=>t.value!==e.value&&e.onPick(t.value),children:t.label},t.value))}),e.hint&&(0,z.jsx)(`p`,{className:`pref-hint muted`,children:e.hint})]})}function wi(e){return(0,z.jsxs)(`button`,{type:`button`,className:`pref-cycle`,disabled:e.disabled,onClick:e.onCycle,children:[(0,z.jsx)(`span`,{className:`pref-label`,children:e.label}),e.hint&&(0,z.jsx)(`span`,{className:`pref-hint muted`,children:e.hint})]})}function Ti(e){return(0,z.jsxs)(`div`,{className:`pref-readonly`,children:[(0,z.jsx)(`span`,{className:`pref-label mono`,children:e.label}),(0,z.jsx)(`span`,{className:`pref-hint muted`,children:e.note})]})}var Ei=[{key:`remoteProjects`,label:`dev.remote`,hint:`dev.remoteHint`},{key:`autoStatus`,label:`dev.autoStatus`,hint:`dev.autoStatusHint`},{key:`dispatcher`,label:`dev.dispatcher`,hint:`dev.dispatcherHint`}];function Di({client:e}){let{prefs:t}=vi(),[n,r]=(0,m.useState)(null),[i,a]=(0,m.useState)(!1),o=async()=>{if(n){a(!0);try{if(n===`reset`){await e.request(`dev.reset`),localStorage.removeItem(`rove.prefs`),window.location.reload();return}await e.request(`daemon.restart`),L(H(`restart.done`)),r(null)}catch(e){L(B(e),`error`)}finally{a(!1)}}},s=(e,t,a,s,c)=>(0,z.jsx)(xi,{title:t,hint:a,children:n===e?(0,z.jsxs)(`div`,{className:`confirm-inline`,children:[(0,z.jsx)(`strong`,{children:H(`${e}.title`)}),(0,z.jsx)(`p`,{className:`muted`,children:T(e===`reset`?`prefs.resetBody`:`prefs.restartBody`)}),(0,z.jsxs)(`div`,{className:`actions`,children:[(0,z.jsx)(`button`,{type:`button`,className:`link`,onClick:()=>r(null),children:T(`dialog.cancel`)}),(0,z.jsx)(`button`,{type:`button`,className:`button ${c?`is-danger`:``}`,disabled:i,onClick:()=>void o(),children:s})]})]}):(0,z.jsx)(`button`,{type:`button`,className:`pref-cycle`,onClick:()=>r(e),children:(0,z.jsx)(`span`,{className:`pref-label`,children:s})})});return(0,z.jsxs)(z.Fragment,{children:[s(`reset`,H(`dev.reset`),T(`prefs.resetHint`),T(`prefs.resetButton`),!0),s(`restart`,H(`dev.restart`),T(`prefs.restartHint`),T(`prefs.restartButton`),!1),(0,z.jsx)(`p`,{className:`muted`,children:H(`dev.doctorHint`)}),(0,z.jsx)(xi,{title:H(`dev.experimental`),children:Ei.map(n=>(0,z.jsx)(Si,{label:H(n.label),hint:H(n.hint),checked:t[n.key],onChange:t=>void _i(e,n.key,t)},n.key))})]})}var Oi={installed:{key:`engines.hookInstalled`,warn:!1},outdated:{key:`engines.hookOutdated`,warn:!0},"not-installed":{key:`engines.hookMissing`,warn:!0}};function ki({engine:e}){let t=e.hooks!==`unsupported`,n=t&&e.hooks===`not-installed`&&e.binaryFound===!1,r=t&&!n?Oi[e.hooks]:void 0,i=H(r?r.key:n?`engines.hookUnavailable`:`engines.hookNone`);return(0,z.jsxs)(`span`,{className:`engine-detail mono`,children:[(0,z.jsx)(`span`,{className:r?r.warn?`tone-warning`:`tone-success`:`muted`,children:i}),` · `,(0,z.jsx)(`span`,{className:e.markers?``:`muted`,children:H(e.markers?`engines.markersYes`:`engines.markersNo`)}),` · `,(0,z.jsx)(`span`,{className:e.screen?``:`muted`,children:H(e.screen?`engines.screenYes`:`engines.screenNo`)}),e.configIssue&&(0,z.jsxs)(`span`,{className:`tone-attention`,children:[` · ! `,e.configIssue]})]})}function Ai({client:e}){let[t,n]=(0,m.useState)(null),[r,i]=(0,m.useState)(null),a=(0,m.useCallback)(()=>e.request(`engines.settings`).then(e=>n(e.engines),e=>L(B(e),`error`)),[e]);(0,m.useEffect)(()=>{a()},[a]);let o=(t,n={})=>void e.request(t,n).then(a).catch(e=>L(B(e),`error`));if(!t)return(0,z.jsx)(`p`,{className:`placeholder-line`,children:T(`preview.loading`)});let s=t.filter(e=>e.hooks!==`unsupported`),c=s.filter(e=>e.hooks!==`installed`).length,l=s.filter(e=>e.hooks!==`not-installed`).length;return(0,z.jsxs)(`section`,{className:`settings-group`,children:[(0,z.jsx)(`p`,{className:`muted`,children:T(`settings.engines.hint`)}),(0,z.jsx)(`div`,{className:`settings-rows`,children:t.map(e=>(0,z.jsxs)(`div`,{className:`engine-row`,children:[(0,z.jsx)(`label`,{className:`engine-check`,children:(0,z.jsx)(`input`,{type:`checkbox`,checked:e.enabled,"aria-label":T(`settings.engines.enabled`,{name:e.name}),onChange:()=>o(`engine.setEnabled`,{id:e.id,enabled:!e.enabled})})}),(0,z.jsx)(`label`,{className:`engine-check`,children:(0,z.jsx)(`input`,{type:`radio`,name:`default-engine`,checked:e.isDefault,disabled:!e.canBeDefault,"aria-label":T(`settings.engines.default`,{name:e.name}),onChange:()=>o(`engine.setDefault`,{id:e.id})})}),(0,z.jsxs)(`div`,{className:`engine-main`,children:[r?.id===e.id?(0,z.jsx)(`form`,{onSubmit:t=>{t.preventDefault(),o(`engine.rename`,{id:e.id,name:r.value}),i(null)},children:(0,z.jsx)(`input`,{className:`input`,autoFocus:!0,value:r.value,placeholder:T(`settings.engines.namePlaceholder`),onChange:t=>i({id:e.id,value:t.target.value}),onKeyDown:e=>{e.key===`Escape`&&(e.stopPropagation(),i(null))}})}):(0,z.jsxs)(`span`,{className:`engine-name`,children:[e.name,e.custom&&(0,z.jsx)(`span`,{className:`muted`,children:H(`engines.customTag`)})]}),(0,z.jsxs)(`span`,{className:`mono muted engine-detail`,children:[e.binaryFound===!1?T(`settings.engines.binaryMissing`,{binary:e.binary}):e.binaryPath??e.binary,` · `,e.login===`yes`?T(`settings.engines.loginReady`):e.login===`no`?T(`settings.engines.loginMissing`):T(`settings.engines.loginUnknown`)]}),(0,z.jsx)(ki,{engine:e})]}),(0,z.jsxs)(`div`,{className:`engine-actions`,children:[(0,z.jsx)(`button`,{type:`button`,className:`link`,onClick:()=>i({id:e.id,value:e.name}),children:T(`settings.engines.rename`)}),(e.custom||e.customized)&&(0,z.jsx)(`button`,{type:`button`,className:`link`,onClick:()=>o(`engine.reset`,{id:e.id}),children:e.custom?T(`settings.engines.remove`):T(`settings.engines.reset`)})]})]},e.id))}),(0,z.jsxs)(`div`,{className:`hook-rows`,children:[(0,z.jsx)(`button`,{type:`button`,className:`link`,onClick:()=>o(`engines.hooks.install`),children:c>0?H(`engines.installHooks`,{count:c}):H(`engines.installHooksDone`)}),(0,z.jsx)(`button`,{type:`button`,className:`link`,onClick:()=>o(`engines.hooks.uninstall`),children:l>0?H(`engines.uninstallHooks`,{count:l}):H(`engines.uninstallHooksDone`)})]})]})}function ji({client:e}){let[t,n]=(0,m.useState)(``),[r,i]=(0,m.useState)(``),[a,o]=(0,m.useState)(!1);return(0,z.jsxs)(`form`,{className:`settings-group`,onSubmit:a=>{a.preventDefault(),!(!t.trim()||!r.trim())&&(o(!0),e.request(`feedback.send`,{title:t.trim(),body:r}).then(e=>{L(T(`settings.feedback.sent`,{url:e.discussion?.url??``})),n(``),i(``)}).catch(e=>L(B(e),`error`)).finally(()=>o(!1)))},children:[(0,z.jsx)(`p`,{className:`muted`,children:T(`settings.feedback.hint`)}),(0,z.jsxs)(`label`,{className:`field`,children:[(0,z.jsx)(`span`,{className:`kicker`,children:T(`settings.feedback.titleLabel`)}),(0,z.jsx)(`input`,{className:`input`,value:t,onChange:e=>n(e.target.value)})]}),(0,z.jsxs)(`label`,{className:`field`,children:[(0,z.jsx)(`span`,{className:`kicker`,children:T(`settings.feedback.body`)}),(0,z.jsx)(`textarea`,{className:`input textarea`,rows:6,value:r,onChange:e=>i(e.target.value)})]}),(0,z.jsx)(`div`,{className:`actions`,children:(0,z.jsx)(`button`,{type:`submit`,className:`button`,disabled:a||!t.trim()||!r.trim(),children:T(`settings.feedback.send`)})})]})}var Mi=`/assets/pulse-3XJkP4CJ.wav`;function Ni(e,t){return e===`error`||t}function Pi(e,t){return t&&e.silent!==!0}function Fi(e){return e===`permission_needed`?`needs_input`:e===`error`||e===`rate_limited`||e===`dead`?`error`:e===`turn_complete`?`done`:null}function Ii(e,t,n,r){if(e===null)return[];let i=[];for(let[a,o]of t){if(a===n||e.get(a)===o)continue;let t=r(o);t&&i.push({key:a,kind:t})}return i}var Li={done:`✓`,needs_input:`?`,error:`✕`};function Ri(e){let t=new Audio(Mi);t.volume=Math.min(1,Math.max(0,e)),t.play().catch(()=>void 0)}function zi(e,t){!document.hidden||typeof Notification>`u`||Notification.permission!==`granted`||new Notification(`Rove — ${e}`,{body:t})}function Bi(){typeof Notification<`u`&&Notification.permission==="default"&&Notification.requestPermission()}function Vi(e){let t=new Map;for(let n of e.tasks)n.activity&&t.set(n.id,n.activity.state);return t}function Hi(e){let t=(0,m.useRef)(null);(0,m.useEffect)(()=>{let n=()=>{let n=e.tasks.get();if(!n)return;let r=Vi(n),i=Ii(t.current,r,null,Fi);t.current=r;let{prefs:a}=pi.get();if(!a.crossTask)return;let o=e.selection.get().taskId,s=new Map(n.tasks.map(e=>[e.id,e.title]));for(let{key:e,kind:t}of i){if(e===o)continue;let n=s.get(e)??e;Ni(t,a.toast)&&L(`${Li[t]} ${n}`,t===`error`?`error`:`info`),Pi({},a.sound)&&(Ri(a.soundVolume),zi(n,Li[t]))}};return n(),e.tasks.subscribe(n)},[e])}var Ui={themeMode:{dark:`appearance.modeDark`,light:`appearance.modeLight`,auto:`appearance.modeAuto`},focusAccent:{primary:`general.accentPrimary`,success:`general.accentSuccess`,info:`general.accentInfo`},splitStyle:{box:`general.splitBox`,line:`general.splitLine`,rail:`general.splitRail`,rule:`general.splitRule`},railFold:{glyphs:`general.railFoldGlyphs`,initials:`general.railFoldInitials`,hairline:`general.railFoldHairline`},tabRowHeight:{1:`appearance.singleRow`,2:`appearance.doubleRow`},workingBorder:{flow:`appearance.borderFlow`,still:`appearance.borderStill`},taskColors:{on:`appearance.enabled`,off:`appearance.disabled`},glyphSet:{braille:`appearance.glyphsBraille`,starburst:`appearance.glyphsStarburst`,ascii:`appearance.glyphsAscii`},colorblind:{on:`appearance.enabled`,off:`appearance.disabled`},runningTitle:{shimmer:`appearance.titleShimmer`,still:`appearance.titleStill`}},Wi=[{key:`theme`,label:`general.theme`},{key:`themeMode`,label:`general.themeMode`},{key:`transparent`,label:`general.transparent`,terminalOnly:!0},{key:`focusAccent`,label:`general.focusAccent`,hint:`general.focusAccentHint`},{key:`splitStyle`,label:`general.splitStyle`,terminalOnly:!0},{key:`railFold`,label:`general.railFold`,hint:`general.railFoldHint`},{key:`tabRowHeight`,label:`general.tabRowHeight`,hint:`general.tabRowHeightHint`},{key:`workingBorder`,label:`general.workingBorder`},{key:`taskColors`,label:`general.taskColors`},{key:`glyphSet`,label:`general.glyphSet`},{key:`colorblind`,label:`general.colorblind`},{key:`runningTitle`,label:`general.runningTitle`}];function Gi({client:e}){let t=vi(),n=(t,n)=>void _i(e,t,n);return(0,z.jsx)(xi,{title:H(`general.appearance`),children:Wi.map(e=>{let r=[e.hint?H(e.hint):null,e.terminalOnly?T(`prefs.terminalOnly`):null].filter(Boolean).join(` `);if(e.key===`transparent`)return(0,z.jsx)(Si,{label:H(e.label),hint:r,checked:t.prefs.transparent,onChange:e=>n(`transparent`,e)},e.key);let i=Ui[e.key],a=(e.key===`theme`?t.themes.map(e=>e.name):yi(t,e.key)).map(t=>({value:t,label:e.key===`theme`?String(t):e.key===`themeMode`&&t===`auto`?T(`prefs.modeAuto`):H(i?.[String(t)]??String(t))}));return(0,z.jsx)(Ci,{label:H(e.label),hint:r||void 0,value:t.prefs[e.key],picks:a,onPick:t=>n(e.key,t)},e.key)})})}var Ki=[{value:`en`,label:`English`},{value:`zh`,label:`中文`}],qi={default:`general.worktreeKindDefault`,nextToProject:`general.worktreeKindNext`,custom:`general.worktreeKindCustom`};function Ji({client:e}){let t=vi(),{prefs:n,info:r}=t,i=()=>pi.get().prefs,a=(t,n)=>void _i(e,t,n),[o,s]=(0,m.useState)(null);(0,m.useEffect)(()=>{e.request(`daemon.info`).then(s,()=>s(null))},[e]);let c=()=>{let e=i().worktreeBase;return e==="default"?`nextToProject`:e===`nextToProject`&&r.worktreeCustomPath?`custom`:`default`};return(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(Ci,{label:H(`general.language`),hint:T(`prefs.languageHint`),value:n.locale,picks:Ki,onPick:e=>a(`locale`,e)}),(0,z.jsx)(Gi,{client:e}),(0,z.jsxs)(xi,{title:H(`general.notifications`),hint:H(`general.notificationsHint`),children:[(0,z.jsx)(Si,{label:H(`general.toast`),hint:T(`prefs.toastHint`),checked:n.toast,onChange:e=>a(`toast`,e)}),(0,z.jsx)(Si,{label:H(`general.sound`),hint:T(`prefs.soundHint`),checked:n.sound,onChange:e=>{e&&Bi(),a(`sound`,e)}}),(0,z.jsx)(wi,{label:H(`general.soundVolume`,{percent:Math.round(n.soundVolume*100)}),hint:T(`prefs.soundVolumeHint`),onCycle:()=>{let e=bi(yi(t,`soundVolume`),i().soundVolume);i().sound&&Ri(e),a(`soundVolume`,e)}}),(0,z.jsx)(Si,{label:H(`general.crossTask`),hint:H(`general.crossTaskHint`),checked:n.crossTask,onChange:e=>a(`crossTask`,e)})]}),(0,z.jsx)(xi,{title:H(`general.keyHints`),hint:T(`prefs.keyHintsHint`),children:(0,z.jsx)(Si,{label:H(`general.keyHintsShow`),hint:H(`general.keyHintsShowHint`),checked:n.keyHints,onChange:e=>a(`keyHints`,e)})}),(0,z.jsx)(xi,{title:H(`general.zen`),hint:T(`prefs.zenHint`),children:(0,z.jsx)(Si,{label:H(`general.zenDefaultOn`),checked:n.zen,onChange:e=>a(`zen`,e)})}),(0,z.jsxs)(xi,{title:H(`general.editor`),hint:H(`general.editorHint`),children:[(0,z.jsx)(wi,{label:H(`general.editorRow`,{kind:n.editorKind}),hint:H(`general.editorRowHint`),onCycle:()=>a(`editorKind`,bi(yi(t,`editorKind`),i().editorKind))}),(0,z.jsx)(Ti,{label:H(`general.editorCustom`,{cmd:r.editorCustomSet?T(`prefs.editorCustomSet`):H(`general.editorCustomUnset`)}),note:T(`prefs.editInTui`)})]}),(0,z.jsxs)(xi,{title:H(`general.worktree`),hint:H(`general.worktreeHint`),children:[(0,z.jsx)(wi,{label:H(`general.worktreeBase`,{kind:H(qi[n.worktreeBase])}),hint:H(`general.worktreeBaseHint`),onCycle:()=>a(`worktreeBase`,c())}),(0,z.jsx)(Ti,{label:H(`general.worktreeCustom`,{path:r.worktreeCustomPath||H(`general.worktreeCustomUnset`)}),note:T(`prefs.editInTui`)})]}),(0,z.jsxs)(xi,{title:H(`general.terminal`),hint:H(`general.terminalHint`),children:[(0,z.jsx)(Yi,{client:e}),(0,z.jsx)(wi,{label:H(`general.tabStripRow`,{mode:H(`general.tabStripMode.${n.tabStrip}`)}),onCycle:()=>a(`tabStrip`,bi(yi(t,`tabStrip`),i().tabStrip))})]}),o?.daemonVersion&&(0,z.jsx)(xi,{title:T(`settings.general.daemon`),children:(0,z.jsx)(`p`,{className:`mono ${o.stale?`tone-warning`:`muted`}`,children:T(o.stale?`settings.general.daemonStale`:`settings.general.daemonCurrent`,{version:o.daemonVersion})})})]})}function Yi({client:e}){let t=vi(),n=t.options.scrollbackRows,r=n&&`min`in n?n:{min:100,max:1e5},[i,a]=(0,m.useState)(String(t.prefs.scrollbackRows));return(0,m.useEffect)(()=>a(String(t.prefs.scrollbackRows)),[t.prefs.scrollbackRows]),(0,z.jsxs)(`label`,{className:`pref-row`,children:[(0,z.jsx)(`span`,{className:`pref-label`,children:H(`general.scrollbackTitle`)}),(0,z.jsx)(`input`,{className:`input pref-number`,inputMode:`numeric`,value:i,"aria-label":H(`general.scrollbackField`),onChange:e=>a(e.target.value),onBlur:()=>{let n=Number(i);if(i.trim()===``||!Number.isInteger(n)){a(String(t.prefs.scrollbackRows));return}let o=Math.min(r.max,Math.max(r.min,n));o===t.prefs.scrollbackRows?a(String(o)):_i(e,`scrollbackRows`,o)},onKeyDown:e=>e.key===`Enter`&&e.currentTarget.blur()}),(0,z.jsx)(`span`,{className:`pref-hint muted`,children:H(`general.scrollbackRowHint`)})]})}[...Array.from({length:12},(e,t)=>`f${t+1}`)];var Xi={"diff.review.cursor":`diff-review cursor is a fixed raw binding (j/k), not keymap-driven`,"diff.review.range":`diff-review range anchor is a fixed raw binding (v), not keymap-driven`,"diff.review.note":`diff-review note is a fixed raw binding (c), not keymap-driven`,"diff.review.send":`diff-review send is a fixed raw binding (s), not keymap-driven`,"diff.review.drop":`diff-review drop-note is a fixed raw binding (x), not keymap-driven`,"diff.review.reload":`preview reload is a fixed raw binding (r), not keymap-driven`};function Zi(e,t){let n=`alternating [${e}, ${t}] pairs`;return{layout:n,validateCount:e=>e>=2&&e%2==0?null:`needs ${n} (an even number of chords — got ${e})`}}Zi(`top (double-tap)`,`bottom`),Zi(`down`,`up`),Zi(`down`,`up`),Zi(`down`,`up`),Zi(`collapse`,`expand`),Zi(`previous tab`,`next tab`);async function Qi(e){try{(await e.request(`keybindings.createFile`)).created||L(T(`keys.exists`),`error`),await qe(e)}catch(e){L(B(e),`error`)}}function $i({client:e}){let{prefs:t}=vi(),n=v(We);(0,m.useEffect)(()=>void qe(e),[e]);let r=n.prefix.key??H(`keybindings.prefixDisabled`),i=Object.keys(Xi).sort();return(0,z.jsxs)(xi,{title:H(`keybindings.title`),hint:H(`keybindings.hint`),children:[(0,z.jsxs)(`div`,{className:`pref-field`,children:[(0,z.jsx)(`span`,{className:`pref-label`,children:H(`keybindings.configFile`)}),(0,z.jsx)(`p`,{className:`muted mono`,children:n.path+(n.exists?``:H(`keybindings.notCreated`))})]}),(0,z.jsx)(Ci,{label:H(`keybindings.tapPresentation`),hint:H(`keybindings.tapPresentationHint`),value:t.prefixTap,picks:[{value:`local`,label:H(`keybindings.tapPresentationLocal`)},{value:`guide`,label:H(`keybindings.tapPresentationGuide`)}],onPick:t=>void _i(e,`prefixTap`,t)}),(0,z.jsxs)(`div`,{className:`pref-field`,children:[(0,z.jsx)(`span`,{className:`pref-label`,children:H(`keybindings.prefixTitle`,{prefix:r})}),(0,z.jsx)(`p`,{className:`pref-hint muted`,children:H(`keybindings.prefixHint`,{prefix:r,timeout:n.prefix.timeoutMs})})]}),n.exists?(0,z.jsxs)(`div`,{className:`pref-field`,children:[(0,z.jsx)(`span`,{className:`pref-label`,children:H(`keybindings.overridesApplied`)}),n.applied.length===0&&(0,z.jsx)(`p`,{className:`muted`,children:H(`keybindings.none`)}),n.applied.map(e=>(0,z.jsx)(`p`,{className:`mono keys-applied`,children:`${e.id} ${e.keys.length>0?e.keys.join(` / `):H(`keybindings.unbound`)} (${H(`keybindings.defaultKeys`,{keys:e.defaultKeys.join(` / `)})})`},e.id))]}):(0,z.jsxs)(`div`,{className:`pref-field`,children:[(0,z.jsx)(`p`,{className:`muted`,children:H(`keybindings.createHint`)}),(0,z.jsx)(wi,{label:T(`keys.createFile`),onCycle:()=>void Qi(e)})]}),n.warnings.length>0&&(0,z.jsxs)(`div`,{className:`pref-field`,children:[(0,z.jsx)(`span`,{className:`pref-label tone-warning`,children:H(`keybindings.warnings`)}),n.warnings.map(e=>(0,z.jsx)(`p`,{className:`muted mono`,children:`! ${e}`},e))]}),(0,z.jsx)(`p`,{className:`muted`,children:H(`keybindings.fixed`,{ids:i.join(`, `)})}),(0,z.jsx)(`p`,{className:`muted`,children:T(`prefs.keysYaml`)})]})}function ea({client:e}){let[t,n]=(0,m.useState)(null),r=(0,m.useCallback)(()=>e.request(`plugins.list`).then(e=>n(e.plugins),e=>L(B(e),`error`)),[e]);return(0,m.useEffect)(()=>{r()},[r]),t?t.length===0?(0,z.jsx)(`p`,{className:`placeholder-line`,children:T(`settings.plugins.empty`)}):(0,z.jsx)(`div`,{className:`settings-rows`,children:t.map(t=>(0,z.jsxs)(`label`,{className:`engine-row`,children:[(0,z.jsx)(`input`,{type:`checkbox`,checked:t.enabled,onChange:()=>void e.request(`plugin.setEnabled`,{id:t.id,enabled:!t.enabled}).then(r).catch(e=>L(B(e),`error`))}),(0,z.jsxs)(`div`,{className:`engine-main`,children:[(0,z.jsx)(`span`,{className:`engine-name`,children:t.id}),(0,z.jsx)(`span`,{className:`muted engine-detail mono`,children:[t.version,t.linked?`linked`:null,t.platformOk===!1?`unsupported platform`:null].filter(Boolean).join(` · `)})]})]},t.id))}):(0,z.jsx)(`p`,{className:`placeholder-line`,children:T(`preview.loading`)})}function ta(e){let[t,n]=(0,m.useState)(e.tier.engine),[r,i]=(0,m.useState)(e.tier.model??``),[a,o]=(0,m.useState)(e.tier.effort??``),s=e.engines.find(e=>e.id===t);return(0,z.jsxs)(`form`,{className:`tier-editor`,onSubmit:n=>{n.preventDefault(),e.onSave(t,s?.takesModel?r.trim():``,a)},onKeyDown:t=>{t.key===`Escape`&&(t.stopPropagation(),e.onCancel())},children:[(0,z.jsx)(`div`,{className:`chips-row`,children:e.engines.map(e=>(0,z.jsx)(`button`,{type:`button`,"aria-pressed":e.id===t,className:`chip-button ${e.id===t?`is-active`:``}`,onClick:()=>{n(e.id),e.effortLevels.includes(a)||o(``),e.takesModel||i(``)},children:e.name},e.id))}),s&&s.effortLevels.length>0&&(0,z.jsx)(`div`,{className:`chips-row`,children:[``,...s.effortLevels].map(e=>(0,z.jsx)(`button`,{type:`button`,"aria-pressed":e===a,className:`chip-button ${e===a?`is-active`:``}`,onClick:()=>o(e),children:e||H(`autoRouting.engineDefault`)},e||`default`))}),s?.takesModel&&(0,z.jsx)(`input`,{className:`input`,value:r,spellCheck:!1,placeholder:H(`autoRouting.engineDefault`),"aria-label":T(`prefs.tierModel`),onChange:e=>i(e.target.value)}),(0,z.jsxs)(`div`,{className:`actions`,children:[(0,z.jsx)(`button`,{type:`button`,className:`link`,onClick:e.onCancel,children:T(`dialog.cancel`)}),(0,z.jsx)(`button`,{type:`submit`,className:`button`,children:H(`action.save`)})]})]})}function na(e){return e.mode===`off`?`jev`:e.mode===`jev`&&e.canCustom?`custom`:`off`}function ra({client:e}){let[t,n]=(0,m.useState)(null),[r,i]=(0,m.useState)(null),a=(0,m.useCallback)(()=>e.request(`autoRouting.get`).then(n,e=>L(B(e),`error`)),[e]);(0,m.useEffect)(()=>{a()},[a]);let o=(0,m.useRef)(null),s=(t,n)=>e.request(t,n).then(a).catch(e=>L(B(e),`error`));if(!t)return(0,z.jsx)(`p`,{className:`placeholder-line`,children:T(`preview.loading`)});let c=t.classifier,l=c.mode===`off`?H(`autoRouting.classifierOff`):c.mode===`jev`?`jev`:H(`autoRouting.classifierCustomLabel`),u=c.mode===`off`?H(`autoRouting.classifierOffHint`):c.mode===`jev`?H(`autoRouting.classifierJevHint`):H(`autoRouting.classifierCustomHint`),d=c.keySource===`env`?H(`autoRouting.keyPresentEnv`,{env:c.keyEnv??``}):c.keySource===`file`?H(`autoRouting.keySaved`):c.keyConfigured?H(`autoRouting.keyMissing`):H(`autoRouting.keyCustomUnused`);return(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(xi,{title:H(`autoRouting.title`),hint:H(`autoRouting.hint`),children:[!t.configured&&(0,z.jsx)(`p`,{className:`tone-warning`,children:H(`autoRouting.unconfigured`)}),(0,z.jsx)(`div`,{className:`settings-rows`,children:t.tiers.map(e=>(0,z.jsxs)(`div`,{className:`tier-row`,children:[(0,z.jsxs)(`div`,{className:`tier-head`,children:[(0,z.jsx)(`span`,{className:`engine-name`,children:li(`tier.${e.tier}`)}),(0,z.jsx)(`span`,{className:`mono muted`,children:[e.engineName,e.model??H(`autoRouting.engineDefault`),e.effort??H(`autoRouting.engineDefault`)].join(` · `)}),(0,z.jsx)(`button`,{type:`button`,className:`link`,onClick:()=>i(r===e.tier?null:e.tier),children:T(`prefs.tierEdit`)})]}),(0,z.jsx)(`span`,{className:`muted engine-detail`,children:li(`tierDesc.${e.tier}`)}),(0,z.jsx)(`span`,{className:`engine-detail ${e.block?`tone-warning`:`tone-success`}`,children:e.block?H(`autoRouting.unavailable`,{reason:e.block}):H(`autoRouting.ready`)}),r===e.tier&&(0,z.jsx)(ta,{tier:e,engines:t.engines,onCancel:()=>i(null),onSave:(t,n,r)=>{i(null),s(`autoRouting.setTier`,{tier:e.tier,engine:t,model:n,effort:r})}})]},e.tier))})]}),(0,z.jsxs)(xi,{title:H(`autoRouting.classifierTitle`),hint:H(`autoRouting.classifierHint`),children:[(0,z.jsx)(`p`,{className:c.mode===`off`?`muted`:`tone-warning`,children:H(`autoRouting.classifierDataFlow`)}),(0,z.jsxs)(`button`,{type:`button`,className:`pref-cycle`,onClick:()=>{let e=na({...c,mode:o.current?.next??c.mode}),t={next:e,inFlight:(o.current?.inFlight??0)+1};o.current=t,s(`autoRouting.setClassifier`,{mode:e}).then(()=>{o.current&&--o.current.inFlight===0&&(o.current=null)})},children:[(0,z.jsxs)(`span`,{className:`pref-label`,children:[H(`autoRouting.classifierLabel`),`: `,l]}),(0,z.jsx)(`span`,{className:`pref-hint muted`,children:u})]}),(0,z.jsx)(Ti,{label:`${H(`autoRouting.endpointLabel`)}: ${c.endpointHost||T(`prefs.unset`)}`,note:T(`prefs.editInTui`)}),(0,z.jsx)(Ti,{label:`${H(`autoRouting.thresholdLabel`)}: ${c.threshold.toFixed(2)}`,note:T(`prefs.editInTui`)}),(0,z.jsx)(Ti,{label:`${H(`autoRouting.keyLabel`)}: ${d}`,note:T(`prefs.editInTui`)})]})]})}var ia=[`general`,`engines`,`autoRouting`,`plugins`,`keys`,`feedback`,`dev`],aa={general:e=>(0,z.jsx)(Ji,{...e}),engines:e=>(0,z.jsx)(Ai,{...e}),autoRouting:e=>(0,z.jsx)(ra,{...e}),plugins:e=>(0,z.jsx)(ea,{...e}),keys:e=>(0,z.jsx)($i,{...e}),feedback:e=>(0,z.jsx)(ji,{...e}),dev:e=>(0,z.jsx)(Di,{...e})};function oa({client:e}){D();let[t,n]=(0,m.useState)(`general`);return(0,z.jsx)(ie,{title:T(`settings.title`),wide:!0,children:(0,z.jsxs)(`div`,{className:`settings`,children:[(0,z.jsx)(`nav`,{className:`settings-nav`,"aria-label":T(`settings.title`),children:ia.map(e=>(0,z.jsx)(`button`,{type:`button`,className:`settings-tab ${t===e?`is-active`:``}`,onClick:()=>n(e),children:H(`sections.${e}`)},e))}),(0,z.jsx)(`div`,{className:`settings-body`,children:aa[t]({client:e})})]})})}function sa(e){return e.kind===`leaf`?[e]:e.children.flatMap(sa)}function ca(e){return!!e&&sa(e.root).length>1}function la(e){let t=[],n=(e,r,i,a,o,s,c)=>{if(e.kind===`leaf`){t.push({id:e.id,x:r,y:i,w:a,h:o,left:s,top:c});return}let l=e.children.length;e.children.forEach((t,u)=>{e.orientation===`row`?n(t,r+a*u/l,i,a/l,o,u>0||s,c):n(t,r,i+o*u/l,a,o/l,s,u>0||c)})};return n(e,0,0,1,1,!1,!1),t}function ua(e,t,n=1){let r=sa(e.root).map(e=>e.id),i=r.indexOf(t);return r[(Math.max(0,i)+n+r.length)%r.length]??t}function da(e,t){let n=new Map,r=new Map;for(let i of sa(e.root)){if(i.title){r.set(i.id,i.title);continue}let e=i.own?t:`shell`,a=(n.get(e)??0)+1;n.set(e,a),r.set(i.id,a===1?e:`${e} ${a}`)}return r}function fa(e){return sa(e.root).map(e=>e.id).join(`,`)}var pa=/LAND_CONFLICT/,ma=/MAIN_CHECKOUT_DIRTY/,ha=/SYNC_CONFLICT(?:: )?(.*)/,ga=/SYNC_WORKTREE_DIRTY(?:: )?(.*)/;function _a(e){let t=B(e);return pa.test(t)?V(`worktrees`,`land.conflict`,{files:t}):ma.test(t)?V(`worktrees`,`land.dirtyBase`):V(`worktrees`,`land.failed`,{error:t})}async function va(e,t,n){let r;try{r=await e.client.request(`task.landPreflight`,{taskId:t.id})}catch(e){L(V(`worktrees`,`land.failed`,{error:B(e)}),`error`);return}if(r.refusal){L(r.refusal===`MAIN_CHECKOUT_DIRTY`?V(`worktrees`,`land.dirtyBase`):V(`worktrees`,`land.failed`,{error:r.message??r.refusal}),`error`);return}let i=t.branch||t.title;k.set((0,z.jsx)(se,{title:V(`worktrees`,`land.confirmTitle`),body:V(`worktrees`,r.ahead===1?`land.confirmBodyOne`:`land.confirmBody`,{branch:i,landedOn:r.landedOn,commits:r.ahead??`?`}),confirmLabel:V(`worktrees`,`land.button`),onConfirm:async()=>{try{let r=await e.client.request(`task.land`,{taskId:t.id});L(V(`worktrees`,`land.done`,{branch:i,landedOn:r.landedOn,commit:r.commit.slice(0,8)})),n?.()}catch(e){throw Error(_a(e))}}}))}async function ya(e,t){try{let n=await e.client.request(`task.syncBase`,{taskId:t});L(V(`tasks`,n.alreadyCurrent?`sync.alreadyCurrent`:`sync.done`,{base:n.baseRef}))}catch(e){let t=B(e),n=ha.exec(t),r=ga.exec(t);L(n?V(`tasks`,`sync.conflict`,{files:n[1]?.trim()||`?`}):r?V(`tasks`,`sync.dirty`,{files:r[1]?.trim()||`?`}):V(`tasks`,`sync.failed`,{error:t}),`error`)}}function ba(e){return e.split(`
|
|
13
|
-
`).find(e=>e.trim().length>0)?.trim()??e.trim()}async function xa(e,t,n){try{let r=await e.client.request(`task.fixChecks`,e.engineTarget(t));r.outcome===`unavailable`?L(V(`files`,`toast.ciChecksUnavailable`,{detail:ba(r.detail??``)}),`error`):r.outcome===`none`?L(V(`files`,`toast.ciNoFailingChecks`),`error`):L(n)}catch(e){L(B(e),`error`)}}async function Sa(e,t){try{let n=await e.client.request(`task.openEditor`,{taskId:t});n.outcome===`noEditor`?L(V(`tasks`,`toast.noEditor`),`error`):n.outcome===`failed`&&L(V(`tasks`,`toast.openWorktreeFailed`,{label:n.label??``}),`error`)}catch(e){L(V(`tasks`,`toast.worktreeErrorGeneric`,{message:B(e)}),`error`)}}function Ca(e,t){return(0,z.jsx)(se,{title:V(`tasks`,`confirm.deleteTitle`,{title:t.title}),body:V(`tasks`,t.kind===`dir`?`confirm.deleteBodyDir`:`confirm.deleteBodyTask`),confirmLabel:V(`tasks`,`confirm.deleteConfirm`),onConfirm:()=>e.client.request(`task.delete`,{taskId:t.id}).then(()=>{}),escalate:{when:e=>e instanceof Ar&&e.code===`DIRTY_WORKTREE`,label:V(`tasks`,`confirm.forceDeleteConfirm`),title:V(`tasks`,`confirm.forceDeleteTitle`,{title:t.title}),body:e=>`${V(`worktrees`,`delete.forceBody`,{branch:t.branch||t.title})}\n\n${V(`worktrees`,`delete.forceReason`,{reason:B(e).replace(`task ${t.id} `,``)})}`,run:()=>e.client.request(`task.delete`,{taskId:t.id,force:!0}).then(()=>{})}})}function wa(e,t,n){return(0,z.jsx)(se,{title:V(`tasks`,`confirm.forgetProjectTitle`,{title:n}),body:V(`tasks`,`confirm.forgetProjectBody`),confirmLabel:V(`tasks`,`confirm.forgetProjectConfirm`),onConfirm:async()=>{try{await e.client.request(`project.forget`,{repo:t})}catch(e){throw Error(V(`tasks`,`toast.forgetProjectFailed`,{error:B(e)}))}}})}var Ta=e=>{let{taskId:t}=e.selection.get();return e.tasks.get()?.tasks.find(e=>e.id===t)??null},Ea=e=>{let{taskId:t,tabId:n}=e.selection.get(),r=t?e.tabs.get()[t]?.find(e=>e.id===n):void 0;return!!r&&!ca(r.split)},Da=[{id:`app.refresh`,live:()=>it.get().stale,run:e=>ct(e.client)},{id:`palette.open`,live:()=>!0,run:Gr},{id:`task.new.global`,live:()=>!0,run:e=>k.set((0,z.jsx)(Hr,{model:e,repo:Ta(e)?.repo}))},{id:`chat.tab.fork`,live:e=>!!Ta(e),run:e=>{let t=Ta(e);t&&k.set((0,z.jsx)(_r,{model:e,taskId:t.id,context:`continue`}))}},{id:`chat.fork.new`,live:e=>!!Ta(e),run:e=>{let t=Ta(e);t&&k.set((0,z.jsx)(_r,{model:e,taskId:t.id,destination:`fork`}))}},{id:`settings.open`,live:()=>!0,run:e=>k.set((0,z.jsx)(oa,{client:e.client}))},{id:`inbox.show`,live:()=>!0,run:e=>k.set((0,z.jsx)(qn,{model:e}))},{id:`focus.previous`,live:()=>!0,run:()=>Xr(-1)},{id:`focus.next`,live:()=>!0,run:()=>Xr(1)},{id:`workspace.zenToggle`,live:e=>!!Ta(e),run:()=>F.set(!F.get())},{id:`files.createPR`,live:e=>!!Ta(e),run:e=>{let t=Ta(e);t&&e.client.request(`tab.requestPR`,e.engineTarget(t.id)).then(()=>L(T(`files.prRequested`))).catch(e=>L(e instanceof Error?e.message:String(e),`error`))}},{id:`chat.tab.close`,live:e=>!!e.selection.get().tabId&&Ea(e),run:e=>{let{taskId:t,tabId:n}=e.selection.get();!t||!n||e.client.request(`tab.close`,{taskId:t,tabId:n}).then(()=>e.refreshTabsNow()).catch(e=>L(e instanceof Error?e.message:String(e),`error`))}},{id:`kanban.open`,live:()=>!0,run:()=>M.set(`kanban`)},{id:`automations.open`,live:()=>!0,run:()=>M.set(`routines`)},{id:`workItems.open`,live:()=>!0,run:()=>M.set(`issues`)},{id:`task.moveMode`,live:e=>!!Qr(e),run:()=>{Jn.set(!Jn.get()),document.querySelector(`.rail`)?.focus()}},{id:`files.syncBase`,live:e=>Qr(e)?.kind===`task`,run:e=>{let t=Qr(e);t&&ya(e,t.id)}},{id:`files.fixChecks`,live:e=>!!Qr(e),run:e=>{let t=Qr(e);t&&xa(e,t.id,T(`taskops.fixSent`))}},{id:`task.openEditor`,live:e=>!!Qr(e),run:e=>{let t=Qr(e);t&&Sa(e,t.id)}}];At(()=>Da.map(e=>({id:e.id,chords:et(e.id),prefix:!0,live:e.live,run:e.run})));function Oa(e){return An(e[0]??``)}function ka(e,t){let n=Ft(),r=Mt().filter(t=>t.prefix&&Nt(t,n)&&t.live?.(e)!==!1);for(let e of t){let t=r.filter(t=>t.chords.includes(e)).sort((e,t)=>Pt(e,n)-Pt(t,n))[0];if(t)return t}}var Aa=null,ja=null;function Ma(){Aa=null,ja!==null&&window.clearTimeout(ja),ja=null;let e=Pn.get();e.guide?.kind===`prefix`&&Pn.set({...e,guide:null})}function Na(){k.get()||Ye()===null||(Aa=Date.now(),Pn.set({...Pn.get(),guide:{kind:`prefix`,armedAt:Aa}}),ja!==null&&window.clearTimeout(ja),ja=window.setTimeout(Ma,We.get().prefix.timeoutMs))}function Pa(e,t){Ma();let n=typeof t==`string`?[t]:t,r=ka(e,n);In(Oa(n),r?.id??null),r?.run(e)}var Fa=null;function Ia(){Fa!==null&&window.clearTimeout(Fa),Fa=null;let e=Pn.get();e.guide?.kind===`direct`&&Pn.set({...e,guide:null})}function La(){Fa!==null||k.get()||(Fa=window.setTimeout(()=>{Ma(),Pn.set({...Pn.get(),guide:{kind:`direct`}})},400))}function Ra(e){(0,m.useEffect)(()=>{let t=t=>{if(t.key===`Control`){t.repeat||La();return}if(Ia(),[`Shift`,`Alt`,`Meta`].includes(t.key))return;let n=kn(t),{firstStrokes:r,timeoutMs:i}=We.get().prefix;if(Aa!==null&&Date.now()-Aa<=i){if(t.preventDefault(),t.stopImmediatePropagation(),t.key===`Escape`)return Ma();Pa(e,n);return}Ma(),!k.get()&&n.some(e=>r.includes(e))&&(t.preventDefault(),t.stopImmediatePropagation(),Na())},n=e=>e.key===`Control`&&Ia();return window.addEventListener(`keydown`,t,{capture:!0}),window.addEventListener(`keyup`,n,{capture:!0}),window.addEventListener(`blur`,Ia),()=>{window.removeEventListener(`keydown`,t,{capture:!0}),window.removeEventListener(`keyup`,n,{capture:!0}),window.removeEventListener(`blur`,Ia),Ia(),Ma()}},[e])}function za(e){let t=Ft(),n=new Map;for(let r of Mt()){if(!r.prefix||!Nt(r,t)||r.live?.(e)===!1)continue;let i=Pt(r,t);for(let e of r.chords){let t=n.get(e);(!t||i<t.rank)&&n.set(e,{action:r.id,rank:i})}}return[...n].map(([e,{action:t}])=>({stroke:e,action:t}))}function Ba(e){let t=new Map(ze.map((e,t)=>[e.id,t])),n=new Map;for(let{stroke:t,action:r}of e)n.set(r,[...n.get(r)??[],t]);let r=new Map,i=[...n].sort(([e],[n])=>(t.get(e)??2**53-1)-(t.get(n)??2**53-1));for(let[e,t]of i){let n=wt(e);r.set(n,[...r.get(n)??[],{action:e,strokes:t}])}return[...r].map(([e,t])=>({category:e,actions:t}))}var Va=e=>e===`prefix.moreCommands`?qt(`moreCommandsPrefix`):Zt(e);function Ha(e){let[,t]=(0,m.useState)(0);(0,m.useEffect)(()=>{if(e===null)return;let n=window.setTimeout(()=>t(e=>e+1),Math.max(30,e-Date.now()));return()=>window.clearTimeout(n)},[e])}function Ua({model:e}){D();let t=v(Pn);v(We),v(e.selection);let n=Date.now(),r=t.entries.filter(e=>n-e.at<Nn),i=t.guide?.kind===`prefix`?t.guide.armedAt:null,a=i!==null&&n-i<Mn?i+Mn:null;Ha(a??(r[0]?r[0].at+Nn:null));let o=t.guide?.kind===`direct`||i!==null&&a===null;if(!o&&!t.guide&&r.length===0)return null;if(o&&t.guide){let n=t.guide.kind===`direct`,r=n?En(It(e,Ft()),Ye()):za(e);return(0,z.jsxs)(`output`,{className:`prefix-guide mono`,onMouseDown:e=>e.preventDefault(),children:[(0,z.jsxs)(`div`,{className:`prefix-guide-head`,children:[(0,z.jsx)(`span`,{className:`tone-accent`,children:n?qt(`directLayer`):qt(`commandLayer`,{prefix:Ye()??``})}),(0,z.jsx)(`span`,{className:`muted`,children:qt(n?`releaseCtrl`:`escCancel`)})]}),(0,z.jsx)(`div`,{className:`prefix-guide-body`,children:Ba(r).map(t=>(0,z.jsxs)(`div`,{className:`prefix-guide-group`,children:[(0,z.jsx)(`div`,{className:`tone-accent`,children:Qt(t.category)}),t.actions.map(({action:t,strokes:r})=>(0,z.jsxs)(`button`,{type:`button`,className:`prefix-guide-row`,disabled:n,onClick:()=>r[0]&&Pa(e,r[0]),children:[(0,z.jsx)(`span`,{className:`prefix-hud-key`,children:r.map(An).join(`/`)}),(0,z.jsx)(`span`,{children:Va(t)})]},t))]},t.category))})]})}return(0,z.jsxs)(`output`,{className:`prefix-hud mono`,children:[r.map(e=>(0,z.jsxs)(`div`,{className:`prefix-hud-head`,children:[(0,z.jsx)(`span`,{className:`tone-accent`,children:Ye()}),` + `,e.stroke,` →`,` `,e.action?Va(e.action):(0,z.jsx)(`span`,{className:`muted`,children:`∅`})]},e.id)),i!==null&&(0,z.jsxs)(`div`,{className:`prefix-hud-head`,children:[(0,z.jsx)(`span`,{className:`tone-accent`,children:Ye()}),` ⋯`]})]})}function Wa({model:e,bindingId:t}){let n=v(Pn);v(We);let r=vi().prefs.prefixTap;if(n.guide?.kind!==`prefix`||r!==`local`)return null;let i=Tn({bindingId:t,reachability:It(e,Ft()),prefixKey:Ye()});if(!i)return null;let a=Mt().find(e=>e.id===t&&e.prefix)?.chords[0];return(0,z.jsx)(`button`,{type:`button`,className:`shortcut-badge mono`,onMouseDown:e=>e.preventDefault(),onClick:t=>{t.stopPropagation(),a&&Pa(e,a)},children:i})}var Ga=1e4;function Ka(e,t){let n=e.hostLabel||e.alias;if(e.state===`online`)return e.version?`${n} · v${e.version}`:n;let r=t[e.state];return e.state===`mismatch`?e.version?`${n} · ⚠ v${e.version} (${r})`:`${n} · ⚠ ${r}`:`${n} · ${r}`}function qa({row:e,words:t}){return(0,z.jsxs)(`h2`,{className:`machine-head ${e.state===`online`?``:`is-stale`}`,title:e.alias,children:[(0,z.jsx)(`span`,{children:Ka(e,t)}),(0,z.jsx)(`span`,{className:`rule`})]})}function Ja({host:e}){return D(),(0,z.jsxs)(`div`,{className:`remote-notice`,children:[(0,z.jsx)(`p`,{className:`muted`,children:V(`tasks`,`machine.filesElsewhere`,{host:e})}),(0,z.jsx)(`p`,{className:`muted`,children:V(`tasks`,`machine.filesHint`,{host:e})})]})}function Ya(e){let t=v(e.client.conn),n=v(e.remote),[r,i]=(0,m.useState)([]),a=[...new Set(n.map(e=>`${e.machine?.id}:${e.machine?.stale??!1}`))].join();return(0,m.useEffect)(()=>{if(t.state!==`open`)return;let n=!0,r=()=>e.client.request(`machines.list`).then(e=>n&&i(e.machines),()=>{});r();let a=window.setInterval(r,Ga);return()=>{n=!1,window.clearInterval(a)}},[e.client,t.state,a]),r}function Xa(e){let t=Math.floor(e/6e4),n=Math.floor(t/60);return{minutes:t,hours:n,days:Math.floor(n/24)}}function Za(e,t=Date.now()){let n=Math.max(0,t-e),r=Math.floor(n/1e3);if(r<60)return`${r}s`;let{minutes:i,hours:a,days:o}=Xa(n);return i<60?`${i}m`:a<24?`${a}h`:`${o}d`}var Qa={title:`ROUTINES`,holdingDaemon:`keeping the daemon awake`,notHolding:`none active`,needAttention:`{count} of {total} need you ·`,paused:`paused`,newTitle:`New routine`,composerLegend:`enter create · tab fields · ←→ ↑↓ edit the focused field · esc cancel`,fieldName:`NAME`,fieldRepo:`REPO`,fieldTarget:`DELIVER TO`,fieldTargetTab:`EXISTING ENGINE TAB`,targetFresh:`New task on each run`,targetStanding:`Routine-owned standing task`,targetExisting:`Existing conversation: {task} / {tab}. Never creates or revives a session.`,fieldPrompt:`PROMPT`,fieldSchedule:`SCHEDULE (FIVE-FIELD CRON)`,namePlaceholder:`weekday dependency audit`,promptPlaceholder:`Audit dependencies and summarize risky changes.`,needRepo:`Open a project first — a routine runs in one.`,cronInvalid:`not a five-field cron`,cronField:{minute:`min`,hour:`hour`,dayOfMonth:`day`,month:`month`,dayOfWeek:`weekday`},schedule:{everyDay:`every day {at}`,weekdays:`weekdays {at}`,weekends:`weekends {at}`,onWeekday:`{weekday} {at}`,everyMinute:`every minute`,everyMinutes:`every {n}m`,everyHours:`every {n}h`,hourlyAt:`hourly at :{minute}`,atClock:`at {time}`,dow:{MON:`Mondays`,TUE:`Tuesdays`,WED:`Wednesdays`,THU:`Thursdays`,FRI:`Fridays`,SAT:`Saturdays`,SUN:`Sundays`}},when:{inMinutes:`in {n}m`,inHours:`in {n}h`,inDays:`in {n}d`,minutesAgo:`{n}m ago`,hoursAgo:`{n}h ago`,now:`now`,justNow:`just now`,dateTime:`{date}, {time}`},runStatus:{dispatched:`dispatched`,revived:`revived`,skipped_cancelled:`cancelled before delivery`,skipped_precheck:`skipped (precheck)`,skipped_missed:`skipped (missed)`,skipped_unavailable:`skipped (unavailable)`,dispatch_failed:`dispatch failed`},cronNever:`valid, but never fires`,missing:{target:`Choose an existing task.`,targetTab:`Enter an existing tab id, e.g. tab-2.`,name:`Give it a name.`,repo:`Pick a project.`,prompt:`Say what it should do.`,schedule:`That schedule will not run.`},empty:`No routines scheduled.`,emptyHint:`Press n to create one.`,precheck:`precheck: {command}`,recentRuns:`RECENT RUNS`,precheckDetail:`WHY IT SKIPPED — precheck {exit} in {duration}ms`,precheckExited:`exited {code}`,precheckTimedOut:`timed out`,precheckStdout:`stdout`,precheckStderr:`stderr`,precheckNoOutput:`(no output)`,noRuns:`Not run yet.`,responses:`RESPONSES`,noResponses:"No run has reported back yet. Agents answer with `routine-respond`.",responseAwaiting:`awaiting response`,responseMissing:`no response`,noSelection:`A routine runs its prompt in a project on a schedule.`,running:`Running {name}…`,ranWith:`{name}: {status}`,latestRunNoTask:`The latest run created no task.`,runNow:`[ run now ]`,deleteTitle:`Delete routine?`,deleteBody:`{name} and its run history will be removed. Tasks it already created are untouched.`,deleteButton:`Delete`,createFailed:`Couldn't create the routine: {error}`,deleteFailed:`Couldn't delete "{name}": {error}`,enableFailed:`"{name}" stays paused: {error}`,disableFailed:`"{name}" stays enabled: {error}`,runFailed:`Couldn't run "{name}" now — schedule unchanged: {error}`},$a={title:`例行任务`,holdingDaemon:`正在保持守护进程常驻`,notHolding:`无启用项`,needAttention:`{total} 个中有 {count} 个需要处理 ·`,paused:`已暂停`,newTitle:`新建例行任务`,composerLegend:`enter 创建 · tab 切字段 · ←→ ↑↓ 编辑当前字段 · esc 取消`,fieldName:`名称`,fieldTarget:`投递目标`,fieldTargetTab:`既有引擎标签页`,targetFresh:`每次新建任务`,targetStanding:`例行任务自有的常驻任务`,targetExisting:`既有会话:{task} / {tab}。不会创建或重启会话。`,fieldRepo:`仓库`,fieldPrompt:`提示词`,fieldSchedule:`调度(五段 cron)`,namePlaceholder:`工作日依赖审计`,promptPlaceholder:`审计依赖并总结有风险的变更。`,needRepo:`先打开一个项目——例行任务要跑在某个项目里。`,cronInvalid:`不是合法的五段 cron`,cronField:{minute:`分`,hour:`时`,dayOfMonth:`日`,month:`月`,dayOfWeek:`星期`},schedule:{everyDay:`每天{at}`,weekdays:`工作日{at}`,weekends:`周末{at}`,onWeekday:`{weekday}{at}`,everyMinute:`每分钟`,everyMinutes:`每 {n} 分钟`,everyHours:`每 {n} 小时`,hourlyAt:`每小时的 :{minute}`,atClock:`{time}`,dow:{MON:`每周一`,TUE:`每周二`,WED:`每周三`,THU:`每周四`,FRI:`每周五`,SAT:`每周六`,SUN:`每周日`}},when:{inMinutes:`{n} 分钟后`,inHours:`{n} 小时后`,inDays:`{n} 天后`,minutesAgo:`{n} 分钟前`,hoursAgo:`{n} 小时前`,now:`即将`,justNow:`刚刚`,dateTime:`{date} {time}`},runStatus:{dispatched:`已派发`,revived:`已重启会话`,skipped_cancelled:`交付前已取消`,skipped_precheck:`已跳过(预检)`,skipped_missed:`已跳过(错过时间)`,skipped_unavailable:`已跳过(不可用)`,dispatch_failed:`派发失败`},cronNever:`语法合法,但永远不会触发`,missing:{target:`请选择既有任务。`,targetTab:`请输入既有标签页 ID,例如 tab-2。`,name:`起个名字。`,repo:`选一个项目。`,prompt:`说明它要做什么。`,schedule:`这个调度不会触发。`},empty:`还没有例行任务。`,emptyHint:`按 n 新建一条。`,precheck:`预检:{command}`,recentRuns:`最近执行`,precheckDetail:`为什么跳过 —— 预检{exit},耗时 {duration}ms`,precheckExited:`退出码 {code}`,precheckTimedOut:`超时`,precheckStdout:`标准输出`,precheckStderr:`标准错误`,precheckNoOutput:`(无输出)`,noRuns:`尚未执行。`,responses:`回报`,noResponses:"还没有执行回报。agent 用 `routine-respond` 回报。",responseAwaiting:`等待回报`,responseMissing:`未回报`,noSelection:`例行任务会按调度在某个项目里跑它的提示词。`,running:`正在运行 {name}…`,ranWith:`{name}:{status}`,latestRunNoTask:`最近一次执行没有创建任务。`,runNow:`[ 立即运行 ]`,deleteTitle:`删除这条例行任务?`,deleteBody:`将删除 {name} 及其执行记录。它已经创建的任务不受影响。`,deleteButton:`删除`,createFailed:`创建例行任务失败:{error}`,deleteFailed:`删除“{name}”失败:{error}`,enableFailed:`“{name}”仍处于暂停状态:{error}`,disableFailed:`“{name}”仍处于启用状态:{error}`,runFailed:`无法立即运行“{name}”——排程未受影响:{error}`},eo={title:`Kanban`,hint:`tab project · ←↓↑→ card · enter detail · n new · d delete · r refresh · esc close`,loading:`Loading issues…`,noRepos:"No projects yet — add one with `rove add <path>`, or file a story with `rove api issue-create`.",empty:"No issues — agents file them via `rove api issue-create`.",readFailed:"Couldn't read this project's stories: {error}. Run `rove doctor`, then reopen Kanban.",readFailedToast:`Couldn't read stories for {repo}: {error}`,columnEmpty:`No cards`,column:{backlog:`Backlog`,inProgress:`In progress`,parked:`Parked`,done:`Done`},more:`+{count} more`,attention:`{count} need you`,turnComplete:`turn done`,menu:{setStatus:`status → {status}`},detail:{status:{open:`open`,doing:`doing`,hold:`hold`,done:`done`},statusLabel:`STATUS`,created:`created {date}`,linked:`linked to a session`,titleLabel:`TITLE`,description:`DESCRIPTION`,noDescription:`No description.`,attachHint:`paste a path / ctrl+v screenshot → inserts an image placeholder`,engine:`ENGINE`,workspace:`WORKSPACE`,placement:{worktree:`New worktree task — its own workspace`,projectWorktree:`New worktree — as a chattab in the project workspace`,project:`Project checkout — a new chattab, no worktree`},jumpLabel:`AFTER START`,jump:{stay:`Stay on the board`,follow:`Jump to the session`},startLegend:`enter/ctrl+enter start · tab fields · ←→ status/engine · ↑↓ workspace · esc save & close`,sessionLabel:`SESSION`,openAction:`Open the linked session ↵`,unlinkAction:`Unlink`,openLegend:`enter open the focused action · tab fields · ←→ status · unlink returns the card to Backlog · esc save & close`,eventsLabel:`EVENTS`,eventsLoading:`Loading events…`,eventsNone:`No engine events recorded yet.`,doneNote:`Done stories have nothing left to start — set the status back to reopen one · esc save & close`,startedBackground:`Started in background: {title}`,newStory:`NEW STORY`,createLegend:`ctrl+s save · enter/ctrl+enter save & start · tab fields · esc cancel`},confirmDelete:{title:`Delete story #{id}?`,body:`“{title}” will be removed from the tracker. A linked task, branch, or worktree is left untouched.`},deleteFailed:`Couldn't delete story #{id}: {error}`,createFailed:`Couldn't create the story: {error}`,updateFailed:`Couldn't save story #{id}: {error}`,statusFailed:`Story #{id} stays in its old column: {error}`,linkFailed:`Story #{id} isn't linked to its task: {error}`,unlinkFailed:`Story #{id} is still linked: {error}`},to={title:`看板`,hint:`tab 切项目 · ←↓↑→ 选卡片 · enter 详情 · n 新建 · d 删除 · r 刷新 · esc 关闭`,loading:`正在加载 issues…`,noRepos:"还没有项目——用 `rove add <路径>` 添加一个,或用 `rove api issue-create` 创建一个 story。",empty:"暂无 issue——agent 可通过 `rove api issue-create` 创建。",readFailed:"读取该项目的 story 失败:{error}。请运行 `rove doctor`,再重新打开看板。",readFailedToast:`读取 {repo} 的 story 失败:{error}`,columnEmpty:`暂无卡片`,column:{backlog:`待办`,inProgress:`进行中`,parked:`搁置`,done:`已完成`},more:`还有 {count} 条`,attention:`{count} 张等你处理`,turnComplete:`回合完成`,menu:{setStatus:`状态 → {status}`},detail:{status:{open:`待办`,doing:`进行中`,hold:`搁置`,done:`已完成`},statusLabel:`状态`,created:`创建于 {date}`,linked:`已关联会话`,titleLabel:`标题`,description:`描述`,noDescription:`暂无描述。`,attachHint:`粘贴路径 / ctrl+v 贴截图 → 插入图片占位行`,engine:`引擎`,workspace:`工作区`,placement:{worktree:`新建 worktree 任务——独立工作区`,projectWorktree:`新建 worktree——作为项目工作区里的 chattab`,project:`项目主目录——新开 chattab,不建 worktree`},jumpLabel:`启动后`,jump:{stay:`留在看板`,follow:`跳转到会话`},startLegend:`enter/ctrl+enter 启动 · tab 切字段 · ←→ 状态/引擎 · ↑↓ 工作区 · esc 保存关闭`,sessionLabel:`会话`,openAction:`打开关联会话 ↵`,unlinkAction:`解除关联`,openLegend:`enter 执行选中操作 · tab 切字段 · ←→ 状态 · 解除关联把卡片退回 Backlog · esc 保存关闭`,eventsLabel:`事件`,eventsLoading:`正在加载事件…`,eventsNone:`暂无引擎事件记录。`,doneNote:`已完成的 story 无需启动——改回状态即可重新打开 · esc 保存关闭`,startedBackground:`已在后台启动:{title}`,newStory:`新建 STORY`,createLegend:`ctrl+s 仅保存 · enter/ctrl+enter 保存并启动 · tab 切字段 · esc 取消`},confirmDelete:{title:`删除 story #{id}?`,body:`「{title}」将从 tracker 中移除。已关联的任务、分支、worktree 不受影响。`},deleteFailed:`删除 story #{id} 失败:{error}`,createFailed:`创建 story 失败:{error}`,updateFailed:`保存 story #{id} 失败:{error}`,statusFailed:`Story #{id} 仍留在原来的列:{error}`,linkFailed:`Story #{id} 未能关联到它的任务:{error}`,unlinkFailed:`Story #{id} 仍处于关联状态:{error}`},no={title:`ISSUES`,noRepo:`no project`,empty:`No open issues.`,assignedFilter:`assigned to me`,starting:`Starting work on #{number}…`,startedNoEngine:`Created {title}, but its engine did not start.`,linkedChip:`→ {title}`,openingLinked:`Opening {title}…`,startFailed:`Couldn't start work on #{number}: {error}`,errorHint:{noRemote:"Add a GitHub remote (`git remote add origin <url>`) and try again, or press q / esc to close.",ghMissing:"Install the `gh` CLI and authenticate, or press q / esc to close.",auth:"Run `gh auth login`, or press q / esc to close.",fallback:`{message} · press q / esc to close`}},ro={title:`议题`,noRepo:`无项目`,empty:`没有开放的议题。`,assignedFilter:`分配给我的`,starting:`正在开始处理 #{number}…`,startedNoEngine:`已创建 {title},但引擎没有启动。`,linkedChip:`→ {title}`,openingLinked:`正在打开 {title}…`,startFailed:`开始处理 #{number} 失败:{error}`,errorHint:{noRemote:"添加 GitHub remote(`git remote add origin <url>`)后重试,或按 q / esc 关闭。",ghMissing:"安装 `gh` CLI 并登录,或按 q / esc 关闭。",auth:"执行 `gh auth login`,或按 q / esc 关闭。",fallback:`{message} · 按 q / esc 关闭`}};function io(){let e=D()===`zh`;return{kanban:e?to:eo,auto:e?$a:Qa,items:e?ro:no,nav:(e?Te:we).nav,group:(e?Te:we).group,common:e?de:ue}}function U(e,t){return e.replace(/\{(\w+)\}/g,(e,n)=>String(t[n]??e))}function ao(e){return e instanceof Error?e.message:String(e)}function oo(e){return e.replace(/^\/private\//,`/`).replace(/\/+$/,``)}function so(e,t){let n=e.split(`/`).filter(Boolean),r=n[n.length-1]??e;return t.some(t=>t!==e&&t.split(`/`).filter(Boolean).pop()===r)&&n.length>1?`${n[n.length-2]}/${r}`:r}function co(...e){let t=new Set,n=[];for(let r of e.flat()){if(!r||r.startsWith(`ssh://`))continue;let e=oo(r);t.has(e)||(t.add(e),n.push(r))}return n}function W(e){return co((v(e.tasks)?.tasks??[]).map(e=>e.repo))}function lo(e){let t=v(e.tasks),{taskId:n}=v(e.selection);return t?.tasks.find(e=>e.id===n)?.repo}function uo(e){let[t,n]=(0,m.useState)(0);return(0,m.useEffect)(()=>{let t=window.setInterval(()=>n(e=>e+1),e);return()=>window.clearInterval(t)},[e]),[t,(0,m.useCallback)(()=>n(e=>e+1),[])]}function fo(e){return e instanceof HTMLElement?e.isContentEditable||[`INPUT`,`TEXTAREA`,`SELECT`].includes(e.tagName):!1}function po(e){let t=(0,m.useRef)(e);t.current=e,(0,m.useEffect)(()=>{let e=e=>{if(e.defaultPrevented||k.get()||O.get())return;let n=e.target instanceof HTMLElement?e.target:null;fo(n)||n?.closest(`.rail, .files, .xterm`)||e.metaKey||e.altKey||e.ctrlKey&&e.key.toLowerCase()===`c`&&window.getSelection()?.toString()||t.current(e)&&(e.preventDefault(),e.stopPropagation())};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[])}function mo(){let e=(0,m.useRef)(null);return(0,m.useEffect)(()=>e.current?.focus(),[]),e}var ho=30;function go(){let{items:e}=io();return t=>{let n=t.indexOf(`: `);switch(n>=0?t.slice(0,n):`failed`){case`no-remote`:return e.errorHint.noRemote;case`gh-missing`:return e.errorHint.ghMissing;case`auth`:return e.errorHint.auth;default:return U(e.errorHint.fallback,{message:t})}}}function _o({model:e}){let{items:t,common:n}=io(),r=go(),i=e.client,a=v(e.tasks),o=W(e),s=lo(e),[c,l]=(0,m.useState)(()=>{let e=s?o.findIndex(e=>oo(e)===oo(s)):-1;return Math.max(0,e)}),u=o[c],[d,f]=(0,m.useState)(null),[p,h]=(0,m.useState)({}),[g,_]=(0,m.useState)(null),[y,b]=(0,m.useState)(!1),[x,S]=(0,m.useState)(0),[C,w]=(0,m.useState)(0),[T,E]=(0,m.useState)(!1),[D,O]=(0,m.useState)(null),k=mo(),ee=(0,m.useRef)(!1);(0,m.useEffect)(()=>{let e=!0;if(!u){f([]);return}_(null);let t=ee.current;return ee.current=!1,i.request(`workitem.list`,{repo:u,limit:ho,...y?{assignee:`@me`}:{},...t?{refresh:!0}:{}}).then(t=>e&&f(t.items)).catch(t=>{e&&(_(ao(t)),f([]))}),i.request(`workitem.links`,{repo:u}).then(t=>e&&h(Object.fromEntries(t.links.map(e=>[e.number,e.taskId])))).catch(()=>e&&h({})),()=>{e=!1}},[i,u,y,x,a?.tasks.length]);let A=d??[],j=Math.min(C,Math.max(0,A.length-1));(0,m.useEffect)(()=>O(null),[u,y]);let N=(0,m.useRef)(null);(0,m.useEffect)(()=>{N.current?.querySelector(`[data-row="${j}"]`)?.scrollIntoView({block:`nearest`})},[j]);let P=e=>a?.tasks.find(t=>t.id===e)?.title??e,F=t=>{M.set(null),e.select(t)},I=async()=>{let e=A[j];if(!e||!u||T)return;let n=p[e.number];if(n){O(U(t.openingLinked,{title:P(n)})),F(n);return}E(!0),O(U(t.starting,{number:e.number}));try{let n=await i.request(`workitem.start`,{repo:u,number:e.number});n.started?F(n.taskId):O(U(t.startedNoEngine,{title:n.title}))}catch(n){L(U(t.startFailed,{number:e.number,error:ao(n)}),`error`)}finally{E(!1)}};po(e=>{if(e.ctrlKey)return e.key===`c`&&(M.set(null),!0);switch(e.key){case`Escape`:case`q`:return M.set(null),!0;case`j`:case`ArrowDown`:return w(Math.min(A.length-1,j+1)),!0;case`k`:case`ArrowUp`:return w(Math.max(0,j-1)),!0;case`Tab`:return l(t=>o.length?(t+(e.shiftKey?o.length-1:1))%o.length:0),!0;case`a`:return b(e=>!e),!0;case`r`:return ee.current=!0,S(e=>e+1),!0;case`Enter`:return I(),!0;default:return!1}});let te=Date.now();return(0,z.jsxs)(`div`,{className:`page`,tabIndex:0,ref:k,children:[(0,z.jsxs)(`div`,{className:`pg-top`,children:[(0,z.jsx)(`h1`,{className:`page-title`,children:t.title}),(0,z.jsxs)(`span`,{className:`muted mono pg-hint`,children:[u?so(u,o):t.noRepo,y?` ${t.assignedFilter}`:``]})]}),g?(0,z.jsxs)(`div`,{className:`pg-list`,children:[(0,z.jsx)(`p`,{className:`error`,children:g}),(0,z.jsx)(`p`,{className:`muted`,children:r(g)})]}):d===null?(0,z.jsx)(`p`,{className:`muted`,children:n.loading}):A.length===0?(0,z.jsx)(`p`,{className:`muted`,children:t.empty}):(0,z.jsx)(`div`,{className:`pg-list`,ref:N,children:A.map((e,n)=>{let r=p[e.number],i=Date.parse(e.updatedAt);return(0,z.jsxs)(`div`,{"data-row":n,className:`pg-issue ${n===j?`is-cursor`:``}`,onClick:()=>n===j?void I():w(n),children:[(0,z.jsxs)(`div`,{className:`pg-issue-line`,children:[(0,z.jsxs)(`span`,{className:`pg-num mono`,children:[`#`,e.number]}),(0,z.jsx)(`span`,{className:`pg-grow`,children:e.title})]}),(0,z.jsxs)(`div`,{className:`pg-issue-sub`,children:[(0,z.jsx)(`span`,{className:`pg-grow`,children:[e.author,...e.labels.slice(0,2)].filter(Boolean).join(` · `)}),r&&(0,z.jsx)(`span`,{children:U(t.linkedChip,{title:P(r)})}),(0,z.jsx)(`span`,{className:`mono`,children:Number.isFinite(i)?Za(i,te):``})]})]},e.number)})}),D&&(0,z.jsx)(`p`,{className:`muted pg-notice`,children:D})]})}var vo={backlog:`active`,in_progress:`active`,in_review:`parked`,error:`parked`,done:`terminal`,canceled:`terminal`,open:`active`,doing:`active`,hold:`parked`};function yo(e){return vo[e]??`parked`}var bo=[`backlog`,`in_progress`,`parked`,`done`];function xo(e,t,n){let r=e.find(e=>e.issues.length>0)?.issues[0]?.id??null;if(t==null)return r;let i=-1,a=-1;for(let[n,r]of e.entries()){let e=r.issues.findIndex(e=>e.id===t);if(e!==-1){i=n,a=e;break}}if(i===-1)return r;if(n===`up`||n===`down`){let r=e[i]?.issues??[],o=n===`up`?a-1:a+1;return r[Math.max(0,Math.min(o,r.length-1))]?.id??t}let o=n===`left`?-1:1;for(let n=i+o;n>=0&&n<e.length;n+=o){let r=e[n]?.issues??[];if(r.length!==0)return r[Math.min(a,r.length-1)]?.id??t}return t}function So(e,t){let n=yo(e.status);return n===`terminal`?`done`:n===`parked`?`parked`:e.taskId!==void 0&&e.taskId!==``&&(t?.(e.taskId)??!0)||e.status===`doing`?`in_progress`:`backlog`}function Co(e,t){let n=0;return{columns:e.map(e=>{if(e.key!==`in_progress`)return e;let r=[],i=[];for(let n of e.issues)n.taskId!==void 0&&n.taskId!==``&&t(n.taskId)?r.push(n):i.push(n);return n=r.length,r.length===0?e:{...e,issues:[...r,...i]}}),attentionCount:n}}function wo(e,t){return e.created===t.created?t.id-e.id:e.created<t.created?1:-1}function To(e,t){let n={backlog:[],in_progress:[],parked:[],done:[]};for(let r of e)n[So(r,t)].push(r);return bo.map(e=>{let t=e===`done`||e===`parked`,r=n[e].sort(wo);return!t||r.length<=20?{key:e,issues:r,hiddenCount:0}:{key:e,issues:r.slice(0,20),hiddenCount:r.length-20}})}var Eo=[`image/png`,`image/jpeg`,`image/gif`,`image/webp`,`application/pdf`],Do=5242880;function Oo(e,t){return/\.pdf$/i.test(e)?`pdf[${t}]`:`images[${t}]`}function ko(e){let t=-1;for(let n of e.matchAll(/^(?:images|pdf)\[(\d+)\]:/gm)){let e=Number.parseInt(n[1],10);e>t&&(t=e)}return t+1}function Ao(e,t){let n=e.replace(/\s+$/,``),r=ko(e);for(let e of t){let t=`${Oo(e,r)}: ${e}`;n=n.length>0?`${n}\n${t}`:t,r+=1}return n}function jo(e){return Array.from(e??[]).filter(e=>Eo.includes(e.type))}function Mo(e){let t=``;for(let n=0;n<e.length;n+=32768)t+=String.fromCharCode(...e.subarray(n,n+32768));return btoa(t)}async function No(e,t){let n=Mo(new Uint8Array(await t.arrayBuffer()));return(await e.request(`attachment.put`,{mime:t.type,data:n})).path}var Po=[`worktree`,`projectWorktree`,`project`];async function Fo(e,t){let n=t.placement===`project`?`project`:`worktree`,{title:r,prompt:i}=await e.request(`issue.prompt`,{repo:t.repo,id:t.issue.id,where:n}),a=[];if(t.placement!==`project`){let{taskId:n}=await e.request(`task.create`,{repo:t.repo,engine:t.engine,title:r,prompt:i});if(await e.request(`issue.update`,{repo:t.repo,id:t.issue.id,task:n}).catch(e=>a.push({kind:`link`,error:ao(e)})),t.placement===`worktree`)return{taskId:n,warnings:a};let o=await e.request(`task.openMain`,{repo:t.repo}),s=await e.request(`tab.openViewport`,{taskId:o.taskId,viewTaskId:n});return{taskId:o.taskId,tabId:s.tabId,warnings:a}}let{taskId:o}=await e.request(`task.openMain`,{repo:t.repo}),{tabId:s}=await e.request(`tab.new`,{taskId:o,kind:`engine`,engine:t.engine,prompt:i});return await e.request(`issue.setStatus`,{repo:t.repo,id:t.issue.id,status:`doing`}).catch(e=>a.push({kind:`status`,error:ao(e)})),{taskId:o,tabId:s,warnings:a}}var Io={choice:`radiogroup`,list:`listbox`,cells:`group`};function Lo(e){return(0,z.jsx)(`div`,{ref:e.fieldRef,role:Io[e.kind??`choice`],tabIndex:0,"aria-label":e.label,className:`kb-group ${e.className??``}`,onKeyDown:e.onKeyDown,onClick:e.onClick,children:e.children})}var Ro=[`open`,`doing`,`hold`,`done`];function zo({model:e,taskId:t}){let{kanban:n}=io(),[r,i]=(0,m.useState)(null);return(0,m.useEffect)(()=>{let n=!0;return e.client.request(`task.events`,{taskId:t}).then(e=>n&&i(e.events)).catch(()=>n&&i([])),()=>{n=!1}},[e,t]),(0,z.jsxs)(`div`,{className:`kb-section`,children:[(0,z.jsx)(`h2`,{className:`kicker`,children:n.detail.eventsLabel}),r===null?(0,z.jsx)(`p`,{className:`muted`,children:n.detail.eventsLoading}):r.length===0?(0,z.jsx)(`p`,{className:`muted`,children:n.detail.eventsNone}):r.map(e=>(0,z.jsxs)(`div`,{className:`kb-event mono`,children:[(0,z.jsx)(`span`,{className:`muted kb-age`,children:Za(e.at)}),(0,z.jsx)(`span`,{children:e.kind}),e.tail&&(0,z.jsxs)(`span`,{className:`muted`,children:[`· `,e.tail]})]},`${e.at}:${e.kind}:${e.tail}`))]})}function Bo(e){let{kanban:t}=io(),{issue:n,mode:r}=e,i=r===`create`,a=!i&&n.taskId?n.taskId:null,o=i||!a&&n.status!==`done`,[s,c]=(0,m.useState)(n.title),[l,u]=(0,m.useState)(n.body),[d,f]=(0,m.useState)(n.status),[p,h]=(0,m.useState)(e.defaultEngine),[g,_]=(0,m.useState)(Po[0]),[v,y]=(0,m.useState)(!1),[b,x]=(0,m.useState)(!1),S=(0,m.useRef)({}),C=e=>t=>{S.current[e]=t},w=i?`title`:o?`workspace`:a?`open`:`title`;(0,m.useEffect)(()=>S.current[w]?.focus(),[w]);let E=()=>({title:s.trim()||n.title,body:l,status:d}),D=()=>({engine:p,placement:g,jump:v}),O=t=>{R(),t&&e.onOutcome(t)},k=()=>s.trim()?!0:(S.current.title?.focus(),!1),ee=()=>{i?k()&&O({kind:`create`,title:s.trim(),body:l,start:D()}):o?O({kind:`start`,...D(),...E()}):a&&O({kind:`open`,taskId:a,...E()})},A=()=>{i&&k()&&O({kind:`create`,title:s.trim(),body:l,start:null})},j=()=>O(i?null:{kind:`close`,...E()}),M=(0,m.useRef)({commit:ee,saveOnly:A,close:j});M.current={commit:ee,saveOnly:A,close:j},(0,m.useEffect)(()=>{let e=e=>{let t=e.key===`Escape`?M.current.close:e.key===`Enter`&&(e.ctrlKey||e.metaKey)?M.current.commit:e.key.toLowerCase()===`s`&&e.ctrlKey&&!e.metaKey?M.current.saveOnly:null;t&&(e.preventDefault(),e.stopImmediatePropagation(),t())};return window.addEventListener(`keydown`,e,{capture:!0}),()=>window.removeEventListener(`keydown`,e,{capture:!0})},[]);let N=async t=>{let n=t.find(e=>e.size>Do);if(n){L(T(`pages.attachTooLarge`,{name:n.name||n.type}),`error`);return}x(!0);try{let n=await Promise.all(t.map(t=>No(e.model.client,t)));u(e=>Ao(e,n))}catch(e){L(B(e),`error`)}finally{x(!1)}},P=e=>{let t=jo(e.clipboardData.files);t.length!==0&&(e.preventDefault(),N(t))},F=e=>{let t=jo(e.dataTransfer.files);e.preventDefault(),t.length>0&&N(t)},I=(e,t,n)=>e[(Math.max(0,e.indexOf(t))+n+e.length)%e.length],te=(e,t,n)=>r=>{if(r.ctrlKey||r.metaKey||r.altKey)return;let i=(e===`x`?{ArrowRight:1,l:1,ArrowLeft:-1,h:-1}:{ArrowDown:1,ArrowUp:-1})[r.key];if(i)t(i);else if(r.key===`Enter`&&n)n();else return;r.preventDefault()},ne=d===`done`?`tone-success`:d===`hold`?`tone-warning`:d===`doing`?`tone-accent`:`muted`,re=e=>t.detail.status[e];return(0,z.jsx)(`div`,{className:`overlay`,onMouseDown:e=>e.target===e.currentTarget&&M.current.close(),children:(0,z.jsxs)(`dialog`,{open:!0,className:`dialog is-wide kb-drawer`,"aria-label":i?t.detail.newStory:`#${n.id}`,onPaste:P,onDrop:F,onDragOver:e=>e.preventDefault(),children:[i?(0,z.jsx)(`h1`,{className:`kicker`,children:t.detail.newStory}):(0,z.jsxs)(`h1`,{className:`kicker kb-drawer-head`,children:[(0,z.jsxs)(`span`,{children:[`#`,n.id]}),(0,z.jsx)(`span`,{className:ne,children:re(d)}),(0,z.jsx)(`span`,{className:`muted`,children:U(t.detail.created,{date:n.created})}),a&&(0,z.jsx)(`span`,{className:`tone-accent`,children:t.detail.linked})]}),(0,z.jsxs)(`div`,{className:`dialog-body`,children:[(0,z.jsxs)(`label`,{className:`field`,children:[(0,z.jsx)(`span`,{className:`kicker`,children:t.detail.titleLabel}),(0,z.jsx)(`input`,{ref:C(`title`),className:`input`,spellCheck:!1,value:s,onChange:e=>c(e.target.value.replace(/[\r\n]+/g,` `)),onKeyDown:e=>{e.key===`Enter`&&!e.ctrlKey&&!e.metaKey&&(e.preventDefault(),S.current.description?.focus())}})]}),(0,z.jsxs)(`label`,{className:`field`,children:[(0,z.jsxs)(`span`,{className:`kicker kb-label`,children:[t.detail.description,(0,z.jsx)(`span`,{className:`muted kb-hint`,children:t.detail.attachHint}),b&&(0,z.jsx)(`span`,{className:`tone-accent`,children:`…`})]}),(0,z.jsx)(`textarea`,{ref:C(`description`),className:`input textarea kb-body`,rows:8,spellCheck:!1,placeholder:t.detail.noDescription,value:l,onChange:e=>u(e.target.value)})]}),!i&&(0,z.jsxs)(`div`,{className:`field`,children:[(0,z.jsxs)(`span`,{className:`kicker kb-label`,children:[t.detail.statusLabel,(0,z.jsx)(`span`,{className:`muted kb-hint`,children:`←/→`})]}),(0,z.jsx)(Lo,{fieldRef:C(`status`),label:t.detail.statusLabel,className:`chips-row`,onKeyDown:te(`x`,e=>f(I(Ro,d,e))),children:Ro.map(e=>(0,z.jsx)(`button`,{type:`button`,tabIndex:-1,"aria-pressed":e===d,className:`chip-button ${e===d?`is-active`:``}`,onClick:()=>{f(e),S.current.status?.focus()},children:re(e)},e))})]}),o?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`div`,{className:`field`,children:[(0,z.jsxs)(`span`,{className:`kicker kb-label`,children:[t.detail.engine,(0,z.jsx)(`span`,{className:`muted kb-hint`,children:`←/→`})]}),(0,z.jsx)(Lo,{fieldRef:C(`engine`),label:t.detail.engine,className:`chips-row`,onKeyDown:te(`x`,t=>h(I(e.engines.map(e=>e.id),p,t)),ee),children:e.engines.map(e=>(0,z.jsx)(`button`,{type:`button`,tabIndex:-1,"aria-pressed":e.id===p,className:`chip-button ${e.id===p?`is-active`:``}`,onClick:()=>{h(e.id),S.current.engine?.focus()},children:e.name},e.id))})]}),(0,z.jsxs)(`div`,{className:`field`,children:[(0,z.jsxs)(`span`,{className:`kicker kb-label`,children:[t.detail.workspace,(0,z.jsx)(`span`,{className:`muted kb-hint`,children:`↑/↓`})]}),(0,z.jsx)(Lo,{fieldRef:C(`workspace`),label:t.detail.workspace,className:`kb-places`,onKeyDown:te(`y`,e=>_(I(Po,g,e)),ee),children:Po.map(e=>(0,z.jsxs)(`button`,{type:`button`,tabIndex:-1,"aria-pressed":e===g,className:`kb-place ${e===g?`is-active`:``}`,onClick:()=>{_(e),S.current.workspace?.focus()},children:[e===g?`▸ `:` `,t.detail.placement[e]]},e))})]}),(0,z.jsxs)(`div`,{className:`field`,children:[(0,z.jsxs)(`span`,{className:`kicker kb-label`,children:[t.detail.jumpLabel,(0,z.jsx)(`span`,{className:`muted kb-hint`,children:`←/→`})]}),(0,z.jsx)(Lo,{fieldRef:C(`jump`),label:t.detail.jumpLabel,className:`chips-row`,onKeyDown:te(`x`,()=>y(!v),ee),children:[!1,!0].map(e=>(0,z.jsx)(`button`,{type:`button`,tabIndex:-1,"aria-pressed":e===v,className:`chip-button ${e===v?`is-active`:``}`,onClick:()=>{y(e),S.current.jump?.focus()},children:e?t.detail.jump.follow:t.detail.jump.stay},String(e)))})]}),(0,z.jsx)(`p`,{className:`muted kb-legend`,children:i?t.detail.createLegend:t.detail.startLegend})]}):a?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`div`,{className:`field`,children:[(0,z.jsx)(`span`,{className:`kicker`,children:t.detail.sessionLabel}),(0,z.jsxs)(`div`,{className:`chips-row kb-group`,children:[(0,z.jsx)(`button`,{ref:C(`open`),type:`button`,className:`chip-button is-active`,onClick:()=>O({kind:`open`,taskId:a,...E()}),children:t.detail.openAction}),(0,z.jsx)(`button`,{ref:C(`unlink`),type:`button`,className:`chip-button`,onClick:()=>O({kind:`unlink`,...E()}),children:t.detail.unlinkAction})]})]}),(0,z.jsx)(zo,{model:e.model,taskId:a}),(0,z.jsx)(`p`,{className:`muted kb-legend`,children:t.detail.openLegend})]}):(0,z.jsx)(`p`,{className:`muted kb-legend`,children:t.detail.doneNote})]})]})})}var Vo={"waiting-on-you":`tone-attention`,landing:`tone-success`,"ready-for-review":`tone-ink`,working:`tone-accent`};function Ho(e){let[t,n]=(0,m.useState)([]);return(0,m.useEffect)(()=>{e.client.request(`engines.list`).then(e=>n(e.engines)).catch(()=>n([]))},[e]),{engines:t,defaultEngine:(t.find(e=>e.ready!==!1)??t[0])?.id??``}}function Uo(e,t){let n=W(e),r=n.join(`
|
|
13
|
+
`).find(e=>e.trim().length>0)?.trim()??e.trim()}async function xa(e,t,n){try{let r=await e.client.request(`task.fixChecks`,e.engineTarget(t));r.outcome===`unavailable`?L(V(`files`,`toast.ciChecksUnavailable`,{detail:ba(r.detail??``)}),`error`):r.outcome===`none`?L(V(`files`,`toast.ciNoFailingChecks`),`error`):L(n)}catch(e){L(B(e),`error`)}}async function Sa(e,t){try{let n=await e.client.request(`task.openEditor`,{taskId:t});n.outcome===`noEditor`?L(V(`tasks`,`toast.noEditor`),`error`):n.outcome===`failed`&&L(V(`tasks`,`toast.openWorktreeFailed`,{label:n.label??``}),`error`)}catch(e){L(V(`tasks`,`toast.worktreeErrorGeneric`,{message:B(e)}),`error`)}}function Ca(e,t){return(0,z.jsx)(se,{title:V(`tasks`,`confirm.deleteTitle`,{title:t.title}),body:V(`tasks`,t.kind===`dir`?`confirm.deleteBodyDir`:`confirm.deleteBodyTask`),confirmLabel:V(`tasks`,`confirm.deleteConfirm`),onConfirm:()=>e.client.request(`task.delete`,{taskId:t.id}).then(()=>{}),escalate:{when:e=>e instanceof Ar&&e.code===`DIRTY_WORKTREE`,label:V(`tasks`,`confirm.forceDeleteConfirm`),title:V(`tasks`,`confirm.forceDeleteTitle`,{title:t.title}),body:e=>`${V(`worktrees`,`delete.forceBody`,{branch:t.branch||t.title})}\n\n${V(`worktrees`,`delete.forceReason`,{reason:B(e).replace(`task ${t.id} `,``)})}`,run:()=>e.client.request(`task.delete`,{taskId:t.id,force:!0}).then(()=>{})}})}function wa(e,t,n){return(0,z.jsx)(se,{title:V(`tasks`,`confirm.forgetProjectTitle`,{title:n}),body:V(`tasks`,`confirm.forgetProjectBody`),confirmLabel:V(`tasks`,`confirm.forgetProjectConfirm`),onConfirm:async()=>{try{await e.client.request(`project.forget`,{repo:t})}catch(e){throw Error(V(`tasks`,`toast.forgetProjectFailed`,{error:B(e)}))}}})}var Ta=e=>{let{taskId:t}=e.selection.get();return e.tasks.get()?.tasks.find(e=>e.id===t)??null},Ea=e=>{let{taskId:t,tabId:n}=e.selection.get(),r=t?e.tabs.get()[t]?.find(e=>e.id===n):void 0;return!!r&&!ca(r.split)},Da=[{id:`app.refresh`,live:()=>it.get().stale,run:e=>ct(e.client)},{id:`palette.open`,live:()=>!0,run:Gr},{id:`task.new.global`,live:()=>!0,run:e=>k.set((0,z.jsx)(Hr,{model:e,repo:Ta(e)?.repo}))},{id:`chat.tab.fork`,live:e=>!!Ta(e),run:e=>{let t=Ta(e);t&&k.set((0,z.jsx)(_r,{model:e,taskId:t.id,context:`continue`}))}},{id:`chat.fork.new`,live:e=>!!Ta(e),run:e=>{let t=Ta(e);t&&k.set((0,z.jsx)(_r,{model:e,taskId:t.id,destination:`fork`}))}},{id:`settings.open`,live:()=>!0,run:e=>k.set((0,z.jsx)(oa,{client:e.client}))},{id:`inbox.show`,live:()=>!0,run:e=>k.set((0,z.jsx)(qn,{model:e}))},{id:`focus.previous`,live:()=>!0,run:()=>Xr(-1)},{id:`focus.next`,live:()=>!0,run:()=>Xr(1)},{id:`workspace.zenToggle`,live:e=>!!Ta(e),run:()=>F.set(!F.get())},{id:`files.createPR`,live:e=>!!Ta(e),run:e=>{let t=Ta(e);t&&e.client.request(`tab.requestPR`,e.engineTarget(t.id)).then(()=>L(T(`files.prRequested`))).catch(e=>L(e instanceof Error?e.message:String(e),`error`))}},{id:`chat.tab.close`,live:e=>!!e.selection.get().tabId&&Ea(e),run:e=>{let{taskId:t,tabId:n}=e.selection.get();!t||!n||e.client.request(`tab.close`,{taskId:t,tabId:n}).then(()=>e.refreshTabsNow()).catch(e=>L(e instanceof Error?e.message:String(e),`error`))}},{id:`kanban.open`,live:()=>!0,run:()=>M.set(`kanban`)},{id:`automations.open`,live:()=>!0,run:()=>M.set(`routines`)},{id:`workItems.open`,live:()=>!0,run:()=>M.set(`issues`)},{id:`task.moveMode`,live:e=>!!Qr(e),run:()=>{Jn.set(!Jn.get()),document.querySelector(`.rail`)?.focus()}},{id:`files.syncBase`,live:e=>Qr(e)?.kind===`task`,run:e=>{let t=Qr(e);t&&ya(e,t.id)}},{id:`files.fixChecks`,live:e=>!!Qr(e),run:e=>{let t=Qr(e);t&&xa(e,t.id,T(`taskops.fixSent`))}},{id:`task.openEditor`,live:e=>!!Qr(e),run:e=>{let t=Qr(e);t&&Sa(e,t.id)}}];At(()=>Da.map(e=>({id:e.id,chords:et(e.id),prefix:!0,live:e.live,run:e.run})));function Oa(e){return An(e[0]??``)}function ka(e,t){let n=Ft(),r=Mt().filter(t=>t.prefix&&Nt(t,n)&&t.live?.(e)!==!1);for(let e of t){let t=r.filter(t=>t.chords.includes(e)).sort((e,t)=>Pt(e,n)-Pt(t,n))[0];if(t)return t}}var Aa=null,ja=null;function Ma(){Aa=null,ja!==null&&window.clearTimeout(ja),ja=null;let e=Pn.get();e.guide?.kind===`prefix`&&Pn.set({...e,guide:null})}function Na(){k.get()||Ye()===null||(Aa=Date.now(),Pn.set({...Pn.get(),guide:{kind:`prefix`,armedAt:Aa}}),ja!==null&&window.clearTimeout(ja),ja=window.setTimeout(Ma,We.get().prefix.timeoutMs))}function Pa(e,t){Ma();let n=typeof t==`string`?[t]:t,r=ka(e,n);In(Oa(n),r?.id??null),r?.run(e)}var Fa=null;function Ia(){Fa!==null&&window.clearTimeout(Fa),Fa=null;let e=Pn.get();e.guide?.kind===`direct`&&Pn.set({...e,guide:null})}function La(){Fa!==null||k.get()||(Fa=window.setTimeout(()=>{Ma(),Pn.set({...Pn.get(),guide:{kind:`direct`}})},400))}function Ra(e){(0,m.useEffect)(()=>{let t=t=>{if(t.key===`Control`){t.repeat||La();return}if(Ia(),[`Shift`,`Alt`,`Meta`].includes(t.key))return;let n=kn(t),{firstStrokes:r,timeoutMs:i}=We.get().prefix;if(Aa!==null&&Date.now()-Aa<=i){if(t.preventDefault(),t.stopImmediatePropagation(),t.key===`Escape`)return Ma();Pa(e,n);return}Ma(),!k.get()&&n.some(e=>r.includes(e))&&(t.preventDefault(),t.stopImmediatePropagation(),Na())},n=e=>e.key===`Control`&&Ia();return window.addEventListener(`keydown`,t,{capture:!0}),window.addEventListener(`keyup`,n,{capture:!0}),window.addEventListener(`blur`,Ia),()=>{window.removeEventListener(`keydown`,t,{capture:!0}),window.removeEventListener(`keyup`,n,{capture:!0}),window.removeEventListener(`blur`,Ia),Ia(),Ma()}},[e])}function za(e){let t=Ft(),n=new Map;for(let r of Mt()){if(!r.prefix||!Nt(r,t)||r.live?.(e)===!1)continue;let i=Pt(r,t);for(let e of r.chords){let t=n.get(e);(!t||i<t.rank)&&n.set(e,{action:r.id,rank:i})}}return[...n].map(([e,{action:t}])=>({stroke:e,action:t}))}function Ba(e){let t=new Map(ze.map((e,t)=>[e.id,t])),n=new Map;for(let{stroke:t,action:r}of e)n.set(r,[...n.get(r)??[],t]);let r=new Map,i=[...n].sort(([e],[n])=>(t.get(e)??2**53-1)-(t.get(n)??2**53-1));for(let[e,t]of i){let n=wt(e);r.set(n,[...r.get(n)??[],{action:e,strokes:t}])}return[...r].map(([e,t])=>({category:e,actions:t}))}var Va=e=>e===`prefix.moreCommands`?qt(`moreCommandsPrefix`):Zt(e);function Ha(e){let[,t]=(0,m.useState)(0);(0,m.useEffect)(()=>{if(e===null)return;let n=window.setTimeout(()=>t(e=>e+1),Math.max(30,e-Date.now()));return()=>window.clearTimeout(n)},[e])}function Ua({model:e}){D();let t=v(Pn);v(We),v(e.selection);let n=Date.now(),r=t.entries.filter(e=>n-e.at<Nn),i=t.guide?.kind===`prefix`?t.guide.armedAt:null,a=i!==null&&n-i<Mn?i+Mn:null;Ha(a??(r[0]?r[0].at+Nn:null));let o=t.guide?.kind===`direct`||i!==null&&a===null;if(!o&&!t.guide&&r.length===0)return null;if(o&&t.guide){let n=t.guide.kind===`direct`,r=n?En(It(e,Ft()),Ye()):za(e);return(0,z.jsxs)(`output`,{className:`prefix-guide mono`,onMouseDown:e=>e.preventDefault(),children:[(0,z.jsxs)(`div`,{className:`prefix-guide-head`,children:[(0,z.jsx)(`span`,{className:`tone-accent`,children:n?qt(`directLayer`):qt(`commandLayer`,{prefix:Ye()??``})}),(0,z.jsx)(`span`,{className:`muted`,children:qt(n?`releaseCtrl`:`escCancel`)})]}),(0,z.jsx)(`div`,{className:`prefix-guide-body`,children:Ba(r).map(t=>(0,z.jsxs)(`div`,{className:`prefix-guide-group`,children:[(0,z.jsx)(`div`,{className:`tone-accent`,children:Qt(t.category)}),t.actions.map(({action:t,strokes:r})=>(0,z.jsxs)(`button`,{type:`button`,className:`prefix-guide-row`,disabled:n,onClick:()=>r[0]&&Pa(e,r[0]),children:[(0,z.jsx)(`span`,{className:`prefix-hud-key`,children:r.map(An).join(`/`)}),(0,z.jsx)(`span`,{children:Va(t)})]},t))]},t.category))})]})}return(0,z.jsxs)(`output`,{className:`prefix-hud mono`,children:[r.map(e=>(0,z.jsxs)(`div`,{className:`prefix-hud-head`,children:[(0,z.jsx)(`span`,{className:`tone-accent`,children:Ye()}),` + `,e.stroke,` →`,` `,e.action?Va(e.action):(0,z.jsx)(`span`,{className:`muted`,children:`∅`})]},e.id)),i!==null&&(0,z.jsxs)(`div`,{className:`prefix-hud-head`,children:[(0,z.jsx)(`span`,{className:`tone-accent`,children:Ye()}),` ⋯`]})]})}function Wa({model:e,bindingId:t}){let n=v(Pn);v(We);let r=vi().prefs.prefixTap;if(n.guide?.kind!==`prefix`||r!==`local`)return null;let i=Tn({bindingId:t,reachability:It(e,Ft()),prefixKey:Ye()});if(!i)return null;let a=Mt().find(e=>e.id===t&&e.prefix)?.chords[0];return(0,z.jsx)(`button`,{type:`button`,className:`shortcut-badge mono`,onMouseDown:e=>e.preventDefault(),onClick:t=>{t.stopPropagation(),a&&Pa(e,a)},children:i})}var Ga=1e4;function Ka(e,t){let n=e.hostLabel||e.alias;if(e.state===`online`)return e.version?`${n} · v${e.version}`:n;let r=t[e.state];return e.state===`mismatch`?e.version?`${n} · ⚠ v${e.version} (${r})`:`${n} · ⚠ ${r}`:`${n} · ${r}`}function qa({row:e,words:t}){return(0,z.jsxs)(`h2`,{className:`machine-head ${e.state===`online`?``:`is-stale`}`,title:e.alias,children:[(0,z.jsx)(`span`,{children:Ka(e,t)}),(0,z.jsx)(`span`,{className:`rule`})]})}function Ja({host:e}){return D(),(0,z.jsxs)(`div`,{className:`remote-notice`,children:[(0,z.jsx)(`p`,{className:`muted`,children:V(`tasks`,`machine.filesElsewhere`,{host:e})}),(0,z.jsx)(`p`,{className:`muted`,children:V(`tasks`,`machine.filesHint`,{host:e})})]})}function Ya(e){let t=v(e.client.conn),n=v(e.remote),[r,i]=(0,m.useState)([]),a=[...new Set(n.map(e=>`${e.machine?.id}:${e.machine?.stale??!1}`))].join();return(0,m.useEffect)(()=>{if(t.state!==`open`)return;let n=!0,r=()=>e.client.request(`machines.list`).then(e=>n&&i(e.machines),()=>{});r();let a=window.setInterval(r,Ga);return()=>{n=!1,window.clearInterval(a)}},[e.client,t.state,a]),r}function Xa(e){let t=Math.floor(e/6e4),n=Math.floor(t/60);return{minutes:t,hours:n,days:Math.floor(n/24)}}function Za(e,t=Date.now()){let n=Math.max(0,t-e),r=Math.floor(n/1e3);if(r<60)return`${r}s`;let{minutes:i,hours:a,days:o}=Xa(n);return i<60?`${i}m`:a<24?`${a}h`:`${o}d`}var Qa={title:`ROUTINES`,holdingDaemon:`keeping the daemon awake`,notHolding:`none active`,needAttention:`{count} of {total} need you ·`,paused:`paused`,newTitle:`New routine`,composerLegend:`enter create · tab fields · ←→ ↑↓ edit the focused field · esc cancel`,fieldName:`NAME`,fieldRepo:`REPO`,fieldTarget:`DELIVER TO`,fieldTargetTab:`EXISTING ENGINE TAB`,targetFresh:`New task on each run`,targetStanding:`Routine-owned standing task`,targetExisting:`Existing conversation: {task} / {tab}. Never creates or revives a session.`,fieldPrompt:`PROMPT`,fieldSchedule:`SCHEDULE (FIVE-FIELD CRON)`,namePlaceholder:`weekday dependency audit`,promptPlaceholder:`Audit dependencies and summarize risky changes.`,needRepo:`Open a project first — a routine runs in one.`,cronInvalid:`not a five-field cron`,cronField:{minute:`min`,hour:`hour`,dayOfMonth:`day`,month:`month`,dayOfWeek:`weekday`},schedule:{everyDay:`every day {at}`,weekdays:`weekdays {at}`,weekends:`weekends {at}`,onWeekday:`{weekday} {at}`,everyMinute:`every minute`,everyMinutes:`every {n}m`,everyHours:`every {n}h`,hourlyAt:`hourly at :{minute}`,atClock:`at {time}`,dow:{MON:`Mondays`,TUE:`Tuesdays`,WED:`Wednesdays`,THU:`Thursdays`,FRI:`Fridays`,SAT:`Saturdays`,SUN:`Sundays`}},when:{inMinutes:`in {n}m`,inHours:`in {n}h`,inDays:`in {n}d`,minutesAgo:`{n}m ago`,hoursAgo:`{n}h ago`,now:`now`,justNow:`just now`,dateTime:`{date}, {time}`},runStatus:{dispatched:`dispatched`,revived:`revived`,skipped_cancelled:`cancelled before delivery`,skipped_precheck:`skipped (precheck)`,skipped_blocked:`skipped (task can't use it)`,skipped_missed:`skipped (missed)`,skipped_unavailable:`skipped (unavailable)`,dispatch_failed:`dispatch failed`},cronNever:`valid, but never fires`,missing:{target:`Choose an existing task.`,targetTab:`Enter an existing tab id, e.g. tab-2.`,name:`Give it a name.`,repo:`Pick a project.`,prompt:`Say what it should do.`,schedule:`That schedule will not run.`},empty:`No routines scheduled.`,emptyHint:`Press n to create one.`,precheck:`precheck: {command}`,recentRuns:`RECENT RUNS`,precheckDetail:`WHY IT SKIPPED — precheck {exit} in {duration}ms`,precheckExited:`exited {code}`,precheckTimedOut:`timed out`,precheckStdout:`stdout`,precheckStderr:`stderr`,precheckNoOutput:`(no output)`,noRuns:`Not run yet.`,responses:`RESPONSES`,noResponses:"No run has reported back yet. Agents answer with `routine-respond`.",responseAwaiting:`awaiting response`,responseMissing:`no response`,noSelection:`A routine runs its prompt in a project on a schedule.`,running:`Running {name}…`,ranWith:`{name}: {status}`,latestRunNoTask:`The latest run created no task.`,runNow:`[ run now ]`,deleteTitle:`Delete routine?`,deleteBody:`{name} and its run history will be removed. Tasks it already created are untouched.`,deleteButton:`Delete`,createFailed:`Couldn't create the routine: {error}`,deleteFailed:`Couldn't delete "{name}": {error}`,enableFailed:`"{name}" stays paused: {error}`,disableFailed:`"{name}" stays enabled: {error}`,runFailed:`Couldn't run "{name}" now — schedule unchanged: {error}`},$a={title:`例行任务`,holdingDaemon:`正在保持守护进程常驻`,notHolding:`无启用项`,needAttention:`{total} 个中有 {count} 个需要处理 ·`,paused:`已暂停`,newTitle:`新建例行任务`,composerLegend:`enter 创建 · tab 切字段 · ←→ ↑↓ 编辑当前字段 · esc 取消`,fieldName:`名称`,fieldTarget:`投递目标`,fieldTargetTab:`既有引擎标签页`,targetFresh:`每次新建任务`,targetStanding:`例行任务自有的常驻任务`,targetExisting:`既有会话:{task} / {tab}。不会创建或重启会话。`,fieldRepo:`仓库`,fieldPrompt:`提示词`,fieldSchedule:`调度(五段 cron)`,namePlaceholder:`工作日依赖审计`,promptPlaceholder:`审计依赖并总结有风险的变更。`,needRepo:`先打开一个项目——例行任务要跑在某个项目里。`,cronInvalid:`不是合法的五段 cron`,cronField:{minute:`分`,hour:`时`,dayOfMonth:`日`,month:`月`,dayOfWeek:`星期`},schedule:{everyDay:`每天{at}`,weekdays:`工作日{at}`,weekends:`周末{at}`,onWeekday:`{weekday}{at}`,everyMinute:`每分钟`,everyMinutes:`每 {n} 分钟`,everyHours:`每 {n} 小时`,hourlyAt:`每小时的 :{minute}`,atClock:`{time}`,dow:{MON:`每周一`,TUE:`每周二`,WED:`每周三`,THU:`每周四`,FRI:`每周五`,SAT:`每周六`,SUN:`每周日`}},when:{inMinutes:`{n} 分钟后`,inHours:`{n} 小时后`,inDays:`{n} 天后`,minutesAgo:`{n} 分钟前`,hoursAgo:`{n} 小时前`,now:`即将`,justNow:`刚刚`,dateTime:`{date} {time}`},runStatus:{dispatched:`已派发`,revived:`已重启会话`,skipped_cancelled:`交付前已取消`,skipped_precheck:`已跳过(预检)`,skipped_blocked:`已跳过(任务暂不能接收)`,skipped_missed:`已跳过(错过时间)`,skipped_unavailable:`已跳过(不可用)`,dispatch_failed:`派发失败`},cronNever:`语法合法,但永远不会触发`,missing:{target:`请选择既有任务。`,targetTab:`请输入既有标签页 ID,例如 tab-2。`,name:`起个名字。`,repo:`选一个项目。`,prompt:`说明它要做什么。`,schedule:`这个调度不会触发。`},empty:`还没有例行任务。`,emptyHint:`按 n 新建一条。`,precheck:`预检:{command}`,recentRuns:`最近执行`,precheckDetail:`为什么跳过 —— 预检{exit},耗时 {duration}ms`,precheckExited:`退出码 {code}`,precheckTimedOut:`超时`,precheckStdout:`标准输出`,precheckStderr:`标准错误`,precheckNoOutput:`(无输出)`,noRuns:`尚未执行。`,responses:`回报`,noResponses:"还没有执行回报。agent 用 `routine-respond` 回报。",responseAwaiting:`等待回报`,responseMissing:`未回报`,noSelection:`例行任务会按调度在某个项目里跑它的提示词。`,running:`正在运行 {name}…`,ranWith:`{name}:{status}`,latestRunNoTask:`最近一次执行没有创建任务。`,runNow:`[ 立即运行 ]`,deleteTitle:`删除这条例行任务?`,deleteBody:`将删除 {name} 及其执行记录。它已经创建的任务不受影响。`,deleteButton:`删除`,createFailed:`创建例行任务失败:{error}`,deleteFailed:`删除“{name}”失败:{error}`,enableFailed:`“{name}”仍处于暂停状态:{error}`,disableFailed:`“{name}”仍处于启用状态:{error}`,runFailed:`无法立即运行“{name}”——排程未受影响:{error}`},eo={title:`Kanban`,hint:`tab project · ←↓↑→ card · enter detail · n new · d delete · r refresh · esc close`,loading:`Loading issues…`,noRepos:"No projects yet — add one with `rove add <path>`, or file a story with `rove api issue-create`.",empty:"No issues — agents file them via `rove api issue-create`.",readFailed:"Couldn't read this project's stories: {error}. Run `rove doctor`, then reopen Kanban.",readFailedToast:`Couldn't read stories for {repo}: {error}`,columnEmpty:`No cards`,column:{backlog:`Backlog`,inProgress:`In progress`,parked:`Parked`,done:`Done`},more:`+{count} more`,attention:`{count} need you`,turnComplete:`turn done`,menu:{setStatus:`status → {status}`},detail:{status:{open:`open`,doing:`doing`,hold:`hold`,done:`done`},statusLabel:`STATUS`,created:`created {date}`,linked:`linked to a session`,titleLabel:`TITLE`,description:`DESCRIPTION`,noDescription:`No description.`,attachHint:`paste a path / ctrl+v screenshot → inserts an image placeholder`,engine:`ENGINE`,workspace:`WORKSPACE`,placement:{worktree:`New worktree task — its own workspace`,projectWorktree:`New worktree — as a chattab in the project workspace`,project:`Project checkout — a new chattab, no worktree`},jumpLabel:`AFTER START`,jump:{stay:`Stay on the board`,follow:`Jump to the session`},startLegend:`enter/ctrl+enter start · tab fields · ←→ status/engine · ↑↓ workspace · esc save & close`,sessionLabel:`SESSION`,openAction:`Open the linked session ↵`,unlinkAction:`Unlink`,openLegend:`enter open the focused action · tab fields · ←→ status · unlink returns the card to Backlog · esc save & close`,eventsLabel:`EVENTS`,eventsLoading:`Loading events…`,eventsNone:`No engine events recorded yet.`,doneNote:`Done stories have nothing left to start — set the status back to reopen one · esc save & close`,startedBackground:`Started in background: {title}`,newStory:`NEW STORY`,createLegend:`ctrl+s save · enter/ctrl+enter save & start · tab fields · esc cancel`},confirmDelete:{title:`Delete story #{id}?`,body:`“{title}” will be removed from the tracker. A linked task, branch, or worktree is left untouched.`},deleteFailed:`Couldn't delete story #{id}: {error}`,createFailed:`Couldn't create the story: {error}`,updateFailed:`Couldn't save story #{id}: {error}`,statusFailed:`Story #{id} stays in its old column: {error}`,linkFailed:`Story #{id} isn't linked to its task: {error}`,unlinkFailed:`Story #{id} is still linked: {error}`},to={title:`看板`,hint:`tab 切项目 · ←↓↑→ 选卡片 · enter 详情 · n 新建 · d 删除 · r 刷新 · esc 关闭`,loading:`正在加载 issues…`,noRepos:"还没有项目——用 `rove add <路径>` 添加一个,或用 `rove api issue-create` 创建一个 story。",empty:"暂无 issue——agent 可通过 `rove api issue-create` 创建。",readFailed:"读取该项目的 story 失败:{error}。请运行 `rove doctor`,再重新打开看板。",readFailedToast:`读取 {repo} 的 story 失败:{error}`,columnEmpty:`暂无卡片`,column:{backlog:`待办`,inProgress:`进行中`,parked:`搁置`,done:`已完成`},more:`还有 {count} 条`,attention:`{count} 张等你处理`,turnComplete:`回合完成`,menu:{setStatus:`状态 → {status}`},detail:{status:{open:`待办`,doing:`进行中`,hold:`搁置`,done:`已完成`},statusLabel:`状态`,created:`创建于 {date}`,linked:`已关联会话`,titleLabel:`标题`,description:`描述`,noDescription:`暂无描述。`,attachHint:`粘贴路径 / ctrl+v 贴截图 → 插入图片占位行`,engine:`引擎`,workspace:`工作区`,placement:{worktree:`新建 worktree 任务——独立工作区`,projectWorktree:`新建 worktree——作为项目工作区里的 chattab`,project:`项目主目录——新开 chattab,不建 worktree`},jumpLabel:`启动后`,jump:{stay:`留在看板`,follow:`跳转到会话`},startLegend:`enter/ctrl+enter 启动 · tab 切字段 · ←→ 状态/引擎 · ↑↓ 工作区 · esc 保存关闭`,sessionLabel:`会话`,openAction:`打开关联会话 ↵`,unlinkAction:`解除关联`,openLegend:`enter 执行选中操作 · tab 切字段 · ←→ 状态 · 解除关联把卡片退回 Backlog · esc 保存关闭`,eventsLabel:`事件`,eventsLoading:`正在加载事件…`,eventsNone:`暂无引擎事件记录。`,doneNote:`已完成的 story 无需启动——改回状态即可重新打开 · esc 保存关闭`,startedBackground:`已在后台启动:{title}`,newStory:`新建 STORY`,createLegend:`ctrl+s 仅保存 · enter/ctrl+enter 保存并启动 · tab 切字段 · esc 取消`},confirmDelete:{title:`删除 story #{id}?`,body:`「{title}」将从 tracker 中移除。已关联的任务、分支、worktree 不受影响。`},deleteFailed:`删除 story #{id} 失败:{error}`,createFailed:`创建 story 失败:{error}`,updateFailed:`保存 story #{id} 失败:{error}`,statusFailed:`Story #{id} 仍留在原来的列:{error}`,linkFailed:`Story #{id} 未能关联到它的任务:{error}`,unlinkFailed:`Story #{id} 仍处于关联状态:{error}`},no={title:`ISSUES`,noRepo:`no project`,empty:`No open issues.`,assignedFilter:`assigned to me`,starting:`Starting work on #{number}…`,startedNoEngine:`Created {title}, but its engine did not start.`,linkedChip:`→ {title}`,openingLinked:`Opening {title}…`,startFailed:`Couldn't start work on #{number}: {error}`,errorHint:{noRemote:"Add a GitHub remote (`git remote add origin <url>`) and try again, or press q / esc to close.",ghMissing:"Install the `gh` CLI and authenticate, or press q / esc to close.",auth:"Run `gh auth login`, or press q / esc to close.",fallback:`{message} · press q / esc to close`}},ro={title:`议题`,noRepo:`无项目`,empty:`没有开放的议题。`,assignedFilter:`分配给我的`,starting:`正在开始处理 #{number}…`,startedNoEngine:`已创建 {title},但引擎没有启动。`,linkedChip:`→ {title}`,openingLinked:`正在打开 {title}…`,startFailed:`开始处理 #{number} 失败:{error}`,errorHint:{noRemote:"添加 GitHub remote(`git remote add origin <url>`)后重试,或按 q / esc 关闭。",ghMissing:"安装 `gh` CLI 并登录,或按 q / esc 关闭。",auth:"执行 `gh auth login`,或按 q / esc 关闭。",fallback:`{message} · 按 q / esc 关闭`}};function io(){let e=D()===`zh`;return{kanban:e?to:eo,auto:e?$a:Qa,items:e?ro:no,nav:(e?Te:we).nav,group:(e?Te:we).group,common:e?de:ue}}function U(e,t){return e.replace(/\{(\w+)\}/g,(e,n)=>String(t[n]??e))}function ao(e){return e instanceof Error?e.message:String(e)}function oo(e){return e.replace(/^\/private\//,`/`).replace(/\/+$/,``)}function so(e,t){let n=e.split(`/`).filter(Boolean),r=n[n.length-1]??e;return t.some(t=>t!==e&&t.split(`/`).filter(Boolean).pop()===r)&&n.length>1?`${n[n.length-2]}/${r}`:r}function co(...e){let t=new Set,n=[];for(let r of e.flat()){if(!r||r.startsWith(`ssh://`))continue;let e=oo(r);t.has(e)||(t.add(e),n.push(r))}return n}function W(e){return co((v(e.tasks)?.tasks??[]).map(e=>e.repo))}function lo(e){let t=v(e.tasks),{taskId:n}=v(e.selection);return t?.tasks.find(e=>e.id===n)?.repo}function uo(e){let[t,n]=(0,m.useState)(0);return(0,m.useEffect)(()=>{let t=window.setInterval(()=>n(e=>e+1),e);return()=>window.clearInterval(t)},[e]),[t,(0,m.useCallback)(()=>n(e=>e+1),[])]}function fo(e){return e instanceof HTMLElement?e.isContentEditable||[`INPUT`,`TEXTAREA`,`SELECT`].includes(e.tagName):!1}function po(e){let t=(0,m.useRef)(e);t.current=e,(0,m.useEffect)(()=>{let e=e=>{if(e.defaultPrevented||k.get()||O.get())return;let n=e.target instanceof HTMLElement?e.target:null;fo(n)||n?.closest(`.rail, .files, .xterm`)||e.metaKey||e.altKey||e.ctrlKey&&e.key.toLowerCase()===`c`&&window.getSelection()?.toString()||t.current(e)&&(e.preventDefault(),e.stopPropagation())};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[])}function mo(){let e=(0,m.useRef)(null);return(0,m.useEffect)(()=>e.current?.focus(),[]),e}var ho=30;function go(){let{items:e}=io();return t=>{let n=t.indexOf(`: `);switch(n>=0?t.slice(0,n):`failed`){case`no-remote`:return e.errorHint.noRemote;case`gh-missing`:return e.errorHint.ghMissing;case`auth`:return e.errorHint.auth;default:return U(e.errorHint.fallback,{message:t})}}}function _o({model:e}){let{items:t,common:n}=io(),r=go(),i=e.client,a=v(e.tasks),o=W(e),s=lo(e),[c,l]=(0,m.useState)(()=>{let e=s?o.findIndex(e=>oo(e)===oo(s)):-1;return Math.max(0,e)}),u=o[c],[d,f]=(0,m.useState)(null),[p,h]=(0,m.useState)({}),[g,_]=(0,m.useState)(null),[y,b]=(0,m.useState)(!1),[x,S]=(0,m.useState)(0),[C,w]=(0,m.useState)(0),[T,E]=(0,m.useState)(!1),[D,O]=(0,m.useState)(null),k=mo(),ee=(0,m.useRef)(!1);(0,m.useEffect)(()=>{let e=!0;if(!u){f([]);return}_(null);let t=ee.current;return ee.current=!1,i.request(`workitem.list`,{repo:u,limit:ho,...y?{assignee:`@me`}:{},...t?{refresh:!0}:{}}).then(t=>e&&f(t.items)).catch(t=>{e&&(_(ao(t)),f([]))}),i.request(`workitem.links`,{repo:u}).then(t=>e&&h(Object.fromEntries(t.links.map(e=>[e.number,e.taskId])))).catch(()=>e&&h({})),()=>{e=!1}},[i,u,y,x,a?.tasks.length]);let A=d??[],j=Math.min(C,Math.max(0,A.length-1));(0,m.useEffect)(()=>O(null),[u,y]);let N=(0,m.useRef)(null);(0,m.useEffect)(()=>{N.current?.querySelector(`[data-row="${j}"]`)?.scrollIntoView({block:`nearest`})},[j]);let P=e=>a?.tasks.find(t=>t.id===e)?.title??e,F=t=>{M.set(null),e.select(t)},I=async()=>{let e=A[j];if(!e||!u||T)return;let n=p[e.number];if(n){O(U(t.openingLinked,{title:P(n)})),F(n);return}E(!0),O(U(t.starting,{number:e.number}));try{let n=await i.request(`workitem.start`,{repo:u,number:e.number});n.started?F(n.taskId):O(U(t.startedNoEngine,{title:n.title}))}catch(n){L(U(t.startFailed,{number:e.number,error:ao(n)}),`error`)}finally{E(!1)}};po(e=>{if(e.ctrlKey)return e.key===`c`&&(M.set(null),!0);switch(e.key){case`Escape`:case`q`:return M.set(null),!0;case`j`:case`ArrowDown`:return w(Math.min(A.length-1,j+1)),!0;case`k`:case`ArrowUp`:return w(Math.max(0,j-1)),!0;case`Tab`:return l(t=>o.length?(t+(e.shiftKey?o.length-1:1))%o.length:0),!0;case`a`:return b(e=>!e),!0;case`r`:return ee.current=!0,S(e=>e+1),!0;case`Enter`:return I(),!0;default:return!1}});let te=Date.now();return(0,z.jsxs)(`div`,{className:`page`,tabIndex:0,ref:k,children:[(0,z.jsxs)(`div`,{className:`pg-top`,children:[(0,z.jsx)(`h1`,{className:`page-title`,children:t.title}),(0,z.jsxs)(`span`,{className:`muted mono pg-hint`,children:[u?so(u,o):t.noRepo,y?` ${t.assignedFilter}`:``]})]}),g?(0,z.jsxs)(`div`,{className:`pg-list`,children:[(0,z.jsx)(`p`,{className:`error`,children:g}),(0,z.jsx)(`p`,{className:`muted`,children:r(g)})]}):d===null?(0,z.jsx)(`p`,{className:`muted`,children:n.loading}):A.length===0?(0,z.jsx)(`p`,{className:`muted`,children:t.empty}):(0,z.jsx)(`div`,{className:`pg-list`,ref:N,children:A.map((e,n)=>{let r=p[e.number],i=Date.parse(e.updatedAt);return(0,z.jsxs)(`div`,{"data-row":n,className:`pg-issue ${n===j?`is-cursor`:``}`,onClick:()=>n===j?void I():w(n),children:[(0,z.jsxs)(`div`,{className:`pg-issue-line`,children:[(0,z.jsxs)(`span`,{className:`pg-num mono`,children:[`#`,e.number]}),(0,z.jsx)(`span`,{className:`pg-grow`,children:e.title})]}),(0,z.jsxs)(`div`,{className:`pg-issue-sub`,children:[(0,z.jsx)(`span`,{className:`pg-grow`,children:[e.author,...e.labels.slice(0,2)].filter(Boolean).join(` · `)}),r&&(0,z.jsx)(`span`,{children:U(t.linkedChip,{title:P(r)})}),(0,z.jsx)(`span`,{className:`mono`,children:Number.isFinite(i)?Za(i,te):``})]})]},e.number)})}),D&&(0,z.jsx)(`p`,{className:`muted pg-notice`,children:D})]})}var vo={backlog:`active`,in_progress:`active`,in_review:`parked`,error:`parked`,done:`terminal`,canceled:`terminal`,open:`active`,doing:`active`,hold:`parked`};function yo(e){return vo[e]??`parked`}var bo=[`backlog`,`in_progress`,`parked`,`done`];function xo(e,t,n){let r=e.find(e=>e.issues.length>0)?.issues[0]?.id??null;if(t==null)return r;let i=-1,a=-1;for(let[n,r]of e.entries()){let e=r.issues.findIndex(e=>e.id===t);if(e!==-1){i=n,a=e;break}}if(i===-1)return r;if(n===`up`||n===`down`){let r=e[i]?.issues??[],o=n===`up`?a-1:a+1;return r[Math.max(0,Math.min(o,r.length-1))]?.id??t}let o=n===`left`?-1:1;for(let n=i+o;n>=0&&n<e.length;n+=o){let r=e[n]?.issues??[];if(r.length!==0)return r[Math.min(a,r.length-1)]?.id??t}return t}function So(e,t){let n=yo(e.status);return n===`terminal`?`done`:n===`parked`?`parked`:e.taskId!==void 0&&e.taskId!==``&&(t?.(e.taskId)??!0)||e.status===`doing`?`in_progress`:`backlog`}function Co(e,t){let n=0;return{columns:e.map(e=>{if(e.key!==`in_progress`)return e;let r=[],i=[];for(let n of e.issues)n.taskId!==void 0&&n.taskId!==``&&t(n.taskId)?r.push(n):i.push(n);return n=r.length,r.length===0?e:{...e,issues:[...r,...i]}}),attentionCount:n}}function wo(e,t){return e.created===t.created?t.id-e.id:e.created<t.created?1:-1}function To(e,t){let n={backlog:[],in_progress:[],parked:[],done:[]};for(let r of e)n[So(r,t)].push(r);return bo.map(e=>{let t=e===`done`||e===`parked`,r=n[e].sort(wo);return!t||r.length<=20?{key:e,issues:r,hiddenCount:0}:{key:e,issues:r.slice(0,20),hiddenCount:r.length-20}})}var Eo=[`image/png`,`image/jpeg`,`image/gif`,`image/webp`,`application/pdf`],Do=5242880;function Oo(e,t){return/\.pdf$/i.test(e)?`pdf[${t}]`:`images[${t}]`}function ko(e){let t=-1;for(let n of e.matchAll(/^(?:images|pdf)\[(\d+)\]:/gm)){let e=Number.parseInt(n[1],10);e>t&&(t=e)}return t+1}function Ao(e,t){let n=e.replace(/\s+$/,``),r=ko(e);for(let e of t){let t=`${Oo(e,r)}: ${e}`;n=n.length>0?`${n}\n${t}`:t,r+=1}return n}function jo(e){return Array.from(e??[]).filter(e=>Eo.includes(e.type))}function Mo(e){let t=``;for(let n=0;n<e.length;n+=32768)t+=String.fromCharCode(...e.subarray(n,n+32768));return btoa(t)}async function No(e,t){let n=Mo(new Uint8Array(await t.arrayBuffer()));return(await e.request(`attachment.put`,{mime:t.type,data:n})).path}var Po=[`worktree`,`projectWorktree`,`project`];async function Fo(e,t){let n=t.placement===`project`?`project`:`worktree`,{title:r,prompt:i}=await e.request(`issue.prompt`,{repo:t.repo,id:t.issue.id,where:n}),a=[];if(t.placement!==`project`){let{taskId:n}=await e.request(`task.create`,{repo:t.repo,engine:t.engine,title:r,prompt:i});if(await e.request(`issue.update`,{repo:t.repo,id:t.issue.id,task:n}).catch(e=>a.push({kind:`link`,error:ao(e)})),t.placement===`worktree`)return{taskId:n,warnings:a};let o=await e.request(`task.openMain`,{repo:t.repo}),s=await e.request(`tab.openViewport`,{taskId:o.taskId,viewTaskId:n});return{taskId:o.taskId,tabId:s.tabId,warnings:a}}let{taskId:o}=await e.request(`task.openMain`,{repo:t.repo}),{tabId:s}=await e.request(`tab.new`,{taskId:o,kind:`engine`,engine:t.engine,prompt:i});return await e.request(`issue.setStatus`,{repo:t.repo,id:t.issue.id,status:`doing`}).catch(e=>a.push({kind:`status`,error:ao(e)})),{taskId:o,tabId:s,warnings:a}}var Io={choice:`radiogroup`,list:`listbox`,cells:`group`};function Lo(e){return(0,z.jsx)(`div`,{ref:e.fieldRef,role:Io[e.kind??`choice`],tabIndex:0,"aria-label":e.label,className:`kb-group ${e.className??``}`,onKeyDown:e.onKeyDown,onClick:e.onClick,children:e.children})}var Ro=[`open`,`doing`,`hold`,`done`];function zo({model:e,taskId:t}){let{kanban:n}=io(),[r,i]=(0,m.useState)(null);return(0,m.useEffect)(()=>{let n=!0;return e.client.request(`task.events`,{taskId:t}).then(e=>n&&i(e.events)).catch(()=>n&&i([])),()=>{n=!1}},[e,t]),(0,z.jsxs)(`div`,{className:`kb-section`,children:[(0,z.jsx)(`h2`,{className:`kicker`,children:n.detail.eventsLabel}),r===null?(0,z.jsx)(`p`,{className:`muted`,children:n.detail.eventsLoading}):r.length===0?(0,z.jsx)(`p`,{className:`muted`,children:n.detail.eventsNone}):r.map(e=>(0,z.jsxs)(`div`,{className:`kb-event mono`,children:[(0,z.jsx)(`span`,{className:`muted kb-age`,children:Za(e.at)}),(0,z.jsx)(`span`,{children:e.kind}),e.tail&&(0,z.jsxs)(`span`,{className:`muted`,children:[`· `,e.tail]})]},`${e.at}:${e.kind}:${e.tail}`))]})}function Bo(e){let{kanban:t}=io(),{issue:n,mode:r}=e,i=r===`create`,a=!i&&n.taskId?n.taskId:null,o=i||!a&&n.status!==`done`,[s,c]=(0,m.useState)(n.title),[l,u]=(0,m.useState)(n.body),[d,f]=(0,m.useState)(n.status),[p,h]=(0,m.useState)(e.defaultEngine),[g,_]=(0,m.useState)(Po[0]),[v,y]=(0,m.useState)(!1),[b,x]=(0,m.useState)(!1),S=(0,m.useRef)({}),C=e=>t=>{S.current[e]=t},w=i?`title`:o?`workspace`:a?`open`:`title`;(0,m.useEffect)(()=>S.current[w]?.focus(),[w]);let E=()=>({title:s.trim()||n.title,body:l,status:d}),D=()=>({engine:p,placement:g,jump:v}),O=t=>{R(),t&&e.onOutcome(t)},k=()=>s.trim()?!0:(S.current.title?.focus(),!1),ee=()=>{i?k()&&O({kind:`create`,title:s.trim(),body:l,start:D()}):o?O({kind:`start`,...D(),...E()}):a&&O({kind:`open`,taskId:a,...E()})},A=()=>{i&&k()&&O({kind:`create`,title:s.trim(),body:l,start:null})},j=()=>O(i?null:{kind:`close`,...E()}),M=(0,m.useRef)({commit:ee,saveOnly:A,close:j});M.current={commit:ee,saveOnly:A,close:j},(0,m.useEffect)(()=>{let e=e=>{let t=e.key===`Escape`?M.current.close:e.key===`Enter`&&(e.ctrlKey||e.metaKey)?M.current.commit:e.key.toLowerCase()===`s`&&e.ctrlKey&&!e.metaKey?M.current.saveOnly:null;t&&(e.preventDefault(),e.stopImmediatePropagation(),t())};return window.addEventListener(`keydown`,e,{capture:!0}),()=>window.removeEventListener(`keydown`,e,{capture:!0})},[]);let N=async t=>{let n=t.find(e=>e.size>Do);if(n){L(T(`pages.attachTooLarge`,{name:n.name||n.type}),`error`);return}x(!0);try{let n=await Promise.all(t.map(t=>No(e.model.client,t)));u(e=>Ao(e,n))}catch(e){L(B(e),`error`)}finally{x(!1)}},P=e=>{let t=jo(e.clipboardData.files);t.length!==0&&(e.preventDefault(),N(t))},F=e=>{let t=jo(e.dataTransfer.files);e.preventDefault(),t.length>0&&N(t)},I=(e,t,n)=>e[(Math.max(0,e.indexOf(t))+n+e.length)%e.length],te=(e,t,n)=>r=>{if(r.ctrlKey||r.metaKey||r.altKey)return;let i=(e===`x`?{ArrowRight:1,l:1,ArrowLeft:-1,h:-1}:{ArrowDown:1,ArrowUp:-1})[r.key];if(i)t(i);else if(r.key===`Enter`&&n)n();else return;r.preventDefault()},ne=d===`done`?`tone-success`:d===`hold`?`tone-warning`:d===`doing`?`tone-accent`:`muted`,re=e=>t.detail.status[e];return(0,z.jsx)(`div`,{className:`overlay`,onMouseDown:e=>e.target===e.currentTarget&&M.current.close(),children:(0,z.jsxs)(`dialog`,{open:!0,className:`dialog is-wide kb-drawer`,"aria-label":i?t.detail.newStory:`#${n.id}`,onPaste:P,onDrop:F,onDragOver:e=>e.preventDefault(),children:[i?(0,z.jsx)(`h1`,{className:`kicker`,children:t.detail.newStory}):(0,z.jsxs)(`h1`,{className:`kicker kb-drawer-head`,children:[(0,z.jsxs)(`span`,{children:[`#`,n.id]}),(0,z.jsx)(`span`,{className:ne,children:re(d)}),(0,z.jsx)(`span`,{className:`muted`,children:U(t.detail.created,{date:n.created})}),a&&(0,z.jsx)(`span`,{className:`tone-accent`,children:t.detail.linked})]}),(0,z.jsxs)(`div`,{className:`dialog-body`,children:[(0,z.jsxs)(`label`,{className:`field`,children:[(0,z.jsx)(`span`,{className:`kicker`,children:t.detail.titleLabel}),(0,z.jsx)(`input`,{ref:C(`title`),className:`input`,spellCheck:!1,value:s,onChange:e=>c(e.target.value.replace(/[\r\n]+/g,` `)),onKeyDown:e=>{e.key===`Enter`&&!e.ctrlKey&&!e.metaKey&&(e.preventDefault(),S.current.description?.focus())}})]}),(0,z.jsxs)(`label`,{className:`field`,children:[(0,z.jsxs)(`span`,{className:`kicker kb-label`,children:[t.detail.description,(0,z.jsx)(`span`,{className:`muted kb-hint`,children:t.detail.attachHint}),b&&(0,z.jsx)(`span`,{className:`tone-accent`,children:`…`})]}),(0,z.jsx)(`textarea`,{ref:C(`description`),className:`input textarea kb-body`,rows:8,spellCheck:!1,placeholder:t.detail.noDescription,value:l,onChange:e=>u(e.target.value)})]}),!i&&(0,z.jsxs)(`div`,{className:`field`,children:[(0,z.jsxs)(`span`,{className:`kicker kb-label`,children:[t.detail.statusLabel,(0,z.jsx)(`span`,{className:`muted kb-hint`,children:`←/→`})]}),(0,z.jsx)(Lo,{fieldRef:C(`status`),label:t.detail.statusLabel,className:`chips-row`,onKeyDown:te(`x`,e=>f(I(Ro,d,e))),children:Ro.map(e=>(0,z.jsx)(`button`,{type:`button`,tabIndex:-1,"aria-pressed":e===d,className:`chip-button ${e===d?`is-active`:``}`,onClick:()=>{f(e),S.current.status?.focus()},children:re(e)},e))})]}),o?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`div`,{className:`field`,children:[(0,z.jsxs)(`span`,{className:`kicker kb-label`,children:[t.detail.engine,(0,z.jsx)(`span`,{className:`muted kb-hint`,children:`←/→`})]}),(0,z.jsx)(Lo,{fieldRef:C(`engine`),label:t.detail.engine,className:`chips-row`,onKeyDown:te(`x`,t=>h(I(e.engines.map(e=>e.id),p,t)),ee),children:e.engines.map(e=>(0,z.jsx)(`button`,{type:`button`,tabIndex:-1,"aria-pressed":e.id===p,className:`chip-button ${e.id===p?`is-active`:``}`,onClick:()=>{h(e.id),S.current.engine?.focus()},children:e.name},e.id))})]}),(0,z.jsxs)(`div`,{className:`field`,children:[(0,z.jsxs)(`span`,{className:`kicker kb-label`,children:[t.detail.workspace,(0,z.jsx)(`span`,{className:`muted kb-hint`,children:`↑/↓`})]}),(0,z.jsx)(Lo,{fieldRef:C(`workspace`),label:t.detail.workspace,className:`kb-places`,onKeyDown:te(`y`,e=>_(I(Po,g,e)),ee),children:Po.map(e=>(0,z.jsxs)(`button`,{type:`button`,tabIndex:-1,"aria-pressed":e===g,className:`kb-place ${e===g?`is-active`:``}`,onClick:()=>{_(e),S.current.workspace?.focus()},children:[e===g?`▸ `:` `,t.detail.placement[e]]},e))})]}),(0,z.jsxs)(`div`,{className:`field`,children:[(0,z.jsxs)(`span`,{className:`kicker kb-label`,children:[t.detail.jumpLabel,(0,z.jsx)(`span`,{className:`muted kb-hint`,children:`←/→`})]}),(0,z.jsx)(Lo,{fieldRef:C(`jump`),label:t.detail.jumpLabel,className:`chips-row`,onKeyDown:te(`x`,()=>y(!v),ee),children:[!1,!0].map(e=>(0,z.jsx)(`button`,{type:`button`,tabIndex:-1,"aria-pressed":e===v,className:`chip-button ${e===v?`is-active`:``}`,onClick:()=>{y(e),S.current.jump?.focus()},children:e?t.detail.jump.follow:t.detail.jump.stay},String(e)))})]}),(0,z.jsx)(`p`,{className:`muted kb-legend`,children:i?t.detail.createLegend:t.detail.startLegend})]}):a?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`div`,{className:`field`,children:[(0,z.jsx)(`span`,{className:`kicker`,children:t.detail.sessionLabel}),(0,z.jsxs)(`div`,{className:`chips-row kb-group`,children:[(0,z.jsx)(`button`,{ref:C(`open`),type:`button`,className:`chip-button is-active`,onClick:()=>O({kind:`open`,taskId:a,...E()}),children:t.detail.openAction}),(0,z.jsx)(`button`,{ref:C(`unlink`),type:`button`,className:`chip-button`,onClick:()=>O({kind:`unlink`,...E()}),children:t.detail.unlinkAction})]})]}),(0,z.jsx)(zo,{model:e.model,taskId:a}),(0,z.jsx)(`p`,{className:`muted kb-legend`,children:t.detail.openLegend})]}):(0,z.jsx)(`p`,{className:`muted kb-legend`,children:t.detail.doneNote})]})]})})}var Vo={"waiting-on-you":`tone-attention`,landing:`tone-success`,"ready-for-review":`tone-ink`,working:`tone-accent`};function Ho(e){let[t,n]=(0,m.useState)([]);return(0,m.useEffect)(()=>{e.client.request(`engines.list`).then(e=>n(e.engines)).catch(()=>n([]))},[e]),{engines:t,defaultEngine:(t.find(e=>e.ready!==!1)??t[0])?.id??``}}function Uo(e,t){let n=W(e),r=n.join(`
|
|
14
14
|
`),[i,a]=(0,m.useState)(null);return(0,m.useEffect)(()=>{let t=!0,r=e.client,i=e=>r.request(e).then(e=>e.repos).catch(()=>[]);return Promise.all([i(`repos.list`),i(`issue.repos`)]).then(([e,t])=>co(e,n,t)).then(e=>Promise.all(e.map(e=>r.request(`issue.list`,{repo:e}).catch(t=>({repoRoot:e,nextId:1,issues:[],readError:ao(t)}))))).then(e=>{t&&a([...e].sort((e,t)=>e.repoRoot.localeCompare(t.repoRoot)))}),()=>{t=!1}},[e,t,r]),i}function Wo(e){let{issue:t}=e,n=t.body.trim();return(0,z.jsxs)(`div`,{"data-issue":t.id,className:`kb-card ${e.selected?`is-selected`:``} ${e.column===`done`?`is-done`:``} ${e.badge?.tone===`tone-attention`?`is-attention`:``}`,onClick:()=>e.selected?e.onOpen():e.onSelect(),onContextMenu:t=>{t.preventDefault(),e.onMenu(t.clientX,t.clientY)},children:[(0,z.jsxs)(`div`,{className:`kb-card-head`,children:[(0,z.jsx)(`span`,{className:`kb-card-title`,children:t.title}),(0,z.jsxs)(`span`,{className:`muted mono`,children:[`#`,t.id]})]}),(0,z.jsx)(`div`,{className:`kb-card-body muted`,children:n}),(0,z.jsxs)(`div`,{className:`kb-card-foot mono muted`,children:[(0,z.jsx)(`span`,{children:t.created}),e.badge&&(0,z.jsx)(`span`,{className:e.badge.tone,children:e.badge.label})]})]})}var Go=5e3,Ko=760;function qo({model:e}){let{kanban:t,group:n,common:r}=io(),[i,a]=uo(Go),o=Uo(e,i),{engines:s,defaultEngine:c}=Ho(e),l=v(e.tasks),u=lo(e),[d,f]=(0,m.useState)(null),[p,h]=(0,m.useState)(null),g=mo(),[_,y]=(0,m.useState)(!1);(0,m.useEffect)(()=>{let e=g.current;if(!e)return;let t=new ResizeObserver(()=>y(e.clientWidth<Ko));return t.observe(e),()=>t.disconnect()},[g]);let b=o??[],x=u?b.find(e=>e.repoRoot.replace(/^\/private\//,`/`)===u.replace(/^\/private\//,`/`)):void 0,S=Math.max(0,b.findIndex(e=>e.repoRoot===(d??x?.repoRoot))),C=b[S],w=b.map(e=>e.repoRoot),T=b.filter(e=>e.readError).map(e=>`${e.repoRoot}\0${e.readError}`).join(`
|
|
15
15
|
`);(0,m.useEffect)(()=>{for(let e of b)e.readError&&L(U(t.readFailedToast,{repo:so(e.repoRoot,w),error:e.readError}),`error`)},[T]);let E=l?.tasks??[],D=new Set(E.map(e=>e.id)),ee=e=>E.find(t=>t.id===e)?.group,{columns:A,attentionCount:j}=Co(C?To(C.issues,D.size===0?void 0:e=>D.has(e)):[],e=>ee(e)===`waiting-on-you`),N={backlog:t.column.backlog,in_progress:t.column.inProgress,parked:t.column.parked,done:t.column.done},P=(e,t)=>{let r=e.taskId&&(t===`in_progress`||t===`parked`)?ee(e.taskId):void 0,i=r===`waiting-on-you`?n.waitingOnYou:r===`landing`?n.landing:r===`ready-for-review`?n.readyForReview:r===`working`?n.working:null;return r&&i?{label:i,tone:Vo[r]??`muted`}:null},F=async(t,n,r,i)=>{try{return await e.client.request(t,{repo:C?.repoRoot,...n})}catch(e){return L(U(r,{id:String(i),error:ao(e)}),`error`),null}finally{a()}},I=(e,n)=>F(`issue.setStatus`,{id:e.id,status:n},t.statusFailed,e.id),te=t=>{M.set(null),e.select(t)},ne=async(n,r,i)=>{try{let a=await Fo(e.client,{repo:n,issue:r,engine:i.engine,placement:i.placement});for(let e of a.warnings)L(U(e.kind===`link`?t.linkFailed:t.statusFailed,{id:String(r.id),error:e.error}),`error`);i.jump?(M.set(null),e.selectWhenListed(a.taskId),a.tabId&&await e.refreshTabsNow().then(()=>e.select(a.taskId,a.tabId))):L(U(t.detail.startedBackground,{title:`#${r.id} ${r.title}`}))}catch(e){L(B(e),`error`)}finally{a()}},R=async(e,n)=>{if(!C||n.kind===`create`)return;let r={};n.title!==e.title&&(r.title=n.title),n.body!==e.body&&(r.body=n.body),(r.title!==void 0||r.body!==void 0)&&await F(`issue.update`,{id:e.id,...r},t.updateFailed,e.id),n.status!==e.status&&await I(e,n.status),n.kind===`open`?te(n.taskId):n.kind===`unlink`?await F(`issue.update`,{id:e.id,task:`none`},t.unlinkFailed,e.id):n.kind===`start`&&await ne(C.repoRoot,{...e,...r},n)},re=t=>{C&&(h(t.id),k.set((0,z.jsx)(Bo,{model:e,issue:t,mode:`detail`,engines:s,defaultEngine:c,onOutcome:e=>void R(t,e)})))},ie=()=>{if(!C)return;let n=C.repoRoot,r={id:C.nextId,title:``,status:`open`,created:new Date().toISOString().slice(0,10),body:``};k.set((0,z.jsx)(Bo,{model:e,issue:r,mode:`create`,engines:s,defaultEngine:c,onOutcome:i=>{i.kind===`create`&&(async()=>{try{let t=await e.client.request(`issue.create`,{repo:n,title:i.title,body:i.body});if(a(),!i.start)return;let o=t.issues.find(e=>e.id===r.id)??t.issues.reduce((e,t)=>e&&e.id>t.id?e:t,null);o&&await ne(n,o,i.start)}catch(e){L(U(t.createFailed,{error:ao(e)}),`error`)}})()}}))},ae=()=>{let n=C?.issues.find(e=>e.id===p);if(!C||!n)return;let i=C.repoRoot;k.set((0,z.jsx)(se,{title:U(t.confirmDelete.title,{id:String(n.id)}),body:U(t.confirmDelete.body,{title:n.title}),confirmLabel:r.confirm,onConfirm:async()=>{try{await e.client.request(`issue.delete`,{repo:i,id:n.id}),h(null)}catch(e){L(U(t.deleteFailed,{id:String(n.id),error:ao(e)}),`error`)}finally{a()}}}))},oe=e=>{b.length!==0&&(f(b[(S+e+b.length)%b.length]?.repoRoot??null),h(null))},ce=e=>{let t=xo(A,p,e);t!=null&&h(t)},le=e=>A.some(e=>e.issues.length>0)?ce(e):oe(e===`left`?-1:1);po(e=>{if(e.ctrlKey)return e.key===`c`&&(M.set(null),!0);switch(e.key){case`Escape`:case`q`:return M.set(null),!0;case`r`:return a(),!0;case`Tab`:return oe(e.shiftKey?-1:1),!0;case`ArrowUp`:return ce(`up`),!0;case`ArrowDown`:return ce(`down`),!0;case`ArrowRight`:case`l`:return le(`right`),!0;case`ArrowLeft`:case`h`:return le(`left`),!0;case`Enter`:{let e=C?.issues.find(e=>e.id===p);return e&&re(e),!0}case`n`:return ie(),!0;case`d`:return ae(),!0;default:return!1}});let ue=(0,m.useRef)(null);(0,m.useEffect)(()=>{ue.current?.querySelector(`[data-issue="${p}"]`)?.scrollIntoView({block:`nearest`})},[p]);let de=(e,n,r)=>{h(e.id),O.set({x:n,y:r,items:Ro.filter(t=>t!==e.status).map(n=>({label:U(t.menu.setStatus,{status:t.detail.status[n]}),run:()=>void I(e,n)}))})},fe=A.find(e=>e.issues.some(e=>e.id===p))??A.find(e=>e.issues.length>0)??A[0],pe=(e,n)=>(0,z.jsxs)(`section`,{className:`kb-lane kb-lane-${e.key}`,children:[n&&(0,z.jsxs)(`h2`,{className:`kb-lane-head`,children:[(0,z.jsxs)(`span`,{children:[N[e.key],` (`,e.issues.length+e.hiddenCount,`)`]}),e.key===`in_progress`&&j>0&&(0,z.jsx)(`span`,{className:`tone-warning`,children:U(t.attention,{count:String(j)})})]}),(0,z.jsxs)(`div`,{className:`kb-cards`,children:[e.issues.map(t=>(0,z.jsx)(Wo,{issue:t,column:e.key,selected:t.id===p,badge:P(t,e.key),onSelect:()=>h(t.id),onOpen:()=>re(t),onMenu:(e,n)=>de(t,e,n)},t.id)),e.issues.length===0&&e.hiddenCount===0&&(0,z.jsx)(`p`,{className:`muted mono`,children:t.columnEmpty}),e.hiddenCount>0&&(0,z.jsx)(`p`,{className:`muted mono`,children:U(t.more,{count:String(e.hiddenCount)})})]})]},e.key);return(0,z.jsxs)(`div`,{className:`page kb-page`,tabIndex:0,ref:g,children:[(0,z.jsxs)(`div`,{className:`kb-top`,children:[(0,z.jsx)(`h1`,{className:`page-title`,children:t.title}),(0,z.jsx)(`span`,{className:`muted mono kb-hint-line`,children:t.hint})]}),o===null?(0,z.jsx)(`p`,{className:`muted`,children:t.loading}):C?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`div`,{className:`kb-project`,children:[(0,z.jsxs)(`button`,{type:`button`,className:`kb-project-name`,onClick:()=>oe(1),children:[so(C.repoRoot,w),b.length>1&&(0,z.jsx)(`span`,{className:`muted`,children:` ${S+1}/${b.length}`})]}),!_&&(0,z.jsx)(`span`,{className:`muted mono kb-project-path`,children:C.repoRoot}),C.issues.length===0&&!C.readError&&(0,z.jsx)(`span`,{className:`muted kb-empty`,children:t.empty})]}),C.readError?(0,z.jsx)(`p`,{className:`error`,children:U(t.readFailed,{error:C.readError})}):_&&fe?(0,z.jsxs)(`div`,{className:`kb-single`,ref:ue,children:[(0,z.jsx)(`div`,{className:`kb-strip mono`,children:A.map(e=>(0,z.jsxs)(`button`,{type:`button`,className:e.key===fe.key?`is-active`:`muted`,onClick:()=>{let t=e.issues[0];t&&h(t.id)},children:[N[e.key],` (`,e.issues.length+e.hiddenCount,`)`]},e.key))}),pe(fe,!1)]}):(0,z.jsx)(`div`,{className:`kb-board`,ref:ue,children:A.map(e=>pe(e,!0))})]}):(0,z.jsx)(`p`,{className:`muted`,children:t.noRepos})]})}var Jo={title:`Mods`,empty:`No mod is drawing anything.`,emptyHint:`A plugin with a [mod] entry draws its panes here, in the TUI and the web alike.`,keys:`↑↓/tab move · enter press · esc back`,pressFailed:`{plugin}: the press did not reach the mod ({reason})`},Yo={title:`Mods`,empty:`当前没有 mod 在绘制内容。`,emptyHint:`声明了 [mod] 的插件会在这里绘制面板,TUI 和 web 显示的是同一份。`,keys:`↑↓/tab 移动 · enter 按下 · esc 返回`,pressFailed:`{plugin}:按键没有送达 mod({reason})`},Xo=[`info`,`success`,`warning`,`error`,`muted`],Zo=4e3,Qo=4e3,$o=/^[A-Za-z0-9._:-]{1,64}$/,es={box:new Set([`type`,`direction`,`gap`,`padding`,`border`,`children`]),text:new Set([`type`,`text`,`tone`,`bold`]),button:new Set([`type`,`key`,`label`,`tone`]),input:new Set([`type`,`key`,`placeholder`,`value`])};function ts(e){return typeof e==`string`&&Xo.includes(e)}function ns(e){return e===0||e===1||e===2||e===3}var rs=class extends Error{};function is(e){let t=0,n=new Set,r=(e,i,a)=>{if(a>12)throw new rs(`${i}: deeper than 12`);if(++t>400)throw new rs(`more than 400 elements`);if(!e||typeof e!=`object`||Array.isArray(e))throw new rs(`${i}: not an element`);let o=e,s=o.type;if(s!==`box`&&s!==`text`&&s!==`button`&&s!==`input`)throw new rs(`${i}: unknown element ${JSON.stringify(s)}`);for(let e of Object.keys(o))if(!es[s].has(e))throw new rs(`${i}: ${s} has no prop "${e}"`);if(o.tone!==void 0&&!ts(o.tone))throw new rs(`${i}: tone must be one of ${Xo.join(`, `)}`);if(s===`text`){if(typeof o.text!=`string`||o.text.length>4e3)throw new rs(`${i}: text must be a string of at most ${Zo} chars`);if(o.bold!==void 0&&typeof o.bold!=`boolean`)throw new rs(`${i}: bold must be boolean`);return{type:s,text:o.text,...o.tone===void 0?{}:{tone:o.tone},...o.bold?{bold:!0}:{}}}if(s===`button`||s===`input`){if(typeof o.key!=`string`||!$o.test(o.key))throw new rs(`${i}: bad ${s} key`);if(n.has(o.key))throw new rs(`${i}: duplicate key "${o.key}"`);n.add(o.key)}if(s===`input`){for(let e of[`placeholder`,`value`]){let t=o[e];if(t!==void 0&&(typeof t!=`string`||t.length>4e3))throw new rs(`${i}: ${e} must be a string of at most ${Qo} chars`)}return{type:s,key:o.key,...o.placeholder===void 0?{}:{placeholder:o.placeholder},...o.value===void 0?{}:{value:o.value}}}if(s===`button`){if(typeof o.label!=`string`||o.label.length===0||o.label.length>40)throw new rs(`${i}: label must be 1-40 chars`);return{type:s,key:o.key,label:o.label,...o.tone===void 0?{}:{tone:o.tone}}}if(o.direction!==void 0&&o.direction!==`row`&&o.direction!==`column`)throw new rs(`${i}: direction must be "row" or "column"`);for(let e of[`gap`,`padding`])if(o[e]!==void 0&&!ns(o[e]))throw new rs(`${i}: ${e} must be 0-3`);if(o.border!==void 0&&typeof o.border!=`boolean`)throw new rs(`${i}: border must be boolean`);if(!Array.isArray(o.children))throw new rs(`${i}: box needs children`);return{type:s,...o.direction===void 0?{}:{direction:o.direction},...o.gap===void 0?{}:{gap:o.gap},...o.padding===void 0?{}:{padding:o.padding},...o.border?{border:!0}:{},children:o.children.map((e,t)=>r(e,`${i}.children[${t}]`,a+1))}};try{return{ok:!0,tree:r(e,`tree`,1)}}catch(e){if(e instanceof rs)return{ok:!1,error:e.message};throw e}}function as(e){let t=e?.panes;if(!Array.isArray(t))return null;let n=[];for(let e of t){if(!e||typeof e!=`object`)continue;let t=e;if(typeof t.plugin!=`string`||typeof t.id!=`string`||typeof t.title!=`string`)continue;let r=is(t.tree);r.ok&&n.push({plugin:t.plugin,id:t.id,title:t.title,tree:r.tree})}return n}function os(e){let t=[],n=(e,r,i)=>{if(e.type===`button`||e.type===`input`)t.push({kind:e.type,plugin:r,pane:i,key:e.key});else if(e.type===`box`)for(let t of e.children)n(t,r,i)};for(let t of e)n(t.tree,t.plugin,t.id);return t}function ss(e,t){return e!==null&&t!==null&&e.plugin===t.plugin&&e.pane===t.pane&&e.key===t.key}function cs(e,t){return e.find(e=>ss(e,t))??e[0]??null}function ls(e,t,n){if(e.length===0)return null;let r=e.findIndex(e=>ss(e,t));return r<0?e[0]??null:e[(r+n+e.length)%e.length]??null}var us=[0,6,12,20];function ds(e){return`mod-${e.kind}:${e.plugin}/${e.pane}/${e.key}`}function fs(e){let[t,n]=(0,m.useState)(e.value??``);return(0,z.jsx)(`form`,{className:`mod-field`,onSubmit:r=>{r.preventDefault(),e.onSubmit(t),n(e.value??``)},children:(0,z.jsx)(`input`,{id:e.id,className:`input`,spellCheck:!1,value:t,placeholder:e.placeholder,onFocus:e.onFocus,onChange:e=>n(e.target.value)})})}function ps(e){let{node:t}=e;if(t.type===`text`){let e=`mod-text${t.tone?` tone-${t.tone}`:``}${t.bold?` is-bold`:``}`;return(0,z.jsx)(`span`,{className:e,children:t.text})}if(t.type===`input`){let n={kind:`input`,plugin:e.pane.plugin,pane:e.pane.id,key:t.key};return(0,z.jsx)(fs,{id:ds(n),placeholder:t.placeholder,value:t.value,onFocus:()=>e.onFocus(n),onSubmit:t=>e.onSubmit(n,t)},t.value??``)}if(t.type===`button`){let n={kind:`button`,plugin:e.pane.plugin,pane:e.pane.id,key:t.key};return(0,z.jsx)(`button`,{type:`button`,id:ds(n),className:`mod-button tone-${t.tone??`info`}${ss(n,e.cursor)?` is-cursor`:``}`,onFocus:()=>e.onFocus(n),onClick:()=>e.onPress(n),children:t.label})}return(0,z.jsx)(`div`,{className:`mod-box${t.direction===`row`?` is-row`:``}${t.border?` is-framed`:``}`,style:{flexDirection:t.direction??`column`,gap:us[t.gap??0],padding:us[t.padding??0]},children:t.children.map((t,n)=>(0,z.jsx)(ps,{...e,node:t},n))})}function ms({model:e}){let t=D()===`zh`?Yo:Jo,n=v(e.mods),r=os(n),[i,a]=(0,m.useState)(null),o=cs(r,i),s=mo(),c=(0,m.useRef)(!1),l=(t,n,r={})=>{a(t),!c.current&&(c.current=!0,e.client.request(n,{plugin:t.plugin,pane:t.pane,key:t.key,...r}).catch(e=>L(e instanceof Error?e.message:String(e),`error`)).finally(()=>{c.current=!1}))},u=e=>l(e,`mod.press`),d=(e,t)=>l(e,`mod.submit`,{value:t}),f=e=>{let t=ls(r,o,e);a(t),t&&document.getElementById(ds(t))?.focus()};return po(e=>{if(e.ctrlKey)return e.key===`c`&&(M.set(null),!0);switch(e.key){case`Escape`:case`q`:return M.set(null),!0;case`ArrowDown`:return f(1),!0;case`ArrowUp`:return f(-1),!0;case`Enter`:return e.target instanceof HTMLButtonElement?!1:(o?.kind===`button`&&u(o),!0);default:return!1}}),(0,z.jsxs)(`div`,{className:`page mods-page`,tabIndex:0,ref:s,children:[(0,z.jsxs)(`div`,{className:`pg-top`,children:[(0,z.jsx)(`h1`,{className:`page-title`,children:t.title}),(0,z.jsx)(`span`,{className:`pg-hint muted`,children:t.keys})]}),n.length===0?(0,z.jsxs)(`div`,{className:`mods-empty`,children:[(0,z.jsx)(`p`,{children:t.empty}),(0,z.jsx)(`p`,{className:`muted`,children:t.emptyHint})]}):n.map(e=>(0,z.jsxs)(`section`,{className:`mod-pane`,children:[(0,z.jsxs)(`header`,{className:`mod-pane-title`,children:[e.title,` `,(0,z.jsxs)(`span`,{className:`muted`,children:[`· `,e.plugin]})]}),(0,z.jsx)(ps,{node:e.tree,pane:e,cursor:o,onPress:u,onSubmit:d,onFocus:a})]},`${e.plugin}/${e.id}`))]})}function hs(e){return e===`dispatch_failed`||e===`skipped_unavailable`}function gs(e,t){return e.response?`responded`:e.status!==`dispatched`&&e.status!==`revived`?null:e.deliveryStatus===`missing`?`missing`:e.deliveryStatus===`awaiting`?`awaiting`:t-Date.parse(e.at)>72e5?`missing`:`awaiting`}var _s=6e4,vs=3294,ys=new Map([[`JAN`,1],[`FEB`,2],[`MAR`,3],[`APR`,4],[`MAY`,5],[`JUN`,6],[`JUL`,7],[`AUG`,8],[`SEP`,9],[`OCT`,10],[`NOV`,11],[`DEC`,12]]),bs=new Map([[`SUN`,0],[`MON`,1],[`TUE`,2],[`WED`,3],[`THU`,4],[`FRI`,5],[`SAT`,6]]),xs=256;function Ss(e,t,n){let r=e.toUpperCase(),i=t?.get(r);if(i!==void 0)return i;if(!/^\d+$/.test(r))throw Error(`invalid cron ${n}: ${e}`);return Number(r)}function Cs(e){let t=new Set;for(let n of e.value.split(`,`)){if(n.length===0)throw Error(`invalid cron ${e.field}: ${e.value}`);let[r,i,...a]=n.split(`/`);if(a.length>0||r===void 0)throw Error(`invalid cron ${e.field}: ${n}`);let o=1;if(i!==void 0&&(!/^\d+$/.test(i)||(o=Number(i),o<1)))throw Error(`invalid cron ${e.field} step: ${n}`);let s,c;if(r===`*`)s=e.min,c=e.max;else if(r.includes(`-`)){let[t,i,...a]=r.split(`-`);if(a.length>0||t===void 0||i===void 0)throw Error(`invalid cron ${e.field} range: ${n}`);s=Ss(t,e.names,e.field),c=Ss(i,e.names,e.field)}else s=Ss(r,e.names,e.field),c=i===void 0?s:e.max;if(s<e.min||c>e.max||s>c)throw Error(`cron ${e.field} out of range: ${n}`);for(let n=s;n<=c;n+=o)t.add(e.normalize?e.normalize(n):n)}return t}function ws(e){if(e.length>xs)throw Error(`cron expression is too long`);let t=e.trim().split(/\s+/).filter(Boolean);if(t.length!==5)throw Error(`cron expression needs 5 fields (minute hour day month weekday), got ${t.length}`);let[n,r,i,a,o]=t;return{minutes:Cs({value:n,min:0,max:59,field:`minute`}),hours:Cs({value:r,min:0,max:23,field:`hour`}),daysOfMonth:Cs({value:i,min:1,max:31,field:`day-of-month`}),months:Cs({value:a,min:1,max:12,field:`month`,names:ys}),daysOfWeek:Cs({value:o,min:0,max:7,field:`weekday`,names:bs,normalize:e=>e%7}),dayOfMonthRestricted:!i.startsWith(`*`),dayOfWeekRestricted:!o.startsWith(`*`)}}function Ts(e){try{return ws(e),!0}catch{return!1}}function Es(e,t,n){return new Date(e.year,e.month-1,e.day,t,n,0,0).getTime()}function Ds(e){let t=new Date(e);return{year:t.getFullYear(),month:t.getMonth()+1,day:t.getDate()}}function Os(e,t){return Ds(new Date(e.year,e.month-1,e.day+t,12,0,0,0).getTime())}function ks(e,t){if(!e.months.has(t.month))return!1;let n=e.daysOfMonth.has(t.day),r=e.daysOfWeek.has(new Date(t.year,t.month-1,t.day).getDay());return e.dayOfMonthRestricted&&e.dayOfWeekRestricted?n||r:n&&r}function As(e){return e-e%_s}function js(e,t){return[...e].sort((e,n)=>(e-n)*t)}function Ms(e,t){let n=ws(e),r=js(n.hours,1),i=js(n.minutes,1),a=new Date(As(t)+_s),o=Ds(a.getTime()),s=a.getHours(),c=a.getMinutes();for(let e=0;e<vs;e++){if(ks(n,o)){for(let e of r)if(!(e<s))for(let n of i){if(e===s&&n<c)continue;let r=Es(o,e,n);if(r>t)return r}}o=Os(o,1),s=0,c=0}throw Error(`cron expression never matches: ${e}`)}var Ns=[`minute`,`hour`,`dayOfMonth`,`month`,`dayOfWeek`];function Ps(e){let t=e.trim().split(/\s+/).filter(Boolean);return Ns.map((e,n)=>t[n]??`*`)}function Fs(e){return Ns.map((t,n)=>e[n]??`*`).join(` `)}var Is=[`*`,`*/5`,`*/10`,`*/15`,`*/30`,...Hs(0,59)],Ls=[`*`,`*/2`,`*/3`,`*/4`,`*/6`,`*/12`,...Hs(0,23)],Rs=[`*`,...Hs(1,31)],zs=[`*`,`JAN`,`FEB`,`MAR`,`APR`,`MAY`,`JUN`,`JUL`,`AUG`,`SEP`,`OCT`,`NOV`,`DEC`],Bs=[`*`,`MON-FRI`,`SAT,SUN`,`MON`,`TUE`,`WED`,`THU`,`FRI`,`SAT`,`SUN`],Vs=[`MON`,`TUE`,`WED`,`THU`,`FRI`,`SAT`,`SUN`];function Hs(e,t){let n=[];for(let r=e;r<=t;r++)n.push(String(r));return n}var Us={minute:Is,hour:Ls,dayOfMonth:Rs,month:zs,dayOfWeek:Bs};function Ws(e,t,n){let r=Us[e],i=r.indexOf(t.trim().toUpperCase());return i<0?(n>0?r[0]:r[r.length-1])??t:r[(i+n+r.length)%r.length]??t}function Gs(e,t){return Math.min(Math.max(e+t,0),Ns.length-1)}function Ks(e,t,n){let r=Ps(e);return t<0||t>=Ns.length||(r[t]=n),Fs(r)}function qs(e,t){let[n,r,i,a,o]=Ps(e);if(a!==`*`||i!==`*`||n===void 0||r===void 0||o===void 0)return null;let s=Js(n,r,t);if(!s)return null;let{at:c,bare:l}=s;if(o===`*`)return l?c:t(`automations.schedule.everyDay`,{at:c});if(o===`MON-FRI`)return t(`automations.schedule.weekdays`,{at:c});if(o===`SAT,SUN`)return t(`automations.schedule.weekends`,{at:c});let u=Vs.find(e=>e===o.toUpperCase());return u?t(`automations.schedule.onWeekday`,{weekday:t(`automations.schedule.dow.${u}`),at:c}):null}function Js(e,t,n){return t===`*`?e===`*`?{at:n(`automations.schedule.everyMinute`),bare:!0}:e.startsWith(`*/`)?{at:n(`automations.schedule.everyMinutes`,{n:e.slice(2)}),bare:!0}:/^\d+$/.test(e)?{at:n(`automations.schedule.hourlyAt`,{minute:e.padStart(2,`0`)}),bare:!1}:null:t.startsWith(`*/`)&&e===`0`?{at:n(`automations.schedule.everyHours`,{n:t.slice(2)}),bare:!0}:/^\d+$/.test(t)&&/^\d+$/.test(e)?{at:n(`automations.schedule.atClock`,{time:`${t.padStart(2,`0`)}:${e.padStart(2,`0`)}`}),bare:!1}:null}function Ys(e,t,n,r){let i=e.trim();if(!Ts(i))return{kind:`invalid`};let a;try{a=Ms(i,t)}catch{return{kind:`never`}}return{kind:`ok`,nextRunMs:a,relative:Xs(a-t,n),absolute:Zs(a,t,n,r)}}function Xs(e,t){let{minutes:n,hours:r,days:i}=Xa(e);return n<60?t(`automations.when.inMinutes`,{n:Math.max(1,n)}):r<24?t(`automations.when.inHours`,{n:r}):t(`automations.when.inDays`,{n:i})}function Zs(e,t,n,r){let i=new Date(e),a=`${String(i.getHours()).padStart(2,`0`)}:${String(i.getMinutes()).padStart(2,`0`)}`,o=new Date(t);if(i.getFullYear()===o.getFullYear()&&i.getMonth()===o.getMonth()&&i.getDate()===o.getDate())return a;let s=e-t<5184e5,c=i.toLocaleDateString(r,s?{weekday:`short`}:{weekday:`short`,month:`short`,day:`numeric`});return s?`${c} ${a}`:n(`automations.when.dateTime`,{date:c,time:a})}var Qs={name:``,repo:``,prompt:``,schedule:`0 9 * * MON-FRI`};function $s(e){return e.name.trim().length>0&&e.repo.trim().length>0&&e.prompt.trim().length>0&&(!e.target||e.target.taskId.trim().length>0&&/^tab-[\w-]+$/.test(e.target.tabId))&&Ts(e.schedule.trim())}function ec(e){return e.name.trim().length===0?`name`:e.repo.trim().length===0?`repo`:e.target&&!e.target.taskId.trim()?`target`:e.target&&!/^tab-[\w-]+$/.test(e.target.tabId)?`targetTab`:e.prompt.trim().length===0?`prompt`:Ts(e.schedule.trim())?null:`schedule`}function tc(){let{auto:e}=io();return(t,n)=>{let r=e;for(let e of t.replace(/^automations\./,``).split(`.`))r=r&&typeof r==`object`?Reflect.get(r,e):void 0;return typeof r==`string`?n?U(r,n):r:t}}function nc(e){let{auto:t,common:n}=io(),r=tc(),i=D()===`zh`?`zh-CN`:`en-US`,[a,o]=(0,m.useState)(()=>({...Qs,repo:e.repos.find(t=>e.defaultRepo&&oo(t)===oo(e.defaultRepo))??e.repos[0]??``})),[s,c]=(0,m.useState)(0),[l,u]=(0,m.useState)(null),d=(0,m.useRef)({}),f=e=>t=>{d.current[e]=t};(0,m.useEffect)(()=>d.current.name?.focus(),[]);let p=e=>{o(t=>({...t,...e})),u(null)};(0,m.useEffect)(()=>{let e=e=>{e.key===`Escape`&&(e.preventDefault(),e.stopImmediatePropagation(),R())};return window.addEventListener(`keydown`,e,{capture:!0}),()=>window.removeEventListener(`keydown`,e,{capture:!0})},[]);let h=()=>{if($s(a)){R(),e.onSubmit({name:a.name.trim(),repo:a.repo.trim(),prompt:a.prompt.trim(),schedule:a.schedule.trim(),...a.target?{target:a.target}:{}});return}let n=ec(a);n&&(d.current[n]?.focus(),u(Reflect.get(t.missing,n)))},g=e.tasks.filter(e=>oo(e.repo)===oo(a.repo)),_=a.target?g.findIndex(e=>e.id===a.target?.taskId)+1:0,v=e=>{let t=(_+e+g.length+1)%(g.length+1),n=g[t-1];p({target:n?{kind:`existing-tab`,taskId:n.id,tabId:`tab-1`}:void 0})},y=t=>{let n=Math.min(Math.max(e.repos.indexOf(a.repo)+t,0),e.repos.length-1),r=e.repos[n];r&&p({repo:r,target:void 0})},b=e=>t=>{(t.key===`ArrowUp`||t.key===`ArrowDown`)&&(t.preventDefault(),e(t.key===`ArrowDown`?1:-1))},x=e=>t=>{t.key===`Enter`&&(t.preventDefault(),d.current[e]?.focus())},S=Ps(a.schedule),C=e=>{if(e.ctrlKey||e.metaKey||e.altKey)return;let t=Ns[s];if(e.key===`ArrowLeft`||e.key===`h`)c(Gs(s,-1));else if(e.key===`ArrowRight`||e.key===`l`)c(Gs(s,1));else if((e.key===`ArrowUp`||e.key===`ArrowDown`)&&t){let n=e.key===`ArrowUp`?1:-1;p({schedule:Ks(a.schedule,s,Ws(t,S[s]??`*`,n))})}else return;e.preventDefault()},w=Ys(a.schedule,Date.now(),r,i),T=qs(a.schedule,r);return(0,z.jsx)(`div`,{className:`overlay`,onMouseDown:e=>e.target===e.currentTarget&&R(),children:(0,z.jsxs)(`dialog`,{open:!0,className:`dialog is-wide kb-drawer`,"aria-label":t.newTitle,children:[(0,z.jsx)(`h1`,{className:`kicker`,children:t.newTitle}),(0,z.jsxs)(`div`,{className:`dialog-body`,children:[(0,z.jsxs)(`label`,{className:`field`,children:[(0,z.jsx)(`span`,{className:`kicker`,children:t.fieldName}),(0,z.jsx)(`input`,{ref:f(`name`),className:`input`,spellCheck:!1,placeholder:t.namePlaceholder,value:a.name,onChange:e=>p({name:e.target.value}),onKeyDown:x(`repo`)})]}),(0,z.jsxs)(`div`,{className:`field`,children:[(0,z.jsxs)(`span`,{className:`kicker kb-label`,children:[t.fieldRepo,e.repos.length>0&&(0,z.jsx)(`span`,{className:`muted kb-hint`,children:`↑/↓`})]}),e.repos.length===0?(0,z.jsx)(`p`,{className:`muted`,children:t.needRepo}):(0,z.jsx)(Lo,{fieldRef:f(`repo`),kind:`list`,label:t.fieldRepo,className:`kb-places`,onKeyDown:b(y),children:e.repos.map(t=>(0,z.jsxs)(`button`,{type:`button`,tabIndex:-1,"aria-selected":t===a.repo,className:`kb-place ${t===a.repo?`is-active`:``}`,onClick:()=>{p({repo:t,target:void 0}),d.current.repo?.focus()},children:[t===a.repo?`▸ `:` `,so(t,e.repos)]},t))})]}),(0,z.jsxs)(`div`,{className:`field`,children:[(0,z.jsxs)(`span`,{className:`kicker kb-label`,children:[t.fieldTarget,(0,z.jsx)(`span`,{className:`muted kb-hint`,children:`↑/↓`})]}),(0,z.jsx)(Lo,{fieldRef:f(`target`),kind:`list`,label:t.fieldTarget,onKeyDown:b(v),onClick:()=>v(1),children:a.target?g[_-1]?.title??a.target.taskId:t.targetFresh})]}),a.target&&(0,z.jsxs)(`label`,{className:`field`,children:[(0,z.jsx)(`span`,{className:`kicker`,children:t.fieldTargetTab}),(0,z.jsx)(`input`,{ref:f(`targetTab`),className:`input`,spellCheck:!1,value:a.target.tabId,onChange:e=>a.target&&p({target:{...a.target,tabId:e.target.value}}),onKeyDown:x(`prompt`)})]}),(0,z.jsxs)(`label`,{className:`field`,children:[(0,z.jsx)(`span`,{className:`kicker`,children:t.fieldPrompt}),(0,z.jsx)(`input`,{ref:f(`prompt`),className:`input`,spellCheck:!1,placeholder:t.promptPlaceholder,value:a.prompt,onChange:e=>p({prompt:e.target.value}),onKeyDown:x(`schedule`)})]}),(0,z.jsxs)(`div`,{className:`field`,children:[(0,z.jsxs)(`span`,{className:`kicker kb-label`,children:[t.fieldSchedule,(0,z.jsx)(`span`,{className:`muted kb-hint`,children:`←/→ ↑/↓`})]}),(0,z.jsx)(Lo,{fieldRef:f(`schedule`),kind:`cells`,label:t.fieldSchedule,className:`pg-cron`,onKeyDown:C,children:Ns.map((e,n)=>(0,z.jsxs)(`button`,{type:`button`,tabIndex:-1,className:n===s?`is-active`:``,onClick:()=>{c(n),d.current.schedule?.focus()},children:[S[n]??`*`,(0,z.jsx)(`span`,{children:t.cronField[e]})]},e))}),w.kind===`ok`?(0,z.jsxs)(`p`,{className:`tone-success mono`,children:[T?`${T} · `:``,w.relative,` · `,w.absolute]}):(0,z.jsx)(`p`,{className:`error mono`,children:w.kind===`never`?t.cronNever:t.cronInvalid})]}),l&&(0,z.jsxs)(`p`,{className:`error`,children:[`※ `,l]}),(0,z.jsx)(`p`,{className:`muted kb-legend`,children:t.composerLegend}),(0,z.jsxs)(`div`,{className:`actions`,children:[(0,z.jsx)(`button`,{type:`button`,className:`link`,onClick:R,children:n.cancel}),(0,z.jsx)(`button`,{ref:f(`confirm`),type:`button`,className:`button`,onClick:h,children:n.create})]})]})]})})}var rc=5e3,ic=5,ac={dispatched:`success`,revived:`success`,skipped_precheck:`muted`,skipped_cancelled:`muted`,skipped_missed:`warning`,skipped_unavailable:`warning`,dispatch_failed:`error`},oc={success:`tone-success`,muted:`muted`,warning:`tone-warning`,error:`tone-attention`},sc={success:`✓`,error:`†`,warning:`!`,muted:`·`},cc=e=>ac[e]??`muted`;function lc({model:e}){let{auto:t,common:n}=io(),r=e.client,[i,a]=uo(rc),o=v(e.tasks),s=W(e),c=lo(e),[l,u]=(0,m.useState)(null),[d,f]=(0,m.useState)([]),[p,h]=(0,m.useState)(0),[g,_]=(0,m.useState)(null),[y,b]=(0,m.useState)(null),x=mo();(0,m.useEffect)(()=>{let e=!0;return r.request(`routine.list`).then(t=>e&&u(t)).catch(()=>e&&u(e=>e??{automations:[],keepsDaemonAlive:!1})),()=>{e=!1}},[r,i]);let S=v(N);(0,m.useEffect)(()=>{if(S===null||!l)return;let e=l.automations.findIndex(e=>e.id===S);e>=0&&h(e),N.set(null)},[S,l]);let C=l?.automations??[],w=l?.lastRunStatus??{},T=Math.min(p,Math.max(0,C.length-1)),E=C[T],D=C.filter(e=>{let t=w[e.id];return t!==void 0&&hs(t)}).length;(0,m.useEffect)(()=>{let e=!0;if(!E){f([]);return}return r.request(`routine.runs`,{id:E.id}).then(t=>e&&f(t.runs)).catch(()=>e&&f([])),()=>{e=!1}},[r,E?.id,i]),(0,m.useEffect)(()=>b(null),[E?.id]);let O=(0,m.useRef)(null);(0,m.useEffect)(()=>{O.current?.querySelector(`[data-row="${T}"]`)?.scrollIntoView({block:`nearest`})},[T]);let ee=Date.now(),A=e=>{let n=e?Date.parse(e):NaN;if(!Number.isFinite(n))return`—`;let r=n-ee,i=r>=0,a=Math.floor(Math.abs(r)/6e4),o=Math.floor(a/60);return a<1?i?t.when.now:t.when.justNow:a<60?U(i?t.when.inMinutes:t.when.minutesAgo,{n:a}):o<24?U(i?t.when.inHours:t.when.hoursAgo,{n:o}):new Date(n).toLocaleDateString()},j=e=>t.runStatus[e]??e,P=e=>o?.tasks.find(t=>t.id===e)?.title??e,F=(e,t,n)=>L(U(e,{name:t,error:ao(n)}),`error`),I=async()=>{if(!(!E||g)){_(E.id);try{await r.request(`routine.setEnabled`,{id:E.id,enabled:!E.enabled}),a()}catch(e){F(E.enabled?t.disableFailed:t.enableFailed,E.name,e)}finally{_(null)}}},te=async()=>{if(!(!E||g)){_(E.id),b(U(t.running,{name:E.name}));try{let e=await r.request(`routine.runNow`,{id:E.id});b(U(t.ranWith,{name:E.name,status:e.status})),a()}catch(e){F(t.runFailed,E.name,e)}finally{_(null)}}},ne=async()=>{if(g)return;let e=co(await r.request(`repos.list`).then(e=>e.repos).catch(()=>[]),s);if(e.length===0){b(t.needRepo);return}k.set((0,z.jsx)(nc,{repos:e,tasks:(o?.tasks??[]).filter(e=>!e.deleting).map(e=>({id:e.id,title:e.title,repo:e.repo})),defaultRepo:c,onSubmit:e=>{(async()=>{_(`new`);try{await r.request(`routine.create`,{repo:e.repo,name:e.name,prompt:e.prompt,schedule:e.schedule,...e.target?{targetTask:e.target.taskId,targetTab:e.target.tabId}:{}}),a()}catch(e){L(U(t.createFailed,{error:ao(e)}),`error`)}finally{_(null)}})()}}))},R=()=>{if(!E||g)return;let e=E;k.set((0,z.jsx)(se,{title:t.deleteTitle,body:U(t.deleteBody,{name:e.name}),confirmLabel:t.deleteButton,onConfirm:async()=>{_(e.id);try{await r.request(`routine.delete`,{id:e.id}),a()}catch(n){F(t.deleteFailed,e.name,n)}finally{_(null)}}}))};po(n=>{if(n.ctrlKey)return n.key===`c`&&(M.set(null),!0);switch(n.key){case`Escape`:case`q`:return M.set(null),!0;case`j`:case`ArrowDown`:return h(Math.min(C.length-1,T+1)),!0;case`k`:case`ArrowUp`:return h(Math.max(0,T-1)),!0;case`n`:return ne(),!0;case`r`:return a(),!0;case`e`:return I(),!0;case`s`:return te(),!0;case`d`:return R(),!0;case`Enter`:{let n=d[0]?.taskId;return n?(M.set(null),e.select(n)):d.length>0&&b(t.latestRunNoTask),!0}default:return!1}});let re=E?.target;return(0,z.jsxs)(`div`,{className:`page`,tabIndex:0,ref:x,children:[(0,z.jsxs)(`div`,{className:`pg-top`,children:[(0,z.jsx)(`h1`,{className:`page-title`,children:t.title}),(0,z.jsxs)(`span`,{className:`pg-actions mono`,children:[D>0&&(0,z.jsx)(`span`,{className:`tone-attention`,children:U(t.needAttention,{count:String(D),total:String(C.length)})}),(0,z.jsx)(`span`,{className:l?.keepsDaemonAlive?`tone-success`:`muted`,children:l?.keepsDaemonAlive?t.holdingDaemon:t.notHolding})]})]}),l===null?(0,z.jsx)(`p`,{className:`muted`,children:n.loading}):C.length===0?(0,z.jsxs)(`div`,{className:`pg-list`,children:[(0,z.jsx)(`p`,{className:`muted`,children:t.empty}),(0,z.jsx)(`p`,{children:t.emptyHint})]}):(0,z.jsx)(`div`,{className:`pg-list`,ref:O,children:C.map((e,n)=>{let r=w[e.id],i=r?cc(r):null;return(0,z.jsxs)(`div`,{"data-row":n,className:`pg-row ${n===T?`is-cursor`:``} ${e.enabled?``:`is-off`}`,onClick:()=>h(n),children:[(0,z.jsx)(`span`,{className:`pg-name`,children:e.name}),(0,z.jsx)(`span`,{className:`pg-grow muted mono`,children:`${so(e.repo,C.map(e=>e.repo))} · ${e.schedule}`}),!e.enabled&&(0,z.jsxs)(`span`,{className:`tone-warning mono`,children:[t.paused,` ·`]}),(0,z.jsx)(`span`,{className:`muted mono`,children:A(e.nextRunAt)}),(0,z.jsx)(`span`,{className:`mono ${i?oc[i]:`muted`}`,style:{width:`1ch`},children:i?sc[i]:` `})]},e.id)})}),(0,z.jsx)(`div`,{className:`pg-detail`,children:E?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`div`,{children:[(0,z.jsxs)(`div`,{className:`pg-actions`,children:[(0,z.jsx)(`span`,{className:`pg-prompt pg-grow`,children:E.prompt}),(0,z.jsx)(`button`,{type:`button`,className:`link`,disabled:g===E.id,onClick:()=>void te(),children:t.runNow})]}),(0,z.jsx)(`p`,{className:`muted`,children:re?U(t.targetExisting,{task:P(re.taskId),tab:re.tabId}):E.persistentSession?t.targetStanding:t.targetFresh}),E.precheck&&(0,z.jsx)(`p`,{className:`muted mono`,children:U(t.precheck,{command:E.precheck.command})}),(0,z.jsx)(`h2`,{className:`kicker`,children:t.recentRuns}),d.length===0?(0,z.jsx)(`p`,{className:`muted`,children:t.noRuns}):d.slice(0,ic).map(e=>{let n=gs(e,ee),r=n===`awaiting`?` · ${t.responseAwaiting}`:n===`missing`?` · ${t.responseMissing}`:``;return(0,z.jsx)(`p`,{className:`pg-run mono ${n===`missing`?`tone-warning`:oc[cc(e.status)]}`,children:`${e.trigger===`manual`?`▸`:`·`} #${e.runNumber} ${j(e.status)}${e.tabId?` · ${e.tabId}`:``}${e.error?` — ${e.error}`:``}${r} ${A(e.at)}`},e.id)}),d[0]?.precheckResult&&(0,z.jsx)(uc,{run:d[0]})]}),(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`h2`,{className:`kicker`,children:t.responses}),d.filter(e=>e.response).length===0?(0,z.jsx)(`p`,{className:`muted`,children:t.noResponses}):d.filter(e=>e.response).map(e=>(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`p`,{className:`pg-run mono ${oc[cc(e.status)]}`,children:`#${e.runNumber} ${j(e.status)} · ${A(e.response?.at)}`}),(0,z.jsx)(`p`,{className:`pg-response`,children:e.response?.text})]},e.id))]})]}):(0,z.jsx)(`p`,{className:`muted`,children:t.noSelection})}),y&&(0,z.jsx)(`p`,{className:`muted pg-notice`,children:y})]})}function uc({run:e}){let{auto:t}=io(),n=e.precheckResult;if(!n)return null;let r=n.timedOut?t.precheckTimedOut:U(t.precheckExited,{code:String(n.exitCode??`?`)}),i=[{label:t.precheckStdout,text:n.stdout},{label:t.precheckStderr,text:n.stderr}].filter(e=>e.text.trim().length>0);return(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`h2`,{className:`kicker`,children:U(t.precheckDetail,{exit:r,duration:String(n.durationMs)})}),i.length===0?(0,z.jsx)(`p`,{className:`muted`,children:t.precheckNoOutput}):i.map(e=>(0,z.jsx)(`p`,{className:`pg-response mono`,children:`${e.label}: ${e.text.replace(/\s+$/,``).split(`
|
|
16
16
|
`).slice(-10).join(`
|
package/dist/web/index.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
6
|
<meta name="referrer" content="no-referrer" />
|
|
7
7
|
<title>rove</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-BydepNFM.js"></script>
|
|
9
9
|
<link rel="stylesheet" crossorigin href="/assets/index-BZjPWX0N.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|