@code-yeongyu/senpi 2026.10.10-11 → 2026.10.10-12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/dist/bundle/chunks/{app-server-command-HYNHHQJH.js → app-server-command-EGTBOL5W.js} +2 -2
- package/dist/bundle/chunks/bun-extension-importer-QSQHKXVG.js +20 -0
- package/dist/bundle/chunks/{chunk-B2RD7QJJ.js → chunk-2AYAOU6W.js} +8 -6
- package/dist/bundle/chunks/{chunk-ML3WDDTX.js → chunk-2ZGQRUGM.js} +95 -94
- package/dist/bundle/chunks/{chunk-OZ2N2E6U.js → chunk-6SBY4ZWC.js} +1 -1
- package/dist/bundle/chunks/chunk-E75RO54O.js +14 -0
- package/dist/bundle/chunks/chunk-N6HU6BEY.js +9 -0
- package/dist/bundle/chunks/chunk-NEFNNQSV.js +9 -0
- package/dist/bundle/chunks/{chunk-YI7SPFDN.js → chunk-Q3R44CGT.js} +2 -2
- package/dist/bundle/chunks/chunk-QKU6JOA4.js +2 -0
- package/dist/bundle/chunks/chunk-SIIACSBE.js +30 -0
- package/dist/bundle/chunks/{chunk-ZHE7JDBG.js → chunk-ZGCPUGLT.js} +1 -1
- package/dist/bundle/chunks/{chunk-4XSQBLXM.js → chunk-ZRWOLP4E.js} +1 -1
- package/dist/bundle/chunks/cli-main-PANLBILV.js +3 -0
- package/dist/bundle/chunks/host-command-MWSVX37K.js +2 -0
- package/dist/bundle/chunks/host-lifecycle-X2J5FTJL.js +3 -0
- package/dist/bundle/chunks/host-lifecycle.js +8 -8
- package/dist/bundle/chunks/interactive-mode-TQJU6K27.js +2 -0
- package/dist/bundle/chunks/{multi-session-host-4SUEFZMU.js → multi-session-host-GBSMDUMG.js} +1 -1
- package/dist/bundle/chunks/{package-manager-cli-XEUK2RUM.js → package-manager-cli-IBPABDGR.js} +1 -1
- package/dist/bundle/chunks/rpc-mode-PFIAS2E5.js +2 -0
- package/dist/bundle/chunks/{runtime-session-6DAEMII3.js → runtime-session-I4NDNGC5.js} +1 -1
- package/dist/bundle/chunks/{schedule-command-DGLRLVWY.js → schedule-command-Q4W37FAP.js} +1 -1
- package/dist/bundle/chunks/{session-control-endpoint-MCV37VI5.js → session-control-endpoint-YYFCJZXZ.js} +1 -1
- package/dist/bundle/chunks/{session-picker-WEFWH5O4.js → session-picker-YLDBGXTR.js} +1 -1
- package/dist/bundle/chunks/session-worker.js +204 -201
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/bundle/runtime-manifest.json +1 -1
- package/dist/core/agent-session.js +10 -32
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts +9 -2
- package/dist/core/extensions/builtin/compaction/deterministic-fallback.js +22 -45
- package/dist/core/extensions/builtin/compaction/index.js +55 -9
- package/dist/core/extensions/builtin/compaction/rejected-recovery.d.ts +11 -0
- package/dist/core/extensions/builtin/compaction/rejected-recovery.js +73 -0
- package/dist/core/extensions/builtin/compaction/retained-message-projection.d.ts +10 -0
- package/dist/core/extensions/builtin/compaction/retained-message-projection.js +102 -0
- package/dist/core/extensions/builtin/goal/format.d.ts +1 -1
- package/dist/core/extensions/builtin/goal/format.js +19 -4
- package/dist/core/extensions/builtin/goal/index.js +12 -1
- package/dist/core/extensions/builtin/goal/lifecycle-helpers.d.ts +1 -0
- package/dist/core/extensions/builtin/goal/lifecycle-helpers.js +3 -0
- package/dist/core/extensions/builtin/goal/renderers.js +9 -4
- package/dist/core/extensions/builtin/goal/types.d.ts +8 -0
- package/dist/core/extensions/builtin/goal/types.js +4 -0
- package/dist/core/extensions/builtin/goal/ui.js +6 -3
- package/dist/core/extensions/builtin/mcp/index.js +4 -2
- package/dist/core/extensions/bun-extension-importer.d.ts +1 -1
- package/dist/core/extensions/bun-extension-importer.js +7 -3
- package/dist/core/extensions/extension-module-cache.d.ts +4 -3
- package/dist/core/extensions/extension-module-cache.js +8 -22
- package/dist/core/resource-loader.js +5 -6
- package/dist/core/session-manager.js +17 -0
- package/dist/modes/app-server/daemon/process.d.ts +3 -1
- package/dist/modes/app-server/daemon/process.js +7 -3
- package/dist/modes/app-server/threads/goal-wire.js +2 -1
- package/dist/modes/rpc/host-client-occupancy.d.ts +2 -1
- package/dist/modes/rpc/host-client-occupancy.js +3 -0
- package/dist/modes/rpc/host-daemon-registration.js +5 -0
- package/dist/modes/rpc/host-daemon-state.d.ts +17 -0
- package/dist/modes/rpc/host-daemon-state.js +60 -0
- package/dist/modes/rpc/host-ensure-start.js +13 -3
- package/dist/modes/rpc/host-ensure-stop.d.ts +1 -1
- package/dist/modes/rpc/host-ensure-stop.js +17 -4
- package/dist/modes/rpc/host-ensure-types.d.ts +2 -0
- package/dist/modes/rpc/host-ensure.js +20 -2
- package/dist/modes/rpc/host-gc-evidence.js +3 -0
- package/dist/modes/rpc/host-generations.js +4 -1
- package/dist/modes/rpc/host-legacy.d.ts +1 -1
- package/dist/modes/rpc/host-legacy.js +3 -1
- package/dist/modes/rpc/host-lifecycle-activity.d.ts +30 -0
- package/dist/modes/rpc/host-lifecycle-activity.js +136 -4
- package/dist/modes/rpc/host-lifecycle-launch.d.ts +4 -0
- package/dist/modes/rpc/host-lifecycle-launch.js +24 -1
- package/dist/modes/rpc/host-lifecycle-proxy.d.ts +2 -0
- package/dist/modes/rpc/host-lifecycle-proxy.js +4 -1
- package/dist/modes/rpc/host-lifecycle-scratch.js +5 -2
- package/dist/modes/rpc/host-lifecycle-shutdown.d.ts +1 -1
- package/dist/modes/rpc/host-lifecycle-shutdown.js +81 -37
- package/dist/modes/rpc/host-lifecycle.js +23 -1
- package/dist/modes/rpc/host-reservations.js +6 -1
- package/dist/modes/rpc/host-stalled-evidence.js +17 -3
- package/dist/modes/rpc/host-stop-intent.d.ts +3 -0
- package/dist/modes/rpc/host-stop-intent.js +3 -0
- package/dist/modes/rpc/host-stop.js +4 -9
- package/dist/modes/rpc/host-successor.js +10 -3
- package/docs/app-server.md +1 -1
- package/docs/rpc.md +54 -1
- package/docs/session-format.md +10 -0
- package/package.json +6 -6
- package/dist/bundle/chunks/bun-extension-importer-3TEDTSKJ.js +0 -20
- package/dist/bundle/chunks/chunk-2KZKVRVC.js +0 -8
- package/dist/bundle/chunks/chunk-CIRZTP7W.js +0 -2
- package/dist/bundle/chunks/chunk-FOGXAY3T.js +0 -2
- package/dist/bundle/chunks/chunk-GNZDD5BK.js +0 -15
- package/dist/bundle/chunks/chunk-KTRCQYDF.js +0 -30
- package/dist/bundle/chunks/chunk-NV3IPLK6.js +0 -9
- package/dist/bundle/chunks/cli-main-WTXDD6H5.js +0 -3
- package/dist/bundle/chunks/host-command-7YS2Y6AT.js +0 -2
- package/dist/bundle/chunks/host-lifecycle-UG7RS5EU.js +0 -3
- package/dist/bundle/chunks/interactive-mode-WLMPVMRU.js +0 -2
- package/dist/bundle/chunks/rpc-mode-G3DAUZCR.js +0 -2
|
@@ -16,14 +16,16 @@ ${msg.output}
|
|
|
16
16
|
|
|
17
17
|
Command exited with code ${msg.exitCode}`),msg.truncated&&msg.fullOutputPath&&(text+=`
|
|
18
18
|
|
|
19
|
-
[Output truncated. Full output: ${msg.fullOutputPath}]`),text}function createBranchSummaryMessage(summary,fromId,timestamp){return{role:"branchSummary",summary,fromId,timestamp:new Date(timestamp).getTime()}}function createCompactionSummaryMessage(summary,tokensBefore,timestamp,details){return{role:"compactionSummary",summary,tokensBefore,details,timestamp:new Date(timestamp).getTime()}}function createCustomMessage(customType,content,display,details,timestamp){return{role:"custom",customType,content,display,details,timestamp:new Date(timestamp).getTime()}}function convertToLlm(messages){let withContextProvenance=(source,target)=>copyContextProvenance(source,target),environmentMessages=new Set,converted=messages.map(m=>{switch(m.role){case"bashExecution":return m.excludeFromContext?void 0:withContextProvenance(m,{role:"user",content:[{type:"text",text:bashExecutionToText(m)}],timestamp:m.timestamp});case"custom":{if(isContextExcludedCustomMessage(m.customType))return;let content=typeof m.content=="string"?[{type:"text",text:m.content}]:m.content,converted2=withContextProvenance(m,{role:"user",content,timestamp:m.timestamp});return m.customType===ENVIRONMENT_CONTEXT_MESSAGE_TYPE&&environmentMessages.add(converted2),converted2}case"branchSummary":return withContextProvenance(m,{role:"user",content:[{type:"text",text:BRANCH_SUMMARY_PREFIX+m.summary+BRANCH_SUMMARY_SUFFIX}],timestamp:m.timestamp});case"compactionSummary":return withContextProvenance(m,{role:"user",content:[{type:"text",text:COMPACTION_SUMMARY_PREFIX+m.summary+COMPACTION_SUMMARY_SUFFIX}],timestamp:m.timestamp});case"configurationUpdate":return m;case"system":case"user":case"assistant":case"toolResult":return m;default:let _exhaustiveCheck=m;return}}).filter(m=>m!==void 0);return foldEnvironmentContextIntoNextUserMessage(appendToolResultUserWords(dropFailedAssistantTurns(omitProviderRejectedImages(converted))),environmentMessages)}var TRANSPORT_IMAGE_BUDGET_BYTES=24*1024*1024,IMAGE_ELISION_PLACEHOLDER="[Image elided: an older image was removed to keep the request within the provider's size limit. Re-read the source file if you need to view it again.]",BLOCKED_IMAGE_PLACEHOLDER="Image reading is disabled.";function dedupeConsecutivePlaceholder(content,placeholder){return content.filter((block,index,blocks)=>!(block.type==="text"&&block.text===placeholder&&index>0&&blocks[index-1].type==="text"&&blocks[index-1].text===placeholder))}function elideOldImages(messages,options){let budgetBytes=options?.budgetBytes??TRANSPORT_IMAGE_BUDGET_BYTES,alwaysKeepNewest=options?.alwaysKeepNewest??1,maxHistoricalImages=options?.maxHistoricalImages,limitHistory=maxHistoricalImages!==void 0,lastAssistantIndex=messages.findLastIndex(message=>message.role==="assistant"),imagesToElide=new Set,keptImages=0,keptHistoricalImages=0,imageBytes=0,cutoffReached=!1;for(let messageIndex=messages.length-1;messageIndex>=0;messageIndex--){let message=messages[messageIndex];if(!(message.role!=="user"&&message.role!=="toolResult"||!Array.isArray(message.content)))for(let blockIndex=message.content.length-1;blockIndex>=0;blockIndex--){let block=message.content[blockIndex];if(block.type!=="image")continue;let isCurrentTurn=limitHistory&&messageIndex>lastAssistantIndex,isProtectedHistory=limitHistory&&!isCurrentTurn&&keptHistoricalImages<maxHistoricalImages;if(limitHistory&&!isCurrentTurn&&!isProtectedHistory||cutoffReached&&!isCurrentTurn&&!isProtectedHistory){imagesToElide.add(`${messageIndex}:${blockIndex}`);continue}if(isCurrentTurn||isProtectedHistory||keptImages<alwaysKeepNewest||imageBytes+block.data.length<=budgetBytes){keptImages++,isCurrentTurn||keptHistoricalImages++,imageBytes+=block.data.length;continue}cutoffReached=!0,imagesToElide.add(`${messageIndex}:${blockIndex}`)}}return imagesToElide.size===0?messages:messages.map((message,messageIndex)=>{if(message.role!=="user"&&message.role!=="toolResult"||!Array.isArray(message.content)||!message.content.some((_block,blockIndex)=>imagesToElide.has(`${messageIndex}:${blockIndex}`)))return message;let replaced=message.content.map((block,blockIndex)=>imagesToElide.has(`${messageIndex}:${blockIndex}`)?{type:"text",text:IMAGE_ELISION_PLACEHOLDER}:block);return{...message,content:dedupeConsecutivePlaceholder(replaced,IMAGE_ELISION_PLACEHOLDER)}})}function convertToLlmForTransport(messages,options){let converted=convertToLlm(messages);return options.blockImages?converted.map(message=>{if(message.role!=="user"&&message.role!=="toolResult"||!Array.isArray(message.content)||!message.content.some(block=>block.type==="image"))return message;let replaced=message.content.map(block=>block.type==="image"?{type:"text",text:BLOCKED_IMAGE_PLACEHOLDER}:block);return{...message,content:dedupeConsecutivePlaceholder(replaced,BLOCKED_IMAGE_PLACEHOLDER)}}):elideOldImages(converted,options)}import{randomBytes,randomUUID as randomUUID2}from"crypto";import{appendFileSync,closeSync as closeSync3,existsSync as existsSync3,mkdirSync as mkdirSync2,openSync as openSync3,readdirSync,readFileSync as readFileSync2,readSync as readSync2,rmSync as rmSync4,statSync as statSync2,writeFileSync as writeFileSync3}from"fs";import{appendFile as appendFile2,open as open2,readdir as readdir2,rm as rm3}from"fs/promises";import{join as join5,resolve as resolve2}from"path";import{StringDecoder as StringDecoder2}from"string_decoder";function sessionCwdMatcher(resolvedCwd){let mapped=new Map;return cwd=>{if(cwd===void 0||cwd==="")return!1;if(resolvePath(cwd)===resolvedCwd)return!0;let target=mapped.get(cwd);return target===void 0&&(target=resolvePath(resolveMovedPath(cwd)),mapped.set(cwd,target)),target===resolvedCwd}}import{existsSync}from"fs";import{readdir}from"fs/promises";import{join as join2}from"path";import{stat as stat2}from"fs/promises";import{resolve}from"path";import{open}from"fs/promises";import{StringDecoder}from"string_decoder";import{execFile}from"node:child_process";var REPOSITORY_IDENTITY_ENTRY_TYPE="repository-identity",GIT_TIMEOUT_MS=5e3,COMMIT_HASH=/^[0-9a-f]{40,64}$/,GIT_LOCATION_ENV=new Set(["GIT_DIR","GIT_WORK_TREE","GIT_COMMON_DIR","GIT_INDEX_FILE"]),runGit=(dir,args)=>new Promise(resolve5=>{let env=Object.fromEntries(Object.entries(process.env).filter(([name])=>!GIT_LOCATION_ENV.has(name)));execFile("git",["-C",dir,...args],{env,timeout:GIT_TIMEOUT_MS,windowsHide:!0},(error,stdout)=>{resolve5(error?void 0:stdout)})});async function readRepositoryIdentity(dir,run=runGit){let[roots,origin]=await Promise.all([run(dir,["rev-list","--max-parents=0","HEAD"]),run(dir,["config","--get","remote.origin.url"])]),rootCommits=(roots??"").split(/\s+/).filter(line=>COMMIT_HASH.test(line)).sort(),originUrl=origin?.trim()?normalizeRemoteUrl(origin):void 0;if(!(rootCommits.length===0&&originUrl===void 0))return originUrl===void 0?{rootCommits}:{rootCommits,originUrl}}function normalizeRemoteUrl(url){let trimmed=url.trim(),scpLike=/^(?:[^@/\s]+@)?([^:/\s]+):(?!\/)(.+)$/.exec(trimmed);return(scpLike?`${scpLike[1]}/${scpLike[2]}`:trimmed.replace(/^[a-z][a-z0-9+.-]*:\/\//i,"").replace(/^[^@/]+@/,"").replace(/^([^/:]+):\d+\//,"$1/")).replace(/\/+$/,"").replace(/\.git$/i,"").toLowerCase()}function compareRepositoryIdentities(a,b){return a===void 0||b===void 0?"unknown":a.rootCommits.length>0&&b.rootCommits.length>0?a.rootCommits.some(commit=>b.rootCommits.includes(commit))?"same":"different":a.originUrl!==void 0&&b.originUrl!==void 0?a.originUrl===b.originUrl?"same":"different":"unknown"}function parseRepositoryIdentity(value){if(typeof value!="object"||value===null)return;let{rootCommits,originUrl}=value;if(!Array.isArray(rootCommits)||!rootCommits.every(commit=>typeof commit=="string")||originUrl!==void 0&&typeof originUrl!="string")return;let commits=rootCommits.filter(commit=>COMMIT_HASH.test(commit)).sort();if(!(commits.length===0&&originUrl===void 0))return originUrl===void 0?{rootCommits:commits}:{rootCommits:commits,originUrl}}function sameRepositoryIdentity(a,b){return a===void 0||b===void 0?a===b:a.originUrl===b.originUrl&&a.rootCommits.join(",")===b.rootCommits.join(",")}function parseEntryLine(line){if(!line.trim())return null;try{return JSON.parse(line)}catch{return null}}function isMessageWithContent(message){return typeof message=="object"&&message!==null&&typeof message.role=="string"&&"content"in message}function extractTextContent(message){let content=message.content;return typeof content=="string"?content:content.filter(block=>block.type==="text").map(block=>block.text).join(" ")}function visibleMessage(entry){if(entry.type!=="message")return null;let message=entry.message;if(!isMessageWithContent(message)||message.role!=="user"&&message.role!=="assistant")return null;let messageTime=message.timestamp,entryTime=Date.parse(entry.timestamp),time=typeof messageTime=="number"?messageTime:Number.isNaN(entryTime)?void 0:entryTime;return{text:extractTextContent(message),role:message.role,time}}function sessionInfoName(entry){return entry.type!=="session_info"?null:entry.name?.trim()||void 0}function newAccumulator(){return{header:null,name:void 0,firstUserMessage:"",messageCount:0,lastActivityTime:void 0,repositoryIdentity:void 0,texts:[]}}function accumulateLine(accumulator,line){let entry=parseEntryLine(line);if(!entry)return!0;if(!accumulator.header)return entry.type!=="session"||typeof entry.id!="string"?!1:(accumulator.header=entry,!0);if(entry.type==="custom"&&entry.customType===REPOSITORY_IDENTITY_ENTRY_TYPE)return accumulator.repositoryIdentity=parseRepositoryIdentity(entry.data)??accumulator.repositoryIdentity,!0;let infoName=sessionInfoName(entry);if(infoName!==null)return accumulator.name=infoName,!0;if(entry.type!=="message")return!0;accumulator.messageCount++;let visible=visibleMessage(entry);return!visible||(typeof visible.time=="number"&&(accumulator.lastActivityTime=Math.max(accumulator.lastActivityTime??0,visible.time)),!visible.text)||(accumulator.texts.push(visible.text),!accumulator.firstUserMessage&&visible.role==="user"&&(accumulator.firstUserMessage=visible.text)),!0}var LINE_READ_BUFFER_SIZE=1024*1024;async function readFileLines(filePath,onLine){let handle=await open(filePath,"r");try{let decoder=new StringDecoder("utf8"),buffer=Buffer.allocUnsafe(LINE_READ_BUFFER_SIZE),pending="",bytes=0,lastByte=-1,emit=line=>onLine(line.endsWith("\r")?line.slice(0,-1):line);for(;;){let{bytesRead}=await handle.read(buffer,0,buffer.length,null);if(bytesRead===0)break;bytes+=bytesRead,lastByte=buffer[bytesRead-1]??-1;let searchFrom=pending.length;pending+=decoder.write(buffer.subarray(0,bytesRead));let lineStart=0,newlineIndex=pending.indexOf(`
|
|
19
|
+
[Output truncated. Full output: ${msg.fullOutputPath}]`),text}function createBranchSummaryMessage(summary,fromId,timestamp){return{role:"branchSummary",summary,fromId,timestamp:new Date(timestamp).getTime()}}function createCompactionSummaryMessage(summary,tokensBefore,timestamp,details){return{role:"compactionSummary",summary,tokensBefore,details,timestamp:new Date(timestamp).getTime()}}function createCustomMessage(customType,content,display,details,timestamp){return{role:"custom",customType,content,display,details,timestamp:new Date(timestamp).getTime()}}function convertToLlm(messages){let withContextProvenance=(source,target)=>copyContextProvenance(source,target),environmentMessages=new Set,converted=messages.map(m=>{switch(m.role){case"bashExecution":return m.excludeFromContext?void 0:withContextProvenance(m,{role:"user",content:[{type:"text",text:bashExecutionToText(m)}],timestamp:m.timestamp});case"custom":{if(isContextExcludedCustomMessage(m.customType))return;let content=typeof m.content=="string"?[{type:"text",text:m.content}]:m.content,converted2=withContextProvenance(m,{role:"user",content,timestamp:m.timestamp});return m.customType===ENVIRONMENT_CONTEXT_MESSAGE_TYPE&&environmentMessages.add(converted2),converted2}case"branchSummary":return withContextProvenance(m,{role:"user",content:[{type:"text",text:BRANCH_SUMMARY_PREFIX+m.summary+BRANCH_SUMMARY_SUFFIX}],timestamp:m.timestamp});case"compactionSummary":return withContextProvenance(m,{role:"user",content:[{type:"text",text:COMPACTION_SUMMARY_PREFIX+m.summary+COMPACTION_SUMMARY_SUFFIX}],timestamp:m.timestamp});case"configurationUpdate":return m;case"system":case"user":case"assistant":case"toolResult":return m;default:let _exhaustiveCheck=m;return}}).filter(m=>m!==void 0);return foldEnvironmentContextIntoNextUserMessage(appendToolResultUserWords(dropFailedAssistantTurns(omitProviderRejectedImages(converted))),environmentMessages)}var TRANSPORT_IMAGE_BUDGET_BYTES=24*1024*1024,IMAGE_ELISION_PLACEHOLDER="[Image elided: an older image was removed to keep the request within the provider's size limit. Re-read the source file if you need to view it again.]",BLOCKED_IMAGE_PLACEHOLDER="Image reading is disabled.";function dedupeConsecutivePlaceholder(content,placeholder){return content.filter((block,index,blocks)=>!(block.type==="text"&&block.text===placeholder&&index>0&&blocks[index-1].type==="text"&&blocks[index-1].text===placeholder))}function elideOldImages(messages,options){let budgetBytes=options?.budgetBytes??TRANSPORT_IMAGE_BUDGET_BYTES,alwaysKeepNewest=options?.alwaysKeepNewest??1,maxHistoricalImages=options?.maxHistoricalImages,limitHistory=maxHistoricalImages!==void 0,lastAssistantIndex=messages.findLastIndex(message=>message.role==="assistant"),imagesToElide=new Set,keptImages=0,keptHistoricalImages=0,imageBytes=0,cutoffReached=!1;for(let messageIndex=messages.length-1;messageIndex>=0;messageIndex--){let message=messages[messageIndex];if(!(message.role!=="user"&&message.role!=="toolResult"||!Array.isArray(message.content)))for(let blockIndex=message.content.length-1;blockIndex>=0;blockIndex--){let block=message.content[blockIndex];if(block.type!=="image")continue;let isCurrentTurn=limitHistory&&messageIndex>lastAssistantIndex,isProtectedHistory=limitHistory&&!isCurrentTurn&&keptHistoricalImages<maxHistoricalImages;if(limitHistory&&!isCurrentTurn&&!isProtectedHistory||cutoffReached&&!isCurrentTurn&&!isProtectedHistory){imagesToElide.add(`${messageIndex}:${blockIndex}`);continue}if(isCurrentTurn||isProtectedHistory||keptImages<alwaysKeepNewest||imageBytes+block.data.length<=budgetBytes){keptImages++,isCurrentTurn||keptHistoricalImages++,imageBytes+=block.data.length;continue}cutoffReached=!0,imagesToElide.add(`${messageIndex}:${blockIndex}`)}}return imagesToElide.size===0?messages:messages.map((message,messageIndex)=>{if(message.role!=="user"&&message.role!=="toolResult"||!Array.isArray(message.content)||!message.content.some((_block,blockIndex)=>imagesToElide.has(`${messageIndex}:${blockIndex}`)))return message;let replaced=message.content.map((block,blockIndex)=>imagesToElide.has(`${messageIndex}:${blockIndex}`)?{type:"text",text:IMAGE_ELISION_PLACEHOLDER}:block);return{...message,content:dedupeConsecutivePlaceholder(replaced,IMAGE_ELISION_PLACEHOLDER)}})}function convertToLlmForTransport(messages,options){let converted=convertToLlm(messages);return options.blockImages?converted.map(message=>{if(message.role!=="user"&&message.role!=="toolResult"||!Array.isArray(message.content)||!message.content.some(block=>block.type==="image"))return message;let replaced=message.content.map(block=>block.type==="image"?{type:"text",text:BLOCKED_IMAGE_PLACEHOLDER}:block);return{...message,content:dedupeConsecutivePlaceholder(replaced,BLOCKED_IMAGE_PLACEHOLDER)}}):elideOldImages(converted,options)}import{randomBytes,randomUUID as randomUUID2}from"crypto";import{appendFileSync,closeSync as closeSync3,existsSync as existsSync3,mkdirSync as mkdirSync2,openSync as openSync3,readdirSync,readFileSync as readFileSync2,readSync as readSync2,rmSync as rmSync4,statSync as statSync2,writeFileSync as writeFileSync3}from"fs";import{appendFile as appendFile2,open as open2,readdir as readdir2,rm as rm3}from"fs/promises";import{join as join5,resolve as resolve2}from"path";import{StringDecoder as StringDecoder2}from"string_decoder";var OMIT_JSON_VALUE=Symbol("omit-json-value");function transformJson(value,transformString){let transformed=transformJsonValue(value,transformString,"",new WeakSet);if(transformed===OMIT_JSON_VALUE){let serialized=JSON.stringify(value);if(serialized===void 0)throw new SyntaxError("JSON-compatible value expected");return JSON.parse(serialized)}return transformed}function transformJsonValue(value,transformString,key,seen){if(typeof value=="string")return transformString(value);if(typeof value=="number")return Number.isFinite(value)?value:null;if(value===null||typeof value=="boolean")return value;if(typeof value=="bigint")throw new TypeError("Do not know how to serialize a BigInt");if(typeof value>"u"||typeof value=="function"||typeof value=="symbol")return OMIT_JSON_VALUE;if(seen.has(value))throw new TypeError("Converting circular structure to JSON");seen.add(value);let jsonValue=hasJsonSerializer(value)?value.toJSON(key):value;if(jsonValue!==value){let transformed2=transformJsonValue(jsonValue,transformString,key,seen);return seen.delete(value),transformed2}if(Array.isArray(value)){let transformed2=Array.from({length:value.length},(_item,index)=>{let item=value[index],transformedItem=transformJsonValue(item,transformString,String(index),seen);return transformedItem===OMIT_JSON_VALUE?null:transformedItem});return seen.delete(value),transformed2}let transformed={};for(let[key2,item]of Object.entries(value)){let transformedItem=transformJsonValue(item,transformString,String(key2),seen);transformedItem!==OMIT_JSON_VALUE&&Object.defineProperty(transformed,key2,{configurable:!0,enumerable:!0,value:transformedItem,writable:!0})}return seen.delete(value),transformed}function hasJsonSerializer(value){return"toJSON"in value&&typeof value.toJSON=="function"}function isRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function isFiniteNumber(value){return typeof value=="number"&&Number.isFinite(value)}function hasTextOnlyContent(content,allowString){return typeof content=="string"?allowString:Array.isArray(content)?content.every(block=>isRecord(block)&&block.type==="text"&&typeof block.text=="string"):!1}function isWellFormedImageBlock(block){return block.type==="image"&&typeof block.mimeType=="string"&&block.mimeType.startsWith("image/")&&typeof block.data=="string"&&block.data.length>0}function hasSafeToolResultContent(content){return Array.isArray(content)?content.every(block=>isRecord(block)&&(block.type==="text"&&typeof block.text=="string"||isWellFormedImageBlock(block))):!1}function isUsage(value){if(!isRecord(value)||!isRecord(value.cost))return!1;for(let field2 of["input","output","cacheRead","cacheWrite","totalTokens"])if(!isFiniteNumber(value[field2]))return!1;for(let field2 of["input","output","cacheRead","cacheWrite","total"])if(!isFiniteNumber(value.cost[field2]))return!1;return(value.cacheWrite1h===void 0||isFiniteNumber(value.cacheWrite1h))&&(value.reasoning===void 0||isFiniteNumber(value.reasoning))}var base64SignaturePattern=/^[A-Za-z0-9+/]+={0,2}$/;function isValidOpaqueSignature(sig){return typeof sig=="string"&&sig.length>0&&sig.length<=65536}function isValidProviderSignature(sig,providerIsGoogle){return isValidOpaqueSignature(sig)?!providerIsGoogle||sig.length%4===0&&base64SignaturePattern.test(sig):!1}function hasSafeAssistantContent(content,providerIsGoogle){if(!Array.isArray(content))return!1;for(let block of content){if(!isRecord(block)||typeof block.type!="string")return!1;switch(block.type){case"text":if(typeof block.text!="string"||block.textSignature!==void 0&&!isValidProviderSignature(block.textSignature,providerIsGoogle))return!1;break;case"thinking":if(typeof block.thinking!="string"||block.startedAt!==void 0&&!isFiniteNumber(block.startedAt)||block.endedAt!==void 0&&!isFiniteNumber(block.endedAt)||block.redacted!==void 0&&typeof block.redacted!="boolean"||block.thinkingSignature!==void 0&&!isValidProviderSignature(block.thinkingSignature,providerIsGoogle)||block.redacted===!0&&!isValidOpaqueSignature(block.thinkingSignature))return!1;break;case"toolCall":if(typeof block.id!="string"||typeof block.name!="string"||!isRecord(block.arguments)||block.incomplete!==void 0&&block.incomplete!==!0||block.errorMessage!==void 0&&typeof block.errorMessage!="string"||block.thoughtSignature!==void 0&&!isValidProviderSignature(block.thoughtSignature,providerIsGoogle))return!1;break;default:return!1}}return!0}function hasSafeAssistantEnvelope(message){let provider=typeof message.provider=="string"?message.provider:"",providerIsGoogle=provider==="google"||provider==="google-vertex",stopReason=message.stopReason,stopDetails=message.stopDetails,safeStopDetails=stopDetails===void 0||isRecord(stopDetails)&&(stopDetails.type==="sensitive"||stopDetails.type==="refusal"&&(stopDetails.explanation===void 0||typeof stopDetails.explanation=="string"));return typeof message.api=="string"&&typeof message.provider=="string"&&typeof message.model=="string"&&isUsage(message.usage)&&(stopReason==="pending"||stopReason==="stop"||stopReason==="length"||stopReason==="toolUse"||stopReason==="error"||stopReason==="aborted")&&safeStopDetails&&isFiniteNumber(message.timestamp)&&(message.responseModel===void 0||typeof message.responseModel=="string")&&(message.responseId===void 0||typeof message.responseId=="string")&&(message.diagnostics===void 0||Array.isArray(message.diagnostics))&&(message.errorMessage===void 0||typeof message.errorMessage=="string")&&(message.rawStopReason===void 0||typeof message.rawStopReason=="string")&&hasSafeAssistantContent(message.content,providerIsGoogle)}function hasSafeToolResultEnvelope(message){return typeof message.toolCallId=="string"&&message.toolCallId.length>0&&typeof message.toolName=="string"&&message.toolName.length>0&&hasSafeToolResultContent(message.content)&&typeof message.isError=="boolean"&&isFiniteNumber(message.timestamp)&&(message.usage===void 0||isUsage(message.usage))&&(message.addedToolNames===void 0||Array.isArray(message.addedToolNames)&&message.addedToolNames.every(name=>typeof name=="string"))}function hasUnsafeRetainedContent(messages){for(let value of messages){if(!isRecord(value)||typeof value.role!="string")return!0;switch(value.role){case"user":if(!isFiniteNumber(value.timestamp)||!hasTextOnlyContent(value.content,!0))return!0;break;case"assistant":if(!hasSafeAssistantEnvelope(value))return!0;break;case"toolResult":if(!hasSafeToolResultEnvelope(value))return!0;break;case"custom":if(typeof value.customType!="string"||typeof value.display!="boolean"||!isFiniteNumber(value.timestamp)||!hasTextOnlyContent(value.content,!0))return!0;break;case"bashExecution":if(typeof value.command!="string"||typeof value.output!="string"||value.exitCode!==void 0&&!isFiniteNumber(value.exitCode)||typeof value.cancelled!="boolean"||typeof value.truncated!="boolean"||value.fullOutputPath!==void 0&&typeof value.fullOutputPath!="string"||value.excludeFromContext!==void 0&&typeof value.excludeFromContext!="boolean"||!isFiniteNumber(value.timestamp))return!0;break;case"compactionSummary":if(typeof value.summary!="string"||!isFiniteNumber(value.tokensBefore)||!isFiniteNumber(value.timestamp))return!0;break;default:return!0}}return!1}function isSafeBoundedValue(value,seen=new Set,depth=0){if(depth>32)return!1;if(value==null)return!0;let kind=typeof value;if(kind==="string"||kind==="number"||kind==="boolean")return!0;if(kind!=="object"||seen.has(value))return!1;if(seen.add(value),Array.isArray(value)){for(let item of value)if(!isSafeBoundedValue(item,seen,depth+1))return!1;return!0}let proto=Object.getPrototypeOf(value);if(proto!==Object.prototype&&proto!==null)return!1;for(let descriptor of Object.values(Object.getOwnPropertyDescriptors(value)))if(descriptor.get!==void 0||descriptor.set!==void 0||!isSafeBoundedValue(descriptor.value,seen,depth+1))return!1;return!0}function projectRetainedMessages(messages){let omittedCalls=new Set;return messages.map(original=>{let message=original,safe=!1;try{message=transformJson(original,text2=>text2),safe=isSafeBoundedValue(message)&&!hasUnsafeRetainedContent([message])}catch{}if(message.role==="assistant"&&Array.isArray(message.content))for(let block of message.content)block?.type!=="toolCall"||typeof block.id!="string"||(safe?omittedCalls.delete(block.id):omittedCalls.add(block.id));let orphanedByOmission=message.role==="toolResult"&&omittedCalls.has(message.toolCallId);if(safe&&!orphanedByOmission)return message;let timestamp=Number.isFinite(message.timestamp)?message.timestamp:0;if(message.role==="toolResult"&&!orphanedByOmission&&typeof message.toolCallId=="string"&&message.toolCallId.length>0&&typeof message.toolName=="string"&&message.toolName.length>0)return{role:"toolResult",toolCallId:message.toolCallId,toolName:message.toolName,content:[{type:"text",text:"[tool result omitted from retained context: not replay-safe]"}],isError:!0,timestamp};let text=message.role==="user"?typeof message.content=="string"?message.content:Array.isArray(message.content)?message.content.flatMap(block=>block?.type==="text"&&typeof block.text=="string"?[block.text]:[]).join(`
|
|
20
|
+
`):"":"";return{role:"user",content:`${text?`${text}
|
|
21
|
+
`:""}[message omitted from retained context: not replay-safe]`,timestamp}})}function sessionCwdMatcher(resolvedCwd){let mapped=new Map;return cwd=>{if(cwd===void 0||cwd==="")return!1;if(resolvePath(cwd)===resolvedCwd)return!0;let target=mapped.get(cwd);return target===void 0&&(target=resolvePath(resolveMovedPath(cwd)),mapped.set(cwd,target)),target===resolvedCwd}}import{existsSync}from"fs";import{readdir}from"fs/promises";import{join as join2}from"path";import{stat as stat2}from"fs/promises";import{resolve}from"path";import{open}from"fs/promises";import{StringDecoder}from"string_decoder";import{execFile}from"node:child_process";var REPOSITORY_IDENTITY_ENTRY_TYPE="repository-identity",GIT_TIMEOUT_MS=5e3,COMMIT_HASH=/^[0-9a-f]{40,64}$/,GIT_LOCATION_ENV=new Set(["GIT_DIR","GIT_WORK_TREE","GIT_COMMON_DIR","GIT_INDEX_FILE"]),runGit=(dir,args)=>new Promise(resolve5=>{let env=Object.fromEntries(Object.entries(process.env).filter(([name])=>!GIT_LOCATION_ENV.has(name)));execFile("git",["-C",dir,...args],{env,timeout:GIT_TIMEOUT_MS,windowsHide:!0},(error,stdout)=>{resolve5(error?void 0:stdout)})});async function readRepositoryIdentity(dir,run=runGit){let[roots,origin]=await Promise.all([run(dir,["rev-list","--max-parents=0","HEAD"]),run(dir,["config","--get","remote.origin.url"])]),rootCommits=(roots??"").split(/\s+/).filter(line=>COMMIT_HASH.test(line)).sort(),originUrl=origin?.trim()?normalizeRemoteUrl(origin):void 0;if(!(rootCommits.length===0&&originUrl===void 0))return originUrl===void 0?{rootCommits}:{rootCommits,originUrl}}function normalizeRemoteUrl(url){let trimmed=url.trim(),scpLike=/^(?:[^@/\s]+@)?([^:/\s]+):(?!\/)(.+)$/.exec(trimmed);return(scpLike?`${scpLike[1]}/${scpLike[2]}`:trimmed.replace(/^[a-z][a-z0-9+.-]*:\/\//i,"").replace(/^[^@/]+@/,"").replace(/^([^/:]+):\d+\//,"$1/")).replace(/\/+$/,"").replace(/\.git$/i,"").toLowerCase()}function compareRepositoryIdentities(a,b){return a===void 0||b===void 0?"unknown":a.rootCommits.length>0&&b.rootCommits.length>0?a.rootCommits.some(commit=>b.rootCommits.includes(commit))?"same":"different":a.originUrl!==void 0&&b.originUrl!==void 0?a.originUrl===b.originUrl?"same":"different":"unknown"}function parseRepositoryIdentity(value){if(typeof value!="object"||value===null)return;let{rootCommits,originUrl}=value;if(!Array.isArray(rootCommits)||!rootCommits.every(commit=>typeof commit=="string")||originUrl!==void 0&&typeof originUrl!="string")return;let commits=rootCommits.filter(commit=>COMMIT_HASH.test(commit)).sort();if(!(commits.length===0&&originUrl===void 0))return originUrl===void 0?{rootCommits:commits}:{rootCommits:commits,originUrl}}function sameRepositoryIdentity(a,b){return a===void 0||b===void 0?a===b:a.originUrl===b.originUrl&&a.rootCommits.join(",")===b.rootCommits.join(",")}function parseEntryLine(line){if(!line.trim())return null;try{return JSON.parse(line)}catch{return null}}function isMessageWithContent(message){return typeof message=="object"&&message!==null&&typeof message.role=="string"&&"content"in message}function extractTextContent(message){let content=message.content;return typeof content=="string"?content:content.filter(block=>block.type==="text").map(block=>block.text).join(" ")}function visibleMessage(entry){if(entry.type!=="message")return null;let message=entry.message;if(!isMessageWithContent(message)||message.role!=="user"&&message.role!=="assistant")return null;let messageTime=message.timestamp,entryTime=Date.parse(entry.timestamp),time=typeof messageTime=="number"?messageTime:Number.isNaN(entryTime)?void 0:entryTime;return{text:extractTextContent(message),role:message.role,time}}function sessionInfoName(entry){return entry.type!=="session_info"?null:entry.name?.trim()||void 0}function newAccumulator(){return{header:null,name:void 0,firstUserMessage:"",messageCount:0,lastActivityTime:void 0,repositoryIdentity:void 0,texts:[]}}function accumulateLine(accumulator,line){let entry=parseEntryLine(line);if(!entry)return!0;if(!accumulator.header)return entry.type!=="session"||typeof entry.id!="string"?!1:(accumulator.header=entry,!0);if(entry.type==="custom"&&entry.customType===REPOSITORY_IDENTITY_ENTRY_TYPE)return accumulator.repositoryIdentity=parseRepositoryIdentity(entry.data)??accumulator.repositoryIdentity,!0;let infoName=sessionInfoName(entry);if(infoName!==null)return accumulator.name=infoName,!0;if(entry.type!=="message")return!0;accumulator.messageCount++;let visible=visibleMessage(entry);return!visible||(typeof visible.time=="number"&&(accumulator.lastActivityTime=Math.max(accumulator.lastActivityTime??0,visible.time)),!visible.text)||(accumulator.texts.push(visible.text),!accumulator.firstUserMessage&&visible.role==="user"&&(accumulator.firstUserMessage=visible.text)),!0}var LINE_READ_BUFFER_SIZE=1024*1024;async function readFileLines(filePath,onLine){let handle=await open(filePath,"r");try{let decoder=new StringDecoder("utf8"),buffer=Buffer.allocUnsafe(LINE_READ_BUFFER_SIZE),pending="",bytes=0,lastByte=-1,emit=line=>onLine(line.endsWith("\r")?line.slice(0,-1):line);for(;;){let{bytesRead}=await handle.read(buffer,0,buffer.length,null);if(bytesRead===0)break;bytes+=bytesRead,lastByte=buffer[bytesRead-1]??-1;let searchFrom=pending.length;pending+=decoder.write(buffer.subarray(0,bytesRead));let lineStart=0,newlineIndex=pending.indexOf(`
|
|
20
22
|
`,searchFrom);for(;newlineIndex!==-1;){if(!emit(pending.slice(lineStart,newlineIndex)))return{completed:!1,bytes,endsWithNewline:!1};lineStart=newlineIndex+1,newlineIndex=pending.indexOf(`
|
|
21
23
|
`,lineStart)}pending=pending.slice(lineStart)}return pending+=decoder.end(),pending&&!emit(pending)?{completed:!1,bytes,endsWithNewline:!1}:{completed:!0,bytes,endsWithNewline:lastByte===10}}finally{await handle.close()}}async function readSessionSummary(filePath){let accumulator=newAccumulator();try{if(!(await readFileLines(filePath,line=>accumulateLine(accumulator,line))).completed)return null}catch(error){if(error instanceof Error)return null;throw error}let header=accumulator.header;return header?{header,name:accumulator.name,firstUserMessage:accumulator.firstUserMessage,messageCount:accumulator.messageCount,lastActivityTime:accumulator.lastActivityTime,allMessagesText:accumulator.texts.join(" "),...accumulator.repositoryIdentity?{repositoryIdentity:accumulator.repositoryIdentity}:{}}:null}import{stat}from"fs/promises";import{basename,join}from"path";import{appendFile,rename,rm,writeFile}from"fs/promises";var SESSION_SUMMARY_INDEX_FILE=".session-summaries.index",INDEX_VERSION=2,HEADER_LINE=`${JSON.stringify({version:INDEX_VERSION})}
|
|
22
|
-
`,UNUSABLE={usable:!1,entries:new Map,entryBytes:0,endsWithNewline:!0};function isObject(value){return typeof value=="object"&&value!==null}function isOptional(value,type){return value===void 0||typeof value===type}function isSessionSummary(value){return!isObject(value)||!isObject(value.header)?!1:value.header.type==="session"&&typeof value.header.id=="string"&&typeof value.firstUserMessage=="string"&&typeof value.messageCount=="number"&&typeof value.allMessagesText=="string"&&isOptional(value.name,"string")&&isOptional(value.lastActivityTime,"number")&&(value.repositoryIdentity===void 0||parseRepositoryIdentity(value.repositoryIdentity)!==void 0)}function
|
|
23
|
-
`)}function withLine(file,stamp,summary,line){return{file,stamp,summary,line,lineBytes:Buffer.byteLength(line,"utf8")}}function parseEntryLine2(line){let parsed;try{parsed=JSON.parse(line)}catch{return}if(!(!isObject(parsed)||typeof parsed.file!="string"||parsed.file.includes("/"))&&!(!
|
|
24
|
+
`,UNUSABLE={usable:!1,entries:new Map,entryBytes:0,endsWithNewline:!0};function isObject(value){return typeof value=="object"&&value!==null}function isOptional(value,type){return value===void 0||typeof value===type}function isSessionSummary(value){return!isObject(value)||!isObject(value.header)?!1:value.header.type==="session"&&typeof value.header.id=="string"&&typeof value.firstUserMessage=="string"&&typeof value.messageCount=="number"&&typeof value.allMessagesText=="string"&&isOptional(value.name,"string")&&isOptional(value.lastActivityTime,"number")&&(value.repositoryIdentity===void 0||parseRepositoryIdentity(value.repositoryIdentity)!==void 0)}function isFiniteNumber2(value){return typeof value=="number"&&Number.isFinite(value)}function toIndexEntry(file,stamp,summary){if(!(summary.lastActivityTime!==void 0&&!Number.isFinite(summary.lastActivityTime)))return withLine(file,stamp,summary,`${JSON.stringify({file,size:stamp.size,mtimeMs:stamp.mtimeMs,summary})}
|
|
25
|
+
`)}function withLine(file,stamp,summary,line){return{file,stamp,summary,line,lineBytes:Buffer.byteLength(line,"utf8")}}function parseEntryLine2(line){let parsed;try{parsed=JSON.parse(line)}catch{return}if(!(!isObject(parsed)||typeof parsed.file!="string"||parsed.file.includes("/"))&&!(!isFiniteNumber2(parsed.size)||!isFiniteNumber2(parsed.mtimeMs)||!isSessionSummary(parsed.summary)))return withLine(parsed.file,{size:parsed.size,mtimeMs:parsed.mtimeMs},parsed.summary,`${line}
|
|
24
26
|
`)}function isCurrentHeader(line){try{let parsed=JSON.parse(line);return isObject(parsed)&&parsed.version===INDEX_VERSION}catch{return!1}}async function loadIndexFile(path2){let entries=new Map,headerSeen=!1,headerBytes=0;try{let read=await readFileLines(path2,line=>{if(!headerSeen)return headerSeen=!0,headerBytes=Buffer.byteLength(line,"utf8")+1,isCurrentHeader(line);let entry=parseEntryLine2(line);return entry&&entries.set(entry.file,entry),!0});return!read.completed||!headerSeen?UNUSABLE:{usable:!0,entries,entryBytes:Math.max(0,read.bytes-headerBytes),endsWithNewline:read.endsWithNewline}}catch(error){if(error instanceof Error)return UNUSABLE;throw error}}async function appendIndexEntries(path2,entries,endsWithNewline){let prefix=endsWithNewline?"":`
|
|
25
|
-
`;for(let entry of entries)await appendFile(path2,prefix+entry.line),prefix=""}async function rewriteIndexFile(path2,entries){let temp=`${path2}.tmp-${process.pid}-${Math.random().toString(36).slice(2)}`;try{await writeFile(temp,HEADER_LINE+entries.map(entry=>entry.line).join("")),await rename(temp,path2)}catch(error){throw await rm(temp,{force:!0}).catch(()=>{}),error}}var SESSION_SUMMARY_INDEX_MAX_BYTES=256*1024*1024,snapshots=new Map;function stampsMatch(left,right){return left.size===right.size&&left.mtimeMs===right.mtimeMs}async function statStamp(path2){try{let stats=await stat(path2);return{size:stats.size,mtimeMs:stats.mtimeMs}}catch(error){if(error instanceof Error)return;throw error}}function recency(entry){let headerTime=Date.parse(entry.summary.header.timestamp);return entry.summary.lastActivityTime??(Number.isNaN(headerTime)?0:headerTime)}function selectWithinBudget(entries,maxBytes){let kept=[],bytes=0;for(let entry of[...entries].sort((left,right)=>recency(right)-recency(left)))if(!(entry.lineBytes>maxBytes)){if(bytes+entry.lineBytes>maxBytes)break;kept.push(entry),bytes+=entry.lineBytes}return kept}var SessionSummaryIndex=class{constructor(dir,options={}){this.recorded=[],this.path=join(dir,SESSION_SUMMARY_INDEX_FILE),this.maxBytes=options.maxBytes??SESSION_SUMMARY_INDEX_MAX_BYTES}async lookup(filePath,stamp){let file=basename(filePath);if(!this.loading){this.snapshot??=this.currentSnapshot();let known=await this.snapshot,indexed=known?.entryStamps.get(file);if(known&&!(indexed&&stampsMatch(indexed,stamp)))return}this.loading??=this.load();let entry=(await this.loading).entries.get(file);return entry&&stampsMatch(entry.stamp,stamp)?entry.summary:void 0}record(filePath,stamp,summary){this.recorded.push({file:basename(filePath),stamp,summary})}async persist(presentFiles){if(!this.loading)return;let loaded=await this.loading,entries=new Map(loaded.entries),added=new Set;for(let{file,stamp,summary}of this.recorded){let existing=entries.get(file);if(existing&&stampsMatch(existing.stamp,stamp))continue;let entry=toIndexEntry(file,stamp,summary);entry&&(entries.set(file,entry),added.add(entry))}let present=new Set(presentFiles.map(path2=>basename(path2))),live=[...entries.values()].filter(entry=>present.has(entry.file)),kept=selectWithinBudget(live,this.maxBytes),keptBytes=kept.reduce((total,entry)=>total+entry.lineBytes,0),appended=kept.filter(entry=>added.has(entry)),appendedBytes=appended.reduce((total,entry)=>total+entry.lineBytes,0);try{if(!loaded.usable&&kept.length>0||loaded.usable&&loaded.entryBytes+appendedBytes>2*keptBytes)await rewriteIndexFile(this.path,kept),this.remember(await statStamp(this.path),kept);else if(loaded.usable&&appended.length>0){await appendIndexEntries(this.path,appended,loaded.endsWithNewline);let inFile=new Map(loaded.entries);for(let entry of appended)inFile.set(entry.file,entry);this.remember(await statStamp(this.path),inFile.values())}}catch(error){if(!(error instanceof Error))throw error;snapshots.delete(this.path)}}async currentSnapshot(){let recorded=snapshots.get(this.path);if(!recorded)return;let current=await statStamp(this.path);return current&&stampsMatch(current,recorded.indexStamp)?recorded:void 0}async load(){let before=await statStamp(this.path),loaded=await loadIndexFile(this.path);return this.remember(before,loaded.usable?loaded.entries.values():void 0),loaded}remember(indexStamp,entries){if(!indexStamp||!entries){snapshots.delete(this.path);return}let entryStamps=new Map;for(let entry of entries)entryStamps.set(entry.file,entry.stamp);snapshots.set(this.path,{indexStamp,entryStamps})}};var SessionSummaryLru=class{constructor(budget){this.entries=new Map,this.retainedTextBytes=0,this.budget=budget}get size(){return this.entries.size}get textBytes(){return this.retainedTextBytes}get(key){let retained=this.entries.get(key);if(retained)return this.entries.delete(key),this.entries.set(key,retained),retained.entry}drop(key){let retained=this.entries.get(key);retained&&(this.entries.delete(key),this.retainedTextBytes-=retained.textBytes)}retain(key,entry){this.drop(key);let textBytes=Buffer.byteLength(entry.summary.allMessagesText,"utf8");textBytes>this.budget.maxTextBytes||(this.entries.set(key,{entry,textBytes}),this.retainedTextBytes+=textBytes,this.evictUntilWithinBudget())}clear(){this.entries.clear(),this.retainedTextBytes=0}evictUntilWithinBudget(){for(;this.entries.size>this.budget.maxEntries||this.retainedTextBytes>this.budget.maxTextBytes;){let oldest=this.entries.keys().next();if(oldest.done)break;this.drop(oldest.value)}}};var SESSION_SUMMARY_CACHE_LIMIT=4096,SESSION_SUMMARY_CACHE_MAX_TEXT_BYTES=64*1024*1024,cache=new SessionSummaryLru({maxEntries:SESSION_SUMMARY_CACHE_LIMIT,maxTextBytes:SESSION_SUMMARY_CACHE_MAX_TEXT_BYTES}),streamedSummaries=0;function stampsMatch2(left,right){return left.size===right.size&&left.mtimeMs===right.mtimeMs}async function readCachedSessionSummary(filePath,store2){let key=resolve(filePath),stamp,mtime;try{let stats=await stat2(filePath);stamp={size:stats.size,mtimeMs:stats.mtimeMs},mtime=stats.mtime}catch(error){if(!(error instanceof Error))throw error;return cache.drop(key),null}let cached=cache.get(key);if(cached&&stampsMatch2(cached.stamp,stamp))return store2?.record(filePath,stamp,cached.summary),{summary:cached.summary,mtime:cached.mtime};let stored=await store2?.lookup(filePath,stamp);if(stored)return cache.retain(key,{stamp,summary:stored,mtime}),{summary:stored,mtime};streamedSummaries++;let summary=await readSessionSummary(filePath);return summary?(cache.retain(key,{stamp,summary,mtime}),store2?.record(filePath,stamp,summary),{summary,mtime}):(cache.drop(key),null)}var MAX_CONCURRENT_SESSION_INFO_LOADS=10,CURRENT_SESSION_LIST_PUBLISH_INTERVAL=10,ALL_SESSION_LIST_PUBLISH_INTERVAL=100;function sortSessionInfos(sessions){return sessions.sort((a,b)=>b.modified.getTime()-a.modified.getTime())}function resolveModified(activityTime,header,mtime){if(typeof activityTime=="number"&&activityTime>0)return new Date(activityTime);let headerTime=typeof header.timestamp=="string"?Date.parse(header.timestamp):Number.NaN;return Number.isNaN(headerTime)?mtime:new Date(headerTime)}async function buildSessionInfo(filePath,store2){let cached=await readCachedSessionSummary(filePath,store2);if(!cached)return null;let{summary,mtime}=cached,header=summary.header;return{path:filePath,id:header.id,cwd:typeof header.cwd=="string"?header.cwd:"",name:summary.name,parentSessionPath:header.parentSession,created:new Date(header.timestamp),modified:resolveModified(summary.lastActivityTime,header,mtime),messageCount:summary.messageCount,firstMessage:summary.firstUserMessage||"(no messages)",allMessagesText:summary.allMessagesText,...summary.repositoryIdentity?{repositoryIdentity:summary.repositoryIdentity}:{}}}async function buildSessionInfosWithConcurrency(files,onLoaded,store2,signal){let results=new Array(files.length).fill(null),inFlight=new Set,nextIndex=0,startNext=()=>{let index=nextIndex++,file=files[index];if(!file)return;let task;task=buildSessionInfo(file,store2).then(info=>{results[index]=info}).catch(()=>{results[index]=null}).finally(()=>{inFlight.delete(task),onLoaded(results[index]??null)}),inFlight.add(task)};for(;nextIndex<files.length||inFlight.size>0;){for(;!signal?.aborted&&nextIndex<files.length&&inFlight.size<MAX_CONCURRENT_SESSION_INFO_LOADS;)startNext();if(inFlight.size===0)break;await Promise.race(inFlight)}return signal?.throwIfAborted(),results}async function listSessionInfos(files,onLoaded,store2,signal){let results=await buildSessionInfosWithConcurrency(files,onLoaded,store2,signal),sessions=[];for(let info of results)info&&sessions.push(info);return sessions}async function listSessionFilesInDir(dir,files,onLoaded,signal){let index=new SessionSummaryIndex(dir),sessions=await listSessionInfos(files,onLoaded,index,signal);return await index.persist(files),sessions}async function listSessionsFromDir(dir,onProgress,signal){if(signal?.throwIfAborted(),!existsSync(dir))return[];try{let files=(await readdir(dir)).filter(name=>name.endsWith(".jsonl")).map(name=>join2(dir,name)),loaded=0,partialSessions=[];return await listSessionFilesInDir(dir,files,info=>{loaded++,info&&partialSessions.push(info);let publish=loaded===1||loaded%CURRENT_SESSION_LIST_PUBLISH_INTERVAL===0||loaded===files.length;onProgress?.(loaded,files.length,publish?sortSessionInfos([...partialSessions]):void 0)},signal)}catch{return signal?.throwIfAborted(),[]}}function materializeSessionEntries(entries,options){let{residentStore,loadHistoryEntries,onMaterialized}=options,missingEntryIds=new Set,materialized=entries.map(entry=>residentStore.materialize(entry,()=>{missingEntryIds.add(entry.id)}));if(missingEntryIds.size===0){for(let entry of materialized)onMaterialized(entry);return materialized}let persistedById=new Map(loadHistoryEntries().filter(entry=>entry.type!=="session").map(entry=>[entry.id,entry])),repaired=materialized.map(entry=>{if(!missingEntryIds.has(entry.id))return entry;let persisted=persistedById.get(entry.id);return persisted===void 0?entry:residentStore.materialize(persisted)});for(let entry of repaired)onMaterialized(entry);return repaired}import{randomUUID}from"node:crypto";import{closeSync,fchmodSync,fsyncSync,openSync,realpathSync,renameSync,rmSync,statSync,writeFileSync}from"node:fs";import{basename as basename2,dirname,join as join3}from"node:path";var UNSUPPORTED_DIRECTORY_SYNC=new Set(["EINVAL","ENOTSUP","EOPNOTSUPP","EISDIR"]),DIRECTORY_NOT_WRITABLE=new Set(["EACCES","EPERM","EROFS"]);function errnoCode(error){return error instanceof Error&&"code"in error&&typeof error.code=="string"?error.code:void 0}function resolveTarget(filePath){try{let path2=realpathSync(filePath);return{path:path2,mode:statSync(path2).mode&4095}}catch(error){if(errnoCode(error)==="ENOENT")return{path:filePath,mode:void 0};throw error}}function openTemp(tempPath){try{return openSync(tempPath,"wx")}catch(error){let code=errnoCode(error);if(code!==void 0&&DIRECTORY_NOT_WRITABLE.has(code))return;throw error}}function rewriteInPlace(path2,chunks){let fd=openSync(path2,"w");try{for(let chunk of chunks)writeFileSync(fd,chunk)}finally{closeSync(fd)}}function writeDurably(fd,chunks,mode){try{mode!==void 0&&fchmodSync(fd,mode);for(let chunk of chunks)writeFileSync(fd,chunk);fsyncSync(fd)}finally{closeSync(fd)}}function syncDirectory(directory){if(process.platform==="win32")return;let fd=openSync(directory,"r");try{fsyncSync(fd)}catch(error){let code=errnoCode(error);if(code===void 0||!UNSUPPORTED_DIRECTORY_SYNC.has(code))throw error}finally{closeSync(fd)}}function replaceFileAtomically(filePath,chunks){let target=resolveTarget(filePath),tempPath=join3(dirname(target.path),`.${basename2(target.path)}.${randomUUID()}.tmp`),tempFd=openTemp(tempPath);if(tempFd===void 0){rewriteInPlace(target.path,chunks);return}try{writeDurably(tempFd,chunks,target.mode),renameSync(tempPath,target.path)}catch(error){try{rmSync(tempPath,{force:!0})}catch(cleanupError){throw new AggregateError([error,cleanupError],"session file rewrite failed and its temporary file could not be removed")}throw error}syncDirectory(dirname(target.path))}import{createHash}from"node:crypto";import{existsSync as existsSync2,mkdirSync,readFileSync,renameSync as renameSync2,rmSync as rmSync2,writeFileSync as writeFileSync2}from"node:fs";import{join as join4}from"node:path";var OMIT_JSON_VALUE=Symbol("omit-json-value");function transformJson(value,transformString){let transformed=transformJsonValue(value,transformString,"",new WeakSet);if(transformed===OMIT_JSON_VALUE){let serialized=JSON.stringify(value);if(serialized===void 0)throw new SyntaxError("JSON-compatible value expected");return JSON.parse(serialized)}return transformed}function transformJsonValue(value,transformString,key,seen){if(typeof value=="string")return transformString(value);if(typeof value=="number")return Number.isFinite(value)?value:null;if(value===null||typeof value=="boolean")return value;if(typeof value=="bigint")throw new TypeError("Do not know how to serialize a BigInt");if(typeof value>"u"||typeof value=="function"||typeof value=="symbol")return OMIT_JSON_VALUE;if(seen.has(value))throw new TypeError("Converting circular structure to JSON");seen.add(value);let jsonValue=hasJsonSerializer(value)?value.toJSON(key):value;if(jsonValue!==value){let transformed2=transformJsonValue(jsonValue,transformString,key,seen);return seen.delete(value),transformed2}if(Array.isArray(value)){let transformed2=Array.from({length:value.length},(_item,index)=>{let item=value[index],transformedItem=transformJsonValue(item,transformString,String(index),seen);return transformedItem===OMIT_JSON_VALUE?null:transformedItem});return seen.delete(value),transformed2}let transformed={};for(let[key2,item]of Object.entries(value)){let transformedItem=transformJsonValue(item,transformString,String(key2),seen);transformedItem!==OMIT_JSON_VALUE&&Object.defineProperty(transformed,key2,{configurable:!0,enumerable:!0,value:transformedItem,writable:!0})}return seen.delete(value),transformed}function hasJsonSerializer(value){return"toJSON"in value&&typeof value.toJSON=="function"}import{Buffer as Buffer2}from"buffer";var ResidentSizeAccounting=class{constructor(){this.bytes=0,this.evictedCount=0,this.evictedBytes=0}get residentBytes(){return this.bytes}added(text){this.bytes+=Buffer2.byteLength(text,"utf8")}removed(text){this.bytes-=Buffer2.byteLength(text,"utf8")}evicted(text){this.evictedCount++,this.evictedBytes+=Buffer2.byteLength(text,"utf8")}reset(){this.bytes=0,this.evictedCount=0,this.evictedBytes=0}stats(){return{blobBytes:this.bytes,evictedCount:this.evictedCount,evictedBytes:this.evictedBytes}}};var RESIDENT_STRING_MIN_BYTES=32*1024,DEFAULT_RESIDENT_STRING_BUDGET_BYTES=64*1024*1024,RESIDENT_STRING_PREFIX="\0senpi-resident-string:v1:",ResidentStringStore=class{constructor(options={}){this.tokenFree=new WeakSet,this.strings=new Map,this.accounting=new ResidentSizeAccounting,this.maxBytes=options.maxBytes??DEFAULT_RESIDENT_STRING_BUDGET_BYTES,this.blobsDir=options.blobsDir}configure(options){this.blobsDir=options.blobsDir}clear(){this.strings.clear(),this.accounting.reset();let dir=this.blobsDir?.();if(dir)try{rmSync2(dir,{force:!0,recursive:!0})}catch{}}spillResident(){if(this.blobsDir?.())for(let[id,text]of this.strings)this._writeBlob(id,text)&&(this.strings.delete(id),this.accounting.removed(text))}stats(){return{blobCount:this.strings.size,...this.accounting.stats()}}size(){return{entries:this.strings.size,approxBytes:this.accounting.residentBytes}}externalize(value){let tokenized=!1,externalized=transformJson(value,text=>{let stored=this.externalizeString(text);return stored.startsWith(RESIDENT_STRING_PREFIX)&&(tokenized=!0),stored});return!tokenized&&typeof externalized=="object"&&externalized!==null&&this.tokenFree.add(externalized),externalized}materialize(value,onMissing){return typeof value=="object"&&value!==null&&this.tokenFree.has(value)?value:transformJson(value,text=>this.materializeString(text,onMissing))}isTokenFree(value){return this.tokenFree.has(value)}adoptTokenFree(value){this.tokenFree.add(value)}resolvedBlobsDir(){return this.blobsDir?.()}externalizeInPlace(value){this._mutateStringsInPlace(value,new Set,text=>this.externalizeString(text))}materializeInPlace(value){this._mutateStringsInPlace(value,new Set,text=>this.materializeString(text))}_mutateStringsInPlace(value,seen,mutate){if(typeof value!="object"||value===null||seen.has(value))return;seen.add(value);let record=value;for(let key of Object.keys(record)){let current=record[key];if(typeof current=="string"){let next=mutate(current);next!==current&&(record[key]=next)}else typeof current=="object"&¤t!==null&&this._mutateStringsInPlace(current,seen,mutate)}}externalizeString(text){if(text.length<RESIDENT_STRING_MIN_BYTES||text.startsWith(RESIDENT_STRING_PREFIX))return text;let id=createHash("sha256").update(text,"utf8").digest("hex"),token=`${RESIDENT_STRING_PREFIX}${id}`;return this.strings.has(id)?(this.strings.delete(id),this.strings.set(id,text),token):(this.strings.set(id,text),this.accounting.added(text),this._enforceBudget(),token)}materializeString(text,onMissing){if(!text.startsWith(RESIDENT_STRING_PREFIX))return text;let id=text.slice(RESIDENT_STRING_PREFIX.length),resident=this.strings.get(id);if(resident!==void 0)return this.strings.delete(id),this.strings.set(id,resident),resident;let hydrated=this._readBlob(id);return hydrated!==void 0?hydrated:onMissing?.(id)??text}_enforceBudget(){for(;this.accounting.residentBytes>this.maxBytes&&this.strings.size>0;){let[oldestId,oldest]=this.strings.entries().next().value;if(!this._writeBlob(oldestId,oldest))return;this.strings.delete(oldestId),this.accounting.removed(oldest)}}_writeBlob(id,text){let dir=this.blobsDir?.();if(!dir)return!1;let final=join4(dir,`${id}.blob`),temp=`${final}.tmp`;try{mkdirSync(dir,{recursive:!0}),existsSync2(final)||(writeFileSync2(temp,JSON.stringify({v:1,text}),"utf8"),renameSync2(temp,final))}catch{try{rmSync2(temp,{force:!0})}catch{}return!1}return this.accounting.evicted(text),!0}_readBlob(id){let dir=this.blobsDir?.();if(!dir)return;let file=join4(dir,`${id}.blob`);try{let parsed=JSON.parse(readFileSync(file,"utf8"));if(typeof parsed.text=="string")return parsed.text}catch{}try{rmSync2(file,{force:!0})}catch{}}};import{closeSync as closeSync2,fstatSync,ftruncateSync,openSync as openSync2,readSync,rmSync as rmSync3}from"node:fs";import{rm as rm2}from"node:fs/promises";var NEWLINE=10,SCAN_CHUNK_BYTES=64*1024;function truncateToLastCompleteLine(path2){let fd=openSync2(path2,"r+");try{let size=fstatSync(fd).size,chunk=Buffer.alloc(Math.min(SCAN_CHUNK_BYTES,size)),end=size;for(;end>0;){let start=Math.max(0,end-chunk.length),read=readSync(fd,chunk,0,end-start,start),newline=chunk.subarray(0,read).lastIndexOf(NEWLINE);if(newline>=0){let completeLength=start+newline+1;completeLength<size&&ftruncateSync(fd,completeLength);return}end=start}}finally{closeSync2(fd)}}function discardFailedFirstFlush(path2,fd,writeError){let cleanupErrors=[];try{closeSync2(fd)}catch(closeError){cleanupErrors.push(closeError)}try{rmSync3(path2,{force:!0})}catch(removeError){cleanupErrors.push(removeError)}throwWriteError(path2,writeError,cleanupErrors)}async function discardFailedFirstFlushAsync(path2,handle,writeError){let cleanupErrors=[];if(handle!==void 0)try{await handle.close()}catch(closeError){cleanupErrors.push(closeError)}try{await rm2(path2,{force:!0})}catch(removeError){cleanupErrors.push(removeError)}throwWriteError(path2,writeError,cleanupErrors)}function throwWriteError(path2,writeError,cleanupErrors){throw cleanupErrors.length>0?new AggregateError([writeError,...cleanupErrors],`Session file write failed and the partial file ${path2} could not be cleaned up`):writeError}var reserve;function reserveSessionWrite(path2){reserve?.(path2)}var liveWriters=new Set,writerRefs=new WeakMap;function registerSessionWriter(owner){if(writerRefs.has(owner))return;let ref=new WeakRef(owner);writerRefs.set(owner,ref),liveWriters.add(ref)}function unregisterSessionWriter(owner){let ref=writerRefs.get(owner);ref&&(writerRefs.delete(owner),liveWriters.delete(ref))}function hasOtherLiveSessionWriter(path2,self){for(let ref of liveWriters){let owner=ref.deref();if(!owner){liveWriters.delete(ref);continue}if(owner!==self&&owner.isPersisted()&&owner.getSessionFile()===path2)return!0}return!1}function uuidv7(){let ts=BigInt(Date.now()),bytes=randomBytes(10),hex=[(ts>>40n&0xffn).toString(16).padStart(2,"0"),(ts>>32n&0xffn).toString(16).padStart(2,"0"),(ts>>24n&0xffn).toString(16).padStart(2,"0"),(ts>>16n&0xffn).toString(16).padStart(2,"0"),(ts>>8n&0xffn).toString(16).padStart(2,"0"),(ts&0xffn).toString(16).padStart(2,"0"),(112|bytes[0]&15).toString(16).padStart(2,"0"),bytes[1].toString(16).padStart(2,"0"),(128|bytes[2]&63).toString(16).padStart(2,"0"),bytes[3].toString(16).padStart(2,"0"),...Array.from(bytes.slice(4),b=>b.toString(16).padStart(2,"0"))].join("");return`${hex.slice(0,8)}-${hex.slice(8,12)}-${hex.slice(12,16)}-${hex.slice(16,20)}-${hex.slice(20,32)}`}function isPlainJson(value,depth=0){if(depth>64)return!1;if(value===null||typeof value=="string"||typeof value=="boolean")return!0;if(typeof value=="number")return Number.isFinite(value);if(Array.isArray(value)){for(let index=0;index<value.length;index++){let item=value[index];if(item===void 0||!isPlainJson(item,depth+1))return!1}return!0}if(typeof value!="object")return!1;let prototype=Object.getPrototypeOf(value);if(prototype!==Object.prototype&&prototype!==null)return!1;for(let item of Object.values(value))if(item!==void 0&&!isPlainJson(item,depth+1))return!1;return!0}var contextMessageEntryIds=new WeakMap,SESSION_CONTEXT_ENTRY_ID="__piSessionContextEntryId";function withContextEntryId(entryId,message){return contextMessageEntryIds.set(message,entryId),message}function getSessionContextEntryId(message){return contextMessageEntryIds.get(message)}function inheritSessionContextEntryId(derived,source){let fromProperty=Object.getOwnPropertyDescriptor(source,SESSION_CONTEXT_ENTRY_ID)?.value,entryId=getSessionContextEntryId(source)??(typeof fromProperty=="string"?fromProperty:void 0);return entryId===void 0||(contextMessageEntryIds.set(derived,entryId),Object.assign(derived,{[SESSION_CONTEXT_ENTRY_ID]:entryId})),derived}var CURRENT_SESSION_VERSION=3;function createSessionId(){return uuidv7()}function assertValidSessionId(id){if(!/^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/.test(id))throw new Error("Session id must be non-empty, contain only alphanumeric characters, '-', '_', and '.', and start and end with an alphanumeric character")}function generateId(byId){for(let i=0;i<100;i++){let id=randomUUID2().slice(0,8);if(!byId.has(id))return id}return randomUUID2()}function migrateV1ToV2(entries){let ids=new Set,prevId=null;for(let entry of entries){if(entry.type==="session"){entry.version=2;continue}if(entry.id=generateId(ids),entry.parentId=prevId,prevId=entry.id,entry.type==="compaction"){let comp=entry;if(typeof comp.firstKeptEntryIndex=="number"){let targetEntry=entries[comp.firstKeptEntryIndex];targetEntry&&targetEntry.type!=="session"&&(comp.firstKeptEntryId=targetEntry.id),delete comp.firstKeptEntryIndex}}}}function migrateV2ToV3(entries){for(let entry of entries){if(entry.type==="session"){entry.version=3;continue}if(entry.type==="message"){let msgEntry=entry;msgEntry.message&&msgEntry.message.role==="hookMessage"&&(msgEntry.message.role="custom")}}}function migrateToCurrentVersion(entries){let version=entries.find(e=>e.type==="session")?.version??1;return version>=CURRENT_SESSION_VERSION?!1:(version<2&&migrateV1ToV2(entries),version<3&&migrateV2ToV3(entries),!0)}function migrateSessionEntries(entries){migrateToCurrentVersion(entries)}function parseSessionEntries(content){let entries=[],lines=content.trim().split(`
|
|
26
|
-
`);for(let line of lines)if(line.trim())try{let entry=JSON.parse(line);entries.push(entry)}catch{}return entries}function getLatestCompactionEntry(entries){for(let i=entries.length-1;i>=0;i--)if(entries[i].type==="compaction")return entries[i];return null}function buildEntryIndex(entries,byId){if(byId)return byId;let index=new Map;for(let entry of entries)index.set(entry.id,entry);return index}function buildSessionPath(entries,leafId,byId){let index=buildEntryIndex(entries,byId),leaf;if(leafId===null)return[];if(leafId&&(leaf=index.get(leafId)),leaf??=entries[entries.length-1],!leaf)return[];let path2=[],visited=new Set,current=leaf;for(;current&&!visited.has(current);)visited.add(current),path2.push(current),current=current.parentId?index.get(current.parentId):void 0;return path2.reverse(),path2}function getSessionContextSettings(path2){let thinkingLevel="off",thinkingSelection,configurationUpdate,model=null,isModelSelectionExplicit=!1,isInFallbackWindow=!1,preFallbackThinkingLevel=thinkingLevel,preFallbackThinkingSelection=thinkingSelection;for(let entry of path2)if(entry.type==="thinking_level_change")thinkingLevel=entry.thinkingLevel,thinkingSelection=entry.thinkingSelection;else if(entry.type==="configuration_update")configurationUpdate={effort:entry.reasoning.effort};else if(entry.type==="model_change")entry.reason==="fallback"?(isInFallbackWindow||(preFallbackThinkingLevel=thinkingLevel,preFallbackThinkingSelection=thinkingSelection,entry.originalProvider&&entry.originalModelId&&(model={provider:normalizeProviderId(entry.originalProvider),modelId:entry.originalModelId},isModelSelectionExplicit=!0)),isInFallbackWindow=!0):entry.reason==="fallback-revert"?(isInFallbackWindow&&(thinkingLevel=preFallbackThinkingLevel,thinkingSelection=preFallbackThinkingSelection),isInFallbackWindow=!1):(isInFallbackWindow=!1,entry.provider&&entry.modelId&&(model={provider:normalizeProviderId(entry.provider),modelId:entry.modelId},isModelSelectionExplicit=!0));else if(entry.type==="message"&&entry.message.role==="assistant"&&!isInFallbackWindow&&!isVirtualModel(entry.message)){if(isModelSelectionExplicit&&model?.provider===normalizeProviderId(entry.message.provider))continue;model={provider:normalizeProviderId(entry.message.provider),modelId:entry.message.model},isModelSelectionExplicit=!1}return isInFallbackWindow&&(thinkingLevel=preFallbackThinkingLevel,thinkingSelection=preFallbackThinkingSelection),{thinkingLevel,thinkingSelection,configurationUpdate,model}}function sessionEntryToContextMessages(entry){if(entry.type==="message"){let message=entry.message;return message.role==="system"&&message.content==null?[{...message,content:""}]:(message.role==="user"||message.role==="assistant"||message.role==="toolResult")&&message.content==null?[withContextEntryId(entry.id,{...message,content:[]})]:[withContextEntryId(entry.id,message)]}if(entry.type==="configuration_update")return[withContextEntryId(entry.id,{role:"configurationUpdate",content:[],effort:entry.reasoning.effort,timestamp:new Date(entry.timestamp).getTime()})];if(entry.type==="custom_message")return[withContextEntryId(entry.id,createCustomMessage(entry.customType,entry.content??[],entry.display,entry.details,entry.timestamp))];if(entry.type==="branch_summary"&&entry.summary)return[withContextEntryId(entry.id,createBranchSummaryMessage(entry.summary,entry.fromId,entry.timestamp))];if(entry.type==="compaction"){let summary=withContextEntryId(entry.id,createCompactionSummaryMessage(entry.summary,entry.tokensBefore,entry.timestamp,entry.details));return entry.systemMessage?[withContextEntryId(entry.id,entry.systemMessage),summary]:[summary]}return[]}function buildContextEntries(entries,leafId,byId){return contextEntriesOfPath(buildSessionPath(entries,leafId,byId))}function contextEntriesOfPath(path2){let compaction=null;for(let entry of path2)entry.type==="compaction"&&(compaction=entry);if(!compaction)return path2;let compactionIdx=path2.findIndex(entry=>entry.id===compaction.id);if(compactionIdx<0)return path2;let contextEntries=[compaction],foundFirstKept=!1;for(let i=0;i<compactionIdx;i++){let entry=path2[i];entry.type!=="compaction"&&(entry.id===compaction.firstKeptEntryId&&(foundFirstKept=!0),foundFirstKept&&!(entry.type==="message"&&entry.message.role==="system")&&contextEntries.push(entry))}return contextEntries.push(...path2.slice(compactionIdx+1)),contextEntries}function projectContextEntry(entry,edit){let messages=sessionEntryToContextMessages(entry);if(!edit)return messages;let replacement=edit.replacement;return replacement===null?[]:messages.map(message=>{if(message.role!=="user"&&message.role!=="assistant"&&message.role!=="toolResult"&&message.role!=="custom")return message;let content=(message.role==="assistant"||message.role==="toolResult")&&typeof replacement.content=="string"?[{type:"text",text:replacement.content}]:replacement.content;return withContextEntryId(entry.id,{...message,content})})}function projectSession(entries,leafId,byId,knownPath){let path2=knownPath??buildSessionPath(entries,leafId,byId),settings=getSessionContextSettings(path2),contextEntries=contextEntriesOfPath(path2),edits=new Map;for(let entry of contextEntries)entry.type==="context_edit"&&edits.set(entry.targetId,entry);let projectedEntries=contextEntries.map((sourceEntry,index)=>({sourceEntry,messages:sourceEntry.type==="compaction"&&index>0?[]:projectContextEntry(sourceEntry,edits.get(sourceEntry.id))}));return{projection:{entries:projectedEntries,messages:projectedEntries.flatMap(entry=>entry.messages),thinkingLevel:settings.thinkingLevel,model:settings.model},settings}}function buildSessionProjection(entries,leafId,byId){return projectSession(entries,leafId,byId).projection}function buildSessionContext(entries,leafId,byId){let{projection,settings}=projectSession(entries,leafId,byId),{thinkingLevel,thinkingSelection,model,configurationUpdate}=settings;return{messages:projection.messages,thinkingLevel,thinkingSelection,model,configurationUpdate}}function getDefaultSessionDirPath(cwd,agentDir=getAgentDir()){let resolvedCwd=resolvePath(cwd),resolvedAgentDir=resolvePath(agentDir),safePath=`--${resolvedCwd.replace(/^[/\\]/,"").replace(/[/\\:]/g,"-")}--`;return join5(resolvedAgentDir,"sessions",safePath)}function getDefaultSessionDir(cwd,agentDir=getAgentDir()){let sessionDir=getDefaultSessionDirPath(cwd,agentDir);return existsSync3(sessionDir)||mkdirSync2(sessionDir,{recursive:!0}),sessionDir}var SESSION_READ_BUFFER_SIZE=1024*1024,SESSION_HEADER_READ_BUFFER_SIZE=4096,MAX_SESSION_HEADER_SCAN_BYTES=1024*1024,SessionHeaderScanLimitError=class extends Error{constructor(filePath){super(`Session header exceeds ${MAX_SESSION_HEADER_SCAN_BYTES}-byte scan limit: ${filePath}`),this.name="SessionHeaderScanLimitError"}};function parseSessionEntryLine(line){if(!line.trim())return null;try{return JSON.parse(line)}catch{return null}}function loadEntriesFromFile(filePath){let resolvedFilePath=normalizePath(filePath);if(!existsSync3(resolvedFilePath))return[];let entries=[],pending="",fd=openSync3(resolvedFilePath,"r");try{let decoder=new StringDecoder2("utf8"),buffer=Buffer.allocUnsafe(SESSION_READ_BUFFER_SIZE);for(;;){let bytesRead=readSync2(fd,buffer,0,buffer.length,null);if(bytesRead===0)break;pending+=decoder.write(buffer.subarray(0,bytesRead));let lineStart=0,newlineIndex=pending.indexOf(`
|
|
27
|
+
`;for(let entry of entries)await appendFile(path2,prefix+entry.line),prefix=""}async function rewriteIndexFile(path2,entries){let temp=`${path2}.tmp-${process.pid}-${Math.random().toString(36).slice(2)}`;try{await writeFile(temp,HEADER_LINE+entries.map(entry=>entry.line).join("")),await rename(temp,path2)}catch(error){throw await rm(temp,{force:!0}).catch(()=>{}),error}}var SESSION_SUMMARY_INDEX_MAX_BYTES=256*1024*1024,snapshots=new Map;function stampsMatch(left,right){return left.size===right.size&&left.mtimeMs===right.mtimeMs}async function statStamp(path2){try{let stats=await stat(path2);return{size:stats.size,mtimeMs:stats.mtimeMs}}catch(error){if(error instanceof Error)return;throw error}}function recency(entry){let headerTime=Date.parse(entry.summary.header.timestamp);return entry.summary.lastActivityTime??(Number.isNaN(headerTime)?0:headerTime)}function selectWithinBudget(entries,maxBytes){let kept=[],bytes=0;for(let entry of[...entries].sort((left,right)=>recency(right)-recency(left)))if(!(entry.lineBytes>maxBytes)){if(bytes+entry.lineBytes>maxBytes)break;kept.push(entry),bytes+=entry.lineBytes}return kept}var SessionSummaryIndex=class{constructor(dir,options={}){this.recorded=[],this.path=join(dir,SESSION_SUMMARY_INDEX_FILE),this.maxBytes=options.maxBytes??SESSION_SUMMARY_INDEX_MAX_BYTES}async lookup(filePath,stamp){let file=basename(filePath);if(!this.loading){this.snapshot??=this.currentSnapshot();let known=await this.snapshot,indexed=known?.entryStamps.get(file);if(known&&!(indexed&&stampsMatch(indexed,stamp)))return}this.loading??=this.load();let entry=(await this.loading).entries.get(file);return entry&&stampsMatch(entry.stamp,stamp)?entry.summary:void 0}record(filePath,stamp,summary){this.recorded.push({file:basename(filePath),stamp,summary})}async persist(presentFiles){if(!this.loading)return;let loaded=await this.loading,entries=new Map(loaded.entries),added=new Set;for(let{file,stamp,summary}of this.recorded){let existing=entries.get(file);if(existing&&stampsMatch(existing.stamp,stamp))continue;let entry=toIndexEntry(file,stamp,summary);entry&&(entries.set(file,entry),added.add(entry))}let present=new Set(presentFiles.map(path2=>basename(path2))),live=[...entries.values()].filter(entry=>present.has(entry.file)),kept=selectWithinBudget(live,this.maxBytes),keptBytes=kept.reduce((total,entry)=>total+entry.lineBytes,0),appended=kept.filter(entry=>added.has(entry)),appendedBytes=appended.reduce((total,entry)=>total+entry.lineBytes,0);try{if(!loaded.usable&&kept.length>0||loaded.usable&&loaded.entryBytes+appendedBytes>2*keptBytes)await rewriteIndexFile(this.path,kept),this.remember(await statStamp(this.path),kept);else if(loaded.usable&&appended.length>0){await appendIndexEntries(this.path,appended,loaded.endsWithNewline);let inFile=new Map(loaded.entries);for(let entry of appended)inFile.set(entry.file,entry);this.remember(await statStamp(this.path),inFile.values())}}catch(error){if(!(error instanceof Error))throw error;snapshots.delete(this.path)}}async currentSnapshot(){let recorded=snapshots.get(this.path);if(!recorded)return;let current=await statStamp(this.path);return current&&stampsMatch(current,recorded.indexStamp)?recorded:void 0}async load(){let before=await statStamp(this.path),loaded=await loadIndexFile(this.path);return this.remember(before,loaded.usable?loaded.entries.values():void 0),loaded}remember(indexStamp,entries){if(!indexStamp||!entries){snapshots.delete(this.path);return}let entryStamps=new Map;for(let entry of entries)entryStamps.set(entry.file,entry.stamp);snapshots.set(this.path,{indexStamp,entryStamps})}};var SessionSummaryLru=class{constructor(budget){this.entries=new Map,this.retainedTextBytes=0,this.budget=budget}get size(){return this.entries.size}get textBytes(){return this.retainedTextBytes}get(key){let retained=this.entries.get(key);if(retained)return this.entries.delete(key),this.entries.set(key,retained),retained.entry}drop(key){let retained=this.entries.get(key);retained&&(this.entries.delete(key),this.retainedTextBytes-=retained.textBytes)}retain(key,entry){this.drop(key);let textBytes=Buffer.byteLength(entry.summary.allMessagesText,"utf8");textBytes>this.budget.maxTextBytes||(this.entries.set(key,{entry,textBytes}),this.retainedTextBytes+=textBytes,this.evictUntilWithinBudget())}clear(){this.entries.clear(),this.retainedTextBytes=0}evictUntilWithinBudget(){for(;this.entries.size>this.budget.maxEntries||this.retainedTextBytes>this.budget.maxTextBytes;){let oldest=this.entries.keys().next();if(oldest.done)break;this.drop(oldest.value)}}};var SESSION_SUMMARY_CACHE_LIMIT=4096,SESSION_SUMMARY_CACHE_MAX_TEXT_BYTES=64*1024*1024,cache=new SessionSummaryLru({maxEntries:SESSION_SUMMARY_CACHE_LIMIT,maxTextBytes:SESSION_SUMMARY_CACHE_MAX_TEXT_BYTES}),streamedSummaries=0;function stampsMatch2(left,right){return left.size===right.size&&left.mtimeMs===right.mtimeMs}async function readCachedSessionSummary(filePath,store2){let key=resolve(filePath),stamp,mtime;try{let stats=await stat2(filePath);stamp={size:stats.size,mtimeMs:stats.mtimeMs},mtime=stats.mtime}catch(error){if(!(error instanceof Error))throw error;return cache.drop(key),null}let cached=cache.get(key);if(cached&&stampsMatch2(cached.stamp,stamp))return store2?.record(filePath,stamp,cached.summary),{summary:cached.summary,mtime:cached.mtime};let stored=await store2?.lookup(filePath,stamp);if(stored)return cache.retain(key,{stamp,summary:stored,mtime}),{summary:stored,mtime};streamedSummaries++;let summary=await readSessionSummary(filePath);return summary?(cache.retain(key,{stamp,summary,mtime}),store2?.record(filePath,stamp,summary),{summary,mtime}):(cache.drop(key),null)}var MAX_CONCURRENT_SESSION_INFO_LOADS=10,CURRENT_SESSION_LIST_PUBLISH_INTERVAL=10,ALL_SESSION_LIST_PUBLISH_INTERVAL=100;function sortSessionInfos(sessions){return sessions.sort((a,b)=>b.modified.getTime()-a.modified.getTime())}function resolveModified(activityTime,header,mtime){if(typeof activityTime=="number"&&activityTime>0)return new Date(activityTime);let headerTime=typeof header.timestamp=="string"?Date.parse(header.timestamp):Number.NaN;return Number.isNaN(headerTime)?mtime:new Date(headerTime)}async function buildSessionInfo(filePath,store2){let cached=await readCachedSessionSummary(filePath,store2);if(!cached)return null;let{summary,mtime}=cached,header=summary.header;return{path:filePath,id:header.id,cwd:typeof header.cwd=="string"?header.cwd:"",name:summary.name,parentSessionPath:header.parentSession,created:new Date(header.timestamp),modified:resolveModified(summary.lastActivityTime,header,mtime),messageCount:summary.messageCount,firstMessage:summary.firstUserMessage||"(no messages)",allMessagesText:summary.allMessagesText,...summary.repositoryIdentity?{repositoryIdentity:summary.repositoryIdentity}:{}}}async function buildSessionInfosWithConcurrency(files,onLoaded,store2,signal){let results=new Array(files.length).fill(null),inFlight=new Set,nextIndex=0,startNext=()=>{let index=nextIndex++,file=files[index];if(!file)return;let task;task=buildSessionInfo(file,store2).then(info=>{results[index]=info}).catch(()=>{results[index]=null}).finally(()=>{inFlight.delete(task),onLoaded(results[index]??null)}),inFlight.add(task)};for(;nextIndex<files.length||inFlight.size>0;){for(;!signal?.aborted&&nextIndex<files.length&&inFlight.size<MAX_CONCURRENT_SESSION_INFO_LOADS;)startNext();if(inFlight.size===0)break;await Promise.race(inFlight)}return signal?.throwIfAborted(),results}async function listSessionInfos(files,onLoaded,store2,signal){let results=await buildSessionInfosWithConcurrency(files,onLoaded,store2,signal),sessions=[];for(let info of results)info&&sessions.push(info);return sessions}async function listSessionFilesInDir(dir,files,onLoaded,signal){let index=new SessionSummaryIndex(dir),sessions=await listSessionInfos(files,onLoaded,index,signal);return await index.persist(files),sessions}async function listSessionsFromDir(dir,onProgress,signal){if(signal?.throwIfAborted(),!existsSync(dir))return[];try{let files=(await readdir(dir)).filter(name=>name.endsWith(".jsonl")).map(name=>join2(dir,name)),loaded=0,partialSessions=[];return await listSessionFilesInDir(dir,files,info=>{loaded++,info&&partialSessions.push(info);let publish=loaded===1||loaded%CURRENT_SESSION_LIST_PUBLISH_INTERVAL===0||loaded===files.length;onProgress?.(loaded,files.length,publish?sortSessionInfos([...partialSessions]):void 0)},signal)}catch{return signal?.throwIfAborted(),[]}}function materializeSessionEntries(entries,options){let{residentStore,loadHistoryEntries,onMaterialized}=options,missingEntryIds=new Set,materialized=entries.map(entry=>residentStore.materialize(entry,()=>{missingEntryIds.add(entry.id)}));if(missingEntryIds.size===0){for(let entry of materialized)onMaterialized(entry);return materialized}let persistedById=new Map(loadHistoryEntries().filter(entry=>entry.type!=="session").map(entry=>[entry.id,entry])),repaired=materialized.map(entry=>{if(!missingEntryIds.has(entry.id))return entry;let persisted=persistedById.get(entry.id);return persisted===void 0?entry:residentStore.materialize(persisted)});for(let entry of repaired)onMaterialized(entry);return repaired}import{randomUUID}from"node:crypto";import{closeSync,fchmodSync,fsyncSync,openSync,realpathSync,renameSync,rmSync,statSync,writeFileSync}from"node:fs";import{basename as basename2,dirname,join as join3}from"node:path";var UNSUPPORTED_DIRECTORY_SYNC=new Set(["EINVAL","ENOTSUP","EOPNOTSUPP","EISDIR"]),DIRECTORY_NOT_WRITABLE=new Set(["EACCES","EPERM","EROFS"]);function errnoCode(error){return error instanceof Error&&"code"in error&&typeof error.code=="string"?error.code:void 0}function resolveTarget(filePath){try{let path2=realpathSync(filePath);return{path:path2,mode:statSync(path2).mode&4095}}catch(error){if(errnoCode(error)==="ENOENT")return{path:filePath,mode:void 0};throw error}}function openTemp(tempPath){try{return openSync(tempPath,"wx")}catch(error){let code=errnoCode(error);if(code!==void 0&&DIRECTORY_NOT_WRITABLE.has(code))return;throw error}}function rewriteInPlace(path2,chunks){let fd=openSync(path2,"w");try{for(let chunk of chunks)writeFileSync(fd,chunk)}finally{closeSync(fd)}}function writeDurably(fd,chunks,mode){try{mode!==void 0&&fchmodSync(fd,mode);for(let chunk of chunks)writeFileSync(fd,chunk);fsyncSync(fd)}finally{closeSync(fd)}}function syncDirectory(directory){if(process.platform==="win32")return;let fd=openSync(directory,"r");try{fsyncSync(fd)}catch(error){let code=errnoCode(error);if(code===void 0||!UNSUPPORTED_DIRECTORY_SYNC.has(code))throw error}finally{closeSync(fd)}}function replaceFileAtomically(filePath,chunks){let target=resolveTarget(filePath),tempPath=join3(dirname(target.path),`.${basename2(target.path)}.${randomUUID()}.tmp`),tempFd=openTemp(tempPath);if(tempFd===void 0){rewriteInPlace(target.path,chunks);return}try{writeDurably(tempFd,chunks,target.mode),renameSync(tempPath,target.path)}catch(error){try{rmSync(tempPath,{force:!0})}catch(cleanupError){throw new AggregateError([error,cleanupError],"session file rewrite failed and its temporary file could not be removed")}throw error}syncDirectory(dirname(target.path))}import{createHash}from"node:crypto";import{existsSync as existsSync2,mkdirSync,readFileSync,renameSync as renameSync2,rmSync as rmSync2,writeFileSync as writeFileSync2}from"node:fs";import{join as join4}from"node:path";import{Buffer as Buffer2}from"buffer";var ResidentSizeAccounting=class{constructor(){this.bytes=0,this.evictedCount=0,this.evictedBytes=0}get residentBytes(){return this.bytes}added(text){this.bytes+=Buffer2.byteLength(text,"utf8")}removed(text){this.bytes-=Buffer2.byteLength(text,"utf8")}evicted(text){this.evictedCount++,this.evictedBytes+=Buffer2.byteLength(text,"utf8")}reset(){this.bytes=0,this.evictedCount=0,this.evictedBytes=0}stats(){return{blobBytes:this.bytes,evictedCount:this.evictedCount,evictedBytes:this.evictedBytes}}};var RESIDENT_STRING_MIN_BYTES=32*1024,DEFAULT_RESIDENT_STRING_BUDGET_BYTES=64*1024*1024,RESIDENT_STRING_PREFIX="\0senpi-resident-string:v1:",ResidentStringStore=class{constructor(options={}){this.tokenFree=new WeakSet,this.strings=new Map,this.accounting=new ResidentSizeAccounting,this.maxBytes=options.maxBytes??DEFAULT_RESIDENT_STRING_BUDGET_BYTES,this.blobsDir=options.blobsDir}configure(options){this.blobsDir=options.blobsDir}clear(){this.strings.clear(),this.accounting.reset();let dir=this.blobsDir?.();if(dir)try{rmSync2(dir,{force:!0,recursive:!0})}catch{}}spillResident(){if(this.blobsDir?.())for(let[id,text]of this.strings)this._writeBlob(id,text)&&(this.strings.delete(id),this.accounting.removed(text))}stats(){return{blobCount:this.strings.size,...this.accounting.stats()}}size(){return{entries:this.strings.size,approxBytes:this.accounting.residentBytes}}externalize(value){let tokenized=!1,externalized=transformJson(value,text=>{let stored=this.externalizeString(text);return stored.startsWith(RESIDENT_STRING_PREFIX)&&(tokenized=!0),stored});return!tokenized&&typeof externalized=="object"&&externalized!==null&&this.tokenFree.add(externalized),externalized}materialize(value,onMissing){return typeof value=="object"&&value!==null&&this.tokenFree.has(value)?value:transformJson(value,text=>this.materializeString(text,onMissing))}isTokenFree(value){return this.tokenFree.has(value)}adoptTokenFree(value){this.tokenFree.add(value)}resolvedBlobsDir(){return this.blobsDir?.()}externalizeInPlace(value){this._mutateStringsInPlace(value,new Set,text=>this.externalizeString(text))}materializeInPlace(value){this._mutateStringsInPlace(value,new Set,text=>this.materializeString(text))}_mutateStringsInPlace(value,seen,mutate){if(typeof value!="object"||value===null||seen.has(value))return;seen.add(value);let record=value;for(let key of Object.keys(record)){let current=record[key];if(typeof current=="string"){let next=mutate(current);next!==current&&(record[key]=next)}else typeof current=="object"&¤t!==null&&this._mutateStringsInPlace(current,seen,mutate)}}externalizeString(text){if(text.length<RESIDENT_STRING_MIN_BYTES||text.startsWith(RESIDENT_STRING_PREFIX))return text;let id=createHash("sha256").update(text,"utf8").digest("hex"),token=`${RESIDENT_STRING_PREFIX}${id}`;return this.strings.has(id)?(this.strings.delete(id),this.strings.set(id,text),token):(this.strings.set(id,text),this.accounting.added(text),this._enforceBudget(),token)}materializeString(text,onMissing){if(!text.startsWith(RESIDENT_STRING_PREFIX))return text;let id=text.slice(RESIDENT_STRING_PREFIX.length),resident=this.strings.get(id);if(resident!==void 0)return this.strings.delete(id),this.strings.set(id,resident),resident;let hydrated=this._readBlob(id);return hydrated!==void 0?hydrated:onMissing?.(id)??text}_enforceBudget(){for(;this.accounting.residentBytes>this.maxBytes&&this.strings.size>0;){let[oldestId,oldest]=this.strings.entries().next().value;if(!this._writeBlob(oldestId,oldest))return;this.strings.delete(oldestId),this.accounting.removed(oldest)}}_writeBlob(id,text){let dir=this.blobsDir?.();if(!dir)return!1;let final=join4(dir,`${id}.blob`),temp=`${final}.tmp`;try{mkdirSync(dir,{recursive:!0}),existsSync2(final)||(writeFileSync2(temp,JSON.stringify({v:1,text}),"utf8"),renameSync2(temp,final))}catch{try{rmSync2(temp,{force:!0})}catch{}return!1}return this.accounting.evicted(text),!0}_readBlob(id){let dir=this.blobsDir?.();if(!dir)return;let file=join4(dir,`${id}.blob`);try{let parsed=JSON.parse(readFileSync(file,"utf8"));if(typeof parsed.text=="string")return parsed.text}catch{}try{rmSync2(file,{force:!0})}catch{}}};import{closeSync as closeSync2,fstatSync,ftruncateSync,openSync as openSync2,readSync,rmSync as rmSync3}from"node:fs";import{rm as rm2}from"node:fs/promises";var NEWLINE=10,SCAN_CHUNK_BYTES=64*1024;function truncateToLastCompleteLine(path2){let fd=openSync2(path2,"r+");try{let size=fstatSync(fd).size,chunk=Buffer.alloc(Math.min(SCAN_CHUNK_BYTES,size)),end=size;for(;end>0;){let start=Math.max(0,end-chunk.length),read=readSync(fd,chunk,0,end-start,start),newline=chunk.subarray(0,read).lastIndexOf(NEWLINE);if(newline>=0){let completeLength=start+newline+1;completeLength<size&&ftruncateSync(fd,completeLength);return}end=start}}finally{closeSync2(fd)}}function discardFailedFirstFlush(path2,fd,writeError){let cleanupErrors=[];try{closeSync2(fd)}catch(closeError){cleanupErrors.push(closeError)}try{rmSync3(path2,{force:!0})}catch(removeError){cleanupErrors.push(removeError)}throwWriteError(path2,writeError,cleanupErrors)}async function discardFailedFirstFlushAsync(path2,handle,writeError){let cleanupErrors=[];if(handle!==void 0)try{await handle.close()}catch(closeError){cleanupErrors.push(closeError)}try{await rm2(path2,{force:!0})}catch(removeError){cleanupErrors.push(removeError)}throwWriteError(path2,writeError,cleanupErrors)}function throwWriteError(path2,writeError,cleanupErrors){throw cleanupErrors.length>0?new AggregateError([writeError,...cleanupErrors],`Session file write failed and the partial file ${path2} could not be cleaned up`):writeError}var reserve;function reserveSessionWrite(path2){reserve?.(path2)}var liveWriters=new Set,writerRefs=new WeakMap;function registerSessionWriter(owner){if(writerRefs.has(owner))return;let ref=new WeakRef(owner);writerRefs.set(owner,ref),liveWriters.add(ref)}function unregisterSessionWriter(owner){let ref=writerRefs.get(owner);ref&&(writerRefs.delete(owner),liveWriters.delete(ref))}function hasOtherLiveSessionWriter(path2,self){for(let ref of liveWriters){let owner=ref.deref();if(!owner){liveWriters.delete(ref);continue}if(owner!==self&&owner.isPersisted()&&owner.getSessionFile()===path2)return!0}return!1}function uuidv7(){let ts=BigInt(Date.now()),bytes=randomBytes(10),hex=[(ts>>40n&0xffn).toString(16).padStart(2,"0"),(ts>>32n&0xffn).toString(16).padStart(2,"0"),(ts>>24n&0xffn).toString(16).padStart(2,"0"),(ts>>16n&0xffn).toString(16).padStart(2,"0"),(ts>>8n&0xffn).toString(16).padStart(2,"0"),(ts&0xffn).toString(16).padStart(2,"0"),(112|bytes[0]&15).toString(16).padStart(2,"0"),bytes[1].toString(16).padStart(2,"0"),(128|bytes[2]&63).toString(16).padStart(2,"0"),bytes[3].toString(16).padStart(2,"0"),...Array.from(bytes.slice(4),b=>b.toString(16).padStart(2,"0"))].join("");return`${hex.slice(0,8)}-${hex.slice(8,12)}-${hex.slice(12,16)}-${hex.slice(16,20)}-${hex.slice(20,32)}`}function isPlainJson(value,depth=0){if(depth>64)return!1;if(value===null||typeof value=="string"||typeof value=="boolean")return!0;if(typeof value=="number")return Number.isFinite(value);if(Array.isArray(value)){for(let index=0;index<value.length;index++){let item=value[index];if(item===void 0||!isPlainJson(item,depth+1))return!1}return!0}if(typeof value!="object")return!1;let prototype=Object.getPrototypeOf(value);if(prototype!==Object.prototype&&prototype!==null)return!1;for(let item of Object.values(value))if(item!==void 0&&!isPlainJson(item,depth+1))return!1;return!0}var contextMessageEntryIds=new WeakMap,SESSION_CONTEXT_ENTRY_ID="__piSessionContextEntryId";function withContextEntryId(entryId,message){return contextMessageEntryIds.set(message,entryId),message}function getSessionContextEntryId(message){return contextMessageEntryIds.get(message)}function inheritSessionContextEntryId(derived,source){let fromProperty=Object.getOwnPropertyDescriptor(source,SESSION_CONTEXT_ENTRY_ID)?.value,entryId=getSessionContextEntryId(source)??(typeof fromProperty=="string"?fromProperty:void 0);return entryId===void 0||(contextMessageEntryIds.set(derived,entryId),Object.assign(derived,{[SESSION_CONTEXT_ENTRY_ID]:entryId})),derived}var CURRENT_SESSION_VERSION=3;function createSessionId(){return uuidv7()}function assertValidSessionId(id){if(!/^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/.test(id))throw new Error("Session id must be non-empty, contain only alphanumeric characters, '-', '_', and '.', and start and end with an alphanumeric character")}function generateId(byId){for(let i=0;i<100;i++){let id=randomUUID2().slice(0,8);if(!byId.has(id))return id}return randomUUID2()}function migrateV1ToV2(entries){let ids=new Set,prevId=null;for(let entry of entries){if(entry.type==="session"){entry.version=2;continue}if(entry.id=generateId(ids),entry.parentId=prevId,prevId=entry.id,entry.type==="compaction"){let comp=entry;if(typeof comp.firstKeptEntryIndex=="number"){let targetEntry=entries[comp.firstKeptEntryIndex];targetEntry&&targetEntry.type!=="session"&&(comp.firstKeptEntryId=targetEntry.id),delete comp.firstKeptEntryIndex}}}}function migrateV2ToV3(entries){for(let entry of entries){if(entry.type==="session"){entry.version=3;continue}if(entry.type==="message"){let msgEntry=entry;msgEntry.message&&msgEntry.message.role==="hookMessage"&&(msgEntry.message.role="custom")}}}function migrateToCurrentVersion(entries){let version=entries.find(e=>e.type==="session")?.version??1;return version>=CURRENT_SESSION_VERSION?!1:(version<2&&migrateV1ToV2(entries),version<3&&migrateV2ToV3(entries),!0)}function migrateSessionEntries(entries){migrateToCurrentVersion(entries)}function parseSessionEntries(content){let entries=[],lines=content.trim().split(`
|
|
28
|
+
`);for(let line of lines)if(line.trim())try{let entry=JSON.parse(line);entries.push(entry)}catch{}return entries}function getLatestCompactionEntry(entries){for(let i=entries.length-1;i>=0;i--)if(entries[i].type==="compaction")return entries[i];return null}function buildEntryIndex(entries,byId){if(byId)return byId;let index=new Map;for(let entry of entries)index.set(entry.id,entry);return index}function buildSessionPath(entries,leafId,byId){let index=buildEntryIndex(entries,byId),leaf;if(leafId===null)return[];if(leafId&&(leaf=index.get(leafId)),leaf??=entries[entries.length-1],!leaf)return[];let path2=[],visited=new Set,current=leaf;for(;current&&!visited.has(current);)visited.add(current),path2.push(current),current=current.parentId?index.get(current.parentId):void 0;return path2.reverse(),path2}function getSessionContextSettings(path2){let thinkingLevel="off",thinkingSelection,configurationUpdate,model=null,isModelSelectionExplicit=!1,isInFallbackWindow=!1,preFallbackThinkingLevel=thinkingLevel,preFallbackThinkingSelection=thinkingSelection;for(let entry of path2)if(entry.type==="thinking_level_change")thinkingLevel=entry.thinkingLevel,thinkingSelection=entry.thinkingSelection;else if(entry.type==="configuration_update")configurationUpdate={effort:entry.reasoning.effort};else if(entry.type==="model_change")entry.reason==="fallback"?(isInFallbackWindow||(preFallbackThinkingLevel=thinkingLevel,preFallbackThinkingSelection=thinkingSelection,entry.originalProvider&&entry.originalModelId&&(model={provider:normalizeProviderId(entry.originalProvider),modelId:entry.originalModelId},isModelSelectionExplicit=!0)),isInFallbackWindow=!0):entry.reason==="fallback-revert"?(isInFallbackWindow&&(thinkingLevel=preFallbackThinkingLevel,thinkingSelection=preFallbackThinkingSelection),isInFallbackWindow=!1):(isInFallbackWindow=!1,entry.provider&&entry.modelId&&(model={provider:normalizeProviderId(entry.provider),modelId:entry.modelId},isModelSelectionExplicit=!0));else if(entry.type==="message"&&entry.message.role==="assistant"&&!isInFallbackWindow&&!isVirtualModel(entry.message)){if(isModelSelectionExplicit&&model?.provider===normalizeProviderId(entry.message.provider))continue;model={provider:normalizeProviderId(entry.message.provider),modelId:entry.message.model},isModelSelectionExplicit=!1}return isInFallbackWindow&&(thinkingLevel=preFallbackThinkingLevel,thinkingSelection=preFallbackThinkingSelection),{thinkingLevel,thinkingSelection,configurationUpdate,model}}function sessionEntryToContextMessages(entry){if(entry.type==="message"){let message=entry.message;return message.role==="system"&&message.content==null?[{...message,content:""}]:(message.role==="user"||message.role==="assistant"||message.role==="toolResult")&&message.content==null?[withContextEntryId(entry.id,{...message,content:[]})]:[withContextEntryId(entry.id,message)]}if(entry.type==="configuration_update")return[withContextEntryId(entry.id,{role:"configurationUpdate",content:[],effort:entry.reasoning.effort,timestamp:new Date(entry.timestamp).getTime()})];if(entry.type==="custom_message")return[withContextEntryId(entry.id,createCustomMessage(entry.customType,entry.content??[],entry.display,entry.details,entry.timestamp))];if(entry.type==="branch_summary"&&entry.summary)return[withContextEntryId(entry.id,createBranchSummaryMessage(entry.summary,entry.fromId,entry.timestamp))];if(entry.type==="compaction"){let summary=withContextEntryId(entry.id,createCompactionSummaryMessage(entry.summary,entry.tokensBefore,entry.timestamp,entry.details));return entry.systemMessage?[withContextEntryId(entry.id,entry.systemMessage),summary]:[summary]}return[]}function buildContextEntries(entries,leafId,byId){return contextEntriesOfPath(buildSessionPath(entries,leafId,byId))}function contextEntriesOfPath(path2){let compaction=null;for(let entry of path2)entry.type==="compaction"&&(compaction=entry);if(!compaction)return path2;let compactionIdx=path2.findIndex(entry=>entry.id===compaction.id);if(compactionIdx<0)return path2;let contextEntries=[compaction],foundFirstKept=!1;for(let i=0;i<compactionIdx;i++){let entry=path2[i];entry.type!=="compaction"&&(entry.id===compaction.firstKeptEntryId&&(foundFirstKept=!0),foundFirstKept&&!(entry.type==="message"&&entry.message.role==="system")&&contextEntries.push(entry))}return contextEntries.push(...path2.slice(compactionIdx+1)),contextEntries}function projectContextEntry(entry,edit){let messages=sessionEntryToContextMessages(entry);if(!edit)return messages;let replacement=edit.replacement;return replacement===null?[]:messages.map(message=>{if(message.role!=="user"&&message.role!=="assistant"&&message.role!=="toolResult"&&message.role!=="custom")return message;let content=(message.role==="assistant"||message.role==="toolResult")&&typeof replacement.content=="string"?[{type:"text",text:replacement.content}]:replacement.content;return withContextEntryId(entry.id,{...message,content})})}function projectSession(entries,leafId,byId,knownPath){let path2=knownPath??buildSessionPath(entries,leafId,byId),settings=getSessionContextSettings(path2),contextEntries=contextEntriesOfPath(path2),edits=new Map;for(let entry of contextEntries)entry.type==="context_edit"&&edits.set(entry.targetId,entry);let projectedEntries=contextEntries.map((sourceEntry,index)=>({sourceEntry,messages:sourceEntry.type==="compaction"&&index>0?[]:projectContextEntry(sourceEntry,edits.get(sourceEntry.id))})),recoveryIndex=path2.findLastIndex(entry=>entry.type==="compaction"&&entry.details!==null&&typeof entry.details=="object"&&"retainedMessagePolicy"in entry.details&&entry.details.retainedMessagePolicy==="omit-unsafe-v1");if(recoveryIndex>=0){let retainedIds=new Set(path2.slice(0,recoveryIndex).map(entry=>entry.id)),retained=projectedEntries.filter(entry=>retainedIds.has(entry.sourceEntry.id)),repaired=projectRetainedMessages(retained.flatMap(entry=>entry.messages)),index=0;for(let entry of retained)entry.messages=entry.messages.map(()=>withContextEntryId(entry.sourceEntry.id,repaired[index++]))}return{projection:{entries:projectedEntries,messages:projectedEntries.flatMap(entry=>entry.messages),thinkingLevel:settings.thinkingLevel,model:settings.model},settings}}function buildSessionProjection(entries,leafId,byId){return projectSession(entries,leafId,byId).projection}function buildSessionContext(entries,leafId,byId){let{projection,settings}=projectSession(entries,leafId,byId),{thinkingLevel,thinkingSelection,model,configurationUpdate}=settings;return{messages:projection.messages,thinkingLevel,thinkingSelection,model,configurationUpdate}}function getDefaultSessionDirPath(cwd,agentDir=getAgentDir()){let resolvedCwd=resolvePath(cwd),resolvedAgentDir=resolvePath(agentDir),safePath=`--${resolvedCwd.replace(/^[/\\]/,"").replace(/[/\\:]/g,"-")}--`;return join5(resolvedAgentDir,"sessions",safePath)}function getDefaultSessionDir(cwd,agentDir=getAgentDir()){let sessionDir=getDefaultSessionDirPath(cwd,agentDir);return existsSync3(sessionDir)||mkdirSync2(sessionDir,{recursive:!0}),sessionDir}var SESSION_READ_BUFFER_SIZE=1024*1024,SESSION_HEADER_READ_BUFFER_SIZE=4096,MAX_SESSION_HEADER_SCAN_BYTES=1024*1024,SessionHeaderScanLimitError=class extends Error{constructor(filePath){super(`Session header exceeds ${MAX_SESSION_HEADER_SCAN_BYTES}-byte scan limit: ${filePath}`),this.name="SessionHeaderScanLimitError"}};function parseSessionEntryLine(line){if(!line.trim())return null;try{return JSON.parse(line)}catch{return null}}function loadEntriesFromFile(filePath){let resolvedFilePath=normalizePath(filePath);if(!existsSync3(resolvedFilePath))return[];let entries=[],pending="",fd=openSync3(resolvedFilePath,"r");try{let decoder=new StringDecoder2("utf8"),buffer=Buffer.allocUnsafe(SESSION_READ_BUFFER_SIZE);for(;;){let bytesRead=readSync2(fd,buffer,0,buffer.length,null);if(bytesRead===0)break;pending+=decoder.write(buffer.subarray(0,bytesRead));let lineStart=0,newlineIndex=pending.indexOf(`
|
|
27
29
|
`,lineStart);for(;newlineIndex!==-1;){let entry=parseSessionEntryLine(pending.slice(lineStart,newlineIndex));entry&&entries.push(entry),lineStart=newlineIndex+1,newlineIndex=pending.indexOf(`
|
|
28
30
|
`,lineStart)}pending=pending.slice(lineStart)}pending+=decoder.end();let finalEntry=parseSessionEntryLine(pending);finalEntry&&entries.push(finalEntry)}finally{closeSync3(fd)}if(entries.length===0)return entries;let header=entries[0];return header.type!=="session"||typeof header.id!="string"?[]:entries}function parseSessionHeaderCandidate(line){if(!line.trim())return;let entry=parseSessionEntryLine(line);if(entry)return entry.type!=="session"||typeof entry.id!="string"?null:entry}function readSessionHeader(filePath){let fd=openSync3(filePath,"r");try{let decoder=new StringDecoder2("utf8"),buffer=Buffer.allocUnsafe(SESSION_HEADER_READ_BUFFER_SIZE),lineChunks=[],scannedBytes=0;for(;scannedBytes<MAX_SESSION_HEADER_SCAN_BYTES;){let readLength=Math.min(buffer.length,MAX_SESSION_HEADER_SCAN_BYTES-scannedBytes),bytesRead=readSync2(fd,buffer,0,readLength,null);if(bytesRead===0)return lineChunks.push(decoder.end()),parseSessionHeaderCandidate(lineChunks.join(""))??null;scannedBytes+=bytesRead;let chunk=decoder.write(buffer.subarray(0,bytesRead)),lineStart=0,newlineIndex=chunk.indexOf(`
|
|
29
31
|
`,lineStart);for(;newlineIndex!==-1;){lineChunks.push(chunk.slice(lineStart,newlineIndex));let header=parseSessionHeaderCandidate(lineChunks.join(""));if(header!==void 0)return header;lineChunks.length=0,lineStart=newlineIndex+1,newlineIndex=chunk.indexOf(`
|
|
@@ -48,4 +50,4 @@ and bugs within Pi. You can observe what is shared using /privacy and make
|
|
|
48
50
|
changes anytime in settings.json.`),1,0)),this.addChild(new Spacer(1)),this.addOptionList(ANALYTICS_OPTIONS.map(option=>option.label),this.analyticsIndex)),this.addChild(new Spacer(1)),this.addChild(new Text(rawKeyHint("\u2191\u2193","navigate")+" "+keyHint("tui.select.confirm",this.step==="theme"?"continue":"finish")+" "+keyHint("tui.select.cancel","skip setup"),1,0)),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder)}addOptionList(labels,selectedIndex){for(let i=0;i<labels.length;i++){let isSelected=i===selectedIndex,prefix=isSelected?theme.fg("accent","\u2192 "):" ",label=isSelected?theme.fg("accent",labels[i]):theme.fg("text",labels[i]);this.addChild(new Text(`${prefix}${label}`,1,0))}}moveSelection(delta){if(this.step==="theme"){let next=Math.max(0,Math.min(THEME_OPTIONS.length-1,this.themeIndex+delta));next!==this.themeIndex&&(this.themeIndex=next,this.options.onThemePreview(THEME_OPTIONS[this.themeIndex].value))}else this.analyticsIndex=Math.max(0,Math.min(ANALYTICS_OPTIONS.length-1,this.analyticsIndex+delta));this.update()}handleInput(keyData){let kb=getKeybindings();kb.matches(keyData,"tui.select.up")||keyData==="k"?this.moveSelection(-1):kb.matches(keyData,"tui.select.down")||keyData==="j"?this.moveSelection(1):kb.matches(keyData,"tui.select.confirm")||keyData===`
|
|
49
51
|
`?this.step==="theme"?(this.step="analytics",this.update()):this.options.onSubmit({theme:THEME_OPTIONS[this.themeIndex].value,shareAnalytics:ANALYTICS_OPTIONS[this.analyticsIndex].value}):kb.matches(keyData,"tui.select.cancel")&&this.options.onCancel()}};var OFFICIAL_PACKAGE_NAME="@earendil-works/pi-coding-agent",OFFICIAL_APP_NAME="pi",OFFICIAL_CONFIG_DIR_NAME=".pi";function isOfficialDistribution({packageName,appName,configDirName}){return packageName===OFFICIAL_PACKAGE_NAME&&appName===OFFICIAL_APP_NAME&&configDirName===OFFICIAL_CONFIG_DIR_NAME}function loadThemes(resources){let themes=[],seen=new Set;for(let resource of resources)if(resource.enabled)try{let loadedTheme=loadThemeFromPath(resource.path);if(loadedTheme.name){if(seen.has(loadedTheme.name))continue;seen.add(loadedTheme.name)}themes.push(loadedTheme)}catch{}return themes}async function loadStartupThemes(settingsManager){let globalSettingsManager=SettingsManager.inMemory(settingsManager.getGlobalSettings(),{projectTrusted:!1}),resolvedPaths=await new DefaultPackageManager({cwd:process.cwd(),agentDir:getAgentDir(),settingsManager:globalSettingsManager}).resolve(async()=>"skip");return loadThemes(resolvedPaths.themes)}async function createStartupTui(settingsManager){setCapabilityOverrides(settingsManager.getTerminalCapabilityOverrides()),setRegisteredThemes(await loadStartupThemes(settingsManager)),markTerminalColorsPending(),initTheme(resolveThemeSetting(settingsManager.getThemeSetting(),getTerminalTheme())??SYSTEM_THEME_NAME),setKeybindings(KeybindingsManager.create());let ui=new TUI(new ProcessTerminal({onExternalStdoutWrite:appendHiddenTuiStdout}),settingsManager.getShowHardwareCursor());return ui.setClearOnShrink(settingsManager.getClearOnShrink()),ui}function startStartupTui(ui,settingsManager){ui.start();let themeSetting=settingsManager.getThemeSetting();queryStartupTerminalColors(ui,()=>{setTheme(resolveThemeSetting(themeSetting,getTerminalTheme())??SYSTEM_THEME_NAME)})}function queryStartupTerminalColors(ui,onColors){requestTerminalColors(ui,colors=>{setTerminalColors(colors),onColors(),ui.invalidate(),ui.requestRender()})}async function clearStartupTui(ui){ui.clear(),ui.requestRender(),await new Promise(resolve5=>setTimeout(resolve5,25))}function shouldRunFirstTimeSetup(settingsPath=getSettingsPath()){return!isOfficialDistribution({packageName:PACKAGE_NAME,appName:APP_NAME,configDirName:CONFIG_DIR_NAME})||!areExperimentalFeaturesEnabled()||process.env[ENV_AGENT_DIR]?!1:!existsSync6(settingsPath)}async function showStartupSelector(settingsManager,title,options){let ui=await createStartupTui(settingsManager);return new Promise(resolve5=>{let settled=!1,finish=async result=>{settled||(settled=!0,await clearStartupTui(ui),ui.stop(),resolve5(result))},selector=new ExtensionSelectorComponent(title,options.map(option=>option.label),option=>{finish(options.find(entry=>entry.label===option)?.value)},()=>{finish(void 0)},{tui:ui});ui.addChild(selector),ui.setFocus(selector),startStartupTui(ui,settingsManager)})}async function showFirstTimeSetup(settingsManager){let ui=await createStartupTui(settingsManager);return new Promise(resolve5=>{let settled=!1,finish=async result=>{settled||(settled=!0,result&&(settingsManager.setTheme(result.theme),settingsManager.setEnableAnalytics(result.shareAnalytics),await settingsManager.flush()),await clearStartupTui(ui),ui.stop(),resolve5())};ui.start();let previewTheme=SYSTEM_THEME_NAME;setTheme(previewTheme);let component=new FirstTimeSetupComponent({onThemePreview:themeName=>{previewTheme=themeName,setTheme(themeName),ui.requestRender()},onSubmit:result=>{finish(result)},onCancel:()=>{finish(void 0)}});ui.addChild(component),ui.setFocus(component),ui.requestRender(),queryStartupTerminalColors(ui,()=>setTheme(previewTheme))})}async function showStartupInput(settingsManager,title,placeholder){let ui=await createStartupTui(settingsManager);return new Promise(resolve5=>{let settled=!1,finish=async result=>{settled||(settled=!0,input.dispose(),await clearStartupTui(ui),ui.stop(),resolve5(result))},input=new ExtensionInputComponent(title,placeholder,value=>{finish(value)},()=>{finish(void 0)},{tui:ui});ui.addChild(input),ui.setFocus(input),startStartupTui(ui,settingsManager)})}import{spawnSync}from"node:child_process";import{existsSync as existsSync8}from"node:fs";import{unlink}from"node:fs/promises";import*as os from"node:os";import{createHash as createHash3,randomBytes as randomBytes2}from"node:crypto";import{chmodSync as chmodSync2,existsSync as existsSync7,lstatSync,mkdirSync as mkdirSync5,readdirSync as readdirSync4,renameSync as renameSync4,rmSync as rmSync6,statSync as statSync5,writeFileSync as writeFileSync6}from"node:fs";import{open as open3}from"node:fs/promises";import{dirname as dirname4,join as join9,resolve as resolve4}from"node:path";var MEDIA_BEARING_RECORD_TYPES=new Set(["tool_execution_end","message_start","message_end","turn_end","agent_end","entry_appended"]),MEDIA_BEARING_RESPONSE_COMMANDS=new Set(["get_messages","get_entries","get_tree","get_state","open_session"]);function base64ByteLength(data){let padding=data.endsWith("==")?2:data.endsWith("=")?1:0;return Math.max(0,Math.floor(data.length*3/4)-padding)}function isPlainObject(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function isInlineImage(value){return isPlainObject(value)&&value.type==="image"&&typeof value.data=="string"}function omitContentImages(content,toolCallId,persist){let replaced;for(let index=0;index<content.length;index++){let block=content[index];if(!isInlineImage(block))continue;replaced??=[...content];let ref={toolCallId,contentIndex:index};replaced[index]={type:"image_ref",mimeType:typeof block.mimeType=="string"?block.mimeType:"application/octet-stream",byteLength:base64ByteLength(block.data),ref,...persist?.(ref,block)}}return replaced??content}function omitToolResultImages(message,persist){let content=message.content,toolCallId=typeof message.toolCallId=="string"?message.toolCallId:"";if(!Array.isArray(content))return message;let omitted=omitContentImages(content,toolCallId,persist);return omitted===content?message:{...message,content:omitted}}function walk(value,persist){if(Array.isArray(value)){let replaced2;for(let index=0;index<value.length;index++){let next=walk(value[index],persist);next!==value[index]&&(replaced2??=[...value],replaced2[index]=next)}return replaced2??value}if(!isPlainObject(value))return value;let scrubbed=value.role==="toolResult"?omitToolResultImages(value,persist):value,replaced=scrubbed===value?void 0:{...scrubbed};for(let[key,child]of Object.entries(scrubbed)){if(key==="content"&&scrubbed!==value||!isPlainObject(child)&&!Array.isArray(child))continue;let next=walk(child,persist);next!==child&&(replaced??={...scrubbed},replaced[key]=next)}return replaced??value}function omitToolExecutionEndImages(record,persist){let result=record.result;if(!isPlainObject(result)||!Array.isArray(result.content))return record;let toolCallId=typeof record.toolCallId=="string"?record.toolCallId:"",omitted=omitContentImages(result.content,toolCallId,persist);return omitted===result.content?record:{...record,result:{...result,content:omitted}}}function carriesMedia(record){return typeof record.type!="string"?!1:MEDIA_BEARING_RECORD_TYPES.has(record.type)?!0:record.type==="response"&&typeof record.command=="string"?MEDIA_BEARING_RESPONSE_COMMANDS.has(record.command):!1}function omitInlineMedia(record,persist){let typed=record;if(!carriesMedia(typed))return record;let scrubbed=typed.type==="tool_execution_end"?omitToolExecutionEndImages(typed,persist):typed,walked=walk(scrubbed,persist);return walked===typed?record:walked}var MAX_TOOL_IMAGE_BYTES=20*1024*1024,MAX_SESSION_MEDIA_BYTES=256*1024*1024,DEFAULT_LIMITS={perImage:MAX_TOOL_IMAGE_BYTES,perSession:MAX_SESSION_MEDIA_BYTES},MEDIA_DIRECTORY="media",EXTENSIONS={"image/png":"png","image/jpeg":"jpg","image/gif":"gif","image/webp":"webp"},reserved=new Map,SIGNATURES={"image/png":bytes=>bytes.subarray(0,8).equals(Buffer.from([137,80,78,71,13,10,26,10])),"image/jpeg":bytes=>bytes.subarray(0,3).equals(Buffer.from([255,216,255])),"image/gif":bytes=>bytes.subarray(0,4).toString("latin1")==="GIF8","image/webp":bytes=>bytes.subarray(0,4).toString("latin1")==="RIFF"&&bytes.subarray(8,12).toString("latin1")==="WEBP"};function assertRealDirectoryChain(root,callDirectory){for(let path2 of[dirname4(root),root,callDirectory]){let stat3;try{stat3=lstatSync(path2)}catch{continue}if(!stat3.isDirectory())throw new Error(`not a real directory: ${path2}`)}}var outcomes=new WeakMap;function liveToolMediaScope(entry){let manager=entry.runtime?.session.sessionManager,sessionFile=manager?.getSessionFile()??entry.worker?.snapshot?.state.sessionFile,durableSessionId=manager?.getSessionId()??entry.worker?.snapshot?.state.sessionId;return sessionFile===void 0||durableSessionId===void 0?void 0:{sessionDir:dirname4(sessionFile),durableSessionId}}function toolMediaRoot(scope){return assertValidSessionId(scope.durableSessionId),join9(scope.sessionDir,MEDIA_DIRECTORY,scope.durableSessionId)}function directoryBytes(directory){let total=0;for(let entry of readdirSync4(directory,{withFileTypes:!0})){let path2=join9(directory,entry.name);total+=entry.isDirectory()?directoryBytes(path2):statSync5(path2).size}return total}function storedBytes(root){let known=reserved.get(root);if(known!==void 0)return known;let scanned=existsSync7(root)?directoryBytes(root):0;return reserved.set(root,scanned),scanned}var unavailable=reason=>({unavailableReason:reason});function writeImage(root,path2,bytes){let callDirectory=dirname4(path2);mkdirSync5(callDirectory,{recursive:!0,mode:448}),assertRealDirectoryChain(root,callDirectory);let staging=`${path2}.${randomBytes2(6).toString("hex")}.tmp`;try{writeFileSync6(staging,bytes,{mode:384,flag:"wx"}),renameSync4(staging,path2),chmodSync2(path2,256)}catch(cause){throw rmSync6(staging,{force:!0}),cause}}function persistToolImage(scope,ref,block,limits=DEFAULT_LIMITS){let known=outcomes.get(block);if(known!==void 0)return known;let outcome=store(scope,ref,block,limits);return(!("unavailableReason"in outcome)||outcome.unavailableReason!=="storage_error")&&outcomes.set(block,outcome),outcome}function store(scope,ref,block,limits){let extension=EXTENSIONS[(block.mimeType??"").toLowerCase()];if(extension===void 0)return unavailable("storage_error");if(base64ByteLength(block.data)>limits.perImage)return unavailable("image_too_large");let bytes=Buffer.from(block.data,"base64");if(bytes.length>limits.perImage)return unavailable("image_too_large");if(SIGNATURES[(block.mimeType??"").toLowerCase()]?.(bytes)!==!0)return unavailable("storage_error");try{let root=toolMediaRoot(scope),callDirectory=createHash3("sha256").update(ref.toolCallId).digest("hex"),digest=createHash3("sha256").update(bytes).digest("hex"),path2=resolve4(root,callDirectory,`${ref.contentIndex}-${digest}.${extension}`);if(assertRealDirectoryChain(root,dirname4(path2)),existsSync7(path2))return{path:path2};let used=storedBytes(root);if(used+bytes.length>limits.perSession)return unavailable("session_limit");reserved.set(root,used+bytes.length);try{writeImage(root,path2,bytes)}catch(cause){throw reserved.set(root,storedBytes(root)-bytes.length),cause}return{path:path2}}catch{return unavailable("storage_error")}}function toolMediaPersister(scope){return(ref,block)=>{let current=scope();return current===void 0?void 0:persistToolImage(current,ref,block)}}function removeToolMedia(scope){let root=toolMediaRoot(scope);reserved.delete(root),makeTreeWritable(root),rmSync6(root,{recursive:!0,force:!0})}function makeTreeWritable(path2){let entries;try{if(!lstatSync(path2).isDirectory())return;chmodSync2(path2,448),entries=readdirSync4(path2,{withFileTypes:!0})}catch{return}for(let entry of entries){let child=join9(path2,entry.name);if(entry.isDirectory())makeTreeWritable(child);else if(entry.isFile())try{chmodSync2(child,384)}catch{}}}async function toolMediaScopeOfSessionFile(sessionFile){try{let handle=await open3(sessionFile,"r");try{let{buffer,bytesRead}=await handle.read(Buffer.alloc(4096),0,4096,0),firstLine=buffer.subarray(0,bytesRead).toString("utf8").split(`
|
|
50
52
|
`,1)[0]??"",id=JSON.parse(firstLine).id;return typeof id=="string"?{sessionDir:dirname4(sessionFile),durableSessionId:id}:void 0}finally{await handle.close()}}catch{return}}function normalizeWhitespaceLower(text){return text.toLowerCase().replace(/\s+/g," ").trim()}var searchTextCache=new WeakMap;function getSessionSearchText(session){let cached=searchTextCache.get(session);if(cached)return cached;let text=`${session.id} ${session.name??""} ${session.allMessagesText} ${session.cwd}`,entry={text,lower:text.toLowerCase()};return searchTextCache.set(session,entry),entry}function prepareTokens(parsed){return parsed.tokens.map(token=>token.kind==="phrase"?{kind:"phrase",normalized:normalizeWhitespaceLower(token.value)}:{kind:"fuzzy",lower:token.value.toLowerCase()})}function hasSessionName(session){return!!session.name?.trim()}function matchesNameFilter(session,filter2){return filter2==="all"?!0:hasSessionName(session)}function parseSearchQuery(query){let trimmed=query.trim();if(!trimmed)return{mode:"tokens",tokens:[],regex:null};if(trimmed.startsWith("re:")){let pattern=trimmed.slice(3).trim();if(!pattern)return{mode:"regex",tokens:[],regex:null,error:"Empty regex"};try{return{mode:"regex",tokens:[],regex:new RegExp(pattern,"i")}}catch(err){let msg=err instanceof Error?err.message:String(err);return{mode:"regex",tokens:[],regex:null,error:msg}}}let tokens=[],buf="",inQuote=!1,hadUnclosedQuote=!1,flush=kind=>{let v=buf.trim();buf="",v&&tokens.push({kind,value:v})};for(let i=0;i<trimmed.length;i++){let ch=trimmed[i];if(ch==='"'){inQuote?(flush("phrase"),inQuote=!1):(flush("fuzzy"),inQuote=!0);continue}if(!inQuote&&/\s/.test(ch)){flush("fuzzy");continue}buf+=ch}return inQuote&&(hadUnclosedQuote=!0),hadUnclosedQuote?{mode:"tokens",tokens:trimmed.split(/\s+/).map(t=>t.trim()).filter(t=>t.length>0).map(t=>({kind:"fuzzy",value:t})),regex:null}:(flush(inQuote?"phrase":"fuzzy"),{mode:"tokens",tokens,regex:null})}function matchPrepared(session,parsed,tokens){let searchText=getSessionSearchText(session);if(parsed.mode==="regex"){if(!parsed.regex)return{matches:!1,score:0};let idx=searchText.text.search(parsed.regex);return idx<0?{matches:!1,score:0}:{matches:!0,score:idx*.1}}if(tokens.length===0)return{matches:!0,score:0};let totalScore=0;for(let token of tokens){if(token.kind==="phrase"){if(searchText.normalized??=normalizeWhitespaceLower(searchText.text),!token.normalized)continue;let idx=searchText.normalized.indexOf(token.normalized);if(idx<0)return{matches:!1,score:0};totalScore+=idx*.1;continue}let m=fuzzyMatchLower(token.lower,searchText.lower);if(!m.matches)return{matches:!1,score:0};totalScore+=m.score}return{matches:!0,score:totalScore}}function filterAndSortSessions(sessions,query,sortMode,nameFilter="all"){let nameFiltered=nameFilter==="all"?sessions:sessions.filter(session=>matchesNameFilter(session,nameFilter));if(!query.trim())return nameFiltered;let parsed=parseSearchQuery(query);if(parsed.error)return[];let tokens=prepareTokens(parsed);if(sortMode==="recent"){let filtered=[];for(let s of nameFiltered)matchPrepared(s,parsed,tokens).matches&&filtered.push(s);return filtered}let scored=[];for(let s of nameFiltered){let res=matchPrepared(s,parsed,tokens);res.matches&&scored.push({session:s,score:res.score})}return scored.sort((a,b)=>a.score!==b.score?a.score-b.score:b.session.modified.getTime()-a.session.modified.getTime()),scored.map(r=>r.session)}function createCanonicalPathResolver(){let cache2=new Map;return path2=>{if(!path2)return path2;let canonical=cache2.get(path2);return canonical===void 0&&(canonical=canonicalizePath(path2),cache2.set(path2,canonical)),canonical}}function buildSessionTree(sessions,canonicalize){let byPath=new Map;for(let session of sessions){let sessionPath=canonicalize(session.path)??session.path;byPath.set(sessionPath,{session,children:[],latestActivity:session.modified.getTime()})}let roots=[];for(let session of sessions){let sessionPath=canonicalize(session.path)??session.path,node=byPath.get(sessionPath),parentPath=canonicalize(session.parentSessionPath);parentPath&&byPath.has(parentPath)?byPath.get(parentPath).children.push(node):roots.push(node)}let updateLatestActivity=node=>{let latestActivity=node.session.modified.getTime();for(let child of node.children)latestActivity=Math.max(latestActivity,updateLatestActivity(child));return node.latestActivity=latestActivity,latestActivity};for(let root of roots)updateLatestActivity(root);let sortNodes=nodes=>{nodes.sort((a,b)=>b.latestActivity-a.latestActivity);for(let node of nodes)sortNodes(node.children)};return sortNodes(roots),roots}function flattenSessionTree(roots){let result=[],walk2=(node,depth,ancestorContinues,isLast)=>{result.push({session:node.session,depth,isLast,ancestorContinues});for(let i=0;i<node.children.length;i++){let childIsLast=i===node.children.length-1,continues=depth>0?!isLast:!1;walk2(node.children[i],depth+1,[...ancestorContinues,continues],childIsLast)}};for(let i=0;i<roots.length;i++)walk2(roots[i],0,[],i===roots.length-1);return result}function shortenPath(path2){let home=os.homedir();return path2&&(path2.startsWith(home)?`~${path2.slice(home.length)}`:path2)}function formatSessionDate(date){let diffMs=new Date().getTime()-date.getTime(),diffMins=Math.floor(diffMs/6e4),diffHours=Math.floor(diffMs/36e5),diffDays=Math.floor(diffMs/864e5);return diffMins<1?"now":diffMins<60?`${diffMins}m`:diffHours<24?`${diffHours}h`:diffDays<7?`${diffDays}d`:diffDays<30?`${Math.floor(diffDays/7)}w`:diffDays<365?`${Math.floor(diffDays/30)}mo`:`${Math.floor(diffDays/365)}y`}var SessionSelectorHeader=class{constructor(scope,sortMode,nameFilter,requestRender){this.loading=!1,this.loadProgress=null,this.showPath=!1,this.confirmingDeletePath=null,this.statusMessage=null,this.statusTimeout=null,this.showRenameHint=!1,this.scope=scope,this.sortMode=sortMode,this.nameFilter=nameFilter,this.requestRender=requestRender}setScope(scope){this.scope=scope}setSortMode(sortMode){this.sortMode=sortMode}setNameFilter(nameFilter){this.nameFilter=nameFilter}setLoading(loading){this.loading=loading,this.loadProgress=null}setProgress(loaded,total){this.loadProgress={loaded,total}}setShowPath(showPath){this.showPath=showPath}setShowRenameHint(show){this.showRenameHint=show}setConfirmingDeletePath(path2){this.confirmingDeletePath=path2}clearStatusTimeout(){this.statusTimeout&&(clearTimeout(this.statusTimeout),this.statusTimeout=null)}setStatusMessage(msg,autoHideMs){this.clearStatusTimeout(),this.statusMessage=msg,!(!msg||!autoHideMs)&&(this.statusTimeout=setTimeout(()=>{this.statusMessage=null,this.statusTimeout=null,this.requestRender()},autoHideMs))}invalidate(){}render(width){let title=this.scope==="current"?"Resume Session (Current Folder)":"Resume Session (All)",leftText=theme.bold(title),sortLabel=this.sortMode==="threaded"?"Threaded":this.sortMode==="recent"?"Recent":"Fuzzy",sortText=theme.fg("muted","Sort: ")+theme.fg("accent",sortLabel),nameLabel=this.nameFilter==="all"?"All":"Named",nameText=theme.fg("muted","Name: ")+theme.fg("accent",nameLabel),scopeText;if(this.loading){let progressText=this.loadProgress?`${this.loadProgress.loaded}/${this.loadProgress.total}`:"...";scopeText=`${theme.fg("muted","\u25CB Current Folder | ")}${theme.fg("accent",`Loading ${progressText}`)}`}else this.scope==="current"?scopeText=`${theme.fg("accent","\u25C9 Current Folder")}${theme.fg("muted"," | \u25CB All")}`:scopeText=`${theme.fg("muted","\u25CB Current Folder | ")}${theme.fg("accent","\u25C9 All")}`;let rightText=truncateToWidth(`${scopeText} ${nameText} ${sortText}`,width,""),availableLeft=Math.max(0,width-visibleWidth(rightText)-1),left=truncateToWidth(leftText,availableLeft,""),spacing=Math.max(0,width-visibleWidth(left)-visibleWidth(rightText)),hintLine1,hintLine2;if(this.confirmingDeletePath!==null){let confirmHint=`Delete session? ${keyHint("tui.select.confirm","confirm")} \xB7 ${keyHint("tui.select.cancel","cancel")}`;hintLine1=theme.fg("error",truncateToWidth(confirmHint,width,"\u2026")),hintLine2=""}else if(this.statusMessage){let color=this.statusMessage.type==="error"?"error":"accent";hintLine1=theme.fg(color,truncateToWidth(this.statusMessage.message,width,"\u2026")),hintLine2=""}else{let pathState=this.showPath?"(on)":"(off)",sep4=theme.fg("muted"," \xB7 "),hint1=keyHint("tui.input.tab","scope")+sep4+theme.fg("muted",'re:<pattern> regex \xB7 "phrase" exact'),hint2Parts=[keyHint("app.session.toggleSort","sort"),keyHint("app.session.toggleNamedFilter","named"),keyHint("app.session.delete","delete"),keyHint("app.session.togglePath",`path ${pathState}`)];this.showRenameHint&&hint2Parts.push(keyHint("app.session.rename","rename"));let hint2=hint2Parts.join(sep4);hintLine1=truncateToWidth(hint1,width,"\u2026"),hintLine2=truncateToWidth(hint2,width,"\u2026")}return[`${left}${" ".repeat(spacing)}${rightText}`,hintLine1,hintLine2]}},SessionList=class{getSelectedSessionPath(){return this.filteredSessions[this.selectedIndex]?.session.path}get focused(){return this._focused}set focused(value){this._focused=value,this.searchInput.focused=value}constructor(sessions,showCwd,sortMode,nameFilter,keybindings,currentSessionFilePath){this.allSessions=[],this.filteredSessions=[],this.selectedIndex=0,this.selectionTouched=!1,this.showCwd=!1,this.sortMode="threaded",this.nameFilter="all",this.showPath=!1,this.confirmingDeletePath=null,this.canonicalPath=createCanonicalPathResolver(),this.onExit=()=>{},this.maxVisible=10,this._focused=!1,this.allSessions=sessions,this.filteredSessions=[],this.searchInput=new Input,this.showCwd=showCwd,this.sortMode=sortMode,this.nameFilter=nameFilter,this.keybindings=keybindings,this.currentSessionCanonicalPath=this.canonicalPath(currentSessionFilePath),this.filterSessions(""),this.searchInput.onSubmit=()=>{if(this.filteredSessions[this.selectedIndex]){let selected=this.filteredSessions[this.selectedIndex];this.onSelect&&this.onSelect(selected.session.path)}}}setSortMode(sortMode){this.sortMode=sortMode,this.filterSessions(this.searchInput.getValue())}setNameFilter(nameFilter){this.nameFilter=nameFilter,this.filterSessions(this.searchInput.getValue())}setSessions(sessions,showCwd){let selectedPath=this.selectionTouched?this.getSelectedSessionPath():void 0;if(this.allSessions=sessions,this.canonicalPath=createCanonicalPathResolver(),this.showCwd=showCwd,this.filterSessions(this.searchInput.getValue()),!this.selectionTouched)this.selectedIndex=0;else if(selectedPath){let selectedIndex=this.filteredSessions.findIndex(node=>node.session.path===selectedPath);selectedIndex>=0&&(this.selectedIndex=selectedIndex)}}filterSessions(query){let trimmed=query.trim(),nameFiltered=this.nameFilter==="all"?this.allSessions:this.allSessions.filter(session=>hasSessionName(session));if(this.sortMode==="threaded"&&!trimmed){let roots=buildSessionTree(nameFiltered,this.canonicalPath);this.filteredSessions=flattenSessionTree(roots)}else{let filtered=filterAndSortSessions(nameFiltered,query,this.sortMode,"all");this.filteredSessions=filtered.map(session=>({session,depth:0,isLast:!0,ancestorContinues:[]}))}this.selectedIndex=Math.min(this.selectedIndex,Math.max(0,this.filteredSessions.length-1))}setConfirmingDeletePath(path2){this.confirmingDeletePath=path2,this.onDeleteConfirmationChange?.(path2)}startDeleteConfirmationForSelectedSession(){let selected=this.filteredSessions[this.selectedIndex];if(selected){if(this.isCurrentSessionPath(selected.session.path)){this.onError?.("Cannot delete the currently active session");return}this.setConfirmingDeletePath(selected.session.path)}}isCurrentSessionPath(path2){return this.currentSessionCanonicalPath?(this.canonicalPath(path2)??path2)===this.currentSessionCanonicalPath:!1}invalidate(){}render(width){let lines=[];if(lines.push(...this.searchInput.render(width)),lines.push(""),this.filteredSessions.length===0){let emptyMessage;if(this.nameFilter==="named"){let toggleKey=keyText("app.session.toggleNamedFilter");this.showCwd?emptyMessage=` No named sessions found. Press ${toggleKey} to show all.`:emptyMessage=` No named sessions in current folder. Press ${toggleKey} to show all, or Tab to view all.`}else this.showCwd?emptyMessage=" No sessions found":emptyMessage=" No sessions in current folder. Press Tab to view all.";return lines.push(theme.fg("muted",truncateToWidth(emptyMessage,width,"\u2026"))),lines}let startIndex=Math.max(0,Math.min(this.selectedIndex-Math.floor(this.maxVisible/2),this.filteredSessions.length-this.maxVisible)),endIndex=Math.min(startIndex+this.maxVisible,this.filteredSessions.length);for(let i=startIndex;i<endIndex;i++){let node=this.filteredSessions[i],session=node.session,isSelected=i===this.selectedIndex,isConfirmingDelete=session.path===this.confirmingDeletePath,isCurrent=this.isCurrentSessionPath(session.path),prefix=this.buildTreePrefix(node),hasName=!!session.name,normalizedMessage=(session.name??session.firstMessage).replace(/[\x00-\x1f\x7f]/g," ").trim(),age=formatSessionDate(session.modified),rightPart=`${String(session.messageCount)} ${age}`;(this.showCwd||session.moved)&&session.cwd&&(rightPart=`${shortenPath(session.cwd)} ${rightPart}`);let movedBadge=session.moved?"moved from ":"";this.showPath&&(rightPart=`${shortenPath(session.path)} ${rightPart}`);let cursor=isSelected?theme.fg("accent","\u203A "):" ",prefixWidth=visibleWidth(prefix),rightWidth=visibleWidth(rightPart)+2,availableForMsg=width-2-prefixWidth-rightWidth,truncatedMsg=truncateToWidth(normalizedMessage,Math.max(10,availableForMsg),"\u2026"),messageColor=null;isConfirmingDelete?messageColor="error":isCurrent?messageColor="accent":hasName&&(messageColor="warning");let styledMsg=messageColor?theme.fg(messageColor,truncatedMsg):truncatedMsg;isSelected&&(styledMsg=theme.bold(styledMsg));let leftPart=cursor+theme.fg("dim",prefix)+styledMsg,leftWidth=visibleWidth(leftPart),spacing=Math.max(1,width-leftWidth-visibleWidth(movedBadge+rightPart)),styledRight=(movedBadge?theme.fg("warning",movedBadge):"")+theme.fg(isConfirmingDelete?"error":"dim",rightPart),line=leftPart+" ".repeat(spacing)+styledRight;isSelected&&(line=theme.bg("selectedBg",line)),lines.push(truncateToWidth(line,width))}if(startIndex>0||endIndex<this.filteredSessions.length){let scrollText=` (${this.selectedIndex+1}/${this.filteredSessions.length})`,scrollInfo=theme.fg("muted",truncateToWidth(scrollText,width,""));lines.push(scrollInfo)}return lines}buildTreePrefix(node){if(node.depth===0)return"";let parts=node.ancestorContinues.map(continues=>continues?"\u2502 ":" "),branch=node.isLast?"\u2514\u2500 ":"\u251C\u2500 ";return parts.join("")+branch}handleInput(keyData){let kb=getKeybindings();if(this.confirmingDeletePath!==null){if(kb.matches(keyData,"tui.select.confirm")){let pathToDelete=this.confirmingDeletePath;this.setConfirmingDeletePath(null),this.onDeleteSession?.(pathToDelete);return}if(kb.matches(keyData,"tui.select.cancel")){this.setConfirmingDeletePath(null);return}return}if(kb.matches(keyData,"tui.input.tab")){this.onToggleScope&&this.onToggleScope();return}if(kb.matches(keyData,"app.session.toggleSort")){this.onToggleSort?.();return}if(this.keybindings.matches(keyData,"app.session.toggleNamedFilter")){this.onToggleNameFilter?.();return}if(kb.matches(keyData,"app.session.togglePath")){this.showPath=!this.showPath,this.onTogglePath?.(this.showPath);return}if(kb.matches(keyData,"app.session.delete")){this.startDeleteConfirmationForSelectedSession();return}if(kb.matches(keyData,"app.session.rename")){let selected=this.filteredSessions[this.selectedIndex];selected&&this.onRenameSession?.(selected.session.path);return}if(kb.matches(keyData,"app.session.deleteNoninvasive")){if(this.searchInput.getValue().length>0){this.searchInput.handleInput(keyData),this.filterSessions(this.searchInput.getValue());return}this.startDeleteConfirmationForSelectedSession();return}if(this.selectionTouched=!0,kb.matches(keyData,"tui.select.up"))this.selectedIndex=Math.max(0,this.selectedIndex-1);else if(kb.matches(keyData,"tui.select.down"))this.selectedIndex=Math.min(this.filteredSessions.length-1,this.selectedIndex+1);else if(kb.matches(keyData,"tui.select.pageUp"))this.selectedIndex=Math.max(0,this.selectedIndex-this.maxVisible);else if(kb.matches(keyData,"tui.select.pageDown"))this.selectedIndex=Math.min(this.filteredSessions.length-1,this.selectedIndex+this.maxVisible);else if(kb.matches(keyData,"tui.select.confirm")){let selected=this.filteredSessions[this.selectedIndex];selected&&this.onSelect&&this.onSelect(selected.session.path)}else kb.matches(keyData,"tui.select.cancel")?this.onCancel&&this.onCancel():(this.searchInput.handleInput(keyData),this.filterSessions(this.searchInput.getValue()))}};function withMediaOutcome(result,mediaError){return mediaError===void 0?result:{...result,mediaError}}async function deleteSessionFile(sessionPath){let mediaScope=await toolMediaScopeOfSessionFile(sessionPath),removeMedia=()=>{if(mediaScope!==void 0)try{removeToolMedia(mediaScope);return}catch(cause){let reason=cause instanceof Error?cause.message:String(cause);return`${toolMediaRoot(mediaScope)}: ${reason}`}},trashArgs=sessionPath.startsWith("-")?["--",sessionPath]:[sessionPath],trashResult=spawnSync("trash",trashArgs,{encoding:"utf-8"}),getTrashErrorHint=()=>{let parts=[];trashResult.error&&parts.push(trashResult.error.message);let stderr=trashResult.stderr?.trim();return stderr&&parts.push(stderr.split(`
|
|
51
|
-
`)[0]??stderr),parts.length===0?null:`trash: ${parts.join(" \xB7 ").slice(0,200)}`};if(trashResult.status===0||!existsSync8(sessionPath))return withMediaOutcome({ok:!0,method:"trash"},removeMedia());try{return await unlink(sessionPath),withMediaOutcome({ok:!0,method:"unlink"},removeMedia())}catch(err){let unlinkError=err instanceof Error?err.message:String(err),trashErrorHint=getTrashErrorHint();return{ok:!1,method:"unlink",error:trashErrorHint?`${unlinkError} (${trashErrorHint})`:unlinkError}}}var SessionSelectorComponent=class extends Container{handleInput(data){if(this.mode==="rename"){if(getKeybindings().matches(data,"tui.select.cancel")){this.exitRenameMode();return}this.renameInput.handleInput(data);return}this.sessionList.handleInput(data)}get focused(){return this._focused}set focused(value){this._focused=value,this.sessionList.focused=value,this.renameInput.focused=value,value&&this.mode==="rename"&&(this.renameInput.focused=!0)}buildBaseLayout(content,options){this.clear(),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder(s=>theme.fg("accent",s))),this.addChild(new Spacer(1)),(options?.showHeader??!0)&&(this.addChild(this.header),this.addChild(new Spacer(1))),this.addChild(content),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder(s=>theme.fg("accent",s)))}constructor(currentSessionsLoader,allSessionsLoader,onSelect,onCancel,onExit,requestRender,options,currentSessionFilePath){super(),this.canRename=!0,this.scope="current",this.sortMode="threaded",this.nameFilter="all",this.currentSessions=null,this.allSessions=null,this.currentLoad=null,this.allLoad=null,this.mode="list",this.renameInput=new Input,this.renameTargetPath=null,this._focused=!1,this.keybindings=options?.keybindings??KeybindingsManager.create(),this.currentSessionsLoader=currentSessionsLoader,this.allSessionsLoader=allSessionsLoader,this.requestRender=requestRender,this.header=new SessionSelectorHeader(this.scope,this.sortMode,this.nameFilter,this.requestRender);let renameSession=options?.renameSession;this.renameSession=renameSession,this.canRename=!!renameSession,this.header.setShowRenameHint(options?.showRenameHint??this.canRename),this.sessionList=new SessionList([],!1,this.sortMode,this.nameFilter,this.keybindings,currentSessionFilePath),this.buildBaseLayout(this.sessionList),this.renameInput.onSubmit=value=>{this.confirmRename(value)};let clearStatusMessage=()=>this.header.setStatusMessage(null);this.sessionList.onSelect=sessionPath=>{clearStatusMessage(),this.cancelLoads(),onSelect(sessionPath)},this.sessionList.onCancel=()=>{clearStatusMessage(),this.cancelLoads(),onCancel()},this.sessionList.onExit=()=>{clearStatusMessage(),this.cancelLoads(),onExit()},this.sessionList.onToggleScope=()=>this.toggleScope(),this.sessionList.onToggleSort=()=>this.toggleSortMode(),this.sessionList.onToggleNameFilter=()=>this.toggleNameFilter(),this.sessionList.onRenameSession=sessionPath=>{if(!renameSession||(this.scope==="current"?this.currentLoad:this.allLoad))return;let session=(this.scope==="all"?this.allSessions??[]:this.currentSessions??[]).find(s=>s.path===sessionPath);this.enterRenameMode(sessionPath,session?.name)},this.sessionList.onTogglePath=showPath=>{this.header.setShowPath(showPath),this.requestRender()},this.sessionList.onDeleteConfirmationChange=path2=>{this.header.setConfirmingDeletePath(path2),this.requestRender()},this.sessionList.onError=msg=>{this.header.setStatusMessage({type:"error",message:msg},3e3),this.requestRender()},this.sessionList.onDeleteSession=async sessionPath=>{let result=await deleteSessionFile(sessionPath);if(result.ok){this.currentSessions&&(this.currentSessions=this.currentSessions.filter(s=>s.path!==sessionPath)),this.allSessions&&(this.allSessions=this.allSessions.filter(s=>s.path!==sessionPath));let sessions=this.scope==="all"?this.allSessions??[]:this.currentSessions??[],showCwd=this.scope==="all";this.sessionList.setSessions(sessions,showCwd);let msg=result.method==="trash"?"Session moved to trash":"Session deleted";result.mediaError?this.header.setStatusMessage({type:"error",message:`${msg}, but its images were not removed: ${result.mediaError}`},8e3):this.header.setStatusMessage({type:"info",message:msg},2e3),await this.refreshSessionsAfterMutation()}else{let errorMessage=result.error??"Unknown error";this.header.setStatusMessage({type:"error",message:`Failed to delete: ${errorMessage}`},3e3)}this.requestRender()},this.loadScope("current")}cancelLoads(){this.currentLoad&&(this.currentLoad.abort(),this.currentLoad=null,this.currentSessions=null),this.allLoad&&(this.allLoad.abort(),this.allLoad=null,this.allSessions=null)}enterRenameMode(sessionPath,currentName){this.mode="rename",this.renameTargetPath=sessionPath,this.renameInput.setValue(currentName??""),this.renameInput.focused=!0;let panel=new Container;panel.addChild(new Text(theme.bold("Rename Session"),1,0)),panel.addChild(new Spacer(1)),panel.addChild(this.renameInput),panel.addChild(new Spacer(1)),panel.addChild(new Text(theme.fg("muted",`${keyText("tui.select.confirm")} to save \xB7 ${keyText("tui.select.cancel")} to cancel`),1,0)),this.buildBaseLayout(panel,{showHeader:!1}),this.requestRender()}exitRenameMode(){this.mode="list",this.renameTargetPath=null,this.buildBaseLayout(this.sessionList),this.requestRender()}async confirmRename(value){let next=value.trim();if(!next)return;let target=this.renameTargetPath;if(!target){this.exitRenameMode();return}let renameSession=this.renameSession;if(!renameSession){this.exitRenameMode();return}try{await renameSession(target,next),await this.refreshSessionsAfterMutation()}finally{this.exitRenameMode()}}async loadScope(scope){if(scope==="current"?this.currentLoad:this.allLoad)return;let showCwd=scope==="all",controller=new AbortController;scope==="current"?this.currentLoad=controller:this.allLoad=controller,this.header.setScope(scope),this.header.setLoading(!0),this.requestRender();let isActive=()=>(scope==="current"?this.currentLoad:this.allLoad)===controller,onProgress=(loaded,total,partialSessions)=>{if(isActive()){if(partialSessions){let sessions=[...partialSessions];scope==="current"?this.currentSessions=sessions:this.allSessions=sessions,scope===this.scope&&this.sessionList.setSessions(sessions,showCwd)}scope===this.scope&&(this.header.setProgress(loaded,total),this.requestRender())}};try{let sessions=await(scope==="current"?this.currentSessionsLoader(onProgress,controller.signal):this.allSessionsLoader(onProgress,controller.signal));if(!isActive()||(scope==="current"?(this.currentSessions=sessions,this.currentLoad=null):(this.allSessions=sessions,this.allLoad=null),scope!==this.scope))return;this.header.setLoading(!1),this.sessionList.setSessions(sessions,showCwd),this.requestRender()}catch(err){if(!isActive()||(scope==="current"?(this.currentLoad=null,this.currentSessions=null):(this.allLoad=null,this.allSessions=null),scope!==this.scope))return;let message=err instanceof Error?err.message:String(err);this.header.setLoading(!1),this.header.setStatusMessage({type:"error",message:`Failed to load sessions: ${message}`},4e3),this.sessionList.setSessions([],showCwd),this.requestRender()}}toggleSortMode(){this.sortMode=this.sortMode==="threaded"?"recent":this.sortMode==="recent"?"relevance":"threaded",this.header.setSortMode(this.sortMode),this.sessionList.setSortMode(this.sortMode),this.requestRender()}toggleNameFilter(){this.nameFilter=this.nameFilter==="all"?"named":"all",this.header.setNameFilter(this.nameFilter),this.sessionList.setNameFilter(this.nameFilter),this.requestRender()}async refreshSessionsAfterMutation(){this.cancelLoads(),this.currentSessions=null,this.allSessions=null,await this.loadScope(this.scope)}toggleScope(){this.scope=this.scope==="current"?"all":"current";let sessions=this.scope==="current"?this.currentSessions:this.allSessions,loading=(this.scope==="current"?this.currentLoad:this.allLoad)!==null;this.header.setScope(this.scope),this.header.setLoading(loading),this.sessionList.setSessions(sessions??[],this.scope==="all"),this.requestRender(),sessions===null&&!loading&&this.loadScope(this.scope)}getSessionList(){return this.sessionList}};export{minimatch,VIRTUAL_MODEL_STATE_ENTRY,isVirtualModel,findLatestResponse,getBranchSelection,getVirtualModelState,createVirtualModel,withVirtualModels,sessionCwdMatcher,REPOSITORY_IDENTITY_ENTRY_TYPE,readRepositoryIdentity,compareRepositoryIdentities,parseRepositoryIdentity,sameRepositoryIdentity,parseEntryLine,readFileLines,listSessionsFromDir,reserveSessionWrite,unregisterSessionWriter,resolveEnvironmentContext,environmentContextMessageIfChanged,rejectedImageSources,toolResultUserWords,userWordBlocks,GOAL_CONTINUATION_MESSAGE_TYPE,isContextExcludedCustomMessage,createBranchSummaryMessage,createCompactionSummaryMessage,createCustomMessage,convertToLlm,TRANSPORT_IMAGE_BUDGET_BYTES,convertToLlmForTransport,SESSION_CONTEXT_ENTRY_ID,getSessionContextEntryId,inheritSessionContextEntryId,CURRENT_SESSION_VERSION,assertValidSessionId,migrateSessionEntries,parseSessionEntries,getLatestCompactionEntry,sessionEntryToContextMessages,buildContextEntries,buildSessionProjection,buildSessionContext,getDefaultSessionDir,loadEntriesFromFile,findMostRecentSession,SessionManager,DynamicBorder,formatKeyText,keyText,keyDisplayText,keyHint,rawKeyHint,areExperimentalFeaturesEnabled,parseGitUrl,readPiManifest,shouldSkipSkillWalkDirectoryName,readSkillMarkdownSource,DefaultPackageManager,CountdownTimer,ExtensionInputComponent,ExtensionSelectorComponent,InteractiveThemeController,createStartupTui,startStartupTui,shouldRunFirstTimeSetup,showStartupSelector,showFirstTimeSetup,showStartupInput,omitInlineMedia,liveToolMediaScope,toolMediaPersister,SessionSelectorComponent};
|
|
53
|
+
`)[0]??stderr),parts.length===0?null:`trash: ${parts.join(" \xB7 ").slice(0,200)}`};if(trashResult.status===0||!existsSync8(sessionPath))return withMediaOutcome({ok:!0,method:"trash"},removeMedia());try{return await unlink(sessionPath),withMediaOutcome({ok:!0,method:"unlink"},removeMedia())}catch(err){let unlinkError=err instanceof Error?err.message:String(err),trashErrorHint=getTrashErrorHint();return{ok:!1,method:"unlink",error:trashErrorHint?`${unlinkError} (${trashErrorHint})`:unlinkError}}}var SessionSelectorComponent=class extends Container{handleInput(data){if(this.mode==="rename"){if(getKeybindings().matches(data,"tui.select.cancel")){this.exitRenameMode();return}this.renameInput.handleInput(data);return}this.sessionList.handleInput(data)}get focused(){return this._focused}set focused(value){this._focused=value,this.sessionList.focused=value,this.renameInput.focused=value,value&&this.mode==="rename"&&(this.renameInput.focused=!0)}buildBaseLayout(content,options){this.clear(),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder(s=>theme.fg("accent",s))),this.addChild(new Spacer(1)),(options?.showHeader??!0)&&(this.addChild(this.header),this.addChild(new Spacer(1))),this.addChild(content),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder(s=>theme.fg("accent",s)))}constructor(currentSessionsLoader,allSessionsLoader,onSelect,onCancel,onExit,requestRender,options,currentSessionFilePath){super(),this.canRename=!0,this.scope="current",this.sortMode="threaded",this.nameFilter="all",this.currentSessions=null,this.allSessions=null,this.currentLoad=null,this.allLoad=null,this.mode="list",this.renameInput=new Input,this.renameTargetPath=null,this._focused=!1,this.keybindings=options?.keybindings??KeybindingsManager.create(),this.currentSessionsLoader=currentSessionsLoader,this.allSessionsLoader=allSessionsLoader,this.requestRender=requestRender,this.header=new SessionSelectorHeader(this.scope,this.sortMode,this.nameFilter,this.requestRender);let renameSession=options?.renameSession;this.renameSession=renameSession,this.canRename=!!renameSession,this.header.setShowRenameHint(options?.showRenameHint??this.canRename),this.sessionList=new SessionList([],!1,this.sortMode,this.nameFilter,this.keybindings,currentSessionFilePath),this.buildBaseLayout(this.sessionList),this.renameInput.onSubmit=value=>{this.confirmRename(value)};let clearStatusMessage=()=>this.header.setStatusMessage(null);this.sessionList.onSelect=sessionPath=>{clearStatusMessage(),this.cancelLoads(),onSelect(sessionPath)},this.sessionList.onCancel=()=>{clearStatusMessage(),this.cancelLoads(),onCancel()},this.sessionList.onExit=()=>{clearStatusMessage(),this.cancelLoads(),onExit()},this.sessionList.onToggleScope=()=>this.toggleScope(),this.sessionList.onToggleSort=()=>this.toggleSortMode(),this.sessionList.onToggleNameFilter=()=>this.toggleNameFilter(),this.sessionList.onRenameSession=sessionPath=>{if(!renameSession||(this.scope==="current"?this.currentLoad:this.allLoad))return;let session=(this.scope==="all"?this.allSessions??[]:this.currentSessions??[]).find(s=>s.path===sessionPath);this.enterRenameMode(sessionPath,session?.name)},this.sessionList.onTogglePath=showPath=>{this.header.setShowPath(showPath),this.requestRender()},this.sessionList.onDeleteConfirmationChange=path2=>{this.header.setConfirmingDeletePath(path2),this.requestRender()},this.sessionList.onError=msg=>{this.header.setStatusMessage({type:"error",message:msg},3e3),this.requestRender()},this.sessionList.onDeleteSession=async sessionPath=>{let result=await deleteSessionFile(sessionPath);if(result.ok){this.currentSessions&&(this.currentSessions=this.currentSessions.filter(s=>s.path!==sessionPath)),this.allSessions&&(this.allSessions=this.allSessions.filter(s=>s.path!==sessionPath));let sessions=this.scope==="all"?this.allSessions??[]:this.currentSessions??[],showCwd=this.scope==="all";this.sessionList.setSessions(sessions,showCwd);let msg=result.method==="trash"?"Session moved to trash":"Session deleted";result.mediaError?this.header.setStatusMessage({type:"error",message:`${msg}, but its images were not removed: ${result.mediaError}`},8e3):this.header.setStatusMessage({type:"info",message:msg},2e3),await this.refreshSessionsAfterMutation()}else{let errorMessage=result.error??"Unknown error";this.header.setStatusMessage({type:"error",message:`Failed to delete: ${errorMessage}`},3e3)}this.requestRender()},this.loadScope("current")}cancelLoads(){this.currentLoad&&(this.currentLoad.abort(),this.currentLoad=null,this.currentSessions=null),this.allLoad&&(this.allLoad.abort(),this.allLoad=null,this.allSessions=null)}enterRenameMode(sessionPath,currentName){this.mode="rename",this.renameTargetPath=sessionPath,this.renameInput.setValue(currentName??""),this.renameInput.focused=!0;let panel=new Container;panel.addChild(new Text(theme.bold("Rename Session"),1,0)),panel.addChild(new Spacer(1)),panel.addChild(this.renameInput),panel.addChild(new Spacer(1)),panel.addChild(new Text(theme.fg("muted",`${keyText("tui.select.confirm")} to save \xB7 ${keyText("tui.select.cancel")} to cancel`),1,0)),this.buildBaseLayout(panel,{showHeader:!1}),this.requestRender()}exitRenameMode(){this.mode="list",this.renameTargetPath=null,this.buildBaseLayout(this.sessionList),this.requestRender()}async confirmRename(value){let next=value.trim();if(!next)return;let target=this.renameTargetPath;if(!target){this.exitRenameMode();return}let renameSession=this.renameSession;if(!renameSession){this.exitRenameMode();return}try{await renameSession(target,next),await this.refreshSessionsAfterMutation()}finally{this.exitRenameMode()}}async loadScope(scope){if(scope==="current"?this.currentLoad:this.allLoad)return;let showCwd=scope==="all",controller=new AbortController;scope==="current"?this.currentLoad=controller:this.allLoad=controller,this.header.setScope(scope),this.header.setLoading(!0),this.requestRender();let isActive=()=>(scope==="current"?this.currentLoad:this.allLoad)===controller,onProgress=(loaded,total,partialSessions)=>{if(isActive()){if(partialSessions){let sessions=[...partialSessions];scope==="current"?this.currentSessions=sessions:this.allSessions=sessions,scope===this.scope&&this.sessionList.setSessions(sessions,showCwd)}scope===this.scope&&(this.header.setProgress(loaded,total),this.requestRender())}};try{let sessions=await(scope==="current"?this.currentSessionsLoader(onProgress,controller.signal):this.allSessionsLoader(onProgress,controller.signal));if(!isActive()||(scope==="current"?(this.currentSessions=sessions,this.currentLoad=null):(this.allSessions=sessions,this.allLoad=null),scope!==this.scope))return;this.header.setLoading(!1),this.sessionList.setSessions(sessions,showCwd),this.requestRender()}catch(err){if(!isActive()||(scope==="current"?(this.currentLoad=null,this.currentSessions=null):(this.allLoad=null,this.allSessions=null),scope!==this.scope))return;let message=err instanceof Error?err.message:String(err);this.header.setLoading(!1),this.header.setStatusMessage({type:"error",message:`Failed to load sessions: ${message}`},4e3),this.sessionList.setSessions([],showCwd),this.requestRender()}}toggleSortMode(){this.sortMode=this.sortMode==="threaded"?"recent":this.sortMode==="recent"?"relevance":"threaded",this.header.setSortMode(this.sortMode),this.sessionList.setSortMode(this.sortMode),this.requestRender()}toggleNameFilter(){this.nameFilter=this.nameFilter==="all"?"named":"all",this.header.setNameFilter(this.nameFilter),this.sessionList.setNameFilter(this.nameFilter),this.requestRender()}async refreshSessionsAfterMutation(){this.cancelLoads(),this.currentSessions=null,this.allSessions=null,await this.loadScope(this.scope)}toggleScope(){this.scope=this.scope==="current"?"all":"current";let sessions=this.scope==="current"?this.currentSessions:this.allSessions,loading=(this.scope==="current"?this.currentLoad:this.allLoad)!==null;this.header.setScope(this.scope),this.header.setLoading(loading),this.sessionList.setSessions(sessions??[],this.scope==="all"),this.requestRender(),sessions===null&&!loading&&this.loadScope(this.scope)}getSessionList(){return this.sessionList}};export{minimatch,VIRTUAL_MODEL_STATE_ENTRY,isVirtualModel,findLatestResponse,getBranchSelection,getVirtualModelState,createVirtualModel,withVirtualModels,sessionCwdMatcher,REPOSITORY_IDENTITY_ENTRY_TYPE,readRepositoryIdentity,compareRepositoryIdentities,parseRepositoryIdentity,sameRepositoryIdentity,parseEntryLine,readFileLines,listSessionsFromDir,hasUnsafeRetainedContent,isSafeBoundedValue,reserveSessionWrite,unregisterSessionWriter,resolveEnvironmentContext,environmentContextMessageIfChanged,rejectedImageSources,toolResultUserWords,userWordBlocks,GOAL_CONTINUATION_MESSAGE_TYPE,isContextExcludedCustomMessage,createBranchSummaryMessage,createCompactionSummaryMessage,createCustomMessage,convertToLlm,TRANSPORT_IMAGE_BUDGET_BYTES,convertToLlmForTransport,SESSION_CONTEXT_ENTRY_ID,getSessionContextEntryId,inheritSessionContextEntryId,CURRENT_SESSION_VERSION,assertValidSessionId,migrateSessionEntries,parseSessionEntries,getLatestCompactionEntry,sessionEntryToContextMessages,buildContextEntries,buildSessionProjection,buildSessionContext,getDefaultSessionDir,loadEntriesFromFile,findMostRecentSession,SessionManager,DynamicBorder,formatKeyText,keyText,keyDisplayText,keyHint,rawKeyHint,areExperimentalFeaturesEnabled,parseGitUrl,readPiManifest,shouldSkipSkillWalkDirectoryName,readSkillMarkdownSource,DefaultPackageManager,CountdownTimer,ExtensionInputComponent,ExtensionSelectorComponent,InteractiveThemeController,createStartupTui,startStartupTui,shouldRunFirstTimeSetup,showStartupSelector,showFirstTimeSetup,showStartupInput,omitInlineMedia,liveToolMediaScope,toolMediaPersister,SessionSelectorComponent};
|