@timqi/pier 0.3.0 → 0.3.1
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/agent/roles.js +1 -1
- package/dist/core/chain.js +5 -2
- package/dist/tasks/agent.js +1 -1
- package/dist/tasks/callbacks.js +1 -1
- package/dist/web/public/assets/{explorer-C4DhXFCm.js → explorer-BoU77faI.js} +1 -1
- package/dist/web/public/assets/{explorer-C4DhXFCm.js.br → explorer-BoU77faI.js.br} +0 -0
- package/dist/web/public/assets/explorer-BoU77faI.js.gz +0 -0
- package/dist/web/public/assets/{index-D0ZYdweB.js → index-DqLJpDE0.js} +3 -3
- package/dist/web/public/assets/index-DqLJpDE0.js.br +0 -0
- package/dist/web/public/assets/index-DqLJpDE0.js.gz +0 -0
- package/dist/web/public/assets/{settings-DSTeuIyc.js → settings-BprIId_R.js} +1 -1
- package/dist/web/public/assets/settings-BprIId_R.js.br +0 -0
- package/dist/web/public/assets/settings-BprIId_R.js.gz +0 -0
- package/dist/web/public/index.html +1 -1
- package/dist/web/public/index.html.br +0 -0
- package/dist/web/public/index.html.gz +0 -0
- package/package.json +1 -1
- package/skills/pier-tasks/SKILL.md +7 -3
- package/dist/web/public/assets/explorer-C4DhXFCm.js.gz +0 -0
- package/dist/web/public/assets/index-D0ZYdweB.js.br +0 -0
- package/dist/web/public/assets/index-D0ZYdweB.js.gz +0 -0
- package/dist/web/public/assets/settings-DSTeuIyc.js.br +0 -0
- package/dist/web/public/assets/settings-DSTeuIyc.js.gz +0 -0
package/dist/agent/roles.js
CHANGED
|
@@ -45,7 +45,7 @@ You own one feature, in this worktree. The design doc you keep here is the state
|
|
|
45
45
|
- Decompose it into worker runs: \`pier task run --name "<a few words>" --prompt … --cwd <worker worktree>\`, one \`wt\` worktree each (\`wt switch -c <branch> --no-cd -y --format json\` in the repo). The prompt is the worker's whole handoff; a worker never delegates.
|
|
46
46
|
- Workers run on \`--model balanced\` for code, \`--model cheap\` for research and mechanical work.
|
|
47
47
|
- Never launch another lead (\`--role lead\` is refused).
|
|
48
|
-
- Each worker's result comes back to you: review it and integrate its branch here. While other results are still owed you, your replies reach only this session; your reply to the last one is the milestone your supervisor reads
|
|
48
|
+
- Each worker's result comes back to you: review it and integrate its branch here. While other results are still owed you, your replies reach only this session; your reply to the last one is the milestone your supervisor reads, in the run result's two parts: the conclusion (done, next, risks one line each), then \`Needs your decision\` only when something does. A worker takes reversible choices itself and names them in its result; it stops only on a destructive step or a question only you or the user can answer — answer with \`--run <id> --prompt\`, or carry it up.
|
|
49
49
|
- The build is yours to declare done, never the user's to confirm: a reply that leaves nothing owed you, workers or none, is that milestone.
|
|
50
50
|
- \`pier task runs\` lists the runs you launched, for orientation, never for waiting.`;
|
|
51
51
|
/** The surface contract handed to every agent Pier launches (main.ts); the
|
package/dist/core/chain.js
CHANGED
|
@@ -51,6 +51,8 @@ function lastExchanges(turns, n) {
|
|
|
51
51
|
.map((t) => `${t.role}: ${t.text}`).join("\n\n");
|
|
52
52
|
}
|
|
53
53
|
const ledgerLine = (r) => `${r.runId} · ${r.name} · ${r.state} · session ${r.targetSessionId ?? "—"} · ${r.cwd ?? "—"}`;
|
|
54
|
+
/** The seed lists what still needs the head: a run that ended well is `pier task runs`' to show. */
|
|
55
|
+
const SEED_RUNS_HIDDEN = new Set(["succeeded", "skipped"]);
|
|
54
56
|
/** `/skills`' answer on every surface, the head's and a thread's (channels/). */
|
|
55
57
|
export const skillsText = (skills) => skills.map((s) => `${s.name} — ${s.description}`).join("\n") || "no skills";
|
|
56
58
|
/** Only the exact word is a command: the composer is not a shell. */
|
|
@@ -196,13 +198,14 @@ export class MainChain {
|
|
|
196
198
|
async seed(reason, previous, open) {
|
|
197
199
|
const today = new Date(this.now());
|
|
198
200
|
const days = [new Date(today.getTime() - 86_400_000), today].map(day);
|
|
199
|
-
const runs = this.deps.ledger(this.members().map((m) => m.sessionId), previous?.startedAt ?? this.now())
|
|
201
|
+
const runs = this.deps.ledger(this.members().map((m) => m.sessionId), previous?.startedAt ?? this.now())
|
|
202
|
+
.filter((r) => !SEED_RUNS_HIDDEN.has(r.state));
|
|
200
203
|
const section = (title, text) => (text ? `## ${title}\n\n${text}` : "");
|
|
201
204
|
return [
|
|
202
205
|
`[Pier: a new session of the continuous conversation — ${WHY[reason]}. The rest of this note is context, not a message.]`,
|
|
203
206
|
section("MEMORY.md", cut(await this.read("MEMORY.md"), MEMORY_CHARS)),
|
|
204
207
|
section("Open", this.deps.status(this.now()).text),
|
|
205
|
-
section("Runs — in flight,
|
|
208
|
+
section("Runs — in flight, or ended short of success since the previous session started (succeeded and skipped: `pier task runs`)", cut(runs.map(ledgerLine).join("\n"), LEDGER_CHARS) || "none"),
|
|
206
209
|
...(await Promise.all(days.map(async (date) => section(`memory/${date}.md`, tail(await this.read(join("memory", `${date}.md`)), NOTES_CHARS, `memory/${date}.md`))))),
|
|
207
210
|
section("The previous session's last exchanges", open ? tail(lastExchanges(await open.history(), EXCHANGES), EXCHANGES_CHARS, `session ${open.id}`) : ""),
|
|
208
211
|
].filter(Boolean).join("\n\n");
|
package/dist/tasks/agent.js
CHANGED
|
@@ -20,7 +20,7 @@ const preamble = (run, supervised, role) => {
|
|
|
20
20
|
: "read by the operator";
|
|
21
21
|
return `[Pier task run ${run.id} — "${run.context.definition.name}"] ` +
|
|
22
22
|
`Your final reply is recorded verbatim as the run result, ${audience}; ` +
|
|
23
|
-
`next-step buttons and file:// attachments do not render there.
|
|
23
|
+
`next-step buttons and file:// attachments do not render there. Two parts: the conclusion — the paths it rests on, risks and unverified points one line each — then, only when something does, \`Needs your decision\`; no process, no log of attempts; a deliverable longer than a screen goes to a file the result names. A reversible choice on the way (how to push, a rebase strategy) is yours: take the recommended option and name it in the result. A destructive or irreversible step — force push, deleting what you did not create, a migration, a deploy, a restart — or a question only that reader can answer stops you: state it as your result and end your turn; the answer resumes this session.` +
|
|
24
24
|
(role === "lead"
|
|
25
25
|
? " You are a feature lead: you may delegate to workers with `pier task run` (never `--role lead`), and their results come back to you."
|
|
26
26
|
: supervised || role === "worker" ? " You cannot delegate from here — `pier task` is refused; if the work needs another agent, say so in your result and your supervisor will run it." : "") +
|
package/dist/tasks/callbacks.js
CHANGED
|
@@ -22,7 +22,7 @@ const oneRun = (run) => {
|
|
|
22
22
|
return { source: runSource(run), state: run.state, ...(cwd ? { cwd } : {}) };
|
|
23
23
|
};
|
|
24
24
|
/** Heads a milestone resume's prompt: the lead's reply is what its supervisor reads. */
|
|
25
|
-
export const MILESTONE = "[Pier: the last result you were waiting on follows; nothing owed to you is still running. Your reply is the milestone your supervisor reads:
|
|
25
|
+
export const MILESTONE = "[Pier: the last result you were waiting on follows; nothing owed to you is still running. Your reply is the milestone your supervisor reads, in two parts: the conclusion (done, next, risks one line each), then `Needs your decision` only when something does.]";
|
|
26
26
|
/** The line a design lead ends on once the user confirms: its milestone, whether a run's or a turn outside any. */
|
|
27
27
|
export const DESIGN_FINAL = /^Design final:/m;
|
|
28
28
|
/** On the record of a lead run that owed its supervisor nothing, so the run says why. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{B as e,Et as t,J as n,M as r,Mt as i,T as a,U as o,V as s,X as c,Z as l,c as u,f as d,g as f,h as p,jt as m,k as h,n as ee,p as te,q as ne,rt as g,s as re,t as ie,wt as _,x as ae}from"./highlight-CDSk2hRJ.js";import{a as oe}from"./index-
|
|
1
|
+
import{B as e,Et as t,J as n,M as r,Mt as i,T as a,U as o,V as s,X as c,Z as l,c as u,f as d,g as f,h as p,jt as m,k as h,n as ee,p as te,q as ne,rt as g,s as re,t as ie,wt as _,x as ae}from"./highlight-CDSk2hRJ.js";import{a as oe}from"./index-DqLJpDE0.js";import{n as se,t as ce}from"./code-CWT27KH1.js";var le=[[`path`,{d:`M12 5v14`}],[`path`,{d:`m19 12-7 7-7-7`}]],ue=[[`path`,{d:`M12 22v-6`}],[`path`,{d:`M12 8V2`}],[`path`,{d:`M4 12H2`}],[`path`,{d:`M10 12H8`}],[`path`,{d:`M16 12h-2`}],[`path`,{d:`M22 12h-2`}],[`path`,{d:`m15 19-3-3-3 3`}],[`path`,{d:`m15 5-3 3-3-3`}]],de=[[`path`,{d:`M10 20a1 1 0 0 0 .553.895l2 1A1 1 0 0 0 14 21v-7a2 2 0 0 1 .517-1.341L21.74 4.67A1 1 0 0 0 21 3H3a1 1 0 0 0-.742 1.67l7.225 7.989A2 2 0 0 1 10 14z`}]],fe=[[`path`,{d:`M15 6a9 9 0 0 0-9 9V3`}],[`circle`,{cx:`18`,cy:`6`,r:`3`}],[`circle`,{cx:`6`,cy:`18`,r:`3`}]],v=[[`path`,{d:`M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8`}],[`path`,{d:`M3 3v5h5`}]],y=e=>{let t=new Date(e),n=e=>String(e).padStart(2,`0`);return`${t.getFullYear()}-${n(t.getMonth()+1)}-${n(t.getDate())} ${n(t.getHours())}:${n(t.getMinutes())}:${n(t.getSeconds())}`},b=e=>[e.subject,e.body,[[e.author,e.email?`<${e.email}>`:``].filter(Boolean).join(` `),e.at?y(e.at):``].filter(Boolean).join(` · `)].filter(Boolean).join(`
|
|
2
2
|
|
|
3
3
|
`),x=null;function S(){x&&(x.remove(),x=null,document.removeEventListener(`pointerdown`,S,!0),window.removeEventListener(`scroll`,S,!0))}function pe(e,t){e.onmouseenter=()=>{S();let r=t();if(!r)return;x=n(`div`,`pointer-events-none fixed z-50 max-w-96 whitespace-pre-wrap rounded-lg bg-neutral-800/95 px-3 py-2 font-sans text-[11.5px] leading-snug text-neutral-100 shadow-lg`),x.textContent=r,(e.closest(`dialog[open]`)??document.body).append(x),document.addEventListener(`pointerdown`,S,!0),window.addEventListener(`scroll`,S,!0);let i=e.getBoundingClientRect();x.style.left=`${Math.max(8,Math.min(i.left,window.innerWidth-x.offsetWidth-8))}px`,x.style.top=i.bottom+6+x.offsetHeight>window.innerHeight?`${i.top-x.offsetHeight-6}px`:`${i.bottom+6}px`},e.onmouseleave=S}function C(e,t,r){let i=n(`button`,`flex w-full cursor-pointer items-center gap-1.5 px-2 py-1 text-left hover:bg-neutral-100`,_(m,`h-3 w-3 text-indigo-600 ${e.value===t?``:`invisible`}`),n(`span`,`inline-flex flex-none items-center gap-1.5 font-mono text-[11.5px] text-neutral-800`,e.label??e.value));return e.subject&&i.append(n(`span`,`min-w-0 truncate text-[11px] text-neutral-400`,e.subject)),e.author&&i.append(n(`span`,`ml-auto flex-none pl-1.5 text-[10.5px] text-neutral-400`,`${e.author} · ${e.at?l(e.at):``}`)),pe(i,()=>b(e)),i.onclick=()=>r(e.value),i}function me(e,t,r,i,a){let{base:o,head:s}=r,c=()=>s&&o===`${s}~1`?s:``,l=c()?`commit`:`compare`,f=t.commits[0],p=e=>[...e?[{value:``,label:`Working tree`,subject:`the files on disk, uncommitted changes included`}]:[],{...f,value:`HEAD`},...t.refs.map(e=>({value:e.name,subject:e.subject})),...t.commits.map(e=>({...e,value:e.hash}))],m=n(`div`,`flex w-[38rem] max-w-full flex-col`);function h(){let e=(e,t)=>{let r=n(`button`,`cursor-pointer rounded-full px-2.5 py-0.5 text-[11.5px] ${l===t?`bg-indigo-50 font-medium text-indigo-700`:`text-neutral-500 hover:bg-neutral-100`}`,e);return r.onclick=()=>{l=t,h()},r},r=(e,t,r,i)=>n(`div`,`flex min-w-0 flex-1 flex-col`,n(`div`,`flex-none px-2 pb-0.5 text-[10.5px] font-semibold uppercase tracking-wide text-neutral-400`,e),n(`div`,`min-h-0 flex-1 overflow-y-auto`,...t.map(e=>C(e,r,i)))),d=l===`compare`?n(`div`,`flex h-72 min-h-0 divide-x divide-neutral-200 pb-1`,r(`base`,p(!1),o,e=>{o=e,h(),i(o,s)}),r(`to`,p(!0),s,e=>{s=e,h(),i(o,s)})):n(`div`,`flex h-72 min-h-0 flex-col overflow-y-auto pb-1`,...t.commits.map(e=>C({value:e.hash,...e},c(),e=>{o=`${e}~1`,s=e,u(),i(o,s)}))),f=n(`div`,`flex-none border-t border-neutral-200`,C({value:a,label:`${a} ↔ Working tree`,subject:`back to the default: the main line's tip vs the files on disk`},o===a&&s===``?a:``,()=>{o=a,s=``,h(),i(o,s)}));f.querySelector(`button > span`).prepend(_(v)),m.replaceChildren(n(`div`,`flex flex-none items-center gap-1 border-b border-neutral-200 px-2 py-1.5`,e(`Compare two points`,`compare`),e(`One commit`,`commit`)),d,...l===`compare`?[f]:[])}h(),d(e,m)}var he=e=>e.slice(0,Math.max(0,e.lastIndexOf(`/`))),ge=/\.(png|jpe?g|gif|webp|avif|bmp|svg)$/i,_e=/\.(md|markdown)$/i,ve={A:`text-emerald-600`,M:`text-amber-600`,D:`text-red-600`},ye=30,w=`pier.filesPrefs`,T=50,E=()=>{try{let e=JSON.parse(localStorage.getItem(w)??`{}`);return e&&typeof e==`object`?e:{}}catch{return{}}},be=e=>{let t=e?E()[e]:void 0;return typeof t?.cwd==`string`&&typeof t.base==`string`&&typeof t.head==`string`?{cwd:t.cwd,base:t.base,head:t.head}:null},xe=(e,t)=>{let n=E();delete n[e],n[e]=t;let r=Object.keys(n);for(let e of r.slice(0,Math.max(0,r.length-T)))delete n[e];try{localStorage.setItem(w,JSON.stringify(n))}catch(e){console.warn(`Files: could not remember this folder`,e)}},Se=`flex min-w-0 flex-none items-center gap-1.5 rounded-full px-2.5 py-1 font-mono text-[11.5px]`,Ce=(e,t=`indigo`)=>ae(e,`${Se} cursor-pointer truncate text-left ${t===`indigo`?`bg-indigo-50 font-medium text-indigo-700 hover:bg-indigo-100`:`bg-neutral-100 text-neutral-600 hover:bg-neutral-200`}`),D,O=()=>D??=N(e(`#files-dialog`)),k=(e,t,n,r)=>O()(e,t,n,r);function A(t){let n=e(`#files-dialog`);n.open?n.close():k(t)}function j(e,t){if(e&&t===e)return{root:e};let n=e&&t.startsWith(`${e}/`)?e:t.slice(0,t.lastIndexOf(`/`))||`/`,r=t.slice(n===`/`?1:n.length+1);return r?{root:n,select:r}:{root:n}}function we(e,t,n){if(!n||n.startsWith(`#`)||n.startsWith(`//`)||/^[a-z][a-z\d+.-]*:/i.test(n))return null;let r=n.replace(/[?#].*$/s,``);try{r=decodeURIComponent(r)}catch{}let i=(r.startsWith(`/`)?r===e||r.startsWith(`${e}/`)?``:e:t).split(`/`).filter(Boolean);for(let e of r.split(`/`))e===`..`?i.pop():e&&e!==`.`&&i.push(e);return`/${i.join(`/`)}`}var Te=e=>e.trim().toLowerCase().replace(/[^\p{L}\p{N}\s_-]/gu,``).replace(/\s/g,`-`);function M(e,t,n){let{root:r,select:i}=j(e?.cwd??``,t);k(e,r,i,n)}function N(e){let l=``,u=``,d={branch:null,refs:[],commits:[],worktrees:[]},m=`HEAD`,v=``,y=new Map,x=!0,S=!1,C=!1,w=[],T=new Set,E=null,D=null,O=null,k,A=n(`header`,`pagehead flex-nowrap`),M=n(`div`,`${te} flex-col items-stretch gap-1.5 px-3 py-2.5`),N=n(`div`,`min-h-0 flex-1 overflow-y-auto px-1.5 py-1.5`),Ee=n(`aside`,`${f} w-64 flex-none text-[12.5px] leading-5 max-md:h-1/2 max-md:w-full`,M,N),P=n(`div`,`${te} flex-wrap gap-2 px-4 py-2.5 font-mono text-[11.5px] text-neutral-500`),F=n(`div`,`h-full min-w-0 overflow-auto`),I=n(`div`,`pointer-events-none absolute inset-y-1 right-0.5 z-20 hidden w-2`),De=n(`div`,`relative min-h-0 flex-1`,F,I),Oe=n(`section`,`${f} min-h-0 min-w-0 flex-1`,P,De);e.append(A,n(`div`,`flex min-h-0 flex-1 gap-3 px-4 pb-4 pt-1 max-md:flex-col`,Ee,Oe));let L=(e,t)=>`/api/explorer/${e}?${new URLSearchParams({root:l,...t})}`,R=(e,t)=>`/api/fs/${e}?${new URLSearchParams({root:l,...t})}`,z=(e,t=`text-neutral-400`)=>n(`p`,`px-3 py-2 text-[12.5px] ${t}`,e),B=e=>n(`div`,`flex h-full items-center justify-center p-6`,a(e)),ke=()=>x&&d.branch!==null,Ae=e=>{let t=0;for(let n of y.keys())n.startsWith(`${e}/`)&&t++;return t};function je(e,t){let n=new Set(t.map(e=>e.name)),r=e?`${e}/`:``;for(let[e,i]of y){if(i.status!==`D`||!e.startsWith(r))continue;let a=e.slice(r.length).split(`/`)[0];n.has(a)||(n.add(a),t.push({name:a,dir:e.slice(r.length).includes(`/`)}))}let i=t;return ke()&&(i=t.filter(e=>e.dir?Ae(`${r}${e.name}`)>0:y.has(`${r}${e.name}`))),i.sort((e,t)=>Number(t.dir)-Number(e.dir)||e.name.localeCompare(t.name)),O&&he(O)===e&&!n.has(o(O))&&(F.replaceChildren(B(`No such file: ${O}`)),O=null),i.map(e=>e.dir?Ne(`${r}${e.name}`,e.name):Pe(`${r}${e.name}`,e.name))}async function Me(e,t){try{let{entries:n}=await g(R(`ls`,{path:t}),`could not list this folder`);e.replaceChildren(...je(t,n)),e.childElementCount||e.append(z(ke()?`No changes.`:`Empty.`))}catch(n){let r=je(t,[]);r.length?e.replaceChildren(...r):e.replaceChildren(z(String(n),`text-red-600`))}}function Ne(e,t){let r=Ae(e),i=[n(`span`,`truncate`,t)];r&&i.push(n(`span`,`ml-auto flex-none rounded-full bg-amber-100/80 px-1.5 font-mono text-[10px] font-semibold text-amber-700`,String(r)));let{el:a,summary:o}=ne(``,i);o.className+=` rounded-lg px-2 py-1 transition-colors hover:bg-neutral-100`;let s=n(`div`,`pl-3`);a.append(s);let c=!1,l=()=>{c||(c=!0,s.append(z(`…`)),Me(s,e))};a.ontoggle=()=>{T[a.open?`add`:`delete`](e),a.open&&l()};let u=d.branch?x:!e.includes(`/`);return e===O&&(O=null),(u&&!C||T.has(e))&&(a.open=!0,l()),a}function V(e){D?.classList.remove(`bg-indigo-50`,`font-medium`,`text-indigo-700`),D=e,e.classList.add(`bg-indigo-50`,`font-medium`,`text-indigo-700`)}function Pe(e,t){let r=y.get(e)?.status,i=n(`button`,`flex w-full cursor-pointer items-center gap-1.5 rounded-lg py-1 pl-6 pr-2 text-left transition-colors hover:bg-neutral-100`,n(`span`,`truncate`,t));return r&&i.append(n(`span`,`ml-auto flex-none font-mono text-[10.5px] font-semibold ${ve[r]??`text-neutral-500`}`,r)),i.title=e,e===E&&V(i),e===O&&(O=null,E=e,V(i),q(e)),i.onclick=()=>{V(i),E=e,q(e)},i}let H=()=>void Me(N,``),Fe=(e,t)=>[...e?[n(`span`,`flex-none font-mono text-[10.5px] font-semibold text-emerald-600`,`+${e}`)]:[],...t?[n(`span`,`flex-none font-mono text-[10.5px] font-semibold text-red-600`,`−${t}`)]:[]];function U(e,t=!1,...r){if(P.classList.toggle(`hidden`,!e),P.classList.toggle(`flex`,!!e),!e)return P.replaceChildren();let i=y.get(e),a=[n(`span`,`min-w-0 truncate`,e)];i&&(a.push(n(`span`,`flex-none font-semibold ${ve[i.status]??``}`,i.status)),a.push(...Fe(i.add,i.del)));let s=n(`div`,`ml-auto flex flex-none items-center gap-2`);if(s.append(...r),t){let t=document.createElement(`a`);t.className=`btn flex-none text-[12px]`,t.href=R(`file`,{path:e}),t.download=o(e),t.textContent=`Download`,s.append(t)}P.replaceChildren(...a,s)}function Ie(e){let t=0;for(;t<e.length;){if(e[t].tone!==`del`){t++;continue}let n=t;for(;t<e.length&&e[t].tone===`del`;)t++;let r=t;for(;t<e.length&&e[t].tone===`add`;)t++;let i=Math.min(r-n,t-r);for(let t=0;t<i;t++){let i=e[n+t],a=e[r+t],o=Math.min(i.text.length,a.text.length),s=0;for(;s<o&&i.text[s]===a.text[s];)s++;let c=0;for(;c<o-s&&i.text[i.text.length-1-c]===a.text[a.text.length-1-c];)c++;s+c!==0&&(i.mark=[s,i.text.length-c],a.mark=[s,a.text.length-c])}}}let W=Je();function G(){I.classList.add(`hidden`),I.replaceChildren(),W.set([],[])}function Le(e,t){let n=e===E?k:void 0;if(n===void 0)return t;k=void 0;let r=t.querySelector(`[data-line="${String(n)}"]`);return r?.classList.add(`bg-indigo-100`),requestAnimationFrame(()=>r?.scrollIntoView({block:`center`})),t}let Re=0,K=e=>e===Re,ze=e=>_e.test(e)&&!S&&(e!==E||k===void 0);function Be(e,t){if(!_e.test(e))return[];let n=r([[`Rendered`,`rendered`],[`Source`,`source`]],t?`rendered`:`source`,n=>{n===`rendered`!==t&&(S=n===`source`,q(e))});return n.classList.add(`font-sans`),[n]}function Ve(e,t){let n=c(e);n.className=`md mx-auto max-w-3xl px-6 py-5 text-[14px] leading-relaxed`,ie(n),s(n);let r=`${l}/${he(t)}`,i=e=>{let t=j(l,e);return`/api/fs/file?${new URLSearchParams({root:t.root,path:t.select??``})}`};for(let e of n.querySelectorAll(`img`)){let t=we(l,r,e.getAttribute(`src`)??``);t&&e.setAttribute(`src`,i(t))}for(let e of n.querySelectorAll(`a`)){let t=e.getAttribute(`href`)??``;if(t.startsWith(`#`)){e.onclick=e=>{e.preventDefault();let r=t.slice(1);try{r=decodeURIComponent(r)}catch{}r=r.toLowerCase(),[...n.querySelectorAll(`h1, h2, h3, h4, h5, h6`)].find(e=>Te(e.textContent??``)===r)?.scrollIntoView({block:`start`})};continue}let a=we(l,r,t);a&&(e.setAttribute(`href`,i(a)),e.onclick=e=>{if(e.metaKey||e.ctrlKey||e.shiftKey||e.button!==0)return;e.preventDefault();let t=j(l,a);$(Q,t.root,t.select)})}return n}function q(e){let t=++Re;return y.has(e)?Ye(e,t):He(e,t)}async function He(e,t){if(!K(t))return;G();let r=R(`file`,{path:e}),i=n(`div`,`min-w-0`);F.classList.remove(`flex`,`flex-col`);let a=ze(e);if(U(e,!0,...Be(e,a)),F.replaceChildren(i),ge.test(e)){let e=n(`img`,`max-w-full p-4`);e.src=r,e.onerror=()=>i.replaceChildren(z(`Could not load image.`,`text-red-600`)),i.append(e);return}if(e.toLowerCase().endsWith(`.pdf`)){let e=document.createElement(`iframe`);e.className=`h-full w-full`,e.src=r,F.replaceChildren(e),F.classList.add(`flex`,`flex-col`);return}i.append(z(`…`));let o=await fetch(r);if(!K(t))return;if(!o.ok){let{error:e}=await o.json().catch(()=>({}));i.replaceChildren(z(e??`HTTP ${o.status}`,`text-red-600`));return}if(!(o.headers.get(`content-type`)??``).startsWith(`text/plain`)){i.replaceChildren(z(`Binary file — use Download.`));return}let s=await o.text();if(!K(t))return;if(a)return void i.replaceChildren(Ve(s,e));let c=se(s),l=await ee(e);K(t)&&i.replaceChildren(Le(e,ce(c,l)))}function Ue(e){let t=[],n=0,r=0,i=!1,a=e.split(`
|
|
4
4
|
`);a.at(-1)===``&&a.pop();for(let e of a){let a=/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/.exec(e);if(a){i&&t.push({nums:[``,``],text:`⋯`,tone:``}),[n,r]=[Number(a[1]),Number(a[2])],i=!0;continue}!i||e.startsWith(`\\`)||(e.startsWith(`+`)?t.push({nums:[``,r++],text:e.slice(1),tone:`add`}):e.startsWith(`-`)?t.push({nums:[n++,``],text:e.slice(1),tone:`del`}):t.push({nums:[n++,r++],text:e.slice(1),tone:``}))}return t}function We(e){let t=[];for(let n=0;n<e.length;n++){let r=e[n].tone;if(!r)continue;let i=t.at(-1);i&&i.end===n-1?(i.end=n,(r===`add`&&i.tone===`del`||r===`del`&&i.tone===`add`)&&(i.tone=`mixed`)):t.push({start:n,end:n,tone:r})}return t}let Ge={add:`bg-emerald-400`,del:`bg-red-400`,mixed:`bg-amber-400`};function Ke(e,t,r){I.replaceChildren(...e.map(e=>{let i=n(`button`,`map-mark pointer-events-auto absolute left-1/2 w-1 -translate-x-1/2 cursor-pointer rounded-full ${Ge[e.tone]}`);return i.style.top=`${e.start/t*100}%`,i.style.height=`${Math.max(.4,(e.end-e.start+1)/t*100)}%`,i.title=`line ${qe(r,e.start)}`,i.onclick=()=>r[e.start].scrollIntoView({block:`center`}),i})),I.classList.remove(`hidden`)}let qe=(e,t)=>e[t]?.querySelector(`span`)?.textContent?.trim()||String(t+1);function Je(){let t=[],r=[],a=-1,o=n(`span`,`flex-none text-[10.5px] text-neutral-400`),s=e=>{t.length&&(a=(a+e+t.length)%t.length,r[t[a].start].scrollIntoView({block:`center`}),o.textContent=`${a+1}/${t.length}`)},c=()=>t.length>0&&e.open,l=(e,t,r,i)=>{let a=n(`button`,`icon-btn flex-none`,_(e));return a.onclick=()=>s(t),oe(a,i,r,()=>s(t),c),a};return{el:n(`div`,`flex flex-none items-center gap-1`,o,l(i,-1,`Previous change`,[`p`,`k`]),l(le,1,`Next change`,[`n`,`j`])),set(e,n){t=e,r=n,a=-1,o.textContent=`${e.length} change${e.length===1?``:`s`}`}}}async function Ye(e,t){G(),F.classList.remove(`flex`,`flex-col`);let n=y.get(e)?.status===`D`,r=!n,i=ze(e),a=Be(e,i);U(e,r,...a),F.replaceChildren(z(`…`));try{let{diff:o}=await g(L(`diff`,{base:m,head:v,file:e,context:`99999`}),`could not read this diff`);if(!K(t))return;if(!o||/^Binary files /m.test(o))return He(e,t);let s=Ue(o);if(i){let t=n?`add`:`del`,r=s.filter(e=>e.tone!==t&&e.nums.some(e=>e!==``)).map(e=>e.text).join(`
|
|
Binary file
|
|
Binary file
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/explorer-
|
|
2
|
-
import{$ as e,B as t,C as n,Ct as r,E as i,Et as a,G as o,H as s,J as c,K as l,Ot as u,P as d,Q as f,R as ee,S as p,St as m,T as te,Tt as ne,U as re,V as ie,W as h,X as ae,Y as oe,Z as se,b as ce,c as g,ct as le,d as ue,dt as de,et as fe,f as pe,ft as me,gt as he,h as ge,ht as _e,i as ve,it as ye,jt as be,kt as xe,l as Se,lt as Ce,mt as we,nt as Te,o as Ee,ot as _,pt as De,q as Oe,rt as ke,st as Ae,t as je,tt as v,u as Me,ut as Ne,vt as Pe,w as Fe,wt as y,x as Ie,xt as Le,yt as b}from"./highlight-CDSk2hRJ.js";import{t as Re}from"./hljs-BRz6a8Dq.js";(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var ze=[[`path`,{d:`m12 19-7-7 7-7`}],[`path`,{d:`M19 12H5`}]],Be=[[`path`,{d:`M7 7h10v10`}],[`path`,{d:`M7 17 17 7`}]],Ve=[[`path`,{d:`M20 4v7a4 4 0 0 1-4 4H4`}],[`path`,{d:`m9 10-5 5 5 5`}]],He=[[`path`,{d:`M12 15V3`}],[`path`,{d:`M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4`}],[`path`,{d:`m7 10 5 5 5-5`}]],Ue=[[`path`,{d:`M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0`}],[`circle`,{cx:`12`,cy:`12`,r:`3`}]],We=[[`path`,{d:`M21 12a9 9 0 1 1-6.219-8.56`}]],Ge=[[`path`,{d:`M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z`}]],Ke=[[`path`,{d:`M16 10a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 14.286V4a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z`}],[`path`,{d:`M20 9a2 2 0 0 1 2 2v10.286a.71.71 0 0 1-1.212.502l-2.202-2.202A2 2 0 0 0 17.172 19H10a2 2 0 0 1-2-2v-1`}]],qe=[[`path`,{d:`M5 12h14`}]],Je=[[`rect`,{width:`20`,height:`14`,x:`2`,y:`3`,rx:`2`}],[`line`,{x1:`8`,x2:`16`,y1:`21`,y2:`21`}],[`line`,{x1:`12`,x2:`12`,y1:`17`,y2:`21`}]],Ye=[[`path`,{d:`M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401`}]],Xe=[[`rect`,{x:`14`,y:`3`,width:`5`,height:`18`,rx:`1`}],[`rect`,{x:`5`,y:`3`,width:`5`,height:`18`,rx:`1`}]],Ze=[[`path`,{d:`M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z`}],[`path`,{d:`m15 5 4 4`}]],Qe=[[`path`,{d:`M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8`}],[`path`,{d:`M3 3v5h5`}],[`path`,{d:`M12 7v5l4 2`}]],$e=[[`path`,{d:`M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915`}],[`circle`,{cx:`12`,cy:`12`,r:`3`}]],et=[[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`}],[`line`,{x1:`9`,x2:`15`,y1:`15`,y2:`9`}]],tt=[[`circle`,{cx:`12`,cy:`12`,r:`4`}],[`path`,{d:`M12 2v2`}],[`path`,{d:`M12 20v2`}],[`path`,{d:`m4.93 4.93 1.41 1.41`}],[`path`,{d:`m17.66 17.66 1.41 1.41`}],[`path`,{d:`M2 12h2`}],[`path`,{d:`M20 12h2`}],[`path`,{d:`m6.34 17.66-1.41 1.41`}],[`path`,{d:`m19.07 4.93-1.41 1.41`}]],nt=String.raw`(?<when>(?:\d{4}-\d{2}-\d{2} )?\d{1,2}:\d{2})`,rt=String.raw`lang=(?<lang>[a-z]{2})`,it=new RegExp(String.raw`^\[(?:(?<name>[^\n[\]<>]*)<(?<id>[^\n[\]<>]+)>)? ?${nt}? ?(?<where>[a-z]+:[^\s[\]<>]+)? ?(?:${rt})?\]\n`),at=new RegExp(String.raw`^\[(?<name>[^\n[\]<>]*?) ${nt}(?: (?<where>[a-z]+))?(?: ${rt})?\]\n`);function ot(e){let t=it.exec(e),{id:n,when:r,where:i,lang:a}=t?.groups??{},o=n||r||i||a?t:at.exec(e);return o?.groups?{...o.groups.name?{name:o.groups.name}:{},...o.groups.id?{id:o.groups.id}:{},...o.groups.when?{when:o.groups.when}:{},...o.groups.where?{where:o.groups.where}:{},...o.groups.lang?{lang:o.groups.lang}:{},text:e.slice(o[0].length)}:{text:e}}var st=/(?:\n\[[^\]\n]*(?:\]\(\s*<?file:\/\/[^\n]*|$))+$/,ct=/^\s*`[^`\n]{40,}`\s+(\S[\s\S]*)$/;function lt(e){if(!e)return e;let{text:t}=ot(e);return t===e?e:t.replace(st,``).replace(ct,`$1`).replace(/\s+/g,` `).trim()||e}var ut=e=>[...new Set([...e].sort((e,t)=>t.createdAt-e.createdAt).map(e=>e.cwd))];function dt(e){let t=ut(e),n=new Set(t);return t.filter(e=>{let t=e.lastIndexOf(`/`),r=e.indexOf(`.`,t+2);return r<0||!n.has(e.slice(0,r))})}var ft=t(`#image-dialog`),x=t(`#image-stage`),pt=t(`#image-full`),mt=t(`#image-prev`),ht=t(`#image-next`),gt=t(`#image-close`),_t=[],vt=0;function yt(e){_t.length<2||(vt=(vt+e+_t.length)%_t.length,St(!1),pt.src=_t[vt])}var bt=2.5,xt=()=>x.dataset.zoom!==void 0;function St(e,t){if(!e){delete x.dataset.zoom,pt.style.cssText=``;return}let n=pt.getBoundingClientRect(),r=x.getBoundingClientRect(),i=t?(t.x-n.left)/n.width:.5,a=t?(t.y-n.top)/n.height:.5,o=n.width*bt,s=n.height*bt;x.dataset.zoom=``,pt.style.width=`${String(o)}px`,pt.style.height=`${String(s)}px`,x.scrollLeft=i*o-r.width/2,x.scrollTop=a*s-r.height/2}function Ct(e){let t=e.closest(`[data-gallery]`);_t=t?[...t.querySelectorAll(`img.thumb`)].map(e=>e.src):[e.src],vt=Math.max(0,_t.indexOf(e.src)),pt.src=e.src;let n=_t.length<2?`none`:`flex`;mt.style.display=n,ht.style.display=n,ft.showModal()}var wt=4,Tt,Et=!1;x.onpointerdown=e=>{Et=!1,!(!xt()||e.button!==0)&&(Tt={x:e.clientX,y:e.clientY,left:x.scrollLeft,top:x.scrollTop},x.setPointerCapture(e.pointerId))},x.onpointermove=e=>{if(!Tt)return;let t=e.clientX-Tt.x,n=e.clientY-Tt.y;(Math.abs(t)>wt||Math.abs(n)>wt)&&(Et=!0),x.scrollLeft=Tt.left-t,x.scrollTop=Tt.top-n};var Dt=()=>{Tt=void 0};x.onpointerup=Dt,x.onpointercancel=Dt,x.onclick=e=>{Et||(e.target===pt?St(!xt(),{x:e.clientX,y:e.clientY}):ft.close())},gt.onclick=()=>ft.close(),ft.onclose=()=>St(!1),mt.onclick=()=>yt(-1),ht.onclick=()=>yt(1),ft.onkeydown=e=>{(e.key===`ArrowLeft`||e.key===`ArrowRight`)&&(e.preventDefault(),yt(e.key===`ArrowLeft`?-1:1))};function Ot(e){let t=e.querySelector(`:scope > .thumbs`);if(t)return t;let n=c(`div`,`thumbs`);return e.append(n),n}function kt(e){let t=document.createElement(`img`);return t.src=e,t.loading=`lazy`,t.className=`thumb`,t.onclick=()=>Ct(t),t}var At=new Set([`png`,`jpg`,`jpeg`,`gif`,`webp`,`avif`,`bmp`]),jt=e=>e.split(`.`).pop()?.toLowerCase()??``,Mt=(e,t)=>`/api/sessions/${encodeURIComponent(e)}/files?path=${encodeURIComponent(t)}`,Nt=(e,t,n,r)=>void ve(()=>import(`./explorer-C4DhXFCm.js`).then(i=>i.openPath({id:e,cwd:t??``},n,r)),__vite__mapDeps([0,1,2]));function Pt(e,t){return m(e,/\]\(\s*<?file:\/\/(\/[^)>\s]*)>?\s*\)/g,e=>{let n=e[1];try{n=decodeURIComponent(n)}catch{}return`](${Mt(t,n)})`})}var Ft=e=>/^\/api\/sessions\/[^/]+\/files\?/.test(e);function It(e,t){let n=re(t)||`file`,r=Mt(e,t);return At.has(jt(n))?Xt(r,n):Zt(r,n)}function Lt(e){return new URLSearchParams(e.slice(e.indexOf(`?`)+1)).get(`path`)??``}var Rt=new Set(`ts.tsx.mts.cts.js.jsx.mjs.cjs.json.md.css.html.py.rs.go.rb.java.c.h.cpp.hpp.sh.sql.yml.yaml.toml.ini.conf.txt.lock`.split(`.`)),zt=/^(?:~|\/(?:home|Users|root|tmp|var|opt|etc|srv|mnt|media|data|usr))(?:\/|$)/;function Bt(e){let t=/^([^\s`"'()[\]{}<>]+?)(?::(\d+))?(?::\d+)?$/.exec(e);if(!t||e.includes(`://`))return null;let n=t[1],r=n.includes(`.`)?jt(n):``;return!zt.test(n)&&(!r||!Rt.has(r)&&!n.includes(`/`))?null:{path:n,line:t[2]===void 0?void 0:Number(t[2])}}var Vt;async function Ht(e,t){let n;if(e.startsWith(`~`)){Vt??=Ee().then(e=>e?.path??null);let r=await Vt;n=r===null?[]:[{path:`${r}${e.slice(1)}`,cwd:t[0]??null}]}else n=e.startsWith(`/`)?[{path:e,cwd:t[0]??null}]:t.map(t=>({path:`${t}/${e}`,cwd:t}));let r=await Promise.all(n.map(e=>Wt(e.path)));return n[r.indexOf(!0)]??null}var Ut=null;function Wt(e){return new Promise(t=>{Ut||(Ut=new Map,setTimeout(()=>void Kt(),0)),Ut.set(e,[...Ut.get(e)??[],t])})}var Gt=1e3;async function Kt(){let e=Ut;Ut=null;let t=[...e.keys()],n=Array.from({length:Math.ceil(t.length/Gt)},(e,n)=>t.slice(n*Gt,(n+1)*Gt)),r=await Promise.all(n.map(e=>ye(`/api/fs/exists`,{paths:e},`Could not check file references`))),i=r.find(e=>!e.ok);i&&!i.ok&&ve(()=>Promise.resolve().then(()=>ei).then(e=>e.report(i.error)),void 0),n.forEach((t,n)=>{let i=r[n];t.forEach((t,n)=>{for(let r of e.get(t)??[])r(i.ok&&i.value.exists[n]===!0)})})}function qt(e,t,n){for(let r of e){let e=Bt(r.textContent?.trim()??``);!e||r.closest(`a`)||Ht(e.path,n).then(n=>{n&&Yt(r,t,n.cwd,n.path,e.line)})}}function Jt(e){let t=e.textContent??``,n=[],r=[],i=0;for(let e of t.matchAll(/`([^`\n]+)`/g)){if(!Bt(e[1].trim()))continue;let a=e.index+1,o=c(`code`,``,e[1]);n.push(t.slice(i,a),o),r.push(o),i=a+e[1].length}return n.length&&e.replaceChildren(...n,t.slice(i)),r}function Yt(e,t,n,r,i){let a=()=>Nt(t,n,r,i);e.classList.add(`fileref`),e.tabIndex=0,e.setAttribute(`role`,`button`),e.title=i===void 0?r:`${r}:${String(i)}`,e.onclick=a,e.addEventListener(`pointerup`,()=>e.blur()),e.onkeydown=e=>{(e.key===`Enter`||e.key===` `)&&(e.preventDefault(),a())}}function Xt(e,t){let n=kt(e);return n.alt=t,n}function Zt(e,t){let n=decodeURIComponent(/^\/api\/sessions\/([^/]+)\//.exec(e)?.[1]??``),r=jt(t),i=c(`span`,`inline-flex max-w-full items-center gap-2.5 rounded-lg border border-neutral-200 bg-neutral-50 px-2.5 py-1.5 no-underline`),a=c(`span`,`flex h-7 w-7 flex-none items-center justify-center rounded-md bg-indigo-50 text-[10px] font-semibold uppercase text-indigo-600`,r.slice(0,4)||`file`),o=c(`span`,`min-w-0 truncate text-[13px] font-medium text-neutral-800`,t),s=c(`span`,`ml-1 flex flex-none items-center gap-0.5`),l=c(`button`,`icon-btn h-6 w-6 text-[13px]`,y(Ue));l.setAttribute(`aria-label`,`Preview`),l.title=`Preview`,l.onclick=t=>{t.preventDefault(),Nt(n,null,Lt(e))},s.append(l);let u=document.createElement(`a`);return u.className=`icon-btn h-6 w-6 text-[13px] no-underline`,u.href=`${e}&download=1`,u.download=t,u.title=`Download`,u.append(y(He)),u.setAttribute(`aria-label`,`Download`),s.append(u),i.append(a,o,s),i}function Qt(e){let t=new Set;for(let n of e)n.parentElement&&t.add(n.parentElement);for(let n of t){let t=[...n.children].filter(t=>e.includes(t));if([...n.childNodes].every(e=>e.nodeType===Node.TEXT_NODE?!e.textContent?.trim():t.includes(e))){n.classList.add(`thumbs`);continue}let r=c(`div`,`thumbs`);r.append(...t),n.after(r)}}function $t(e){let t=[];for(let n of e.querySelectorAll(`img`)){let e=n.getAttribute(`src`)??``;if(!Ft(e))continue;let r=Xt(e,re(Lt(e)));n.replaceWith(r),t.push(r)}for(let n of e.querySelectorAll(`a`)){let e=n.getAttribute(`href`)??``;if(!Ft(e))continue;let r=re(Lt(e))||n.textContent?.trim()||`file`,i=At.has(jt(r))?Xt(e,r):Zt(e,r);n.replaceWith(i),t.push(i)}t.length&&Qt(t)}var en=null,tn=`max-w-full cursor-pointer break-words rounded-full border border-indigo-200 bg-indigo-50 px-2.5 py-0.5 text-left text-[12.5px] text-indigo-700 transition-colors hover:border-indigo-300 hover:bg-indigo-100`;function nn(){en=null}function rn(e,t,n){if(en?.remove(),en=null,!t.length)return;let r=c(`div`,`mt-1.5 flex flex-wrap gap-1.5`);for(let e of t){let t=c(`button`,tn,e);t.type=`button`,t.onclick=()=>{en===r&&(en=null),r.remove(),n(e)},r.append(t)}e.append(r),en=r}var an,S;function on(e,t){an=e,S=t}var sn=e=>e.slice(0,8),cn=e=>`system-card group relative mt-1.5 rounded-xl py-2.5 ${e}`,ln=e=>c(`div`,cn(e)),un=`fold-row`,dn=e=>c(`div`,`mt-1 whitespace-pre-wrap break-words text-[12.5px] leading-normal text-neutral-500`,e);function fn(e,t,n){let r=e.textContent??``,i=[],a=0;for(let e of r.matchAll(/\brun ([\w-]+)(…?)/g)){let[o,s=``,l]=e,u=Object.keys(t).find(e=>l?e.startsWith(s):e===s);if(!u)continue;let d=c(`button`,`text-indigo-600 hover:underline`,o);d.setAttribute(`type`,`button`),d.title=`Open run ${u}'s session`,d.onclick=()=>n(t[u]),i.push(r.slice(a,e.index),d),a=e.index+o.length}i.length&&e.replaceChildren(...i,r.slice(a))}function pn(e){let t=c(`div`,`flex ${e.expands?``:`flex-wrap`} items-center gap-x-2 gap-y-1 text-[11px] text-neutral-500`),n=e.expands?mn(t,e.expands,e.open??!1):t;if(n.append(e.glyph,c(`span`,`run-label flex-none font-semibold ${e.labelCls}`,e.label)),e.taskName&&n.append(c(`span`,e.expands?`min-w-0 truncate text-[12.5px] font-medium text-neutral-800`:`min-w-0 grow basis-0 truncate text-[12.5px] font-medium text-neutral-800 max-md:order-1 max-md:basis-full max-md:whitespace-normal max-md:line-clamp-2`,e.taskName)),e.failure){let t=c(`span`,`min-w-0 truncate text-[12.5px] ${e.labelCls}`,e.failure);t.title=e.failure,n.append(t)}n!==t&&t.append(n);let r=c(`div`,`run-meta ml-auto flex min-w-0 flex-wrap items-center gap-x-2 font-mono`);if(e.note&&r.append(c(`span`,`run-note flex-none`,e.note)),e.model){let t=c(`span`,`run-model flex-none rounded bg-black/[0.05] px-1.5 py-px font-medium text-neutral-700 dark:bg-neutral-200`,e.model.id);t.title=`${e.model.provider} / ${e.model.id}`,r.append(t)}if(e.thinking){let t=c(`span`,`run-thinking flex-none`,e.thinking);t.title=`Reasoning effort`,r.append(t)}if(e.runId){let t=c(`span`,`run-id flex-none`,sn(e.runId));t.title=`Run ${e.runId}`,r.append(t)}if(e.sessionId&&e.sessionId!==`console`){let t=e.sessionId,n=c(`button`,`run-session flex-none cursor-pointer text-indigo-600 hover:underline pointer-coarse:min-h-11`,sn(t));n.title=`Open session ${t}`,n.onclick=()=>an.select(t),r.append(n)}return t.append(r),t}function mn(e,t,n){let r=c(`button`,`flex min-w-0 grow cursor-pointer items-center gap-2 rounded-md text-left pointer-coarse:min-h-11`,h());return r.setAttribute(`type`,`button`),r.setAttribute(`aria-expanded`,String(n)),r.classList.toggle(`chev-open`,n),t.hidden=!n,r.onclick=()=>{let n=t.hidden===!0;t.hidden=!n,r.classList.toggle(`chev-open`,n),r.setAttribute(`aria-expanded`,String(n)),e.parentElement?.toggleAttribute(`data-expanded`,n)},r}var hn={queued:{edge:`border-l-amber-400`,label:`text-amber-700`,glyph:We},running:{edge:`border-l-neutral-400`,label:`text-neutral-600`,glyph:We},succeeded:{edge:`border-l-green-500`,label:`text-green-700`,glyph:be},failed:{edge:`border-l-red-500`,label:`text-red-600`,glyph:a},cancelled:{edge:`border-l-neutral-300`,label:`text-neutral-500`,glyph:qe},interrupted:{edge:`border-l-amber-400`,label:`text-amber-700`,glyph:Xe},skipped:{edge:`border-l-neutral-300`,label:`text-neutral-500`,glyph:qe}},gn=e=>y(hn[e].glyph,`h-3 w-3 ${e===`queued`||e===`running`?`spinner`:``} ${hn[e].label}`),_n=new Map,vn=new WeakMap;function yn(e){for(let[e,t]of _n)t.isConnected||_n.delete(e);let t=_n.get(e.runId);t||(t=ln(hn[e.state].edge),t.dataset.kind=`background-run`,S.el.append(t),_n.set(e.runId,t));let n=t.hasAttribute(`data-expanded`);t.className=`${cn(hn[e.state].edge)} ${un} system-row`;let r=e.state===`queued`||e.state===`running`;t.toggleAttribute(`data-active`,r);let i=Math.max(0,Math.round(((e.finishedAt??Date.now())-(e.startedAt??e.queuedAt))/1e3)),a=vn.get(t);!a&&e.prompt!==null&&(a=dn(e.prompt),vn.set(t,a));let o=pn({glyph:gn(e.state),label:`run · ${e.state}`,labelCls:hn[e.state].label,taskName:e.taskName,note:`${e.sessionMode??`task`} · ${String(i)}s${e.queuedMessages>0?` · ${String(e.queuedMessages)} queued`:``}`,runId:e.runId,sessionId:e.targetSessionId,...a?{expands:a,open:n}:{}});t.replaceChildren(o,...a?[a]:[]),S.scroll()}var C=null,w=null,bn=null,xn=!1;function Sn(){if(!w)return;w.text=w.text.slice(-4e3),w.pre.textContent=w.text;let e=(w.text.split(`
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/explorer-BoU77faI.js","assets/highlight-CDSk2hRJ.js","assets/code-CWT27KH1.js","assets/settings-BprIId_R.js"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{$ as e,B as t,C as n,Ct as r,E as i,Et as a,G as o,H as s,J as c,K as l,Ot as u,P as d,Q as f,R as ee,S as p,St as m,T as te,Tt as ne,U as re,V as ie,W as h,X as ae,Y as oe,Z as se,b as ce,c as g,ct as le,d as ue,dt as de,et as fe,f as pe,ft as me,gt as he,h as ge,ht as _e,i as ve,it as ye,jt as be,kt as xe,l as Se,lt as Ce,mt as we,nt as Te,o as Ee,ot as _,pt as De,q as Oe,rt as ke,st as Ae,t as je,tt as v,u as Me,ut as Ne,vt as Pe,w as Fe,wt as y,x as Ie,xt as Le,yt as b}from"./highlight-CDSk2hRJ.js";import{t as Re}from"./hljs-BRz6a8Dq.js";(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var ze=[[`path`,{d:`m12 19-7-7 7-7`}],[`path`,{d:`M19 12H5`}]],Be=[[`path`,{d:`M7 7h10v10`}],[`path`,{d:`M7 17 17 7`}]],Ve=[[`path`,{d:`M20 4v7a4 4 0 0 1-4 4H4`}],[`path`,{d:`m9 10-5 5 5 5`}]],He=[[`path`,{d:`M12 15V3`}],[`path`,{d:`M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4`}],[`path`,{d:`m7 10 5 5 5-5`}]],Ue=[[`path`,{d:`M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0`}],[`circle`,{cx:`12`,cy:`12`,r:`3`}]],We=[[`path`,{d:`M21 12a9 9 0 1 1-6.219-8.56`}]],Ge=[[`path`,{d:`M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z`}]],Ke=[[`path`,{d:`M16 10a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 14.286V4a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z`}],[`path`,{d:`M20 9a2 2 0 0 1 2 2v10.286a.71.71 0 0 1-1.212.502l-2.202-2.202A2 2 0 0 0 17.172 19H10a2 2 0 0 1-2-2v-1`}]],qe=[[`path`,{d:`M5 12h14`}]],Je=[[`rect`,{width:`20`,height:`14`,x:`2`,y:`3`,rx:`2`}],[`line`,{x1:`8`,x2:`16`,y1:`21`,y2:`21`}],[`line`,{x1:`12`,x2:`12`,y1:`17`,y2:`21`}]],Ye=[[`path`,{d:`M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401`}]],Xe=[[`rect`,{x:`14`,y:`3`,width:`5`,height:`18`,rx:`1`}],[`rect`,{x:`5`,y:`3`,width:`5`,height:`18`,rx:`1`}]],Ze=[[`path`,{d:`M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z`}],[`path`,{d:`m15 5 4 4`}]],Qe=[[`path`,{d:`M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8`}],[`path`,{d:`M3 3v5h5`}],[`path`,{d:`M12 7v5l4 2`}]],$e=[[`path`,{d:`M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915`}],[`circle`,{cx:`12`,cy:`12`,r:`3`}]],et=[[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`}],[`line`,{x1:`9`,x2:`15`,y1:`15`,y2:`9`}]],tt=[[`circle`,{cx:`12`,cy:`12`,r:`4`}],[`path`,{d:`M12 2v2`}],[`path`,{d:`M12 20v2`}],[`path`,{d:`m4.93 4.93 1.41 1.41`}],[`path`,{d:`m17.66 17.66 1.41 1.41`}],[`path`,{d:`M2 12h2`}],[`path`,{d:`M20 12h2`}],[`path`,{d:`m6.34 17.66-1.41 1.41`}],[`path`,{d:`m19.07 4.93-1.41 1.41`}]],nt=String.raw`(?<when>(?:\d{4}-\d{2}-\d{2} )?\d{1,2}:\d{2})`,rt=String.raw`lang=(?<lang>[a-z]{2})`,it=new RegExp(String.raw`^\[(?:(?<name>[^\n[\]<>]*)<(?<id>[^\n[\]<>]+)>)? ?${nt}? ?(?<where>[a-z]+:[^\s[\]<>]+)? ?(?:${rt})?\]\n`),at=new RegExp(String.raw`^\[(?<name>[^\n[\]<>]*?) ${nt}(?: (?<where>[a-z]+))?(?: ${rt})?\]\n`);function ot(e){let t=it.exec(e),{id:n,when:r,where:i,lang:a}=t?.groups??{},o=n||r||i||a?t:at.exec(e);return o?.groups?{...o.groups.name?{name:o.groups.name}:{},...o.groups.id?{id:o.groups.id}:{},...o.groups.when?{when:o.groups.when}:{},...o.groups.where?{where:o.groups.where}:{},...o.groups.lang?{lang:o.groups.lang}:{},text:e.slice(o[0].length)}:{text:e}}var st=/(?:\n\[[^\]\n]*(?:\]\(\s*<?file:\/\/[^\n]*|$))+$/,ct=/^\s*`[^`\n]{40,}`\s+(\S[\s\S]*)$/;function lt(e){if(!e)return e;let{text:t}=ot(e);return t===e?e:t.replace(st,``).replace(ct,`$1`).replace(/\s+/g,` `).trim()||e}var ut=e=>[...new Set([...e].sort((e,t)=>t.createdAt-e.createdAt).map(e=>e.cwd))];function dt(e){let t=ut(e),n=new Set(t);return t.filter(e=>{let t=e.lastIndexOf(`/`),r=e.indexOf(`.`,t+2);return r<0||!n.has(e.slice(0,r))})}var ft=t(`#image-dialog`),x=t(`#image-stage`),pt=t(`#image-full`),mt=t(`#image-prev`),ht=t(`#image-next`),gt=t(`#image-close`),_t=[],vt=0;function yt(e){_t.length<2||(vt=(vt+e+_t.length)%_t.length,St(!1),pt.src=_t[vt])}var bt=2.5,xt=()=>x.dataset.zoom!==void 0;function St(e,t){if(!e){delete x.dataset.zoom,pt.style.cssText=``;return}let n=pt.getBoundingClientRect(),r=x.getBoundingClientRect(),i=t?(t.x-n.left)/n.width:.5,a=t?(t.y-n.top)/n.height:.5,o=n.width*bt,s=n.height*bt;x.dataset.zoom=``,pt.style.width=`${String(o)}px`,pt.style.height=`${String(s)}px`,x.scrollLeft=i*o-r.width/2,x.scrollTop=a*s-r.height/2}function Ct(e){let t=e.closest(`[data-gallery]`);_t=t?[...t.querySelectorAll(`img.thumb`)].map(e=>e.src):[e.src],vt=Math.max(0,_t.indexOf(e.src)),pt.src=e.src;let n=_t.length<2?`none`:`flex`;mt.style.display=n,ht.style.display=n,ft.showModal()}var wt=4,Tt,Et=!1;x.onpointerdown=e=>{Et=!1,!(!xt()||e.button!==0)&&(Tt={x:e.clientX,y:e.clientY,left:x.scrollLeft,top:x.scrollTop},x.setPointerCapture(e.pointerId))},x.onpointermove=e=>{if(!Tt)return;let t=e.clientX-Tt.x,n=e.clientY-Tt.y;(Math.abs(t)>wt||Math.abs(n)>wt)&&(Et=!0),x.scrollLeft=Tt.left-t,x.scrollTop=Tt.top-n};var Dt=()=>{Tt=void 0};x.onpointerup=Dt,x.onpointercancel=Dt,x.onclick=e=>{Et||(e.target===pt?St(!xt(),{x:e.clientX,y:e.clientY}):ft.close())},gt.onclick=()=>ft.close(),ft.onclose=()=>St(!1),mt.onclick=()=>yt(-1),ht.onclick=()=>yt(1),ft.onkeydown=e=>{(e.key===`ArrowLeft`||e.key===`ArrowRight`)&&(e.preventDefault(),yt(e.key===`ArrowLeft`?-1:1))};function Ot(e){let t=e.querySelector(`:scope > .thumbs`);if(t)return t;let n=c(`div`,`thumbs`);return e.append(n),n}function kt(e){let t=document.createElement(`img`);return t.src=e,t.loading=`lazy`,t.className=`thumb`,t.onclick=()=>Ct(t),t}var At=new Set([`png`,`jpg`,`jpeg`,`gif`,`webp`,`avif`,`bmp`]),jt=e=>e.split(`.`).pop()?.toLowerCase()??``,Mt=(e,t)=>`/api/sessions/${encodeURIComponent(e)}/files?path=${encodeURIComponent(t)}`,Nt=(e,t,n,r)=>void ve(()=>import(`./explorer-BoU77faI.js`).then(i=>i.openPath({id:e,cwd:t??``},n,r)),__vite__mapDeps([0,1,2]));function Pt(e,t){return m(e,/\]\(\s*<?file:\/\/(\/[^)>\s]*)>?\s*\)/g,e=>{let n=e[1];try{n=decodeURIComponent(n)}catch{}return`](${Mt(t,n)})`})}var Ft=e=>/^\/api\/sessions\/[^/]+\/files\?/.test(e);function It(e,t){let n=re(t)||`file`,r=Mt(e,t);return At.has(jt(n))?Xt(r,n):Zt(r,n)}function Lt(e){return new URLSearchParams(e.slice(e.indexOf(`?`)+1)).get(`path`)??``}var Rt=new Set(`ts.tsx.mts.cts.js.jsx.mjs.cjs.json.md.css.html.py.rs.go.rb.java.c.h.cpp.hpp.sh.sql.yml.yaml.toml.ini.conf.txt.lock`.split(`.`)),zt=/^(?:~|\/(?:home|Users|root|tmp|var|opt|etc|srv|mnt|media|data|usr))(?:\/|$)/;function Bt(e){let t=/^([^\s`"'()[\]{}<>]+?)(?::(\d+))?(?::\d+)?$/.exec(e);if(!t||e.includes(`://`))return null;let n=t[1],r=n.includes(`.`)?jt(n):``;return!zt.test(n)&&(!r||!Rt.has(r)&&!n.includes(`/`))?null:{path:n,line:t[2]===void 0?void 0:Number(t[2])}}var Vt;async function Ht(e,t){let n;if(e.startsWith(`~`)){Vt??=Ee().then(e=>e?.path??null);let r=await Vt;n=r===null?[]:[{path:`${r}${e.slice(1)}`,cwd:t[0]??null}]}else n=e.startsWith(`/`)?[{path:e,cwd:t[0]??null}]:t.map(t=>({path:`${t}/${e}`,cwd:t}));let r=await Promise.all(n.map(e=>Wt(e.path)));return n[r.indexOf(!0)]??null}var Ut=null;function Wt(e){return new Promise(t=>{Ut||(Ut=new Map,setTimeout(()=>void Kt(),0)),Ut.set(e,[...Ut.get(e)??[],t])})}var Gt=1e3;async function Kt(){let e=Ut;Ut=null;let t=[...e.keys()],n=Array.from({length:Math.ceil(t.length/Gt)},(e,n)=>t.slice(n*Gt,(n+1)*Gt)),r=await Promise.all(n.map(e=>ye(`/api/fs/exists`,{paths:e},`Could not check file references`))),i=r.find(e=>!e.ok);i&&!i.ok&&ve(()=>Promise.resolve().then(()=>ei).then(e=>e.report(i.error)),void 0),n.forEach((t,n)=>{let i=r[n];t.forEach((t,n)=>{for(let r of e.get(t)??[])r(i.ok&&i.value.exists[n]===!0)})})}function qt(e,t,n){for(let r of e){let e=Bt(r.textContent?.trim()??``);!e||r.closest(`a`)||Ht(e.path,n).then(n=>{n&&Yt(r,t,n.cwd,n.path,e.line)})}}function Jt(e){let t=e.textContent??``,n=[],r=[],i=0;for(let e of t.matchAll(/`([^`\n]+)`/g)){if(!Bt(e[1].trim()))continue;let a=e.index+1,o=c(`code`,``,e[1]);n.push(t.slice(i,a),o),r.push(o),i=a+e[1].length}return n.length&&e.replaceChildren(...n,t.slice(i)),r}function Yt(e,t,n,r,i){let a=()=>Nt(t,n,r,i);e.classList.add(`fileref`),e.tabIndex=0,e.setAttribute(`role`,`button`),e.title=i===void 0?r:`${r}:${String(i)}`,e.onclick=a,e.addEventListener(`pointerup`,()=>e.blur()),e.onkeydown=e=>{(e.key===`Enter`||e.key===` `)&&(e.preventDefault(),a())}}function Xt(e,t){let n=kt(e);return n.alt=t,n}function Zt(e,t){let n=decodeURIComponent(/^\/api\/sessions\/([^/]+)\//.exec(e)?.[1]??``),r=jt(t),i=c(`span`,`inline-flex max-w-full items-center gap-2.5 rounded-lg border border-neutral-200 bg-neutral-50 px-2.5 py-1.5 no-underline`),a=c(`span`,`flex h-7 w-7 flex-none items-center justify-center rounded-md bg-indigo-50 text-[10px] font-semibold uppercase text-indigo-600`,r.slice(0,4)||`file`),o=c(`span`,`min-w-0 truncate text-[13px] font-medium text-neutral-800`,t),s=c(`span`,`ml-1 flex flex-none items-center gap-0.5`),l=c(`button`,`icon-btn h-6 w-6 text-[13px]`,y(Ue));l.setAttribute(`aria-label`,`Preview`),l.title=`Preview`,l.onclick=t=>{t.preventDefault(),Nt(n,null,Lt(e))},s.append(l);let u=document.createElement(`a`);return u.className=`icon-btn h-6 w-6 text-[13px] no-underline`,u.href=`${e}&download=1`,u.download=t,u.title=`Download`,u.append(y(He)),u.setAttribute(`aria-label`,`Download`),s.append(u),i.append(a,o,s),i}function Qt(e){let t=new Set;for(let n of e)n.parentElement&&t.add(n.parentElement);for(let n of t){let t=[...n.children].filter(t=>e.includes(t));if([...n.childNodes].every(e=>e.nodeType===Node.TEXT_NODE?!e.textContent?.trim():t.includes(e))){n.classList.add(`thumbs`);continue}let r=c(`div`,`thumbs`);r.append(...t),n.after(r)}}function $t(e){let t=[];for(let n of e.querySelectorAll(`img`)){let e=n.getAttribute(`src`)??``;if(!Ft(e))continue;let r=Xt(e,re(Lt(e)));n.replaceWith(r),t.push(r)}for(let n of e.querySelectorAll(`a`)){let e=n.getAttribute(`href`)??``;if(!Ft(e))continue;let r=re(Lt(e))||n.textContent?.trim()||`file`,i=At.has(jt(r))?Xt(e,r):Zt(e,r);n.replaceWith(i),t.push(i)}t.length&&Qt(t)}var en=null,tn=`max-w-full cursor-pointer break-words rounded-full border border-indigo-200 bg-indigo-50 px-2.5 py-0.5 text-left text-[12.5px] text-indigo-700 transition-colors hover:border-indigo-300 hover:bg-indigo-100`;function nn(){en=null}function rn(e,t,n){if(en?.remove(),en=null,!t.length)return;let r=c(`div`,`mt-1.5 flex flex-wrap gap-1.5`);for(let e of t){let t=c(`button`,tn,e);t.type=`button`,t.onclick=()=>{en===r&&(en=null),r.remove(),n(e)},r.append(t)}e.append(r),en=r}var an,S;function on(e,t){an=e,S=t}var sn=e=>e.slice(0,8),cn=e=>`system-card group relative mt-1.5 rounded-xl py-2.5 ${e}`,ln=e=>c(`div`,cn(e)),un=`fold-row`,dn=e=>c(`div`,`mt-1 whitespace-pre-wrap break-words text-[12.5px] leading-normal text-neutral-500`,e);function fn(e,t,n){let r=e.textContent??``,i=[],a=0;for(let e of r.matchAll(/\brun ([\w-]+)(…?)/g)){let[o,s=``,l]=e,u=Object.keys(t).find(e=>l?e.startsWith(s):e===s);if(!u)continue;let d=c(`button`,`text-indigo-600 hover:underline`,o);d.setAttribute(`type`,`button`),d.title=`Open run ${u}'s session`,d.onclick=()=>n(t[u]),i.push(r.slice(a,e.index),d),a=e.index+o.length}i.length&&e.replaceChildren(...i,r.slice(a))}function pn(e){let t=c(`div`,`flex ${e.expands?``:`flex-wrap`} items-center gap-x-2 gap-y-1 text-[11px] text-neutral-500`),n=e.expands?mn(t,e.expands,e.open??!1):t;if(n.append(e.glyph,c(`span`,`run-label flex-none font-semibold ${e.labelCls}`,e.label)),e.taskName&&n.append(c(`span`,e.expands?`min-w-0 truncate text-[12.5px] font-medium text-neutral-800`:`min-w-0 grow basis-0 truncate text-[12.5px] font-medium text-neutral-800 max-md:order-1 max-md:basis-full max-md:whitespace-normal max-md:line-clamp-2`,e.taskName)),e.failure){let t=c(`span`,`min-w-0 truncate text-[12.5px] ${e.labelCls}`,e.failure);t.title=e.failure,n.append(t)}n!==t&&t.append(n);let r=c(`div`,`run-meta ml-auto flex min-w-0 flex-wrap items-center gap-x-2 font-mono`);if(e.note&&r.append(c(`span`,`run-note flex-none`,e.note)),e.model){let t=c(`span`,`run-model flex-none rounded bg-black/[0.05] px-1.5 py-px font-medium text-neutral-700 dark:bg-neutral-200`,e.model.id);t.title=`${e.model.provider} / ${e.model.id}`,r.append(t)}if(e.thinking){let t=c(`span`,`run-thinking flex-none`,e.thinking);t.title=`Reasoning effort`,r.append(t)}if(e.runId){let t=c(`span`,`run-id flex-none`,sn(e.runId));t.title=`Run ${e.runId}`,r.append(t)}if(e.sessionId&&e.sessionId!==`console`){let t=e.sessionId,n=c(`button`,`run-session flex-none cursor-pointer text-indigo-600 hover:underline pointer-coarse:min-h-11`,sn(t));n.title=`Open session ${t}`,n.onclick=()=>an.select(t),r.append(n)}return t.append(r),t}function mn(e,t,n){let r=c(`button`,`flex min-w-0 grow cursor-pointer items-center gap-2 rounded-md text-left pointer-coarse:min-h-11`,h());return r.setAttribute(`type`,`button`),r.setAttribute(`aria-expanded`,String(n)),r.classList.toggle(`chev-open`,n),t.hidden=!n,r.onclick=()=>{let n=t.hidden===!0;t.hidden=!n,r.classList.toggle(`chev-open`,n),r.setAttribute(`aria-expanded`,String(n)),e.parentElement?.toggleAttribute(`data-expanded`,n)},r}var hn={queued:{edge:`border-l-amber-400`,label:`text-amber-700`,glyph:We},running:{edge:`border-l-neutral-400`,label:`text-neutral-600`,glyph:We},succeeded:{edge:`border-l-green-500`,label:`text-green-700`,glyph:be},failed:{edge:`border-l-red-500`,label:`text-red-600`,glyph:a},cancelled:{edge:`border-l-neutral-300`,label:`text-neutral-500`,glyph:qe},interrupted:{edge:`border-l-amber-400`,label:`text-amber-700`,glyph:Xe},skipped:{edge:`border-l-neutral-300`,label:`text-neutral-500`,glyph:qe}},gn=e=>y(hn[e].glyph,`h-3 w-3 ${e===`queued`||e===`running`?`spinner`:``} ${hn[e].label}`),_n=new Map,vn=new WeakMap;function yn(e){for(let[e,t]of _n)t.isConnected||_n.delete(e);let t=_n.get(e.runId);t||(t=ln(hn[e.state].edge),t.dataset.kind=`background-run`,S.el.append(t),_n.set(e.runId,t));let n=t.hasAttribute(`data-expanded`);t.className=`${cn(hn[e.state].edge)} ${un} system-row`;let r=e.state===`queued`||e.state===`running`;t.toggleAttribute(`data-active`,r);let i=Math.max(0,Math.round(((e.finishedAt??Date.now())-(e.startedAt??e.queuedAt))/1e3)),a=vn.get(t);!a&&e.prompt!==null&&(a=dn(e.prompt),vn.set(t,a));let o=pn({glyph:gn(e.state),label:`run · ${e.state}`,labelCls:hn[e.state].label,taskName:e.taskName,note:`${e.sessionMode??`task`} · ${String(i)}s${e.queuedMessages>0?` · ${String(e.queuedMessages)} queued`:``}`,runId:e.runId,sessionId:e.targetSessionId,...a?{expands:a,open:n}:{}});t.replaceChildren(o,...a?[a]:[]),S.scroll()}var C=null,w=null,bn=null,xn=!1;function Sn(){if(!w)return;w.text=w.text.slice(-4e3),w.pre.textContent=w.text;let e=(w.text.split(`
|
|
3
3
|
`).filter(Boolean).pop()??``).replace(/^[\s*_#]+|[\s*_]+$/g,``)||`thinking…`,t=w.summary.lastElementChild;t.textContent=e.length>90?`…`+e.slice(-90):e}function Cn(){if(bn){xn=!0;return}xn=!1,Sn(),bn=setTimeout(()=>{bn=null,xn&&Cn()},80)}function wn(){bn&&clearTimeout(bn),bn=null,xn&&Sn(),xn=!1}var Tn=new WeakMap,En=e=>{let t=Tn.get(e)??[];return Tn.set(e,t),t};function Dn(){C&&!C.toolRows.size&&Vn(`done`)}var On=null;function kn(){C=null,On=null,w=null,wn(),_n.clear()}function An(){let e=On;return!e||C?.el===e||(On=null,e!==S.el.lastElementChild)?null:(e.remove(),e.dataset.adopted=`1`,Mn(e,e.dataset.status),e)}var jn={running:`text-neutral-500 open:bg-black/[0.02] dark:open:bg-neutral-100`,done:`text-neutral-400 hover:text-neutral-600 open:bg-black/[0.02] open:text-neutral-500 dark:open:bg-neutral-100`,failed:`text-red-600 open:bg-red-50`,interrupted:`text-amber-700 open:bg-amber-50`};function Mn(e,t){e.dataset.status=t,e.className=`${un} py-1 rounded-xl text-[11.5px] leading-normal open:ring-1 open:ring-inset open:ring-neutral-200 open:py-2 ${jn[t]}`}var Nn={failed:a,interrupted:Xe};function Pn(e){return e===`running`?y(We,`spinner`):e===`done`?c(`span`,`hidden`):y(Nn[e],`h-3 w-3`)}function Fn(e){if(C)return C;let t=Pn(`running`),n=c(`span`,`min-w-0 truncate`,`working…`),{el:r}=Oe(``,[t,n]);r.dataset.kind=`activity`,Mn(r,`running`);let i=c(`div`,`mt-1.5 flex max-h-64 flex-col gap-1 overflow-y-auto overscroll-contain border-t border-black/5 pt-1.5 dark:border-neutral-200`);return r.append(i),Rn(r,i),S.el.append(r),On=r,S.scroll(),C={el:r,statusIcon:t,headline:n,rowsEl:i,toolRows:new Map,thinking:null,steps:0,failedSteps:0,startTs:e,sawError:!1},C}function In(e,t=``){let n=Fn(e);wn(),n.thinking=null,n.steps+=1;let r=c(`div`,`whitespace-pre-wrap break-words text-[12.5px] text-neutral-600`,t);r.dataset.raw=t;let i=c(`div`,`border-l-2 border-neutral-200 py-0.5 pl-5`,r);return i.dataset.kind=`progress`,n.rowsEl.append(i),Bn(n,`running`,`writing…`),zn(n),S.scroll(),r}function Ln(e){let t=e.closest(`details[data-kind="activity"]`);e.parentElement?.remove(),t&&!t.lastElementChild?.childElementCount&&(C?.el===t&&(C=null),On===t&&(On=null),t.remove())}function Rn(e,t){t.dataset.follow=`1`,t.addEventListener(`scroll`,()=>{let e=t.scrollHeight-t.scrollTop-t.clientHeight<24;t.dataset.follow=e?`1`:``}),e.addEventListener(`toggle`,()=>{e.open&&(t.scrollTop=t.scrollHeight,t.dataset.follow=`1`)})}function zn(e){S.bulk()||!e.el.open||!e.rowsEl.dataset.follow||(e.rowsEl.scrollTop=e.rowsEl.scrollHeight)}function Bn(e,t,n){let r=Math.max(1,Math.round((Date.now()-e.startTs)/1e3)),i=[t===`running`?`working`:t===`done`?`Completed`:t,e.steps?`${e.steps} step${e.steps===1?``:`s`}`:``,`${r}s`,t===`running`?n:``];e.headline.textContent=i.filter(Boolean).join(` · `),Mn(e.el,t);let a=Pn(t);e.statusIcon.replaceWith(a),e.statusIcon=a}function Vn(e){if(!C)return;wn();for(let e of C.toolRows.values())e.el.dataset.state===`running`&&Gn(e,`interrupted`);let t=En(C.el).length,n=t>0&&C.failedSteps===t;Bn(C,(C.sawError||n)&&e===`done`?`failed`:e===`done`&&C.toolRows.size?`interrupted`:e),C=null}function Hn(){C&&(C.sawError=!0)}function Un(e){let t=e.slice(0,400).replace(/\s+/g,` `);return t.length>100?t.slice(0,100)+`…`:t}function Wn(e,t,n,r){let i=Fn(e);i.steps+=1,wn(),i.thinking=null;let a=JSON.stringify(r,null,2)??``,o=c(`span`,`ml-auto flex flex-none`),s=c(`span`,`min-w-0 truncate text-neutral-500`,Un(a)),{el:l}=Oe(`rounded-md px-1 py-0.5 font-mono text-[12.5px] hover:bg-black/[0.03] dark:hover:bg-neutral-100`,[c(`span`,`flex-none font-semibold`,n),s,o]),u=c(`pre`,`max-h-40 overflow-y-auto whitespace-pre-wrap break-words rounded bg-black/[0.04] p-1.5 text-[12px] dark:bg-neutral-100`,a),d=c(`pre`,`hidden max-h-56 overflow-y-auto whitespace-pre-wrap break-words rounded bg-black/[0.04] p-1.5 text-[12px] dark:bg-neutral-100`);l.append(c(`div`,`mt-1 flex flex-col gap-1 pl-4`,u,d)),En(i.el).push({tool:n,call:t,preview:s,argsPre:u,outputPre:d});let f={el:l,statusEl:o,outputPre:d};Gn(f,`running`),i.toolRows.set(t,f),i.rowsEl.append(l),zn(i),Bn(i,`running`,n),S.scroll()}function Gn(e,t){e.el.dataset.state=t,e.statusEl.replaceChildren(gn(t)),e.statusEl.title=t;let n=e.el.firstElementChild;for(let e of[`rounded`,`bg-red-50`,`text-red-700`])n.classList.toggle(e,t===`failed`)}function Kn(e,t,n){let r=C;if(!r)return;let i=r.toolRows.get(e);r.toolRows.delete(e),i&&(Gn(i,t?`failed`:`succeeded`),n&&(i.outputPre.textContent=n.length>8e3?n.slice(0,he)+`…`:n,i.outputPre.classList.remove(`hidden`)),t&&(r.failedSteps+=1)),Bn(r,`running`)}function qn(e,t){let n=Fn(e);if(!n.thinking){wn();let{el:e,summary:t}=Oe(`rounded-md px-1 py-0.5 text-[12.5px] italic text-neutral-500 hover:bg-black/[0.03] dark:hover:bg-neutral-100`,[c(`span`,`min-w-0 truncate`,`thinking…`)]),r=c(`div`,`mt-1 max-h-56 overflow-y-auto whitespace-pre-wrap break-words pl-4 not-italic text-neutral-500`,``);e.append(r),n.rowsEl.append(e),n.steps+=1,n.thinking={pre:r,summary:t,text:``},w=n.thinking,zn(n),Bn(n,`running`,`thinking…`)}n.thinking.text+=t,Cn()}var Jn=0;function Yn(e,t=0,n=!1,r){let i=Date.now()-t,a=Fn(i).el;for(let t of e){if(t.kind===`progress`){In(i,t.text??``);continue}if(t.kind===`thinking`){qn(i,t.text??``);continue}let e=t.id??`replay-${++Jn}`;Wn(i,e,t.toolName??``,t.args),t.done&&Kn(e,t.isError??!1,t.output??``)}r!==void 0&&e.some(e=>e.kind===`tool`&&e.args===void 0)&&Xn(a,r),!n&&Vn(e.some(e=>e.kind===`tool`&&!e.done)?`interrupted`:`done`)}function Xn(e,t){let n=()=>{e.open&&(e.removeEventListener(`toggle`,n),Zn(e,t))};e.addEventListener(`toggle`,n)}async function Zn(e,t){let n=an.sessionId(),r=En(e),i=new Set(r.filter(e=>!e.argsPre.textContent)),a=e=>{for(let t of i)t.argsPre.textContent=e};if(a(`loading…`),!n)return a(`no session`);let o=await Te(`/api/sessions/${n}/turns/${t}/steps`,`could not load these steps`);if(!o.ok)return a(o.error);let s=o.value.steps.filter(e=>e.kind===`tool`);for(let[e,t]of r.entries()){if(!i.has(t))continue;let n=s[e];if(!(n&&(n.id?n.id===t.call:n.toolName===t.tool))){t.argsPre.textContent=`detail no longer available — reload the session`;continue}let r=JSON.stringify(n.args,null,2)??``;t.argsPre.textContent=r,t.preview.textContent=Un(r),n.output&&(t.outputPre.textContent=n.output,t.outputPre.classList.remove(`hidden`))}}var T,E=t(`#turns`);function Qn(e){T=e,on(e,{el:E,scroll:O,bulk:()=>D})}var D=!1,$n=()=>E.scrollHeight-E.scrollTop-E.clientHeight<80,er=!0,tr=0;E.addEventListener(`scroll`,()=>{let e=E.scrollTop,t=e<tr-4;tr=e,!D&&(t||$n())&&(er=$n())},{passive:!0});var nr=0;function rr(){!er||D||nr||(nr=requestAnimationFrame(()=>{nr=0,er&&!D&&(E.scrollTop=E.scrollHeight)}))}new ResizeObserver(rr).observe(E),E.addEventListener(`load`,rr,!0),new MutationObserver(rr).observe(E,{childList:!0,subtree:!0,characterData:!0});function ir(){$n()&&(er=!0)}function O(e=!1){D||(e&&(er=!0),er&&(E.scrollTop=E.scrollHeight))}var ar=1200;function or(e,t){let n=E.querySelector(`[data-kind="${e}"][data-at="${t}"]`);return n?(sr(n),!0):!1}function sr(e){er=!1,e.scrollIntoView({block:e.offsetHeight>E.clientHeight?`start`:`center`}),e.dataset.reveal=``,setTimeout(()=>delete e.dataset.reveal,ar)}var cr=500,lr=0,ur=0,dr=[],k=null,fr=!1;function pr(){if(!E.querySelector(`[data-readonly]`)){for(;E.childElementCount>cr;){let e=E.firstElementChild;e.remove(),e!==k&&(e.dataset.kind===`user`&&lr++,ur++)}ur&&(k||(k=c(`div`,`px-5 py-2 text-center text-[11.5px] italic text-neutral-400`),k.dataset.kind=`trim`),k.textContent=`${ur} earlier row${ur===1?``:`s`} not shown — still in the transcript, not on this screen`,E.firstElementChild!==k&&E.prepend(k))}}var mr={user:{row:``,body:`text-inherit`},assistant:{row:``,body:`text-neutral-900`},error:{row:`border-l-red-400 bg-red-50`,body:`text-red-700`},system:{row:`system-card border-l-cyan-500`,body:`text-neutral-500`}};function A(e,t,n=!1,i){Dn();let a=e===`assistant`?An():null,o=mr[e],s=e===`user`&&i!==void 0&&Ar(i)?i:void 0,l=s===void 0&&E.lastElementChild?.dataset.kind===e,u=c(`div`,`group relative ${o.row}`);u.dataset.kind=e,fr&&(u.dataset.readonly=``),l&&(u.dataset.grouped=``),D||(u.dataset.enter=``);let d=e===`user`?r(t):null,ee=d?.text??t,p=e===`user`?ot(ee):null,m=p?.id||p?.when||p?.where||p?.lang?p:null,te=m&&(m.id?m.id!==`web`:m.name)?m:null,ne=c(`div`,`whitespace-pre-wrap break-words ${o.body}`,m?.text??ee);(d?.paths.length||m)&&(ne.dataset.raw=t),n&&Nr(ne,t),i!==void 0&&jr(u,i),te&&u.append(hr(te)),u.append(ne);let re=T.sessionId();if(d?.paths.length&&re){let e=Ot(u);for(let t of d.paths)e.append(It(re,t))}if(e===`user`&&!fr){yr?.();let e=c(`button`,`message-edit absolute right-full top-1 flex h-8 w-8 items-center justify-center rounded-full`);e.title=`Edit message — resends it and drops everything after it`,e.setAttribute(`type`,`button`),e.setAttribute(`aria-label`,`Edit message`),e.append(y(Ze)),e.onclick=()=>Sr(u,ne),u.append(e)}if(s!==void 0){let e=c(`div`,`my-3 text-center text-[11px] text-neutral-400`);e.dataset.kind=`time`,e.dataset.at=String(s),Dr(e),Er??=setInterval(Or,6e4),e.title=f(s),E.append(e)}return a&&E.append(a),E.append(u),pr(),O(),ne}function hr(e){let t=c(`div`,`mb-1 flex flex-wrap items-baseline gap-x-2 gap-y-1 text-[11.5px] leading-tight opacity-85`),n=e?.name??e?.id;if(n){let r=c(`span`,`font-semibold text-inherit`,n);e?.id&&(r.title=e.id),t.append(r)}let r=T.sessionChannel();return r&&r!==`web`&&t.append(c(`span`,`text-[10px] uppercase tracking-wide opacity-60`,r)),t}var gr={"task-delegation":[Be,`delegation`,`text-cyan-700`],"task-callback":[Ve,`callback`,`text-cyan-700`],"session-seed":[Qe,`session seed`,`text-cyan-700`],"chat-command":[et,`command`,`text-cyan-700`]};function _r(e){let t=e.indexOf(`
|
|
4
4
|
|
|
5
5
|
`);if(t<0)return[null,e];let n=e.slice(0,t);return n.length>600||n.split(`
|
|
@@ -11,4 +11,4 @@ import{$ as e,B as t,C as n,Ct as r,E as i,Et as a,G as o,H as s,J as c,K as l,O
|
|
|
11
11
|
`);o&&(N.value=i,ba(),n===ga&&M.chatVisible()&&document.activeElement===r&&N.focus()),I(e,i)}catch(t){A(`error`,`Could not save recalled messages for session ${e}: ${String(t)}\nRecalled messages (not saved):\n${a.join(`
|
|
12
12
|
`)}`)}o&&t===Ri&&Zi([],[])}finally{Vi.delete(e)}}function Ta(e){M=e,_a(),Ui(),Wi();let n=()=>{let e=M.sessionId();e&&fetch(`/api/sessions/${e}/abort`,{method:`POST`})};ki.onclick=n,xi(ki,`Stop the running turn`,n,()=>M.sessionState()===`streaming`&&M.chatVisible()),t(`#queue-steer`).onclick=()=>void Ca(`steer`),t(`#queue-restart`).onclick=()=>void Ca(`restart`),t(`#queue-recall`).onclick=()=>void wa(),Ti.onsubmit=e=>{e.preventDefault(),Sa(`auto`)},Ci(N,[`/`],`Write a message`,Gi,M.chatVisible),N.onfocus=ir,N.oninput=()=>{ba(),I(),oa=!1,fa()};let r=!matchMedia(`(pointer: coarse)`).matches;N.onkeydown=e=>{e.isComposing||e.keyCode===229||pa(e)||r&&e.key===`Enter`&&!e.shiftKey&&(e.preventDefault(),Sa(`auto`))},N.onpaste=e=>{for(let t of e.clipboardData?.items??[]){let e=t.kind===`file`?t.getAsFile():null;e&&ta(e)}let t=e.clipboardData?.getData(`text/plain`)??``,n=t.trim();!n||n===t||(e.preventDefault(),N.setRangeText(n,N.selectionStart??0,N.selectionEnd??0,`end`),ba(),I())},E.ondragover=e=>e.preventDefault(),E.ondrop=e=>{e.preventDefault();for(let t of e.dataTransfer?.files??[])ta(t)},t(`#attach`).onclick=()=>Ii.click(),Ii.onchange=()=>{for(let e of Ii.files??[])ta(e);Ii.value=``},Yi()}var Ea=`pier.push`,Da=`/app/sw.js`,Oa=()=>/iPad|iPhone|iPod/.test(navigator.userAgent)||navigator.maxTouchPoints>1&&/Macintosh/.test(navigator.userAgent),ka=()=>matchMedia(`(display-mode: standalone)`).matches||navigator.standalone===!0;function Aa(){return window.isSecureContext?Oa()&&!ka()?`On iPhone and iPad, notifications work only from the installed app: Share → Add to Home Screen, then open Pier from that icon.`:!(`serviceWorker`in navigator)||!(`PushManager`in window)||!(`Notification`in window)?`This browser has no Web Push support.`:``:`Notifications need HTTPS. Reach this Pier through its public URL, not over plain http.`}var ja=[[/iPhone/,`iPhone`],[/iPad/,`iPad`],[/Android/,`Android`],[/Macintosh/,`Mac`],[/Windows/,`Windows`]],Ma=[[/Edg\//,`Edge`],[/Chrome\//,`Chrome`],[/Firefox\//,`Firefox`],[/Safari\//,`Safari`]];function Na(){let e=navigator.userAgent,t=(t,n)=>t.find(([t])=>t.test(e))?.[1]??n;return`${t(ja,`Linux`)} · ${t(Ma,`browser`)}${ka()?` (installed)`:``}`}var Pa=e=>{let t=atob(e.replace(/-/g,`+`).replace(/_/g,`/`)),n=new Uint8Array(t.length);for(let e=0;e<t.length;e++)n[e]=t.charCodeAt(e);return n},Fa=null;async function Ia(){return!(`serviceWorker`in navigator)||!window.isSecureContext?null:(Fa??=await navigator.serviceWorker.register(Da,{scope:`/app/`}).catch(e=>(console.warn(`service worker registration failed`,e),null)),Fa)}var La=(e,t)=>{let n=e?new Uint8Array(e):null;return n?.length===t.length&&n.every((e,n)=>e===t[n])};async function Ra(e){let{publicKey:t}=await ke(`/api/push`,`Could not read this instance's push key`),n=Pa(t),r=await e.pushManager.getSubscription();if(r){if(La(r.options.applicationServerKey,n))return r;await r.unsubscribe()}return e.pushManager.subscribe({userVisibleOnly:!0,applicationServerKey:n})}async function za(e){return _(`/api/push/subscribe`,{...e.toJSON(),label:Na()})}async function Ba(){Ua();let e=await Ia();if(!(!e||localStorage.getItem(Ea)!==`on`)&&!(!(`Notification`in window)||Notification.permission!==`granted`))try{await za(await Ra(e))}catch(e){console.warn(`re-registering this browser for notifications failed`,e)}}var Va=null,Ha=null;function Ua(){window.addEventListener(`beforeinstallprompt`,e=>{e.preventDefault(),Va=e,Ha?.()}),window.addEventListener(`appinstalled`,()=>{Va=null,Ha?.()})}function Wa(e){let t=navigator;(e>0?t.setAppBadge?.(e):t.clearAppBadge?.())?.catch(()=>{})}function Ga(){let e=c(`span`,`text-[11.5px]`,``),t=p(`Send a test notification`),r=c(`div`,`flex items-center gap-3`,t,e),i=c(`div`,`flex flex-col gap-4`),a=()=>localStorage.getItem(Ea)===`on`,o=c(`div`,`flex flex-col gap-2`),l=c(`span`,`text-[11.5px]`,``),u=c(`div`,`flex flex-col gap-2`,o,l);async function f(e){d(l,`saving`,`removing…`);try{let t=await _(`/api/push/unsubscribe`,{endpoint:e.endpoint});if(!t.ok)d(l,`failed`,await v(t,`Could not remove it`));else{let t=await(await Ia())?.pushManager.getSubscription();t?.endpoint===e.endpoint&&(localStorage.setItem(Ea,`off`),await t.unsubscribe(),h()),d(l,`saved`,`Removed.`)}}catch(e){d(l,`failed`,`Could not remove it: ${String(e)}`)}await m()}async function m(){let e=await Te(`/api/push/subscriptions`,`Could not load subscribed devices`);if(!e.ok)return d(l,`failed`,e.error);if(!e.value.devices.length){o.replaceChildren(te(`No device is subscribed.`));return}o.replaceChildren(...e.value.devices.map(e=>{let t=p(`Remove`);return t.onclick=()=>{t.disabled=!0,f(e)},Fe(e.label,`subscribed ${s(e.createdAt)}`,t,{tag:e.current?ce(`This browser`,`bg-neutral-50 text-neutral-500 ring-neutral-200`):void 0})}))}async function ne(){d(e,`saving`,`asking this browser…`);let t=await Notification.requestPermission();if(t!==`granted`)return localStorage.setItem(Ea,`off`),h(),d(e,`failed`,t===`denied`?`Notifications are blocked for this site — allow them in the browser's site settings, then try again.`:`No answer to the permission prompt.`);let n=await Ia();if(!n)return d(e,`failed`,`This browser refused to register a service worker.`);try{let t=await za(await Ra(n));if(!t.ok)return d(e,`failed`,await v(t,`Could not register this browser`));localStorage.setItem(Ea,`on`),h(),d(e,`saved`,`This browser will be notified when a turn finishes unseen.`),m()}catch(t){d(e,`failed`,`Could not subscribe: ${String(t)}`)}}async function re(){localStorage.setItem(Ea,`off`),h();let t=await(await Ia())?.pushManager.getSubscription();t&&(await _(`/api/push/unsubscribe`,{endpoint:t.endpoint}),await t.unsubscribe()),d(e,`idle`,`This browser will not be notified.`),m()}t.onclick=()=>{d(e,`saving`,`sending…`),(async()=>{let t=await _(`/api/push/test`,{});if(!t.ok)return d(e,`failed`,await v(t,`Could not send`));let{sent:n,failed:r}=await t.json();d(e,r?`failed`:`saved`,`Handed ${String(n)} device(s) to their push service${r?`, ${String(r)} refused`:``}.`)})()};function ie(){if(!Va)return[];let e=p(`Install Pier`,!0);return e.onclick=()=>{let e=Va;e&&e.prompt().then(()=>e.userChoice).finally(()=>{Va=null,h()})},[c(`div`,`flex items-center gap-3`,e,c(`span`,`text-[11.5px] leading-snug text-neutral-500`,`Its own window and icon — and where notifications look like an app's.`))]}function h(){let e=Aa();if(e){i.replaceChildren(...ie(),c(`p`,`text-[12.5px] leading-snug text-neutral-500`,e),u);return}let n=a()&&Notification.permission===`granted`;t.disabled=!n,i.replaceChildren(...ie(),ee(`Notify this device`,`A turn that finishes while nobody is looking at it becomes a notification here. Per browser — each device is enabled on its own.`,n,e=>void(e?ne():re())),r,u)}return Ha=h,h(),{el:n(`Notifications`,`Web Push, so a finished turn reaches you with the workbench closed. Installed — Chrome's address-bar icon, or Share → Add to Home Screen on iOS — Pier notifies you the way an app does.`,i),load:()=>{d(l,`idle`,``),m()}}}var L,R=t(`#status-chip`),Ka=e=>e.modified??e.createdAt,qa=e=>e.unread,Ja=e=>e.state===`streaming`||qa(e)||e.activeRuns>0||e.runLive===!0||e.designOpen===!0;function Ya(e){return e.state===`streaming`?`working`:qa(e)?`unread`:e.activeRuns>0?`runs`:e.runLive?`queued`:e.designOpen?`design`:null}var Xa=e=>e===`unread`||e===`design`;function Za(e){let t=Ya(e);return t?$a(t===`working`?Qa:t===`unread`?[`bg-amber-500`,`turn finished — not viewed yet`]:t===`runs`?[`bg-sky-500`,`${e.activeRuns} subagent${e.activeRuns>1?`s`:``} running`]:[`bg-neutral-400`,t===`queued`?`lead — run queued`:`design — waiting for you to finalize`]):[]}var Qa=[`bg-green-500 animate-pulse`,`working…`];function $a([e,t]){let n=c(`span`,`h-2 w-2 flex-none rounded-full ${e}`);return n.title=t,[n]}var eo=e=>e.phase?to(e.phase,e.phase===`design`?`lead — designing with you`:`lead — building per the design`):[],to=(e,t)=>{let n=c(`span`,`flex-none rounded bg-neutral-100 px-1 text-[0.6875rem] font-medium leading-4 text-neutral-500`,e);return n.title=t,[n]};function no(e,t){let n=new Set(t.map(e=>e.sessionId));return e.filter(e=>Ja(e)&&!n.has(e.id))}var ro=()=>{let e=L.chain()[0]?.sessionId;return L.sessions().find(t=>t.id===e)},io=`flex items-center gap-1 rounded-[10px] px-1.5 hover:bg-neutral-100`,ao=`session-open flex min-h-10 min-w-0 flex-1 cursor-pointer items-center gap-1.5 text-left`,oo={"waiting on you":`bg-amber-50 text-amber-700`,running:`bg-green-50 text-green-700`,queued:`bg-neutral-100 text-neutral-600`,"pending release":`bg-neutral-100 text-neutral-600`};function so(e){let t=c(`li`,io),n=c(`span`,`min-w-0 flex-1 py-1`,c(`span`,`flex min-w-0 items-center gap-1.5`,c(`span`,`min-w-0 truncate`,e.label),...e.who?to(e.who,e.who):[]),c(`span`,`block truncate text-xs leading-4 text-neutral-500`,e.detail)),r=c(`span`,`flex-none rounded px-1.5 text-[0.6875rem] font-medium leading-5 ${oo[e.status]}`,e.status),i=c(`button`,ao,n,r);return i.setAttribute(`type`,`button`),i.onclick=()=>{g(),e.open()},e.id===L.currentId()&&i.setAttribute(`aria-current`,`page`),t.dataset.sessionId=e.id,t.title=e.title,t.append(i),t}var co=e=>e?.phase?`lead · ${e.phase}`:e?.channel&&e.channel!==`web`?e.channel:``,lo={working:[`running`,()=>`working`],unread:[`waiting on you`,()=>`turn finished — not viewed yet`],runs:[`running`,e=>`${e.activeRuns} subagent${e.activeRuns>1?`s`:``} running`],queued:[`queued`,()=>`run queued`],design:[`waiting on you`,()=>`design — finalize when it is ready`]};function uo(e,t){let[n,r]=lo[t];return{id:e.id,label:e.title??`untitled`,who:co(e),status:n,detail:`${r(e)} · active ${s(Ka(e))}`,title:[e.cwd,`created ${new Date(e.createdAt).toLocaleDateString()}`,...e.channel&&e.channel!==`web`?[`answering ${e.channel}`]:[]].join(`
|
|
13
13
|
`),open:()=>L.select(e.id)}}function fo(e,t){let n=[...e.runs.map(e=>Ce(e,t)),e.stage].filter(Boolean).join(` · `),r=e.runs.find(e=>e.targetSessionId),i=r?.targetSessionId??void 0,a=r?co(L.sessions().find(e=>e.id===i))||(r.workers?`lead`:`worker`):``;return{id:i??`item:${e.problem}`,label:e.problem,who:a,detail:n,status:e.status,title:[e.problem,n,...e.runs.flatMap(e=>e.cwd?[e.cwd]:[])].filter(Boolean).join(`
|
|
14
|
-
`),open:()=>i?L.select(i):L.openContinuous()}}var po=(e,t)=>({...fo({problem:e.name,stage:``,runs:[e],status:`running`},t),...e.state===`queued`?{status:`queued`}:{}});function mo(e){let t=L.open()??{items:[],unlisted:[]},n=new Set([...t.items.flatMap(e=>e.runs),...t.unlisted].flatMap(e=>e.targetSessionId?[e.targetSessionId]:[])),r=no(L.sessions(),L.chain()),i=[...t.items.map(t=>fo(t,e)),...t.unlisted.map(t=>po(t,e)),...r.flatMap(e=>{let t=Ya(e);return t&&!n.has(e.id)?[uo(e,t)]:[]})],a=e=>e.status===`waiting on you`||e.status===`pending release`;return{waiting:i.filter(a).map(so),running:i.filter(e=>!a(e)).map(so),sessions:r}}var ho=null,go=[[],[]],_o=!1,vo=()=>`${L.currentId()??``}\n${JSON.stringify(L.chain())}\n${JSON.stringify(L.sessions())}\n${JSON.stringify(L.open())}`,yo=``;function z(){let e=vo();if(e===yo)return;yo=e;let{waiting:t,running:n,sessions:r}=mo(Date.now());go=[t,n],Wa(r.filter(e=>Xa(Ya(e))).length+ +!!ro()?.unread);let i=[...n.length?[`${n.length} running`]:[],...t.length?[`${t.length} needs you`]:[]].join(` · `);_o=!!i,R.textContent=i,R.classList.toggle(`hidden`,!i),R.classList.toggle(`block`,!!i),R.classList.toggle(`text-amber-700`,t.length>0),R.classList.toggle(`text-neutral-600`,t.length===0),ho?.[0].isConnected&&!ho[0].closest(`[inert]`)&&(_o?bo(ho):g()),Xo()}function bo(e){let t=document.activeElement?.closest(`[data-session-id]`)?.dataset.sessionId;e.forEach((e,t)=>{e.replaceChildren(...go[t]),e.previousElementSibling?.classList.toggle(`hidden`,!go[t].length)}),e[1].previousElementSibling?.classList.toggle(`mt-2`,go[0].length>0),t&&go.flat().find(e=>e.dataset.sessionId===t)?.querySelector(`.session-open`)?.focus({preventScroll:!0})}var xo=`px-2 pb-1 text-xs font-semibold leading-5 text-neutral-500`;function So(){if(R.getAttribute(`aria-expanded`)===`true`)return g();if(!_o)return;let[e,t]=[c(`ul`,``),c(`ul`,``)];e.dataset.list=`waiting`,t.dataset.list=`running`;let n=c(`div`,`w-[min(32rem,calc(100vw-2rem))] max-sm:w-full font-sans text-sm`,c(`div`,xo,`Waiting on you`),e,c(`div`,xo,`In progress`),t);ho=[e,t],bo(ho),pe(R,n).setAttribute(`aria-label`,`Status`)}function Co(e){L=e,R.onclick=So,wi(`shift+p`,So,vi)}var wo,B=t(`#palette`),To=t(`#palette-input`),Eo=t(`#palette-list`),Do=t(`#palette-count`),Oo=[{name:`settings`,icon:$e,label:`Settings`,detail:`Console — models and providers, agent files and extensions, channels, password, sign out, security`}],ko=7,Ao=8,jo=80,Mo=``,No,Po,Fo;function Io(e){Mo!==e&&(clearTimeout(Fo),Po?.abort(),Po=void 0,Mo=e,No=void 0,e&&(Fo=setTimeout(()=>{let t=Po=new AbortController;Te(`/api/search?q=${encodeURIComponent(e)}`,`Search unavailable`,{signal:t.signal}).then(n=>{t.signal.aborted||Mo!==e||(Po=void 0,No=n.ok?{hits:n.value.hits}:{error:n.error},B.open&&Yo())})},jo)))}var V=[],H=0;function Lo(e){if(V.length){H=(e+V.length)%V.length;for(let[e,{el:t}]of V.entries())t.classList.toggle(`bg-indigo-50`,e===H),t.setAttribute(`aria-selected`,String(e===H));V[H]?.el.scrollIntoView({block:`nearest`})}}var Ro=e=>e.hit?.at??e.session?.createdAt;function zo(e){let t=c(`span`,`min-w-0 flex-1 truncate text-neutral-500`);for(let n of e.replaceAll(/\s+/g,` `).split(``)){let[e=``,r]=n.split(``,2);r===void 0?t.append(e):t.append(c(`span`,`font-medium text-neutral-800`,e),r)}return t}var Bo=`flex min-w-0 flex-1 items-baseline gap-2`,Vo=`shrink-0 truncate`,Ho=`min-w-[2.5em] truncate text-[0.8125rem] text-neutral-400`,Uo=`flex-none text-[0.75rem] tabular-nums text-neutral-400`,Wo=`flex h-7 w-7 flex-none items-center justify-center rounded-[8px] bg-neutral-100 text-neutral-500`;function Go(e){let t=c(`li`,`palette-row flex cursor-pointer items-center gap-3 rounded-[10px] px-2 leading-5 ${e.hit?`py-1.5`:`min-h-10`}`);t.setAttribute(`role`,`option`),t.append(c(`span`,Wo,y(e.icon,`h-4 w-4`)));let n=c(`div`,`flex min-w-0 flex-1 flex-col`),r=c(`div`,`flex items-center gap-2`);e.session&&r.append(...Za(e.session));let i=c(`span`,Bo,c(`span`,`${Vo} ${e.detail?`max-w-[calc(100%-3em)]`:`max-w-full`}`,e.label));e.detail&&i.append(c(`span`,Ho,e.detail)),r.append(i);let a=Ro(e);return e.session&&r.append(...eo(e.session)),a!==void 0&&r.append(c(`span`,Uo,se(a))),n.append(r),e.hit&&n.append(c(`div`,`flex items-baseline gap-2 text-[0.8125rem] leading-5`,c(`span`,`flex-none text-[0.75rem] text-neutral-400`,e.hit.role===`user`?`You`:`Agent`),zo(e.hit.snippet))),t.append(n),t.onclick=e.open,t}var Ko=e=>c(`li`,`px-2 pb-1.5 pt-4 text-[0.6875rem] font-semibold leading-4 tracking-[0.02em] text-neutral-400 first:pt-2`,e);function qo(e,t){let n=c(`li`,`px-2 py-2 pl-12 text-[0.8125rem] leading-5 text-neutral-400`,e);return t&&(n.title=t),n}var Jo=e=>e.channel&&e.channel!==`web`?e.channel:``;function Yo(){let t=To.value.trim(),n=t.toLowerCase().split(/\s+/).filter(Boolean),r=e=>{let t=e.toLowerCase();return n.every(e=>t.includes(e))},i=e=>()=>{B.close(),e()},a=wo.sessions(),o=new Map(a.map(e=>[e.id,e])),s=t=>({icon:Ge,label:t.title??e(t.cwd),detail:[re(t.cwd),Jo(t)].filter(Boolean).join(` · `),open:i(()=>void wo.select(t.id)),session:t}),c=ro(),l=!t||r(`pier conversation`)?[{icon:Ke,label:`Pier`,detail:``,open:i(wo.openContinuous),...c?{session:c}:{}}]:[],u=Oo.filter(e=>!t||r(`${e.label} ${e.detail}`)).map(({name:e,icon:t,label:n,detail:r})=>({icon:t,label:n,detail:r,open:i(()=>wo.openConsole(e))})),d=[[``,l]];if(!t)d.push([`Recent`,a.filter(e=>!Ja(e)&&e.id!==c?.id).slice(0,ko).map(s)],[`Actions`,u]);else{let e=a.filter(e=>r(`${e.title??``} ${e.cwd} ${Jo(e)}`)).slice(0,Ao),n=new Set(e.map(e=>e.id)),c=e.map(s);if(Mo!==t||!No)c.push(qo(`Searching messages…`));else if(`error`in No)c.push(qo(`Message search unavailable`,No.error));else{for(let e of No.hits){if(c.length>=Ao)break;let t=o.get(e.sessionId);!t||n.has(t.id)||c.push({...s(t),hit:e,open:i(()=>void wo.select(t.id).then(()=>or(e.role,e.at)))})}c.length||c.push(qo(`No sessions match`))}d.push([`Actions`,u],[`Sessions`,c])}V=[];let f=[];for(let[e,t]of d)if(t.length){e&&f.push(Ko(e));for(let e of t){if(e instanceof HTMLElement){f.push(e);continue}let t=Go(e);V.push({el:t,open:e.open}),f.push(t)}}Eo.replaceChildren(...f.length?f:[qo(`Nothing matches`)]),Do.textContent=`${V.length} ${V.length===1?`row`:`rows`}`,Lo(Math.min(H,Math.max(0,V.length-1)))}function Xo(){B.open&&Yo()}function Zo(){if(B.open)return B.close();To.value=``,H=0,Io(``),Yo(),B.showModal(),To.focus(),wo.loadSessions().then(Xo)}function Qo(e){wo=e,wi(`k`,Zo,()=>B.open||Me()),B.onclick=e=>{e.target===B&&B.close()},B.onclose=()=>Io(``),To.oninput=()=>{H=0,Io(To.value.trim()),Yo()},To.onkeydown=e=>{let t=Se(e);if(t!==void 0){e.preventDefault(),Lo(H+t);return}e.key===`Enter`&&!e.ctrlKey&&(e.preventDefault(),V[H]?.open())}}var $o=0,es=null;async function ts(){let{modelMenu:e}=await ke(`/api/settings`,`Could not read the pinned model menu`);return e}function ns(e){let t=c(`button`,`flex w-full min-w-0 cursor-pointer items-center gap-2 px-3 py-1.5 text-left hover:bg-neutral-100`,y(be,`h-3 w-3 text-indigo-600 ${e.checked?``:`invisible`}`),c(`span`,`truncate`,e.label));return e.hint&&t.append(c(`span`,`ml-auto flex-none text-[11.5px] text-neutral-400`,e.hint)),t.onclick=()=>e.onSelect(),t}function rs({models:e,current:t,thinkingLevel:n,thinkingLevels:r,onPick:i,onThinkingPick:a}){let o=n,s=c(`div`,`flex w-full min-w-0 flex-col sm:min-w-72`),l=c(`div`,`flex flex-col gap-2 border-b border-neutral-200 px-2 py-2`),d=document.createElement(`input`);if(d.type=`search`,d.placeholder=`Search models`,d.setAttribute(`aria-label`,`Search models`),d.className=`w-full rounded-md border border-neutral-300 px-2 py-1.5 text-[12.5px] focus:border-indigo-400 focus:outline-none`,l.append(d),r.length){let e=document.createElement(`details`),t=c(`span`,`ml-auto font-medium text-indigo-700`,we(o)),n=c(`summary`,`flex min-h-11 cursor-pointer list-none items-center gap-2 rounded-xl px-3 text-sm text-neutral-700 hover:bg-neutral-100 [&::-webkit-details-marker]:hidden`,c(`span`,`font-medium`,`Reasoning effort`),t,y(u,`chev h-3 w-3 text-neutral-400`)),i=c(`fieldset`,`grid grid-cols-2 gap-1 rounded-xl bg-neutral-50 p-1`);i.append(c(`legend`,`sr-only`,`Reasoning effort`));let s=`reasoning-${++$o}`;for(let e of r){let n=document.createElement(`input`);n.type=`radio`,n.name=s,n.value=e,n.checked=e===o,n.className=`peer sr-only`,n.onchange=()=>{n.checked&&(o=e,t.textContent=we(o),m(d.value),a(o))},i.append(c(`label`,`relative cursor-pointer`,n,c(`span`,`flex min-h-11 items-center rounded-lg border border-transparent px-3 text-sm text-neutral-700 hover:bg-neutral-100 peer-checked:border-indigo-200 peer-checked:bg-indigo-50 peer-checked:font-semibold peer-checked:text-indigo-700 peer-focus-visible:outline-2 peer-focus-visible:outline-indigo-500`,we(e))))}e.append(n,i),l.append(e)}let f=c(`div`,`max-h-72 overflow-y-auto py-1`),ee=new Map(e.map(e=>[b(e),e])),p=e=>{let n=(es??[]).map(e=>({e,model:ee.get(b(e))})).filter(t=>!!t.model&&(!e||b(t.model).toLowerCase().includes(e)));n.length&&f.append(c(`div`,`px-3 pb-0.5 pt-1 text-[10.5px] font-semibold uppercase tracking-wide text-neutral-400`,`Pinned`),...n.map(({e,model:n})=>ns({label:n.id,hint:we(e.thinking),checked:!!t&&b(t)===b(n)&&o===e.thinking,onSelect:()=>i(n,e.thinking)})),c(`div`,`my-1 border-t border-neutral-100`))},m=n=>{f.replaceChildren();let r=n.trim().toLowerCase();p(r);let a=new Map;for(let t of e){if(r&&!b(t).toLowerCase().includes(r))continue;let e=a.get(t.provider);e?e.push(t):a.set(t.provider,[t])}if(!a.size){f.append(c(`div`,`px-3 py-2 text-[12.5px] text-neutral-400`,e.length?`No matching models.`:`No models available.`));return}for(let[e,n]of a){let a=n.some(e=>!!t&&b(t)===b(e)),o=document.createElement(`details`);o.open=a||r.length>0;let s=c(`summary`,`flex cursor-pointer select-none items-center gap-1.5 px-3 py-1 text-[10.5px] font-semibold uppercase tracking-wide text-neutral-400 hover:bg-neutral-100`,y(u,`chev h-3 w-3`),c(`span`,`truncate`,e),c(`span`,`ml-auto flex-none normal-case text-neutral-300`,String(n.length)));o.append(s,...n.map(e=>ns({label:e.id,checked:!!t&&b(t)===b(e),onSelect:()=>i(e)}))),f.append(o)}};return d.oninput=()=>m(d.value),m(``),ts().then(e=>{let t=JSON.stringify(e)!==JSON.stringify(es);es=e,t&&m(d.value)}).catch(e=>si(`model menu unavailable`,e)),s.append(l,f),queueMicrotask(()=>d.focus()),s}function is(e,t,n,r){let a=t.model?`${t.model.id}${t.thinking?` · ${we(t.thinking)}`:``}`:t.thinking?`Pi default · ${we(t.thinking)}`:`Pi default`,o=Ie(a,`${ge} flex items-center gap-1.5 ${t.model?`text-neutral-700`:`text-neutral-400`}`);return o.title=t.model?b(t.model):`Whatever the project and Pi pick`,o.onclick=()=>{let e=rs({models:n,current:t.model,thinkingLevel:t.thinking??`medium`,thinkingLevels:[...Pe],onPick:(e,n)=>{g(),r({model:e,thinking:n??t.thinking})},onThinkingPick:e=>{t={...t,thinking:e},r(t)}}),i=Ie(`Pi default`,`w-full cursor-pointer px-3 py-1.5 text-left text-[12.5px] text-neutral-500 hover:bg-neutral-100`);i.onclick=()=>{g(),r({model:null,thinking:null})};let a=c(`div`,`flex flex-col`);a.append(e,c(`div`,`border-t border-neutral-200`),i),pe(o,a)},i(e,o)}var U;function as(e){U=e,ss.onclick=()=>U.openContinuous(),us.onclick=()=>ks(us),wi(os,()=>{U.currentSession()&&(g(),U.toggleFiles())},()=>vi(t(`#files-dialog`)))}var os=`i`,ss=t(`#bar-back`),cs=t(`#chat-title`),ls=t(`#chat-phase`),us=t(`#chat-menu`),ds=t(`#session-meta`),fs=null,ps=new Map,W=null,G=null,K=null,ms=null;function hs(){W=null,G=null,K=null,ms=null,Ss()}function gs(e,t,n,r){W=e,G=t,K=n,ms=r,q()}function _s(e){ms=e.completedAt,G&&={...G,tokens:e.tokens},Ss()}function q(){let t=U.currentSession(),n=U.continuousOpen();cs.textContent=n?`Pier`:t?t.title??e(t.cwd):U.currentId()??`no session`,cs.disabled=!t,cs.classList.toggle(`cursor-pointer`,!!t),cs.title=t?`Session info`:``,cs.onclick=t?()=>Cs(cs,t):null,ss.classList.toggle(`hidden`,n),ss.classList.toggle(`flex`,!n);let r=n?void 0:ro();ss.replaceChildren(y(xe,`h-4.5 w-4.5`),...r&&(r.state===`streaming`||r.unread)?Za(r):[]),ls.replaceChildren(...!n&&t?eo(t):[]),Ss()}var vs=70,ys=(e,t)=>Math.min(100,Math.round(e/t*100)),bs=e=>U.continuousOpen()?U.rotateAt():e.compactAt,xs=(e,t)=>e.tokens===null?`?/${Ae(t)}`:`${Ae(e.tokens)}/${Ae(t)} · ${100-ys(e.tokens,t)}% left`;function Ss(){let e=G,t=e?.tokens??null,n=U.currentId(),r=U.continuousOpen(),i=[];if(n&&!r){let e=(e,t)=>{let r=c(`button`,`cursor-pointer font-mono ${t}`,e);return r.title=`Change model or reasoning`,r.onclick=()=>void ws(r,n),r};W&&i.push(e(W.id,`min-w-0 truncate rounded bg-indigo-50 px-1.5 py-px font-medium text-indigo-700 hover:bg-indigo-100`)),K&&i.push(e(K,`flex-none text-neutral-500 hover:text-indigo-700`))}let a=e?bs(e):null,o=0;if(e&&t!==null&&a){o=ys(t,a);let n=o>=90?`text-red-700`:o>=vs?`text-amber-700`:`text-neutral-500`;if(r){let r=c(`span`,`flex-none rounded-full bg-neutral-100 px-2 py-0.5 font-mono text-[12px] ${n}`,Ae(t).toLowerCase());r.title=`Context: ${xs(e,a)} before the next message starts a new session`,i.push(r)}else i.push(c(`span`,`flex-none font-mono ${n}`,Ae(t).toLowerCase()))}let s=i.flatMap((e,t)=>t===0?[e]:[c(`span`,`flex-none text-neutral-300`,`·`),e]);ds.replaceChildren(...s),ds.classList.toggle(`hidden`,i.length===0),ds.classList.toggle(`flex`,i.length>0),ds.toggleAttribute(`data-urgent`,o>=vs),ds.toggleAttribute(`data-inline`,r)}function Cs(t,n,r){let i=[[`Directory`,n.cwd],[`Session`,n.id]],o=n.id===U.currentId();if(o){i.push([`Model`,W?.id??`—`]),i.push([`Reasoning`,K??`—`]);let e=G?bs(G):null;i.push([`Context`,G&&e?xs(G,e):`—`])}if(i.push([`Created`,f(n.createdAt),s(n.createdAt)]),o){let e=ms;i.push(e===null?[`Last reply`,`—`]:[`Last reply`,f(e),s(e)])}let u=c(`div`,`w-[min(26rem,calc(100vw-2rem))] max-sm:w-full rounded-xl bg-white px-3 py-3 font-sans text-[15px] leading-normal`),d=c(`button`,`icon-btn h-11 w-11 sm:h-8 sm:w-8`,y(a));d.setAttribute(`aria-label`,`Close session info`),d.onclick=g;let ee=c(`div`,`sticky top-0 z-10 flex items-start gap-2 bg-white pb-2`,c(`div`,`min-w-0 flex-1`,c(`div`,`text-sm font-medium text-neutral-500`,`Session info`),c(`h2`,`mt-1 [overflow-wrap:anywhere] text-lg leading-7 font-semibold text-neutral-900`,n.title??e(n.cwd))),d);if(r){let e=c(`button`,`icon-btn h-11 w-11 sm:h-8 sm:w-8`,y(ze));e.setAttribute(`aria-label`,`Back to session actions`),e.onclick=r,ee.prepend(e)}u.append(ee);let p=c(`dl`,``);for(let[e,t,n]of i){let r=e===`Directory`||e===`Session`,i=c(`dd`,`min-w-0 flex items-start gap-2 text-neutral-700 ${r?`font-mono text-sm leading-6`:``}`,c(`span`,`min-w-0 flex-1 [overflow-wrap:anywhere]`,t));if(r){let n=l(`min-h-11 min-w-11 sm:min-h-8 shrink-0 cursor-pointer rounded-lg px-2 py-1 text-[13px] font-sans text-neutral-500 hover:bg-neutral-100 focus-visible:outline-2`,()=>t);n.setAttribute(`aria-label`,`Copy ${e.toLowerCase()}`),i.append(n)}n&&i.firstElementChild?.append(c(`span`,`ml-2 inline-block font-sans text-[13px] leading-5 text-neutral-500`,n));let a=e===`Model`||e===`Created`;p.append(c(`div`,`grid gap-1 py-1.5 sm:grid-cols-[5.5rem_minmax(0,1fr)] sm:gap-3 ${a?`mt-2 border-t border-neutral-200 pt-2.5`:``}`,c(`dt`,`text-[15px] text-neutral-500`,e===`Session`?`Session ID`:e),i))}return u.append(p),pe(t,u)}async function ws(t,n,r){let i=c(`div`,`px-3 py-3 text-[15px] text-neutral-500`,`Loading models…`),a=c(`div`,`w-[min(24rem,calc(100vw-2rem))] min-w-0 max-sm:w-full`,i),o=i;r&&a.prepend(Os(t,r.title??e(r.cwd),`Close model picker`)),pe(t,a);let s=()=>o.isConnected&&!o.closest(`[inert]`),l=``,u=(e,r,i)=>{let s=JSON.stringify([e,r,i]);if(s===l)return;l=s;let c=rs({models:e,current:n===U.currentId()?W:null,thinkingLevel:r,thinkingLevels:i,onPick:(e,t)=>{g(),Ts(n,e,t)},onThinkingPick:e=>void Ds(n,e)});o.replaceWith(c),o=c,pe(t,a)},d=n===U.currentId()&&W?ps.get(b(W)):void 0;fs&&d&&K&&u(fs,K,d);try{let[e,t]=await Promise.all([ke(`/api/sessions/${n}/models`,`Could not load models`),ke(`/api/sessions/${n}/thinking`,`Could not read the reasoning level`)]);if(fs=e,n===U.currentId()&&W&&ps.set(b(W),t.levels),!s())return;u(e,t.level,t.levels)}catch(e){l?A(`error`,`model options are stale: ${String(e)}`):s()?(i.textContent=`Could not load models: ${String(e)}`,i.setAttribute(`role`,`alert`)):A(`error`,`model options failed: ${String(e)}`)}}async function Ts(e,t,n){await Es(e,t)&&n&&await Ds(e,n)}async function Es(e,t){let n=W;e===U.currentId()&&(W=t,q());let r=await _(`/api/sessions/${e}/model`,t);if(!r.ok){let{error:t}=await r.json().catch(()=>({}));return e===U.currentId()&&(W=n,q()),A(`error`,`model change failed: ${t??r.status}`),!1}let{model:i}=await r.json();return e===U.currentId()&&i&&(W=i,q()),!0}async function Ds(e,t){let n=await _(`/api/sessions/${e}/thinking`,{level:t});if(!n.ok){A(`error`,`reasoning change failed: ${n.status}`);return}let{level:r}=await n.json();e===U.currentId()&&(K=r,Ss())}function Os(e,t,n){let r=c(`button`,`icon-btn h-11 w-11`,y(ze));r.setAttribute(`aria-label`,`Back to session actions`),r.onclick=()=>ks(e);let i=c(`button`,`icon-btn h-11 w-11`,y(a));i.setAttribute(`aria-label`,n),i.onclick=g;let o=c(`span`,`min-w-0 flex-1 truncate text-sm font-medium`,t);return o.title=o.textContent??``,c(`div`,`flex items-center gap-2 border-b border-neutral-200 pb-2 mb-2`,r,o,i)}function ks(t){let n=U.currentSession(),r=U.continuousOpen(),i=n?{}:{disabled:!0,hint:`after the first reply`},a=[...r?[{label:`Search`,hint:_i(`k`),onSelect:()=>{g(),Zo()}}]:[],{label:`Session info`,separatorBefore:r,onSelect:()=>n&&Cs(t,n,()=>ks(t)),...i},{label:`Browse files`,hint:_i(os),onSelect:()=>{g(),U.openFiles()}},{label:`Model & reasoning…`,separatorBefore:!0,hint:W?.id??`…`,onSelect:()=>n&&void ws(t,n.id,n),...i},{label:`Settings`,separatorBefore:!0,onSelect:()=>{g(),U.openSettings()}}];ue(t,a,r?`Pier`:n?n.title??e(n.cwd):`Session`)}var As=`pier.theme`,js=[`system`,`light`,`dark`],Ms=window.matchMedia(`(prefers-color-scheme: dark)`),Ns={system:Je,light:tt,dark:Ye},Ps=()=>{let e=null;try{e=localStorage.getItem(As)}catch{return`system`}return e===`light`||e===`dark`?e:`system`},Fs=()=>{let e=Ps();return e===`system`?Ms.matches?`dark`:`light`:e};function Is(){let e=Fs();document.documentElement.dataset.theme=e;let n=getComputedStyle(document.documentElement).getPropertyValue(`--workbench-canvas`).trim();t(`meta[name="theme-color"]`).setAttribute(`content`,n)}function Ls(){let e=t(`#theme-toggle`),n=()=>{let t=Ps();e.title=`Theme: ${t}${t===`system`?` (${Fs()})`:``}`,e.replaceChildren(y(Ns[t])),e.setAttribute(`aria-label`,e.title),Is()};e.onclick=()=>{let e=js[(js.indexOf(Ps())+1)%js.length];try{e===`system`?localStorage.removeItem(As):localStorage.setItem(As,e)}catch{}n()},Ms.addEventListener(`change`,n),n()}var Rs=`https://github.com/timqi/pier`,zs=[`text-neutral-400`,`hover:text-neutral-700`],Bs=[`rounded-full`,`bg-emerald-50`,`px-1.5`,`text-emerald-700`,`ring-1`,`ring-inset`,`ring-emerald-600/20`,`hover:bg-emerald-100`],Vs=18e5,J=null,Hs=t(`#version`);function Us(e){let t=J?.available===!0&&J.latest!==null;Hs.textContent=`v${e}`,Hs.title=t?`Pier ${J?.latest} is out`:``,Hs.classList.remove(...t?zs:Bs),Hs.classList.add(...t?Bs:zs)}var Ws=(e,t=`px-3 py-1 text-[12px] leading-snug text-neutral-500`)=>c(`p`,t,e);function Gs(){let e=c(`div`,`flex w-72 flex-col gap-1 py-1`);if(!J)return e.append(Ws(`Checking the registry…`)),e;let{current:t,latest:n,available:r,canApply:i,problem:a}=J,o=c(`span`,``,``),s=(e,t)=>d(o,e?`failed`:`idle`,t),l=c(`div`,`flex items-center gap-2 px-3 py-1.5`);if(e.append(Ws(r?`Pier ${n} is out`:`Pier ${t}`,`px-3 py-1 text-[12.5px] font-medium text-neutral-700`),Ws(r?`You are running ${t}.`:n===null?`The registry could not be reached, so this may not be the latest.`:`This is the latest release.`)),a&&e.append(Ws(a,`mx-3 my-1 rounded-md bg-red-50 px-2 py-1.5 text-[11.5px] leading-snug text-red-700`)),r&&i&&!a){let e=p(`Update now`,!0);e.onclick=()=>void(async()=>{e.disabled=!0,s(!1,`starting the updater…`);let t=await _(`/api/update`,{});if(!t.ok)return e.disabled=!1,s(!0,await v(t,`Could not update`));let{draining:n}=await t.json();s(!1,n?`Waiting for running work to finish — Pier then installs and restarts.`:`Installing — Pier restarts once it is on disk, and this page reconnects on its own.`)})(),l.append(e)}l.append(Object.assign(c(`a`,`btn text-[12.5px] no-underline`,`Source`),{href:r?`${Rs}/releases`:Rs,target:`_blank`,rel:`noreferrer`,title:`Pier is free software (AGPL-3.0)`})),e.append(l,c(`div`,`px-3`,o)),r&&!i&&!a&&e.append(Ws(`No service manager owns this Pier, so it cannot restart itself — update it with: pier update`));let u=ee(`Update automatically`,i?`Installs a new release once nothing is running — no turn in flight, no task run.`:`Needs the systemd service (pier service install); nothing here can restart Pier.`,J.autoUpdate,e=>void(async()=>{J&&(J.autoUpdate=e);let t=await _(`/api/settings`,{autoUpdate:e},`PUT`);t.ok||(J&&(J.autoUpdate=!e),f&&(f.checked=!e),s(!0,await v(t,`Could not save`)))})()),f=u.querySelector(`input`);return f&&(f.disabled=!i),e.append(c(`div`,`mt-1 border-t border-neutral-200 px-3 pb-1 pt-2`,u)),e}async function Ks(e){let t=await Te(`/api/update`,`Update check failed`);t.ok&&Us((J=t.value).current||e)}function qs(e){Us(e),Hs.onclick=e=>{e.preventDefault(),pe(Hs,Gs())};let t=()=>void Ks(e);t(),setInterval(t,Vs)}var Y,Js=t(`#composer`),Ys=[t(`#bar`),E,Js],Xs=()=>$s===null,Zs=new Map,Qs=new Map,$s=null,ec=0,tc=new Map,nc={settings:`Settings`};function rc(e,t,n){let r=fc();r&&(r.kind!==`console`||r.name!==e)&&tc.set(e,r),mc({kind:`console`,name:e,arg:t,query:n}),$s=e;for(let e of Ys)e.classList.add(`hidden`);Xi();for(let[t,n]of Zs)t!==e&&n.hide();ic(e,t,n,++ec)}async function ic(e,n,r,i){let a=Zs.get(e);if(!a){let n=Qs.get(e);if(!n){let r=t(`#${e}-view`);n=yc[e](r).catch(t=>(console.warn(`${e} view failed to load`,t),o(r,()=>r.replaceChildren(c(`p`,`p-4 text-[13px] text-red-600`,`Could not load ${nc[e]} — reload the page.`))))),Qs.set(e,n)}a=await n,Zs.set(e,a),Qs.delete(e)}$s===e&&i===ec&&a.show(n,r)}var ac=(e,t)=>void ve(()=>import(`./explorer-C4DhXFCm.js`).then(n=>n.openFiles(Y.currentSession(),e,t)),__vite__mapDeps([0,1,2])),oc=()=>void ve(()=>import(`./explorer-C4DhXFCm.js`).then(e=>e.toggleFiles(Y.currentSession())),__vite__mapDeps([0,1,2]));function sc(e){let t=Y.currentId(),n=tc.get(e)??(t?hc(t):lc);tc.delete(e),mc(n)}function cc(){if($s){$s=null;for(let e of Zs.values())e.hide();for(let e of Ys)e.classList.remove(`hidden`);Xi(),Y.maybeAckRead()}}var lc={kind:`conversation`},uc=e=>e.kind===`session`?`#/session/${encodeURIComponent(e.id)}`:e.kind===`conversation`?`#/conversation`:`#/${e.name}${e.arg?`/${encodeURIComponent(e.arg)}`:``}${e.query?`?${e.query}`:``}`,dc={config:`files`,channels:`channels`,providers:`models`};function fc(){let e=location.hash.replace(/^#\/?/,``),t=e.indexOf(`?`),[n=``,r]=(t<0?e:e.slice(0,t)).split(`/`),i=t<0?void 0:e.slice(t+1)||void 0,a;try{a=r?decodeURIComponent(r):void 0}catch{return null}return dc[n]?{kind:`console`,name:`settings`,arg:dc[n]}:Object.hasOwn(nc,n)?{kind:`console`,name:n,arg:a,query:i}:n===`session`&&a?{kind:`session`,id:a}:n===`conversation`?lc:null}var pc=!1;function mc(e,t=!1){if(pc)return;let n=uc(e);location.hash!==n&&(t?history.replaceState(null,``,n):location.hash=n)}var hc=e=>Y.inConversation(e)?lc:{kind:`session`,id:e},gc=e=>mc(hc(e)),_c=()=>mc(lc);function vc(){let e=fc()??lc;pc=!0;try{e.kind===`conversation`?Y.openContinuous():e.kind===`session`?e.id===Y.currentId()?cc():Y.select(e.id):(Y.currentId()||Y.openContinuous(),rc(e.name,e.arg,e.query))}finally{pc=!1}e.kind===`conversation`?mc(lc,!0):e.kind===`session`&&mc(hc(e.id),!0)}var yc={settings:async e=>(await ve(async()=>{let{createSettingsView:e}=await import(`./settings-DSTeuIyc.js`);return{createSettingsView:e}},__vite__mapDeps([3,1,2]))).createSettingsView(e,()=>dt(Y.sessions()),e=>rc(`settings`,e),ac,()=>sc(`settings`))};function bc(e){Y=e,window.onhashchange=vc}var X=[],xc=null,Sc=0,Cc=!1,Z=null,wc=`idle`,Tc=null,Ec=0,Dc=!1,Oc=!1,kc=[],Ac=null,Q=[],jc=!1,Mc=!1,Nc=0,Pc=null,Fc=()=>kc[0]?.sessionId??null,Ic=e=>kc.some(t=>t.sessionId===e),Lc=()=>jc||Z!==null&&Z===Fc(),Rc={first:`new session`,idle:`new session — idle 1h`,lost:`new session — the previous one was lost`,full:`new session — the previous one was full`,new:`new session — /new`};async function zc(){let e=await fetch(`/api/continuous`);if(!e.ok)throw Error(await v(e,`Could not load the continuous conversation`));let{chain:t,rotateAt:n}=await e.json();if(!Array.isArray(t)||typeof n!=`number`||!(n>0))throw Error(`The continuous conversation's chain is malformed`);return{chain:t,rotateAt:n}}async function Bc(){let e=await fetch(`/api/continuous/open`);if(!e.ok)throw Error(await v(e,`Could not load the open items`));return await e.json()}var Vc=fe(async()=>{Pc=await Bc(),z()});function Hc(){let e=Fc();if(e)return void tl(e);if(jc)return cc(),_c();++Sc,I(),cc(),Tc?.close(),Tc=null,Z=null,xc=null,wc=`idle`,jc=!0,Q=[],nl(),A(`system`,`The continuous conversation — your first message starts it.`),_c(),z(),q(),Yi(),Gi()}async function Uc(e){Q=[],jc=!1,await tl(e),kc.length>1&&await Wc()}async function Wc(){let e=Fc(),t=kc[Q.length+1];if(!(Mc||!e||!t||Z!==e)){Mc=!0;try{let n=await Te(`/api/sessions/${t.sessionId}/history`,`Could not load the earlier session`);if(Z!==e)return;Q.unshift(n.ok?{member:t,turns:n.value.turns,runs:n.value.backgroundRuns}:{member:t,turns:[],runs:[],error:n.error});let r=E.scrollHeight-E.scrollTop,i=document.activeElement?.id===`chain-pager`;await rl(e,!0),E.scrollTop=E.scrollHeight-r,i&&document.getElementById(`chain-pager`)?.focus({preventScroll:!0}),Nc=Date.now()}finally{Mc=!1}}}function Gc(){Q.length<kc.length-1&&Qr(()=>void Wc());for(let[e,t]of Q.entries()){t.error&&A(`error`,t.error),$r(t.turns,`idle`,t.runs,!0);let n=Q[e+1]?.member??kc[0];Zr(Rc[n.reason],n.startedAt)}}E.addEventListener(`scroll`,()=>{E.scrollTop<40&&Lc()&&!Cc&&Date.now()-Nc>500&&Wc()},{passive:!0});function Kc(e){X=e.map(e=>({...e,title:lt(e.title)})),X.sort((e,t)=>t.createdAt-e.createdAt),z(),q(),qc()}var $=fe(async()=>{let[e,t,n]=await Promise.all([ke(`/api/sessions`,`Could not load sessions`),zc(),Bc()]),r=Lc(),i=Fc();kc=t.chain,Ac=t.rotateAt,Pc=n,Kc(e);let a=Fc();r&&a&&a!==i&&await Uc(a)});function qc(){if(document.hidden||!document.hasFocus()||!Xs())return;let e=X.find(e=>e.id===Z);e?.unread&&(e.unread=!1,z(),fetch(`/api/sessions/${e.id}/read`,{method:`POST`}))}function Jc(){return X.find(e=>e.id===Z)??(xc&&xc.id===Z?xc:void 0)}async function Yc(e){let t=await Te(`/api/sessions/${e}`,`failed to load session`);Z!==e||!t.ok||(xc={...t.value,title:lt(t.value.title)},q())}function Xc(e,t){let n=X.find(t=>t.id===e);!n||n.title||!t.trim()||(n.title=t.trim().slice(0,80),z(),q())}function Zc(e){wc=e;let t=X.find(e=>e.id===Z);t&&(t.state=e),z(),q(),Yi(),e===`idle`&&$()}function Qc(e){if(!(e.sessionId!==Z||e.seq<=Ec))switch(Ec=e.seq,e.type){case`turn-start`:Dc=!0,Oc=!1;break;case`system-input`:Gr(),vr(e.text,e.origin),e.origin.kind===`task-message`&&Qi(e.origin.messageId);break;case`task-status`:yn(e.run);break;case`user-message`:{let t=ot(e.text).text;if(Xc(e.sessionId,t),Ki(t))break;Gr(),A(`user`,e.text,!1,e.ts),O();break}case`text-start`:Gr();break;case`text-delta`:Wr(e.text);break;case`thinking-delta`:Gr(),qn(e.ts,e.text);break;case`tool-start`:Gr(),Wn(e.ts,e.toolCallId,e.toolName,e.args);break;case`tool-end`:Kn(e.toolCallId,e.isError,e.output);break;case`turn-end`:Dc=!1,qr(e.text,e.meta),e.meta&&_s(e.meta);break;case`queue-state`:Zi(e.steering,e.followUp);break;case`context-compacted`:Gr(),A(`system`,`Context compacted — ${Ae(e.before)} → ${Ae(e.after)}`,!1,e.ts),O();break;case`error`:Hn(),A(`error`,e.message),Oc&&(Oc=!1,Zc(`idle`));break;case`state`:Oc=!1,e.state===`idle`&&Dc&&(Dc=!1,Jr()),e.state===`idle`&&Zi([],[]),Zc(e.state)}}function $c(){let e=new EventSource(`/api/events`);e.onopen=()=>void $(),e.onerror=()=>fi(e,`Workspace`),e.onmessage=e=>{let t=JSON.parse(e.data);if(t.type===`sessions-changed`){$();return}if(t.type===`tasks-changed`||t.type===`task-run-changed`||t.type===`task-message-changed`||t.type===`task-group-changed`){t.type===`task-run-changed`&&$();return}if(t.type===`open-items-changed`){Vc();return}if(Pc&&[...Pc.items.flatMap(e=>e.runs),...Pc.unlisted].some(e=>e.targetSessionId===t.sessionId)&&Vc(),t.sessionId===Z)return;let n=X.find(e=>e.id===t.sessionId);if(!n){$();return}n.state=t.state,z(),t.sessionId===Fc()&&q()}}function el(e,t,n){Tc?.close();let r=new EventSource(`/api/sessions/${e}/events?after=${t}`),i=()=>Tc===r&&Z===e&&n===Sc;r.onmessage=e=>{i()&&Qc(JSON.parse(e.data))},r.addEventListener(`reset`,()=>{i()&&rl(e)}),r.onerror=()=>{i()&&fi(r,`Session`)},Tc=r}async function tl(e){Ic(e)&&(e=Fc()),(e!==Z||jc)&&(Q=[],jc=!1),cc(),gc(e),!(e===Z&&(Tc||Cc))&&(++Sc,I(),Z=e,xc=null,X.some(t=>t.id===e)||Yc(e),wc=X.find(t=>t.id===e)?.state??`idle`,ya(e),z(),q(),qc(),await rl(e))}function nl(){Yr(),Zi([],[],[]),sa([]),hs(),Dc=!1,Oc=!1,Ji(),Ec=0}async function rl(e,t=!1){if(Z!==e)return;let n=++Sc;Tc?.close(),Tc=null,Cc=!0,t||(nl(),Xr(!0));let r=await Te(`/api/sessions/${e}/history`,`failed to load session`);if(Z!==e||n!==Sc)return;if(Cc=!1,t&&nl(),!r.ok){Xr(!1),A(`error`,r.error);return}let i=r.value;Lc()&&Gc(),$r(i.turns,i.state,i.backgroundRuns),Ec=i.lastSeq,Dc=i.state===`streaming`,Zc(i.state),Zi(i.queue.steering,i.queue.followUp,i.queue.parked),sa(i.skills);let a=i.turns.reduce((e,t)=>t.meta?.completedAt??e,null);gs(i.model,i.context,i.thinkingLevel,a),el(e,`${i.epoch}:${i.lastSeq}`,n)}ci(),ne(),di(),Ls();var il=e=>{Oc=e===`streaming`,Zc(e)},al=async e=>{Z===e&&await rl(e)};Qn({sessionId:()=>Z,sessionCwd:()=>Jc()?.cwd??null,sessionChannel:()=>Jc()?.channel??null,sessionState:()=>wc,select:e=>void tl(e),send:(e,t)=>void Sa(e,t),ownTurn:e=>{qi(e),il(`streaming`)},reload:al}),Ta({sessionId:()=>Z,sessionState:()=>wc,chatVisible:Xs,setState:il,reload:al,continuous:Lc,headMoved:()=>void $()}),Co({sessions:()=>X,currentId:()=>Z,select:e=>void tl(e),chain:()=>kc,openContinuous:Hc,open:()=>Pc}),Qo({sessions:()=>X,loadSessions:$,select:tl,openContinuous:Hc,openConsole:rc}),as({currentId:()=>Z,currentSession:Jc,openFiles:ac,toggleFiles:oc,openSettings:()=>rc(`settings`),continuousOpen:Lc,rotateAt:()=>Ac,openContinuous:Hc}),bc({sessions:()=>X,currentId:()=>Z,currentSession:Jc,select:e=>void tl(e),inConversation:Ic,openContinuous:Hc,maybeAckRead:qc}),qs(`0.3.0`),Ba(),document.addEventListener(`gesturestart`,e=>e.preventDefault()),document.addEventListener(`visibilitychange`,qc),window.addEventListener(`focus`,qc),$c(),$().then(vc);export{Ci as a,xi as i,rs as n,We as o,Ga as r,is as t};
|
|
14
|
+
`),open:()=>i?L.select(i):L.openContinuous()}}var po=(e,t)=>({...fo({problem:e.name,stage:``,runs:[e],status:`running`},t),...e.state===`queued`?{status:`queued`}:{}});function mo(e){let t=L.open()??{items:[],unlisted:[]},n=new Set([...t.items.flatMap(e=>e.runs),...t.unlisted].flatMap(e=>e.targetSessionId?[e.targetSessionId]:[])),r=no(L.sessions(),L.chain()),i=[...t.items.map(t=>fo(t,e)),...t.unlisted.map(t=>po(t,e)),...r.flatMap(e=>{let t=Ya(e);return t&&!n.has(e.id)?[uo(e,t)]:[]})],a=e=>e.status===`waiting on you`||e.status===`pending release`;return{waiting:i.filter(a).map(so),running:i.filter(e=>!a(e)).map(so),sessions:r}}var ho=null,go=[[],[]],_o=!1,vo=()=>`${L.currentId()??``}\n${JSON.stringify(L.chain())}\n${JSON.stringify(L.sessions())}\n${JSON.stringify(L.open())}`,yo=``;function z(){let e=vo();if(e===yo)return;yo=e;let{waiting:t,running:n,sessions:r}=mo(Date.now());go=[t,n],Wa(r.filter(e=>Xa(Ya(e))).length+ +!!ro()?.unread);let i=[...n.length?[`${n.length} running`]:[],...t.length?[`${t.length} needs you`]:[]].join(` · `);_o=!!i,R.textContent=i,R.classList.toggle(`hidden`,!i),R.classList.toggle(`block`,!!i),R.classList.toggle(`text-amber-700`,t.length>0),R.classList.toggle(`text-neutral-600`,t.length===0),ho?.[0].isConnected&&!ho[0].closest(`[inert]`)&&(_o?bo(ho):g()),Xo()}function bo(e){let t=document.activeElement?.closest(`[data-session-id]`)?.dataset.sessionId;e.forEach((e,t)=>{e.replaceChildren(...go[t]),e.previousElementSibling?.classList.toggle(`hidden`,!go[t].length)}),e[1].previousElementSibling?.classList.toggle(`mt-2`,go[0].length>0),t&&go.flat().find(e=>e.dataset.sessionId===t)?.querySelector(`.session-open`)?.focus({preventScroll:!0})}var xo=`px-2 pb-1 text-xs font-semibold leading-5 text-neutral-500`;function So(){if(R.getAttribute(`aria-expanded`)===`true`)return g();if(!_o)return;let[e,t]=[c(`ul`,``),c(`ul`,``)];e.dataset.list=`waiting`,t.dataset.list=`running`;let n=c(`div`,`w-[min(32rem,calc(100vw-2rem))] max-sm:w-full font-sans text-sm`,c(`div`,xo,`Waiting on you`),e,c(`div`,xo,`In progress`),t);ho=[e,t],bo(ho),pe(R,n).setAttribute(`aria-label`,`Status`)}function Co(e){L=e,R.onclick=So,wi(`shift+p`,So,vi)}var wo,B=t(`#palette`),To=t(`#palette-input`),Eo=t(`#palette-list`),Do=t(`#palette-count`),Oo=[{name:`settings`,icon:$e,label:`Settings`,detail:`Console — models and providers, agent files and extensions, channels, password, sign out, security`}],ko=7,Ao=8,jo=80,Mo=``,No,Po,Fo;function Io(e){Mo!==e&&(clearTimeout(Fo),Po?.abort(),Po=void 0,Mo=e,No=void 0,e&&(Fo=setTimeout(()=>{let t=Po=new AbortController;Te(`/api/search?q=${encodeURIComponent(e)}`,`Search unavailable`,{signal:t.signal}).then(n=>{t.signal.aborted||Mo!==e||(Po=void 0,No=n.ok?{hits:n.value.hits}:{error:n.error},B.open&&Yo())})},jo)))}var V=[],H=0;function Lo(e){if(V.length){H=(e+V.length)%V.length;for(let[e,{el:t}]of V.entries())t.classList.toggle(`bg-indigo-50`,e===H),t.setAttribute(`aria-selected`,String(e===H));V[H]?.el.scrollIntoView({block:`nearest`})}}var Ro=e=>e.hit?.at??e.session?.createdAt;function zo(e){let t=c(`span`,`min-w-0 flex-1 truncate text-neutral-500`);for(let n of e.replaceAll(/\s+/g,` `).split(``)){let[e=``,r]=n.split(``,2);r===void 0?t.append(e):t.append(c(`span`,`font-medium text-neutral-800`,e),r)}return t}var Bo=`flex min-w-0 flex-1 items-baseline gap-2`,Vo=`shrink-0 truncate`,Ho=`min-w-[2.5em] truncate text-[0.8125rem] text-neutral-400`,Uo=`flex-none text-[0.75rem] tabular-nums text-neutral-400`,Wo=`flex h-7 w-7 flex-none items-center justify-center rounded-[8px] bg-neutral-100 text-neutral-500`;function Go(e){let t=c(`li`,`palette-row flex cursor-pointer items-center gap-3 rounded-[10px] px-2 leading-5 ${e.hit?`py-1.5`:`min-h-10`}`);t.setAttribute(`role`,`option`),t.append(c(`span`,Wo,y(e.icon,`h-4 w-4`)));let n=c(`div`,`flex min-w-0 flex-1 flex-col`),r=c(`div`,`flex items-center gap-2`);e.session&&r.append(...Za(e.session));let i=c(`span`,Bo,c(`span`,`${Vo} ${e.detail?`max-w-[calc(100%-3em)]`:`max-w-full`}`,e.label));e.detail&&i.append(c(`span`,Ho,e.detail)),r.append(i);let a=Ro(e);return e.session&&r.append(...eo(e.session)),a!==void 0&&r.append(c(`span`,Uo,se(a))),n.append(r),e.hit&&n.append(c(`div`,`flex items-baseline gap-2 text-[0.8125rem] leading-5`,c(`span`,`flex-none text-[0.75rem] text-neutral-400`,e.hit.role===`user`?`You`:`Agent`),zo(e.hit.snippet))),t.append(n),t.onclick=e.open,t}var Ko=e=>c(`li`,`px-2 pb-1.5 pt-4 text-[0.6875rem] font-semibold leading-4 tracking-[0.02em] text-neutral-400 first:pt-2`,e);function qo(e,t){let n=c(`li`,`px-2 py-2 pl-12 text-[0.8125rem] leading-5 text-neutral-400`,e);return t&&(n.title=t),n}var Jo=e=>e.channel&&e.channel!==`web`?e.channel:``;function Yo(){let t=To.value.trim(),n=t.toLowerCase().split(/\s+/).filter(Boolean),r=e=>{let t=e.toLowerCase();return n.every(e=>t.includes(e))},i=e=>()=>{B.close(),e()},a=wo.sessions(),o=new Map(a.map(e=>[e.id,e])),s=t=>({icon:Ge,label:t.title??e(t.cwd),detail:[re(t.cwd),Jo(t)].filter(Boolean).join(` · `),open:i(()=>void wo.select(t.id)),session:t}),c=ro(),l=!t||r(`pier conversation`)?[{icon:Ke,label:`Pier`,detail:``,open:i(wo.openContinuous),...c?{session:c}:{}}]:[],u=Oo.filter(e=>!t||r(`${e.label} ${e.detail}`)).map(({name:e,icon:t,label:n,detail:r})=>({icon:t,label:n,detail:r,open:i(()=>wo.openConsole(e))})),d=[[``,l]];if(!t)d.push([`Recent`,a.filter(e=>!Ja(e)&&e.id!==c?.id).slice(0,ko).map(s)],[`Actions`,u]);else{let e=a.filter(e=>r(`${e.title??``} ${e.cwd} ${Jo(e)}`)).slice(0,Ao),n=new Set(e.map(e=>e.id)),c=e.map(s);if(Mo!==t||!No)c.push(qo(`Searching messages…`));else if(`error`in No)c.push(qo(`Message search unavailable`,No.error));else{for(let e of No.hits){if(c.length>=Ao)break;let t=o.get(e.sessionId);!t||n.has(t.id)||c.push({...s(t),hit:e,open:i(()=>void wo.select(t.id).then(()=>or(e.role,e.at)))})}c.length||c.push(qo(`No sessions match`))}d.push([`Actions`,u],[`Sessions`,c])}V=[];let f=[];for(let[e,t]of d)if(t.length){e&&f.push(Ko(e));for(let e of t){if(e instanceof HTMLElement){f.push(e);continue}let t=Go(e);V.push({el:t,open:e.open}),f.push(t)}}Eo.replaceChildren(...f.length?f:[qo(`Nothing matches`)]),Do.textContent=`${V.length} ${V.length===1?`row`:`rows`}`,Lo(Math.min(H,Math.max(0,V.length-1)))}function Xo(){B.open&&Yo()}function Zo(){if(B.open)return B.close();To.value=``,H=0,Io(``),Yo(),B.showModal(),To.focus(),wo.loadSessions().then(Xo)}function Qo(e){wo=e,wi(`k`,Zo,()=>B.open||Me()),B.onclick=e=>{e.target===B&&B.close()},B.onclose=()=>Io(``),To.oninput=()=>{H=0,Io(To.value.trim()),Yo()},To.onkeydown=e=>{let t=Se(e);if(t!==void 0){e.preventDefault(),Lo(H+t);return}e.key===`Enter`&&!e.ctrlKey&&(e.preventDefault(),V[H]?.open())}}var $o=0,es=null;async function ts(){let{modelMenu:e}=await ke(`/api/settings`,`Could not read the pinned model menu`);return e}function ns(e){let t=c(`button`,`flex w-full min-w-0 cursor-pointer items-center gap-2 px-3 py-1.5 text-left hover:bg-neutral-100`,y(be,`h-3 w-3 text-indigo-600 ${e.checked?``:`invisible`}`),c(`span`,`truncate`,e.label));return e.hint&&t.append(c(`span`,`ml-auto flex-none text-[11.5px] text-neutral-400`,e.hint)),t.onclick=()=>e.onSelect(),t}function rs({models:e,current:t,thinkingLevel:n,thinkingLevels:r,onPick:i,onThinkingPick:a}){let o=n,s=c(`div`,`flex w-full min-w-0 flex-col sm:min-w-72`),l=c(`div`,`flex flex-col gap-2 border-b border-neutral-200 px-2 py-2`),d=document.createElement(`input`);if(d.type=`search`,d.placeholder=`Search models`,d.setAttribute(`aria-label`,`Search models`),d.className=`w-full rounded-md border border-neutral-300 px-2 py-1.5 text-[12.5px] focus:border-indigo-400 focus:outline-none`,l.append(d),r.length){let e=document.createElement(`details`),t=c(`span`,`ml-auto font-medium text-indigo-700`,we(o)),n=c(`summary`,`flex min-h-11 cursor-pointer list-none items-center gap-2 rounded-xl px-3 text-sm text-neutral-700 hover:bg-neutral-100 [&::-webkit-details-marker]:hidden`,c(`span`,`font-medium`,`Reasoning effort`),t,y(u,`chev h-3 w-3 text-neutral-400`)),i=c(`fieldset`,`grid grid-cols-2 gap-1 rounded-xl bg-neutral-50 p-1`);i.append(c(`legend`,`sr-only`,`Reasoning effort`));let s=`reasoning-${++$o}`;for(let e of r){let n=document.createElement(`input`);n.type=`radio`,n.name=s,n.value=e,n.checked=e===o,n.className=`peer sr-only`,n.onchange=()=>{n.checked&&(o=e,t.textContent=we(o),m(d.value),a(o))},i.append(c(`label`,`relative cursor-pointer`,n,c(`span`,`flex min-h-11 items-center rounded-lg border border-transparent px-3 text-sm text-neutral-700 hover:bg-neutral-100 peer-checked:border-indigo-200 peer-checked:bg-indigo-50 peer-checked:font-semibold peer-checked:text-indigo-700 peer-focus-visible:outline-2 peer-focus-visible:outline-indigo-500`,we(e))))}e.append(n,i),l.append(e)}let f=c(`div`,`max-h-72 overflow-y-auto py-1`),ee=new Map(e.map(e=>[b(e),e])),p=e=>{let n=(es??[]).map(e=>({e,model:ee.get(b(e))})).filter(t=>!!t.model&&(!e||b(t.model).toLowerCase().includes(e)));n.length&&f.append(c(`div`,`px-3 pb-0.5 pt-1 text-[10.5px] font-semibold uppercase tracking-wide text-neutral-400`,`Pinned`),...n.map(({e,model:n})=>ns({label:n.id,hint:we(e.thinking),checked:!!t&&b(t)===b(n)&&o===e.thinking,onSelect:()=>i(n,e.thinking)})),c(`div`,`my-1 border-t border-neutral-100`))},m=n=>{f.replaceChildren();let r=n.trim().toLowerCase();p(r);let a=new Map;for(let t of e){if(r&&!b(t).toLowerCase().includes(r))continue;let e=a.get(t.provider);e?e.push(t):a.set(t.provider,[t])}if(!a.size){f.append(c(`div`,`px-3 py-2 text-[12.5px] text-neutral-400`,e.length?`No matching models.`:`No models available.`));return}for(let[e,n]of a){let a=n.some(e=>!!t&&b(t)===b(e)),o=document.createElement(`details`);o.open=a||r.length>0;let s=c(`summary`,`flex cursor-pointer select-none items-center gap-1.5 px-3 py-1 text-[10.5px] font-semibold uppercase tracking-wide text-neutral-400 hover:bg-neutral-100`,y(u,`chev h-3 w-3`),c(`span`,`truncate`,e),c(`span`,`ml-auto flex-none normal-case text-neutral-300`,String(n.length)));o.append(s,...n.map(e=>ns({label:e.id,checked:!!t&&b(t)===b(e),onSelect:()=>i(e)}))),f.append(o)}};return d.oninput=()=>m(d.value),m(``),ts().then(e=>{let t=JSON.stringify(e)!==JSON.stringify(es);es=e,t&&m(d.value)}).catch(e=>si(`model menu unavailable`,e)),s.append(l,f),queueMicrotask(()=>d.focus()),s}function is(e,t,n,r){let a=t.model?`${t.model.id}${t.thinking?` · ${we(t.thinking)}`:``}`:t.thinking?`Pi default · ${we(t.thinking)}`:`Pi default`,o=Ie(a,`${ge} flex items-center gap-1.5 ${t.model?`text-neutral-700`:`text-neutral-400`}`);return o.title=t.model?b(t.model):`Whatever the project and Pi pick`,o.onclick=()=>{let e=rs({models:n,current:t.model,thinkingLevel:t.thinking??`medium`,thinkingLevels:[...Pe],onPick:(e,n)=>{g(),r({model:e,thinking:n??t.thinking})},onThinkingPick:e=>{t={...t,thinking:e},r(t)}}),i=Ie(`Pi default`,`w-full cursor-pointer px-3 py-1.5 text-left text-[12.5px] text-neutral-500 hover:bg-neutral-100`);i.onclick=()=>{g(),r({model:null,thinking:null})};let a=c(`div`,`flex flex-col`);a.append(e,c(`div`,`border-t border-neutral-200`),i),pe(o,a)},i(e,o)}var U;function as(e){U=e,ss.onclick=()=>U.openContinuous(),us.onclick=()=>ks(us),wi(os,()=>{U.currentSession()&&(g(),U.toggleFiles())},()=>vi(t(`#files-dialog`)))}var os=`i`,ss=t(`#bar-back`),cs=t(`#chat-title`),ls=t(`#chat-phase`),us=t(`#chat-menu`),ds=t(`#session-meta`),fs=null,ps=new Map,W=null,G=null,K=null,ms=null;function hs(){W=null,G=null,K=null,ms=null,Ss()}function gs(e,t,n,r){W=e,G=t,K=n,ms=r,q()}function _s(e){ms=e.completedAt,G&&={...G,tokens:e.tokens},Ss()}function q(){let t=U.currentSession(),n=U.continuousOpen();cs.textContent=n?`Pier`:t?t.title??e(t.cwd):U.currentId()??`no session`,cs.disabled=!t,cs.classList.toggle(`cursor-pointer`,!!t),cs.title=t?`Session info`:``,cs.onclick=t?()=>Cs(cs,t):null,ss.classList.toggle(`hidden`,n),ss.classList.toggle(`flex`,!n);let r=n?void 0:ro();ss.replaceChildren(y(xe,`h-4.5 w-4.5`),...r&&(r.state===`streaming`||r.unread)?Za(r):[]),ls.replaceChildren(...!n&&t?eo(t):[]),Ss()}var vs=70,ys=(e,t)=>Math.min(100,Math.round(e/t*100)),bs=e=>U.continuousOpen()?U.rotateAt():e.compactAt,xs=(e,t)=>e.tokens===null?`?/${Ae(t)}`:`${Ae(e.tokens)}/${Ae(t)} · ${100-ys(e.tokens,t)}% left`;function Ss(){let e=G,t=e?.tokens??null,n=U.currentId(),r=U.continuousOpen(),i=[];if(n&&!r){let e=(e,t)=>{let r=c(`button`,`cursor-pointer font-mono ${t}`,e);return r.title=`Change model or reasoning`,r.onclick=()=>void ws(r,n),r};W&&i.push(e(W.id,`min-w-0 truncate rounded bg-indigo-50 px-1.5 py-px font-medium text-indigo-700 hover:bg-indigo-100`)),K&&i.push(e(K,`flex-none text-neutral-500 hover:text-indigo-700`))}let a=e?bs(e):null,o=0;if(e&&t!==null&&a){o=ys(t,a);let n=o>=90?`text-red-700`:o>=vs?`text-amber-700`:`text-neutral-500`;if(r){let r=c(`span`,`flex-none rounded-full bg-neutral-100 px-2 py-0.5 font-mono text-[12px] ${n}`,Ae(t).toLowerCase());r.title=`Context: ${xs(e,a)} before the next message starts a new session`,i.push(r)}else i.push(c(`span`,`flex-none font-mono ${n}`,Ae(t).toLowerCase()))}let s=i.flatMap((e,t)=>t===0?[e]:[c(`span`,`flex-none text-neutral-300`,`·`),e]);ds.replaceChildren(...s),ds.classList.toggle(`hidden`,i.length===0),ds.classList.toggle(`flex`,i.length>0),ds.toggleAttribute(`data-urgent`,o>=vs),ds.toggleAttribute(`data-inline`,r)}function Cs(t,n,r){let i=[[`Directory`,n.cwd],[`Session`,n.id]],o=n.id===U.currentId();if(o){i.push([`Model`,W?.id??`—`]),i.push([`Reasoning`,K??`—`]);let e=G?bs(G):null;i.push([`Context`,G&&e?xs(G,e):`—`])}if(i.push([`Created`,f(n.createdAt),s(n.createdAt)]),o){let e=ms;i.push(e===null?[`Last reply`,`—`]:[`Last reply`,f(e),s(e)])}let u=c(`div`,`w-[min(26rem,calc(100vw-2rem))] max-sm:w-full rounded-xl bg-white px-3 py-3 font-sans text-[15px] leading-normal`),d=c(`button`,`icon-btn h-11 w-11 sm:h-8 sm:w-8`,y(a));d.setAttribute(`aria-label`,`Close session info`),d.onclick=g;let ee=c(`div`,`sticky top-0 z-10 flex items-start gap-2 bg-white pb-2`,c(`div`,`min-w-0 flex-1`,c(`div`,`text-sm font-medium text-neutral-500`,`Session info`),c(`h2`,`mt-1 [overflow-wrap:anywhere] text-lg leading-7 font-semibold text-neutral-900`,n.title??e(n.cwd))),d);if(r){let e=c(`button`,`icon-btn h-11 w-11 sm:h-8 sm:w-8`,y(ze));e.setAttribute(`aria-label`,`Back to session actions`),e.onclick=r,ee.prepend(e)}u.append(ee);let p=c(`dl`,``);for(let[e,t,n]of i){let r=e===`Directory`||e===`Session`,i=c(`dd`,`min-w-0 flex items-start gap-2 text-neutral-700 ${r?`font-mono text-sm leading-6`:``}`,c(`span`,`min-w-0 flex-1 [overflow-wrap:anywhere]`,t));if(r){let n=l(`min-h-11 min-w-11 sm:min-h-8 shrink-0 cursor-pointer rounded-lg px-2 py-1 text-[13px] font-sans text-neutral-500 hover:bg-neutral-100 focus-visible:outline-2`,()=>t);n.setAttribute(`aria-label`,`Copy ${e.toLowerCase()}`),i.append(n)}n&&i.firstElementChild?.append(c(`span`,`ml-2 inline-block font-sans text-[13px] leading-5 text-neutral-500`,n));let a=e===`Model`||e===`Created`;p.append(c(`div`,`grid gap-1 py-1.5 sm:grid-cols-[5.5rem_minmax(0,1fr)] sm:gap-3 ${a?`mt-2 border-t border-neutral-200 pt-2.5`:``}`,c(`dt`,`text-[15px] text-neutral-500`,e===`Session`?`Session ID`:e),i))}return u.append(p),pe(t,u)}async function ws(t,n,r){let i=c(`div`,`px-3 py-3 text-[15px] text-neutral-500`,`Loading models…`),a=c(`div`,`w-[min(24rem,calc(100vw-2rem))] min-w-0 max-sm:w-full`,i),o=i;r&&a.prepend(Os(t,r.title??e(r.cwd),`Close model picker`)),pe(t,a);let s=()=>o.isConnected&&!o.closest(`[inert]`),l=``,u=(e,r,i)=>{let s=JSON.stringify([e,r,i]);if(s===l)return;l=s;let c=rs({models:e,current:n===U.currentId()?W:null,thinkingLevel:r,thinkingLevels:i,onPick:(e,t)=>{g(),Ts(n,e,t)},onThinkingPick:e=>void Ds(n,e)});o.replaceWith(c),o=c,pe(t,a)},d=n===U.currentId()&&W?ps.get(b(W)):void 0;fs&&d&&K&&u(fs,K,d);try{let[e,t]=await Promise.all([ke(`/api/sessions/${n}/models`,`Could not load models`),ke(`/api/sessions/${n}/thinking`,`Could not read the reasoning level`)]);if(fs=e,n===U.currentId()&&W&&ps.set(b(W),t.levels),!s())return;u(e,t.level,t.levels)}catch(e){l?A(`error`,`model options are stale: ${String(e)}`):s()?(i.textContent=`Could not load models: ${String(e)}`,i.setAttribute(`role`,`alert`)):A(`error`,`model options failed: ${String(e)}`)}}async function Ts(e,t,n){await Es(e,t)&&n&&await Ds(e,n)}async function Es(e,t){let n=W;e===U.currentId()&&(W=t,q());let r=await _(`/api/sessions/${e}/model`,t);if(!r.ok){let{error:t}=await r.json().catch(()=>({}));return e===U.currentId()&&(W=n,q()),A(`error`,`model change failed: ${t??r.status}`),!1}let{model:i}=await r.json();return e===U.currentId()&&i&&(W=i,q()),!0}async function Ds(e,t){let n=await _(`/api/sessions/${e}/thinking`,{level:t});if(!n.ok){A(`error`,`reasoning change failed: ${n.status}`);return}let{level:r}=await n.json();e===U.currentId()&&(K=r,Ss())}function Os(e,t,n){let r=c(`button`,`icon-btn h-11 w-11`,y(ze));r.setAttribute(`aria-label`,`Back to session actions`),r.onclick=()=>ks(e);let i=c(`button`,`icon-btn h-11 w-11`,y(a));i.setAttribute(`aria-label`,n),i.onclick=g;let o=c(`span`,`min-w-0 flex-1 truncate text-sm font-medium`,t);return o.title=o.textContent??``,c(`div`,`flex items-center gap-2 border-b border-neutral-200 pb-2 mb-2`,r,o,i)}function ks(t){let n=U.currentSession(),r=U.continuousOpen(),i=n?{}:{disabled:!0,hint:`after the first reply`},a=[...r?[{label:`Search`,hint:_i(`k`),onSelect:()=>{g(),Zo()}}]:[],{label:`Session info`,separatorBefore:r,onSelect:()=>n&&Cs(t,n,()=>ks(t)),...i},{label:`Browse files`,hint:_i(os),onSelect:()=>{g(),U.openFiles()}},{label:`Model & reasoning…`,separatorBefore:!0,hint:W?.id??`…`,onSelect:()=>n&&void ws(t,n.id,n),...i},{label:`Settings`,separatorBefore:!0,onSelect:()=>{g(),U.openSettings()}}];ue(t,a,r?`Pier`:n?n.title??e(n.cwd):`Session`)}var As=`pier.theme`,js=[`system`,`light`,`dark`],Ms=window.matchMedia(`(prefers-color-scheme: dark)`),Ns={system:Je,light:tt,dark:Ye},Ps=()=>{let e=null;try{e=localStorage.getItem(As)}catch{return`system`}return e===`light`||e===`dark`?e:`system`},Fs=()=>{let e=Ps();return e===`system`?Ms.matches?`dark`:`light`:e};function Is(){let e=Fs();document.documentElement.dataset.theme=e;let n=getComputedStyle(document.documentElement).getPropertyValue(`--workbench-canvas`).trim();t(`meta[name="theme-color"]`).setAttribute(`content`,n)}function Ls(){let e=t(`#theme-toggle`),n=()=>{let t=Ps();e.title=`Theme: ${t}${t===`system`?` (${Fs()})`:``}`,e.replaceChildren(y(Ns[t])),e.setAttribute(`aria-label`,e.title),Is()};e.onclick=()=>{let e=js[(js.indexOf(Ps())+1)%js.length];try{e===`system`?localStorage.removeItem(As):localStorage.setItem(As,e)}catch{}n()},Ms.addEventListener(`change`,n),n()}var Rs=`https://github.com/timqi/pier`,zs=[`text-neutral-400`,`hover:text-neutral-700`],Bs=[`rounded-full`,`bg-emerald-50`,`px-1.5`,`text-emerald-700`,`ring-1`,`ring-inset`,`ring-emerald-600/20`,`hover:bg-emerald-100`],Vs=18e5,J=null,Hs=t(`#version`);function Us(e){let t=J?.available===!0&&J.latest!==null;Hs.textContent=`v${e}`,Hs.title=t?`Pier ${J?.latest} is out`:``,Hs.classList.remove(...t?zs:Bs),Hs.classList.add(...t?Bs:zs)}var Ws=(e,t=`px-3 py-1 text-[12px] leading-snug text-neutral-500`)=>c(`p`,t,e);function Gs(){let e=c(`div`,`flex w-72 flex-col gap-1 py-1`);if(!J)return e.append(Ws(`Checking the registry…`)),e;let{current:t,latest:n,available:r,canApply:i,problem:a}=J,o=c(`span`,``,``),s=(e,t)=>d(o,e?`failed`:`idle`,t),l=c(`div`,`flex items-center gap-2 px-3 py-1.5`);if(e.append(Ws(r?`Pier ${n} is out`:`Pier ${t}`,`px-3 py-1 text-[12.5px] font-medium text-neutral-700`),Ws(r?`You are running ${t}.`:n===null?`The registry could not be reached, so this may not be the latest.`:`This is the latest release.`)),a&&e.append(Ws(a,`mx-3 my-1 rounded-md bg-red-50 px-2 py-1.5 text-[11.5px] leading-snug text-red-700`)),r&&i&&!a){let e=p(`Update now`,!0);e.onclick=()=>void(async()=>{e.disabled=!0,s(!1,`starting the updater…`);let t=await _(`/api/update`,{});if(!t.ok)return e.disabled=!1,s(!0,await v(t,`Could not update`));let{draining:n}=await t.json();s(!1,n?`Waiting for running work to finish — Pier then installs and restarts.`:`Installing — Pier restarts once it is on disk, and this page reconnects on its own.`)})(),l.append(e)}l.append(Object.assign(c(`a`,`btn text-[12.5px] no-underline`,`Source`),{href:r?`${Rs}/releases`:Rs,target:`_blank`,rel:`noreferrer`,title:`Pier is free software (AGPL-3.0)`})),e.append(l,c(`div`,`px-3`,o)),r&&!i&&!a&&e.append(Ws(`No service manager owns this Pier, so it cannot restart itself — update it with: pier update`));let u=ee(`Update automatically`,i?`Installs a new release once nothing is running — no turn in flight, no task run.`:`Needs the systemd service (pier service install); nothing here can restart Pier.`,J.autoUpdate,e=>void(async()=>{J&&(J.autoUpdate=e);let t=await _(`/api/settings`,{autoUpdate:e},`PUT`);t.ok||(J&&(J.autoUpdate=!e),f&&(f.checked=!e),s(!0,await v(t,`Could not save`)))})()),f=u.querySelector(`input`);return f&&(f.disabled=!i),e.append(c(`div`,`mt-1 border-t border-neutral-200 px-3 pb-1 pt-2`,u)),e}async function Ks(e){let t=await Te(`/api/update`,`Update check failed`);t.ok&&Us((J=t.value).current||e)}function qs(e){Us(e),Hs.onclick=e=>{e.preventDefault(),pe(Hs,Gs())};let t=()=>void Ks(e);t(),setInterval(t,Vs)}var Y,Js=t(`#composer`),Ys=[t(`#bar`),E,Js],Xs=()=>$s===null,Zs=new Map,Qs=new Map,$s=null,ec=0,tc=new Map,nc={settings:`Settings`};function rc(e,t,n){let r=fc();r&&(r.kind!==`console`||r.name!==e)&&tc.set(e,r),mc({kind:`console`,name:e,arg:t,query:n}),$s=e;for(let e of Ys)e.classList.add(`hidden`);Xi();for(let[t,n]of Zs)t!==e&&n.hide();ic(e,t,n,++ec)}async function ic(e,n,r,i){let a=Zs.get(e);if(!a){let n=Qs.get(e);if(!n){let r=t(`#${e}-view`);n=yc[e](r).catch(t=>(console.warn(`${e} view failed to load`,t),o(r,()=>r.replaceChildren(c(`p`,`p-4 text-[13px] text-red-600`,`Could not load ${nc[e]} — reload the page.`))))),Qs.set(e,n)}a=await n,Zs.set(e,a),Qs.delete(e)}$s===e&&i===ec&&a.show(n,r)}var ac=(e,t)=>void ve(()=>import(`./explorer-BoU77faI.js`).then(n=>n.openFiles(Y.currentSession(),e,t)),__vite__mapDeps([0,1,2])),oc=()=>void ve(()=>import(`./explorer-BoU77faI.js`).then(e=>e.toggleFiles(Y.currentSession())),__vite__mapDeps([0,1,2]));function sc(e){let t=Y.currentId(),n=tc.get(e)??(t?hc(t):lc);tc.delete(e),mc(n)}function cc(){if($s){$s=null;for(let e of Zs.values())e.hide();for(let e of Ys)e.classList.remove(`hidden`);Xi(),Y.maybeAckRead()}}var lc={kind:`conversation`},uc=e=>e.kind===`session`?`#/session/${encodeURIComponent(e.id)}`:e.kind===`conversation`?`#/conversation`:`#/${e.name}${e.arg?`/${encodeURIComponent(e.arg)}`:``}${e.query?`?${e.query}`:``}`,dc={config:`files`,channels:`channels`,providers:`models`};function fc(){let e=location.hash.replace(/^#\/?/,``),t=e.indexOf(`?`),[n=``,r]=(t<0?e:e.slice(0,t)).split(`/`),i=t<0?void 0:e.slice(t+1)||void 0,a;try{a=r?decodeURIComponent(r):void 0}catch{return null}return dc[n]?{kind:`console`,name:`settings`,arg:dc[n]}:Object.hasOwn(nc,n)?{kind:`console`,name:n,arg:a,query:i}:n===`session`&&a?{kind:`session`,id:a}:n===`conversation`?lc:null}var pc=!1;function mc(e,t=!1){if(pc)return;let n=uc(e);location.hash!==n&&(t?history.replaceState(null,``,n):location.hash=n)}var hc=e=>Y.inConversation(e)?lc:{kind:`session`,id:e},gc=e=>mc(hc(e)),_c=()=>mc(lc);function vc(){let e=fc()??lc;pc=!0;try{e.kind===`conversation`?Y.openContinuous():e.kind===`session`?e.id===Y.currentId()?cc():Y.select(e.id):(Y.currentId()||Y.openContinuous(),rc(e.name,e.arg,e.query))}finally{pc=!1}e.kind===`conversation`?mc(lc,!0):e.kind===`session`&&mc(hc(e.id),!0)}var yc={settings:async e=>(await ve(async()=>{let{createSettingsView:e}=await import(`./settings-BprIId_R.js`);return{createSettingsView:e}},__vite__mapDeps([3,1,2]))).createSettingsView(e,()=>dt(Y.sessions()),e=>rc(`settings`,e),ac,()=>sc(`settings`))};function bc(e){Y=e,window.onhashchange=vc}var X=[],xc=null,Sc=0,Cc=!1,Z=null,wc=`idle`,Tc=null,Ec=0,Dc=!1,Oc=!1,kc=[],Ac=null,Q=[],jc=!1,Mc=!1,Nc=0,Pc=null,Fc=()=>kc[0]?.sessionId??null,Ic=e=>kc.some(t=>t.sessionId===e),Lc=()=>jc||Z!==null&&Z===Fc(),Rc={first:`new session`,idle:`new session — idle 1h`,lost:`new session — the previous one was lost`,full:`new session — the previous one was full`,new:`new session — /new`};async function zc(){let e=await fetch(`/api/continuous`);if(!e.ok)throw Error(await v(e,`Could not load the continuous conversation`));let{chain:t,rotateAt:n}=await e.json();if(!Array.isArray(t)||typeof n!=`number`||!(n>0))throw Error(`The continuous conversation's chain is malformed`);return{chain:t,rotateAt:n}}async function Bc(){let e=await fetch(`/api/continuous/open`);if(!e.ok)throw Error(await v(e,`Could not load the open items`));return await e.json()}var Vc=fe(async()=>{Pc=await Bc(),z()});function Hc(){let e=Fc();if(e)return void tl(e);if(jc)return cc(),_c();++Sc,I(),cc(),Tc?.close(),Tc=null,Z=null,xc=null,wc=`idle`,jc=!0,Q=[],nl(),A(`system`,`The continuous conversation — your first message starts it.`),_c(),z(),q(),Yi(),Gi()}async function Uc(e){Q=[],jc=!1,await tl(e),kc.length>1&&await Wc()}async function Wc(){let e=Fc(),t=kc[Q.length+1];if(!(Mc||!e||!t||Z!==e)){Mc=!0;try{let n=await Te(`/api/sessions/${t.sessionId}/history`,`Could not load the earlier session`);if(Z!==e)return;Q.unshift(n.ok?{member:t,turns:n.value.turns,runs:n.value.backgroundRuns}:{member:t,turns:[],runs:[],error:n.error});let r=E.scrollHeight-E.scrollTop,i=document.activeElement?.id===`chain-pager`;await rl(e,!0),E.scrollTop=E.scrollHeight-r,i&&document.getElementById(`chain-pager`)?.focus({preventScroll:!0}),Nc=Date.now()}finally{Mc=!1}}}function Gc(){Q.length<kc.length-1&&Qr(()=>void Wc());for(let[e,t]of Q.entries()){t.error&&A(`error`,t.error),$r(t.turns,`idle`,t.runs,!0);let n=Q[e+1]?.member??kc[0];Zr(Rc[n.reason],n.startedAt)}}E.addEventListener(`scroll`,()=>{E.scrollTop<40&&Lc()&&!Cc&&Date.now()-Nc>500&&Wc()},{passive:!0});function Kc(e){X=e.map(e=>({...e,title:lt(e.title)})),X.sort((e,t)=>t.createdAt-e.createdAt),z(),q(),qc()}var $=fe(async()=>{let[e,t,n]=await Promise.all([ke(`/api/sessions`,`Could not load sessions`),zc(),Bc()]),r=Lc(),i=Fc();kc=t.chain,Ac=t.rotateAt,Pc=n,Kc(e);let a=Fc();r&&a&&a!==i&&await Uc(a)});function qc(){if(document.hidden||!document.hasFocus()||!Xs())return;let e=X.find(e=>e.id===Z);e?.unread&&(e.unread=!1,z(),fetch(`/api/sessions/${e.id}/read`,{method:`POST`}))}function Jc(){return X.find(e=>e.id===Z)??(xc&&xc.id===Z?xc:void 0)}async function Yc(e){let t=await Te(`/api/sessions/${e}`,`failed to load session`);Z!==e||!t.ok||(xc={...t.value,title:lt(t.value.title)},q())}function Xc(e,t){let n=X.find(t=>t.id===e);!n||n.title||!t.trim()||(n.title=t.trim().slice(0,80),z(),q())}function Zc(e){wc=e;let t=X.find(e=>e.id===Z);t&&(t.state=e),z(),q(),Yi(),e===`idle`&&$()}function Qc(e){if(!(e.sessionId!==Z||e.seq<=Ec))switch(Ec=e.seq,e.type){case`turn-start`:Dc=!0,Oc=!1;break;case`system-input`:Gr(),vr(e.text,e.origin),e.origin.kind===`task-message`&&Qi(e.origin.messageId);break;case`task-status`:yn(e.run);break;case`user-message`:{let t=ot(e.text).text;if(Xc(e.sessionId,t),Ki(t))break;Gr(),A(`user`,e.text,!1,e.ts),O();break}case`text-start`:Gr();break;case`text-delta`:Wr(e.text);break;case`thinking-delta`:Gr(),qn(e.ts,e.text);break;case`tool-start`:Gr(),Wn(e.ts,e.toolCallId,e.toolName,e.args);break;case`tool-end`:Kn(e.toolCallId,e.isError,e.output);break;case`turn-end`:Dc=!1,qr(e.text,e.meta),e.meta&&_s(e.meta);break;case`queue-state`:Zi(e.steering,e.followUp);break;case`context-compacted`:Gr(),A(`system`,`Context compacted — ${Ae(e.before)} → ${Ae(e.after)}`,!1,e.ts),O();break;case`error`:Hn(),A(`error`,e.message),Oc&&(Oc=!1,Zc(`idle`));break;case`state`:Oc=!1,e.state===`idle`&&Dc&&(Dc=!1,Jr()),e.state===`idle`&&Zi([],[]),Zc(e.state)}}function $c(){let e=new EventSource(`/api/events`);e.onopen=()=>void $(),e.onerror=()=>fi(e,`Workspace`),e.onmessage=e=>{let t=JSON.parse(e.data);if(t.type===`sessions-changed`){$();return}if(t.type===`tasks-changed`||t.type===`task-run-changed`||t.type===`task-message-changed`||t.type===`task-group-changed`){t.type===`task-run-changed`&&$();return}if(t.type===`open-items-changed`){Vc();return}if(Pc&&[...Pc.items.flatMap(e=>e.runs),...Pc.unlisted].some(e=>e.targetSessionId===t.sessionId)&&Vc(),t.sessionId===Z)return;let n=X.find(e=>e.id===t.sessionId);if(!n){$();return}n.state=t.state,z(),t.sessionId===Fc()&&q()}}function el(e,t,n){Tc?.close();let r=new EventSource(`/api/sessions/${e}/events?after=${t}`),i=()=>Tc===r&&Z===e&&n===Sc;r.onmessage=e=>{i()&&Qc(JSON.parse(e.data))},r.addEventListener(`reset`,()=>{i()&&rl(e)}),r.onerror=()=>{i()&&fi(r,`Session`)},Tc=r}async function tl(e){Ic(e)&&(e=Fc()),(e!==Z||jc)&&(Q=[],jc=!1),cc(),gc(e),!(e===Z&&(Tc||Cc))&&(++Sc,I(),Z=e,xc=null,X.some(t=>t.id===e)||Yc(e),wc=X.find(t=>t.id===e)?.state??`idle`,ya(e),z(),q(),qc(),await rl(e))}function nl(){Yr(),Zi([],[],[]),sa([]),hs(),Dc=!1,Oc=!1,Ji(),Ec=0}async function rl(e,t=!1){if(Z!==e)return;let n=++Sc;Tc?.close(),Tc=null,Cc=!0,t||(nl(),Xr(!0));let r=await Te(`/api/sessions/${e}/history`,`failed to load session`);if(Z!==e||n!==Sc)return;if(Cc=!1,t&&nl(),!r.ok){Xr(!1),A(`error`,r.error);return}let i=r.value;Lc()&&Gc(),$r(i.turns,i.state,i.backgroundRuns),Ec=i.lastSeq,Dc=i.state===`streaming`,Zc(i.state),Zi(i.queue.steering,i.queue.followUp,i.queue.parked),sa(i.skills);let a=i.turns.reduce((e,t)=>t.meta?.completedAt??e,null);gs(i.model,i.context,i.thinkingLevel,a),el(e,`${i.epoch}:${i.lastSeq}`,n)}ci(),ne(),di(),Ls();var il=e=>{Oc=e===`streaming`,Zc(e)},al=async e=>{Z===e&&await rl(e)};Qn({sessionId:()=>Z,sessionCwd:()=>Jc()?.cwd??null,sessionChannel:()=>Jc()?.channel??null,sessionState:()=>wc,select:e=>void tl(e),send:(e,t)=>void Sa(e,t),ownTurn:e=>{qi(e),il(`streaming`)},reload:al}),Ta({sessionId:()=>Z,sessionState:()=>wc,chatVisible:Xs,setState:il,reload:al,continuous:Lc,headMoved:()=>void $()}),Co({sessions:()=>X,currentId:()=>Z,select:e=>void tl(e),chain:()=>kc,openContinuous:Hc,open:()=>Pc}),Qo({sessions:()=>X,loadSessions:$,select:tl,openContinuous:Hc,openConsole:rc}),as({currentId:()=>Z,currentSession:Jc,openFiles:ac,toggleFiles:oc,openSettings:()=>rc(`settings`),continuousOpen:Lc,rotateAt:()=>Ac,openContinuous:Hc}),bc({sessions:()=>X,currentId:()=>Z,currentSession:Jc,select:e=>void tl(e),inConversation:Ic,openContinuous:Hc,maybeAckRead:qc}),qs(`0.3.1`),Ba(),document.addEventListener(`gesturestart`,e=>e.preventDefault()),document.addEventListener(`visibilitychange`,qc),window.addEventListener(`focus`,qc),$c(),$().then(vc);export{Ci as a,xi as i,rs as n,We as o,Ga as r,is as t};
|
|
Binary file
|
|
Binary file
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{A as e,At as t,B as n,C as r,D as i,Dt as a,E as o,Et as s,F as c,G as l,H as u,I as d,J as f,K as p,L as m,M as h,N as g,O as _,Ot as v,P as y,Q as b,R as x,S,T as C,U as w,Z as T,_ as E,_t as D,a as O,at as k,b as A,c as ee,d as te,f as j,g as M,h as N,it as P,j as F,jt as I,k as L,m as R,mt as z,n as B,nt as V,ot as H,p as ne,tt as U,v as W,vt as G,w as re,wt as K,x as q,y as J,yt as Y,z as ie}from"./highlight-CDSk2hRJ.js";import{i as ae,n as X,o as oe,r as se,t as Z}from"./index-D0ZYdweB.js";import{n as ce,t as le}from"./code-CWT27KH1.js";var ue=[[`path`,{d:`m18 15-6-6-6 6`}]],de=[[`path`,{d:`M15 3h6v6`}],[`path`,{d:`M10 14 21 3`}],[`path`,{d:`M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6`}]],fe=[[`path`,{d:`m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3`}],[`path`,{d:`M12 9v4`}],[`path`,{d:`M12 17h.01`}]],Q=e=>e.public&&e.token?`/p/${e.slug}-${e.token}/`:`/boards/${e.slug}/`;function $(){let e=f(`div`,`flex flex-col gap-2`),t=f(`span`,`text-[11.5px]`,``);async function n(e,n){let r=await H(`/api/boards/${e.slug}`,{public:n},`PATCH`);r.ok?y(t,`saved`,`${e.slug} is ${n?`public`:`private`}.`):y(t,`failed`,await U(r,`Could not change ${e.slug}`)),await o()}async function i(e){let n=await k(`/api/boards/${e.slug}`,`DELETE`,`Could not delete ${e.slug}`);n?y(t,`failed`,n):y(t,`saved`,`Deleted ${e.slug} — the folder is kept as ${e.slug}.deleted-<time>.`),await o()}function a(e){let t=f(`a`,`min-w-0 truncate text-[12.5px] font-medium text-neutral-700 hover:text-indigo-700`,e.title);t.href=Q(e),t.target=`_blank`,t.rel=`noreferrer`;let r=[e.slug,`updated ${T(Date.parse(e.updatedAt))}`];e.description&&r.push(e.description);let a=f(`div`,`flex min-w-0 flex-col gap-1`,t,f(`span`,`truncate text-[11.5px] text-neutral-400`,r.join(` · `))),o=x(``,``,e.public,t=>void n(e,t));o.title=`Public: anyone holding the /p/ link can read it, no password`,o.append(f(`span`,`text-[11.5px] text-neutral-500`,`Public`));let s=p(F(`hover:text-indigo-600`),()=>`${location.origin}${Q(e)}`);s.title=`Copy the board's link`;let c=q(`Delete`,F());return c.title=`Renames the folder on disk; nothing is erased`,c.onclick=()=>void i(e),f(`div`,`group flex items-center justify-between gap-3 rounded-lg border border-neutral-200 px-3 py-2`,a,f(`div`,`flex flex-none items-center gap-3`,o,s,c))}async function o(){let t=await V(`/api/boards`,`Could not load boards`);if(!t.ok)return void e.replaceChildren(C(t.error));e.replaceChildren(...t.value.length?t.value.map(a):[C(`No boards yet. Ask an agent to build one — it writes a folder under ~/.pier/boards.`)])}return{el:f(`div`,`mx-auto flex w-full min-w-0 max-w-3xl flex-col`,r(`Boards`,`Static pages agents wrote, freshest first. A private board opens on a link good for 8 hours; a public one on /p/<slug>-<token>/ for anyone holding it.`,e,t)),show:()=>void o()}}var pe={display_information:{name:`Pier`,description:`Coding agent sessions in Slack threads`,background_color:`#262626`},features:{bot_user:{display_name:`Pier`,always_online:!1},app_home:{messages_tab_enabled:!0,messages_tab_read_only_enabled:!1}},oauth_config:{scopes:{bot:[`chat:write`,`reactions:write`,`channels:history`,`channels:read`,`groups:history`,`groups:read`,`im:history`,`im:write`,`mpim:history`,`mpim:read`,`mpim:write`,`users:read`,`files:read`,`files:write`]}},settings:{event_subscriptions:{bot_events:[`message.channels`,`message.groups`,`message.im`,`message.mpim`]},interactivity:{is_enabled:!0},socket_mode_enabled:!0,token_rotation_enabled:!1}},me=()=>`https://api.slack.com/apps?new_app=1&manifest_json=${encodeURIComponent(JSON.stringify(pe))}`;function he(){let e=S(`Create Slack app`,!0);e.append(K(de)),e.classList.add(`inline-flex`,`items-center`,`gap-1.5`),e.classList.add(`mt-1`,`w-fit`),e.onclick=()=>window.open(me(),`_blank`,`noreferrer`);let t=p(`btn w-fit text-[12.5px]`,()=>JSON.stringify(pe,null,2));return i(`Creating a Slack app`,[ie(`Opens Slack with every scope, event and Socket Mode already filled in. Pick your workspace → Create.`,e),"`Install to Workspace` → allow. Then `OAuth & Permissions` → copy the bot token (`xoxb-…`) into the field above.","`Basic Information` → `App-Level Tokens` → `Generate` with scope `connections:write`. Paste that `xapp-…` token below. The manifest cannot mint this one for you.","In Slack, invite the bot where you want it: `/invite @Pier`. It answers in threads only, so it never adds noise to the channel.",ie(`Prefer to paste it yourself? Create the app from a manifest and use this:`,t)])}var ge=()=>i(`How Slack threads work here`,[`Pier never posts in a channel's main flow. A message in the channel is answered in *its own thread*; a message in a thread is answered in that thread.`,`Each thread is its own Pi session, so one channel hosts many parallel sessions.`,`The same applies in a DM: every new message you send there starts its own thread and its own session. Reply *inside* a thread to continue that conversation.`,"Inside a thread Pier already owns, no `@mention` is needed — continuing that thread is addressing it.","Commands start with `%`: `%settings`, `%stop`, `%bind <code>`, since Slack's client swallows an unregistered `/command` before it ever reaches an app. `%s <question>`, as the first message of a thread, drafts a session — directory, model, reasoning — and Start runs the question in it."]),_e=()=>i(`Creating a Feishu app`,["On [open.feishu.cn](https://open.feishu.cn/app) create a 企业自建应用 (custom app). `Credentials & Basic Info` shows the App ID (`cli_…`) and App Secret — paste both here.","`Add Features` → enable **Bot** (机器人).","`Permissions` (权限管理), add: `im:message` (read messages), `im:message:send_as_bot` (send), `im:resource` (attachments, both directions), `im:message.reactions:create` + `:read` + `:delete` (the 👀 receipt), `im:chat:readonly` (chat names for this page), `contact:user.base:readonly` (speaker names).","`Events & Callbacks` → set the mode to **长连接 (long connection)** — no public URL needed. Under Events subscribe `im.message.receive_v1` (接收消息); Callbacks gain `card.action.trigger` automatically once cards are sent, add it if listed.",`**Publish a version** (版本管理与发布 → 创建版本 → 申请发布). Nothing above takes effect until this is approved — the usual reason a configured bot stays silent.`,`Add the bot to a group (群设置 → 群机器人), or DM it directly.`]),ve=()=>i(`How Lark topics work here`,[`Pier never posts in a chat's main flow. A message in the chat is answered in *its own topic* (话题); a message inside a topic is answered there.`,`Each topic is its own Pi session, so one group hosts many parallel sessions.`,`The same applies in a DM: every new message starts its own topic and its own session. Reply *inside* a topic to continue that conversation.`,`Inside a topic Pier already owns, no @mention is needed — continuing that topic is addressing it.`,"Commands start with `/` or `%`: `/stop`, `/settings`, `/bind <code>`. `/s <question>`, outside any topic, drafts a session — directory, model, reasoning — and Start runs the question in it."]),ye=[[`slack`,`Slack`],[`lark`,`Lark`]],be={dm:`bg-sky-50 text-sky-700 ring-sky-200`,group:`bg-neutral-100 text-neutral-600 ring-neutral-200`},xe=`Discovered from inbound traffic — no platform reliably lists every chat a bot is in.`,Se=`pier.channelsPlatform`;function Ce(e){let t=localStorage.getItem(Se),n=ye.some(([e])=>e===t)?t:`slack`,i=null,a=[],s=f(`div`,`ml-auto flex items-center gap-1.5 text-[11.5px]`),c=f(`div`,`pagehead pagehead-hug sticky top-[-8px] z-30`,s),u=f(`div`,`px-4 pb-5 pt-4`);e.append(f(`div`,`min-h-0 flex-1 overflow-y-auto`,c,u));function p(){c.replaceChildren(h(ye.map(([e,t])=>[t,e]),n,e=>{m&&T(),n=e,localStorage.setItem(Se,e),E()}),s)}let m,g=!1,_=null;function v(e){if(s.replaceChildren(),e!==`clean`){if(s.className=`ml-auto flex items-center gap-1.5 text-[11.5px] ${J[e]}`,e===`saving`)s.append(K(oe,`spinner`),f(`span`,``,`Saving…`));else if(e===`saved`)s.append(K(I),f(`span`,``,`Saved`)),setTimeout(()=>{s.textContent?.includes(`Saved`)&&v(`clean`)},2e3);else{let e=q(`Retry`,`cursor-pointer underline`);e.onclick=T,s.append(K(fe),f(`span`,``,`Save failed`),e)}}}function y(){v(`saving`),clearTimeout(m),m=setTimeout(T,500)}let b=e=>t=>{e(t),y()};async function w(e){g=!0,v(`saving`);try{v((await H(`/api/channels/${e.platform}`,e.config,`PUT`)).ok?`saved`:`failed`)}catch{v(`failed`)}finally{g=!1;let e=_;_=null,e&&w(e)}}function T(){if(clearTimeout(m),m=void 0,!i)return;let e={platform:n,config:i};g?_=e:w(e)}async function E(){if(!a.length){let e=await V(`/api/models`,`Could not load the model catalog`);e.ok&&(a=e.value)}let e=await V(`/api/channels/${n}`,`Failed to load`);if(!e.ok){i=null,p(),u.replaceChildren(C(e.error));return}i=e.value,v(`clean`),M()}function D(e){let t=n===`lark`,i=d(e.token,t?`cli_…`:`xoxb-…`,b(t=>e.token=t),!0),a=d(e.appToken,t?``:`xapp-…`,b(t=>e.appToken=t),!0),s=O(e.cwd,`(pier process cwd)`,b(t=>e.cwd=t));return r(`Connection`,t?`Pier connects over Feishu's WebSocket long connection; no public URL or webhook needed.`:`Pier connects over Socket Mode; no public URL or webhook needed.`,x(`Enabled`,`Start the adapter when Pier boots.`,e.enabled,b(t=>{e.enabled=t,p()})),o(t?`App ID`:`Bot token`,i,{hint:`Stored locally, shown masked once saved.`,help:t?_e():he()}),t?o(`App Secret`,a,{hint:`From Credentials & Basic Info, beside the App ID.`}):o(`App-level token`,a,{hint:`Opens the Socket Mode connection. Needs connections:write.`}),o(`Default working directory`,s.el,{hint:`Where sessions this channel opens start.`}),f(`span`,`flex items-center gap-1.5 text-[13px] text-neutral-400`,f(`span`,``,t?`Every topic is its own session.`:`Every thread is its own session.`),t?ve():ge()))}function k(e){return r(`Defaults for new chats`,`Copied into a group the first time the bot sees it; changing them here never touches a group that already exists. DMs are always bound-users-only.`,x(`Require mention in groups`,`Ignore group messages that do not @mention or reply to the bot.`,e.requireMention,b(t=>e.requireMention=t)),x(`Require bound user`,`Only users bound with a code below can drive the agent.`,e.requireBind,b(t=>e.requireBind=t)),Z(`Model & reasoning`,e,a,b(t=>{e.model=t.model,e.thinking=t.thinking,M()})))}function ee(e){let t=f(`span`,`font-mono text-[15px] font-semibold tracking-widest`),i=f(`div`,`hidden items-center gap-2 rounded-lg bg-indigo-50 px-3 py-2 text-[12.5px] text-indigo-800`,t,f(`span`,`text-[11.5px] text-indigo-500`,`DM the bot /bind <code> · expires in 10 min`)),a=S(`Generate bind code`);a.onclick=async()=>{let e=await fetch(`/api/channels/${n}/bind-code`,{method:`POST`});if(!e.ok)return;let{code:r}=await e.json();t.textContent=r,i.classList.replace(`hidden`,`flex`)};let o=f(`div`,`flex flex-col`);e.users.length||o.append(C(`No bound users yet.`));for(let t of e.users){let e=q(`Remove`,F());e.onclick=async()=>{await fetch(`/api/channels/${n}/users/${encodeURIComponent(t.id)}`,{method:`DELETE`}),await E()},o.append(f(`div`,`group flex items-center gap-2.5 border-b border-neutral-100 py-2 last:border-0`,f(`span`,`flex h-6 w-6 flex-none items-center justify-center rounded-full bg-neutral-100 text-[11px] font-semibold text-neutral-500`,(t.name[0]??`?`).toUpperCase()),f(`span`,`min-w-0 flex-1 truncate text-[13px] text-neutral-700`,t.name),f(`span`,`flex-none font-mono text-[11.5px] text-neutral-400`,t.id),e))}return r(`Bound users`,`A code is single-use and expires; redeeming it in a DM binds that account.`,o,f(`div`,`flex flex-col gap-2`,a,i))}function te(e,t){let r=f(`div`,`group rounded-xl border px-3.5 py-3 transition-colors ${t.enabled?`border-neutral-200 bg-white`:`border-neutral-200 bg-neutral-50/60`}`),i=t.botId!==e.botId,s=q(`Remove`,F());s.onclick=async()=>{let e=t.name||t.id;window.confirm(`Remove ${e}? Threads in it lose their sessions; a chat the bot can still reach comes back on its next message.`)&&(await fetch(`/api/channels/${n}/chats/${encodeURIComponent(t.id)}`,{method:`DELETE`}),await E())};let c=f(`div`,`flex flex-wrap items-center gap-2`,f(`span`,`min-w-0 flex-1 basis-full truncate text-[13px] font-medium sm:basis-0 ${t.enabled?`text-neutral-800`:`text-neutral-400`}`,t.name||t.id),A(t.kind,be[t.kind]),...i?[A(t.botId?`other bot`:`no bot`,`bg-amber-50 text-amber-700 ring-amber-200`)]:[],f(`span`,`flex-none font-mono text-[11px] text-neutral-400`,t.id),s),l=x(``,``,t.enabled,b(e=>{t.enabled=e,M()}));l.classList.add(`flex-none`,`items-center`),c.append(l);let u=f(`div`,`mt-3 flex flex-wrap items-center gap-x-6 gap-y-2`);if(t.kind===`dm`?u.append(f(`span`,`text-[13px] text-neutral-400`,`Direct message · bound users only, mention not applicable`),x(`This DM is the conversation`,``,t.home===!0,b(n=>{for(let t of e.chats)delete t.home;n&&(t.home=!0),M()}))):u.append(x(`Require mention`,``,t.requireMention,b(e=>t.requireMention=e)),x(`Require bind`,``,t.requireBind,b(e=>t.requireBind=e))),i&&u.append(f(`span`,`w-full text-[12.5px] text-amber-700`,t.botId?`Last seen under bot ${t.botId}${e.botId?`, not the current ${e.botId}`:``} — remove it if nothing arrives here.`:`No message since Pier started recording bot identities — remove it if nothing arrives here.`)),t.home)return r.append(c,u,f(`p`,`mt-3 text-[13px] text-neutral-400`,`The conversation's model and reasoning are set from its ⋯ menu.`)),r;let d=O(t.cwd,``,b(e=>t.cwd=e)),p=f(`div`,`mt-3 grid grid-cols-1 gap-3 sm:grid-cols-2`,o(`Working directory`,d.el),Z(`Model & reasoning`,t,a,b(e=>{t.model=e.model,t.thinking=e.thinking,M()})));return r.append(c,u,p),r}function j(e){let t=f(`div`,`flex flex-col gap-2.5`);return e.chats.length?t.append(...e.chats.map(t=>te(e,t))):t.append(C(`None yet. Chats appear here after the bot sees a message in them.`)),r(n===`slack`?`Channels`:`Chats`,e.botId?`${xe} Current bot: ${e.botId}.`:xe,t)}function M(){if(!i)return;p();let e=f(`div`,`mx-auto flex max-w-3xl flex-col gap-4`);e.append(D(i),k(i),ee(i),j(i)),u.replaceChildren(e)}return l(e,()=>void E(),()=>{m&&T()})}var we=`Managed by the configuration subscription: the source's copy is applied on every sync. To edit here, pause it under Agent → Configuration sync.`,Te=async()=>{let e=await V(`/api/config-sync`,``,{cache:`no-store`});return e.ok&&e.value.enabled};function Ee(){let e=f(`div`,`min-h-0 min-w-0 flex-1 overflow-y-auto p-4`),t=f(`div`,`mx-auto flex max-w-3xl min-w-0 flex-col gap-4`),n=f(`p`,`text-[12px] break-words`),r=f(`section`,`flex min-w-0 flex-col gap-3 border-b border-neutral-200 pb-4`),i=f(`section`,`flex min-w-0 flex-col gap-3`);t.append(f(`h2`,`text-[14px] font-semibold text-neutral-700`,`Configuration sync`),n,r,i),e.append(t);let a=null,s=!1,c=!1,l=0,u=``,m=!1,h=e=>e?new Date(e).toLocaleString():`Never`;async function g(){let e=l,t=await V(`/api/config-sync`,`Could not load configuration sync`,{cache:`no-store`});if(!(c||e!==l)){if(!t.ok){y(n,`failed`,t.error);return}a=t.value,m||(u=a.sourceUrl),b()}}async function _(e){if(!s){++l,s=!0,b(),y(n,`saving`,`Working...`);try{let t=await H(`/api/config-sync`,{action:e,...e===`subscribe`?{url:u}:{}});if(!t.ok)throw Error(await U(t,`Configuration sync failed`));let r=await t.json();a=r,m=!1,u=r.sourceUrl,y(n,`saved`,r.result??`Saved`)}catch(e){y(n,`failed`,e instanceof Error?e.message:`Configuration sync failed`),await g()}finally{s=!1,c||b()}}}function v(e,t){let n=S(e);return n.disabled=s,n.onclick=()=>{_(t)},n}function b(){if(!a||c)return;if(r.replaceChildren(f(`h3`,`text-[13px] font-medium text-neutral-700`,`Publish`)),a.publishedPath){let e=`${a.publicUrl||window.location.origin}${a.publishedPath}`,t=d(e,``,()=>{},!0);t.readOnly=!0,t.setAttribute(`aria-label`,`Sharing URL`),r.append(t,f(`div`,`flex flex-wrap items-center gap-2`,p(`btn text-[12px]`,()=>e),v(`Revoke link`,`revoke`)))}else r.append(f(`div`,``,v(`Generate link`,`publish`)));r.append(f(`p`,`text-[12px] text-neutral-500`,`Anyone with the link can read shared prompts, model definitions, the default model and its reasoning effort. API keys, headers and endpoints stay private.`));let e=d(u,`https://example.com/config-sync/...`,e=>{u=e,m=!0},!0);e.type=`url`,e.setAttribute(`aria-label`,`Configuration source URL`),e.disabled=s||a.enabled;let t=x(`Automatic sync`,``,a.enabled,e=>{_(e?`subscribe`:`pause`)});t.querySelector(`input`).disabled=s;let n=f(`div`,`flex flex-wrap items-center gap-3`,t);a.enabled&&n.append(v(`Sync now`,`sync`)),i.replaceChildren(f(`h3`,`text-[13px] font-medium text-neutral-700`,`Source`),o(`Source URL`,e),n);let l=f(`dl`,`grid grid-cols-[auto_minmax(0,1fr)] gap-x-4 gap-y-1 text-[12px]`);for(let[e,t]of[[`Last checked`,h(a.lastChecked)],[`Last applied`,h(a.lastApplied)],[`Next check`,a.enabled?h(a.nextRunAt):`Paused`]])l.append(f(`dt`,`text-neutral-500`,e),f(`dd`,`min-w-0 break-words text-neutral-700`,t));i.append(l),a.error&&i.append(f(`p`,`text-[12px] break-words text-red-600`,a.error)),a.needsReload&&i.append(f(`p`,`text-[12px] text-amber-700`,`Reload pending; retry synchronization.`))}g();let C=setInterval(()=>{!s&&!m&&g()},15e3);return{el:e,dispose:()=>{c=!0,clearInterval(C)}}}var De=`text-[11.5px] text-neutral-400`,Oe=`bg-neutral-50 text-neutral-500 ring-neutral-200`,ke=`bg-amber-50 text-amber-700 ring-amber-100`,Ae=`Pi packages run with full system access: an extension executes arbitrary code, and a skill can instruct the model to run anything. Review the source before installing.`,je=e=>e===`pier`||e===`local`?e:e.replace(/^(npm|git):/,``).replace(/\.git$/,``).replace(/@[^@/]*$/,``).split(`/`).filter(Boolean).pop()??e,Me=e=>e.startsWith(`npm:`)?`npm`:/^(git:|(https?|ssh|git):\/\/)/.test(e)?`git`:`path`,Ne=e=>e.kind===`pier`||e.kind===`local`,Pe=e=>e.slice(0,e.lastIndexOf(`/`))||`/`;function Fe(e){let t=null,n=``,r=()=>{let t=e.cwd();return t?`?cwd=${encodeURIComponent(t)}`:``},i=t=>!Ne(t)&&t.scope===`global`&&e.cwd()===void 0;async function a(){let e=await V(`/api/packages${r()}`,`packages could not be loaded`,{cache:`no-store`});t=e.ok?e.value:null,n=e.ok?``:e.error}let s=(e,n)=>t?.packages.find(t=>t.source===e&&t.scope===n),c=(e,n,r)=>{for(let i of t?.packages.filter(t=>t.source===e)??[]){let e=i.resources.find(e=>e.kind===n&&e.path===r);if(e)return{pkg:i,resource:e}}};async function l(t,n,r){let i=e.cwd(),a=await P(`/api/packages/resource`,{source:t.source,kind:n.kind,path:n.path,enabled:r,...i?{cwd:i}:{}},`could not save`,`PUT`);return a.ok?(t.resources=t.resources.map(e=>e.kind===n.kind&&e.path===n.path?a.value:e),e.changed(),{state:`saved`,text:`Saved — sessions take it on their next message.`}):{state:`failed`,text:a.error}}let p=t=>{e.pane.replaceChildren(f(`p`,`px-4 py-3 text-[12.5px] leading-relaxed text-red-600`,t))},m=(...e)=>f(`div`,`flex min-h-0 flex-1 flex-col gap-4 overflow-y-auto p-4`,...e),h=(e,t,n=!0)=>[f(`dt`,`text-[12px] text-neutral-500`,e),f(`dd`,`text-[12px] leading-snug text-neutral-700 ${n?`font-mono break-all`:``}`,t)],g=(t,n)=>{let r=q(`Browse files`,`btn text-[12px]`);return r.onclick=()=>e.browse(t,n),r},_=(e,t,n,r,i)=>x(n,r,t.enabled,n=>void l(e,t,n).then(i));function v(t,n,r){let i=q(n.name,`font-mono text-[13px] text-neutral-700 hover:text-indigo-600 hover:underline`);i.onclick=()=>{let r={type:`resource`,source:t.source,kind:n.kind,path:n.path};e.select(r),T(r.source,r.kind,r.path)};let a=f(`div`,`flex min-w-0 flex-1 flex-col gap-0.5`,f(`span`,`flex flex-wrap items-center gap-2`,i,A(n.kind,Oe)),...n.state?[f(`span`,`text-[11.5px] leading-snug text-amber-700`,n.state)]:[]);return f(`div`,`flex max-w-2xl items-start gap-3 border-b border-neutral-100 py-2.5 last:border-0`,a,_(t,n,``,``,r))}function b(n,r,o){let c=e.claim(),l=s(n,r);if(!l)return p(`unknown package: ${n}`);let d=f(`span`,De,``);o&&y(d,o.state,o.text);let _=t?.busy===l.source;_&&!o&&y(d,`saving`,`${l.installedPath?`updating`:`installing`}…`);let x=t=>{e.live(c)&&b(n,r,t)},S=[...h(`Source`,l.source),...h(`Kind`,l.kind===`pier`?`built in — ships with Pier`:l.kind===`local`?`the agent directory's own files`:l.kind,!1),...l.version?h(`Version`,l.version):[],...l.installedPath===null?Ne(l)?[]:h(`Installed at`,`not installed`,!1):h(`Installed at`,f(`span`,`flex flex-wrap items-center gap-2`,f(`span`,`font-mono break-all`,l.installedPath),g(l.installedPath)),!1)],w=[];if(i(l)&&l.kind!==`path`){let i=t?.checkedAt?`checked ${u(Date.parse(t.checkedAt))}`:`not checked yet`,o=q(`Check for updates`,`btn text-[12px]`);o.disabled=_,o.onclick=()=>{o.disabled=!0,y(d,`saving`,`checking…`),P(`/api/packages/check`,{},`update check failed`).then(i=>{i.ok&&(t=i.value),e.changed();let a=s(n,r);x(i.ok?{state:`saved`,text:a?.updateAvailable?`Checked — an update is available.`:`Checked — up to date.`}:{state:`failed`,text:i.error})})},S.push(...h(`Updates`,f(`span`,`flex flex-wrap items-center gap-2`,f(`span`,l.updateAvailable?`text-emerald-700`:``,l.updateAvailable?`update available (${i})`:i),o),!1));let c=q(`Update`,`btn text-[12.5px]`);c.disabled=_,c.onclick=()=>{c.disabled=!0,t&&={...t,busy:l.source},e.changed(),x({state:`saved`,text:`updating…`}),P(`/api/packages/update`,{source:l.source},`update failed`).then(async t=>{await a(),e.changed();let n=t.ok?t.value.packages.find(e=>e.source===l.source):void 0;x(t.ok?{state:`saved`,text:`Updated${n?.version?` to ${n.version}`:``} — sessions take it on their next message.`}:{state:`failed`,text:t.error})})},w.push(c)}if(i(l)){let t=q(`Remove`,`btn text-[12.5px] text-neutral-600 hover:text-red-600`);t.disabled=_,t.onclick=()=>{let n=l.kind===`path`?`settings.json forgets it; the directory stays.`:`Its files are deleted and settings.json forgets it.`;window.confirm(`Remove ${l.source}? ${n}`)&&(t.disabled=!0,y(d,`saving`,`removing…`),P(`/api/packages/remove`,{source:l.source},`remove failed`).then(async t=>{if(!t.ok)return x({state:`failed`,text:t.error});await a(),e.select(null),e.live(c)&&e.pane.replaceChildren(f(`div`,`flex min-h-0 flex-1 items-center justify-center p-6`,C(`Removed ${l.source}.`)))}))},w.push(t)}e.pane.replaceChildren(e.paneBar(je(l.source),A(l.kind,Oe),...l.scope===`project`?[A(`project`,ke)]:[],...w.length?[f(`div`,`ml-auto flex flex-none items-center gap-2`,...w)]:[]),m(f(`dl`,`grid max-w-2xl grid-cols-[auto_1fr] gap-x-4 gap-y-1.5`,...S),l.resources.length?f(`div`,`flex max-w-2xl flex-col`,...l.resources.map(e=>v(l,e,x))):C(l.installedPath?`No extensions or skills.`:`Not installed — nothing to load.`),d))}let S=(t,n)=>t.kind===`pier`?n.kind===`skill`?`Pier's own skill. Off, no session is offered it.`:`Loaded from inside Pier — nothing installed, nothing to update. A session mid-turn keeps the tools it started with.`:`Written to ${e.cwd()?`this project's .pi/settings.json`:`settings.json`} as +path / −path for ${je(t.source)}; sessions pick it up on their next open.`;async function T(t,n,r,i){let a=e.claim(),o=c(t,n,r);if(!o)return p(`unknown ${n}: ${r}`);let{pkg:s,resource:l}=o,u=f(`span`,De,``);i&&y(u,i.state,i.text);let d=f(`div`,`min-h-0 flex-1 overflow-auto`),m=r.startsWith(`/`);if(e.pane.replaceChildren(e.paneBar(l.name,A(je(s.source),Oe),A(l.kind,Oe),f(`span`,`ml-auto flex flex-wrap items-center gap-2`,f(`span`,`font-mono text-[11px] text-neutral-400 break-all`,l.path),...m?[g(Pe(r),w(r))]:[])),f(`div`,`flex flex-none flex-col gap-2 border-b border-neutral-200 px-4 py-3`,_(s,l,`Enabled`,S(s,l),i=>{e.live(a)&&T(t,n,r,i)}),...l.state?[f(`p`,`text-[12px] text-amber-700`,l.state)]:[],u),d),r.startsWith(`<inline:`)){d.append(f(`p`,`px-4 py-3 text-[12.5px] text-neutral-400`,`Loaded from inside Pier — there is no file to show.`));return}let h=await E(r);if(!e.live(a))return;if(!h.ok)return d.append(f(`p`,`px-4 py-3 text-[12.5px] text-red-600`,h.error));let v=await B(r);e.live(a)&&d.append(le(ce(h.value),v))}async function E(e){let t=`/api/fs/file?root=${encodeURIComponent(Pe(e))}&path=${encodeURIComponent(w(e))}`,n;try{n=await fetch(t,{cache:`no-store`})}catch(t){return{ok:!1,error:`could not read ${e}: ${String(t)}`}}return n.ok?{ok:!0,value:await n.text()}:{ok:!1,error:await U(n,`could not read ${e}`)}}function D(n,r=``){let i=e.claim(),s=f(`span`,De,``);n&&y(s,n.state,n.text);let c=r,l=d(r,`npm:@scope/name · git:github.com/owner/repo · /path/to/package`,e=>c=e,!0),u=q(`Install`,`btn btn-primary text-[12.5px]`),p=()=>{let n=c.trim();if(!n)return y(s,`failed`,`A package source is required.`);u.disabled=!0,y(s,`saving`,`installing ${n}…`),t&&(t={...t,busy:n,packages:[...t.packages,{source:n,kind:Me(n),scope:`global`,version:null,installedPath:null,updateAvailable:!1,resources:[]}]},e.changed()),P(`/api/packages`,{source:n},`install failed`).then(async t=>{if(await a(),e.changed(),!e.live(i))return;if(!t.ok)return D({state:`failed`,text:t.error},n);let{package:r}=t.value;e.select({type:`package`,source:r.source,scope:r.scope}),b(r.source,r.scope,{state:`saved`,text:`Installed ${r.source} — sessions take it on their next message.`})})};u.onclick=p,l.onkeydown=e=>{e.key===`Enter`&&p()},e.pane.replaceChildren(e.paneBar(`Add package`),m(f(`div`,`flex max-w-2xl flex-col gap-3`,o(`Source`,l,{hint:"What `pi install` takes: an npm package, a git URL (both may pin @version), or a directory on this machine."}),f(`p`,`text-[12.5px] leading-relaxed text-amber-800`,Ae),f(`div`,`flex items-center gap-3`,u,s)))),l.focus()}return{get registry(){return t},get error(){return n},load:a,openPackage:b,openResource:T,openAdd:D}}async function Ie(e,t){let n;try{n=await H(`/api/settings`,e,`PUT`)}catch(e){return{outcome:{state:`failed`,text:`Could not save: ${String(e)}`}}}if(!n.ok)return{outcome:{state:`failed`,text:await U(n,`could not save`)}};let r;try{r=await n.json()}catch(e){return{outcome:{state:`failed`,text:`Saved, but the answer could not be read: ${String(e)}`}}}return r.toolsSync?.state===`refused`?{outcome:{state:`failed`,text:`Saved, but nothing will install it: ${r.toolsSync.reason}`},answer:r}:r.toolsSync?.state===`waiting`?{outcome:{state:`saved`,text:`Saved — a sync is already running; this change goes in the run right after it.`},answer:r}:{outcome:{state:`saved`,text:t},answer:r}}function Le(e,t){return e.enabled?{body:{tool:{name:e.name,on:!1}},saved:`Switched ${e.name} off — the next run uninstalls it. Remove it again once its binary is gone.`}:{body:{customTools:t.filter(t=>t.name!==e.name)},saved:`Removed ${e.name}.`}}function Re(e,n,r){let i=`global`,a=null,s=0,c=0,u=``,p=()=>u?`Global (${u})`:`Global`,m=null,h=[],g=``,_=null,b=null,S=()=>{b?.dispose(),b=null},T=()=>{S(),++c,b=Ee(),I.replaceChildren(b.el)},E=[],D=e=>e.custom===!0,O=f(`span`,`min-w-0 flex-1 truncate`),k=f(`button`,`${N} flex items-center gap-1.5`,O,K(t,`h-3.5 w-3.5 text-neutral-500`));k.setAttribute(`aria-haspopup`,`true`),k.onclick=()=>{if(k.getAttribute(`aria-expanded`)===`true`)return ee();te(k,[{label:p(),checked:i===`global`,onSelect:()=>be(`global`)},...n().map(e=>({label:e,hint:w(e),checked:i===e,onSelect:()=>be(e)}))],`Scope`)};let j=f(`div`,`${ne} flex-col items-stretch gap-1.5 px-3 py-2.5`);j.append(f(`span`,`field-label`,`Scope`),k);let P=f(`div`,`min-h-0 flex-1 overflow-y-auto py-1.5`),F=f(`nav`,`${M} w-64 flex-none text-[13px] leading-5 max-md:max-h-48 max-md:w-full`);F.append(j,P);let I=f(`div`,`${M} min-w-0 flex-1`),L=f(`div`,`flex min-h-0 flex-1 gap-3 px-4 pb-4 pt-1 max-md:flex-col`);L.append(F,I),e.append(L);let z=(e,...t)=>f(`div`,`${ne} flex-wrap gap-3 px-4 py-2.5`,f(`span`,`font-mono text-[12.5px] text-neutral-500`,e),...t),W=Fe({pane:I,paneBar:z,claim:()=>++c,live:e=>e===c,cwd:()=>i===`global`?void 0:i,changed:()=>$(m),browse:r,select:e=>{a=e,e?.type===`resource`&&Z.set(e.source,!0),$(m)}}),G=(e=``)=>`?scope=${encodeURIComponent(i)}${e}`;async function re(){if(i!==`global`){h=[],g=``;return}let e=await V(`/api/settings`,`could not be loaded`,{cache:`no-store`});if(!e.ok){h=[],g=e.error;return}J(e.value),g=``}function J(e){h=e.catalog,E=e.customTools,_=e.toolsTaskId}async function Y(e,t){let{outcome:n,answer:r}=await Ie(e,t);return r&&(J(r),$(m)),n}async function ie(){let e=++s;c++;let[t]=await Promise.all([V(`/api/config${G()}`,`failed to load config`,{cache:`no-store`}),re(),W.load()]);if(e!==s)return;if(!t.ok){$(null),me(t.error);return}let n=t.value;i===`global`&&n.dir&&(u=n.dir,xe()),m=n,$(n),a?a.type===`sync`&&T():pe()}function ae(e,t){return f(`div`,`flex items-center justify-between gap-2 px-3 pb-1 pt-3 text-[10.5px] font-semibold uppercase tracking-wide text-neutral-400`,f(`span`,``,e),...t?[t]:[])}let X=e=>f(`span`,`flex-none rounded bg-neutral-100 px-1 text-[10px] font-semibold uppercase tracking-wide text-neutral-500`,e),oe=()=>f(`span`,`flex-none rounded bg-emerald-50 px-1 text-[10px] font-semibold uppercase tracking-wide text-emerald-700`,`on`);function se(e,t,n,r,i={}){let a=f(`button`,`config-row flex w-full cursor-pointer items-center gap-1.5 py-1.5 pr-3 text-left transition-colors hover:bg-neutral-100 ${t?`bg-indigo-50 font-medium hover:bg-indigo-50`:``} ${n?`text-neutral-400`:``}`),o=f(`span`,`truncate`,e);if(i.note){let e=f(`span`,`truncate text-[11px] font-normal leading-4 text-amber-700`,i.note);e.title=i.note,a.append(f(`span`,`flex min-w-0 flex-1 flex-col`,o,e))}else a.append(o);return a.append(...i.tags??[]),a.style.paddingLeft=`${i.flush?0:20+(i.depth??0)*14}px`,a.title=e,a.onclick=r,a}let Z=new Map;function ue(e,t,n,r){let i=Z.get(e)??n.openByDefault,a=f(`button`,`flex w-5 flex-none cursor-pointer items-center justify-center self-stretch text-neutral-500 hover:bg-neutral-100`,K(v,`chev h-3 w-3`));i&&a.classList.add(`chev-open`),a.title=`${i?`Collapse`:`Expand`} ${t}`,a.setAttribute(`aria-label`,a.title),a.setAttribute(`aria-expanded`,String(i)),a.onclick=()=>{Z.set(e,!i),$(m)};let o=se(t,n.active,n.dim,n.onPick,{tags:n.tags,flush:!0}),s=[f(`div`,`flex items-stretch ${n.active?`bg-indigo-50`:``}`,a,o)];return i?[...s,...r()]:s}function de(e,t,n){let r={type:`package`,source:e.source,scope:e.scope},i=[];return W.registry?.busy===e.source?i.push(f(`span`,`flex-none text-[11px] text-neutral-400`,e.installedPath?`updating…`:`installing…`)):e.resources.some(e=>e.enabled)&&i.push(oe()),e.scope===`project`&&i.push(X(`project`)),ue(e.source,je(e.source),{active:t(r),dim:e.installedPath===null&&!Ne(e),tags:i,onPick:()=>n(r),openByDefault:Ne(e)},()=>fe(e,t,n))}function fe(e,t,n){let r=[],i=e.resources.map(e=>e.name),a=new Set(i.filter((e,t)=>i.indexOf(e)!==t));for(let[i,o]of[[`extensions`,`extension`],[`skills`,`skill`]]){let s=e.resources.filter(e=>e.kind===o);if(!s.length)continue;let c=f(`div`,`py-0.5 text-[10.5px] font-semibold uppercase tracking-wide text-neutral-400`,i);c.style.paddingLeft=`34px`,r.push(c);for(let i of s){let s={type:`resource`,source:e.source,kind:o,path:i.path};r.push(se(i.name,t(s),!i.enabled,()=>n(s),{depth:2,note:i.state,tags:a.has(i.name)?[X(o)]:[]}))}}return r}function Q(e,t){let n={type:`tools`};return ue(`tools`,`tools`,{active:e(n),dim:!1,tags:h.some(e=>e.enabled)?[oe()]:[],onPick:()=>t(n),openByDefault:!0},()=>g?[f(`p`,`py-1 pl-5 pr-3 text-[12.5px] text-red-600`,g)]:h.map(n=>{let r={type:`tool`,name:n.name};return se(n.name,e(r),!n.enabled,()=>t(r),{depth:1,note:n.binary.error,tags:D(n)?[X(`yours`)]:[]})}))}function $(e){if(!e){P.replaceChildren();return}let t=e=>JSON.stringify(e)===JSON.stringify(a),n=t=>{S(),a=t,$(e),t.type===`file`?he(t.name,t.readonly,t.managed):t.type===`tools`||t.type===`tool`?ve():t.type===`sync`?T():t.type===`package`?W.openPackage(t.source,t.scope):t.type===`resource`?W.openResource(t.source,t.kind,t.path):W.openAdd()},r=[];if(i===`global`){let e={type:`sync`};r.push(ae(`Instance`),se(`Configuration sync`,t(e),!1,()=>n(e)))}r.push(ae(`Files`));for(let i of e.files){let e={type:`file`,name:i.name,readonly:i.readonly,managed:i.managed};r.push(se(i.name,t(e),!i.exists,()=>n(e)))}let o={type:`add`},s=q(`Add package`,`normal-case tracking-normal hover:underline ${t(o)?`text-indigo-700`:`text-indigo-600`}`);s.onclick=()=>n(o),r.push(ae(`Packages`,i===`global`?s:void 0)),W.error&&r.push(f(`p`,`py-1 pl-5 pr-3 text-[12.5px] text-red-600`,W.error));for(let e of W.registry?.packages??[])r.push(...de(e,t,n));i===`global`&&r.push(...Q(t,n)),P.replaceChildren(...r)}function pe(){I.replaceChildren(f(`div`,`flex min-h-0 flex-1 items-center justify-center p-6`,C(`Select a file to edit, or a package, extension, skill or tool to switch.`)))}function me(e){I.replaceChildren(f(`p`,`px-4 py-3 text-[12.5px] leading-relaxed text-red-600`,e))}async function he(e,t,n){let r=++c,i=await V(`/api/config/files/${encodeURIComponent(e)}${G()}`,`failed to load ${e}`,{cache:`no-store`});if(!i.ok){r===c&&me(i.error);return}if(r!==c)return;let{content:a}=i.value,o=a,s=f(`span`,`text-[11.5px] text-neutral-400`,``),l=f(`button`,`btn btn-primary text-[12.5px]`,`Save`),u=document.createElement(`textarea`);u.className=`block min-h-0 flex-1 resize-none bg-white p-4 font-mono text-[13px] leading-relaxed focus:outline-none`,u.spellcheck=!1,u.value=a;let d=async()=>{if(l.disabled)return;let t=u.value;l.disabled=!0,y(s,`saving`,`saving…`);try{let n=await H(`/api/config/files/${encodeURIComponent(e)}${G()}`,{content:t,expected:o},`PUT`);if(!n.ok)return y(s,`failed`,await U(n,`save failed`));let r=await n.json();o=r.content,u.value===t?(u.value=r.content,y(s,`saved`,`saved — applies to new sessions`)):y(s,`idle`,`saved; newer changes are unsaved`)}catch(e){y(s,`failed`,`save failed: ${String(e)}`)}finally{l.disabled=!1}},p=f(`button`,`btn text-[12.5px]`,`Edit`),m=f(`button`,`btn text-[12.5px]`,`View`),h=(...e)=>f(`div`,`ml-auto flex flex-none items-center gap-2`,...e),g=()=>{I.replaceChildren(z(e,s,h(m,l)),u),u.focus()},_=async()=>{let i=await B(e);if(r!==c)return;let a=n?we:t?`Pier manages this file: the default model is set in Settings → Models; other keys are edited on disk, then pier reload.`:null;I.replaceChildren(a?z(e,f(`span`,`ml-auto text-[11px] uppercase tracking-wide text-neutral-400`,`read-only`)):z(e,s,h(p)),...a?[f(`p`,`border-b border-neutral-200 px-4 py-2 text-[12.5px] leading-relaxed text-neutral-500`,a)]:[],f(`div`,`min-h-0 flex-1 overflow-auto`,le(ce(u.value),i)))};p.onclick=g,m.onclick=()=>void _(),l.onclick=()=>void d(),u.onkeydown=e=>{(e.metaKey||e.ctrlKey)&&e.key===`s`&&(e.preventDefault(),d())},u.oninput=()=>{y(s,`idle`,`unsaved changes`)},await _()}let ge=()=>{let e=f(`a`,`text-indigo-600 hover:underline`,`ubix`);return e.href=`https://github.com/timqi/ubix`,e.target=`_blank`,e.rel=`noreferrer`,e};function _e(e){let{spec:t,error:n,installed:r,version:i,path:a}=e.binary;return n?`${t} — ${n}`:r?`${t} — ${i??`unknown version`} at ${a??`an unknown path`}`:`${t} — not installed`}function ve(e,t={name:``,toml:``}){c++;let n=a?.type===`tool`?a.name:null,r=f(`span`,`text-[11.5px] text-neutral-400`,``);e&&y(r,e.state,e.text);let i=h.map(e=>{let t=f(`div`,`flex min-w-0 flex-1 flex-col gap-0.5`,f(`span`,`flex items-center gap-2 text-[13px] text-neutral-700`,f(`span`,`font-mono`,e.name),...D(e)?[A(`yours`,`bg-neutral-50 text-neutral-500 ring-neutral-200`)]:[]),f(`span`,`text-[11.5px] leading-snug text-neutral-400`,e.summary||_e(e)),...e.summary?[f(`span`,`font-mono text-[11px] leading-snug ${e.binary.error?`text-red-600`:`text-neutral-400`}`,_e(e))]:[]),r=x(``,``,e.enabled,t=>void ye(e.name,t,e=>ve(e))),i=f(`button`,`btn text-[12px] text-neutral-500 hover:text-red-600`,`Remove`);return i.onclick=()=>{i.disabled=!0;let t=Le(e,E);Y(t.body,t.saved).then(e=>ve(e))},f(`div`,`flex max-w-2xl items-start gap-3 border-b border-neutral-100 py-2.5 last:border-0 ${e.name===n?`rounded bg-indigo-50 ring-8 ring-indigo-50`:``}`,t,...D(e)?[i]:[],r)}),s={...t},l=f(`span`,`font-mono text-[12px] text-neutral-500`,`[tools.<name>]`),u=d(s.name,`claude`,e=>{s.name=e,l.textContent=`[tools.${e.trim()||`<name>`}]`},!0),p=document.createElement(`textarea`);p.className=`${R} h-24 resize-y font-mono leading-snug`,p.spellcheck=!1,p.value=s.toml,p.placeholder=`spec = "github:owner/repo"
|
|
1
|
+
import{A as e,At as t,B as n,C as r,D as i,Dt as a,E as o,Et as s,F as c,G as l,H as u,I as d,J as f,K as p,L as m,M as h,N as g,O as _,Ot as v,P as y,Q as b,R as x,S,T as C,U as w,Z as T,_ as E,_t as D,a as O,at as k,b as A,c as ee,d as te,f as j,g as M,h as N,it as P,j as F,jt as I,k as L,m as R,mt as z,n as B,nt as V,ot as H,p as ne,tt as U,v as W,vt as G,w as re,wt as K,x as q,y as J,yt as Y,z as ie}from"./highlight-CDSk2hRJ.js";import{i as ae,n as X,o as oe,r as se,t as Z}from"./index-DqLJpDE0.js";import{n as ce,t as le}from"./code-CWT27KH1.js";var ue=[[`path`,{d:`m18 15-6-6-6 6`}]],de=[[`path`,{d:`M15 3h6v6`}],[`path`,{d:`M10 14 21 3`}],[`path`,{d:`M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6`}]],fe=[[`path`,{d:`m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3`}],[`path`,{d:`M12 9v4`}],[`path`,{d:`M12 17h.01`}]],Q=e=>e.public&&e.token?`/p/${e.slug}-${e.token}/`:`/boards/${e.slug}/`;function $(){let e=f(`div`,`flex flex-col gap-2`),t=f(`span`,`text-[11.5px]`,``);async function n(e,n){let r=await H(`/api/boards/${e.slug}`,{public:n},`PATCH`);r.ok?y(t,`saved`,`${e.slug} is ${n?`public`:`private`}.`):y(t,`failed`,await U(r,`Could not change ${e.slug}`)),await o()}async function i(e){let n=await k(`/api/boards/${e.slug}`,`DELETE`,`Could not delete ${e.slug}`);n?y(t,`failed`,n):y(t,`saved`,`Deleted ${e.slug} — the folder is kept as ${e.slug}.deleted-<time>.`),await o()}function a(e){let t=f(`a`,`min-w-0 truncate text-[12.5px] font-medium text-neutral-700 hover:text-indigo-700`,e.title);t.href=Q(e),t.target=`_blank`,t.rel=`noreferrer`;let r=[e.slug,`updated ${T(Date.parse(e.updatedAt))}`];e.description&&r.push(e.description);let a=f(`div`,`flex min-w-0 flex-col gap-1`,t,f(`span`,`truncate text-[11.5px] text-neutral-400`,r.join(` · `))),o=x(``,``,e.public,t=>void n(e,t));o.title=`Public: anyone holding the /p/ link can read it, no password`,o.append(f(`span`,`text-[11.5px] text-neutral-500`,`Public`));let s=p(F(`hover:text-indigo-600`),()=>`${location.origin}${Q(e)}`);s.title=`Copy the board's link`;let c=q(`Delete`,F());return c.title=`Renames the folder on disk; nothing is erased`,c.onclick=()=>void i(e),f(`div`,`group flex items-center justify-between gap-3 rounded-lg border border-neutral-200 px-3 py-2`,a,f(`div`,`flex flex-none items-center gap-3`,o,s,c))}async function o(){let t=await V(`/api/boards`,`Could not load boards`);if(!t.ok)return void e.replaceChildren(C(t.error));e.replaceChildren(...t.value.length?t.value.map(a):[C(`No boards yet. Ask an agent to build one — it writes a folder under ~/.pier/boards.`)])}return{el:f(`div`,`mx-auto flex w-full min-w-0 max-w-3xl flex-col`,r(`Boards`,`Static pages agents wrote, freshest first. A private board opens on a link good for 8 hours; a public one on /p/<slug>-<token>/ for anyone holding it.`,e,t)),show:()=>void o()}}var pe={display_information:{name:`Pier`,description:`Coding agent sessions in Slack threads`,background_color:`#262626`},features:{bot_user:{display_name:`Pier`,always_online:!1},app_home:{messages_tab_enabled:!0,messages_tab_read_only_enabled:!1}},oauth_config:{scopes:{bot:[`chat:write`,`reactions:write`,`channels:history`,`channels:read`,`groups:history`,`groups:read`,`im:history`,`im:write`,`mpim:history`,`mpim:read`,`mpim:write`,`users:read`,`files:read`,`files:write`]}},settings:{event_subscriptions:{bot_events:[`message.channels`,`message.groups`,`message.im`,`message.mpim`]},interactivity:{is_enabled:!0},socket_mode_enabled:!0,token_rotation_enabled:!1}},me=()=>`https://api.slack.com/apps?new_app=1&manifest_json=${encodeURIComponent(JSON.stringify(pe))}`;function he(){let e=S(`Create Slack app`,!0);e.append(K(de)),e.classList.add(`inline-flex`,`items-center`,`gap-1.5`),e.classList.add(`mt-1`,`w-fit`),e.onclick=()=>window.open(me(),`_blank`,`noreferrer`);let t=p(`btn w-fit text-[12.5px]`,()=>JSON.stringify(pe,null,2));return i(`Creating a Slack app`,[ie(`Opens Slack with every scope, event and Socket Mode already filled in. Pick your workspace → Create.`,e),"`Install to Workspace` → allow. Then `OAuth & Permissions` → copy the bot token (`xoxb-…`) into the field above.","`Basic Information` → `App-Level Tokens` → `Generate` with scope `connections:write`. Paste that `xapp-…` token below. The manifest cannot mint this one for you.","In Slack, invite the bot where you want it: `/invite @Pier`. It answers in threads only, so it never adds noise to the channel.",ie(`Prefer to paste it yourself? Create the app from a manifest and use this:`,t)])}var ge=()=>i(`How Slack threads work here`,[`Pier never posts in a channel's main flow. A message in the channel is answered in *its own thread*; a message in a thread is answered in that thread.`,`Each thread is its own Pi session, so one channel hosts many parallel sessions.`,`The same applies in a DM: every new message you send there starts its own thread and its own session. Reply *inside* a thread to continue that conversation.`,"Inside a thread Pier already owns, no `@mention` is needed — continuing that thread is addressing it.","Commands start with `%`: `%settings`, `%stop`, `%bind <code>`, since Slack's client swallows an unregistered `/command` before it ever reaches an app. `%s <question>`, as the first message of a thread, drafts a session — directory, model, reasoning — and Start runs the question in it."]),_e=()=>i(`Creating a Feishu app`,["On [open.feishu.cn](https://open.feishu.cn/app) create a 企业自建应用 (custom app). `Credentials & Basic Info` shows the App ID (`cli_…`) and App Secret — paste both here.","`Add Features` → enable **Bot** (机器人).","`Permissions` (权限管理), add: `im:message` (read messages), `im:message:send_as_bot` (send), `im:resource` (attachments, both directions), `im:message.reactions:create` + `:read` + `:delete` (the 👀 receipt), `im:chat:readonly` (chat names for this page), `contact:user.base:readonly` (speaker names).","`Events & Callbacks` → set the mode to **长连接 (long connection)** — no public URL needed. Under Events subscribe `im.message.receive_v1` (接收消息); Callbacks gain `card.action.trigger` automatically once cards are sent, add it if listed.",`**Publish a version** (版本管理与发布 → 创建版本 → 申请发布). Nothing above takes effect until this is approved — the usual reason a configured bot stays silent.`,`Add the bot to a group (群设置 → 群机器人), or DM it directly.`]),ve=()=>i(`How Lark topics work here`,[`Pier never posts in a chat's main flow. A message in the chat is answered in *its own topic* (话题); a message inside a topic is answered there.`,`Each topic is its own Pi session, so one group hosts many parallel sessions.`,`The same applies in a DM: every new message starts its own topic and its own session. Reply *inside* a topic to continue that conversation.`,`Inside a topic Pier already owns, no @mention is needed — continuing that topic is addressing it.`,"Commands start with `/` or `%`: `/stop`, `/settings`, `/bind <code>`. `/s <question>`, outside any topic, drafts a session — directory, model, reasoning — and Start runs the question in it."]),ye=[[`slack`,`Slack`],[`lark`,`Lark`]],be={dm:`bg-sky-50 text-sky-700 ring-sky-200`,group:`bg-neutral-100 text-neutral-600 ring-neutral-200`},xe=`Discovered from inbound traffic — no platform reliably lists every chat a bot is in.`,Se=`pier.channelsPlatform`;function Ce(e){let t=localStorage.getItem(Se),n=ye.some(([e])=>e===t)?t:`slack`,i=null,a=[],s=f(`div`,`ml-auto flex items-center gap-1.5 text-[11.5px]`),c=f(`div`,`pagehead pagehead-hug sticky top-[-8px] z-30`,s),u=f(`div`,`px-4 pb-5 pt-4`);e.append(f(`div`,`min-h-0 flex-1 overflow-y-auto`,c,u));function p(){c.replaceChildren(h(ye.map(([e,t])=>[t,e]),n,e=>{m&&T(),n=e,localStorage.setItem(Se,e),E()}),s)}let m,g=!1,_=null;function v(e){if(s.replaceChildren(),e!==`clean`){if(s.className=`ml-auto flex items-center gap-1.5 text-[11.5px] ${J[e]}`,e===`saving`)s.append(K(oe,`spinner`),f(`span`,``,`Saving…`));else if(e===`saved`)s.append(K(I),f(`span`,``,`Saved`)),setTimeout(()=>{s.textContent?.includes(`Saved`)&&v(`clean`)},2e3);else{let e=q(`Retry`,`cursor-pointer underline`);e.onclick=T,s.append(K(fe),f(`span`,``,`Save failed`),e)}}}function y(){v(`saving`),clearTimeout(m),m=setTimeout(T,500)}let b=e=>t=>{e(t),y()};async function w(e){g=!0,v(`saving`);try{v((await H(`/api/channels/${e.platform}`,e.config,`PUT`)).ok?`saved`:`failed`)}catch{v(`failed`)}finally{g=!1;let e=_;_=null,e&&w(e)}}function T(){if(clearTimeout(m),m=void 0,!i)return;let e={platform:n,config:i};g?_=e:w(e)}async function E(){if(!a.length){let e=await V(`/api/models`,`Could not load the model catalog`);e.ok&&(a=e.value)}let e=await V(`/api/channels/${n}`,`Failed to load`);if(!e.ok){i=null,p(),u.replaceChildren(C(e.error));return}i=e.value,v(`clean`),M()}function D(e){let t=n===`lark`,i=d(e.token,t?`cli_…`:`xoxb-…`,b(t=>e.token=t),!0),a=d(e.appToken,t?``:`xapp-…`,b(t=>e.appToken=t),!0),s=O(e.cwd,`(pier process cwd)`,b(t=>e.cwd=t));return r(`Connection`,t?`Pier connects over Feishu's WebSocket long connection; no public URL or webhook needed.`:`Pier connects over Socket Mode; no public URL or webhook needed.`,x(`Enabled`,`Start the adapter when Pier boots.`,e.enabled,b(t=>{e.enabled=t,p()})),o(t?`App ID`:`Bot token`,i,{hint:`Stored locally, shown masked once saved.`,help:t?_e():he()}),t?o(`App Secret`,a,{hint:`From Credentials & Basic Info, beside the App ID.`}):o(`App-level token`,a,{hint:`Opens the Socket Mode connection. Needs connections:write.`}),o(`Default working directory`,s.el,{hint:`Where sessions this channel opens start.`}),f(`span`,`flex items-center gap-1.5 text-[13px] text-neutral-400`,f(`span`,``,t?`Every topic is its own session.`:`Every thread is its own session.`),t?ve():ge()))}function k(e){return r(`Defaults for new chats`,`Copied into a group the first time the bot sees it; changing them here never touches a group that already exists. DMs are always bound-users-only.`,x(`Require mention in groups`,`Ignore group messages that do not @mention or reply to the bot.`,e.requireMention,b(t=>e.requireMention=t)),x(`Require bound user`,`Only users bound with a code below can drive the agent.`,e.requireBind,b(t=>e.requireBind=t)),Z(`Model & reasoning`,e,a,b(t=>{e.model=t.model,e.thinking=t.thinking,M()})))}function ee(e){let t=f(`span`,`font-mono text-[15px] font-semibold tracking-widest`),i=f(`div`,`hidden items-center gap-2 rounded-lg bg-indigo-50 px-3 py-2 text-[12.5px] text-indigo-800`,t,f(`span`,`text-[11.5px] text-indigo-500`,`DM the bot /bind <code> · expires in 10 min`)),a=S(`Generate bind code`);a.onclick=async()=>{let e=await fetch(`/api/channels/${n}/bind-code`,{method:`POST`});if(!e.ok)return;let{code:r}=await e.json();t.textContent=r,i.classList.replace(`hidden`,`flex`)};let o=f(`div`,`flex flex-col`);e.users.length||o.append(C(`No bound users yet.`));for(let t of e.users){let e=q(`Remove`,F());e.onclick=async()=>{await fetch(`/api/channels/${n}/users/${encodeURIComponent(t.id)}`,{method:`DELETE`}),await E()},o.append(f(`div`,`group flex items-center gap-2.5 border-b border-neutral-100 py-2 last:border-0`,f(`span`,`flex h-6 w-6 flex-none items-center justify-center rounded-full bg-neutral-100 text-[11px] font-semibold text-neutral-500`,(t.name[0]??`?`).toUpperCase()),f(`span`,`min-w-0 flex-1 truncate text-[13px] text-neutral-700`,t.name),f(`span`,`flex-none font-mono text-[11.5px] text-neutral-400`,t.id),e))}return r(`Bound users`,`A code is single-use and expires; redeeming it in a DM binds that account.`,o,f(`div`,`flex flex-col gap-2`,a,i))}function te(e,t){let r=f(`div`,`group rounded-xl border px-3.5 py-3 transition-colors ${t.enabled?`border-neutral-200 bg-white`:`border-neutral-200 bg-neutral-50/60`}`),i=t.botId!==e.botId,s=q(`Remove`,F());s.onclick=async()=>{let e=t.name||t.id;window.confirm(`Remove ${e}? Threads in it lose their sessions; a chat the bot can still reach comes back on its next message.`)&&(await fetch(`/api/channels/${n}/chats/${encodeURIComponent(t.id)}`,{method:`DELETE`}),await E())};let c=f(`div`,`flex flex-wrap items-center gap-2`,f(`span`,`min-w-0 flex-1 basis-full truncate text-[13px] font-medium sm:basis-0 ${t.enabled?`text-neutral-800`:`text-neutral-400`}`,t.name||t.id),A(t.kind,be[t.kind]),...i?[A(t.botId?`other bot`:`no bot`,`bg-amber-50 text-amber-700 ring-amber-200`)]:[],f(`span`,`flex-none font-mono text-[11px] text-neutral-400`,t.id),s),l=x(``,``,t.enabled,b(e=>{t.enabled=e,M()}));l.classList.add(`flex-none`,`items-center`),c.append(l);let u=f(`div`,`mt-3 flex flex-wrap items-center gap-x-6 gap-y-2`);if(t.kind===`dm`?u.append(f(`span`,`text-[13px] text-neutral-400`,`Direct message · bound users only, mention not applicable`),x(`This DM is the conversation`,``,t.home===!0,b(n=>{for(let t of e.chats)delete t.home;n&&(t.home=!0),M()}))):u.append(x(`Require mention`,``,t.requireMention,b(e=>t.requireMention=e)),x(`Require bind`,``,t.requireBind,b(e=>t.requireBind=e))),i&&u.append(f(`span`,`w-full text-[12.5px] text-amber-700`,t.botId?`Last seen under bot ${t.botId}${e.botId?`, not the current ${e.botId}`:``} — remove it if nothing arrives here.`:`No message since Pier started recording bot identities — remove it if nothing arrives here.`)),t.home)return r.append(c,u,f(`p`,`mt-3 text-[13px] text-neutral-400`,`The conversation's model and reasoning are set from its ⋯ menu.`)),r;let d=O(t.cwd,``,b(e=>t.cwd=e)),p=f(`div`,`mt-3 grid grid-cols-1 gap-3 sm:grid-cols-2`,o(`Working directory`,d.el),Z(`Model & reasoning`,t,a,b(e=>{t.model=e.model,t.thinking=e.thinking,M()})));return r.append(c,u,p),r}function j(e){let t=f(`div`,`flex flex-col gap-2.5`);return e.chats.length?t.append(...e.chats.map(t=>te(e,t))):t.append(C(`None yet. Chats appear here after the bot sees a message in them.`)),r(n===`slack`?`Channels`:`Chats`,e.botId?`${xe} Current bot: ${e.botId}.`:xe,t)}function M(){if(!i)return;p();let e=f(`div`,`mx-auto flex max-w-3xl flex-col gap-4`);e.append(D(i),k(i),ee(i),j(i)),u.replaceChildren(e)}return l(e,()=>void E(),()=>{m&&T()})}var we=`Managed by the configuration subscription: the source's copy is applied on every sync. To edit here, pause it under Agent → Configuration sync.`,Te=async()=>{let e=await V(`/api/config-sync`,``,{cache:`no-store`});return e.ok&&e.value.enabled};function Ee(){let e=f(`div`,`min-h-0 min-w-0 flex-1 overflow-y-auto p-4`),t=f(`div`,`mx-auto flex max-w-3xl min-w-0 flex-col gap-4`),n=f(`p`,`text-[12px] break-words`),r=f(`section`,`flex min-w-0 flex-col gap-3 border-b border-neutral-200 pb-4`),i=f(`section`,`flex min-w-0 flex-col gap-3`);t.append(f(`h2`,`text-[14px] font-semibold text-neutral-700`,`Configuration sync`),n,r,i),e.append(t);let a=null,s=!1,c=!1,l=0,u=``,m=!1,h=e=>e?new Date(e).toLocaleString():`Never`;async function g(){let e=l,t=await V(`/api/config-sync`,`Could not load configuration sync`,{cache:`no-store`});if(!(c||e!==l)){if(!t.ok){y(n,`failed`,t.error);return}a=t.value,m||(u=a.sourceUrl),b()}}async function _(e){if(!s){++l,s=!0,b(),y(n,`saving`,`Working...`);try{let t=await H(`/api/config-sync`,{action:e,...e===`subscribe`?{url:u}:{}});if(!t.ok)throw Error(await U(t,`Configuration sync failed`));let r=await t.json();a=r,m=!1,u=r.sourceUrl,y(n,`saved`,r.result??`Saved`)}catch(e){y(n,`failed`,e instanceof Error?e.message:`Configuration sync failed`),await g()}finally{s=!1,c||b()}}}function v(e,t){let n=S(e);return n.disabled=s,n.onclick=()=>{_(t)},n}function b(){if(!a||c)return;if(r.replaceChildren(f(`h3`,`text-[13px] font-medium text-neutral-700`,`Publish`)),a.publishedPath){let e=`${a.publicUrl||window.location.origin}${a.publishedPath}`,t=d(e,``,()=>{},!0);t.readOnly=!0,t.setAttribute(`aria-label`,`Sharing URL`),r.append(t,f(`div`,`flex flex-wrap items-center gap-2`,p(`btn text-[12px]`,()=>e),v(`Revoke link`,`revoke`)))}else r.append(f(`div`,``,v(`Generate link`,`publish`)));r.append(f(`p`,`text-[12px] text-neutral-500`,`Anyone with the link can read shared prompts, model definitions, the default model and its reasoning effort. API keys, headers and endpoints stay private.`));let e=d(u,`https://example.com/config-sync/...`,e=>{u=e,m=!0},!0);e.type=`url`,e.setAttribute(`aria-label`,`Configuration source URL`),e.disabled=s||a.enabled;let t=x(`Automatic sync`,``,a.enabled,e=>{_(e?`subscribe`:`pause`)});t.querySelector(`input`).disabled=s;let n=f(`div`,`flex flex-wrap items-center gap-3`,t);a.enabled&&n.append(v(`Sync now`,`sync`)),i.replaceChildren(f(`h3`,`text-[13px] font-medium text-neutral-700`,`Source`),o(`Source URL`,e),n);let l=f(`dl`,`grid grid-cols-[auto_minmax(0,1fr)] gap-x-4 gap-y-1 text-[12px]`);for(let[e,t]of[[`Last checked`,h(a.lastChecked)],[`Last applied`,h(a.lastApplied)],[`Next check`,a.enabled?h(a.nextRunAt):`Paused`]])l.append(f(`dt`,`text-neutral-500`,e),f(`dd`,`min-w-0 break-words text-neutral-700`,t));i.append(l),a.error&&i.append(f(`p`,`text-[12px] break-words text-red-600`,a.error)),a.needsReload&&i.append(f(`p`,`text-[12px] text-amber-700`,`Reload pending; retry synchronization.`))}g();let C=setInterval(()=>{!s&&!m&&g()},15e3);return{el:e,dispose:()=>{c=!0,clearInterval(C)}}}var De=`text-[11.5px] text-neutral-400`,Oe=`bg-neutral-50 text-neutral-500 ring-neutral-200`,ke=`bg-amber-50 text-amber-700 ring-amber-100`,Ae=`Pi packages run with full system access: an extension executes arbitrary code, and a skill can instruct the model to run anything. Review the source before installing.`,je=e=>e===`pier`||e===`local`?e:e.replace(/^(npm|git):/,``).replace(/\.git$/,``).replace(/@[^@/]*$/,``).split(`/`).filter(Boolean).pop()??e,Me=e=>e.startsWith(`npm:`)?`npm`:/^(git:|(https?|ssh|git):\/\/)/.test(e)?`git`:`path`,Ne=e=>e.kind===`pier`||e.kind===`local`,Pe=e=>e.slice(0,e.lastIndexOf(`/`))||`/`;function Fe(e){let t=null,n=``,r=()=>{let t=e.cwd();return t?`?cwd=${encodeURIComponent(t)}`:``},i=t=>!Ne(t)&&t.scope===`global`&&e.cwd()===void 0;async function a(){let e=await V(`/api/packages${r()}`,`packages could not be loaded`,{cache:`no-store`});t=e.ok?e.value:null,n=e.ok?``:e.error}let s=(e,n)=>t?.packages.find(t=>t.source===e&&t.scope===n),c=(e,n,r)=>{for(let i of t?.packages.filter(t=>t.source===e)??[]){let e=i.resources.find(e=>e.kind===n&&e.path===r);if(e)return{pkg:i,resource:e}}};async function l(t,n,r){let i=e.cwd(),a=await P(`/api/packages/resource`,{source:t.source,kind:n.kind,path:n.path,enabled:r,...i?{cwd:i}:{}},`could not save`,`PUT`);return a.ok?(t.resources=t.resources.map(e=>e.kind===n.kind&&e.path===n.path?a.value:e),e.changed(),{state:`saved`,text:`Saved — sessions take it on their next message.`}):{state:`failed`,text:a.error}}let p=t=>{e.pane.replaceChildren(f(`p`,`px-4 py-3 text-[12.5px] leading-relaxed text-red-600`,t))},m=(...e)=>f(`div`,`flex min-h-0 flex-1 flex-col gap-4 overflow-y-auto p-4`,...e),h=(e,t,n=!0)=>[f(`dt`,`text-[12px] text-neutral-500`,e),f(`dd`,`text-[12px] leading-snug text-neutral-700 ${n?`font-mono break-all`:``}`,t)],g=(t,n)=>{let r=q(`Browse files`,`btn text-[12px]`);return r.onclick=()=>e.browse(t,n),r},_=(e,t,n,r,i)=>x(n,r,t.enabled,n=>void l(e,t,n).then(i));function v(t,n,r){let i=q(n.name,`font-mono text-[13px] text-neutral-700 hover:text-indigo-600 hover:underline`);i.onclick=()=>{let r={type:`resource`,source:t.source,kind:n.kind,path:n.path};e.select(r),T(r.source,r.kind,r.path)};let a=f(`div`,`flex min-w-0 flex-1 flex-col gap-0.5`,f(`span`,`flex flex-wrap items-center gap-2`,i,A(n.kind,Oe)),...n.state?[f(`span`,`text-[11.5px] leading-snug text-amber-700`,n.state)]:[]);return f(`div`,`flex max-w-2xl items-start gap-3 border-b border-neutral-100 py-2.5 last:border-0`,a,_(t,n,``,``,r))}function b(n,r,o){let c=e.claim(),l=s(n,r);if(!l)return p(`unknown package: ${n}`);let d=f(`span`,De,``);o&&y(d,o.state,o.text);let _=t?.busy===l.source;_&&!o&&y(d,`saving`,`${l.installedPath?`updating`:`installing`}…`);let x=t=>{e.live(c)&&b(n,r,t)},S=[...h(`Source`,l.source),...h(`Kind`,l.kind===`pier`?`built in — ships with Pier`:l.kind===`local`?`the agent directory's own files`:l.kind,!1),...l.version?h(`Version`,l.version):[],...l.installedPath===null?Ne(l)?[]:h(`Installed at`,`not installed`,!1):h(`Installed at`,f(`span`,`flex flex-wrap items-center gap-2`,f(`span`,`font-mono break-all`,l.installedPath),g(l.installedPath)),!1)],w=[];if(i(l)&&l.kind!==`path`){let i=t?.checkedAt?`checked ${u(Date.parse(t.checkedAt))}`:`not checked yet`,o=q(`Check for updates`,`btn text-[12px]`);o.disabled=_,o.onclick=()=>{o.disabled=!0,y(d,`saving`,`checking…`),P(`/api/packages/check`,{},`update check failed`).then(i=>{i.ok&&(t=i.value),e.changed();let a=s(n,r);x(i.ok?{state:`saved`,text:a?.updateAvailable?`Checked — an update is available.`:`Checked — up to date.`}:{state:`failed`,text:i.error})})},S.push(...h(`Updates`,f(`span`,`flex flex-wrap items-center gap-2`,f(`span`,l.updateAvailable?`text-emerald-700`:``,l.updateAvailable?`update available (${i})`:i),o),!1));let c=q(`Update`,`btn text-[12.5px]`);c.disabled=_,c.onclick=()=>{c.disabled=!0,t&&={...t,busy:l.source},e.changed(),x({state:`saved`,text:`updating…`}),P(`/api/packages/update`,{source:l.source},`update failed`).then(async t=>{await a(),e.changed();let n=t.ok?t.value.packages.find(e=>e.source===l.source):void 0;x(t.ok?{state:`saved`,text:`Updated${n?.version?` to ${n.version}`:``} — sessions take it on their next message.`}:{state:`failed`,text:t.error})})},w.push(c)}if(i(l)){let t=q(`Remove`,`btn text-[12.5px] text-neutral-600 hover:text-red-600`);t.disabled=_,t.onclick=()=>{let n=l.kind===`path`?`settings.json forgets it; the directory stays.`:`Its files are deleted and settings.json forgets it.`;window.confirm(`Remove ${l.source}? ${n}`)&&(t.disabled=!0,y(d,`saving`,`removing…`),P(`/api/packages/remove`,{source:l.source},`remove failed`).then(async t=>{if(!t.ok)return x({state:`failed`,text:t.error});await a(),e.select(null),e.live(c)&&e.pane.replaceChildren(f(`div`,`flex min-h-0 flex-1 items-center justify-center p-6`,C(`Removed ${l.source}.`)))}))},w.push(t)}e.pane.replaceChildren(e.paneBar(je(l.source),A(l.kind,Oe),...l.scope===`project`?[A(`project`,ke)]:[],...w.length?[f(`div`,`ml-auto flex flex-none items-center gap-2`,...w)]:[]),m(f(`dl`,`grid max-w-2xl grid-cols-[auto_1fr] gap-x-4 gap-y-1.5`,...S),l.resources.length?f(`div`,`flex max-w-2xl flex-col`,...l.resources.map(e=>v(l,e,x))):C(l.installedPath?`No extensions or skills.`:`Not installed — nothing to load.`),d))}let S=(t,n)=>t.kind===`pier`?n.kind===`skill`?`Pier's own skill. Off, no session is offered it.`:`Loaded from inside Pier — nothing installed, nothing to update. A session mid-turn keeps the tools it started with.`:`Written to ${e.cwd()?`this project's .pi/settings.json`:`settings.json`} as +path / −path for ${je(t.source)}; sessions pick it up on their next open.`;async function T(t,n,r,i){let a=e.claim(),o=c(t,n,r);if(!o)return p(`unknown ${n}: ${r}`);let{pkg:s,resource:l}=o,u=f(`span`,De,``);i&&y(u,i.state,i.text);let d=f(`div`,`min-h-0 flex-1 overflow-auto`),m=r.startsWith(`/`);if(e.pane.replaceChildren(e.paneBar(l.name,A(je(s.source),Oe),A(l.kind,Oe),f(`span`,`ml-auto flex flex-wrap items-center gap-2`,f(`span`,`font-mono text-[11px] text-neutral-400 break-all`,l.path),...m?[g(Pe(r),w(r))]:[])),f(`div`,`flex flex-none flex-col gap-2 border-b border-neutral-200 px-4 py-3`,_(s,l,`Enabled`,S(s,l),i=>{e.live(a)&&T(t,n,r,i)}),...l.state?[f(`p`,`text-[12px] text-amber-700`,l.state)]:[],u),d),r.startsWith(`<inline:`)){d.append(f(`p`,`px-4 py-3 text-[12.5px] text-neutral-400`,`Loaded from inside Pier — there is no file to show.`));return}let h=await E(r);if(!e.live(a))return;if(!h.ok)return d.append(f(`p`,`px-4 py-3 text-[12.5px] text-red-600`,h.error));let v=await B(r);e.live(a)&&d.append(le(ce(h.value),v))}async function E(e){let t=`/api/fs/file?root=${encodeURIComponent(Pe(e))}&path=${encodeURIComponent(w(e))}`,n;try{n=await fetch(t,{cache:`no-store`})}catch(t){return{ok:!1,error:`could not read ${e}: ${String(t)}`}}return n.ok?{ok:!0,value:await n.text()}:{ok:!1,error:await U(n,`could not read ${e}`)}}function D(n,r=``){let i=e.claim(),s=f(`span`,De,``);n&&y(s,n.state,n.text);let c=r,l=d(r,`npm:@scope/name · git:github.com/owner/repo · /path/to/package`,e=>c=e,!0),u=q(`Install`,`btn btn-primary text-[12.5px]`),p=()=>{let n=c.trim();if(!n)return y(s,`failed`,`A package source is required.`);u.disabled=!0,y(s,`saving`,`installing ${n}…`),t&&(t={...t,busy:n,packages:[...t.packages,{source:n,kind:Me(n),scope:`global`,version:null,installedPath:null,updateAvailable:!1,resources:[]}]},e.changed()),P(`/api/packages`,{source:n},`install failed`).then(async t=>{if(await a(),e.changed(),!e.live(i))return;if(!t.ok)return D({state:`failed`,text:t.error},n);let{package:r}=t.value;e.select({type:`package`,source:r.source,scope:r.scope}),b(r.source,r.scope,{state:`saved`,text:`Installed ${r.source} — sessions take it on their next message.`})})};u.onclick=p,l.onkeydown=e=>{e.key===`Enter`&&p()},e.pane.replaceChildren(e.paneBar(`Add package`),m(f(`div`,`flex max-w-2xl flex-col gap-3`,o(`Source`,l,{hint:"What `pi install` takes: an npm package, a git URL (both may pin @version), or a directory on this machine."}),f(`p`,`text-[12.5px] leading-relaxed text-amber-800`,Ae),f(`div`,`flex items-center gap-3`,u,s)))),l.focus()}return{get registry(){return t},get error(){return n},load:a,openPackage:b,openResource:T,openAdd:D}}async function Ie(e,t){let n;try{n=await H(`/api/settings`,e,`PUT`)}catch(e){return{outcome:{state:`failed`,text:`Could not save: ${String(e)}`}}}if(!n.ok)return{outcome:{state:`failed`,text:await U(n,`could not save`)}};let r;try{r=await n.json()}catch(e){return{outcome:{state:`failed`,text:`Saved, but the answer could not be read: ${String(e)}`}}}return r.toolsSync?.state===`refused`?{outcome:{state:`failed`,text:`Saved, but nothing will install it: ${r.toolsSync.reason}`},answer:r}:r.toolsSync?.state===`waiting`?{outcome:{state:`saved`,text:`Saved — a sync is already running; this change goes in the run right after it.`},answer:r}:{outcome:{state:`saved`,text:t},answer:r}}function Le(e,t){return e.enabled?{body:{tool:{name:e.name,on:!1}},saved:`Switched ${e.name} off — the next run uninstalls it. Remove it again once its binary is gone.`}:{body:{customTools:t.filter(t=>t.name!==e.name)},saved:`Removed ${e.name}.`}}function Re(e,n,r){let i=`global`,a=null,s=0,c=0,u=``,p=()=>u?`Global (${u})`:`Global`,m=null,h=[],g=``,_=null,b=null,S=()=>{b?.dispose(),b=null},T=()=>{S(),++c,b=Ee(),I.replaceChildren(b.el)},E=[],D=e=>e.custom===!0,O=f(`span`,`min-w-0 flex-1 truncate`),k=f(`button`,`${N} flex items-center gap-1.5`,O,K(t,`h-3.5 w-3.5 text-neutral-500`));k.setAttribute(`aria-haspopup`,`true`),k.onclick=()=>{if(k.getAttribute(`aria-expanded`)===`true`)return ee();te(k,[{label:p(),checked:i===`global`,onSelect:()=>be(`global`)},...n().map(e=>({label:e,hint:w(e),checked:i===e,onSelect:()=>be(e)}))],`Scope`)};let j=f(`div`,`${ne} flex-col items-stretch gap-1.5 px-3 py-2.5`);j.append(f(`span`,`field-label`,`Scope`),k);let P=f(`div`,`min-h-0 flex-1 overflow-y-auto py-1.5`),F=f(`nav`,`${M} w-64 flex-none text-[13px] leading-5 max-md:max-h-48 max-md:w-full`);F.append(j,P);let I=f(`div`,`${M} min-w-0 flex-1`),L=f(`div`,`flex min-h-0 flex-1 gap-3 px-4 pb-4 pt-1 max-md:flex-col`);L.append(F,I),e.append(L);let z=(e,...t)=>f(`div`,`${ne} flex-wrap gap-3 px-4 py-2.5`,f(`span`,`font-mono text-[12.5px] text-neutral-500`,e),...t),W=Fe({pane:I,paneBar:z,claim:()=>++c,live:e=>e===c,cwd:()=>i===`global`?void 0:i,changed:()=>$(m),browse:r,select:e=>{a=e,e?.type===`resource`&&Z.set(e.source,!0),$(m)}}),G=(e=``)=>`?scope=${encodeURIComponent(i)}${e}`;async function re(){if(i!==`global`){h=[],g=``;return}let e=await V(`/api/settings`,`could not be loaded`,{cache:`no-store`});if(!e.ok){h=[],g=e.error;return}J(e.value),g=``}function J(e){h=e.catalog,E=e.customTools,_=e.toolsTaskId}async function Y(e,t){let{outcome:n,answer:r}=await Ie(e,t);return r&&(J(r),$(m)),n}async function ie(){let e=++s;c++;let[t]=await Promise.all([V(`/api/config${G()}`,`failed to load config`,{cache:`no-store`}),re(),W.load()]);if(e!==s)return;if(!t.ok){$(null),me(t.error);return}let n=t.value;i===`global`&&n.dir&&(u=n.dir,xe()),m=n,$(n),a?a.type===`sync`&&T():pe()}function ae(e,t){return f(`div`,`flex items-center justify-between gap-2 px-3 pb-1 pt-3 text-[10.5px] font-semibold uppercase tracking-wide text-neutral-400`,f(`span`,``,e),...t?[t]:[])}let X=e=>f(`span`,`flex-none rounded bg-neutral-100 px-1 text-[10px] font-semibold uppercase tracking-wide text-neutral-500`,e),oe=()=>f(`span`,`flex-none rounded bg-emerald-50 px-1 text-[10px] font-semibold uppercase tracking-wide text-emerald-700`,`on`);function se(e,t,n,r,i={}){let a=f(`button`,`config-row flex w-full cursor-pointer items-center gap-1.5 py-1.5 pr-3 text-left transition-colors hover:bg-neutral-100 ${t?`bg-indigo-50 font-medium hover:bg-indigo-50`:``} ${n?`text-neutral-400`:``}`),o=f(`span`,`truncate`,e);if(i.note){let e=f(`span`,`truncate text-[11px] font-normal leading-4 text-amber-700`,i.note);e.title=i.note,a.append(f(`span`,`flex min-w-0 flex-1 flex-col`,o,e))}else a.append(o);return a.append(...i.tags??[]),a.style.paddingLeft=`${i.flush?0:20+(i.depth??0)*14}px`,a.title=e,a.onclick=r,a}let Z=new Map;function ue(e,t,n,r){let i=Z.get(e)??n.openByDefault,a=f(`button`,`flex w-5 flex-none cursor-pointer items-center justify-center self-stretch text-neutral-500 hover:bg-neutral-100`,K(v,`chev h-3 w-3`));i&&a.classList.add(`chev-open`),a.title=`${i?`Collapse`:`Expand`} ${t}`,a.setAttribute(`aria-label`,a.title),a.setAttribute(`aria-expanded`,String(i)),a.onclick=()=>{Z.set(e,!i),$(m)};let o=se(t,n.active,n.dim,n.onPick,{tags:n.tags,flush:!0}),s=[f(`div`,`flex items-stretch ${n.active?`bg-indigo-50`:``}`,a,o)];return i?[...s,...r()]:s}function de(e,t,n){let r={type:`package`,source:e.source,scope:e.scope},i=[];return W.registry?.busy===e.source?i.push(f(`span`,`flex-none text-[11px] text-neutral-400`,e.installedPath?`updating…`:`installing…`)):e.resources.some(e=>e.enabled)&&i.push(oe()),e.scope===`project`&&i.push(X(`project`)),ue(e.source,je(e.source),{active:t(r),dim:e.installedPath===null&&!Ne(e),tags:i,onPick:()=>n(r),openByDefault:Ne(e)},()=>fe(e,t,n))}function fe(e,t,n){let r=[],i=e.resources.map(e=>e.name),a=new Set(i.filter((e,t)=>i.indexOf(e)!==t));for(let[i,o]of[[`extensions`,`extension`],[`skills`,`skill`]]){let s=e.resources.filter(e=>e.kind===o);if(!s.length)continue;let c=f(`div`,`py-0.5 text-[10.5px] font-semibold uppercase tracking-wide text-neutral-400`,i);c.style.paddingLeft=`34px`,r.push(c);for(let i of s){let s={type:`resource`,source:e.source,kind:o,path:i.path};r.push(se(i.name,t(s),!i.enabled,()=>n(s),{depth:2,note:i.state,tags:a.has(i.name)?[X(o)]:[]}))}}return r}function Q(e,t){let n={type:`tools`};return ue(`tools`,`tools`,{active:e(n),dim:!1,tags:h.some(e=>e.enabled)?[oe()]:[],onPick:()=>t(n),openByDefault:!0},()=>g?[f(`p`,`py-1 pl-5 pr-3 text-[12.5px] text-red-600`,g)]:h.map(n=>{let r={type:`tool`,name:n.name};return se(n.name,e(r),!n.enabled,()=>t(r),{depth:1,note:n.binary.error,tags:D(n)?[X(`yours`)]:[]})}))}function $(e){if(!e){P.replaceChildren();return}let t=e=>JSON.stringify(e)===JSON.stringify(a),n=t=>{S(),a=t,$(e),t.type===`file`?he(t.name,t.readonly,t.managed):t.type===`tools`||t.type===`tool`?ve():t.type===`sync`?T():t.type===`package`?W.openPackage(t.source,t.scope):t.type===`resource`?W.openResource(t.source,t.kind,t.path):W.openAdd()},r=[];if(i===`global`){let e={type:`sync`};r.push(ae(`Instance`),se(`Configuration sync`,t(e),!1,()=>n(e)))}r.push(ae(`Files`));for(let i of e.files){let e={type:`file`,name:i.name,readonly:i.readonly,managed:i.managed};r.push(se(i.name,t(e),!i.exists,()=>n(e)))}let o={type:`add`},s=q(`Add package`,`normal-case tracking-normal hover:underline ${t(o)?`text-indigo-700`:`text-indigo-600`}`);s.onclick=()=>n(o),r.push(ae(`Packages`,i===`global`?s:void 0)),W.error&&r.push(f(`p`,`py-1 pl-5 pr-3 text-[12.5px] text-red-600`,W.error));for(let e of W.registry?.packages??[])r.push(...de(e,t,n));i===`global`&&r.push(...Q(t,n)),P.replaceChildren(...r)}function pe(){I.replaceChildren(f(`div`,`flex min-h-0 flex-1 items-center justify-center p-6`,C(`Select a file to edit, or a package, extension, skill or tool to switch.`)))}function me(e){I.replaceChildren(f(`p`,`px-4 py-3 text-[12.5px] leading-relaxed text-red-600`,e))}async function he(e,t,n){let r=++c,i=await V(`/api/config/files/${encodeURIComponent(e)}${G()}`,`failed to load ${e}`,{cache:`no-store`});if(!i.ok){r===c&&me(i.error);return}if(r!==c)return;let{content:a}=i.value,o=a,s=f(`span`,`text-[11.5px] text-neutral-400`,``),l=f(`button`,`btn btn-primary text-[12.5px]`,`Save`),u=document.createElement(`textarea`);u.className=`block min-h-0 flex-1 resize-none bg-white p-4 font-mono text-[13px] leading-relaxed focus:outline-none`,u.spellcheck=!1,u.value=a;let d=async()=>{if(l.disabled)return;let t=u.value;l.disabled=!0,y(s,`saving`,`saving…`);try{let n=await H(`/api/config/files/${encodeURIComponent(e)}${G()}`,{content:t,expected:o},`PUT`);if(!n.ok)return y(s,`failed`,await U(n,`save failed`));let r=await n.json();o=r.content,u.value===t?(u.value=r.content,y(s,`saved`,`saved — applies to new sessions`)):y(s,`idle`,`saved; newer changes are unsaved`)}catch(e){y(s,`failed`,`save failed: ${String(e)}`)}finally{l.disabled=!1}},p=f(`button`,`btn text-[12.5px]`,`Edit`),m=f(`button`,`btn text-[12.5px]`,`View`),h=(...e)=>f(`div`,`ml-auto flex flex-none items-center gap-2`,...e),g=()=>{I.replaceChildren(z(e,s,h(m,l)),u),u.focus()},_=async()=>{let i=await B(e);if(r!==c)return;let a=n?we:t?`Pier manages this file: the default model is set in Settings → Models; other keys are edited on disk, then pier reload.`:null;I.replaceChildren(a?z(e,f(`span`,`ml-auto text-[11px] uppercase tracking-wide text-neutral-400`,`read-only`)):z(e,s,h(p)),...a?[f(`p`,`border-b border-neutral-200 px-4 py-2 text-[12.5px] leading-relaxed text-neutral-500`,a)]:[],f(`div`,`min-h-0 flex-1 overflow-auto`,le(ce(u.value),i)))};p.onclick=g,m.onclick=()=>void _(),l.onclick=()=>void d(),u.onkeydown=e=>{(e.metaKey||e.ctrlKey)&&e.key===`s`&&(e.preventDefault(),d())},u.oninput=()=>{y(s,`idle`,`unsaved changes`)},await _()}let ge=()=>{let e=f(`a`,`text-indigo-600 hover:underline`,`ubix`);return e.href=`https://github.com/timqi/ubix`,e.target=`_blank`,e.rel=`noreferrer`,e};function _e(e){let{spec:t,error:n,installed:r,version:i,path:a}=e.binary;return n?`${t} — ${n}`:r?`${t} — ${i??`unknown version`} at ${a??`an unknown path`}`:`${t} — not installed`}function ve(e,t={name:``,toml:``}){c++;let n=a?.type===`tool`?a.name:null,r=f(`span`,`text-[11.5px] text-neutral-400`,``);e&&y(r,e.state,e.text);let i=h.map(e=>{let t=f(`div`,`flex min-w-0 flex-1 flex-col gap-0.5`,f(`span`,`flex items-center gap-2 text-[13px] text-neutral-700`,f(`span`,`font-mono`,e.name),...D(e)?[A(`yours`,`bg-neutral-50 text-neutral-500 ring-neutral-200`)]:[]),f(`span`,`text-[11.5px] leading-snug text-neutral-400`,e.summary||_e(e)),...e.summary?[f(`span`,`font-mono text-[11px] leading-snug ${e.binary.error?`text-red-600`:`text-neutral-400`}`,_e(e))]:[]),r=x(``,``,e.enabled,t=>void ye(e.name,t,e=>ve(e))),i=f(`button`,`btn text-[12px] text-neutral-500 hover:text-red-600`,`Remove`);return i.onclick=()=>{i.disabled=!0;let t=Le(e,E);Y(t.body,t.saved).then(e=>ve(e))},f(`div`,`flex max-w-2xl items-start gap-3 border-b border-neutral-100 py-2.5 last:border-0 ${e.name===n?`rounded bg-indigo-50 ring-8 ring-indigo-50`:``}`,t,...D(e)?[i]:[],r)}),s={...t},l=f(`span`,`font-mono text-[12px] text-neutral-500`,`[tools.<name>]`),u=d(s.name,`claude`,e=>{s.name=e,l.textContent=`[tools.${e.trim()||`<name>`}]`},!0),p=document.createElement(`textarea`);p.className=`${R} h-24 resize-y font-mono leading-snug`,p.spellcheck=!1,p.value=s.toml,p.placeholder=`spec = "github:owner/repo"
|
|
2
2
|
exe = "tool"`,p.oninput=()=>s.toml=p.value;let m=f(`button`,`btn btn-primary text-[12.5px]`,`Add`);m.onclick=()=>{let e={name:s.name.trim(),toml:s.toml.trim()};if(!e.name||!e.toml)return y(r,`failed`,`A custom tool needs a name and a block with a spec line.`);m.disabled=!0,Y({customTools:[...E,e],tool:{name:e.name,on:!0}},`Added ${e.name} — installing now.`).then(e=>ve(e,e.state===`failed`?s:void 0))},I.replaceChildren(z(`command-line tools`,f(`span`,`ml-auto text-[11px] uppercase tracking-wide text-neutral-400`,`installed by Pier`)),f(`div`,`flex min-h-0 flex-1 flex-col gap-4 overflow-y-auto p-4`,f(`p`,`max-w-2xl text-[12.5px] leading-relaxed text-neutral-500`,`Pier writes no downloader: `,ge(),` does the work — a declarative installer that resolves a spec like `,f(`span`,`font-mono text-[11.5px]`,`github:owner/repo`),` to the right release asset for this machine, verifies it, and upgrades in place. Pier bootstraps it, generates its config from the switches below, and keeps its files under Pier's own directory — your own ubix setup is untouched.`),g?f(`p`,`max-w-2xl text-[12.5px] text-red-600`,g):f(`div`,`flex max-w-2xl flex-col`,...i),f(`div`,`flex max-w-2xl flex-col gap-2 border-t border-neutral-200 pt-4`,f(`span`,`text-[12.5px] font-medium text-neutral-600`,`Add one of your own`),o(`Name`,u),o(`The block Pier writes under the header`,p,{hint:`A line that opens a section of its own is refused, because it could rewrite the rest of the file.`}),f(`div`,`flex items-center gap-3`,l,m)),f(`p`,`max-w-2xl text-[12px] leading-snug text-neutral-400`,_?`Installs and daily updates run as the update task; a failure shows on the tool's row.`:`Switching one on creates the daily task that installs it and keeps it current.`),r)),i[h.findIndex(e=>e.name===n)]?.scrollIntoView({block:`nearest`})}async function ye(e,t,n){n(await Y({tool:{name:e,on:t}},t?`Saved — installing now; watch the run.`:`Saved — uninstalling in the next run.`))}function be(e){ee(),e!==i&&(S(),i=e,a=null,xe(),ie())}function xe(){i!==`global`&&!n().includes(i)&&(i=`global`),O.textContent=i===`global`?p():w(i),k.title=i===`global`?u:i}return l(e,()=>{xe(),ie()},S)}var ze=`medium`,Be=e=>({model:e.defaultModel,thinking:e.defaultThinkingLevel}),Ve=`Off — the first message is the title`;function He(){let e=[],n=[],i=!1,s,c={model:null,thinking:null},l=!1,u=null,d=f(`span`,`text-[11.5px]`,``),p=f(`span`,`text-[11.5px]`,``),m=f(`div`,`flex items-center gap-3`),h=f(`span`,`text-[11.5px]`,``),_=f(`div`,`flex flex-col gap-1.5`),v=S(`Save menu`,!0),b=f(`div`,`flex min-w-0 flex-col gap-2`),x=f(`div`,`flex items-center gap-2`),w=f(`fieldset`,`contents`),T=f(`fieldset`,`contents`),E=[0,1].map(()=>f(`p`,`text-[12px] leading-snug text-amber-700`,we)),O=f(`div`,`mx-auto flex w-full max-w-3xl min-w-0 flex-col gap-6`);function k(){i=!0,y(d,`idle`,`unsaved changes`)}function A(t,n,r,i){let a=e.indexOf(t),o=a+n,s=q(``,`icon-btn max-md:h-11 max-md:w-11 disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:bg-transparent`);return s.append(K(r)),s.title=i,s.setAttribute(`aria-label`,`${i}: ${Y(t)}`),s.disabled=o<0||o>=e.length,s.onclick=()=>{e.splice(o,0,...e.splice(a,1)),u={at:t,step:n},k(),L()},s}function te(n){let r=g(G.map(e=>[`thinking: ${z(e)}`,e]),n.thinking);r.classList.replace(`w-full`,`w-44`),r.classList.add(`flex-none`),r.onchange=()=>{n.thinking=r.value,k()};let i=g([[`tier: none`,``],...D.map(e=>[`tier: ${e}`,e])],n.tier??``);i.classList.replace(`w-full`,`w-36`),i.classList.add(`flex-none`),i.onchange=()=>{i.value?n.tier=i.value:delete n.tier,k()};let a=S(`Remove`);a.classList.add(`flex-none`),a.onclick=()=>{e=e.filter(e=>e!==n),k(),L()};let o=f(`span`,`min-w-0 flex-1 truncate font-mono text-[12px] text-neutral-700`,Y(n));o.title=Y(n);let s=A(n,-1,ue,`Move up`),c=A(n,1,t,`Move down`);if(u?.at===n){let[e,t]=u.step===-1?[s,c]:[c,s];u=null,queueMicrotask(()=>(e.disabled?t:e).focus())}return f(`div`,`flex min-w-0 items-center gap-2 rounded-lg border border-neutral-200 bg-white px-3 py-2 shadow-2xs max-md:flex-wrap`,f(`span`,`flex flex-none items-center`,s,c),o,r,i,a)}function M(){let t=S(`Pin model`);t.prepend(K(a)),t.classList.add(`inline-flex`,`items-center`,`gap-1.5`,`flex-none`,`whitespace-nowrap`),t.disabled=n.length===0,t.onclick=()=>{let r=ze;j(t,X({models:n,current:null,thinkingLevel:r,thinkingLevels:[...G],onThinkingPick:e=>{r=e},onPick:t=>{ee();let n=r,i=e.findIndex(e=>Y(e)===Y(t)&&e.thinking===n);if(i>=0){y(d,`failed`,`${Y(t)} is already pinned at ${z(n)} (row ${String(i+1)})`);return}e.push({provider:t.provider,id:t.id,thinking:n}),k(),L()}}))},x.replaceChildren(t)}function P(){let e=s,t=e&&!n.some(t=>Y(t)===Y(e))?[e,...n]:n,r=q(e?e.id:Ve,`${N} flex min-w-0 flex-1 items-center ${e?`text-neutral-700`:`text-neutral-400`}`);e&&(r.title=Y(e));let i=e=>{ee(),(async()=>{y(p,`saving`,`saving…`);let t=await H(`/api/settings`,{titleModel:e&&{provider:e.provider,id:e.id}},`PUT`);if(!t.ok)return y(p,`failed`,await U(t,`Could not save`)),P();s=(await t.json()).titleModel,y(p,`saved`,s?`Saved — names the next new session after its first reply.`:`Off.`),P()})()};r.onclick=()=>{let n=X({models:t,current:e,thinkingLevel:`medium`,thinkingLevels:[],onThinkingPick:()=>{},onPick:i}),a=q(Ve,`w-full cursor-pointer px-3 py-1.5 text-left text-[12.5px] text-neutral-500 hover:bg-neutral-100`);a.onclick=()=>i(null);let o=f(`div`,`flex flex-col`);o.append(n,f(`div`,`border-t border-neutral-200`),a),j(r,o)},m.replaceChildren(r,p)}function F(){_.replaceChildren(Z(`Default model`,c,n,e=>void I(e)),h)}async function I(e){y(h,`saving`,`saving…`);let t=await H(`/api/config/defaults`,{defaultModel:e.model,defaultThinkingLevel:e.thinking},`PUT`);if(!t.ok)return y(h,`failed`,await U(t,`Could not save`)),F();c=Be(await t.json()),y(h,`saved`,c.model||c.thinking?`Saved — the next new session starts on it.`:`Pi default.`),F()}function L(){b.replaceChildren(...e.length?e.map(te):[C(`Nothing pinned — every picker shows the curated catalog as is.`)]),M(),F(),P(),w.disabled=l,T.disabled=l;for(let e of E)e.hidden=!l}async function R(){y(d,`saving`,`saving…`);let t=e.map(({provider:e,id:t,thinking:n,tier:r})=>({provider:e,id:t,thinking:n,...r?{tier:r}:{}})),n=await H(`/api/settings`,{modelMenu:t},`PUT`);if(!n.ok)return y(d,`failed`,await U(n,`Could not save`));e=(await n.json()).modelMenu,i=!1,y(d,`saved`,`Saved — agents see it on their next models call.`),L()}v.onclick=()=>void R();function B(){i||(async()=>{let[t,r,i,a]=await Promise.all([V(`/api/settings`,`Could not load the menu`),V(`/api/models`,`Could not load the model catalog`),V(`/api/config/defaults`,`Could not read the default model`),Te()]);if(!t.ok)return y(d,`failed`,t.error);l=a,e=t.value.modelMenu,s=t.value.titleModel,n=r.ok?r.value:[],i.ok?(c=Be(i.value),h.textContent=``):y(h,`failed`,i.error),d.textContent=``,L()})()}return w.append(E[0],o(`Pinned models`,b,{hint:"The tier is what a dispatcher names — `--model balanced` is the first balanced row, and the balanced rows below it are tried in turn when it is not in the catalog. The arrows set that order, the order pickers and `pier task --model ?` list."}),o(`Add`,x,{hint:`The list is the live catalog — only models that exist right now can be pinned. A model may be pinned again at another reasoning level, each row with its own tier.`}),f(`div`,`flex items-center gap-3`,v,d)),T.append(E[1],_),O.append(r(`Model menu`,`Which few models this deployment favors, each with a usual reasoning level and a tier. Pinned entries lead every model picker, and agents delegating work name a tier instead of guessing ids.`,w),r(`New sessions`,`The model and reasoning effort a session starts on when nothing names one — a channel, chat or task with its own launch choice overrides it. Pi default leaves the pick to Pi. Stored in settings.json; applies to sessions opened from now on.`,T),r(`Session titles`,`A session is titled by its first message unless a model names it: one short request after the first reply, on the model picked here — a small, cheap one is plenty. A failed request is reported in the session and the first message stays the title.`,o(`Title model`,m))),{el:O,load:B}}var Ue=e=>Uint8Array.from(atob(e.replace(/-/g,`+`).replace(/_/g,`/`)),e=>e.charCodeAt(0)),We=e=>btoa(String.fromCharCode(...new Uint8Array(e))).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``);function Ge(){let e=f(`div`,`flex flex-col gap-2`),t=f(`span`,`text-[11.5px]`,``),n=_();n.placeholder=`Label, e.g. MacBook Touch ID`,n.autocomplete=`off`,n.maxLength=80;let i=S(`Add a passkey`,!0),a=f(`div`,`flex flex-wrap items-center gap-3`,n,i,t),o=f(`p`,`hidden text-[12.5px] leading-snug text-neutral-600`),s=f(`p`,`hidden text-[12px] text-neutral-400`);function c(n){if(s.textContent=n.reason??``,s.classList.toggle(`hidden`,n.enabled),a.classList.toggle(`hidden`,!n.enabled),o.textContent=`Password sign-in is off while a passkey is registered; remove every passkey to turn it back on.`,o.classList.toggle(`hidden`,!n.passkeys.length),!n.passkeys.length){e.replaceChildren(C(`No passkey is registered.`));return}e.replaceChildren(...n.passkeys.map(e=>{let n=S(`Remove`);n.onclick=()=>{n.disabled=!0,(async()=>{let n=await k(`/api/passkeys/${encodeURIComponent(e.id)}`,`DELETE`,`Could not remove it`);n?y(t,`failed`,n):y(t,`saved`,`Removed.`),await d()})()};let r=e.lastUsedAt?`last used ${u(e.lastUsedAt)}`:`never used`,i=e.transports.length?` · ${e.transports.join(`, `)}`:``;return re(e.label,`added ${u(e.createdAt)} · ${r}${i}`,n)}))}async function l(){if(!window.PublicKeyCredential)return y(t,`failed`,`This browser has no passkey support.`);i.disabled=!0,y(t,`saving`,`asking this browser…`);try{let e=await P(`/api/passkeys/register/options`,{},`Could not start`);if(!e.ok)return y(t,`failed`,e.error);let r={...e.value,challenge:Ue(e.value.challenge),user:{...e.value.user,id:Ue(e.value.user.id)},excludeCredentials:e.value.excludeCredentials.map(e=>({...e,id:Ue(e.id),transports:e.transports}))},i=await navigator.credentials.create({publicKey:r});if(!i)return y(t,`failed`,`No passkey was created.`);let a=i.response,o=await H(`/api/passkeys/register/verify`,{id:i.id,type:i.type,label:n.value,response:{clientDataJSON:We(a.clientDataJSON),attestationObject:We(a.attestationObject),transports:a.getTransports?.()??[]}});if(!o.ok)return y(t,`failed`,await U(o,`Could not register it`));n.value=``,c(await o.json()),y(t,`saved`,`Added. The password is off until every passkey is removed.`)}catch(e){let n=e instanceof DOMException&&e.name===`NotAllowedError`;y(t,`failed`,n?`The prompt was dismissed or timed out.`:`Could not add it: ${String(e)}`)}finally{i.disabled=!1}}i.onclick=()=>void l();async function d(){let t=await V(`/api/passkeys`,`Could not load passkeys`);return t.ok?(c(t.value),t.value.passkeys.length>0):(e.replaceChildren(C(t.error)),!1)}return{el:r(`Passkeys`,`Sign in with Touch ID, Windows Hello, a phone or a security key instead of the password. Bound to the public URL's host.`,e,o,s,a),load:d}}var Ke=(e,t)=>{let n;try{n=new URL(e)}catch{return null}if(n.protocol!==`http:`&&n.protocol!==`https:`)return null;let r=f(`a`,`text-indigo-600 hover:underline`,t);return r.href=n.href,r.target=`_blank`,r.rel=`noreferrer`,r};function qe(e,t,n,r){let i=document.createElement(`dialog`);i.className=`m-auto w-[min(32rem,92vw)] rounded-lg border border-neutral-200 bg-white p-0 shadow-xl backdrop:bg-black/30`;let a=f(`div`,`flex flex-col gap-2`),o=f(`div`,`flex flex-col gap-2`),s=f(`p`,`text-[12.5px] text-neutral-400`,`Starting…`),c=S(`Cancel`),l=(e,t)=>{s.className=`text-[12.5px] ${J[e]}`,s.textContent=t};i.append(f(`div`,`border-b border-neutral-200 px-4 py-2.5 text-[14px] font-semibold`,t),f(`div`,`flex max-h-[65vh] flex-col gap-3 overflow-y-auto px-4 py-3`,a,o,s),f(`div`,`flex justify-end border-t border-neutral-200 px-4 py-2.5`,c)),document.body.append(i),i.showModal();let u=e.id,d=e.state,m,h,g=new Set,v=!1,y=!1,b=async e=>{if(!y){if(e&&d===`running`){y=!0,c.disabled=!0;try{let e=await H(`/api/providers/flows/${u}/cancel`,{});if(!e.ok&&e.status!==404){l(`failed`,await U(e,`Could not cancel authentication flow`));return}}catch(e){l(`failed`,`Could not cancel authentication flow: ${String(e)}`);return}finally{y=!1,c.disabled=!1}}clearTimeout(m),i.close()}};c.onclick=()=>void b(!0),i.oncancel=e=>{e.preventDefault(),b(!0)},i.onclose=()=>{v=!0,clearTimeout(m),i.remove()};let x=e=>{if(e.type===`auth_url`){let t=f(`div`,`flex flex-col gap-1 text-[12.5px] text-neutral-600`);return e.instructions&&t.append(f(`p`,``,e.instructions)),t.append(Ke(e.url,`Open authorization page`)??f(`span`,`text-red-600`,`Invalid authorization URL`)),t}if(e.type===`device_code`){let t=f(`div`,`flex flex-col gap-2 text-[12.5px] text-neutral-600`);return t.append(f(`div`,`flex items-center gap-2`,f(`code`,`font-mono text-[17px] font-semibold text-neutral-800`,e.userCode),p(`btn text-[11px]`,()=>e.userCode))),t.append(Ke(e.verificationUri,`Open verification page`)??f(`span`,`text-red-600`,`Invalid verification URL`)),t}let t=f(`div`,`text-[12.5px] text-neutral-600`,e.message);if(e.type===`info`)for(let n of e.links??[]){let e=Ke(n.url,n.label??n.url);e&&t.append(` `,e)}return t},C=(e,t)=>{h=t.id;let n;if(t.type===`select`){let e=document.createElement(`select`);e.append(...t.options.map(e=>new Option(e.description?`${e.label} — ${e.description}`:e.label,e.id))),n=e}else{let e=_(``,t.type===`secret`?`password`:`text`);e.placeholder=t.placeholder??``,e.autocomplete=`off`,n=e}n.className=`${n.tagName===`SELECT`?`select `:``}w-full rounded-lg border border-neutral-300 bg-white px-2.5 py-1.5 text-[12.5px] focus:border-indigo-400 focus:outline-none`;let r=S(`Continue`,!0);r.type=`submit`;let i=f(`form`,`flex flex-col gap-2`,f(`label`,`text-[12.5px] font-medium text-neutral-700`,t.message),n,f(`div`,`flex justify-end`,r));i.onsubmit=i=>{i.preventDefault(),r.disabled=!0,(async()=>{try{let r=await H(`/api/providers/flows/${e.id}/respond`,{promptId:t.id,value:n.value});if(v)return;if(!r.ok){l(`failed`,await U(r,`Could not submit response`));return}g.add(t.id),h=void 0,o.replaceChildren(),l(`saving`,`Waiting for provider…`)}catch(e){v||l(`failed`,`Could not submit response: ${String(e)}`)}finally{r.disabled=!1}})()},o.replaceChildren(i),n.focus()},w=e=>{d=e.state,a.replaceChildren(...e.events.map(x));let t=e.prompt&&!g.has(e.prompt.id)?e.prompt:void 0;if(t?.id!==h&&(t?C(e,t):(h=void 0,o.replaceChildren())),e.state===`running`){l(`saving`,t?`Waiting for your response.`:`Waiting for provider…`);return}clearTimeout(m),o.replaceChildren(),e.state===`succeeded`?l(`saved`,`${n} configured.`):l(`failed`,e.state===`cancelled`?`Cancelled.`:e.error??`Authentication failed.`),c.textContent=`Close`,c.onclick=()=>void b(!1),e.state===`succeeded`&&r()},T=async()=>{if(!(v||d!==`running`))try{let e=await fetch(`/api/providers/flows/${u}`,{cache:`no-store`});if(v)return;if(!e.ok){l(`failed`,await U(e,`Authentication status unavailable`)),e.status===404?d=`failed`:m=setTimeout(()=>void T(),1e3);return}w(await e.json()),d===`running`&&(m=setTimeout(()=>void T(),500))}catch(e){if(v)return;l(`failed`,`Authentication status unavailable: ${String(e)}`),m=setTimeout(()=>void T(),1e3)}};w(e),d===`running`&&(m=setTimeout(()=>void T(),500))}var Je=[`anthropic`,`openai`,`openai-codex`,`google`,`openrouter`,`deepseek`],Ye=[[`OpenAI Chat Completions`,`openai-completions`],[`OpenAI Responses`,`openai-responses`],[`Anthropic Messages`,`anthropic-messages`],[`Google Generative AI`,`google-generative-ai`]],Xe=`__custom__`;async function Ze(e){let t=S(`Add provider`,!0);t.classList.add(`ml-auto`);let n=f(`div`,`flex flex-none items-center gap-3 rounded-t-3xl ${W} px-4 py-2`,f(`h2`,`text-[13px] font-semibold text-neutral-700`,`Providers`),t),r=f(`div`,`min-h-0 flex-1 overflow-y-auto`);e.replaceChildren(n,r);let i=[],a=``,o=async()=>{r.replaceChildren(f(`p`,`px-4 py-3 text-[13px] text-neutral-400`,`Loading…`));try{let[e,n]=await Promise.all([V(`/api/providers`,`Could not load providers`,{cache:`no-store`}),V(`/api/models`,`the model catalog could not be read`,{cache:`no-store`})]);if(i=n.ok?n.value:[],a=n.ok?``:n.error,!e.ok){r.replaceChildren(C(e.error));return}let s=e.value;t.onclick=()=>$e(s,void 0,o),d(s)}catch(e){r.replaceChildren(C(`Could not load providers: ${String(e)}`))}},s=async e=>{if(window.confirm(`Remove the stored credential for ${e.name}?`))try{let t=await H(`/api/providers/${encodeURIComponent(e.id)}/logout`,{});if(!t.ok){window.alert(await U(t,`Could not remove credential`));return}await o()}catch(e){window.alert(`Could not remove credential: ${String(e)}`)}},c=e=>[...new Set([...(e.models??[]).map(e=>e.id),...i.filter(t=>t.provider===e.id).map(e=>e.id)])],l=(e,t)=>f(`div`,`flex flex-col gap-1`,f(`span`,`text-[10.5px] font-semibold uppercase tracking-wide text-neutral-400`,e),f(`pre`,`max-h-56 overflow-auto whitespace-pre-wrap break-all rounded-md bg-neutral-50 p-2 font-mono text-[11.5px] leading-relaxed text-neutral-600`,t)),u=async(e,t)=>{try{let n=await H(`/api/providers/${encodeURIComponent(e)}/check`,{model:t});return n.ok?await n.json():await U(n,`Could not test`)}catch(e){return`Could not test: ${String(e)}`}},d=e=>{let t=e.filter(e=>e.configured);if(!t.length){r.replaceChildren(C(`No providers configured.`));return}r.replaceChildren(...t.map(t=>{let n=f(`div`,`min-w-0 flex-1`,f(`div`,`truncate text-[13px] font-medium text-neutral-700`,t.name),f(`div`,`truncate font-mono text-[11px] text-neutral-400`,t.id)),r=t.stored===`api_key`?`API key`:t.stored===`oauth`?`OAuth`:t.source??`configured`,i=t.endpoint??`Default endpoint`,d=f(`div`,`flex min-w-32 flex-col items-start gap-1`,A(`configured`,`bg-emerald-50 text-emerald-700 ring-emerald-200`),f(`span`,`max-w-48 truncate text-[11px] text-neutral-500`,r),f(`span`,`max-w-48 truncate text-[11px] text-neutral-400`,i));d.title=i;let p=f(`span`,`text-[11.5px]`,``),m=f(`div`,`hidden flex-col gap-2 px-4 pb-3`,p),h=f(`div`,`flex flex-wrap justify-end gap-1.5`),_=c(t);if(!_.length)y(p,`idle`,a||`No models to test: none are configured here.`),m.classList.replace(`hidden`,`flex`);else{let e=g([[`Model to test…`,``],..._.map(e=>[e,e])],``);e.classList.add(`max-w-52`,`text-[12px]`);let n=S(`Test`);n.disabled=!0,e.onchange=()=>n.disabled=!e.value,n.onclick=()=>{let r=e.value;n.disabled=!0,m.replaceChildren(p),m.classList.replace(`hidden`,`flex`),y(p,`saving`,`asking ${r}…`),u(t.id,r).then(e=>{if(n.disabled=!1,typeof e==`string`)return y(p,`failed`,e);y(p,e.ok?`saved`:`failed`,`${e.model} ${e.ok?`answered`:`did not answer`} in ${e.ms} ms`),m.append(l(`sent`,e.request||`(the request was never made)`),l(e.ok?`answered`:`replied`,e.response))})},h.append(e,n)}if(t.builtin||t.api&&t.models){let n=S(`Edit`);n.onclick=()=>$e(e,t,o),h.append(n)}if(t.stored){let e=S(`Remove credential`);e.onclick=()=>void s(t),h.append(e)}return f(`div`,`border-b border-neutral-100`,f(`div`,`grid grid-cols-[minmax(8rem,1fr)_minmax(8rem,auto)_minmax(9rem,auto)] items-center gap-3 px-4 py-2.5 max-sm:grid-cols-[1fr_auto]`,n,d,h),m)}))};await o()}function Qe(e,t){let n=t.filter(e=>!e.configured&&e.methods.length&&(e.builtin||e.api!==void 0&&e.models!==void 0)),r=(t,n)=>{if(!n.length)return;let r=document.createElement(`optgroup`);r.label=t,r.append(...n.map(e=>new Option(e.name,e.id))),e.append(r)};r(`Common`,Je.flatMap(e=>n.filter(t=>t.id===e))),r(`More providers`,n.filter(e=>e.builtin&&!Je.includes(e.id)).sort((e,t)=>e.name.localeCompare(t.name))),r(`Custom providers`,n.filter(e=>!e.builtin).sort((e,t)=>e.name.localeCompare(t.name))),e.append(new Option(`Custom provider…`,Xe))}function $e(e,t,n){let r=document.createElement(`dialog`);r.className=`m-auto w-[min(32rem,92vw)] rounded-lg border border-neutral-200 bg-white p-0 shadow-xl backdrop:bg-black/30`;let i=document.createElement(`select`);i.className=`${R} select`,t||Qe(i,e);let a=_(),s=_(),c=_(),l=document.createElement(`select`);l.className=`${R} select`,l.append(...Ye.map(([e,t])=>new Option(e,t)));let u=m(``,4);u.placeholder=`model-id
|
|
3
3
|
another-model-id`;let d=document.createElement(`input`);d.type=`checkbox`;let p=g([[`Up to High`,`high`],[`Up to Extra high`,`xhigh`],[`Up to Max`,`max`]],`high`);p.classList.replace(`w-full`,`w-48`),d.onchange=()=>{p.disabled=!d.checked};let h=document.createElement(`select`);h.className=`${R} select`;let v=f(`div`,`flex flex-col gap-4`),y=f(`span`,`text-[11.5px] text-red-600`,``),b=S(`Cancel`),x=S(t?`Save`:`Add`,!0);x.type=`submit`;let C=()=>t??e.find(e=>e.id===i.value),w=()=>{let e=C(),n=e?!e.builtin:i.value===Xe;a.value=e?.id??``,a.disabled=t!==void 0,s.value=e?.name??``,c.value=e?.endpoint??``,l.value=e?.api??`openai-completions`,u.value=e?.models?.map(e=>e.id).join(`
|
|
4
4
|
`)??``;let r=e?.models?.map(e=>e.reasoning)??[];d.checked=r.length?r.every(Boolean):!e,d.indeterminate=r.some(Boolean)&&!r.every(Boolean);let m=new Set((e?.models??[]).filter(e=>e.reasoning).map(e=>e.effort??`high`)),g=m.size>1;p.replaceChildren(...g?[new Option(`Keep as configured`,``)]:[],new Option(`Up to High`,`high`),new Option(`Up to Extra high`,`xhigh`),new Option(`Up to Max`,`max`)),p.value=g?``:[...m][0]??`high`,p.disabled=!d.checked&&!d.indeterminate;let _=[];e?.configured&&_.push(new Option(`Keep current authentication`,``));let y=e?.methods??[{type:`api_key`,name:`API key`}];for(let t of y.filter(t=>e?.builtin!==!1||t.type===`api_key`))_.push(new Option(t.name,t.type));h.replaceChildren(..._);let b=[];t||b.push(o(`Provider`,i)),n?b.push(o(`Provider ID`,a),o(`Display name`,s),o(`Endpoint`,c),o(`API format`,l),o(`Models`,u),o(`Model capabilities`,f(`div`,`flex flex-wrap items-center gap-3`,f(`label`,`flex items-center gap-2 text-[12.5px] text-neutral-600`,d,f(`span`,``,`Reasoning`)),p),{hint:`Extra high and Max reach the model only if it accepts them; every reasoning model has High.`})):(c.placeholder=`Provider default`,b.push(o(`Endpoint`,c))),b.push(o(`Authentication`,h)),v.replaceChildren(...b)};i.onchange=w,w();let T=f(`form`,`flex flex-col gap-4 px-4 py-3`,v,f(`div`,`flex items-center justify-end gap-2`,y,b,x)),E=!1;b.onclick=()=>{E||r.close()},r.oncancel=e=>{E&&e.preventDefault()},T.onsubmit=e=>{if(e.preventDefault(),E)return;y.textContent=``;let t=C(),o=(t?!t.builtin:i.value===Xe)?{kind:`custom`,id:a.value.trim(),...s.value.trim()?{name:s.value.trim()}:{},endpoint:c.value.trim(),api:l.value,models:[...new Set(u.value.split(`
|
|
Binary file
|
|
Binary file
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
which style.css pays for with the safe-area inset. -->
|
|
39
39
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
|
40
40
|
<title>Pier</title>
|
|
41
|
-
<script type="module" crossorigin src="/app/assets/index-
|
|
41
|
+
<script type="module" crossorigin src="/app/assets/index-DqLJpDE0.js"></script>
|
|
42
42
|
<link rel="modulepreload" crossorigin href="/app/assets/highlight-CDSk2hRJ.js">
|
|
43
43
|
<link rel="modulepreload" crossorigin href="/app/assets/hljs-BRz6a8Dq.js">
|
|
44
44
|
<link rel="stylesheet" crossorigin href="/app/assets/index-JN0Ic8K5.css">
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -39,9 +39,13 @@ already run several at once. Raise `--timeout` past the hour a long one needs,
|
|
|
39
39
|
or it is killed and reported as timed out. A non-zero exit still delivers what
|
|
40
40
|
it printed.
|
|
41
41
|
|
|
42
|
-
A
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
A result is two parts: the conclusion (paths, risks and unverified points one
|
|
43
|
+
line each), then `Needs your decision` only when something does. A child takes
|
|
44
|
+
reversible choices itself (how to push, a rebase strategy) with the recommended
|
|
45
|
+
option, named in its result; it stops only on a destructive or irreversible
|
|
46
|
+
step (force push, deleting what it did not create, migrations, deploys, restarts) or a question
|
|
47
|
+
only you can answer, ending its turn with that as its result; answer it with
|
|
48
|
+
`--run <id> --prompt`. Core owns the join: never aggregate members by hand.
|
|
45
49
|
|
|
46
50
|
## Model choice
|
|
47
51
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|