heyiam 0.3.9 → 0.3.11
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/db.js +51 -3
- package/dist/format-utils.js +19 -0
- package/dist/index.js +27 -10
- package/dist/public/assets/{index-LQHTU1Wz.js → index-DU5On5Al.js} +1 -1
- package/dist/public/index.html +1 -1
- package/dist/routes/delete.js +18 -1
- package/dist/routes/project-session-upload.js +63 -1
- package/dist/routes/publish.js +27 -4
- package/dist/routes/sessions.js +36 -11
- package/dist/sync.js +3 -13
- package/package.json +1 -1
package/dist/db.js
CHANGED
|
@@ -5,6 +5,7 @@ import crypto from 'node:crypto';
|
|
|
5
5
|
import { mkdirSync, statSync } from 'node:fs';
|
|
6
6
|
import { join } from 'node:path';
|
|
7
7
|
import { homedir } from 'node:os';
|
|
8
|
+
import { projectDirFromPath } from './format-utils.js';
|
|
8
9
|
// ── Constants ────────────────────────────────────────────────
|
|
9
10
|
function getDataDir() {
|
|
10
11
|
return process.env.HEYIAM_DATA_DIR || join(homedir(), '.local', 'share', 'heyiam');
|
|
@@ -12,7 +13,7 @@ function getDataDir() {
|
|
|
12
13
|
export function getDbPath() {
|
|
13
14
|
return join(getDataDir(), 'sessions.db');
|
|
14
15
|
}
|
|
15
|
-
const CURRENT_SCHEMA_VERSION =
|
|
16
|
+
const CURRENT_SCHEMA_VERSION = 6;
|
|
16
17
|
// ── Singleton ────────────────────────────────────────────────
|
|
17
18
|
let _db = null;
|
|
18
19
|
export function getDatabase(dbPath = getDbPath()) {
|
|
@@ -53,6 +54,9 @@ function runMigrations(db) {
|
|
|
53
54
|
if (currentVersion < 5) {
|
|
54
55
|
migrateToV5(db);
|
|
55
56
|
}
|
|
57
|
+
if (currentVersion < 6) {
|
|
58
|
+
migrateToV6(db);
|
|
59
|
+
}
|
|
56
60
|
}
|
|
57
61
|
function migrateToV2(db) {
|
|
58
62
|
// Drop old tables if upgrading from v1
|
|
@@ -169,14 +173,48 @@ function migrateToV4(db) {
|
|
|
169
173
|
});
|
|
170
174
|
tx();
|
|
171
175
|
}
|
|
176
|
+
/**
|
|
177
|
+
* One-time repair: backfill rows where project_dir drifted from file_path.
|
|
178
|
+
*
|
|
179
|
+
* Claude Code v2.1+ relocates a session to a new project dir when the cwd
|
|
180
|
+
* changes mid-session. Earlier versions of this CLI healed file_path in
|
|
181
|
+
* isolation, leaving project_dir pointing at the original directory and
|
|
182
|
+
* making sessions appear under the wrong project in the UI.
|
|
183
|
+
*/
|
|
184
|
+
function migrateToV6(db) {
|
|
185
|
+
const tx = db.transaction(() => {
|
|
186
|
+
const rows = db.prepare('SELECT id, file_path, is_subagent, project_dir FROM sessions WHERE file_path IS NOT NULL').all();
|
|
187
|
+
const update = db.prepare('UPDATE sessions SET project_dir = ? WHERE id = ?');
|
|
188
|
+
let healed = 0;
|
|
189
|
+
for (const r of rows) {
|
|
190
|
+
if (r.file_path.includes('://'))
|
|
191
|
+
continue;
|
|
192
|
+
const derived = projectDirFromPath(r.file_path, r.is_subagent === 1);
|
|
193
|
+
if (derived && derived !== r.project_dir) {
|
|
194
|
+
update.run(derived, r.id);
|
|
195
|
+
healed++;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
if (healed > 0) {
|
|
199
|
+
console.log('[migrate v6] Repaired project_dir for ' + healed + ' session(s)');
|
|
200
|
+
}
|
|
201
|
+
db.prepare('UPDATE schema_version SET version = ?').run(6);
|
|
202
|
+
});
|
|
203
|
+
tx();
|
|
204
|
+
}
|
|
172
205
|
// ── Staleness Check ──────────────────────────────────────────
|
|
173
206
|
export function isSessionStale(db, sessionId, filePath) {
|
|
174
|
-
const row = db.prepare('SELECT file_mtime, file_size FROM sessions WHERE id = ?').get(sessionId);
|
|
207
|
+
const row = db.prepare('SELECT file_mtime, file_size, file_path FROM sessions WHERE id = ?').get(sessionId);
|
|
175
208
|
if (!row)
|
|
176
209
|
return true; // Not in DB — needs indexing
|
|
177
210
|
// Skip stat for non-filesystem paths (e.g. cursor:// URLs) — F23 fix
|
|
178
211
|
if (filePath.includes('://'))
|
|
179
212
|
return true;
|
|
213
|
+
// Claude Code v2.1+ renames a session file when cwd changes mid-session.
|
|
214
|
+
// A rename preserves mtime/size, so without this check the row's stale
|
|
215
|
+
// project_dir would never get refreshed.
|
|
216
|
+
if (row.file_path && row.file_path !== filePath)
|
|
217
|
+
return true;
|
|
180
218
|
try {
|
|
181
219
|
const stat = statSync(filePath);
|
|
182
220
|
// F21: Use Math.floor to avoid floating-point comparison issues
|
|
@@ -379,9 +417,19 @@ export function deleteSession(db, sessionId) {
|
|
|
379
417
|
* we discover the originally-indexed path has been deleted by its source
|
|
380
418
|
* tool (e.g., Claude Code's 30-day cleanup) and we've fallen back to an
|
|
381
419
|
* archived copy.
|
|
420
|
+
*
|
|
421
|
+
* Also re-derives project_dir from the new path. Claude Code v2.1+ relocates
|
|
422
|
+
* sessions when the cwd changes mid-session, and project_dir is a denormalized
|
|
423
|
+
* cache of dirname(file_path) — they must move together or the UI groups
|
|
424
|
+
* sessions under their old project.
|
|
382
425
|
*/
|
|
383
426
|
export function updateSessionPath(db, sessionId, newPath) {
|
|
384
|
-
db.prepare('
|
|
427
|
+
const row = db.prepare('SELECT is_subagent FROM sessions WHERE id = ?').get(sessionId);
|
|
428
|
+
if (!row)
|
|
429
|
+
return;
|
|
430
|
+
const projectDir = projectDirFromPath(newPath, row.is_subagent === 1);
|
|
431
|
+
db.prepare('UPDATE sessions SET file_path = ?, project_dir = ? WHERE id = ?')
|
|
432
|
+
.run(newPath, projectDir, sessionId);
|
|
385
433
|
}
|
|
386
434
|
// ── Rebuild Index ────────────────────────────────────────────
|
|
387
435
|
export function rebuildIndex(db, onProgress) {
|
package/dist/format-utils.js
CHANGED
|
@@ -1,7 +1,26 @@
|
|
|
1
|
+
import { basename, dirname } from 'node:path';
|
|
1
2
|
/** Escape HTML special characters for safe embedding. */
|
|
2
3
|
export function escapeHtml(str) {
|
|
3
4
|
return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
|
4
5
|
}
|
|
6
|
+
/**
|
|
7
|
+
* Derive the project_dir segment from a Claude Code session file path.
|
|
8
|
+
*
|
|
9
|
+
* Layouts:
|
|
10
|
+
* .../projects/{projectDir}/{sessionId}.jsonl — parent session
|
|
11
|
+
* .../projects/{projectDir}/{parentSessionId}/subagents/X.jsonl — subagent
|
|
12
|
+
*
|
|
13
|
+
* Claude Code v2.1+ relocates session files when cwd changes mid-session,
|
|
14
|
+
* so we need to re-derive project_dir from the current file path rather than
|
|
15
|
+
* trusting a value stored at first-index time.
|
|
16
|
+
*/
|
|
17
|
+
export function projectDirFromPath(filePath, isSubagent) {
|
|
18
|
+
if (isSubagent) {
|
|
19
|
+
const sessionDataDir = dirname(dirname(filePath));
|
|
20
|
+
return basename(dirname(sessionDataDir));
|
|
21
|
+
}
|
|
22
|
+
return basename(dirname(filePath));
|
|
23
|
+
}
|
|
5
24
|
/** Format LOC as human-readable (e.g. "2.4k"). */
|
|
6
25
|
export function formatLoc(loc) {
|
|
7
26
|
if (loc >= 1000)
|
package/dist/index.js
CHANGED
|
@@ -23,14 +23,7 @@ program
|
|
|
23
23
|
.name('heyiam')
|
|
24
24
|
.description('Turn AI coding sessions into portfolio case studies')
|
|
25
25
|
.version(pkg.version);
|
|
26
|
-
|
|
27
|
-
.command('open')
|
|
28
|
-
.description('Start the local server and open the browser')
|
|
29
|
-
.option('-p, --port <number>', 'Port to run on', '17845')
|
|
30
|
-
.option('--no-open', 'Start server without opening browser')
|
|
31
|
-
.option('--demo', 'Start with fake data for screenshots and recordings')
|
|
32
|
-
.option('--verbose', 'Show detailed sync and discovery logs')
|
|
33
|
-
.action(async (opts) => {
|
|
26
|
+
async function runOpenServer(opts) {
|
|
34
27
|
if (opts.verbose)
|
|
35
28
|
process.env.HEYIAM_VERBOSE = '1';
|
|
36
29
|
const port = parseInt(opts.port, 10);
|
|
@@ -120,6 +113,23 @@ program
|
|
|
120
113
|
process.on('SIGINT', shutdown);
|
|
121
114
|
process.on('SIGTERM', shutdown);
|
|
122
115
|
setInterval(() => { }, 60_000);
|
|
116
|
+
}
|
|
117
|
+
program
|
|
118
|
+
.command('open')
|
|
119
|
+
.description('Start the local server and open the browser')
|
|
120
|
+
.option('-p, --port <number>', 'Port to run on', '17845')
|
|
121
|
+
.option('--no-open', 'Start server without opening browser')
|
|
122
|
+
.option('--demo', 'Start with fake data for screenshots and recordings')
|
|
123
|
+
.option('--verbose', 'Show detailed sync and discovery logs')
|
|
124
|
+
.action(runOpenServer);
|
|
125
|
+
program
|
|
126
|
+
.command('login')
|
|
127
|
+
.description('Sign in to heyiam.com (opens the dashboard in your browser)')
|
|
128
|
+
.option('-p, --port <number>', 'Port to run on', '17845')
|
|
129
|
+
.option('--verbose', 'Show detailed sync and discovery logs')
|
|
130
|
+
.action(async (opts) => {
|
|
131
|
+
console.log('\n Sign in from the dashboard that opens in your browser.\n');
|
|
132
|
+
await runOpenServer({ port: opts.port, open: true, verbose: opts.verbose });
|
|
123
133
|
});
|
|
124
134
|
program
|
|
125
135
|
.command('time')
|
|
@@ -847,9 +857,16 @@ const resolvedArgv = process.argv[1] ? realpathSync(process.argv[1]) : '';
|
|
|
847
857
|
const isDirectRun = resolvedArgv.endsWith('/dist/index.js') ||
|
|
848
858
|
resolvedArgv.endsWith('/src/index.ts');
|
|
849
859
|
if (isDirectRun) {
|
|
860
|
+
// Default to `open` when the user runs `heyiam` bare or `heyiam --flag …`,
|
|
861
|
+
// so `heyiam --port 1234` becomes `heyiam open --port 1234`. We only do
|
|
862
|
+
// this for *flags* (args starting with `-`) — bare unknown words like
|
|
863
|
+
// `heyiam blargh` should fall through to Commander so the user sees a
|
|
864
|
+
// clean "unknown command" error instead of a confusing "too many
|
|
865
|
+
// arguments for 'open'".
|
|
850
866
|
const args = process.argv.slice(2);
|
|
851
|
-
const
|
|
852
|
-
|
|
867
|
+
const firstArg = args[0];
|
|
868
|
+
const shouldDefaultToOpen = args.length === 0 || (firstArg !== undefined && firstArg.startsWith('-'));
|
|
869
|
+
if (shouldDefaultToOpen) {
|
|
853
870
|
process.argv.splice(2, 0, 'open');
|
|
854
871
|
}
|
|
855
872
|
program.parseAsync(process.argv).catch((err) => {
|
|
@@ -34,4 +34,4 @@ Error generating stack: `+e.message+`
|
|
|
34
34
|
While dragging, use the arrow keys to move the item.
|
|
35
35
|
Press space again to drop the item in its new position, or press escape to cancel.
|
|
36
36
|
`},Fl={onDragStart(e){let{active:t}=e;return`Picked up draggable item `+t.id+`.`},onDragOver(e){let{active:t,over:n}=e;return n?`Draggable item `+t.id+` was moved over droppable area `+n.id+`.`:`Draggable item `+t.id+` is no longer over a droppable area.`},onDragEnd(e){let{active:t,over:n}=e;return n?`Draggable item `+t.id+` was dropped over droppable area `+n.id:`Draggable item `+t.id+` was dropped.`},onDragCancel(e){let{active:t}=e;return`Dragging was cancelled. Draggable item `+t.id+` was dropped.`}};function Il(e){let{announcements:t=Fl,container:n,hiddenTextDescribedById:r,screenReaderInstructions:i=Pl}=e,{announce:a,announcement:o}=Al(),s=gl(`DndLiveRegion`),[c,l]=(0,_.useState)(!1);if((0,_.useEffect)(()=>{l(!0)},[]),Ml((0,_.useMemo)(()=>({onDragStart(e){let{active:n}=e;a(t.onDragStart({active:n}))},onDragMove(e){let{active:n,over:r}=e;t.onDragMove&&a(t.onDragMove({active:n,over:r}))},onDragOver(e){let{active:n,over:r}=e;a(t.onDragOver({active:n,over:r}))},onDragEnd(e){let{active:n,over:r}=e;a(t.onDragEnd({active:n,over:r}))},onDragCancel(e){let{active:n,over:r}=e;a(t.onDragCancel({active:n,over:r}))}}),[a,t])),!c)return null;let u=_.createElement(_.Fragment,null,_.createElement(Ol,{id:r,value:i.draggable}),_.createElement(kl,{id:s,announcement:o}));return n?(0,el.createPortal)(u,n):u}var Ll;(function(e){e.DragStart=`dragStart`,e.DragMove=`dragMove`,e.DragEnd=`dragEnd`,e.DragCancel=`dragCancel`,e.DragOver=`dragOver`,e.RegisterDroppable=`registerDroppable`,e.SetDroppableDisabled=`setDroppableDisabled`,e.UnregisterDroppable=`unregisterDroppable`})(Ll||={});function Rl(){}function K(e,t){return(0,_.useMemo)(()=>({sensor:e,options:t??{}}),[e,t])}function q(){var e=[...arguments];return(0,_.useMemo)(()=>[...e].filter(e=>e!=null),[...e])}var J=Object.freeze({x:0,y:0});function Y(e,t){return Math.sqrt((e.x-t.x)**2+(e.y-t.y)**2)}function X(e,t){let{data:{value:n}}=e,{data:{value:r}}=t;return n-r}function zl(e,t){let{data:{value:n}}=e,{data:{value:r}}=t;return r-n}function Bl(e){let{left:t,top:n,height:r,width:i}=e;return[{x:t,y:n},{x:t+i,y:n},{x:t,y:n+r},{x:t+i,y:n+r}]}function Vl(e,t){if(!e||e.length===0)return null;let[n]=e;return t?n[t]:n}function Hl(e,t,n){return t===void 0&&(t=e.left),n===void 0&&(n=e.top),{x:t+e.width*.5,y:n+e.height*.5}}var Ul=e=>{let{collisionRect:t,droppableRects:n,droppableContainers:r}=e,i=Hl(t,t.left,t.top),a=[];for(let e of r){let{id:t}=e,r=n.get(t);if(r){let n=Y(Hl(r),i);a.push({id:t,data:{droppableContainer:e,value:n}})}}return a.sort(X)},Wl=e=>{let{collisionRect:t,droppableRects:n,droppableContainers:r}=e,i=Bl(t),a=[];for(let e of r){let{id:t}=e,r=n.get(t);if(r){let n=Bl(r),o=i.reduce((e,t,r)=>e+Y(n[r],t),0),s=Number((o/4).toFixed(4));a.push({id:t,data:{droppableContainer:e,value:s}})}}return a.sort(X)};function Gl(e,t){let n=Math.max(t.top,e.top),r=Math.max(t.left,e.left),i=Math.min(t.left+t.width,e.left+e.width),a=Math.min(t.top+t.height,e.top+e.height),o=i-r,s=a-n;if(r<i&&n<a){let n=t.width*t.height,r=e.width*e.height,i=o*s,a=i/(n+r-i);return Number(a.toFixed(4))}return 0}var Kl=e=>{let{collisionRect:t,droppableRects:n,droppableContainers:r}=e,i=[];for(let e of r){let{id:r}=e,a=n.get(r);if(a){let n=Gl(a,t);n>0&&i.push({id:r,data:{droppableContainer:e,value:n}})}}return i.sort(zl)};function ql(e,t,n){return{...e,scaleX:t&&n?t.width/n.width:1,scaleY:t&&n?t.height/n.height:1}}function Jl(e,t){return e&&t?{x:e.left-t.left,y:e.top-t.top}:J}function Yl(e){return function(t){return[...arguments].slice(1).reduce((t,n)=>({...t,top:t.top+e*n.y,bottom:t.bottom+e*n.y,left:t.left+e*n.x,right:t.right+e*n.x}),{...t})}}var Xl=Yl(1);function Zl(e){if(e.startsWith(`matrix3d(`)){let t=e.slice(9,-1).split(/, /);return{x:+t[12],y:+t[13],scaleX:+t[0],scaleY:+t[5]}}else if(e.startsWith(`matrix(`)){let t=e.slice(7,-1).split(/, /);return{x:+t[4],y:+t[5],scaleX:+t[0],scaleY:+t[3]}}return null}function Ql(e,t,n){let r=Zl(t);if(!r)return e;let{scaleX:i,scaleY:a,x:o,y:s}=r,c=e.left-o-(1-i)*parseFloat(n),l=e.top-s-(1-a)*parseFloat(n.slice(n.indexOf(` `)+1)),u=i?e.width/i:e.width,d=a?e.height/a:e.height;return{width:u,height:d,top:l,right:c+u,bottom:l+d,left:c}}var $l={ignoreTransform:!1};function eu(e,t){t===void 0&&(t=$l);let n=e.getBoundingClientRect();if(t.ignoreTransform){let{transform:t,transformOrigin:r}=W(e).getComputedStyle(e);t&&(n=Ql(n,t,r))}let{top:r,left:i,width:a,height:o,bottom:s,right:c}=n;return{top:r,left:i,width:a,height:o,bottom:s,right:c}}function tu(e){return eu(e,{ignoreTransform:!0})}function nu(e){let t=e.innerWidth,n=e.innerHeight;return{top:0,left:0,right:t,bottom:n,width:t,height:n}}function ru(e,t){return t===void 0&&(t=W(e).getComputedStyle(e)),t.position===`fixed`}function iu(e,t){t===void 0&&(t=W(e).getComputedStyle(e));let n=/(auto|scroll|overlay)/;return[`overflow`,`overflowX`,`overflowY`].some(e=>{let r=t[e];return typeof r==`string`?n.test(r):!1})}function au(e,t){let n=[];function r(i){if(t!=null&&n.length>=t||!i)return n;if(al(i)&&i.scrollingElement!=null&&!n.includes(i.scrollingElement))return n.push(i.scrollingElement),n;if(!ol(i)||sl(i)||n.includes(i))return n;let a=W(e).getComputedStyle(i);return i!==e&&iu(i,a)&&n.push(i),ru(i,a)?n:r(i.parentNode)}return e?r(e):n}function ou(e){let[t]=au(e,1);return t??null}function su(e){return!nl||!e?null:rl(e)?e:il(e)?al(e)||e===G(e).scrollingElement?window:ol(e)?e:null:null}function cu(e){return rl(e)?e.scrollX:e.scrollLeft}function lu(e){return rl(e)?e.scrollY:e.scrollTop}function uu(e){return{x:cu(e),y:lu(e)}}var du;(function(e){e[e.Forward=1]=`Forward`,e[e.Backward=-1]=`Backward`})(du||={});function fu(e){return!nl||!e?!1:e===document.scrollingElement}function pu(e){let t={x:0,y:0},n=fu(e)?{height:window.innerHeight,width:window.innerWidth}:{height:e.clientHeight,width:e.clientWidth},r={x:e.scrollWidth-n.width,y:e.scrollHeight-n.height};return{isTop:e.scrollTop<=t.y,isLeft:e.scrollLeft<=t.x,isBottom:e.scrollTop>=r.y,isRight:e.scrollLeft>=r.x,maxScroll:r,minScroll:t}}var mu={x:.2,y:.2};function hu(e,t,n,r,i){let{top:a,left:o,right:s,bottom:c}=n;r===void 0&&(r=10),i===void 0&&(i=mu);let{isTop:l,isBottom:u,isLeft:d,isRight:f}=pu(e),p={x:0,y:0},m={x:0,y:0},h={height:t.height*i.y,width:t.width*i.x};return!l&&a<=t.top+h.height?(p.y=du.Backward,m.y=r*Math.abs((t.top+h.height-a)/h.height)):!u&&c>=t.bottom-h.height&&(p.y=du.Forward,m.y=r*Math.abs((t.bottom-h.height-c)/h.height)),!f&&s>=t.right-h.width?(p.x=du.Forward,m.x=r*Math.abs((t.right-h.width-s)/h.width)):!d&&o<=t.left+h.width&&(p.x=du.Backward,m.x=r*Math.abs((t.left+h.width-o)/h.width)),{direction:p,speed:m}}function gu(e){if(e===document.scrollingElement){let{innerWidth:e,innerHeight:t}=window;return{top:0,left:0,right:e,bottom:t,width:e,height:t}}let{top:t,left:n,right:r,bottom:i}=e.getBoundingClientRect();return{top:t,left:n,right:r,bottom:i,width:e.clientWidth,height:e.clientHeight}}function _u(e){return e.reduce((e,t)=>vl(e,uu(t)),J)}function vu(e){return e.reduce((e,t)=>e+cu(t),0)}function yu(e){return e.reduce((e,t)=>e+lu(t),0)}function bu(e,t){if(t===void 0&&(t=eu),!e)return;let{top:n,left:r,bottom:i,right:a}=t(e);ou(e)&&(i<=0||a<=0||n>=window.innerHeight||r>=window.innerWidth)&&e.scrollIntoView({block:`center`,inline:`center`})}var xu=[[`x`,[`left`,`right`],vu],[`y`,[`top`,`bottom`],yu]],Su=class{constructor(e,t){this.rect=void 0,this.width=void 0,this.height=void 0,this.top=void 0,this.bottom=void 0,this.right=void 0,this.left=void 0;let n=au(t),r=_u(n);this.rect={...e},this.width=e.width,this.height=e.height;for(let[e,t,i]of xu)for(let a of t)Object.defineProperty(this,a,{get:()=>{let t=i(n),o=r[e]-t;return this.rect[a]+o},enumerable:!0});Object.defineProperty(this,`rect`,{enumerable:!1})}},Cu=class{constructor(e){this.target=void 0,this.listeners=[],this.removeAll=()=>{this.listeners.forEach(e=>this.target?.removeEventListener(...e))},this.target=e}add(e,t,n){var r;(r=this.target)==null||r.addEventListener(e,t,n),this.listeners.push([e,t,n])}};function wu(e){let{EventTarget:t}=W(e);return e instanceof t?e:G(e)}function Tu(e,t){let n=Math.abs(e.x),r=Math.abs(e.y);return typeof t==`number`?Math.sqrt(n**2+r**2)>t:`x`in t&&`y`in t?n>t.x&&r>t.y:`x`in t?n>t.x:`y`in t?r>t.y:!1}var Eu;(function(e){e.Click=`click`,e.DragStart=`dragstart`,e.Keydown=`keydown`,e.ContextMenu=`contextmenu`,e.Resize=`resize`,e.SelectionChange=`selectionchange`,e.VisibilityChange=`visibilitychange`})(Eu||={});function Du(e){e.preventDefault()}function Ou(e){e.stopPropagation()}var ku;(function(e){e.Space=`Space`,e.Down=`ArrowDown`,e.Right=`ArrowRight`,e.Left=`ArrowLeft`,e.Up=`ArrowUp`,e.Esc=`Escape`,e.Enter=`Enter`,e.Tab=`Tab`})(ku||={});var Au={start:[ku.Space,ku.Enter],cancel:[ku.Esc],end:[ku.Space,ku.Enter,ku.Tab]},ju=(e,t)=>{let{currentCoordinates:n}=t;switch(e.code){case ku.Right:return{...n,x:n.x+25};case ku.Left:return{...n,x:n.x-25};case ku.Down:return{...n,y:n.y+25};case ku.Up:return{...n,y:n.y-25}}},Mu=class{constructor(e){this.props=void 0,this.autoScrollEnabled=!1,this.referenceCoordinates=void 0,this.listeners=void 0,this.windowListeners=void 0,this.props=e;let{event:{target:t}}=e;this.props=e,this.listeners=new Cu(G(t)),this.windowListeners=new Cu(W(t)),this.handleKeyDown=this.handleKeyDown.bind(this),this.handleCancel=this.handleCancel.bind(this),this.attach()}attach(){this.handleStart(),this.windowListeners.add(Eu.Resize,this.handleCancel),this.windowListeners.add(Eu.VisibilityChange,this.handleCancel),setTimeout(()=>this.listeners.add(Eu.Keydown,this.handleKeyDown))}handleStart(){let{activeNode:e,onStart:t}=this.props,n=e.node.current;n&&bu(n),t(J)}handleKeyDown(e){if(xl(e)){let{active:t,context:n,options:r}=this.props,{keyboardCodes:i=Au,coordinateGetter:a=ju,scrollBehavior:o=`smooth`}=r,{code:s}=e;if(i.end.includes(s)){this.handleEnd(e);return}if(i.cancel.includes(s)){this.handleCancel(e);return}let{collisionRect:c}=n.current,l=c?{x:c.left,y:c.top}:J;this.referenceCoordinates||=l;let u=a(e,{active:t,context:n.current,currentCoordinates:l});if(u){let t=yl(u,l),r={x:0,y:0},{scrollableAncestors:i}=n.current;for(let n of i){let i=e.code,{isTop:a,isRight:s,isLeft:c,isBottom:l,maxScroll:d,minScroll:f}=pu(n),p=gu(n),m={x:Math.min(i===ku.Right?p.right-p.width/2:p.right,Math.max(i===ku.Right?p.left:p.left+p.width/2,u.x)),y:Math.min(i===ku.Down?p.bottom-p.height/2:p.bottom,Math.max(i===ku.Down?p.top:p.top+p.height/2,u.y))},h=i===ku.Right&&!s||i===ku.Left&&!c,g=i===ku.Down&&!l||i===ku.Up&&!a;if(h&&m.x!==u.x){let e=n.scrollLeft+t.x,a=i===ku.Right&&e<=d.x||i===ku.Left&&e>=f.x;if(a&&!t.y){n.scrollTo({left:e,behavior:o});return}a?r.x=n.scrollLeft-e:r.x=i===ku.Right?n.scrollLeft-d.x:n.scrollLeft-f.x,r.x&&n.scrollBy({left:-r.x,behavior:o});break}else if(g&&m.y!==u.y){let e=n.scrollTop+t.y,a=i===ku.Down&&e<=d.y||i===ku.Up&&e>=f.y;if(a&&!t.x){n.scrollTo({top:e,behavior:o});return}a?r.y=n.scrollTop-e:r.y=i===ku.Down?n.scrollTop-d.y:n.scrollTop-f.y,r.y&&n.scrollBy({top:-r.y,behavior:o});break}}this.handleMove(e,vl(yl(u,this.referenceCoordinates),r))}}}handleMove(e,t){let{onMove:n}=this.props;e.preventDefault(),n(t)}handleEnd(e){let{onEnd:t}=this.props;e.preventDefault(),this.detach(),t()}handleCancel(e){let{onCancel:t}=this.props;e.preventDefault(),this.detach(),t()}detach(){this.listeners.removeAll(),this.windowListeners.removeAll()}};Mu.activators=[{eventName:`onKeyDown`,handler:(e,t,n)=>{let{keyboardCodes:r=Au,onActivation:i}=t,{active:a}=n,{code:o}=e.nativeEvent;if(r.start.includes(o)){let t=a.activatorNode.current;return t&&e.target!==t?!1:(e.preventDefault(),i?.({event:e.nativeEvent}),!0)}return!1}}];function Nu(e){return!!(e&&`distance`in e)}function Pu(e){return!!(e&&`delay`in e)}var Fu=class{constructor(e,t,n){n===void 0&&(n=wu(e.event.target)),this.props=void 0,this.events=void 0,this.autoScrollEnabled=!0,this.document=void 0,this.activated=!1,this.initialCoordinates=void 0,this.timeoutId=null,this.listeners=void 0,this.documentListeners=void 0,this.windowListeners=void 0,this.props=e,this.events=t;let{event:r}=e,{target:i}=r;this.props=e,this.events=t,this.document=G(i),this.documentListeners=new Cu(this.document),this.listeners=new Cu(n),this.windowListeners=new Cu(W(i)),this.initialCoordinates=Cl(r)??J,this.handleStart=this.handleStart.bind(this),this.handleMove=this.handleMove.bind(this),this.handleEnd=this.handleEnd.bind(this),this.handleCancel=this.handleCancel.bind(this),this.handleKeydown=this.handleKeydown.bind(this),this.removeTextSelection=this.removeTextSelection.bind(this),this.attach()}attach(){let{events:e,props:{options:{activationConstraint:t,bypassActivationConstraint:n}}}=this;if(this.listeners.add(e.move.name,this.handleMove,{passive:!1}),this.listeners.add(e.end.name,this.handleEnd),e.cancel&&this.listeners.add(e.cancel.name,this.handleCancel),this.windowListeners.add(Eu.Resize,this.handleCancel),this.windowListeners.add(Eu.DragStart,Du),this.windowListeners.add(Eu.VisibilityChange,this.handleCancel),this.windowListeners.add(Eu.ContextMenu,Du),this.documentListeners.add(Eu.Keydown,this.handleKeydown),t){if(n!=null&&n({event:this.props.event,activeNode:this.props.activeNode,options:this.props.options}))return this.handleStart();if(Pu(t)){this.timeoutId=setTimeout(this.handleStart,t.delay),this.handlePending(t);return}if(Nu(t)){this.handlePending(t);return}}this.handleStart()}detach(){this.listeners.removeAll(),this.windowListeners.removeAll(),setTimeout(this.documentListeners.removeAll,50),this.timeoutId!==null&&(clearTimeout(this.timeoutId),this.timeoutId=null)}handlePending(e,t){let{active:n,onPending:r}=this.props;r(n,e,this.initialCoordinates,t)}handleStart(){let{initialCoordinates:e}=this,{onStart:t}=this.props;e&&(this.activated=!0,this.documentListeners.add(Eu.Click,Ou,{capture:!0}),this.removeTextSelection(),this.documentListeners.add(Eu.SelectionChange,this.removeTextSelection),t(e))}handleMove(e){let{activated:t,initialCoordinates:n,props:r}=this,{onMove:i,options:{activationConstraint:a}}=r;if(!n)return;let o=Cl(e)??J,s=yl(n,o);if(!t&&a){if(Nu(a)){if(a.tolerance!=null&&Tu(s,a.tolerance))return this.handleCancel();if(Tu(s,a.distance))return this.handleStart()}if(Pu(a)&&Tu(s,a.tolerance))return this.handleCancel();this.handlePending(a,s);return}e.cancelable&&e.preventDefault(),i(o)}handleEnd(){let{onAbort:e,onEnd:t}=this.props;this.detach(),this.activated||e(this.props.active),t()}handleCancel(){let{onAbort:e,onCancel:t}=this.props;this.detach(),this.activated||e(this.props.active),t()}handleKeydown(e){e.code===ku.Esc&&this.handleCancel()}removeTextSelection(){var e;(e=this.document.getSelection())==null||e.removeAllRanges()}},Iu={cancel:{name:`pointercancel`},move:{name:`pointermove`},end:{name:`pointerup`}},Lu=class extends Fu{constructor(e){let{event:t}=e,n=G(t.target);super(e,Iu,n)}};Lu.activators=[{eventName:`onPointerDown`,handler:(e,t)=>{let{nativeEvent:n}=e,{onActivation:r}=t;return!n.isPrimary||n.button!==0?!1:(r?.({event:n}),!0)}}];var Ru={move:{name:`mousemove`},end:{name:`mouseup`}},zu;(function(e){e[e.RightClick=2]=`RightClick`})(zu||={});var Bu=class extends Fu{constructor(e){super(e,Ru,G(e.event.target))}};Bu.activators=[{eventName:`onMouseDown`,handler:(e,t)=>{let{nativeEvent:n}=e,{onActivation:r}=t;return n.button===zu.RightClick?!1:(r?.({event:n}),!0)}}];var Vu={cancel:{name:`touchcancel`},move:{name:`touchmove`},end:{name:`touchend`}},Hu=class extends Fu{constructor(e){super(e,Vu)}static setup(){return window.addEventListener(Vu.move.name,e,{capture:!1,passive:!1}),function(){window.removeEventListener(Vu.move.name,e)};function e(){}}};Hu.activators=[{eventName:`onTouchStart`,handler:(e,t)=>{let{nativeEvent:n}=e,{onActivation:r}=t,{touches:i}=n;return i.length>1?!1:(r?.({event:n}),!0)}}];var Uu;(function(e){e[e.Pointer=0]=`Pointer`,e[e.DraggableRect=1]=`DraggableRect`})(Uu||={});var Wu;(function(e){e[e.TreeOrder=0]=`TreeOrder`,e[e.ReversedTreeOrder=1]=`ReversedTreeOrder`})(Wu||={});function Z(e){let{acceleration:t,activator:n=Uu.Pointer,canScroll:r,draggingRect:i,enabled:a,interval:o=5,order:s=Wu.TreeOrder,pointerCoordinates:c,scrollableAncestors:l,scrollableAncestorRects:u,delta:d,threshold:f}=e,p=Ku({delta:d,disabled:!a}),[m,h]=ul(),g=(0,_.useRef)({x:0,y:0}),v=(0,_.useRef)({x:0,y:0}),y=(0,_.useMemo)(()=>{switch(n){case Uu.Pointer:return c?{top:c.y,bottom:c.y,left:c.x,right:c.x}:null;case Uu.DraggableRect:return i}},[n,i,c]),b=(0,_.useRef)(null),x=(0,_.useCallback)(()=>{let e=b.current;if(!e)return;let t=g.current.x*v.current.x,n=g.current.y*v.current.y;e.scrollBy(t,n)},[]),S=(0,_.useMemo)(()=>s===Wu.TreeOrder?[...l].reverse():l,[s,l]);(0,_.useEffect)(()=>{if(!a||!l.length||!y){h();return}for(let e of S){if(r?.(e)===!1)continue;let n=u[l.indexOf(e)];if(!n)continue;let{direction:i,speed:a}=hu(e,n,y,t,f);for(let e of[`x`,`y`])p[e][i[e]]||(a[e]=0,i[e]=0);if(a.x>0||a.y>0){h(),b.current=e,m(x,o),g.current=a,v.current=i;return}}g.current={x:0,y:0},v.current={x:0,y:0},h()},[t,x,r,h,a,o,JSON.stringify(y),JSON.stringify(p),m,l,S,u,JSON.stringify(f)])}var Gu={x:{[du.Backward]:!1,[du.Forward]:!1},y:{[du.Backward]:!1,[du.Forward]:!1}};function Ku(e){let{delta:t,disabled:n}=e,r=ml(t);return fl(e=>{if(n||!r||!e)return Gu;let i={x:Math.sign(t.x-r.x),y:Math.sign(t.y-r.y)};return{x:{[du.Backward]:e.x[du.Backward]||i.x===-1,[du.Forward]:e.x[du.Forward]||i.x===1},y:{[du.Backward]:e.y[du.Backward]||i.y===-1,[du.Forward]:e.y[du.Forward]||i.y===1}}},[n,t,r])}function qu(e,t){let n=t==null?void 0:e.get(t),r=n?n.node.current:null;return fl(e=>t==null?null:r??e??null,[r,t])}function Ju(e,t){return(0,_.useMemo)(()=>e.reduce((e,n)=>{let{sensor:r}=n,i=r.activators.map(e=>({eventName:e.eventName,handler:t(e.handler,n)}));return[...e,...i]},[]),[e,t])}var Yu;(function(e){e[e.Always=0]=`Always`,e[e.BeforeDragging=1]=`BeforeDragging`,e[e.WhileDragging=2]=`WhileDragging`})(Yu||={});var Xu;(function(e){e.Optimized=`optimized`})(Xu||={});var Zu=new Map;function Qu(e,t){let{dragging:n,dependencies:r,config:i}=t,[a,o]=(0,_.useState)(null),{frequency:s,measure:c,strategy:l}=i,u=(0,_.useRef)(e),d=g(),f=dl(d),p=(0,_.useCallback)(function(e){e===void 0&&(e=[]),!f.current&&o(t=>t===null?e:t.concat(e.filter(e=>!t.includes(e))))},[f]),m=(0,_.useRef)(null),h=fl(t=>{if(d&&!n)return Zu;if(!t||t===Zu||u.current!==e||a!=null){let t=new Map;for(let n of e){if(!n)continue;if(a&&a.length>0&&!a.includes(n.id)&&n.rect.current){t.set(n.id,n.rect.current);continue}let e=n.node.current,r=e?new Su(c(e),e):null;n.rect.current=r,r&&t.set(n.id,r)}return t}return t},[e,a,n,d,c]);return(0,_.useEffect)(()=>{u.current=e},[e]),(0,_.useEffect)(()=>{d||p()},[n,d]),(0,_.useEffect)(()=>{a&&a.length>0&&o(null)},[JSON.stringify(a)]),(0,_.useEffect)(()=>{d||typeof s!=`number`||m.current!==null||(m.current=setTimeout(()=>{p(),m.current=null},s))},[s,d,p,...r]),{droppableRects:h,measureDroppableContainers:p,measuringScheduled:a!=null};function g(){switch(l){case Yu.Always:return!1;case Yu.BeforeDragging:return n;default:return!n}}}function $u(e,t){return fl(n=>e?n||(typeof t==`function`?t(e):e):null,[t,e])}function ed(e,t){return $u(e,t)}function td(e){let{callback:t,disabled:n}=e,r=ll(t),i=(0,_.useMemo)(()=>{if(n||typeof window>`u`||window.MutationObserver===void 0)return;let{MutationObserver:e}=window;return new e(r)},[r,n]);return(0,_.useEffect)(()=>()=>i?.disconnect(),[i]),i}function nd(e){let{callback:t,disabled:n}=e,r=ll(t),i=(0,_.useMemo)(()=>{if(n||typeof window>`u`||window.ResizeObserver===void 0)return;let{ResizeObserver:e}=window;return new e(r)},[n]);return(0,_.useEffect)(()=>()=>i?.disconnect(),[i]),i}function rd(e){return new Su(eu(e),e)}function id(e,t,n){t===void 0&&(t=rd);let[r,i]=(0,_.useState)(null);function a(){i(r=>{if(!e)return null;if(e.isConnected===!1)return r??n??null;let i=t(e);return JSON.stringify(r)===JSON.stringify(i)?r:i})}let o=td({callback(t){if(e)for(let n of t){let{type:t,target:r}=n;if(t===`childList`&&r instanceof HTMLElement&&r.contains(e)){a();break}}}}),s=nd({callback:a});return cl(()=>{a(),e?(s?.observe(e),o?.observe(document.body,{childList:!0,subtree:!0})):(s?.disconnect(),o?.disconnect())},[e]),r}function ad(e){return Jl(e,$u(e))}var od=[];function sd(e){let t=(0,_.useRef)(e),n=fl(n=>e?n&&n!==od&&e&&t.current&&e.parentNode===t.current.parentNode?n:au(e):od,[e]);return(0,_.useEffect)(()=>{t.current=e},[e]),n}function cd(e){let[t,n]=(0,_.useState)(null),r=(0,_.useRef)(e),i=(0,_.useCallback)(e=>{let t=su(e.target);t&&n(e=>e?(e.set(t,uu(t)),new Map(e)):null)},[]);return(0,_.useEffect)(()=>{let t=r.current;if(e!==t){a(t);let o=e.map(e=>{let t=su(e);return t?(t.addEventListener(`scroll`,i,{passive:!0}),[t,uu(t)]):null}).filter(e=>e!=null);n(o.length?new Map(o):null),r.current=e}return()=>{a(e),a(t)};function a(e){e.forEach(e=>{su(e)?.removeEventListener(`scroll`,i)})}},[i,e]),(0,_.useMemo)(()=>e.length?t?Array.from(t.values()).reduce((e,t)=>vl(e,t),J):_u(e):J,[e,t])}function ld(e,t){t===void 0&&(t=[]);let n=(0,_.useRef)(null);return(0,_.useEffect)(()=>{n.current=null},t),(0,_.useEffect)(()=>{let t=e!==J;t&&!n.current&&(n.current=e),!t&&n.current&&(n.current=null)},[e]),n.current?yl(e,n.current):J}function ud(e){(0,_.useEffect)(()=>{if(!nl)return;let t=e.map(e=>{let{sensor:t}=e;return t.setup==null?void 0:t.setup()});return()=>{for(let e of t)e?.()}},e.map(e=>{let{sensor:t}=e;return t}))}function dd(e,t){return(0,_.useMemo)(()=>e.reduce((e,n)=>{let{eventName:r,handler:i}=n;return e[r]=e=>{i(e,t)},e},{}),[e,t])}function fd(e){return(0,_.useMemo)(()=>e?nu(e):null,[e])}var pd=[];function md(e,t){t===void 0&&(t=eu);let[n]=e,r=fd(n?W(n):null),[i,a]=(0,_.useState)(pd);function o(){a(()=>e.length?e.map(e=>fu(e)?r:new Su(t(e),e)):pd)}let s=nd({callback:o});return cl(()=>{s?.disconnect(),o(),e.forEach(e=>s?.observe(e))},[e]),i}function hd(e){if(!e)return null;if(e.children.length>1)return e;let t=e.children[0];return ol(t)?t:e}function gd(e){let{measure:t}=e,[n,r]=(0,_.useState)(null),i=nd({callback:(0,_.useCallback)(e=>{for(let{target:n}of e)if(ol(n)){r(e=>{let r=t(n);return e?{...e,width:r.width,height:r.height}:r});break}},[t])}),[a,o]=pl((0,_.useCallback)(e=>{let n=hd(e);i?.disconnect(),n&&i?.observe(n),r(n?t(n):null)},[t,i]));return(0,_.useMemo)(()=>({nodeRef:a,rect:n,setRef:o}),[n,a,o])}var _d=[{sensor:Lu,options:{}},{sensor:Mu,options:{}}],vd={current:{}},yd={draggable:{measure:tu},droppable:{measure:tu,strategy:Yu.WhileDragging,frequency:Xu.Optimized},dragOverlay:{measure:eu}},Q=class extends Map{get(e){return e==null?void 0:super.get(e)??void 0}toArray(){return Array.from(this.values())}getEnabled(){return this.toArray().filter(e=>{let{disabled:t}=e;return!t})}getNodeFor(e){return this.get(e)?.node.current??void 0}},bd={activatorEvent:null,active:null,activeNode:null,activeNodeRect:null,collisions:null,containerNodeRect:null,draggableNodes:new Map,droppableRects:new Map,droppableContainers:new Q,over:null,dragOverlay:{nodeRef:{current:null},rect:null,setRef:Rl},scrollableAncestors:[],scrollableAncestorRects:[],measuringConfiguration:yd,measureDroppableContainers:Rl,windowRect:null,measuringScheduled:!1},xd={activatorEvent:null,activators:[],active:null,activeNodeRect:null,ariaDescribedById:{draggable:``},dispatch:Rl,draggableNodes:new Map,over:null,measureDroppableContainers:Rl},Sd=(0,_.createContext)(xd),Cd=(0,_.createContext)(bd);function wd(){return{draggable:{active:null,initialCoordinates:{x:0,y:0},nodes:new Map,translate:{x:0,y:0}},droppable:{containers:new Q}}}function Td(e,t){switch(t.type){case Ll.DragStart:return{...e,draggable:{...e.draggable,initialCoordinates:t.initialCoordinates,active:t.active}};case Ll.DragMove:return e.draggable.active==null?e:{...e,draggable:{...e.draggable,translate:{x:t.coordinates.x-e.draggable.initialCoordinates.x,y:t.coordinates.y-e.draggable.initialCoordinates.y}}};case Ll.DragEnd:case Ll.DragCancel:return{...e,draggable:{...e.draggable,active:null,initialCoordinates:{x:0,y:0},translate:{x:0,y:0}}};case Ll.RegisterDroppable:{let{element:n}=t,{id:r}=n,i=new Q(e.droppable.containers);return i.set(r,n),{...e,droppable:{...e.droppable,containers:i}}}case Ll.SetDroppableDisabled:{let{id:n,key:r,disabled:i}=t,a=e.droppable.containers.get(n);if(!a||r!==a.key)return e;let o=new Q(e.droppable.containers);return o.set(n,{...a,disabled:i}),{...e,droppable:{...e.droppable,containers:o}}}case Ll.UnregisterDroppable:{let{id:n,key:r}=t,i=e.droppable.containers.get(n);if(!i||r!==i.key)return e;let a=new Q(e.droppable.containers);return a.delete(n),{...e,droppable:{...e.droppable,containers:a}}}default:return e}}function Ed(e){let{disabled:t}=e,{active:n,activatorEvent:r,draggableNodes:i}=(0,_.useContext)(Sd),a=ml(r),o=ml(n?.id);return(0,_.useEffect)(()=>{if(!t&&!r&&a&&o!=null){if(!xl(a)||document.activeElement===a.target)return;let e=i.get(o);if(!e)return;let{activatorNode:t,node:n}=e;if(!t.current&&!n.current)return;requestAnimationFrame(()=>{for(let e of[t.current,n.current]){if(!e)continue;let t=El(e);if(t){t.focus();break}}})}},[r,t,i,o,a]),null}function Dd(e,t){let{transform:n,...r}=t;return e!=null&&e.length?e.reduce((e,t)=>t({transform:e,...r}),n):n}function Od(e){return(0,_.useMemo)(()=>({draggable:{...yd.draggable,...e?.draggable},droppable:{...yd.droppable,...e?.droppable},dragOverlay:{...yd.dragOverlay,...e?.dragOverlay}}),[e?.draggable,e?.droppable,e?.dragOverlay])}function kd(e){let{activeNode:t,measure:n,initialRect:r,config:i=!0}=e,a=(0,_.useRef)(!1),{x:o,y:s}=typeof i==`boolean`?{x:i,y:i}:i;cl(()=>{if(!o&&!s||!t){a.current=!1;return}if(a.current||!r)return;let e=t?.node.current;if(!e||e.isConnected===!1)return;let i=Jl(n(e),r);if(o||(i.x=0),s||(i.y=0),a.current=!0,Math.abs(i.x)>0||Math.abs(i.y)>0){let t=ou(e);t&&t.scrollBy({top:i.y,left:i.x})}},[t,o,s,r,n])}var Ad=(0,_.createContext)({...J,scaleX:1,scaleY:1}),jd;(function(e){e[e.Uninitialized=0]=`Uninitialized`,e[e.Initializing=1]=`Initializing`,e[e.Initialized=2]=`Initialized`})(jd||={});var Md=(0,_.memo)(function(e){let{id:t,accessibility:n,autoScroll:r=!0,children:i,sensors:a=_d,collisionDetection:o=Kl,measuring:s,modifiers:c,...l}=e,[u,d]=(0,_.useReducer)(Td,void 0,wd),[f,p]=Nl(),[m,h]=(0,_.useState)(jd.Uninitialized),g=m===jd.Initialized,{draggable:{active:v,nodes:y,translate:b},droppable:{containers:x}}=u,S=v==null?null:y.get(v),C=(0,_.useRef)({initial:null,translated:null}),w=(0,_.useMemo)(()=>v==null?null:{id:v,data:S?.data??vd,rect:C},[v,S]),T=(0,_.useRef)(null),[E,D]=(0,_.useState)(null),[O,k]=(0,_.useState)(null),A=dl(l,Object.values(l)),j=gl(`DndDescribedBy`,t),M=(0,_.useMemo)(()=>x.getEnabled(),[x]),N=Od(s),{droppableRects:P,measureDroppableContainers:ee,measuringScheduled:F}=Qu(M,{dragging:g,dependencies:[b.x,b.y],config:N.droppable}),I=qu(y,v),te=(0,_.useMemo)(()=>O?Cl(O):null,[O]),L=Me(),ne=ed(I,N.draggable.measure);kd({activeNode:v==null?null:y.get(v),config:L.layoutShiftCompensation,initialRect:ne,measure:N.draggable.measure});let re=id(I,N.draggable.measure,ne),ie=id(I?I.parentElement:null),ae=(0,_.useRef)({activatorEvent:null,active:null,activeNode:I,collisionRect:null,collisions:null,droppableRects:P,draggableNodes:y,draggingNode:null,draggingNodeRect:null,droppableContainers:x,over:null,scrollableAncestors:[],scrollAdjustedTranslate:null}),oe=x.getNodeFor(ae.current.over?.id),se=gd({measure:N.dragOverlay.measure}),ce=se.nodeRef.current??I,le=g?se.rect??re:null,ue=!!(se.nodeRef.current&&se.rect),de=ad(ue?null:re),fe=fd(ce?W(ce):null),pe=sd(g?oe??I:null),me=md(pe),he=Dd(c,{transform:{x:b.x-de.x,y:b.y-de.y,scaleX:1,scaleY:1},activatorEvent:O,active:w,activeNodeRect:re,containerNodeRect:ie,draggingNodeRect:le,over:ae.current.over,overlayNodeRect:se.rect,scrollableAncestors:pe,scrollableAncestorRects:me,windowRect:fe}),ge=te?vl(te,b):null,_e=cd(pe),ve=ld(_e),ye=ld(_e,[re]),be=vl(he,ve),xe=le?Xl(le,he):null,Se=w&&xe?o({active:w,collisionRect:xe,droppableRects:P,droppableContainers:M,pointerCoordinates:ge}):null,Ce=Vl(Se,`id`),[we,Te]=(0,_.useState)(null),Ee=ql(ue?he:vl(he,ye),we?.rect??null,re),De=(0,_.useRef)(null),Oe=(0,_.useCallback)((e,t)=>{let{sensor:n,options:r}=t;if(T.current==null)return;let i=y.get(T.current);if(!i)return;let a=e.nativeEvent;De.current=new n({active:T.current,activeNode:i,event:a,options:r,context:ae,onAbort(e){if(!y.get(e))return;let{onDragAbort:t}=A.current,n={id:e};t?.(n),f({type:`onDragAbort`,event:n})},onPending(e,t,n,r){if(!y.get(e))return;let{onDragPending:i}=A.current,a={id:e,constraint:t,initialCoordinates:n,offset:r};i?.(a),f({type:`onDragPending`,event:a})},onStart(e){let t=T.current;if(t==null)return;let n=y.get(t);if(!n)return;let{onDragStart:r}=A.current,i={activatorEvent:a,active:{id:t,data:n.data,rect:C}};(0,el.unstable_batchedUpdates)(()=>{r?.(i),h(jd.Initializing),d({type:Ll.DragStart,initialCoordinates:e,active:t}),f({type:`onDragStart`,event:i}),D(De.current),k(a)})},onMove(e){d({type:Ll.DragMove,coordinates:e})},onEnd:o(Ll.DragEnd),onCancel:o(Ll.DragCancel)});function o(e){return async function(){let{active:t,collisions:n,over:r,scrollAdjustedTranslate:i}=ae.current,o=null;if(t&&i){let{cancelDrop:s}=A.current;o={activatorEvent:a,active:t,collisions:n,delta:i,over:r},e===Ll.DragEnd&&typeof s==`function`&&await Promise.resolve(s(o))&&(e=Ll.DragCancel)}T.current=null,(0,el.unstable_batchedUpdates)(()=>{d({type:e}),h(jd.Uninitialized),Te(null),D(null),k(null),De.current=null;let t=e===Ll.DragEnd?`onDragEnd`:`onDragCancel`;if(o){let e=A.current[t];e?.(o),f({type:t,event:o})}})}}},[y]),ke=Ju(a,(0,_.useCallback)((e,t)=>(n,r)=>{let i=n.nativeEvent,a=y.get(r);if(T.current!==null||!a||i.dndKit||i.defaultPrevented)return;let o={active:a};e(n,t.options,o)===!0&&(i.dndKit={capturedBy:t.sensor},T.current=r,Oe(n,t))},[y,Oe]));ud(a),cl(()=>{re&&m===jd.Initializing&&h(jd.Initialized)},[re,m]),(0,_.useEffect)(()=>{let{onDragMove:e}=A.current,{active:t,activatorEvent:n,collisions:r,over:i}=ae.current;if(!t||!n)return;let a={active:t,activatorEvent:n,collisions:r,delta:{x:be.x,y:be.y},over:i};(0,el.unstable_batchedUpdates)(()=>{e?.(a),f({type:`onDragMove`,event:a})})},[be.x,be.y]),(0,_.useEffect)(()=>{let{active:e,activatorEvent:t,collisions:n,droppableContainers:r,scrollAdjustedTranslate:i}=ae.current;if(!e||T.current==null||!t||!i)return;let{onDragOver:a}=A.current,o=r.get(Ce),s=o&&o.rect.current?{id:o.id,rect:o.rect.current,data:o.data,disabled:o.disabled}:null,c={active:e,activatorEvent:t,collisions:n,delta:{x:i.x,y:i.y},over:s};(0,el.unstable_batchedUpdates)(()=>{Te(s),a?.(c),f({type:`onDragOver`,event:c})})},[Ce]),cl(()=>{ae.current={activatorEvent:O,active:w,activeNode:I,collisionRect:xe,collisions:Se,droppableRects:P,draggableNodes:y,draggingNode:ce,draggingNodeRect:le,droppableContainers:x,over:we,scrollableAncestors:pe,scrollAdjustedTranslate:be},C.current={initial:le,translated:xe}},[w,I,Se,xe,y,ce,le,P,x,we,pe,be]),Z({...L,delta:b,draggingRect:xe,pointerCoordinates:ge,scrollableAncestors:pe,scrollableAncestorRects:me});let Ae=(0,_.useMemo)(()=>({active:w,activeNode:I,activeNodeRect:re,activatorEvent:O,collisions:Se,containerNodeRect:ie,dragOverlay:se,draggableNodes:y,droppableContainers:x,droppableRects:P,over:we,measureDroppableContainers:ee,scrollableAncestors:pe,scrollableAncestorRects:me,measuringConfiguration:N,measuringScheduled:F,windowRect:fe}),[w,I,re,O,Se,ie,se,y,x,P,we,ee,pe,me,N,F,fe]),je=(0,_.useMemo)(()=>({activatorEvent:O,activators:ke,active:w,activeNodeRect:re,ariaDescribedById:{draggable:j},dispatch:d,draggableNodes:y,over:we,measureDroppableContainers:ee}),[O,ke,w,re,d,j,y,we,ee]);return _.createElement(jl.Provider,{value:p},_.createElement(Sd.Provider,{value:je},_.createElement(Cd.Provider,{value:Ae},_.createElement(Ad.Provider,{value:Ee},i)),_.createElement(Ed,{disabled:n?.restoreFocus===!1})),_.createElement(Il,{...n,hiddenTextDescribedById:j}));function Me(){let e=E?.autoScrollEnabled===!1,t=typeof r==`object`?r.enabled===!1:r===!1,n=g&&!e&&!t;return typeof r==`object`?{...r,enabled:n}:{enabled:n}}}),$=(0,_.createContext)(null),Nd=`button`,Pd=`Draggable`;function Fd(e){let{id:t,data:n,disabled:r=!1,attributes:i}=e,a=gl(Pd),{activators:o,activatorEvent:s,active:c,activeNodeRect:l,ariaDescribedById:u,draggableNodes:d,over:f}=(0,_.useContext)(Sd),{role:p=Nd,roleDescription:m=`draggable`,tabIndex:h=0}=i??{},g=c?.id===t,v=(0,_.useContext)(g?Ad:$),[y,b]=pl(),[x,S]=pl(),C=dd(o,t),w=dl(n);return cl(()=>(d.set(t,{id:t,key:a,node:y,activatorNode:x,data:w}),()=>{let e=d.get(t);e&&e.key===a&&d.delete(t)}),[d,t]),{active:c,activatorEvent:s,activeNodeRect:l,attributes:(0,_.useMemo)(()=>({role:p,tabIndex:h,"aria-disabled":r,"aria-pressed":g&&p===Nd?!0:void 0,"aria-roledescription":m,"aria-describedby":u.draggable}),[r,p,h,g,m,u.draggable]),isDragging:g,listeners:r?void 0:C,node:y,over:f,setNodeRef:b,setActivatorNodeRef:S,transform:v}}function Id(){return(0,_.useContext)(Cd)}var Ld=`Droppable`,Rd={timeout:25};function zd(e){let{data:t,disabled:n=!1,id:r,resizeObserverConfig:i}=e,a=gl(Ld),{active:o,dispatch:s,over:c,measureDroppableContainers:l}=(0,_.useContext)(Sd),u=(0,_.useRef)({disabled:n}),d=(0,_.useRef)(!1),f=(0,_.useRef)(null),p=(0,_.useRef)(null),{disabled:m,updateMeasurementsFor:h,timeout:g}={...Rd,...i},v=dl(h??r),y=nd({callback:(0,_.useCallback)(()=>{if(!d.current){d.current=!0;return}p.current!=null&&clearTimeout(p.current),p.current=setTimeout(()=>{l(Array.isArray(v.current)?v.current:[v.current]),p.current=null},g)},[g]),disabled:m||!o}),[b,x]=pl((0,_.useCallback)((e,t)=>{y&&(t&&(y.unobserve(t),d.current=!1),e&&y.observe(e))},[y])),S=dl(t);return(0,_.useEffect)(()=>{!y||!b.current||(y.disconnect(),d.current=!1,y.observe(b.current))},[b,y]),(0,_.useEffect)(()=>(s({type:Ll.RegisterDroppable,element:{id:r,key:a,disabled:n,node:b,rect:f,data:S}}),()=>s({type:Ll.UnregisterDroppable,key:a,id:r})),[r]),(0,_.useEffect)(()=>{n!==u.current.disabled&&(s({type:Ll.SetDroppableDisabled,id:r,key:a,disabled:n}),u.current.disabled=n)},[r,a,n,s]),{active:o,rect:f,isOver:c?.id===r,node:b,over:c,setNodeRef:x}}function Bd(e,t,n){let r=e.slice();return r.splice(n<0?r.length+n:n,0,r.splice(t,1)[0]),r}function Vd(e,t){return e.reduce((e,n,r)=>{let i=t.get(n);return i&&(e[r]=i),e},Array(e.length))}function Hd(e){return e!==null&&e>=0}function Ud(e,t){if(e===t)return!0;if(e.length!==t.length)return!1;for(let n=0;n<e.length;n++)if(e[n]!==t[n])return!1;return!0}function Wd(e){return typeof e==`boolean`?{draggable:e,droppable:e}:e}var Gd=e=>{let{rects:t,activeIndex:n,overIndex:r,index:i}=e,a=Bd(t,r,n),o=t[i],s=a[i];return!s||!o?null:{x:s.left-o.left,y:s.top-o.top,scaleX:s.width/o.width,scaleY:s.height/o.height}},Kd={scaleX:1,scaleY:1},qd=e=>{let{activeIndex:t,activeNodeRect:n,index:r,rects:i,overIndex:a}=e,o=i[t]??n;if(!o)return null;if(r===t){let e=i[a];return e?{x:0,y:t<a?e.top+e.height-(o.top+o.height):e.top-o.top,...Kd}:null}let s=Jd(i,r,t);return r>t&&r<=a?{x:0,y:-o.height-s,...Kd}:r<t&&r>=a?{x:0,y:o.height+s,...Kd}:{x:0,y:0,...Kd}};function Jd(e,t,n){let r=e[t],i=e[t-1],a=e[t+1];return r?n<t?i?r.top-(i.top+i.height):a?a.top-(r.top+r.height):0:a?a.top-(r.top+r.height):i?r.top-(i.top+i.height):0:0}var Yd=`Sortable`,Xd=_.createContext({activeIndex:-1,containerId:Yd,disableTransforms:!1,items:[],overIndex:-1,useDragOverlay:!1,sortedRects:[],strategy:Gd,disabled:{draggable:!1,droppable:!1}});function Zd(e){let{children:t,id:n,items:r,strategy:i=Gd,disabled:a=!1}=e,{active:o,dragOverlay:s,droppableRects:c,over:l,measureDroppableContainers:u}=Id(),d=gl(Yd,n),f=s.rect!==null,p=(0,_.useMemo)(()=>r.map(e=>typeof e==`object`&&`id`in e?e.id:e),[r]),m=o!=null,h=o?p.indexOf(o.id):-1,g=l?p.indexOf(l.id):-1,v=(0,_.useRef)(p),y=!Ud(p,v.current),b=g!==-1&&h===-1||y,x=Wd(a);cl(()=>{y&&m&&u(p)},[y,p,m,u]),(0,_.useEffect)(()=>{v.current=p},[p]);let S=(0,_.useMemo)(()=>({activeIndex:h,containerId:d,disabled:x,disableTransforms:b,items:p,overIndex:g,useDragOverlay:f,sortedRects:Vd(p,c),strategy:i}),[h,d,x.draggable,x.droppable,b,p,g,c,f,i]);return _.createElement(Xd.Provider,{value:S},t)}var Qd=e=>{let{id:t,items:n,activeIndex:r,overIndex:i}=e;return Bd(n,r,i).indexOf(t)},$d=e=>{let{containerId:t,isSorting:n,wasDragging:r,index:i,items:a,newIndex:o,previousItems:s,previousContainerId:c,transition:l}=e;return!l||!r||s!==a&&i===o?!1:n?!0:o!==i&&t===c},ef={duration:200,easing:`ease`},tf=`transform`,nf=wl.Transition.toString({property:tf,duration:0,easing:`linear`}),rf={roleDescription:`sortable`};function af(e){let{disabled:t,index:n,node:r,rect:i}=e,[a,o]=(0,_.useState)(null),s=(0,_.useRef)(n);return cl(()=>{if(!t&&n!==s.current&&r.current){let e=i.current;if(e){let t=eu(r.current,{ignoreTransform:!0}),n={x:e.left-t.left,y:e.top-t.top,scaleX:e.width/t.width,scaleY:e.height/t.height};(n.x||n.y)&&o(n)}}n!==s.current&&(s.current=n)},[t,n,r,i]),(0,_.useEffect)(()=>{a&&o(null)},[a]),a}function of(e){let{animateLayoutChanges:t=$d,attributes:n,disabled:r,data:i,getNewIndex:a=Qd,id:o,strategy:s,resizeObserverConfig:c,transition:l=ef}=e,{items:u,containerId:d,activeIndex:f,disabled:p,disableTransforms:m,sortedRects:h,overIndex:g,useDragOverlay:v,strategy:y}=(0,_.useContext)(Xd),b=sf(r,p),x=u.indexOf(o),S=(0,_.useMemo)(()=>({sortable:{containerId:d,index:x,items:u},...i}),[d,i,x,u]),C=(0,_.useMemo)(()=>u.slice(u.indexOf(o)),[u,o]),{rect:w,node:T,isOver:E,setNodeRef:D}=zd({id:o,data:S,disabled:b.droppable,resizeObserverConfig:{updateMeasurementsFor:C,...c}}),{active:O,activatorEvent:k,activeNodeRect:A,attributes:j,setNodeRef:M,listeners:N,isDragging:P,over:ee,setActivatorNodeRef:F,transform:I}=Fd({id:o,data:S,attributes:{...rf,...n},disabled:b.draggable}),te=tl(D,M),L=!!O,ne=L&&!m&&Hd(f)&&Hd(g),re=!v&&P,ie=ne?(re&&ne?I:null)??(s??y)({rects:h,activeNodeRect:A,activeIndex:f,overIndex:g,index:x}):null,ae=Hd(f)&&Hd(g)?a({id:o,items:u,activeIndex:f,overIndex:g}):x,oe=O?.id,se=(0,_.useRef)({activeId:oe,items:u,newIndex:ae,containerId:d}),ce=u!==se.current.items,le=t({active:O,containerId:d,isDragging:P,isSorting:L,id:o,index:x,items:u,newIndex:se.current.newIndex,previousItems:se.current.items,previousContainerId:se.current.containerId,transition:l,wasDragging:se.current.activeId!=null}),ue=af({disabled:!le,index:x,node:T,rect:w});return(0,_.useEffect)(()=>{L&&se.current.newIndex!==ae&&(se.current.newIndex=ae),d!==se.current.containerId&&(se.current.containerId=d),u!==se.current.items&&(se.current.items=u)},[L,ae,d,u]),(0,_.useEffect)(()=>{if(oe===se.current.activeId)return;if(oe!=null&&se.current.activeId==null){se.current.activeId=oe;return}let e=setTimeout(()=>{se.current.activeId=oe},50);return()=>clearTimeout(e)},[oe]),{active:O,activeIndex:f,attributes:j,data:S,rect:w,index:x,newIndex:ae,items:u,isOver:E,isSorting:L,isDragging:P,listeners:N,node:T,overIndex:g,over:ee,setNodeRef:te,setActivatorNodeRef:F,setDroppableNodeRef:D,setDraggableNodeRef:M,transform:ue??ie,transition:de()};function de(){if(ue||ce&&se.current.newIndex===x)return nf;if(!(re&&!xl(k)||!l)&&(L||le))return wl.Transition.toString({...l,property:tf})}}function sf(e,t){return typeof e==`boolean`?{draggable:e,droppable:!1}:{draggable:e?.draggable??t.draggable,droppable:e?.droppable??t.droppable}}function cf(e){if(!e)return!1;let t=e.data.current;return!!(t&&`sortable`in t&&typeof t.sortable==`object`&&`containerId`in t.sortable&&`items`in t.sortable&&`index`in t.sortable)}var lf=[ku.Down,ku.Right,ku.Up,ku.Left],uf=(e,t)=>{let{context:{active:n,collisionRect:r,droppableRects:i,droppableContainers:a,over:o,scrollableAncestors:s}}=t;if(lf.includes(e.code)){if(e.preventDefault(),!n||!r)return;let t=[];a.getEnabled().forEach(n=>{if(!n||n!=null&&n.disabled)return;let a=i.get(n.id);if(a)switch(e.code){case ku.Down:r.top<a.top&&t.push(n);break;case ku.Up:r.top>a.top&&t.push(n);break;case ku.Left:r.left>a.left&&t.push(n);break;case ku.Right:r.left<a.left&&t.push(n);break}});let c=Wl({active:n,collisionRect:r,droppableRects:i,droppableContainers:t,pointerCoordinates:null}),l=Vl(c,`id`);if(l===o?.id&&c.length>1&&(l=c[1].id),l!=null){let e=a.get(n.id),t=a.get(l),o=t?i.get(t.id):null,c=t?.node.current;if(c&&o&&e&&t){let n=au(c).some((e,t)=>s[t]!==e),i=df(e,t),a=ff(e,t),l=n||!i?{x:0,y:0}:{x:a?r.width-o.width:0,y:a?r.height-o.height:0},u={x:o.left,y:o.top};return l.x&&l.y?u:yl(u,l)}}}};function df(e,t){return!cf(e)||!cf(t)?!1:e.data.current.sortable.containerId===t.data.current.sortable.containerId}function ff(e,t){return!cf(e)||!cf(t)||!df(e,t)?!1:e.data.current.sortable.index<t.data.current.sortable.index}var pf=300,mf=5*1024*1024,hf=10*1024*1024;function gf(e,t){return(e??``)!==(t??``)}var _f=`w-full bg-surface-low border border-ghost rounded-md px-3 py-1.5 text-sm text-on-surface placeholder:text-outline`;function vf(e,t=``){return[_f,e?`border-l-2 border-amber-500`:``,t].filter(Boolean).join(` `)}function yf({id:e,title:t,meta:n,defaultOpen:r=!1,children:i}){let[a,o]=(0,_.useState)(r);return(0,R.jsxs)(`section`,{"data-testid":`editrail-section-${e}`,className:`border-b border-ghost`,children:[(0,R.jsxs)(`button`,{type:`button`,"data-testid":`editrail-section-toggle-${e}`,onClick:()=>o(e=>!e),"aria-expanded":a,className:`w-full flex items-center justify-between px-4 py-3 text-left hover:bg-surface-low transition-colors`,children:[(0,R.jsxs)(`span`,{className:`font-mono text-[11px] uppercase tracking-wider text-on-surface-variant`,children:[t,n?(0,R.jsx)(`span`,{className:`ml-2 text-outline normal-case`,children:n}):null]}),(0,R.jsx)(`span`,{className:`text-on-surface-variant text-xs`,"aria-hidden":`true`,children:a?`−`:`+`})]}),a?(0,R.jsx)(`div`,{"data-testid":`editrail-section-body-${e}`,className:`pl-3 ml-4 mr-4 mb-3 border-l border-ghost space-y-3`,children:(0,R.jsx)(`div`,{className:`pl-3`,children:i})}):null]})}function bf({htmlFor:e,children:t}){return(0,R.jsx)(`label`,{htmlFor:e,className:`font-mono text-[11px] uppercase tracking-wider text-on-surface-variant block mb-1`,children:t})}function xf({id:e,field:t,label:n,type:r=`text`,placeholder:i,maxLength:a,multiline:o=!1,rows:s=3}){let{state:c,dispatch:l}=zc(),u=c.profile[t]??``,d=c.publishState?.targets[`heyi.am`]?.lastPublishedProfile[t]??void 0,f=(0,_.useRef)(c.profile);(0,_.useEffect)(()=>{f.current=c.profile},[c.profile]);let p=(0,_.useRef)(null);(0,_.useEffect)(()=>()=>{p.current!==null&&(clearTimeout(p.current),p.current=null)},[]);let m=gf(u,d);function h(e){let n=e===``?void 0:e;l({type:`UPDATE_PROFILE_FIELD`,field:t,value:n}),p.current!==null&&clearTimeout(p.current),p.current=setTimeout(()=>{p.current=null,_r({...f.current,[t]:n}).then(()=>{l({type:`PROFILE_SAVED`})}).catch(e=>{console.error(`[EditRail] Failed to persist profile field`,t,e)})},pf)}return o?(0,R.jsxs)(`div`,{children:[(0,R.jsx)(bf,{htmlFor:e,children:n}),(0,R.jsx)(`textarea`,{id:e,"data-testid":`editrail-field-${t}`,value:u,onChange:e=>h(e.target.value),placeholder:i,maxLength:a,rows:s,className:vf(m,`resize-y`)})]}):(0,R.jsxs)(`div`,{children:[(0,R.jsx)(bf,{htmlFor:e,children:n}),(0,R.jsx)(`input`,{id:e,type:r,"data-testid":`editrail-field-${t}`,value:u,onChange:e=>h(e.target.value),placeholder:i,maxLength:a,className:vf(m)})]})}function Sf(){let{state:e,dispatch:t}=zc(),n=e.profile.photoBase64,r=e.publishState?.targets[`heyi.am`]?.lastPublishedProfile.photoBase64,i=gf(n,r),a=(0,_.useRef)(e.profile);(0,_.useEffect)(()=>{a.current=e.profile},[e.profile]);function o(e){_r(e).then(()=>{t({type:`PROFILE_SAVED`})}).catch(e=>{console.error(`[EditRail] Failed to persist photo`,e)})}function s(e){let n=e.target.files?.[0];if(!n)return;if(n.size>mf){alert(`Photo must be under 5MB`),e.target.value=``;return}let r=new FileReader;r.onload=()=>{let e=r.result;t({type:`UPDATE_PROFILE_FIELD`,field:`photoBase64`,value:e}),o({...a.current,photoBase64:e})},r.readAsDataURL(n),e.target.value=``}function c(){t({type:`UPDATE_PROFILE_FIELD`,field:`photoBase64`,value:void 0}),o({...a.current,photoBase64:void 0})}return(0,R.jsxs)(`div`,{children:[(0,R.jsx)(bf,{children:`Profile photo`}),(0,R.jsxs)(`div`,{className:i?`border-l-2 border-amber-500 pl-2 flex items-center gap-3`:`flex items-center gap-3`,children:[n?(0,R.jsx)(`div`,{className:`relative w-14 h-14 rounded-full overflow-hidden border border-ghost shrink-0`,children:(0,R.jsx)(`img`,{src:n,alt:`Profile`,className:`w-full h-full object-cover`})}):(0,R.jsx)(`div`,{className:`w-14 h-14 rounded-full bg-surface-low border border-ghost shrink-0 flex items-center justify-center`,children:(0,R.jsx)(`span`,{className:`text-on-surface-variant text-[10px]`,children:`No photo`})}),(0,R.jsxs)(`label`,{className:`text-xs font-mono text-primary hover:underline cursor-pointer`,children:[n?`Change photo`:`Upload photo`,(0,R.jsx)(`input`,{type:`file`,accept:`image/png,image/jpeg,image/webp`,className:`hidden`,"data-testid":`editrail-field-photoBase64`,onChange:s})]}),n?(0,R.jsx)(`button`,{type:`button`,onClick:c,className:`text-xs text-on-surface-variant hover:text-on-surface transition-colors`,children:`Remove`}):null]})]})}function Cf(){let{state:e,dispatch:t}=zc(),n=e.profile.resumeBase64,r=e.profile.resumeFilename,i=e.publishState?.targets[`heyi.am`]?.lastPublishedProfile.resumeBase64,a=gf(n,i),o=(0,_.useRef)(e.profile);(0,_.useEffect)(()=>{o.current=e.profile},[e.profile]);function s(e){_r(e).then(()=>{t({type:`PROFILE_SAVED`})}).catch(e=>{console.error(`[EditRail] Failed to persist resume`,e)})}function c(e){let n=e.target.files?.[0];if(!n)return;if(n.size>hf){alert(`Resume must be under 10MB`),e.target.value=``;return}let r=new FileReader;r.onload=()=>{let e=r.result;t({type:`UPDATE_PROFILE_FIELD`,field:`resumeBase64`,value:e}),t({type:`UPDATE_PROFILE_FIELD`,field:`resumeFilename`,value:n.name}),s({...o.current,resumeBase64:e,resumeFilename:n.name})},r.readAsDataURL(n),e.target.value=``}function l(){t({type:`UPDATE_PROFILE_FIELD`,field:`resumeBase64`,value:void 0}),t({type:`UPDATE_PROFILE_FIELD`,field:`resumeFilename`,value:void 0}),s({...o.current,resumeBase64:void 0,resumeFilename:void 0})}return(0,R.jsxs)(`div`,{children:[(0,R.jsx)(bf,{children:`Resume (PDF)`}),(0,R.jsxs)(`div`,{className:a?`border-l-2 border-amber-500 pl-2 flex items-center gap-3`:`flex items-center gap-3`,children:[n?(0,R.jsx)(`span`,{className:`font-mono text-xs text-on-surface truncate max-w-[180px]`,children:r??`resume.pdf`}):(0,R.jsx)(`span`,{className:`text-xs text-on-surface-variant`,children:`No resume`}),(0,R.jsxs)(`label`,{className:`text-xs font-mono text-primary hover:underline cursor-pointer`,children:[n?`Replace`:`Upload PDF`,(0,R.jsx)(`input`,{type:`file`,accept:`application/pdf`,className:`hidden`,"data-testid":`editrail-field-resumeBase64`,onChange:c})]}),n?(0,R.jsx)(`button`,{type:`button`,onClick:l,className:`text-xs text-on-surface-variant hover:text-on-surface transition-colors`,children:`Remove`}):null]})]})}function wf({projectId:e,title:t,included:n,onToggle:r}){let{attributes:i,listeners:a,setNodeRef:o,transform:s,transition:c,isDragging:l}=of({id:e});return(0,R.jsxs)(`div`,{ref:o,style:{transform:wl.Transform.toString(s),transition:c,opacity:l?.5:1},"data-testid":`editrail-project-row-${e}`,className:`group flex items-center gap-2 py-1.5 px-1 hover:bg-surface-low rounded-sm`,children:[(0,R.jsx)(`button`,{type:`button`,"aria-label":`Drag ${t}`,"data-testid":`editrail-project-handle-${e}`,className:`opacity-0 group-hover:opacity-100 transition-opacity cursor-grab text-on-surface-variant text-xs font-mono px-1`,...i,...a,children:`::`}),(0,R.jsx)(`input`,{type:`checkbox`,checked:n,"data-testid":`editrail-project-checkbox-${e}`,onChange:()=>r(e),className:`shrink-0`}),(0,R.jsx)(`span`,{className:`text-sm truncate ${n?`text-on-surface`:`text-on-surface-variant`}`,children:t})]})}function Tf(){let{state:e,dispatch:t}=zc(),[n,r]=(0,_.useState)({}),i=(0,_.useRef)(e.profile),a=(0,_.useRef)(e.projects);(0,_.useEffect)(()=>{i.current=e.profile},[e.profile]),(0,_.useEffect)(()=>{a.current=e.projects},[e.projects]);let o=(0,_.useRef)(null);(0,_.useEffect)(()=>()=>{o.current!==null&&(clearTimeout(o.current),o.current=null)},[]);function s(){o.current!==null&&clearTimeout(o.current),o.current=setTimeout(()=>{o.current=null,_r({...i.current,projectsOnPortfolio:a.current.slice().sort((e,t)=>e.order-t.order).map((e,t)=>({projectId:e.projectId,included:e.included,order:t}))}).then(()=>{t({type:`BUMP_REFRESH`})}).catch(e=>{console.error(`[EditRail] Failed to persist projectsOnPortfolio`,e)})},pf)}(0,_.useEffect)(()=>{let e=!1;return Jn().then(t=>{if(e)return;let n={};for(let e of t)n[e.dirName]=e.name;r(n)}).catch(()=>{}),()=>{e=!0}},[]);let c=(0,_.useMemo)(()=>e.projects.slice().sort((e,t)=>e.order-t.order),[e.projects]),l=`${c.filter(e=>e.included).length} of ${c.length}`,u=q(K(Lu),K(Mu,{coordinateGetter:uf}));function d(e){let{active:n,over:r}=e;if(!r||n.id===r.id)return;let i=c.map(e=>e.projectId),a=i.indexOf(String(n.id)),o=i.indexOf(String(r.id));a<0||o<0||(t({type:`REORDER_PROJECT`,projectId:String(n.id),newIndex:o}),s())}function f(e){t({type:`TOGGLE_PROJECT_INCLUDED`,projectId:e}),s()}return(0,R.jsx)(yf,{id:`projects`,title:`Projects on portfolio`,meta:`· ${l}`,children:c.length===0?(0,R.jsx)(`p`,{className:`text-xs text-on-surface-variant`,children:`No projects yet.`}):(0,R.jsx)(Md,{sensors:u,collisionDetection:Ul,onDragEnd:d,children:(0,R.jsx)(Zd,{items:c.map(e=>e.projectId),strategy:qd,children:(0,R.jsx)(`div`,{"data-testid":`editrail-projects-list`,children:c.map(e=>(0,R.jsx)(wf,{projectId:e.projectId,title:n[e.projectId]??e.projectId,included:e.included,onToggle:f},e.projectId))})})})})}function Ef(){let[e,t]=(0,_.useState)(`editorial`),[n,r]=(0,_.useState)(!1);(0,_.useEffect)(()=>{let e=!1;return mr().then(n=>{e||t(n.template)}).catch(()=>{}),()=>{e=!0}},[]);let i=async n=>{r(!1);let i=e;t(n);try{await hr(n)}catch{t(i)}};return(0,R.jsxs)(yf,{id:`template`,title:`Template`,children:[(0,R.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,R.jsx)(`span`,{"data-testid":`editrail-template-pill`,className:`font-mono text-xs px-2 py-1 rounded-sm bg-surface-low border border-ghost text-on-surface`,children:e}),(0,R.jsx)(`button`,{type:`button`,"data-testid":`editrail-template-change`,className:`text-xs font-mono text-primary hover:underline`,onClick:()=>r(!0),children:`Change template`})]}),n&&(0,R.jsx)(Cc,{mode:`modal`,onClose:()=>r(!1),onSelectTemplate:i})]})}function Df(){return(0,R.jsxs)(`aside`,{"data-testid":`portfolio-editrail`,className:`w-[360px] shrink-0 border-l border-ghost bg-surface-lowest overflow-y-auto`,children:[(0,R.jsxs)(yf,{id:`identity`,title:`Identity`,defaultOpen:!0,children:[(0,R.jsx)(xf,{id:`editrail-displayName`,field:`displayName`,label:`Display name`,placeholder:`Jane Smith`,maxLength:200}),(0,R.jsx)(xf,{id:`editrail-bio`,field:`bio`,label:`Bio / About`,placeholder:`A short bio for your portfolio...`,maxLength:2e3,multiline:!0,rows:3}),(0,R.jsx)(xf,{id:`editrail-location`,field:`location`,label:`Location`,placeholder:`San Francisco, CA`})]}),(0,R.jsxs)(yf,{id:`contact`,title:`Contact`,children:[(0,R.jsx)(xf,{id:`editrail-email`,field:`email`,label:`Email`,type:`email`,placeholder:`jane@example.com`}),(0,R.jsx)(xf,{id:`editrail-phone`,field:`phone`,label:`Phone`,type:`tel`,placeholder:`+1 (555) 123-4567`}),(0,R.jsx)(xf,{id:`editrail-linkedin`,field:`linkedinUrl`,label:`LinkedIn URL`,type:`url`,placeholder:`https://linkedin.com/in/janesmith`}),(0,R.jsx)(xf,{id:`editrail-github`,field:`githubUrl`,label:`GitHub URL`,type:`url`,placeholder:`https://github.com/janesmith`}),(0,R.jsx)(xf,{id:`editrail-twitter`,field:`twitterHandle`,label:`Twitter / X`,placeholder:`@janesmith`}),(0,R.jsx)(xf,{id:`editrail-website`,field:`websiteUrl`,label:`Personal website`,type:`url`,placeholder:`https://janesmith.dev`})]}),(0,R.jsxs)(yf,{id:`photo-resume`,title:`Photo & resume`,children:[(0,R.jsx)(Sf,{}),(0,R.jsx)(Cf,{})]}),(0,R.jsx)(Tf,{}),(0,R.jsx)(Ef,{})]})}function Of(){let{dispatch:e}=zc();return(0,_.useEffect)(()=>{let t=!1;return Promise.all([gr().catch(()=>({})),vr().catch(()=>({targets:{}})),Jn().catch(()=>[])]).then(([n,r,i])=>{if(t)return;let a=n.projectsOnPortfolio??[],o;if(a.length===0){let e=i.slice().sort((e,t)=>{let n=e.lastSessionDate||``,r=t.lastSessionDate||``;return n===r?t.dirName.localeCompare(e.dirName):r.localeCompare(n)}),t=new Set(e.slice(0,3).map(e=>e.dirName));o=e.map((e,n)=>({projectId:e.dirName,included:t.has(e.dirName),order:n}))}else{let e=new Map(a.map(e=>[e.projectId,e])),t=a.filter(e=>i.some(t=>t.dirName===e.projectId)).map(e=>({projectId:e.projectId,included:e.included,order:e.order}));t.sort((e,t)=>e.order-t.order);let n=i.filter(t=>!e.has(t.dirName)).map(e=>({projectId:e.dirName,included:!0,order:0}));o=[...t,...n].map((e,t)=>({...e,order:t}))}e({type:`LOAD`,profile:n,publishState:r,projects:o})}),()=>{t=!0}},[e]),null}function kf(){return(0,R.jsxs)(U,{children:[(0,R.jsx)(Of,{}),(0,R.jsx)(ii,{children:(0,R.jsxs)(`div`,{className:`flex flex-col h-[calc(100vh-3rem)] min-h-0`,children:[(0,R.jsx)(Gc,{}),(0,R.jsxs)(`div`,{className:`flex flex-1 min-h-0 overflow-hidden`,children:[(0,R.jsx)(Zc,{}),(0,R.jsx)(Df,{})]})]})})]})}var Af=[`Claude`,`Cursor`,`Codex`,`Gemini`];function jf(e){try{return new Date(e).toLocaleDateString(`en-US`,{month:`short`,day:`numeric`})}catch{return e}}function Mf(){let[e,t]=kn(),n=tt(),r=e.get(`q`)??``,i=e.get(`source`)??``,a=e.get(`project`)??``,o=e.get(`skill`)??``,[s,c]=(0,_.useState)(r),[l,u]=(0,_.useState)([]),[d,f]=(0,_.useState)(0),[p,m]=(0,_.useState)(!1),[h,g]=(0,_.useState)(!1),v=i,y=a,b=o,[x,S]=(0,_.useState)([]),[C,w]=(0,_.useState)([]),T=(0,_.useCallback)(async(e,t,n,r)=>{if(!e&&!t&&!n&&!r){u([]),f(0),g(!1);return}m(!0),g(!0);try{let i=await Rr(e,{source:t||void 0,project:n||void 0,skill:r||void 0});u(i.results),f(i.total);let a=[...new Set(i.results.map(e=>e.projectName))].sort(),o=[...new Set(i.results.flatMap(e=>e.skills))].sort();S(a),w(o)}catch{u([]),f(0)}finally{m(!1)}},[]);(0,_.useEffect)(()=>{let e=setTimeout(()=>{let e=new URLSearchParams;s&&e.set(`q`,s),v&&e.set(`source`,v),y&&e.set(`project`,y),b&&e.set(`skill`,b),t(e,{replace:!0}),T(s,v,y,b)},300);return()=>clearTimeout(e)},[s,v,y,b,t,T]),(0,_.useEffect)(()=>{(r||i||a||o)&&(c(r),T(r,i,a,o))},[]);function E(n,r){let i=new URLSearchParams(e);i.get(n)===r?i.delete(n):i.set(n,r),t(i,{replace:!0})}return(0,R.jsx)(ii,{chips:[{label:`Search`}],children:(0,R.jsxs)(`div`,{className:`p-6 max-w-3xl mx-auto`,children:[(0,R.jsx)(ni,{value:s,onChange:c,autoFocus:!0,placeholder:`Search sessions...`}),(0,R.jsxs)(`div`,{className:`flex flex-wrap items-center gap-1.5 mt-3`,children:[(0,R.jsx)(`span`,{className:`font-mono text-[9px] uppercase tracking-wider text-outline mr-1`,children:`Source`}),Af.map(e=>(0,R.jsx)(`button`,{onClick:()=>E(`source`,e.toLowerCase()),className:[`font-mono text-[11px] leading-tight py-0.5 px-2 rounded-sm border transition-colors cursor-pointer`,v===e.toLowerCase()?`bg-primary/10 text-primary border-primary/30`:`bg-surface-low text-on-surface-variant border-ghost hover:border-outline`].join(` `),children:e},e)),x.length>0&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(`span`,{className:`font-mono text-[9px] uppercase tracking-wider text-outline ml-3 mr-1`,children:`Project`}),x.slice(0,5).map(e=>(0,R.jsx)(`button`,{onClick:()=>E(`project`,e),className:[`font-mono text-[11px] leading-tight py-0.5 px-2 rounded-sm border transition-colors cursor-pointer`,y===e?`bg-primary/10 text-primary border-primary/30`:`bg-surface-low text-on-surface-variant border-ghost hover:border-outline`].join(` `),children:e},e))]}),C.length>0&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(`span`,{className:`font-mono text-[9px] uppercase tracking-wider text-outline ml-3 mr-1`,children:`Skill`}),C.slice(0,5).map(e=>(0,R.jsx)(`button`,{onClick:()=>E(`skill`,e),className:[`font-mono text-[11px] leading-tight py-0.5 px-2 rounded-sm border transition-colors cursor-pointer`,b===e?`bg-violet-bg text-violet border-violet/30`:`bg-surface-low text-on-surface-variant border-ghost hover:border-outline`].join(` `),children:e},e))]})]}),(0,R.jsx)(`div`,{className:`h-4`}),p?(0,R.jsx)(`div`,{className:`text-sm text-on-surface-variant`,children:`Searching...`}):h?(0,R.jsxs)(R.Fragment,{children:[(0,R.jsxs)(`div`,{className:`font-mono text-[11px] text-on-surface-variant mb-3`,children:[d,` result`,d===1?``:`s`,s?` for '${s}'`:``]}),l.length===0?(0,R.jsx)(ai,{children:(0,R.jsx)(`p`,{className:`text-sm text-on-surface-variant`,children:`No sessions found. Try a different query or adjust filters.`})}):(0,R.jsx)(`div`,{className:`flex flex-col gap-2`,children:l.map(e=>(0,R.jsx)(`button`,{onClick:()=>n(`/session/${encodeURIComponent(e.sessionId)}${s?`?q=${encodeURIComponent(s)}`:``}`),className:`text-left w-full cursor-pointer`,children:(0,R.jsxs)(ai,{hover:!0,children:[(0,R.jsxs)(`div`,{className:`flex items-start justify-between gap-3`,children:[(0,R.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,R.jsx)(`h4`,{className:`font-display text-[0.8125rem] font-semibold text-on-surface truncate`,children:e.title}),(0,R.jsxs)(`div`,{className:`flex items-center gap-2 mt-1`,children:[(0,R.jsx)(`span`,{className:`text-xs text-on-surface-variant`,children:e.projectName}),(0,R.jsx)(ti,{children:e.source}),(0,R.jsx)(`span`,{className:`text-xs text-outline`,children:jf(e.date)})]})]}),(0,R.jsxs)(`div`,{className:`flex items-center gap-3 font-mono text-[0.6875rem] text-outline shrink-0`,children:[(0,R.jsx)(`span`,{children:ua(e.durationMinutes)}),(0,R.jsxs)(`span`,{children:[e.turns,` turns`]}),(0,R.jsxs)(`span`,{children:[da(e.linesOfCode),` lines`]})]})]}),e.snippet&&(0,R.jsx)(`p`,{className:`text-xs text-on-surface-variant mt-2 line-clamp-2 font-mono`,children:e.snippet}),e.skills.length>0&&(0,R.jsx)(`div`,{className:`flex flex-wrap gap-1 mt-2`,children:e.skills.map(e=>(0,R.jsx)(ti,{variant:`violet`,children:e},e))})]})},e.sessionId))})]}):(0,R.jsxs)(`div`,{className:`flex flex-col items-center justify-center py-16 text-center`,children:[(0,R.jsxs)(`svg`,{className:`w-12 h-12 text-outline mb-4`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`1.5`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,R.jsx)(`circle`,{cx:`11`,cy:`11`,r:`8`}),(0,R.jsx)(`line`,{x1:`21`,y1:`21`,x2:`16.65`,y2:`16.65`})]}),(0,R.jsx)(`p`,{className:`font-display text-sm font-semibold text-on-surface`,children:`Search across all your AI sessions`}),(0,R.jsx)(`p`,{className:`text-xs text-on-surface-variant mt-1`,children:`Full-text search with source, project, and skill filters`})]})]})})}var Nf={Read:`📄`,Write:`✏️`,Edit:`✏️`,Bash:`▶`,Grep:`🔍`,Glob:`📂`,Agent:`🤖`,WebSearch:`🌐`,WebFetch:`🌐`};function Pf(e){return Nf[e]??`⚙`}function Ff(e){let{toolName:t,input:n}=e;if(!n)return t;switch(t){case`Read`:return n;case`Write`:return n;case`Edit`:return n;case`Bash`:return n.length>80?n.slice(0,77)+`...`:n;case`Grep`:case`Glob`:return n;case`Agent`:return n;default:return n.length>60?n.slice(0,57)+`...`:n}}function If({block:e}){let[t,n]=(0,_.useState)(!1),r=!!e.output,i=e.toolName===`Edit`,a=e.toolName===`Bash`;return(0,R.jsxs)(`div`,{className:`my-1.5 border border-ghost rounded-md bg-surface-lowest overflow-hidden`,children:[(0,R.jsxs)(`button`,{type:`button`,onClick:()=>n(!t),className:`w-full flex items-center gap-2 px-3 py-2 text-left hover:bg-surface-low transition-colors cursor-pointer`,children:[(0,R.jsx)(`span`,{className:`text-xs shrink-0 w-4 text-center`,children:Pf(e.toolName)}),(0,R.jsx)(`span`,{className:`font-mono text-[11px] font-semibold text-primary shrink-0`,children:e.toolName}),(0,R.jsx)(`span`,{className:`font-mono text-[11px] text-on-surface-variant truncate flex-1`,children:Ff(e)}),e.isError&&(0,R.jsx)(`span`,{className:`font-mono text-[9px] uppercase tracking-wider text-error shrink-0`,children:`error`}),(0,R.jsx)(`span`,{className:`text-[10px] text-outline shrink-0 transition-transform`,style:{transform:t?`rotate(90deg)`:`rotate(0deg)`},children:`▸`})]}),t&&(0,R.jsxs)(`div`,{className:`border-t border-ghost`,children:[i&&e.inputData&&(0,R.jsxs)(`div`,{className:`px-3 py-2 border-b border-ghost`,children:[typeof e.inputData.old_string==`string`&&(0,R.jsxs)(`div`,{className:`mb-2`,children:[(0,R.jsx)(`div`,{className:`font-mono text-[9px] uppercase tracking-wider text-outline mb-1`,children:`old`}),(0,R.jsx)(`pre`,{className:`font-mono text-[11px] text-error/80 bg-error/5 rounded px-2 py-1.5 overflow-x-auto whitespace-pre-wrap break-all max-h-40 overflow-y-auto`,children:e.inputData.old_string})]}),typeof e.inputData.new_string==`string`&&(0,R.jsxs)(`div`,{children:[(0,R.jsx)(`div`,{className:`font-mono text-[9px] uppercase tracking-wider text-outline mb-1`,children:`new`}),(0,R.jsx)(`pre`,{className:`font-mono text-[11px] text-green/80 bg-green/5 rounded px-2 py-1.5 overflow-x-auto whitespace-pre-wrap break-all max-h-40 overflow-y-auto`,children:e.inputData.new_string})]})]}),a&&e.input&&(0,R.jsx)(`div`,{className:`px-3 py-2 border-b border-ghost bg-[var(--inverse-surface)]`,children:(0,R.jsxs)(`pre`,{className:`font-mono text-[11px] text-[var(--inverse-on-surface)] whitespace-pre-wrap break-all`,children:[`$ `,e.input]})}),r&&(0,R.jsxs)(`div`,{className:`px-3 py-2 max-h-64 overflow-y-auto`,children:[(0,R.jsx)(`pre`,{className:`font-mono text-[11px] whitespace-pre-wrap break-all ${e.isError?`text-error`:`text-on-surface-variant`}`,children:e.output}),e.outputTruncated&&(0,R.jsx)(`div`,{className:`font-mono text-[9px] uppercase tracking-wider text-outline mt-2`,children:`output truncated`})]}),!r&&!i&&!a&&(0,R.jsx)(`div`,{className:`px-3 py-2 text-[11px] text-outline italic`,children:`no output`})]})]})}function Lf({text:e}){let[t,n]=(0,_.useState)(!1),r=e.slice(0,80).replace(/\n/g,` `);return(0,R.jsxs)(`div`,{className:`my-1`,children:[(0,R.jsxs)(`button`,{type:`button`,onClick:()=>n(!t),className:`flex items-center gap-2 text-left cursor-pointer group`,children:[(0,R.jsx)(`span`,{className:`text-[10px] text-outline transition-transform shrink-0`,style:{transform:t?`rotate(90deg)`:`rotate(0deg)`},children:`▸`}),(0,R.jsx)(`span`,{className:`font-mono text-[11px] text-outline italic group-hover:text-on-surface-variant transition-colors`,children:t?`thinking`:`thinking: ${r}${e.length>80?`...`:``}`})]}),t&&(0,R.jsx)(`div`,{className:`ml-5 mt-1.5 pl-3 border-l-2 border-ghost`,children:(0,R.jsx)(`pre`,{className:`font-mono text-[11px] text-on-surface-variant/70 whitespace-pre-wrap break-words max-h-96 overflow-y-auto`,children:e})})]})}var Rf=300;function zf({text:e,highlights:t}){let[n,r]=(0,_.useState)(e.length<=Rf),i=e.length>Rf,a=(()=>{if(!i)return e.length;let t=e.slice(0,Rf+50),n=t.lastIndexOf(`. `,Rf);if(n>Rf*.6)return n+1;let r=t.lastIndexOf(` `,Rf);return r>Rf*.6?r:Rf})(),o=n?e:e.slice(0,a);if(t){let e=RegExp(`(${Gf(t)})`,`gi`);return(0,R.jsxs)(`div`,{className:`text-[0.8125rem] leading-relaxed whitespace-pre-wrap break-words`,children:[o.split(e).map((t,n)=>e.test(t)?(0,R.jsx)(`mark`,{className:`bg-amber/30 text-on-surface rounded-sm px-0.5`,children:t},n):(0,R.jsx)(`span`,{children:t},n)),i&&(0,R.jsx)(Bf,{expanded:n,onToggle:()=>r(!n)})]})}return(0,R.jsxs)(`div`,{children:[(0,R.jsx)(Vf,{text:o}),i&&(0,R.jsx)(Bf,{expanded:n,onToggle:()=>r(!n)})]})}function Bf({expanded:e,onToggle:t}){return(0,R.jsx)(`button`,{type:`button`,onClick:t,className:`inline-block mt-1 font-mono text-[11px] text-primary hover:underline cursor-pointer`,children:e?`▴ Show less`:`▾ Show more`})}function Vf({text:e}){return(0,R.jsx)(`div`,{className:`text-[0.8125rem] leading-relaxed whitespace-pre-wrap break-words`,children:e.split(/(```[\s\S]*?```)/g).map((e,t)=>{if(e.startsWith("```")&&e.endsWith("```")){let n=e.slice(3,-3),r=n.indexOf(`
|
|
37
|
-
`),i=r>0?n.slice(0,r).trim():``,a=r>0?n.slice(r+1):n;return(0,R.jsxs)(`pre`,{className:`my-2 bg-surface-lowest border border-ghost rounded-md px-3 py-2 font-mono text-[11px] overflow-x-auto`,children:[i&&(0,R.jsx)(`div`,{className:`font-mono text-[9px] uppercase tracking-wider text-outline mb-1.5`,children:i}),a]},t)}return(0,R.jsx)(`span`,{children:e.split(/(`[^`]+`)/g).map((e,t)=>e.startsWith("`")&&e.endsWith("`")?(0,R.jsx)(`code`,{className:`bg-surface-low rounded px-1 py-0.5 font-mono text-[11px]`,children:e.slice(1,-1)},t):(0,R.jsx)(`span`,{children:e},t))},t)})})}function Hf({message:e,searchQuery:t,messageIndex:n,showRoleBadge:r=!0}){let i=e.role===`user`,a=e.blocks.filter(e=>e.type===`tool_call`),o=e.blocks.filter(e=>e.type===`text`),s=e.blocks.filter(e=>e.type===`thinking`),[c,l]=(0,_.useState)(a.length<=3);return(0,R.jsxs)(`div`,{className:`relative`,"data-message-index":n,children:[r&&(0,R.jsx)(`div`,{className:`flex items-center gap-2 mb-1.5`,children:(0,R.jsx)(`span`,{className:`inline-flex items-center font-mono text-[11px] uppercase tracking-wider font-bold px-1.5 py-0.5 rounded-sm ${i?`bg-primary/10 text-primary`:`bg-green/10 text-green`}`,children:i?`you`:`assistant`})}),(0,R.jsxs)(`div`,{className:`${i?`bg-primary/5 border-l-[3px] border-primary pl-3 py-2 rounded-r-md`:`pl-0.5`}`,children:[s.map((e,n)=>(0,R.jsx)(Uf,{block:e,searchQuery:t},`t-${n}`)),o.map((e,n)=>(0,R.jsx)(Uf,{block:e,searchQuery:t},`x-${n}`)),a.length>3&&!c?(0,R.jsxs)(`button`,{type:`button`,onClick:()=>l(!0),className:`mt-1.5 flex items-center gap-2 font-mono text-[11px] text-on-surface-variant hover:text-on-surface cursor-pointer transition-colors`,children:[(0,R.jsx)(`span`,{className:`text-[10px] text-outline`,children:`▸`}),(0,R.jsxs)(`span`,{children:[a.length,` tool calls`]}),(0,R.jsxs)(`span`,{className:`text-outline`,children:[`(`,[...new Set(a.map(e=>e.type===`tool_call`?e.toolName:``))].join(`, `),`)`]})]}):a.map((e,n)=>(0,R.jsx)(Uf,{block:e,searchQuery:t},`tc-${n}`)),a.length>3&&c&&(0,R.jsxs)(`button`,{type:`button`,onClick:()=>l(!1),className:`mt-1 font-mono text-[10px] text-outline hover:text-on-surface-variant cursor-pointer`,children:[`▾ Collapse `,a.length,` tool calls`]})]})]})}function Uf({block:e,searchQuery:t}){switch(e.type){case`text`:return(0,R.jsx)(zf,{text:e.text,highlights:t});case`thinking`:return(0,R.jsx)(Lf,{text:e.text});case`tool_call`:return(0,R.jsx)(If,{block:e})}}function Wf({query:e,onQueryChange:t,matchCount:n,currentMatch:r,onNext:i,onPrev:a,onClose:o}){let s=(0,_.useRef)(null);return(0,_.useEffect)(()=>{s.current?.focus()},[]),(0,R.jsxs)(`div`,{className:`flex items-center gap-2 bg-surface-lowest border border-ghost rounded-md px-3 py-1.5 shadow-sm`,children:[(0,R.jsxs)(`svg`,{className:`w-3.5 h-3.5 text-outline shrink-0`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,children:[(0,R.jsx)(`circle`,{cx:`11`,cy:`11`,r:`8`}),(0,R.jsx)(`line`,{x1:`21`,y1:`21`,x2:`16.65`,y2:`16.65`})]}),(0,R.jsx)(`input`,{ref:s,type:`text`,value:e,onChange:e=>t(e.target.value),onKeyDown:e=>{e.key===`Enter`&&(e.shiftKey?a():i()),e.key===`Escape`&&o()},placeholder:`Search in session...`,className:`bg-transparent text-sm text-on-surface outline-none flex-1 min-w-0`}),e&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(`span`,{className:`font-mono text-[10px] text-outline shrink-0`,children:n>0?`${r+1}/${n}`:`no matches`}),(0,R.jsx)(`button`,{type:`button`,onClick:a,disabled:n===0,className:`text-xs text-on-surface-variant hover:text-on-surface disabled:opacity-30 cursor-pointer`,children:`↑`}),(0,R.jsx)(`button`,{type:`button`,onClick:i,disabled:n===0,className:`text-xs text-on-surface-variant hover:text-on-surface disabled:opacity-30 cursor-pointer`,children:`↓`})]}),(0,R.jsx)(`button`,{type:`button`,onClick:o,className:`text-xs text-outline hover:text-on-surface cursor-pointer ml-1`,children:`✕`})]})}function Gf(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function Kf({messages:e,initialSearchQuery:t,compact:n}){let[r,i]=(0,_.useState)(!!t),[a,o]=(0,_.useState)(t??``),[s,c]=(0,_.useState)(0),l=(0,_.useRef)(null);(0,_.useEffect)(()=>{if(n)return;function e(e){(e.metaKey||e.ctrlKey)&&e.key===`f`&&(e.preventDefault(),i(!0))}return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[n]);let u=(0,_.useMemo)(()=>{if(!a)return 0;let t=new RegExp(Gf(a),`gi`),n=0;for(let r of e)for(let e of r.blocks)if(e.type===`text`){let r=e.text.match(t);r&&(n+=r.length)}return n},[e,a]),d=(0,_.useCallback)(()=>{c(e=>(e+1)%Math.max(1,u))},[u]),f=(0,_.useCallback)(()=>{c(e=>(e-1+Math.max(1,u))%Math.max(1,u))},[u]),p=(0,_.useCallback)(()=>{i(!1),o(``),c(0)},[]);return e.length===0?(0,R.jsx)(`div`,{className:`text-center ${n?`py-4`:`py-12`}`,children:(0,R.jsx)(`p`,{className:`text-sm text-on-surface-variant`,children:`No conversation data available.`})}):(0,R.jsxs)(`div`,{ref:l,className:`relative`,children:[!n&&r&&(0,R.jsx)(`div`,{className:`sticky top-12 z-40 mb-4`,children:(0,R.jsx)(Wf,{query:a,onQueryChange:e=>{o(e),c(0)},matchCount:u,currentMatch:s,onNext:d,onPrev:f,onClose:p})}),(0,R.jsx)(`div`,{className:`flex flex-col gap-4`,children:e.map((t,n)=>{let r=n>0?e[n-1].role:null,i=r!==t.role;return(0,R.jsxs)(`div`,{children:[r!==null&&r!==t.role&&t.role===`user`&&(0,R.jsx)(`div`,{className:`border-t border-ghost/60 mb-4 mt-1`}),(0,R.jsx)(Hf,{message:t,messageIndex:n,searchQuery:a||void 0,showRoleBadge:i})]},t.id)})}),!n&&!r&&(0,R.jsx)(`button`,{type:`button`,onClick:()=>i(!0),className:`fixed bottom-6 right-6 z-40 bg-surface-lowest border border-ghost rounded-full w-10 h-10 flex items-center justify-center shadow-lg hover:shadow-xl transition-shadow cursor-pointer group`,title:`Search in session (Cmd+F)`,children:(0,R.jsxs)(`svg`,{className:`w-4 h-4 text-on-surface-variant group-hover:text-on-surface transition-colors`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,children:[(0,R.jsx)(`circle`,{cx:`11`,cy:`11`,r:`8`}),(0,R.jsx)(`line`,{x1:`21`,y1:`21`,x2:`16.65`,y2:`16.65`})]})})]})}function qf(e){try{return new Date(e).toLocaleDateString(`en-US`,{month:`short`,day:`numeric`,year:`numeric`,hour:`numeric`,minute:`2-digit`})}catch{return e}}function Jf(e){let t=e.replace(/^#+\s*/gm,``).replace(/\*\*/g,``).replace(/\n.*/s,``);return t.length>120&&(t=t.slice(0,117)+`...`),t}function Yf(){let{sessionId:e}=rt(),[t]=kn(),n=tt(),r=t.get(`q`)??``,[i,a]=(0,_.useState)(null),[o,s]=(0,_.useState)(!0),[c,l]=(0,_.useState)(null),[u,d]=(0,_.useState)([]),[f,p]=(0,_.useState)(!1),[m,h]=(0,_.useState)(!1),[g,v]=(0,_.useState)(!1),[y,b]=(0,_.useState)(!1),[x,S]=(0,_.useState)(null),[C,w]=(0,_.useState)(!1);(0,_.useEffect)(()=>{e&&(s(!0),zr(e).then(a).catch(e=>l(e.message)).finally(()=>s(!1)))},[e]),(0,_.useEffect)(()=>{!e||m||(p(!0),Vr(e).then(e=>{d(e.messages),h(!0)}).catch(()=>{}).finally(()=>p(!1)))},[e,m]),(0,_.useEffect)(()=>{if(!x)return;let e=setTimeout(()=>S(null),3e3);return()=>clearTimeout(e)},[x]);async function T(t){if(!(!e||y)){b(!0),v(!1);try{let n=await Br(e,t);await navigator.clipboard.writeText(n.content),S(`Context copied (${n.tokens.toLocaleString()} tokens)`)}catch{S(`Failed to copy context`)}finally{b(!1)}}}async function E(){if(!(!e||C)){w(!0);try{let t=await Br(e,`summary`),n=new Blob([t.content],{type:`text/markdown`}),r=URL.createObjectURL(n),i=document.createElement(`a`);i.href=r,i.download=`session-${e.slice(0,8)}.md`,i.click(),URL.revokeObjectURL(r),S(`Downloaded summary (${t.tokens.toLocaleString()} tokens)`)}catch{S(`Failed to download summary`)}finally{w(!1)}}}if(o)return(0,R.jsx)(`div`,{className:`min-h-screen flex items-center justify-center bg-surface-mid`,children:(0,R.jsx)(`span`,{className:`text-sm text-on-surface-variant`,children:`Loading session...`})});if(c||!i)return(0,R.jsxs)(`div`,{className:`min-h-screen flex flex-col items-center justify-center bg-surface-mid gap-3`,children:[(0,R.jsx)(`span`,{className:`text-sm text-on-surface-variant`,children:c??`Session not found.`}),(0,R.jsx)(`button`,{onClick:()=>n(-1),className:`text-xs text-primary hover:underline cursor-pointer`,children:`Go back`})]});let D=i.filesChanged??[],O=i.toolBreakdown??[],k=Math.max(...O.map(e=>e.count),1),A=(()=>{if(u.length>0&&u[0].role===`user`)return u;let e=i.title.replace(/\.\.\.$/,``).replace(/\s*##\s*$/,``).trim();return[{id:`first-prompt`,timestamp:i.date,role:`user`,blocks:[{type:`text`,text:e}]},...u]})();return(0,R.jsxs)(`div`,{className:`min-h-screen bg-surface-mid`,children:[(0,R.jsx)(`header`,{className:`sticky top-0 z-50 bg-surface-lowest border-b border-ghost`,children:(0,R.jsxs)(`div`,{className:`flex items-center justify-between h-12 px-4`,children:[(0,R.jsxs)(`div`,{className:`flex items-center gap-3 min-w-0`,children:[(0,R.jsx)(`button`,{onClick:()=>n(-1),className:`text-sm text-on-surface-variant hover:text-on-surface transition-colors cursor-pointer shrink-0`,children:`← Back`}),(0,R.jsx)(`span`,{className:`text-outline text-xs shrink-0`,children:`/`}),(0,R.jsx)(`span`,{className:`font-display text-sm font-semibold text-on-surface truncate`,children:Jf(i.title)})]}),(0,R.jsxs)(`div`,{className:`flex items-center gap-2 shrink-0`,children:[(0,R.jsx)(`button`,{onClick:E,disabled:C,className:`inline-flex items-center gap-1.5 text-[0.8125rem] px-3 py-1.5 rounded-sm border border-ghost text-on-surface-variant hover:text-on-surface hover:border-outline transition-colors cursor-pointer disabled:opacity-50`,children:C?`Downloading...`:`↓ Summary`}),(0,R.jsxs)(`div`,{className:`relative`,children:[(0,R.jsx)(`button`,{onClick:()=>v(!g),disabled:y,className:`inline-flex items-center gap-1.5 font-semibold text-[0.8125rem] px-3.5 py-1.5 rounded-sm bg-primary text-on-primary hover:bg-primary-hover transition-colors cursor-pointer disabled:opacity-50`,children:y?`Copying...`:`Copy for AI`}),g&&(0,R.jsx)(`div`,{className:`absolute right-0 top-full mt-1 bg-surface-lowest border border-ghost rounded-md shadow-lg z-50 py-1 min-w-[160px]`,children:[`compact`,`summary`,`full`].map(e=>(0,R.jsxs)(`button`,{onClick:()=>T(e),className:`w-full text-left px-3 py-1.5 text-sm text-on-surface hover:bg-surface-low transition-colors cursor-pointer`,children:[(0,R.jsx)(`span`,{className:`font-semibold capitalize`,children:e}),(0,R.jsx)(`span`,{className:`text-on-surface-variant text-xs ml-1.5`,children:e===`compact`?`~500 tokens`:e===`summary`?`~2k tokens`:`~5k+ tokens`})]},e))})]})]})]})}),x&&(0,R.jsx)(`div`,{className:`fixed bottom-4 right-4 z-50 bg-surface-dark text-on-primary font-mono text-xs px-4 py-2.5 rounded-md shadow-lg`,children:x}),(0,R.jsxs)(`div`,{className:`p-6 max-w-3xl mx-auto`,children:[(0,R.jsxs)(`div`,{className:`flex flex-wrap items-center gap-1.5 mb-2`,children:[i.source&&(0,R.jsx)(ti,{children:i.source}),(0,R.jsx)(ti,{children:qf(i.date)}),i.projectName&&(0,R.jsx)(ti,{variant:`primary`,children:i.projectName})]}),(0,R.jsxs)(`div`,{className:`flex items-center gap-4 font-mono text-[11px] text-on-surface-variant mb-4`,children:[(0,R.jsxs)(`span`,{children:[ua(i.durationMinutes),` active`]}),(0,R.jsx)(`span`,{className:`text-ghost`,children:`|`}),(0,R.jsxs)(`span`,{children:[i.turns,` turns`]}),(0,R.jsx)(`span`,{className:`text-ghost`,children:`|`}),(0,R.jsxs)(`span`,{children:[D.length,` files`]}),(0,R.jsx)(`span`,{className:`text-ghost`,children:`|`}),(0,R.jsxs)(`span`,{children:[da(i.linesOfCode),` lines`]})]}),i.developerTake&&(0,R.jsx)(`div`,{className:`mb-5`,children:(0,R.jsx)(`p`,{className:`text-[0.9375rem] leading-relaxed text-on-surface border-l-[3px] border-primary pl-3`,children:i.developerTake})}),i.skills&&i.skills.length>0&&(0,R.jsx)(`div`,{className:`flex flex-wrap gap-1 mb-5`,children:i.skills.map(e=>(0,R.jsx)(ti,{variant:`violet`,children:e},e))}),f?(0,R.jsx)(`div`,{className:`flex items-center justify-center py-16`,children:(0,R.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,R.jsx)(`span`,{className:`w-4 h-4 border-2 border-primary border-t-transparent rounded-full animate-spin`}),(0,R.jsx)(`span`,{className:`text-sm text-on-surface-variant`,children:`Loading transcript...`})]})}):(0,R.jsx)(Kf,{messages:A,initialSearchQuery:r}),(O.length>0||D.length>0||i.qaPairs&&i.qaPairs.length>0)&&(0,R.jsxs)(`div`,{className:`mt-8 pt-6 border-t border-ghost`,children:[(0,R.jsx)(`div`,{className:`font-mono text-[9px] uppercase tracking-wider text-outline mb-4`,children:`Supporting detail`}),D.length>0&&(0,R.jsxs)(`div`,{className:`mb-5`,children:[(0,R.jsxs)(`div`,{className:`font-mono text-[10px] uppercase tracking-wider text-on-surface-variant mb-2`,children:[`Files changed · `,D.length]}),(0,R.jsx)(`div`,{className:`flex flex-col divide-y divide-ghost bg-surface-lowest border border-ghost rounded-md`,children:D.map(e=>(0,R.jsxs)(`div`,{className:`flex items-center justify-between px-3 py-2`,children:[(0,R.jsx)(`span`,{className:`font-mono text-xs text-on-surface truncate flex-1 mr-3`,children:e.path}),(0,R.jsxs)(`div`,{className:`flex items-center gap-2 font-mono text-[11px] shrink-0`,children:[e.additions>0&&(0,R.jsxs)(`span`,{className:`text-green`,children:[`+`,e.additions]}),e.deletions>0&&(0,R.jsxs)(`span`,{className:`text-error`,children:[`-`,e.deletions]})]})]},e.path))})]}),O.length>0&&(0,R.jsxs)(`div`,{className:`mb-5`,children:[(0,R.jsxs)(`div`,{className:`font-mono text-[10px] uppercase tracking-wider text-on-surface-variant mb-2`,children:[`Tool breakdown · `,O.reduce((e,t)=>e+t.count,0),` calls`]}),(0,R.jsx)(`div`,{className:`flex flex-col gap-2`,children:O.sort((e,t)=>t.count-e.count).map(e=>(0,R.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,R.jsx)(`span`,{className:`font-mono text-[11px] text-on-surface-variant w-28 truncate shrink-0`,children:e.tool}),(0,R.jsx)(`div`,{className:`flex-1 h-4 bg-surface-low rounded-sm overflow-hidden`,children:(0,R.jsx)(`div`,{className:`h-full bg-primary/20 rounded-sm`,style:{width:`${e.count/k*100}%`}})}),(0,R.jsx)(`span`,{className:`font-mono text-[11px] text-outline w-8 text-right shrink-0`,children:e.count})]},e.tool))})]}),i.qaPairs&&i.qaPairs.length>0&&(0,R.jsxs)(`div`,{className:`mb-5`,children:[(0,R.jsx)(`div`,{className:`font-mono text-[10px] uppercase tracking-wider text-on-surface-variant mb-2`,children:`Questions & Answers`}),(0,R.jsx)(`div`,{className:`bg-surface-lowest border border-ghost rounded-md divide-y divide-ghost`,children:i.qaPairs.map((e,t)=>(0,R.jsxs)(`div`,{className:`px-3 py-3`,children:[(0,R.jsx)(`div`,{className:`font-semibold text-sm text-on-surface mb-1`,children:e.question}),(0,R.jsx)(`div`,{className:`text-[0.8125rem] text-on-surface-variant leading-relaxed`,children:e.answer})]},t))})]})]})]})]})}function Xf(e){try{return new Date(e).toLocaleDateString(`en-US`,{month:`short`,day:`numeric`,year:`numeric`})}catch{return e}}function Zf(){let{dirName:e}=rt(),t=tt(),[n,r]=(0,_.useState)(null),[i,a]=(0,_.useState)(!0),[o,s]=(0,_.useState)(`date`),[c,l]=(0,_.useState)(!0),[u,d]=(0,_.useState)(``);if((0,_.useEffect)(()=>{e&&nr(e).then(r).catch(()=>{}).finally(()=>a(!1))},[e]),i)return(0,R.jsx)(`div`,{className:`min-h-screen flex items-center justify-center bg-surface-mid`,children:(0,R.jsx)(`span`,{className:`text-sm text-on-surface-variant`,children:`Loading sessions...`})});if(!n)return(0,R.jsxs)(`div`,{className:`min-h-screen flex flex-col items-center justify-center bg-surface-mid gap-3`,children:[(0,R.jsx)(`span`,{className:`text-sm text-on-surface-variant`,children:`Project not found.`}),(0,R.jsx)(`button`,{onClick:()=>t(-1),className:`text-xs text-primary hover:underline cursor-pointer`,children:`Go back`})]});let{sessions:f}=n,p=[...u?f.filter(e=>e.title.toLowerCase().includes(u.toLowerCase())||(e.skills??[]).some(e=>e.toLowerCase().includes(u.toLowerCase()))||(e.source??``).toLowerCase().includes(u.toLowerCase())):f].sort((e,t)=>{let n=0;switch(o){case`date`:n=new Date(e.date).getTime()-new Date(t.date).getTime();break;case`duration`:n=e.durationMinutes-t.durationMinutes;break;case`loc`:n=e.linesOfCode-t.linesOfCode;break;case`turns`:n=e.turns-t.turns;break}return c?-n:n});function m(e){o===e?l(!c):(s(e),l(!0))}function h({label:e,sortKey:t}){let n=o===t;return(0,R.jsxs)(`button`,{type:`button`,onClick:()=>m(t),className:`font-mono text-[9px] uppercase tracking-wider cursor-pointer transition-colors ${n?`text-primary font-bold`:`text-outline hover:text-on-surface-variant`}`,children:[e,` `,n?c?`↓`:`↑`:``]})}return(0,R.jsxs)(`div`,{className:`min-h-screen bg-surface-mid`,children:[(0,R.jsx)(`header`,{className:`sticky top-0 z-50 bg-surface-lowest border-b border-ghost`,children:(0,R.jsxs)(`div`,{className:`flex items-center justify-between h-12 px-4`,children:[(0,R.jsxs)(`div`,{className:`flex items-center gap-3 min-w-0`,children:[(0,R.jsxs)(`button`,{onClick:()=>t(`/project/${encodeURIComponent(e??``)}`),className:`text-sm text-on-surface-variant hover:text-on-surface transition-colors cursor-pointer shrink-0`,children:[`← `,n.project.name]}),(0,R.jsx)(`span`,{className:`text-outline text-xs shrink-0`,children:`/`}),(0,R.jsx)(`span`,{className:`font-display text-sm font-semibold text-on-surface`,children:`All sessions`})]}),(0,R.jsxs)(ti,{variant:`primary`,children:[f.length,` sessions`]})]})}),(0,R.jsxs)(`div`,{className:`p-6 max-w-4xl mx-auto`,children:[(0,R.jsxs)(`div`,{className:`flex items-center gap-4 mb-4`,children:[(0,R.jsx)(`input`,{type:`text`,value:u,onChange:e=>d(e.target.value),placeholder:`Filter by title, skill, or source...`,className:`flex-1 bg-surface-lowest border border-ghost rounded-md px-3 py-2 text-sm text-on-surface placeholder:text-outline outline-none focus:border-primary transition-colors`}),(0,R.jsxs)(`div`,{className:`flex items-center gap-3 shrink-0`,children:[(0,R.jsx)(`span`,{className:`font-mono text-[9px] uppercase tracking-wider text-outline`,children:`Sort:`}),(0,R.jsx)(h,{label:`Date`,sortKey:`date`}),(0,R.jsx)(h,{label:`Duration`,sortKey:`duration`}),(0,R.jsx)(h,{label:`Lines`,sortKey:`loc`}),(0,R.jsx)(h,{label:`Turns`,sortKey:`turns`})]})]}),(0,R.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[p.map(e=>(0,R.jsxs)(xn,{to:`/session/${encodeURIComponent(e.id)}`,className:`flex items-start gap-4 bg-surface-lowest border border-ghost rounded-md px-4 py-3 hover:shadow-md transition-shadow`,children:[(0,R.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,R.jsx)(`div`,{className:`font-display text-[0.8125rem] font-semibold text-on-surface mb-0.5 truncate`,children:e.title}),(0,R.jsxs)(`div`,{className:`flex items-center gap-3 font-mono text-[10px] text-on-surface-variant`,children:[(0,R.jsx)(`span`,{children:Xf(e.date)}),(0,R.jsx)(`span`,{className:`text-ghost`,children:`|`}),(0,R.jsx)(`span`,{children:ua(e.durationMinutes)}),(0,R.jsx)(`span`,{className:`text-ghost`,children:`|`}),(0,R.jsxs)(`span`,{children:[e.turns,` turns`]}),(0,R.jsx)(`span`,{className:`text-ghost`,children:`|`}),(0,R.jsxs)(`span`,{children:[da(e.linesOfCode),` lines`]})]}),e.developerTake&&(0,R.jsx)(`p`,{className:`text-xs text-on-surface-variant mt-1 line-clamp-1`,children:e.developerTake})]}),(0,R.jsxs)(`div`,{className:`flex items-center gap-1.5 shrink-0 pt-0.5`,children:[e.source&&(0,R.jsx)(ti,{children:e.source}),e.skills?.[0]&&(0,R.jsx)(ti,{variant:`violet`,children:e.skills[0]}),(e.skills?.length??0)>1&&(0,R.jsxs)(`span`,{className:`font-mono text-[9px] text-outline`,children:[`+`,e.skills.length-1]})]})]},e.id)),p.length===0&&(0,R.jsx)(`div`,{className:`text-center py-12`,children:(0,R.jsx)(`p`,{className:`text-sm text-on-surface-variant`,children:u?`No sessions match your filter.`:`No sessions in this project.`})})]})]})]})}function Qf({dirName:e}){let[t,n]=(0,_.useState)(!1),r=(0,_.useRef)(null);(0,_.useEffect)(()=>{function e(e){r.current&&!r.current.contains(e.target)&&n(!1)}return document.addEventListener(`mousedown`,e),()=>document.removeEventListener(`mousedown`,e)},[]);let i=encodeURIComponent(e),a=[{label:`HTML (.zip)`,href:`/api/projects/${i}/download-html`},{label:`Markdown (.zip)`,href:`/api/projects/${i}/download-markdown`},{label:`JSON`,href:`/api/projects/${i}/download-json`}];return(0,R.jsxs)(`div`,{className:`relative`,ref:r,children:[(0,R.jsxs)(`button`,{onClick:()=>n(e=>!e),className:`inline-flex items-center gap-1.5 font-semibold text-[0.8125rem] px-3.5 py-1.5 rounded-sm border border-ghost text-primary hover:border-outline transition-colors`,children:[`Export`,(0,R.jsx)(`svg`,{width:`12`,height:`12`,viewBox:`0 0 12 12`,fill:`none`,className:`transition-transform ${t?`rotate-180`:``}`,children:(0,R.jsx)(`path`,{d:`M3 4.5L6 7.5L9 4.5`,stroke:`currentColor`,strokeWidth:`1.5`,strokeLinecap:`round`,strokeLinejoin:`round`})})]}),t&&(0,R.jsx)(`div`,{className:`absolute right-0 top-full mt-1 z-50 min-w-[160px] rounded-md border border-outline bg-surface py-1 shadow-lg`,children:a.map(e=>(0,R.jsx)(`a`,{href:e.href,className:`block px-3 py-1.5 text-[0.8125rem] text-on-surface hover:bg-surface-low transition-colors`,onClick:()=>n(!1),children:e.label},e.label))})]})}function $f(){let{dirName:e}=rt(),[t,n]=(0,_.useState)(null);return(0,_.useEffect)(()=>{e&&nr(e).then(e=>{n(e.project.name)}).catch(()=>{})},[e]),(0,R.jsx)(ii,{back:{label:`Projects`,to:`/projects`},chips:[{label:t??`...`}],actions:(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(xn,{to:`/project/${encodeURIComponent(e??``)}/enhance`,className:`inline-flex items-center gap-1.5 font-semibold text-[0.8125rem] px-3.5 py-1.5 rounded-sm bg-primary text-on-primary hover:bg-primary-hover transition-colors`,children:`Enhance project`}),(0,R.jsx)(Qf,{dirName:e??``}),(0,R.jsx)(xn,{to:`/project/${encodeURIComponent(e??``)}/publish`,className:`text-xs text-on-surface-variant hover:text-on-surface transition-colors`,children:`Upload to heyiam.com`})]}),children:(0,R.jsx)(Hs,{})})}function ep(){return(0,R.jsx)(vn,{children:(0,R.jsxs)(kt,{children:[(0,R.jsx)(Dt,{path:`/`,element:(0,R.jsx)(Ea,{})}),(0,R.jsx)(Dt,{path:`/sources`,element:(0,R.jsx)(Ia,{})}),(0,R.jsx)(Dt,{path:`/archive`,element:(0,R.jsx)(Ra,{})}),(0,R.jsx)(Dt,{path:`/projects`,element:(0,R.jsx)(Ha,{})}),(0,R.jsx)(Dt,{path:`/project/:dirName`,element:(0,R.jsx)($f,{})}),(0,R.jsx)(Dt,{path:`/project/:dirName/sessions`,element:(0,R.jsx)(Zf,{})}),(0,R.jsx)(Dt,{path:`/project/:dirName/boundaries`,element:(0,R.jsx)(Us,{})}),(0,R.jsx)(Dt,{path:`/project/:dirName/enhance`,element:(0,R.jsx)(cc,{})}),(0,R.jsx)(Dt,{path:`/search`,element:(0,R.jsx)(Mf,{})}),(0,R.jsx)(Dt,{path:`/session/:sessionId`,element:(0,R.jsx)(Yf,{})}),(0,R.jsx)(Dt,{path:`/project/:dirName/publish`,element:(0,R.jsx)(dc,{})}),(0,R.jsx)(Dt,{path:`/settings`,element:(0,R.jsx)(pc,{})}),(0,R.jsx)(Dt,{path:`/portfolio`,element:(0,R.jsx)(kf,{})}),(0,R.jsx)(Dt,{path:`/templates`,element:(0,R.jsx)(Cc,{})})]})})}(0,v.createRoot)(document.getElementById(`root`)).render((0,R.jsx)(_.StrictMode,{children:(0,R.jsx)(ep,{})}));
|
|
37
|
+
`),i=r>0?n.slice(0,r).trim():``,a=r>0?n.slice(r+1):n;return(0,R.jsxs)(`pre`,{className:`my-2 bg-surface-lowest border border-ghost rounded-md px-3 py-2 font-mono text-[11px] overflow-x-auto`,children:[i&&(0,R.jsx)(`div`,{className:`font-mono text-[9px] uppercase tracking-wider text-outline mb-1.5`,children:i}),a]},t)}return(0,R.jsx)(`span`,{children:e.split(/(`[^`]+`)/g).map((e,t)=>e.startsWith("`")&&e.endsWith("`")?(0,R.jsx)(`code`,{className:`bg-surface-low rounded px-1 py-0.5 font-mono text-[11px]`,children:e.slice(1,-1)},t):(0,R.jsx)(`span`,{children:e},t))},t)})})}function Hf({message:e,searchQuery:t,messageIndex:n,showRoleBadge:r=!0}){let i=e.role===`user`,a=e.blocks.filter(e=>e.type===`tool_call`),o=e.blocks.filter(e=>e.type===`text`),s=e.blocks.filter(e=>e.type===`thinking`),[c,l]=(0,_.useState)(a.length<=3);return(0,R.jsxs)(`div`,{className:`relative`,"data-message-index":n,children:[r&&(0,R.jsx)(`div`,{className:`flex items-center gap-2 mb-1.5`,children:(0,R.jsx)(`span`,{className:`inline-flex items-center font-mono text-[11px] uppercase tracking-wider font-bold px-1.5 py-0.5 rounded-sm ${i?`bg-primary/10 text-primary`:`bg-green/10 text-green`}`,children:i?`you`:`assistant`})}),(0,R.jsxs)(`div`,{className:`${i?`bg-primary/5 border-l-[3px] border-primary pl-3 py-2 rounded-r-md`:`pl-0.5`}`,children:[s.map((e,n)=>(0,R.jsx)(Uf,{block:e,searchQuery:t},`t-${n}`)),o.map((e,n)=>(0,R.jsx)(Uf,{block:e,searchQuery:t},`x-${n}`)),a.length>3&&!c?(0,R.jsxs)(`button`,{type:`button`,onClick:()=>l(!0),className:`mt-1.5 flex items-center gap-2 font-mono text-[11px] text-on-surface-variant hover:text-on-surface cursor-pointer transition-colors`,children:[(0,R.jsx)(`span`,{className:`text-[10px] text-outline`,children:`▸`}),(0,R.jsxs)(`span`,{children:[a.length,` tool calls`]}),(0,R.jsxs)(`span`,{className:`text-outline`,children:[`(`,[...new Set(a.map(e=>e.type===`tool_call`?e.toolName:``))].join(`, `),`)`]})]}):a.map((e,n)=>(0,R.jsx)(Uf,{block:e,searchQuery:t},`tc-${n}`)),a.length>3&&c&&(0,R.jsxs)(`button`,{type:`button`,onClick:()=>l(!1),className:`mt-1 font-mono text-[10px] text-outline hover:text-on-surface-variant cursor-pointer`,children:[`▾ Collapse `,a.length,` tool calls`]})]})]})}function Uf({block:e,searchQuery:t}){switch(e.type){case`text`:return(0,R.jsx)(zf,{text:e.text,highlights:t});case`thinking`:return(0,R.jsx)(Lf,{text:e.text});case`tool_call`:return(0,R.jsx)(If,{block:e})}}function Wf({query:e,onQueryChange:t,matchCount:n,currentMatch:r,onNext:i,onPrev:a,onClose:o}){let s=(0,_.useRef)(null);return(0,_.useEffect)(()=>{s.current?.focus()},[]),(0,R.jsxs)(`div`,{className:`flex items-center gap-2 bg-surface-lowest border border-ghost rounded-md px-3 py-1.5 shadow-sm`,children:[(0,R.jsxs)(`svg`,{className:`w-3.5 h-3.5 text-outline shrink-0`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,children:[(0,R.jsx)(`circle`,{cx:`11`,cy:`11`,r:`8`}),(0,R.jsx)(`line`,{x1:`21`,y1:`21`,x2:`16.65`,y2:`16.65`})]}),(0,R.jsx)(`input`,{ref:s,type:`text`,value:e,onChange:e=>t(e.target.value),onKeyDown:e=>{e.key===`Enter`&&(e.shiftKey?a():i()),e.key===`Escape`&&o()},placeholder:`Search in session...`,className:`bg-transparent text-sm text-on-surface outline-none flex-1 min-w-0`}),e&&(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(`span`,{className:`font-mono text-[10px] text-outline shrink-0`,children:n>0?`${r+1}/${n}`:`no matches`}),(0,R.jsx)(`button`,{type:`button`,onClick:a,disabled:n===0,className:`text-xs text-on-surface-variant hover:text-on-surface disabled:opacity-30 cursor-pointer`,children:`↑`}),(0,R.jsx)(`button`,{type:`button`,onClick:i,disabled:n===0,className:`text-xs text-on-surface-variant hover:text-on-surface disabled:opacity-30 cursor-pointer`,children:`↓`})]}),(0,R.jsx)(`button`,{type:`button`,onClick:o,className:`text-xs text-outline hover:text-on-surface cursor-pointer ml-1`,children:`✕`})]})}function Gf(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}function Kf({messages:e,initialSearchQuery:t,compact:n}){let[r,i]=(0,_.useState)(!!t),[a,o]=(0,_.useState)(t??``),[s,c]=(0,_.useState)(0),l=(0,_.useRef)(null);(0,_.useEffect)(()=>{if(n)return;function e(e){(e.metaKey||e.ctrlKey)&&e.key===`f`&&(e.preventDefault(),i(!0))}return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[n]);let u=(0,_.useMemo)(()=>{if(!a)return 0;let t=new RegExp(Gf(a),`gi`),n=0;for(let r of e)for(let e of r.blocks)if(e.type===`text`){let r=e.text.match(t);r&&(n+=r.length)}return n},[e,a]),d=(0,_.useCallback)(()=>{c(e=>(e+1)%Math.max(1,u))},[u]),f=(0,_.useCallback)(()=>{c(e=>(e-1+Math.max(1,u))%Math.max(1,u))},[u]),p=(0,_.useCallback)(()=>{i(!1),o(``),c(0)},[]);return e.length===0?(0,R.jsx)(`div`,{className:`text-center ${n?`py-4`:`py-12`}`,children:(0,R.jsx)(`p`,{className:`text-sm text-on-surface-variant`,children:`No conversation data available.`})}):(0,R.jsxs)(`div`,{ref:l,className:`relative`,children:[!n&&r&&(0,R.jsx)(`div`,{className:`sticky top-12 z-40 mb-4`,children:(0,R.jsx)(Wf,{query:a,onQueryChange:e=>{o(e),c(0)},matchCount:u,currentMatch:s,onNext:d,onPrev:f,onClose:p})}),(0,R.jsx)(`div`,{className:`flex flex-col gap-4`,children:e.map((t,n)=>{let r=n>0?e[n-1].role:null,i=r!==t.role;return(0,R.jsxs)(`div`,{children:[r!==null&&r!==t.role&&t.role===`user`&&(0,R.jsx)(`div`,{className:`border-t border-ghost/60 mb-4 mt-1`}),(0,R.jsx)(Hf,{message:t,messageIndex:n,searchQuery:a||void 0,showRoleBadge:i})]},t.id)})}),!n&&!r&&(0,R.jsx)(`button`,{type:`button`,onClick:()=>i(!0),className:`fixed bottom-6 right-6 z-40 bg-surface-lowest border border-ghost rounded-full w-10 h-10 flex items-center justify-center shadow-lg hover:shadow-xl transition-shadow cursor-pointer group`,title:`Search in session (Cmd+F)`,children:(0,R.jsxs)(`svg`,{className:`w-4 h-4 text-on-surface-variant group-hover:text-on-surface transition-colors`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,children:[(0,R.jsx)(`circle`,{cx:`11`,cy:`11`,r:`8`}),(0,R.jsx)(`line`,{x1:`21`,y1:`21`,x2:`16.65`,y2:`16.65`})]})})]})}function qf(e){try{return new Date(e).toLocaleDateString(`en-US`,{month:`short`,day:`numeric`,year:`numeric`,hour:`numeric`,minute:`2-digit`})}catch{return e}}function Jf(e){let t=e.replace(/^#+\s*/gm,``).replace(/\*\*/g,``).replace(/\n.*/s,``);return t.length>120&&(t=t.slice(0,117)+`...`),t}function Yf(){let{sessionId:e}=rt(),[t]=kn(),n=tt(),r=t.get(`q`)??``,[i,a]=(0,_.useState)(null),[o,s]=(0,_.useState)(!0),[c,l]=(0,_.useState)(null),[u,d]=(0,_.useState)([]),[f,p]=(0,_.useState)(!1),[m,h]=(0,_.useState)(!1),[g,v]=(0,_.useState)(!1),[y,b]=(0,_.useState)(!1),[x,S]=(0,_.useState)(null),[C,w]=(0,_.useState)(!1);(0,_.useEffect)(()=>{e&&(s(!0),zr(e).then(r=>{if(a(r),r.id&&r.id!==e){let e=t.toString();n(`/session/${encodeURIComponent(r.id)}${e?`?${e}`:``}`,{replace:!0})}}).catch(e=>l(e.message)).finally(()=>s(!1)))},[e,n,t]),(0,_.useEffect)(()=>{!e||m||(p(!0),Vr(e).then(e=>{d(e.messages),h(!0)}).catch(()=>{}).finally(()=>p(!1)))},[e,m]),(0,_.useEffect)(()=>{if(!x)return;let e=setTimeout(()=>S(null),3e3);return()=>clearTimeout(e)},[x]);async function T(t){if(!(!e||y)){b(!0),v(!1);try{let n=await Br(e,t);await navigator.clipboard.writeText(n.content),S(`Context copied (${n.tokens.toLocaleString()} tokens)`)}catch{S(`Failed to copy context`)}finally{b(!1)}}}async function E(){if(!(!e||C)){w(!0);try{let t=await Br(e,`summary`),n=new Blob([t.content],{type:`text/markdown`}),r=URL.createObjectURL(n),i=document.createElement(`a`);i.href=r,i.download=`session-${e.slice(0,8)}.md`,i.click(),URL.revokeObjectURL(r),S(`Downloaded summary (${t.tokens.toLocaleString()} tokens)`)}catch{S(`Failed to download summary`)}finally{w(!1)}}}if(o)return(0,R.jsx)(`div`,{className:`min-h-screen flex items-center justify-center bg-surface-mid`,children:(0,R.jsx)(`span`,{className:`text-sm text-on-surface-variant`,children:`Loading session...`})});if(c||!i)return(0,R.jsxs)(`div`,{className:`min-h-screen flex flex-col items-center justify-center bg-surface-mid gap-3`,children:[(0,R.jsx)(`span`,{className:`text-sm text-on-surface-variant`,children:c??`Session not found.`}),(0,R.jsx)(`button`,{onClick:()=>n(-1),className:`text-xs text-primary hover:underline cursor-pointer`,children:`Go back`})]});let D=i.filesChanged??[],O=i.toolBreakdown??[],k=Math.max(...O.map(e=>e.count),1),A=(()=>{if(u.length>0&&u[0].role===`user`)return u;let e=i.title.replace(/\.\.\.$/,``).replace(/\s*##\s*$/,``).trim();return[{id:`first-prompt`,timestamp:i.date,role:`user`,blocks:[{type:`text`,text:e}]},...u]})();return(0,R.jsxs)(`div`,{className:`min-h-screen bg-surface-mid`,children:[(0,R.jsx)(`header`,{className:`sticky top-0 z-50 bg-surface-lowest border-b border-ghost`,children:(0,R.jsxs)(`div`,{className:`flex items-center justify-between h-12 px-4`,children:[(0,R.jsxs)(`div`,{className:`flex items-center gap-3 min-w-0`,children:[(0,R.jsx)(`button`,{onClick:()=>n(-1),className:`text-sm text-on-surface-variant hover:text-on-surface transition-colors cursor-pointer shrink-0`,children:`← Back`}),(0,R.jsx)(`span`,{className:`text-outline text-xs shrink-0`,children:`/`}),(0,R.jsx)(`span`,{className:`font-display text-sm font-semibold text-on-surface truncate`,children:Jf(i.title)})]}),(0,R.jsxs)(`div`,{className:`flex items-center gap-2 shrink-0`,children:[(0,R.jsx)(`button`,{onClick:E,disabled:C,className:`inline-flex items-center gap-1.5 text-[0.8125rem] px-3 py-1.5 rounded-sm border border-ghost text-on-surface-variant hover:text-on-surface hover:border-outline transition-colors cursor-pointer disabled:opacity-50`,children:C?`Downloading...`:`↓ Summary`}),(0,R.jsxs)(`div`,{className:`relative`,children:[(0,R.jsx)(`button`,{onClick:()=>v(!g),disabled:y,className:`inline-flex items-center gap-1.5 font-semibold text-[0.8125rem] px-3.5 py-1.5 rounded-sm bg-primary text-on-primary hover:bg-primary-hover transition-colors cursor-pointer disabled:opacity-50`,children:y?`Copying...`:`Copy for AI`}),g&&(0,R.jsx)(`div`,{className:`absolute right-0 top-full mt-1 bg-surface-lowest border border-ghost rounded-md shadow-lg z-50 py-1 min-w-[160px]`,children:[`compact`,`summary`,`full`].map(e=>(0,R.jsxs)(`button`,{onClick:()=>T(e),className:`w-full text-left px-3 py-1.5 text-sm text-on-surface hover:bg-surface-low transition-colors cursor-pointer`,children:[(0,R.jsx)(`span`,{className:`font-semibold capitalize`,children:e}),(0,R.jsx)(`span`,{className:`text-on-surface-variant text-xs ml-1.5`,children:e===`compact`?`~500 tokens`:e===`summary`?`~2k tokens`:`~5k+ tokens`})]},e))})]})]})]})}),x&&(0,R.jsx)(`div`,{className:`fixed bottom-4 right-4 z-50 bg-surface-dark text-on-primary font-mono text-xs px-4 py-2.5 rounded-md shadow-lg`,children:x}),(0,R.jsxs)(`div`,{className:`p-6 max-w-3xl mx-auto`,children:[(0,R.jsxs)(`div`,{className:`flex flex-wrap items-center gap-1.5 mb-2`,children:[i.source&&(0,R.jsx)(ti,{children:i.source}),(0,R.jsx)(ti,{children:qf(i.date)}),i.projectName&&(0,R.jsx)(ti,{variant:`primary`,children:i.projectName})]}),(0,R.jsxs)(`div`,{className:`flex items-center gap-4 font-mono text-[11px] text-on-surface-variant mb-4`,children:[(0,R.jsxs)(`span`,{children:[ua(i.durationMinutes),` active`]}),(0,R.jsx)(`span`,{className:`text-ghost`,children:`|`}),(0,R.jsxs)(`span`,{children:[i.turns,` turns`]}),(0,R.jsx)(`span`,{className:`text-ghost`,children:`|`}),(0,R.jsxs)(`span`,{children:[D.length,` files`]}),(0,R.jsx)(`span`,{className:`text-ghost`,children:`|`}),(0,R.jsxs)(`span`,{children:[da(i.linesOfCode),` lines`]})]}),i.developerTake&&(0,R.jsx)(`div`,{className:`mb-5`,children:(0,R.jsx)(`p`,{className:`text-[0.9375rem] leading-relaxed text-on-surface border-l-[3px] border-primary pl-3`,children:i.developerTake})}),i.skills&&i.skills.length>0&&(0,R.jsx)(`div`,{className:`flex flex-wrap gap-1 mb-5`,children:i.skills.map(e=>(0,R.jsx)(ti,{variant:`violet`,children:e},e))}),f?(0,R.jsx)(`div`,{className:`flex items-center justify-center py-16`,children:(0,R.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,R.jsx)(`span`,{className:`w-4 h-4 border-2 border-primary border-t-transparent rounded-full animate-spin`}),(0,R.jsx)(`span`,{className:`text-sm text-on-surface-variant`,children:`Loading transcript...`})]})}):(0,R.jsx)(Kf,{messages:A,initialSearchQuery:r}),(O.length>0||D.length>0||i.qaPairs&&i.qaPairs.length>0)&&(0,R.jsxs)(`div`,{className:`mt-8 pt-6 border-t border-ghost`,children:[(0,R.jsx)(`div`,{className:`font-mono text-[9px] uppercase tracking-wider text-outline mb-4`,children:`Supporting detail`}),D.length>0&&(0,R.jsxs)(`div`,{className:`mb-5`,children:[(0,R.jsxs)(`div`,{className:`font-mono text-[10px] uppercase tracking-wider text-on-surface-variant mb-2`,children:[`Files changed · `,D.length]}),(0,R.jsx)(`div`,{className:`flex flex-col divide-y divide-ghost bg-surface-lowest border border-ghost rounded-md`,children:D.map(e=>(0,R.jsxs)(`div`,{className:`flex items-center justify-between px-3 py-2`,children:[(0,R.jsx)(`span`,{className:`font-mono text-xs text-on-surface truncate flex-1 mr-3`,children:e.path}),(0,R.jsxs)(`div`,{className:`flex items-center gap-2 font-mono text-[11px] shrink-0`,children:[e.additions>0&&(0,R.jsxs)(`span`,{className:`text-green`,children:[`+`,e.additions]}),e.deletions>0&&(0,R.jsxs)(`span`,{className:`text-error`,children:[`-`,e.deletions]})]})]},e.path))})]}),O.length>0&&(0,R.jsxs)(`div`,{className:`mb-5`,children:[(0,R.jsxs)(`div`,{className:`font-mono text-[10px] uppercase tracking-wider text-on-surface-variant mb-2`,children:[`Tool breakdown · `,O.reduce((e,t)=>e+t.count,0),` calls`]}),(0,R.jsx)(`div`,{className:`flex flex-col gap-2`,children:O.sort((e,t)=>t.count-e.count).map(e=>(0,R.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,R.jsx)(`span`,{className:`font-mono text-[11px] text-on-surface-variant w-28 truncate shrink-0`,children:e.tool}),(0,R.jsx)(`div`,{className:`flex-1 h-4 bg-surface-low rounded-sm overflow-hidden`,children:(0,R.jsx)(`div`,{className:`h-full bg-primary/20 rounded-sm`,style:{width:`${e.count/k*100}%`}})}),(0,R.jsx)(`span`,{className:`font-mono text-[11px] text-outline w-8 text-right shrink-0`,children:e.count})]},e.tool))})]}),i.qaPairs&&i.qaPairs.length>0&&(0,R.jsxs)(`div`,{className:`mb-5`,children:[(0,R.jsx)(`div`,{className:`font-mono text-[10px] uppercase tracking-wider text-on-surface-variant mb-2`,children:`Questions & Answers`}),(0,R.jsx)(`div`,{className:`bg-surface-lowest border border-ghost rounded-md divide-y divide-ghost`,children:i.qaPairs.map((e,t)=>(0,R.jsxs)(`div`,{className:`px-3 py-3`,children:[(0,R.jsx)(`div`,{className:`font-semibold text-sm text-on-surface mb-1`,children:e.question}),(0,R.jsx)(`div`,{className:`text-[0.8125rem] text-on-surface-variant leading-relaxed`,children:e.answer})]},t))})]})]})]})]})}function Xf(e){try{return new Date(e).toLocaleDateString(`en-US`,{month:`short`,day:`numeric`,year:`numeric`})}catch{return e}}function Zf(){let{dirName:e}=rt(),t=tt(),[n,r]=(0,_.useState)(null),[i,a]=(0,_.useState)(!0),[o,s]=(0,_.useState)(`date`),[c,l]=(0,_.useState)(!0),[u,d]=(0,_.useState)(``);if((0,_.useEffect)(()=>{e&&nr(e).then(r).catch(()=>{}).finally(()=>a(!1))},[e]),i)return(0,R.jsx)(`div`,{className:`min-h-screen flex items-center justify-center bg-surface-mid`,children:(0,R.jsx)(`span`,{className:`text-sm text-on-surface-variant`,children:`Loading sessions...`})});if(!n)return(0,R.jsxs)(`div`,{className:`min-h-screen flex flex-col items-center justify-center bg-surface-mid gap-3`,children:[(0,R.jsx)(`span`,{className:`text-sm text-on-surface-variant`,children:`Project not found.`}),(0,R.jsx)(`button`,{onClick:()=>t(-1),className:`text-xs text-primary hover:underline cursor-pointer`,children:`Go back`})]});let{sessions:f}=n,p=[...u?f.filter(e=>e.title.toLowerCase().includes(u.toLowerCase())||(e.skills??[]).some(e=>e.toLowerCase().includes(u.toLowerCase()))||(e.source??``).toLowerCase().includes(u.toLowerCase())):f].sort((e,t)=>{let n=0;switch(o){case`date`:n=new Date(e.date).getTime()-new Date(t.date).getTime();break;case`duration`:n=e.durationMinutes-t.durationMinutes;break;case`loc`:n=e.linesOfCode-t.linesOfCode;break;case`turns`:n=e.turns-t.turns;break}return c?-n:n});function m(e){o===e?l(!c):(s(e),l(!0))}function h({label:e,sortKey:t}){let n=o===t;return(0,R.jsxs)(`button`,{type:`button`,onClick:()=>m(t),className:`font-mono text-[9px] uppercase tracking-wider cursor-pointer transition-colors ${n?`text-primary font-bold`:`text-outline hover:text-on-surface-variant`}`,children:[e,` `,n?c?`↓`:`↑`:``]})}return(0,R.jsxs)(`div`,{className:`min-h-screen bg-surface-mid`,children:[(0,R.jsx)(`header`,{className:`sticky top-0 z-50 bg-surface-lowest border-b border-ghost`,children:(0,R.jsxs)(`div`,{className:`flex items-center justify-between h-12 px-4`,children:[(0,R.jsxs)(`div`,{className:`flex items-center gap-3 min-w-0`,children:[(0,R.jsxs)(`button`,{onClick:()=>t(`/project/${encodeURIComponent(e??``)}`),className:`text-sm text-on-surface-variant hover:text-on-surface transition-colors cursor-pointer shrink-0`,children:[`← `,n.project.name]}),(0,R.jsx)(`span`,{className:`text-outline text-xs shrink-0`,children:`/`}),(0,R.jsx)(`span`,{className:`font-display text-sm font-semibold text-on-surface`,children:`All sessions`})]}),(0,R.jsxs)(ti,{variant:`primary`,children:[f.length,` sessions`]})]})}),(0,R.jsxs)(`div`,{className:`p-6 max-w-4xl mx-auto`,children:[(0,R.jsxs)(`div`,{className:`flex items-center gap-4 mb-4`,children:[(0,R.jsx)(`input`,{type:`text`,value:u,onChange:e=>d(e.target.value),placeholder:`Filter by title, skill, or source...`,className:`flex-1 bg-surface-lowest border border-ghost rounded-md px-3 py-2 text-sm text-on-surface placeholder:text-outline outline-none focus:border-primary transition-colors`}),(0,R.jsxs)(`div`,{className:`flex items-center gap-3 shrink-0`,children:[(0,R.jsx)(`span`,{className:`font-mono text-[9px] uppercase tracking-wider text-outline`,children:`Sort:`}),(0,R.jsx)(h,{label:`Date`,sortKey:`date`}),(0,R.jsx)(h,{label:`Duration`,sortKey:`duration`}),(0,R.jsx)(h,{label:`Lines`,sortKey:`loc`}),(0,R.jsx)(h,{label:`Turns`,sortKey:`turns`})]})]}),(0,R.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[p.map(e=>(0,R.jsxs)(xn,{to:`/session/${encodeURIComponent(e.id)}`,className:`flex items-start gap-4 bg-surface-lowest border border-ghost rounded-md px-4 py-3 hover:shadow-md transition-shadow`,children:[(0,R.jsxs)(`div`,{className:`flex-1 min-w-0`,children:[(0,R.jsx)(`div`,{className:`font-display text-[0.8125rem] font-semibold text-on-surface mb-0.5 truncate`,children:e.title}),(0,R.jsxs)(`div`,{className:`flex items-center gap-3 font-mono text-[10px] text-on-surface-variant`,children:[(0,R.jsx)(`span`,{children:Xf(e.date)}),(0,R.jsx)(`span`,{className:`text-ghost`,children:`|`}),(0,R.jsx)(`span`,{children:ua(e.durationMinutes)}),(0,R.jsx)(`span`,{className:`text-ghost`,children:`|`}),(0,R.jsxs)(`span`,{children:[e.turns,` turns`]}),(0,R.jsx)(`span`,{className:`text-ghost`,children:`|`}),(0,R.jsxs)(`span`,{children:[da(e.linesOfCode),` lines`]})]}),e.developerTake&&(0,R.jsx)(`p`,{className:`text-xs text-on-surface-variant mt-1 line-clamp-1`,children:e.developerTake})]}),(0,R.jsxs)(`div`,{className:`flex items-center gap-1.5 shrink-0 pt-0.5`,children:[e.source&&(0,R.jsx)(ti,{children:e.source}),e.skills?.[0]&&(0,R.jsx)(ti,{variant:`violet`,children:e.skills[0]}),(e.skills?.length??0)>1&&(0,R.jsxs)(`span`,{className:`font-mono text-[9px] text-outline`,children:[`+`,e.skills.length-1]})]})]},e.id)),p.length===0&&(0,R.jsx)(`div`,{className:`text-center py-12`,children:(0,R.jsx)(`p`,{className:`text-sm text-on-surface-variant`,children:u?`No sessions match your filter.`:`No sessions in this project.`})})]})]})]})}function Qf({dirName:e}){let[t,n]=(0,_.useState)(!1),r=(0,_.useRef)(null);(0,_.useEffect)(()=>{function e(e){r.current&&!r.current.contains(e.target)&&n(!1)}return document.addEventListener(`mousedown`,e),()=>document.removeEventListener(`mousedown`,e)},[]);let i=encodeURIComponent(e),a=[{label:`HTML (.zip)`,href:`/api/projects/${i}/download-html`},{label:`Markdown (.zip)`,href:`/api/projects/${i}/download-markdown`},{label:`JSON`,href:`/api/projects/${i}/download-json`}];return(0,R.jsxs)(`div`,{className:`relative`,ref:r,children:[(0,R.jsxs)(`button`,{onClick:()=>n(e=>!e),className:`inline-flex items-center gap-1.5 font-semibold text-[0.8125rem] px-3.5 py-1.5 rounded-sm border border-ghost text-primary hover:border-outline transition-colors`,children:[`Export`,(0,R.jsx)(`svg`,{width:`12`,height:`12`,viewBox:`0 0 12 12`,fill:`none`,className:`transition-transform ${t?`rotate-180`:``}`,children:(0,R.jsx)(`path`,{d:`M3 4.5L6 7.5L9 4.5`,stroke:`currentColor`,strokeWidth:`1.5`,strokeLinecap:`round`,strokeLinejoin:`round`})})]}),t&&(0,R.jsx)(`div`,{className:`absolute right-0 top-full mt-1 z-50 min-w-[160px] rounded-md border border-outline bg-surface py-1 shadow-lg`,children:a.map(e=>(0,R.jsx)(`a`,{href:e.href,className:`block px-3 py-1.5 text-[0.8125rem] text-on-surface hover:bg-surface-low transition-colors`,onClick:()=>n(!1),children:e.label},e.label))})]})}function $f(){let{dirName:e}=rt(),[t,n]=(0,_.useState)(null);return(0,_.useEffect)(()=>{e&&nr(e).then(e=>{n(e.project.name)}).catch(()=>{})},[e]),(0,R.jsx)(ii,{back:{label:`Projects`,to:`/projects`},chips:[{label:t??`...`}],actions:(0,R.jsxs)(R.Fragment,{children:[(0,R.jsx)(xn,{to:`/project/${encodeURIComponent(e??``)}/enhance`,className:`inline-flex items-center gap-1.5 font-semibold text-[0.8125rem] px-3.5 py-1.5 rounded-sm bg-primary text-on-primary hover:bg-primary-hover transition-colors`,children:`Enhance project`}),(0,R.jsx)(Qf,{dirName:e??``}),(0,R.jsx)(xn,{to:`/project/${encodeURIComponent(e??``)}/publish`,className:`text-xs text-on-surface-variant hover:text-on-surface transition-colors`,children:`Upload to heyiam.com`})]}),children:(0,R.jsx)(Hs,{})})}function ep(){return(0,R.jsx)(vn,{children:(0,R.jsxs)(kt,{children:[(0,R.jsx)(Dt,{path:`/`,element:(0,R.jsx)(Ea,{})}),(0,R.jsx)(Dt,{path:`/sources`,element:(0,R.jsx)(Ia,{})}),(0,R.jsx)(Dt,{path:`/archive`,element:(0,R.jsx)(Ra,{})}),(0,R.jsx)(Dt,{path:`/projects`,element:(0,R.jsx)(Ha,{})}),(0,R.jsx)(Dt,{path:`/project/:dirName`,element:(0,R.jsx)($f,{})}),(0,R.jsx)(Dt,{path:`/project/:dirName/sessions`,element:(0,R.jsx)(Zf,{})}),(0,R.jsx)(Dt,{path:`/project/:dirName/boundaries`,element:(0,R.jsx)(Us,{})}),(0,R.jsx)(Dt,{path:`/project/:dirName/enhance`,element:(0,R.jsx)(cc,{})}),(0,R.jsx)(Dt,{path:`/search`,element:(0,R.jsx)(Mf,{})}),(0,R.jsx)(Dt,{path:`/session/:sessionId`,element:(0,R.jsx)(Yf,{})}),(0,R.jsx)(Dt,{path:`/project/:dirName/publish`,element:(0,R.jsx)(dc,{})}),(0,R.jsx)(Dt,{path:`/settings`,element:(0,R.jsx)(pc,{})}),(0,R.jsx)(Dt,{path:`/portfolio`,element:(0,R.jsx)(kf,{})}),(0,R.jsx)(Dt,{path:`/templates`,element:(0,R.jsx)(Cc,{})})]})})}(0,v.createRoot)(document.getElementById(`root`)).render((0,R.jsx)(_.StrictMode,{children:(0,R.jsx)(ep,{})}));
|
package/dist/public/index.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>app</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-DU5On5Al.js"></script>
|
|
9
9
|
<link rel="stylesheet" crossorigin href="/assets/index-ByoBtx7P.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
package/dist/routes/delete.js
CHANGED
|
@@ -2,6 +2,7 @@ import { Router } from 'express';
|
|
|
2
2
|
import { getAuthToken } from '../auth.js';
|
|
3
3
|
import { API_URL, warnIfNonDefaultApiUrl } from '../config.js';
|
|
4
4
|
import { getUploadedState, clearUploadedState, saveUploadedState, loadEnhancedData, saveEnhancedData, } from '../settings.js';
|
|
5
|
+
import { toSlug } from '../format-utils.js';
|
|
5
6
|
function sendError(res, status, error) {
|
|
6
7
|
res.status(status).json({ error });
|
|
7
8
|
}
|
|
@@ -139,7 +140,23 @@ export function createDeleteRouter(_ctx) {
|
|
|
139
140
|
return;
|
|
140
141
|
}
|
|
141
142
|
try {
|
|
142
|
-
|
|
143
|
+
// Phoenix DELETE /api/sessions/:id expects an integer share ID,
|
|
144
|
+
// which the CLI never has — POST /api/sessions returns a token,
|
|
145
|
+
// not the DB row id. So we send the Claude UUID in the path
|
|
146
|
+
// (Phoenix accepts it as an opaque marker) and the real lookup
|
|
147
|
+
// key — (project_id, slug) — in query params. The server resolves
|
|
148
|
+
// by (project_id, slug) when the path :id isn't a valid integer.
|
|
149
|
+
const uploadedState = getUploadedState(project);
|
|
150
|
+
const enhanced = loadEnhancedData(sessionId);
|
|
151
|
+
const slug = toSlug(enhanced?.title ?? sessionId, 80);
|
|
152
|
+
const serverProjectId = uploadedState?.projectId;
|
|
153
|
+
const query = new URLSearchParams();
|
|
154
|
+
if (serverProjectId !== undefined)
|
|
155
|
+
query.set('project_id', String(serverProjectId));
|
|
156
|
+
if (slug)
|
|
157
|
+
query.set('slug', slug);
|
|
158
|
+
const qs = query.toString();
|
|
159
|
+
const phoenixRes = await fetch(`${API_URL}/api/sessions/${encodeURIComponent(sessionId)}${qs ? `?${qs}` : ''}`, {
|
|
143
160
|
method: 'DELETE',
|
|
144
161
|
headers: { Authorization: `Bearer ${auth.token}` },
|
|
145
162
|
});
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { readFileSync } from 'node:fs';
|
|
6
6
|
import { API_URL } from '../config.js';
|
|
7
|
-
import { loadEnhancedData, saveEnhancedData, getDefaultTemplate, isTranscriptIncluded, } from '../settings.js';
|
|
7
|
+
import { loadEnhancedData, saveEnhancedData, getDefaultTemplate, isTranscriptIncluded, getUploadedState, } from '../settings.js';
|
|
8
8
|
import { redactSession, redactText, scanTextSync, formatFindings, stripHomePathsInText } from '../redact.js';
|
|
9
9
|
import { renderSessionHtml } from '../render/index.js';
|
|
10
10
|
import { buildSessionRenderData, buildSessionCard } from '../render/build-render-data.js';
|
|
@@ -222,3 +222,65 @@ export async function uploadSelectedSessions(ctx, auth, options) {
|
|
|
222
222
|
}
|
|
223
223
|
return { uploadedCount, failedSessions, uploadedSessionCards };
|
|
224
224
|
}
|
|
225
|
+
/**
|
|
226
|
+
* Delete previously-uploaded sessions that are no longer in the user's
|
|
227
|
+
* selected set. Called before re-uploading so the published portfolio
|
|
228
|
+
* reflects deselections made through the Manage Sessions modal.
|
|
229
|
+
*
|
|
230
|
+
* Identifies each session on the server by (project_id, slug) — the same
|
|
231
|
+
* fallback contract used by the single-session trash button. Failures
|
|
232
|
+
* are logged but non-fatal: the upload continues so partial cleanup
|
|
233
|
+
* doesn't block the user's primary action.
|
|
234
|
+
*/
|
|
235
|
+
export async function demoteRemovedSessions(auth, options) {
|
|
236
|
+
const { projectDirName, selectedSessionIds, send } = options;
|
|
237
|
+
const notify = send ?? (() => { });
|
|
238
|
+
const uploaded = getUploadedState(projectDirName);
|
|
239
|
+
if (!uploaded || !uploaded.projectId) {
|
|
240
|
+
return { demotedCount: 0, failed: [] };
|
|
241
|
+
}
|
|
242
|
+
const selected = new Set(selectedSessionIds);
|
|
243
|
+
const removed = (uploaded.uploadedSessions ?? []).filter((id) => !selected.has(id));
|
|
244
|
+
if (removed.length === 0) {
|
|
245
|
+
return { demotedCount: 0, failed: [] };
|
|
246
|
+
}
|
|
247
|
+
let demotedCount = 0;
|
|
248
|
+
const failed = [];
|
|
249
|
+
for (const sessionId of removed) {
|
|
250
|
+
const enhanced = loadEnhancedData(sessionId);
|
|
251
|
+
const slug = toSlug(enhanced?.title ?? sessionId, 80);
|
|
252
|
+
notify({ type: 'session', sessionId, status: 'demoting' });
|
|
253
|
+
try {
|
|
254
|
+
const query = new URLSearchParams({
|
|
255
|
+
project_id: String(uploaded.projectId),
|
|
256
|
+
slug,
|
|
257
|
+
});
|
|
258
|
+
const res = await fetch(`${API_URL}/api/sessions/${encodeURIComponent(sessionId)}?${query.toString()}`, {
|
|
259
|
+
method: 'DELETE',
|
|
260
|
+
headers: { Authorization: `Bearer ${auth.token}` },
|
|
261
|
+
});
|
|
262
|
+
if (res.status === 204 || res.status === 404) {
|
|
263
|
+
// 404 = already gone server-side; either way, the local state
|
|
264
|
+
// should reflect "not uploaded" so the next re-publish doesn't
|
|
265
|
+
// try to demote it again.
|
|
266
|
+
if (enhanced?.uploaded) {
|
|
267
|
+
saveEnhancedData(sessionId, { ...enhanced, uploaded: false });
|
|
268
|
+
}
|
|
269
|
+
demotedCount++;
|
|
270
|
+
notify({ type: 'session', sessionId, status: 'demoted' });
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
const body = await res.text().catch(() => '');
|
|
274
|
+
const error = `HTTP ${res.status}: ${body.slice(0, 200)}`;
|
|
275
|
+
failed.push({ sessionId, error });
|
|
276
|
+
notify({ type: 'session', sessionId, status: 'demote_failed', error });
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
catch (err) {
|
|
280
|
+
const error = err.message;
|
|
281
|
+
failed.push({ sessionId, error });
|
|
282
|
+
notify({ type: 'session', sessionId, status: 'demote_failed', error });
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
return { demotedCount, failed };
|
|
286
|
+
}
|
package/dist/routes/publish.js
CHANGED
|
@@ -12,7 +12,7 @@ import { buildProjectDetail } from './context.js';
|
|
|
12
12
|
import { captureScreenshot } from '../screenshot.js';
|
|
13
13
|
import { renderProjectHtml } from '../render/index.js';
|
|
14
14
|
import { buildProjectRenderData } from '../render/build-render-data.js';
|
|
15
|
-
import { uploadSelectedSessions } from './project-session-upload.js';
|
|
15
|
+
import { uploadSelectedSessions, demoteRemovedSessions } from './project-session-upload.js';
|
|
16
16
|
import { invalidatePortfolioPreviewCache } from './preview.js';
|
|
17
17
|
import { startSSE } from './sse.js';
|
|
18
18
|
import { displayNameFromDir } from '../sync.js';
|
|
@@ -105,7 +105,7 @@ export function createPublishRouter(ctx) {
|
|
|
105
105
|
});
|
|
106
106
|
// Publish project -- SSE stream with per-session progress
|
|
107
107
|
router.post('/api/projects/:project/upload', async (req, res) => {
|
|
108
|
-
const
|
|
108
|
+
const project = String(req.params.project);
|
|
109
109
|
const auth = getAuthToken();
|
|
110
110
|
warnIfNonDefaultApiUrl();
|
|
111
111
|
if (!auth) {
|
|
@@ -114,11 +114,11 @@ export function createPublishRouter(ctx) {
|
|
|
114
114
|
}
|
|
115
115
|
const { title: rawTitle, slug: rawSlug, narrative, repoUrl, projectUrl, timeline, skills, totalSessions, totalLoc, totalDurationMinutes, totalAgentDurationMinutes, totalFilesChanged, skippedSessions, selectedSessionIds, screenshotBase64, } = req.body;
|
|
116
116
|
// Ensure slug is the short project name, not the full encoded directory path
|
|
117
|
-
const shortName = displayNameFromDir(
|
|
117
|
+
const shortName = displayNameFromDir(project);
|
|
118
118
|
const baseSlug = toSlug(shortName);
|
|
119
119
|
const title = rawTitle === rawSlug ? shortName : rawTitle;
|
|
120
120
|
// Get stable project UUID from CLI database
|
|
121
|
-
const clientProjectId = getProjectUuid(ctx.db,
|
|
121
|
+
const clientProjectId = getProjectUuid(ctx.db, project);
|
|
122
122
|
const send = startSSE(res);
|
|
123
123
|
try {
|
|
124
124
|
// Step 1: Upsert project on Phoenix (with slug conflict retry)
|
|
@@ -248,6 +248,17 @@ export function createPublishRouter(ctx) {
|
|
|
248
248
|
const failedSessions = [];
|
|
249
249
|
let uploadedSessionCards = [];
|
|
250
250
|
if (proj) {
|
|
251
|
+
// Honor Manage Sessions deselections: remove server-side sessions
|
|
252
|
+
// that were previously uploaded but are no longer in the
|
|
253
|
+
// selection. Failures are non-fatal — proceed with the upload.
|
|
254
|
+
const demoteResult = await demoteRemovedSessions(auth, {
|
|
255
|
+
projectDirName: project,
|
|
256
|
+
selectedSessionIds,
|
|
257
|
+
send,
|
|
258
|
+
});
|
|
259
|
+
if (demoteResult.failed.length > 0) {
|
|
260
|
+
console.warn(`[upload] ${demoteResult.failed.length} session(s) could not be removed from heyi.am`);
|
|
261
|
+
}
|
|
251
262
|
const sessionResult = await uploadSelectedSessions(ctx, auth, {
|
|
252
263
|
proj,
|
|
253
264
|
projectData,
|
|
@@ -530,6 +541,18 @@ export function createPublishRouter(ctx) {
|
|
|
530
541
|
slugMap.set(baseSlug, projectData.slug);
|
|
531
542
|
}
|
|
532
543
|
send({ type: 'project', project: title, index: projectIndex, total: filteredProjects.length, status: 'created' });
|
|
544
|
+
// Honor Manage Sessions deselections before re-uploading: remove
|
|
545
|
+
// server-side sessions that were previously uploaded but aren't
|
|
546
|
+
// in the current `selectedSessionIds`. Without this step, the
|
|
547
|
+
// bulk-status PATCH below silently re-lists everything.
|
|
548
|
+
const demoteResult = await demoteRemovedSessions(auth, {
|
|
549
|
+
projectDirName: rawProj.dirName,
|
|
550
|
+
selectedSessionIds,
|
|
551
|
+
send: (evt) => send({ ...evt, project: title }),
|
|
552
|
+
});
|
|
553
|
+
if (demoteResult.failed.length > 0) {
|
|
554
|
+
console.warn(`[portfolio-upload] ${title}: ${demoteResult.failed.length} session(s) could not be removed from heyi.am`);
|
|
555
|
+
}
|
|
533
556
|
send({ type: 'progress', message: `Uploading ${selectedSessionIds.length} session${selectedSessionIds.length === 1 ? '' : 's'} for ${title}…` });
|
|
534
557
|
const { uploadedSessionCards } = await uploadSelectedSessions(ctx, auth, {
|
|
535
558
|
proj: projInfo,
|
package/dist/routes/sessions.js
CHANGED
|
@@ -2,23 +2,48 @@ import { Router } from 'express';
|
|
|
2
2
|
import { listSessions, parseSession } from '../parsers/index.js';
|
|
3
3
|
import { bridgeToAnalyzer } from '../bridge.js';
|
|
4
4
|
import { analyzeSession } from '../analyzer.js';
|
|
5
|
-
import { getSessionRow } from '../db.js';
|
|
5
|
+
import { getSessionRow, getAllSessionMetas } from '../db.js';
|
|
6
6
|
import { ensureSessionIndexed } from '../sync.js';
|
|
7
7
|
import { exportSessionContext } from '../context-export.js';
|
|
8
8
|
import { buildTranscriptResponse } from '../transcript.js';
|
|
9
9
|
import { loadEnhancedData } from '../settings.js';
|
|
10
|
+
import { toSlug } from '../format-utils.js';
|
|
10
11
|
import { displayNameFromDir } from './context.js';
|
|
11
12
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
13
|
+
* Resolve an :id param to a real session. Accepts either:
|
|
14
|
+
* - A canonical UUID (the path used by SPA links built from session.id)
|
|
15
|
+
* - A title-derived slug, optionally with a ".html" suffix (the path
|
|
16
|
+
* baked into rendered Liquid HTML — used when a user lands on a
|
|
17
|
+
* session URL directly via refresh, bookmark, or modifier-click that
|
|
18
|
+
* slipped past the SPA's click interceptor)
|
|
19
|
+
*
|
|
20
|
+
* Falls back to live discovery on a UUID miss, mirroring the original
|
|
21
|
+
* behavior. Slug resolution is DB-only because the slug source-of-truth
|
|
22
|
+
* is the enhanced title, which lives in the local-state store.
|
|
14
23
|
*/
|
|
15
|
-
async function resolveSession(ctx,
|
|
16
|
-
|
|
24
|
+
async function resolveSession(ctx, rawId) {
|
|
25
|
+
const id = rawId.replace(/\.html$/, '');
|
|
26
|
+
// 1. Try DB by UUID
|
|
17
27
|
const row = getSessionRow(ctx.db, id);
|
|
18
28
|
if (row?.file_path) {
|
|
19
|
-
return { filePath: row.file_path, projectName: displayNameFromDir(row.project_dir) };
|
|
29
|
+
return { filePath: row.file_path, projectName: displayNameFromDir(row.project_dir), sessionId: id };
|
|
20
30
|
}
|
|
21
|
-
//
|
|
31
|
+
// 2. Try DB by title-derived slug
|
|
32
|
+
const slugTarget = toSlug(id, 80);
|
|
33
|
+
if (slugTarget) {
|
|
34
|
+
const metas = getAllSessionMetas(ctx.db);
|
|
35
|
+
for (const meta of metas) {
|
|
36
|
+
if (meta.isSubagent)
|
|
37
|
+
continue;
|
|
38
|
+
const enhanced = loadEnhancedData(meta.sessionId);
|
|
39
|
+
const titleRow = getSessionRow(ctx.db, meta.sessionId);
|
|
40
|
+
const title = enhanced?.title ?? titleRow?.title ?? meta.sessionId;
|
|
41
|
+
if (toSlug(title, 80) === slugTarget) {
|
|
42
|
+
return { filePath: meta.path, projectName: displayNameFromDir(meta.projectDir), sessionId: meta.sessionId };
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// 3. Fallback: discover live sessions and index the match (UUID only)
|
|
22
47
|
const allSessions = await listSessions(ctx.sessionsBasePath);
|
|
23
48
|
const meta = allSessions.find((s) => s.sessionId === id);
|
|
24
49
|
if (!meta)
|
|
@@ -28,7 +53,7 @@ async function resolveSession(ctx, id) {
|
|
|
28
53
|
await ensureSessionIndexed(ctx.db, meta, projectName);
|
|
29
54
|
}
|
|
30
55
|
catch { /* best effort */ }
|
|
31
|
-
return { filePath: meta.path, projectName };
|
|
56
|
+
return { filePath: meta.path, projectName, sessionId: id };
|
|
32
57
|
}
|
|
33
58
|
export function createSessionsRouter(ctx) {
|
|
34
59
|
const router = Router();
|
|
@@ -41,7 +66,7 @@ export function createSessionsRouter(ctx) {
|
|
|
41
66
|
res.status(404).json({ error: { code: 'SESSION_NOT_FOUND', message: 'Session not found' } });
|
|
42
67
|
return;
|
|
43
68
|
}
|
|
44
|
-
const session = await ctx.loadSession(resolved.filePath, resolved.projectName,
|
|
69
|
+
const session = await ctx.loadSession(resolved.filePath, resolved.projectName, resolved.sessionId);
|
|
45
70
|
res.json({ session });
|
|
46
71
|
}
|
|
47
72
|
catch (err) {
|
|
@@ -59,12 +84,12 @@ export function createSessionsRouter(ctx) {
|
|
|
59
84
|
return;
|
|
60
85
|
}
|
|
61
86
|
const parsed = await parseSession(resolved.filePath);
|
|
62
|
-
const analyzerInput = bridgeToAnalyzer(parsed, { sessionId:
|
|
87
|
+
const analyzerInput = bridgeToAnalyzer(parsed, { sessionId: resolved.sessionId, projectName: resolved.projectName });
|
|
63
88
|
let session = analyzeSession(analyzerInput);
|
|
64
89
|
const turns = analyzerInput.turns;
|
|
65
90
|
// Merge enhanced data (LLM-generated title, context, developer take,
|
|
66
91
|
// execution steps, Q&A) when available — hybrid output
|
|
67
|
-
const enhanced = loadEnhancedData(
|
|
92
|
+
const enhanced = loadEnhancedData(resolved.sessionId);
|
|
68
93
|
if (enhanced) {
|
|
69
94
|
session = {
|
|
70
95
|
...session,
|
package/dist/sync.js
CHANGED
|
@@ -12,7 +12,7 @@ import { analyzeSession } from './analyzer.js';
|
|
|
12
12
|
import { isSessionStale, indexSession, rebuildIndex, optimizeFtsIndex, } from './db.js';
|
|
13
13
|
import { renderCompact } from './context-export.js';
|
|
14
14
|
import { getArchiveDir } from './settings.js';
|
|
15
|
-
import { displayNameFromDir } from './format-utils.js';
|
|
15
|
+
import { displayNameFromDir, projectDirFromPath } from './format-utils.js';
|
|
16
16
|
export { displayNameFromDir } from './format-utils.js';
|
|
17
17
|
let _syncState = {
|
|
18
18
|
status: 'idle',
|
|
@@ -216,18 +216,8 @@ async function handleFileChange(db, filePath) {
|
|
|
216
216
|
const parentDirName = basename(dirname(filePath));
|
|
217
217
|
// Detect subagent: path contains /subagents/ directory
|
|
218
218
|
const isSubagent = parentDirName === 'subagents';
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
if (isSubagent) {
|
|
222
|
-
// .../projects/{projectDir}/{parentSessionId}/subagents/{agentId}.jsonl
|
|
223
|
-
const sessionDataDir = dirname(dirname(filePath)); // up past subagents/
|
|
224
|
-
parentSessionId = basename(sessionDataDir);
|
|
225
|
-
projectDir = basename(dirname(sessionDataDir));
|
|
226
|
-
}
|
|
227
|
-
else {
|
|
228
|
-
// .../projects/{projectDir}/{sessionId}.jsonl
|
|
229
|
-
projectDir = parentDirName;
|
|
230
|
-
}
|
|
219
|
+
const projectDir = projectDirFromPath(filePath, isSubagent);
|
|
220
|
+
const parentSessionId = isSubagent ? basename(dirname(dirname(filePath))) : undefined;
|
|
231
221
|
const projectName = displayNameFromDir(projectDir);
|
|
232
222
|
const meta = {
|
|
233
223
|
path: filePath,
|