@smoose/asc 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,115 @@
1
+ # ASC
2
+
3
+ ASC(Agent Session Clean)是一个 Pi、Claude Code、Antigravity、Codex、Grok 和 OpenCode session 管理器,用项目组织、查看和删除本机 session。
4
+
5
+ ## 安装
6
+
7
+ ASC 以 npm 包发布,运行需要 Bun 1.3.0 或更高版本:
8
+
9
+ ```bash
10
+ bun add --global @smoose/asc
11
+ asc
12
+ ```
13
+
14
+ 也可以使用 npm 安装:
15
+
16
+ ```bash
17
+ npm install --global @smoose/asc
18
+ ```
19
+
20
+ ## 开发运行
21
+
22
+ ```bash
23
+ bun install
24
+ bun run dev
25
+ ```
26
+
27
+ 本机也可以编译当前平台的独立二进制,但它不是主要发布方式:
28
+
29
+ ```bash
30
+ bun run compile
31
+ ./dist/asc-<os>-<arch>
32
+ ```
33
+
34
+ 覆盖 Pi session 目录:
35
+
36
+ ```bash
37
+ bun run src/main.tsx --pi-sessions-dir /path/to/sessions
38
+ ASC_PI_SESSIONS_DIR=/path/to/sessions bun run src/main.tsx
39
+ ```
40
+
41
+ 覆盖 Codex rollout 目录:
42
+
43
+ ```bash
44
+ bun run src/main.tsx --codex-sessions-dir /path/to/sessions
45
+ ASC_CODEX_SESSIONS_DIR=/path/to/sessions bun run src/main.tsx
46
+ ```
47
+
48
+ 覆盖 OpenCode 数据目录:
49
+
50
+ ```bash
51
+ bun run src/main.tsx --opencode-data-dir /path/to/opencode
52
+ ASC_OPENCODE_DATA_DIR=/path/to/opencode bun run src/main.tsx
53
+ ```
54
+
55
+ 覆盖 Claude Code session 目录:
56
+
57
+ ```bash
58
+ bun run src/main.tsx --claude-code-sessions-dir /path/to/projects
59
+ ASC_CLAUDE_CODE_SESSIONS_DIR=/path/to/projects bun run src/main.tsx
60
+ ```
61
+
62
+ 覆盖 Antigravity 数据目录:
63
+
64
+ ```bash
65
+ bun run src/main.tsx --antigravity-data-dir /path/to/antigravity-cli
66
+ ASC_ANTIGRAVITY_DATA_DIR=/path/to/antigravity-cli bun run src/main.tsx
67
+ ```
68
+
69
+ 覆盖 Grok session 目录:
70
+
71
+ ```bash
72
+ bun run src/main.tsx --grok-sessions-dir /path/to/sessions
73
+ ASC_GROK_SESSIONS_DIR=/path/to/sessions bun run src/main.tsx
74
+ ```
75
+
76
+ Codex 默认读取 `~/.codex/sessions`,也会根据 `CODEX_HOME` 读取 `$CODEX_HOME/sessions`。OpenCode 默认读取 `~/.local/share/opencode`(可用 `OPENCODE_DATA_DIR` 或 `XDG_DATA_HOME` 覆盖)。Claude Code 默认读取 `~/.claude/projects`(可用 `CLAUDE_CONFIG_DIR` 覆盖配置根目录)。Antigravity 默认读取 `~/.gemini/antigravity-cli`(可用 `GEMINI_HOME` 覆盖配置根目录)。Grok 默认读取 `~/.grok/sessions`(可用 `GROK_HOME` 覆盖配置根目录)。顶部 Agent 选择器可以在已接入的 Agent 之间切换。
77
+
78
+ 本地开发也可以使用 `asc` 命令:
79
+
80
+ ```bash
81
+ bun link
82
+ asc
83
+ ```
84
+
85
+ ## 快捷键
86
+
87
+ - `↑` / `↓`、`j` / `k`:移动
88
+ - `Tab` / `Shift+Tab`:切换焦点
89
+ - `1` / `2` / `3`:聚焦项目、session、详情
90
+ - `Space`:在 Session 列表中切换多选状态
91
+ - `d`:删除当前 session、已选 session 或当前项目
92
+ - `/`:搜索
93
+ - `r`:重新扫描
94
+ - `s`:切换排序
95
+ - `?`:帮助
96
+ - `q`:退出
97
+
98
+ ASC 不联网。删除操作会永久删除 session,无法撤销。Pi、Claude Code 和 Codex 扫描本地 JSONL;Grok 扫描 `summary.json` 并删除整个 session 目录;Antigravity 扫描 `conversation_summaries.db` 并删除对应 conversation 文件;OpenCode 扫描本地 `opencode.db`,删除时会去掉对应数据库行和 `storage` 文件。
99
+
100
+ 发布新版本时,先更新 `package.json` 的版本号,再创建并推送 `v*` tag。GitHub Actions 会运行检查并使用 `NPM_TOKEN` 发布到 npm。
101
+
102
+ ## 架构
103
+
104
+ - `domain/`:Agent 无关的项目、session、扫描、选择和操作类型。
105
+ - `application/`:扫描、详情、删除用例,以及 scanner/parser/deleter 统一接口。
106
+ - `adapters/`:每个 Agent 自己实现 scanner、parser 和 deleter。
107
+ - `store/`:TUI 状态、焦点、过滤、选择和异步操作状态。
108
+ - `components/`:只依赖统一状态和领域模型,不访问文件系统或 Agent 格式。
109
+
110
+ ## 开发
111
+
112
+ ```bash
113
+ bun run typecheck
114
+ bun test
115
+ ```
package/bin/asc.js ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env bun
2
+
3
+ import "@opentui/solid/preload"
4
+
5
+ await import("../dist/npm/main.js")
@@ -0,0 +1,10 @@
1
+ // @bun
2
+ import{createComponent as Sa}from"@opentui/solid";import{render as ya}from"@opentui/solid";import Ws from"os";import Qe from"path";function $(e){let t=Qe.isAbsolute(e)?e:Qe.resolve(e);return Qe.normalize(t)}function Ie(e){let t=Qe.normalize(Ws.homedir()),r=Qe.normalize(e);if(r===t)return"~";if(r.startsWith(`${t}${Qe.sep}`))return`~${r.slice(t.length)}`;return r}function Ce(e,t){let r=$(e);return t?`project:${t}:${r}`:`project:${r}`}import{lstat as Vs,realpath as cn,rm as dn}from"fs/promises";import et from"path";import{constants as nn,Database as ir}from"bun:sqlite";import{lstat as on}from"fs/promises";import{pathToFileURL as Hs}from"url";async function sn(e){try{return await on(e),!0}catch{return!1}}async function Ke(e,t){await on(e);let r=e,n=!1;if(t){let[s,o]=await Promise.all([sn(`${e}-wal`),sn(`${e}-shm`)]);if(!s&&!o)r=`${Hs(e).href}?immutable=1`,n=!0}let i=n?new ir(r,nn.SQLITE_OPEN_READONLY|nn.SQLITE_OPEN_URI):t?new ir(r,{readonly:!0,create:!1}):new ir(r);return i.run("PRAGMA busy_timeout = 3000"),i}function Ye(e){let t=e.query("SELECT name FROM sqlite_master WHERE type = 'table'").all();return new Set(t.map((r)=>r.name))}import qs from"os";import Ot from"path";function an(){if(process.env.ASC_ANTIGRAVITY_DATA_DIR)return $(process.env.ASC_ANTIGRAVITY_DATA_DIR);let e=process.env.GEMINI_HOME||Ot.join(qs.homedir(),".gemini");return Ot.join(e,"antigravity-cli")}function $e(e){return Ot.join(e,"conversation_summaries.db")}function Ze(e){return Ot.join(e,"conversations")}var Tt=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function Nt(e){if(!e)return;let t=e;try{let r=JSON.parse(e);t=Array.isArray(r)?r[0]:r}catch{}if(typeof t!=="string"||t.length===0)return;if(t.startsWith("file://"))try{return decodeURIComponent(t.slice(7))}catch{return t.slice(7)}return t}function Xs(e,t){let r=et.relative(e,t);return r.length>0&&!r.startsWith(`..${et.sep}`)&&r!==".."&&!et.isAbsolute(r)}async function ar(e,t){let r;try{r=await cn(t)}catch{try{await dn(t,{recursive:!0,force:!0})}catch{}return}if(!Xs(e,r)&&r!==e)return;await dn(r,{recursive:!0,force:!0})}class dr{dataDir;constructor(e){this.dataDir=e}async deleteSessions(e,t){let r=[],n;try{n=await cn(this.dataDir)}catch(o){return{items:e.map((l)=>({sessionId:l.id,success:!1,message:`Cannot access Antigravity data directory: ${o instanceof Error?o.message:String(o)}`}))}}let i=$e(this.dataDir);try{if(!(await Vs(i)).isFile())return{items:e.map((l)=>({sessionId:l.id,success:!1,message:"Antigravity summaries database path is not a file"}))}}catch(o){return{items:e.map((l)=>({sessionId:l.id,success:!1,message:o instanceof Error?o.message:String(o)}))}}let s=await Ke(i,!1);try{let o=Ye(s),l=Ze(n);for(let a of e){if(t?.signal?.aborted)throw new DOMException("Delete aborted","AbortError");if(a.agentId!=="antigravity"||a.ref.agentId!=="antigravity"){r.push({sessionId:a.id,success:!1,message:"Session belongs to another agent"});continue}let d=a.ref.sourceId;if(!Tt.test(d)){r.push({sessionId:a.id,success:!1,message:"Invalid Antigravity session id"});continue}for(let c of[`${d}.db`,`${d}.db-wal`,`${d}.db-shm`,`${d}.pb`])await ar(n,et.join(l,c));if(await ar(n,et.join(n,"brain",d)),await ar(n,et.join(n,"presence",`${d}.lock`)),o.has("conversation_summaries"))try{s.query("DELETE FROM conversation_summaries WHERE conversation_id = ?").run(d)}catch(c){r.push({sessionId:a.id,success:!1,message:c instanceof Error?c.message:String(c)});continue}r.push({sessionId:a.id,success:!0})}}finally{s.close()}return{items:r}}}import{createReadStream as Ys}from"fs";import{lstat as Zs}from"fs/promises";import{createInterface as eo}from"readline";import ln from"path";var Qs=/[\u001B\u009B][[\]()#;?]*(?:(?:(?:[a-zA-Z\d]*(?:;[-a-zA-Z\d/#&.:=?%@~_]+)*)?\u0007)|(?:(?:\d{1,4}(?:[;:]\d{0,4})*)?[\dA-PR-TZcf-nq-uy=><~]))/g;function Ks(e){return e.replace(Qs,"")}function cr(e){return Ks(e).replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]/g," ").replace(/\s+/g," ").trim()}function N(e,t){let r=cr(e);if(r.length<=t)return r;if(t<=1)return r.slice(0,t);return`${r.slice(0,t-1).trimEnd()}\u2026`}function to(e){return e&&typeof e==="object"&&!Array.isArray(e)?e:void 0}async function ro(e,t,r){let n=ln.join(e,"history.jsonl");try{await Zs(n)}catch{return{}}let i=Ys(n,{encoding:"utf8",signal:r}),s=eo({input:i,crlfDelay:1/0}),o,l;try{for await(let a of s){if(r?.aborted)throw new DOMException("Scan aborted","AbortError");let d;try{d=JSON.parse(a)}catch{continue}let c=to(d);if(!c||c.conversationId!==t)continue;let u=typeof c.display==="string"?c.display.trim():"";if(!u)continue;let g=N(u,1000);o??=g,l=g}}finally{s.close(),i.destroy()}return{firstUserMessage:o,lastUserMessage:l}}class lr{dataDir;constructor(e){this.dataDir=e}async parseSummary(e){let t=await this.loadFromDb(e.ref.sourceId);return{sessionId:t.sessionId,projectLocation:t.projectLocation,title:t.title,messageCount:void 0,providerModels:[],warnings:t.warnings,detailFields:[{label:"Source",value:e.locator}]}}async loadDetail(e,t){if(t?.aborted)throw new DOMException("Scan aborted","AbortError");let r=await this.loadFromDb(e.ref.sourceId,t),n=[...new Set([...e.warnings,...r.warnings])];return{...e,sessionId:r.sessionId||e.sessionId,projectLocation:r.projectLocation??e.projectLocation,title:N(r.title||e.title,160)||e.title,messageCount:r.messageCount??e.messageCount,firstUserMessage:r.firstUserMessage,lastUserMessage:r.lastUserMessage,providerModels:r.providerModels.length>0?r.providerModels:e.providerModels,warnings:n,fields:r.fields,warningCount:n.length}}async loadFromDb(e,t){let r=[],n=$e(this.dataDir),i=ln.join(Ze(this.dataDir),`${e}.db`),s;try{let g=await Ke(n,!0);try{if(Ye(g).has("conversation_summaries"))s=g.query("SELECT conversation_id, title, preview, step_count, last_modified_time, workspace_uris, project_id, agent_name FROM conversation_summaries WHERE conversation_id = ?").get(e);else r.push("Antigravity database has no conversation_summaries table")}finally{g.close()}}catch(g){r.push(`Unable to read Antigravity summaries: ${g instanceof Error?g.message:String(g)}`)}let o=Nt(s?.workspace_uris),l=s?.title&&s.title.trim()||s?.preview&&s.preview.trim()||e,a=await ro(this.dataDir,e,t),d=a.firstUserMessage??(s?.preview?.trim()||void 0),c=a.lastUserMessage??d,u=[{label:"Source",value:i}];if(o)u.push({label:"Workspace",value:o});if(s?.project_id)u.push({label:"Project id",value:s.project_id});if(s?.agent_name)u.push({label:"Agent",value:s.agent_name});if(s?.step_count!=null)u.push({label:"Steps",value:String(s.step_count)});return{sessionId:s?.conversation_id??e,projectLocation:o,title:l,updatedAt:s?.last_modified_time??void 0,messageCount:s?.step_count??void 0,firstUserMessage:d,lastUserMessage:c,providerModels:s?.agent_name?[s.agent_name]:[],warnings:r,fields:u}}}import{lstat as mn}from"fs/promises";import _t from"path";function no(e){if(!e||e.startsWith("0001-"))return;let t=Date.parse(e);return Number.isFinite(t)?new Date(t).toISOString():void 0}function Ft(e){if(!e)return 0;let t=Date.parse(e);return Number.isFinite(t)?t:0}function un(e){return e.sort((t,r)=>Ft(r.updatedAt)-Ft(t.updatedAt))}async function so(e,t){let r=Ze(e);for(let n of[`${t}.db`,`${t}.pb`]){let i=_t.join(r,n);try{let s=await mn(i);if(s.isFile())return{path:i,sizeBytes:s.size}}catch{}}return}class ur{rootPath;constructor(e){this.rootPath=e}async detect(){let e=$e(this.rootPath);try{if(!(await mn(e)).isFile())return{available:!1,location:e,reason:"Antigravity summaries database path is not a file"};return{available:!0,location:this.rootPath}}catch(t){return{available:!1,location:this.rootPath,reason:t instanceof Error?t.message:String(t)}}}async scan(e){if(e?.signal?.aborted)throw new DOMException("Scan aborted","AbortError");let t=$e(this.rootPath),r;try{r=await Ke(t,!0)}catch(n){return{agentId:"antigravity",rootPath:_t.resolve(this.rootPath),projects:[],sessions:[],issues:[{location:t,message:n instanceof Error?n.message:String(n),severity:"error"}],scannedSources:0,failedSources:0}}try{if(!Ye(r).has("conversation_summaries"))return{agentId:"antigravity",rootPath:_t.resolve(this.rootPath),projects:[],sessions:[],issues:[{location:t,message:"Antigravity database has no conversation_summaries table",severity:"error"}],scannedSources:0,failedSources:0};let i=r.query("SELECT conversation_id, title, preview, step_count, last_modified_time, workspace_uris, project_id, agent_name FROM conversation_summaries").all(),s=[];for(let l of i){if(e?.signal?.aborted)throw new DOMException("Scan aborted","AbortError");if(!Tt.test(l.conversation_id))continue;let a=await so(this.rootPath,l.conversation_id);if(!a)continue;let d=Nt(l.workspace_uris)||(l.project_id&&l.project_id!=="default-cli-project"?l.project_id:"unknown"),c=d==="unknown"||d==="outside-of-project"?d:$(d),u=no(l.last_modified_time)??new Date(0).toISOString(),g=l.title&&l.title.trim()||l.preview&&l.preview.trim()||l.conversation_id;s.push({id:`session:antigravity:${l.conversation_id}`,ref:{agentId:"antigravity",sourceId:l.conversation_id},agentId:"antigravity",sessionId:l.conversation_id,projectId:Ce(c,"antigravity"),projectName:Ie(c),projectLocation:c,title:N(g,96)||l.conversation_id,updatedAt:u,sizeBytes:a.sizeBytes,messageCount:l.step_count??void 0,providerModels:l.agent_name?[l.agent_name]:[],warnings:[]})}let o=new Map;for(let l of s){let a=o.get(l.projectId);if(a){if(a.sessionCount+=1,a.totalSizeBytes+=l.sizeBytes??0,Ft(l.updatedAt)>Ft(a.updatedAt))a.updatedAt=l.updatedAt;continue}o.set(l.projectId,{id:l.projectId,agentId:"antigravity",name:l.projectName,location:l.projectLocation,displayPath:l.projectName,sessionCount:1,totalSizeBytes:l.sizeBytes??0,updatedAt:l.updatedAt,warningCount:0})}return{agentId:"antigravity",rootPath:_t.resolve(this.rootPath),projects:un([...o.values()]),sessions:un(s),issues:[],scannedSources:s.length,failedSources:0}}finally{r.close()}}}class mr{id="antigravity";info={id:"antigravity",label:"Antigravity",status:"available",capabilities:{canDelete:!0,canBulkDelete:!0}};dataDir;parser;scanner;deleter;constructor(e){this.dataDir=$(e??an()),this.info.detail=this.dataDir,this.parser=new lr(this.dataDir),this.scanner=new ur(this.dataDir),this.deleter=new dr(this.dataDir)}}import Do from"os";import xn from"path";import{realpath as Sn,rm as lo}from"fs/promises";import rt from"path";import{lstat as oo,readdir as gn,realpath as pn,rm as hn,unlink as io}from"fs/promises";import ve from"path";function fr(e,t){let r=ve.relative(e,t);return r.length>0&&!r.startsWith(`..${ve.sep}`)&&r!==".."&&!ve.isAbsolute(r)}function ao(e){return ve.extname(e).toLowerCase()===".jsonl"}async function fn(e,t,r){let n=t;while(fr(e,n)){if(r?.aborted)throw new DOMException("Delete aborted","AbortError");let i;try{i=await gn(n)}catch{return}if(i.length>0)return;try{await hn(n)}catch{return}n=ve.dirname(n)}}async function co(e,t,r){if(r.agentId!==e||r.ref.agentId!==e)return{sessionId:r.id,success:!1,message:"Session belongs to another agent"};let n=ve.resolve(r.ref.sourceId);try{let i=await oo(n);if(!i.isFile())return{sessionId:r.id,success:!1,message:"Session source is not a regular file"};if(r.sizeBytes!==void 0&&i.size!==r.sizeBytes||i.mtime.toISOString()!==r.updatedAt)return{sessionId:r.id,success:!1,message:"Session changed since the last scan"};let s=await pn(n);if(!fr(t,s))return{sessionId:r.id,success:!1,message:"Session is outside the configured session directory"};return{session:r,targetPath:n,resolvedTarget:s}}catch(i){let s=i.code;return{sessionId:r.id,success:!1,message:s==="ENOENT"?"Session source no longer exists":i instanceof Error?i.message:String(i)}}}async function tt(e,t,r,n){let i=[],s;try{s=await pn(t)}catch(a){return{items:r.map((d)=>({sessionId:d.id,success:!1,message:`Cannot access session directory: ${a instanceof Error?a.message:String(a)}`}))}}let o=[];for(let a of r){if(n?.signal?.aborted)throw new DOMException("Delete aborted","AbortError");let d=await co(e,s,a);if("success"in d)i.push(d);else o.push(d)}let l=new Map;for(let a of o){let d=ve.dirname(a.resolvedTarget),c=l.get(d)??[];c.push(a),l.set(d,c)}for(let[a,d]of l){if(n?.signal?.aborted)throw new DOMException("Delete aborted","AbortError");let c=new Set(d.map((p)=>ve.basename(p.resolvedTarget))),u;try{u=await gn(a,{withFileTypes:!0})}catch(p){i.push(...d.map((S)=>({sessionId:S.session.id,success:!1,message:p instanceof Error?p.message:String(p)})));continue}let g=u.some((p)=>p.isFile()&&ao(p.name)&&!c.has(p.name)),h=u.some((p)=>p.isDirectory());if(!g&&!h&&a!==s&&fr(s,a))try{await hn(a,{recursive:!0,force:!0}),i.push(...d.map((p)=>({sessionId:p.session.id,success:!0}))),await fn(s,ve.dirname(a),n?.signal);continue}catch(p){i.push(...d.map((S)=>({sessionId:S.session.id,success:!1,message:p instanceof Error?p.message:String(p)})));continue}for(let p of d){if(n?.signal?.aborted)throw new DOMException("Delete aborted","AbortError");try{await io(p.targetPath),i.push({sessionId:p.session.id,success:!0})}catch(S){let w=S.code;i.push({sessionId:p.session.id,success:!1,message:w==="ENOENT"?"Session source no longer exists":S instanceof Error?S.message:String(S)})}}await fn(s,a,n?.signal)}return{items:i}}var uo=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function mo(e,t){let r=rt.relative(e,t);return r.length>0&&!r.startsWith(`..${rt.sep}`)&&r!==".."&&!rt.isAbsolute(r)}class gr{rootPath;constructor(e){this.rootPath=e}async deleteSessions(e,t){let r=await tt("claude-code",this.rootPath,e,t),n=rt.dirname(rt.resolve(this.rootPath)),i;try{i=await Sn(n)}catch{return r}for(let s of r.items){if(!s.success)continue;let l=e.find((d)=>d.id===s.sessionId)?.sessionId;if(!l||!uo.test(l))continue;let a=rt.join(i,"file-history",l);try{let d=await Sn(a);if(!mo(i,d))continue;await lo(d,{recursive:!0,force:!0})}catch{}}return r}}import{createReadStream as fo}from"fs";import{createInterface as go}from"readline";import wt from"path";function vt(e){return e&&typeof e==="object"&&!Array.isArray(e)?e:void 0}function ce(e){return typeof e==="string"&&e.length>0?e:void 0}function nt(e,t){if(!e.includes(t))e.push(t)}function po(e,t){if(t&&!e.includes(t))e.push(t)}function yn(e){if(typeof e==="string")return e;if(!Array.isArray(e)){let r=vt(e);return ce(r?.text)??ce(r?.content)}return e.map((r)=>{if(typeof r==="string")return r;let n=vt(r);return ce(n?.text)}).filter((r)=>Boolean(r)).join(" ")||void 0}function ho(e){return e.includes("<command-name>")||e.includes("<command-message>")||e.includes("<local-command-caveat>")||e.includes("<local-command-stdout>")}function So(e){if(e.type!=="user"||e.isMeta===!0)return;let t=vt(e.message),r=yn(t?.content)??yn(e.content);if(!r||ho(r))return;return r}function yo(e){if(!e.startsWith("-"))return;return e.replaceAll("-","/")}async function wn(e,t,r="full"){let n={recordCount:0,messageCount:0,providerModels:[],warnings:[]},i=fo(e,{encoding:"utf8",signal:t}),s=go({input:i,crlfDelay:1/0});try{for await(let o of s){if(t?.aborted)throw new DOMException("Scan aborted","AbortError");n.recordCount+=1;let l;try{l=JSON.parse(o)}catch{nt(n.warnings,`Invalid JSON on line ${n.recordCount}`);continue}let a=vt(l);if(!a){nt(n.warnings,`Record ${n.recordCount} is not an object`);continue}n.sessionId??=ce(a.sessionId),n.projectPath??=ce(a.cwd),n.createdAt??=ce(a.timestamp),n.version??=ce(a.version);let d=ce(a.aiTitle)??ce(a.customTitle);if(d)n.title=d;if(r==="summary"){if(n.sessionId&&n.projectPath&&(n.title||n.recordCount>=16))break;continue}let c=So(a);if(c)n.messageCount+=1,n.firstUserMessage??=c,n.lastUserMessage=c,n.title??=c;else if(a.type==="user"||a.type==="assistant")n.messageCount+=1;let u=vt(a.message);po(n.providerModels,ce(u?.model)??ce(a.model))}}catch(o){if(o.code==="ABORT_ERR"||o.name==="AbortError")throw o;nt(n.warnings,`Unable to read session: ${o instanceof Error?o.message:String(o)}`)}finally{s.close(),i.destroy()}if(!n.sessionId){let o=wt.basename(e,wt.extname(e));if(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(o))n.sessionId=o}if(!n.projectPath)n.projectPath=yo(wt.basename(wt.dirname(e)));if(n.recordCount===0)nt(n.warnings,"Session file is empty");if(!n.sessionId)nt(n.warnings,"Claude Code session is missing id");if(!n.projectPath)nt(n.warnings,"Claude Code session is missing cwd");return n}function vn(e,t){let r=[{label:"Source",value:t}];if(e.version)r.push({label:"Claude Code version",value:e.version});if(r.push({label:"Records",value:String(e.recordCount)}),e.providerModels.length>0)r.push({label:"Provider / model",value:e.providerModels.join(", ")});return r}function wo(e,t,r="full"){return{sessionId:t.sessionId,projectLocation:t.projectPath,createdAt:t.createdAt,title:t.title??wt.basename(e.locator),messageCount:r==="summary"?void 0:t.messageCount,firstUserMessage:r==="summary"?void 0:t.firstUserMessage,lastUserMessage:r==="summary"?void 0:t.lastUserMessage,providerModels:r==="summary"?[]:t.providerModels,warnings:t.warnings,detailFields:r==="summary"?[{label:"Source",value:e.locator}]:vn(t,e.locator)}}class pr{async parseSummary(e,t){return wo(e,await wn(e.locator,t,"summary"),"summary")}async loadDetail(e,t){let r=await wn(e.ref.sourceId,t),n=[...new Set([...e.warnings,...r.warnings])];return{...e,sessionId:r.sessionId??e.sessionId,projectLocation:r.projectPath??e.projectLocation,title:N(r.title??e.title,160)||"Untitled session",createdAt:r.createdAt??e.createdAt,messageCount:r.messageCount,firstUserMessage:r.firstUserMessage,lastUserMessage:r.lastUserMessage,providerModels:r.providerModels,warnings:n,fields:vn(r,e.ref.sourceId),warningCount:n.length}}}import{lstat as xo}from"fs/promises";import{lstat as Ao}from"fs/promises";import An from"path";import{lstat as vo,readdir as bo}from"fs/promises";import hr from"path";async function bn(e,t,r){let n=[],i=[],s=hr.resolve(e),o;try{o=await vo(s)}catch(a){let d=a.code;return i.push({location:s,message:d==="ENOENT"?`${t} session directory does not exist`:`Cannot access ${t} session directory: ${a instanceof Error?a.message:String(a)}`,severity:"error"}),{files:n,issues:i}}if(!o.isDirectory())return i.push({location:s,message:`${t} session path is not a directory`,severity:"error"}),{files:n,issues:i};async function l(a){if(r?.aborted)throw new DOMException("Scan aborted","AbortError");let d;try{d=await bo(a,{withFileTypes:!0})}catch(c){i.push({location:a,message:`Cannot read directory: ${c instanceof Error?c.message:String(c)}`,severity:"error"});return}for(let c of d){if(r?.aborted)throw new DOMException("Scan aborted","AbortError");let u=hr.join(a,c.name);if(c.isSymbolicLink())continue;if(c.isDirectory()){await l(u);continue}if(!c.isFile())continue;if(hr.extname(c.name).toLowerCase()!==".jsonl")continue;n.push(u)}}return await l(s),n.sort(),{files:n,issues:i}}function Ut(e){if(!e)return 0;let t=Date.parse(e);return Number.isFinite(t)?t:0}function Pn(e){return e.sort((t,r)=>Ut(r.updatedAt)-Ut(t.updatedAt))}function Po(e){return e.startsWith("Invalid JSON")||e.includes("Unable to read")||e.startsWith("First record is not")}async function st(e,t,r,n,i={}){let s=await bn(e,r,i.signal),o=[...s.issues],l=[],a=0;for(let c of s.files){if(i.signal?.aborted)throw new DOMException("Scan aborted","AbortError");let u;try{u=await Ao(c)}catch(M){a+=1,o.push({location:c,message:`Cannot read file metadata: ${M instanceof Error?M.message:String(M)}`,severity:"error"});continue}if(!u.isFile()){a+=1,o.push({location:c,message:"Session path is not a regular file",severity:"warning"});continue}let g={ref:{agentId:t,sourceId:c},locator:c,sizeBytes:u.size,updatedAt:u.mtime.toISOString(),createdAt:u.birthtime.getTime()>0?u.birthtime.toISOString():void 0},h;try{h=await n.parseSummary(g,i.signal)}catch(M){if(M.name==="AbortError"||M.code==="ABORT_ERR")throw M;a+=1,o.push({location:c,message:`Cannot parse session: ${M instanceof Error?M.message:String(M)}`,severity:"error"});continue}let p=h.projectLocation||An.dirname(c),S=$(p),w=[...new Set(h.warnings)];for(let M of w)o.push({location:c,message:M,severity:"warning"});if(w.some(Po))a+=1;if(u.size===0&&!w.includes("Session file is empty"))w.push("Session file is empty"),o.push({location:c,message:"Session file is empty",severity:"warning"});let z=g.updatedAt,A=h.createdAt??g.createdAt,B=h.sessionId?`session:${t}:${h.sessionId}:${c}`:`source:${t}:${c}`,H=Ce(S,t);l.push({id:B,ref:g.ref,agentId:t,sessionId:h.sessionId,projectId:H,projectName:h.projectName??Ie(S),projectLocation:S,title:N(h.title??"Untitled session",96)||"Untitled session",createdAt:A,updatedAt:z,sizeBytes:g.sizeBytes,messageCount:h.messageCount,firstUserMessage:h.firstUserMessage,lastUserMessage:h.lastUserMessage,providerModels:h.providerModels,warnings:w})}let d=new Map;for(let c of l){let u=d.get(c.projectId),g=c.warnings.length;if(u){if(u.sessionCount+=1,u.totalSizeBytes+=c.sizeBytes??0,u.warningCount+=g,Ut(c.updatedAt)>Ut(u.updatedAt))u.updatedAt=c.updatedAt;continue}d.set(c.projectId,{id:c.projectId,agentId:t,name:c.projectName,location:c.projectLocation,displayPath:c.projectName,sessionCount:1,totalSizeBytes:c.sizeBytes??0,updatedAt:c.updatedAt,warningCount:g})}return{agentId:t,rootPath:An.resolve(e),projects:Pn([...d.values()]),sessions:Pn(l),issues:o,scannedSources:s.files.length,failedSources:a}}class Sr{rootPath;parser;constructor(e,t){this.rootPath=e,this.parser=t}async detect(){try{if(!(await xo(this.rootPath)).isDirectory())return{available:!1,location:this.rootPath,reason:"Session path is not a directory"};return{available:!0,location:this.rootPath}}catch(e){return{available:!1,location:this.rootPath,reason:e instanceof Error?e.message:String(e)}}}scan(e){return st(this.rootPath,"claude-code","Claude Code",this.parser,e)}}function Io(){let e=process.env.CLAUDE_CONFIG_DIR||xn.join(Do.homedir(),".claude");return xn.join(e,"projects")}class yr{id="claude-code";info={id:"claude-code",label:"Claude Code",status:"available",capabilities:{canDelete:!0,canBulkDelete:!0}};sessionsDir;parser;scanner;deleter;constructor(e){this.sessionsDir=$(e??process.env.ASC_CLAUDE_CODE_SESSIONS_DIR??Io()),this.info.detail=this.sessionsDir,this.parser=new pr,this.scanner=new Sr(this.sessionsDir,this.parser),this.deleter=new gr(this.sessionsDir)}}import _o from"os";import Pr from"path";class wr{rootPath;constructor(e){this.rootPath=e}deleteSessions(e,t){return tt("codex",this.rootPath,e,t)}}import{createReadStream as Co}from"fs";import{createInterface as jo}from"readline";import Eo from"path";function kt(e){return e&&typeof e==="object"&&!Array.isArray(e)?e:void 0}function bt(e){return typeof e==="string"&&e.length>0?e:void 0}function Mo(e){return kt(e.payload)}function je(e,t,...r){for(let n of r){let i=bt(t?.[n])??bt(e[n]);if(i)return i}return}function ot(e){if(typeof e==="string")return e;let t=kt(e);if(!t)return;return bt(t.text)??bt(t.message)}function vr(e){if(!Array.isArray(e))return ot(e);return e.map((r)=>ot(r)).filter((r)=>Boolean(r)).join(" ")||void 0}function Ro(e){if(!e||e.type!=="message")return;let t=e.role;if(t!=="user"&&t!=="assistant")return;return{role:t,text:vr(e.content)}}function Oo(e){if(!e)return;if(e.type==="user_message")return{role:"user",text:ot(e.message)??ot(e.text)};if(e.type==="agent_message")return{role:"assistant",text:ot(e.message)??ot(e.text)};if(e.type!=="item_completed")return;let t=kt(e.item);if(t?.type==="UserMessage")return{role:"user",text:vr(t.content)};if(t?.type==="AgentMessage")return{role:"assistant",text:vr(t.content)};return}function Ee(e,t){if(!e.includes(t))e.push(t)}function Dn(e,t,r){if(!t&&!r)return;let n=t&&r?`${t}/${r}`:t??r;if(n&&!e.includes(n))e.push(n)}async function In(e,t,r="full"){let n={recordCount:0,messageCount:0,providerModels:[],warnings:[]},i=!0,s,o=[],l=[],a=Co(e,{encoding:"utf8",signal:t}),d=jo({input:a,crlfDelay:1/0});try{for await(let u of d){if(t?.aborted)throw new DOMException("Scan aborted","AbortError");n.recordCount+=1;let g;try{g=JSON.parse(u)}catch{Ee(n.warnings,`Invalid JSON on line ${n.recordCount}`),i=!1;continue}let h=kt(g);if(!h){Ee(n.warnings,`Record ${n.recordCount} is not an object`),i=!1;continue}let p=bt(h.type),S=Mo(h);if(i&&p!=="session_meta")Ee(n.warnings,"First record is not a Codex session header");if(p==="session_meta"){if(n.sessionId??=je(h,S,"id","session_id","thread_id"),n.projectPath??=je(h,S,"cwd","current_working_dir"),n.createdAt??=je(h,S,"timestamp"),n.title??=je(h,S,"title","name"),s??=je(h,S,"model_provider","provider"),r==="full")Dn(n.providerModels,s,je(h,S,"model"));if(i=!1,r==="summary")break;continue}if(i=!1,r==="summary")continue;if(p==="turn_context"){let w=je(h,S,"model_provider","provider")??s;Dn(n.providerModels,w,je(h,S,"model","model_name"))}if(p==="response_item"){let w=Ro(S);if(w)o.push(w)}if(p==="event_msg"){let w=Oo(S);if(w)l.push(w)}}}catch(u){if(u.code==="ABORT_ERR"||u.name==="AbortError")throw u;Ee(n.warnings,`Unable to read session: ${u instanceof Error?u.message:String(u)}`)}finally{d.close(),a.destroy()}let c=l.length>0?l:o;n.messageCount=c.length;for(let u of c){if(u.role!=="user"||!u.text)continue;let g=N(u.text,1000);n.firstUserMessage??=g,n.lastUserMessage=g,n.title??=g}if(n.recordCount===0)Ee(n.warnings,"Session file is empty");if(!n.sessionId)Ee(n.warnings,"Codex session header is missing id");if(!n.createdAt)Ee(n.warnings,"Codex session header is missing timestamp");if(!n.projectPath)Ee(n.warnings,"Codex session header is missing cwd");return n}function Cn(e,t){let r=[{label:"Source",value:t},{label:"Records",value:String(e.recordCount)}];if(e.providerModels.length>0)r.push({label:"Provider / model",value:e.providerModels.join(", ")});return r}function To(e,t,r="full"){return{sessionId:t.sessionId,projectLocation:t.projectPath,createdAt:t.createdAt,title:t.title??Eo.basename(e.locator),messageCount:r==="summary"?void 0:t.messageCount,firstUserMessage:r==="summary"?void 0:t.firstUserMessage,lastUserMessage:r==="summary"?void 0:t.lastUserMessage,providerModels:r==="summary"?[]:t.providerModels,warnings:t.warnings,detailFields:r==="summary"?[{label:"Source",value:e.locator}]:Cn(t,e.locator)}}class br{async parseSummary(e,t){return To(e,await In(e.locator,t,"summary"),"summary")}async loadDetail(e,t){let r=await In(e.ref.sourceId,t),n=r.projectPath??e.projectLocation,i=[...new Set([...e.warnings,...r.warnings])];return{...e,sessionId:r.sessionId??e.sessionId,projectLocation:n,title:N(r.title??e.title,160)||"Untitled session",createdAt:r.createdAt??e.createdAt,messageCount:r.messageCount,firstUserMessage:r.firstUserMessage,lastUserMessage:r.lastUserMessage,providerModels:r.providerModels,warnings:i,fields:Cn(r,e.ref.sourceId),warningCount:i.length}}}import{lstat as No}from"fs/promises";class Ar{rootPath;parser;constructor(e,t){this.rootPath=e,this.parser=t}async detect(){try{if(!(await No(this.rootPath)).isDirectory())return{available:!1,location:this.rootPath,reason:"Session path is not a directory"};return{available:!0,location:this.rootPath}}catch(e){return{available:!1,location:this.rootPath,reason:e instanceof Error?e.message:String(e)}}}scan(e){return st(this.rootPath,"codex","Codex",this.parser,e)}}var Fo=Pr.join(_o.homedir(),".codex"),Uo=Pr.join(Fo,"sessions");class xr{id="codex";info={id:"codex",label:"Codex",status:"available",capabilities:{canDelete:!0,canBulkDelete:!0}};sessionsDir;parser;scanner;deleter;constructor(e){let t=process.env.CODEX_HOME?Pr.join(process.env.CODEX_HOME,"sessions"):Uo;this.sessionsDir=$(e??process.env.ASC_CODEX_SESSIONS_DIR??t),this.info.detail=this.sessionsDir,this.parser=new br,this.scanner=new Ar(this.sessionsDir,this.parser),this.deleter=new wr(this.sessionsDir)}}import ei from"os";import _n from"path";import{Database as ko}from"bun:sqlite";import{lstat as Lo,readdir as $o,realpath as jn,rm as En}from"fs/promises";import it from"path";function Mn(e,t){let r=it.relative(e,t);return r.length>0&&!r.startsWith(`..${it.sep}`)&&r!==".."&&!it.isAbsolute(r)}async function Bo(e,t){if(!Mn(e,t))return;try{if((await $o(t)).length>0)return;await En(t)}catch{}}function zo(e,t){let r=it.join(e,"session_search.sqlite");try{let n=new ko(r);try{n.run("PRAGMA busy_timeout = 3000"),n.query("DELETE FROM session_docs WHERE session_id = ?").run(t)}finally{n.close()}}catch{}}class Dr{rootPath;constructor(e){this.rootPath=e}async deleteSessions(e,t){let r=[],n;try{n=await jn(this.rootPath)}catch(i){return{items:e.map((s)=>({sessionId:s.id,success:!1,message:`Cannot access session directory: ${i instanceof Error?i.message:String(i)}`}))}}for(let i of e){if(t?.signal?.aborted)throw new DOMException("Delete aborted","AbortError");if(i.agentId!=="grok"||i.ref.agentId!=="grok"){r.push({sessionId:i.id,success:!1,message:"Session belongs to another agent"});continue}let s=it.resolve(i.ref.sourceId);try{if(!(await Lo(s)).isDirectory()){r.push({sessionId:i.id,success:!1,message:"Grok session source is not a directory"});continue}let l=await jn(s);if(!Mn(n,l)){r.push({sessionId:i.id,success:!1,message:"Session is outside the configured session directory"});continue}if(await En(l,{recursive:!0,force:!0}),await Bo(n,it.dirname(l)),i.sessionId)zo(this.rootPath,i.sessionId);r.push({sessionId:i.id,success:!0})}catch(o){let l=o.code;r.push({sessionId:i.id,success:!1,message:l==="ENOENT"?"Session source no longer exists":o instanceof Error?o.message:String(o)})}}return{items:r}}}import{createReadStream as Jo}from"fs";import{lstat as Go,readFile as Wo}from"fs/promises";import{createInterface as Ho}from"readline";import at from"path";function At(e){return e&&typeof e==="object"&&!Array.isArray(e)?e:void 0}function ge(e){return typeof e==="string"&&e.length>0?e:void 0}function Rn(e){return typeof e==="number"&&Number.isFinite(e)?e:void 0}function qo(e){if(typeof e==="string")return e;if(!Array.isArray(e))return ge(At(e)?.text);return e.map((r)=>typeof r==="string"?r:ge(At(r)?.text)).filter((r)=>Boolean(r)).join(" ")||void 0}function Vo(e){let t=e.match(/<user_query>\s*([\s\S]*?)\s*<\/user_query>/);if(t?.[1])return t[1].trim()||void 0;if(e.includes("<system-reminder>")||e.includes("<user_info>")||e.includes("<image_files>"))return;return e.trim()||void 0}function Xo(e){try{let t=decodeURIComponent(e);return t.startsWith("/")?t:void 0}catch{return}}async function On(e){let t=[],r=at.basename(e),n=Xo(at.basename(at.dirname(e)));try{let i=await Wo(at.join(e,"summary.json"),"utf8"),s=At(JSON.parse(i));if(!s)return{sessionId:r,projectPath:n,warnings:["Grok summary.json is not an object"]};let o=At(s.info);return{sessionId:ge(o?.id)??r,projectPath:ge(o?.cwd)??n,title:ge(s.generated_title)??ge(s.session_summary),createdAt:ge(s.created_at),updatedAt:ge(s.updated_at)??ge(s.last_active_at),messageCount:Rn(s.num_chat_messages)??Rn(s.num_messages),model:ge(s.current_model_id),warnings:t}}catch(i){if(i.code!=="ENOENT")t.push(`Unable to read Grok summary: ${i instanceof Error?i.message:String(i)}`);return{sessionId:r,projectPath:n,warnings:t}}}async function Qo(e,t){let r=[],n=at.join(e,"chat_history.jsonl");try{await Go(n)}catch{return{warnings:r}}let i=Jo(n,{encoding:"utf8",signal:t}),s=Ho({input:i,crlfDelay:1/0}),o,l,a=0;try{for await(let d of s){if(t?.aborted)throw new DOMException("Scan aborted","AbortError");a+=1;let c;try{c=JSON.parse(d)}catch{r.push(`Invalid JSON on line ${a}`);continue}let u=At(c);if(!u||u.type!=="user"||u.synthetic_reason)continue;let g=Vo(qo(u.content)??"");if(!g)continue;let h=N(g,1000);o??=h,l=h}}catch(d){if(d.code==="ABORT_ERR"||d.name==="AbortError")throw d;r.push(`Unable to read chat history: ${d instanceof Error?d.message:String(d)}`)}finally{s.close(),i.destroy()}return{firstUserMessage:o,lastUserMessage:l,warnings:r}}function Ko(e,t){let r=[{label:"Source",value:t}];if(e.model)r.push({label:"Provider / model",value:e.model});if(e.messageCount!==void 0)r.push({label:"Messages",value:String(e.messageCount)});return r}function Yo(e,t){return{sessionId:t.sessionId,projectLocation:t.projectPath,createdAt:t.createdAt,title:t.title??at.basename(e.locator),messageCount:t.messageCount,providerModels:t.model?[t.model]:[],warnings:t.warnings,detailFields:[{label:"Source",value:e.locator}]}}class Ir{async parseSummary(e){return Yo(e,await On(e.locator))}async loadDetail(e,t){let r=await On(e.ref.sourceId),n=await Qo(e.ref.sourceId,t),i=[...new Set([...e.warnings,...r.warnings,...n.warnings])];return{...e,sessionId:r.sessionId??e.sessionId,projectLocation:r.projectPath??e.projectLocation,title:N(r.title??e.title,160)||e.title,createdAt:r.createdAt??e.createdAt,messageCount:r.messageCount,firstUserMessage:n.firstUserMessage,lastUserMessage:n.lastUserMessage,providerModels:r.model?[r.model]:e.providerModels,warnings:i,fields:Ko(r,e.ref.sourceId),warningCount:i.length}}}import{lstat as Lt,readdir as Tn}from"fs/promises";import Me from"path";function $t(e){if(!e)return 0;let t=Date.parse(e);return Number.isFinite(t)?t:0}function Nn(e){return e.sort((t,r)=>$t(r.updatedAt)-$t(t.updatedAt))}async function Zo(e,t){let r=[],n;try{n=await Tn(e)}catch{return r}for(let i of n){if(t?.aborted)throw new DOMException("Scan aborted","AbortError");let s=Me.join(e,i),o;try{o=await Lt(s)}catch{continue}if(!o.isDirectory())continue;let l;try{l=await Tn(s)}catch{continue}for(let a of l){if(t?.aborted)throw new DOMException("Scan aborted","AbortError");let d=Me.join(s,a),c;try{c=await Lt(d)}catch{continue}if(!c.isDirectory())continue;r.push(d)}}return r}class Cr{rootPath;parser;constructor(e,t){this.rootPath=e,this.parser=t}async detect(){try{if(!(await Lt(this.rootPath)).isDirectory())return{available:!1,location:this.rootPath,reason:"Session path is not a directory"};return{available:!0,location:this.rootPath}}catch(e){return{available:!1,location:this.rootPath,reason:e instanceof Error?e.message:String(e)}}}async scan(e){if(e?.signal?.aborted)throw new DOMException("Scan aborted","AbortError");let t=[],r=[],n=0,i=await Zo(this.rootPath,e?.signal);for(let o of i){if(e?.signal?.aborted)throw new DOMException("Scan aborted","AbortError");let l,a;try{let p=await Lt(Me.join(o,"chat_history.jsonl"));if(p.isFile())l=p.size,a=p.mtime.toISOString()}catch{}let d;try{d=await this.parser.parseSummary({ref:{agentId:"grok",sourceId:o},locator:o,sizeBytes:l??0,updatedAt:a??new Date(0).toISOString()},e?.signal)}catch(p){if(p.name==="AbortError"||p.code==="ABORT_ERR")throw p;n+=1,t.push({location:o,message:`Cannot parse session: ${p instanceof Error?p.message:String(p)}`,severity:"error"});continue}let c=d.projectLocation||Me.dirname(o),u=c.startsWith("/")?$(c):c,g=[...new Set(d.warnings)];for(let p of g)t.push({location:o,message:p,severity:"warning"});let h=Ce(u,"grok");r.push({id:`session:grok:${d.sessionId??Me.basename(o)}`,ref:{agentId:"grok",sourceId:o},agentId:"grok",sessionId:d.sessionId,projectId:h,projectName:Ie(u),projectLocation:u,title:N(d.title??Me.basename(o),96)||Me.basename(o),createdAt:d.createdAt,updatedAt:a??d.createdAt??new Date(0).toISOString(),sizeBytes:l,messageCount:d.messageCount,providerModels:d.providerModels,warnings:g})}let s=new Map;for(let o of r){let l=s.get(o.projectId),a=o.warnings.length;if(l){if(l.sessionCount+=1,l.totalSizeBytes+=o.sizeBytes??0,l.warningCount+=a,$t(o.updatedAt)>$t(l.updatedAt))l.updatedAt=o.updatedAt;continue}s.set(o.projectId,{id:o.projectId,agentId:"grok",name:o.projectName,location:o.projectLocation,displayPath:o.projectName,sessionCount:1,totalSizeBytes:o.sizeBytes??0,updatedAt:o.updatedAt,warningCount:a})}return{agentId:"grok",rootPath:Me.resolve(this.rootPath),projects:Nn([...s.values()]),sessions:Nn(r),issues:t,scannedSources:i.length,failedSources:n}}}function ti(){let e=process.env.GROK_HOME||_n.join(ei.homedir(),".grok");return _n.join(e,"sessions")}class jr{id="grok";info={id:"grok",label:"Grok",status:"available",capabilities:{canDelete:!0,canBulkDelete:!0}};sessionsDir;parser;scanner;deleter;constructor(e){this.sessionsDir=$(e??process.env.ASC_GROK_SESSIONS_DIR??ti()),this.info.detail=this.sessionsDir,this.parser=new Ir,this.scanner=new Cr(this.sessionsDir,this.parser),this.deleter=new Dr(this.sessionsDir)}}import{lstat as si,readdir as oi,realpath as $n,rm as ii}from"fs/promises";import pe from"path";import{Database as Fn}from"bun:sqlite";import{lstat as ri}from"fs/promises";async function dt(e,t){await ri(e);let r=t?new Fn(e,{readonly:!0,create:!1}):new Fn(e);return r.run("PRAGMA busy_timeout = 3000"),r}function ct(e){let t=e.query("SELECT name FROM sqlite_master WHERE type = 'table'").all();return new Set(t.map((r)=>r.name))}import ni from"os";import Bt from"path";function Un(){if(process.env.ASC_OPENCODE_DATA_DIR)return $(process.env.ASC_OPENCODE_DATA_DIR);if(process.env.OPENCODE_DATA_DIR)return $(process.env.OPENCODE_DATA_DIR);let e=process.env.OPENCODE_APPNAME||"opencode",t=process.env.XDG_DATA_HOME;if(t)return $(Bt.join(t,e));return Bt.join(ni.homedir(),".local","share",e)}function Re(e){return Bt.join(e,"opencode.db")}function kn(e){return Bt.join(e,"storage")}var Ln=/^ses_[A-Za-z0-9]+$/;var ai=["part","message","session_message","session_pending","session_share","todo","instruction_entry","instruction_state","session_v2","session"];function di(e,t){let r=pe.relative(e,t);return r.length>0&&!r.startsWith(`..${pe.sep}`)&&r!==".."&&!pe.isAbsolute(r)}async function Be(e,t){let r;try{r=await $n(t)}catch{return}if(!di(e,r)&&r!==e)return;await ii(r,{recursive:!0,force:!0})}class Er{dataDir;constructor(e){this.dataDir=e}async deleteSessions(e,t){let r=[],n;try{n=await $n(this.dataDir)}catch(o){return{items:e.map((l)=>({sessionId:l.id,success:!1,message:`Cannot access OpenCode data directory: ${o instanceof Error?o.message:String(o)}`}))}}let i=Re(this.dataDir);try{if(!(await si(i)).isFile())return{items:e.map((l)=>({sessionId:l.id,success:!1,message:"OpenCode database path is not a file"}))}}catch(o){return{items:e.map((l)=>({sessionId:l.id,success:!1,message:o instanceof Error?o.message:String(o)}))}}let s=await dt(i,!1);try{let o=ct(s),l=kn(n);for(let a of e){if(t?.signal?.aborted)throw new DOMException("Delete aborted","AbortError");if(a.agentId!=="opencode"||a.ref.agentId!=="opencode"){r.push({sessionId:a.id,success:!1,message:"Session belongs to another agent"});continue}let d=a.ref.sourceId;if(!Ln.test(d)){r.push({sessionId:a.id,success:!1,message:"Invalid OpenCode session id"});continue}let c=o.has("session")?"session":o.has("session_v2")?"session_v2":void 0;if(!c){r.push({sessionId:a.id,success:!1,message:"OpenCode database has no session table"});continue}let u=s.query(`SELECT id, project_id FROM ${c} WHERE id = ?`).get(d);if(!u){r.push({sessionId:a.id,success:!1,message:"OpenCode session was not found"});continue}let g=o.has("message")?s.query("SELECT id FROM message WHERE session_id = ?").all(d).map((S)=>S.id):[],h=s.transaction(()=>{if(o.has("event"))s.query("DELETE FROM event WHERE aggregate_id = ?").run(d);for(let S of ai){if(!o.has(S))continue;if(S==="session"||S==="session_v2")s.query(`DELETE FROM ${S} WHERE id = ?`).run(d);else s.query(`DELETE FROM ${S} WHERE session_id = ?`).run(d)}});try{h()}catch(S){r.push({sessionId:a.id,success:!1,message:S instanceof Error?S.message:String(S)});continue}await Be(n,pe.join(l,"session",u.project_id??"",d+".json")),await Be(n,pe.join(l,"message",d)),await Be(n,pe.join(l,"todo",d+".json")),await Be(n,pe.join(l,"agent-usage-reminder",d+".json")),await Be(n,pe.join(l,"session_diff",d));for(let S of g)await Be(n,pe.join(l,"part",S));let p=pe.join(l,"session",u.project_id??"");try{if((await oi(p)).length===0)await Be(n,p)}catch{}r.push({sessionId:a.id,success:!0})}}finally{s.close()}return{items:r}}}function ci(e){return e&&typeof e==="object"&&!Array.isArray(e)?e:void 0}function Bn(e){if(!e)return;try{return ci(JSON.parse(e))}catch{return}}function li(e){if(!e||e.type!=="text")return;return typeof e.text==="string"&&e.text.length>0?e.text:void 0}function ui(e,t){let r=t&&typeof t.providerID==="string"&&typeof t.modelID==="string"?`${t.providerID}/${t.modelID}`:void 0;if(r)return[r];if(!e)return[];try{let n=JSON.parse(e),i=typeof n.id==="string"?n.id:void 0,s=typeof n.providerID==="string"?n.providerID:void 0;if(s&&i)return[`${s}/${i}`];if(i)return[i]}catch{if(e.trim())return[e.trim()]}return[]}class Mr{dataDir;constructor(e){this.dataDir=e}async parseSummary(e){let t=await this.loadFromDb(e.ref.sourceId);return{sessionId:t.sessionId,projectLocation:t.projectLocation,createdAt:t.createdAt,title:t.title,messageCount:void 0,providerModels:[],warnings:t.warnings,detailFields:[{label:"Source",value:e.locator}]}}async loadDetail(e,t){if(t?.aborted)throw new DOMException("Scan aborted","AbortError");let r=await this.loadFromDb(e.ref.sourceId),n=[...new Set([...e.warnings,...r.warnings])];return{...e,sessionId:r.sessionId??e.sessionId,projectLocation:r.projectLocation??e.projectLocation,title:N(r.title??e.title,160)||e.title,createdAt:r.createdAt??e.createdAt,messageCount:r.messageCount,firstUserMessage:r.firstUserMessage,lastUserMessage:r.lastUserMessage,providerModels:r.providerModels.length>0?r.providerModels:e.providerModels,warnings:n,fields:r.fields,warningCount:n.length}}async loadFromDb(e){let t=[],r=await dt(Re(this.dataDir),!0);try{let n=ct(r),i=n.has("session")?"session":n.has("session_v2")?"session_v2":void 0;if(!i)return{providerModels:[],warnings:["OpenCode database has no session table"],fields:[]};let s=r.query(`SELECT id, directory, title, version, agent, model, time_created FROM ${i} WHERE id = ?`).get(e);if(!s)return{providerModels:[],warnings:["OpenCode session was not found"],fields:[]};let o,l,a,d=ui(s.model);if(n.has("part")&&n.has("message")){let u=r.query("SELECT p.data AS part, m.data AS message FROM part p LEFT JOIN message m ON m.id = p.message_id WHERE p.session_id = ? ORDER BY p.time_created").all(e);for(let g of u){let h=Bn(g.part),p=Bn(g.message),S=li(h);if(!S)continue;if(p?.role==="user"){let w=N(S,1000);l??=w,a=w}}}if(n.has("message"))o=r.query("SELECT COUNT(*) AS count FROM message WHERE session_id = ?").get(e).count;let c=[{label:"Source",value:Re(this.dataDir)},{label:"Session",value:s.id}];if(s.agent)c.push({label:"Agent",value:s.agent});if(s.version)c.push({label:"OpenCode version",value:s.version});if(d.length>0)c.push({label:"Provider / model",value:d.join(", ")});return{sessionId:s.id,projectLocation:s.directory??void 0,createdAt:s.time_created?new Date(s.time_created).toISOString():void 0,title:s.title??void 0,messageCount:o,firstUserMessage:l,lastUserMessage:a,providerModels:d,warnings:t,fields:c}}finally{r.close()}}}import{lstat as mi}from"fs/promises";import Rr from"path";function Or(e){if(!e||!Number.isFinite(e))return;let t=new Date(e);return Number.isNaN(t.getTime())?void 0:t.toISOString()}function zt(e){if(!e)return 0;let t=Date.parse(e);return Number.isFinite(t)?t:0}function fi(e){if(!e)return[];try{let t=JSON.parse(e),r=typeof t.id==="string"?t.id:void 0,n=typeof t.providerID==="string"?t.providerID:void 0;if(n&&r)return[`${n}/${r}`];if(r)return[r];if(n)return[n]}catch{if(e.trim())return[e.trim()]}return[]}function zn(e){return e.sort((t,r)=>zt(r.updatedAt)-zt(t.updatedAt))}class Tr{rootPath;constructor(e){this.rootPath=e}async detect(){let e=Re(this.rootPath);try{if(!(await mi(e)).isFile())return{available:!1,location:e,reason:"OpenCode database path is not a file"};return{available:!0,location:this.rootPath}}catch(t){return{available:!1,location:this.rootPath,reason:t instanceof Error?t.message:String(t)}}}async scan(e){if(e?.signal?.aborted)throw new DOMException("Scan aborted","AbortError");let t=Re(this.rootPath),r;try{r=await dt(t,!0)}catch(n){return{agentId:"opencode",rootPath:Rr.resolve(this.rootPath),projects:[],sessions:[],issues:[{location:t,message:n instanceof Error?n.message:String(n),severity:"error"}],scannedSources:0,failedSources:0}}try{let n=ct(r),i=n.has("session")?"session":n.has("session_v2")?"session_v2":void 0;if(!i)return{agentId:"opencode",rootPath:Rr.resolve(this.rootPath),projects:[],sessions:[],issues:[{location:t,message:"OpenCode database has no session table",severity:"error"}],scannedSources:0,failedSources:0};let s=n.has("project"),o=r.query(s?`SELECT s.id, s.project_id, s.directory, s.title, s.version, s.agent, s.model, s.time_created, s.time_updated, p.worktree FROM ${i} s LEFT JOIN project p ON p.id = s.project_id`:`SELECT id, project_id, directory, title, version, agent, model, time_created, time_updated, NULL AS worktree FROM ${i}`).all(),l=new Map;if(n.has("message")){let c=r.query("SELECT session_id AS id, COUNT(*) AS count FROM message GROUP BY session_id").all();for(let u of c)l.set(u.id,u.count)}let a=[];for(let c of o){if(e?.signal?.aborted)throw new DOMException("Scan aborted","AbortError");let u=c.directory||c.worktree||(c.project_id==="global"?"global":c.project_id)||"unknown",g=u==="global"||u==="unknown"?u:$(u),h=Or(c.time_updated)??Or(c.time_created)??new Date(0).toISOString(),p=Ce(g,"opencode");a.push({id:`session:opencode:${c.id}`,ref:{agentId:"opencode",sourceId:c.id},agentId:"opencode",sessionId:c.id,projectId:p,projectName:Ie(g),projectLocation:g,title:N(c.title||c.id,96)||c.id,createdAt:Or(c.time_created),updatedAt:h,messageCount:l.get(c.id),providerModels:fi(c.model),warnings:[]})}let d=new Map;for(let c of a){let u=d.get(c.projectId);if(u){if(u.sessionCount+=1,zt(c.updatedAt)>zt(u.updatedAt))u.updatedAt=c.updatedAt;continue}d.set(c.projectId,{id:c.projectId,agentId:"opencode",name:c.projectName,location:c.projectLocation,displayPath:c.projectName,sessionCount:1,totalSizeBytes:0,updatedAt:c.updatedAt,warningCount:0})}return{agentId:"opencode",rootPath:Rr.resolve(this.rootPath),projects:zn([...d.values()]),sessions:zn(a),issues:[],scannedSources:a.length,failedSources:0}}finally{r.close()}}}class Nr{id="opencode";info={id:"opencode",label:"OpenCode",status:"available",capabilities:{canDelete:!0,canBulkDelete:!0}};dataDir;parser;scanner;deleter;constructor(e){this.dataDir=$(e??Un()),this.info.detail=this.dataDir,this.parser=new Mr(this.dataDir),this.scanner=new Tr(this.dataDir),this.deleter=new Er(this.dataDir)}}import bi from"os";import Ai from"path";class _r{rootPath;constructor(e){this.rootPath=e}deleteSessions(e,t){return tt("pi",this.rootPath,e,t)}}import{createReadStream as gi}from"fs";import{createInterface as pi}from"readline";import hi from"path";function Jn(e){return typeof e.message?.role==="string"?e.message.role:void 0}function Gn(e){if(!e)return;if(typeof e.content==="string")return N(e.content,1000);if(!Array.isArray(e.content))return;let t=e.content.flatMap((r)=>{if(!r||typeof r!=="object")return[];let n=r;return n.type==="text"&&typeof n.text==="string"?[n.text]:[]}).join(" ");return t?N(t,1000):void 0}function Wn(e){let t=typeof e.provider==="string"?e.provider:e.message?.provider,r=typeof e.modelId==="string"?e.modelId:typeof e.model==="string"?e.model:e.message?.modelId??e.message?.model;if(!t&&!r)return;if(t&&r)return`${t}/${r}`;return t??r}function Hn(e){let t=e.title??e.name;return typeof t==="string"?cr(t):void 0}function Si(e){return e&&typeof e==="object"&&!Array.isArray(e)?e:void 0}function yi(e){if(e.type!=="session")return;return{type:"session",version:typeof e.version==="number"?e.version:void 0,id:typeof e.id==="string"?e.id:void 0,timestamp:typeof e.timestamp==="string"?e.timestamp:void 0,cwd:typeof e.cwd==="string"?e.cwd:void 0,title:typeof e.title==="string"?e.title:void 0,name:typeof e.name==="string"?e.name:void 0}}function Oe(e,t){if(!e.includes(t))e.push(t)}async function qn(e,t,r="full"){let n={recordCount:0,messageCount:0,providerModels:[],warnings:[]},i=!0,s=gi(e,{encoding:"utf8",signal:t}),o=pi({input:s,crlfDelay:1/0});try{for await(let l of o){if(t?.aborted)throw new DOMException("Scan aborted","AbortError");n.recordCount+=1;let a;try{a=JSON.parse(l)}catch{Oe(n.warnings,`Invalid JSON on line ${n.recordCount}`),i=!1;continue}let d=Si(a);if(!d){Oe(n.warnings,`Record ${n.recordCount} is not an object`),i=!1;continue}let c=yi(d);if(i&&!c)Oe(n.warnings,"First record is not a session header");if(c&&!n.header){if(n.header=c,c.title||c.name)n.title=c.title??c.name}if(i=!1,r==="summary"){if(n.header)break;continue}let u=Jn(d),g=Gn(d.message);if(u==="user"&&g){if(n.messageCount+=1,n.firstUserMessage??=g,n.lastUserMessage=g,!n.title)n.title=g}else if(u)n.messageCount+=1;let h=Hn(d);if(!n.title&&h)n.title=h;let p=Wn(d);if(p&&!n.providerModels.includes(p))n.providerModels.push(p)}}catch(l){if(l.code==="ABORT_ERR"||l.name==="AbortError")throw l;Oe(n.warnings,`Unable to read session: ${l instanceof Error?l.message:String(l)}`)}finally{o.close(),s.destroy()}if(n.recordCount===0)Oe(n.warnings,"Session file is empty");if(!n.header?.id)Oe(n.warnings,"Session header is missing id");if(!n.header?.timestamp)Oe(n.warnings,"Session header is missing timestamp");if(!n.header?.cwd)Oe(n.warnings,"Session header is missing cwd");return n}function Vn(e,t){let r=[{label:"Source",value:t}];if(e.header?.version!==void 0)r.push({label:"Pi version",value:String(e.header.version)});if(r.push({label:"Records",value:String(e.recordCount)}),e.providerModels.length>0)r.push({label:"Provider / model",value:e.providerModels.join(", ")});return r}function wi(e,t,r="full"){return{sessionId:t.header?.id,projectLocation:t.header?.cwd,createdAt:t.header?.timestamp,title:t.title??t.header?.title??t.header?.name??hi.basename(e.locator),messageCount:r==="summary"?void 0:t.messageCount,firstUserMessage:r==="summary"?void 0:t.firstUserMessage,lastUserMessage:r==="summary"?void 0:t.lastUserMessage,providerModels:r==="summary"?[]:t.providerModels,warnings:t.warnings,detailFields:r==="summary"?[{label:"Source",value:e.locator}]:Vn(t,e.locator)}}class Fr{async parseSummary(e,t){return wi(e,await qn(e.locator,t,"summary"),"summary")}async loadDetail(e,t){let r=await qn(e.ref.sourceId,t),n=r.header?.cwd??e.projectLocation,i=[...new Set([...e.warnings,...r.warnings])];return{...e,sessionId:r.header?.id??e.sessionId,projectLocation:n,title:N(r.title??e.title,160)||"Untitled session",createdAt:r.header?.timestamp??e.createdAt,messageCount:r.messageCount,firstUserMessage:r.firstUserMessage,lastUserMessage:r.lastUserMessage,providerModels:r.providerModels,warnings:i,fields:Vn(r,e.ref.sourceId),warningCount:i.length}}}import{lstat as vi}from"fs/promises";class Ur{rootPath;parser;constructor(e,t){this.rootPath=e,this.parser=t}async detect(){try{if(!(await vi(this.rootPath)).isDirectory())return{available:!1,location:this.rootPath,reason:"Session path is not a directory"};return{available:!0,location:this.rootPath}}catch(e){return{available:!1,location:this.rootPath,reason:e instanceof Error?e.message:String(e)}}}scan(e){return st(this.rootPath,"pi","Pi",this.parser,e)}}var Pi=Ai.join(bi.homedir(),".pi","agent","sessions");class kr{id="pi";info={id:"pi",label:"Pi",status:"available",capabilities:{canDelete:!0,canBulkDelete:!0}};sessionsDir;parser;scanner;deleter;constructor(e){this.sessionsDir=$(e??process.env.ASC_PI_SESSIONS_DIR??Pi),this.info.detail=this.sessionsDir,this.parser=new Fr,this.scanner=new Ur(this.sessionsDir,this.parser),this.deleter=new _r(this.sessionsDir)}}function Xn(...e){return new Map(e.map((t)=>[t.id,t]))}async function Qn(e,t,r){let n=new Map;for(let s of t){let o=n.get(s.agentId)??[];o.push(s),n.set(s.agentId,o)}let i=[];for(let[s,o]of n){if(r?.signal?.aborted)throw new DOMException("Delete aborted","AbortError");let l=e.get(s);if(!l?.deleter){i.push(...o.map((a)=>({sessionId:a.id,success:!1,message:`${l?.info.label??s} does not support deletion`})));continue}try{let a=await l.deleter.deleteSessions(o,r);i.push(...a.items)}catch(a){if(a.name==="AbortError"||a.code==="ABORT_ERR")throw a;i.push(...o.map((d)=>({sessionId:d.id,success:!1,message:a instanceof Error?a.message:String(a)})))}}return{items:i}}async function Kn(e,t,r){let n=e.get(t.agentId);if(!n)throw Error(`Agent is not registered: ${t.agentId}`);return n.parser.loadDetail(t,r)}async function Yn(e,t,r){let n=e.get(t);if(!n)throw Error(`Agent is not registered: ${t}`);return n.scanner.scan(r)}function Zn(e){return{agents:[...e.values()].map((t)=>t.info),scanSessions:(t,r)=>Yn(e,t,r),loadSessionDetail:(t,r)=>Kn(e,t,r),deleteSessions:(t,r)=>Qn(e,t,r)}}import{createComponent as fa}from"@opentui/solid";import{onCleanup as ga,onMount as pa}from"solid-js";import{CliRenderEvents as js}from"@opentui/core";import{useRenderer as ha}from"@opentui/solid";import{effect as Zr}from"@opentui/solid";import{memo as bs}from"@opentui/solid";import{insert as te}from"@opentui/solid";import{createComponent as L}from"@opentui/solid";import{createTextNode as As}from"@opentui/solid";import{insertNode as He}from"@opentui/solid";import{setProp as C}from"@opentui/solid";import{createElement as xe}from"@opentui/solid";import{Show as oe,createSignal as Ue}from"solid-js";import{useKeyboard as da,useRenderer as ca,useTerminalDimensions as la}from"@opentui/solid";import{RGBA as le}from"@opentui/core";import{createStore as xi}from"solid-js/store";function Te(e,t){return e?.palette[t]??void 0}function es(e){return{background:le.defaultBackground(e?.defaultBackground??void 0),panel:"transparent",panelAlt:le.fromIndex(8,Te(e,8)),border:le.fromIndex(2,Te(e,2)),text:le.defaultForeground(e?.defaultForeground??void 0),muted:le.fromIndex(8,Te(e,8)),accent:le.fromIndex(5,Te(e,5)),cyan:le.fromIndex(6,Te(e,6)),error:le.fromIndex(1,Te(e,1)),warning:le.fromIndex(3,Te(e,3)),selected:le.fromIndex(4,Te(e,4)),overlay:le.fromInts(0,0,0,150)}}var[m,Di]=xi(es());function ts(e){Di(es(e))}import{effect as Lr}from"@opentui/solid";import{createComponent as rs}from"@opentui/solid";import{insert as Pt}from"@opentui/solid";import{createTextNode as ns}from"@opentui/solid";import{insertNode as $r}from"@opentui/solid";import{memo as Gl}from"@opentui/solid";import{setProp as ee}from"@opentui/solid";import{createElement as Jt}from"@opentui/solid";import{For as Ii,Show as Ci}from"solid-js";function ss(e){let t=()=>e.store.agents().find((s)=>s.id===e.store.activeAgentId()),r=()=>e.store.agents().map((s)=>`${s.label}${s.id===e.store.activeAgentId()?" *":""}`),n=()=>Math.max(1,...r().map((s)=>s.length))+4,i=()=>Math.max(1,r().length)+2;return(()=>{var s=Jt("box"),o=Jt("text"),l=ns("Agent [ \u25CF "),a=ns(" \u25BE ]");return $r(s,o),ee(s,"position","relative"),ee(s,"width",28),$r(o,l),$r(o,a),Pt(o,()=>t()?.label??"Pi",a),Pt(s,rs(Ci,{get when(){return e.open},get children(){var d=Jt("box");return ee(d,"position","absolute"),ee(d,"top",1),ee(d,"left",0),ee(d,"paddingX",2),ee(d,"paddingY",1),ee(d,"zIndex",100),Pt(d,rs(Ii,{get each(){return e.store.agents()},children:(c,u)=>(()=>{var g=Jt("text");return Pt(g,()=>c.label,null),Pt(g,()=>c.id===e.store.activeAgentId()?" *":"",null),Lr((h)=>{var p=u()===e.selectedIndex?m.selected:m.panel,S=u()===e.selectedIndex?m.muted:m.text;return p!==h.e&&(h.e=ee(g,"bg",p,h.e)),S!==h.t&&(h.t=ee(g,"fg",S,h.t)),h},{e:void 0,t:void 0}),g})()})),Lr((c)=>{var u=n(),g=i(),h=m.panelAlt;return u!==c.e&&(c.e=ee(d,"width",u,c.e)),g!==c.t&&(c.t=ee(d,"height",g,c.t)),h!==c.a&&(c.a=ee(d,"backgroundColor",h,c.a)),c},{e:void 0,t:void 0,a:void 0}),d}}),null),Lr((d)=>ee(o,"fg",m.cyan,d)),s})()}import{effect as ji}from"@opentui/solid";import{insert as Ei}from"@opentui/solid";import{createTextNode as Gt}from"@opentui/solid";import{insertNode as re}from"@opentui/solid";import{setProp as T}from"@opentui/solid";import{createElement as he}from"@opentui/solid";import{useTerminalDimensions as Mi}from"@opentui/solid";function os(e){let t=Mi(),r=7,n=()=>{if(e.scope!=="project")return`Delete ${e.count} ${e.count===1?"session":"sessions"}?`;let a=e.projectCount??1;return a>1?`Delete ${a} projects and all ${e.count} sessions?`:`Delete this project and all ${e.count} sessions?`},i=()=>Math.min(Math.max(n().length+4,36),Math.max(20,t().width-4)),s=()=>Math.max(0,Math.floor((t().width-i())/2)),o=()=>Math.max(0,Math.floor((t().height-7)/2)),l=(a,d)=>{e.onActionChange(a),d()};return(()=>{var a=he("box"),d=he("box"),c=he("text"),u=he("text"),g=he("text"),h=he("box"),p=he("box"),S=he("text"),w=he("box"),z=he("text");return re(a,d),re(a,h),T(a,"position","absolute"),T(a,"height",7),T(a,"flexDirection","column"),T(a,"flexShrink",0),T(a,"zIndex",40),T(a,"padding",1),re(d,c),re(d,u),re(d,g),T(d,"flexGrow",1),T(d,"flexDirection","column"),re(c,Gt("Permanent deletion")),T(c,"attributes",1),Ei(u,n),re(g,Gt("This cannot be undone.")),re(h,p),re(h,w),T(h,"height",1),T(h,"flexDirection","row"),T(h,"justifyContent","flex-end"),T(h,"gap",2),re(p,S),T(p,"width",12),T(p,"height",1),T(p,"justifyContent","center"),T(p,"alignItems","center"),T(p,"onMouseDown",()=>l("confirm",e.onConfirm)),re(S,Gt("Confirm")),re(w,z),T(w,"width",10),T(w,"height",1),T(w,"justifyContent","center"),T(w,"alignItems","center"),T(w,"onMouseDown",()=>l("cancel",e.onCancel)),re(z,Gt("Cancel")),ji((A)=>{var B=o(),H=s(),M=i(),y=m.panelAlt,O=m.error,X=m.text,de=m.warning,ie=e.action==="confirm"?m.accent:m.panelAlt,Se=e.action==="confirm"?m.background:m.text,Q=e.action==="cancel"?m.accent:m.panelAlt,f=e.action==="cancel"?m.background:m.text;return B!==A.e&&(A.e=T(a,"top",B,A.e)),H!==A.t&&(A.t=T(a,"left",H,A.t)),M!==A.a&&(A.a=T(a,"width",M,A.a)),y!==A.o&&(A.o=T(a,"backgroundColor",y,A.o)),O!==A.i&&(A.i=T(c,"fg",O,A.i)),X!==A.n&&(A.n=T(u,"fg",X,A.n)),de!==A.s&&(A.s=T(g,"fg",de,A.s)),ie!==A.h&&(A.h=T(p,"backgroundColor",ie,A.h)),Se!==A.r&&(A.r=T(S,"fg",Se,A.r)),Q!==A.d&&(A.d=T(w,"backgroundColor",Q,A.d)),f!==A.l&&(A.l=T(z,"fg",f,A.l)),A},{e:void 0,t:void 0,a:void 0,o:void 0,i:void 0,n:void 0,s:void 0,h:void 0,r:void 0,d:void 0,l:void 0}),a})()}import{effect as is}from"@opentui/solid";import{insert as Br}from"@opentui/solid";import{createComponent as Ri}from"@opentui/solid";import{createTextNode as zr}from"@opentui/solid";import{insertNode as xt}from"@opentui/solid";import{setProp as Y}from"@opentui/solid";import{createElement as Wt}from"@opentui/solid";import{For as Oi}from"solid-js";import{useTerminalDimensions as Ti}from"@opentui/solid";var Jr=[["\u2191\u2193 / j k","Navigate current list"],["g / G","Jump to first / last item"],["Tab / Shift+Tab","Switch focus"],["1 2 3","Focus projects / sessions / details"],["Enter","Open selector or confirm choice"],["\u2190 / \u2192","Switch confirm / cancel"],["Space","Select project or session"],["Esc","Clear selected items"],["d","Delete current or marked items"],["/","Search"],["r","Rescan"],["s","Cycle sort order"],["?","This help"],["q","Quit"]],Ni="Keyboard shortcuts",_i="Press Esc to close",Fi=Math.max(Ni.length,_i.length,...Jr.map((e)=>(e[0]??"").length+2+(e[1]??"").length)),Ui=Jr.length+2;function as(){let e=Ti(),t=()=>Math.min(Fi+2,Math.max(24,e().width-4)),r=()=>Math.min(Ui+2,Math.max(8,e().height-2)),n=()=>Math.max(0,Math.floor((e().width-t())/2)),i=()=>Math.max(0,Math.floor((e().height-r())/2));return(()=>{var s=Wt("box"),o=Wt("text"),l=Wt("text");return xt(s,o),xt(s,l),Y(s,"position","absolute"),Y(s,"flexDirection","column"),Y(s,"flexShrink",0),Y(s,"zIndex",30),Y(s,"paddingX",1),Y(s,"paddingTop",1),Y(s,"paddingBottom",1),xt(o,zr("Keyboard shortcuts")),Y(o,"attributes",1),Br(s,Ri(Oi,{each:Jr,children:(a)=>(()=>{var d=Wt("text"),c=zr(" ");return xt(d,c),Br(d,()=>a[0],c),Br(d,()=>a[1],null),is((u)=>Y(d,"fg",m.text,u)),d})()}),l),xt(l,zr("Press Esc to close")),is((a)=>{var d=i(),c=n(),u=t(),g=r(),h=m.panelAlt,p=m.accent,S=m.text;return d!==a.e&&(a.e=Y(s,"top",d,a.e)),c!==a.t&&(a.t=Y(s,"left",c,a.t)),u!==a.a&&(a.a=Y(s,"width",u,a.a)),g!==a.o&&(a.o=Y(s,"height",g,a.o)),h!==a.i&&(a.i=Y(s,"backgroundColor",h,a.i)),p!==a.n&&(a.n=Y(o,"fg",p,a.n)),S!==a.s&&(a.s=Y(l,"fg",S,a.s)),a},{e:void 0,t:void 0,a:void 0,o:void 0,i:void 0,n:void 0,s:void 0}),s})()}import{effect as ds}from"@opentui/solid";import{createComponent as ki}from"@opentui/solid";import{insert as Gr}from"@opentui/solid";import{createTextNode as cs}from"@opentui/solid";import{insertNode as Ht}from"@opentui/solid";import{setProp as ne}from"@opentui/solid";import{createElement as qt}from"@opentui/solid";import{For as Li}from"solid-js";function ls(e){let t=()=>e.store.issues().some((n)=>n.severity==="error"),r=(n)=>{let i=n.severity==="error"?"\u2715":"!";return N(`${i} ${n.location?`${n.location}: `:""}${n.message}`,180)};return(()=>{var n=qt("box"),i=qt("text"),s=cs("[!] Issues ("),o=cs(")"),l=qt("scrollbox");return Ht(n,i),Ht(n,l),ne(n,"height",6),ne(n,"flexDirection","column"),ne(n,"border",!0),ne(n,"borderStyle","rounded"),Ht(i,s),Ht(i,o),ne(i,"height",1),ne(i,"paddingX",1),ne(i,"attributes",1),Gr(i,()=>e.store.issues().length,o),ne(l,"flexGrow",1),ne(l,"paddingX",1),Gr(l,ki(Li,{get each(){return e.store.issues()},children:(a)=>(()=>{var d=qt("text");return Gr(d,()=>r(a)),ds((c)=>ne(d,"fg",a.severity==="error"?m.error:m.warning,c)),d})()})),ds((a)=>{var d=m.panel,c=t()?m.error:m.warning,u=t()?m.error:m.warning;return d!==a.e&&(a.e=ne(n,"backgroundColor",d,a.e)),c!==a.t&&(a.t=ne(n,"borderColor",c,a.t)),u!==a.a&&(a.a=ne(i,"fg",u,a.a)),a},{e:void 0,t:void 0,a:void 0}),n})()}import{memo as Bi}from"@opentui/solid";import{effect as fs}from"@opentui/solid";import{insert as Je}from"@opentui/solid";import{createComponent as Vr}from"@opentui/solid";import{use as zi}from"@opentui/solid";import{createTextNode as gs}from"@opentui/solid";import{insertNode as Fe}from"@opentui/solid";import{setProp as _}from"@opentui/solid";import{createElement as be}from"@opentui/solid";import{createEffect as Ji,For as Gi,onCleanup as Wi,Show as Hi}from"solid-js";import{useRenderer as qi}from"@opentui/solid";function Ne(e){if(e<1024)return`${e} B`;if(e<1048576)return`${(e/1024).toFixed(e<10240?1:0)} KB`;if(e<1073741824)return`${(e/1048576).toFixed(e<10485760?1:0)} MB`;return`${(e/1073741824).toFixed(1)} GB`}function Vt(e){if(!e)return"Unknown time";let t=Date.parse(e);if(!Number.isFinite(t))return"Unknown time";let r=Math.max(0,Math.floor((Date.now()-t)/1000));if(r<60)return"just now";if(r<3600)return`${Math.floor(r/60)}m ago`;if(r<86400)return`${Math.floor(r/3600)}h ago`;if(r<604800)return`${Math.floor(r/86400)}d ago`;return new Date(t).toLocaleDateString()}function Wr(e){if(!e)return"Unknown";let t=Date.parse(e);if(!Number.isFinite(t))return e;return new Date(t).toLocaleString()}import{CliRenderEvents as Hr}from"@opentui/core";function Xt(e,t,r){if(!t)return()=>{return};let n=0,i=()=>{let o=t.content.findDescendantById(r);if(!o||o.height<=0)return!1;return t.scrollChildIntoView(r),!0};if(i())return()=>{return};let s=()=>{if(n+=1,i()||n>=8)e.off(Hr.FRAME,s)};return e.on(Hr.FRAME,s),()=>e.off(Hr.FRAME,s)}import{effect as $i}from"@opentui/solid";import{insertNode as us}from"@opentui/solid";import{insert as ms}from"@opentui/solid";import{setProp as _e}from"@opentui/solid";import{createElement as qr}from"@opentui/solid";function ze(e){return(()=>{var t=qr("box"),r=qr("text"),n=qr("text");return us(t,r),us(t,n),_e(t,"flexGrow",1),_e(t,"padding",2),_e(t,"justifyContent","center"),_e(t,"alignItems","center"),ms(r,()=>e.title),_e(n,"wrapMode","word"),_e(n,"width","100%"),ms(n,()=>e.detail),$i((i)=>{var s=m.muted,o=m.muted;return s!==i.e&&(i.e=_e(r,"fg",s,i.e)),o!==i.t&&(i.t=_e(n,"fg",o,i.t)),i},{e:void 0,t:void 0}),t})()}function Qt(e){let t=qi(),r;return Ji(()=>{let n=e.store.filteredProjects(),i=e.store.selectedProjectId();if(!i||!n.some((s)=>s.id===i))return;Wi(Xt(t,r,`project-item-${i}`))}),(()=>{var n=be("box"),i=be("text");return Fe(n,i),_(n,"flexDirection","column"),_(n,"flexGrow",1),_(n,"flexShrink",1),_(n,"minHeight",0),_(n,"minWidth",24),_(n,"border",!0),_(n,"borderStyle","rounded"),Fe(i,gs("[1] Projects")),_(i,"height",2),_(i,"paddingX",1),_(i,"attributes",1),Je(n,Vr(Hi,{get when(){return e.store.filteredProjects().length>0},get fallback(){return Vr(ze,{title:"No projects found",get detail(){return e.store.searchQuery()?"Try a different search.":"The session directory is empty."}})},get children(){var s=be("scrollbox");return zi((o)=>{r=o},s),_(s,"flexGrow",1),_(s,"minHeight",0),_(s,"contentOptions",{gap:1}),Je(s,Vr(Gi,{get each(){return e.store.filteredProjects()},children:(o)=>{let l=()=>e.store.selectedProjectId()===o.id,a=()=>e.store.selectedProjectIds().has(o.id);return(()=>{var d=be("box"),c=be("text"),u=be("box"),g=be("text"),h=be("text"),p=gs(" sessions \xB7 "),S=be("text");return Fe(d,c),Fe(d,u),_(d,"height",3),_(d,"flexDirection","row"),_(c,"width",1),Je(c,()=>a()?`\u258C
3
+ \u258C
4
+ \u258C`:`
5
+
6
+ `),Fe(u,g),Fe(u,h),Fe(u,S),_(u,"flexGrow",1),_(u,"flexDirection","column"),_(u,"paddingLeft",1),_(u,"paddingRight",1),Je(g,()=>o.displayPath),Fe(h,p),Je(h,()=>o.sessionCount,p),Je(h,()=>Ne(o.totalSizeBytes),null),Je(S,(()=>{var w=Bi(()=>o.warningCount>0);return()=>w()?`! ${o.warningCount} warnings`:Vt(o.updatedAt)})()),fs((w)=>{var z=`project-item-${o.id}`,A=l()?m.selected:m.panel,B=m.selected,H=l()?m.muted:m.text,M=m.muted,y=o.warningCount>0?m.warning:m.muted;return z!==w.e&&(w.e=_(d,"id",z,w.e)),A!==w.t&&(w.t=_(d,"backgroundColor",A,w.t)),B!==w.a&&(w.a=_(c,"fg",B,w.a)),H!==w.o&&(w.o=_(g,"fg",H,w.o)),M!==w.i&&(w.i=_(h,"fg",M,w.i)),y!==w.n&&(w.n=_(S,"fg",y,w.n)),w},{e:void 0,t:void 0,a:void 0,o:void 0,i:void 0,n:void 0}),d})()}})),s}}),null),fs((s)=>{var o=e.width??"28%",l=m.panel,a=e.store.focus()==="projects"?m.accent:m.border,d=m.accent,c=e.store.focus()==="projects",u=m.accent;return o!==s.e&&(s.e=_(n,"width",o,s.e)),l!==s.t&&(s.t=_(n,"backgroundColor",l,s.t)),a!==s.a&&(s.a=_(n,"borderColor",a,s.a)),d!==s.o&&(s.o=_(n,"focusedBorderColor",d,s.o)),c!==s.i&&(s.i=_(n,"focused",c,s.i)),u!==s.n&&(s.n=_(i,"fg",u,s.n)),s},{e:void 0,t:void 0,a:void 0,o:void 0,i:void 0,n:void 0}),n})()}import{effect as Vi}from"@opentui/solid";import{use as Xi}from"@opentui/solid";import{createTextNode as Qi}from"@opentui/solid";import{insertNode as Xr}from"@opentui/solid";import{setProp as se}from"@opentui/solid";import{createElement as Qr}from"@opentui/solid";import{onMount as Ki}from"solid-js";function ps(e){let t;return Ki(()=>t?.focus()),(()=>{var r=Qr("box"),n=Qr("text"),i=Qr("input");Xr(r,n),Xr(r,i),se(r,"flexGrow",1),se(r,"height",1),Xr(n,Qi("/ "));var s=t;return typeof s==="function"?Xi(s,i):t=i,se(i,"flexGrow",1),se(i,"placeholder","Search projects, sessions, IDs, messages"),se(i,"onInput",(o)=>e.store.setSearchQuery(o)),Vi((o)=>{var l=m.panelAlt,a=m.cyan,d=e.store.searchQuery(),c=m.text,u=m.cyan,g=m.panelAlt,h=m.panelAlt,p=e.onClose;return l!==o.e&&(o.e=se(r,"backgroundColor",l,o.e)),a!==o.t&&(o.t=se(n,"fg",a,o.t)),d!==o.a&&(o.a=se(i,"value",d,o.a)),c!==o.o&&(o.o=se(i,"textColor",c,o.o)),u!==o.i&&(o.i=se(i,"cursorColor",u,o.i)),g!==o.n&&(o.n=se(i,"backgroundColor",g,o.n)),h!==o.s&&(o.s=se(i,"focusedBackgroundColor",h,o.s)),p!==o.h&&(o.h=se(i,"onSubmit",p,o.h)),o},{e:void 0,t:void 0,a:void 0,o:void 0,i:void 0,n:void 0,s:void 0,h:void 0}),r})()}import{effect as lt}from"@opentui/solid";import{createComponent as Ge}from"@opentui/solid";import{memo as hs}from"@opentui/solid";import{insert as Z}from"@opentui/solid";import{createTextNode as ae}from"@opentui/solid";import{insertNode as k}from"@opentui/solid";import{setProp as P}from"@opentui/solid";import{createElement as J}from"@opentui/solid";import{For as Ss,Show as Kr}from"solid-js";function Kt(e){return(()=>{var t=J("box"),r=J("text");return k(t,r),P(t,"flexDirection","column"),P(t,"flexGrow",1),P(t,"flexShrink",1),P(t,"minHeight",0),P(t,"minWidth",34),P(t,"border",!0),P(t,"borderStyle","rounded"),k(r,ae("[3] Session details")),P(r,"height",2),P(r,"paddingX",1),P(r,"attributes",1),Z(t,Ge(Kr,{get when(){return!e.store.detailLoading()},get fallback(){return Ge(ze,{title:"Loading details",detail:"Reading this session as a stream\u2026"})},get children(){return Ge(Kr,{get when(){return e.store.sessionDetail()},get fallback(){return Ge(ze,{title:"No session selected",detail:"Select a session to inspect its metadata."})},get children(){var n=J("scrollbox"),i=J("text"),s=J("text"),o=J("text"),l=J("text"),a=J("text"),d=J("text"),c=J("text"),u=J("text"),g=J("text"),h=J("text"),p=J("text"),S=J("text"),w=J("text"),z=ae(" \xB7 "),A=J("text"),B=J("text"),H=J("text"),M=J("text");return k(n,i),k(n,s),k(n,o),k(n,l),k(n,a),k(n,d),k(n,c),k(n,u),k(n,g),k(n,h),k(n,p),k(n,S),k(n,w),k(n,A),k(n,B),k(n,H),k(n,M),P(n,"flexGrow",1),P(n,"minHeight",0),P(n,"padding",1),P(i,"attributes",1),Z(i,()=>e.store.sessionDetail()?.title),k(s,ae("Agent")),Z(o,()=>e.store.sessionDetail()?.agentId),k(l,ae("Session ID")),Z(a,()=>e.store.sessionDetail()?.sessionId??"Unknown"),k(d,ae("Project")),P(c,"wrapMode","word"),Z(c,()=>e.store.sessionDetail()?.projectLocation??e.store.sessionDetail()?.projectName),k(u,ae("Created")),Z(g,()=>Wr(e.store.sessionDetail()?.createdAt)),k(h,ae("Updated")),Z(p,()=>Wr(e.store.sessionDetail()?.updatedAt)),k(S,ae("Size \xB7 messages")),k(w,z),Z(w,()=>Ne(e.store.sessionDetail()?.sizeBytes??0),z),Z(w,()=>e.store.sessionDetail()?.messageCount??0,null),Z(n,Ge(Ss,{get each(){return e.store.sessionDetail()?.fields??[]},children:(y)=>[(()=>{var O=J("text");return Z(O,()=>y.label),lt((X)=>P(O,"fg",m.muted,X)),O})(),(()=>{var O=J("text");return P(O,"wrapMode","word"),Z(O,()=>y.value),lt((X)=>P(O,"fg",m.text,X)),O})()]}),A),k(A,ae("First user message")),P(B,"wrapMode","word"),Z(B,(()=>{var y=hs(()=>!!e.store.sessionDetail()?.firstUserMessage);return()=>y()?N(e.store.sessionDetail()?.firstUserMessage??"",240):"Unknown"})()),k(H,ae("Last user message")),P(M,"wrapMode","word"),Z(M,(()=>{var y=hs(()=>!!e.store.sessionDetail()?.lastUserMessage);return()=>y()?N(e.store.sessionDetail()?.lastUserMessage??"",240):"Unknown"})()),Z(n,Ge(Kr,{get when(){return(e.store.sessionDetail()?.warnings.length??0)>0},get children(){return[(()=>{var y=J("text");return k(y,ae("Warnings")),lt((O)=>P(y,"fg",m.warning,O)),y})(),Ge(Ss,{get each(){return e.store.sessionDetail()?.warnings??[]},children:(y)=>(()=>{var O=J("text"),X=ae("! ");return k(O,X),P(O,"wrapMode","word"),Z(O,y,null),lt((de)=>P(O,"fg",m.warning,de)),O})()})]}}),null),lt((y)=>{var O=e.store.focus()==="detail",X=m.text,de=m.muted,ie=m.text,Se=m.muted,Q=m.text,f=m.muted,b=m.text,E=m.muted,G=m.text,V=m.muted,ue=m.text,q=m.muted,D=m.text,K=m.muted,ke=m.text,me=m.muted,Le=m.text;return O!==y.e&&(y.e=P(n,"focused",O,y.e)),X!==y.t&&(y.t=P(i,"fg",X,y.t)),de!==y.a&&(y.a=P(s,"fg",de,y.a)),ie!==y.o&&(y.o=P(o,"fg",ie,y.o)),Se!==y.i&&(y.i=P(l,"fg",Se,y.i)),Q!==y.n&&(y.n=P(a,"fg",Q,y.n)),f!==y.s&&(y.s=P(d,"fg",f,y.s)),b!==y.h&&(y.h=P(c,"fg",b,y.h)),E!==y.r&&(y.r=P(u,"fg",E,y.r)),G!==y.d&&(y.d=P(g,"fg",G,y.d)),V!==y.l&&(y.l=P(h,"fg",V,y.l)),ue!==y.u&&(y.u=P(p,"fg",ue,y.u)),q!==y.c&&(y.c=P(S,"fg",q,y.c)),D!==y.w&&(y.w=P(w,"fg",D,y.w)),K!==y.m&&(y.m=P(A,"fg",K,y.m)),ke!==y.f&&(y.f=P(B,"fg",ke,y.f)),me!==y.y&&(y.y=P(H,"fg",me,y.y)),Le!==y.g&&(y.g=P(M,"fg",Le,y.g)),y},{e:void 0,t:void 0,a:void 0,o:void 0,i:void 0,n:void 0,s:void 0,h:void 0,r:void 0,d:void 0,l:void 0,u:void 0,c:void 0,w:void 0,m:void 0,f:void 0,y:void 0,g:void 0}),n}})}}),null),lt((n)=>{var i=e.width??"33%",s=m.panel,o=e.store.focus()==="detail"?m.accent:m.border,l=m.accent,a=e.store.focus()==="detail",d=e.overlay?"absolute":"relative",c=e.overlay?0:void 0,u=e.overlay?0:void 0,g=e.overlay?"100%":void 0,h=e.overlay?10:void 0,p=m.accent;return i!==n.e&&(n.e=P(t,"width",i,n.e)),s!==n.t&&(n.t=P(t,"backgroundColor",s,n.t)),o!==n.a&&(n.a=P(t,"borderColor",o,n.a)),l!==n.o&&(n.o=P(t,"focusedBorderColor",l,n.o)),a!==n.i&&(n.i=P(t,"focused",a,n.i)),d!==n.n&&(n.n=P(t,"position",d,n.n)),c!==n.s&&(n.s=P(t,"top",c,n.s)),u!==n.h&&(n.h=P(t,"right",u,n.h)),g!==n.r&&(n.r=P(t,"height",g,n.r)),h!==n.d&&(n.d=P(t,"zIndex",h,n.d)),p!==n.l&&(n.l=P(r,"fg",p,n.l)),n},{e:void 0,t:void 0,a:void 0,o:void 0,i:void 0,n:void 0,s:void 0,h:void 0,r:void 0,d:void 0,l:void 0}),t})()}import{memo as Yi}from"@opentui/solid";import{effect as ys}from"@opentui/solid";import{insert as ut}from"@opentui/solid";import{createComponent as Yr}from"@opentui/solid";import{use as Zi}from"@opentui/solid";import{createTextNode as ea}from"@opentui/solid";import{insertNode as We}from"@opentui/solid";import{setProp as F}from"@opentui/solid";import{createElement as Ae}from"@opentui/solid";import{createEffect as ta,For as ra,onCleanup as na,Show as sa}from"solid-js";import{useRenderer as oa}from"@opentui/solid";function Yt(e){let t=oa(),r;return ta(()=>{let n=e.store.filteredSessions(),i=e.store.selectedSessionId();if(!i||!n.some((s)=>s.id===i))return;na(Xt(t,r,`session-item-${i}`))}),(()=>{var n=Ae("box"),i=Ae("text");return We(n,i),F(n,"flexDirection","column"),F(n,"flexGrow",1),F(n,"flexShrink",1),F(n,"minHeight",0),F(n,"minWidth",30),F(n,"border",!0),F(n,"borderStyle","rounded"),We(i,ea("[2] Sessions")),F(i,"height",2),F(i,"paddingX",1),F(i,"attributes",1),ut(n,Yr(sa,{get when(){return e.store.filteredSessions().length>0},get fallback(){return Yr(ze,{title:"No sessions in this project",get detail(){return e.store.searchQuery()?"Try a different search.":"Try another project or press r to rescan."}})},get children(){var s=Ae("scrollbox");return Zi((o)=>{r=o},s),F(s,"flexGrow",1),F(s,"minHeight",0),F(s,"contentOptions",{gap:1}),ut(s,Yr(ra,{get each(){return e.store.filteredSessions()},children:(o)=>{let l=()=>e.store.selectedSessionId()===o.id,a=()=>e.store.selectedSessionIds().has(o.id);return(()=>{var d=Ae("box"),c=Ae("text"),u=Ae("box"),g=Ae("text"),h=Ae("text"),p=Ae("text");return We(d,c),We(d,u),F(d,"height",3),F(d,"flexDirection","row"),F(c,"width",1),ut(c,()=>a()?`\u258C
7
+ \u258C
8
+ \u258C`:`
9
+
10
+ `),We(u,g),We(u,h),We(u,p),F(u,"flexGrow",1),F(u,"flexDirection","column"),F(u,"paddingLeft",1),F(u,"paddingRight",1),ut(g,()=>o.title),ut(h,()=>[Vt(o.updatedAt),o.sizeBytes===void 0?void 0:Ne(o.sizeBytes),o.messageCount===void 0?void 0:`${o.messageCount} messages`].filter((S)=>Boolean(S)).join(" \xB7 ")),ut(p,(()=>{var S=Yi(()=>o.warnings.length>0);return()=>S()?`! ${o.warnings.length} parse warnings`:o.sessionId??"no session id"})()),ys((S)=>{var w=`session-item-${o.id}`,z=l()?m.selected:m.panel,A=m.selected,B=l()?m.muted:m.text,H=m.muted,M=o.warnings.length>0?m.warning:m.muted;return w!==S.e&&(S.e=F(d,"id",w,S.e)),z!==S.t&&(S.t=F(d,"backgroundColor",z,S.t)),A!==S.a&&(S.a=F(c,"fg",A,S.a)),B!==S.o&&(S.o=F(g,"fg",B,S.o)),H!==S.i&&(S.i=F(h,"fg",H,S.i)),M!==S.n&&(S.n=F(p,"fg",M,S.n)),S},{e:void 0,t:void 0,a:void 0,o:void 0,i:void 0,n:void 0}),d})()}})),s}}),null),ys((s)=>{var o=e.width??"39%",l=m.panel,a=e.store.focus()==="sessions"?m.accent:m.border,d=m.accent,c=e.store.focus()==="sessions",u=m.accent;return o!==s.e&&(s.e=F(n,"width",o,s.e)),l!==s.t&&(s.t=F(n,"backgroundColor",l,s.t)),a!==s.a&&(s.a=F(n,"borderColor",a,s.a)),d!==s.o&&(s.o=F(n,"focusedBorderColor",d,s.o)),c!==s.i&&(s.i=F(n,"focused",c,s.i)),u!==s.n&&(s.n=F(i,"fg",u,s.n)),s},{e:void 0,t:void 0,a:void 0,o:void 0,i:void 0,n:void 0}),n})()}import{createComponent as ia}from"@opentui/solid";import{effect as ws}from"@opentui/solid";import{createTextNode as Zt}from"@opentui/solid";import{insertNode as mt}from"@opentui/solid";import{insert as er}from"@opentui/solid";import{setProp as Pe}from"@opentui/solid";import{createElement as tr}from"@opentui/solid";import{Show as aa}from"solid-js";function vs(e){let t=()=>{if(e.store.scanStatus()==="scanning")return"Scanning\u2026";if(e.store.scanStatus()==="error")return"Scan error";if(e.store.issues().length>0)return`Scan complete \xB7 ${e.store.issues().length} issues`;return`Scan complete \xB7 ${e.store.scannedSources()} sources`};return(()=>{var r=tr("box"),n=tr("text"),i=Zt(" \xB7 "),s=tr("text");return mt(r,n),mt(r,s),Pe(r,"height",1),Pe(r,"marginX",1),Pe(r,"flexDirection","row"),Pe(r,"paddingX",1),mt(n,i),Pe(n,"flexGrow",1),er(n,t,i),er(n,()=>e.store.summary(),null),er(r,ia(aa,{get when(){return e.store.searchQuery()},get children(){var o=tr("text"),l=Zt("Search: "),a=Zt(" \xB7 ");return mt(o,l),mt(o,a),er(o,()=>e.store.searchQuery(),a),ws((d)=>Pe(o,"fg",m.warning,d)),o}}),s),mt(s,Zt("\u2191\u2193/jk Navigate \xB7 Space Select \xB7 d Delete \xB7 / Search \xB7 r Refresh \xB7 ? Help \xB7 q Quit")),ws((o)=>{var l=m.panel,a=e.store.scanStatus()==="error"?m.error:m.cyan,d=m.muted;return l!==o.e&&(o.e=Pe(r,"backgroundColor",l,o.e)),a!==o.t&&(o.t=Pe(n,"fg",a,o.t)),d!==o.a&&(o.a=Pe(s,"fg",d,o.a)),o},{e:void 0,t:void 0,a:void 0}),r})()}var rr=["agent","projects","sessions","detail"];function Ps(e){let t=ca(),r=la(),[n,i]=Ue(!1),[s,o]=Ue(!1),[l,a]=Ue(!1),[d,c]=Ue(0),[u,g]=Ue(!1),[h,p]=Ue([]),[S,w]=Ue("session"),[z,A]=Ue("confirm"),B=()=>r().width>=120?"wide":r().width>=90?"medium":"narrow",H=(f)=>{let b=e.store.filteredProjects();if(b.length===0)return;let E=b.findIndex((V)=>V.id===e.store.selectedProjectId()),G=Math.max(0,Math.min(b.length-1,(E<0?0:E)+f));e.store.chooseProject(b[G]?.id)},M=(f)=>{let b=e.store.filteredSessions();if(b.length===0)return;let E=b.findIndex((V)=>V.id===e.store.selectedSessionId()),G=Math.max(0,Math.min(b.length-1,(E<0?0:E)+f));e.store.chooseSession(b[G]?.id)},y=(f)=>{if(e.store.focus()==="projects"){let b=e.store.filteredProjects(),E=f==="start"?b[0]:b[b.length-1];if(E)e.store.chooseProject(E.id);return}if(e.store.focus()==="sessions"){let b=e.store.filteredSessions(),E=f==="start"?b[0]:b[b.length-1];if(E)e.store.chooseSession(E.id)}},O=(f)=>{let E=(rr.indexOf(e.store.focus())+f+rr.length)%rr.length;e.store.setFocus(rr[E]??"projects")},X=()=>i(!1),de=()=>{let f=["updated-desc","updated-asc","name-asc","size-desc"],b=f.indexOf(e.store.sort());e.store.setSort(f[(b+1)%f.length]??"updated-desc")},ie=()=>{let f=e.store.sessions();if(e.store.focus()==="projects"){let G=[...e.store.selectedProjectIds()],V=G.length>0?G:e.store.selectedProjectId()?[e.store.selectedProjectId()]:[];return{ids:f.filter((ue)=>V.includes(ue.projectId)).map((ue)=>ue.id),scope:"project"}}let b=f.filter((G)=>e.store.selectedSessionIds().has(G.id));if(b.length>0)return{ids:b.map((G)=>G.id),scope:"session"};let E=e.store.selectedSession();return{ids:E?[E.id]:[],scope:"session"}},Se=()=>{let f=e.store.agents().find((E)=>E.id===e.store.activeAgentId());if(e.store.focus()==="agent"||!f?.capabilities.canDelete||e.store.deleteStatus()==="deleting")return;let b=ie();if(b.ids.length===0)return;p(b.ids),w(b.scope),A("confirm"),g(!0)},Q=()=>{let f=e.store.sessions().filter((b)=>h().includes(b.id));g(!1),e.store.deleteSessions(f)};return da((f)=>{if(u()){if(f.name==="escape"){g(!1);return}if(f.name==="left"||f.name==="h"){f.preventDefault(),A("confirm");return}if(f.name==="right"||f.name==="l"){f.preventDefault(),A("cancel");return}if(f.name==="return"||f.name==="enter")if(z()==="confirm")Q();else g(!1);return}if(n()){if(f.name==="escape")X();return}if(s()){if(f.name==="escape"||f.name==="question")o(!1);return}if(l()){if(f.name==="escape"){a(!1);return}if(f.name==="up"||f.name==="k"){c((b)=>Math.max(0,b-1));return}if(f.name==="down"||f.name==="j"){c((b)=>Math.min(e.store.agents().length-1,b+1));return}if(f.name==="return"||f.name==="enter"){let b=e.store.agents()[d()];if(b?.status==="available")e.store.setActiveAgent(b.id),e.store.setFocus("projects");a(!1);return}return}if(f.name==="escape"){if(e.store.selectedProjectIds().size>0||e.store.selectedSessionIds().size>0)f.preventDefault(),e.store.clearSelected();return}if(f.ctrl&&f.name==="c"){t.destroy();return}if(f.name==="q"){t.destroy();return}if(f.name==="r"){e.store.scan();return}if(f.name==="d"){Se();return}if(f.name==="space"||f.name===" "||f.sequence===" "||f.raw===" "){if(e.store.focus()==="projects"){let E=e.store.selectedProject();if(E)f.preventDefault(),f.stopPropagation(),e.store.toggleProject(E.id);return}let b=e.store.selectedSession();if(b)f.preventDefault(),f.stopPropagation(),e.store.toggleSession(b.id);return}if(f.name==="s"){de();return}if(f.name==="question"||f.sequence==="?"){o(!0);return}if(f.name==="slash"||f.sequence==="/"){i(!0);return}if(f.name==="tab"){O(f.shift?-1:1);return}if(f.name==="1"){e.store.setFocus("projects");return}if(f.name==="2"){e.store.setFocus("sessions");return}if(f.name==="3"){e.store.setFocus("detail");return}if(f.name==="up"||f.name==="k"){if(e.store.focus()==="projects")f.preventDefault(),H(-1);if(e.store.focus()==="sessions")f.preventDefault(),M(-1);return}if(f.name==="down"||f.name==="j"){if(e.store.focus()==="projects")f.preventDefault(),H(1);if(e.store.focus()==="sessions")f.preventDefault(),M(1);return}if(f.name==="g"&&!f.shift){if(e.store.focus()==="projects"||e.store.focus()==="sessions")f.preventDefault(),y("start");return}if(f.name==="G"||f.name==="g"&&f.shift){if(e.store.focus()==="projects"||e.store.focus()==="sessions")f.preventDefault(),y("end");return}if(f.name==="return"||f.name==="enter"){if(e.store.focus()==="agent"){a(!0);return}if(e.store.focus()==="sessions"&&B()!=="wide"){e.store.setFocus("detail");return}if(e.store.focus()==="detail"&&B()!=="wide")e.store.setFocus("sessions")}}),(()=>{var f=xe("box"),b=xe("box"),E=xe("box"),G=xe("text"),V=xe("text"),ue=As(" "),q=xe("box");return He(f,b),He(f,q),C(f,"width","100%"),C(f,"height","100%"),C(f,"flexDirection","column"),C(f,"position","relative"),C(f,"overflow","hidden"),He(b,E),C(b,"marginX",1),C(b,"flexDirection","column"),C(b,"paddingX",1),C(b,"border",!0),C(b,"borderStyle","rounded"),C(b,"position","relative"),C(b,"overflow","visible"),He(E,G),He(E,V),C(E,"height",1),C(E,"flexDirection","row"),C(E,"alignItems","center"),He(G,As("ASC \xB7 Agent Session Clean")),C(G,"width",31),C(G,"attributes",1),te(E,L(ss,{get store(){return e.store},get open(){return l()},get selectedIndex(){return d()}}),V),He(V,ue),C(V,"flexGrow",1),te(V,()=>e.store.rootPath(),null),te(E,L(oe,{get when(){return!n()},get children(){var D=xe("text");return te(D,(()=>{var K=bs(()=>e.store.scanStatus()==="scanning");return()=>K()?"Scanning\u2026":e.store.summary()})()),Zr((K)=>C(D,"fg",m.cyan,K)),D}}),null),te(b,L(oe,{get when(){return n()},get children(){return L(ps,{get store(){return e.store},onClose:X})}}),null),C(q,"flexGrow",1),C(q,"flexShrink",1),C(q,"flexBasis",0),C(q,"minHeight",0),C(q,"overflow","hidden"),C(q,"flexDirection","row"),C(q,"position","relative"),C(q,"gap",1),C(q,"paddingX",1),te(q,L(oe,{get when(){return B()==="wide"},get children(){return[L(Qt,{get store(){return e.store},width:"28%"}),L(Yt,{get store(){return e.store},width:"39%"}),L(Kt,{get store(){return e.store},width:"33%"})]}}),null),te(q,L(oe,{get when(){return B()==="medium"},get children(){return[L(Qt,{get store(){return e.store},width:"32%"}),L(Yt,{get store(){return e.store},width:"68%"}),L(oe,{get when(){return e.store.focus()==="detail"},get children(){return L(Kt,{get store(){return e.store},overlay:!0,width:"70%"})}})]}}),null),te(q,L(oe,{get when(){return B()==="narrow"},get children(){return[L(oe,{get when(){return e.store.focus()==="detail"},get children(){return L(Kt,{get store(){return e.store},width:"100%"})}}),L(oe,{get when(){return bs(()=>e.store.focus()!=="detail")()&&e.store.focus()!=="sessions"},get children(){return L(Qt,{get store(){return e.store},width:"100%"})}}),L(oe,{get when(){return e.store.focus()==="sessions"},get children(){return L(Yt,{get store(){return e.store},width:"100%"})}})]}}),null),te(f,L(oe,{get when(){return e.store.issues().length>0},get children(){var D=xe("box");return C(D,"paddingX",1),te(D,L(ls,{get store(){return e.store}})),D}}),null),te(f,L(vs,{get store(){return e.store}}),null),te(f,L(oe,{get when(){return u()||s()},get children(){var D=xe("box");return C(D,"position","absolute"),C(D,"top",0),C(D,"left",0),C(D,"width","100%"),C(D,"height","100%"),C(D,"zIndex",29),Zr((K)=>C(D,"backgroundColor",m.overlay,K)),D}}),null),te(f,L(oe,{get when(){return u()},get children(){return L(os,{get count(){return h().length},get projectCount(){return new Set(e.store.sessions().filter((D)=>h().includes(D.id)).map((D)=>D.projectId)).size},get scope(){return S()},get action(){return z()},onActionChange:A,onConfirm:Q,onCancel:()=>g(!1)})}}),null),te(f,L(oe,{get when(){return s()},get children(){return L(as,{})}}),null),Zr((D)=>{var K=m.background,ke=n()?4:3,me=m.panel,Le=e.store.focus()==="agent"?m.accent:m.border,Dt=l()?100:0,It=m.text,Ct=m.muted;return K!==D.e&&(D.e=C(f,"backgroundColor",K,D.e)),ke!==D.t&&(D.t=C(b,"height",ke,D.t)),me!==D.a&&(D.a=C(b,"backgroundColor",me,D.a)),Le!==D.o&&(D.o=C(b,"borderColor",Le,D.o)),Dt!==D.i&&(D.i=C(b,"zIndex",Dt,D.i)),It!==D.n&&(D.n=C(G,"fg",It,D.n)),Ct!==D.s&&(D.s=C(V,"fg",Ct,D.s)),D},{e:void 0,t:void 0,a:void 0,o:void 0,i:void 0,n:void 0,s:void 0}),f})()}import{createEffect as ua,createSignal as W,onCleanup as ma}from"solid-js";function en(e,t){let r=new Set(e);if(r.has(t))r.delete(t);else r.add(t);return r}function xs(e,t){let r=new Set(e);for(let n of t)r.add(n);return r}function qe(){return new Set}function tn(e){return[e.title,e.sessionId,e.ref.sourceId,e.firstUserMessage,e.lastUserMessage].filter(Boolean).join(" ").toLowerCase()}function nr(e,t){return[...e].sort((r,n)=>{if(t==="name-asc")return r.title.localeCompare(n.title);if(t==="size-desc")return(n.sizeBytes??0)-(r.sizeBytes??0);let i=Date.parse(r.updatedAt)||0,s=Date.parse(n.updatedAt)||0;return t==="updated-asc"?i-s:s-i})}function Ds(e,t){return[...e].sort((r,n)=>{if(t==="name-asc")return r.displayPath.localeCompare(n.displayPath);if(t==="size-desc")return n.totalSizeBytes-r.totalSizeBytes;let i=Date.parse(r.updatedAt)||0,s=Date.parse(n.updatedAt)||0;return t==="updated-asc"?i-s:s-i})}function Is(e,t,r){let n=e.find((s)=>s.id===t);if(n)return n;let i=r.findIndex((s)=>s.id===t);if(i<0)return e[0];return e[Math.min(i,e.length-1)]}function Cs(e,t=e.agents[0]?.id??"pi"){let[r]=W(e.agents),[n,i]=W(t),[s,o]=W("idle"),l=e.agents.find((v)=>v.id===t),[a,d]=W(l?.detail??l?.label??t),[c,u]=W([]),[g,h]=W([]),[p,S]=W(),[w,z]=W(),[A,B]=W(new Set),[H,M]=W(new Set),[y,O]=W(),[X,de]=W("projects"),[ie,Se]=W(""),[Q,f]=W("updated-desc"),[b,E]=W([]),[G,V]=W(0),[ue,q]=W(0),[D,K]=W(!1),[ke,me]=W("idle"),[Le,Dt]=W(),[It,Ct]=W(),jt=0,pt=0,ht=0,Et,Mt,Rt,ye=(v,x)=>Boolean(v&&v.toLowerCase().includes(x)),St=()=>{let v=ie().trim().toLowerCase(),x=c();if(!v)return Ds(x,Q());return Ds(x.filter((j)=>{if(ye(j.name,v)||ye(j.location,v)||ye(j.displayPath,v))return!0;return g().some((R)=>R.projectId===j.id&&tn(R).includes(v))}),Q())},yt=()=>{let v=p();if(!v)return[];let x=ie().trim().toLowerCase(),j=c().find((I)=>I.id===v),R=Boolean(x&&j&&(ye(j.name,x)||ye(j.location,x)||ye(j.displayPath,x))),U=g().filter((I)=>I.projectId===v);if(!x||R)return nr(U,Q());return nr(U.filter((I)=>tn(I).includes(x)),Q())},Os=()=>c().find((v)=>v.id===p()),Ts=()=>g().find((v)=>v.id===w()),Ns=()=>{let v=g(),x=v.reduce((j,R)=>j+(R.sizeBytes??0),0);return`${c().length} projects \xB7 ${v.length} sessions \xB7 ${Ne(x)}`};async function Ve(v){let x=++pt;if(Mt?.abort(),!v){O(void 0),K(!1);return}let j=g().find((U)=>U.id===v);if(!j){O(void 0),K(!1);return}let R=new AbortController;Mt=R,O(void 0),K(!0);try{let U=await e.loadSessionDetail(j,R.signal);if(x===pt&&w()===v)O(U)}catch(U){if(x!==pt||w()!==v)return;if(U.name==="AbortError"||U.code==="ABORT_ERR")return;let I=U instanceof Error?U.message:String(U);O({...j,warnings:[...j.warnings,I],fields:[],warningCount:j.warnings.length+1})}finally{if(x===pt)K(!1)}}function sr(v){let x=ie().trim().toLowerCase(),j=c().find((I)=>I.id===v),R=Boolean(x&&j&&(ye(j.name,x)||ye(j.location,x)||ye(j.displayPath,x))),U=g().filter((I)=>I.projectId===v);if(!x||R)return nr(U,Q());return nr(U.filter((I)=>tn(I).includes(x)),Q())}function _s(v,x=!0){let j=St(),R=j.find((I)=>I.id===v)??j[0];S(R?.id);let U=R?sr(R.id)[0]:void 0;if(z(U?.id),O(void 0),x)Ve(U?.id)}function Fs(v,x=!0){let j=yt(),R=j.find((U)=>U.id===v)??j[0];if(z(R?.id),O(void 0),x)Ve(R?.id)}function Us(v,x,j){let R=St(),U=yt();d(v.rootPath),u(v.projects),h(v.sessions),E(v.issues),V(v.scannedSources),q(v.failedSources),Ct(new Date().toISOString()),B((we)=>new Set([...we].filter((De)=>v.projects.some((Xe)=>Xe.id===De)))),M((we)=>new Set([...we].filter((De)=>v.sessions.some((Xe)=>Xe.id===De))));let I=Is(St(),x,R);S(I?.id);let fe=Is(I?sr(I.id):[],j,U);if(z(fe?.id),O(void 0),fe)Ve(fe.id)}function ks(v){let x=r().find((j)=>j.id===v);if(!x||x.id===n())return;Et?.abort(),Mt?.abort(),Rt?.abort(),jt+=1,pt+=1,ht+=1,i(v),d(x.detail??x.label),o("idle"),me("idle"),u([]),h([]),E([]),V(0),q(0),S(void 0),z(void 0),B(qe()),M(qe()),O(void 0),or()}async function or(){let v=n(),x=++jt;Et?.abort();let j=new AbortController;Et=j;let R=p(),U=w();o("scanning");try{let I=await e.scanSessions(v,{signal:j.signal});if(x!==jt||n()!==v)return;Us(I,R,U),o(I.issues.some((fe)=>fe.severity==="error")||I.failedSources>0&&I.sessions.length===0?"error":"complete")}catch(I){if(x!==jt||I.name==="AbortError"||I.code==="ABORT_ERR")return;o("error"),E([{message:I instanceof Error?I.message:String(I),severity:"error"}]),u([]),h([]),S(void 0),z(void 0),M(qe()),O(void 0)}}async function rn(v){let x=n(),j=v.filter((I)=>I.agentId===x&&I.ref.agentId===x);if(j.length===0)return;let R=++ht;Rt?.abort();let U=new AbortController;Rt=U,me("deleting");try{let I=await e.deleteSessions(j,{signal:U.signal});if(R!==ht)return I;Dt(I);let fe=I.items.filter((we)=>!we.success);if(me(fe.length>0?"error":"complete"),M(new Set(fe.map((we)=>we.sessionId))),await or(),R===ht&&fe.length>0){let we=new Map(j.map((De)=>[De.id,De]));E((De)=>[...De,...fe.map((Xe)=>({location:we.get(Xe.sessionId)?.ref.sourceId,message:Xe.message??"Unable to delete session",severity:"error"}))]),o("error")}return I}catch(I){if(I.name==="AbortError"||I.code==="ABORT_ERR")return;if(R===ht)me("error"),E([{message:I instanceof Error?I.message:String(I),severity:"error"}]);return}}async function Ls(){let v=g().filter((x)=>H().has(x.id));return rn(v)}function $s(v){B((x)=>en(x,v))}function Bs(v){M((x)=>en(x,v))}function zs(){M((v)=>xs(v,yt().map((x)=>x.id)))}function Js(){M(qe())}function Gs(){B(qe()),M(qe())}return ua(()=>{let v=St(),x=p();if(!v.some((R)=>R.id===x)){let R=v[0];S(R?.id);let U=R?sr(R.id)[0]:void 0;if(z(U?.id),O(void 0),U)Ve(U.id);return}let j=yt();if(!j.some((R)=>R.id===w())){let R=j[0];if(z(R?.id),O(void 0),R)Ve(R.id)}}),ma(()=>{Et?.abort(),Mt?.abort(),Rt?.abort()}),{agents:r,activeAgentId:n,setActiveAgent:ks,scanStatus:s,rootPath:a,projects:c,sessions:g,filteredProjects:St,filteredSessions:yt,selectedProject:Os,selectedSession:Ts,selectedProjectId:p,selectedSessionId:w,selectedProjectIds:A,selectedSessionIds:H,sessionDetail:y,focus:X,searchQuery:ie,sort:Q,issues:b,scannedSources:G,failedSources:ue,detailLoading:D,deleteStatus:ke,lastDeleteResult:Le,lastScanAt:It,summary:Ns,scan:or,deleteSessions:rn,deleteSelected:Ls,chooseProject:_s,chooseSession:Fs,loadDetail:Ve,toggleProject:$s,toggleSession:Bs,selectAllVisibleSessions:zs,clearSelectedSessions:Js,clearSelected:Gs,setFocus:de,setSearchQuery:Se,setSort:f}}function Es(e){let t=ha(),r=Cs(e.useCases,e.initialAgentId);return pa(()=>{let n=(i)=>ts(i);t.on(js.PALETTE,n),t.getPalette().then(n).catch(()=>{return}),r.scan(),ga(()=>t.off(js.PALETTE,n))}),fa(Ps,{store:r})}function ft(e,t){let r=e.indexOf(t);return r>=0?e[r+1]:void 0}var gt=process.argv.slice(2),wa=ft(gt,"--pi-sessions-dir"),va=ft(gt,"--codex-sessions-dir"),ba=ft(gt,"--opencode-data-dir"),Aa=ft(gt,"--claude-code-sessions-dir"),Pa=ft(gt,"--grok-sessions-dir"),xa=ft(gt,"--antigravity-data-dir"),Ms=new kr(wa),Da=new yr(Aa),Ia=new mr(xa),Ca=new xr(va),ja=new jr(Pa),Ea=new Nr(ba),Rs=Xn(Ms,Da,Ia,Ca,ja,Ea),Ma=Rs.get("pi")??Ms,Ra=Zn(Rs);await ya(()=>Sa(Es,{useCases:Ra,get initialAgentId(){return Ma.id}}),{exitOnCtrlC:!0,backgroundColor:"#17151d",targetFps:30});
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@smoose/asc",
3
+ "version": "0.0.1",
4
+ "description": "Agent session manager for Pi, Claude Code, Antigravity, Codex, Grok, and OpenCode",
5
+ "type": "module",
6
+ "bin": {
7
+ "asc": "bin/asc.js"
8
+ },
9
+ "files": [
10
+ "bin",
11
+ "dist/npm",
12
+ "README.md"
13
+ ],
14
+ "scripts": {
15
+ "dev": "bun run src/main.tsx",
16
+ "start": "bun run bin/asc.js",
17
+ "compile": "bun run scripts/compile.ts",
18
+ "compile:all": "bun run scripts/compile.ts --all",
19
+ "build:package": "bun run scripts/build-package.ts",
20
+ "pack:check": "npm pack --dry-run",
21
+ "prepack": "bun run build:package",
22
+ "test": "bun test",
23
+ "typecheck": "tsc --noEmit",
24
+ "prepublishOnly": "bun run typecheck && bun test"
25
+ },
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "git+https://github.com/smoosex/agent-session-clean.git"
29
+ },
30
+ "homepage": "https://github.com/smoosex/agent-session-clean",
31
+ "bugs": {
32
+ "url": "https://github.com/smoosex/agent-session-clean/issues"
33
+ },
34
+ "keywords": [
35
+ "agent",
36
+ "session",
37
+ "terminal",
38
+ "tui",
39
+ "opentui"
40
+ ],
41
+ "engines": {
42
+ "bun": ">=1.3.0"
43
+ },
44
+ "publishConfig": {
45
+ "access": "public"
46
+ },
47
+ "dependencies": {
48
+ "@opentui/core": "0.5.8",
49
+ "@opentui/solid": "0.5.8",
50
+ "solid-js": "1.9.12"
51
+ },
52
+ "devDependencies": {
53
+ "@types/bun": "latest",
54
+ "@types/node": "latest",
55
+ "typescript": "^5"
56
+ }
57
+ }