@timqi/pier 0.1.11 → 0.1.12
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/boards/pier.css +37 -22
- package/dist/channels/config.js +24 -2
- package/dist/channels/routes.js +13 -1
- package/dist/main.js +1 -1
- package/dist/web/public/assets/{activity-dxSOEHmf.js → activity-CJtsniqS.js} +2 -2
- package/dist/web/public/assets/activity-CJtsniqS.js.br +0 -0
- package/dist/web/public/assets/activity-CJtsniqS.js.gz +0 -0
- package/dist/web/public/assets/boards-DyQtNqgv.js +1 -0
- package/dist/web/public/assets/boards-DyQtNqgv.js.br +0 -0
- package/dist/web/public/assets/boards-DyQtNqgv.js.gz +0 -0
- package/dist/web/public/assets/explorer-BQYNIR0V.js +4 -0
- package/dist/web/public/assets/explorer-BQYNIR0V.js.br +0 -0
- package/dist/web/public/assets/explorer-BQYNIR0V.js.gz +0 -0
- package/dist/web/public/assets/index-CLNTSmYN.js +85 -0
- package/dist/web/public/assets/index-CLNTSmYN.js.br +0 -0
- package/dist/web/public/assets/index-CLNTSmYN.js.gz +0 -0
- package/dist/web/public/assets/index-DiHj0w1i.css +2 -0
- package/dist/web/public/assets/index-DiHj0w1i.css.br +0 -0
- package/dist/web/public/assets/index-DiHj0w1i.css.gz +0 -0
- package/dist/web/public/assets/{runs-DtvDXSfo.js → runs-tYH577mL.js} +1 -1
- package/dist/web/public/assets/runs-tYH577mL.js.br +0 -0
- package/dist/web/public/assets/runs-tYH577mL.js.gz +0 -0
- package/dist/web/public/assets/settings-B42zHcpu.js +5 -0
- package/dist/web/public/assets/settings-B42zHcpu.js.br +0 -0
- package/dist/web/public/assets/settings-B42zHcpu.js.gz +0 -0
- package/dist/web/public/assets/{task-runs-DcORJXHU.js → task-runs-COIFbwwz.js} +2 -2
- package/dist/web/public/assets/task-runs-COIFbwwz.js.br +0 -0
- package/dist/web/public/assets/task-runs-COIFbwwz.js.gz +0 -0
- package/dist/web/public/assets/tasks-D1dGhkTZ.js +4 -0
- package/dist/web/public/assets/tasks-D1dGhkTZ.js.br +0 -0
- package/dist/web/public/assets/tasks-D1dGhkTZ.js.gz +0 -0
- package/dist/web/public/index.html +2 -2
- 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-boards/SKILL.md +89 -124
- package/dist/web/public/assets/activity-dxSOEHmf.js.br +0 -0
- package/dist/web/public/assets/activity-dxSOEHmf.js.gz +0 -0
- package/dist/web/public/assets/boards-BRwn5UZi.js +0 -1
- package/dist/web/public/assets/boards-BRwn5UZi.js.br +0 -0
- package/dist/web/public/assets/boards-BRwn5UZi.js.gz +0 -0
- package/dist/web/public/assets/explorer-CCJQ22Dp.js +0 -4
- package/dist/web/public/assets/explorer-CCJQ22Dp.js.br +0 -0
- package/dist/web/public/assets/explorer-CCJQ22Dp.js.gz +0 -0
- package/dist/web/public/assets/index-CzV2cZEH.js +0 -85
- package/dist/web/public/assets/index-CzV2cZEH.js.br +0 -0
- package/dist/web/public/assets/index-CzV2cZEH.js.gz +0 -0
- package/dist/web/public/assets/index-sQWFDUPu.css +0 -2
- package/dist/web/public/assets/index-sQWFDUPu.css.br +0 -0
- package/dist/web/public/assets/index-sQWFDUPu.css.gz +0 -0
- package/dist/web/public/assets/runs-DtvDXSfo.js.br +0 -0
- package/dist/web/public/assets/runs-DtvDXSfo.js.gz +0 -0
- package/dist/web/public/assets/settings-CJbHCEZo.js +0 -5
- package/dist/web/public/assets/settings-CJbHCEZo.js.br +0 -0
- package/dist/web/public/assets/settings-CJbHCEZo.js.gz +0 -0
- package/dist/web/public/assets/task-runs-DcORJXHU.js.br +0 -0
- package/dist/web/public/assets/task-runs-DcORJXHU.js.gz +0 -0
- package/dist/web/public/assets/tasks-8l1M8EJU.js +0 -4
- package/dist/web/public/assets/tasks-8l1M8EJU.js.br +0 -0
- package/dist/web/public/assets/tasks-8l1M8EJU.js.gz +0 -0
package/dist/boards/pier.css
CHANGED
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
--good: #0f7b4f;
|
|
22
22
|
--warn: #a25b00;
|
|
23
23
|
--bad: #b42318;
|
|
24
|
-
--serif: ui-serif, Georgia, Cambria, "Songti SC", "Noto Serif CJK SC",
|
|
24
|
+
--serif: ui-serif, Georgia, Cambria, "Songti SC", "Noto Serif CJK SC",
|
|
25
|
+
"Source Han Serif SC", serif;
|
|
25
26
|
color-scheme: light dark;
|
|
26
27
|
}
|
|
27
28
|
|
|
@@ -50,19 +51,18 @@ html {
|
|
|
50
51
|
-webkit-text-size-adjust: 100%;
|
|
51
52
|
}
|
|
52
53
|
|
|
53
|
-
/* The
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
stretching into 150-character lines. */
|
|
54
|
+
/* The container is the reading measure: text runs as wide as the page on a
|
|
55
|
+
desktop and reflows on a phone. A narrower measure belongs to the whole
|
|
56
|
+
page, never to one section among full-width siblings. */
|
|
57
57
|
body {
|
|
58
|
-
--measure: 44rem;
|
|
59
58
|
margin: 0 auto;
|
|
60
59
|
max-width: 44rem;
|
|
61
60
|
padding: 3rem 1.25rem 6rem;
|
|
62
61
|
background: var(--bg);
|
|
63
62
|
color: var(--fg);
|
|
64
63
|
font: 17px/1.7 -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans",
|
|
65
|
-
"PingFang SC", "Hiragino Sans GB", "Microsoft YaHei",
|
|
64
|
+
"PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans CJK SC",
|
|
65
|
+
sans-serif;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
@media (min-width: 64rem) {
|
|
@@ -78,19 +78,12 @@ body {
|
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
/*
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
body > blockquote {
|
|
88
|
-
max-width: var(--measure);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
.hero .lede,
|
|
92
|
-
.hero > p {
|
|
93
|
-
max-width: var(--measure);
|
|
81
|
+
/* Only the ultrawide canvas is wider than a line should be read: `.prose`
|
|
82
|
+
caps a reading column there and is a no-op below, so mixing it with
|
|
83
|
+
full-width siblings cannot ragged the page's edges. */
|
|
84
|
+
.prose {
|
|
85
|
+
max-width: 62rem;
|
|
86
|
+
margin-inline: auto;
|
|
94
87
|
}
|
|
95
88
|
|
|
96
89
|
/* Serif headings against a sans body: the contrast is what makes a plain
|
|
@@ -195,7 +188,7 @@ pre code {
|
|
|
195
188
|
font-size: 0.85rem;
|
|
196
189
|
}
|
|
197
190
|
|
|
198
|
-
/*
|
|
191
|
+
/* Unwrapped tables retain their scrolling fallback for existing boards. */
|
|
199
192
|
table {
|
|
200
193
|
display: block;
|
|
201
194
|
width: 100%;
|
|
@@ -204,6 +197,20 @@ table {
|
|
|
204
197
|
font-size: 0.94rem;
|
|
205
198
|
}
|
|
206
199
|
|
|
200
|
+
/* A wrapper lets the native table fill the canvas without losing column
|
|
201
|
+
alignment when its minimum width needs a horizontal scrollbar. */
|
|
202
|
+
.table-scroll {
|
|
203
|
+
width: 100%;
|
|
204
|
+
min-width: 0;
|
|
205
|
+
overflow-x: auto;
|
|
206
|
+
margin: 0 0 1rem;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.table-scroll > table {
|
|
210
|
+
display: table;
|
|
211
|
+
margin: 0;
|
|
212
|
+
}
|
|
213
|
+
|
|
207
214
|
th,
|
|
208
215
|
td {
|
|
209
216
|
padding: 0.45rem 0.7rem;
|
|
@@ -252,10 +259,17 @@ details {
|
|
|
252
259
|
}
|
|
253
260
|
|
|
254
261
|
summary {
|
|
262
|
+
min-height: 44px;
|
|
263
|
+
padding-block: 0.35rem;
|
|
255
264
|
cursor: pointer;
|
|
256
265
|
font-weight: 560;
|
|
257
266
|
}
|
|
258
267
|
|
|
268
|
+
:where(a, summary, .table-scroll):focus-visible {
|
|
269
|
+
outline: 2px solid var(--accent);
|
|
270
|
+
outline-offset: 3px;
|
|
271
|
+
}
|
|
272
|
+
|
|
259
273
|
details[open] summary {
|
|
260
274
|
margin-bottom: 0.6rem;
|
|
261
275
|
}
|
|
@@ -298,6 +312,8 @@ footer {
|
|
|
298
312
|
}
|
|
299
313
|
|
|
300
314
|
.card {
|
|
315
|
+
min-width: 0;
|
|
316
|
+
overflow-wrap: anywhere;
|
|
301
317
|
padding: 1.05rem 1.25rem;
|
|
302
318
|
margin: 0 0 1rem;
|
|
303
319
|
border: 1px solid var(--line);
|
|
@@ -358,7 +374,6 @@ footer {
|
|
|
358
374
|
|
|
359
375
|
.kpi {
|
|
360
376
|
display: block;
|
|
361
|
-
font-family: var(--serif);
|
|
362
377
|
font-size: 1.8rem;
|
|
363
378
|
font-weight: 700;
|
|
364
379
|
line-height: 1.15;
|
package/dist/channels/config.js
CHANGED
|
@@ -38,6 +38,10 @@ export class ChannelStore {
|
|
|
38
38
|
for (const [key, name] of credentials(platform)) {
|
|
39
39
|
config[key] = this.vault.get(name) ?? "";
|
|
40
40
|
}
|
|
41
|
+
// A row written before chats carried an owner: "" is "never stamped", which
|
|
42
|
+
// is what the Console shows.
|
|
43
|
+
for (const chat of config.chats)
|
|
44
|
+
chat.botId ??= "";
|
|
41
45
|
this.cache.set(platform, config);
|
|
42
46
|
return config;
|
|
43
47
|
}
|
|
@@ -72,25 +76,43 @@ export class ChannelStore {
|
|
|
72
76
|
* and happens on every message: the unchanged case must cost no clone. A new
|
|
73
77
|
* chat copies the platform defaults and owns them from then on. */
|
|
74
78
|
discoverChat(platform, chat) {
|
|
75
|
-
|
|
76
|
-
|
|
79
|
+
// Traffic is the proof of ownership: a message in this chat reached the bot
|
|
80
|
+
// running now, so the row is stamped with it and a row no message renews
|
|
81
|
+
// keeps the identity it was last reachable under.
|
|
82
|
+
const { botId, chats } = this.cached(platform);
|
|
83
|
+
const cached = chats.find((c) => c.id === chat.id);
|
|
84
|
+
if (cached && cached.name === chat.name && cached.kind === chat.kind && cached.botId === botId)
|
|
77
85
|
return;
|
|
78
86
|
const config = this.get(platform);
|
|
79
87
|
const known = config.chats.find((c) => c.id === chat.id);
|
|
80
88
|
if (known) {
|
|
81
89
|
known.name = chat.name || known.name;
|
|
82
90
|
known.kind = chat.kind;
|
|
91
|
+
known.botId = botId;
|
|
83
92
|
}
|
|
84
93
|
else {
|
|
85
94
|
config.chats.push({
|
|
86
95
|
id: chat.id,
|
|
87
96
|
name: chat.name,
|
|
88
97
|
kind: chat.kind,
|
|
98
|
+
botId,
|
|
89
99
|
...this.policy(platform, chat.id),
|
|
90
100
|
});
|
|
91
101
|
}
|
|
92
102
|
this.save(platform, config);
|
|
93
103
|
}
|
|
104
|
+
/** The Console's delete, for the chat no swap will ever claim: a row nothing
|
|
105
|
+
* can reach reads like a live one. Traffic re-discovers a chat that is still
|
|
106
|
+
* alive, so this is undone by using it. */
|
|
107
|
+
removeChat(platform, chatId) {
|
|
108
|
+
const config = this.get(platform);
|
|
109
|
+
const rest = config.chats.filter((c) => c.id !== chatId);
|
|
110
|
+
if (rest.length === config.chats.length)
|
|
111
|
+
return false;
|
|
112
|
+
config.chats = rest;
|
|
113
|
+
this.save(platform, config);
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
94
116
|
/** A DM's id belongs to the bot it was opened with, so a new app or a rotated
|
|
95
117
|
* token leaves DMs no one can reach and nothing on screen tells them apart
|
|
96
118
|
* from the live ones — they are dropped. Group ids survive the swap. Returns
|
package/dist/channels/routes.js
CHANGED
|
@@ -43,7 +43,7 @@ function parseChats(raw, known) {
|
|
|
43
43
|
};
|
|
44
44
|
});
|
|
45
45
|
}
|
|
46
|
-
export function registerChannelRoutes(app, store, runtime, handoff) {
|
|
46
|
+
export function registerChannelRoutes(app, store, runtime, handoff, conversations) {
|
|
47
47
|
app.get("/api/channels/:platform", (c) => {
|
|
48
48
|
const platform = c.req.param("platform");
|
|
49
49
|
if (!isChannelPlatform(platform))
|
|
@@ -93,6 +93,18 @@ export function registerChannelRoutes(app, store, runtime, handoff) {
|
|
|
93
93
|
return c.json({ error: "unknown platform" }, 404);
|
|
94
94
|
return c.json(store.issueBindCode(platform));
|
|
95
95
|
});
|
|
96
|
+
app.delete("/api/channels/:platform/chats/:id", (c) => {
|
|
97
|
+
const platform = c.req.param("platform");
|
|
98
|
+
if (!isChannelPlatform(platform))
|
|
99
|
+
return c.json({ error: "unknown platform" }, 404);
|
|
100
|
+
const chatId = c.req.param("id");
|
|
101
|
+
if (!store.removeChat(platform, chatId))
|
|
102
|
+
return c.json({ error: "unknown chat" }, 404);
|
|
103
|
+
// The threads go with the chat: a binding to a chat nobody lists is a
|
|
104
|
+
// session no message can ever reach.
|
|
105
|
+
conversations.forgetChat(platform, chatId);
|
|
106
|
+
return c.json({ ok: true });
|
|
107
|
+
});
|
|
96
108
|
app.delete("/api/channels/:platform/users/:id", (c) => {
|
|
97
109
|
const platform = c.req.param("platform");
|
|
98
110
|
if (!isChannelPlatform(platform))
|
package/dist/main.js
CHANGED
|
@@ -279,7 +279,7 @@ registerConfigSyncRoutes(app, {
|
|
|
279
279
|
run: configurationSync.run,
|
|
280
280
|
});
|
|
281
281
|
registerTaskRoutes(app, tasks, { factory, router });
|
|
282
|
-
registerChannelRoutes(app, channelStore, channels, handoff);
|
|
282
|
+
registerChannelRoutes(app, channelStore, channels, handoff, conversations);
|
|
283
283
|
registerVaultRoutes(app, { vault, doctor: () => secrets.doctor() });
|
|
284
284
|
registerBoardRoutes(app);
|
|
285
285
|
registerPushRoutes(app, {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{$ as e,C as t,F as n,H as r,K as i,O as a,Q as o,X as s,Y as c,ot as l,t as u,tt as d,u as f}from"./index-CLNTSmYN.js";var p=[[`path`,{d:`M3 5h.01`}],[`path`,{d:`M3 12h.01`}],[`path`,{d:`M3 19h.01`}],[`path`,{d:`M8 5h13`}],[`path`,{d:`M8 12h13`}],[`path`,{d:`M8 19h13`}]],m=[[`path`,{d:`m10.586 5.414-5.172 5.172`}],[`path`,{d:`m18.586 13.414-5.172 5.172`}],[`path`,{d:`M6 12h12`}],[`circle`,{cx:`12`,cy:`20`,r:`2`}],[`circle`,{cx:`12`,cy:`4`,r:`2`}],[`circle`,{cx:`20`,cy:`12`,r:`2`}],[`circle`,{cx:`4`,cy:`12`,r:`2`}]],h=(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},g=e=>e===null?`-`:c(Date.now()-e),_={invocation:{stroke:`stroke-neutral-400`,fill:`fill-neutral-400`},callback:{stroke:`stroke-cyan-500`,fill:`fill-cyan-500`,dash:`6 5`},message:{stroke:`stroke-amber-500`,fill:`fill-amber-500`,dash:`2 5`}},v={scheduler:`border-violet-200 bg-violet-50 text-violet-700`,console:`border-indigo-200 bg-indigo-50 text-indigo-700`,task:`border-amber-200 bg-amber-50 text-amber-700`,process:`border-dashed border-neutral-300 bg-neutral-50 text-neutral-500`,streaming:`border-emerald-200 bg-white font-medium text-neutral-800`,idle:`border-neutral-200 bg-white font-medium text-neutral-600`},y=300,b=4;function x(e,t){let n,r=null,i=!1,a=!1,o=()=>{clearTimeout(n),n=setTimeout(()=>{i||a||!r||r.dataset.closing!==void 0||(f(),r=null)},120)};e.onpointerenter=s=>{s.pointerType!==`touch`&&(i=!0,clearTimeout(n),!(r?.isConnected&&r.dataset.closing===void 0)&&(n=setTimeout(()=>{!e.isConnected||!i||(r=u(e,t),r.onpointerenter=()=>{a=!0,clearTimeout(n)},r.onpointerleave=()=>{a=!1,o()})},y)))},e.onpointerleave=()=>{i=!1,o()},e.onpointerdown=()=>clearTimeout(n)}function S(e){let t,n=!1;e.classList.add(`cursor-grab`),e.onpointerdown=r=>{n=!1,!(r.button!==0||r.pointerType===`touch`||r.target.closest(`[data-node], path`))&&(t={x:r.clientX,y:r.clientY,left:e.scrollLeft,top:e.scrollTop},e.setPointerCapture(r.pointerId),e.classList.add(`cursor-grabbing`,`select-none`))},e.onpointermove=r=>{if(!t)return;let i=r.clientX-t.x,a=r.clientY-t.y;(Math.abs(i)>b||Math.abs(a)>b)&&(n=!0),e.scrollLeft=t.left-i,e.scrollTop=t.top-a};let r=()=>{t=void 0,e.classList.remove(`cursor-grabbing`,`select-none`)};e.onpointerup=r,e.onpointercancel=r,e.addEventListener(`click`,e=>{n&&(e.stopPropagation(),e.preventDefault())},!0)}function C(c,u,f){let y=`sessions`,b=`active`,C={sessions:[],runs:[],messages:[]},w=``,T=e(async()=>{let e=b,t=await d(`/api/activity?scope=${e}`,`Failed to load activity`);if(!t.ok){w=``,c.replaceChildren(s(`p`,`p-4 text-[13px] text-red-600`,t.error));return}if(e!==b)return;let n=JSON.stringify(t.value);if(`${e}:${n}`===w)return;w=`${e}:${n}`;let r=t.value;C={...r,sessions:r.sessions.map(e=>({...e,title:l(e.title)}))},E()});function E(){let e=r(n([[`Sessions`,`sessions`,p],[`Relationships`,`dependencies`,m]],y,e=>{y=e,E()}),s(`span`,`ml-auto text-[11.5px] text-neutral-400`,`${C.sessions.length} sessions · ${C.runs.length} runs`),n([[`Current`,`active`],[`Last 24h`,`recent`]],b,e=>{b=e,E(),T()})),t=s(`div`,`automation-list min-h-0 flex-1 overflow-auto`);y===`sessions`?D(t):k(t),c.replaceChildren(e,t)}function D(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 n=document.createElement(`tbody`);for(let e of C.sessions){let t=document.createElement(`tr`);t.className=`cursor-pointer border-b border-neutral-100 transition-colors hover:bg-neutral-50`,t.onclick=()=>
|
|
5
|
+
<th class="px-2 py-2 font-semibold">In state</th></tr></thead>`;let n=document.createElement(`tbody`);for(let e of C.sessions){let t=document.createElement(`tr`);t.className=`cursor-pointer border-b border-neutral-100 transition-colors hover:bg-neutral-50`,t.onclick=()=>u(e.id);let r=s(`button`,`block w-full cursor-pointer truncate text-left font-medium text-neutral-800`,e.title??o(e.cwd));r.setAttribute(`type`,`button`),r.title=`${e.id}\n${e.cwd}`,r.onclick=t=>{t.stopPropagation(),u(e.id)},t.append(s(`td`,`px-4 py-2.5`,r,s(`div`,`truncate font-mono text-[11px] text-neutral-400 md:hidden`,e.cwd||`-`)),s(`td`,`hidden truncate px-2 py-2.5 font-mono text-[11.5px] text-neutral-500 md:table-cell`,e.cwd||`-`),s(`td`,`px-2 py-2.5`,O(e.state)),s(`td`,`px-2 py-2.5 font-mono text-[11.5px] text-neutral-400`,g(e.stateSince))),n.append(t)}t.append(n),e.append(t),C.sessions.length||e.append(s(`div`,`p-4`,a(b===`active`?`No active sessions.`:`No sessions in the last 24 hours.`)))}function O(e){return e===`streaming`?t(e,`bg-emerald-50 text-emerald-700 ring-emerald-200`,`animate-pulse bg-emerald-500`):t(e,`bg-neutral-100 text-neutral-600 ring-neutral-200`,`bg-neutral-300`)}function k(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 C.sessions)r(e.id,e.title??e.id.slice(0,10),`session`,e.state);for(let e of C.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 C.messages){if(!e.fromSessionId||!e.toSessionId||e.fromSessionId===e.toSessionId)continue;let t=C.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(s(`div`,`p-4`,a(b===`active`?`No active dependencies.`:`No dependencies in the last 24 hours.`)));return}let i=[...t.values()],o=new Set(n.map(e=>e.to)),c=new Map,l=i.filter(e=>!o.has(e.id)).map(e=>e.id);l.length||l.push(i[0].id);for(let e of l)c.set(e,0);for(;l.length;){let e=l.shift();for(let t of n)t.from!==e||c.has(t.to)||(c.set(t.to,c.get(e)+1),l.push(t.to))}for(let e of i)c.has(e.id)||c.set(e.id,0);let d=new Map;for(let e of i){let t=c.get(e.id);d.set(t,[...d.get(t)??[],e])}let p=Math.max(...d.keys())+1,m=Math.max(...[...d.values()].map(e=>e.length)),g=n.some(e=>e.from!==e.to&&c.get(e.from)===c.get(e.to))?40:0,y=56+p*180+(p-1)*110+g,w=56+m*46+(m-1)*30,T=new Map;for(let[e,t]of d)t.forEach((t,n)=>T.set(t.id,{x:28+e*290+90,y:28+n*76+23}));let E=s(`div`,`relative`);E.style.width=`${y}px`,E.style.height=`${w}px`;let D=h(`svg`,{width:String(y),height:String(w),viewBox:`0 0 ${y} ${w}`,class:`absolute inset-0`}),O=h(`defs`);for(let[e,t]of Object.entries(_)){let n=h(`marker`,{id:`activity-arrow-${e}`,viewBox:`0 0 10 10`,refX:`9`,refY:`5`,markerWidth:`6`,markerHeight:`6`,orient:`auto-start-reverse`});n.append(h(`path`,{d:`M 0 0 L 10 5 L 0 10 z`,class:t.fill})),O.append(n)}D.append(O);let k=new Set;for(let e of n){let t=`${e.from}→${e.to}:${e.kind}`;if(k.has(t))continue;k.add(t);let n=T.get(e.from),r=T.get(e.to),i=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}`})(),a=_[e.kind],o=h(`path`,{d:i,fill:`none`,class:`cursor-pointer ${a.stroke}`,"stroke-width":`1.5`,"marker-end":`url(#activity-arrow-${e.kind})`});a.dash&&o.setAttribute(`stroke-dasharray`,a.dash),o.onclick=()=>f(e.run.id),D.append(o)}E.append(D);for(let e of i){let t=T.get(e.id),n=e.kind===`session`?e.state===`streaming`?v.streaming:v.idle:v[e.kind],r=s(e.kind===`session`?`button`:`div`,`absolute flex items-center gap-2 rounded-xl border px-3 text-left text-[11.5px] shadow-xs ${n} ${e.kind===`session`?`cursor-pointer hover:bg-neutral-50`:`cursor-default`}`,...e.kind===`session`?[s(`span`,`inline-block h-1.5 w-1.5 flex-none rounded-full ${e.state===`streaming`?`animate-pulse bg-emerald-500`:`bg-neutral-300`}`)]:[],s(`span`,`min-w-0 truncate`,e.label));if(r.dataset.node=e.id,r.style.left=`${t.x-90}px`,r.style.top=`${t.y-23}px`,r.style.width=`180px`,r.style.height=`46px`,r.title=e.label===e.id?e.id:`${e.label}\n${e.id}`,e.kind===`session`){r.setAttribute(`type`,`button`),r.onclick=()=>u(e.id);let t=C.sessions.find(t=>t.id===e.id);t&&t.createdAt!==null&&x(r,{...t,createdAt:t.createdAt})}E.append(r)}S(e);let A=e=>s(`span`,`inline-block h-2 w-2 rounded-full ${e}`),j=e=>s(`span`,`inline-block h-0 w-6 border-t-2 ${e}`);e.append(s(`div`,`w-max p-4`,E),s(`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`,s(`span`,`inline-flex items-center gap-2`,j(`border-solid border-neutral-400`),`task invocation`),s(`span`,`inline-flex items-center gap-2 text-cyan-700`,j(`border-dashed border-cyan-500`),`callback`),s(`span`,`inline-flex items-center gap-2 text-amber-700`,j(`border-dotted border-amber-500`),`control message`),s(`span`,`inline-flex items-center gap-1.5`,A(`bg-emerald-500`),`streaming`),s(`span`,`inline-flex items-center gap-1.5`,A(`bg-neutral-300`),`idle`)))}let A=i(c,e=>{e===`dependencies`?y=`dependencies`:e===`sessions`&&(y=`sessions`),T()},()=>{c.replaceChildren(),C={sessions:[],runs:[],messages:[]},w=``});return Object.assign(A,{refresh(){A.visible&&T()}})}export{C as createActivityView};
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{E as e,K as t,M as n,O as r,P as i,V as a,X as o,Z as s,at as c,et as l,it as u,q as d,tt as f,w as p}from"./index-CLNTSmYN.js";var m=e=>e.public&&e.token?`/p/${e.slug}-${e.token}/`:`/boards/${e.slug}/`;function h(h,g){let _=[],v=``,y=o(`header`,`pagehead sticky top-[-8px] z-30 max-md:hidden`,n(`Boards`)),b=o(`div`,`px-4 pb-5 pt-1`);h.append(o(`div`,`min-h-0 flex-1 overflow-y-auto`,y,b));async function x(e,t){let n=await c(`/api/boards/${e.slug}`,{public:t},`PATCH`);if(n.ok)return e.token=(await n.json().catch(()=>({}))).token??``,T();v=await l(n,`Could not change ${e.slug}`),await E()}async function S(e){v=await u(`/api/boards/${e}`,`DELETE`,`Could not delete ${e}`)??``,await E()}function C(e){let t=o(`div`,`group flex flex-col gap-1 py-2.5`),n=document.createElement(`a`);n.className=`min-w-0 flex-1 truncate text-[13px] font-medium text-neutral-800 hover:text-indigo-700 max-md:basis-full`,n.href=m(e),n.target=`_blank`,n.rel=`noreferrer`,n.textContent=e.title;let r=o(`div`,`flex flex-wrap items-center gap-x-2 gap-y-1`,n),c=a(``,``,e.public,t=>{e.public=t,x(e,t)});c.className=`flex flex-none cursor-pointer items-center gap-1.5 text-[11.5px] text-neutral-500`,c.append(o(`span`,``,`Public`));let l=p(`Delete`,i());l.title=`Renames the folder on disk; nothing is erased`,l.onclick=()=>void S(e.slug);let u=d(i(`hover:text-indigo-600`),()=>`${location.origin}${m(e)}`);u.title=`Copy the board's link`,r.append(o(`div`,`ml-auto flex flex-none items-center gap-2`,c,u,l)),t.append(r);let f=o(`div`,`flex flex-wrap items-center gap-x-3 gap-y-1 text-[11.5px] text-neutral-500`);f.append(o(`span`,`min-w-0 break-all font-mono text-neutral-400`,e.slug)),e.description&&f.append(o(`span`,`min-w-0 truncate`,e.description)),f.append(o(`span`,`flex-none text-neutral-400`,s(Date.parse(e.updatedAt))));for(let t of e.sessions){let e=p(t.slice(0,8),`flex-none cursor-pointer font-mono text-indigo-600 hover:underline`);e.title=`Open session ${t}`,e.onclick=()=>g(t),f.append(e)}if(e.public&&e.token){let t=o(`span`,`min-w-0 break-all font-mono text-neutral-400`,m(e));t.title=`Public URL — anyone holding this link can read the board, no password`,f.append(t)}return t.append(f),t}let w=[{title:`Public`,hint:`Readable at /p/<slug>-<token>/ by anyone holding the link.`,wanted:!0},{title:`Private`,hint:`Opened from here; the address that opens is a temporary link, good for 8 hours.`,wanted:!1}];function T(){let t=o(`div`,`mx-auto flex w-full max-w-3xl flex-col gap-4`);_.length===0&&t.append(r(`No boards yet. Ask an agent to build one — it writes a folder under ~/.pier/boards.`));for(let{title:n,hint:r,wanted:i}of w){let a=_.filter(e=>e.public===i);a.length!==0&&t.append(e(n,r,o(`div`,`flex flex-col divide-y divide-neutral-200/70`,...a.map(C))))}b.replaceChildren(...v?[o(`p`,`mb-3 text-[13px] text-red-600`,v)]:[],t)}async function E(){let e=await f(`/api/boards`,`Could not load boards`);if(!e.ok)return v=e.error,T();_=e.value,T(),v=``}let D=t(h,()=>void E());return window.addEventListener(`focus`,()=>{D.visible&&E()}),D}export{h as createBoardsView};
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import{G as e,J as t,K as n,M as r,O as i,X as a,Z as o,a as s,ct as c,f as l,g as u,h as d,ht as f,l as p,lt as m,m as h,mt as ee,nt as g,p as _,u as te,v as ne,w as re,y as ie}from"./index-CLNTSmYN.js";var ae=[[`path`,{d:`M12 5v14`}],[`path`,{d:`m19 12-7 7-7-7`}]],oe=[[`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`}]],se=[[`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`}]],ce=[[`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())}`},le=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
|
+
|
|
3
|
+
`),b=null;function x(){b&&(b.remove(),b=null,document.removeEventListener(`pointerdown`,x,!0),window.removeEventListener(`scroll`,x,!0))}function ue(e,t){e.onmouseenter=()=>{x();let n=t();if(!n)return;b=a(`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`),b.textContent=n,document.body.append(b),document.addEventListener(`pointerdown`,x,!0),window.addEventListener(`scroll`,x,!0);let r=e.getBoundingClientRect();b.style.left=`${Math.max(8,Math.min(r.left,window.innerWidth-b.offsetWidth-8))}px`,b.style.top=r.bottom+6+b.offsetHeight>window.innerHeight?`${r.top-b.offsetHeight-6}px`:`${r.bottom+6}px`},e.onmouseleave=x}function S(e,t,n){let r=a(`button`,`flex w-full cursor-pointer items-center gap-1.5 px-2 py-1 text-left hover:bg-neutral-100`,c(ee,`h-3 w-3 text-indigo-600 ${e.value===t?``:`invisible`}`),a(`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&&r.append(a(`span`,`min-w-0 truncate text-[11px] text-neutral-400`,e.subject)),e.author&&r.append(a(`span`,`ml-auto flex-none pl-1.5 text-[10.5px] text-neutral-400`,`${e.author} · ${e.at?o(e.at):``}`)),ue(r,()=>le(e)),r.onclick=()=>n(e.value),r}function de(e,t,n,r,i){let{base:o,head:s}=n,u=()=>s&&o===`${s}~1`?s:``,d=u()?`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=a(`div`,`flex w-[38rem] max-w-full flex-col`);function h(){let e=(e,t)=>{let n=a(`button`,`cursor-pointer rounded-full px-2.5 py-0.5 text-[11.5px] ${d===t?`bg-indigo-50 font-medium text-indigo-700`:`text-neutral-500 hover:bg-neutral-100`}`,e);return n.onclick=()=>{d=t,h()},n},n=(e,t,n,r)=>a(`div`,`flex min-w-0 flex-1 flex-col`,a(`div`,`flex-none px-2 pb-0.5 text-[10.5px] font-semibold uppercase tracking-wide text-neutral-400`,e),a(`div`,`min-h-0 flex-1 overflow-y-auto`,...t.map(e=>S(e,n,r)))),l=d===`compare`?a(`div`,`flex h-72 min-h-0 divide-x divide-neutral-200 pb-1`,n(`base`,p(!1),o,e=>{o=e,h(),r(o,s)}),n(`to`,p(!0),s,e=>{s=e,h(),r(o,s)})):a(`div`,`flex h-72 min-h-0 flex-col overflow-y-auto pb-1`,...t.commits.map(e=>S({value:e.hash,...e},u(),e=>{o=`${e}~1`,s=e,te(),r(o,s)}))),f=a(`div`,`flex-none border-t border-neutral-200`,S({value:i,label:`${i} ↔ Working tree`,subject:`back to the default: the main line's tip vs the files on disk`},o===i&&s===``?i:``,()=>{o=i,s=``,h(),r(o,s)}));f.querySelector(`button > span`).prepend(c(v)),m.replaceChildren(a(`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`)),l,...d===`compare`?[f]:[])}h(),l(e,m)}var fe=/\.(png|jpe?g|gif|webp|avif|bmp|svg)$/i,C={A:`text-emerald-600`,M:`text-amber-600`,D:`text-red-600`},pe=30,w=`pier.filesPrefs`,T=50,E=()=>{try{let e=JSON.parse(localStorage.getItem(w)??`{}`);return e&&typeof e==`object`?e:{}}catch{return{}}},me=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},he=(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)}},ge=`flex min-w-0 flex-none items-center gap-1.5 rounded-full px-2.5 py-1 font-mono text-[11.5px]`,_e=(e,t=`indigo`)=>re(e,`${ge} 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`}`);function D(o,l,ee,te){let v=``,y=``,b={branch:null,refs:[],commits:[],worktrees:[]},x=`HEAD`,S=``,w=new Map,T=!0,E=!1,D=[],O=new Set,k=null,A=null,j=null,ve=a(`header`,`pagehead flex-nowrap`),M=a(`div`,`${u} flex-col items-stretch gap-1.5 px-3 py-2.5`),N=a(`div`,`min-h-0 flex-1 overflow-y-auto px-1.5 py-1.5`),ye=a(`aside`,`${ie} w-64 flex-none text-[12.5px] leading-5 max-md:h-1/2 max-md:w-full`,M,N),P=a(`div`,`${u} flex-wrap gap-2 px-4 py-2.5 font-mono text-[11.5px] text-neutral-500`),F=a(`div`,`h-full min-w-0 overflow-auto`),I=a(`div`,`pointer-events-none absolute inset-y-1 right-0.5 z-20 hidden w-2`),be=a(`div`,`relative min-h-0 flex-1`,F,I),xe=a(`section`,`${ie} min-h-0 min-w-0 flex-1`,P,be);o.append(ve,a(`div`,`flex min-h-0 flex-1 gap-3 px-4 pb-4 pt-1 max-md:flex-col`,ye,xe));let L=(e,t)=>`/api/explorer/${e}?${new URLSearchParams({root:v,...t})}`,R=(e,t)=>`/api/fs/${e}?${new URLSearchParams({root:v,...t})}`,z=(e,t=`text-neutral-400`)=>a(`p`,`px-3 py-2 text-[12.5px] ${t}`,e),B=e=>a(`div`,`flex h-full items-center justify-center p-6`,i(e)),Se=()=>T&&b.branch!==null,Ce=e=>{let t=0;for(let n of w.keys())n.startsWith(`${e}/`)&&t++;return t};function we(e,t){let n=new Set(t.map(e=>e.name)),r=e?`${e}/`:``;for(let[e,i]of w){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 Se()&&(i=t.filter(e=>e.dir?Ce(`${r}${e.name}`)>0:w.has(`${r}${e.name}`))),i.sort((e,t)=>Number(t.dir)-Number(e.dir)||e.name.localeCompare(t.name)),i.map(e=>e.dir?Ee(`${r}${e.name}`,e.name):De(`${r}${e.name}`,e.name))}async function Te(e,t){try{let{entries:n}=await g(R(`ls`,{path:t}),`could not list this folder`);e.replaceChildren(...we(t,n)),e.childElementCount||e.append(z(Se()?`No changes.`:`Empty.`))}catch(n){let r=we(t,[]);r.length?e.replaceChildren(...r):e.replaceChildren(z(String(n),`text-red-600`))}}function Ee(e,n){let r=Ce(e),i=[a(`span`,`truncate`,n)];r&&i.push(a(`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:o,summary:s}=t(``,i);s.className+=` rounded-lg px-2 py-1 transition-colors hover:bg-neutral-100`;let c=a(`div`,`pl-3`);o.append(c);let l=!1,u=()=>{l||(l=!0,c.append(z(`…`)),Te(c,e))};return o.ontoggle=()=>{O[o.open?`add`:`delete`](e),o.open&&u()},((b.branch?T:!e.includes(`/`))&&!E||O.has(e))&&(o.open=!0,u()),o}function V(e){A?.classList.remove(`bg-indigo-50`,`font-medium`,`text-indigo-700`),A=e,e.classList.add(`bg-indigo-50`,`font-medium`,`text-indigo-700`)}function De(e,t){let n=w.get(e)?.status,r=a(`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`,a(`span`,`truncate`,t));return n&&r.append(a(`span`,`ml-auto flex-none font-mono text-[10.5px] font-semibold ${C[n]??`text-neutral-500`}`,n)),r.title=e,e===k&&V(r),e===j&&(j=null,k=e,V(r),J(e)),r.onclick=()=>{V(r),k=e,J(e)},r}let H=()=>void Te(N,``),U=(e,t)=>[...e?[a(`span`,`flex-none font-mono text-[10.5px] font-semibold text-emerald-600`,`+${e}`)]:[],...t?[a(`span`,`flex-none font-mono text-[10.5px] font-semibold text-red-600`,`−${t}`)]:[]];function W(t,n=!1,r){if(P.classList.toggle(`hidden`,!t),P.classList.toggle(`flex`,!!t),!t)return P.replaceChildren();let i=w.get(t),o=[a(`span`,`min-w-0 truncate`,t)];i&&(o.push(a(`span`,`flex-none font-semibold ${C[i.status]??``}`,i.status)),o.push(...U(i.add,i.del)));let s=a(`div`,`ml-auto flex flex-none items-center gap-2`);if(r&&s.append(r),n){let n=document.createElement(`a`);n.className=`btn flex-none text-[12px]`,n.href=R(`file`,{path:t}),n.download=e(t),n.textContent=`Download`,s.append(n)}P.replaceChildren(...o,s)}function Oe(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 G=Ie();function K(){I.classList.add(`hidden`),I.replaceChildren(),G.set([],[])}let ke=0,q=e=>e===ke;function J(e){let t=++ke;return w.has(e)?Le(e,t):Ae(e,t)}async function Ae(e,t){if(!q(t))return;K();let n=R(`file`,{path:e}),r=a(`div`,`min-w-0`);if(F.classList.remove(`flex`,`flex-col`),W(e,!0),F.replaceChildren(r),fe.test(e)){let e=a(`img`,`max-w-full p-4`);e.src=n,e.onerror=()=>r.replaceChildren(z(`Could not load image.`,`text-red-600`)),r.append(e);return}if(e.toLowerCase().endsWith(`.pdf`)){let e=document.createElement(`iframe`);e.className=`h-full w-full`,e.src=n,F.replaceChildren(e),F.classList.add(`flex`,`flex-col`);return}r.append(z(`…`));let i=await fetch(n);if(!q(t))return;if(!i.ok){let{error:e}=await i.json().catch(()=>({}));r.replaceChildren(z(e??`HTTP ${i.status}`,`text-red-600`));return}if(!(i.headers.get(`content-type`)??``).startsWith(`text/plain`)){r.replaceChildren(z(`Binary file — use Download.`));return}let o=h(await i.text());if(!q(t))return;let s=await d(e);q(t)&&r.replaceChildren(_(o,s))}function je(e){let t=[],n=0,r=0,i=!1,a=e.split(`
|
|
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 Me(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 Ne={add:`bg-emerald-400`,del:`bg-red-400`,mixed:`bg-amber-400`};function Pe(e,t,n){I.replaceChildren(...e.map(e=>{let r=a(`button`,`map-mark pointer-events-auto absolute left-1/2 w-1 -translate-x-1/2 cursor-pointer rounded-full ${Ne[e.tone]}`);return r.style.top=`${e.start/t*100}%`,r.style.height=`${Math.max(.4,(e.end-e.start+1)/t*100)}%`,r.title=`line ${Fe(n,e.start)}`,r.onclick=()=>n[e.start].scrollIntoView({block:`center`}),r})),I.classList.remove(`hidden`)}let Fe=(e,t)=>e[t]?.querySelector(`span`)?.textContent?.trim()||String(t+1);function Ie(){let e=[],t=[],n=-1,r=a(`span`,`flex-none text-[10.5px] text-neutral-400`),i=i=>{e.length&&(n=(n+i+e.length)%e.length,t[e[n].start].scrollIntoView({block:`center`}),r.textContent=`${n+1}/${e.length}`)},l=()=>e.length>0&&!o.classList.contains(`hidden`),u=(e,t,n,r)=>{let o=a(`button`,`icon-btn flex-none`,c(e));return o.onclick=()=>i(t),s(o,r,n,()=>i(t),l),o};return{el:a(`div`,`flex flex-none items-center gap-1`,r,u(f,-1,`Previous change`,[`p`,`k`]),u(ae,1,`Next change`,[`n`,`j`])),set(i,a){e=i,t=a,n=-1,r.textContent=`${i.length} change${i.length===1?``:`s`}`}}}async function Le(e,t){K(),F.classList.remove(`flex`,`flex-col`);let n=w.get(e)?.status!==`D`;W(e,n),F.replaceChildren(z(`…`));try{let{diff:r}=await g(L(`diff`,{base:x,head:S,file:e,context:`99999`}),`could not read this diff`);if(!q(t))return;if(!r||/^Binary files /m.test(r))return Ae(e,t);let i=je(r);Oe(i);let a=await d(e);if(!q(t))return;let o=_(i,a),s=[...o.children],c=Me(i);G.set(c,s),W(e,n,G.el),F.replaceChildren(o),Pe(c,i.length,s)}catch(n){if(!q(t))return;W(e),F.replaceChildren(z(String(n),`text-red-600`))}}let Y=()=>S&&x===`${S}~1`?S:``,Re=()=>b.commits.find(e=>e.hash===Y())?.subject??``,ze=()=>Y()?`${Y()} — ${Re()||`commit`}`:`${x} ↔ ${S||`working tree`}`,Be=(e,t,n,r)=>{let i=a(`button`,`icon-btn ${n?`bg-indigo-50 text-indigo-700 hover:bg-indigo-100 hover:text-indigo-700`:``}`);return i.append(c(e)),i.title=t,i.setAttribute(`aria-label`,t),i.setAttribute(`aria-pressed`,String(n)),i.onclick=r,i};function X(){let e=Be(se,`Show only files that differ`,T,()=>{T=!T,X(),H()}),t=Be(oe,E?`Restore folders`:`Collapse all folders`,E,()=>{if(E=!E,E)D=[...O],O.clear();else for(let e of D)O.add(e);X(),H()});if(!b.branch){M.replaceChildren(a(`div`,`flex items-center gap-1.5`,a(`span`,`min-w-0 flex-1 text-[11px] leading-snug text-neutral-400`,`Not a git repository — nothing to compare.`),t));return}let n=re(ze(),`${ne} font-mono`);if(Y()){let e=b.commits.find(e=>e.hash===Y());ue(n,()=>e?le(e):``)}else n.title=`Choose what to diff`;n.onclick=async()=>{await We(),de(n,b,{base:x,head:S},(e,t)=>{x=e,S=t,Z()},$())};let[r,i]=[0,0];for(let e of w.values())r+=e.add,i+=e.del;M.replaceChildren(n,a(`div`,`flex items-center gap-1.5 pl-0.5`,a(`span`,`text-[11px] text-neutral-400`,`${w.size} changed file${w.size===1?``:`s`}`),...U(r,i),a(`span`,`ml-auto`),e,t))}let Ve=()=>{y&&v&&he(y,{cwd:v,base:x,head:S})},He=e=>{let t=e.replace(/~\d+$/,``);return!t||t===`HEAD`||b.refs.some(e=>e.name===t)||b.commits.some(e=>e.hash===t)};async function Ue(){if(w=new Map,!b.branch)return;let{files:e}=await g(L(`diff`,{base:x,head:S}),`could not read what changed`);for(let t of e)w.set(t.path,{status:t.status,add:t.add,del:t.del});if(w.size<=pe)for(let e of w.keys()){let t=e.split(`/`);for(let e=1;e<t.length;e++)O.add(t.slice(0,e).join(`/`))}}async function Z(){Ve();try{await Ue()}catch(e){X(),N.replaceChildren(z(String(e),`text-red-600`));return}X(),H(),k&&J(k)}function Q(){let t=_e(``,`neutral`);t.className+=` max-w-72`,t.append(a(`span`,`truncate max-md:hidden`,v||`Choose a folder…`),a(`span`,`truncate md:hidden`,v?e(v):`Choose a folder…`)),t.title=v?`${v} — switch folder`:`Choose a folder`,t.onclick=()=>p(t,b.worktrees.map(e=>({path:e.path,...e.branch?{hint:e.branch}:{}})),v||void 0,ee);let n=a(`button`,`icon-btn ml-auto`,c(m));n.type=`button`,n.title=`Close Files`,n.setAttribute(`aria-label`,`Close Files`),n.onclick=te;let i=b.branch?[a(`span`,`${ge} bg-neutral-100 text-neutral-600`,c(ce),a(`span`,`truncate`,b.branch))]:[];ve.replaceChildren(r(`Files`),t,...i,n)}async function We(){if(v)try{b=await g(L(`git`,{}),`could not read this repository`),Q()}catch(e){F.replaceChildren(B(String(e)))}}let $=()=>b.refs.some(e=>e.name===`main`)?`main`:b.refs.some(e=>e.name===`master`)?`master`:`HEAD`;async function Ge(e){if(Q(),k=null,A=null,O.clear(),j=e||null,e){T=!1;let t=e.split(`/`);for(let e=1;e<t.length;e++)O.add(t.slice(0,e).join(`/`))}if(K(),F.classList.remove(`flex`,`flex-col`),W(),F.replaceChildren(B(`Select a file.`)),!v){M.replaceChildren(),N.replaceChildren(),F.replaceChildren(B(`No folder yet — pick one from the chip above.`));return}try{b=await g(L(`git`,{}),`could not read this repository`)}catch(e){b={branch:null,refs:[],commits:[],worktrees:[]},F.replaceChildren(B(String(e)))}let t=me(y),n=t&&t.cwd===v&&He(t.base)&&He(t.head)?t:null;x=n?.base??$(),S=n?.head??``,Q(),await Z()}return n(o,(e,t)=>{let n=l(),r=n?.id??``,i=new URLSearchParams(t).get(`select`)??void 0,a=e?.startsWith(`/`)?e:(r===y?v:``)||me(r)?.cwd||n?.cwd||``;if(a===v&&r===y&&N.childElementCount&&(!i||i===k)){Q(),We().then(Z);return}y=r,v=a,Ge(i)},()=>{K(),F.classList.remove(`flex`,`flex-col`),W(),F.replaceChildren(B(`Select a file.`))})}export{D as createExplorerView};
|
|
Binary file
|
|
Binary file
|