@qiaolei81/copilot-session-viewer 0.3.5 → 0.3.6

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 CHANGED
@@ -69,7 +69,7 @@ copilot-session-viewer
69
69
  - **Vue 3** - Reactive virtual scrolling
70
70
  - **Express.js** - Robust backend API
71
71
  - **ZIP Import/Export** - Session sharing capabilities with security validation
72
- - **Multi-Source Support** - Copilot CLI (`~/.copilot/session-state/`), Copilot Chat (`~/Library/Application Support/Code/User/workspaceStorage/`), Claude (`~/.claude/projects/`), Pi-Mono (`~/.pi/agent/sessions/`)
72
+ - **Multi-Source Support** - Copilot CLI (`~/.copilot/session-state/`), Copilot Chat (auto-detected per OS), Claude (`~/.claude/projects/`), Pi-Mono (`~/.pi/agent/sessions/`)
73
73
  - **Unified Event Format** - Consistent schema across all sources
74
74
  - **Memory Pagination** - Efficient handling of large sessions
75
75
  - **XSS Protection** - DOMPurify-based HTML sanitization
@@ -82,7 +82,7 @@ copilot-session-viewer
82
82
  1. **Generate Sessions** - Use GitHub Copilot CLI, Claude Code CLI, or Pi-Mono to create session logs
83
83
  2. **Auto-Discovery** - Sessions are automatically detected from:
84
84
  - Copilot CLI: `~/.copilot/session-state/`
85
- - Copilot Chat: `~/Library/Application Support/Code/User/workspaceStorage/`
85
+ - Copilot Chat: auto-detected — `~/Library/Application Support/Code/User/workspaceStorage/` (macOS), `~/.config/Code/User/workspaceStorage/` (Linux), `%APPDATA%\Code\User\workspaceStorage\` (Windows)
86
86
  - Claude: `~/.claude/projects/`
87
87
  - Pi-Mono: `~/.pi/agent/sessions/`
88
88
  3. **Browse & Analyze** - View sessions with infinite scroll and detailed event streams
@@ -189,7 +189,7 @@ GitHub Actions workflow includes:
189
189
  ┌─────────────────────────────────────────────────┐
190
190
  │ Data Layer (Multi-Source) │
191
191
  │ • Copilot CLI: ~/.copilot/session-state/ │
192
- │ • Copilot Chat: ~/Library/.../workspaceStorage/ │
192
+ │ • Copilot Chat: <OS-specific>/workspaceStorage/ │
193
193
  │ • Claude: ~/.claude/projects/ │
194
194
  │ • Pi-Mono: ~/.pi/agent/sessions/ │
195
195
  └─────────────────────────────────────────────────┘
@@ -1,13 +1,13 @@
1
- var b=(p,e)=>()=>(e||p((e={exports:{}}).exports,e),e.exports);var O=b((nn,We)=>{var ie=require("applicationinsights"),X=require("fs"),Q=require("path"),Vt=require("crypto"),ze=require("os");function Bt(){let p=Q.join(ze.homedir(),".copilot-session-viewer"),e=Q.join(p,"analytics-id");try{return X.readFileSync(e,"utf8").trim()}catch{let s=Vt.randomUUID();try{X.mkdirSync(p,{recursive:!0}),X.writeFileSync(e,s)}catch{}return s}}function Wt(){try{let p=[Q.join(__dirname,"..","package.json"),Q.join(__dirname,"package.json")];for(let e of p)try{return JSON.parse(X.readFileSync(e,"utf8")).version}catch{}}catch{}return"unknown"}var Ve=process.env.NODE_ENV==="test",Be=process.env.DISABLE_TELEMETRY==="true"||Ve,Gt="InstrumentationKey=39f4fbf1-d82f-42c3-b4ef-ea92a1fd82cb;IngestionEndpoint=https://eastus-8.in.applicationinsights.azure.com/;LiveEndpoint=https://eastus.livediagnostics.monitor.azure.com/;ApplicationId=7d4bb432-f2f5-4526-a5e6-31901e5a2db2",C=null;if(Be)C=Ue(),console.log(Ve?"\u{1F4CA} Telemetry disabled (test environment)":"\u{1F4CA} Telemetry disabled (DISABLE_TELEMETRY=true)");else try{let p=process.env.APPLICATIONINSIGHTS_CONNECTION_STRING||Gt;ie.setup(p).setAutoDependencyCorrelation(!0).setAutoCollectRequests(!0).setAutoCollectPerformance(!0,!0).setAutoCollectExceptions(!0).setAutoCollectDependencies(!0).setAutoCollectConsole(!1).setUseDiskRetryCaching(!0).setSendLiveMetrics(!1).setDistributedTracingMode(ie.DistributedTracingModes.AI_AND_W3C).start(),C=ie.defaultClient;let e=Wt(),s=Bt();C.context.tags[C.context.keys.cloudRole]="copilot-session-viewer",C.context.tags[C.context.keys.cloudRoleInstance]=ze.hostname(),C.context.tags[C.context.keys.applicationVersion]=e,C.context.tags[C.context.keys.userId]=s,C.addTelemetryProcessor(t=>(t.data.baseData.properties=t.data.baseData.properties||{},t.data.baseData.properties.appVersion=e,!0)),console.log("\u2705 Application Insights telemetry initialized")}catch(p){console.error("\u274C Failed to initialize Application Insights:",p.message),C=Ue()}function Ue(){return{trackEvent:()=>{},trackMetric:()=>{},trackException:()=>{},trackTrace:()=>{},trackDependency:()=>{},trackRequest:()=>{},flush:p=>{p&&p()}}}function Jt(p,e={}){C&&C.trackEvent&&C.trackEvent({name:p,properties:e})}function Ht(p,e,s={}){C&&C.trackMetric&&C.trackMetric({name:p,value:e,properties:s})}function Kt(p,e={}){C&&C.trackException&&C.trackException({exception:p,properties:e})}function Yt(){return new Promise(p=>{C&&C.flush?C.flush({callback:()=>p()}):p()})}We.exports={client:C,trackEvent:Jt,trackMetric:Ht,trackException:Kt,flush:Yt,isEnabled:!Be}});var q=b((on,Ge)=>{Ge.exports={PORT:process.env.PORT||3838,NODE_ENV:process.env.NODE_ENV||"production",LOG_LEVEL:process.env.LOG_LEVEL||(process.env.NODE_ENV==="development"?"DEBUG":"INFO"),INSIGHT_TIMEOUT_MS:300*1e3,INSIGHT_CACHE_TTL_MS:1440*60*1e3,MAX_UPLOAD_SIZE:10*1024*1024,SESSION_CACHE_TTL_MS:30*1e3,RATE_LIMIT_WINDOW_MS:900*1e3,RATE_LIMIT_MAX_REQUESTS:15,REQUEST_TIMEOUT_MS:30*1e3}});var Ke=b((rn,He)=>{var ae=q(),{trackException:Zt,isEnabled:Je}=O(),Xt=(p,e,s)=>{p.setTimeout(ae.REQUEST_TIMEOUT_MS),s()},Qt=(p,e,s)=>{e.locals.telemetryEnabled=Je,e.locals.telemetryConnectionString=Je?process.env.APPLICATIONINSIGHTS_CONNECTION_STRING||"InstrumentationKey=39f4fbf1-d82f-42c3-b4ef-ea92a1fd82cb;IngestionEndpoint=https://eastus-8.in.applicationinsights.azure.com/;LiveEndpoint=https://eastus.livediagnostics.monitor.azure.com/;ApplicationId=7d4bb432-f2f5-4526-a5e6-31901e5a2db2":null,s()},es=(p,e,s)=>{if(ae.NODE_ENV==="development"){let t=["http://localhost:3838","http://127.0.0.1:3838"],n=p.headers.origin;t.includes(n)&&(e.header("Access-Control-Allow-Origin",n),e.header("Access-Control-Allow-Methods","GET, POST, DELETE, OPTIONS"),e.header("Access-Control-Allow-Headers","Content-Type"))}s()},ts=(p,e,s,t)=>{console.error("Unhandled error:",p.stack),Zt(p,{url:e.url,method:e.method,statusCode:(p.status||500).toString(),userAgent:e.headers&&e.headers["user-agent"]||"unknown"});let n=p.status||500,o=ae.NODE_ENV==="development",r=o?p.message:"Internal server error";s.status(n).json({error:r,...o&&{stack:p.stack}})},ss=(p,e)=>{e.status(404).json({error:"Not found"})};He.exports={requestTimeout:Xt,developmentCors:es,errorHandler:ts,notFoundHandler:ss,telemetryLocals:Qt}});var L=b((an,Ye)=>{function ns(p){let e=p.toJSON?p.toJSON():{};return{type:p.type,source:p.source,sourceName:e.sourceName||p.source,sourceBadgeClass:e.sourceBadgeClass||"source-unknown",summary:p.summary,model:p.selectedModel||p.model,repo:p.workspace?.repository,branch:p.workspace?.branch,cwd:p.workspace?.cwd,created:p.createdAt,updated:p.updatedAt,copilotVersion:p.copilotVersion,sessionStatus:p.sessionStatus}}function os(p){return typeof p=="string"&&/^[a-zA-Z0-9_-]+$/.test(p)&&p.length<256}Ye.exports={buildMetadata:ns,isValidSessionId:os}});var Xe=b((ln,Ze)=>{var rs=require("path"),le=class p{constructor(e,s,t={}){this.id=e,this.type=s,this.source=t.source||"copilot",this.directory=t.directory||null,this.filePath=t.filePath||null,this.workspace=t.workspace||{},this.createdAt=t.createdAt,this.updatedAt=t.updatedAt,this.summary=t.summary||(s==="file"?"Legacy session":"No summary"),this.hasEvents=t.hasEvents||!1,this.eventCount=t.eventCount||0,this.duration=t.duration||null,this.isImported=t.isImported||!1,this.hasInsight=t.hasInsight||!1,this.copilotVersion=t.copilotVersion||null,this.selectedModel=t.selectedModel||null,this.sessionStatus=t.sessionStatus||"completed"}static fromDirectory(e,s,t,n,o,r,i,a,l,c,d){let u=n?.created_at?new Date(n.created_at):n?.startTime?new Date(n.startTime):t.birthtime,m=n?.updated_at?new Date(n.updated_at):n?.endTime?new Date(n.endTime):t.mtime;return new p(s,"directory",{directory:e,workspace:n,createdAt:u,updatedAt:m,summary:n?.summary||"No summary",hasEvents:o>0,eventCount:o,duration:r,isImported:i,hasInsight:a,copilotVersion:l,selectedModel:c,sessionStatus:d})}static fromFile(e,s,t,n,o,r,i,a,l){return new p(s,"file",{filePath:e,directory:rs.dirname(e),createdAt:t.birthtime,updatedAt:t.mtime,summary:o||"Legacy session",hasEvents:!0,eventCount:n,duration:r,isImported:!1,hasInsight:!1,copilotVersion:i,selectedModel:a,sessionStatus:l})}toJSON(){let e=this._getSourceDisplayMetadata(this.source);return{id:this.id,type:this.type,source:this.source,sourceName:e.name,sourceBadgeClass:e.badgeClass,directory:this.directory,workspace:this.workspace,createdAt:this.createdAt,updatedAt:this.updatedAt,summary:this.summary,hasEvents:this.hasEvents,eventCount:this.eventCount,duration:this.duration,isImported:this.isImported,hasInsight:this.hasInsight,copilotVersion:this.copilotVersion,selectedModel:this.selectedModel,sessionStatus:this.sessionStatus}}_getSourceDisplayMetadata(e){return{copilot:{name:"Copilot CLI",badgeClass:"source-copilot"},claude:{name:"Claude",badgeClass:"source-claude"},"pi-mono":{name:"Pi",badgeClass:"source-pi-mono"},vscode:{name:"Copilot Chat",badgeClass:"source-vscode"}}[e]||{name:e,badgeClass:"source-unknown"}}};Ze.exports=le});var tt=b((cn,et)=>{var Qe=require("fs").promises,J=require("fs"),H=require("readline");async function is(p){try{return await Qe.access(p),!0}catch{return!1}}async function as(p){try{let e=J.createReadStream(p,{encoding:"utf-8"}),s=H.createInterface({input:e,crlfDelay:1/0}),t=0;for await(let n of s)n.trim()&&t++;return t}catch(e){return console.error(`Error counting lines in ${p}:`,e.message),0}}async function ls(p){try{let s=(await Qe.readFile(p,"utf-8")).split(`
2
- `),t={};for(let n of s){let o=n.match(/^(\w+):\s*(.+)$/);o&&(t[o[1]]=o[2].trim())}return t}catch(e){return console.error(`Error parsing YAML ${p}:`,e.message),{}}}async function cs(p,e=200){try{let s=J.createReadStream(p,{encoding:"utf-8"}),t=H.createInterface({input:s,crlfDelay:1/0}),n="",o=null,r=null,i=null,a=null,l=!1;for await(let d of t)if(d.trim())try{let u=JSON.parse(d);if(u.timestamp){let m=new Date(u.timestamp).getTime();isNaN(m)||(o||(o=m),r=m)}if(!n&&u.type==="user.message"){let m=u.data?.message||u.data?.content||u.data?.text||"";m&&(n=m.length>e?m.substring(0,e)+"...":m)}u.type==="session.end"&&(l=!0),u.type==="session.start"&&u.data?.copilotVersion&&!i&&(i=u.data.copilotVersion),(u.type==="session.start"||u.type==="session.model_change")&&!a&&(u.data?.selectedModel?a=u.data.selectedModel:u.data?.newModel?a=u.data.newModel:u.data?.model&&(a=u.data.model))}catch{}t.close(),s.destroy();let c=o&&r&&r>o?r-o:null;return{firstUserMessage:n||"",duration:c,copilotVersion:i||null,selectedModel:a||null,hasSessionEnd:l,lastEventTime:r,firstEventTime:o}}catch(s){return console.error(`Error reading session metadata from ${p}:`,s.message),{firstUserMessage:"",duration:null,copilotVersion:null,selectedModel:null,hasSessionEnd:!1,lastEventTime:null}}}async function us(p,e=200){try{let s=J.createReadStream(p,{encoding:"utf-8"}),t=H.createInterface({input:s,crlfDelay:1/0});for await(let n of t)if(n.trim())try{let o=JSON.parse(n);if(o.type==="user.message"){let r=o.data?.message||o.data?.content||o.data?.text||"";if(r)return t.close(),s.destroy(),r.length>e?r.substring(0,e)+"...":r}}catch{}return""}catch{return""}}async function ds(p){try{let e=J.createReadStream(p,{encoding:"utf-8"}),s=H.createInterface({input:e,crlfDelay:1/0}),t=null,n=null;for await(let o of s)if(o.trim())try{let r=JSON.parse(o);if(r.timestamp){let i=new Date(r.timestamp).getTime();t||(t=i),n=i}}catch{}return t&&n&&n>=t?n-t:null}catch(e){return console.error(`Error calculating session duration for ${p}:`,e.message),null}}async function ps(p){try{let e=J.createReadStream(p,{encoding:"utf-8"}),s=H.createInterface({input:e,crlfDelay:1/0}),t=null,n=null;for await(let o of s)if(o.trim())try{let r=JSON.parse(o);if(r.type==="session.start"&&r.data&&(t=r.data.copilotVersion||null,n=r.data.selectedModel||null,n))return s.close(),e.destroy(),{copilotVersion:t,selectedModel:n};if(!n&&r.type==="session.model_change"&&r.data)return n=r.data.newModel||null,s.close(),e.destroy(),{copilotVersion:t,selectedModel:n}}catch{}return{copilotVersion:t,selectedModel:n}}catch(e){return console.error(`Error reading session metadata from ${p}:`,e.message),{copilotVersion:null,selectedModel:null}}}function ms(p){return p===".DS_Store"||p.startsWith(".")}et.exports={fileExists:is,countLines:as,parseYAML:ls,getFirstUserMessage:us,getSessionDuration:ds,getSessionMetadata:ps,getSessionMetadataOptimized:cs,shouldSkipEntry:ms}});var U=b((un,st)=>{var ce=class{canParse(e){throw new Error("canParse() must be implemented")}parse(e){throw new Error("parse() must be implemented")}getMetadata(e){throw new Error("getMetadata() must be implemented")}extractTurns(e){throw new Error("extractTurns() must be implemented")}extractToolCalls(e){throw new Error("extractToolCalls() must be implemented")}};st.exports=ce});var de=b((dn,nt)=>{var fs=U(),ue=class extends fs{canParse(e){if(!e||e.length===0)return!1;let s=["session.start","user.message","assistant.turn_start","assistant.message","tool.execution_start"];return e.some(t=>t.type&&s.some(n=>t.type.startsWith(n)))}parse(e){return{metadata:this.getMetadata(e),turns:this.extractTurns(e),toolCalls:this.extractToolCalls(e),allEvents:e}}getMetadata(e){let s=e.find(n=>n.type==="session.start");if(!s)return null;let t=s.data||{};return{sessionId:t.sessionId,startTime:t.startTime,model:t.selectedModel,version:t.copilotVersion,producer:t.producer,cwd:t.context?.cwd,gitRoot:t.context?.gitRoot,branch:t.context?.branch,repository:t.context?.repository}}extractTurns(e){let s=[],t=null;for(let n of e)if(n.type==="user.message")t&&s.push(t),t={turnId:n.id,userMessage:{id:n.id,content:n.data?.content||"",transformedContent:n.data?.transformedContent,timestamp:n.timestamp},assistantMessages:[],toolCalls:[]};else if(n.type==="assistant.message"&&t)t.assistantMessages.push({id:n.id,messageId:n.data?.messageId,content:n.data?.content||"",toolRequests:n.data?.toolRequests||[],reasoningText:n.data?.reasoningText,timestamp:n.timestamp});else if(n.type.startsWith("tool.execution_")&&t){let o=n.data?.toolCallId,r=t.toolCalls.find(i=>i.toolCallId===o);r||(r={toolCallId:o,events:[]},t.toolCalls.push(r)),r.events.push(n),n.type==="tool.execution_start"?(r.name=n.data?.toolName,r.arguments=n.data?.arguments):n.type==="tool.execution_complete"&&(r.result=n.data?.result,r.exitCode=n.data?.exitCode)}return t&&s.push(t),s}extractToolCalls(e){let s=[],t=new Map;for(let n of e)if(n.type==="tool.execution_start"){let o=n.data?.toolCallId;t.set(o,{toolCallId:o,name:n.data?.toolName,arguments:n.data?.arguments,startEvent:n,completeEvent:null})}else if(n.type==="tool.execution_complete"){let o=n.data?.toolCallId,r=t.get(o);r&&(r.completeEvent=n,r.result=n.data?.result,r.exitCode=n.data?.exitCode,s.push(r))}return s}};nt.exports=ue});var me=b((pn,ot)=>{var gs=U(),pe=class extends gs{canParse(e){return!e||e.length===0?!1:e.some(s=>s.type&&["user","assistant"].includes(s.type)&&s.uuid&&Object.prototype.hasOwnProperty.call(s,"parentUuid")&&s.sessionId)}parse(e){return{metadata:this.getMetadata(e),turns:this.extractTurns(e),toolCalls:this.extractToolCalls(e),allEvents:e}}getMetadata(e){let s=e.find(o=>o.type==="user");if(!s)return null;let n=e.find(o=>o.type==="assistant"&&o.message?.model)?.message?.model||"unknown";return{sessionId:s.sessionId,startTime:s.timestamp,model:n,version:s.version,producer:"claude-code",cwd:s.cwd,gitRoot:null,branch:s.gitBranch,repository:null}}extractTurns(e){let s=[],t=e.filter(r=>["user","assistant"].includes(r.type)&&r.type!=="file-history-snapshot"&&r.type!=="queue-operation"),n=new Map;for(let r of t)n.set(r.uuid,r);let o=t.filter(r=>r.type==="user"&&(!r.parentUuid||!n.has(r.parentUuid)));for(let r of o){let i={turnId:r.uuid,userMessage:{id:r.uuid,content:this._extractMessageContent(r.message),timestamp:r.timestamp},assistantMessages:[],toolCalls:[]};this._collectAssistantResponses(r.uuid,n,i),s.push(i)}return s}_collectAssistantResponses(e,s,t){for(let[n,o]of s.entries())if(o.parentUuid===e&&o.type==="assistant"){let r={id:o.uuid,messageId:o.message?.id,content:this._extractMessageContent(o.message),model:o.message?.model,timestamp:o.timestamp},i=this._extractToolUse(o.message);i.length>0&&(r.toolRequests=i,t.toolCalls.push(...i.map(a=>({toolCallId:a.id,name:a.name,arguments:a.input,parentUuid:o.uuid})))),t.assistantMessages.push(r),this._collectAssistantResponses(o.uuid,s,t)}}_extractMessageContent(e){return!e||!e.content?"":typeof e.content=="string"?e.content:Array.isArray(e.content)?e.content.filter(s=>s.type==="text").map(s=>s.text).join(`
3
- `):""}_extractToolUse(e){return!e||!e.content||!Array.isArray(e.content)?[]:e.content.filter(s=>s.type==="tool_use").map(s=>({id:s.id,name:s.name,input:s.input}))}extractToolCalls(e){let s=[];for(let t of e)if(t.type==="assistant"&&t.message?.content){let n=this._extractToolUse(t.message);for(let o of n)s.push({toolCallId:o.id,name:o.name,arguments:o.input,parentUuid:t.uuid,timestamp:t.timestamp,result:null,exitCode:null})}return s}};ot.exports=pe});var ge=b((mn,rt)=>{var hs=U(),fe=class extends hs{constructor(){super("pi-mono")}async parseSessionDir(e){let s=require("fs").promises,t=require("path");try{let o=(await s.readdir(e)).filter(d=>d.endsWith(".jsonl"));if(o.length===0)return null;o.sort().reverse();let r=t.join(e,o[0]),i=await this._readFirstLine(r);if(!i)return null;let a=JSON.parse(i);if(a.type!=="session")return console.warn(`Pi-Mono file ${r} doesn't start with session event`),null;let c=t.basename(e).replace(/^--/,"").replace(/--$/,"");return{id:a.id,type:"pi-mono",source:"pi-mono",cwd:a.cwd||c,createdAt:new Date(a.timestamp),updatedAt:new Date(a.timestamp),summary:`Pi-Mono: ${c}`,fileCount:o.length}}catch(n){return console.error(`Error parsing Pi-Mono session dir ${e}:`,n.message),null}}async _readFirstLine(e){let s=require("fs"),t=require("readline");return new Promise(n=>{let o=s.createReadStream(e,{encoding:"utf-8"}),r=t.createInterface({input:o,crlfDelay:1/0});r.on("line",i=>{r.close(),o.destroy(),n(i.trim())}),r.on("close",()=>n(null))})}async parseEvents(e){let s=require("fs"),t=require("readline"),n=[],o=s.createReadStream(e,{encoding:"utf-8"}),r=t.createInterface({input:o,crlfDelay:1/0}),i=0;for await(let a of r){i++;let l=a.trim();if(l)try{let c=JSON.parse(l);n.push(c)}catch(c){console.error(`Error parsing Pi-Mono line ${i}:`,c.message)}}return n}};rt.exports=fe});var at=b((fn,it)=>{var ys=U(),he=class extends ys{canParse(e){if(!Array.isArray(e)||e.length===0)return!1;let s=e[0];return!!(s&&typeof s=="object"&&s.kind===0&&s.v&&s.v.sessionId)}parseVsCode(e){let s=this._getMetadata(e),t=this._toEvents(e);return{metadata:s,turns:this._extractTurns(t),toolCalls:this._extractToolCalls(t),allEvents:t}}parseJsonl(e){let s=this.replayMutations(e),t=this._getMetadata(s),n=this._toEvents(s);return{metadata:t,turns:this._extractTurns(n),toolCalls:this._extractToolCalls(n),allEvents:n}}replayMutations(e){let s=null;for(let t of e){if(!t||typeof t!="object")continue;let{kind:n,k:o,v:r,i}=t;switch(n){case 0:s=r;break;case 1:o&&Array.isArray(o)&&this._applySet(s,o,r);break;case 2:o&&Array.isArray(o)&&this._applyPush(s,o,r,i);break;case 3:o&&Array.isArray(o)&&this._applyDelete(s,o);break;default:console.warn(`[VsCodeParser] Unknown mutation kind: ${n}`)}}return s}_applySet(e,s,t){if(!e||s.length===0)return;let n=e;for(let r=0;r<s.length-1;r++){let i=s[r];n[i]||(n[i]=typeof s[r+1]=="number"?[]:{}),n=n[i]}let o=s[s.length-1];n[o]=t}_applyPush(e,s,t,n){if(!e||s.length===0)return;let o=e;for(let a=0;a<s.length-1;a++){let l=s[a];o[l]||(o[l]=typeof s[a+1]=="number"?[]:{}),o=o[l]}let r=s[s.length-1];o[r]||(o[r]=[]);let i=o[r];if(!Array.isArray(i)){console.warn(`[VsCodeParser] Push target is not an array: ${s.join(".")}`);return}n!=null&&(i.length=n),t&&Array.isArray(t)&&t.length>0&&i.push(...t)}_applyDelete(e,s){if(!e||s.length===0)return;let t=e;for(let o=0;o<s.length-1;o++){let r=s[o];if(!t[r])return;t=t[r]}let n=s[s.length-1];delete t[n]}parse(e){return Array.isArray(e)&&e.length>0&&this.canParse(e)?this.parseJsonl(e):null}getMetadata(e){let s=this.parse(e);return s?s.metadata:null}extractTurns(e){let s=this.parse(e);return s?s.turns:[]}extractToolCalls(e){let s=this.parse(e);return s?s.toolCalls:[]}_getMetadata(e){let s=e.requests||[],t=s[0]||{},n=s[s.length-1]||{},o=t.agent?.name||t.agent?.id||"vscode-copilot";return{sessionId:e.sessionId,startTime:e.creationDate?new Date(e.creationDate).toISOString():t.timestamp?new Date(t.timestamp).toISOString():null,endTime:e.lastMessageDate?new Date(e.lastMessageDate).toISOString():n.timestamp?new Date(n.timestamp).toISOString():null,model:t.modelId||null,producer:"vscode-copilot-chat",version:t.agent?.extensionVersion||null,agentName:o,requestCount:s.length}}_toEvents(e){let s=[],t=e.requests||[];s.push({type:"session.start",id:`${e.sessionId}-start`,timestamp:e.creationDate?new Date(e.creationDate).toISOString():null,data:{sessionId:e.sessionId,producer:"vscode-copilot-chat",selectedModel:t[0]?.modelId||null}});for(let n of t){let o=n.timestamp?new Date(n.timestamp).toISOString():null,r=n.modelState?.completedAt?new Date(n.modelState.completedAt).toISOString():o,i=Array.isArray(n.response)?n.response:[],a=this._buildSubAgentNameMap(i),l=this._extractUserText(n.message);s.push({type:"user.message",id:n.requestId,timestamp:o,data:{message:l,content:l}}),s.push({type:"assistant.turn_start",id:`${n.requestId}-turn`,timestamp:o,parentId:n.requestId,data:{}});let c="",d=0,u=null,m=()=>{let f=c.trim().replace(/^`{3,}$/gm,"").trim();if(c="",!f)return;let g=u,S=g?a[g]||g.slice(0,8):null;s.push({type:"assistant.message",id:`${n.requestId}-text-${d}`,timestamp:r,parentId:n.requestId,data:{message:f,content:f,tools:[],subAgentId:g||null,subAgentName:S,parentToolCallId:null}})};for(let f of i)switch(d++,f.kind){case"thinking":{let g=f.content?.value||f.content||"";g&&(c+=g+`
1
+ var b=(p,e)=>()=>(e||p((e={exports:{}}).exports,e),e.exports);var R=b((rn,We)=>{var ie=require("applicationinsights"),Q=require("fs"),ee=require("path"),Bt=require("crypto"),ze=require("os");function Wt(){let p=ee.join(ze.homedir(),".copilot-session-viewer"),e=ee.join(p,"analytics-id");try{return Q.readFileSync(e,"utf8").trim()}catch{let s=Bt.randomUUID();try{Q.mkdirSync(p,{recursive:!0}),Q.writeFileSync(e,s)}catch{}return s}}function Gt(){try{let p=[ee.join(__dirname,"..","package.json"),ee.join(__dirname,"package.json")];for(let e of p)try{return JSON.parse(Q.readFileSync(e,"utf8")).version}catch{}}catch{}return"unknown"}var Ve=process.env.NODE_ENV==="test",Be=process.env.DISABLE_TELEMETRY==="true"||Ve,Jt="InstrumentationKey=39f4fbf1-d82f-42c3-b4ef-ea92a1fd82cb;IngestionEndpoint=https://eastus-8.in.applicationinsights.azure.com/;LiveEndpoint=https://eastus.livediagnostics.monitor.azure.com/;ApplicationId=7d4bb432-f2f5-4526-a5e6-31901e5a2db2",C=null;if(Be)C=Ue(),console.log(Ve?"\u{1F4CA} Telemetry disabled (test environment)":"\u{1F4CA} Telemetry disabled (DISABLE_TELEMETRY=true)");else try{let p=process.env.APPLICATIONINSIGHTS_CONNECTION_STRING||Jt;ie.setup(p).setAutoDependencyCorrelation(!0).setAutoCollectRequests(!0).setAutoCollectPerformance(!0,!0).setAutoCollectExceptions(!0).setAutoCollectDependencies(!0).setAutoCollectConsole(!1).setUseDiskRetryCaching(!0).setSendLiveMetrics(!1).setDistributedTracingMode(ie.DistributedTracingModes.AI_AND_W3C).start(),C=ie.defaultClient;let e=Gt(),s=Wt();C.context.tags[C.context.keys.cloudRole]="copilot-session-viewer",C.context.tags[C.context.keys.cloudRoleInstance]=ze.hostname(),C.context.tags[C.context.keys.applicationVersion]=e,C.context.tags[C.context.keys.userId]=s,C.addTelemetryProcessor(t=>(t.data.baseData.properties=t.data.baseData.properties||{},t.data.baseData.properties.appVersion=e,!0)),console.log("\u2705 Application Insights telemetry initialized")}catch(p){console.error("\u274C Failed to initialize Application Insights:",p.message),C=Ue()}function Ue(){return{trackEvent:()=>{},trackMetric:()=>{},trackException:()=>{},trackTrace:()=>{},trackDependency:()=>{},trackRequest:()=>{},flush:p=>{p&&p()}}}function Ht(p,e={}){C&&C.trackEvent&&C.trackEvent({name:p,properties:e})}function Kt(p,e,s={}){C&&C.trackMetric&&C.trackMetric({name:p,value:e,properties:s})}function Yt(p,e={}){C&&C.trackException&&C.trackException({exception:p,properties:e})}function Zt(){return new Promise(p=>{C&&C.flush?C.flush({callback:()=>p()}):p()})}We.exports={client:C,trackEvent:Ht,trackMetric:Kt,trackException:Yt,flush:Zt,isEnabled:!Be}});var L=b((an,Ge)=>{Ge.exports={PORT:process.env.PORT||3838,NODE_ENV:process.env.NODE_ENV||"production",LOG_LEVEL:process.env.LOG_LEVEL||(process.env.NODE_ENV==="development"?"DEBUG":"INFO"),INSIGHT_TIMEOUT_MS:300*1e3,INSIGHT_CACHE_TTL_MS:1440*60*1e3,MAX_UPLOAD_SIZE:10*1024*1024,SESSION_CACHE_TTL_MS:30*1e3,RATE_LIMIT_WINDOW_MS:900*1e3,RATE_LIMIT_MAX_REQUESTS:15,REQUEST_TIMEOUT_MS:30*1e3}});var Ke=b((ln,He)=>{var ae=L(),{trackException:Xt,isEnabled:Je}=R(),Qt=(p,e,s)=>{p.setTimeout(ae.REQUEST_TIMEOUT_MS),s()},es=(p,e,s)=>{e.locals.telemetryEnabled=Je,e.locals.telemetryConnectionString=Je?process.env.APPLICATIONINSIGHTS_CONNECTION_STRING||"InstrumentationKey=39f4fbf1-d82f-42c3-b4ef-ea92a1fd82cb;IngestionEndpoint=https://eastus-8.in.applicationinsights.azure.com/;LiveEndpoint=https://eastus.livediagnostics.monitor.azure.com/;ApplicationId=7d4bb432-f2f5-4526-a5e6-31901e5a2db2":null,s()},ts=(p,e,s)=>{if(ae.NODE_ENV==="development"){let t=["http://localhost:3838","http://127.0.0.1:3838"],n=p.headers.origin;t.includes(n)&&(e.header("Access-Control-Allow-Origin",n),e.header("Access-Control-Allow-Methods","GET, POST, DELETE, OPTIONS"),e.header("Access-Control-Allow-Headers","Content-Type"))}s()},ss=(p,e,s,t)=>{console.error("Unhandled error:",p.stack),Xt(p,{url:e.url,method:e.method,statusCode:(p.status||500).toString(),userAgent:e.headers&&e.headers["user-agent"]||"unknown"});let n=p.status||500,o=ae.NODE_ENV==="development",r=o?p.message:"Internal server error";s.status(n).json({error:r,...o&&{stack:p.stack}})},ns=(p,e)=>{e.status(404).json({error:"Not found"})};He.exports={requestTimeout:Qt,developmentCors:ts,errorHandler:ss,notFoundHandler:ns,telemetryLocals:es}});var U=b((cn,Ye)=>{function os(p){let e=p.toJSON?p.toJSON():{};return{type:p.type,source:p.source,sourceName:e.sourceName||p.source,sourceBadgeClass:e.sourceBadgeClass||"source-unknown",summary:p.summary,model:p.selectedModel||p.model,repo:p.workspace?.repository,branch:p.workspace?.branch,cwd:p.workspace?.cwd,created:p.createdAt,updated:p.updatedAt,copilotVersion:p.copilotVersion,sessionStatus:p.sessionStatus}}function rs(p){return typeof p=="string"&&/^[a-zA-Z0-9_-]+$/.test(p)&&p.length<256}Ye.exports={buildMetadata:os,isValidSessionId:rs}});var Xe=b((un,Ze)=>{var is=require("path"),le=class p{constructor(e,s,t={}){this.id=e,this.type=s,this.source=t.source||"copilot",this.directory=t.directory||null,this.filePath=t.filePath||null,this.workspace=t.workspace||{},this.createdAt=t.createdAt,this.updatedAt=t.updatedAt,this.summary=t.summary||(s==="file"?"Legacy session":"No summary"),this.hasEvents=t.hasEvents||!1,this.eventCount=t.eventCount||0,this.duration=t.duration||null,this.isImported=t.isImported||!1,this.hasInsight=t.hasInsight||!1,this.copilotVersion=t.copilotVersion||null,this.selectedModel=t.selectedModel||null,this.sessionStatus=t.sessionStatus||"completed"}static fromDirectory(e,s,t,n,o,r,i,a,l,c,d){let u=n?.created_at?new Date(n.created_at):n?.startTime?new Date(n.startTime):t.birthtime,m=n?.updated_at?new Date(n.updated_at):n?.endTime?new Date(n.endTime):t.mtime;return new p(s,"directory",{directory:e,workspace:n,createdAt:u,updatedAt:m,summary:n?.summary||"No summary",hasEvents:o>0,eventCount:o,duration:r,isImported:i,hasInsight:a,copilotVersion:l,selectedModel:c,sessionStatus:d})}static fromFile(e,s,t,n,o,r,i,a,l){return new p(s,"file",{filePath:e,directory:is.dirname(e),createdAt:t.birthtime,updatedAt:t.mtime,summary:o||"Legacy session",hasEvents:!0,eventCount:n,duration:r,isImported:!1,hasInsight:!1,copilotVersion:i,selectedModel:a,sessionStatus:l})}toJSON(){let e=this._getSourceDisplayMetadata(this.source);return{id:this.id,type:this.type,source:this.source,sourceName:e.name,sourceBadgeClass:e.badgeClass,directory:this.directory,workspace:this.workspace,createdAt:this.createdAt,updatedAt:this.updatedAt,summary:this.summary,hasEvents:this.hasEvents,eventCount:this.eventCount,duration:this.duration,isImported:this.isImported,hasInsight:this.hasInsight,copilotVersion:this.copilotVersion,selectedModel:this.selectedModel,sessionStatus:this.sessionStatus}}_getSourceDisplayMetadata(e){return{copilot:{name:"Copilot CLI",badgeClass:"source-copilot"},claude:{name:"Claude",badgeClass:"source-claude"},"pi-mono":{name:"Pi",badgeClass:"source-pi-mono"},vscode:{name:"Copilot Chat",badgeClass:"source-vscode"}}[e]||{name:e,badgeClass:"source-unknown"}}};Ze.exports=le});var tt=b((dn,et)=>{var Qe=require("fs").promises,H=require("fs"),K=require("readline");async function as(p){try{return await Qe.access(p),!0}catch{return!1}}async function ls(p){try{let e=H.createReadStream(p,{encoding:"utf-8"}),s=K.createInterface({input:e,crlfDelay:1/0}),t=0;for await(let n of s)n.trim()&&t++;return t}catch(e){return console.error(`Error counting lines in ${p}:`,e.message),0}}async function cs(p){try{let s=(await Qe.readFile(p,"utf-8")).split(`
2
+ `),t={};for(let n of s){let o=n.match(/^(\w+):\s*(.+)$/);o&&(t[o[1]]=o[2].trim())}return t}catch(e){return console.error(`Error parsing YAML ${p}:`,e.message),{}}}async function us(p,e=200){try{let s=H.createReadStream(p,{encoding:"utf-8"}),t=K.createInterface({input:s,crlfDelay:1/0}),n="",o=null,r=null,i=null,a=null,l=!1;for await(let d of t)if(d.trim())try{let u=JSON.parse(d);if(u.timestamp){let m=new Date(u.timestamp).getTime();isNaN(m)||(o||(o=m),r=m)}if(!n&&u.type==="user.message"){let m=u.data?.message||u.data?.content||u.data?.text||"";m&&(n=m.length>e?m.substring(0,e)+"...":m)}u.type==="session.end"&&(l=!0),u.type==="session.start"&&u.data?.copilotVersion&&!i&&(i=u.data.copilotVersion),(u.type==="session.start"||u.type==="session.model_change")&&!a&&(u.data?.selectedModel?a=u.data.selectedModel:u.data?.newModel?a=u.data.newModel:u.data?.model&&(a=u.data.model))}catch{}t.close(),s.destroy();let c=o&&r&&r>o?r-o:null;return{firstUserMessage:n||"",duration:c,copilotVersion:i||null,selectedModel:a||null,hasSessionEnd:l,lastEventTime:r,firstEventTime:o}}catch(s){return console.error(`Error reading session metadata from ${p}:`,s.message),{firstUserMessage:"",duration:null,copilotVersion:null,selectedModel:null,hasSessionEnd:!1,lastEventTime:null}}}async function ds(p,e=200){try{let s=H.createReadStream(p,{encoding:"utf-8"}),t=K.createInterface({input:s,crlfDelay:1/0});for await(let n of t)if(n.trim())try{let o=JSON.parse(n);if(o.type==="user.message"){let r=o.data?.message||o.data?.content||o.data?.text||"";if(r)return t.close(),s.destroy(),r.length>e?r.substring(0,e)+"...":r}}catch{}return""}catch{return""}}async function ps(p){try{let e=H.createReadStream(p,{encoding:"utf-8"}),s=K.createInterface({input:e,crlfDelay:1/0}),t=null,n=null;for await(let o of s)if(o.trim())try{let r=JSON.parse(o);if(r.timestamp){let i=new Date(r.timestamp).getTime();t||(t=i),n=i}}catch{}return t&&n&&n>=t?n-t:null}catch(e){return console.error(`Error calculating session duration for ${p}:`,e.message),null}}async function ms(p){try{let e=H.createReadStream(p,{encoding:"utf-8"}),s=K.createInterface({input:e,crlfDelay:1/0}),t=null,n=null;for await(let o of s)if(o.trim())try{let r=JSON.parse(o);if(r.type==="session.start"&&r.data&&(t=r.data.copilotVersion||null,n=r.data.selectedModel||null,n))return s.close(),e.destroy(),{copilotVersion:t,selectedModel:n};if(!n&&r.type==="session.model_change"&&r.data)return n=r.data.newModel||null,s.close(),e.destroy(),{copilotVersion:t,selectedModel:n}}catch{}return{copilotVersion:t,selectedModel:n}}catch(e){return console.error(`Error reading session metadata from ${p}:`,e.message),{copilotVersion:null,selectedModel:null}}}function fs(p){return p===".DS_Store"||p.startsWith(".")}et.exports={fileExists:as,countLines:ls,parseYAML:cs,getFirstUserMessage:ds,getSessionDuration:ps,getSessionMetadata:ms,getSessionMetadataOptimized:us,shouldSkipEntry:fs}});var z=b((pn,st)=>{var ce=class{canParse(e){throw new Error("canParse() must be implemented")}parse(e){throw new Error("parse() must be implemented")}getMetadata(e){throw new Error("getMetadata() must be implemented")}extractTurns(e){throw new Error("extractTurns() must be implemented")}extractToolCalls(e){throw new Error("extractToolCalls() must be implemented")}};st.exports=ce});var de=b((mn,nt)=>{var gs=z(),ue=class extends gs{canParse(e){if(!e||e.length===0)return!1;let s=["session.start","user.message","assistant.turn_start","assistant.message","tool.execution_start"];return e.some(t=>t.type&&s.some(n=>t.type.startsWith(n)))}parse(e){return{metadata:this.getMetadata(e),turns:this.extractTurns(e),toolCalls:this.extractToolCalls(e),allEvents:e}}getMetadata(e){let s=e.find(n=>n.type==="session.start");if(!s)return null;let t=s.data||{};return{sessionId:t.sessionId,startTime:t.startTime,model:t.selectedModel,version:t.copilotVersion,producer:t.producer,cwd:t.context?.cwd,gitRoot:t.context?.gitRoot,branch:t.context?.branch,repository:t.context?.repository}}extractTurns(e){let s=[],t=null;for(let n of e)if(n.type==="user.message")t&&s.push(t),t={turnId:n.id,userMessage:{id:n.id,content:n.data?.content||"",transformedContent:n.data?.transformedContent,timestamp:n.timestamp},assistantMessages:[],toolCalls:[]};else if(n.type==="assistant.message"&&t)t.assistantMessages.push({id:n.id,messageId:n.data?.messageId,content:n.data?.content||"",toolRequests:n.data?.toolRequests||[],reasoningText:n.data?.reasoningText,timestamp:n.timestamp});else if(n.type.startsWith("tool.execution_")&&t){let o=n.data?.toolCallId,r=t.toolCalls.find(i=>i.toolCallId===o);r||(r={toolCallId:o,events:[]},t.toolCalls.push(r)),r.events.push(n),n.type==="tool.execution_start"?(r.name=n.data?.toolName,r.arguments=n.data?.arguments):n.type==="tool.execution_complete"&&(r.result=n.data?.result,r.exitCode=n.data?.exitCode)}return t&&s.push(t),s}extractToolCalls(e){let s=[],t=new Map;for(let n of e)if(n.type==="tool.execution_start"){let o=n.data?.toolCallId;t.set(o,{toolCallId:o,name:n.data?.toolName,arguments:n.data?.arguments,startEvent:n,completeEvent:null})}else if(n.type==="tool.execution_complete"){let o=n.data?.toolCallId,r=t.get(o);r&&(r.completeEvent=n,r.result=n.data?.result,r.exitCode=n.data?.exitCode,s.push(r))}return s}};nt.exports=ue});var me=b((fn,ot)=>{var hs=z(),pe=class extends hs{canParse(e){return!e||e.length===0?!1:e.some(s=>s.type&&["user","assistant"].includes(s.type)&&s.uuid&&Object.prototype.hasOwnProperty.call(s,"parentUuid")&&s.sessionId)}parse(e){return{metadata:this.getMetadata(e),turns:this.extractTurns(e),toolCalls:this.extractToolCalls(e),allEvents:e}}getMetadata(e){let s=e.find(o=>o.type==="user");if(!s)return null;let n=e.find(o=>o.type==="assistant"&&o.message?.model)?.message?.model||"unknown";return{sessionId:s.sessionId,startTime:s.timestamp,model:n,version:s.version,producer:"claude-code",cwd:s.cwd,gitRoot:null,branch:s.gitBranch,repository:null}}extractTurns(e){let s=[],t=e.filter(r=>["user","assistant"].includes(r.type)&&r.type!=="file-history-snapshot"&&r.type!=="queue-operation"),n=new Map;for(let r of t)n.set(r.uuid,r);let o=t.filter(r=>r.type==="user"&&(!r.parentUuid||!n.has(r.parentUuid)));for(let r of o){let i={turnId:r.uuid,userMessage:{id:r.uuid,content:this._extractMessageContent(r.message),timestamp:r.timestamp},assistantMessages:[],toolCalls:[]};this._collectAssistantResponses(r.uuid,n,i),s.push(i)}return s}_collectAssistantResponses(e,s,t){for(let[n,o]of s.entries())if(o.parentUuid===e&&o.type==="assistant"){let r={id:o.uuid,messageId:o.message?.id,content:this._extractMessageContent(o.message),model:o.message?.model,timestamp:o.timestamp},i=this._extractToolUse(o.message);i.length>0&&(r.toolRequests=i,t.toolCalls.push(...i.map(a=>({toolCallId:a.id,name:a.name,arguments:a.input,parentUuid:o.uuid})))),t.assistantMessages.push(r),this._collectAssistantResponses(o.uuid,s,t)}}_extractMessageContent(e){return!e||!e.content?"":typeof e.content=="string"?e.content:Array.isArray(e.content)?e.content.filter(s=>s.type==="text").map(s=>s.text).join(`
3
+ `):""}_extractToolUse(e){return!e||!e.content||!Array.isArray(e.content)?[]:e.content.filter(s=>s.type==="tool_use").map(s=>({id:s.id,name:s.name,input:s.input}))}extractToolCalls(e){let s=[];for(let t of e)if(t.type==="assistant"&&t.message?.content){let n=this._extractToolUse(t.message);for(let o of n)s.push({toolCallId:o.id,name:o.name,arguments:o.input,parentUuid:t.uuid,timestamp:t.timestamp,result:null,exitCode:null})}return s}};ot.exports=pe});var ge=b((gn,rt)=>{var ys=z(),fe=class extends ys{constructor(){super("pi-mono")}async parseSessionDir(e){let s=require("fs").promises,t=require("path");try{let o=(await s.readdir(e)).filter(d=>d.endsWith(".jsonl"));if(o.length===0)return null;o.sort().reverse();let r=t.join(e,o[0]),i=await this._readFirstLine(r);if(!i)return null;let a=JSON.parse(i);if(a.type!=="session")return console.warn(`Pi-Mono file ${r} doesn't start with session event`),null;let c=t.basename(e).replace(/^--/,"").replace(/--$/,"");return{id:a.id,type:"pi-mono",source:"pi-mono",cwd:a.cwd||c,createdAt:new Date(a.timestamp),updatedAt:new Date(a.timestamp),summary:`Pi-Mono: ${c}`,fileCount:o.length}}catch(n){return console.error(`Error parsing Pi-Mono session dir ${e}:`,n.message),null}}async _readFirstLine(e){let s=require("fs"),t=require("readline");return new Promise(n=>{let o=s.createReadStream(e,{encoding:"utf-8"}),r=t.createInterface({input:o,crlfDelay:1/0});r.on("line",i=>{r.close(),o.destroy(),n(i.trim())}),r.on("close",()=>n(null))})}async parseEvents(e){let s=require("fs"),t=require("readline"),n=[],o=s.createReadStream(e,{encoding:"utf-8"}),r=t.createInterface({input:o,crlfDelay:1/0}),i=0;for await(let a of r){i++;let l=a.trim();if(l)try{let c=JSON.parse(l);n.push(c)}catch(c){console.error(`Error parsing Pi-Mono line ${i}:`,c.message)}}return n}};rt.exports=fe});var at=b((hn,it)=>{var Ss=z(),he=class extends Ss{canParse(e){if(!Array.isArray(e)||e.length===0)return!1;let s=e[0];return!!(s&&typeof s=="object"&&s.kind===0&&s.v&&s.v.sessionId)}parseVsCode(e){let s=this._getMetadata(e),t=this._toEvents(e);return{metadata:s,turns:this._extractTurns(t),toolCalls:this._extractToolCalls(t),allEvents:t}}parseJsonl(e){let s=this.replayMutations(e),t=this._getMetadata(s),n=this._toEvents(s);return{metadata:t,turns:this._extractTurns(n),toolCalls:this._extractToolCalls(n),allEvents:n}}replayMutations(e){let s=null;for(let t of e){if(!t||typeof t!="object")continue;let{kind:n,k:o,v:r,i}=t;switch(n){case 0:s=r;break;case 1:o&&Array.isArray(o)&&this._applySet(s,o,r);break;case 2:o&&Array.isArray(o)&&this._applyPush(s,o,r,i);break;case 3:o&&Array.isArray(o)&&this._applyDelete(s,o);break;default:console.warn(`[VsCodeParser] Unknown mutation kind: ${n}`)}}return s}_applySet(e,s,t){if(!e||s.length===0)return;let n=e;for(let r=0;r<s.length-1;r++){let i=s[r];n[i]||(n[i]=typeof s[r+1]=="number"?[]:{}),n=n[i]}let o=s[s.length-1];n[o]=t}_applyPush(e,s,t,n){if(!e||s.length===0)return;let o=e;for(let a=0;a<s.length-1;a++){let l=s[a];o[l]||(o[l]=typeof s[a+1]=="number"?[]:{}),o=o[l]}let r=s[s.length-1];o[r]||(o[r]=[]);let i=o[r];if(!Array.isArray(i)){console.warn(`[VsCodeParser] Push target is not an array: ${s.join(".")}`);return}n!=null&&(i.length=n),t&&Array.isArray(t)&&t.length>0&&i.push(...t)}_applyDelete(e,s){if(!e||s.length===0)return;let t=e;for(let o=0;o<s.length-1;o++){let r=s[o];if(!t[r])return;t=t[r]}let n=s[s.length-1];delete t[n]}parse(e){return Array.isArray(e)&&e.length>0&&this.canParse(e)?this.parseJsonl(e):null}getMetadata(e){let s=this.parse(e);return s?s.metadata:null}extractTurns(e){let s=this.parse(e);return s?s.turns:[]}extractToolCalls(e){let s=this.parse(e);return s?s.toolCalls:[]}_getMetadata(e){let s=e.requests||[],t=s[0]||{},n=s[s.length-1]||{},o=t.agent?.name||t.agent?.id||"vscode-copilot";return{sessionId:e.sessionId,startTime:e.creationDate?new Date(e.creationDate).toISOString():t.timestamp?new Date(t.timestamp).toISOString():null,endTime:e.lastMessageDate?new Date(e.lastMessageDate).toISOString():n.timestamp?new Date(n.timestamp).toISOString():null,model:t.modelId||null,producer:"vscode-copilot-chat",version:t.agent?.extensionVersion||null,agentName:o,requestCount:s.length}}_toEvents(e){let s=[],t=e.requests||[];s.push({type:"session.start",id:`${e.sessionId}-start`,timestamp:e.creationDate?new Date(e.creationDate).toISOString():null,data:{sessionId:e.sessionId,producer:"vscode-copilot-chat",selectedModel:t[0]?.modelId||null}});for(let n of t){let o=n.timestamp?new Date(n.timestamp).toISOString():null,r=n.modelState?.completedAt?new Date(n.modelState.completedAt).toISOString():o,i=Array.isArray(n.response)?n.response:[],a=this._buildSubAgentNameMap(i),l=this._extractUserText(n.message);s.push({type:"user.message",id:n.requestId,timestamp:o,data:{message:l,content:l}}),s.push({type:"assistant.turn_start",id:`${n.requestId}-turn`,timestamp:o,parentId:n.requestId,data:{}});let c="",d=0,u=null,m=()=>{let f=c.trim().replace(/^`{3,}$/gm,"").trim();if(c="",!f)return;let g=u,w=g?a[g]||g.slice(0,8):null;s.push({type:"assistant.message",id:`${n.requestId}-text-${d}`,timestamp:r,parentId:n.requestId,data:{message:f,content:f,tools:[],subAgentId:g||null,subAgentName:w,parentToolCallId:null}})};for(let f of i)switch(d++,f.kind){case"thinking":{let g=f.content?.value||f.content||"";g&&(c+=g+`
4
4
  `);break}case"markdownContent":{let g=f.content?.value||f.content||"";g&&(c+=g+`
5
- `);break}case void 0:case null:{let g=f.value||"";g&&(c+=g);break}case"inlineReference":{let g=f.name||"";g&&(c+="`"+g+"`");break}case"toolInvocationSerialized":{m();let g=f.toolId==="runSubagent"?f.toolCallId:f.subAgentInvocationId;f.toolId==="runSubagent"&&(u=g),g&&(u=g);let S=this._normalizeTool(f);if(S){let _=g?a[g]||g.slice(0,8):null;s.push({type:"tool.invocation",id:S.id||`${n.requestId}-tool-${d}`,timestamp:r,parentId:n.requestId,data:{tool:S,subAgentId:g||null,subAgentName:_,parentToolCallId:g||null,badgeLabel:S.name,badgeClass:S.status==="error"?"badge-error":"badge-tool"}})}break}case"textEditGroup":{m();let g=f.edits||f.uri?[f]:[];s.push({type:"tool.invocation",id:`${n.requestId}-edit-${d}`,timestamp:r,parentId:n.requestId,data:{tool:{type:"tool_use",id:`${n.requestId}-edit-${d}`,name:"textEdit",startTime:o,endTime:o,status:"completed",input:{uri:f.uri,edits:g},result:"file edit",error:null},badgeLabel:"textEdit",badgeClass:"badge-tool"}});break}case"prepareToolInvocation":case"undoStop":case"codeblockUri":case"mcpServersStarting":break;default:break}m()}return s}_buildSubAgentNameMap(e){let s={};for(let t of e){if(!t||typeof t!="object"||t.kind!=="toolInvocationSerialized"||t.toolId!=="runSubagent")continue;let n=t.toolCallId;if(!n||s[n])continue;let o=t.toolSpecificData?.agentName;if(o){s[n]=o;continue}let r=t.invocationMessage,i=typeof r=="string"?r:r&&typeof r=="object"&&r.value||"";if(i){s[n]=i;continue}let a=i.match(/agents\/([^/\]]+?)\.agent\.md/);if(a){s[n]=a[1];continue}let l=t.resultDetails,c=Array.isArray(l)?l:l?[l]:[];for(let d of c){if(typeof d!="object")continue;if(a=(d.fsPath||d.path||"").match(/agents\/([^/]+?)\.agent\.md/),a){s[n]=a[1];break}}}return s}_extractUserText(e){return e?typeof e.text=="string"?e.text:Array.isArray(e.parts)?e.parts.filter(s=>s.kind==="text").map(s=>s.text||"").join(""):"":""}_normalizeTool(e){if(!e.toolCallId)return null;let s=e.toolSpecificData||{},t=s.input||s.parameters||s.request||{},n=s.output||s.result||null,o=e.isConfirmed===!1;if(!n&&(e.generatedTitle||e.resultDetails))if(e.resultDetails){let l=(Array.isArray(e.resultDetails)?e.resultDetails:[e.resultDetails]).map(c=>c.fsPath||c.path||c.external||JSON.stringify(c)).filter(Boolean);n=l.length>0?l.join(`
6
- `):e.generatedTitle||null}else n=e.generatedTitle||null;if(Object.keys(t).length===0&&e.invocationMessage){let a=e.invocationMessage,l=typeof a=="string"?a:a&&typeof a=="object"&&a.value||"";l&&(t={description:l})}let r=a=>{if(!a||typeof a!="object")return a;let l=a.fsPath||a.path||a.external||"";return l?l.replace(/.*\//,""):JSON.stringify(a)},i=a=>{if(!a||typeof a!="object")return a;let l={};for(let[c,d]of Object.entries(a))if(!(c==="$mid"||c==="external"||c==="scheme")){if(c==="fsPath"||c==="path"){l.file=d.replace(/.*\//,"");continue}d&&typeof d=="object"&&("fsPath"in d||"$mid"in d)?l[c]=r(d):Array.isArray(d)&&c==="edits"?l.edits=`${d.length} edit(s)`:l[c]=d}return l};return t&&typeof t=="object"&&!t.description&&(t=i(t)),{type:"tool_use",id:e.toolCallId,name:e.toolId||"unknown",startTime:null,endTime:null,status:o?"error":e.isComplete?"completed":"pending",input:t,result:typeof n=="string"?n:JSON.stringify(n),error:o?e.resultDetails||"Tool invocation not confirmed":null}}_extractTurns(e){let s=[],t=null;for(let n of e)n.type==="user.message"?(t&&s.push(t),t={userMessage:n,assistantMessages:[],toolCalls:[]}):t&&(n.type==="assistant.message"?t.assistantMessages.push(n):n.type==="tool.invocation"&&t.toolCalls.push(n.data?.tool));return t&&s.push(t),s}_extractToolCalls(e){return e.filter(s=>s.type==="tool.invocation"&&s.data?.tool).map(s=>s.data.tool)}};it.exports=he});var ct=b((gn,lt)=>{var ye=de(),Se=me(),we=ge(),_e=class{constructor(){this.parsers=[new ye,new Se,new we],this.parserMap={copilot:new ye,claude:new Se,"pi-mono":new we}}getParser(e){if(typeof e=="string")return this.parserMap[e]||null;let s=e;for(let t of this.parsers)if(t.canParse(s))return t;return null}parse(e){let s=this.getParser(e);return s?s.parse(e):null}getParserType(e){let s=this.getParser(e);return s?s instanceof ye?"copilot":s instanceof Se?"claude":s instanceof we?"pi-mono":"unknown":null}};lt.exports=_e});var Ie=b((hn,ut)=>{var Ss=U(),ws=de(),_s=me(),Is=ge(),Ts=at(),Es=ct();ut.exports={BaseSessionParser:Ss,CopilotSessionParser:ws,ClaudeSessionParser:_s,PiMonoParser:Is,VsCodeParser:Ts,ParserFactory:Es}});var Ee=b((yn,pt)=>{var E=require("fs").promises,w=require("path"),ee=require("os"),R=Xe(),{fileExists:K,countLines:z,parseYAML:Cs,getSessionMetadataOptimized:dt,shouldSkipEntry:te}=tt(),{ParserFactory:bs}=Ie(),Te=class{constructor(e){typeof e=="string"?this.sources=[{type:"copilot",dir:e}]:Array.isArray(e)?this.sources=e:this.sources=[{type:"copilot",dir:process.env.COPILOT_SESSION_DIR||process.env.SESSION_DIR||w.join(ee.homedir(),".copilot","session-state")},{type:"claude",dir:process.env.CLAUDE_SESSION_DIR||w.join(ee.homedir(),".claude","projects")},{type:"pi-mono",dir:process.env.PI_MONO_SESSION_DIR||w.join(ee.homedir(),".pi","agent","sessions")},{type:"vscode",dir:process.env.VSCODE_WORKSPACE_STORAGE_DIR||w.join(ee.homedir(),"Library","Application Support","Code","User","workspaceStorage")}],this.parserFactory=new bs,this._cache=new Map,this._cacheTTL=60*1e3,this._pendingScans=new Map}invalidateCache(e=null){e?(this._cache.delete(e),this._cache.delete(null)):this._cache.clear()}async findAll(e=null){let s=e||"__all__",t=this._cache.get(s);if(t&&Date.now()-t.timestamp<this._cacheTTL)return t.data;if(this._pendingScans.has(s))return this._pendingScans.get(s);let n=this._doFindAll(e).then(o=>(this._cache.set(s,{data:o,timestamp:Date.now()}),this._pendingScans.delete(s),o)).catch(o=>{throw this._pendingScans.delete(s),o});return this._pendingScans.set(s,n),n}async _doFindAll(e=null){let s=[],t=e?this.sources.filter(n=>n.type===e):this.sources;for(let n of t)try{let o=await this._scanSource(n);s.push(...o)}catch(o){console.error(`Error reading ${n.type} sessions from ${n.dir}:`,o.message)}return this._sortByUpdatedAt(this._deduplicateSessions(s))}_deduplicateSessions(e){let s=new Map;for(let t of e){let n=s.get(t.id);(!n||t.updatedAt&&n.updatedAt&&new Date(t.updatedAt)>new Date(n.updatedAt))&&s.set(t.id,t)}return Array.from(s.values())}async _scanSource(e){try{await E.access(e.dir)}catch{return console.warn(`Source directory not found: ${e.dir}`),[]}let t=(await E.readdir(e.dir)).filter(o=>!te(o)).map(async o=>{let r=w.join(e.dir,o),i=await E.stat(r);if(e.type==="copilot"){if(i.isDirectory())return this._createDirectorySession(o,r,i,"copilot");if(o.endsWith(".jsonl"))return this._createFileSession(o,r,i,"copilot")}else if(e.type==="claude"){if(i.isDirectory())return this._scanClaudeProjectDir(r,o)}else if(e.type==="pi-mono"){if(i.isDirectory())return this._scanPiMonoDir(r,o)}else if(e.type==="vscode"&&i.isDirectory())return this._scanVsCodeWorkspaceDir(r);return null});return(await Promise.allSettled(t)).filter(o=>o.status==="fulfilled"&&o.value!==null&&o.value!==void 0).map(o=>o.value).flat()}async _scanClaudeProjectDir(e,s){try{let t=await E.readdir(e),n=[];for(let o of t){if(te(o))continue;let r=w.join(e,o),i=await E.stat(r);if(i.isFile()&&o.endsWith(".jsonl")){let a=await this._createClaudeSession(o,r,i,s);a&&n.push(a)}if(i.isDirectory()){let a=w.join(r,"subagents");try{if((await E.stat(a)).isDirectory()){let c=await this._createClaudeSubagentsSession(o,r,i,s);c&&n.push(c)}}catch{}}}return n}catch(t){return console.error(`Error scanning Claude project dir ${e}:`,t.message),[]}}async _createClaudeSession(e,s,t,n){let o=e.replace(".jsonl",""),r=await z(s);console.log(`[DEBUG] _createClaudeSession: ${e}, events: ${r}`);try{let l=(await E.readFile(s,"utf-8")).trim().split(`
7
- `).filter(S=>S.trim()).map(S=>{try{return JSON.parse(S)}catch{return null}}).filter(S=>S!==null);console.log(`[DEBUG] Parsed ${l.length} events from ${e}`);let c=l.some(S=>S.type==="assistant"||S.type==="user"),d=l.some(S=>S.type==="assistant.message"||S.type==="user.message");if(console.log(`[DEBUG] ${e}: hasClaudeCoreEvents=${c}, hasCopilotCoreEvents=${d}`),!c&&d)return console.warn(`File ${s} contains only Copilot core events, skipping as Claude session`),null;if(!c)return console.warn(`File ${s} has no Claude core events (assistant/user), skipping`),null;if(console.log(`[DEBUG] ${e} passed validation, creating session...`),this.parserFactory.getParserType(l)!=="claude")return null;let m=this.parserFactory.parse(l),f=m.metadata||{},g=n.replace(/^-/,"/").replace(/-/g,"/");return new R(o,"file",{source:"claude",filePath:s,directory:w.dirname(s),workspace:{summary:f.model?`Claude Code session (${f.model})`:"Claude Code session",cwd:f.cwd||g},createdAt:f.startTime||t.birthtime,updatedAt:t.mtime,summary:m.turns[0]?.userMessage?.content?.substring(0,100)||"No summary",hasEvents:r>0,eventCount:r,duration:null,isImported:!1,hasInsight:!1,copilotVersion:f.version,selectedModel:f.model,sessionStatus:"completed"})}catch(i){return console.error(`Error creating Claude session ${o}:`,i.message),null}}async findById(e){if(te(e))return null;for(let s of this.sources){let t=null;if(s.type==="copilot"?t=await this._findCopilotSession(e,s.dir):s.type==="claude"?t=await this._findClaudeSession(e,s.dir):s.type==="pi-mono"?t=await this._findPiMonoSession(e,s.dir):s.type==="vscode"&&(t=await this._findVsCodeSession(e,s.dir)),t)return t}return null}async _findCopilotSession(e,s){try{let t=w.join(s,e),n=await E.stat(t);if(n.isDirectory())return await this._createDirectorySession(e,t,n,"copilot")}catch{}try{let t=w.join(s,`${e}.jsonl`),n=await E.stat(t);if(n.isFile())return await this._createFileSession(`${e}.jsonl`,t,n,"copilot")}catch{}return null}async _findClaudeSession(e,s){try{let t=await E.readdir(s);for(let n of t){let o=w.join(s,n),r=w.join(o,`${e}.jsonl`);try{let a=await E.stat(r);if(a.isFile()){console.log(`[DEBUG] Found file: ${r}`);let l=await this._createClaudeSession(`${e}.jsonl`,r,a,n);if(l)return console.log("[DEBUG] File validated as Claude session, returning"),l;console.log("[DEBUG] File validation failed, checking directory...")}}catch(a){console.log(`[DEBUG] File not found: ${r}, error: ${a.message}`)}let i=w.join(o,e);console.log(`[DEBUG] Checking directory: ${i}`);try{let a=await E.stat(i);if(a.isDirectory()){console.log("[DEBUG] Directory exists, checking for subagents...");let l=w.join(i,"subagents");try{if((await E.stat(l)).isDirectory()){console.log("[DEBUG] Found subagents directory, creating session...");let d=await this._createClaudeSubagentsSession(e,i,a,n);return console.log("[DEBUG] Created subagents session:",d?"SUCCESS":"FAILED"),d}}catch(c){console.log(`[DEBUG] No subagents directory: ${c.message}`)}}}catch(a){console.log(`[DEBUG] Directory not found: ${a.message}`)}}}catch(t){console.error(`[DEBUG] Projects dir error: ${t.message}`)}return console.log(`[DEBUG] Session ${e} not found in any project`),null}async _findPiMonoSession(e,s){try{let t=await E.readdir(s);for(let n of t){let o=w.join(s,n);try{let i=(await E.readdir(o)).find(a=>a.includes(`_${e}.jsonl`));if(i){let a=w.join(o,i),l=await E.stat(a),c=await this._readFirstLine(a);if(c){let d=JSON.parse(c);if(d.type==="session"){let u=n.replace(/^--/,"").replace(/--$/,""),m=await z(a);return new R(e,"directory",{source:"pi-mono",filePath:a,directory:o,workspace:{cwd:d.cwd||u},createdAt:new Date(d.timestamp),updatedAt:new Date(l.mtime),summary:`Pi-Mono: ${w.basename(d.cwd||u)}`,hasEvents:m>0,eventCount:m,duration:null,sessionStatus:"completed"})}}}}catch{}}}catch(t){console.error(`Error searching Pi-Mono sessions: ${t.message}`)}return null}async _findVsCodeSession(e,s){try{let t=await E.readdir(s),n=[];for(let o of t){let r=w.join(s,o,"chatSessions");try{let a=(await E.readdir(r)).find(l=>l===`${e}.json`||l===`${e}.jsonl`||l.replace(/\.jsonl?$/,"")===e);if(a){let l=w.join(r,a),c=await E.stat(l),d=await E.readFile(l,"utf-8"),u;if(a.endsWith(".jsonl")){if(u=this._parseVsCodeJsonl(d),!u)continue}else u=JSON.parse(d);let m=u.requests||[];if(m.length===0)continue;let f=await this._resolveVsCodeWorkspacePath(w.join(s,o)),g={...c,filePath:l};n.push(this._buildVsCodeSession(e,m,u,g,o,f||w.join(s,o)))}}catch{}}if(n.length>0)return n.sort((o,r)=>(r.updatedAt?.getTime?.()??0)-(o.updatedAt?.getTime?.()??0)),n[0]}catch(t){console.error(`[VSCode findById] Error searching VSCode sessions: ${t.message}`,t.stack)}return console.log(`[VSCode findById] Session ${e} not found in vscode sessions`),null}async _createClaudeSubagentsSession(e,s,t,n){try{let o=w.join(s,"subagents"),i=(await E.readdir(o)).filter(g=>g.startsWith("agent-")&&g.endsWith(".jsonl"));if(i.length===0)return null;let a=0;for(let g of i){let S=w.join(o,g);a+=await z(S)}let l=w.join(o,i[0]),d=(await E.readFile(l,"utf-8")).trim().split(`
8
- `).filter(g=>g.trim()),u=d.length>0?JSON.parse(d[0]):null,m={cwd:u?.cwd||n,version:u?.version,model:u?.message?.model,startTime:u?.timestamp},f=n.replace(/^-/,"/").replace(/-/g,"/");return new R(e,"directory",{source:"claude",directory:s,workspace:{summary:`Claude session (${i.length} sub-agents)`,cwd:m.cwd||f},createdAt:m.startTime||t.birthtime,updatedAt:t.mtime,summary:u?.message?.content?.substring(0,100)||"Sub-agent tasks",hasEvents:a>0,eventCount:a,duration:null,isImported:!1,hasInsight:!1,copilotVersion:m.version,selectedModel:m.model,sessionStatus:"completed"})}catch(o){return console.error(`Error creating Claude subagents session ${e}:`,o.message),null}}async _createDirectorySession(e,s,t,n="copilot"){let o=w.join(s,"workspace.yaml"),r=w.join(s,"events.jsonl"),i=w.join(s,".imported"),a=w.join(s,`${e}.agent-review.md`),l=await K(o)?await Cs(o):{summary:e,repo:"unknown"},c=await K(r)?await z(r):0,d=await K(i),u=await K(a),m=null,f=null,g=null,S="completed";if(await K(r)){let y=await dt(r);if(m=y.duration,f=y.copilotVersion,g=y.selectedModel,S=this._computeSessionStatus(y),!l.summary&&y.firstUserMessage&&(l.summary=y.firstUserMessage),y.lastEventTime){let j=new Date(y.lastEventTime).getTime(),v=new Date(t.mtime).getTime();j>v&&(t={...t,mtime:new Date(j)})}}let _=R.fromDirectory(s,e,t,l,c,m,d,u,f,g,S);return _.source=n,_}async _createFileSession(e,s,t,n="copilot"){let o=e.replace(".jsonl",""),r=await z(s),i=await dt(s),a=this._computeSessionStatus(i),l=R.fromFile(s,o,t,r,i.firstUserMessage,i.duration,i.copilotVersion,i.selectedModel,a);return l.source=n,l}_computeSessionStatus(e){return e.hasSessionEnd?"completed":e.lastEventTime!==null&&e.lastEventTime!==void 0&&Date.now()-e.lastEventTime<3e5?"wip":"completed"}async _scanPiMonoDir(e,s){try{console.log(`[PI-MONO] Scanning directory: ${e}`);let n=(await E.readdir(e)).filter(r=>r.endsWith(".jsonl"));if(console.log(`[PI-MONO] Found ${n.length} .jsonl files in ${s}`),n.length===0)return[];let o=[];n.sort().reverse();for(let r of n){let i=w.join(e,r),a=await E.stat(i),l=r.match(/_([a-f0-9-]+)\.jsonl$/);if(!l){console.log(`[PI-MONO] Skipping ${r}: no UUID match`);continue}let c=l[1],d=await this._readFirstLine(i);if(!d){console.log(`[PI-MONO] Skipping ${r}: no first line`);continue}try{let u=JSON.parse(d);if(u.type!=="session"){console.log(`[PI-MONO] Skipping ${r}: first event type is ${u.type}, not 'session'`);continue}let m=await z(i),f=s.replace(/^--/,"").replace(/--$/,""),g=new R(c,"directory",{source:"pi-mono",directory:e,workspace:{cwd:u.cwd||f},createdAt:new Date(u.timestamp),updatedAt:new Date(a.mtime),summary:`Pi-Mono: ${w.basename(u.cwd||f)}`,hasEvents:m>0,eventCount:m,duration:null,sessionStatus:"completed"});console.log(`[PI-MONO] Created session: ${c} from ${r}`),o.push(g)}catch(u){console.error(`[PI-MONO] Error parsing session ${r}:`,u.message)}}return console.log(`[PI-MONO] Total sessions found in ${s}: ${o.length}`),o}catch(t){return console.error(`[PI-MONO] Error scanning dir ${e}:`,t.message),[]}}_parseVsCodeJsonl(e){let s=e.split(`
9
- `).filter(o=>o.trim());if(s.length===0)return null;let t=JSON.parse(s[0]),n=t.v||t;for(let o=1;o<s.length;o++)try{let r=JSON.parse(s[o]),i=r.k||[],a=r.v;if(r.kind===2&&Array.isArray(a)){let l=n;for(let d=0;d<i.length-1;d++){let u=i[d];typeof u=="number"||l[u]||(l[u]={}),l=l[u]}let c=i[i.length-1];if(c!==void 0){l[c]||(l[c]=[]);let d=l[c],u=r.i;u==null?d.push(...a):d.splice(u,0,...a)}else{let d=r.i;d==null&&n.push?.(...a)}}else if(r.kind===1&&i.length>0){let l=n;for(let d=0;d<i.length-1;d++){let u=i[d];typeof u=="number"||l[u]||(l[u]={}),l=l[u]}let c=i[i.length-1];l[c]=a}}catch{}return n}async _resolveVsCodeWorkspacePath(e){try{let s=w.join(e,"workspace.json"),t=await E.readFile(s,"utf-8"),n=JSON.parse(t);if(n.folder)return decodeURIComponent(n.folder.replace("file://",""));if(n.workspace){let o=decodeURIComponent(n.workspace.replace("file://",""));try{let r=await E.readFile(o,"utf-8"),i=JSON.parse(r);if(Array.isArray(i.folders)&&i.folders.length>0){let a=w.dirname(o);return w.resolve(a,i.folders[0].path)}}catch{}}}catch{}return null}async _scanVsCodeWorkspaceDir(e){let s=w.join(e,"chatSessions");try{await E.access(s)}catch{return[]}let t=w.basename(e),n=await this._resolveVsCodeWorkspacePath(e),r=(await E.readdir(s)).filter(a=>(a.endsWith(".json")||a.endsWith(".jsonl"))&&!te(a));if(r.length===0)return[];let i=[];for(let a of r){let l=w.join(s,a);try{let c=await E.stat(l),d=await E.readFile(l,"utf-8"),u;if(a.endsWith(".jsonl")){if(u=this._parseVsCodeJsonl(d),!u)continue}else u=JSON.parse(d);let m=u.sessionId||w.basename(a).replace(/\.jsonl?$/,""),f=u.requests||[];if(f.length===0)continue;let g={...c,filePath:l},S=this._buildVsCodeSession(m,f,u,g,t,n||e);i.push(S)}catch{}}return i}_buildVsCodeSession(e,s,t,n,o,r){let i=s[0],a=s[s.length-1],l=t.creationDate?new Date(t.creationDate):i.timestamp?new Date(i.timestamp):n.birthtime,c=a.timestamp?new Date(a.timestamp):null,d=t.lastMessageDate?new Date(t.lastMessageDate):c||n.mtime,m=this._extractLastTerminalTimestamp(s)||c||d,f=Date.now()-m.getTime()<900*1e3,g=this._extractVsCodeUserText(i.message),S=s.reduce((_,y)=>_+(y.response||[]).filter(j=>j.kind==="toolInvocationSerialized").length,0);return new R(e,"file",{source:"vscode",filePath:n.filePath,workspaceHash:o,createdAt:l,updatedAt:m,summary:g?g.slice(0,120):`VSCode chat (${s.length} requests)`,hasEvents:!0,eventCount:s.reduce((_,y)=>_+(y.response||[]).length,0)+s.length*2+1,duration:m.getTime()-l.getTime(),sessionStatus:f?"wip":"completed",selectedModel:i.modelId||null,agentId:i.agent?.id||"vscode-copilot",toolCount:S,copilotVersion:i.agent?.extensionVersion||null,workspace:{cwd:r}})}_extractLastTerminalTimestamp(e){let s=0;function t(n){if(!(!n||typeof n!="object")){if(Array.isArray(n)){n.forEach(t);return}if(n.terminalCommandState&&typeof n.terminalCommandState.timestamp=="number"){let o=n.terminalCommandState.timestamp;o>1e12&&o<9999999999999&&o>s&&(s=o)}for(let o of Object.values(n))t(o)}}for(let n of e)t(n.response);return s>0?new Date(s):null}_extractVsCodeUserText(e){return e?typeof e.text=="string"?e.text:Array.isArray(e.parts)?e.parts.filter(s=>s.kind==="text").map(s=>s.text||"").join(""):"":""}async _readFirstLine(e){let s=require("fs"),t=require("readline");return new Promise((n,o)=>{let r=s.createReadStream(e,{encoding:"utf-8"}),i=t.createInterface({input:r,crlfDelay:1/0}),a=!1;i.on("line",l=>{a||(a=!0,i.close(),n(l.trim()))}),i.on("close",()=>{a||n(null)}),i.on("error",l=>{a||(a=!0,o(l))}),r.on("error",l=>{a||(a=!0,i.close(),o(l))})})}_sortByUpdatedAt(e){return e.sort((s,t)=>new Date(t.updatedAt)-new Date(s.updatedAt))}};pt.exports=Te});var ft=b((Sn,mt)=>{var Ce=class{normalizeEvents(e,s){return Array.isArray(e)?e.filter(t=>!t._isToolResultWrapper).map(t=>this.normalizeEvent(t,s)):(console.warn("[EventNormalizer] normalizeEvents: events is not an array",typeof e),[])}normalizeEvent(e,s){return!e||typeof e!="object"?(console.warn("[EventNormalizer] normalizeEvent: invalid event",e),e):this._isAssistantMessage(e)?this._normalizeAssistantMessage(e,s):this._isTimelineEvent(e)?this._normalizeTimelineEvent(e,s):e}_isAssistantMessage(e){return e.data?.tools&&Array.isArray(e.data.tools)&&e.data.tools.length>0?!0:e.type==="assistant.message"||e.type==="assistant"||e.type==="user.message"||e.type==="user"}_isTimelineEvent(e){return e.type?.startsWith("tool.")||e.type?.startsWith("subagent.")}_normalizeAssistantMessage(e,s){let t={...e};return e.data?.tools&&Array.isArray(e.data.tools)&&(t.data={...e.data,tools:e.data.tools.filter(n=>n.type!=="tool_result").map(n=>this._normalizeToolCall(n,s,e.timestamp))}),t}_normalizeToolCall(e,s,t){if(e.type==="tool_use"){let n=this._computeStatus(e),o=t,r=e._matched?t:null;return{type:"tool_use",id:e.id,name:e.name,startTime:o,endTime:r,status:n,input:e.input||{},result:e.result||null,error:e.error||null,metadata:{source:s,matched:e._matched,duration:this._computeDuration(o,r)}}}if(e.name&&e.status){let n=t,o=e.status==="success"?"completed":e.status,r=o==="completed"||o==="error"?t:null;return{id:e.id||this._generateToolId(),name:e.name,startTime:n,endTime:r,status:o,input:e.input||{},result:e.isError?null:e.result||null,error:e.isError?e.result:null,metadata:{source:s,duration:this._computeDuration(n,r)}}}return console.warn("[EventNormalizer] Unknown tool format, applying fallback normalization",e),{id:e.id||this._generateToolId(),name:e.name||"unknown",startTime:t,endTime:null,status:"running",input:e.input||{},result:null,error:null,metadata:{source:s,fallback:!0}}}_computeStatus(e){return e.error?"error":e.result!==void 0&&e.result!==null&&e.result!==""?"completed":e._matched===!1?"running":e._matched?"completed":"running"}_computeDuration(e,s){if(!(!e||!s))try{let t=new Date(e),n=new Date(s);if(isNaN(t.getTime())||isNaN(n.getTime()))return;let o=n.getTime()-t.getTime();return o>=0?o:void 0}catch{return}}_generateToolId(){return`tool-${Date.now()}-${Math.random().toString(36).substr(2,9)}`}_normalizeTimelineEvent(e){return e.type==="tool.execution_start"||e.type==="tool.execution_complete"?{...e,data:{...e.data,toolCallId:e.data?.toolCallId||e.data?.id,toolName:e.data?.toolName||e.data?.tool||e.data?.name,...e.data}}:(e.type?.startsWith("subagent."),e)}};mt.exports=Ce});var je=b((wn,St)=>{var D=require("fs"),x=require("path"),gt=require("readline"),{isValidSessionId:ht,buildMetadata:js}=L(),yt=Ee(),vs=ft(),be=class{constructor(e){e?(this.SESSION_DIR=e,this.sessionRepository=new yt(e)):this.sessionRepository=new yt,this.eventNormalizer=new vs}async getAllSessions(e=null){return(await this.sessionRepository.findAll(e)).map(t=>t.toJSON())}async getPaginatedSessions(e=1,s=20,t=null){let o=(await this.sessionRepository.findAll(t)).map(l=>l.toJSON()),r=(e-1)*s,i=r+s;return{sessions:o.slice(r,i),totalSessions:o.length,currentPage:e,totalPages:Math.ceil(o.length/s),hasNextPage:i<o.length,hasPrevPage:e>1}}async getSessionById(e){return ht(e)?(await this.getAllSessions()).find(t=>t.id===e):null}async getSessionEvents(e,s=null){if(!ht(e))return s?{events:[],total:0}:[];let t=await this.sessionRepository.findById(e);if(!t)return s?{events:[],total:0}:[];let n;if(t.source==="copilot")if(this.SESSION_DIR){let r=x.join(this.SESSION_DIR,e);try{(await D.promises.stat(r)).isDirectory()?n=x.join(r,"events.jsonl"):n=x.join(this.SESSION_DIR,`${e}.jsonl`)}catch{n=x.join(this.SESSION_DIR,`${e}.jsonl`)}}else{let r=this.sessionRepository.sources.find(a=>a.type==="copilot");if(!r)return[];let i=x.join(r.dir,e);try{(await D.promises.stat(i)).isDirectory()?n=x.join(i,"events.jsonl"):n=x.join(r.dir,`${e}.jsonl`)}catch{n=x.join(r.dir,`${e}.jsonl`)}}else if(t.source==="claude"){let r=this.sessionRepository.sources.find(i=>i.type==="claude");if(!r)return[];if(t.type!=="directory")try{let i=await D.promises.readdir(r.dir);for(let a of i){let l=x.join(r.dir,a,`${e}.jsonl`);try{await D.promises.access(l),n=l;break}catch{}}}catch(i){return console.error("Error searching Claude projects:",i),[]}}else if(t.source==="pi-mono"){let r=this.sessionRepository.sources.find(i=>i.type==="pi-mono");if(!r)return[];try{let i=await D.promises.readdir(r.dir);for(let a of i){let l=x.join(r.dir,a);try{let d=(await D.promises.readdir(l)).find(u=>u.includes(`_${e}.jsonl`));if(d){n=x.join(l,d);break}}catch{}}}catch(i){return console.error("Error searching Pi-Mono sessions:",i),[]}}else if(t.source==="vscode"){let{VsCodeParser:r}=Ie(),i=new r;try{let a=await D.promises.readFile(t.filePath,"utf-8"),c=a.trim().split(`
10
- `).filter(m=>m.trim()).map(m=>{try{return JSON.parse(m)}catch{return null}}).filter(m=>m!==null);if(c.length===0)return[];let d;if(i.canParse(c))d=i.parseJsonl(c);else{let m=JSON.parse(a);d=i.parseVsCode(m)}let u=this._expandVsCodeEvents(d.allEvents);if(u.length>0)try{let m=await D.promises.stat(t.filePath),f=new Date(m.mtime).toISOString(),g=u[u.length-1];if(g&&g.timestamp){let S=new Date(g.timestamp).getTime(),y=(new Date(f).getTime()-S)/1e3;y>10&&(g.timestamp=f,console.log(`[VSCode] Updated session ${t.id} end time to file mtime (${y.toFixed(0)}s difference)`))}}catch(m){console.error("[VSCode] Error getting file mtime:",m)}return u=this._expandVsCodeToTimelineFormat(u),u}catch(a){return console.error("Error reading VSCode session:",a),[]}}let o=[];if(n)try{await D.promises.access(n);let r=D.createReadStream(n,{encoding:"utf-8"}),i=gt.createInterface({input:r,crlfDelay:1/0}),a=0,l=[];for await(let d of i){let u=d.trim();if(u)try{let m=JSON.parse(u);m._fileIndex=a,l.push(m)}catch(m){console.error(`Error parsing line ${a+1}:`,m.message)}a++}o=l,o.sort((d,u)=>{let m=d.timestamp?new Date(d.timestamp).getTime():0,f=u.timestamp?new Date(u.timestamp).getTime():0;return m!==f?m-f:d._fileIndex-u._fileIndex}),o=o.map(d=>this._normalizeEvent(d,t.source)),t.source==="copilot"?this._matchCopilotToolCalls(o):t.source==="claude"&&this._matchClaudeToolResults(o)}catch(r){console.error("Error reading main events file:",r)}if(await this._mergeSubAgentEvents(o,n,e,t.source),t.source==="copilot"?(this._matchCopilotToolCalls(o),o=this._expandCopilotToTimelineFormat(o)):t.source==="claude"?(this._matchClaudeToolResults(o),o=this._expandClaudeToTimelineFormat(o)):t.source==="pi-mono"&&this._mergePiMonoToolResults(o),o=o.filter(r=>r.timestamp||r.snapshot?.timestamp?!0:(console.warn("[SessionService] Filtered event without timestamp:",r.type,r.id||r._fileIndex),!1)),o.forEach(r=>{r._fileIndex===999999&&r.timestamp&&delete r._fileIndex}),o=this.eventNormalizer.normalizeEvents(o,t.source),s&&typeof s.limit=="number"&&typeof s.offset=="number"){let r=o.length;return{events:o.slice(s.offset,s.offset+s.limit),total:r}}return o}async _mergeSubAgentEvents(e,s,t,n){let o;if(n==="claude"){let r=this.sessionRepository.sources.find(i=>i.type==="claude");if(!r)return;try{let i=await D.promises.readdir(r.dir);for(let a of i){let l=x.join(r.dir,a,t,"subagents");try{if((await D.promises.stat(l)).isDirectory()){o=l;break}}catch{}}}catch(i){console.error("Error searching Claude subagents:",i);return}}else if(n==="copilot"&&s){let r=x.dirname(s);x.basename(s)==="events.jsonl"?o=x.join(r,"subagents"):o=x.join(r,t,"subagents")}if(o){try{if(!(await D.promises.stat(o)).isDirectory())return}catch{return}try{let i=(await D.promises.readdir(o)).filter(a=>a.startsWith("agent-")&&a.endsWith(".jsonl"));if(i.length===0)return;for(let a of i){let l=a.replace(".jsonl",""),c=x.join(o,a);try{let d=D.createReadStream(c,{encoding:"utf-8"}),u=gt.createInterface({input:d,crlfDelay:1/0}),m=[];for await(let A of u){let $=A.trim();$&&m.push($)}if(m.length===0)continue;let f=l.replace("agent-",""),g=f.toUpperCase(),S=`Sub-agent ${l}`;try{let A=JSON.parse(m[0]);if(A.agentId&&(f=A.agentId,g=`agent-${A.agentId}`),A.message?.content){let $=typeof A.message.content=="string"?A.message.content:JSON.stringify(A.message.content);S=$.length>100?$.slice(0,100)+"...":$}}catch{}let _=m.map((A,$)=>{try{let G=JSON.parse(A);return G._fileIndex=1e6+$,G._subagent={id:l,name:f},G}catch(G){return console.error(`Error parsing sub-agent ${l} line ${$+1}:`,G.message),null}}).filter(A=>A!==null);if(_.length===0)continue;let y=_.map(A=>this._normalizeEvent(A,n)),j=y[0],v=y[y.length-1],F=j.timestamp||new Date().toISOString(),oe=v.timestamp||new Date().toISOString(),re={type:"subagent.started",id:`${l}-start`,timestamp:F,_fileIndex:j._fileIndex-1,_subagent:{id:l,name:f},data:{toolCallId:l,agentName:f,agentDisplayName:g,agentDescription:S}},Le={type:"subagent.completed",id:`${l}-end`,timestamp:oe,_fileIndex:v._fileIndex+1,_subagent:{id:l,name:f},data:{toolCallId:l,result:`Sub-agent ${g} completed`}};e.push(re,...y,Le)}catch(d){console.error(`Error reading sub-agent ${l}:`,d)}}e.sort((a,l)=>{let c=a.timestamp?new Date(a.timestamp).getTime():0,d=l.timestamp?new Date(l.timestamp).getTime():0;return c!==d?c-d:a._fileIndex-l._fileIndex})}catch(r){console.error("Error processing sub-agents:",r)}}}_matchClaudeToolResults(e){let s=new Map;e.forEach(t=>{t.data?.tools&&t.data.tools.forEach(n=>{n.type==="tool_result"&&(n.tool_use_id?s.set(n.tool_use_id,n):console.warn("[sessionService] tool_result missing tool_use_id:",n))})}),e.forEach(t=>{t.type==="user"&&Array.isArray(t.message?.content)&&t.message.content.length>0&&t.message.content.every(o=>o?.type==="tool_result")&&(t._isToolResultWrapper=!0)}),e.forEach(t=>{t.data?.tools&&(t.data.tools=t.data.tools.map(n=>{if(n.type==="tool_use"){let o=s.get(n.id);return o?{...n,result:o.content,_matched:!0}:{...n,_matched:!1}}return n}),t.type==="assistant"||t.type==="assistant.message"?t.data.tools=t.data.tools.filter(n=>n.type!=="tool_result"):(t.type==="user"||t.type==="user.message")&&t.data.tools.length>0&&t.data.tools.every(o=>o.type==="tool_result")&&(t._isToolResultWrapper=!0))})}_mergePiMonoToolResults(e){let s=new Set;e.forEach(n=>{if(n.type==="assistant.message"&&n.data.tools&&n.data.tools.length>0){let o=n.data.tools,r=[],i=n.id,a=!0;for(;a&&r.length<o.length;){a=!1;for(let l of e)if(l.type==="message"&&l.data.role==="toolResult"&&l.parentId===i&&!r.includes(l)){r.push(l),i=l.id,a=!0;break}}r.forEach((l,c)=>{if(c<o.length){let d=o[c];d.result=l.data.result,d.resultId=l.id,d.status="completed",s.add(l.id)}})}});let t=e.length;for(let n=e.length-1;n>=0;n--)e[n].type==="message"&&e[n].data.role==="toolResult"&&s.has(e[n].id)&&e.splice(n,1);s.size>0&&console.log(`[PI-MONO] Merged ${s.size} toolResult events into assistant messages (${t} \u2192 ${e.length} events)`)}_matchPiMonoToolResults_OLD(e){let s=new Set;e.forEach(n=>{if(n.type==="assistant.message"&&n.data.tools&&n.data.tools.length>0){let o=n.data.tools,r=[],i=n.id,a=!0;for(;a&&r.length<o.length;){a=!1;for(let l of e)if(l.type==="tool.result"&&l.parentId===i&&!r.includes(l)){r.push(l),i=l.id,a=!0;break}}r.forEach((l,c)=>{if(c<o.length){let d=o[c];d.status="completed",d._matched=!0,d.result=l.data.result,d.resultId=l.id,s.add(l.id)}})}});let t=e.length;for(let n=e.length-1;n>=0;n--)e[n].type==="tool.result"&&s.has(e[n].id)&&e.splice(n,1);s.size>0&&console.log(`[PI-MONO] Removed ${s.size} matched tool.result events (${t} \u2192 ${e.length} events)`)}_matchCopilotToolCalls(e){let s=new Map;e.forEach(t=>{if(t.type==="tool.execution_start"){let n=t.data?.toolCallId;n&&s.set(n,{name:t.data.toolName,input:t.data.arguments||{},start:t})}else if(t.type==="tool.execution_complete"){let n=t.data?.toolCallId;if(n)if(s.has(n)){let o=s.get(n);o.complete=t,o.result=t.data?.result,o.status=t.data?.error?"error":"completed",o.error=t.data?.error}else console.warn(`[sessionService] Orphaned tool.execution_complete for toolCallId=${n}`),s.set(n,{name:t.data.toolName||"unknown",input:{},start:null,complete:t,result:t.data?.result,status:t.data?.error?"error":"completed",error:t.data?.error})}}),e.forEach(t=>{if(t.type==="assistant.message"&&t.data?.toolRequests){let n=[];t.data.toolRequests.forEach(o=>{let r=o.toolCallId;if(s.has(r)){let i=s.get(r);n.push({type:"tool_use",id:r,name:o.name||i.name,input:o.arguments||i.input,result:i.result,status:i.status||"running",error:i.error,_matched:!!i.complete})}else n.push({type:"tool_use",id:r,name:o.name,input:o.arguments||{},status:"running",_matched:!1})}),n.length>0&&(t.data.tools=n)}})}_generateBadgeInfo(e){let s=e.type,t=e.data||{};if(s==="message"&&t.role==="toolResult"){e.data.badgeLabel="TOOL RESULT",e.data.badgeClass="badge-tool";return}if(s==="session.model_change"||s==="model.change"){e.data.badgeLabel="MODEL CHANGE",e.data.badgeClass="badge-session";return}if(s==="session.truncation"){e.data.badgeLabel="TRUNCATION",e.data.badgeClass="badge-truncation";return}if(s==="session.compaction_start"||s==="session.compaction_complete"||s==="compaction"){e.data.badgeLabel="COMPACTION",e.data.badgeClass="badge-compaction";return}if(s==="thinking.change"){e.data.badgeLabel="THINKING",e.data.badgeClass="badge-session";return}if(s==="system.notification"){e.data.badgeLabel="SYSTEM",e.data.badgeClass="badge-system";return}let o=(s||"").split(".")[0]||"unknown",i={user:{label:"USER",class:"badge-user"},assistant:{label:"ASSISTANT",class:"badge-assistant"},reasoning:{label:"REASONING",class:"badge-reasoning"},turn:{label:"TURN",class:"badge-turn"},tool:{label:"TOOL",class:"badge-tool"},subagent:{label:"SUBAGENT",class:"badge-subagent"},skill:{label:"SKILL",class:"badge-skill"},session:{label:"SESSION",class:"badge-session"},error:{label:"ERROR",class:"badge-error"},abort:{label:"ABORT",class:"badge-error"}}[o]||{label:o.toUpperCase(),class:"badge-info"};e.data.badgeLabel=i.label,e.data.badgeClass=i.class}_normalizeEvent(e,s){let t={...e};if(t.data=t.data||{},s==="copilot"){if(e.type==="user.message"&&e.data?.source==="system"){t.type="system.notification";let n=e.data.content||e.data.message||"",o=n.match(/<system_notification>([\s\S]*?)<\/system_notification>/);return t.data.message=o?o[1].trim():n.trim(),this._generateBadgeInfo(t),t}if(e.type==="request"){if(t.type="user",e.payload?.messages&&Array.isArray(e.payload.messages)){let n=e.payload.messages.find(o=>o.role==="user");n&&(t.message={role:"user",content:n.content||""})}}else if(e.type==="response"&&(t.type="assistant",e.payload?.content&&Array.isArray(e.payload.content))){let n=e.payload.content.filter(o=>o.type==="text");n.length>0&&(t.message={role:"assistant",content:n.map(o=>o.text).join(`
5
+ `);break}case void 0:case null:{let g=f.value||"";g&&(c+=g);break}case"inlineReference":{let g=f.name||"";g&&(c+="`"+g+"`");break}case"toolInvocationSerialized":{m();let g=f.toolId==="runSubagent"?f.toolCallId:f.subAgentInvocationId;f.toolId==="runSubagent"&&(u=g),g&&(u=g);let w=this._normalizeTool(f);if(w){let _=g?a[g]||g.slice(0,8):null;s.push({type:"tool.invocation",id:w.id||`${n.requestId}-tool-${d}`,timestamp:r,parentId:n.requestId,data:{tool:w,subAgentId:g||null,subAgentName:_,parentToolCallId:g||null,badgeLabel:w.name,badgeClass:w.status==="error"?"badge-error":"badge-tool"}})}break}case"textEditGroup":{m();let g=f.edits||f.uri?[f]:[];s.push({type:"tool.invocation",id:`${n.requestId}-edit-${d}`,timestamp:r,parentId:n.requestId,data:{tool:{type:"tool_use",id:`${n.requestId}-edit-${d}`,name:"textEdit",startTime:o,endTime:o,status:"completed",input:{uri:f.uri,edits:g},result:"file edit",error:null},badgeLabel:"textEdit",badgeClass:"badge-tool"}});break}case"prepareToolInvocation":case"undoStop":case"codeblockUri":case"mcpServersStarting":break;default:break}m()}return s}_buildSubAgentNameMap(e){let s={};for(let t of e){if(!t||typeof t!="object"||t.kind!=="toolInvocationSerialized"||t.toolId!=="runSubagent")continue;let n=t.toolCallId;if(!n||s[n])continue;let o=t.toolSpecificData?.agentName;if(o){s[n]=o;continue}let r=t.invocationMessage,i=typeof r=="string"?r:r&&typeof r=="object"&&r.value||"";if(i){s[n]=i;continue}let a=i.match(/agents\/([^/\]]+?)\.agent\.md/);if(a){s[n]=a[1];continue}let l=t.resultDetails,c=Array.isArray(l)?l:l?[l]:[];for(let d of c){if(typeof d!="object")continue;if(a=(d.fsPath||d.path||"").match(/agents\/([^/]+?)\.agent\.md/),a){s[n]=a[1];break}}}return s}_extractUserText(e){return e?typeof e.text=="string"?e.text:Array.isArray(e.parts)?e.parts.filter(s=>s.kind==="text").map(s=>s.text||"").join(""):"":""}_normalizeTool(e){if(!e.toolCallId)return null;let s=e.toolSpecificData||{},t=s.input||s.parameters||s.request||{},n=s.output||s.result||null,o=e.isConfirmed===!1;if(!n&&(e.generatedTitle||e.resultDetails))if(e.resultDetails){let l=(Array.isArray(e.resultDetails)?e.resultDetails:[e.resultDetails]).map(c=>c.fsPath||c.path||c.external||JSON.stringify(c)).filter(Boolean);n=l.length>0?l.join(`
6
+ `):e.generatedTitle||null}else n=e.generatedTitle||null;if(Object.keys(t).length===0&&e.invocationMessage){let a=e.invocationMessage,l=typeof a=="string"?a:a&&typeof a=="object"&&a.value||"";l&&(t={description:l})}let r=a=>{if(!a||typeof a!="object")return a;let l=a.fsPath||a.path||a.external||"";return l?l.replace(/.*\//,""):JSON.stringify(a)},i=a=>{if(!a||typeof a!="object")return a;let l={};for(let[c,d]of Object.entries(a))if(!(c==="$mid"||c==="external"||c==="scheme")){if(c==="fsPath"||c==="path"){l.file=d.replace(/.*\//,"");continue}d&&typeof d=="object"&&("fsPath"in d||"$mid"in d)?l[c]=r(d):Array.isArray(d)&&c==="edits"?l.edits=`${d.length} edit(s)`:l[c]=d}return l};return t&&typeof t=="object"&&!t.description&&(t=i(t)),{type:"tool_use",id:e.toolCallId,name:e.toolId||"unknown",startTime:null,endTime:null,status:o?"error":e.isComplete?"completed":"pending",input:t,result:typeof n=="string"?n:JSON.stringify(n),error:o?e.resultDetails||"Tool invocation not confirmed":null}}_extractTurns(e){let s=[],t=null;for(let n of e)n.type==="user.message"?(t&&s.push(t),t={userMessage:n,assistantMessages:[],toolCalls:[]}):t&&(n.type==="assistant.message"?t.assistantMessages.push(n):n.type==="tool.invocation"&&t.toolCalls.push(n.data?.tool));return t&&s.push(t),s}_extractToolCalls(e){return e.filter(s=>s.type==="tool.invocation"&&s.data?.tool).map(s=>s.data.tool)}};it.exports=he});var ct=b((yn,lt)=>{var ye=de(),Se=me(),we=ge(),_e=class{constructor(){this.parsers=[new ye,new Se,new we],this.parserMap={copilot:new ye,claude:new Se,"pi-mono":new we}}getParser(e){if(typeof e=="string")return this.parserMap[e]||null;let s=e;for(let t of this.parsers)if(t.canParse(s))return t;return null}parse(e){let s=this.getParser(e);return s?s.parse(e):null}getParserType(e){let s=this.getParser(e);return s?s instanceof ye?"copilot":s instanceof Se?"claude":s instanceof we?"pi-mono":"unknown":null}};lt.exports=_e});var Ie=b((Sn,ut)=>{var ws=z(),_s=de(),Is=me(),Ts=ge(),Es=at(),Cs=ct();ut.exports={BaseSessionParser:ws,CopilotSessionParser:_s,ClaudeSessionParser:Is,PiMonoParser:Ts,VsCodeParser:Es,ParserFactory:Cs}});var Ee=b((wn,mt)=>{var E=require("fs").promises,S=require("path"),P=require("os"),{fileURLToPath:dt}=require("url"),F=Xe(),{fileExists:Y,countLines:V,parseYAML:bs,getSessionMetadataOptimized:pt,shouldSkipEntry:te}=tt(),{ParserFactory:js}=Ie();function vs(){let p;switch(P.platform()){case"win32":p=S.join(process.env.APPDATA||S.join(P.homedir(),"AppData","Roaming"));break;case"darwin":p=S.join(P.homedir(),"Library","Application Support");break;case"linux":p=S.join(P.homedir(),".config");break;default:p=S.join(P.homedir(),".config")}return[S.join(p,"Code","User","workspaceStorage"),S.join(p,"Code - Insiders","User","workspaceStorage")]}var Te=class{constructor(e){typeof e=="string"?this.sources=[{type:"copilot",dir:e}]:Array.isArray(e)?this.sources=e:this.sources=[{type:"copilot",dir:process.env.COPILOT_SESSION_DIR||process.env.SESSION_DIR||S.join(P.homedir(),".copilot","session-state")},{type:"claude",dir:process.env.CLAUDE_SESSION_DIR||S.join(P.homedir(),".claude","projects")},{type:"pi-mono",dir:process.env.PI_MONO_SESSION_DIR||S.join(P.homedir(),".pi","agent","sessions")},{type:"vscode",...process.env.VSCODE_WORKSPACE_STORAGE_DIR?{dir:process.env.VSCODE_WORKSPACE_STORAGE_DIR}:(()=>{let s=vs();return{dir:s[0],dirCandidates:s}})()}],this.parserFactory=new js,this._cache=new Map,this._cacheTTL=60*1e3,this._pendingScans=new Map}invalidateCache(e=null){e?(this._cache.delete(e),this._cache.delete(null)):this._cache.clear()}async findAll(e=null){let s=e||"__all__",t=this._cache.get(s);if(t&&Date.now()-t.timestamp<this._cacheTTL)return t.data;if(this._pendingScans.has(s))return this._pendingScans.get(s);let n=this._doFindAll(e).then(o=>(this._cache.set(s,{data:o,timestamp:Date.now()}),this._pendingScans.delete(s),o)).catch(o=>{throw this._pendingScans.delete(s),o});return this._pendingScans.set(s,n),n}async _doFindAll(e=null){let s=[],t=e?this.sources.filter(n=>n.type===e):this.sources;for(let n of t)try{let o=await this._scanSource(n);s.push(...o)}catch(o){console.error(`Error reading ${n.type} sessions from ${n.dir}:`,o.message)}return this._sortByUpdatedAt(this._deduplicateSessions(s))}_deduplicateSessions(e){let s=new Map;for(let t of e){let n=s.get(t.id);(!n||t.updatedAt&&n.updatedAt&&new Date(t.updatedAt)>new Date(n.updatedAt))&&s.set(t.id,t)}return Array.from(s.values())}async _resolveSourceDir(e){if(!e.dirCandidates)return e.dir;for(let s of e.dirCandidates)try{return await E.access(s),e.dir=s,s}catch{}return null}async _scanSource(e){if(e.dirCandidates&&!await this._resolveSourceDir(e))return console.warn(`No ${e.type} directory found (tried: ${e.dirCandidates.join(", ")})`),[];try{await E.access(e.dir)}catch{return console.warn(`Source directory not found: ${e.dir}`),[]}let t=(await E.readdir(e.dir)).filter(o=>!te(o)).map(async o=>{let r=S.join(e.dir,o),i=await E.stat(r);if(e.type==="copilot"){if(i.isDirectory())return this._createDirectorySession(o,r,i,"copilot");if(o.endsWith(".jsonl"))return this._createFileSession(o,r,i,"copilot")}else if(e.type==="claude"){if(i.isDirectory())return this._scanClaudeProjectDir(r,o)}else if(e.type==="pi-mono"){if(i.isDirectory())return this._scanPiMonoDir(r,o)}else if(e.type==="vscode"&&i.isDirectory())return this._scanVsCodeWorkspaceDir(r);return null});return(await Promise.allSettled(t)).filter(o=>o.status==="fulfilled"&&o.value!==null&&o.value!==void 0).map(o=>o.value).flat()}async _scanClaudeProjectDir(e,s){try{let t=await E.readdir(e),n=[];for(let o of t){if(te(o))continue;let r=S.join(e,o),i=await E.stat(r);if(i.isFile()&&o.endsWith(".jsonl")){let a=await this._createClaudeSession(o,r,i,s);a&&n.push(a)}if(i.isDirectory()){let a=S.join(r,"subagents");try{if((await E.stat(a)).isDirectory()){let c=await this._createClaudeSubagentsSession(o,r,i,s);c&&n.push(c)}}catch{}}}return n}catch(t){return console.error(`Error scanning Claude project dir ${e}:`,t.message),[]}}async _createClaudeSession(e,s,t,n){let o=e.replace(".jsonl",""),r=await V(s);console.log(`[DEBUG] _createClaudeSession: ${e}, events: ${r}`);try{let l=(await E.readFile(s,"utf-8")).trim().split(`
7
+ `).filter(w=>w.trim()).map(w=>{try{return JSON.parse(w)}catch{return null}}).filter(w=>w!==null);console.log(`[DEBUG] Parsed ${l.length} events from ${e}`);let c=l.some(w=>w.type==="assistant"||w.type==="user"),d=l.some(w=>w.type==="assistant.message"||w.type==="user.message");if(console.log(`[DEBUG] ${e}: hasClaudeCoreEvents=${c}, hasCopilotCoreEvents=${d}`),!c&&d)return console.warn(`File ${s} contains only Copilot core events, skipping as Claude session`),null;if(!c)return console.warn(`File ${s} has no Claude core events (assistant/user), skipping`),null;if(console.log(`[DEBUG] ${e} passed validation, creating session...`),this.parserFactory.getParserType(l)!=="claude")return null;let m=this.parserFactory.parse(l),f=m.metadata||{},g=n.replace(/^-/,"/").replace(/-/g,"/");return new F(o,"file",{source:"claude",filePath:s,directory:S.dirname(s),workspace:{summary:f.model?`Claude Code session (${f.model})`:"Claude Code session",cwd:f.cwd||g},createdAt:f.startTime||t.birthtime,updatedAt:t.mtime,summary:m.turns[0]?.userMessage?.content?.substring(0,100)||"No summary",hasEvents:r>0,eventCount:r,duration:null,isImported:!1,hasInsight:!1,copilotVersion:f.version,selectedModel:f.model,sessionStatus:"completed"})}catch(i){return console.error(`Error creating Claude session ${o}:`,i.message),null}}async findById(e){if(te(e))return null;for(let s of this.sources){let t=null;if(s.type==="copilot")t=await this._findCopilotSession(e,s.dir);else if(s.type==="claude")t=await this._findClaudeSession(e,s.dir);else if(s.type==="pi-mono")t=await this._findPiMonoSession(e,s.dir);else if(s.type==="vscode"){let n=s.dirCandidates?await this._resolveSourceDir(s):s.dir;n&&(t=await this._findVsCodeSession(e,n))}if(t)return t}return null}async _findCopilotSession(e,s){try{let t=S.join(s,e),n=await E.stat(t);if(n.isDirectory())return await this._createDirectorySession(e,t,n,"copilot")}catch{}try{let t=S.join(s,`${e}.jsonl`),n=await E.stat(t);if(n.isFile())return await this._createFileSession(`${e}.jsonl`,t,n,"copilot")}catch{}return null}async _findClaudeSession(e,s){try{let t=await E.readdir(s);for(let n of t){let o=S.join(s,n),r=S.join(o,`${e}.jsonl`);try{let a=await E.stat(r);if(a.isFile()){console.log(`[DEBUG] Found file: ${r}`);let l=await this._createClaudeSession(`${e}.jsonl`,r,a,n);if(l)return console.log("[DEBUG] File validated as Claude session, returning"),l;console.log("[DEBUG] File validation failed, checking directory...")}}catch(a){console.log(`[DEBUG] File not found: ${r}, error: ${a.message}`)}let i=S.join(o,e);console.log(`[DEBUG] Checking directory: ${i}`);try{let a=await E.stat(i);if(a.isDirectory()){console.log("[DEBUG] Directory exists, checking for subagents...");let l=S.join(i,"subagents");try{if((await E.stat(l)).isDirectory()){console.log("[DEBUG] Found subagents directory, creating session...");let d=await this._createClaudeSubagentsSession(e,i,a,n);return console.log("[DEBUG] Created subagents session:",d?"SUCCESS":"FAILED"),d}}catch(c){console.log(`[DEBUG] No subagents directory: ${c.message}`)}}}catch(a){console.log(`[DEBUG] Directory not found: ${a.message}`)}}}catch(t){console.error(`[DEBUG] Projects dir error: ${t.message}`)}return console.log(`[DEBUG] Session ${e} not found in any project`),null}async _findPiMonoSession(e,s){try{let t=await E.readdir(s);for(let n of t){let o=S.join(s,n);try{let i=(await E.readdir(o)).find(a=>a.includes(`_${e}.jsonl`));if(i){let a=S.join(o,i),l=await E.stat(a),c=await this._readFirstLine(a);if(c){let d=JSON.parse(c);if(d.type==="session"){let u=n.replace(/^--/,"").replace(/--$/,""),m=await V(a);return new F(e,"directory",{source:"pi-mono",filePath:a,directory:o,workspace:{cwd:d.cwd||u},createdAt:new Date(d.timestamp),updatedAt:new Date(l.mtime),summary:`Pi-Mono: ${S.basename(d.cwd||u)}`,hasEvents:m>0,eventCount:m,duration:null,sessionStatus:"completed"})}}}}catch{}}}catch(t){console.error(`Error searching Pi-Mono sessions: ${t.message}`)}return null}async _findVsCodeSession(e,s){try{let t=await E.readdir(s),n=[];for(let o of t){let r=S.join(s,o,"chatSessions");try{let a=(await E.readdir(r)).find(l=>l===`${e}.json`||l===`${e}.jsonl`||l.replace(/\.jsonl?$/,"")===e);if(a){let l=S.join(r,a),c=await E.stat(l),d=await E.readFile(l,"utf-8"),u;if(a.endsWith(".jsonl")){if(u=this._parseVsCodeJsonl(d),!u)continue}else u=JSON.parse(d);let m=u.requests||[];if(m.length===0)continue;let f=await this._resolveVsCodeWorkspacePath(S.join(s,o)),g={...c,filePath:l};n.push(this._buildVsCodeSession(e,m,u,g,o,f||S.join(s,o)))}}catch{}}if(n.length>0)return n.sort((o,r)=>(r.updatedAt?.getTime?.()??0)-(o.updatedAt?.getTime?.()??0)),n[0]}catch(t){console.error(`[VSCode findById] Error searching VSCode sessions: ${t.message}`,t.stack)}return console.log(`[VSCode findById] Session ${e} not found in vscode sessions`),null}async _createClaudeSubagentsSession(e,s,t,n){try{let o=S.join(s,"subagents"),i=(await E.readdir(o)).filter(g=>g.startsWith("agent-")&&g.endsWith(".jsonl"));if(i.length===0)return null;let a=0;for(let g of i){let w=S.join(o,g);a+=await V(w)}let l=S.join(o,i[0]),d=(await E.readFile(l,"utf-8")).trim().split(`
8
+ `).filter(g=>g.trim()),u=d.length>0?JSON.parse(d[0]):null,m={cwd:u?.cwd||n,version:u?.version,model:u?.message?.model,startTime:u?.timestamp},f=n.replace(/^-/,"/").replace(/-/g,"/");return new F(e,"directory",{source:"claude",directory:s,workspace:{summary:`Claude session (${i.length} sub-agents)`,cwd:m.cwd||f},createdAt:m.startTime||t.birthtime,updatedAt:t.mtime,summary:u?.message?.content?.substring(0,100)||"Sub-agent tasks",hasEvents:a>0,eventCount:a,duration:null,isImported:!1,hasInsight:!1,copilotVersion:m.version,selectedModel:m.model,sessionStatus:"completed"})}catch(o){return console.error(`Error creating Claude subagents session ${e}:`,o.message),null}}async _createDirectorySession(e,s,t,n="copilot"){let o=S.join(s,"workspace.yaml"),r=S.join(s,"events.jsonl"),i=S.join(s,".imported"),a=S.join(s,`${e}.agent-review.md`),l=await Y(o)?await bs(o):{summary:e,repo:"unknown"},c=await Y(r)?await V(r):0,d=await Y(i),u=await Y(a),m=null,f=null,g=null,w="completed";if(await Y(r)){let y=await pt(r);if(m=y.duration,f=y.copilotVersion,g=y.selectedModel,w=this._computeSessionStatus(y),!l.summary&&y.firstUserMessage&&(l.summary=y.firstUserMessage),y.lastEventTime){let j=new Date(y.lastEventTime).getTime(),v=new Date(t.mtime).getTime();j>v&&(t={...t,mtime:new Date(j)})}}let _=F.fromDirectory(s,e,t,l,c,m,d,u,f,g,w);return _.source=n,_}async _createFileSession(e,s,t,n="copilot"){let o=e.replace(".jsonl",""),r=await V(s),i=await pt(s),a=this._computeSessionStatus(i),l=F.fromFile(s,o,t,r,i.firstUserMessage,i.duration,i.copilotVersion,i.selectedModel,a);return l.source=n,l}_computeSessionStatus(e){return e.hasSessionEnd?"completed":e.lastEventTime!==null&&e.lastEventTime!==void 0&&Date.now()-e.lastEventTime<3e5?"wip":"completed"}async _scanPiMonoDir(e,s){try{console.log(`[PI-MONO] Scanning directory: ${e}`);let n=(await E.readdir(e)).filter(r=>r.endsWith(".jsonl"));if(console.log(`[PI-MONO] Found ${n.length} .jsonl files in ${s}`),n.length===0)return[];let o=[];n.sort().reverse();for(let r of n){let i=S.join(e,r),a=await E.stat(i),l=r.match(/_([a-f0-9-]+)\.jsonl$/);if(!l){console.log(`[PI-MONO] Skipping ${r}: no UUID match`);continue}let c=l[1],d=await this._readFirstLine(i);if(!d){console.log(`[PI-MONO] Skipping ${r}: no first line`);continue}try{let u=JSON.parse(d);if(u.type!=="session"){console.log(`[PI-MONO] Skipping ${r}: first event type is ${u.type}, not 'session'`);continue}let m=await V(i),f=s.replace(/^--/,"").replace(/--$/,""),g=new F(c,"directory",{source:"pi-mono",directory:e,workspace:{cwd:u.cwd||f},createdAt:new Date(u.timestamp),updatedAt:new Date(a.mtime),summary:`Pi-Mono: ${S.basename(u.cwd||f)}`,hasEvents:m>0,eventCount:m,duration:null,sessionStatus:"completed"});console.log(`[PI-MONO] Created session: ${c} from ${r}`),o.push(g)}catch(u){console.error(`[PI-MONO] Error parsing session ${r}:`,u.message)}}return console.log(`[PI-MONO] Total sessions found in ${s}: ${o.length}`),o}catch(t){return console.error(`[PI-MONO] Error scanning dir ${e}:`,t.message),[]}}_parseVsCodeJsonl(e){let s=e.split(`
9
+ `).filter(o=>o.trim());if(s.length===0)return null;let t=JSON.parse(s[0]),n=t.v||t;for(let o=1;o<s.length;o++)try{let r=JSON.parse(s[o]),i=r.k||[],a=r.v;if(r.kind===2&&Array.isArray(a)){let l=n;for(let d=0;d<i.length-1;d++){let u=i[d];typeof u=="number"||l[u]||(l[u]={}),l=l[u]}let c=i[i.length-1];if(c!==void 0){l[c]||(l[c]=[]);let d=l[c],u=r.i;u==null?d.push(...a):d.splice(u,0,...a)}else{let d=r.i;d==null&&n.push?.(...a)}}else if(r.kind===1&&i.length>0){let l=n;for(let d=0;d<i.length-1;d++){let u=i[d];typeof u=="number"||l[u]||(l[u]={}),l=l[u]}let c=i[i.length-1];l[c]=a}}catch{}return n}async _resolveVsCodeWorkspacePath(e){try{let s=S.join(e,"workspace.json"),t=await E.readFile(s,"utf-8"),n=JSON.parse(t);if(n.folder)return dt(n.folder);if(n.workspace){let o=dt(n.workspace);try{let r=await E.readFile(o,"utf-8"),i=JSON.parse(r);if(Array.isArray(i.folders)&&i.folders.length>0){let a=S.dirname(o);return S.resolve(a,i.folders[0].path)}}catch{}}}catch{}return null}async _scanVsCodeWorkspaceDir(e){let s=S.join(e,"chatSessions");try{await E.access(s)}catch{return[]}let t=S.basename(e),n=await this._resolveVsCodeWorkspacePath(e),r=(await E.readdir(s)).filter(a=>(a.endsWith(".json")||a.endsWith(".jsonl"))&&!te(a));if(r.length===0)return[];let i=[];for(let a of r){let l=S.join(s,a);try{let c=await E.stat(l),d=await E.readFile(l,"utf-8"),u;if(a.endsWith(".jsonl")){if(u=this._parseVsCodeJsonl(d),!u)continue}else u=JSON.parse(d);let m=u.sessionId||S.basename(a).replace(/\.jsonl?$/,""),f=u.requests||[];if(f.length===0)continue;let g={...c,filePath:l},w=this._buildVsCodeSession(m,f,u,g,t,n||e);i.push(w)}catch{}}return i}_buildVsCodeSession(e,s,t,n,o,r){let i=s[0],a=s[s.length-1],l=t.creationDate?new Date(t.creationDate):i.timestamp?new Date(i.timestamp):n.birthtime,c=a.timestamp?new Date(a.timestamp):null,d=t.lastMessageDate?new Date(t.lastMessageDate):c||n.mtime,m=this._extractLastTerminalTimestamp(s)||c||d,f=Date.now()-m.getTime()<900*1e3,g=this._extractVsCodeUserText(i.message),w=s.reduce((_,y)=>_+(y.response||[]).filter(j=>j.kind==="toolInvocationSerialized").length,0);return new F(e,"file",{source:"vscode",filePath:n.filePath,workspaceHash:o,createdAt:l,updatedAt:m,summary:g?g.slice(0,120):`VSCode chat (${s.length} requests)`,hasEvents:!0,eventCount:s.reduce((_,y)=>_+(y.response||[]).length,0)+s.length*2+1,duration:m.getTime()-l.getTime(),sessionStatus:f?"wip":"completed",selectedModel:i.modelId||null,agentId:i.agent?.id||"vscode-copilot",toolCount:w,copilotVersion:i.agent?.extensionVersion||null,workspace:{cwd:r}})}_extractLastTerminalTimestamp(e){let s=0;function t(n){if(!(!n||typeof n!="object")){if(Array.isArray(n)){n.forEach(t);return}if(n.terminalCommandState&&typeof n.terminalCommandState.timestamp=="number"){let o=n.terminalCommandState.timestamp;o>1e12&&o<9999999999999&&o>s&&(s=o)}for(let o of Object.values(n))t(o)}}for(let n of e)t(n.response);return s>0?new Date(s):null}_extractVsCodeUserText(e){return e?typeof e.text=="string"?e.text:Array.isArray(e.parts)?e.parts.filter(s=>s.kind==="text").map(s=>s.text||"").join(""):"":""}async _readFirstLine(e){let s=require("fs"),t=require("readline");return new Promise((n,o)=>{let r=s.createReadStream(e,{encoding:"utf-8"}),i=t.createInterface({input:r,crlfDelay:1/0}),a=!1;i.on("line",l=>{a||(a=!0,i.close(),n(l.trim()))}),i.on("close",()=>{a||n(null)}),i.on("error",l=>{a||(a=!0,o(l))}),r.on("error",l=>{a||(a=!0,i.close(),o(l))})})}_sortByUpdatedAt(e){return e.sort((s,t)=>new Date(t.updatedAt)-new Date(s.updatedAt))}};mt.exports=Te});var gt=b((_n,ft)=>{var Ce=class{normalizeEvents(e,s){return Array.isArray(e)?e.filter(t=>!t._isToolResultWrapper).map(t=>this.normalizeEvent(t,s)):(console.warn("[EventNormalizer] normalizeEvents: events is not an array",typeof e),[])}normalizeEvent(e,s){return!e||typeof e!="object"?(console.warn("[EventNormalizer] normalizeEvent: invalid event",e),e):this._isAssistantMessage(e)?this._normalizeAssistantMessage(e,s):this._isTimelineEvent(e)?this._normalizeTimelineEvent(e,s):e}_isAssistantMessage(e){return e.data?.tools&&Array.isArray(e.data.tools)&&e.data.tools.length>0?!0:e.type==="assistant.message"||e.type==="assistant"||e.type==="user.message"||e.type==="user"}_isTimelineEvent(e){return e.type?.startsWith("tool.")||e.type?.startsWith("subagent.")}_normalizeAssistantMessage(e,s){let t={...e};return e.data?.tools&&Array.isArray(e.data.tools)&&(t.data={...e.data,tools:e.data.tools.filter(n=>n.type!=="tool_result").map(n=>this._normalizeToolCall(n,s,e.timestamp))}),t}_normalizeToolCall(e,s,t){if(e.type==="tool_use"){let n=this._computeStatus(e),o=e._startTime||t,r=e._matched?e._endTime||t:null;return{type:"tool_use",id:e.id,name:e.name,startTime:o,endTime:r,status:n,input:e.input||{},result:e.result||null,error:e.error||null,metadata:{source:s,matched:e._matched,duration:this._computeDuration(o,r)}}}if(e.name&&e.status){let n=t,o=e.status==="success"?"completed":e.status,r=o==="completed"||o==="error"?t:null;return{id:e.id||this._generateToolId(),name:e.name,startTime:n,endTime:r,status:o,input:e.input||{},result:e.isError?null:e.result||null,error:e.isError?e.result:null,metadata:{source:s,duration:this._computeDuration(n,r)}}}return console.warn("[EventNormalizer] Unknown tool format, applying fallback normalization",e),{id:e.id||this._generateToolId(),name:e.name||"unknown",startTime:t,endTime:null,status:"running",input:e.input||{},result:null,error:null,metadata:{source:s,fallback:!0}}}_computeStatus(e){return e.error?"error":e.result!==void 0&&e.result!==null&&e.result!==""?"completed":e._matched===!1?"running":e._matched?"completed":"running"}_computeDuration(e,s){if(!(!e||!s))try{let t=new Date(e),n=new Date(s);if(isNaN(t.getTime())||isNaN(n.getTime()))return;let o=n.getTime()-t.getTime();return o>=0?o:void 0}catch{return}}_generateToolId(){return`tool-${Date.now()}-${Math.random().toString(36).substr(2,9)}`}_normalizeTimelineEvent(e){return e.type==="tool.execution_start"||e.type==="tool.execution_complete"?{...e,data:{...e.data,toolCallId:e.data?.toolCallId||e.data?.id,toolName:e.data?.toolName||e.data?.tool||e.data?.name,...e.data}}:(e.type?.startsWith("subagent."),e)}};ft.exports=Ce});var je=b((In,wt)=>{var D=require("fs"),x=require("path"),ht=require("readline"),{isValidSessionId:yt,buildMetadata:xs}=U(),St=Ee(),As=gt(),be=class{constructor(e){e?(this.SESSION_DIR=e,this.sessionRepository=new St(e)):this.sessionRepository=new St,this.eventNormalizer=new As}async getAllSessions(e=null){return(await this.sessionRepository.findAll(e)).map(t=>t.toJSON())}async getPaginatedSessions(e=1,s=20,t=null){let o=(await this.sessionRepository.findAll(t)).map(l=>l.toJSON()),r=(e-1)*s,i=r+s;return{sessions:o.slice(r,i),totalSessions:o.length,currentPage:e,totalPages:Math.ceil(o.length/s),hasNextPage:i<o.length,hasPrevPage:e>1}}async getSessionById(e){return yt(e)?(await this.getAllSessions()).find(t=>t.id===e):null}async getSessionEvents(e,s=null){if(!yt(e))return s?{events:[],total:0}:[];let t=await this.sessionRepository.findById(e);if(!t)return s?{events:[],total:0}:[];let n;if(t.source==="copilot")if(this.SESSION_DIR){let r=x.join(this.SESSION_DIR,e);try{(await D.promises.stat(r)).isDirectory()?n=x.join(r,"events.jsonl"):n=x.join(this.SESSION_DIR,`${e}.jsonl`)}catch{n=x.join(this.SESSION_DIR,`${e}.jsonl`)}}else{let r=this.sessionRepository.sources.find(a=>a.type==="copilot");if(!r)return[];let i=x.join(r.dir,e);try{(await D.promises.stat(i)).isDirectory()?n=x.join(i,"events.jsonl"):n=x.join(r.dir,`${e}.jsonl`)}catch{n=x.join(r.dir,`${e}.jsonl`)}}else if(t.source==="claude"){let r=this.sessionRepository.sources.find(i=>i.type==="claude");if(!r)return[];if(t.type!=="directory")try{let i=await D.promises.readdir(r.dir);for(let a of i){let l=x.join(r.dir,a,`${e}.jsonl`);try{await D.promises.access(l),n=l;break}catch{}}}catch(i){return console.error("Error searching Claude projects:",i),[]}}else if(t.source==="pi-mono"){let r=this.sessionRepository.sources.find(i=>i.type==="pi-mono");if(!r)return[];try{let i=await D.promises.readdir(r.dir);for(let a of i){let l=x.join(r.dir,a);try{let d=(await D.promises.readdir(l)).find(u=>u.includes(`_${e}.jsonl`));if(d){n=x.join(l,d);break}}catch{}}}catch(i){return console.error("Error searching Pi-Mono sessions:",i),[]}}else if(t.source==="vscode"){let{VsCodeParser:r}=Ie(),i=new r;try{let a=await D.promises.readFile(t.filePath,"utf-8"),c=a.trim().split(`
10
+ `).filter(m=>m.trim()).map(m=>{try{return JSON.parse(m)}catch{return null}}).filter(m=>m!==null);if(c.length===0)return[];let d;if(i.canParse(c))d=i.parseJsonl(c);else{let m=JSON.parse(a);d=i.parseVsCode(m)}let u=this._expandVsCodeEvents(d.allEvents);if(u.length>0)try{let m=await D.promises.stat(t.filePath),f=new Date(m.mtime).toISOString(),g=u[u.length-1];if(g&&g.timestamp){let w=new Date(g.timestamp).getTime(),y=(new Date(f).getTime()-w)/1e3;y>10&&(g.timestamp=f,console.log(`[VSCode] Updated session ${t.id} end time to file mtime (${y.toFixed(0)}s difference)`))}}catch(m){console.error("[VSCode] Error getting file mtime:",m)}return u=this._expandVsCodeToTimelineFormat(u),u}catch(a){return console.error("Error reading VSCode session:",a),[]}}let o=[];if(n)try{await D.promises.access(n);let r=D.createReadStream(n,{encoding:"utf-8"}),i=ht.createInterface({input:r,crlfDelay:1/0}),a=0,l=[];for await(let d of i){let u=d.trim();if(u)try{let m=JSON.parse(u);m._fileIndex=a,l.push(m)}catch(m){console.error(`Error parsing line ${a+1}:`,m.message)}a++}o=l,o.sort((d,u)=>{let m=d.timestamp?new Date(d.timestamp).getTime():0,f=u.timestamp?new Date(u.timestamp).getTime():0;return m!==f?m-f:d._fileIndex-u._fileIndex}),o=o.map(d=>this._normalizeEvent(d,t.source)),t.source==="copilot"?this._matchCopilotToolCalls(o):t.source==="claude"&&this._matchClaudeToolResults(o)}catch(r){console.error("Error reading main events file:",r)}if(await this._mergeSubAgentEvents(o,n,e,t.source),t.source==="copilot"?(this._matchCopilotToolCalls(o),o=this._expandCopilotToTimelineFormat(o)):t.source==="claude"?(this._matchClaudeToolResults(o),o=this._expandClaudeToTimelineFormat(o)):t.source==="pi-mono"&&this._mergePiMonoToolResults(o),o=o.filter(r=>r.timestamp||r.snapshot?.timestamp?!0:(console.warn("[SessionService] Filtered event without timestamp:",r.type,r.id||r._fileIndex),!1)),o.forEach(r=>{r._fileIndex===999999&&r.timestamp&&delete r._fileIndex}),o=this.eventNormalizer.normalizeEvents(o,t.source),s&&typeof s.limit=="number"&&typeof s.offset=="number"){let r=o.length;return{events:o.slice(s.offset,s.offset+s.limit),total:r}}return o}async _mergeSubAgentEvents(e,s,t,n){let o;if(n==="claude"){let r=this.sessionRepository.sources.find(i=>i.type==="claude");if(!r)return;try{let i=await D.promises.readdir(r.dir);for(let a of i){let l=x.join(r.dir,a,t,"subagents");try{if((await D.promises.stat(l)).isDirectory()){o=l;break}}catch{}}}catch(i){console.error("Error searching Claude subagents:",i);return}}else if(n==="copilot"&&s){let r=x.dirname(s);x.basename(s)==="events.jsonl"?o=x.join(r,"subagents"):o=x.join(r,t,"subagents")}if(o){try{if(!(await D.promises.stat(o)).isDirectory())return}catch{return}try{let i=(await D.promises.readdir(o)).filter(a=>a.startsWith("agent-")&&a.endsWith(".jsonl"));if(i.length===0)return;for(let a of i){let l=a.replace(".jsonl",""),c=x.join(o,a);try{let d=D.createReadStream(c,{encoding:"utf-8"}),u=ht.createInterface({input:d,crlfDelay:1/0}),m=[];for await(let A of u){let $=A.trim();$&&m.push($)}if(m.length===0)continue;let f=l.replace("agent-",""),g=f.toUpperCase(),w=`Sub-agent ${l}`;try{let A=JSON.parse(m[0]);if(A.agentId&&(f=A.agentId,g=`agent-${A.agentId}`),A.message?.content){let $=typeof A.message.content=="string"?A.message.content:JSON.stringify(A.message.content);w=$.length>100?$.slice(0,100)+"...":$}}catch{}let _=m.map((A,$)=>{try{let J=JSON.parse(A);return J._fileIndex=1e6+$,J._subagent={id:l,name:f},J}catch(J){return console.error(`Error parsing sub-agent ${l} line ${$+1}:`,J.message),null}}).filter(A=>A!==null);if(_.length===0)continue;let y=_.map(A=>this._normalizeEvent(A,n)),j=y[0],v=y[y.length-1],q=j.timestamp||new Date().toISOString(),oe=v.timestamp||new Date().toISOString(),re={type:"subagent.started",id:`${l}-start`,timestamp:q,_fileIndex:j._fileIndex-1,_subagent:{id:l,name:f},data:{toolCallId:l,agentName:f,agentDisplayName:g,agentDescription:w}},Le={type:"subagent.completed",id:`${l}-end`,timestamp:oe,_fileIndex:v._fileIndex+1,_subagent:{id:l,name:f},data:{toolCallId:l,result:`Sub-agent ${g} completed`}};e.push(re,...y,Le)}catch(d){console.error(`Error reading sub-agent ${l}:`,d)}}e.sort((a,l)=>{let c=a.timestamp?new Date(a.timestamp).getTime():0,d=l.timestamp?new Date(l.timestamp).getTime():0;return c!==d?c-d:a._fileIndex-l._fileIndex})}catch(r){console.error("Error processing sub-agents:",r)}}}_matchClaudeToolResults(e){let s=new Map;e.forEach(t=>{t.data?.tools&&t.data.tools.forEach(n=>{n.type==="tool_result"&&(n.tool_use_id?s.set(n.tool_use_id,n):console.warn("[sessionService] tool_result missing tool_use_id:",n))})}),e.forEach(t=>{t.type==="user"&&Array.isArray(t.message?.content)&&t.message.content.length>0&&t.message.content.every(o=>o?.type==="tool_result")&&(t._isToolResultWrapper=!0)}),e.forEach(t=>{t.data?.tools&&(t.data.tools=t.data.tools.map(n=>{if(n.type==="tool_use"){let o=s.get(n.id);return o?{...n,result:o.content,_matched:!0}:{...n,_matched:!1}}return n}),t.type==="assistant"||t.type==="assistant.message"?t.data.tools=t.data.tools.filter(n=>n.type!=="tool_result"):(t.type==="user"||t.type==="user.message")&&t.data.tools.length>0&&t.data.tools.every(o=>o.type==="tool_result")&&(t._isToolResultWrapper=!0))})}_mergePiMonoToolResults(e){let s=new Set;e.forEach(n=>{if(n.type==="assistant.message"&&n.data.tools&&n.data.tools.length>0){let o=n.data.tools,r=[],i=n.id,a=!0;for(;a&&r.length<o.length;){a=!1;for(let l of e)if(l.type==="message"&&l.data.role==="toolResult"&&l.parentId===i&&!r.includes(l)){r.push(l),i=l.id,a=!0;break}}r.forEach((l,c)=>{if(c<o.length){let d=o[c];d.result=l.data.result,d.resultId=l.id,d.status="completed",s.add(l.id)}})}});let t=e.length;for(let n=e.length-1;n>=0;n--)e[n].type==="message"&&e[n].data.role==="toolResult"&&s.has(e[n].id)&&e.splice(n,1);s.size>0&&console.log(`[PI-MONO] Merged ${s.size} toolResult events into assistant messages (${t} \u2192 ${e.length} events)`)}_matchPiMonoToolResults_OLD(e){let s=new Set;e.forEach(n=>{if(n.type==="assistant.message"&&n.data.tools&&n.data.tools.length>0){let o=n.data.tools,r=[],i=n.id,a=!0;for(;a&&r.length<o.length;){a=!1;for(let l of e)if(l.type==="tool.result"&&l.parentId===i&&!r.includes(l)){r.push(l),i=l.id,a=!0;break}}r.forEach((l,c)=>{if(c<o.length){let d=o[c];d.status="completed",d._matched=!0,d.result=l.data.result,d.resultId=l.id,s.add(l.id)}})}});let t=e.length;for(let n=e.length-1;n>=0;n--)e[n].type==="tool.result"&&s.has(e[n].id)&&e.splice(n,1);s.size>0&&console.log(`[PI-MONO] Removed ${s.size} matched tool.result events (${t} \u2192 ${e.length} events)`)}_matchCopilotToolCalls(e){let s=new Map;e.forEach(t=>{if(t.type==="tool.execution_start"){let n=t.data?.toolCallId;n&&s.set(n,{name:t.data.toolName,input:t.data.arguments||{},start:t})}else if(t.type==="tool.execution_complete"){let n=t.data?.toolCallId;if(n)if(s.has(n)){let o=s.get(n);o.complete=t,o.result=t.data?.result,o.status=t.data?.error?"error":"completed",o.error=t.data?.error}else console.warn(`[sessionService] Orphaned tool.execution_complete for toolCallId=${n}`),s.set(n,{name:t.data.toolName||"unknown",input:{},start:null,complete:t,result:t.data?.result,status:t.data?.error?"error":"completed",error:t.data?.error})}}),e.forEach(t=>{if(t.type==="assistant.message"&&t.data?.toolRequests){let n=[];t.data.toolRequests.forEach(o=>{let r=o.toolCallId;if(s.has(r)){let i=s.get(r);n.push({type:"tool_use",id:r,name:o.name||i.name,input:o.arguments||i.input,result:i.result,status:i.status||"running",error:i.error,_matched:!!i.complete,_startTime:i.start?.timestamp,_endTime:i.complete?.timestamp})}else n.push({type:"tool_use",id:r,name:o.name,input:o.arguments||{},status:"running",_matched:!1})}),n.length>0&&(t.data.tools=n)}})}_generateBadgeInfo(e){let s=e.type,t=e.data||{};if(s==="message"&&t.role==="toolResult"){e.data.badgeLabel="TOOL RESULT",e.data.badgeClass="badge-tool";return}if(s==="session.model_change"||s==="model.change"){e.data.badgeLabel="MODEL CHANGE",e.data.badgeClass="badge-session";return}if(s==="session.truncation"){e.data.badgeLabel="TRUNCATION",e.data.badgeClass="badge-truncation";return}if(s==="session.compaction_start"||s==="session.compaction_complete"||s==="compaction"){e.data.badgeLabel="COMPACTION",e.data.badgeClass="badge-compaction";return}if(s==="thinking.change"){e.data.badgeLabel="THINKING",e.data.badgeClass="badge-session";return}if(s==="system.notification"){e.data.badgeLabel="SYSTEM",e.data.badgeClass="badge-system";return}let o=(s||"").split(".")[0]||"unknown",i={user:{label:"USER",class:"badge-user"},assistant:{label:"ASSISTANT",class:"badge-assistant"},reasoning:{label:"REASONING",class:"badge-reasoning"},turn:{label:"TURN",class:"badge-turn"},tool:{label:"TOOL",class:"badge-tool"},subagent:{label:"SUBAGENT",class:"badge-subagent"},skill:{label:"SKILL",class:"badge-skill"},session:{label:"SESSION",class:"badge-session"},error:{label:"ERROR",class:"badge-error"},abort:{label:"ABORT",class:"badge-error"}}[o]||{label:o.toUpperCase(),class:"badge-info"};e.data.badgeLabel=i.label,e.data.badgeClass=i.class}_normalizeEvent(e,s){let t={...e};if(t.data=t.data||{},s==="copilot"){if(e.type==="user.message"&&e.data?.source==="system"){t.type="system.notification";let n=e.data.content||e.data.message||"",o=n.match(/<system_notification>([\s\S]*?)<\/system_notification>/);return t.data.message=o?o[1].trim():n.trim(),this._generateBadgeInfo(t),t}if(e.type==="request"){if(t.type="user",e.payload?.messages&&Array.isArray(e.payload.messages)){let n=e.payload.messages.find(o=>o.role==="user");n&&(t.message={role:"user",content:n.content||""})}}else if(e.type==="response"&&(t.type="assistant",e.payload?.content&&Array.isArray(e.payload.content))){let n=e.payload.content.filter(o=>o.type==="text");n.length>0&&(t.message={role:"assistant",content:n.map(o=>o.text).join(`
11
11
  `)})}return e.type==="assistant.message"&&e.data?.content&&e.data.content.trim()&&(t.data.message=e.data.content),this._generateBadgeInfo(t),t}if(s==="pi-mono"){if(e.type==="message"){let{message:n}=e;if(n.role==="user"?t.type="user.message":n.role==="assistant"?t.type="assistant.message":n.role==="toolResult"&&(t.type="message"),t.data.role=n.role,Array.isArray(n.content)){let o=n.content.filter(r=>r.type==="text");if(o.length>0&&(t.data.message=o.map(r=>r.text).join(`
12
12
  `)),n.role==="assistant"){let r=n.content.filter(i=>i.type==="toolCall");r.length>0&&(t.data.tools=r.map(i=>({type:"tool_use",id:i.id,name:i.name,input:i.arguments})))}n.role==="toolResult"&&(t.data.result=o.map(r=>r.text).join(`
13
13
  `))}n.usage&&(t.usage=n.usage)}else if(e.type==="model_change")t.type="model.change",t.data={provider:e.provider,model:e.modelId},e.provider&&e.modelId?t.data.message=`Model changed to ${e.provider}/${e.modelId}`:e.modelId&&(t.data.message=`Model changed to ${e.modelId}`);else if(e.type==="thinking_level_change")t.type="thinking.change",t.data={level:e.thinkingLevel},e.thinkingLevel&&(t.data.message=`Thinking level: ${e.thinkingLevel}`);else if(e.type==="session"){t.data={cwd:e.cwd,version:e.version};let n=[];e.cwd&&n.push(`Working directory: ${e.cwd}`),e.version&&n.push(`Session version: ${e.version}`),n.length>0&&(t.data.message=n.join(`
@@ -16,13 +16,13 @@ var b=(p,e)=>()=>(e||p((e={exports:{}}).exports,e),e.exports);var O=b((nn,We)=>{
16
16
  ${o}`}else t.data.message="No files tracked"}break;case"progress":if(e.data){let n=[];if(e.data.hookName&&n.push(`Hook: ${e.data.hookName}`),e.data.hookEvent&&n.push(`Event: ${e.data.hookEvent}`),e.data.command&&n.push(`Command: ${e.data.command}`),n.length>0&&(t.data.message=n.join(`
17
17
  `)),e.data.message?.message?.content&&Array.isArray(e.data.message.message.content)){let o=e.data.message.message.content.filter(r=>r&&typeof r=="object"&&(r.type==="tool_use"||r.type==="tool_result"));o.length>0&&(t.data.tools=o.map(r=>r.type==="tool_use"?{type:"tool_use",id:r.id,name:r.name,input:r.input}:{type:"tool_result",tool_use_id:r.tool_use_id,content:r.content}))}}break;default:e.data?.message&&!t.data.message&&(t.data.message=e.data.message)}return this._generateBadgeInfo(t),t}_extractClaudeTextContent(e){if(typeof e=="string")return e;if(Array.isArray(e)){let s=[];for(let t of e)if(t.type==="text")s.push(t.text);else if(t.type==="tool_result"){if(typeof t.content=="string")s.push(t.content);else if(Array.isArray(t.content)){let n=t.content.filter(o=>o.type==="text").map(o=>o.text).join(`
18
18
  `);n&&s.push(n)}}return s.join(`
19
- `)}return""}async getSessionWithEvents(e){let s=await this.getSessionById(e);if(!s)return null;let t=await this.getSessionEvents(e),n=js(s),o=t.find(i=>i.type==="session.start");o?.data?.selectedModel&&(n.model=o.data.selectedModel);let r=t.find(i=>i.type==="session.model_change");if(r?.data&&(n.model=r.data.newModel||r.data.model),t.length){let i=t[t.length-1];i?.timestamp&&(n.updated=i.timestamp)}if(t.length){let i=t[0];i?.timestamp&&(n.created=i.timestamp)}return{session:s,events:t,metadata:n}}async getTimeline(e){let s=await this.getSessionById(e);if(!s)return null;let t=await this.getSessionEvents(e);return s.source==="copilot"?this._buildCopilotTimeline(t,s):s.source==="claude"?this._buildClaudeTimeline(t,s):s.source==="pi-mono"?this._buildPiMonoTimeline(t,s):{turns:[],summary:{}}}_buildPiMonoTimeline(e,s){let t=[],n=0;for(let i=0;i<e.length;i++){let a=e[i];if(a.type==="user.message"){n++;let l={id:`turn-${n}`,type:"user-request",message:a.data.message||"",startTime:a.timestamp,endTime:a.timestamp,assistantTurns:[],subagents:[]},c=i+1,d=0;for(;c<e.length&&e[c].type!=="user.message";){let u=e[c];if(u.type==="assistant.message"){d++,l.endTime=u.timestamp;let m={id:`assistant-${d}`,startTime:u.timestamp,endTime:u.timestamp,tools:[]};if(u.data.tools&&Array.isArray(u.data.tools))for(let f of u.data.tools)m.tools.push({name:f.name,startTime:u.timestamp,endTime:u.timestamp,status:f.status||"completed",input:f.input,result:f.result});l.assistantTurns.push(m)}c++}t.push(l)}}let o=t.reduce((i,a)=>i+a.assistantTurns.reduce((l,c)=>l+c.tools.length,0),0),r={totalTurns:t.length,totalAssistantTurns:t.reduce((i,a)=>i+a.assistantTurns.length,0),totalTools:o,totalSubagents:0,startTime:e[0]?.timestamp,endTime:e[e.length-1]?.timestamp};return{turns:t,summary:r}}_buildCopilotTimeline(e,s){let t=[],n=null,o=0;for(let i of e)if(i.type==="assistant.turn_start")o++,n={id:`turn-${o}`,type:"assistant-turn",message:i.data.message||"",startTime:i.timestamp,endTime:null,tools:[],subagents:[]};else if(i.type==="assistant.turn_complete"&&n)n.endTime=i.timestamp,t.push(n),n=null;else if(i.type==="tool.execution_start"&&n){let a={name:i.data.tool||i.data.name,startTime:i.timestamp,endTime:null,status:"running",input:i.data.arguments||i.data.input};n.tools.push(a)}else if(i.type==="tool.execution_complete"&&n){let a=n.tools.find(l=>l.name===(i.data.tool||i.data.name)&&!l.endTime);a&&(a.endTime=i.timestamp,a.status=i.data.error||i.data.isError?"error":"completed",a.result=i.data.result||i.data.output)}n&&(n.endTime=e[e.length-1]?.timestamp,t.push(n));let r={totalTurns:t.length,totalTools:t.reduce((i,a)=>i+a.tools.length,0),totalSubagents:0,startTime:e[0]?.timestamp,endTime:e[e.length-1]?.timestamp};return{turns:t,summary:r}}_buildClaudeTimeline(e,s){return this._buildPiMonoTimeline(e,s)}_expandPiMonoToCopilotFormat(e){let s=[],t=0,n=0;for(let o=0;o<e.length;o++){let r=e[o];if(r.type!=="user.message"&&r.type!=="assistant.message"){s.push(r);continue}if(r.type==="user.message"){t++,s.push({...r,_turnNumber:t});continue}if(r.type==="assistant.message"){let i=r.data.tools||[],a=r.timestamp,l=`pi-turn-${o}`;s.push({type:"assistant.turn_start",id:`${l}-start`,timestamp:a,parentId:r.parentId,data:{message:r.data.message||"",model:r.data.model,tools:i.length>0?i:void 0},_synthetic:!0,_turnNumber:t,_fileIndex:r._fileIndex}),s.push({...r,_fileIndex:r._fileIndex+.05}),i.forEach((c,d)=>{let u=`pi-tool-${n++}`,m=a,f=a;s.push({type:"tool.execution_start",id:`${u}-start`,timestamp:m,parentId:l,data:{toolCallId:u,toolName:c.name,tool:c.name,arguments:c.input||{}},_synthetic:!0,_fileIndex:r._fileIndex+.1+d*.01}),s.push({type:"tool.execution_complete",id:`${u}-complete`,timestamp:f,parentId:u,data:{toolCallId:u,toolName:c.name,tool:c.name,result:c.result,error:c.status==="error"?"Tool execution failed":null,isError:c.status==="error"},_synthetic:!0,_fileIndex:r._fileIndex+.15+d*.01})}),s.push({type:"assistant.turn_complete",id:`${l}-complete`,timestamp:r.timestamp,parentId:l,data:{message:r.data.message||""},_synthetic:!0,_turnNumber:t,_fileIndex:r._fileIndex+.9})}}return s}_expandVsCodeEvents(e){let s=[],t=[],n=null,o=null,r=0,i=null,a=null,l=()=>{t.length!==0&&(s.push({type:"assistant.message",id:`vscode-tools-${r}`,timestamp:o,parentId:n,data:{message:"",content:"",tools:t,subAgentId:i,subAgentName:a},_synthetic:!0}),t=[],i=null,a=null)};for(let c=0;c<e.length;c++){let d=e[c];if(d.type==="tool.invocation"){let u=d.data?.subAgentId||null;t.length>0&&u!==i&&l(),t.length===0&&(n=d.parentId,o=d.timestamp,r=c,i=u,a=d.data?.subAgentName||null),d.data?.tool&&t.push(d.data.tool)}else l(),s.push(d)}return l(),s}_expandCopilotToTimelineFormat(e){let s=[],t=0;for(let n=0;n<e.length;n++){let o=e[n];if(o.type==="user"){t++,s.push({...o,type:"user.message",_turnNumber:t,data:{...o.data,message:o.message?.content||o.data?.message||""}});continue}if(o.type==="assistant"){let r=o.uuid||`copilot-assistant-${n}`,i=o.timestamp,a="";o.message?.content?Array.isArray(o.message.content)?a=o.message.content.filter(l=>l&&l.type==="text").map(l=>l.text).join(`
20
- `):typeof o.message.content=="string"&&(a=o.message.content):o.data?.message&&(a=o.data.message),s.push({type:"assistant.turn_start",id:`${r}-start`,timestamp:i,parentId:o.parentId,uuid:o.uuid,data:{message:a,turnId:r},_synthetic:!0,_turnNumber:t,_fileIndex:o._fileIndex}),s.push({type:"assistant.message",id:r,timestamp:i,parentId:o.parentId,uuid:o.uuid,data:{message:a,tools:o.data?.tools||[]},_synthetic:!0,_turnNumber:t,_fileIndex:o._fileIndex+.05}),o.data?.tools&&o.data.tools.length>0&&o.data.tools.forEach((l,c)=>{let d=l.toolId||`tool-${n}-${c}`;l.start&&s.push({...l.start,_fileIndex:o._fileIndex+.1+c*.02}),l.complete&&s.push({...l.complete,_fileIndex:o._fileIndex+.15+c*.02})}),s.push({type:"assistant.turn_complete",id:`${r}-complete`,timestamp:i,parentId:r,uuid:o.uuid,data:{message:a},_synthetic:!0,_turnNumber:t,_fileIndex:o._fileIndex+.9});continue}s.push(o)}return s}_expandClaudeToTimelineFormat(e){let s=[],t=0;for(let n=0;n<e.length;n++){let o=e[n];if(o.type==="user"){t++,s.push({...o,type:"user.message",_turnNumber:t,data:{...o.data,message:o.data?.message||""}});continue}if(o.type==="assistant"){let r=o.id||`claude-assistant-${n}`,i=o.timestamp,a=o.data?.message||"";s.push({type:"assistant.turn_start",id:`${r}-start`,timestamp:i,parentId:o.parentId,data:{message:a,turnId:r},_synthetic:!0,_turnNumber:t,_fileIndex:o._fileIndex}),s.push({type:"assistant.message",id:r,timestamp:i,parentId:o.parentId,data:{message:a,tools:o.data?.tools||[]},_synthetic:!0,_turnNumber:t,_fileIndex:o._fileIndex+.05}),o.data?.tools&&o.data.tools.length>0&&o.data.tools.forEach((l,c)=>{l.type==="tool_use"&&(s.push({type:"tool.execution_start",id:`${l.id}-start`,timestamp:i,data:{toolCallId:l.id,toolName:l.name,arguments:l.input||{}},_synthetic:!0,_fileIndex:o._fileIndex+.1+c*.02}),l.result&&s.push({type:"tool.execution_complete",id:`${l.id}-complete`,timestamp:i,data:{toolCallId:l.id,toolName:l.name,result:l.result,isError:!1},_synthetic:!0,_fileIndex:o._fileIndex+.15+c*.02}))}),s.push({type:"assistant.turn_complete",id:`${r}-complete`,timestamp:i,parentId:r,data:{message:a},_synthetic:!0,_turnNumber:t,_fileIndex:o._fileIndex+.9});continue}s.push(o)}return s}_expandVsCodeToTimelineFormat(e){let s=[];for(let t=0;t<e.length;t++){let n=e[t];s.push(n),n.type==="assistant.message"&&n.data?.tools&&n.data.tools.length>0&&n.data.tools.forEach((o,r)=>{if(!o.id||!o.name)return;let i=o.startTime||n.timestamp,a=o.endTime||n.timestamp;s.push({type:"tool.execution_start",id:`${o.id}-start`,timestamp:i,parentId:n.id,data:{toolCallId:o.id,toolName:o.name,tool:o.name,arguments:o.input||{}},_synthetic:!0,_fileIndex:n._fileIndex?n._fileIndex+.1+r*.02:void 0}),s.push({type:"tool.execution_complete",id:`${o.id}-complete`,timestamp:a,parentId:o.id,data:{toolCallId:o.id,toolName:o.name,tool:o.name,result:o.result||null,error:o.error||(o.status==="error"?"Tool execution failed":null),isError:o.status==="error"},_synthetic:!0,_fileIndex:n._fileIndex?n._fileIndex+.15+r*.02:void 0})})}return s}};St.exports=be});var xe=b((_n,wt)=>{var k=require("fs").promises,N=require("path"),xs=require("os"),ve=class{constructor(){this.knownTagsDir=N.join(xs.homedir(),".session-viewer"),this.knownTagsFilePath=N.join(this.knownTagsDir,"known-tags.json")}async ensureKnownTagsFile(){try{await k.access(this.knownTagsFilePath)}catch{await k.mkdir(this.knownTagsDir,{recursive:!0}),await k.writeFile(this.knownTagsFilePath,JSON.stringify([]),"utf8")}}async readKnownTagsFile(){await this.ensureKnownTagsFile();try{let e=await k.readFile(this.knownTagsFilePath,"utf8");return JSON.parse(e)}catch(e){return console.error("Error reading known tags file:",e),[]}}async writeKnownTagsFile(e){await this.ensureKnownTagsFile(),await k.writeFile(this.knownTagsFilePath,JSON.stringify(e,null,2),"utf8")}getSessionTagsFilePath(e){if(e.filePath){let s=N.dirname(e.filePath),t=N.basename(e.filePath,N.extname(e.filePath));return N.join(s,`${t}.tags.json`)}return e.directory?N.join(e.directory,"tags.json"):N.join(this.knownTagsDir,"session-tags",`${e.id}.tags.json`)}normalizeTag(e){return e.trim().toLowerCase().substring(0,30)}async getAllKnownTags(){return(await this.readKnownTagsFile()).sort()}async getSessionTags(e){let s=this.getSessionTagsFilePath(e);try{await k.access(s);let t=await k.readFile(s,"utf8");return JSON.parse(t)}catch{return[]}}async setSessionTags(e,s){if(!Array.isArray(s))throw new Error("Tags must be an array");let t=s.map(o=>this.normalizeTag(o)).filter(o=>o.length>0).filter((o,r,i)=>i.indexOf(o)===r);if(t.length>10)throw new Error("Maximum 10 tags per session");let n=this.getSessionTagsFilePath(e);if(t.length===0)try{await k.unlink(n)}catch{}else await k.mkdir(N.dirname(n),{recursive:!0}),await k.writeFile(n,JSON.stringify(t,null,2),"utf8"),await this.updateKnownTags(t);return t}async updateKnownTags(e){let t=[...await this.readKnownTagsFile(),...e],n=[...new Set(t)];await this.writeKnownTagsFile(n)}async addSessionTags(e,s){let n=[...await this.getSessionTags(e),...s];return await this.setSessionTags(e,n)}async removeSessionTags(e,s){let t=await this.getSessionTags(e),n=s.map(r=>this.normalizeTag(r)),o=t.filter(r=>!n.includes(r));return await this.setSessionTags(e,o)}async getMultipleSessionTags(e){let s={};for(let t of e)s[t.id]=await this.getSessionTags(t);return s}};wt.exports=ve});var Et=b((In,Tt)=>{var As=je(),{isValidSessionId:Y,buildMetadata:_t}=L(),{trackEvent:V,trackMetric:It}=O(),Ds=require("adm-zip"),B=require("path"),P=require("fs"),Ae=class{constructor(e=null){this.sessionService=e||new As}async getHomepage(e,s){try{let t=await this.sessionService.getPaginatedSessions(1,20,"copilot"),n={};if(this.sessionService.sessionRepository&&this.sessionService.sessionRepository.sources)for(let r of this.sessionService.sessionRepository.sources){let i=require("os").homedir(),a=r.dir;a.startsWith(i)&&(a="~"+a.slice(i.length)),a=a.replace(/\\/g,"/"),a.endsWith("/")||(a+="/"),n[r.type]=a}let o={sessions:t.sessions,hasMore:t.hasNextPage,totalSessions:t.totalSessions,sourceHints:JSON.stringify(n)};V("HomepageViewed",{sessionCount:t.totalSessions.toString(),sourceFilter:"copilot"}),s.render("index",o)}catch(t){console.error("Error loading sessions:",t),s.status(500).send("Error loading sessions")}}async getSessionDetail(e,s){try{let t=e.params.id;if(!Y(t))return s.status(400).json({error:"Invalid session ID"});let n=await this.sessionService.sessionRepository.findById(t);if(!n)return s.status(404).json({error:"Session not found"});let o=_t(n);V("SessionViewed",{sessionId:t,source:n.source||"unknown",eventCount:(n.eventCount||o.totalEvents||0).toString(),duration:(n.duration||o.duration||0).toString(),model:n.model||o.model||"unknown",sessionStatus:n.status||o.status||"unknown"});let r=n.eventCount||o.totalEvents||0;r>0&&It("SessionEventCount",r,{sessionId:t,source:n.source||"unknown"});let i=n.duration||o.duration||0;i>0&&It("SessionDuration",i,{sessionId:t,source:n.source||"unknown"}),s.render("session-vue",{sessionId:t,events:[],metadata:o})}catch(t){console.error("Error loading session:",t),s.status(500).json({error:"Error loading session"})}}async getTimeAnalysis(e,s){try{let t=e.params.id;if(!Y(t))return s.status(400).json({error:"Invalid session ID"});let n=await this.sessionService.sessionRepository.findById(t);if(!n)return s.status(404).json({error:"Session not found"});let o=_t(n);V("TimeAnalysisViewed",{sessionId:t,turnCount:(o.totalEvents||0).toString()}),s.render("time-analyze",{sessionId:t,events:[],metadata:o})}catch(t){console.error("Error loading time analysis:",t),s.status(500).json({error:"Error loading analysis"})}}async getSessions(e,s){try{let t=e.query.page?parseInt(e.query.page):null,n=e.query.limit?parseInt(e.query.limit):null,o=e.query.source||null;if(t&&n){if(t<1||n<1||n>100)return s.status(400).json({error:"Invalid pagination parameters"});let r=await this.sessionService.getPaginatedSessions(t,n,o);V("SessionListLoaded",{page:t.toString(),limit:n.toString(),totalSessions:r.totalSessions.toString()}),s.set({"Cache-Control":"public, max-age=60"}),s.json(r)}else if(o&&n){let r=await this.sessionService.getAllSessions(o),i=r.slice(0,n);s.set({"Cache-Control":"public, max-age=60"}),s.json({sessions:i,hasMore:r.length>n,totalSessions:r.length})}else{let r=await this.sessionService.getAllSessions(o);s.set({"Cache-Control":"public, max-age=300"}),s.json(r)}}catch(t){console.error("Error loading sessions:",t),s.status(500).json({error:"Error loading sessions"})}}async loadMoreSessions(e,s){try{let t=parseInt(e.query.offset)||0,n=parseInt(e.query.limit)||20,o=e.query.source||null;if(t<0||n<1||n>50)return s.status(400).json({error:"Invalid parameters"});let r=Math.floor(t/n)+1,i=await this.sessionService.getPaginatedSessions(r,n,o);V("SessionListLoaded",{page:r.toString(),limit:n.toString(),totalSessions:i.totalSessions.toString()}),s.json({sessions:i.sessions,hasMore:i.hasNextPage,totalSessions:i.totalSessions})}catch(t){console.error("Error loading more sessions:",t),s.status(500).json({error:"Error loading more sessions"})}}async getSessionEvents(e,s){try{let t=e.params.id;if(!Y(t))return s.status(400).json({error:"Invalid session ID"});let n=e.query.limit!==void 0||e.query.offset!==void 0,o,r,i;if(n){if(o=parseInt(e.query.limit)||100,r=parseInt(e.query.offset)||0,o<1||o>1e3)return s.status(400).json({error:"Limit must be between 1 and 1000"});if(r<0)return s.status(400).json({error:"Offset must be non-negative"})}if(!await this.sessionService.sessionRepository.findById(t))return s.status(404).json({error:"Session not found"});n?i=await this.sessionService.getSessionEvents(t,{limit:o,offset:r}):i=await this.sessionService.getSessionEvents(t),s.set({"Cache-Control":"no-store",Vary:"Accept-Encoding"}),n?s.json({events:i.events,pagination:{total:i.total,limit:o,offset:r,hasMore:r+o<i.total}}):s.json(i)}catch(t){console.error("Error loading events:",t),s.status(500).json({error:"Error loading events"})}}async getTimeline(e,s){try{let t=e.params.id;if(!Y(t))return s.status(400).json({error:"Invalid session ID"});let n=await this.sessionService.getSessionById(t);if(!n)return s.status(404).json({error:"Session not found"});let o=await this.sessionService.getTimeline(t),r=require("crypto"),i=`${t}-timeline-${n.updatedAt||n.createdAt}`,a=r.createHash("md5").update(i).digest("hex");s.set({ETag:a,"Cache-Control":"private, max-age=300",Vary:"Accept-Encoding"}),s.json(o)}catch(t){console.error("Error loading timeline:",t),s.status(500).json({error:"Error loading timeline"})}}async exportSession(e,s){let t=e.params.id;if(!Y(t))return s.status(400).json({error:"Invalid session ID"});try{let n=await this.sessionService.sessionRepository.findById(t);if(!n)return s.status(404).json({error:"Session not found"});let o,r=!1;if(n.directory)try{(await P.promises.stat(n.directory)).isDirectory()&&(o=n.directory,r=!0)}catch{}if(!o&&n.filePath)try{await P.promises.access(n.filePath),o=n.filePath}catch{}if(!o){if(n.source==="copilot"){let l=this.sessionService.sessionRepository.sources.find(c=>c.type==="copilot");if(l){let c=B.join(l.dir,t);try{(await P.promises.stat(c)).isDirectory()?(o=c,r=!0):o=`${c}.jsonl`}catch{o=`${c}.jsonl`}}}else if(n.source==="claude"){let l=this.sessionService.sessionRepository.sources.find(c=>c.type==="claude");if(l){let c=await P.promises.readdir(B.join(l.dir,"projects"));for(let d of c){let u=B.join(l.dir,"projects",d,`${t}.jsonl`);try{await P.promises.access(u),o=u;break}catch{}}}}else if(n.source==="pi-mono"){let l=this.sessionService.sessionRepository.sources.find(c=>c.type==="pi-mono");if(l){let d=(await P.promises.readdir(l.dir)).find(u=>u.includes(t)&&u.endsWith(".jsonl"));d&&(o=B.join(l.dir,d))}}}if(!o)return s.status(404).json({error:"Session file not found"});try{await P.promises.access(o)}catch{return s.status(404).json({error:"Session file not accessible"})}let i=new Ds;if(r)i.addLocalFolder(o,t);else{let l=B.basename(o);i.addLocalFile(o,"",l);let c=xe(),u=new c().getSessionTagsFilePath(n);try{await P.promises.access(u),i.addLocalFile(u,"",B.basename(u))}catch{}}let a=i.toBuffer();s.setHeader("Content-Type","application/zip"),s.setHeader("Content-Disposition",`attachment; filename="session-${t}.zip"`),V("SessionExported",{sessionId:t}),s.send(a)}catch(n){console.error("Error exporting session:",n),s.status(500).json({error:"Error exporting session"})}}};Tt.exports=Ae});var se=b((Tn,Ct)=>{var De=class{constructor(){this.activeProcesses=new Set,this.isShuttingDown=!1,this._setupCleanupHandlers()}register(e,s={}){let t={process:e,metadata:s,startTime:Date.now()};return this.activeProcesses.add(t),e.on("exit",()=>{this.activeProcesses.delete(t);let n=Date.now()-t.startTime;console.log(`\u{1F504} Process exited (${s.name||"unknown"}): ${n}ms`)}),t}killAll(){console.log(`\u{1F6D1} Killing ${this.activeProcesses.size} active processes...`);for(let{process:e,metadata:s}of this.activeProcesses)try{e.killed||(e.kill("SIGTERM"),console.log(` \u2713 Killed ${s.name||e.pid}`))}catch(t){console.error(` \u2717 Failed to kill ${s.name||e.pid}:`,t.message)}this.activeProcesses.clear()}getActiveCount(){return this.activeProcesses.size}_setupCleanupHandlers(){let e=(s,t=0)=>{this.isShuttingDown||(this.isShuttingDown=!0,console.log(`
21
- \u{1F4DB} Received ${s}, shutting down gracefully...`),this.killAll(),setTimeout(()=>{process.exit(t)},1e3))};process.on("SIGTERM",()=>e("SIGTERM",0)),process.on("SIGINT",()=>e("SIGINT",0)),process.on("uncaughtException",s=>{console.error("\u{1F4A5} Uncaught exception:",s),e("uncaughtException",1)})}};Ct.exports=new De});var xt=b((En,vt)=>{var I=require("fs").promises,bt=require("fs"),M=require("path"),Ms=require("os"),{spawn:ks}=require("child_process"),jt=q(),$s=se(),Me=class{constructor(){}_getToolConfig(e,s){let t={copilot:{name:"Copilot",cli:"copilot",args:(n,o)=>["--config-dir",n,"--yolo","-p",o],cwd:s},vscode:{name:"Copilot",cli:"copilot",args:(n,o)=>["--config-dir",n,"--yolo","-p",o],cwd:s},claude:{name:"Claude Code",cli:"claude",args:(n,o)=>["-p",o,"--dangerously-skip-permissions"],cwd:s},"pi-mono":{name:"Pi",cli:"pi",args:(n,o)=>["-p",o],cwd:s}};return t[e]||t.copilot}async generateInsight(e,s,t="copilot",n=!1){let o=M.join(s,`${e}.agent-review.md`),r=M.join(s,`${e}.agent-review.md.lock`),i=M.join(s,"events.jsonl");try{await I.access(i)}catch{try{i=M.join(s,`${e}.jsonl`),await I.access(i)}catch{let d=(await I.readdir(s)).find(u=>u.endsWith(`_${e}.jsonl`));d&&(i=M.join(s,d))}}let a=this._getToolConfig(t,s),l=a.name;if(!n)try{let c=await I.readFile(o,"utf-8"),d=await I.stat(o);return{status:"completed",report:c,generatedAt:d.mtime}}catch{}try{await I.writeFile(r,JSON.stringify({sessionId:e,startTime:new Date().toISOString(),pid:process.pid}),{flag:"wx"})}catch(c){if(c.code==="EEXIST")try{let d=JSON.parse(await I.readFile(r,"utf-8")),u=await I.stat(r),m=Date.now()-u.mtime.getTime();if(m<jt.INSIGHT_TIMEOUT_MS)return{status:"generating",report:`# Generating ${l} Insight...
19
+ `)}return""}async getSessionWithEvents(e){let s=await this.getSessionById(e);if(!s)return null;let t=await this.getSessionEvents(e),n=xs(s),o=t.find(i=>i.type==="session.start");o?.data?.selectedModel&&(n.model=o.data.selectedModel);let r=t.find(i=>i.type==="session.model_change");if(r?.data&&(n.model=r.data.newModel||r.data.model),t.length){let i=t[t.length-1];i?.timestamp&&(n.updated=i.timestamp)}if(t.length){let i=t[0];i?.timestamp&&(n.created=i.timestamp)}return{session:s,events:t,metadata:n}}async getTimeline(e){let s=await this.getSessionById(e);if(!s)return null;let t=await this.getSessionEvents(e);return s.source==="copilot"?this._buildCopilotTimeline(t,s):s.source==="claude"?this._buildClaudeTimeline(t,s):s.source==="pi-mono"?this._buildPiMonoTimeline(t,s):{turns:[],summary:{}}}_buildPiMonoTimeline(e,s){let t=[],n=0;for(let i=0;i<e.length;i++){let a=e[i];if(a.type==="user.message"){n++;let l={id:`turn-${n}`,type:"user-request",message:a.data.message||"",startTime:a.timestamp,endTime:a.timestamp,assistantTurns:[],subagents:[]},c=i+1,d=0;for(;c<e.length&&e[c].type!=="user.message";){let u=e[c];if(u.type==="assistant.message"){d++,l.endTime=u.timestamp;let m={id:`assistant-${d}`,startTime:u.timestamp,endTime:u.timestamp,tools:[]};if(u.data.tools&&Array.isArray(u.data.tools))for(let f of u.data.tools)m.tools.push({name:f.name,startTime:u.timestamp,endTime:u.timestamp,status:f.status||"completed",input:f.input,result:f.result});l.assistantTurns.push(m)}c++}t.push(l)}}let o=t.reduce((i,a)=>i+a.assistantTurns.reduce((l,c)=>l+c.tools.length,0),0),r={totalTurns:t.length,totalAssistantTurns:t.reduce((i,a)=>i+a.assistantTurns.length,0),totalTools:o,totalSubagents:0,startTime:e[0]?.timestamp,endTime:e[e.length-1]?.timestamp};return{turns:t,summary:r}}_buildCopilotTimeline(e,s){let t=[],n=null,o=0;for(let i of e)if(i.type==="assistant.turn_start")o++,n={id:`turn-${o}`,type:"assistant-turn",message:i.data.message||"",startTime:i.timestamp,endTime:null,tools:[],subagents:[]};else if(i.type==="assistant.turn_complete"&&n)n.endTime=i.timestamp,t.push(n),n=null;else if(i.type==="tool.execution_start"&&n){let a={name:i.data.tool||i.data.name,startTime:i.timestamp,endTime:null,status:"running",input:i.data.arguments||i.data.input};n.tools.push(a)}else if(i.type==="tool.execution_complete"&&n){let a=n.tools.find(l=>l.name===(i.data.tool||i.data.name)&&!l.endTime);a&&(a.endTime=i.timestamp,a.status=i.data.error||i.data.isError?"error":"completed",a.result=i.data.result||i.data.output)}n&&(n.endTime=e[e.length-1]?.timestamp,t.push(n));let r={totalTurns:t.length,totalTools:t.reduce((i,a)=>i+a.tools.length,0),totalSubagents:0,startTime:e[0]?.timestamp,endTime:e[e.length-1]?.timestamp};return{turns:t,summary:r}}_buildClaudeTimeline(e,s){return this._buildPiMonoTimeline(e,s)}_expandPiMonoToCopilotFormat(e){let s=[],t=0,n=0;for(let o=0;o<e.length;o++){let r=e[o];if(r.type!=="user.message"&&r.type!=="assistant.message"){s.push(r);continue}if(r.type==="user.message"){t++,s.push({...r,_turnNumber:t});continue}if(r.type==="assistant.message"){let i=r.data.tools||[],a=r.timestamp,l=`pi-turn-${o}`;s.push({type:"assistant.turn_start",id:`${l}-start`,timestamp:a,parentId:r.parentId,data:{message:r.data.message||"",model:r.data.model,tools:i.length>0?i:void 0},_synthetic:!0,_turnNumber:t,_fileIndex:r._fileIndex}),s.push({...r,_fileIndex:r._fileIndex+.05}),i.forEach((c,d)=>{let u=`pi-tool-${n++}`,m=a,f=a;s.push({type:"tool.execution_start",id:`${u}-start`,timestamp:m,parentId:l,data:{toolCallId:u,toolName:c.name,tool:c.name,arguments:c.input||{}},_synthetic:!0,_fileIndex:r._fileIndex+.1+d*.01}),s.push({type:"tool.execution_complete",id:`${u}-complete`,timestamp:f,parentId:u,data:{toolCallId:u,toolName:c.name,tool:c.name,result:c.result,error:c.status==="error"?"Tool execution failed":null,isError:c.status==="error"},_synthetic:!0,_fileIndex:r._fileIndex+.15+d*.01})}),s.push({type:"assistant.turn_complete",id:`${l}-complete`,timestamp:r.timestamp,parentId:l,data:{message:r.data.message||""},_synthetic:!0,_turnNumber:t,_fileIndex:r._fileIndex+.9})}}return s}_expandVsCodeEvents(e){let s=[],t=[],n=null,o=null,r=0,i=null,a=null,l=()=>{t.length!==0&&(s.push({type:"assistant.message",id:`vscode-tools-${r}`,timestamp:o,parentId:n,data:{message:"",content:"",tools:t,subAgentId:i,subAgentName:a},_synthetic:!0}),t=[],i=null,a=null)};for(let c=0;c<e.length;c++){let d=e[c];if(d.type==="tool.invocation"){let u=d.data?.subAgentId||null;t.length>0&&u!==i&&l(),t.length===0&&(n=d.parentId,o=d.timestamp,r=c,i=u,a=d.data?.subAgentName||null),d.data?.tool&&t.push(d.data.tool)}else l(),s.push(d)}return l(),s}_expandCopilotToTimelineFormat(e){let s=[],t=0;for(let n=0;n<e.length;n++){let o=e[n];if(o.type==="user"){t++,s.push({...o,type:"user.message",_turnNumber:t,data:{...o.data,message:o.message?.content||o.data?.message||""}});continue}if(o.type==="assistant"){let r=o.uuid||`copilot-assistant-${n}`,i=o.timestamp,a="";o.message?.content?Array.isArray(o.message.content)?a=o.message.content.filter(l=>l&&l.type==="text").map(l=>l.text).join(`
20
+ `):typeof o.message.content=="string"&&(a=o.message.content):o.data?.message&&(a=o.data.message),s.push({type:"assistant.turn_start",id:`${r}-start`,timestamp:i,parentId:o.parentId,uuid:o.uuid,data:{message:a,turnId:r},_synthetic:!0,_turnNumber:t,_fileIndex:o._fileIndex}),s.push({type:"assistant.message",id:r,timestamp:i,parentId:o.parentId,uuid:o.uuid,data:{message:a,tools:o.data?.tools||[]},_synthetic:!0,_turnNumber:t,_fileIndex:o._fileIndex+.05}),o.data?.tools&&o.data.tools.length>0&&o.data.tools.forEach((l,c)=>{let d=l.toolId||`tool-${n}-${c}`;l.start&&s.push({...l.start,_fileIndex:o._fileIndex+.1+c*.02}),l.complete&&s.push({...l.complete,_fileIndex:o._fileIndex+.15+c*.02})}),s.push({type:"assistant.turn_complete",id:`${r}-complete`,timestamp:i,parentId:r,uuid:o.uuid,data:{message:a},_synthetic:!0,_turnNumber:t,_fileIndex:o._fileIndex+.9});continue}s.push(o)}return s}_expandClaudeToTimelineFormat(e){let s=[],t=0;for(let n=0;n<e.length;n++){let o=e[n];if(o.type==="user"){t++,s.push({...o,type:"user.message",_turnNumber:t,data:{...o.data,message:o.data?.message||""}});continue}if(o.type==="assistant"){let r=o.id||`claude-assistant-${n}`,i=o.timestamp,a=o.data?.message||"";s.push({type:"assistant.turn_start",id:`${r}-start`,timestamp:i,parentId:o.parentId,data:{message:a,turnId:r},_synthetic:!0,_turnNumber:t,_fileIndex:o._fileIndex}),s.push({type:"assistant.message",id:r,timestamp:i,parentId:o.parentId,data:{message:a,tools:o.data?.tools||[]},_synthetic:!0,_turnNumber:t,_fileIndex:o._fileIndex+.05}),o.data?.tools&&o.data.tools.length>0&&o.data.tools.forEach((l,c)=>{l.type==="tool_use"&&(s.push({type:"tool.execution_start",id:`${l.id}-start`,timestamp:i,data:{toolCallId:l.id,toolName:l.name,arguments:l.input||{}},_synthetic:!0,_fileIndex:o._fileIndex+.1+c*.02}),l.result&&s.push({type:"tool.execution_complete",id:`${l.id}-complete`,timestamp:i,data:{toolCallId:l.id,toolName:l.name,result:l.result,isError:!1},_synthetic:!0,_fileIndex:o._fileIndex+.15+c*.02}))}),s.push({type:"assistant.turn_complete",id:`${r}-complete`,timestamp:i,parentId:r,data:{message:a},_synthetic:!0,_turnNumber:t,_fileIndex:o._fileIndex+.9});continue}s.push(o)}return s}_expandVsCodeToTimelineFormat(e){let s=[];for(let t=0;t<e.length;t++){let n=e[t];s.push(n),n.type==="assistant.message"&&n.data?.tools&&n.data.tools.length>0&&n.data.tools.forEach((o,r)=>{if(!o.id||!o.name)return;let i=o.startTime||n.timestamp,a=o.endTime||n.timestamp;s.push({type:"tool.execution_start",id:`${o.id}-start`,timestamp:i,parentId:n.id,data:{toolCallId:o.id,toolName:o.name,tool:o.name,arguments:o.input||{}},_synthetic:!0,_fileIndex:n._fileIndex?n._fileIndex+.1+r*.02:void 0}),s.push({type:"tool.execution_complete",id:`${o.id}-complete`,timestamp:a,parentId:o.id,data:{toolCallId:o.id,toolName:o.name,tool:o.name,result:o.result||null,error:o.error||(o.status==="error"?"Tool execution failed":null),isError:o.status==="error"},_synthetic:!0,_fileIndex:n._fileIndex?n._fileIndex+.15+r*.02:void 0})})}return s}};wt.exports=be});var xe=b((Tn,_t)=>{var k=require("fs").promises,N=require("path"),Ds=require("os"),ve=class{constructor(){this.knownTagsDir=N.join(Ds.homedir(),".session-viewer"),this.knownTagsFilePath=N.join(this.knownTagsDir,"known-tags.json")}async ensureKnownTagsFile(){try{await k.access(this.knownTagsFilePath)}catch{await k.mkdir(this.knownTagsDir,{recursive:!0}),await k.writeFile(this.knownTagsFilePath,JSON.stringify([]),"utf8")}}async readKnownTagsFile(){await this.ensureKnownTagsFile();try{let e=await k.readFile(this.knownTagsFilePath,"utf8");return JSON.parse(e)}catch(e){return console.error("Error reading known tags file:",e),[]}}async writeKnownTagsFile(e){await this.ensureKnownTagsFile(),await k.writeFile(this.knownTagsFilePath,JSON.stringify(e,null,2),"utf8")}getSessionTagsFilePath(e){if(e.filePath){let s=N.dirname(e.filePath),t=N.basename(e.filePath,N.extname(e.filePath));return N.join(s,`${t}.tags.json`)}return e.directory?N.join(e.directory,"tags.json"):N.join(this.knownTagsDir,"session-tags",`${e.id}.tags.json`)}normalizeTag(e){return e.trim().toLowerCase().substring(0,30)}async getAllKnownTags(){return(await this.readKnownTagsFile()).sort()}async getSessionTags(e){let s=this.getSessionTagsFilePath(e);try{await k.access(s);let t=await k.readFile(s,"utf8");return JSON.parse(t)}catch{return[]}}async setSessionTags(e,s){if(!Array.isArray(s))throw new Error("Tags must be an array");let t=s.map(o=>this.normalizeTag(o)).filter(o=>o.length>0).filter((o,r,i)=>i.indexOf(o)===r);if(t.length>10)throw new Error("Maximum 10 tags per session");let n=this.getSessionTagsFilePath(e);if(t.length===0)try{await k.unlink(n)}catch{}else await k.mkdir(N.dirname(n),{recursive:!0}),await k.writeFile(n,JSON.stringify(t,null,2),"utf8"),await this.updateKnownTags(t);return t}async updateKnownTags(e){let t=[...await this.readKnownTagsFile(),...e],n=[...new Set(t)];await this.writeKnownTagsFile(n)}async addSessionTags(e,s){let n=[...await this.getSessionTags(e),...s];return await this.setSessionTags(e,n)}async removeSessionTags(e,s){let t=await this.getSessionTags(e),n=s.map(r=>this.normalizeTag(r)),o=t.filter(r=>!n.includes(r));return await this.setSessionTags(e,o)}async getMultipleSessionTags(e){let s={};for(let t of e)s[t.id]=await this.getSessionTags(t);return s}};_t.exports=ve});var Ct=b((En,Et)=>{var Ms=je(),{isValidSessionId:Z,buildMetadata:It}=U(),{trackEvent:B,trackMetric:Tt}=R(),ks=require("adm-zip"),W=require("path"),O=require("fs"),Ae=class{constructor(e=null){this.sessionService=e||new Ms}async getHomepage(e,s){try{let t=await this.sessionService.getPaginatedSessions(1,20,"copilot"),n={};if(this.sessionService.sessionRepository&&this.sessionService.sessionRepository.sources)for(let r of this.sessionService.sessionRepository.sources)n[r.type]=r.dir;let o={sessions:t.sessions,hasMore:t.hasNextPage,totalSessions:t.totalSessions,sourceHints:JSON.stringify(n)};B("HomepageViewed",{sessionCount:t.totalSessions.toString(),sourceFilter:"copilot"}),s.render("index",o)}catch(t){console.error("Error loading sessions:",t),s.status(500).send("Error loading sessions")}}async getSessionDetail(e,s){try{let t=e.params.id;if(!Z(t))return s.status(400).json({error:"Invalid session ID"});let n=await this.sessionService.sessionRepository.findById(t);if(!n)return s.status(404).json({error:"Session not found"});let o=It(n);B("SessionViewed",{sessionId:t,source:n.source||"unknown",eventCount:(n.eventCount||o.totalEvents||0).toString(),duration:(n.duration||o.duration||0).toString(),model:n.model||o.model||"unknown",sessionStatus:n.status||o.status||"unknown"});let r=n.eventCount||o.totalEvents||0;r>0&&Tt("SessionEventCount",r,{sessionId:t,source:n.source||"unknown"});let i=n.duration||o.duration||0;i>0&&Tt("SessionDuration",i,{sessionId:t,source:n.source||"unknown"}),s.render("session-vue",{sessionId:t,events:[],metadata:o})}catch(t){console.error("Error loading session:",t),s.status(500).json({error:"Error loading session"})}}async getTimeAnalysis(e,s){try{let t=e.params.id;if(!Z(t))return s.status(400).json({error:"Invalid session ID"});let n=await this.sessionService.sessionRepository.findById(t);if(!n)return s.status(404).json({error:"Session not found"});let o=It(n);B("TimeAnalysisViewed",{sessionId:t,turnCount:(o.totalEvents||0).toString()}),s.render("time-analyze",{sessionId:t,events:[],metadata:o})}catch(t){console.error("Error loading time analysis:",t),s.status(500).json({error:"Error loading analysis"})}}async getSessions(e,s){try{let t=e.query.page?parseInt(e.query.page):null,n=e.query.limit?parseInt(e.query.limit):null,o=e.query.source||null;if(t&&n){if(t<1||n<1||n>100)return s.status(400).json({error:"Invalid pagination parameters"});let r=await this.sessionService.getPaginatedSessions(t,n,o);B("SessionListLoaded",{page:t.toString(),limit:n.toString(),totalSessions:r.totalSessions.toString()}),s.set({"Cache-Control":"public, max-age=60"}),s.json(r)}else if(o&&n){let r=await this.sessionService.getAllSessions(o),i=r.slice(0,n);s.set({"Cache-Control":"public, max-age=60"}),s.json({sessions:i,hasMore:r.length>n,totalSessions:r.length})}else{let r=await this.sessionService.getAllSessions(o);s.set({"Cache-Control":"public, max-age=300"}),s.json(r)}}catch(t){console.error("Error loading sessions:",t),s.status(500).json({error:"Error loading sessions"})}}async loadMoreSessions(e,s){try{let t=parseInt(e.query.offset)||0,n=parseInt(e.query.limit)||20,o=e.query.source||null;if(t<0||n<1||n>50)return s.status(400).json({error:"Invalid parameters"});let r=Math.floor(t/n)+1,i=await this.sessionService.getPaginatedSessions(r,n,o);B("SessionListLoaded",{page:r.toString(),limit:n.toString(),totalSessions:i.totalSessions.toString()}),s.json({sessions:i.sessions,hasMore:i.hasNextPage,totalSessions:i.totalSessions})}catch(t){console.error("Error loading more sessions:",t),s.status(500).json({error:"Error loading more sessions"})}}async getSessionEvents(e,s){try{let t=e.params.id;if(!Z(t))return s.status(400).json({error:"Invalid session ID"});let n=e.query.limit!==void 0||e.query.offset!==void 0,o,r,i;if(n){if(o=parseInt(e.query.limit)||100,r=parseInt(e.query.offset)||0,o<1||o>1e3)return s.status(400).json({error:"Limit must be between 1 and 1000"});if(r<0)return s.status(400).json({error:"Offset must be non-negative"})}if(!await this.sessionService.sessionRepository.findById(t))return s.status(404).json({error:"Session not found"});n?i=await this.sessionService.getSessionEvents(t,{limit:o,offset:r}):i=await this.sessionService.getSessionEvents(t),s.set({"Cache-Control":"no-store",Vary:"Accept-Encoding"}),n?s.json({events:i.events,pagination:{total:i.total,limit:o,offset:r,hasMore:r+o<i.total}}):s.json(i)}catch(t){console.error("Error loading events:",t),s.status(500).json({error:"Error loading events"})}}async getTimeline(e,s){try{let t=e.params.id;if(!Z(t))return s.status(400).json({error:"Invalid session ID"});let n=await this.sessionService.getSessionById(t);if(!n)return s.status(404).json({error:"Session not found"});let o=await this.sessionService.getTimeline(t),r=require("crypto"),i=`${t}-timeline-${n.updatedAt||n.createdAt}`,a=r.createHash("md5").update(i).digest("hex");s.set({ETag:a,"Cache-Control":"private, max-age=300",Vary:"Accept-Encoding"}),s.json(o)}catch(t){console.error("Error loading timeline:",t),s.status(500).json({error:"Error loading timeline"})}}async exportSession(e,s){let t=e.params.id;if(!Z(t))return s.status(400).json({error:"Invalid session ID"});try{let n=await this.sessionService.sessionRepository.findById(t);if(!n)return s.status(404).json({error:"Session not found"});let o,r=!1;if(n.directory)try{(await O.promises.stat(n.directory)).isDirectory()&&(o=n.directory,r=!0)}catch{}if(!o&&n.filePath)try{await O.promises.access(n.filePath),o=n.filePath}catch{}if(!o){if(n.source==="copilot"){let l=this.sessionService.sessionRepository.sources.find(c=>c.type==="copilot");if(l){let c=W.join(l.dir,t);try{(await O.promises.stat(c)).isDirectory()?(o=c,r=!0):o=`${c}.jsonl`}catch{o=`${c}.jsonl`}}}else if(n.source==="claude"){let l=this.sessionService.sessionRepository.sources.find(c=>c.type==="claude");if(l){let c=await O.promises.readdir(W.join(l.dir,"projects"));for(let d of c){let u=W.join(l.dir,"projects",d,`${t}.jsonl`);try{await O.promises.access(u),o=u;break}catch{}}}}else if(n.source==="pi-mono"){let l=this.sessionService.sessionRepository.sources.find(c=>c.type==="pi-mono");if(l){let d=(await O.promises.readdir(l.dir)).find(u=>u.includes(t)&&u.endsWith(".jsonl"));d&&(o=W.join(l.dir,d))}}}if(!o)return s.status(404).json({error:"Session file not found"});try{await O.promises.access(o)}catch{return s.status(404).json({error:"Session file not accessible"})}let i=new ks;if(r)i.addLocalFolder(o,t);else{let l=W.basename(o);i.addLocalFile(o,"",l);let c=xe(),u=new c().getSessionTagsFilePath(n);try{await O.promises.access(u),i.addLocalFile(u,"",W.basename(u))}catch{}}let a=i.toBuffer();s.setHeader("Content-Type","application/zip"),s.setHeader("Content-Disposition",`attachment; filename="session-${t}.zip"`),B("SessionExported",{sessionId:t}),s.send(a)}catch(n){console.error("Error exporting session:",n),s.status(500).json({error:"Error exporting session"})}}};Et.exports=Ae});var se=b((Cn,bt)=>{var De=class{constructor(){this.activeProcesses=new Set,this.isShuttingDown=!1,this._setupCleanupHandlers()}register(e,s={}){let t={process:e,metadata:s,startTime:Date.now()};return this.activeProcesses.add(t),e.on("exit",()=>{this.activeProcesses.delete(t);let n=Date.now()-t.startTime;console.log(`\u{1F504} Process exited (${s.name||"unknown"}): ${n}ms`)}),t}killAll(){console.log(`\u{1F6D1} Killing ${this.activeProcesses.size} active processes...`);for(let{process:e,metadata:s}of this.activeProcesses)try{e.killed||(e.kill("SIGTERM"),console.log(` \u2713 Killed ${s.name||e.pid}`))}catch(t){console.error(` \u2717 Failed to kill ${s.name||e.pid}:`,t.message)}this.activeProcesses.clear()}getActiveCount(){return this.activeProcesses.size}_setupCleanupHandlers(){let e=(s,t=0)=>{this.isShuttingDown||(this.isShuttingDown=!0,console.log(`
21
+ \u{1F4DB} Received ${s}, shutting down gracefully...`),this.killAll(),setTimeout(()=>{process.exit(t)},1e3))};process.on("SIGTERM",()=>e("SIGTERM",0)),process.on("SIGINT",()=>e("SIGINT",0)),process.on("uncaughtException",s=>{console.error("\u{1F4A5} Uncaught exception:",s),e("uncaughtException",1)})}};bt.exports=new De});var At=b((bn,xt)=>{var I=require("fs").promises,jt=require("fs"),M=require("path"),$s=require("os"),{spawn:Ns}=require("child_process"),vt=L(),Ps=se(),Me=class{constructor(){}_getToolConfig(e,s){let t={copilot:{name:"Copilot",cli:"copilot",args:(n,o)=>["--config-dir",n,"--yolo","-p",o],cwd:s},vscode:{name:"Copilot",cli:"copilot",args:(n,o)=>["--config-dir",n,"--yolo","-p",o],cwd:s},claude:{name:"Claude Code",cli:"claude",args:(n,o)=>["-p",o,"--dangerously-skip-permissions"],cwd:s},"pi-mono":{name:"Pi",cli:"pi",args:(n,o)=>["-p",o],cwd:s}};return t[e]||t.copilot}async generateInsight(e,s,t="copilot",n=!1){let o=M.join(s,`${e}.agent-review.md`),r=M.join(s,`${e}.agent-review.md.lock`),i=M.join(s,"events.jsonl");try{await I.access(i)}catch{try{i=M.join(s,`${e}.jsonl`),await I.access(i)}catch{let d=(await I.readdir(s)).find(u=>u.endsWith(`_${e}.jsonl`));d&&(i=M.join(s,d))}}let a=this._getToolConfig(t,s),l=a.name;if(!n)try{let c=await I.readFile(o,"utf-8"),d=await I.stat(o);return{status:"completed",report:c,generatedAt:d.mtime}}catch{}try{await I.writeFile(r,JSON.stringify({sessionId:e,startTime:new Date().toISOString(),pid:process.pid}),{flag:"wx"})}catch(c){if(c.code==="EEXIST")try{let d=JSON.parse(await I.readFile(r,"utf-8")),u=await I.stat(r),m=Date.now()-u.mtime.getTime();if(m<vt.INSIGHT_TIMEOUT_MS)return{status:"generating",report:`# Generating ${l} Insight...
22
22
 
23
23
  Another request is currently generating this insight. Please wait.`,startedAt:u.birthtime,lastUpdate:u.mtime,ageMs:Date.now()-u.birthtime.getTime()};console.log(`\u26A0\uFE0F Removing stale lock file (${Math.floor(m/1e3)}s old)`),await I.unlink(r),await I.writeFile(r,JSON.stringify({sessionId:e,startTime:new Date().toISOString(),pid:process.pid}),{flag:"wx"})}catch(d){throw new Error("Failed to acquire lock for insight generation",{cause:d})}else throw c}try{await I.access(i)}catch(c){throw await I.unlink(r),new Error("Events file not found",{cause:c})}if(n)try{await I.unlink(o)}catch{}return await this._spawnAnalysisProcess(s,i,o,r,a),{status:"generating",report:`# Generating ${l} Insight...
24
24
 
25
- Analysis in progress. Please wait.`,startedAt:new Date}}async _spawnAnalysisProcess(e,s,t,n,o){let r=M.basename(e),i=M.join(Ms.tmpdir(),`agent-review-${r}-${Date.now()}`);await I.mkdir(i,{recursive:!0});let a=this._buildPrompt(t,s),l=M.join(e,`${r}.agent-review.md.tmp`),c=o.cli,d=o.args(i,a);console.log(`\u{1F916} Starting ${o.name} analysis: ${c} ${d.slice(0,2).join(" ")}...`),console.log(`\u{1F4CB} Args count: ${d.length}, prompt length: ${a.length} chars`);let u=ks(c,d,{env:{...process.env},cwd:e,stdio:["pipe","pipe","pipe"]});if($s.register(u,{name:`insight-${r}`}),o.cli==="copilot"){let _=bt.createReadStream(s);u.stdin.on("error",y=>{y.code==="EPIPE"?_.destroy():console.error("\u274C stdin error:",y)}),_.pipe(u.stdin)}else u.stdin.end();let m=bt.createWriteStream(l);u.stdout.pipe(m);let f=[],g=0,S=64*1024;u.stderr.on("data",_=>{g<S&&(f.push(_),g+=_.length)}),u.on("close",async _=>{try{m.end();let y=Buffer.concat(f).toString("utf-8").slice(0,S);if(console.log(`\u{1F4CB} ${o.name} process exited with code ${_}`),y&&console.log(`\u{1F4CB} ${o.name} stderr:`,y.substring(0,500)),_!==0)console.error(`\u274C ${o.name} CLI failed (code ${_}):`,y),await I.writeFile(t,`# \u274C Generation Failed
25
+ Analysis in progress. Please wait.`,startedAt:new Date}}async _spawnAnalysisProcess(e,s,t,n,o){let r=M.basename(e),i=M.join($s.tmpdir(),`agent-review-${r}-${Date.now()}`);await I.mkdir(i,{recursive:!0});let a=this._buildPrompt(t,s),l=M.join(e,`${r}.agent-review.md.tmp`),c=o.cli,d=o.args(i,a);console.log(`\u{1F916} Starting ${o.name} analysis: ${c} ${d.slice(0,2).join(" ")}...`),console.log(`\u{1F4CB} Args count: ${d.length}, prompt length: ${a.length} chars`);let u=Ns(c,d,{env:{...process.env},cwd:e,stdio:["pipe","pipe","pipe"]});if(Ps.register(u,{name:`insight-${r}`}),o.cli==="copilot"){let _=jt.createReadStream(s);u.stdin.on("error",y=>{y.code==="EPIPE"?_.destroy():console.error("\u274C stdin error:",y)}),_.pipe(u.stdin)}else u.stdin.end();let m=jt.createWriteStream(l);u.stdout.pipe(m);let f=[],g=0,w=64*1024;u.stderr.on("data",_=>{g<w&&(f.push(_),g+=_.length)}),u.on("close",async _=>{try{m.end();let y=Buffer.concat(f).toString("utf-8").slice(0,w);if(console.log(`\u{1F4CB} ${o.name} process exited with code ${_}`),y&&console.log(`\u{1F4CB} ${o.name} stderr:`,y.substring(0,500)),_!==0)console.error(`\u274C ${o.name} CLI failed (code ${_}):`,y),await I.writeFile(t,`# \u274C Generation Failed
26
26
 
27
27
  Exit code: ${_}
28
28
 
@@ -95,5 +95,5 @@ IMPORTANT CONSTRAINTS:
95
95
  `),r=[],i=!1;for(let a of o){if(/^● /.test(a)){i=!0;continue}if(/^ {2}\$ /.test(a)){i=!0;continue}if(/^ {2}└ /.test(a)){i=!1;continue}if(!/^\(\+\d+ lines?\)/.test(a)&&!/^ {2}└ \d+ lines/.test(a)){if(/^● Asked user:/.test(a)){i=!0;continue}if(/^ {2}└ User responded:/.test(a)){i=!1;continue}i&&/\S/.test(a)&&!/^ {2}/.test(a)&&(i=!1),!i&&r.push(a)}}e=r.join(`
96
96
  `)}}return e=e.replace(/\n{3,}/g,`
97
97
 
98
- `).trim(),e}async getInsightStatus(e,s,t="copilot"){return await this._getStatusForSource(e,s)}async _getStatusForSource(e,s){let t=M.join(s,`${e}.agent-review.md`),n=M.join(s,`${e}.agent-review.md.lock`),o=M.join(s,`${e}.agent-review.md.tmp`);try{let r=await I.readFile(t,"utf-8"),i=await I.stat(t);return{status:"completed",report:r,generatedAt:i.mtime}}catch{try{await I.access(n);let i=await I.stat(n),a=Date.now()-i.birthtime.getTime(),l=null;try{l=await I.readFile(o,"utf-8")}catch{}return a>=jt.INSIGHT_TIMEOUT_MS?{status:"timeout",log:l,startedAt:i.birthtime,lastUpdate:i.mtime,ageMs:a}:{status:"generating",log:l,startedAt:i.birthtime,lastUpdate:i.mtime,ageMs:a}}catch{return{status:"not_started"}}}}async deleteInsight(e,s,t="copilot"){let n=M.join(s,`${e}.agent-review.md`);try{return await I.unlink(n),{success:!0}}catch(o){if(o.code==="ENOENT")return{success:!0,message:"Insight file not found"};throw o}}};vt.exports=Me});var Dt=b((Cn,At)=>{var Ns=xt(),{isValidSessionId:ke}=L(),{trackEvent:$e,trackMetric:Ps,trackException:Os}=O(),Ne=class{constructor(e=null,s=null){if(e?this.insightService=e:this.insightService=new Ns,s)this.sessionService=s;else{let t=je();this.sessionService=new t}}async generateInsight(e,s){try{let t=e.params.id,n=e.body?.force===!0;if(!ke(t))return s.status(400).json({error:"Invalid session ID"});let o=await this.sessionService.getSessionById(t);if(!o)return s.status(404).json({error:"Session not found"});if(!o.directory)return s.status(400).json({error:"Session directory not available"});let r=Date.now(),i=await this.insightService.generateInsight(o.id,o.directory,o.source,n),a=Date.now()-r;$e("InsightGenerated",{sessionId:t,source:o.source||"unknown",durationMs:a.toString()}),Ps("InsightGenerationTime",a,{sessionId:t,source:o.source||"unknown"}),s.json(i)}catch(t){console.error("Error generating insight:",t),Os(t,{sessionId:e.params.id,operation:"generateInsight"}),s.status(500).json({error:t.message||"Error generating insight"})}}async getInsightStatus(e,s){try{let t=e.params.id;if(!ke(t))return s.status(400).json({error:"Invalid session ID"});let n=await this.sessionService.getSessionById(t);if(!n)return s.status(404).json({error:"Session not found"});if(!n.directory)return s.status(400).json({error:"Session directory not available"});let o=await this.insightService.getInsightStatus(n.id,n.directory,n.source);o.status==="ready"&&o.report&&$e("InsightViewed",{sessionId:t}),s.json(o)}catch(t){console.error("Error getting insight status:",t),s.status(500).json({error:"Error getting insight status"})}}async deleteInsight(e,s){try{let t=e.params.id;if(!ke(t))return s.status(400).json({error:"Invalid session ID"});let n=await this.sessionService.getSessionById(t);if(!n)return s.status(404).json({error:"Session not found"});if(!n.directory)return s.status(400).json({error:"Session directory not available"});let o=await this.insightService.deleteInsight(n.id,n.directory,n.source);$e("InsightDeleted",{sessionId:t}),s.json(o)}catch(t){console.error("Error deleting insight:",t),s.status(500).json({error:"Error deleting insight"})}}};At.exports=Ne});var Nt=b((bn,$t)=>{var h=require("fs"),T=require("path"),Z=require("os"),Rs=require("multer"),{spawn:Pe}=require("child_process"),{isValidSessionId:W}=L(),{trackEvent:Mt,trackException:Oe}=O(),kt=se(),Fs=q(),Re=class{constructor(){this.SESSION_DIR=process.env.SESSION_DIR||T.join(Z.homedir(),".copilot","session-state"),this.uploadDir=process.env.UPLOAD_DIR||T.join(Z.tmpdir(),"copilot-session-uploads"),this.SESSION_DIRS={copilot:this.SESSION_DIR,claude:T.join(Z.homedir(),".claude","projects"),"pi-mono":T.join(Z.homedir(),".pi","agent","sessions")},this.upload=this.createMulterInstance()}createMulterInstance(){return Rs({dest:this.uploadDir,limits:{fileSize:Fs.MAX_UPLOAD_SIZE},fileFilter:(e,s,t)=>{let n=s.originalname.toLowerCase().endsWith(".zip"),o=s.mimetype==="application/zip"||s.mimetype==="application/x-zip-compressed";if(!n||!o)return t(new Error("Only .zip files are allowed"));t(null,!0)}})}async shareSession(e,s){try{let t=e.params.id;if(!W(t))return s.status(400).json({error:"Invalid session ID"});let n=T.join(this.SESSION_DIR,t);try{await h.promises.access(n)}catch{return s.status(404).json({error:"Session not found"})}let o=T.join(Z.tmpdir(),`session-${t}.zip`),r=Pe("zip",["-r","-q",o,t],{cwd:this.SESSION_DIR});kt.register(r,{name:`zip-${t}`}),r.on("close",i=>{if(i!==0)return s.status(500).json({error:"Failed to create zip file"});Mt("SessionShared",{sessionId:t}),s.download(o,`session-${t}.zip`,a=>{h.promises.unlink(o).catch(()=>{}),a&&console.error("Error sending zip:",a)})}),r.on("error",i=>{console.error("Error creating zip:",i),s.status(500).json({error:"Failed to create zip file"})})}catch(t){console.error("Error sharing session:",t),s.status(500).json({error:"Error sharing session"})}}async importSession(e,s){try{if(!e.file)return s.status(400).json({error:"No file uploaded"});let t=e.file.path,n=T.join(this.uploadDir,`extract-${Date.now()}`);await h.promises.mkdir(n,{recursive:!0});let o=50*1024*1024,r=200*1024*1024,i=1e3,a=5;if((await h.promises.stat(t)).size>o)return await h.promises.unlink(t),s.status(400).json({error:"Compressed file too large (max 50MB)"});let c=Pe("unzip",["-l",t]),d="";c.stdout.on("data",_=>{d+=_.toString()}),await new Promise((_,y)=>{c.on("close",j=>{j!==0?y(new Error("Failed to list zip contents")):_()}),c.on("error",y)});let u=d.split(`
99
- `),m=0,f=0,g=0;for(let _ of u){let y=_.trim().match(/^\s*(\d+)\s+\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}\s+(.+)$/);if(y){let j=parseInt(y[1]),v=y[2];m+=j,f++;let F=(v.match(/\//g)||[]).length;g=Math.max(g,F)}}if(m>r)return await h.promises.unlink(t),s.status(400).json({error:`Uncompressed size too large (${Math.round(m/1024/1024)}MB > ${r/1024/1024}MB)`});if(f>i)return await h.promises.unlink(t),s.status(400).json({error:`Too many files in archive (${f} > ${i})`});if(g>a)return await h.promises.unlink(t),s.status(400).json({error:`Directory nesting too deep (${g} > ${a})`});let S=Pe("unzip",["-q",t,"-d",n]);kt.register(S,{name:"unzip-import"}),S.on("close",async _=>{let y;try{if(await h.promises.unlink(t),_!==0)return await h.promises.rm(n,{recursive:!0,force:!0}),s.status(500).json({error:"Failed to extract zip file"});let j=await h.promises.readdir(n);if(j.length===0)return await h.promises.rm(n,{recursive:!0,force:!0}),s.status(400).json({error:"Empty zip file"});if(y=j[0],!W(y))return await h.promises.rm(n,{recursive:!0,force:!0}),s.status(400).json({error:"Invalid session directory name in zip file"});let v=T.join(n,y),F=T.join(this.SESSION_DIR,y),oe=T.join(v,"events.jsonl");try{await h.promises.access(oe)}catch{return await h.promises.rm(n,{recursive:!0,force:!0}),s.status(400).json({error:"Invalid session structure (no events.jsonl)"})}if(h.existsSync(F))return await h.promises.rm(n,{recursive:!0,force:!0}),s.status(409).json({error:"Session already exists"});await h.promises.rename(v,F),await h.promises.rm(n,{recursive:!0,force:!0});let re=await h.promises.stat(t).catch(()=>({size:0}));Mt("SessionImported",{format:"copilot",fileSize:re.size.toString()}),s.json({success:!0,sessionId:y})}catch(j){console.error("Error importing session:",j),Oe(j,{operation:"importSession",sessionId:y||"unknown"}),await h.promises.rm(n,{recursive:!0,force:!0}).catch(()=>{}),s.status(500).json({error:"Error importing session"})}}),S.on("error",async _=>{console.error("Error extracting zip:",_),Oe(_,{operation:"importSession_unzip"}),await h.promises.unlink(t).catch(()=>{}),await h.promises.rm(n,{recursive:!0,force:!0}).catch(()=>{}),s.status(500).json({error:"Failed to extract zip file"})})}catch(t){console.error("Error processing upload:",t),Oe(t,{operation:"importSession_upload"}),e.file&&await h.promises.unlink(e.file.path).catch(()=>{}),s.status(500).json({error:"Error processing upload"})}}getUploadMiddleware(){return this.upload.single("zipFile")}async _detectFormat(e){try{let s=await h.promises.readdir(e);if(s.length===0)return null;let t=/^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}-\d{3}Z_([a-zA-Z0-9_-]+)\.jsonl$/;for(let o of s){let r=o.match(t);if(r)return{format:"pi-mono",sessionId:r[1],fileName:o,extractDir:e}}for(let o of s){let r=T.join(e,o);if((await h.promises.stat(r)).isDirectory()){let a=T.join(r,"events.jsonl");if(h.existsSync(a))return{format:"copilot",sessionId:o,directoryName:o,extractDir:e}}}let n=/^([a-zA-Z0-9_-]+)\.jsonl$/;for(let o of s){let r=T.join(e,o);if((await h.promises.stat(r)).isFile()){let a=o.match(n);if(a){let l=a[1],c=T.join(e,l),d=h.existsSync(c);return{format:"claude",sessionId:l,fileName:o,hasDirectory:d,directoryName:d?l:void 0,extractDir:e}}}}return null}catch(s){return console.error("Error detecting format:",s),null}}async _importCopilotSession(e,s){try{let{sessionId:t,directoryName:n}=e;if(!W(t))return{success:!1,error:"Invalid session ID",statusCode:400};let o=T.join(s,n),r=T.join(this.SESSION_DIRS.copilot,t),i=T.join(o,"events.jsonl");return h.existsSync(i)?h.existsSync(r)?{success:!1,error:"Session already exists",statusCode:409}:(await h.promises.rename(o,r),await h.promises.writeFile(T.join(r,".imported"),""),{success:!0,sessionId:t,format:"copilot"}):{success:!1,error:"Invalid session structure (no events.jsonl)",statusCode:400}}catch(t){return console.error("Error importing Copilot session:",t),{success:!1,error:`Error importing Copilot session: ${t.message}`,statusCode:500}}}async _importClaudeSession(e,s,t){try{let{sessionId:n,fileName:o,hasDirectory:r,directoryName:i}=e;if(!W(n))return{success:!1,error:"Invalid session ID",statusCode:400};let a=t.query.project||"imported-sessions",l=T.join(this.SESSION_DIRS.claude,a);await h.promises.mkdir(l,{recursive:!0});let c=T.join(s,o),d=T.join(l,o);if(await h.promises.rename(c,d),r&&i){let u=T.join(s,i),m=T.join(l,i);await h.promises.rename(u,m)}return{success:!0,sessionId:n,format:"claude",project:a}}catch(n){return console.error("Error importing Claude session:",n),{success:!1,error:`Error importing Claude session: ${n.message}`,statusCode:500}}}async _importPiMonoSession(e,s,t){try{let{sessionId:n,fileName:o}=e;if(!W(n))return{success:!1,error:"Invalid session ID",statusCode:400};let r=t.query.project||"imported-sessions",i=T.join(this.SESSION_DIRS["pi-mono"],r);await h.promises.mkdir(i,{recursive:!0});let a=T.join(s,o),l=T.join(i,o);return await h.promises.rename(a,l),{success:!0,sessionId:n,format:"pi-mono",project:r}}catch(n){return console.error("Error importing Pi-Mono session:",n),{success:!1,error:`Error importing Pi-Mono session: ${n.message}`,statusCode:500}}}async _importByFormat(e,s,t){if(!W(e.sessionId))return{success:!1,error:"Invalid session ID",statusCode:400};switch(e.format){case"copilot":return await this._importCopilotSession(e,s);case"claude":return await this._importClaudeSession(e,s,t);case"pi-mono":return await this._importPiMonoSession(e,s,t);default:return{success:!1,error:`Unsupported format: ${e.format}`,statusCode:400}}}async _findSessionLocation(e,s=null){try{let t=s?[s,...Object.keys(this.SESSION_DIRS).filter(n=>n!==s)]:Object.keys(this.SESSION_DIRS);for(let n of t){let o=this.SESSION_DIRS[n];if(n==="copilot"){let r=T.join(o,e);if(h.existsSync(r)){let i=T.join(r,"events.jsonl");if(h.existsSync(i))return{source:"copilot",sessionId:e,sessionPath:r,baseDir:o}}}else if(n==="claude"){if(h.existsSync(o)){let r=await h.promises.readdir(o);for(let i of r){let a=T.join(o,i);if((await h.promises.stat(a)).isDirectory()){let c=T.join(a,`${e}.jsonl`);if(h.existsSync(c))return{source:"claude",sessionId:e,sessionFile:c,projectPath:a,project:i,baseDir:o}}}}}else if(n==="pi-mono"&&h.existsSync(o)){let r=await h.promises.readdir(o);for(let i of r){let a=T.join(o,i);if((await h.promises.stat(a)).isDirectory()){let c=await h.promises.readdir(a),d=new RegExp(`^\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}-\\d{3}Z_${e}\\.jsonl$`);for(let u of c)if(d.test(u))return{source:"pi-mono",sessionId:e,fileName:u,sessionFile:T.join(a,u),projectPath:a,project:i,baseDir:o}}}}}return null}catch(t){return console.error("Error finding session location:",t),null}}};$t.exports=Re});var Rt=b((jn,Ot)=>{var qs=xe(),Ls=Ee(),{isValidSessionId:Pt}=L(),{trackEvent:Us}=O(),Fe=class{constructor(e=null,s=null){this.tagService=e||new qs,this.sessionRepository=s||new Ls}async getAllTags(e,s){try{let t=await this.tagService.getAllKnownTags();s.json({tags:t})}catch(t){console.error("Error getting all tags:",t),s.status(500).json({error:"Error loading tags"})}}async getSessionTags(e,s){try{let t=e.params.id;if(!Pt(t))return s.status(400).json({error:"Invalid session ID"});let n=await this.sessionRepository.findById(t);if(!n)return s.status(404).json({error:"Session not found"});let o=await this.tagService.getSessionTags(n);s.json({tags:o})}catch(t){console.error("Error getting session tags:",t),s.status(500).json({error:"Error loading session tags"})}}async setSessionTags(e,s){try{let t=e.params.id,{tags:n}=e.body;if(!Pt(t))return s.status(400).json({error:"Invalid session ID"});if(!Array.isArray(n))return s.status(400).json({error:"Tags must be an array"});if(n.length>10)return s.status(400).json({error:"Maximum 10 tags per session"});for(let i of n){if(typeof i!="string"||i.trim().length===0)return s.status(400).json({error:"Tags must be non-empty strings"});if(i.length>30)return s.status(400).json({error:"Tag length must not exceed 30 characters"})}let o=await this.sessionRepository.findById(t);if(!o)return s.status(404).json({error:"Session not found"});let r=await this.tagService.setSessionTags(o,n);Us("TagUpdated",{sessionId:t,tagCount:r.length.toString()}),s.json({tags:r})}catch(t){if(console.error("Error setting session tags:",t),t.message==="Maximum 10 tags per session")return s.status(400).json({error:t.message});if(t.message==="Session must have a directory field")return s.status(400).json({error:"Session does not support tagging"});s.status(500).json({error:"Error saving session tags"})}}};Ot.exports=Fe});var Ut=b((vn,Lt)=>{var ne=require("express"),Ft=require("path"),qt=require("compression"),zs=require("helmet"),Vs=q(),{requestTimeout:Bs,developmentCors:Ws,errorHandler:Gs,notFoundHandler:Js,telemetryLocals:Hs}=Ke(),Ks=Et(),Ys=Dt(),Zs=Nt(),Xs=Rt();function Qs(p={}){let e=ne();e.set("etag",!1);let s=new Ks(p.sessionService),t=new Ys(p.insightService,p.sessionService),n=new Zs,o=new Xs(p.tagService);return e.use((r,i,a)=>{i.setHeader("Content-Security-Policy","default-src 'self'; style-src 'self' 'unsafe-inline' https: http:; font-src 'self' https: http:; script-src 'self' 'unsafe-inline' 'unsafe-eval' https: http:; img-src 'self' data: https: http:; connect-src 'self' https: http:"),a()}),e.use(zs({contentSecurityPolicy:!1,hsts:!1,referrerPolicy:!1,crossOriginEmbedderPolicy:!1,crossOriginOpenerPolicy:!1,crossOriginResourcePolicy:!1})),e.use(qt({level:1,threshold:1024,filter:(r,i)=>r.path.includes("/events")&&i.getHeader("Content-Type")?.includes("application/json")?!1:qt.filter(r,i)})),e.use(ne.json({limit:"1mb"})),e.use(ne.urlencoded({extended:!0})),e.use(Bs),e.use(Hs),Vs.NODE_ENV==="development"&&e.use(Ws),e.use("/public",ne.static(Ft.join(__dirname,"../public"))),e.set("view engine","ejs"),e.set("views",Ft.join(__dirname,"../views")),e.get("/",s.getHomepage.bind(s)),e.get("/session/:id",s.getSessionDetail.bind(s)),e.get("/session/:id/time-analyze",s.getTimeAnalysis.bind(s)),e.get("/session/:id/export",s.exportSession.bind(s)),e.get("/api/sessions/load-more",s.loadMoreSessions.bind(s)),e.get("/api/sessions",s.getSessions.bind(s)),e.get("/api/sessions/:id/events",s.getSessionEvents.bind(s)),e.get("/api/sessions/:id/timeline",s.getTimeline.bind(s)),e.get("/api/tags",o.getAllTags.bind(o)),e.get("/api/sessions/:id/tags",o.getSessionTags.bind(o)),e.put("/api/sessions/:id/tags",o.setSessionTags.bind(o)),e.get("/session/:id/share",n.shareSession.bind(n)),e.post("/session/import",(r,i,a)=>n.getUploadMiddleware()(r,i,a),n.importSession.bind(n)),e.post("/session/:id/insight",t.generateInsight.bind(t)),e.get("/session/:id/insight",t.getInsightStatus.bind(t)),e.delete("/session/:id/insight",t.deleteInsight.bind(t)),e.use(Js),e.use(Gs),e}Lt.exports=Qs});O();var en=Ut(),qe=q(),tn=se(),zt=en();module.exports=zt;if(require.main===module){let p=zt.listen(qe.PORT,()=>{console.log(`\u{1F680} Copilot Session Viewer running at http://localhost:${qe.PORT}`),console.log(`\u{1F527} Environment: ${qe.NODE_ENV}`),console.log(`\u26A1 Active processes: ${tn.getActiveCount()}`)});process.on("SIGTERM",()=>{console.log("\u{1F4DB} SIGTERM received, closing server..."),p.close(()=>{console.log("\u2705 Server closed")})})}
98
+ `).trim(),e}async getInsightStatus(e,s,t="copilot"){return await this._getStatusForSource(e,s)}async _getStatusForSource(e,s){let t=M.join(s,`${e}.agent-review.md`),n=M.join(s,`${e}.agent-review.md.lock`),o=M.join(s,`${e}.agent-review.md.tmp`);try{let r=await I.readFile(t,"utf-8"),i=await I.stat(t);return{status:"completed",report:r,generatedAt:i.mtime}}catch{try{await I.access(n);let i=await I.stat(n),a=Date.now()-i.birthtime.getTime(),l=null;try{l=await I.readFile(o,"utf-8")}catch{}return a>=vt.INSIGHT_TIMEOUT_MS?{status:"timeout",log:l,startedAt:i.birthtime,lastUpdate:i.mtime,ageMs:a}:{status:"generating",log:l,startedAt:i.birthtime,lastUpdate:i.mtime,ageMs:a}}catch{return{status:"not_started"}}}}async deleteInsight(e,s,t="copilot"){let n=M.join(s,`${e}.agent-review.md`);try{return await I.unlink(n),{success:!0}}catch(o){if(o.code==="ENOENT")return{success:!0,message:"Insight file not found"};throw o}}};xt.exports=Me});var Mt=b((jn,Dt)=>{var Os=At(),{isValidSessionId:ke}=U(),{trackEvent:$e,trackMetric:Rs,trackException:Fs}=R(),Ne=class{constructor(e=null,s=null){if(e?this.insightService=e:this.insightService=new Os,s)this.sessionService=s;else{let t=je();this.sessionService=new t}}async generateInsight(e,s){try{let t=e.params.id,n=e.body?.force===!0;if(!ke(t))return s.status(400).json({error:"Invalid session ID"});let o=await this.sessionService.getSessionById(t);if(!o)return s.status(404).json({error:"Session not found"});if(!o.directory)return s.status(400).json({error:"Session directory not available"});let r=Date.now(),i=await this.insightService.generateInsight(o.id,o.directory,o.source,n),a=Date.now()-r;$e("InsightGenerated",{sessionId:t,source:o.source||"unknown",durationMs:a.toString()}),Rs("InsightGenerationTime",a,{sessionId:t,source:o.source||"unknown"}),s.json(i)}catch(t){console.error("Error generating insight:",t),Fs(t,{sessionId:e.params.id,operation:"generateInsight"}),s.status(500).json({error:t.message||"Error generating insight"})}}async getInsightStatus(e,s){try{let t=e.params.id;if(!ke(t))return s.status(400).json({error:"Invalid session ID"});let n=await this.sessionService.getSessionById(t);if(!n)return s.status(404).json({error:"Session not found"});if(!n.directory)return s.status(400).json({error:"Session directory not available"});let o=await this.insightService.getInsightStatus(n.id,n.directory,n.source);o.status==="ready"&&o.report&&$e("InsightViewed",{sessionId:t}),s.json(o)}catch(t){console.error("Error getting insight status:",t),s.status(500).json({error:"Error getting insight status"})}}async deleteInsight(e,s){try{let t=e.params.id;if(!ke(t))return s.status(400).json({error:"Invalid session ID"});let n=await this.sessionService.getSessionById(t);if(!n)return s.status(404).json({error:"Session not found"});if(!n.directory)return s.status(400).json({error:"Session directory not available"});let o=await this.insightService.deleteInsight(n.id,n.directory,n.source);$e("InsightDeleted",{sessionId:t}),s.json(o)}catch(t){console.error("Error deleting insight:",t),s.status(500).json({error:"Error deleting insight"})}}};Dt.exports=Ne});var Pt=b((vn,Nt)=>{var h=require("fs"),T=require("path"),X=require("os"),qs=require("multer"),{spawn:Pe}=require("child_process"),{isValidSessionId:G}=U(),{trackEvent:kt,trackException:Oe}=R(),$t=se(),Ls=L(),Re=class{constructor(){this.SESSION_DIR=process.env.SESSION_DIR||T.join(X.homedir(),".copilot","session-state"),this.uploadDir=process.env.UPLOAD_DIR||T.join(X.tmpdir(),"copilot-session-uploads"),this.SESSION_DIRS={copilot:this.SESSION_DIR,claude:T.join(X.homedir(),".claude","projects"),"pi-mono":T.join(X.homedir(),".pi","agent","sessions")},this.upload=this.createMulterInstance()}createMulterInstance(){return qs({dest:this.uploadDir,limits:{fileSize:Ls.MAX_UPLOAD_SIZE},fileFilter:(e,s,t)=>{let n=s.originalname.toLowerCase().endsWith(".zip"),o=s.mimetype==="application/zip"||s.mimetype==="application/x-zip-compressed";if(!n||!o)return t(new Error("Only .zip files are allowed"));t(null,!0)}})}async shareSession(e,s){try{let t=e.params.id;if(!G(t))return s.status(400).json({error:"Invalid session ID"});let n=T.join(this.SESSION_DIR,t);try{await h.promises.access(n)}catch{return s.status(404).json({error:"Session not found"})}let o=T.join(X.tmpdir(),`session-${t}.zip`),r=Pe("zip",["-r","-q",o,t],{cwd:this.SESSION_DIR});$t.register(r,{name:`zip-${t}`}),r.on("close",i=>{if(i!==0)return s.status(500).json({error:"Failed to create zip file"});kt("SessionShared",{sessionId:t}),s.download(o,`session-${t}.zip`,a=>{h.promises.unlink(o).catch(()=>{}),a&&console.error("Error sending zip:",a)})}),r.on("error",i=>{console.error("Error creating zip:",i),s.status(500).json({error:"Failed to create zip file"})})}catch(t){console.error("Error sharing session:",t),s.status(500).json({error:"Error sharing session"})}}async importSession(e,s){try{if(!e.file)return s.status(400).json({error:"No file uploaded"});let t=e.file.path,n=T.join(this.uploadDir,`extract-${Date.now()}`);await h.promises.mkdir(n,{recursive:!0});let o=50*1024*1024,r=200*1024*1024,i=1e3,a=5;if((await h.promises.stat(t)).size>o)return await h.promises.unlink(t),s.status(400).json({error:"Compressed file too large (max 50MB)"});let c=Pe("unzip",["-l",t]),d="";c.stdout.on("data",_=>{d+=_.toString()}),await new Promise((_,y)=>{c.on("close",j=>{j!==0?y(new Error("Failed to list zip contents")):_()}),c.on("error",y)});let u=d.split(`
99
+ `),m=0,f=0,g=0;for(let _ of u){let y=_.trim().match(/^\s*(\d+)\s+\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}\s+(.+)$/);if(y){let j=parseInt(y[1]),v=y[2];m+=j,f++;let q=(v.match(/\//g)||[]).length;g=Math.max(g,q)}}if(m>r)return await h.promises.unlink(t),s.status(400).json({error:`Uncompressed size too large (${Math.round(m/1024/1024)}MB > ${r/1024/1024}MB)`});if(f>i)return await h.promises.unlink(t),s.status(400).json({error:`Too many files in archive (${f} > ${i})`});if(g>a)return await h.promises.unlink(t),s.status(400).json({error:`Directory nesting too deep (${g} > ${a})`});let w=Pe("unzip",["-q",t,"-d",n]);$t.register(w,{name:"unzip-import"}),w.on("close",async _=>{let y;try{if(await h.promises.unlink(t),_!==0)return await h.promises.rm(n,{recursive:!0,force:!0}),s.status(500).json({error:"Failed to extract zip file"});let j=await h.promises.readdir(n);if(j.length===0)return await h.promises.rm(n,{recursive:!0,force:!0}),s.status(400).json({error:"Empty zip file"});if(y=j[0],!G(y))return await h.promises.rm(n,{recursive:!0,force:!0}),s.status(400).json({error:"Invalid session directory name in zip file"});let v=T.join(n,y),q=T.join(this.SESSION_DIR,y),oe=T.join(v,"events.jsonl");try{await h.promises.access(oe)}catch{return await h.promises.rm(n,{recursive:!0,force:!0}),s.status(400).json({error:"Invalid session structure (no events.jsonl)"})}if(h.existsSync(q))return await h.promises.rm(n,{recursive:!0,force:!0}),s.status(409).json({error:"Session already exists"});await h.promises.rename(v,q),await h.promises.rm(n,{recursive:!0,force:!0});let re=await h.promises.stat(t).catch(()=>({size:0}));kt("SessionImported",{format:"copilot",fileSize:re.size.toString()}),s.json({success:!0,sessionId:y})}catch(j){console.error("Error importing session:",j),Oe(j,{operation:"importSession",sessionId:y||"unknown"}),await h.promises.rm(n,{recursive:!0,force:!0}).catch(()=>{}),s.status(500).json({error:"Error importing session"})}}),w.on("error",async _=>{console.error("Error extracting zip:",_),Oe(_,{operation:"importSession_unzip"}),await h.promises.unlink(t).catch(()=>{}),await h.promises.rm(n,{recursive:!0,force:!0}).catch(()=>{}),s.status(500).json({error:"Failed to extract zip file"})})}catch(t){console.error("Error processing upload:",t),Oe(t,{operation:"importSession_upload"}),e.file&&await h.promises.unlink(e.file.path).catch(()=>{}),s.status(500).json({error:"Error processing upload"})}}getUploadMiddleware(){return this.upload.single("zipFile")}async _detectFormat(e){try{let s=await h.promises.readdir(e);if(s.length===0)return null;let t=/^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}-\d{3}Z_([a-zA-Z0-9_-]+)\.jsonl$/;for(let o of s){let r=o.match(t);if(r)return{format:"pi-mono",sessionId:r[1],fileName:o,extractDir:e}}for(let o of s){let r=T.join(e,o);if((await h.promises.stat(r)).isDirectory()){let a=T.join(r,"events.jsonl");if(h.existsSync(a))return{format:"copilot",sessionId:o,directoryName:o,extractDir:e}}}let n=/^([a-zA-Z0-9_-]+)\.jsonl$/;for(let o of s){let r=T.join(e,o);if((await h.promises.stat(r)).isFile()){let a=o.match(n);if(a){let l=a[1],c=T.join(e,l),d=h.existsSync(c);return{format:"claude",sessionId:l,fileName:o,hasDirectory:d,directoryName:d?l:void 0,extractDir:e}}}}return null}catch(s){return console.error("Error detecting format:",s),null}}async _importCopilotSession(e,s){try{let{sessionId:t,directoryName:n}=e;if(!G(t))return{success:!1,error:"Invalid session ID",statusCode:400};let o=T.join(s,n),r=T.join(this.SESSION_DIRS.copilot,t),i=T.join(o,"events.jsonl");return h.existsSync(i)?h.existsSync(r)?{success:!1,error:"Session already exists",statusCode:409}:(await h.promises.rename(o,r),await h.promises.writeFile(T.join(r,".imported"),""),{success:!0,sessionId:t,format:"copilot"}):{success:!1,error:"Invalid session structure (no events.jsonl)",statusCode:400}}catch(t){return console.error("Error importing Copilot session:",t),{success:!1,error:`Error importing Copilot session: ${t.message}`,statusCode:500}}}async _importClaudeSession(e,s,t){try{let{sessionId:n,fileName:o,hasDirectory:r,directoryName:i}=e;if(!G(n))return{success:!1,error:"Invalid session ID",statusCode:400};let a=t.query.project||"imported-sessions",l=T.join(this.SESSION_DIRS.claude,a);await h.promises.mkdir(l,{recursive:!0});let c=T.join(s,o),d=T.join(l,o);if(await h.promises.rename(c,d),r&&i){let u=T.join(s,i),m=T.join(l,i);await h.promises.rename(u,m)}return{success:!0,sessionId:n,format:"claude",project:a}}catch(n){return console.error("Error importing Claude session:",n),{success:!1,error:`Error importing Claude session: ${n.message}`,statusCode:500}}}async _importPiMonoSession(e,s,t){try{let{sessionId:n,fileName:o}=e;if(!G(n))return{success:!1,error:"Invalid session ID",statusCode:400};let r=t.query.project||"imported-sessions",i=T.join(this.SESSION_DIRS["pi-mono"],r);await h.promises.mkdir(i,{recursive:!0});let a=T.join(s,o),l=T.join(i,o);return await h.promises.rename(a,l),{success:!0,sessionId:n,format:"pi-mono",project:r}}catch(n){return console.error("Error importing Pi-Mono session:",n),{success:!1,error:`Error importing Pi-Mono session: ${n.message}`,statusCode:500}}}async _importByFormat(e,s,t){if(!G(e.sessionId))return{success:!1,error:"Invalid session ID",statusCode:400};switch(e.format){case"copilot":return await this._importCopilotSession(e,s);case"claude":return await this._importClaudeSession(e,s,t);case"pi-mono":return await this._importPiMonoSession(e,s,t);default:return{success:!1,error:`Unsupported format: ${e.format}`,statusCode:400}}}async _findSessionLocation(e,s=null){try{let t=s?[s,...Object.keys(this.SESSION_DIRS).filter(n=>n!==s)]:Object.keys(this.SESSION_DIRS);for(let n of t){let o=this.SESSION_DIRS[n];if(n==="copilot"){let r=T.join(o,e);if(h.existsSync(r)){let i=T.join(r,"events.jsonl");if(h.existsSync(i))return{source:"copilot",sessionId:e,sessionPath:r,baseDir:o}}}else if(n==="claude"){if(h.existsSync(o)){let r=await h.promises.readdir(o);for(let i of r){let a=T.join(o,i);if((await h.promises.stat(a)).isDirectory()){let c=T.join(a,`${e}.jsonl`);if(h.existsSync(c))return{source:"claude",sessionId:e,sessionFile:c,projectPath:a,project:i,baseDir:o}}}}}else if(n==="pi-mono"&&h.existsSync(o)){let r=await h.promises.readdir(o);for(let i of r){let a=T.join(o,i);if((await h.promises.stat(a)).isDirectory()){let c=await h.promises.readdir(a),d=new RegExp(`^\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}-\\d{3}Z_${e}\\.jsonl$`);for(let u of c)if(d.test(u))return{source:"pi-mono",sessionId:e,fileName:u,sessionFile:T.join(a,u),projectPath:a,project:i,baseDir:o}}}}}return null}catch(t){return console.error("Error finding session location:",t),null}}};Nt.exports=Re});var Ft=b((xn,Rt)=>{var Us=xe(),zs=Ee(),{isValidSessionId:Ot}=U(),{trackEvent:Vs}=R(),Fe=class{constructor(e=null,s=null){this.tagService=e||new Us,this.sessionRepository=s||new zs}async getAllTags(e,s){try{let t=await this.tagService.getAllKnownTags();s.json({tags:t})}catch(t){console.error("Error getting all tags:",t),s.status(500).json({error:"Error loading tags"})}}async getSessionTags(e,s){try{let t=e.params.id;if(!Ot(t))return s.status(400).json({error:"Invalid session ID"});let n=await this.sessionRepository.findById(t);if(!n)return s.status(404).json({error:"Session not found"});let o=await this.tagService.getSessionTags(n);s.json({tags:o})}catch(t){console.error("Error getting session tags:",t),s.status(500).json({error:"Error loading session tags"})}}async setSessionTags(e,s){try{let t=e.params.id,{tags:n}=e.body;if(!Ot(t))return s.status(400).json({error:"Invalid session ID"});if(!Array.isArray(n))return s.status(400).json({error:"Tags must be an array"});if(n.length>10)return s.status(400).json({error:"Maximum 10 tags per session"});for(let i of n){if(typeof i!="string"||i.trim().length===0)return s.status(400).json({error:"Tags must be non-empty strings"});if(i.length>30)return s.status(400).json({error:"Tag length must not exceed 30 characters"})}let o=await this.sessionRepository.findById(t);if(!o)return s.status(404).json({error:"Session not found"});let r=await this.tagService.setSessionTags(o,n);Vs("TagUpdated",{sessionId:t,tagCount:r.length.toString()}),s.json({tags:r})}catch(t){if(console.error("Error setting session tags:",t),t.message==="Maximum 10 tags per session")return s.status(400).json({error:t.message});if(t.message==="Session must have a directory field")return s.status(400).json({error:"Session does not support tagging"});s.status(500).json({error:"Error saving session tags"})}}};Rt.exports=Fe});var zt=b((An,Ut)=>{var ne=require("express"),qt=require("path"),Lt=require("compression"),Bs=require("helmet"),Ws=L(),{requestTimeout:Gs,developmentCors:Js,errorHandler:Hs,notFoundHandler:Ks,telemetryLocals:Ys}=Ke(),Zs=Ct(),Xs=Mt(),Qs=Pt(),en=Ft();function tn(p={}){let e=ne();e.set("etag",!1);let s=new Zs(p.sessionService),t=new Xs(p.insightService,p.sessionService),n=new Qs,o=new en(p.tagService);return e.use((r,i,a)=>{i.setHeader("Content-Security-Policy","default-src 'self'; style-src 'self' 'unsafe-inline' https: http:; font-src 'self' https: http:; script-src 'self' 'unsafe-inline' 'unsafe-eval' https: http:; img-src 'self' data: https: http:; connect-src 'self' https: http:"),a()}),e.use(Bs({contentSecurityPolicy:!1,hsts:!1,referrerPolicy:!1,crossOriginEmbedderPolicy:!1,crossOriginOpenerPolicy:!1,crossOriginResourcePolicy:!1})),e.use(Lt({level:1,threshold:1024,filter:(r,i)=>r.path.includes("/events")&&i.getHeader("Content-Type")?.includes("application/json")?!1:Lt.filter(r,i)})),e.use(ne.json({limit:"1mb"})),e.use(ne.urlencoded({extended:!0})),e.use(Gs),e.use(Ys),Ws.NODE_ENV==="development"&&e.use(Js),e.use("/public",ne.static(qt.join(__dirname,"../public"))),e.set("view engine","ejs"),e.set("views",qt.join(__dirname,"../views")),e.get("/",s.getHomepage.bind(s)),e.get("/session/:id",s.getSessionDetail.bind(s)),e.get("/session/:id/time-analyze",s.getTimeAnalysis.bind(s)),e.get("/session/:id/export",s.exportSession.bind(s)),e.get("/api/sessions/load-more",s.loadMoreSessions.bind(s)),e.get("/api/sessions",s.getSessions.bind(s)),e.get("/api/sessions/:id/events",s.getSessionEvents.bind(s)),e.get("/api/sessions/:id/timeline",s.getTimeline.bind(s)),e.get("/api/tags",o.getAllTags.bind(o)),e.get("/api/sessions/:id/tags",o.getSessionTags.bind(o)),e.put("/api/sessions/:id/tags",o.setSessionTags.bind(o)),e.get("/session/:id/share",n.shareSession.bind(n)),e.post("/session/import",(r,i,a)=>n.getUploadMiddleware()(r,i,a),n.importSession.bind(n)),e.post("/session/:id/insight",t.generateInsight.bind(t)),e.get("/session/:id/insight",t.getInsightStatus.bind(t)),e.delete("/session/:id/insight",t.deleteInsight.bind(t)),e.use(Ks),e.use(Hs),e}Ut.exports=tn});R();var sn=zt(),qe=L(),nn=se(),Vt=sn();module.exports=Vt;if(require.main===module){let p=Vt.listen(qe.PORT,()=>{console.log(`\u{1F680} Copilot Session Viewer running at http://localhost:${qe.PORT}`),console.log(`\u{1F527} Environment: ${qe.NODE_ENV}`),console.log(`\u26A1 Active processes: ${nn.getActiveCount()}`)});process.on("SIGTERM",()=>{console.log("\u{1F4DB} SIGTERM received, closing server..."),p.close(()=>{console.log("\u2705 Server closed")})})}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qiaolei81/copilot-session-viewer",
3
- "version": "0.3.5",
3
+ "version": "0.3.6",
4
4
  "description": "Web UI for viewing GitHub Copilot CLI session logs",
5
5
  "author": "Lei Qiao <qiaolei81@gmail.com>",
6
6
  "license": "MIT",
@@ -1,21 +1,21 @@
1
- (()=>{var v=window.__PAGE_DATA||{},L=v.sessions||[],V=v.totalSessions||0,x=v.hasMore||!1,E=v.sourceHints||{},m=[...L],u={};u.copilot={offset:L.length,hasMore:x};var p=!1,i="copilot";function h(){return u[i]||(u[i]={offset:0,hasMore:!0}),u[i]}async function A(){let e=h();if(p||!e.hasMore)return;p=!0;let t=document.getElementById("loading-indicator");t.style.display="block",window.trackClick("LoadMoreClicked",{currentPage:Math.floor(e.offset/20)+1,offset:e.offset,source:i});try{let s=await fetch(`/api/sessions/load-more?offset=${h().offset}&limit=20&source=${encodeURIComponent(i)}`);if(!s.ok)throw new Error("Failed to load more sessions");let o=await s.json(),n=new Set(m.map(r=>r.id)),a=[];for(let r of o.sessions)n.has(r.id)||(m.push(r),a.push(r));h().offset+=o.sessions.length,h().hasMore=o.hasMore,await $(a),S()}catch(s){console.error("Error loading more sessions:",s)}finally{p=!1,t.style.display="none"}}function D(){return m.filter(e=>e.source===i)}function S(){let e=document.getElementById("sessions-container");e.innerHTML="";let t=D();if(t.length===0){e.innerHTML='<div style="text-align: center; color: #6e7681; padding: 40px; font-size: 14px;">No sessions found for this filter.</div>';return}let s=z(t);Object.keys(s).sort((n,a)=>a.localeCompare(n)).forEach(n=>{let a=document.createElement("div");a.className="date-group-header",a.textContent=Z(s[n][0].createdAt),e.appendChild(a);let r=document.createElement("div");r.className="recent-list",s[n].forEach(l=>{r.innerHTML+=j(l)}),e.appendChild(r)})}function T(){let e=window.pageYOffset||document.documentElement.scrollTop,t=window.innerHeight,s=document.documentElement.scrollHeight;e+t>=s-500&&h().hasMore&&!p&&A()}var y;function B(){y||(y=setTimeout(()=>{T(),y=null},100))}function F(e){e.preventDefault();let t=document.getElementById("sessionInput").value.trim();t&&(window.location.href=`/session/${t}`)}document.getElementById("sessionForm").addEventListener("submit",F);var w=document.getElementById("fileInput"),d=document.getElementById("importLink"),I=document.getElementById("importStatus");d.addEventListener("click",e=>{e.preventDefault(),w.click()});w.addEventListener("change",async e=>{let t=e.target.files[0];if(t){if(!t.name.endsWith(".zip")){g("error","\u274C Please select a .zip file");return}d.style.pointerEvents="none",d.style.opacity="0.5",d.textContent="Importing...",g("loading","Uploading and extracting session...");try{let s=new FormData;s.append("sessionZip",t);let o=await fetch("/session/import",{method:"POST",body:s}),n=await o.json();o.ok?(g("success",`\u2705 Session ${n.sessionId} imported successfully!`),setTimeout(()=>{window.location.reload()},1500)):(g("error",`\u274C Import failed: ${n.error}`),d.style.pointerEvents="auto",d.style.opacity="1",d.textContent="Import session from zip")}catch(s){g("error",`\u274C Import failed: ${s.message}`),d.style.pointerEvents="auto",d.style.opacity="1",d.textContent="Import session from zip"}finally{w.value=""}}});function g(e,t){I.className=`import-status ${e}`,I.textContent=t}function P(e){if(!e||e<0)return"\u2014";let t=Math.floor(e/1e3),s=Math.floor(t/60),o=Math.floor(s/60);if(o>0){let n=s%60;return`${o}h ${n}m`}else if(s>0){let n=t%60;return`${s}m ${n}s`}else return`${t}s`}function Z(e){let t=new Date(e),s=t.getFullYear(),o=String(t.getMonth()+1).padStart(2,"0"),n=String(t.getDate()).padStart(2,"0");return`${s}/${o}/${n}`}function N(e){if(!e)return"Unknown";let t=new Date(e),s=t.getFullYear(),o=String(t.getMonth()+1).padStart(2,"0"),n=String(t.getDate()).padStart(2,"0");return`${s}-${o}-${n}`}function z(e){let t={};return e.forEach(s=>{let o=N(s.createdAt);t[o]||(t[o]=[]),t[o].push(s)}),t}function j(e){let t="",s=e.sourceBadgeClass||"source-copilot",o=e.sourceName||"Copilot";if(t+=`<span class="status-badge ${s}" title="${o}">${o}</span>`,e.sessionStatus==="wip"&&(t+='<span class="status-badge wip" title="Session in progress">\u{1F504} WIP</span>'),e.isImported&&(t+='<span class="status-badge imported" title="Imported session">\u{1F4E5}</span>'),e.hasInsight&&(t+='<span class="status-badge insight" title="Has Agent Review">\u{1F4A1}</span>'),e.selectedModel){let C=e.selectedModel.replace("claude-","").replace("gpt-","").replace("gemini-",""),f="model-other";e.selectedModel.includes("claude")?f="model-claude":e.selectedModel.includes("gpt")?f="model-gpt":e.selectedModel.includes("gemini")&&(f="model-gemini"),t+=`<span class="status-badge model ${f}" title="Model: ${c(e.selectedModel)}">${c(C)}</span>`}e.copilotVersion&&(t+=`<span class="status-badge version" title="CLI version">${c(e.copilotVersion)}</span>`);let n="";e.summary&&e.summary!=="No summary"&&e.summary!=="Legacy session"?n=`<div class="session-summary">${c(e.summary)}</div>`:n='<div class="session-summary" style="color: #6e7681; font-style: italic;">No summary available</div>';let a="";e.workspace&&e.workspace.cwd&&(a=`
1
+ (()=>{var v=window.__PAGE_DATA||{},A=v.sessions||[],K=v.totalSessions||0,D=v.hasMore||!1,k=v.sourceHints||{},m=[...A],d={};d.copilot={offset:A.length,hasMore:D};var f=!1,w="sessionViewer.sourceFilter",S;try{S=localStorage.getItem(w)}catch{S=null}var i=S||"copilot";function g(){return d[i]||(d[i]={offset:0,hasMore:!0}),d[i]}async function B(){let e=g();if(f||!e.hasMore)return;f=!0;let t=document.getElementById("loading-indicator");t.style.display="block",window.trackClick("LoadMoreClicked",{currentPage:Math.floor(e.offset/20)+1,offset:e.offset,source:i});try{let s=await fetch(`/api/sessions/load-more?offset=${g().offset}&limit=20&source=${encodeURIComponent(i)}`);if(!s.ok)throw new Error("Failed to load more sessions");let o=await s.json(),n=new Set(m.map(r=>r.id)),a=[];for(let r of o.sessions)n.has(r.id)||(m.push(r),a.push(r));g().offset+=o.sessions.length,g().hasMore=o.hasMore,await E(a),M()}catch(s){console.error("Error loading more sessions:",s)}finally{f=!1,t.style.display="none"}}function F(){return m.filter(e=>e.source===i)}function M(){let e=document.getElementById("sessions-container");e.innerHTML="";let t=F();if(t.length===0){e.innerHTML='<div style="text-align: center; color: #6e7681; padding: 40px; font-size: 14px;">No sessions found for this filter.</div>';return}let s=R(t);Object.keys(s).sort((n,a)=>a.localeCompare(n)).forEach(n=>{let a=document.createElement("div");a.className="date-group-header",a.textContent=z(s[n][0].createdAt),e.appendChild(a);let r=document.createElement("div");r.className="recent-list",s[n].forEach(h=>{r.innerHTML+=O(h)}),e.appendChild(r)})}function P(){let e=window.pageYOffset||document.documentElement.scrollTop,t=window.innerHeight,s=document.documentElement.scrollHeight;e+t>=s-500&&g().hasMore&&!f&&B()}var y;function Z(){y||(y=setTimeout(()=>{P(),y=null},100))}function _(e){e.preventDefault();let t=document.getElementById("sessionInput").value.trim();t&&(window.location.href=`/session/${t}`)}document.getElementById("sessionForm").addEventListener("submit",_);var $=document.getElementById("fileInput"),l=document.getElementById("importLink"),H=document.getElementById("importStatus");l.addEventListener("click",e=>{e.preventDefault(),$.click()});$.addEventListener("change",async e=>{let t=e.target.files[0];if(t){if(!t.name.endsWith(".zip")){p("error","\u274C Please select a .zip file");return}l.style.pointerEvents="none",l.style.opacity="0.5",l.textContent="Importing...",p("loading","Uploading and extracting session...");try{let s=new FormData;s.append("sessionZip",t);let o=await fetch("/session/import",{method:"POST",body:s}),n=await o.json();o.ok?(p("success",`\u2705 Session ${n.sessionId} imported successfully!`),setTimeout(()=>{window.location.reload()},1500)):(p("error",`\u274C Import failed: ${n.error}`),l.style.pointerEvents="auto",l.style.opacity="1",l.textContent="Import session from zip")}catch(s){p("error",`\u274C Import failed: ${s.message}`),l.style.pointerEvents="auto",l.style.opacity="1",l.textContent="Import session from zip"}finally{$.value=""}}});function p(e,t){H.className=`import-status ${e}`,H.textContent=t}function N(e){if(!e||e<0)return"\u2014";let t=Math.floor(e/1e3),s=Math.floor(t/60),o=Math.floor(s/60);if(o>0){let n=s%60;return`${o}h ${n}m`}else if(s>0){let n=t%60;return`${s}m ${n}s`}else return`${t}s`}function z(e){let t=new Date(e),s=t.getFullYear(),o=String(t.getMonth()+1).padStart(2,"0"),n=String(t.getDate()).padStart(2,"0");return`${s}/${o}/${n}`}function j(e){if(!e)return"Unknown";let t=new Date(e),s=t.getFullYear(),o=String(t.getMonth()+1).padStart(2,"0"),n=String(t.getDate()).padStart(2,"0");return`${s}-${o}-${n}`}function R(e){let t={};return e.forEach(s=>{let o=j(s.createdAt);t[o]||(t[o]=[]),t[o].push(s)}),t}function O(e){let t="",s=e.sourceBadgeClass||"source-copilot",o=e.sourceName||"Copilot";if(t+=`<span class="status-badge ${s}" title="${o}">${o}</span>`,e.sessionStatus==="wip"&&(t+='<span class="status-badge wip" title="Session in progress">\u{1F504} WIP</span>'),e.isImported&&(t+='<span class="status-badge imported" title="Imported session">\u{1F4E5}</span>'),e.hasInsight&&(t+='<span class="status-badge insight" title="Has Agent Review">\u{1F4A1}</span>'),e.selectedModel){let I=e.selectedModel.replace("claude-","").replace("gpt-","").replace("gemini-",""),u="model-other";e.selectedModel.includes("claude")?u="model-claude":e.selectedModel.includes("gpt")?u="model-gpt":e.selectedModel.includes("gemini")&&(u="model-gemini"),t+=`<span class="status-badge model ${u}" title="Model: ${c(e.selectedModel)}">${c(I)}</span>`}e.copilotVersion&&(t+=`<span class="status-badge version" title="CLI version">${c(e.copilotVersion)}</span>`);let n="";e.summary&&e.summary!=="No summary"&&e.summary!=="Legacy session"?n=`<div class="session-summary">${c(e.summary)}</div>`:n='<div class="session-summary" style="color: #6e7681; font-style: italic;">No summary available</div>';let a="";e.workspace&&e.workspace.cwd&&(a=`
2
2
  <div class="session-info-item workspace" title="${c(e.workspace.cwd)}">
3
3
  <svg viewBox="0 0 16 16" fill="currentColor"><path d="M1.75 1A1.75 1.75 0 000 2.75v10.5C0 14.216.784 15 1.75 15h12.5A1.75 1.75 0 0016 13.25v-8.5A1.75 1.75 0 0014.25 3H7.5a.25.25 0 01-.2-.1l-.9-1.2C6.07 1.26 5.55 1 5 1H1.75z"></path></svg>
4
- <span class="session-info-value">${c(e.workspace.cwd.replace(/^\/Users\/[^/]+/,"~"))}</span>
4
+ <span class="session-info-value">${c(e.workspace.cwd)}</span>
5
5
  </div>
6
- `);let r=e.createdAt?new Date(e.createdAt).toLocaleString("en-US",{month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hour12:!1}):"unknown",l="";e.duration&&(l=`
6
+ `);let r=e.createdAt?new Date(e.createdAt).toLocaleString("en-US",{month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",hour12:!1}):"unknown",h="";e.duration&&(h=`
7
7
  <div class="session-info-item">
8
8
  <svg viewBox="0 0 16 16" fill="currentColor"><path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM7.25 12.5v-5A.75.75 0 0 1 8 6.75h2.5a.75.75 0 0 1 0 1.5H8.75v4.25a.75.75 0 0 1-1.5 0Z"></path></svg>
9
- <span class="session-info-value">${P(e.duration)}</span>
9
+ <span class="session-info-value">${N(e.duration)}</span>
10
10
  </div>
11
- `);let b=e.sessionStatus==="wip"?" recent-item-wip":"",M="";return e.tags&&e.tags.length>0&&(M=`<div class="session-tags">${e.tags.map(f=>`<span class="session-tag" style="background-color: ${U(f)}" title="${c(f)}">${c(f)}</span>`).join("")}</div>`),`
12
- <a href="/session/${e.id}" class="recent-item${b}" onclick="trackClick('SessionCardClicked', { sessionId: '${c(e.id)}', source: '${c(e.source||"unknown")}' })">
11
+ `);let T=e.sessionStatus==="wip"?" recent-item-wip":"",C="";return e.tags&&e.tags.length>0&&(C=`<div class="session-tags">${e.tags.map(u=>`<span class="session-tag" style="background-color: ${U(u)}" title="${c(u)}">${c(u)}</span>`).join("")}</div>`),`
12
+ <a href="/session/${e.id}" class="recent-item${T}" onclick="trackClick('SessionCardClicked', { sessionId: '${c(e.id)}', source: '${c(e.source||"unknown")}' })">
13
13
  <div class="session-id">
14
14
  <span class="session-id-text" title="${c(e.id)}">${c(e.id)}</span>
15
15
  </div>
16
16
  <div class="session-badges-tags">
17
17
  <div class="session-badges">${t}</div>
18
- ${M}
18
+ ${C}
19
19
  </div>
20
20
  ${n}
21
21
  <div class="session-divider"></div>
@@ -25,11 +25,11 @@
25
25
  <svg viewBox="0 0 16 16" fill="currentColor"><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm7-3.25v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5a.75.75 0 0 1 1.5 0Z"></path></svg>
26
26
  <span class="session-info-value">${r}</span>
27
27
  </div>
28
- ${l}
28
+ ${h}
29
29
  <div class="session-info-item">
30
30
  <svg viewBox="0 0 16 16" fill="currentColor"><path d="M7.72.72a.75.75 0 0 1 1.06 0l1.5 1.5a.75.75 0 0 1-1.06 1.06l-.22-.22v1.69a.75.75 0 0 1-1.5 0V3.06l-.22.22a.75.75 0 0 1-1.06-1.06ZM2 7a.75.75 0 0 0 0 1.5h3.69l-.22.22a.75.75 0 1 0 1.06 1.06l1.5-1.5a.75.75 0 0 0 0-1.06l-1.5-1.5a.75.75 0 0 0-1.06 1.06l.22.22Zm8.53-.28a.75.75 0 0 0 0 1.06l1.5 1.5a.75.75 0 1 0 1.06-1.06l-.22-.22H16a.75.75 0 0 0 0-1.5h-3.13l.22-.22a.75.75 0 0 0-1.06-1.06ZM7.72 12.22a.75.75 0 0 1 1.06 0l1.5 1.5a.75.75 0 1 1-1.06 1.06l-.22-.22v1.69a.75.75 0 0 1-1.5 0v-1.69l-.22.22a.75.75 0 0 1-1.06-1.06Z"></path></svg>
31
31
  <span class="session-info-value">${e.eventCount||0} events</span>
32
32
  </div>
33
33
  </div>
34
34
  </a>
35
- `}function c(e){let t=document.createElement("div");return t.textContent=e,t.innerHTML}var k=["#3b82f6","#10b981","#f59e0b","#ef4444","#8b5cf6","#ec4899","#06b6d4","#f97316"];function U(e){let t=0;for(let s=0;s<e.length;s++)t=e.charCodeAt(s)+((t<<5)-t);return k[Math.abs(t)%k.length]}async function O(e){try{let t=e.map(n=>fetch(`/api/sessions/${n}/tags`).then(a=>a.ok?a.json():{tags:[]}).then(a=>({id:n,tags:a.tags||[]})).catch(()=>({id:n,tags:[]}))),s=await Promise.all(t),o={};return s.forEach(({id:n,tags:a})=>{o[n]=a}),o}catch(t){return console.error("Error loading session tags:",t),{}}}async function $(e){let t=e.map(o=>o.id),s=await O(t);e.forEach(o=>{o.tags=s[o.id]||[]})}function H(e){let t=document.getElementById("sourceHint");t&&E[e]?t.innerHTML='Sessions from <span class="hint-code">'+E[e]+"</span>":t&&(t.textContent="")}function _(){let e=document.querySelectorAll(".filter-pill");H(i),e.forEach(t=>{t.addEventListener("click",async()=>{if(e.forEach(s=>s.classList.remove("active")),t.classList.add("active"),i=t.getAttribute("data-source"),H(i),window.trackClick("FilterPillClicked",{pillName:t.textContent.trim(),dataSource:i}),u[i]||(u[i]={offset:0,hasMore:!0}),u[i].offset===0&&!p){p=!0;let s=document.getElementById("sessions-container");s.innerHTML='<div style="text-align: center; color: #6e7681; padding: 40px; font-size: 14px;">\u23F3 Loading...</div>',document.getElementById("loading-indicator").style.display="none";try{let o=await fetch(`/api/sessions/load-more?offset=0&limit=20&source=${encodeURIComponent(i)}`);if(o.ok){let n=await o.json(),a=new Set(m.map(l=>l.id)),r=[];for(let l of n.sessions||[])a.has(l.id)||(m.push(l),r.push(l));u[i].offset=(n.sessions||[]).length,u[i].hasMore=n.hasMore,await $(r)}}catch(o){console.error("Failed to load sessions for source:",i,o)}finally{p=!1}}S()})})}document.addEventListener("DOMContentLoaded",async function(){await $(m),S(),window.addEventListener("scroll",B),_()});})();
35
+ `}function c(e){let t=document.createElement("div");return t.textContent=e,t.innerHTML}var L=["#3b82f6","#10b981","#f59e0b","#ef4444","#8b5cf6","#ec4899","#06b6d4","#f97316"];function U(e){let t=0;for(let s=0;s<e.length;s++)t=e.charCodeAt(s)+((t<<5)-t);return L[Math.abs(t)%L.length]}async function V(e){try{let t=e.map(n=>fetch(`/api/sessions/${n}/tags`).then(a=>a.ok?a.json():{tags:[]}).then(a=>({id:n,tags:a.tags||[]})).catch(()=>({id:n,tags:[]}))),s=await Promise.all(t),o={};return s.forEach(({id:n,tags:a})=>{o[n]=a}),o}catch(t){return console.error("Error loading session tags:",t),{}}}async function E(e){let t=e.map(o=>o.id),s=await V(t);e.forEach(o=>{o.tags=s[o.id]||[]})}function b(e){let t=document.getElementById("sourceHint");t&&k[e]?t.innerHTML='Sessions from <span class="hint-code">'+k[e]+"</span>":t&&(t.textContent="")}async function x(e){if(d[e]||(d[e]={offset:0,hasMore:!0}),d[e].offset===0&&!f){f=!0;let t=document.getElementById("sessions-container");t.innerHTML='<div style="text-align: center; color: #6e7681; padding: 40px; font-size: 14px;">\u23F3 Loading...</div>',document.getElementById("loading-indicator").style.display="none";try{let s=await fetch(`/api/sessions/load-more?offset=0&limit=20&source=${encodeURIComponent(e)}`);if(s.ok){let o=await s.json(),n=new Set(m.map(r=>r.id)),a=[];for(let r of o.sessions||[])n.has(r.id)||(m.push(r),a.push(r));d[e].offset=(o.sessions||[]).length,d[e].hasMore=o.hasMore,await E(a)}}catch(s){console.error("Failed to load sessions for source:",e,s)}finally{f=!1}}M()}function Y(){let e=document.querySelectorAll(".filter-pill");if(!new Set([...e].map(s=>s.getAttribute("data-source"))).has(i)){i="copilot";try{localStorage.setItem(w,i)}catch{}}e.forEach(s=>{s.classList.toggle("active",s.getAttribute("data-source")===i)}),b(i),e.forEach(s=>{s.addEventListener("click",async()=>{e.forEach(o=>o.classList.remove("active")),s.classList.add("active"),i=s.getAttribute("data-source");try{localStorage.setItem(w,i)}catch{}b(i),window.trackClick("FilterPillClicked",{pillName:s.textContent.trim(),dataSource:i}),await x(i)})})}document.addEventListener("DOMContentLoaded",async function(){await E(m),window.addEventListener("scroll",Z),Y(),i==="copilot"?M():await x(i)});})();
@@ -1,12 +1,12 @@
1
- (()=>{(function(){if(typeof Vue>"u"){console.error("Vue is not loaded");return}if(typeof window.VueVirtualScroller>"u"){console.error("VueVirtualScroller is not loaded");return}console.log("Initializing Vue app...");let{createApp:ue,ref:u,computed:T,onMounted:F,onBeforeUnmount:me,watch:$}=Vue,{DynamicScroller:ge,DynamicScrollerItem:pe}=window.VueVirtualScroller,G=ue({components:{DynamicScroller:ge,DynamicScrollerItem:pe},setup(){let m=u(window.__PAGE_DATA.sessionId),W=u(window.__PAGE_DATA.metadata),z=u(!1),K=()=>window.innerWidth<=640,q=u(K()?!0:localStorage.getItem("sidebarCollapsed")==="true");$(q,e=>{K()||localStorage.setItem("sidebarCollapsed",e.toString())});let x=u({}),w=u({}),U=50,J=()=>{let e=Object.keys(x.value);e.length>U&&e.slice(0,e.length-U).forEach(s=>delete x.value[s]);let t=Object.keys(w.value);t.length>U&&t.slice(0,t.length-U).forEach(s=>delete w.value[s])},S=u("all"),V=u(""),E=u(""),X=u(0),g=u(null),Y=u({start:0,end:0}),L=null;$(V,e=>{clearTimeout(L),L=setTimeout(()=>{E.value=e,e.trim()&&window.trackClick&&window.trackClick("SearchUsed",{query:e.substring(0,50),resultCount:M.value.length,sessionId:m.value})},300)}),$(S,()=>{J()}),$(E,()=>{J()});let I=u([]),Z=u(!0),Q=u(null),v=T(()=>I.value.filter(t=>t.type!=="assistant.turn_end"&&t.type!=="assistant.turn_complete").sort((t,a)=>{let s=t.timestamp?new Date(t.timestamp).getTime():0,n=a.timestamp?new Date(a.timestamp).getTime():0;return s!==n?s-n:(t._fileIndex??0)-(a._fileIndex??0)}).map((t,a)=>({...t,virtualIndex:a,stableId:t.id||`${t.timestamp}-${t.type}-${a}`}))),ve=e=>{if(!E.value.trim())return!0;let t=E.value.toLowerCase();return[e.data?.message,e.data?.text,e.data?.content,e.data?.reason,e.data?.errorType,e.data?.previousModel,e.data?.newModel].filter(Boolean).join(" ").toLowerCase().includes(t)},M=T(()=>{let e=a=>{let s=a.type||"";return s!=="tool.execution_start"&&s!=="tool.execution_complete"},t=v.value.filter(e);return E.value.trim()&&(t=t.filter(ve)),t}),A=T(()=>{let e=M.value;S.value!=="all"&&(e=e.filter(s=>s.type===S.value));let t=["assistant.turn_start","subagent.started","subagent.completed","subagent.failed"],a=e.length;return e.map((s,n)=>{let r=e[n+1],o=n===a-1,i=r&&t.includes(r.type);return{...s,filteredIndex:n,filteredTotal:a,isLastEvent:o||i}})}),fe=T(()=>{let e={};return M.value.forEach(t=>{t.type&&(e[t.type]=(e[t.type]||0)+1)}),e}),be=T(()=>{if(!E.value.trim())return null;let e=M.value.length;return e>0?`${e} result${e!==1?"s":""}`:"No matches"}),he=T(()=>{let e=Object.keys(x.value).filter(a=>x.value[a]).length,t=Object.keys(w.value).filter(a=>w.value[a]).length;return e+t}),ee=T(()=>{let e=M.value.length,t=[{type:"all",label:`All (${e})`,count:e}],a={};M.value.forEach(n=>{n.type&&(a[n.type]=(a[n.type]||0)+1)});let s=Object.entries(a).sort((n,r)=>r[1]-n[1]).map(([n,r])=>({type:n,label:`${n} (${r})`,count:r,disabled:!1}));return[...t,...s]}),R=T(()=>{let e=v.value.filter(a=>a.type==="assistant.turn_start"),t=v.value.filter(a=>a.type==="user.message");return e.map((a,s)=>{let n=s,r=new Date(a.timestamp).getTime(),o,i=e.indexOf(a)+1;i<e.length?o=new Date(e[i].timestamp).getTime():o=Date.now();let c=o-r,l=Math.floor(c/1e3),d=Math.floor(l/60),y=l%60,P=d>0?`${d}m ${y}s`:`${y}s`,p=v.value.slice(0,v.value.indexOf(a)).reverse().find(_=>_.type==="user.message"),N=p?t.indexOf(p)+1:0;return{id:n,index:a.virtualIndex,originalTurnId:a.data?.turnId,timestamp:a.timestamp,duration:P,message:p?.data?.content||p?.data?.transformedContent||"",userReqNumber:N}})}),Te=T(()=>{let e=[],t=new Map;return R.value.forEach(a=>{let s=a.userReqNumber||0;if(!t.has(s)){let n={reqNumber:s,message:a.message,turns:[]};t.set(s,n),e.push(n)}t.get(s).turns.push(a)}),e}),ye=(e,t)=>e?e.length<=t?e:e.substring(0,t)+"\u2026":"",xe=T(()=>{let e=v.value,t=new Map,a=new Map,s=0;for(let o of e)if(o.type==="subagent.started"){let i=o.data?.toolCallId;i&&a.set(i,{name:o.data?.agentDisplayName||o.data?.agentName||"SubAgent",colorIndex:s++})}for(let o of e)if(o.type==="assistant.message"&&o.data?.subAgentName&&o.data?.subAgentId){let i=o.data.subAgentId;a.has(i)||a.set(i,{name:o.data.subAgentName,colorIndex:s++}),t.set(o.stableId,i)}if(a.size===0)return{ownerMap:t,subagentInfo:a};let n=new Map;for(let o of e)o.id&&n.set(o.id,o);for(let o of e)if(o.type==="assistant.message"){let i=o.data?.parentToolCallId;i&&a.has(i)&&t.set(o.stableId,i)}for(let o of e){if(o.type!=="reasoning")continue;let i=o.parentId,c=0;for(;i&&c<10;){let l=n.get(i);if(!l)break;if(l.type==="assistant.message"){let d=l.data?.parentToolCallId;d&&a.has(d)&&t.set(o.stableId,d);break}i=l.parentId,c++}}let r=new Map;for(let o of e){if(o.type!=="tool.execution_start")continue;let i=o.parentId,c=0;for(;i&&c<10;){let l=n.get(i);if(!l)break;if(l.type==="assistant.message"){let d=l.data?.parentToolCallId;if(d&&a.has(d)){t.set(o.stableId,d);let y=o.data?.toolCallId;y&&r.set(y,d)}break}i=l.parentId,c++}}for(let o of e){if(o.type!=="tool.execution_complete")continue;let i=o.data?.toolCallId;i&&r.has(i)&&t.set(o.stableId,r.get(i))}for(let o of e){if(o.type!=="tool.invocation")continue;let i=o.data?.parentToolCallId;i&&a.has(i)&&t.set(o.stableId,i)}return{ownerMap:t,subagentInfo:a}}),we=e=>{if(!e)return"";let t=new Date(e),a=String(t.getHours()).padStart(2,"0"),s=String(t.getMinutes()).padStart(2,"0"),n=String(t.getSeconds()).padStart(2,"0");return`${a}:${s}:${n}`},f=new Map,te=200,Ie=e=>{if(!e)return"";if(f.has(e))return f.get(e);try{let t=e.replace(/\\r\\n/g,`
1
+ (()=>{(function(){if(typeof Vue>"u"){console.error("Vue is not loaded");return}if(typeof window.VueVirtualScroller>"u"){console.error("VueVirtualScroller is not loaded");return}console.log("Initializing Vue app...");let{createApp:ue,ref:u,computed:h,onMounted:F,onBeforeUnmount:me,watch:$}=Vue,{DynamicScroller:ge,DynamicScrollerItem:pe}=window.VueVirtualScroller,G=ue({components:{DynamicScroller:ge,DynamicScrollerItem:pe},setup(){let m=u(window.__PAGE_DATA.sessionId),W=u(window.__PAGE_DATA.metadata),z=u(!1),K=()=>window.innerWidth<=640,q=u(K()?!0:localStorage.getItem("sidebarCollapsed")==="true");$(q,t=>{K()||localStorage.setItem("sidebarCollapsed",t.toString())});let x=u({}),w=u({}),U=50,J=()=>{let t=Object.keys(x.value);t.length>U&&t.slice(0,t.length-U).forEach(s=>delete x.value[s]);let e=Object.keys(w.value);e.length>U&&e.slice(0,e.length-U).forEach(s=>delete w.value[s])},k=u("all"),V=u(""),E=u(""),X=u(0),g=u(null),Y=u({start:0,end:0}),L=null;$(V,t=>{clearTimeout(L),L=setTimeout(()=>{E.value=t,t.trim()&&window.trackClick&&window.trackClick("SearchUsed",{query:t.substring(0,50),resultCount:M.value.length,sessionId:m.value})},300)}),$(k,()=>{J()}),$(E,()=>{J()});let S=u([]),Z=u(!0),Q=u(null),v=h(()=>S.value.filter(e=>e.type!=="assistant.turn_end"&&e.type!=="assistant.turn_complete").sort((e,a)=>{let s=e.timestamp?new Date(e.timestamp).getTime():0,n=a.timestamp?new Date(a.timestamp).getTime():0;return s!==n?s-n:(e._fileIndex??0)-(a._fileIndex??0)}).map((e,a)=>({...e,virtualIndex:a,stableId:e.id||`${e.timestamp}-${e.type}-${a}`}))),ve=t=>{if(!E.value.trim())return!0;let e=E.value.toLowerCase();return[t.data?.message,t.data?.text,t.data?.content,t.data?.reason,t.data?.reasoningText,t.data?.errorType,t.data?.previousModel,t.data?.newModel].filter(Boolean).join(" ").toLowerCase().includes(e)},M=h(()=>{let t=a=>{let s=a.type||"";return s!=="tool.execution_start"&&s!=="tool.execution_complete"},e=v.value.filter(t);return E.value.trim()&&(e=e.filter(ve)),e}),A=h(()=>{let t=M.value;k.value!=="all"&&(t=t.filter(s=>s.type===k.value));let e=["assistant.turn_start","subagent.started","subagent.completed","subagent.failed"],a=t.length;return t.map((s,n)=>{let i=t[n+1],o=n===a-1,r=i&&e.includes(i.type);return{...s,filteredIndex:n,filteredTotal:a,isLastEvent:o||r}})}),fe=h(()=>{let t={};return M.value.forEach(e=>{e.type&&(t[e.type]=(t[e.type]||0)+1)}),t}),be=h(()=>{if(!E.value.trim())return null;let t=M.value.length;return t>0?`${t} result${t!==1?"s":""}`:"No matches"}),Te=h(()=>{let t=Object.keys(x.value).filter(a=>x.value[a]).length,e=Object.keys(w.value).filter(a=>w.value[a]).length;return t+e}),ee=h(()=>{let t=M.value.length,e=[{type:"all",label:`All (${t})`,count:t}],a={};M.value.forEach(n=>{n.type&&(a[n.type]=(a[n.type]||0)+1)});let s=Object.entries(a).sort((n,i)=>i[1]-n[1]).map(([n,i])=>({type:n,label:`${n} (${i})`,count:i,disabled:!1}));return[...e,...s]}),R=h(()=>{let t=v.value.filter(a=>a.type==="assistant.turn_start"),e=v.value.filter(a=>a.type==="user.message");return t.map((a,s)=>{let n=s,i=new Date(a.timestamp).getTime(),o,r=t.indexOf(a)+1;r<t.length?o=new Date(t[r].timestamp).getTime():o=Date.now();let c=o-i,l=Math.floor(c/1e3),d=Math.floor(l/60),y=l%60,B=d>0?`${d}m ${y}s`:`${y}s`,p=v.value.slice(0,v.value.indexOf(a)).reverse().find(_=>_.type==="user.message"),N=p?e.indexOf(p)+1:0;return{id:n,index:a.virtualIndex,originalTurnId:a.data?.turnId,timestamp:a.timestamp,duration:B,message:p?.data?.content||p?.data?.transformedContent||"",userReqNumber:N}})}),he=h(()=>{let t=[],e=new Map;return R.value.forEach(a=>{let s=a.userReqNumber||0;if(!e.has(s)){let n={reqNumber:s,message:a.message,turns:[]};e.set(s,n),t.push(n)}e.get(s).turns.push(a)}),t}),ye=(t,e)=>t?t.length<=e?t:t.substring(0,e)+"\u2026":"",xe=h(()=>{let t=v.value,e=new Map,a=new Map,s=0;for(let o of t)if(o.type==="subagent.started"){let r=o.data?.toolCallId;r&&a.set(r,{name:o.data?.agentDisplayName||o.data?.agentName||"SubAgent",colorIndex:s++})}for(let o of t)if(o.type==="assistant.message"&&o.data?.subAgentName&&o.data?.subAgentId){let r=o.data.subAgentId;a.has(r)||a.set(r,{name:o.data.subAgentName,colorIndex:s++}),e.set(o.stableId,r)}if(a.size===0)return{ownerMap:e,subagentInfo:a};let n=new Map;for(let o of t)o.id&&n.set(o.id,o);for(let o of t)if(o.type==="assistant.message"){let r=o.data?.parentToolCallId;r&&a.has(r)&&e.set(o.stableId,r)}for(let o of t){if(o.type!=="reasoning")continue;let r=o.parentId,c=0;for(;r&&c<10;){let l=n.get(r);if(!l)break;if(l.type==="assistant.message"){let d=l.data?.parentToolCallId;d&&a.has(d)&&e.set(o.stableId,d);break}r=l.parentId,c++}}let i=new Map;for(let o of t){if(o.type!=="tool.execution_start")continue;let r=o.parentId,c=0;for(;r&&c<10;){let l=n.get(r);if(!l)break;if(l.type==="assistant.message"){let d=l.data?.parentToolCallId;if(d&&a.has(d)){e.set(o.stableId,d);let y=o.data?.toolCallId;y&&i.set(y,d)}break}r=l.parentId,c++}}for(let o of t){if(o.type!=="tool.execution_complete")continue;let r=o.data?.toolCallId;r&&i.has(r)&&e.set(o.stableId,i.get(r))}for(let o of t){if(o.type!=="tool.invocation")continue;let r=o.data?.parentToolCallId;r&&a.has(r)&&e.set(o.stableId,r)}return{ownerMap:e,subagentInfo:a}}),we=t=>{if(!t)return"";let e=new Date(t),a=String(e.getHours()).padStart(2,"0"),s=String(e.getMinutes()).padStart(2,"0"),n=String(e.getSeconds()).padStart(2,"0");return`${a}:${s}:${n}`},Se=t=>{if(!t)return"";let e=new Date(t),a=String(e.getHours()).padStart(2,"0"),s=String(e.getMinutes()).padStart(2,"0"),n=String(e.getSeconds()).padStart(2,"0"),i=String(e.getMilliseconds()).padStart(3,"0");return`${a}:${s}:${n}.${i}`},f=new Map,te=200,Ce=t=>{if(!t)return"";if(f.has(t))return f.get(t);try{let e=t.replace(/\\r\\n/g,`
2
2
  `).replace(/\\n/g,`
3
- `).replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\"),a={ALLOWED_TAGS:["p","br","strong","em","code","pre","a","ul","ol","li","h1","h2","h3","h4","h5","h6","blockquote","table","thead","tbody","tr","th","td","hr","del","span","div","mark"],ALLOWED_ATTR:["href","style","class"],ALLOW_DATA_ATTR:!1,ALLOWED_URI_REGEXP:/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.-]+(?:[^a-z+.\-:]|$))/i},s=t.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);if(s){let o=s[1],i=s[2],c=o.split(`
4
- `).filter(p=>p.trim()&&p.includes(":")).map(p=>{let N=p.indexOf(":"),_=p.substring(0,N).trim(),tt=p.substring(N+1).trim();return{key:_,value:tt}}),l='<table style="margin-bottom: 16px; border-collapse: collapse; width: 100%;"><tbody>';c.forEach(p=>{let N=DOMPurify.sanitize(p.key,{ALLOWED_TAGS:[]}),_=DOMPurify.sanitize(p.value,{ALLOWED_TAGS:[]});l+=`<tr><td style="padding: 4px 12px; border: 1px solid #30363d; font-weight: 600; color: #7d8590;">${N}</td><td style="padding: 4px 12px; border: 1px solid #30363d;">${_}</td></tr>`}),l+="</tbody></table>";let d=marked.parse(i),y=DOMPurify.sanitize(d,a),P=l+y;if(f.size>=te){let p=f.keys().next().value;f.delete(p)}return f.set(e,P),P}let n=marked.parse(t),r=DOMPurify.sanitize(n,a);if(f.size>=te){let o=f.keys().next().value;f.delete(o)}return f.set(e,r),r}catch{return e}},Ce=e=>{let t={...x.value},a=!!t[e];t[e]?delete t[e]:t[e]=!0,x.value=t,window.trackClick&&window.trackClick("EventExpanded",{eventType:"tool",action:a?"collapse":"expand",sessionId:m.value})},ke=(e,t)=>{if(!t||!t.trim()||!e)return e;let a=t.trim(),s=re(a).replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),n=document.createElement("div");n.innerHTML=e;let r=o=>{if(o.nodeType===Node.TEXT_NODE){let i=o.textContent,c=new RegExp(`(${s})`,"gi");if(c.test(i)){let l=i.replace(c,'<mark class="search-highlight">$1</mark>'),d=document.createElement("span");d.innerHTML=l,o.parentNode.replaceChild(d,o)}}else o.nodeType===Node.ELEMENT_NODE&&o.tagName!=="SCRIPT"&&o.tagName!=="STYLE"&&Array.from(o.childNodes).forEach(r)};return Array.from(n.childNodes).forEach(r),n.innerHTML},Se=e=>{let t={...w.value},a=!!t[e];t[e]?delete t[e]:t[e]=!0,w.value=t,window.trackClick&&window.trackClick("EventExpanded",{eventType:"content",action:a?"collapse":"expand",sessionId:m.value})},Ee=e=>e?e.split(`
5
- `).length>20||e.length>2e3:!1,Me=e=>{let t=e.split(`
6
- `);return t.length<=20?e:t.slice(0,20).join(`
3
+ `).replace(/\\t/g," ").replace(/\\"/g,'"').replace(/\\\\/g,"\\"),a={ALLOWED_TAGS:["p","br","strong","em","code","pre","a","ul","ol","li","h1","h2","h3","h4","h5","h6","blockquote","table","thead","tbody","tr","th","td","hr","del","span","div","mark"],ALLOWED_ATTR:["href","style","class"],ALLOW_DATA_ATTR:!1,ALLOWED_URI_REGEXP:/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.-]+(?:[^a-z+.\-:]|$))/i},s=e.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);if(s){let o=s[1],r=s[2],c=o.split(`
4
+ `).filter(p=>p.trim()&&p.includes(":")).map(p=>{let N=p.indexOf(":"),_=p.substring(0,N).trim(),at=p.substring(N+1).trim();return{key:_,value:at}}),l='<table style="margin-bottom: 16px; border-collapse: collapse; width: 100%;"><tbody>';c.forEach(p=>{let N=DOMPurify.sanitize(p.key,{ALLOWED_TAGS:[]}),_=DOMPurify.sanitize(p.value,{ALLOWED_TAGS:[]});l+=`<tr><td style="padding: 4px 12px; border: 1px solid #30363d; font-weight: 600; color: #7d8590;">${N}</td><td style="padding: 4px 12px; border: 1px solid #30363d;">${_}</td></tr>`}),l+="</tbody></table>";let d=marked.parse(r),y=DOMPurify.sanitize(d,a),B=l+y;if(f.size>=te){let p=f.keys().next().value;f.delete(p)}return f.set(t,B),B}let n=marked.parse(e),i=DOMPurify.sanitize(n,a);if(f.size>=te){let o=f.keys().next().value;f.delete(o)}return f.set(t,i),i}catch{return t}},Ie=t=>{let e={...x.value},a=!!e[t];e[t]?delete e[t]:e[t]=!0,x.value=e,window.trackClick&&window.trackClick("EventExpanded",{eventType:"tool",action:a?"collapse":"expand",sessionId:m.value})},ke=(t,e)=>{if(!e||!e.trim()||!t)return t;let a=e.trim(),s=ie(a).replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),n=document.createElement("div");n.innerHTML=t;let i=o=>{if(o.nodeType===Node.TEXT_NODE){let r=o.textContent,c=new RegExp(`(${s})`,"gi");if(c.test(r)){let l=r.replace(c,'<mark class="search-highlight">$1</mark>'),d=document.createElement("span");d.innerHTML=l,o.parentNode.replaceChild(d,o)}}else o.nodeType===Node.ELEMENT_NODE&&o.tagName!=="SCRIPT"&&o.tagName!=="STYLE"&&Array.from(o.childNodes).forEach(i)};return Array.from(n.childNodes).forEach(i),n.innerHTML},Ee=t=>{let e={...w.value},a=!!e[t];e[t]?delete e[t]:e[t]=!0,w.value=e,window.trackClick&&window.trackClick("EventExpanded",{eventType:"content",action:a?"collapse":"expand",sessionId:m.value})},Me=t=>t?t.split(`
5
+ `).length>20||t.length>2e3:!1,Ne=t=>{let e=t.split(`
6
+ `);return e.length<=20?t:e.slice(0,20).join(`
7
7
  `)+`
8
8
 
9
- ...`},Ne=(e,t)=>{if(t?.data?.badgeLabel&&t?.data?.badgeClass)return{label:t.data.badgeLabel,class:t.data.badgeClass};if(e==="message"&&t?.data?.role==="toolResult")return{label:"TOOL RESULT",class:"badge-tool"};if(e==="session.model_change")return{label:"MODEL CHANGE",class:"badge-session"};if(e==="session.truncation")return{label:"TRUNCATION",class:"badge-truncation"};if(e==="session.compaction_start"||e==="session.compaction_complete")return{label:"COMPACTION",class:"badge-compaction"};if(e==="system.notification")return{label:"SYSTEM",class:"badge-system"};let s=(e||"").split(".")[0]||"unknown";return{user:{label:"USER",class:"badge-user"},assistant:{label:"ASSISTANT",class:"badge-assistant"},reasoning:{label:"REASONING",class:"badge-reasoning"},turn:{label:"TURN",class:"badge-turn"},tool:{label:"TOOL",class:"badge-tool"},subagent:{label:"SUBAGENT",class:"badge-subagent"},skill:{label:"SKILL",class:"badge-skill"},session:{label:"SESSION",class:"badge-session"},error:{label:"ERROR",class:"badge-error"},abort:{label:"ABORT",class:"badge-error"}}[s]||{label:s.toUpperCase(),class:"badge-info"}},Le=e=>{if(!e.complete)return{icon:"\u23F3",color:"tool-status-running",text:""};let t=e.complete.data||{};return t.error||t.isError?{icon:"\u274C",color:"tool-status-error",text:""}:{icon:"\u2713",color:"tool-status-success",text:""}},Ae=e=>{if(!e.complete?.data?.error)return"";let t=e.complete.data.error;if(typeof t=="object"&&t.message)return t.message;if(typeof t=="string"){try{let a=JSON.parse(t);if(a.message)return a.message}catch{}return t}return String(t)},Re=e=>{if(!e.complete)return"";let t=new Date(e.start.timestamp).getTime(),s=new Date(e.complete.timestamp).getTime()-t;return s>=100?`${(s/1e3).toFixed(1)}s`:""},De=e=>{if(!e.start)return"";let t=e.start.data?.arguments||{},a=e.start.data?.toolName||e.tool||"",s="";if(a==="bash"||a==="exec")s=t.command||t.description||"";else if(a==="ask_user")s=t.question||t.message||"";else if(a==="read"||a==="write"||a==="edit")s=t.file_path||t.path||"";else if(a==="view")s=t.path||t.file||"";else if(a==="create")s=t.path||t.name||"";else if(a==="report_intent")s=t.intent||t.message||"";else if(a==="web_search")s=t.query||"";else if(a==="web_fetch")s=t.url||"";else if(a==="browser"){let n=t.action||"",r=t.targetUrl||t.url||"";s=r?`${n} ${r}`:n}else s=t.description||t.command||t.message||t.path||t.file_path||t.query||"";return s&&s.length>200&&(s=s.substring(0,200)+"..."),s},Oe=e=>e.data?.tools&&e.data.tools.length>0,_e=e=>e.data?.tools&&Array.isArray(e.data.tools)?e.data.tools.filter(t=>t&&typeof t=="object"&&t.name).map(t=>{let a=t.result!==void 0||t.status==="completed"||t.status==="error";return{tool:t.name,start:{data:{toolName:t.name,arguments:t.input||t.arguments||{}}},complete:a?{data:{result:t.result,error:t.status==="error"?t.error:null}}:null}}):[],ae=["#58a6ff","#f0883e","#a371f7","#3fb950","#f778ba","#79c0ff","#d29922","#56d4dd"],$e=e=>{let t=0;for(let a=0;a<e.length;a++){let s=e.charCodeAt(a);t=(t<<5)-t+s,t=t&t}return t},se=e=>{let{ownerMap:t,subagentInfo:a}=xe.value;if(e.type==="subagent.started"||e.type==="subagent.completed"||e.type==="subagent.failed"){let r=e.data?.toolCallId;if(r&&a.has(r)){let o=a.get(r);return{name:o.name,toolCallId:r,colorIndex:o.colorIndex}}return null}if(e._subagent){let r=e._subagent.id,o=e._subagent.name;if(a.has(r)){let i=a.get(r);return{name:i.name,toolCallId:r,colorIndex:i.colorIndex}}return{name:o,toolCallId:r,colorIndex:Math.abs($e(r))}}if(e.data?.subAgentId){let r=e.data.subAgentId,o=a.get(r);if(o)return{name:o.name,toolCallId:r,colorIndex:o.colorIndex}}let s=t.get(e.stableId);if(!s)return null;let n=a.get(s);return n?{name:n.name,toolCallId:s,colorIndex:n.colorIndex}:null},qe=e=>{let t=se(e);return t?ae[t.colorIndex%ae.length]:null},Ue=e=>{if(window.trackClick){let t=ee.value.find(a=>a.type===e);window.trackClick("EventFilterClicked",{filterType:e,filterLabel:t?t.label:e,sessionId:m.value})}S.value=e},oe=e=>{V.value="",S.value="all",X.value=e.id,Vue.nextTick(()=>{if(g.value){let t=A.value.findIndex(a=>a.virtualIndex===e.index);if(t>=0){let a=s=>{s<=0||!g.value||(g.value.scrollToItem(t),setTimeout(()=>a(s-1),100))};setTimeout(()=>a(3),50)}}})},Be=()=>{if(!g.value)return;let e=t=>{t<=0||!g.value||(g.value.scrollToItem(0),setTimeout(()=>e(t-1),100))};e(3)},Pe=()=>{if(!g.value)return;let e=A.value.length-1,t=a=>{a<=0||!g.value||(g.value.scrollToItem(e),setTimeout(()=>t(a-1),100))};t(5)},ne=e=>{window.trackClick&&window.trackClick("TurnClicked",{turnNumber:e,sessionId:m.value});let t=R.value.find(a=>a.id===e);if(t){let a=`UserReq${t.userReqNumber}_Turn${t.id}`,s=`${window.location.pathname}?eventType=assistant.turn_start&eventName=${a}`;window.history.pushState({},"",s),oe(t)}},ze=e=>{if(!e)return"";let t=e.replace(/\/$/,"").split("/");return t[t.length-1]||e},Ve=e=>{let t=R.value.find(s=>s.index===e);if(!t)return"?";let a=t.originalTurnId??t.id;return t.userReqNumber>0?`${t.userReqNumber} - Turn ${a}`:`Turn ${a}`},He=e=>R.value.find(a=>a.index===e)?.duration||null,re=e=>{let t=document.createElement("div");return t.textContent=e,t.innerHTML},je=e=>e?new Date(e).toLocaleString():"N/A",Fe=async()=>{console.log("[Export] exportSession called"),window.trackClick&&window.trackClick("ExportClicked",{sessionId:m.value}),z.value=!0;try{console.log("[Export] Fetching:",`/session/${m.value}/export`);let e=await fetch(`/session/${m.value}/export`);if(console.log("[Export] Response received:",e.status,e.ok),console.log("[Export] Response received:",e.status,e.ok),!e.ok)throw new Error("Share failed");console.log("[Export] Creating blob...");let t=await e.blob();console.log("[Export] Blob size:",t.size,"type:",t.type);let a=window.URL.createObjectURL(t);console.log("[Export] Creating download link...");let s=document.createElement("a");s.href=a,s.download=`session-${m.value}.zip`,document.body.appendChild(s),s.click(),console.log("[Export] Download triggered"),window.URL.revokeObjectURL(a),document.body.removeChild(s),console.log("[Export] Showing success feedback...");let n="\u{1F4E4} Share Session",r="\u2713 Downloaded!",o=document.querySelector(".export-btn");o&&(o.textContent=r,o.style.background="#238636",console.log("[Export] Button text updated to:",o.textContent),setTimeout(()=>{o.textContent=n,o.style.background="",console.log("[Export] Button text restored")},2e3))}catch(e){console.error("[Export] Share session error:",e),alert("Failed to share session: "+e.message)}finally{z.value=!1,console.log("[Export] Export complete")}};F(async()=>{try{console.log("[Navigation] Starting event loading...");let a=await fetch(`/api/sessions/${m.value}/events`);if(!a.ok)throw new Error(`Failed to load events: ${a.statusText}`);let s=await a.json();if(Array.isArray(s))I.value=s;else if(s.events&&Array.isArray(s.events))I.value=s.events,console.log("[Navigation] Pagination:",s.pagination);else throw new Error("Invalid response format");if(console.log("[Navigation] Events loaded:",I.value.length),I.value.length>0){let c=I.value[I.value.length-1],l=c.timestamp||c.time||c.data?.timestamp;l&&(W.value.updated=new Date(l))}let n=new URLSearchParams(window.location.search),r=n.get("eventType"),o=n.get("eventName"),i=n.get("eventTimestamp");console.log("[Navigation] URL params:",r,o,i),r&&o&&(console.log("[Navigation] Waiting for Vue to render..."),Vue.nextTick(()=>{console.log("[Navigation] nextTick - flatEvents count:",v.value?.length);let c=null;if(r==="assistant.turn_start"){let l=o.match(/UserReq(\d+)_Turn(\d+)/);if(l){let d=parseInt(l[2],10);if(!isNaN(d)){console.log("[Navigation] Jumping to turn:",d),ne(d);return}}}else r==="subagent.started"?(console.log("[Navigation] Searching for subagent:",o,"timestamp:",i),i&&(c=v.value.find(l=>l.type==="subagent.started"&&l.timestamp===i)),c||(c=v.value.find(l=>l.type==="subagent.started"&&(l.data?.agentDisplayName===o||l.data?.agentName===o||l.data?.label===o))),console.log("[Navigation] Target event found:",c?"YES":"NO","virtualIndex:",c?.virtualIndex)):c=v.value.find(l=>l.type===r);if(c){let l=A.value.findIndex(d=>d.virtualIndex===c.virtualIndex);if(console.log("[Navigation] Target in filteredEvents at index:",l),l>=0&&g.value){console.log("[Navigation] Scrolling to index:",l);let d=y=>{y<=0||!g.value||(g.value.scrollToItem(l),setTimeout(()=>d(y-1),100))};setTimeout(()=>d(3),50)}else console.log("[Navigation] Failed - targetIndex:",l,"scrollerRef:",!!g.value)}else console.log("[Navigation] Target event not found")}))}catch(a){console.error("Error loading events:",a),Q.value=a.message}finally{Z.value=!1}window.addEventListener("keydown",a=>{a.ctrlKey&&a.key==="b"&&(a.preventDefault(),q.value=!q.value)}),window.marked&&marked.setOptions({breaks:!0,gfm:!0});let e=()=>{if(!g.value)return;let a=null;if(g.value.$el&&typeof g.value.$el.querySelector=="function"?a=g.value.$el.querySelector(".vue-recycle-scroller"):g.value.querySelector&&typeof g.value.querySelector=="function"&&(a=g.value.querySelector(".vue-recycle-scroller")),a||(a=document.querySelector(".vue-recycle-scroller")),a){let s=a.scrollTop,n=a.clientHeight,r=80,o=Math.floor(s/r),i=Math.ceil(n/r),c=Math.min(o+i,A.value.length),l=Math.max(1,o+1),d=Math.max(1,c);Y.value={start:Math.min(l,d),end:d}}},t=null;setTimeout(()=>{e();let a=document.querySelector(".vue-recycle-scroller");a&&(a.addEventListener("scroll",e),t=()=>{a.removeEventListener("scroll",e)})},500),me(()=>{L&&(clearTimeout(L),L=null),t&&t(),x.value={},w.value={},f.clear()})});let D=u([]),H=u([]),O=u(!1),b=u([]),C=u(""),j=u(null),h=u(""),k=u(!1),B=u([]),ie=u(0),le=["#3b82f6","#10b981","#f59e0b","#ef4444","#8b5cf6","#ec4899","#06b6d4","#f97316"],Ge=e=>{let t=0;for(let a=0;a<e.length;a++)t=e.charCodeAt(a)+((t<<5)-t);return le[Math.abs(t)%le.length]},We=async()=>{try{let e=await fetch(`/api/sessions/${m.value}/tags`);if(e.ok){let t=await e.json();D.value=t.tags||[]}}catch(e){console.error("Error loading tags:",e)}},de=async()=>{try{let e=await fetch("/api/tags");if(e.ok){let t=await e.json();H.value=t.tags||[]}}catch(e){console.error("Error loading all tags:",e)}},Ke=async e=>{try{window.trackClick&&e.filter(s=>!D.value.includes(s)).forEach(s=>{window.trackClick("TagAdded",{sessionId:m.value,tag:s})});let t=await fetch(`/api/sessions/${m.value}/tags`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({tags:e})});if(t.ok){let a=await t.json();return D.value=a.tags||[],h.value="",!0}else{let a=await t.json();return h.value=a.error||"Failed to save tags",!1}}catch(t){return console.error("Error saving tags:",t),h.value="Network error",!1}},Je=()=>{b.value=[...D.value],O.value=!0,h.value="",setTimeout(()=>{j.value&&j.value.focus()},10)},Xe=()=>{O.value=!1,b.value=[],C.value="",k.value=!1,h.value=""},ce=()=>{let e=C.value.trim().toLowerCase();if(e){if(e.length>30){h.value="Tag must be 30 characters or less";return}if(b.value.length>=10){h.value="Maximum 10 tags per session";return}if(b.value.includes(e)){h.value="Tag already added",C.value="";return}b.value.push(e),C.value="",k.value=!1,h.value=""}},Ye=e=>{b.value=b.value.filter(t=>t!==e),h.value=""},Ze=()=>{let e=C.value.trim().toLowerCase();if(!e){k.value=!1,B.value=[];return}let t=H.value.filter(a=>a.toLowerCase().includes(e)&&!b.value.includes(a)).slice(0,5);t.length>0?(k.value=!0,B.value=t,ie.value=0):(k.value=!1,B.value=[])},Qe=e=>{C.value=e,ce()},et=async()=>{setTimeout(async()=>{if(!O.value)return;await Ke(b.value)&&(O.value=!1,b.value=[],C.value="",k.value=!1,await de())},200)};return F(async()=>{await We(),await de()}),{sessionId:m,metadata:W,exporting:z,sidebarCollapsed:q,expandedTools:x,expandedContent:w,expansionCount:he,currentFilter:S,searchText:V,currentTurnIndex:X,scrollerRef:g,visibleRange:Y,loadedEvents:I,eventsLoading:Z,eventsError:Q,flatEvents:v,filteredEvents:A,eventCounts:fe,filters:ee,turns:R,userReqs:Te,truncateText:ye,formatTime:we,formatDateTime:je,renderMarkdown:Ie,highlightSearchText:ke,toggleTool:Ce,toggleContent:Se,isContentTooLong:Ee,truncateContent:Me,getBadgeInfo:Ne,getToolStatus:Le,getToolErrorMessage:Ae,getToolDuration:Re,getToolCommand:De,hasTools:Oe,getToolGroups:_e,getSubagentInfo:se,getSubagentColor:qe,setFilter:Ue,scrollToTurn:oe,scrollToTop:Be,scrollToBottom:Pe,jumpToTurn:ne,getTurnNumber:Ve,getTurnDuration:He,repoBasename:ze,escapeHtml:re,exportSession:Fe,searchResultCount:be,sessionTags:D,allTags:H,tagsEditing:O,editingTags:b,tagInputValue:C,tagInputRef:j,tagsError:h,showAutocomplete:k,autocompleteOptions:B,autocompleteSelectedIndex:ie,getTagColor:Ge,startEditTags:Je,cancelEditTags:Xe,addTag:ce,removeTagFromEdit:Ye,updateAutocomplete:Ze,selectAutocompleteOption:Qe,saveTagsOnBlur:et}},template:`
9
+ ...`},Le=(t,e)=>{if(e?.data?.badgeLabel&&e?.data?.badgeClass)return{label:e.data.badgeLabel,class:e.data.badgeClass};if(t==="message"&&e?.data?.role==="toolResult")return{label:"TOOL RESULT",class:"badge-tool"};if(t==="session.model_change")return{label:"MODEL CHANGE",class:"badge-session"};if(t==="session.truncation")return{label:"TRUNCATION",class:"badge-truncation"};if(t==="session.compaction_start"||t==="session.compaction_complete")return{label:"COMPACTION",class:"badge-compaction"};if(t==="system.notification")return{label:"SYSTEM",class:"badge-system"};let s=(t||"").split(".")[0]||"unknown";return{user:{label:"USER",class:"badge-user"},assistant:{label:"ASSISTANT",class:"badge-assistant"},reasoning:{label:"REASONING",class:"badge-reasoning"},turn:{label:"TURN",class:"badge-turn"},tool:{label:"TOOL",class:"badge-tool"},subagent:{label:"SUBAGENT",class:"badge-subagent"},skill:{label:"SKILL",class:"badge-skill"},session:{label:"SESSION",class:"badge-session"},error:{label:"ERROR",class:"badge-error"},abort:{label:"ABORT",class:"badge-error"}}[s]||{label:s.toUpperCase(),class:"badge-info"}},Ae=t=>{if(!t.complete)return{icon:"\u23F3",color:"tool-status-running",text:""};let e=t.complete.data||{};return e.error||e.isError?{icon:"\u274C",color:"tool-status-error",text:""}:{icon:"\u2713",color:"tool-status-success",text:""}},Re=t=>{if(!t.complete?.data?.error)return"";let e=t.complete.data.error;if(typeof e=="object"&&e.message)return e.message;if(typeof e=="string"){try{let a=JSON.parse(e);if(a.message)return a.message}catch{}return e}return String(e)},De=t=>{if(!t.complete)return"";let e=new Date(t.start.timestamp).getTime(),s=new Date(t.complete.timestamp).getTime()-e;return s>=100?`${parseFloat((s/1e3).toPrecision(3))}s`:""},st=t=>{let e={};if(t.start?.timestamp&&(e.startTime=t.start.timestamp),t.complete?.timestamp&&(e.endTime=t.complete.timestamp),e.startTime&&e.endTime){let a=new Date(e.endTime).getTime()-new Date(e.startTime).getTime();a>=0&&(e.duration=`${parseFloat((a/1e3).toPrecision(3))}s (${a}ms)`)}return e},Oe=t=>{if(!t.start)return"";let e=t.start.data?.arguments||{},a=t.start.data?.toolName||t.tool||"",s="";if(a==="bash"||a==="exec")s=e.command||e.description||"";else if(a==="ask_user")s=e.question||e.message||"";else if(a==="read"||a==="write"||a==="edit")s=e.file_path||e.path||"";else if(a==="view")s=e.path||e.file||"";else if(a==="create")s=e.path||e.name||"";else if(a==="report_intent")s=e.intent||e.message||"";else if(a==="web_search")s=e.query||"";else if(a==="web_fetch")s=e.url||"";else if(a==="browser"){let n=e.action||"",i=e.targetUrl||e.url||"";s=i?`${n} ${i}`:n}else s=e.description||e.command||e.message||e.path||e.file_path||e.query||"";return s&&s.length>200&&(s=s.substring(0,200)+"..."),s},_e=t=>t.data?.tools&&t.data.tools.length>0,$e=t=>t.data?.tools&&Array.isArray(t.data.tools)?t.data.tools.filter(e=>e&&typeof e=="object"&&e.name).map(e=>{let a=e.result!==void 0||e.status==="completed"||e.status==="error",s={};if(e.startTime&&(s.startTime=e.startTime),e.endTime&&(s.endTime=e.endTime),s.startTime&&s.endTime){let n=new Date(s.endTime).getTime()-new Date(s.startTime).getTime();n>=0&&(s.duration=`${parseFloat((n/1e3).toPrecision(3))}s (${n}ms)`)}return{tool:e.name,timing:s,start:{timestamp:e.startTime,data:{toolName:e.name,arguments:e.input||e.arguments||{}}},complete:a?{timestamp:e.endTime,data:{result:e.result,error:e.status==="error"?e.error:null}}:null}}):[],ae=["#58a6ff","#f0883e","#a371f7","#3fb950","#f778ba","#79c0ff","#d29922","#56d4dd"],qe=t=>{let e=0;for(let a=0;a<t.length;a++){let s=t.charCodeAt(a);e=(e<<5)-e+s,e=e&e}return e},se=t=>{let{ownerMap:e,subagentInfo:a}=xe.value;if(t.type==="subagent.started"||t.type==="subagent.completed"||t.type==="subagent.failed"){let i=t.data?.toolCallId;if(i&&a.has(i)){let o=a.get(i);return{name:o.name,toolCallId:i,colorIndex:o.colorIndex}}return null}if(t._subagent){let i=t._subagent.id,o=t._subagent.name;if(a.has(i)){let r=a.get(i);return{name:r.name,toolCallId:i,colorIndex:r.colorIndex}}return{name:o,toolCallId:i,colorIndex:Math.abs(qe(i))}}if(t.data?.subAgentId){let i=t.data.subAgentId,o=a.get(i);if(o)return{name:o.name,toolCallId:i,colorIndex:o.colorIndex}}let s=e.get(t.stableId);if(!s)return null;let n=a.get(s);return n?{name:n.name,toolCallId:s,colorIndex:n.colorIndex}:null},Ue=t=>{let e=se(t);return e?ae[e.colorIndex%ae.length]:null},Pe=t=>{if(window.trackClick){let e=ee.value.find(a=>a.type===t);window.trackClick("EventFilterClicked",{filterType:t,filterLabel:e?e.label:t,sessionId:m.value})}k.value=t},oe=t=>{V.value="",k.value="all",X.value=t.id,Vue.nextTick(()=>{if(g.value){let e=A.value.findIndex(a=>a.virtualIndex===t.index);if(e>=0){let a=s=>{s<=0||!g.value||(g.value.scrollToItem(e),setTimeout(()=>a(s-1),100))};setTimeout(()=>a(3),50)}}})},Be=()=>{if(!g.value)return;let t=e=>{e<=0||!g.value||(g.value.scrollToItem(0),setTimeout(()=>t(e-1),100))};t(3)},ze=()=>{if(!g.value)return;let t=A.value.length-1,e=a=>{a<=0||!g.value||(g.value.scrollToItem(t),setTimeout(()=>e(a-1),100))};e(5)},ne=t=>{window.trackClick&&window.trackClick("TurnClicked",{turnNumber:t,sessionId:m.value});let e=R.value.find(a=>a.id===t);if(e){let a=`UserReq${e.userReqNumber}_Turn${e.id}`,s=`${window.location.pathname}?eventType=assistant.turn_start&eventName=${a}`;window.history.pushState({},"",s),oe(e)}},Ve=t=>{if(!t)return"";let e=t.replace(/\/$/,"").split("/");return e[e.length-1]||t},He=t=>{let e=R.value.find(s=>s.index===t);if(!e)return"?";let a=e.originalTurnId??e.id;return e.userReqNumber>0?`${e.userReqNumber} - Turn ${a}`:`Turn ${a}`},je=t=>R.value.find(a=>a.index===t)?.duration||null,ie=t=>{let e=document.createElement("div");return e.textContent=t,e.innerHTML},Fe=t=>t?new Date(t).toLocaleString():"N/A",Ge=async()=>{console.log("[Export] exportSession called"),window.trackClick&&window.trackClick("ExportClicked",{sessionId:m.value}),z.value=!0;try{console.log("[Export] Fetching:",`/session/${m.value}/export`);let t=await fetch(`/session/${m.value}/export`);if(console.log("[Export] Response received:",t.status,t.ok),console.log("[Export] Response received:",t.status,t.ok),!t.ok)throw new Error("Share failed");console.log("[Export] Creating blob...");let e=await t.blob();console.log("[Export] Blob size:",e.size,"type:",e.type);let a=window.URL.createObjectURL(e);console.log("[Export] Creating download link...");let s=document.createElement("a");s.href=a,s.download=`session-${m.value}.zip`,document.body.appendChild(s),s.click(),console.log("[Export] Download triggered"),window.URL.revokeObjectURL(a),document.body.removeChild(s),console.log("[Export] Showing success feedback...");let n="\u{1F4E4} Share Session",i="\u2713 Downloaded!",o=document.querySelector(".export-btn");o&&(o.textContent=i,o.style.background="#238636",console.log("[Export] Button text updated to:",o.textContent),setTimeout(()=>{o.textContent=n,o.style.background="",console.log("[Export] Button text restored")},2e3))}catch(t){console.error("[Export] Share session error:",t),alert("Failed to share session: "+t.message)}finally{z.value=!1,console.log("[Export] Export complete")}};F(async()=>{try{console.log("[Navigation] Starting event loading...");let a=await fetch(`/api/sessions/${m.value}/events`);if(!a.ok)throw new Error(`Failed to load events: ${a.statusText}`);let s=await a.json();if(Array.isArray(s))S.value=s;else if(s.events&&Array.isArray(s.events))S.value=s.events,console.log("[Navigation] Pagination:",s.pagination);else throw new Error("Invalid response format");if(console.log("[Navigation] Events loaded:",S.value.length),S.value.length>0){let c=S.value[S.value.length-1],l=c.timestamp||c.time||c.data?.timestamp;l&&(W.value.updated=new Date(l))}let n=new URLSearchParams(window.location.search),i=n.get("eventType"),o=n.get("eventName"),r=n.get("eventTimestamp");console.log("[Navigation] URL params:",i,o,r),i&&o&&(console.log("[Navigation] Waiting for Vue to render..."),Vue.nextTick(()=>{console.log("[Navigation] nextTick - flatEvents count:",v.value?.length);let c=null;if(i==="assistant.turn_start"){let l=o.match(/UserReq(\d+)_Turn(\d+)/);if(l){let d=parseInt(l[2],10);if(!isNaN(d)){console.log("[Navigation] Jumping to turn:",d),ne(d);return}}}else i==="subagent.started"?(console.log("[Navigation] Searching for subagent:",o,"timestamp:",r),r&&(c=v.value.find(l=>l.type==="subagent.started"&&l.timestamp===r)),c||(c=v.value.find(l=>l.type==="subagent.started"&&(l.data?.agentDisplayName===o||l.data?.agentName===o||l.data?.label===o))),console.log("[Navigation] Target event found:",c?"YES":"NO","virtualIndex:",c?.virtualIndex)):c=v.value.find(l=>l.type===i);if(c){let l=A.value.findIndex(d=>d.virtualIndex===c.virtualIndex);if(console.log("[Navigation] Target in filteredEvents at index:",l),l>=0&&g.value){console.log("[Navigation] Scrolling to index:",l);let d=y=>{y<=0||!g.value||(g.value.scrollToItem(l),setTimeout(()=>d(y-1),100))};setTimeout(()=>d(3),50)}else console.log("[Navigation] Failed - targetIndex:",l,"scrollerRef:",!!g.value)}else console.log("[Navigation] Target event not found")}))}catch(a){console.error("Error loading events:",a),Q.value=a.message}finally{Z.value=!1}window.addEventListener("keydown",a=>{a.ctrlKey&&a.key==="b"&&(a.preventDefault(),q.value=!q.value)}),window.marked&&marked.setOptions({breaks:!0,gfm:!0});let t=()=>{if(!g.value)return;let a=null;if(g.value.$el&&typeof g.value.$el.querySelector=="function"?a=g.value.$el.querySelector(".vue-recycle-scroller"):g.value.querySelector&&typeof g.value.querySelector=="function"&&(a=g.value.querySelector(".vue-recycle-scroller")),a||(a=document.querySelector(".vue-recycle-scroller")),a){let s=a.scrollTop,n=a.clientHeight,i=80,o=Math.floor(s/i),r=Math.ceil(n/i),c=Math.min(o+r,A.value.length),l=Math.max(1,o+1),d=Math.max(1,c);Y.value={start:Math.min(l,d),end:d}}},e=null;setTimeout(()=>{t();let a=document.querySelector(".vue-recycle-scroller");a&&(a.addEventListener("scroll",t),e=()=>{a.removeEventListener("scroll",t)})},500),me(()=>{L&&(clearTimeout(L),L=null),e&&e(),x.value={},w.value={},f.clear()})});let D=u([]),H=u([]),O=u(!1),b=u([]),C=u(""),j=u(null),T=u(""),I=u(!1),P=u([]),re=u(0),le=["#3b82f6","#10b981","#f59e0b","#ef4444","#8b5cf6","#ec4899","#06b6d4","#f97316"],We=t=>{let e=0;for(let a=0;a<t.length;a++)e=t.charCodeAt(a)+((e<<5)-e);return le[Math.abs(e)%le.length]},Ke=async()=>{try{let t=await fetch(`/api/sessions/${m.value}/tags`);if(t.ok){let e=await t.json();D.value=e.tags||[]}}catch(t){console.error("Error loading tags:",t)}},de=async()=>{try{let t=await fetch("/api/tags");if(t.ok){let e=await t.json();H.value=e.tags||[]}}catch(t){console.error("Error loading all tags:",t)}},Je=async t=>{try{window.trackClick&&t.filter(s=>!D.value.includes(s)).forEach(s=>{window.trackClick("TagAdded",{sessionId:m.value,tag:s})});let e=await fetch(`/api/sessions/${m.value}/tags`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({tags:t})});if(e.ok){let a=await e.json();return D.value=a.tags||[],T.value="",!0}else{let a=await e.json();return T.value=a.error||"Failed to save tags",!1}}catch(e){return console.error("Error saving tags:",e),T.value="Network error",!1}},Xe=()=>{b.value=[...D.value],O.value=!0,T.value="",setTimeout(()=>{j.value&&j.value.focus()},10)},Ye=()=>{O.value=!1,b.value=[],C.value="",I.value=!1,T.value=""},ce=()=>{let t=C.value.trim().toLowerCase();if(t){if(t.length>30){T.value="Tag must be 30 characters or less";return}if(b.value.length>=10){T.value="Maximum 10 tags per session";return}if(b.value.includes(t)){T.value="Tag already added",C.value="";return}b.value.push(t),C.value="",I.value=!1,T.value=""}},Ze=t=>{b.value=b.value.filter(e=>e!==t),T.value=""},Qe=()=>{let t=C.value.trim().toLowerCase();if(!t){I.value=!1,P.value=[];return}let e=H.value.filter(a=>a.toLowerCase().includes(t)&&!b.value.includes(a)).slice(0,5);e.length>0?(I.value=!0,P.value=e,re.value=0):(I.value=!1,P.value=[])},et=t=>{C.value=t,ce()},tt=async()=>{setTimeout(async()=>{if(!O.value)return;await Je(b.value)&&(O.value=!1,b.value=[],C.value="",I.value=!1,await de())},200)};return F(async()=>{await Ke(),await de()}),{sessionId:m,metadata:W,exporting:z,sidebarCollapsed:q,expandedTools:x,expandedContent:w,expansionCount:Te,currentFilter:k,searchText:V,currentTurnIndex:X,scrollerRef:g,visibleRange:Y,loadedEvents:S,eventsLoading:Z,eventsError:Q,flatEvents:v,filteredEvents:A,eventCounts:fe,filters:ee,turns:R,userReqs:he,truncateText:ye,formatTime:we,formatToolTime:Se,formatDateTime:Fe,renderMarkdown:Ce,highlightSearchText:ke,toggleTool:Ie,toggleContent:Ee,isContentTooLong:Me,truncateContent:Ne,getBadgeInfo:Le,getToolStatus:Ae,getToolErrorMessage:Re,getToolDuration:De,getToolCommand:Oe,hasTools:_e,getToolGroups:$e,getSubagentInfo:se,getSubagentColor:Ue,setFilter:Pe,scrollToTurn:oe,scrollToTop:Be,scrollToBottom:ze,jumpToTurn:ne,getTurnNumber:He,getTurnDuration:je,repoBasename:Ve,escapeHtml:ie,exportSession:Ge,searchResultCount:be,sessionTags:D,allTags:H,tagsEditing:O,editingTags:b,tagInputValue:C,tagInputRef:j,tagsError:T,showAutocomplete:I,autocompleteOptions:P,autocompleteSelectedIndex:re,getTagColor:We,startEditTags:Xe,cancelEditTags:Ye,addTag:ce,removeTagFromEdit:Ze,updateAutocomplete:Qe,selectAutocompleteOption:et,saveTagsOnBlur:tt}},template:`
10
10
  <div class="container">
11
11
  <div class="header">
12
12
  <a href="/" class="home-btn">\u2190 Back to Home</a>
@@ -393,10 +393,32 @@
393
393
  </div>
394
394
 
395
395
  <!-- No content at all (no message and no tools) -->
396
- <div v-else-if="!hasTools(item)" class="event-content" style="color: #7d8590; font-style: italic;">
396
+ <div v-else-if="!hasTools(item) && !item.data?.reasoningText" class="event-content" style="color: #7d8590; font-style: italic;">
397
397
  No available message
398
398
  </div>
399
399
 
400
+ <!-- Reasoning text (shown after main content, before tool calls) -->
401
+ <div v-if="item.data?.reasoningText" class="event-content reasoning-text-content">
402
+ <div
403
+ v-html="highlightSearchText(
404
+ renderMarkdown(
405
+ (expandedContent[item.stableId + '-reasoning'] || !isContentTooLong(item.data.reasoningText))
406
+ ? item.data.reasoningText
407
+ : truncateContent(item.data.reasoningText)
408
+ ),
409
+ searchText
410
+ )"
411
+ ></div>
412
+ <div v-if="isContentTooLong(item.data.reasoningText)" style="margin-top: 8px;">
413
+ <button
414
+ @click="toggleContent(item.stableId + '-reasoning')"
415
+ style="background: none; border: 1px solid #30363d; color: #58a6ff; padding: 4px 12px; border-radius: 4px; cursor: pointer; font-size: 13px;"
416
+ >
417
+ {{ expandedContent[item.stableId + '-reasoning'] ? 'Show less \u25B2' : 'Show more \u25BC' }}
418
+ </button>
419
+ </div>
420
+ </div>
421
+
400
422
  <!-- Tool calls section (independent of message content, but don't need "No available message" if tools exist) -->
401
423
  <div v-if="hasTools(item)" class="tool-list">
402
424
  <div
@@ -417,6 +439,13 @@
417
439
  </div>
418
440
 
419
441
  <div v-if="expandedTools[item.stableId + '-' + idx]" class="tool-detail">
442
+ <div v-if="group.timing.startTime || group.timing.endTime || group.timing.duration" class="tool-detail-section">
443
+ <div class="tool-detail-content tool-timing-line">
444
+ <span v-if="group.timing.startTime"><span class="tool-timing-label">Start</span> {{ formatToolTime(group.timing.startTime) }}</span>
445
+ <span v-if="group.timing.endTime"><span class="tool-timing-label">Complete</span> {{ formatToolTime(group.timing.endTime) }}</span>
446
+ <span v-if="group.timing.duration"><span class="tool-timing-label">Duration</span> {{ group.timing.duration }}</span>
447
+ </div>
448
+ </div>
420
449
  <div v-if="group.start?.data?.arguments" class="tool-detail-section">
421
450
  <div class="tool-detail-title">Arguments:</div>
422
451
  <div class="tool-detail-content">
@@ -807,7 +807,6 @@
807
807
  text-align: left;
808
808
  font-size: 13px;
809
809
  }
810
-
811
810
  /* Model change styling */
812
811
  .model-change-content {
813
812
  margin-top: 6px;
@@ -894,6 +893,22 @@
894
893
  .event-content p {
895
894
  margin: 6px 0;
896
895
  }
896
+
897
+ /* Reasoning text: muted color — placed after .event-content markdown rules
898
+ so the higher-specificity selectors (0,2,1) override .event-content strong etc. (0,1,1) */
899
+ .reasoning-text-content.event-content,
900
+ .reasoning-text-content.event-content strong,
901
+ .reasoning-text-content.event-content em,
902
+ .reasoning-text-content.event-content h1,
903
+ .reasoning-text-content.event-content h2,
904
+ .reasoning-text-content.event-content h3,
905
+ .reasoning-text-content.event-content h4,
906
+ .reasoning-text-content.event-content h5,
907
+ .reasoning-text-content.event-content h6,
908
+ .reasoning-text-content.event-content code,
909
+ .reasoning-text-content.event-content a {
910
+ color: #7d8590;
911
+ }
897
912
 
898
913
  /* Markdown table styling */
899
914
  .event-content table {
@@ -1016,6 +1031,16 @@
1016
1031
  line-height: 1.3;
1017
1032
  color: #e6edf3;
1018
1033
  }
1034
+ .tool-timing-line {
1035
+ display: flex;
1036
+ flex-wrap: wrap;
1037
+ gap: 4px 16px;
1038
+ }
1039
+ .tool-timing-label {
1040
+ color: #8b949e;
1041
+ font-weight: 500;
1042
+ margin-right: 3px;
1043
+ }
1019
1044
 
1020
1045
  /* Turn divider - Design 3: Slack Style (居中对称) */
1021
1046
  .turn-divider {