@timqi/pier 0.0.23 → 0.0.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/agent/config.js +3 -4
  2. package/dist/channels/config.js +1 -7
  3. package/dist/core/reply.js +1 -1
  4. package/dist/main.js +9 -0
  5. package/dist/service.js +2 -1
  6. package/dist/tasks/agent.js +1 -10
  7. package/dist/tools-task.js +4 -5
  8. package/dist/web/public/assets/{activity-atEIVnGA.js → activity-DRJDNEP9.js} +2 -2
  9. package/dist/web/public/assets/activity-DRJDNEP9.js.br +0 -0
  10. package/dist/web/public/assets/activity-DRJDNEP9.js.gz +0 -0
  11. package/dist/web/public/assets/{boards-DSkfMEvN.js → boards-ZmKTkCZ-.js} +1 -1
  12. package/dist/web/public/assets/boards-ZmKTkCZ-.js.br +0 -0
  13. package/dist/web/public/assets/boards-ZmKTkCZ-.js.gz +0 -0
  14. package/dist/web/public/assets/{code-1nUOCxAb.js → code-D1-CYID1.js} +1 -1
  15. package/dist/web/public/assets/{explorer-CS1kLPMl.js → explorer-De8NHWLj.js} +4 -4
  16. package/dist/web/public/assets/explorer-De8NHWLj.js.br +0 -0
  17. package/dist/web/public/assets/explorer-De8NHWLj.js.gz +0 -0
  18. package/dist/web/public/assets/index-DuhZm2hI.js +83 -0
  19. package/dist/web/public/assets/index-DuhZm2hI.js.br +0 -0
  20. package/dist/web/public/assets/index-DuhZm2hI.js.gz +0 -0
  21. package/dist/web/public/assets/runs-C7BNc137.js +1 -0
  22. package/dist/web/public/assets/runs-C7BNc137.js.br +0 -0
  23. package/dist/web/public/assets/runs-C7BNc137.js.gz +0 -0
  24. package/dist/web/public/assets/settings-BcWcHc7F.js +6 -0
  25. package/dist/web/public/assets/settings-BcWcHc7F.js.br +0 -0
  26. package/dist/web/public/assets/settings-BcWcHc7F.js.gz +0 -0
  27. package/dist/web/public/assets/task-runs-CJz8WLzY.js +3 -0
  28. package/dist/web/public/assets/task-runs-CJz8WLzY.js.br +0 -0
  29. package/dist/web/public/assets/task-runs-CJz8WLzY.js.gz +0 -0
  30. package/dist/web/public/assets/tasks-DQnZGbBg.js +4 -0
  31. package/dist/web/public/assets/tasks-DQnZGbBg.js.br +0 -0
  32. package/dist/web/public/assets/tasks-DQnZGbBg.js.gz +0 -0
  33. package/dist/web/public/index.html +1 -1
  34. package/dist/web/public/index.html.br +0 -0
  35. package/dist/web/public/index.html.gz +0 -0
  36. package/docs/deploy.md +0 -1
  37. package/package.json +1 -1
  38. package/dist/web/public/assets/activity-atEIVnGA.js.br +0 -0
  39. package/dist/web/public/assets/activity-atEIVnGA.js.gz +0 -0
  40. package/dist/web/public/assets/boards-DSkfMEvN.js.br +0 -0
  41. package/dist/web/public/assets/boards-DSkfMEvN.js.gz +0 -0
  42. package/dist/web/public/assets/explorer-CS1kLPMl.js.br +0 -0
  43. package/dist/web/public/assets/explorer-CS1kLPMl.js.gz +0 -0
  44. package/dist/web/public/assets/index-a7A8xfoi.js +0 -83
  45. package/dist/web/public/assets/index-a7A8xfoi.js.br +0 -0
  46. package/dist/web/public/assets/index-a7A8xfoi.js.gz +0 -0
  47. package/dist/web/public/assets/runs-bHSlJwXk.js +0 -1
  48. package/dist/web/public/assets/runs-bHSlJwXk.js.br +0 -0
  49. package/dist/web/public/assets/runs-bHSlJwXk.js.gz +0 -0
  50. package/dist/web/public/assets/settings-CrC-yuXh.js +0 -6
  51. package/dist/web/public/assets/settings-CrC-yuXh.js.br +0 -0
  52. package/dist/web/public/assets/settings-CrC-yuXh.js.gz +0 -0
  53. package/dist/web/public/assets/task-runs-C2PHAhAf.js +0 -3
  54. package/dist/web/public/assets/task-runs-C2PHAhAf.js.br +0 -0
  55. package/dist/web/public/assets/task-runs-C2PHAhAf.js.gz +0 -0
  56. package/dist/web/public/assets/tasks-7S90iYr1.js +0 -4
  57. package/dist/web/public/assets/tasks-7S90iYr1.js.br +0 -0
  58. package/dist/web/public/assets/tasks-7S90iYr1.js.gz +0 -0
@@ -147,9 +147,8 @@ export class PiConfigStore {
147
147
  validateProviderSetup(input);
148
148
  await this.#withWrite(async () => {
149
149
  const path = join(this.agentDir, "models.json");
150
- const existed = await pathExists(path);
151
- const raw = await readOptional(path);
152
- const parsed = raw.trim() ? parseModels(raw) : {};
150
+ const raw = await readNullable(path);
151
+ const parsed = raw?.trim() ? parseModels(raw) : {};
153
152
  if (!parsed)
154
153
  throw new Error("models.json must be valid JSON before configuring a provider");
155
154
  const providers = { ...parsed.providers };
@@ -198,7 +197,7 @@ export class PiConfigStore {
198
197
  throw new Error(`${path} changed while provider setup was being validated`, { cause: err });
199
198
  }
200
199
  try {
201
- if (existed)
200
+ if (raw !== null)
202
201
  await atomicWrite(path, raw, 0o600);
203
202
  else
204
203
  await fs.unlink(path);
@@ -93,13 +93,7 @@ export class ChannelStore {
93
93
  id: chat.id,
94
94
  name: chat.name,
95
95
  kind: chat.kind,
96
- enabled: true,
97
- requireMention: config.requireMention,
98
- requireBind: config.requireBind,
99
- topicMode: config.topicMode,
100
- cwd: config.cwd,
101
- model: config.model,
102
- thinking: config.thinking,
96
+ ...this.policy(platform, chat.id),
103
97
  });
104
98
  }
105
99
  this.save(platform, config);
@@ -213,7 +213,7 @@ export function splitReply(rawMarkdown, meta) {
213
213
  // Every surface that renders this goes through here, and every CommonMark
214
214
  // parser has some version of the CJK emphasis hole — so the repair belongs
215
215
  // once, at the seam, not per adapter.
216
- const markdown = cjkFriendly(rawMarkdown.replace(SILENT, "").trim());
216
+ const markdown = streamBody(rawMarkdown);
217
217
  const silence = silentReason(rawMarkdown);
218
218
  const m = BLOCK.exec(markdown);
219
219
  if (!m?.[1])
package/dist/main.js CHANGED
@@ -386,6 +386,15 @@ app.route("/", createServer({
386
386
  }));
387
387
  const port = Number(process.env.PORT ?? 3141);
388
388
  const hostname = process.env.HOST ?? "127.0.0.1";
389
+ // Read above, and dropped here so nothing else reads them: these three
390
+ // configure *this* process, and every command a turn runs inherits its env.
391
+ // `NODE_ENV=production` makes an agent's `npm install` skip devDependencies and
392
+ // silently changes what half the ecosystem builds; PORT and HOST would aim an
393
+ // agent's own dev server at Pier's socket. Deleted at runtime rather than only
394
+ // dropped from the unit, because an installed unit is rewritten by
395
+ // `pier service install --force` and by nothing else.
396
+ for (const leak of ["NODE_ENV", "PORT", "HOST"])
397
+ delete process.env[leak];
389
398
  const server = serve({ fetch: app.fetch, port, hostname }, () => {
390
399
  log.info(`workbench on http://${hostname}:${port}`);
391
400
  log.info(`pid ${process.pid}, node ${process.version}, home ${PIER_HOME}`);
package/dist/service.js CHANGED
@@ -64,7 +64,8 @@ WorkingDirectory=%h
64
64
  # Absolute paths on purpose: systemd starts with a minimal PATH, and the node
65
65
  # that installed Pier is usually not on it.
66
66
  ExecStart=${quote(execPath, true)} ${quote(entry, true)}
67
- ${environment("NODE_ENV", "production")}
67
+ # No NODE_ENV: nothing in Pier reads it, and it is inherited by every command a
68
+ # turn runs — an agent's "npm install" would skip devDependencies.
68
69
  # Inherited by every command a turn runs, which is why it is here and not just
69
70
  # in the updater: an agent typing "npm test" on systemd's minimal PATH would be
70
71
  # told node does not exist on a machine that installed Pier with it.
@@ -9,7 +9,6 @@ import { runSource } from "./callbacks.js";
9
9
  import { TaskMessenger } from "./messages.js";
10
10
  import { TaskStore } from "./store.js";
11
11
  const MAX_ACTIVE_AGENTS = 4;
12
- const MAX_ACTIVE_PER_ROOT = 4;
13
12
  /** What a child cannot know unless told. Every session gets the chat-surface
14
13
  * contract (<pier>/AGENTS.md), task runs included — so the delegation prompt
15
14
  * says which of it does not apply here, and a supervised run how to reach the
@@ -180,7 +179,7 @@ export class AgentTaskRunner {
180
179
  return session;
181
180
  }
182
181
  async acquireSlot(run, signal) {
183
- while (this.active.size >= MAX_ACTIVE_AGENTS || this.activeForRoot(run.rootRunId) >= MAX_ACTIVE_PER_ROOT) {
182
+ while (this.active.size >= MAX_ACTIVE_AGENTS) {
184
183
  if (signal.aborted)
185
184
  throw new Error("cancelled");
186
185
  await new Promise((resolve, reject) => {
@@ -199,14 +198,6 @@ export class AgentTaskRunner {
199
198
  }
200
199
  this.active.add(run.id);
201
200
  }
202
- activeForRoot(rootRunId) {
203
- let count = 0;
204
- for (const id of this.active) {
205
- if (this.store.getRun(id)?.rootRunId === rootRunId)
206
- count += 1;
207
- }
208
- return count;
209
- }
210
201
  releaseSlot(id) {
211
202
  this.active.delete(id);
212
203
  for (const wake of this.slotWaiters)
@@ -72,6 +72,7 @@ export function toolsTask(tasks) {
72
72
  const draft = {
73
73
  name: "tools: daily update",
74
74
  description: "Installs the CLI tools switched on in Settings → Agent and keeps them current.",
75
+ enabled: true,
75
76
  trigger: {
76
77
  type: "cron",
77
78
  expression: "17 4 * * *",
@@ -79,9 +80,9 @@ export function toolsTask(tasks) {
79
80
  },
80
81
  // PIER_HOME as cwd: the command belongs to the instance, not to a project.
81
82
  action: { type: "bash", script: command.script, cwd: PIER_HOME },
83
+ callback: { type: "none" },
82
84
  timeoutSeconds: 1800,
83
85
  };
84
- const draftShape = [draft.name, draft.description, true, draft.trigger, draft.action, { type: "none" }, draft.timeoutSeconds];
85
86
  // Archived is not "owned but edited": nothing can un-archive a task, so the
86
87
  // replacement is a new one and the old one keeps its history.
87
88
  const owned = tasks.list().filter((task) => task.creator === TOOLS_TASK_CREATOR && !task.archived);
@@ -95,13 +96,11 @@ export function toolsTask(tasks) {
95
96
  // Every field Pier owns, not just the command: a paused task, a renamed one
96
97
  // or one pointed at a callback still claims to be keeping the tools current
97
98
  // while the daily run never happens.
98
- const current = task &&
99
- JSON.stringify([task.name, task.description, task.enabled, task.trigger, task.action, task.callback, task.timeoutSeconds]);
100
- if (task && current !== JSON.stringify(draftShape)) {
99
+ if (task && Object.entries(draft).some(([key, value]) => JSON.stringify(task[key]) !== JSON.stringify(value))) {
101
100
  log.warn("the tools update task was edited — restoring the definition Pier owns");
102
101
  // Named as the owner: this is the one path allowed to write it back
103
102
  // (tasks/definitions.ts).
104
- await tasks.update(task.id, { ...draft, enabled: true, callback: { type: "none" } }, TOOLS_TASK_CREATOR);
103
+ await tasks.update(task.id, draft, TOOLS_TASK_CREATOR);
105
104
  }
106
105
  const id = task ? task.id : (await tasks.create(draft, TOOLS_TASK_CREATOR)).id;
107
106
  toolsTaskId = id;
@@ -1,5 +1,5 @@
1
- import{F as e,G as t,I as n,M as r,O as i,R as a,S as o,V as s,_ as c,p as l,z as u}from"./index-a7A8xfoi.js";var d=(e,t={})=>{let n=document.createElementNS(`http://www.w3.org/2000/svg`,e);for(let[e,r]of Object.entries(t))n.setAttribute(e,r);return n},f=t=>t===null?`-`:e(Date.now()-t),p={light:{edge:`#a3a3a3`,callback:`#0891b2`,message:`#d97706`,scheduler:{fill:`#f5f3ff`,stroke:`#a78bfa`,text:`#5b21b6`},console:{fill:`#eff6ff`,stroke:`#93c5fd`,text:`#1d4ed8`},task:{fill:`#fffbeb`,stroke:`#fbbf24`,text:`#92400e`},process:{fill:`#f5f5f5`,stroke:`#a3a3a3`,text:`#525252`,dash:`4 3`},streaming:{fill:`#ffffff`,stroke:`#10b981`,text:`#262626`},idle:{fill:`#fafafa`,stroke:`#d4d4d4`,text:`#737373`}},dark:{edge:`#7a7a7a`,callback:`#3fc3dd`,message:`#e0a13a`,scheduler:{fill:`#2b2440`,stroke:`#7d63c9`,text:`#c9b8f5`},console:{fill:`#1f2a3d`,stroke:`#4a7fbf`,text:`#a8c8f0`},task:{fill:`#3a2f1c`,stroke:`#b8862a`,text:`#f0d49a`},process:{fill:`#262626`,stroke:`#5c5c5c`,text:`#a3a3a3`,dash:`4 3`},streaming:{fill:`#22302a`,stroke:`#10b981`,text:`#e5e5e5`},idle:{fill:`#212121`,stroke:`#4a4a4a`,text:`#9a9a9a`}}},m=()=>p[document.documentElement.dataset.theme===`dark`?`dark`:`light`];function h(e,p,h){let g=`sessions`,_=`active`,v={sessions:[],runs:[],messages:[]},y=``,b=u(async()=>{let r=_,i=await s(`/api/activity?scope=${r}`,`Failed to load activity`);if(!i.ok){y=``,e.replaceChildren(n(`p`,`p-4 text-[13px] text-red-600`,i.error));return}if(r!==_)return;let a=JSON.stringify(i.value);if(`${r}:${a}`===y)return;y=`${r}:${a}`;let o=i.value;v={...o,sessions:o.sessions.map(e=>({...e,title:t(e.title)}))},x()});function x(){let t=i(o([[`Sessions`,`sessions`],[`Relationships`,`dependencies`]],g,e=>{g=e,x()}),n(`span`,`ml-auto text-[11.5px] text-neutral-400`,`${v.sessions.length} sessions · ${v.runs.length} runs`),o([[`Current`,`active`],[`Last 24h`,`recent`]],_,e=>{_=e,x(),b()})),r=n(`div`,`min-h-0 flex-1 overflow-auto`);g===`sessions`?S(r):w(r),e.replaceChildren(t,r)}function S(e){let t=document.createElement(`table`);t.className=`w-full table-fixed text-left text-[12.5px]`,t.innerHTML=`<thead class="sticky top-0 bg-neutral-50 text-[10.5px] uppercase tracking-wide text-neutral-400 shadow-[inset_0_-1px_0_var(--color-neutral-200)]"><tr>
1
+ import{B as e,C as t,H as n,I as r,K as i,L as a,N as o,k as s,m as c,v as l,z as u}from"./index-DuhZm2hI.js";var d=(e,t={})=>{let n=document.createElementNS(`http://www.w3.org/2000/svg`,e);for(let[e,r]of Object.entries(t))n.setAttribute(e,r);return n},f=e=>e===null?`-`:r(Date.now()-e),p={light:{edge:`#a3a3a3`,callback:`#0891b2`,message:`#d97706`,scheduler:{fill:`#f5f3ff`,stroke:`#a78bfa`,text:`#5b21b6`},console:{fill:`#eff6ff`,stroke:`#93c5fd`,text:`#1d4ed8`},task:{fill:`#fffbeb`,stroke:`#fbbf24`,text:`#92400e`},process:{fill:`#f5f5f5`,stroke:`#a3a3a3`,text:`#525252`,dash:`4 3`},streaming:{fill:`#ffffff`,stroke:`#10b981`,text:`#262626`},idle:{fill:`#fafafa`,stroke:`#d4d4d4`,text:`#737373`}},dark:{edge:`#7a7a7a`,callback:`#3fc3dd`,message:`#e0a13a`,scheduler:{fill:`#2b2440`,stroke:`#7d63c9`,text:`#c9b8f5`},console:{fill:`#1f2a3d`,stroke:`#4a7fbf`,text:`#a8c8f0`},task:{fill:`#3a2f1c`,stroke:`#b8862a`,text:`#f0d49a`},process:{fill:`#262626`,stroke:`#5c5c5c`,text:`#a3a3a3`,dash:`4 3`},streaming:{fill:`#22302a`,stroke:`#10b981`,text:`#e5e5e5`},idle:{fill:`#212121`,stroke:`#4a4a4a`,text:`#9a9a9a`}}},m=()=>p[document.documentElement.dataset.theme===`dark`?`dark`:`light`];function h(r,p,h){let g=`sessions`,_=`active`,v={sessions:[],runs:[],messages:[]},y=``,b=e(async()=>{let e=_,t=await n(`/api/activity?scope=${e}`,`Failed to load activity`);if(!t.ok){y=``,r.replaceChildren(a(`p`,`p-4 text-[13px] text-red-600`,t.error));return}if(e!==_)return;let o=JSON.stringify(t.value);if(`${e}:${o}`===y)return;y=`${e}:${o}`;let s=t.value;v={...s,sessions:s.sessions.map(e=>({...e,title:i(e.title)}))},x()});function x(){let e=s(t([[`Sessions`,`sessions`],[`Relationships`,`dependencies`]],g,e=>{g=e,x()}),a(`span`,`ml-auto text-[11.5px] text-neutral-400`,`${v.sessions.length} sessions · ${v.runs.length} runs`),t([[`Current`,`active`],[`Last 24h`,`recent`]],_,e=>{_=e,x(),b()})),n=a(`div`,`min-h-0 flex-1 overflow-auto`);g===`sessions`?S(n):w(n),r.replaceChildren(e,n)}function S(e){let t=document.createElement(`table`);t.className=`w-full table-fixed text-left text-[12.5px]`,t.innerHTML=`<thead class="sticky top-0 bg-neutral-50 text-[10.5px] uppercase tracking-wide text-neutral-400 shadow-[inset_0_-1px_0_var(--color-neutral-200)]"><tr>
2
2
  <th class="w-[50%] px-4 py-2 font-semibold md:w-[34%]">Session</th>
3
3
  <th class="hidden w-[38%] px-2 py-2 font-semibold md:table-cell">Project</th>
4
4
  <th class="px-2 py-2 font-semibold md:w-[14%]">State</th>
5
- <th class="px-2 py-2 font-semibold">In state</th></tr></thead>`;let r=document.createElement(`tbody`);for(let e of v.sessions){let t=document.createElement(`tr`);t.className=`cursor-pointer border-b border-neutral-100 transition-colors hover:bg-neutral-50`,t.onclick=()=>p(e.id);let i=n(`button`,`block w-full cursor-pointer truncate text-left font-medium text-neutral-800`,e.title??a(e.cwd));i.setAttribute(`type`,`button`),i.title=`${e.id}\n${e.cwd}`,i.onclick=t=>{t.stopPropagation(),p(e.id)},t.append(n(`td`,`px-4 py-2.5`,i,n(`div`,`truncate font-mono text-[11px] text-neutral-400 md:hidden`,e.cwd||`-`)),n(`td`,`hidden truncate px-2 py-2.5 font-mono text-[11.5px] text-neutral-500 md:table-cell`,e.cwd||`-`),n(`td`,`px-2 py-2.5`,C(e.state)),n(`td`,`px-2 py-2.5 font-mono text-[11.5px] text-neutral-400`,f(e.stateSince))),r.append(t)}t.append(r),e.append(t),v.sessions.length||e.append(n(`div`,`p-4`,c(_===`active`?`No active sessions.`:`No sessions in the last 24 hours.`)))}function C(e){return e===`streaming`?l(e,`bg-emerald-50 text-emerald-700 ring-emerald-200`,`animate-pulse bg-emerald-500`):l(e,`bg-neutral-100 text-neutral-600 ring-neutral-200`,`bg-neutral-300`)}function w(e){let t=new Map,r=[],i=(e,n,r,i)=>{t.has(e)||t.set(e,{id:e,label:n,kind:r,state:i})};for(let e of v.sessions)i(e.id,e.title??e.id.slice(0,10),`session`,e.state);for(let e of v.runs){let t=e.invokedBySessionId??`scheduler`,n=e.targetSessionId??(e.context.definition.action.type===`bash`?`process:${e.id}`:`task:${e.id}`);i(t,t===`scheduler`?`Scheduler`:t.slice(0,10),t===`scheduler`?`scheduler`:`session`),i(n,e.targetSessionId?e.targetSessionId.slice(0,10):e.context.definition.action.type===`bash`?`Bash process`:`Task`,e.targetSessionId?`session`:e.context.definition.action.type===`bash`?`process`:`task`),r.push({from:t,to:n,run:e,kind:`invocation`}),e.callbackSessionId&&(i(e.callbackSessionId,e.callbackSessionId.slice(0,10),`session`),r.push({from:n,to:e.callbackSessionId,run:e,kind:`callback`}))}for(let e of v.messages){if(!e.fromSessionId||!e.toSessionId||e.fromSessionId===e.toSessionId)continue;let t=v.runs.find(t=>t.id===e.runId);if(t){for(let t of[e.fromSessionId,e.toSessionId])i(t,t===`console`?`Console`:t.slice(0,10),t===`console`?`console`:`session`);r.push({from:e.fromSessionId,to:e.toSessionId,run:t,kind:`message`})}}if(!t.size){e.append(n(`div`,`p-4`,c(_===`active`?`No active dependencies.`:`No dependencies in the last 24 hours.`)));return}let a=[...t.values()],o=new Set(r.map(e=>e.to)),s=new Map,l=a.filter(e=>!o.has(e.id)).map(e=>e.id);l.length||l.push(a[0].id);for(let e of l)s.set(e,0);for(;l.length;){let e=l.shift();for(let t of r)t.from!==e||s.has(t.to)||(s.set(t.to,s.get(e)+1),l.push(t.to))}for(let e of a)s.has(e.id)||s.set(e.id,0);let u=new Map;for(let e of a){let t=s.get(e.id);u.set(t,[...u.get(t)??[],e])}let f=Math.max(...u.keys())+1,g=Math.max(...[...u.values()].map(e=>e.length)),y=r.some(e=>e.from!==e.to&&s.get(e.from)===s.get(e.to))?40:0,b=56+f*180+(f-1)*110+y,x=56+g*46+(g-1)*30,S=new Map;for(let[e,t]of u)t.forEach((t,n)=>S.set(t.id,{x:28+e*290+90,y:28+n*76+23}));let C=d(`svg`,{width:String(b),height:String(x),viewBox:`0 0 ${b} ${x}`,class:`block`}),w=d(`defs`),T=m();for(let[e,t]of[[`activity-arrow`,T.edge],[`activity-arrow-cb`,T.callback],[`activity-arrow-msg`,T.message]]){let n=d(`marker`,{id:e,viewBox:`0 0 10 10`,refX:`9`,refY:`5`,markerWidth:`6`,markerHeight:`6`,orient:`auto-start-reverse`});n.append(d(`path`,{d:`M 0 0 L 10 5 L 0 10 z`,fill:t})),w.append(n)}C.append(w);let E=new Set;for(let e of r){let t=`${e.from}→${e.to}:${e.kind}`;if(E.has(t))continue;E.add(t);let n=S.get(e.from),r=S.get(e.to),i=d(`path`,{d:n.x===r.x?`M ${n.x+90} ${n.y} C ${n.x+90+46} ${n.y}, ${r.x+90+46} ${r.y}, ${r.x+90} ${r.y}`:(()=>{let e=r.x>n.x,t=n.x+(e?90:-90),i=r.x+(e?-90:90),a=Math.max(36,Math.abs(i-t)*.45)*(e?1:-1);return`M ${t} ${n.y} C ${t+a} ${n.y}, ${i-a} ${r.y}, ${i} ${r.y}`})(),fill:`none`,stroke:e.kind===`callback`?T.callback:e.kind===`message`?T.message:T.edge,"stroke-width":`1.5`,"marker-end":e.kind===`callback`?`url(#activity-arrow-cb)`:e.kind===`message`?`url(#activity-arrow-msg)`:`url(#activity-arrow)`});e.kind===`callback`&&i.setAttribute(`stroke-dasharray`,`6 5`),e.kind===`message`&&i.setAttribute(`stroke-dasharray`,`2 5`),i.classList.add(`cursor-pointer`),i.onclick=()=>h(e.run.id),C.append(i)}let D=/[\u1100-\u11FF\u2E80-\uA4CF\uAC00-\uD7A3\uF900-\uFAFF\uFE30-\uFE4F\uFF00-\uFF60\uFFE0-\uFFE6]/,O=(e,t)=>{let n=0;for(let r=0;r<e.length;r++)if(n+=D.test(e[r])?2:1,n>t)return`${e.slice(0,r)}…`;return e};for(let e of a){let t=S.get(e.id),n=e.kind===`session`?e.state===`streaming`?T.streaming:T.idle:T[e.kind],r=d(`g`,{transform:`translate(${t.x},${t.y})`});e.kind===`session`&&r.classList.add(`cursor-pointer`),r.onclick=()=>{e.kind===`session`&&p(e.id)};let i=d(`rect`,{x:`-90`,y:`-23`,width:`180`,height:`46`,rx:`8`,fill:n.fill,stroke:n.stroke,"stroke-width":e.kind===`session`&&e.state===`streaming`?`1.5`:`1`});n.dash&&i.setAttribute(`stroke-dasharray`,n.dash),r.append(i);let a=-78;if(e.kind===`session`){let t=d(`circle`,{cx:`-75`,cy:`0`,r:`3.5`,fill:n.stroke});if(e.state===`streaming`){let e=d(`animate`,{attributeName:`opacity`,values:`1;0.3;1`,dur:`1.6s`,repeatCount:`indefinite`});t.append(e)}r.append(t),a=-64}let o=d(`text`,{x:String(a),"text-anchor":`start`,"dominant-baseline":`middle`,"font-size":`11.5`,"font-weight":e.kind===`session`?`500`:`400`,fill:n.text});o.textContent=O(e.label,e.kind===`session`?22:25);let s=d(`title`);s.textContent=e.label===e.id?e.id:`${e.label}\n${e.id}`,r.append(o,s),C.append(r)}let k=e=>n(`span`,`inline-block h-2 w-2 rounded-full ${e}`),A=e=>n(`span`,`inline-block h-0 w-6 border-t-2 ${e}`);e.append(n(`div`,`w-max p-4`,C),n(`div`,`flex flex-wrap gap-x-5 gap-y-1.5 border-t border-neutral-200 bg-neutral-50/60 px-4 py-2 text-[11px] text-neutral-500`,n(`span`,`inline-flex items-center gap-2`,A(`border-solid border-neutral-400`),`task invocation`),n(`span`,`inline-flex items-center gap-2 text-cyan-700`,A(`border-dashed border-cyan-500`),`callback`),n(`span`,`inline-flex items-center gap-2 text-amber-700`,A(`border-dotted border-amber-500`),`supervisor / control`),n(`span`,`inline-flex items-center gap-1.5`,k(`bg-emerald-500`),`streaming`),n(`span`,`inline-flex items-center gap-1.5`,k(`bg-neutral-300`),`idle`)))}let T=r(e,e=>{e===`dependencies`?g=`dependencies`:e===`sessions`&&(g=`sessions`),b()},()=>{e.replaceChildren(),v={sessions:[],runs:[],messages:[]},y=``});return window.addEventListener(`pier:theme`,()=>{T.visible&&x()}),Object.assign(T,{refresh(){T.visible&&b()}})}export{h as createActivityView};
5
+ <th class="px-2 py-2 font-semibold">In state</th></tr></thead>`;let n=document.createElement(`tbody`);for(let e of v.sessions){let t=document.createElement(`tr`);t.className=`cursor-pointer border-b border-neutral-100 transition-colors hover:bg-neutral-50`,t.onclick=()=>p(e.id);let r=a(`button`,`block w-full cursor-pointer truncate text-left font-medium text-neutral-800`,e.title??u(e.cwd));r.setAttribute(`type`,`button`),r.title=`${e.id}\n${e.cwd}`,r.onclick=t=>{t.stopPropagation(),p(e.id)},t.append(a(`td`,`px-4 py-2.5`,r,a(`div`,`truncate font-mono text-[11px] text-neutral-400 md:hidden`,e.cwd||`-`)),a(`td`,`hidden truncate px-2 py-2.5 font-mono text-[11.5px] text-neutral-500 md:table-cell`,e.cwd||`-`),a(`td`,`px-2 py-2.5`,C(e.state)),a(`td`,`px-2 py-2.5 font-mono text-[11.5px] text-neutral-400`,f(e.stateSince))),n.append(t)}t.append(n),e.append(t),v.sessions.length||e.append(a(`div`,`p-4`,l(_===`active`?`No active sessions.`:`No sessions in the last 24 hours.`)))}function C(e){return e===`streaming`?c(e,`bg-emerald-50 text-emerald-700 ring-emerald-200`,`animate-pulse bg-emerald-500`):c(e,`bg-neutral-100 text-neutral-600 ring-neutral-200`,`bg-neutral-300`)}function w(e){let t=new Map,n=[],r=(e,n,r,i)=>{t.has(e)||t.set(e,{id:e,label:n,kind:r,state:i})};for(let e of v.sessions)r(e.id,e.title??e.id.slice(0,10),`session`,e.state);for(let e of v.runs){let t=e.invokedBySessionId??`scheduler`,i=e.targetSessionId??(e.context.definition.action.type===`bash`?`process:${e.id}`:`task:${e.id}`);r(t,t===`scheduler`?`Scheduler`:t.slice(0,10),t===`scheduler`?`scheduler`:`session`),r(i,e.targetSessionId?e.targetSessionId.slice(0,10):e.context.definition.action.type===`bash`?`Bash process`:`Task`,e.targetSessionId?`session`:e.context.definition.action.type===`bash`?`process`:`task`),n.push({from:t,to:i,run:e,kind:`invocation`}),e.callbackSessionId&&(r(e.callbackSessionId,e.callbackSessionId.slice(0,10),`session`),n.push({from:i,to:e.callbackSessionId,run:e,kind:`callback`}))}for(let e of v.messages){if(!e.fromSessionId||!e.toSessionId||e.fromSessionId===e.toSessionId)continue;let t=v.runs.find(t=>t.id===e.runId);if(t){for(let t of[e.fromSessionId,e.toSessionId])r(t,t===`console`?`Console`:t.slice(0,10),t===`console`?`console`:`session`);n.push({from:e.fromSessionId,to:e.toSessionId,run:t,kind:`message`})}}if(!t.size){e.append(a(`div`,`p-4`,l(_===`active`?`No active dependencies.`:`No dependencies in the last 24 hours.`)));return}let i=[...t.values()],o=new Set(n.map(e=>e.to)),s=new Map,c=i.filter(e=>!o.has(e.id)).map(e=>e.id);c.length||c.push(i[0].id);for(let e of c)s.set(e,0);for(;c.length;){let e=c.shift();for(let t of n)t.from!==e||s.has(t.to)||(s.set(t.to,s.get(e)+1),c.push(t.to))}for(let e of i)s.has(e.id)||s.set(e.id,0);let u=new Map;for(let e of i){let t=s.get(e.id);u.set(t,[...u.get(t)??[],e])}let f=Math.max(...u.keys())+1,g=Math.max(...[...u.values()].map(e=>e.length)),y=n.some(e=>e.from!==e.to&&s.get(e.from)===s.get(e.to))?40:0,b=56+f*180+(f-1)*110+y,x=56+g*46+(g-1)*30,S=new Map;for(let[e,t]of u)t.forEach((t,n)=>S.set(t.id,{x:28+e*290+90,y:28+n*76+23}));let C=d(`svg`,{width:String(b),height:String(x),viewBox:`0 0 ${b} ${x}`,class:`block`}),w=d(`defs`),T=m();for(let[e,t]of[[`activity-arrow`,T.edge],[`activity-arrow-cb`,T.callback],[`activity-arrow-msg`,T.message]]){let n=d(`marker`,{id:e,viewBox:`0 0 10 10`,refX:`9`,refY:`5`,markerWidth:`6`,markerHeight:`6`,orient:`auto-start-reverse`});n.append(d(`path`,{d:`M 0 0 L 10 5 L 0 10 z`,fill:t})),w.append(n)}C.append(w);let E=new Set;for(let e of n){let t=`${e.from}→${e.to}:${e.kind}`;if(E.has(t))continue;E.add(t);let n=S.get(e.from),r=S.get(e.to),i=d(`path`,{d:n.x===r.x?`M ${n.x+90} ${n.y} C ${n.x+90+46} ${n.y}, ${r.x+90+46} ${r.y}, ${r.x+90} ${r.y}`:(()=>{let e=r.x>n.x,t=n.x+(e?90:-90),i=r.x+(e?-90:90),a=Math.max(36,Math.abs(i-t)*.45)*(e?1:-1);return`M ${t} ${n.y} C ${t+a} ${n.y}, ${i-a} ${r.y}, ${i} ${r.y}`})(),fill:`none`,stroke:e.kind===`callback`?T.callback:e.kind===`message`?T.message:T.edge,"stroke-width":`1.5`,"marker-end":e.kind===`callback`?`url(#activity-arrow-cb)`:e.kind===`message`?`url(#activity-arrow-msg)`:`url(#activity-arrow)`});e.kind===`callback`&&i.setAttribute(`stroke-dasharray`,`6 5`),e.kind===`message`&&i.setAttribute(`stroke-dasharray`,`2 5`),i.classList.add(`cursor-pointer`),i.onclick=()=>h(e.run.id),C.append(i)}let D=/[\u1100-\u11FF\u2E80-\uA4CF\uAC00-\uD7A3\uF900-\uFAFF\uFE30-\uFE4F\uFF00-\uFF60\uFFE0-\uFFE6]/,O=(e,t)=>{let n=0;for(let r=0;r<e.length;r++)if(n+=D.test(e[r])?2:1,n>t)return`${e.slice(0,r)}…`;return e};for(let e of i){let t=S.get(e.id),n=e.kind===`session`?e.state===`streaming`?T.streaming:T.idle:T[e.kind],r=d(`g`,{transform:`translate(${t.x},${t.y})`});e.kind===`session`&&r.classList.add(`cursor-pointer`),r.onclick=()=>{e.kind===`session`&&p(e.id)};let i=d(`rect`,{x:`-90`,y:`-23`,width:`180`,height:`46`,rx:`8`,fill:n.fill,stroke:n.stroke,"stroke-width":e.kind===`session`&&e.state===`streaming`?`1.5`:`1`});n.dash&&i.setAttribute(`stroke-dasharray`,n.dash),r.append(i);let a=-78;if(e.kind===`session`){let t=d(`circle`,{cx:`-75`,cy:`0`,r:`3.5`,fill:n.stroke});if(e.state===`streaming`){let e=d(`animate`,{attributeName:`opacity`,values:`1;0.3;1`,dur:`1.6s`,repeatCount:`indefinite`});t.append(e)}r.append(t),a=-64}let o=d(`text`,{x:String(a),"text-anchor":`start`,"dominant-baseline":`middle`,"font-size":`11.5`,"font-weight":e.kind===`session`?`500`:`400`,fill:n.text});o.textContent=O(e.label,e.kind===`session`?22:25);let s=d(`title`);s.textContent=e.label===e.id?e.id:`${e.label}\n${e.id}`,r.append(o,s),C.append(r)}let k=e=>a(`span`,`inline-block h-2 w-2 rounded-full ${e}`),A=e=>a(`span`,`inline-block h-0 w-6 border-t-2 ${e}`);e.append(a(`div`,`w-max p-4`,C),a(`div`,`flex flex-wrap gap-x-5 gap-y-1.5 border-t border-neutral-200 bg-neutral-50/60 px-4 py-2 text-[11px] text-neutral-500`,a(`span`,`inline-flex items-center gap-2`,A(`border-solid border-neutral-400`),`task invocation`),a(`span`,`inline-flex items-center gap-2 text-cyan-700`,A(`border-dashed border-cyan-500`),`callback`),a(`span`,`inline-flex items-center gap-2 text-amber-700`,A(`border-dotted border-amber-500`),`supervisor / control`),a(`span`,`inline-flex items-center gap-1.5`,k(`bg-emerald-500`),`streaming`),a(`span`,`inline-flex items-center gap-1.5`,k(`bg-neutral-300`),`idle`)))}let T=o(r,e=>{e===`dependencies`?g=`dependencies`:e===`sessions`&&(g=`sessions`),b()},()=>{r.replaceChildren(),v={sessions:[],runs:[],messages:[]},y=``});return window.addEventListener(`pier:theme`,()=>{T.visible&&x()}),Object.assign(T,{refresh(){T.visible&&b()}})}export{h as createActivityView};
@@ -1 +1 @@
1
- import{B as e,D as t,I as n,L as r,M as i,N as a,U as o,V as s,W as c,m as l}from"./index-a7A8xfoi.js";var u=e=>e.public&&e.token?`/p/${e.slug}-${e.token}/`:`/boards/${e.slug}/`;function d(d,f){let p=[],m=``,h=n(`header`,`sticky top-0 z-30 flex h-10 items-center gap-3 border-b border-neutral-200 bg-white px-4`,n(`span`,`font-medium max-md:hidden`,`Boards`)),g=n(`div`,`px-4 py-5`);d.append(n(`div`,`min-h-0 flex-1 overflow-y-auto`,h,g));async function _(t,n){let r=await c(`/api/boards/${t.slug}`,{public:n},`PATCH`);if(r.ok)return t.token=(await r.json().catch(()=>({}))).token??``,x();m=await e(r,`Could not change ${t.slug}`),await S()}async function v(e){m=await o(`/api/boards/${e}`,`DELETE`,`Could not delete ${e}`)??``,await S()}function y(e){let i=n(`div`,`group flex flex-col gap-1 border-b border-neutral-200/70 px-1 py-2.5 last:border-b-0`),o=document.createElement(`a`);o.className=`truncate font-medium text-neutral-800 hover:text-indigo-700`,o.href=u(e),o.target=`_blank`,o.rel=`noreferrer`,o.textContent=e.title;let s=n(`div`,`flex items-center gap-2`,o,n(`span`,`flex-none font-mono text-[11.5px] text-neutral-400`,e.slug)),c=t(``,``,e.public,t=>{e.public=t,_(e,t)});c.className=`ml-auto flex flex-none cursor-pointer items-center gap-1.5 text-[11.5px] text-neutral-500`,c.append(n(`span`,``,`Public`));let d=l(`Delete`,`flex-none cursor-pointer text-[11.5px] text-neutral-400 opacity-0 transition-opacity hover:text-red-600 group-hover:opacity-100`);d.title=`Renames the folder on disk; nothing is erased`,d.onclick=()=>void v(e.slug);let p=a(`flex-none cursor-pointer text-[11.5px] text-neutral-400 opacity-0 transition-opacity hover:text-indigo-600 group-hover:opacity-100`,()=>`${location.origin}${u(e)}`);p.title=`Copy the board's link`,s.append(c,p,d),i.append(s);let m=n(`div`,`flex flex-wrap items-center gap-x-3 gap-y-1 text-[11.5px] text-neutral-500`);e.description&&m.append(n(`span`,`min-w-0 truncate`,e.description)),m.append(n(`span`,`flex-none text-neutral-400`,r(Date.parse(e.updatedAt))));for(let t of e.sessions){let e=l(t.slice(0,8),`flex-none cursor-pointer font-mono text-indigo-600 hover:underline`);e.title=`Open session ${t}`,e.onclick=()=>f(t),m.append(e)}if(e.public&&e.token){let t=n(`span`,`flex-none font-mono text-neutral-400`,u(e));t.title=`Public URL — anyone holding this link can read the board, no password`,m.append(t)}return i.append(m),i}let b=[{title:`Public`,hint:`Readable at /p/<slug>-<token>/ by anyone holding the link.`,wanted:!0},{title:`Private`,hint:`Reachable from the Console only.`,wanted:!1}];function x(){let e=n(`div`,`mx-auto flex max-w-3xl flex-col`);p.length===0&&e.append(n(`p`,`rounded-xl border border-dashed border-neutral-300 px-4 py-6 text-center text-[12.5px] text-neutral-500`,`No boards yet. Ask an agent to build one — it writes a folder under ~/.pier/boards.`));for(let{title:t,hint:r,wanted:i}of b){let a=p.filter(e=>e.public===i);if(a.length===0)continue;let o=n(`section`,`mb-6`);o.append(n(`h2`,`text-[13px] font-semibold text-neutral-700`,t)),o.append(n(`p`,`mb-1 text-[11.5px] leading-snug text-neutral-500`,r));let s=n(`div`,`rounded-xl border border-neutral-200 bg-white px-3`);s.append(...a.map(y)),o.append(s),e.append(o)}g.replaceChildren(...m?[n(`p`,`mb-3 text-[13px] text-red-600`,m)]:[],e)}async function S(){let e=await s(`/api/boards`,`Could not load boards`);if(!e.ok)return m=e.error,x();p=e.value,x(),m=``}let C=i(d,()=>void S());return window.addEventListener(`focus`,()=>{C.visible&&S()}),C}export{d as createBoardsView};
1
+ import{G as e,H as t,L as n,N as r,O as i,P as a,R as o,V as s,W as c,h as l}from"./index-DuhZm2hI.js";var u=e=>e.public&&e.token?`/p/${e.slug}-${e.token}/`:`/boards/${e.slug}/`;function d(d,f){let p=[],m=``,h=n(`header`,`sticky top-0 z-30 flex h-10 items-center gap-3 border-b border-neutral-200 bg-white px-4`,n(`span`,`font-medium max-md:hidden`,`Boards`)),g=n(`div`,`px-4 py-5`);d.append(n(`div`,`min-h-0 flex-1 overflow-y-auto`,h,g));async function _(t,n){let r=await e(`/api/boards/${t.slug}`,{public:n},`PATCH`);if(r.ok)return t.token=(await r.json().catch(()=>({}))).token??``,x();m=await s(r,`Could not change ${t.slug}`),await S()}async function v(e){m=await c(`/api/boards/${e}`,`DELETE`,`Could not delete ${e}`)??``,await S()}function y(e){let t=n(`div`,`group flex flex-col gap-1 border-b border-neutral-200/70 px-1 py-2.5 last:border-b-0`),r=document.createElement(`a`);r.className=`truncate font-medium text-neutral-800 hover:text-indigo-700`,r.href=u(e),r.target=`_blank`,r.rel=`noreferrer`,r.textContent=e.title;let s=n(`div`,`flex items-center gap-2`,r,n(`span`,`flex-none font-mono text-[11.5px] text-neutral-400`,e.slug)),c=i(``,``,e.public,t=>{e.public=t,_(e,t)});c.className=`ml-auto flex flex-none cursor-pointer items-center gap-1.5 text-[11.5px] text-neutral-500`,c.append(n(`span`,``,`Public`));let d=l(`Delete`,`flex-none cursor-pointer text-[11.5px] text-neutral-400 opacity-0 transition-opacity hover:text-red-600 group-hover:opacity-100`);d.title=`Renames the folder on disk; nothing is erased`,d.onclick=()=>void v(e.slug);let p=a(`flex-none cursor-pointer text-[11.5px] text-neutral-400 opacity-0 transition-opacity hover:text-indigo-600 group-hover:opacity-100`,()=>`${location.origin}${u(e)}`);p.title=`Copy the board's link`,s.append(c,p,d),t.append(s);let m=n(`div`,`flex flex-wrap items-center gap-x-3 gap-y-1 text-[11.5px] text-neutral-500`);e.description&&m.append(n(`span`,`min-w-0 truncate`,e.description)),m.append(n(`span`,`flex-none text-neutral-400`,o(Date.parse(e.updatedAt))));for(let t of e.sessions){let e=l(t.slice(0,8),`flex-none cursor-pointer font-mono text-indigo-600 hover:underline`);e.title=`Open session ${t}`,e.onclick=()=>f(t),m.append(e)}if(e.public&&e.token){let t=n(`span`,`flex-none font-mono text-neutral-400`,u(e));t.title=`Public URL — anyone holding this link can read the board, no password`,m.append(t)}return t.append(m),t}let b=[{title:`Public`,hint:`Readable at /p/<slug>-<token>/ by anyone holding the link.`,wanted:!0},{title:`Private`,hint:`Reachable from the Console only.`,wanted:!1}];function x(){let e=n(`div`,`mx-auto flex max-w-3xl flex-col`);p.length===0&&e.append(n(`p`,`rounded-xl border border-dashed border-neutral-300 px-4 py-6 text-center text-[12.5px] text-neutral-500`,`No boards yet. Ask an agent to build one — it writes a folder under ~/.pier/boards.`));for(let{title:t,hint:r,wanted:i}of b){let a=p.filter(e=>e.public===i);if(a.length===0)continue;let o=n(`section`,`mb-6`);o.append(n(`h2`,`text-[13px] font-semibold text-neutral-700`,t)),o.append(n(`p`,`mb-1 text-[11.5px] leading-snug text-neutral-500`,r));let s=n(`div`,`rounded-xl border border-neutral-200 bg-white px-3`);s.append(...a.map(y)),o.append(s),e.append(o)}g.replaceChildren(...m?[n(`p`,`mb-3 text-[13px] text-red-600`,m)]:[],e)}async function S(){let e=await t(`/api/boards`,`Could not load boards`);if(!e.ok)return m=e.error,x();p=e.value,x(),m=``}let C=r(d,()=>void S());return window.addEventListener(`focus`,()=>{C.visible&&S()}),C}export{d as createBoardsView};
@@ -1 +1 @@
1
- import{I as e,u as t}from"./index-a7A8xfoi.js";var n=2e4,r=e=>e.map((e,t)=>({nums:[t+1],text:e,tone:``}));function i(t,r){let i=t.length<=n?r:null,o=Math.max(2,...t.map(e=>e.nums.reduce((e,t)=>Math.max(e,String(t).length),0))),s=e(`div`,`py-2 font-mono text-[12px] leading-[1.5]`);for(let n of t){let t=e(`div`,`flex pl-2 pr-4 ${n.tone===`add`?`bg-emerald-50`:n.tone===`del`?`bg-red-50`:``}`);for(let r of n.nums){let n=e(`span`,`flex-none select-none pr-1.5 text-right text-neutral-300`,r===``?``:String(r));n.style.width=`calc(${o}ch + 0.375rem)`,t.append(n)}t.append(a(n,i)),s.append(t)}return s}function a(n,r){let i=`min-w-0 flex-1 whitespace-pre-wrap [overflow-wrap:anywhere]`;if(!n.mark||n.mark[0]>=n.mark[1]){let e=t(n.text,r);return e.className=i,e}let[a,o]=n.mark,s=t(n.text.slice(a,o),r);return s.className=`rounded-xs ${n.tone===`add`?`bg-emerald-200/80`:`bg-red-200/70`}`,e(`span`,i,t(n.text.slice(0,a),r),s,t(n.text.slice(o),r))}export{r as n,i as t};
1
+ import{L as e,d as t}from"./index-DuhZm2hI.js";var n=2e4,r=e=>e.map((e,t)=>({nums:[t+1],text:e,tone:``}));function i(t,r){let i=t.length<=n?r:null,o=Math.max(2,...t.map(e=>e.nums.reduce((e,t)=>Math.max(e,String(t).length),0))),s=e(`div`,`py-2 font-mono text-[12px] leading-[1.5]`);for(let n of t){let t=e(`div`,`flex pl-2 pr-4 ${n.tone===`add`?`bg-emerald-50`:n.tone===`del`?`bg-red-50`:``}`);for(let r of n.nums){let n=e(`span`,`flex-none select-none pr-1.5 text-right text-neutral-300`,r===``?``:String(r));n.style.width=`calc(${o}ch + 0.375rem)`,t.append(n)}t.append(a(n,i)),s.append(t)}return s}function a(n,r){let i=`min-w-0 flex-1 whitespace-pre-wrap [overflow-wrap:anywhere]`;if(!n.mark||n.mark[0]>=n.mark[1]){let e=t(n.text,r);return e.className=i,e}let[a,o]=n.mark,s=t(n.text.slice(a,o),r);return s.className=`rounded-xs ${n.tone===`add`?`bg-emerald-200/80`:`bg-red-200/70`}`,e(`span`,i,t(n.text.slice(0,a),r),s,t(n.text.slice(o),r))}export{r as n,i as t};
@@ -1,5 +1,5 @@
1
- import{H as e,I as t,L as n,M as r,P as i,a,i as o,j as s,l as c,n as l,s as u}from"./index-a7A8xfoi.js";import{n as d,t as f}from"./code-1nUOCxAb.js";var p=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())}`},m=e=>[e.subject,e.body,[[e.author,e.email?`<${e.email}>`:``].filter(Boolean).join(` `),e.at?p(e.at):``].filter(Boolean).join(` · `)].filter(Boolean).join(`
1
+ import{F as e,L as t,M as n,N as r,R as i,U as a,a as o,i as s,n as c,s as l,u}from"./index-DuhZm2hI.js";import{n as d,t as f}from"./code-D1-CYID1.js";var p=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())}`},m=e=>[e.subject,e.body,[[e.author,e.email?`<${e.email}>`:``].filter(Boolean).join(` `),e.at?p(e.at):``].filter(Boolean).join(` · `)].filter(Boolean).join(`
2
2
 
3
- `),h=null;function g(){h&&(h.remove(),h=null,document.removeEventListener(`pointerdown`,g,!0),window.removeEventListener(`scroll`,g,!0))}function _(e,n){e.onmouseenter=()=>{g();let r=n();if(!r)return;h=t(`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`),h.textContent=r,document.body.append(h),document.addEventListener(`pointerdown`,g,!0),window.addEventListener(`scroll`,g,!0);let i=e.getBoundingClientRect();h.style.left=`${Math.max(8,Math.min(i.left,window.innerWidth-h.offsetWidth-8))}px`,h.style.top=i.bottom+6+h.offsetHeight>window.innerHeight?`${i.top-h.offsetHeight-6}px`:`${i.bottom+6}px`},e.onmouseleave=g}function v(e,r,i){let a=t(`button`,`flex w-full cursor-pointer items-center gap-1.5 px-2 py-1 text-left hover:bg-neutral-100`,t(`span`,`w-3 flex-none text-indigo-600`,e.value===r?`✓`:``),t(`span`,`flex-none font-mono text-[11.5px] text-neutral-800`,e.label??e.value));return e.subject&&a.append(t(`span`,`min-w-0 truncate text-[11px] text-neutral-400`,e.subject)),e.author&&a.append(t(`span`,`ml-auto flex-none pl-1.5 text-[10.5px] text-neutral-400`,`${e.author} · ${e.at?n(e.at):``}`)),_(a,()=>m(e)),a.onclick=()=>i(e.value),a}function ee(e,n,r,i,s){let{base:c,head:l}=r,u=()=>l&&c===`${l}~1`?l:``,d=u()?`commit`:`compare`,f=n.commits[0],p=e=>[...e?[{value:``,label:`Working tree`,subject:`the files on disk, uncommitted changes included`}]:[],{...f,value:`HEAD`},...n.refs.map(e=>({value:e.name,subject:e.subject})),...n.commits.map(e=>({...e,value:e.hash}))],m=t(`div`,`flex w-[38rem] max-w-full flex-col`);function h(){let e=(e,n)=>{let r=t(`button`,`cursor-pointer rounded-full px-2.5 py-0.5 text-[11.5px] ${d===n?`bg-indigo-50 font-medium text-indigo-700`:`text-neutral-500 hover:bg-neutral-100`}`,e);return r.onclick=()=>{d=n,h()},r},r=(e,n,r,i)=>t(`div`,`flex min-w-0 flex-1 flex-col`,t(`div`,`flex-none px-2 pb-0.5 text-[10.5px] font-semibold uppercase tracking-wide text-neutral-400`,e),t(`div`,`min-h-0 flex-1 overflow-y-auto`,...n.map(e=>v(e,r,i)))),a=d===`compare`?t(`div`,`flex h-72 min-h-0 divide-x divide-neutral-200 pb-1`,r(`base`,p(!1),c,e=>{c=e,h(),i(c,l)}),r(`to`,p(!0),l,e=>{l=e,h(),i(c,l)})):t(`div`,`flex h-72 min-h-0 flex-col overflow-y-auto pb-1`,...n.commits.map(e=>v({value:e.hash,...e},u(),e=>{c=`${e}~1`,l=e,o(),i(c,l)}))),f=t(`div`,`flex-none border-t border-neutral-200`,v({value:s,label:`↺ ${s} ↔ Working tree`,subject:`back to the default: the main line's tip vs the files on disk`},c===s&&l===``?s:``,()=>{c=s,l=``,h(),i(c,l)}));m.replaceChildren(t(`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`)),a,...d===`compare`?[f]:[])}h(),a(e,m)}var te=/\.(png|jpe?g|gif|webp|avif|bmp|svg)$/i,ne={A:`text-emerald-600`,M:`text-amber-600`,D:`text-red-600`},re=30,y=`pier.filesPrefs`,b=50,x=()=>{try{let e=JSON.parse(localStorage.getItem(y)??`{}`);return e&&typeof e==`object`?e:{}}catch{return{}}},S=e=>{let t=e?x()[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},ie=(e,t)=>{let n=x();delete n[e],n[e]=t;let r=Object.keys(n);for(let e of r.slice(0,Math.max(0,r.length-b)))delete n[e];try{localStorage.setItem(y,JSON.stringify(n))}catch(e){console.warn(`Files: could not remember this folder`,e)}},C=(e,n=`indigo`)=>{let r=t(`button`,`min-w-0 cursor-pointer truncate rounded-md px-2 py-0.5 text-left font-mono text-[11.5px] ${n===`indigo`?`bg-indigo-50 font-medium text-indigo-700 hover:bg-indigo-100`:`bg-neutral-100 text-neutral-600 hover:bg-neutral-200`}`,e);return r.type=`button`,r};function w(n,a,o,p){let h=``,g=``,v={branch:null,refs:[],commits:[],worktrees:[]},y=`HEAD`,b=``,x=new Map,w=!0,T=!1,ae=[],E=new Set,D=null,O=null,k=t(`header`,`flex h-10 flex-none items-center gap-2 border-b border-neutral-200 bg-white px-3`),A=t(`div`,`flex-none border-b border-neutral-200`),j=t(`div`,`min-h-0 flex-1 overflow-y-auto py-1`),oe=t(`aside`,`flex w-64 flex-none flex-col border-r border-neutral-200 text-[12.5px] max-md:h-2/5 max-md:w-full max-md:border-b max-md:border-r-0`,A,j),M=t(`div`,`h-full min-w-0 overflow-auto`),N=t(`div`,`pointer-events-none absolute inset-y-0 right-0 z-20 hidden w-2`),se=t(`section`,`relative min-h-0 min-w-0 flex-1`,M,N);n.append(k,t(`div`,`flex min-h-0 flex-1 max-md:flex-col`,oe,se));let P=(e,t)=>`/api/explorer/${e}?${new URLSearchParams({root:h,...t})}`,F=(e,t)=>`/api/fs/${e}?${new URLSearchParams({root:h,...t})}`,I=(e,n=`text-neutral-400`)=>t(`p`,`px-4 py-3 text-[12.5px] ${n}`,e),L=e=>{let t=0;for(let n of x.keys())n.startsWith(`${e}/`)&&t++;return t};function R(e,t){let n=new Set(t.map(e=>e.name)),r=e?`${e}/`:``;for(let[e,i]of x){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 w&&v.branch&&(i=t.filter(e=>e.dir?L(`${r}${e.name}`)>0:x.has(`${r}${e.name}`))),i.sort((e,t)=>Number(t.dir)-Number(e.dir)||e.name.localeCompare(t.name)),i.map(e=>e.dir?ce(`${r}${e.name}`,e.name):le(`${r}${e.name}`,e.name))}async function z(t,n){try{let{entries:r}=await e(F(`ls`,{path:n}),`could not list this folder`);t.replaceChildren(...R(n,r)),t.childElementCount||t.append(I(w?`No changes.`:`Empty.`))}catch(e){let r=R(n,[]);r.length?t.replaceChildren(...r):t.replaceChildren(I(String(e),`text-red-600`))}}function ce(e,n){let r=L(e),a=[t(`span`,`truncate`,n)];r&&a.push(t(`span`,`ml-auto flex-none rounded bg-amber-100/80 px-1 font-mono text-[10px] text-amber-700`,String(r)));let{el:o,summary:s}=i(``,a);s.className+=` px-2 py-0.5 hover:bg-neutral-100`;let c=t(`div`,`pl-3`);o.append(c);let l=!1,u=()=>{l||(l=!0,c.append(I(`…`)),z(c,e))};return o.ontoggle=()=>{E[o.open?`add`:`delete`](e),o.open&&u()},(w&&v.branch&&!T||E.has(e))&&(o.open=!0,u()),o}function B(e){O?.classList.remove(`bg-indigo-50`,`text-indigo-700`),O=e,e.classList.add(`bg-indigo-50`,`text-indigo-700`)}function le(e,n){let r=x.get(e)?.status,i=t(`button`,`flex w-full cursor-pointer items-center gap-1.5 px-2 py-0.5 pl-6 text-left hover:bg-neutral-100`,t(`span`,`truncate`,n));return r&&i.append(t(`span`,`ml-auto flex-none font-mono text-[10.5px] font-semibold ${ne[r]??`text-neutral-500`}`,r)),i.title=e,e===D&&B(i),i.onclick=()=>{B(i),D=e,de(e)},i}let V=()=>void z(j,``),H=(e,n)=>[...e?[t(`span`,`flex-none font-mono text-[10.5px] font-semibold text-emerald-600`,`+${e}`)]:[],...n?[t(`span`,`flex-none font-mono text-[10.5px] font-semibold text-red-600`,`−${n}`)]:[]];function U(e,n,r){let i=x.get(e),a=t(`div`,`sticky top-0 z-10 flex items-center gap-2 border-b border-neutral-200 bg-white px-4 py-1.5 font-mono text-[11.5px] text-neutral-500`,t(`span`,`truncate`,e));i&&(a.append(t(`span`,`flex-none font-semibold ${ne[i.status]??``}`,i.status)),a.append(...H(i.add,i.del)));let o=t(`div`,`ml-auto flex flex-none items-center gap-2`);if(r&&o.append(r),n){let t=document.createElement(`a`);t.className=`flex-none text-neutral-400 hover:text-indigo-700 hover:underline`,t.href=F(`file`,{path:e}),t.download=s(e),t.textContent=`Download`,o.append(t)}return a.append(o),a}function ue(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=_e();function G(){N.classList.add(`hidden`),N.replaceChildren(),W.set([],[])}let K=0,q=e=>e===K;function de(e){let t=++K;return x.has(e)?ve(e,t):J(e,t)}async function J(e,n){if(!q(n))return;G();let r=F(`file`,{path:e}),i=t(`div`,`min-w-0`);if(M.classList.remove(`flex`,`flex-col`),M.replaceChildren(U(e,!0),i),te.test(e)){let e=t(`img`,`max-w-full p-4`);e.src=r,e.onerror=()=>i.replaceChildren(I(`Could not load image.`,`text-red-600`)),i.append(e);return}if(e.toLowerCase().endsWith(`.pdf`)){let t=document.createElement(`iframe`);t.className=`h-full w-full`,t.src=r,M.replaceChildren(U(e,!0),t),M.classList.add(`flex`,`flex-col`);return}i.append(I(`…`));let a=await fetch(r);if(!q(n))return;if(!a.ok){let{error:e}=await a.json().catch(()=>({}));i.replaceChildren(I(e??`HTTP ${a.status}`,`text-red-600`));return}if(!(a.headers.get(`content-type`)??``).startsWith(`text/plain`)){i.replaceChildren(I(`Binary file — use Download.`));return}let o=(await a.text()).split(`
4
- `);if(!q(n))return;o.at(-1)===``&&o.pop();let s=await c(e);q(n)&&i.replaceChildren(f(d(o),s))}function fe(e){let t=[],n=0,r=0,i=!1,a=e.split(`
5
- `);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 pe(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 me={add:`bg-emerald-400`,del:`bg-red-400`,mixed:`bg-amber-400`};function he(e,n,r){N.replaceChildren(...e.map(e=>{let i=t(`button`,`pointer-events-auto absolute w-full cursor-pointer ${me[e.tone]}`);return i.style.top=`${e.start/n*100}%`,i.style.height=`${Math.max(.4,(e.end-e.start+1)/n*100)}%`,i.title=`line ${ge(r,e.start)}`,i.onclick=()=>r[e.start].scrollIntoView({block:`center`}),i})),N.classList.remove(`hidden`)}let ge=(e,t)=>e[t]?.querySelector(`span`)?.textContent?.trim()||String(t+1);function _e(){let e=[],r=[],i=-1,a=t(`span`,`flex-none text-[10.5px] text-neutral-400`),o=t=>{e.length&&(i=(i+t+e.length)%e.length,r[e[i].start].scrollIntoView({block:`center`}),a.textContent=`${i+1}/${e.length}`)},s=()=>e.length>0&&!n.classList.contains(`hidden`),c=(e,n,r,i)=>{let a=t(`button`,`icon-btn flex-none`,e);return a.onclick=()=>o(n),u(a,i,r,()=>o(n),s),a};return{el:t(`div`,`flex flex-none items-center gap-1`,a,c(`↑`,-1,`Previous change`,[`p`,`k`]),c(`↓`,1,`Next change`,[`n`,`j`])),set(t,n){e=t,r=n,i=-1,a.textContent=`${t.length} change${t.length===1?``:`s`}`}}}async function ve(t,n){G(),M.classList.remove(`flex`,`flex-col`);let r=x.get(t)?.status!==`D`;M.replaceChildren(U(t,r),I(`…`));try{let{diff:i}=await e(P(`diff`,{base:y,head:b,file:t,context:`99999`}),`could not read this diff`);if(!q(n))return;if(!i||/^Binary files /m.test(i))return J(t,n);let a=fe(i);ue(a);let o=await c(t);if(!q(n))return;let s=f(a,o),l=[...s.children],u=pe(a);W.set(u,l),M.replaceChildren(U(t,r,W.el),s),he(u,a.length,l)}catch(e){q(n)&&M.replaceChildren(U(t,!1),I(String(e),`text-red-600`))}}let Y=()=>b&&y===`${b}~1`?b:``,ye=()=>v.commits.find(e=>e.hash===Y())?.subject??``,be=()=>Y()?`${Y()} — ${ye()||`commit`}`:`${y} ↔ ${b||`working tree`}`,xe=(e,n,r,i)=>{let a=t(`button`,`flex h-6 w-6 flex-none cursor-pointer items-center justify-center rounded-md ${r?`bg-indigo-50 text-indigo-700`:`text-neutral-400 hover:bg-neutral-100 hover:text-neutral-700`}`);return a.innerHTML=e,a.title=n,a.onclick=i,a};function X(){let e=xe(`<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" class="h-3.5 w-3.5"><path d="M2.5 3h11l-4.25 5v4.5l-2.5 1.25V8L2.5 3z" stroke-linejoin="round"/></svg>`,`Show only files that differ`,w,()=>{w=!w,X(),V()}),n=xe(`<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" class="h-3.5 w-3.5"><path d="m4.5 2.5 3.5 3 3.5-3M4.5 13.5l3.5-3 3.5 3" stroke-linecap="round" stroke-linejoin="round"/></svg>`,T?`Restore folders`:`Collapse all folders`,T,()=>{if(T=!T,T)ae=[...E],E.clear();else for(let e of ae)E.add(e);X(),V()});if(!v.branch){A.replaceChildren(t(`div`,`flex items-center justify-end gap-1 p-1.5`,n));return}let r=C(be());if(Y()){let e=v.commits.find(e=>e.hash===Y());_(r,()=>e?m(e):``)}else r.title=`Choose what to diff`;r.onclick=async()=>{await Te(),ee(r,v,{base:y,head:b},(e,t)=>{y=e,b=t,Z()},$())};let[i,a]=[0,0];for(let e of x.values())i+=e.add,a+=e.del;A.replaceChildren(t(`div`,`flex flex-col gap-1 p-2`,r,t(`div`,`flex items-center gap-1.5 pl-1`,t(`span`,`text-[11px] text-neutral-400`,`${x.size} changed file${x.size===1?``:`s`}`),...H(i,a),t(`span`,`ml-auto`),e,n)))}let Se=()=>{g&&h&&ie(g,{cwd:h,base:y,head:b})},Ce=e=>{let t=e.replace(/~\d+$/,``);return!t||t===`HEAD`||v.refs.some(e=>e.name===t)||v.commits.some(e=>e.hash===t)};async function we(){if(x=new Map,!v.branch)return;let{files:t}=await e(P(`diff`,{base:y,head:b}),`could not read what changed`);for(let e of t)x.set(e.path,{status:e.status,add:e.add,del:e.del});if(x.size<=re)for(let e of x.keys()){let t=e.split(`/`);for(let e=1;e<t.length;e++)E.add(t.slice(0,e).join(`/`))}}async function Z(){Se();try{await we()}catch(e){X(),j.replaceChildren(I(String(e),`text-red-600`));return}X(),V(),D&&de(D)}function Q(){let e=C(h||`Choose a folder…`,`neutral`);e.className+=` max-w-72`,e.title=`Switch folder`,e.onclick=()=>l(e,v.worktrees.map(e=>({path:e.path,...e.branch?{hint:e.branch}:{}})),h||void 0,o);let n=t(`button`,`icon-btn`,`✕`);n.type=`button`,n.title=`Close Files`,n.setAttribute(`aria-label`,`Close Files`),n.onclick=p,n.classList.add(`ml-auto`),k.replaceChildren(e,t(`span`,`truncate font-mono text-[11.5px] text-neutral-400`,v.branch?`⎇ ${v.branch}`:`no git`),n)}async function Te(){if(h)try{v=await e(P(`git`,{}),`could not read this repository`),Q()}catch(e){M.replaceChildren(I(String(e),`text-red-600`))}}let $=()=>v.refs.some(e=>e.name===`main`)?`main`:v.refs.some(e=>e.name===`master`)?`master`:`HEAD`;async function Ee(){if(Q(),D=null,O=null,E.clear(),G(),M.classList.remove(`flex`,`flex-col`),M.replaceChildren(I(`Select a file.`)),!h){A.replaceChildren(),j.replaceChildren(),M.replaceChildren(I(`No folder yet — pick one from the chip above.`));return}try{v=await e(P(`git`,{}),`could not read this repository`)}catch(e){v={branch:null,refs:[],commits:[],worktrees:[]},M.replaceChildren(I(String(e),`text-red-600`))}let t=S(g),n=t&&t.cwd===h&&Ce(t.base)&&Ce(t.head)?t:null;y=n?.base??$(),b=n?.head??``,Q(),await Z()}return r(n,e=>{let t=a(),n=t?.id??``,r=e?.startsWith(`/`)?e:(n===g?h:``)||S(n)?.cwd||t?.cwd||``;if(r===h&&n===g&&j.childElementCount){Q(),Te().then(Z);return}g=n,h=r,Ee()},()=>{G(),M.classList.remove(`flex`,`flex-col`),M.replaceChildren(I(`Select a file.`))})}export{w as createExplorerView};
3
+ `),h=null;function g(){h&&(h.remove(),h=null,document.removeEventListener(`pointerdown`,g,!0),window.removeEventListener(`scroll`,g,!0))}function _(e,n){e.onmouseenter=()=>{g();let r=n();if(!r)return;h=t(`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`),h.textContent=r,document.body.append(h),document.addEventListener(`pointerdown`,g,!0),window.addEventListener(`scroll`,g,!0);let i=e.getBoundingClientRect();h.style.left=`${Math.max(8,Math.min(i.left,window.innerWidth-h.offsetWidth-8))}px`,h.style.top=i.bottom+6+h.offsetHeight>window.innerHeight?`${i.top-h.offsetHeight-6}px`:`${i.bottom+6}px`},e.onmouseleave=g}function v(e,n,r){let a=t(`button`,`flex w-full cursor-pointer items-center gap-1.5 px-2 py-1 text-left hover:bg-neutral-100`,t(`span`,`w-3 flex-none text-indigo-600`,e.value===n?`✓`:``),t(`span`,`flex-none font-mono text-[11.5px] text-neutral-800`,e.label??e.value));return e.subject&&a.append(t(`span`,`min-w-0 truncate text-[11px] text-neutral-400`,e.subject)),e.author&&a.append(t(`span`,`ml-auto flex-none pl-1.5 text-[10.5px] text-neutral-400`,`${e.author} · ${e.at?i(e.at):``}`)),_(a,()=>m(e)),a.onclick=()=>r(e.value),a}function ee(e,n,r,i,a){let{base:c,head:l}=r,u=()=>l&&c===`${l}~1`?l:``,d=u()?`commit`:`compare`,f=n.commits[0],p=e=>[...e?[{value:``,label:`Working tree`,subject:`the files on disk, uncommitted changes included`}]:[],{...f,value:`HEAD`},...n.refs.map(e=>({value:e.name,subject:e.subject})),...n.commits.map(e=>({...e,value:e.hash}))],m=t(`div`,`flex w-[38rem] max-w-full flex-col`);function h(){let e=(e,n)=>{let r=t(`button`,`cursor-pointer rounded-full px-2.5 py-0.5 text-[11.5px] ${d===n?`bg-indigo-50 font-medium text-indigo-700`:`text-neutral-500 hover:bg-neutral-100`}`,e);return r.onclick=()=>{d=n,h()},r},r=(e,n,r,i)=>t(`div`,`flex min-w-0 flex-1 flex-col`,t(`div`,`flex-none px-2 pb-0.5 text-[10.5px] font-semibold uppercase tracking-wide text-neutral-400`,e),t(`div`,`min-h-0 flex-1 overflow-y-auto`,...n.map(e=>v(e,r,i)))),o=d===`compare`?t(`div`,`flex h-72 min-h-0 divide-x divide-neutral-200 pb-1`,r(`base`,p(!1),c,e=>{c=e,h(),i(c,l)}),r(`to`,p(!0),l,e=>{l=e,h(),i(c,l)})):t(`div`,`flex h-72 min-h-0 flex-col overflow-y-auto pb-1`,...n.commits.map(e=>v({value:e.hash,...e},u(),e=>{c=`${e}~1`,l=e,s(),i(c,l)}))),f=t(`div`,`flex-none border-t border-neutral-200`,v({value:a,label:`↺ ${a} ↔ Working tree`,subject:`back to the default: the main line's tip vs the files on disk`},c===a&&l===``?a:``,()=>{c=a,l=``,h(),i(c,l)}));m.replaceChildren(t(`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`)),o,...d===`compare`?[f]:[])}h(),o(e,m)}var te=/\.(png|jpe?g|gif|webp|avif|bmp|svg)$/i,ne={A:`text-emerald-600`,M:`text-amber-600`,D:`text-red-600`},re=30,y=`pier.filesPrefs`,b=50,x=()=>{try{let e=JSON.parse(localStorage.getItem(y)??`{}`);return e&&typeof e==`object`?e:{}}catch{return{}}},S=e=>{let t=e?x()[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},ie=(e,t)=>{let n=x();delete n[e],n[e]=t;let r=Object.keys(n);for(let e of r.slice(0,Math.max(0,r.length-b)))delete n[e];try{localStorage.setItem(y,JSON.stringify(n))}catch(e){console.warn(`Files: could not remember this folder`,e)}},C=(e,n=`indigo`)=>{let r=t(`button`,`min-w-0 cursor-pointer truncate rounded-md px-2 py-0.5 text-left font-mono text-[11.5px] ${n===`indigo`?`bg-indigo-50 font-medium text-indigo-700 hover:bg-indigo-100`:`bg-neutral-100 text-neutral-600 hover:bg-neutral-200`}`,e);return r.type=`button`,r};function w(i,o,s,p){let h=``,g=``,v={branch:null,refs:[],commits:[],worktrees:[]},y=`HEAD`,b=``,x=new Map,w=!0,T=!1,ae=[],E=new Set,D=null,O=null,k=t(`header`,`flex h-10 flex-none items-center gap-2 border-b border-neutral-200 bg-white px-3`),A=t(`div`,`flex-none border-b border-neutral-200`),j=t(`div`,`min-h-0 flex-1 overflow-y-auto py-1`),oe=t(`aside`,`flex w-64 flex-none flex-col border-r border-neutral-200 text-[12.5px] max-md:h-2/5 max-md:w-full max-md:border-b max-md:border-r-0`,A,j),M=t(`div`,`h-full min-w-0 overflow-auto`),N=t(`div`,`pointer-events-none absolute inset-y-0 right-0 z-20 hidden w-2`),se=t(`section`,`relative min-h-0 min-w-0 flex-1`,M,N);i.append(k,t(`div`,`flex min-h-0 flex-1 max-md:flex-col`,oe,se));let P=(e,t)=>`/api/explorer/${e}?${new URLSearchParams({root:h,...t})}`,F=(e,t)=>`/api/fs/${e}?${new URLSearchParams({root:h,...t})}`,I=(e,n=`text-neutral-400`)=>t(`p`,`px-4 py-3 text-[12.5px] ${n}`,e),L=e=>{let t=0;for(let n of x.keys())n.startsWith(`${e}/`)&&t++;return t};function R(e,t){let n=new Set(t.map(e=>e.name)),r=e?`${e}/`:``;for(let[e,i]of x){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 w&&v.branch&&(i=t.filter(e=>e.dir?L(`${r}${e.name}`)>0:x.has(`${r}${e.name}`))),i.sort((e,t)=>Number(t.dir)-Number(e.dir)||e.name.localeCompare(t.name)),i.map(e=>e.dir?ce(`${r}${e.name}`,e.name):le(`${r}${e.name}`,e.name))}async function z(e,t){try{let{entries:n}=await a(F(`ls`,{path:t}),`could not list this folder`);e.replaceChildren(...R(t,n)),e.childElementCount||e.append(I(w?`No changes.`:`Empty.`))}catch(n){let r=R(t,[]);r.length?e.replaceChildren(...r):e.replaceChildren(I(String(n),`text-red-600`))}}function ce(n,r){let i=L(n),a=[t(`span`,`truncate`,r)];i&&a.push(t(`span`,`ml-auto flex-none rounded bg-amber-100/80 px-1 font-mono text-[10px] text-amber-700`,String(i)));let{el:o,summary:s}=e(``,a);s.className+=` px-2 py-0.5 hover:bg-neutral-100`;let c=t(`div`,`pl-3`);o.append(c);let l=!1,u=()=>{l||(l=!0,c.append(I(`…`)),z(c,n))};return o.ontoggle=()=>{E[o.open?`add`:`delete`](n),o.open&&u()},(w&&v.branch&&!T||E.has(n))&&(o.open=!0,u()),o}function B(e){O?.classList.remove(`bg-indigo-50`,`text-indigo-700`),O=e,e.classList.add(`bg-indigo-50`,`text-indigo-700`)}function le(e,n){let r=x.get(e)?.status,i=t(`button`,`flex w-full cursor-pointer items-center gap-1.5 px-2 py-0.5 pl-6 text-left hover:bg-neutral-100`,t(`span`,`truncate`,n));return r&&i.append(t(`span`,`ml-auto flex-none font-mono text-[10.5px] font-semibold ${ne[r]??`text-neutral-500`}`,r)),i.title=e,e===D&&B(i),i.onclick=()=>{B(i),D=e,de(e)},i}let V=()=>void z(j,``),H=(e,n)=>[...e?[t(`span`,`flex-none font-mono text-[10.5px] font-semibold text-emerald-600`,`+${e}`)]:[],...n?[t(`span`,`flex-none font-mono text-[10.5px] font-semibold text-red-600`,`−${n}`)]:[]];function U(e,r,i){let a=x.get(e),o=t(`div`,`sticky top-0 z-10 flex items-center gap-2 border-b border-neutral-200 bg-white px-4 py-1.5 font-mono text-[11.5px] text-neutral-500`,t(`span`,`truncate`,e));a&&(o.append(t(`span`,`flex-none font-semibold ${ne[a.status]??``}`,a.status)),o.append(...H(a.add,a.del)));let s=t(`div`,`ml-auto flex flex-none items-center gap-2`);if(i&&s.append(i),r){let t=document.createElement(`a`);t.className=`flex-none text-neutral-400 hover:text-indigo-700 hover:underline`,t.href=F(`file`,{path:e}),t.download=n(e),t.textContent=`Download`,s.append(t)}return o.append(s),o}function ue(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=_e();function G(){N.classList.add(`hidden`),N.replaceChildren(),W.set([],[])}let K=0,q=e=>e===K;function de(e){let t=++K;return x.has(e)?ve(e,t):J(e,t)}async function J(e,n){if(!q(n))return;G();let r=F(`file`,{path:e}),i=t(`div`,`min-w-0`);if(M.classList.remove(`flex`,`flex-col`),M.replaceChildren(U(e,!0),i),te.test(e)){let e=t(`img`,`max-w-full p-4`);e.src=r,e.onerror=()=>i.replaceChildren(I(`Could not load image.`,`text-red-600`)),i.append(e);return}if(e.toLowerCase().endsWith(`.pdf`)){let t=document.createElement(`iframe`);t.className=`h-full w-full`,t.src=r,M.replaceChildren(U(e,!0),t),M.classList.add(`flex`,`flex-col`);return}i.append(I(`…`));let a=await fetch(r);if(!q(n))return;if(!a.ok){let{error:e}=await a.json().catch(()=>({}));i.replaceChildren(I(e??`HTTP ${a.status}`,`text-red-600`));return}if(!(a.headers.get(`content-type`)??``).startsWith(`text/plain`)){i.replaceChildren(I(`Binary file — use Download.`));return}let o=(await a.text()).split(`
4
+ `);if(!q(n))return;o.at(-1)===``&&o.pop();let s=await u(e);q(n)&&i.replaceChildren(f(d(o),s))}function fe(e){let t=[],n=0,r=0,i=!1,a=e.split(`
5
+ `);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 pe(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 me={add:`bg-emerald-400`,del:`bg-red-400`,mixed:`bg-amber-400`};function he(e,n,r){N.replaceChildren(...e.map(e=>{let i=t(`button`,`pointer-events-auto absolute w-full cursor-pointer ${me[e.tone]}`);return i.style.top=`${e.start/n*100}%`,i.style.height=`${Math.max(.4,(e.end-e.start+1)/n*100)}%`,i.title=`line ${ge(r,e.start)}`,i.onclick=()=>r[e.start].scrollIntoView({block:`center`}),i})),N.classList.remove(`hidden`)}let ge=(e,t)=>e[t]?.querySelector(`span`)?.textContent?.trim()||String(t+1);function _e(){let e=[],n=[],r=-1,a=t(`span`,`flex-none text-[10.5px] text-neutral-400`),o=t=>{e.length&&(r=(r+t+e.length)%e.length,n[e[r].start].scrollIntoView({block:`center`}),a.textContent=`${r+1}/${e.length}`)},s=()=>e.length>0&&!i.classList.contains(`hidden`),c=(e,n,r,i)=>{let a=t(`button`,`icon-btn flex-none`,e);return a.onclick=()=>o(n),l(a,i,r,()=>o(n),s),a};return{el:t(`div`,`flex flex-none items-center gap-1`,a,c(`↑`,-1,`Previous change`,[`p`,`k`]),c(`↓`,1,`Next change`,[`n`,`j`])),set(t,i){e=t,n=i,r=-1,a.textContent=`${t.length} change${t.length===1?``:`s`}`}}}async function ve(e,t){G(),M.classList.remove(`flex`,`flex-col`);let n=x.get(e)?.status!==`D`;M.replaceChildren(U(e,n),I(`…`));try{let{diff:r}=await a(P(`diff`,{base:y,head:b,file:e,context:`99999`}),`could not read this diff`);if(!q(t))return;if(!r||/^Binary files /m.test(r))return J(e,t);let i=fe(r);ue(i);let o=await u(e);if(!q(t))return;let s=f(i,o),c=[...s.children],l=pe(i);W.set(l,c),M.replaceChildren(U(e,n,W.el),s),he(l,i.length,c)}catch(n){q(t)&&M.replaceChildren(U(e,!1),I(String(n),`text-red-600`))}}let Y=()=>b&&y===`${b}~1`?b:``,ye=()=>v.commits.find(e=>e.hash===Y())?.subject??``,be=()=>Y()?`${Y()} — ${ye()||`commit`}`:`${y} ↔ ${b||`working tree`}`,xe=(e,n,r,i)=>{let a=t(`button`,`flex h-6 w-6 flex-none cursor-pointer items-center justify-center rounded-md ${r?`bg-indigo-50 text-indigo-700`:`text-neutral-400 hover:bg-neutral-100 hover:text-neutral-700`}`);return a.innerHTML=e,a.title=n,a.onclick=i,a};function X(){let e=xe(`<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" class="h-3.5 w-3.5"><path d="M2.5 3h11l-4.25 5v4.5l-2.5 1.25V8L2.5 3z" stroke-linejoin="round"/></svg>`,`Show only files that differ`,w,()=>{w=!w,X(),V()}),n=xe(`<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" class="h-3.5 w-3.5"><path d="m4.5 2.5 3.5 3 3.5-3M4.5 13.5l3.5-3 3.5 3" stroke-linecap="round" stroke-linejoin="round"/></svg>`,T?`Restore folders`:`Collapse all folders`,T,()=>{if(T=!T,T)ae=[...E],E.clear();else for(let e of ae)E.add(e);X(),V()});if(!v.branch){A.replaceChildren(t(`div`,`flex items-center justify-end gap-1 p-1.5`,n));return}let r=C(be());if(Y()){let e=v.commits.find(e=>e.hash===Y());_(r,()=>e?m(e):``)}else r.title=`Choose what to diff`;r.onclick=async()=>{await Te(),ee(r,v,{base:y,head:b},(e,t)=>{y=e,b=t,Z()},$())};let[i,a]=[0,0];for(let e of x.values())i+=e.add,a+=e.del;A.replaceChildren(t(`div`,`flex flex-col gap-1 p-2`,r,t(`div`,`flex items-center gap-1.5 pl-1`,t(`span`,`text-[11px] text-neutral-400`,`${x.size} changed file${x.size===1?``:`s`}`),...H(i,a),t(`span`,`ml-auto`),e,n)))}let Se=()=>{g&&h&&ie(g,{cwd:h,base:y,head:b})},Ce=e=>{let t=e.replace(/~\d+$/,``);return!t||t===`HEAD`||v.refs.some(e=>e.name===t)||v.commits.some(e=>e.hash===t)};async function we(){if(x=new Map,!v.branch)return;let{files:e}=await a(P(`diff`,{base:y,head:b}),`could not read what changed`);for(let t of e)x.set(t.path,{status:t.status,add:t.add,del:t.del});if(x.size<=re)for(let e of x.keys()){let t=e.split(`/`);for(let e=1;e<t.length;e++)E.add(t.slice(0,e).join(`/`))}}async function Z(){Se();try{await we()}catch(e){X(),j.replaceChildren(I(String(e),`text-red-600`));return}X(),V(),D&&de(D)}function Q(){let e=C(h||`Choose a folder…`,`neutral`);e.className+=` max-w-72`,e.title=`Switch folder`,e.onclick=()=>c(e,v.worktrees.map(e=>({path:e.path,...e.branch?{hint:e.branch}:{}})),h||void 0,s);let n=t(`button`,`icon-btn`,`✕`);n.type=`button`,n.title=`Close Files`,n.setAttribute(`aria-label`,`Close Files`),n.onclick=p,n.classList.add(`ml-auto`),k.replaceChildren(e,t(`span`,`truncate font-mono text-[11.5px] text-neutral-400`,v.branch?`⎇ ${v.branch}`:`no git`),n)}async function Te(){if(h)try{v=await a(P(`git`,{}),`could not read this repository`),Q()}catch(e){M.replaceChildren(I(String(e),`text-red-600`))}}let $=()=>v.refs.some(e=>e.name===`main`)?`main`:v.refs.some(e=>e.name===`master`)?`master`:`HEAD`;async function Ee(){if(Q(),D=null,O=null,E.clear(),G(),M.classList.remove(`flex`,`flex-col`),M.replaceChildren(I(`Select a file.`)),!h){A.replaceChildren(),j.replaceChildren(),M.replaceChildren(I(`No folder yet — pick one from the chip above.`));return}try{v=await a(P(`git`,{}),`could not read this repository`)}catch(e){v={branch:null,refs:[],commits:[],worktrees:[]},M.replaceChildren(I(String(e),`text-red-600`))}let e=S(g),t=e&&e.cwd===h&&Ce(e.base)&&Ce(e.head)?e:null;y=t?.base??$(),b=t?.head??``,Q(),await Z()}return r(i,e=>{let t=o(),n=t?.id??``,r=e?.startsWith(`/`)?e:(n===g?h:``)||S(n)?.cwd||t?.cwd||``;if(r===h&&n===g&&j.childElementCount){Q(),Te().then(Z);return}g=n,h=r,Ee()},()=>{G(),M.classList.remove(`flex`,`flex-col`),M.replaceChildren(I(`Select a file.`))})}export{w as createExplorerView};