@code-yeongyu/senpi 2026.11.6-1 → 2026.11.6-2

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.
Files changed (167) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/dist/bundle/chunks/{chunk-5MWHZH2O.js → chunk-2FDW2LQL.js} +1 -1
  3. package/dist/bundle/chunks/{chunk-GG2JO3CL.js → chunk-4E7GDG4H.js} +1 -1
  4. package/dist/bundle/chunks/{chunk-K5JLYACP.js → chunk-4GKU755E.js} +1 -1
  5. package/dist/bundle/chunks/{chunk-437VLZQZ.js → chunk-7III44PV.js} +1 -1
  6. package/dist/bundle/chunks/chunk-7PSBD5KS.js +9 -0
  7. package/dist/bundle/chunks/{chunk-KFWHLVVH.js → chunk-C7OKUC7L.js} +1 -1
  8. package/dist/bundle/chunks/{chunk-CX32K5KD.js → chunk-CF5OGBC4.js} +7 -7
  9. package/dist/bundle/chunks/{chunk-7TGZJH6Z.js → chunk-D5MRJWUK.js} +40 -39
  10. package/dist/bundle/chunks/{chunk-E6L5VZSM.js → chunk-DSWDJ7HT.js} +1 -1
  11. package/dist/bundle/chunks/{chunk-6NMTFURP.js → chunk-ECW7VBMB.js} +1 -1
  12. package/dist/bundle/chunks/{chunk-2CSLJLM6.js → chunk-GKAYPJ4E.js} +2 -2
  13. package/dist/bundle/chunks/{chunk-KCGUUIUS.js → chunk-GNSMNSL7.js} +1 -1
  14. package/dist/bundle/chunks/{chunk-V3JSQ3PG.js → chunk-GSKCWXXG.js} +1 -1
  15. package/dist/bundle/chunks/{chunk-USKWGPA6.js → chunk-GTJJ73DE.js} +1 -1
  16. package/dist/bundle/chunks/{chunk-HHSYTDKO.js → chunk-HLM46XEB.js} +2 -2
  17. package/dist/bundle/chunks/{chunk-A4F4J2KH.js → chunk-I3PHVJAS.js} +2 -2
  18. package/dist/bundle/chunks/{chunk-LAMRXFHZ.js → chunk-LNPAT22L.js} +1 -1
  19. package/dist/bundle/chunks/chunk-NH7SYIGN.js +2 -0
  20. package/dist/bundle/chunks/{chunk-ZIIDIVTG.js → chunk-R2Z7CX77.js} +1 -1
  21. package/dist/bundle/chunks/{chunk-32I42CEY.js → chunk-RQ6CHXQ2.js} +1 -1
  22. package/dist/bundle/chunks/chunk-SJI6UB23.js +2 -0
  23. package/dist/bundle/chunks/{chunk-KUIEHAPR.js → chunk-T2SMQPRE.js} +1 -1
  24. package/dist/bundle/chunks/{chunk-IPG434JT.js → chunk-TIPKAMSS.js} +1 -1
  25. package/dist/bundle/chunks/{chunk-RI5ABX7A.js → chunk-TMXRR3N7.js} +2 -2
  26. package/dist/bundle/chunks/chunk-VD7AKTGP.js +3 -0
  27. package/dist/bundle/chunks/{chunk-22JICYKS.js → chunk-WAOGBBZR.js} +1 -1
  28. package/dist/bundle/chunks/{chunk-6MHCFJDB.js → chunk-WGRKM3N6.js} +2 -2
  29. package/dist/bundle/chunks/{chunk-WF5R2VSP.js → chunk-X5ZVYNOL.js} +1 -1
  30. package/dist/bundle/chunks/{chunk-H2FBGZNP.js → chunk-XCMII2VQ.js} +2 -2
  31. package/dist/bundle/chunks/{chunk-5JUCTKYS.js → chunk-YK3ZZCHI.js} +1 -1
  32. package/dist/bundle/chunks/{cli-main-ZQBSX5H5.js → cli-main-T74YJGIF.js} +1 -1
  33. package/dist/bundle/chunks/{hand-entry-7U7354GG.js → hand-entry-AYRUGE2A.js} +2 -2
  34. package/dist/bundle/chunks/{headless-host-7LKTG76U.js → headless-host-ES74ZB6M.js} +1 -1
  35. package/dist/bundle/chunks/{help-fast-path-NLSWH2CA.js → help-fast-path-TMTGLOBG.js} +1 -1
  36. package/dist/bundle/chunks/{host-command-3YRFN35E.js → host-command-YRXZE4TV.js} +1 -1
  37. package/dist/bundle/chunks/{host-lifecycle-6XLVIECJ.js → host-lifecycle-6VCXMPDW.js} +1 -1
  38. package/dist/bundle/chunks/host-lifecycle.js +1 -1
  39. package/dist/bundle/chunks/{host-session-command-F7USXUZV.js → host-session-command-N7IN7ZDV.js} +1 -1
  40. package/dist/bundle/chunks/{interactive-mode-4RF3PUQ2.js → interactive-mode-B5SQDLH7.js} +1 -1
  41. package/dist/bundle/chunks/{list-tips-H6VGDFTS.js → list-tips-DU57HHKA.js} +1 -1
  42. package/dist/bundle/chunks/{main-G2SRZYQN.js → main-UQFVFCNY.js} +1 -1
  43. package/dist/bundle/chunks/{multi-session-host-RPN54GUC.js → multi-session-host-XSUJDHFZ.js} +5 -5
  44. package/dist/bundle/chunks/{openai-codex-responses-MJZKUS6I.js → openai-codex-responses-7V6LTDRU.js} +2 -2
  45. package/dist/bundle/chunks/{package-manager-cli-D2VFD463.js → package-manager-cli-GLUNPQJU.js} +1 -1
  46. package/dist/bundle/chunks/{role-37WVG42T.js → role-RRFFHZF5.js} +1 -1
  47. package/dist/bundle/chunks/{rotation-stream-QELPMM4N.js → rotation-stream-BN2YK2MC.js} +1 -1
  48. package/dist/bundle/chunks/{rpc-mode-P4D3DVYD.js → rpc-mode-JYN3E7P7.js} +1 -1
  49. package/dist/bundle/chunks/rpc-monitor-source-C6VQ3BC4.js +3 -0
  50. package/dist/bundle/chunks/{run-attached-tui-CGA6O5FR.js → run-attached-tui-W236SEOR.js} +1 -1
  51. package/dist/bundle/chunks/{schedule-command-XWSNOAGG.js → schedule-command-B2EJTBOE.js} +1 -1
  52. package/dist/bundle/chunks/session-control-endpoint-YIMLHGLG.js +3 -0
  53. package/dist/bundle/chunks/{session-picker-OA2AUVZG.js → session-picker-E6ZONUJB.js} +1 -1
  54. package/dist/bundle/chunks/session-worker.js +294 -292
  55. package/dist/bundle/cli.js +2 -2
  56. package/dist/bundle/host-supervisor.js +1 -1
  57. package/dist/bundle/index.js +1 -1
  58. package/dist/bundle/rpc-entry.js +1 -1
  59. package/dist/bundle/runtime-manifest.json +1 -1
  60. package/dist/cli/project-trust-headless.d.ts +13 -0
  61. package/dist/cli/project-trust-headless.js +35 -0
  62. package/dist/cli/project-trust.js +13 -50
  63. package/dist/cli/schedule-delivery.d.ts +4 -0
  64. package/dist/cli/schedule-delivery.js +6 -0
  65. package/dist/cli/schedule-runner.js +8 -0
  66. package/dist/cli/session-opening.d.ts +19 -0
  67. package/dist/cli/session-opening.js +47 -1
  68. package/dist/core/agent-session-runtime.d.ts +12 -0
  69. package/dist/core/agent-session-runtime.js +41 -0
  70. package/dist/core/agent-session.js +13 -22
  71. package/dist/core/egress/api-table.d.ts +121 -0
  72. package/dist/core/egress/api-table.js +41 -0
  73. package/dist/core/egress/classify.d.ts +19 -0
  74. package/dist/core/egress/classify.js +197 -0
  75. package/dist/core/egress/credential-fields.d.ts +18 -0
  76. package/dist/core/egress/credential-fields.js +83 -0
  77. package/dist/core/egress/custody-sidecar.d.ts +44 -0
  78. package/dist/core/egress/custody-sidecar.js +91 -0
  79. package/dist/core/egress/device-custody.d.ts +12 -0
  80. package/dist/core/egress/device-custody.js +82 -0
  81. package/dist/core/egress/endpoint.d.ts +33 -0
  82. package/dist/core/egress/endpoint.js +115 -0
  83. package/dist/core/execute-tool-on-host.d.ts +26 -0
  84. package/dist/core/execute-tool-on-host.js +96 -0
  85. package/dist/core/extensions/builtin/compaction/retained-message-safety.js +15 -0
  86. package/dist/core/extensions/builtin/goal/index.js +15 -3
  87. package/dist/core/extensions/builtin/goal/stop-pause.d.ts +2 -0
  88. package/dist/core/extensions/builtin/goal/stop-pause.js +5 -0
  89. package/dist/core/extensions/builtin/herdr/herdr-state.d.ts +10 -0
  90. package/dist/core/extensions/builtin/herdr/herdr-state.js +34 -6
  91. package/dist/core/extensions/builtin/herdr/index.js +6 -2
  92. package/dist/core/extensions/builtin/mcp/service.d.ts +9 -1
  93. package/dist/core/extensions/builtin/mcp/service.js +32 -1
  94. package/dist/core/extensions/builtin/terminal/rpc-monitor-remote.d.ts +43 -0
  95. package/dist/core/extensions/builtin/terminal/rpc-monitor-remote.js +158 -0
  96. package/dist/core/extensions/builtin/terminal/rpc-monitor-render.d.ts +2 -0
  97. package/dist/core/extensions/builtin/terminal/rpc-monitor-render.js +4 -0
  98. package/dist/core/extensions/builtin/terminal/rpc-monitor-source.d.ts +5 -2
  99. package/dist/core/extensions/builtin/terminal/rpc-monitor-source.js +19 -4
  100. package/dist/core/extensions/builtin/terminal/rpc-monitor-targets.d.ts +4 -0
  101. package/dist/core/extensions/builtin/terminal/rpc-monitor-targets.js +15 -0
  102. package/dist/core/extensions/builtin/terminal/rpc-monitor-watch.d.ts +10 -0
  103. package/dist/core/extensions/builtin/terminal/rpc-monitor-watch.js +28 -2
  104. package/dist/core/extensions/builtin/terminal/rpc-remote-source.d.ts +59 -0
  105. package/dist/core/extensions/builtin/terminal/rpc-remote-source.js +15 -0
  106. package/dist/core/extensions/builtin/terminal/terminal-manifest-model.d.ts +5 -0
  107. package/dist/core/extensions/builtin/terminal/terminal-manifest-parse.js +14 -1
  108. package/dist/core/extensions/builtin/terminal/tools/monitor-rpc.js +8 -1
  109. package/dist/core/extensions/loader.js +8 -0
  110. package/dist/core/extensions/types.d.ts +6 -0
  111. package/dist/core/foreign-session-holders.d.ts +1 -1
  112. package/dist/core/foreign-session-holders.js +3 -3
  113. package/dist/core/session-import/jsonl-import.d.ts +8 -12
  114. package/dist/core/session-import/jsonl-import.js +99 -40
  115. package/dist/core/session-manager.d.ts +2 -0
  116. package/dist/core/session-manager.js +7 -2
  117. package/dist/core/session-store/durable-binding.d.ts +2 -0
  118. package/dist/core/session-store/durable-binding.js +26 -4
  119. package/dist/core/settings-manager.d.ts +20 -0
  120. package/dist/core/settings-manager.js +51 -0
  121. package/dist/core/trust-manager.d.ts +1 -18
  122. package/dist/core/trust-manager.js +3 -124
  123. package/dist/core/trust-requiring-resources.d.ts +21 -0
  124. package/dist/core/trust-requiring-resources.js +189 -0
  125. package/dist/index.d.ts +1 -0
  126. package/dist/index.js +1 -0
  127. package/dist/main.js +42 -12
  128. package/dist/modes/interactive/interactive-mode.js +2 -2
  129. package/dist/modes/interactive/session-control-commands.js +2 -0
  130. package/dist/modes/rpc/connection-handler.js +17 -0
  131. package/dist/modes/rpc/connection-question-bridge.js +7 -4
  132. package/dist/modes/rpc/effect-commands.d.ts +24 -0
  133. package/dist/modes/rpc/host-boot-extensions.d.ts +4 -0
  134. package/dist/modes/rpc/host-boot-extensions.js +17 -0
  135. package/dist/modes/rpc/host-lifecycle-shutdown.js +11 -2
  136. package/dist/modes/rpc/loopless-runtime-settings.js +5 -1
  137. package/dist/modes/rpc/method-classes-schema-session.d.ts +33 -0
  138. package/dist/modes/rpc/method-classes-schema-session.js +4 -0
  139. package/dist/modes/rpc/method-classes-schema.d.ts +33 -0
  140. package/dist/modes/rpc/method-classes.d.ts +4 -0
  141. package/dist/modes/rpc/method-classes.js +7 -0
  142. package/dist/modes/rpc/multi-session-host.d.ts +2 -0
  143. package/dist/modes/rpc/multi-session-host.js +7 -2
  144. package/dist/modes/rpc/project-workspace-commands.d.ts +60 -0
  145. package/dist/modes/rpc/project-workspace-commands.js +145 -0
  146. package/dist/modes/rpc/rpc-error-types.d.ts +11 -1
  147. package/dist/modes/rpc/rpc-error-types.js +10 -0
  148. package/dist/modes/rpc/rpc-input-validation.js +4 -0
  149. package/dist/modes/rpc/rpc-mutation-response-types.d.ts +13 -0
  150. package/dist/modes/rpc/rpc-read-response-types.d.ts +13 -0
  151. package/dist/modes/rpc/rpc-session-command-types.d.ts +15 -0
  152. package/dist/modes/rpc/session-attachment-gate.js +2 -0
  153. package/dist/modes/rpc/session-command-activity.js +2 -0
  154. package/docs/engine-socket/fixtures/admission-routes/h-legacy.json +1 -1
  155. package/docs/engine-socket/fixtures/rpc-inbound-samples.json +41 -2
  156. package/docs/extensions.md +17 -1
  157. package/docs/rpc.md +121 -4
  158. package/docs/terminal-tools.md +8 -0
  159. package/native/socket-secret/prebuilds/win32-arm64/senpi_socket_secret.win32-arm64.node +0 -0
  160. package/native/socket-secret/prebuilds/win32-x64/senpi_socket_secret.win32-x64.node +0 -0
  161. package/package.json +6 -6
  162. package/dist/bundle/chunks/chunk-FUQJK2TU.js +0 -2
  163. package/dist/bundle/chunks/chunk-POZMRM6V.js +0 -2
  164. package/dist/bundle/chunks/chunk-XBG63MJZ.js +0 -8
  165. package/dist/bundle/chunks/chunk-YP47G4YP.js +0 -3
  166. package/dist/bundle/chunks/rpc-monitor-source-KKN2UP4T.js +0 -3
  167. package/dist/bundle/chunks/session-control-endpoint-OST7WAKP.js +0 -3
@@ -1,5 +1,5 @@
1
1
  import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url); { const __piWorkerThreads = require("node:worker_threads"); if (typeof __piWorkerThreads.markAsUncloneable !== "function") { __piWorkerThreads.markAsUncloneable = () => {}; } }
2
- import{resolveMovedPath}from"./chunk-USKWGPA6.js";import{appendToolResultUserWords}from"./chunk-22YXCY7K.js";import{BaseContentHash,EventLoopSlicer,TranscriptJournal,blockCallKey,captureAndCloseFileIdentity,captureFileIdentity,captureTranscriptBase,compactUpdatesEnabled,discardFailedFirstFlush,discardFailedFirstFlushAsync,loadEntriesFromFile,loadEntriesFromFileAsync,loadedContentFingerprints,loadedFileIdentities,mapInSlices,parseSessionEntryLine,readForkSource,replaceFileAtomically,sessionRecoveryCause,snapshotTranscript,terminateFinalSessionLine,truncateToLastCompleteLine}from"./chunk-J2I56WLK.js";import{SessionWriteFence}from"./chunk-SOMFLLPD.js";import{createAdmissionLine,openSessionStore,openSyncSessionStore}from"./chunk-2CSLJLM6.js";import{dropFailedAssistantTurns}from"./chunk-YUVC7SJB.js";import{copyContextProvenance}from"./chunk-ZDHAJROE.js";import{getCurrentSystemMessage,isModelType,lazyStream,normalizeProviderId}from"./chunk-OKMHSVCA.js";import{APP_NAME,getAgentDir,getSessionsDir,normalizePath,resolvePath}from"./chunk-SODMQEHO.js";var VIRTUAL_MODEL_API="pi-virtual",VIRTUAL_MODEL_STATE_ENTRY="pi.virtual-model-state",THINKING_LEVELS=["off","minimal","low","medium","high","xhigh","max"];function isVirtualModel(model){return model.api===VIRTUAL_MODEL_API}function findLatestResponse(messages){for(let i=messages.length-1;i>=0;i--){let message=messages[i];if(message.role==="assistant"&&message.stopReason!=="error"&&message.stopReason!=="aborted")return message}}function getBranchSelection(branch,getModel){for(let i=branch.length-1;i>=0;i--){let entry=branch[i];if(entry.type==="model_change")return{provider:entry.provider,modelId:entry.modelId};if(entry.type==="message"&&entry.message.role==="assistant"&&!isVirtualModel(entry.message)){let response={provider:entry.message.provider,modelId:entry.message.model},change=findLastModelChange(branch,i),model=change&&getModel(change.provider,change.modelId);return change&&model&&isVirtualModel(model)?change:response}}}function findLastModelChange(branch,before){for(let i=before-1;i>=0;i--){let entry=branch[i];if(entry.type==="model_change")return{provider:entry.provider,modelId:entry.modelId}}}function getVirtualModelState(branch,provider,modelId){for(let i=branch.length-1;i>=0;i--){let entry=branch[i];if(entry.type!=="custom"||entry.customType!==VIRTUAL_MODEL_STATE_ENTRY)continue;let data=entry.data;if(data?.provider===provider&&data.modelId===modelId)return data.state}}function createVirtualModel(definition){let levels=definition.thinkingLevels??["off"],thinkingLevelMap={};for(let level of THINKING_LEVELS)thinkingLevelMap[level]=levels.includes(level)?level:null;return{id:definition.id,name:definition.name,api:VIRTUAL_MODEL_API,provider:definition.provider,baseUrl:"",reasoning:levels.some(level=>level!=="off"),thinkingLevelMap,input:definition.input??["text","image"],cost:{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:definition.contextWindow??0,maxTokens:definition.maxTokens??0}}function unroutedStream(model){return lazyStream(model,async()=>{throw new Error(`Virtual model ${model.provider}/${model.id} must be routed before streaming`)})}function withVirtualModels(providerId,provider,virtualModels){if(!provider)return{id:providerId,name:providerId,auth:{apiKey:{name:"Virtual model",resolve:async()=>({auth:{},source:"virtual"})}},getModels:()=>virtualModels,stream:unroutedStream,streamSimple:unroutedStream};let ids=new Set(virtualModels.map(model=>model.id)),physical=models=>models.filter(model=>!isVirtualModel(model)&&!(isModelType(model,"chat")&&ids.has(model.id))),virtual=models=>models.filter(model=>isVirtualModel(model)),{filterModels,filterAllModels}=provider;return{...provider,getModels:()=>[...physical(provider.getModels()),...virtualModels],getAllModels:()=>[...physical(provider.getAllModels?.()??provider.getModels()),...virtualModels],filterModels:(models,credential)=>{let real=physical(models);return[...filterModels?.(real,credential)??real,...virtual(models)]},filterAllModels:filterAllModels&&((models,credential)=>[...filterAllModels(physical(models),credential),...virtual(models)]),stream:(model,context,options)=>isVirtualModel(model)?unroutedStream(model):provider.stream(model,context,options),streamSimple:(model,context,options)=>isVirtualModel(model)?unroutedStream(model):provider.streamSimple(model,context,options)}}var ENVIRONMENT_CONTEXT_MESSAGE_TYPE="environment-context",CURRENT_DATE_ENV="SENPI_TEST_CURRENT_DATE";function pinnedCurrentDate(){let value=process.env[CURRENT_DATE_ENV];if(value===void 0||value==="")return;let parsed=new Date(`${value}T00:00:00.000Z`);if(!(/^\d{4}-\d{2}-\d{2}$/.test(value)&&!Number.isNaN(parsed.getTime())&&parsed.toISOString().startsWith(value)))throw new Error(`${CURRENT_DATE_ENV} must be a calendar date YYYY-MM-DD, got ${JSON.stringify(value)}`);return value}function resolveEnvironmentContext(cwd,now=new Date){return{cwd:cwd.replace(/\\/g,"/"),currentDate:pinnedCurrentDate()??now.toISOString().slice(0,10)}}function formatEnvironmentContext(context){return["<environment_context>",` <cwd>${context.cwd}</cwd>`,` <current_date>${context.currentDate}</current_date>`,"</environment_context>"].join(`
2
+ import{parseEntryLine,resolveMovedPath,sessionInfoName,visibleMessage}from"./chunk-GTJJ73DE.js";import{appendToolResultUserWords}from"./chunk-22YXCY7K.js";import{BaseContentHash,EventLoopSlicer,TranscriptJournal,blockCallKey,captureAndCloseFileIdentity,captureFileIdentity,captureTranscriptBase,compactUpdatesEnabled,discardFailedFirstFlush,discardFailedFirstFlushAsync,loadEntriesFromFile,loadEntriesFromFileAsync,loadedContentFingerprints,loadedFileIdentities,mapInSlices,parseSessionEntryLine,readForkSource,replaceFileAtomically,sessionRecoveryCause,snapshotTranscript,terminateFinalSessionLine,truncateToLastCompleteLine}from"./chunk-J2I56WLK.js";import{SessionWriteFence}from"./chunk-SOMFLLPD.js";import{appendRecordWrites,createAdmissionLine,divergenceWrite,manifestWrite,openSessionStore,openSyncSessionStore,readSessionState,rewriteRecordWrite}from"./chunk-GKAYPJ4E.js";import{dropFailedAssistantTurns}from"./chunk-YUVC7SJB.js";import{copyContextProvenance}from"./chunk-ZDHAJROE.js";import{getCurrentSystemMessage,isModelType,lazyStream,normalizeProviderId}from"./chunk-OKMHSVCA.js";import{APP_NAME,getAgentDir,getSessionsDir,normalizePath,resolvePath}from"./chunk-SODMQEHO.js";var VIRTUAL_MODEL_API="pi-virtual",VIRTUAL_MODEL_STATE_ENTRY="pi.virtual-model-state",THINKING_LEVELS=["off","minimal","low","medium","high","xhigh","max"];function isVirtualModel(model){return model.api===VIRTUAL_MODEL_API}function findLatestResponse(messages){for(let i=messages.length-1;i>=0;i--){let message=messages[i];if(message.role==="assistant"&&message.stopReason!=="error"&&message.stopReason!=="aborted")return message}}function getBranchSelection(branch,getModel){for(let i=branch.length-1;i>=0;i--){let entry=branch[i];if(entry.type==="model_change")return{provider:entry.provider,modelId:entry.modelId};if(entry.type==="message"&&entry.message.role==="assistant"&&!isVirtualModel(entry.message)){let response={provider:entry.message.provider,modelId:entry.message.model},change=findLastModelChange(branch,i),model=change&&getModel(change.provider,change.modelId);return change&&model&&isVirtualModel(model)?change:response}}}function findLastModelChange(branch,before){for(let i=before-1;i>=0;i--){let entry=branch[i];if(entry.type==="model_change")return{provider:entry.provider,modelId:entry.modelId}}}function getVirtualModelState(branch,provider,modelId){for(let i=branch.length-1;i>=0;i--){let entry=branch[i];if(entry.type!=="custom"||entry.customType!==VIRTUAL_MODEL_STATE_ENTRY)continue;let data=entry.data;if(data?.provider===provider&&data.modelId===modelId)return data.state}}function createVirtualModel(definition){let levels=definition.thinkingLevels??["off"],thinkingLevelMap={};for(let level of THINKING_LEVELS)thinkingLevelMap[level]=levels.includes(level)?level:null;return{id:definition.id,name:definition.name,api:VIRTUAL_MODEL_API,provider:definition.provider,baseUrl:"",reasoning:levels.some(level=>level!=="off"),thinkingLevelMap,input:definition.input??["text","image"],cost:{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:definition.contextWindow??0,maxTokens:definition.maxTokens??0}}function unroutedStream(model){return lazyStream(model,async()=>{throw new Error(`Virtual model ${model.provider}/${model.id} must be routed before streaming`)})}function withVirtualModels(providerId,provider,virtualModels){if(!provider)return{id:providerId,name:providerId,auth:{apiKey:{name:"Virtual model",resolve:async()=>({auth:{},source:"virtual"})}},getModels:()=>virtualModels,stream:unroutedStream,streamSimple:unroutedStream};let ids=new Set(virtualModels.map(model=>model.id)),physical=models=>models.filter(model=>!isVirtualModel(model)&&!(isModelType(model,"chat")&&ids.has(model.id))),virtual=models=>models.filter(model=>isVirtualModel(model)),{filterModels,filterAllModels}=provider;return{...provider,getModels:()=>[...physical(provider.getModels()),...virtualModels],getAllModels:()=>[...physical(provider.getAllModels?.()??provider.getModels()),...virtualModels],filterModels:(models,credential)=>{let real=physical(models);return[...filterModels?.(real,credential)??real,...virtual(models)]},filterAllModels:filterAllModels&&((models,credential)=>[...filterAllModels(physical(models),credential),...virtual(models)]),stream:(model,context,options)=>isVirtualModel(model)?unroutedStream(model):provider.stream(model,context,options),streamSimple:(model,context,options)=>isVirtualModel(model)?unroutedStream(model):provider.streamSimple(model,context,options)}}var ENVIRONMENT_CONTEXT_MESSAGE_TYPE="environment-context",CURRENT_DATE_ENV="SENPI_TEST_CURRENT_DATE";function pinnedCurrentDate(){let value=process.env[CURRENT_DATE_ENV];if(value===void 0||value==="")return;let parsed=new Date(`${value}T00:00:00.000Z`);if(!(/^\d{4}-\d{2}-\d{2}$/.test(value)&&!Number.isNaN(parsed.getTime())&&parsed.toISOString().startsWith(value)))throw new Error(`${CURRENT_DATE_ENV} must be a calendar date YYYY-MM-DD, got ${JSON.stringify(value)}`);return value}function resolveEnvironmentContext(cwd,now=new Date){return{cwd:cwd.replace(/\\/g,"/"),currentDate:pinnedCurrentDate()??now.toISOString().slice(0,10)}}function formatEnvironmentContext(context){return["<environment_context>",` <cwd>${context.cwd}</cwd>`,` <current_date>${context.currentDate}</current_date>`,"</environment_context>"].join(`
3
3
  `)}function isEnvironmentContext(value){if(typeof value!="object"||value===null)return!1;let candidate=value;return typeof candidate.cwd=="string"&&typeof candidate.currentDate=="string"}function latestEnvironmentContext(messages){for(let index=messages.length-1;index>=0;index--){let message=messages[index];if(message.role==="custom"&&message.customType===ENVIRONMENT_CONTEXT_MESSAGE_TYPE&&isEnvironmentContext(message.details))return message.details}}function createEnvironmentContextMessage(context,timestamp=Date.now()){return{role:"custom",customType:ENVIRONMENT_CONTEXT_MESSAGE_TYPE,content:formatEnvironmentContext(context),display:!1,details:{cwd:context.cwd,currentDate:context.currentDate},timestamp}}function environmentContextMessageIfChanged(messages,current){let latest=latestEnvironmentContext(messages);if(!(latest?.cwd===current.cwd&&latest.currentDate===current.currentDate))return createEnvironmentContextMessage(current)}function contentBlocks(content){return typeof content=="string"?[{type:"text",text:content}]:content}function foldEnvironmentContextIntoNextUserMessage(messages,environmentMessages){let folded=[];for(let index=0;index<messages.length;index++){let message=messages[index],next=messages[index+1];if(environmentMessages.has(message)&&message.role==="user"&&next?.role==="user"&&!environmentMessages.has(next)){folded.push({...next,content:[...contentBlocks(message.content),...contentBlocks(next.content)]}),index++;continue}folded.push(message)}return folded}import{createHash}from"node:crypto";var 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.]",IMAGE_ID_LENGTH=12,ID_SUFFIX=new RegExp(`^ \\(image ids?: ([0-9a-f]{${IMAGE_ID_LENGTH}}(?:, [0-9a-f]{${IMAGE_ID_LENGTH}})*)\\)$`);function imageContentId(data){return createHash("sha256").update(data).digest("hex").slice(0,IMAGE_ID_LENGTH)}function elisionPlaceholder(ids){let label=ids.length===1?"id":"ids";return{type:"text",text:`${IMAGE_ELISION_PLACEHOLDER} (image ${label}: ${ids.join(", ")})`}}function elidedImageIds(text){return text.startsWith(IMAGE_ELISION_PLACEHOLDER)?ID_SUFFIX.exec(text.slice(IMAGE_ELISION_PLACEHOLDER.length))?.[1]?.split(", "):void 0}function replaceElidedImages(content,isElided){let replaced=[],pending=[],flush=()=>{pending.length>0&&replaced.push(elisionPlaceholder(pending)),pending=[]};return content.forEach((block,blockIndex)=>{if(block.type==="image"&&isElided(blockIndex)){pending.push(imageContentId(block.data));return}flush(),replaced.push(block)}),flush(),replaced}var PROVIDER_IMAGE_REJECTION_PATTERN=/does not represent a valid image|image_parse_error|invalid_image|unsupported image|could not process image|unable to process input image|image_url'?\.?[^\n]*invalid base64|expected a base64-encoded data url|image was specified using the image\/[a-z]+ media type|unsupported media type for base64 image|invalid data url for image/i;function isProviderImageRejection(errorMessage){return errorMessage!==void 0&&PROVIDER_IMAGE_REJECTION_PATTERN.test(errorMessage)}function rejectedImagePlaceholder(source){return`[Image omitted: the provider rejected this image (${source}) as invalid, so it is no longer sent with the conversation.]`}function field(message,key){return key in message?message[key]:void 0}function contentBlocks2(message){let content=field(message,"content");return Array.isArray(content)?content:[]}function toolCallSource(block){let args=block.arguments;if(typeof args!="object"||args===null)return;let record=args;for(let key of["path","file_path","filePath"]){let value=record[key];if(typeof value=="string"&&value.trim().length>0)return value}}function imageSource(message,toolCallSources){if(message.role!=="toolResult")return"an attached image";let toolCallId=field(message,"toolCallId"),known=typeof toolCallId=="string"?toolCallSources.get(toolCallId):void 0;if(known)return known;let toolName=field(message,"toolName");return typeof toolName=="string"?`${toolName} tool result`:"a tool result"}function scanRejectedImages(messages){let toolCallSources=new Map,rejections=new Map,unconfirmed=[];return messages.forEach((message,messageIndex)=>{if(message.role==="assistant"){for(let block of contentBlocks2(message)){let source=block.type==="toolCall"?toolCallSource(block):void 0;source&&typeof block.id=="string"&&toolCallSources.set(block.id,source)}let stopReason=field(message,"stopReason"),errorMessage=field(message,"errorMessage");stopReason==="error"&&isProviderImageRejection(typeof errorMessage=="string"?errorMessage:void 0)?(unconfirmed.length>0&&rejections.set(messageIndex,unconfirmed),unconfirmed=[]):stopReason!=="error"&&stopReason!=="aborted"&&(unconfirmed=[]);return}message.role!=="user"&&message.role!=="toolResult"||contentBlocks2(message).forEach((block,blockIndex)=>{block.type==="image"&&unconfirmed.push({messageIndex,blockIndex,source:imageSource(message,toolCallSources)})})}),rejections}function rejectedImageSources(messages,failedTurn){let failedIndex=messages.lastIndexOf(failedTurn);return(scanRejectedImages(messages).get(failedIndex)??[]).map(image=>image.source)}function omitProviderRejectedImages(messages){let rejected=new Map;for(let images of scanRejectedImages(messages).values())for(let image of images){let blocks=rejected.get(image.messageIndex)??new Map;blocks.set(image.blockIndex,image.source),rejected.set(image.messageIndex,blocks)}return rejected.size===0?messages:messages.map((message,messageIndex)=>{let blocks=rejected.get(messageIndex);if(!blocks)return message;let content=contentBlocks2(message).map((block,blockIndex)=>{let source=blocks.get(blockIndex);return source===void 0?block:{type:"text",text:rejectedImagePlaceholder(source)}});return{...message,content}})}var COMPACTION_SUMMARY_PREFIX=`The conversation history before this point was compacted into the following summary:
4
4
 
5
5
  <summary>
@@ -16,22 +16,22 @@ ${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,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,lastAssistantIndex=messages.findLastIndex(message=>message.role==="assistant"),images=[];messages.forEach((message,messageIndex)=>{message.role!=="user"&&message.role!=="toolResult"||!Array.isArray(message.content)||message.content.forEach((block,blockIndex)=>{block.type==="image"&&images.push({key:`${messageIndex}:${blockIndex}`,bytes:block.data.length,currentTurn:maxHistoricalImages!==void 0&&messageIndex>lastAssistantIndex})})});let imagesToElide=new Set;if(maxHistoricalImages!==void 0){let historical=images.filter(image=>!image.currentTurn),step=Math.max(1,Math.floor(maxHistoricalImages/2)),excess=historical.length-maxHistoricalImages,cutoff=excess>0?Math.ceil(excess/step)*step:0;for(let image of historical.slice(0,cutoff))imagesToElide.add(image.key)}else{let protectedKeys=new Set(images.slice(Math.max(0,images.length-alwaysKeepNewest)).map(image=>image.key)),total=images.reduce((sum,image)=>sum+image.bytes,0);if(total>budgetBytes){let step=Math.max(1,Math.floor(budgetBytes/2)),threshold=Math.ceil((total-budgetBytes)/step)*step,offset=0,elidedBytes=0,straddler;for(let image of images){let start=offset;offset+=image.bytes,!protectedKeys.has(image.key)&&(offset<=threshold?(imagesToElide.add(image.key),elidedBytes+=image.bytes):start<threshold&&straddler===void 0&&(straddler=image))}straddler!==void 0&&total-elidedBytes>budgetBytes&&imagesToElide.add(straddler.key)}}return imagesToElide.size===0?messages:messages.map((message,messageIndex)=>message.role!=="user"&&message.role!=="toolResult"||!Array.isArray(message.content)||!message.content.some((_block,blockIndex)=>imagesToElide.has(`${messageIndex}:${blockIndex}`))?message:{...message,content:replaceElidedImages(message.content,blockIndex=>imagesToElide.has(`${messageIndex}:${blockIndex}`))})}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 randomUUID4}from"crypto";import{appendFileSync,closeSync,existsSync as existsSync3,mkdirSync as mkdirSync2,openSync,readdirSync,readSync,rmSync as rmSync2,statSync,writeFileSync as writeFileSync2}from"fs";import{appendFile as appendFile2,open as open4,readdir as readdir2,rm as rm3}from"fs/promises";import{basename as basename3,join as join5,resolve as resolve4}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 field3 of["input","output","cacheRead","cacheWrite","totalTokens"])if(!isFiniteNumber(value[field3]))return!1;for(let field3 of["input","output","cacheRead","cacheWrite","total"])if(!isFiniteNumber(value.cost[field3]))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(`
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,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,lastAssistantIndex=messages.findLastIndex(message=>message.role==="assistant"),images=[];messages.forEach((message,messageIndex)=>{message.role!=="user"&&message.role!=="toolResult"||!Array.isArray(message.content)||message.content.forEach((block,blockIndex)=>{block.type==="image"&&images.push({key:`${messageIndex}:${blockIndex}`,bytes:block.data.length,currentTurn:maxHistoricalImages!==void 0&&messageIndex>lastAssistantIndex})})});let imagesToElide=new Set;if(maxHistoricalImages!==void 0){let historical=images.filter(image=>!image.currentTurn),step=Math.max(1,Math.floor(maxHistoricalImages/2)),excess=historical.length-maxHistoricalImages,cutoff=excess>0?Math.ceil(excess/step)*step:0;for(let image of historical.slice(0,cutoff))imagesToElide.add(image.key)}else{let protectedKeys=new Set(images.slice(Math.max(0,images.length-alwaysKeepNewest)).map(image=>image.key)),total=images.reduce((sum,image)=>sum+image.bytes,0);if(total>budgetBytes){let step=Math.max(1,Math.floor(budgetBytes/2)),threshold=Math.ceil((total-budgetBytes)/step)*step,offset=0,elidedBytes=0,straddler;for(let image of images){let start=offset;offset+=image.bytes,!protectedKeys.has(image.key)&&(offset<=threshold?(imagesToElide.add(image.key),elidedBytes+=image.bytes):start<threshold&&straddler===void 0&&(straddler=image))}straddler!==void 0&&total-elidedBytes>budgetBytes&&imagesToElide.add(straddler.key)}}return imagesToElide.size===0?messages:messages.map((message,messageIndex)=>message.role!=="user"&&message.role!=="toolResult"||!Array.isArray(message.content)||!message.content.some((_block,blockIndex)=>imagesToElide.has(`${messageIndex}:${blockIndex}`))?message:{...message,content:replaceElidedImages(message.content,blockIndex=>imagesToElide.has(`${messageIndex}:${blockIndex}`))})}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 randomUUID4}from"crypto";import{appendFileSync,closeSync,existsSync as existsSync3,mkdirSync as mkdirSync2,openSync,readdirSync,readSync,rmSync as rmSync2,statSync,writeFileSync as writeFileSync2}from"fs";import{appendFile as appendFile2,open as open4,readdir as readdir2,rm as rm3}from"fs/promises";import{basename as basename3,join as join5,resolve as resolve4}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 field3 of["input","output","cacheRead","cacheWrite","totalTokens"])if(!isFiniteNumber(value[field3]))return!1;for(let field3 of["input","output","cacheRead","cacheWrite","total"])if(!isFiniteNumber(value.cost[field3]))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"))}var CONFIGURATION_UPDATE_EFFORTS=new Set(["off","minimal","low","medium","high","xhigh","max"]);function hasSafeConfigurationUpdate(message){return typeof message.effort=="string"&&CONFIGURATION_UPDATE_EFFORTS.has(message.effort)&&Array.isArray(message.content)&&message.content.length===0&&isFiniteNumber(message.timestamp)}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"configurationUpdate":if(!hasSafeConfigurationUpdate(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
20
  `):"":"";return{role:"user",content:`${text?`${text}
21
- `:""}[message omitted from retained context: not replay-safe]`,timestamp}})}import{randomUUID}from"node:crypto";var roleOf=entry=>entry.type==="message"?entry.message.role:void 0,partsOf=entry=>{let content=entry.type==="message"?Reflect.get(entry.message,"content"):void 0;return Array.isArray(content)?content:[]};function takeKeys(entry){let role=roleOf(entry);if(role==="assistant"){let parts=partsOf(entry).map(part=>typeof part.runtimeItemKey=="string"?part.runtimeItemKey:void 0);if(!parts.some(key2=>key2!==void 0))return;for(let part of partsOf(entry))typeof part=="object"&&part!==null&&Reflect.deleteProperty(part,"runtimeItemKey");return{parts}}if(role!=="toolResult")return;let key=Reflect.get(entry,"runtimeItemKey"),unknown=Reflect.get(entry,"callUnknown")===!0;return key!==void 0&&Reflect.deleteProperty(entry,"runtimeItemKey"),unknown&&Reflect.deleteProperty(entry,"callUnknown"),unknown?{result:{callUnknown:!0}}:typeof key=="string"?{result:{runtimeItemKey:key}}:void 0}var SessionFileCallKeys=class{constructor(){this.byEntry=new Map}clear(){this.byEntry.clear()}adopt(entries){for(let entry of entries){let keys=takeKeys(entry);keys&&"id"in entry&&this.byEntry.set(entry.id,keys)}}strip(entry){return takeKeys(entry),entry}recordAssistant(entry,owner,bridged=new Map){let prefix=owner??randomUUID(),parts=partsOf(entry).map((part,index)=>part.type==="toolCall"?bridged.get(index)??blockCallKey(prefix,index):void 0);parts.some(key=>key!==void 0)&&this.byEntry.set(entry.id,{parts})}recordResult(entry,leafId,entryOf){let id=entry.message.role==="toolResult"?entry.message.toolCallId:void 0,closed=new Set,assistant;for(let at=entryOf(leafId??"");at&&!assistant;at=at.parentId===null?void 0:entryOf(at.parentId))roleOf(at)==="assistant"?assistant=at:at.type==="message"&&at.message.role==="toolResult"&&closed.add(at.message.toolCallId);let matches=assistant?partsOf(assistant).flatMap((part,index)=>part.type==="toolCall"&&part.id===id?[index]:[]):[],open5=id!==void 0&&matches.length===1&&!closed.has(id),key=assistant&&open5?this.byEntry.get(assistant.id)?.parts?.[matches[0]??-1]:void 0;this.byEntry.set(entry.id,{result:key===void 0?{callUnknown:!0}:{runtimeItemKey:key}})}decorate(entry){let keys="id"in entry?this.byEntry.get(entry.id):void 0;if(!keys||entry.type!=="message")return entry;if(keys.result)return{...entry,...keys.result};let content=partsOf(entry).map((part,index)=>{let key=keys.parts?.[index];return key===void 0?part:{...part,runtimeItemKey:key}});return{...entry,message:{...entry.message,content}}}};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(`
21
+ `:""}[message omitted from retained context: not replay-safe]`,timestamp}})}import{randomUUID}from"node:crypto";var roleOf=entry=>entry.type==="message"?entry.message.role:void 0,partsOf=entry=>{let content=entry.type==="message"?Reflect.get(entry.message,"content"):void 0;return Array.isArray(content)?content:[]};function takeKeys(entry){let role=roleOf(entry);if(role==="assistant"){let parts=partsOf(entry).map(part=>typeof part.runtimeItemKey=="string"?part.runtimeItemKey:void 0);if(!parts.some(key2=>key2!==void 0))return;for(let part of partsOf(entry))typeof part=="object"&&part!==null&&Reflect.deleteProperty(part,"runtimeItemKey");return{parts}}if(role!=="toolResult")return;let key=Reflect.get(entry,"runtimeItemKey"),unknown=Reflect.get(entry,"callUnknown")===!0;return key!==void 0&&Reflect.deleteProperty(entry,"runtimeItemKey"),unknown&&Reflect.deleteProperty(entry,"callUnknown"),unknown?{result:{callUnknown:!0}}:typeof key=="string"?{result:{runtimeItemKey:key}}:void 0}var SessionFileCallKeys=class{constructor(){this.byEntry=new Map}clear(){this.byEntry.clear()}adopt(entries){for(let entry of entries){let keys=takeKeys(entry);keys&&"id"in entry&&this.byEntry.set(entry.id,keys)}}strip(entry){return takeKeys(entry),entry}recordAssistant(entry,owner,bridged=new Map){let prefix=owner??randomUUID(),parts=partsOf(entry).map((part,index)=>part.type==="toolCall"?bridged.get(index)??blockCallKey(prefix,index):void 0);parts.some(key=>key!==void 0)&&this.byEntry.set(entry.id,{parts})}recordResult(entry,leafId,entryOf){let id=entry.message.role==="toolResult"?entry.message.toolCallId:void 0,closed=new Set,assistant;for(let at=entryOf(leafId??"");at&&!assistant;at=at.parentId===null?void 0:entryOf(at.parentId))roleOf(at)==="assistant"?assistant=at:at.type==="message"&&at.message.role==="toolResult"&&closed.add(at.message.toolCallId);let matches=assistant?partsOf(assistant).flatMap((part,index)=>part.type==="toolCall"&&part.id===id?[index]:[]):[],open5=id!==void 0&&matches.length===1&&!closed.has(id),key=assistant&&open5?this.byEntry.get(assistant.id)?.parts?.[matches[0]??-1]:void 0;this.byEntry.set(entry.id,{result:key===void 0?{callUnknown:!0}:{runtimeItemKey:key}})}decorate(entry){let keys="id"in entry?this.byEntry.get(entry.id):void 0;if(!keys||entry.type!=="message")return entry;if(keys.result)return{...entry,...keys.result};let content=partsOf(entry).map((part,index)=>{let key=keys.parts?.[index];return key===void 0?part:{...part,runtimeItemKey:key}});return{...entry,message:{...entry.message,content}}}};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 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(`
22
22
  `,searchFrom);for(;newlineIndex!==-1;){if(!emit(pending.slice(lineStart,newlineIndex)))return{completed:!1,bytes,endsWithNewline:!1};lineStart=newlineIndex+1,newlineIndex=pending.indexOf(`
23
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})}
24
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
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}
26
26
  `)}function isCurrentHeader(line){try{let parsed=JSON.parse(line);return isObject(parsed)&&parsed.version===INDEX_VERSION}catch{return!1}}async function loadIndexFile(path){let entries=new Map,headerSeen=!1,headerBytes=0;try{let read=await readFileLines(path,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(path,entries,endsWithNewline){let prefix=endsWithNewline?"":`
27
- `;for(let entry of entries)await appendFile(path,prefix+entry.line),prefix=""}async function rewriteIndexFile(path,entries){let temp=`${path}.tmp-${process.pid}-${Math.random().toString(36).slice(2)}`;try{await writeFile(temp,HEADER_LINE+entries.map(entry=>entry.line).join("")),await rename(temp,path)}catch(error){throw await rm(temp,{force:!0}).catch(()=>{}),error}}var SESSION_SUMMARY_INDEX_MAX_BYTES=256*1024*1024,snapshots=new Map;function stampsMatch(left2,right){return left2.size===right.size&&left2.mtimeMs===right.mtimeMs}async function statStamp(path){try{let stats=await stat(path);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((left2,right)=>recency(right)-recency(left2)))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(path=>basename(path))),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(left2,right){return left2.size===right.size&&left2.mtimeMs===right.mtimeMs}async function readCachedSessionSummary(filePath,store){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 store?.record(filePath,stamp,cached.summary),{summary:cached.summary,mtime:cached.mtime};let stored=await store?.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}),store?.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,store){let cached=await readCachedSessionSummary(filePath,store);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,store,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,store).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,store,signal){let results=await buildSessionInfosWithConcurrency(files,onLoaded,store,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}var HistoryReductions=class{constructor(source){this.reductions=new WeakMap,this.source=source}reduce(reducer){let generation=this.source.generation(),count=this.source.count(),previous=this.reductions.get(reducer);if(previous!==void 0&&previous.generation===generation&&previous.count<=count){let state=previous.state;if(previous.count===count)return state;let appended=this.source.appendedSince(previous.count);if(appended!==void 0)return this.store(reducer,generation,count,this.fold(reducer,state,appended))}return this.store(reducer,generation,count,this.fold(reducer,reducer.initial(),this.source.readAll()))}fold(reducer,initial,entries){try{let state=initial;for(let entry of entries)state=reducer.add(state,entry);return state}catch(error){throw this.reductions.delete(reducer),error}}store(reducer,generation,count,state){return this.reductions.set(reducer,{generation,count,state}),state}};function planLoadedTail(entries){let byId=new Map,leaf;for(let entry of entries)if(entry.type!=="session"){if(byId.has(entry.id))return;byId.set(entry.id,entry),leaf=entry}let path=leafPath(leaf,byId),compaction=path.find(entry=>entry.type==="compaction");if(compaction===void 0)return;let pathIds=new Set(path.map(entry=>entry.id));if(!pathIds.has(compaction.firstKeptEntryId))return;let firstKeptIndex=entries.findIndex(entry=>entry.type!=="session"&&entry.id===compaction.firstKeptEntryId),firstKept=entries[firstKeptIndex];if(firstKept===void 0||firstKept.type==="session")return;let boundaryParent=firstKept.parentId,window=entries.slice(firstKeptIndex).filter(entry=>entry.type!=="session"),windowIds=new Set(window.map(entry=>entry.id));for(let entry of window)if(entry.parentId!==null&&entry.parentId!==boundaryParent&&!windowIds.has(entry.parentId))return;let header=entries.find(entry=>entry.type==="session"),prefix=entries.slice(0,firstKeptIndex).filter(entry=>entry.type!=="session"&&keepsBeforeWindow(entry,pathIds)),retained=header===void 0?[]:[header],parentId=null;for(let entry of prefix)retained.push({...entry,parentId}),parentId=entry.id;for(let entry of window)retained.push(entry.parentId===boundaryParent?{...entry,parentId}:entry);let retainedIds=new Set([...prefix,...window].map(entry=>entry.id)),trimmedIds=[...byId.keys()].filter(id=>!retainedIds.has(id));return trimmedIds.length===0?void 0:{retained,trimmedIds,windowLength:window.length}}function keepsBeforeWindow(entry,pathIds){return entry.type==="label"||entry.type==="session_info"?!0:entry.type!=="message"&&pathIds.has(entry.id)}function leafPath(leaf,byId){let path=[],visited=new Set,current=leaf;for(;current!==void 0&&!visited.has(current.id);)visited.add(current.id),path.push(current),current=current.parentId===null?void 0:byId.get(current.parentId);return path}var ROLES=new Set(["user","assistant","toolResult","custom"]);function ownedFlowMessage(message){return message&&ROLES.has(message.role)?JSON.parse(JSON.stringify(message)):void 0}function contextMessage({sourceEntry,messages}){let message=messages[0];return(sourceEntry.type==="message"||sourceEntry.type==="custom_message")&&message&&ROLES.has(message.role)?message:void 0}function left(from,to){let kept=new Set(to.map(entry=>entry.sourceEntry.id));return from.filter(entry=>!kept.has(entry.sourceEntry.id)&&contextMessage(entry)).map(entry=>entry.sourceEntry.id)}function compactionFlow(from,to){return{kind:"compaction",removedIds:left(from,to)}}function branchFlow(from,to){let before=new Set(from.map(entry=>entry.sourceEntry.id));return{kind:"branch",removedIds:left(from,to),installed:to.flatMap(entry=>{let message=before.has(entry.sourceEntry.id)?void 0:ownedFlowMessage(contextMessage(entry));return message?[{id:entry.sourceEntry.id,message}]:[]})}}function contextEditFlow(edit,edited){return edit.replacement===null?{kind:"context_edit_removal",targetId:edit.targetId}:edited?{kind:"edit",targetId:edit.targetId,message:edited}:void 0}var TranscriptFile=class{constructor(){this.base=null,this.history=0,this.ready=Promise.resolve(),this.generation=0}reset(){this.generation++,this.base=null,this.history=0,this.identity=void 0,this.unavailable=void 0,this.ready=Promise.resolve()}capture(identity,entries,publish){this.reset();let generation=this.generation,captured=entries?captureTranscriptBase(entries):void 0,contentFingerprint=entries?loadedContentFingerprints.get(entries):void 0;this.ready=identity.then(fileIdentity=>{if(generation===this.generation){if(!fileIdentity||captured&&contentFingerprint===void 0)this.unavailable="transcript_file_identity_unavailable";else if(this.identity=fileIdentity,captured&&contentFingerprint!==void 0){let{count,idFingerprint}=captured;this.base={fileIdentity,count,idFingerprint,contentFingerprint},this.history=captured.history}publish()}})}};var SESSION_RELEASED="session_released",SESSION_MOVED_IN="session_moved_in",SESSION_MOVED="session_moved",SESSION_RECLAIMED="session_reclaimed",WRITABLE={writable:!0},NONE={kind:"none"},REFUSED={kind:"refused"},OWNERSHIP_TYPES=new Set([SESSION_RELEASED,SESSION_MOVED_IN,SESSION_MOVED,SESSION_RECLAIMED]);function isOwnershipEntryType(customType){return customType!==void 0&&OWNERSHIP_TYPES.has(customType)}function field2(data,key){if(typeof data!="object"||data===null)return;let value=data[key];return typeof value=="string"?value:void 0}function requested(entry){let moveId=field2(entry.data,"move_id")??"",target=field2(entry.data,"target")??"";return entry.customType===SESSION_MOVED?{writable:!1,state:"moved",moveId,target}:entry.customType===SESSION_RELEASED&&field2(entry.data,"reason")==="move"?{writable:!1,state:"moving",moveId,target}:WRITABLE}function ownershipStep(current,entry,sessionId){if(entry.type!=="custom"||!isOwnershipEntryType(entry.customType))return NONE;let owner=field2(entry.data,"session_id");if(owner!==void 0&&sessionId!==void 0&&owner!==sessionId)return NONE;let next=requested(entry);if(current.writable)return{kind:"apply",next};if(current.state==="moved")return REFUSED;let sameMove=field2(entry.data,"move_id")===current.moveId,continuesMove=entry.customType===SESSION_MOVED||entry.customType===SESSION_RECLAIMED||entry.customType===SESSION_MOVED_IN;return sameMove&&continuesMove?{kind:"apply",next}:REFUSED}function headerSessionId(entries){let header=entries.find(entry=>entry.type==="session");return typeof header?.id=="string"?header.id:void 0}function sessionOwnership(entries){let sessionId=headerSessionId(entries),verdict=WRITABLE;for(let entry of entries){let step=ownershipStep(verdict,entry,sessionId);step.kind==="apply"&&(verdict=step.next)}return verdict}var SessionMovedAwayError=class extends Error{constructor(sessionFile,ownership){let where=ownership.target===""?"another device":ownership.target;super(ownership.state==="moving"?`This session is being moved to ${where}; it is read-only here. Wait for the move to finish, or make a copy to keep working here. (${sessionFile})`:`This session was moved to ${where}; it is read-only here. Open it on ${where}, or make a copy here. (${sessionFile})`),this.code="session_moved_away",this.name="SessionMovedAwayError",this.ownership=ownership}};var SessionWriteGuard=class{constructor(){this.seen=0,this.verdict={writable:!0}}assertWritable(entries,entry,sessionFile){let ownership=this.ownership(entries);if(!ownership.writable&&ownershipStep(ownership,entry,this.sessionId).kind!=="apply")throw new SessionMovedAwayError(sessionFile,ownership)}assertRewritable(entries,sessionFile){let ownership=this.ownership(entries);if(!ownership.writable)throw new SessionMovedAwayError(sessionFile,ownership)}isWritable(entries){return this.ownership(entries).writable}ownership(entries){for((entries!==this.source||entries.length<this.seen)&&(this.source=entries,this.seen=0,this.sessionId=headerSessionId(entries),this.verdict={writable:!0});this.seen<entries.length;this.seen+=1){let entry=entries[this.seen];if(entry===void 0)continue;let step=ownershipStep(this.verdict,entry,this.sessionId);step.kind==="apply"&&(this.verdict=step.next)}return this.verdict}};import{createHash as createHash2}from"node:crypto";import{existsSync as existsSync2,mkdirSync,readFileSync,renameSync,rmSync,writeFileSync}from"node:fs";import{join as join3}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{rmSync(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"&&current!==null&&this._mutateStringsInPlace(current,seen,mutate)}}externalizeString(text){if(text.length<RESIDENT_STRING_MIN_BYTES||text.startsWith(RESIDENT_STRING_PREFIX))return text;let id=createHash2("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=join3(dir,`${id}.blob`),temp=`${final}.tmp`;try{mkdirSync(dir,{recursive:!0}),existsSync2(final)||(writeFileSync(temp,JSON.stringify({v:1,text}),"utf8"),renameSync(temp,final))}catch{try{rmSync(temp,{force:!0})}catch{}return!1}return this.accounting.evicted(text),!0}_readBlob(id){let dir=this.blobsDir?.();if(!dir)return;let file=join3(dir,`${id}.blob`);try{let parsed=JSON.parse(readFileSync(file,"utf8"));if(typeof parsed.text=="string")return parsed.text}catch{}try{rmSync(file,{force:!0})}catch{}}};import{randomUUID as randomUUID3}from"node:crypto";import{open as open3,rename as rename3,rm as rm2,stat as stat4}from"node:fs/promises";import{basename as basename2,dirname,join as join4,resolve as resolve3}from"node:path";import{createHash as createHash3,randomUUID as randomUUID2}from"node:crypto";import{open as open2,readFile,rename as rename2,stat as stat3,unlink}from"node:fs/promises";import{resolve as resolve2}from"node:path";import{isDeepStrictEqual}from"node:util";var jsonlFiles={async stat(path){let value=await stat3(path);return{size:value.size,mtimeMs:value.mtimeMs,ctimeMs:value.ctimeMs}},async read(path,start,end){let file=await open2(path,"r");try{let bytes=Buffer.alloc(end-start),read=0;for(;read<bytes.length;){let{bytesRead}=await file.read(bytes,read,bytes.length-read,start+read);if(bytesRead===0)break;read+=bytesRead}return bytes.subarray(0,read)}finally{await file.close()}},async marker(path){try{let value=JSON.parse(await readFile(`${path}.k9f2`,"utf8"));return typeof value=="object"&&value!==null&&"size"in value&&typeof value.size=="number"&&"mtimeMs"in value&&typeof value.mtimeMs=="number"?{size:value.size,mtimeMs:value.mtimeMs}:void 0}catch(error){if(error instanceof SyntaxError||error.code==="ENOENT")return;throw error}}};var SESSION="session-import/session/",ENTRY="session-import/entry/",LEDGER="session-import/file/",sessionKey=id=>SESSION+encodeURIComponent(id),entryKey=(sessionId,id)=>`${ENTRY}${encodeURIComponent(sessionId)}/${encodeURIComponent(id)}`,ledgerKey=path=>LEDGER+path,hash=bytes=>createHash3("sha256").update(bytes).digest("hex").slice(0,32),sameStamp=(a,b)=>a.size===b.size&&a.mtimeMs===b.mtimeMs&&a.ctimeMs===b.ctimeMs,isObject2=value=>typeof value=="object"&&value!==null&&!Array.isArray(value);function migrateV1(values){let previous=null,ordinal=0;for(let value of values){if(!isObject2(value))continue;let entry=value;if(entry.type==="session"){entry.version=2;continue}let id=`legacy-${ordinal++}`;if(entry.id=id,entry.parentId=previous,previous=id,entry.type==="compaction"&&typeof entry.firstKeptEntryIndex=="number"){let target=values[entry.firstKeptEntryIndex];isObject2(target)&&target.type!=="session"&&typeof target.id=="string"&&(entry.firstKeptEntryId=target.id),delete entry.firstKeptEntryIndex}}}function parse(bytes){let lines=[],offset=0;for(let end=0;end<=bytes.length;end++){if(end!==bytes.length&&bytes[end]!==10)continue;let raw=Buffer.from(bytes.subarray(offset,end)).toString("utf8"),value;try{value=JSON.parse(raw)}catch{offset=end+1;continue}value&&lines.push({value,raw,offset,end}),offset=end+1}let values=lines.map(line=>line.value),first=values[0];if(!isObject2(first)||first.type!=="session"||typeof first.id!="string")throw new Error("JSONL session has no header");let version=Number(first.version??1);version<2&&migrateV1(values),version<3&&migrateSessionEntries(values);let stored=(value,raw)=>version<3?JSON.stringify(value):raw,[headerLine,...entryLines]=lines,header={...headerLine,value:first,key:first.id,stored:stored(first,headerLine.raw)},keys=new Set,entries=entryLines.map((line,index)=>{if(isObject2(line.value)&&line.value.type==="session")throw new Error("Duplicate JSONL session entry");let id=isObject2(line.value)&&typeof line.value.id=="string"?line.value.id:void 0,key=id===void 0?`~line-${index}`:id.startsWith("~")?`~${id}`:id;if(keys.has(key))throw new Error("Duplicate JSONL session entry");return keys.add(key),{...line,key,stored:stored(line.value,line.raw)}});return{header,entries}}var highWaterMark=record=>({id:record.key,hash:hash(record.raw),offset:record.offset,end:record.end});function createJsonlImporter(options){let{store,epoch,admission}=options,files=options.files??jsonlFiles,now=options.now??Date.now,tick=options.mtimeTickMs??1,manifest=async id=>await store.getDocument(sessionKey(id)),ledger=async path=>await store.getDocument(ledgerKey(path)),heldEntries=async held=>Promise.all(held.entryIds.map(async id=>{let raw=await store.getDocument(entryKey(held.id,id));if(typeof raw!="string")throw new Error(`Missing imported session entry ${id}`);return JSON.parse(raw)})),commit=writes=>store.commit(epoch,writes,()=>{}),importFile=async path=>{let stamp=await files.stat(path),previous=await ledger(path);if(previous&&stamp.size===previous.size){let uncertain=Math.abs(previous.checkedAt-previous.mtimeMs)<=tick,sameMtime=stamp.mtimeMs===previous.mtimeMs,sameHighWater=!0;if(!sameMtime||uncertain){let hwm=previous.highWaterMark;sameHighWater=hash(await files.read(path,hwm.offset,hwm.end))===hwm.hash}if(sameMtime&&sameHighWater&&stamp.ctimeMs===previous.ctimeMs)return uncertain&&await commit([{op:"put",key:ledgerKey(path),data:{...previous,checkedAt:now()}}]),{outcome:"unchanged",sessionId:previous.sessionId,imported:0}}let bytes=await files.read(path,0,stamp.size),marker=await files.marker(path);if(bytes.length!==stamp.size||!sameStamp(stamp,await files.stat(path)))throw new Error("JSONL session changed during import; reopen it to import the next snapshot");let{header,entries}=parse(bytes),sourceSessionId=header.value.id,target=previous?.sourceSessionId===sourceSessionId?previous.sessionId:sourceSessionId,held=await manifest(target),oldEntries=held?await heldEntries(held):[],cursor=0;for(let record of entries)isDeepStrictEqual(record.value,oldEntries[cursor])&&cursor++;let extendsHeld=cursor===oldEntries.length,writerKind=marker?.size===stamp.size&&marker.mtimeMs===stamp.mtimeMs?"hatch":"other",fork=held!==void 0&&!extendsHeld&&writerKind==="hatch",sessionId=fork?store.mintId():target,divergence=fork?{kind:"k9f2",parentSessionId:target,note:"Imported a developer-hatch history that diverged from its original session."}:held?.divergence??null,next={id:sessionId,header:{...header.value,id:sessionId},entryIds:entries.map(record=>record.key),divergence},nextLedger={...stamp,path,sourceSessionId,sessionId,highWaterMark:highWaterMark(entries.at(-1)??header),writerKind,checkedAt:now()},writes=[],oldByKey=new Map(held?.entryIds.map((key,index)=>[key,oldEntries[index]])),nextIds=new Set(next.entryIds);if(held&&!fork)for(let id of held.entryIds)nextIds.has(id)||writes.push({op:"delete",key:entryKey(sessionId,id)});let imported=0;for(let record of entries)!fork&&isDeepStrictEqual(record.value,oldByKey.get(record.key))||(writes.push({op:"put",key:entryKey(sessionId,record.key),data:record.stored}),imported++);return writes.push({op:"put",key:sessionKey(sessionId),data:next},{op:"put",key:ledgerKey(path),data:nextLedger}),await commit(writes),{outcome:held?fork?"forked":extendsHeld?"extended":"adopted":"imported",sessionId,imported}};return{open:paths=>admission.admit(async()=>{let results=[];for(let path of paths)results.push(await importFile(resolve2(path)));return results}),importFile:path=>admission.admit(()=>importFile(resolve2(path))),getLedger:path=>ledger(resolve2(path)),getSession:id=>admission.admit(async()=>{let held=await manifest(id);if(held)return{id:held.id,header:held.header,entries:await heldEntries(held),divergence:held.divergence??void 0}}),async recordProjectedTail(path,sessionId,tail,written){path=resolve2(path);let end=tail.offset+Buffer.byteLength(tail.line);if(written.size!==end+1)throw new Error("Projection size does not match its written image");let record={...written,path,sourceSessionId:sessionId,sessionId,highWaterMark:{id:tail.key,hash:hash(tail.line),offset:tail.offset,end},writerKind:"store",checkedAt:now()};await commit([{op:"put",key:ledgerKey(path),data:record}])},async recordProjection(path,contents,written){path=resolve2(path);let bytes=Buffer.from(contents);if(bytes.length!==written.size)throw new Error("Projection size does not match its written image");let{header,entries}=parse(bytes),held=await manifest(header.value.id);if(!held||!isDeepStrictEqual(await heldEntries(held),entries.map(record2=>record2.value)))throw new Error("Projection does not match the committed session");let record={...written,path,sourceSessionId:header.value.id,sessionId:held.id,highWaterMark:highWaterMark(entries.at(-1)??header),writerKind:"store",checkedAt:now()};await commit([{op:"put",key:ledgerKey(path),data:record}])}}}var storeKeyOf=entryId=>entryId.startsWith("~")?`~${entryId}`:entryId,STALE="session-store/projection-stale/",staleKey=path=>STALE+encodeURIComponent(path),codeOf=error=>error instanceof Error&&"code"in error&&typeof error.code=="string"?error.code:"unknown",messageOf=error=>error instanceof Error?error.message:String(error);function projectionImage(header,entries){return[JSON.stringify(header),...entries.map(entry=>entry.line)].map(line=>`${line}
28
- `).join("")}async function stampOf(path){try{let value=await stat4(path);return{size:value.size,mtimeMs:value.mtimeMs,ctimeMs:value.ctimeMs}}catch(error){if(codeOf(error)==="ENOENT")return;throw error}}async function replaceAtomically(path,contents){let mode=await modeOf(path)??384,temp=join4(dirname(path),`.${basename2(path)}.${randomUUID3()}.tmp`),handle=await open3(temp,"wx",mode),identity;try{await handle.writeFile(contents),await handle.sync(),identity=await captureFileIdentity(handle.fd,path)}finally{await handle.close()}try{await rename3(temp,path)}catch(error){throw await rm2(temp,{force:!0}),error}return identity}async function modeOf(path){try{return(await stat4(path)).mode&511}catch(error){if(codeOf(error)==="ENOENT")return;throw error}}var isRecord2=value=>typeof value=="object"&&value!==null&&!Array.isArray(value),staleSessionIdOf=mark=>isRecord2(mark)&&typeof mark.sessionId=="string"?mark.sessionId:void 0;async function replaceWith(files,path,contents){if(files===void 0)return replaceAtomically(path,contents);await files.replace(path,contents)}var DurableSessionBinding=class _DurableSessionBinding{constructor(binding,handle,importer,admission,warn,hooks,projectedSize){this.stale=!1,this.generation=0,this.binding=binding,this.handle=handle,this.importer=importer,this.admission=admission,this.warn=warn,this.hooks=hooks,this.projectedSize=projectedSize}static async open(binding,sessionFile,sessionId,headerLine,warn,hooks){let{store,epoch}=binding,path=resolve3(sessionFile),admission=createAdmissionLine(),importer=createJsonlImporter({store,epoch,admission}),id=sessionId,reprojected=!1;if(await stampOf(path)!==void 0){let mark=await store.getDocument(staleKey(path)),markedId=staleSessionIdOf(mark);if(markedId!==void 0){let stored=await openSessionStore(store,epoch).load(markedId);if(stored===void 0)throw new Error(`the store marks ${path} stale but holds no session ${markedId}`);await reprojectFile(importer,admission,binding,hooks,path,projectionImage(stored.header,stored.entries)),id=markedId,reprojected=!0}else id=(await importer.importFile(path)).sessionId}let handle=await openSyncSessionStore(store,epoch).open(id,JSON.parse(headerLine)),size=(await stampOf(path))?.size??0;return{session:new _DurableSessionBinding(binding,handle,importer,admission,warn,hooks,size),reprojected}}commitAppend(entries){this.handle.appendSync(entries),this.generation++}commitRewrite(headerLine,entries){this.handle.rewriteSync(JSON.parse(headerLine),entries),this.generation++}projectionStale(){return this.stale}projected(sessionFile,entry){let path=resolve3(sessionFile),offset=this.projectedSize;this.projectedSize+=Buffer.byteLength(entry.line)+1;let sessionId=String(this.handle.header().id);this.record(path,async()=>{let written=await stampOf(path);written!==void 0&&await this.importer.recordProjectedTail(path,sessionId,{...entry,offset},written)})}recordWhole(sessionFile){let path=resolve3(sessionFile),contents=projectionImage(this.handle.header(),this.handle.entries());this.projectedSize=Buffer.byteLength(contents),this.record(path,async()=>{let written=await stampOf(path);written!==void 0&&await this.importer.recordProjection(path,contents,written)})}projectionFailed(sessionFile,error){let path=resolve3(sessionFile),unmarked="";if(!this.stale){try{let data={sessionId:String(this.handle.header().id)};this.binding.store.commitSync(this.binding.epoch,[{op:"put",key:staleKey(path),data}],()=>{})}catch(markError){unmarked=`; the stale mark was not stored (${messageOf(markError)})`}this.stale=!0}this.warn({path,code:codeOf(error),message:`${messageOf(error)}${unmarked}`})}markProjectionStale(sessionFile){let path=resolve3(sessionFile);if(!this.stale){let data={sessionId:String(this.handle.header().id)};this.binding.store.commitSync(this.binding.epoch,[{op:"put",key:staleKey(path),data}],()=>{}),this.stale=!0}this.scheduleRepair(path)}settled(){return this.admission.admit(async()=>{})}scheduleRepair(sessionFile){let path=resolve3(sessionFile);this.admission.admit(async()=>{if(!this.stale)return;let generation=this.generation,contents=projectionImage(this.handle.header(),this.handle.entries());if(this.hooks.beforeWrite(path),this.hooks.afterReplace(path,await replaceWith(this.binding.files,path,contents)),generation!==this.generation)return this.scheduleRepair(path);this.binding.store.commitSync(this.binding.epoch,[{op:"delete",key:staleKey(path)}],()=>{}),this.stale=!1,this.projectedSize=Buffer.byteLength(contents);let written=await stampOf(path);written!==void 0&&generation===this.generation&&await this.importer.recordProjection(path,contents,written)}).catch(error=>this.projectionFailed(path,error))}record(path,write){let generation=this.generation;this.admission.admit(async()=>{generation===this.generation&&await write()}).catch(error=>{generation===this.generation&&this.warn({path,code:codeOf(error),message:`projection ledger not recorded: ${messageOf(error)}`})})}};async function reprojectFile(importer,admission,binding,hooks,path,contents){hooks.beforeWrite(path),hooks.afterReplace(path,await replaceWith(binding.files,path,contents));let written=await stampOf(path);written!==void 0&&await admission.admit(()=>importer.recordProjection(path,contents,written)),binding.store.commitSync(binding.epoch,[{op:"delete",key:staleKey(path)}],()=>{})}var reserve;function reserveSessionWrite(path){reserve?.(path)}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(path,self){for(let ref of liveWriters){let owner=ref.deref();if(!owner){liveWriters.delete(ref);continue}if(owner!==self&&owner.isPersisted()&&owner.getSessionFile()===path)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}function emptyUsageTotals(){return{input:0,output:0,cacheRead:0,cacheWrite:0,cost:0,latestCacheHitRate:void 0}}var CURRENT_SESSION_VERSION=3;function createSessionId(){return uuidv7()}var SESSION_FILE_NAME=/^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}-\d{3}Z_(.+)\.jsonl$/;function sessionFileNameId(path){let id=SESSION_FILE_NAME.exec(basename3(path))?.[1];if(id!==void 0)try{return assertValidSessionId(id),id}catch{return}}function withFileNameId(path,options){if(options?.id!==void 0)return options;let id=sessionFileNameId(path);return id===void 0?options:{...options,id}}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=randomUUID4().slice(0,8);if(!byId.has(id))return id}return randomUUID4()}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(`
27
+ `;for(let entry of entries)await appendFile(path,prefix+entry.line),prefix=""}async function rewriteIndexFile(path,entries){let temp=`${path}.tmp-${process.pid}-${Math.random().toString(36).slice(2)}`;try{await writeFile(temp,HEADER_LINE+entries.map(entry=>entry.line).join("")),await rename(temp,path)}catch(error){throw await rm(temp,{force:!0}).catch(()=>{}),error}}var SESSION_SUMMARY_INDEX_MAX_BYTES=256*1024*1024,snapshots=new Map;function stampsMatch(left2,right){return left2.size===right.size&&left2.mtimeMs===right.mtimeMs}async function statStamp(path){try{let stats=await stat(path);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((left2,right)=>recency(right)-recency(left2)))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(path=>basename(path))),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(left2,right){return left2.size===right.size&&left2.mtimeMs===right.mtimeMs}async function readCachedSessionSummary(filePath,store){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 store?.record(filePath,stamp,cached.summary),{summary:cached.summary,mtime:cached.mtime};let stored=await store?.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}),store?.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,store){let cached=await readCachedSessionSummary(filePath,store);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,store,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,store).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,store,signal){let results=await buildSessionInfosWithConcurrency(files,onLoaded,store,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}var HistoryReductions=class{constructor(source){this.reductions=new WeakMap,this.source=source}reduce(reducer){let generation=this.source.generation(),count=this.source.count(),previous=this.reductions.get(reducer);if(previous!==void 0&&previous.generation===generation&&previous.count<=count){let state=previous.state;if(previous.count===count)return state;let appended=this.source.appendedSince(previous.count);if(appended!==void 0)return this.store(reducer,generation,count,this.fold(reducer,state,appended))}return this.store(reducer,generation,count,this.fold(reducer,reducer.initial(),this.source.readAll()))}fold(reducer,initial,entries){try{let state=initial;for(let entry of entries)state=reducer.add(state,entry);return state}catch(error){throw this.reductions.delete(reducer),error}}store(reducer,generation,count,state){return this.reductions.set(reducer,{generation,count,state}),state}};function planLoadedTail(entries){let byId=new Map,leaf;for(let entry of entries)if(entry.type!=="session"){if(byId.has(entry.id))return;byId.set(entry.id,entry),leaf=entry}let path=leafPath(leaf,byId),compaction=path.find(entry=>entry.type==="compaction");if(compaction===void 0)return;let pathIds=new Set(path.map(entry=>entry.id));if(!pathIds.has(compaction.firstKeptEntryId))return;let firstKeptIndex=entries.findIndex(entry=>entry.type!=="session"&&entry.id===compaction.firstKeptEntryId),firstKept=entries[firstKeptIndex];if(firstKept===void 0||firstKept.type==="session")return;let boundaryParent=firstKept.parentId,window=entries.slice(firstKeptIndex).filter(entry=>entry.type!=="session"),windowIds=new Set(window.map(entry=>entry.id));for(let entry of window)if(entry.parentId!==null&&entry.parentId!==boundaryParent&&!windowIds.has(entry.parentId))return;let header=entries.find(entry=>entry.type==="session"),prefix=entries.slice(0,firstKeptIndex).filter(entry=>entry.type!=="session"&&keepsBeforeWindow(entry,pathIds)),retained=header===void 0?[]:[header],parentId=null;for(let entry of prefix)retained.push({...entry,parentId}),parentId=entry.id;for(let entry of window)retained.push(entry.parentId===boundaryParent?{...entry,parentId}:entry);let retainedIds=new Set([...prefix,...window].map(entry=>entry.id)),trimmedIds=[...byId.keys()].filter(id=>!retainedIds.has(id));return trimmedIds.length===0?void 0:{retained,trimmedIds,windowLength:window.length}}function keepsBeforeWindow(entry,pathIds){return entry.type==="label"||entry.type==="session_info"?!0:entry.type!=="message"&&pathIds.has(entry.id)}function leafPath(leaf,byId){let path=[],visited=new Set,current=leaf;for(;current!==void 0&&!visited.has(current.id);)visited.add(current.id),path.push(current),current=current.parentId===null?void 0:byId.get(current.parentId);return path}var ROLES=new Set(["user","assistant","toolResult","custom"]);function ownedFlowMessage(message){return message&&ROLES.has(message.role)?JSON.parse(JSON.stringify(message)):void 0}function contextMessage({sourceEntry,messages}){let message=messages[0];return(sourceEntry.type==="message"||sourceEntry.type==="custom_message")&&message&&ROLES.has(message.role)?message:void 0}function left(from,to){let kept=new Set(to.map(entry=>entry.sourceEntry.id));return from.filter(entry=>!kept.has(entry.sourceEntry.id)&&contextMessage(entry)).map(entry=>entry.sourceEntry.id)}function compactionFlow(from,to){return{kind:"compaction",removedIds:left(from,to)}}function branchFlow(from,to){let before=new Set(from.map(entry=>entry.sourceEntry.id));return{kind:"branch",removedIds:left(from,to),installed:to.flatMap(entry=>{let message=before.has(entry.sourceEntry.id)?void 0:ownedFlowMessage(contextMessage(entry));return message?[{id:entry.sourceEntry.id,message}]:[]})}}function contextEditFlow(edit,edited){return edit.replacement===null?{kind:"context_edit_removal",targetId:edit.targetId}:edited?{kind:"edit",targetId:edit.targetId,message:edited}:void 0}var TranscriptFile=class{constructor(){this.base=null,this.history=0,this.ready=Promise.resolve(),this.generation=0}reset(){this.generation++,this.base=null,this.history=0,this.identity=void 0,this.unavailable=void 0,this.ready=Promise.resolve()}capture(identity,entries,publish){this.reset();let generation=this.generation,captured=entries?captureTranscriptBase(entries):void 0,contentFingerprint=entries?loadedContentFingerprints.get(entries):void 0;this.ready=identity.then(fileIdentity=>{if(generation===this.generation){if(!fileIdentity||captured&&contentFingerprint===void 0)this.unavailable="transcript_file_identity_unavailable";else if(this.identity=fileIdentity,captured&&contentFingerprint!==void 0){let{count,idFingerprint}=captured;this.base={fileIdentity,count,idFingerprint,contentFingerprint},this.history=captured.history}publish()}})}};var SESSION_RELEASED="session_released",SESSION_MOVED_IN="session_moved_in",SESSION_MOVED="session_moved",SESSION_RECLAIMED="session_reclaimed",WRITABLE={writable:!0},NONE={kind:"none"},REFUSED={kind:"refused"},OWNERSHIP_TYPES=new Set([SESSION_RELEASED,SESSION_MOVED_IN,SESSION_MOVED,SESSION_RECLAIMED]);function isOwnershipEntryType(customType){return customType!==void 0&&OWNERSHIP_TYPES.has(customType)}function field2(data,key){if(typeof data!="object"||data===null)return;let value=data[key];return typeof value=="string"?value:void 0}function requested(entry){let moveId=field2(entry.data,"move_id")??"",target=field2(entry.data,"target")??"";return entry.customType===SESSION_MOVED?{writable:!1,state:"moved",moveId,target}:entry.customType===SESSION_RELEASED&&field2(entry.data,"reason")==="move"?{writable:!1,state:"moving",moveId,target}:WRITABLE}function ownershipStep(current,entry,sessionId){if(entry.type!=="custom"||!isOwnershipEntryType(entry.customType))return NONE;let owner=field2(entry.data,"session_id");if(owner!==void 0&&sessionId!==void 0&&owner!==sessionId)return NONE;let next=requested(entry);if(current.writable)return{kind:"apply",next};if(current.state==="moved")return REFUSED;let sameMove=field2(entry.data,"move_id")===current.moveId,continuesMove=entry.customType===SESSION_MOVED||entry.customType===SESSION_RECLAIMED||entry.customType===SESSION_MOVED_IN;return sameMove&&continuesMove?{kind:"apply",next}:REFUSED}function headerSessionId(entries){let header=entries.find(entry=>entry.type==="session");return typeof header?.id=="string"?header.id:void 0}function sessionOwnership(entries){let sessionId=headerSessionId(entries),verdict=WRITABLE;for(let entry of entries){let step=ownershipStep(verdict,entry,sessionId);step.kind==="apply"&&(verdict=step.next)}return verdict}var SessionMovedAwayError=class extends Error{constructor(sessionFile,ownership){let where=ownership.target===""?"another device":ownership.target;super(ownership.state==="moving"?`This session is being moved to ${where}; it is read-only here. Wait for the move to finish, or make a copy to keep working here. (${sessionFile})`:`This session was moved to ${where}; it is read-only here. Open it on ${where}, or make a copy here. (${sessionFile})`),this.code="session_moved_away",this.name="SessionMovedAwayError",this.ownership=ownership}};var SessionWriteGuard=class{constructor(){this.seen=0,this.verdict={writable:!0}}assertWritable(entries,entry,sessionFile){let ownership=this.ownership(entries);if(!ownership.writable&&ownershipStep(ownership,entry,this.sessionId).kind!=="apply")throw new SessionMovedAwayError(sessionFile,ownership)}assertRewritable(entries,sessionFile){let ownership=this.ownership(entries);if(!ownership.writable)throw new SessionMovedAwayError(sessionFile,ownership)}isWritable(entries){return this.ownership(entries).writable}ownership(entries){for((entries!==this.source||entries.length<this.seen)&&(this.source=entries,this.seen=0,this.sessionId=headerSessionId(entries),this.verdict={writable:!0});this.seen<entries.length;this.seen+=1){let entry=entries[this.seen];if(entry===void 0)continue;let step=ownershipStep(this.verdict,entry,this.sessionId);step.kind==="apply"&&(this.verdict=step.next)}return this.verdict}};import{createHash as createHash2}from"node:crypto";import{existsSync as existsSync2,mkdirSync,readFileSync,renameSync,rmSync,writeFileSync}from"node:fs";import{join as join3}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{rmSync(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"&&current!==null&&this._mutateStringsInPlace(current,seen,mutate)}}externalizeString(text){if(text.length<RESIDENT_STRING_MIN_BYTES||text.startsWith(RESIDENT_STRING_PREFIX))return text;let id=createHash2("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=join3(dir,`${id}.blob`),temp=`${final}.tmp`;try{mkdirSync(dir,{recursive:!0}),existsSync2(final)||(writeFileSync(temp,JSON.stringify({v:1,text}),"utf8"),renameSync(temp,final))}catch{try{rmSync(temp,{force:!0})}catch{}return!1}return this.accounting.evicted(text),!0}_readBlob(id){let dir=this.blobsDir?.();if(!dir)return;let file=join3(dir,`${id}.blob`);try{let parsed=JSON.parse(readFileSync(file,"utf8"));if(typeof parsed.text=="string")return parsed.text}catch{}try{rmSync(file,{force:!0})}catch{}}};import{randomUUID as randomUUID3}from"node:crypto";import{open as open3,rename as rename3,rm as rm2,stat as stat4}from"node:fs/promises";import{basename as basename2,dirname,join as join4,resolve as resolve3}from"node:path";import{createHash as createHash3,randomUUID as randomUUID2}from"node:crypto";import{open as open2,readFile,rename as rename2,stat as stat3,unlink}from"node:fs/promises";import{resolve as resolve2}from"node:path";import{isDeepStrictEqual}from"node:util";var PREFIX_DOMAIN="senpi-jsonl-prefix/1",chainLine=(previous,raw)=>createHash3("sha256").update(previous).update("\0").update(raw).digest("hex"),chainOf=raws=>{let digests=[],digest=createHash3("sha256").update(PREFIX_DOMAIN).digest("hex");for(let raw of raws)digest=chainLine(digest,raw),digests.push(digest);return digests},isStoreRecord=value=>typeof value=="object"&&value!==null&&!Array.isArray(value);function divergenceOf(value){return isStoreRecord(value)&&value.kind==="k9f2"&&typeof value.parentSessionId=="string"&&typeof value.note=="string"?{kind:"k9f2",parentSessionId:value.parentSessionId,note:value.note}:null}var jsonlFiles={async stat(path){let value=await stat3(path);return{size:value.size,mtimeMs:value.mtimeMs,ctimeMs:value.ctimeMs}},async read(path,start,end){let file=await open2(path,"r");try{let bytes=Buffer.alloc(end-start),read=0;for(;read<bytes.length;){let{bytesRead}=await file.read(bytes,read,bytes.length-read,start+read);if(bytesRead===0)break;read+=bytesRead}return bytes.subarray(0,read)}finally{await file.close()}},async marker(path){try{let value=JSON.parse(await readFile(`${path}.k9f2`,"utf8"));return typeof value=="object"&&value!==null&&"size"in value&&typeof value.size=="number"&&"mtimeMs"in value&&typeof value.mtimeMs=="number"?{size:value.size,mtimeMs:value.mtimeMs}:void 0}catch(error){if(error instanceof SyntaxError||error.code==="ENOENT")return;throw error}}};var LEDGER="session-import/file/",ledgerKey=path=>LEDGER+path,hash=bytes=>createHash3("sha256").update(bytes).digest("hex").slice(0,32),sameStamp=(a,b)=>a.size===b.size&&a.mtimeMs===b.mtimeMs&&a.ctimeMs===b.ctimeMs,isObject2=value=>typeof value=="object"&&value!==null&&!Array.isArray(value);function migrateV1(values){let previous=null,ordinal=0;for(let value of values){if(!isObject2(value))continue;let entry=value;if(entry.type==="session"){entry.version=2;continue}let id=`legacy-${ordinal++}`;if(entry.id=id,entry.parentId=previous,previous=id,entry.type==="compaction"&&typeof entry.firstKeptEntryIndex=="number"){let target=values[entry.firstKeptEntryIndex];isObject2(target)&&target.type!=="session"&&typeof target.id=="string"&&(entry.firstKeptEntryId=target.id),delete entry.firstKeptEntryIndex}}}function parse(bytes){let lines=[],offset=0;for(let end=0;end<=bytes.length;end++){if(end!==bytes.length&&bytes[end]!==10)continue;let raw=Buffer.from(bytes.subarray(offset,end)).toString("utf8"),value;try{value=JSON.parse(raw)}catch{offset=end+1;continue}value&&lines.push({value,raw,offset,end}),offset=end+1}let values=lines.map(line=>line.value),first=values[0];if(!isObject2(first)||first.type!=="session"||typeof first.id!="string")throw new Error("JSONL session has no header");let version=Number(first.version??1);version<2&&migrateV1(values),version<3&&migrateSessionEntries(values);let stored=(value,raw)=>version<3?JSON.stringify(value):raw,[headerLine,...entryLines]=lines,header={...headerLine,value:first,key:first.id,stored:stored(first,headerLine.raw)},keys=new Set,entries=entryLines.map((line,index)=>{if(isObject2(line.value)&&line.value.type==="session")throw new Error("Duplicate JSONL session entry");let id=isObject2(line.value)&&typeof line.value.id=="string"?line.value.id:void 0,key=id===void 0?`~line-${index}`:id.startsWith("~")?`~${id}`:id;if(keys.has(key))throw new Error("Duplicate JSONL session entry");return keys.add(key),{...line,key,stored:stored(line.value,line.raw)}});return{header,entries}}var highWaterMark=record=>({id:record.key,hash:hash(record.raw),offset:record.offset,end:record.end});function createJsonlImporter(options){let{store,epoch,admission}=options,files=options.files??jsonlFiles,now=options.now??Date.now,tick=options.mtimeTickMs??1,manifest=id=>readSessionState(store,id),ledger=async path=>await store.getDocument(ledgerKey(path)),heldEntries=held=>held.entries.map(entry=>JSON.parse(entry.line)),commit=writes=>store.commit(epoch,writes,()=>{}),importFile=async path=>{let stamp=await files.stat(path),previous=await ledger(path);if(previous&&stamp.size===previous.size){let uncertain=Math.abs(previous.checkedAt-previous.mtimeMs)<=tick,sameMtime=stamp.mtimeMs===previous.mtimeMs,sameHighWater=!0;if(!sameMtime||uncertain){let hwm=previous.highWaterMark;sameHighWater=hash(await files.read(path,hwm.offset,hwm.end))===hwm.hash}if(sameMtime&&sameHighWater&&stamp.ctimeMs===previous.ctimeMs)return uncertain&&await commit([{op:"put",key:ledgerKey(path),data:{...previous,checkedAt:now()}}]),{outcome:"unchanged",sessionId:previous.sessionId,imported:0}}let bytes=await files.read(path,0,stamp.size),marker=await files.marker(path);if(bytes.length!==stamp.size||!sameStamp(stamp,await files.stat(path)))throw new Error("JSONL session changed during import; reopen it to import the next snapshot");let{header,entries}=parse(bytes),sourceSessionId=header.value.id,target=previous?.sourceSessionId===sourceSessionId?previous.sessionId:sourceSessionId,held=await manifest(target),lines=[header,...entries],digests=chainOf(lines.map(line=>line.raw)),markIndex=held!==void 0&&previous?.sessionId===target&&previous.prefixDigest!==void 0?lines.findIndex((line,index)=>line.key===previous.highWaterMark.id&&digests[index]===previous.prefixDigest):-1;if(held!==void 0&&markIndex>=0){let heldKeys=new Set(held.entries.map(entry=>entry.key)),fresh=entries.slice(markIndex).filter(record=>!heldKeys.has(record.key)),grown={...stamp,path,sourceSessionId,sessionId:target,highWaterMark:highWaterMark(lines.at(-1)??header),prefixDigest:digests.at(-1),writerKind:marker?.size===stamp.size&&marker.mtimeMs===stamp.mtimeMs?"hatch":"other",checkedAt:now()};return await commit([...appendRecordWrites(target,held.rewrites,fresh.map(record=>({key:record.key,line:record.stored}))),{op:"put",key:ledgerKey(path),data:grown}]),{outcome:"extended",sessionId:target,imported:fresh.length}}let oldEntries=held?heldEntries(held):[],cursor=0;for(let record of entries)isDeepStrictEqual(record.value,oldEntries[cursor])&&cursor++;let extendsHeld=cursor===oldEntries.length,writerKind=marker?.size===stamp.size&&marker.mtimeMs===stamp.mtimeMs?"hatch":"other",fork=held!==void 0&&!extendsHeld&&writerKind==="hatch",sessionId=fork?store.mintId():target,divergence=fork?{kind:"k9f2",parentSessionId:target,note:"Imported a developer-hatch history that diverged from its original session."}:divergenceOf(held?.divergence??null),nextHeader={...header.value,id:sessionId},nextLedger={...stamp,path,sourceSessionId,sessionId,highWaterMark:highWaterMark(entries.at(-1)??header),prefixDigest:digests.at(-1),writerKind,checkedAt:now()},oldByKey=new Map(held?.entries.map((entry,index)=>[entry.key,oldEntries[index]])),imported=0;for(let record of entries)(fork||!isDeepStrictEqual(record.value,oldByKey.get(record.key)))&&imported++;let stored=entries.map(record=>({key:record.key,line:record.stored})),writes=held!==void 0&&!fork&&entries.length>=oldEntries.length&&oldEntries.every((value,index)=>isDeepStrictEqual(entries[index]?.value,value))&&isDeepStrictEqual(nextHeader,held.header)&&isDeepStrictEqual(divergence,held.divergence)?appendRecordWrites(sessionId,held?.rewrites??0,stored.slice(oldEntries.length)):[manifestWrite(sessionId,nextHeader),divergenceWrite(sessionId,divergence),rewriteRecordWrite(store,sessionId,nextHeader,stored)];return writes.push({op:"put",key:ledgerKey(path),data:nextLedger}),await commit(writes),{outcome:held?fork?"forked":extendsHeld?"extended":"adopted":"imported",sessionId,imported}};return{open:paths=>admission.admit(async()=>{let results=[];for(let path of paths)results.push(await importFile(resolve2(path)));return results}),importFile:path=>admission.admit(()=>importFile(resolve2(path))),getLedger:path=>ledger(resolve2(path)),getSession:id=>admission.admit(async()=>{let held=await manifest(id);if(held)return{id:held.id,header:held.header,entries:heldEntries(held),divergence:divergenceOf(held.divergence)??void 0}}),async recordProjectedTail(path,sessionId,tails,written){path=resolve2(path);let tail=tails.at(-1);if(tail===void 0)return;let end=tail.offset+Buffer.byteLength(tail.line);if(written.size!==end+1)throw new Error("Projection size does not match its written image");let previous=await ledger(path),prefixDigest=previous?.prefixDigest,next=previous===void 0?void 0:previous.highWaterMark.end+1;for(let each of tails){if(prefixDigest===void 0||each.offset!==next){prefixDigest=void 0;break}prefixDigest=chainLine(prefixDigest,each.line),next=each.offset+Buffer.byteLength(each.line)+1}let record={...written,path,sourceSessionId:sessionId,sessionId,highWaterMark:{id:tail.key,hash:hash(tail.line),offset:tail.offset,end},...prefixDigest===void 0?{}:{prefixDigest},writerKind:"store",checkedAt:now()};await commit([{op:"put",key:ledgerKey(path),data:record}])},async recordProjection(path,contents,written){path=resolve2(path);let bytes=Buffer.from(contents);if(bytes.length!==written.size)throw new Error("Projection size does not match its written image");let{header,entries}=parse(bytes),held=await manifest(header.value.id);if(!held||!isDeepStrictEqual(heldEntries(held),entries.map(record2=>record2.value)))throw new Error("Projection does not match the committed session");let record={...written,path,sourceSessionId:header.value.id,sessionId:held.id,highWaterMark:highWaterMark(entries.at(-1)??header),prefixDigest:chainOf([header.raw,...entries.map(record2=>record2.raw)]).at(-1),writerKind:"store",checkedAt:now()};await commit([{op:"put",key:ledgerKey(path),data:record}])}}}var storeKeyOf=entryId=>entryId.startsWith("~")?`~${entryId}`:entryId,STALE="session-store/projection-stale/",staleKey=path=>STALE+encodeURIComponent(path),codeOf=error=>error instanceof Error&&"code"in error&&typeof error.code=="string"?error.code:"unknown",messageOf=error=>error instanceof Error?error.message:String(error);function projectionImage(header,entries){return[JSON.stringify(header),...entries.map(entry=>entry.line)].map(line=>`${line}
28
+ `).join("")}async function stampOf(path){try{let value=await stat4(path);return{size:value.size,mtimeMs:value.mtimeMs,ctimeMs:value.ctimeMs}}catch(error){if(codeOf(error)==="ENOENT")return;throw error}}async function replaceAtomically(path,contents){let mode=await modeOf(path)??384,temp=join4(dirname(path),`.${basename2(path)}.${randomUUID3()}.tmp`),handle=await open3(temp,"wx",mode),identity;try{await handle.writeFile(contents),await handle.sync(),identity=await captureFileIdentity(handle.fd,path)}finally{await handle.close()}try{await rename3(temp,path)}catch(error){throw await rm2(temp,{force:!0}),error}return identity}async function modeOf(path){try{return(await stat4(path)).mode&511}catch(error){if(codeOf(error)==="ENOENT")return;throw error}}var isRecord2=value=>typeof value=="object"&&value!==null&&!Array.isArray(value),staleSessionIdOf=mark=>isRecord2(mark)&&typeof mark.sessionId=="string"?mark.sessionId:void 0;async function replaceWith(files,path,contents){if(files===void 0)return replaceAtomically(path,contents);await files.replace(path,contents)}var DurableSessionBinding=class _DurableSessionBinding{constructor(binding,handle,importer,admission,warn,hooks,projectedSize){this.stale=!1,this.generation=0,this.unrecordedTails=[],this.wholeUnrecorded=!1,this.binding=binding,this.handle=handle,this.importer=importer,this.admission=admission,this.warn=warn,this.hooks=hooks,this.projectedSize=projectedSize}static async open(binding,sessionFile,sessionId,headerLine,warn,hooks){let{store,epoch}=binding,path=resolve3(sessionFile),admission=createAdmissionLine(),importer=createJsonlImporter({store,epoch,admission}),id=sessionId,reprojected=!1;if(await stampOf(path)!==void 0){let mark=await store.getDocument(staleKey(path)),markedId=staleSessionIdOf(mark);if(markedId!==void 0){let stored=await openSessionStore(store,epoch).load(markedId);if(stored===void 0)throw new Error(`the store marks ${path} stale but holds no session ${markedId}`);await reprojectFile(importer,admission,binding,hooks,path,projectionImage(stored.header,stored.entries)),id=markedId,reprojected=!0}else id=(await importer.importFile(path)).sessionId}let handle=await openSyncSessionStore(store,epoch).open(id,JSON.parse(headerLine)),size=(await stampOf(path))?.size??0;return{session:new _DurableSessionBinding(binding,handle,importer,admission,warn,hooks,size),reprojected}}commitAppend(entries){this.handle.appendSync(entries),this.generation++}commitRewrite(headerLine,entries){this.handle.rewriteSync(JSON.parse(headerLine),entries),this.generation++}projectionStale(){return this.stale}projected(sessionFile,entry){let path=resolve3(sessionFile),offset=this.projectedSize;this.projectedSize+=Buffer.byteLength(entry.line)+1;let sessionId=String(this.handle.header().id);this.unrecordedTails.push({key:entry.key,line:entry.line,offset}),this.record(path,async()=>{let tails=[...this.unrecordedTails],whole=this.wholeUnrecorded?projectionImage(this.handle.header(),this.handle.entries()):void 0,written=await stampOf(path);written!==void 0&&(whole===void 0?await this.importer.recordProjectedTail(path,sessionId,tails,written):await this.importer.recordProjection(path,whole,written),this.unrecordedTails.splice(0,tails.length),whole!==void 0&&(this.wholeUnrecorded=!1))})}recordWhole(sessionFile){let path=resolve3(sessionFile),contents=projectionImage(this.handle.header(),this.handle.entries());this.projectedSize=Buffer.byteLength(contents),this.unrecordedTails=[],this.wholeUnrecorded=!0,this.record(path,async()=>{let written=await stampOf(path);written!==void 0&&(await this.importer.recordProjection(path,contents,written),this.wholeUnrecorded=!1)})}projectionFailed(sessionFile,error){let path=resolve3(sessionFile),unmarked="";if(!this.stale){try{let data={sessionId:String(this.handle.header().id)};this.binding.store.commitSync(this.binding.epoch,[{op:"put",key:staleKey(path),data}],()=>{})}catch(markError){unmarked=`; the stale mark was not stored (${messageOf(markError)})`}this.stale=!0}this.warn({path,code:codeOf(error),message:`${messageOf(error)}${unmarked}`})}markProjectionStale(sessionFile){let path=resolve3(sessionFile);if(!this.stale){let data={sessionId:String(this.handle.header().id)};this.binding.store.commitSync(this.binding.epoch,[{op:"put",key:staleKey(path),data}],()=>{}),this.stale=!0}this.scheduleRepair(path)}settled(){return this.admission.admit(async()=>{})}scheduleRepair(sessionFile){let path=resolve3(sessionFile);this.admission.admit(async()=>{if(!this.stale)return;let generation=this.generation,contents=projectionImage(this.handle.header(),this.handle.entries());if(this.hooks.beforeWrite(path),this.hooks.afterReplace(path,await replaceWith(this.binding.files,path,contents)),generation!==this.generation)return this.scheduleRepair(path);this.binding.store.commitSync(this.binding.epoch,[{op:"delete",key:staleKey(path)}],()=>{}),this.stale=!1,this.projectedSize=Buffer.byteLength(contents),this.unrecordedTails=[],this.wholeUnrecorded=!1;let written=await stampOf(path);written!==void 0&&generation===this.generation&&await this.importer.recordProjection(path,contents,written)}).catch(error=>this.projectionFailed(path,error))}record(path,write){let generation=this.generation;this.admission.admit(async()=>{generation===this.generation&&await write()}).catch(error=>{generation===this.generation&&this.warn({path,code:codeOf(error),message:`projection ledger not recorded: ${messageOf(error)}`})})}};async function reprojectFile(importer,admission,binding,hooks,path,contents){hooks.beforeWrite(path),hooks.afterReplace(path,await replaceWith(binding.files,path,contents));let written=await stampOf(path);written!==void 0&&await admission.admit(()=>importer.recordProjection(path,contents,written)),binding.store.commitSync(binding.epoch,[{op:"delete",key:staleKey(path)}],()=>{})}var reserve;function reserveSessionWrite(path){reserve?.(path)}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(path,self){for(let ref of liveWriters){let owner=ref.deref();if(!owner){liveWriters.delete(ref);continue}if(owner!==self&&owner.isPersisted()&&owner.getSessionFile()===path)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}function emptyUsageTotals(){return{input:0,output:0,cacheRead:0,cacheWrite:0,cost:0,latestCacheHitRate:void 0}}var CURRENT_SESSION_VERSION=3;function createSessionId(){return uuidv7()}var SESSION_FILE_NAME=/^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}-\d{3}Z_(.+)\.jsonl$/;function sessionFileNameId(path){let id=SESSION_FILE_NAME.exec(basename3(path))?.[1];if(id!==void 0)try{return assertValidSessionId(id),id}catch{return}}function withFileNameId(path,options){if(options?.id!==void 0)return options;let id=sessionFileNameId(path);return id===void 0?options:{...options,id}}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=randomUUID4().slice(0,8);if(!byId.has(id))return id}return randomUUID4()}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(`
29
29
  `);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 path=[],visited=new Set,current=leaf;for(;current&&!visited.has(current);)visited.add(current),path.push(current),current=current.parentId?index.get(current.parentId):void 0;return path.reverse(),path}function getSessionContextSettings(path){let thinkingLevel="off",thinkingSelection,configurationUpdate,model=null,isModelSelectionExplicit=!1,isInFallbackWindow=!1,preFallbackThinkingLevel=thinkingLevel,preFallbackThinkingSelection=thinkingSelection;for(let entry of path)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(path){let compaction=null;for(let entry of path)entry.type==="compaction"&&(compaction=entry);if(!compaction)return path;let compactionIdx=path.findIndex(entry=>entry.id===compaction.id);if(compactionIdx<0)return path;let contextEntries=[compaction],foundFirstKept=!1;for(let i=0;i<compactionIdx;i++){let entry=path[i];entry.type!=="compaction"&&(entry.id===compaction.firstKeptEntryId&&(foundFirstKept=!0),foundFirstKept&&!(entry.type==="message"&&entry.message.role==="system")&&contextEntries.push(entry))}return contextEntries.push(...path.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 path=knownPath??buildSessionPath(entries,leafId,byId),settings=getSessionContextSettings(path),contextEntries=contextEntriesOfPath(path),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=path.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(path.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_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 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=openSync(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=readSync(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(`
30
30
  `,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(`
31
31
  `,lineStart)}lineChunks.push(chunk.slice(lineStart))}let probe=Buffer.allocUnsafe(1);if(readSync(fd,probe,0,probe.length,null)===0)return lineChunks.push(decoder.end()),parseSessionHeaderCandidate(lineChunks.join(""))??null;throw new SessionHeaderScanLimitError(filePath)}finally{closeSync(fd)}}function readSessionHeaderForDiscovery(filePath){try{return readSessionHeader(filePath)}catch{return null}}function getSessionHeaderCwd(header){let cwd=header.cwd;return typeof cwd=="string"?cwd:void 0}function discoverOpenHeader(resolvedPath,cwdOverride){if(cwdOverride!==void 0||!existsSync3(resolvedPath))return{header:null,needsFullLoad:!1};try{return{header:readSessionHeader(resolvedPath),needsFullLoad:!1}}catch(error){if(!(error instanceof SessionHeaderScanLimitError))throw error;return{header:null,needsFullLoad:!0}}}function headerOf(entries){let firstEntry=entries?.[0];return firstEntry?.type==="session"?firstEntry:null}function openLocation(resolvedPath,sessionDir,cwdOverride,header){let headerCwd=header?getSessionHeaderCwd(header):void 0,cwd=cwdOverride??(headerCwd&&resolveMovedPath(headerCwd))??process.cwd(),dir=sessionDir?normalizePath(sessionDir):resolve4(resolvedPath,"..");return{cwd,dir}}function findMostRecentSession(sessionDir,cwd){let resolvedSessionDir=normalizePath(sessionDir),matchesCwd=cwd?sessionCwdMatcher(resolvePath(cwd)):void 0;try{let files=readdirSync(resolvedSessionDir).filter(file=>file.endsWith(".jsonl")).map(file=>join5(resolvedSessionDir,file)).map(path=>({path,mtime:statSync(path).mtimeMs})).sort((a,b)=>b.mtime-a.mtime);for(let{path}of files){let header=readSessionHeaderForDiscovery(path);if(header&&(!matchesCwd||matchesCwd(getSessionHeaderCwd(header))))return path}return null}catch{return null}}var sessionEntryLoader=loadEntriesFromFile,DEFERRED_FILE_LOAD=Symbol("deferred-session-file-load");var SETUP_ENTRY_TYPES=new Set(["session","model_change","model_change_rejected","thinking_level_change","configuration_update","label"]),LIFECYCLE_ENTRY_TYPES=new Set(["session-lifecycle","work-custody","child-lifecycle"]);function isDisposableEntry(entry){return entry.type==="custom"?entry.startupBookkeeping===!0||LIFECYCLE_ENTRY_TYPES.has(entry.customType):SETUP_ENTRY_TYPES.has(entry.type)}function isConversationEntry(entry){return entry.type==="message"&&(entry.message.role==="user"||entry.message.role==="assistant")}var SessionManager=class _SessionManager{constructor(cwd,sessionDir,sessionFile,persist,newSessionOptions,preloadedFileEntries){this.sessionId="",this.writeGuard=new SessionWriteGuard,this.writeFence=new SessionWriteFence,this.bindPending=!1,this.bindRaced=!1,this.projectionWarningListeners=new Set,this.flushed=!1,this.tailMayBeTorn=!1,this.tornTailCause="unknown",this.pendingRecoveries=[],this.fileEntries=[],this.byId=new Map,this.entryOrdersById=new Map,this.messageEntryPositions=new WeakMap,this.labelsById=new Map,this.labelTimestampsById=new Map,this.leafId=null,this.transcriptFile=new TranscriptFile,this.transcriptBytes=new WeakMap,this.capturesTranscriptBase=compactUpdatesEnabled(),this.residentStore=new ResidentStringStore,this.callKeys=new SessionFileCallKeys,this.mirrorTrimmed=!1,this.loadingFullMirror=!1,this.trimmedIds=new Set,this.idsInUse={has:id=>this.byId.has(id)||this.trimmedIds.has(id)},this.fullEntryCount=0,this.historyGeneration=0,this.verbatimFromCount=0,this.historyReductions=new HistoryReductions({generation:()=>this.historyGeneration,count:()=>this.fullEntryCount,appendedSince:count=>this._appendedSince(count),readAll:()=>this._readWholeHistory()}),this.compactEntriesCache=null,this.compactView=null,this.projectionMemo=null,this.historyView=null,this.compactLookup=null,this.mutationCount=0,this.entriesCache=null,this.branchCache=null,this.sessionNameCache=void 0,this.usageTotals={input:0,output:0,cacheRead:0,cacheWrite:0,cost:0,latestCacheHitRate:void 0},this.cwd=resolvePath(cwd),this.sessionDir=normalizePath(sessionDir),this.persist=persist,persist&&registerSessionWriter(this),persist&&this.sessionDir&&!existsSync3(this.sessionDir)&&mkdirSync2(this.sessionDir,{recursive:!0}),this.residentStore.configure({blobsDir:()=>this.persist&&this.sessionId?join5(this.sessionDir,"resident-blobs",this.sessionId):void 0}),sessionFile?preloadedFileEntries!==DEFERRED_FILE_LOAD&&this._setSessionFile(sessionFile,preloadedFileEntries,newSessionOptions):preloadedFileEntries!==DEFERRED_FILE_LOAD&&preloadedFileEntries?.length?this._loadEntries(preloadedFileEntries,newSessionOptions):this.newSession(newSessionOptions)}reloadFromDisk(){if(!this.sessionFile||!existsSync3(this.sessionFile))return;let fileEntries=loadEntriesFromFile(this.sessionFile,this.capturesTranscriptBase);if(fileEntries.length===0){if(statSync(this.sessionFile).size===0)return;throw new Error(`Session file is not a valid ${APP_NAME} session: ${this.sessionFile}`)}this._setSessionFile(this.sessionFile,fileEntries),this._journalReplace()}_loadFullMirrorFor(id){if(!(this.byId.has(id)||!this.sessionFile)){this.loadingFullMirror=!0;try{this.reloadFromDisk()}finally{this.loadingFullMirror=!1}}}setSessionFile(sessionFile){this._setSessionFile(sessionFile),this._journalReplace()}_setSessionFile(sessionFile,preloadedFileEntries,newSessionOptions){let existingFile=this._beginSessionFile(sessionFile,newSessionOptions);if(existingFile===void 0)return;let entries=preloadedFileEntries??loadEntriesFromFile(existingFile,this.capturesTranscriptBase);if(this._captureTranscriptBase(loadedFileIdentities.get(entries),entries),!this._adoptFileEntries(existingFile,entries,newSessionOptions))return;let loadedHistory=this._retainLoadedTail();this.fileEntries=this.fileEntries.map(entry=>this.residentStore.externalize(entry)),this._completeFileLoad(loadedHistory)}async _setSessionFileAsync(sessionFile,preloadedFileEntries,newSessionOptions,slicer){let existingFile=this._beginSessionFile(sessionFile,newSessionOptions);if(existingFile===void 0)return;let entries=preloadedFileEntries??await loadEntriesFromFileAsync(existingFile,slicer,this.capturesTranscriptBase);if(this._captureTranscriptBase(loadedFileIdentities.get(entries),entries),!this._adoptFileEntries(existingFile,entries,newSessionOptions))return;let loadedHistory=this._retainLoadedTail();this.fileEntries=await mapInSlices(this.fileEntries,entry=>this.residentStore.externalize(entry),slicer),this._completeFileLoad(loadedHistory),await this.transcriptFile.ready}_beginSessionFile(sessionFile,newSessionOptions){let resolvedFile=resolvePath(sessionFile);this.sessionFile!==resolvedFile&&(this.durable=void 0),this.persist&&(reserveSessionWrite(resolvedFile),this.writeFence.opened(resolvedFile));let recoveryCause=this.sessionFile===resolvedFile&&this.tailMayBeTorn?this.tornTailCause:"unknown";if(this.tailMayBeTorn=!1,this.tornTailCause="unknown",this.sessionFile=resolvedFile,this.transcriptFile.reset(),this.mirrorTrimmed=!1,this.trimmedIds.clear(),this.residentStore.clear(),this.callKeys.clear(),existsSync3(resolvedFile))return this.persist&&this._settleFinalLine(resolvedFile,recoveryCause),resolvedFile;let created=withFileNameId(resolvedFile,newSessionOptions);this._resetToNewSession(created),created?.id!==void 0&&(this._rewriteFile(),this.flushed=!0)}_adoptFileEntries(sessionFile,entries,newSessionOptions){if(entries.length===0){if(statSync(sessionFile).size>0)throw new Error(`Session file is not a valid ${APP_NAME} session: ${sessionFile}`);return this._resetToNewSession(withFileNameId(sessionFile,newSessionOptions)),this._rewriteFile(),this.flushed=!0,!1}this.fileEntries=entries,this.callKeys.adopt(entries);let header=this.fileEntries.find(e=>e.type==="session");return this.sessionId=header?.id??createSessionId(),this._releaseBlobsDirUnlessShared(),migrateToCurrentVersion(this.fileEntries)&&this.writeGuard.isWritable(this.fileEntries)&&this._rewriteFile(),!0}_completeFileLoad(loadedHistory){this._buildIndex(),this.historyGeneration++,loadedHistory!==void 0&&(this.historyView={source:this.fileEntries,length:this.fileEntries.length,entries:loadedHistory}),this.mutationCount++,this.flushed=!0,this.ownedHeaderFile=void 0}newSession(options){this.durable=void 0;let timestamp=this._resetToNewSession(options);if(this.ownedHeaderFile=void 0,this.persist){let fileTimestamp=timestamp.replace(/[:.]/g,"-"),path=join5(this.getSessionDir(),`${fileTimestamp}_${this.sessionId}.jsonl`);reserveSessionWrite(path),this.sessionFile=path}return this._journalReplace(),this.sessionFile}_resetToNewSession(options){options?.id!==void 0&&assertValidSessionId(options.id);let previousBlobsDir=this.residentStore.resolvedBlobsDir();this.sessionId=options?.id??createSessionId();let timestamp=new Date().toISOString(),header={type:"session",version:CURRENT_SESSION_VERSION,id:this.sessionId,timestamp,cwd:this.cwd,parentSession:options?.parentSession,...options?.spawnedBy?{spawnedBy:options.spawnedBy}:{}};return this.fileEntries=[header],this.callKeys.clear(),this.transcriptFile.reset(),this.transcriptBytes=new WeakMap,this.historyGeneration++,this.verbatimFromCount=0,this.mirrorTrimmed=!1,this.trimmedIds.clear(),this.fullEntryCount=0,this.residentStore.clear(),previousBlobsDir&&this._removeBlobsDir(previousBlobsDir),this.byId.clear(),this.entryOrdersById.clear(),this.messageEntryPositions=new WeakMap,this.labelsById.clear(),this.labelTimestampsById.clear(),this.leafId=null,this.sessionNameCache=void 0,this.usageTotals={input:0,output:0,cacheRead:0,cacheWrite:0,cost:0,latestCacheHitRate:void 0},this.mutationCount++,this.flushed=!1,timestamp}_loadEntries(entries,options){let header=entries.find(e=>e.type==="session");header?(this.fileEntries=entries,this.callKeys.adopt(entries),this.sessionId=header.id,migrateToCurrentVersion(this.fileEntries)&&this._rewriteFile()):(this.newSession(options),this.callKeys.adopt(entries),this.fileEntries=this.fileEntries.concat(entries)),this.fileEntries=this.fileEntries.map(entry=>this.residentStore.externalize(entry)),this._buildIndex(),this.historyGeneration++,this.mutationCount++}_retainLoadedTail(){if(!this.persist||this.loadingFullMirror)return;let tail=planLoadedTail(this.fileEntries);if(tail===void 0)return;let history=this.fileEntries.filter(entry=>entry.type!=="session");this.usageTotals=emptyUsageTotals(),this.fullEntryCount=history.length;for(let entry of history)this._accumulateUsage(entry);for(let id of tail.trimmedIds)this.trimmedIds.add(id);return this.mirrorTrimmed=!0,this.fileEntries=tail.retained,this.verbatimFromCount=history.length-tail.windowLength,history}_buildIndex(){this.mirrorTrimmed||(this.verbatimFromCount=0),this.byId.clear(),this.entryOrdersById.clear(),this.messageEntryPositions=new WeakMap,this.labelsById.clear(),this.labelTimestampsById.clear(),this.leafId=null,this.sessionNameCache=void 0,this.mirrorTrimmed||(this.usageTotals=emptyUsageTotals());let fullEntryCount=0;for(let[order,entry]of this.fileEntries.entries())entry.type!=="session"&&(fullEntryCount++,this.byId.set(entry.id,entry),this.entryOrdersById.set(entry.id,order),this.leafId=entry.id,this.mirrorTrimmed||this._accumulateUsage(entry),entry.type==="session_info"&&(this.sessionNameCache=entry.name?.trim()||void 0),entry.type==="label"&&(entry.label?(this.labelsById.set(entry.targetId,entry.label),this.labelTimestampsById.set(entry.targetId,entry.timestamp)):(this.labelsById.delete(entry.targetId),this.labelTimestampsById.delete(entry.targetId))));this.mirrorTrimmed||(this.fullEntryCount=fullEntryCount)}_rewriteFile(){if(!this.persist||!this.sessionFile)return;this.writeGuard.assertRewritable(this.fileEntries,this.sessionFile),this.writeFence.assertOwned(this.sessionFile),reserveSessionWrite(this.sessionFile);let durable=this.durable;if(this.bindPending&&(this.bindRaced=!0),durable&&(durable.commitRewrite(this._headerLine(),this._storedEntries(this.fileEntries)),durable.projectionStale())){durable.scheduleRepair(this.sessionFile);return}try{replaceFileAtomically(this.sessionFile,this._serializedFileEntries(),this.capturesTranscriptBase?identity=>this._captureTranscriptBase(identity,this.fileEntries):void 0)}catch(error){if(!durable)throw error;durable.projectionFailed(this.sessionFile,error);return}durable?.recordWhole(this.sessionFile)}_captureTranscriptBase(identity,entries){identity&&this.transcriptFile.capture(identity,entries,()=>{let persistence=this._transcriptPersistence();persistence?(this.transcriptJournal?.record({kind:"persisted",persistence}),entries&&this._journalReplace()):this.transcriptFile.unavailable&&this.transcriptJournal?.record({kind:"unavailable",reason:this.transcriptFile.unavailable}),this.transcriptBytes=new WeakMap})}beginTranscriptJournal(){return this.transcriptJournal=new TranscriptJournal,this._transcriptSnapshot()}drainTranscript(){return this.transcriptJournal?.drain()??[]}_journalReplace(){this.transcriptJournal?.record(...this._transcriptSnapshot())}_transcriptSnapshot(){let{base,history,unavailable}=this.transcriptFile;if(unavailable)return[{kind:"unavailable",reason:unavailable}];let unpersisted=base?this.fullEntryCount-history:this.fileEntries.length,resident=base?this.fileEntries.length-1:this.mirrorTrimmed?-1:this.fileEntries.length;return snapshotTranscript({base,unpersisted:unpersisted<=resident?this.fileEntries.slice(this.fileEntries.length-unpersisted):void 0,leafId:this.leafId,own:entry=>this._transcriptEntryBytes(entry),persistence:this._transcriptPersistence()})}_transcriptPersistence(){if(!(!this.flushed||!this.transcriptFile.identity))return{fileIdentity:this.transcriptFile.identity,count:this.fullEntryCount+1}}_transcriptEntryBytes(entry){let cached=this.transcriptBytes.get(entry);if(cached!==void 0)return cached;let bytes=JSON.stringify(this.callKeys.decorate(this.residentStore.materialize(entry)));return this.persist&&this.capturesTranscriptBase&&!this.transcriptFile.unavailable&&(!this.flushed||!this.transcriptFile.identity)&&this.transcriptBytes.set(entry,bytes),bytes}*_serializedFileEntries(){let content=this.capturesTranscriptBase?new BaseContentHash:void 0;for(let entry of this.fileEntries){let bytes=this._transcriptEntryBytes(entry);this.capturesTranscriptBase&&!this.transcriptFile.unavailable&&this.transcriptBytes.set(entry,bytes),content?.line(bytes),yield`${bytes}
32
32
  `}content&&loadedContentFingerprints.set(this.fileEntries,content.digest())}isPersisted(){return this.persist}getCwd(){return this.cwd}getSessionDir(){return this.sessionDir}usesDefaultSessionDir(){return this.sessionDir===getDefaultSessionDirPath(this.cwd)}getSessionId(){return this.sessionId}getSessionFile(){return this.sessionFile}getOwnership(){return!this.persist||!this.sessionFile?{writable:!0}:this.writeGuard.ownership(this.fileEntries)}getResidentStore(){return this.residentStore}getResidentStoreStats(){return this.residentStore.stats()}persistHeaderNow(){if(!this.persist||!this.sessionFile||this.flushed)return this.headerWrite??this.transcriptFile.ready;let sessionFile=this.sessionFile,durable=this.durable;if(this.bindPending&&(this.bindRaced=!0),durable&&this.headerWrite===void 0)try{durable.commitRewrite(this._headerLine(),this._storedEntries(this.fileEntries))}catch(error){return Promise.reject(error)}return this.headerWrite??=(durable?this._writeHeaderAsync(sessionFile).then(()=>durable.recordWhole(sessionFile),error=>durable.projectionFailed(sessionFile,error)):this._writeHeaderAsync(sessionFile)).finally(()=>{this.headerWrite=void 0}),this.headerWrite}isTranscriptFlushed(){return this.flushed}async discardHeaderOnlyFile(){return await this.headerWrite,!this.persist||!this.sessionFile||!this.flushed||this.ownedHeaderFile!==this.sessionFile||!this.fileEntries.every(isDisposableEntry)?!1:(await rm3(this.sessionFile,{force:!0}),this.ownedHeaderFile=void 0,this.flushed=!1,this.transcriptFile.reset(),!0)}async _writeHeaderAsync(sessionFile){this.writeFence.assertOwned(sessionFile),reserveSessionWrite(sessionFile);let entries=this.fileEntries,serialize=batch=>batch.map(e=>`${this._transcriptEntryBytes(e)}
33
33
  `).join(""),written=0,handle=await open4(sessionFile,"wx");try{for(;written<entries.length;){let batch=entries.slice(written);written+=batch.length,await handle.writeFile(serialize(batch))}let closing=handle;for(this.capturesTranscriptBase&&this.sessionFile===sessionFile&&this.fileEntries===entries&&(this._captureTranscriptBase(captureFileIdentity(closing.fd,sessionFile)),await this.transcriptFile.ready),handle=void 0,await closing.close();written<entries.length&&this.sessionFile===sessionFile&&this.fileEntries===entries;){let batch=entries.slice(written);written+=batch.length,await appendFile2(sessionFile,serialize(batch))}}catch(error){return discardFailedFirstFlushAsync(sessionFile,handle,error)}if(this.sessionFile===sessionFile&&this.fileEntries===entries&&written===entries.length){this.flushed=!0,this.ownedHeaderFile=sessionFile,this.transcriptBytes=new WeakMap;let persistence=this.transcriptJournal&&this._transcriptPersistence();persistence&&this.transcriptJournal?.record({kind:"persisted",persistence})}}_hasConversation(){return this.fileEntries.some(isConversationEntry)}onRecovery(listener){this.recoveryListener=listener;for(let recovery of this.pendingRecoveries.splice(0))listener(recovery);return()=>{this.recoveryListener===listener&&(this.recoveryListener=void 0)}}_reportRecovery(recovery){this.recoveryListener===void 0?this.pendingRecoveries.push(recovery):this.recoveryListener(recovery)}_settleFinalLine(sessionFile,cause){let repair=terminateFinalSessionLine(sessionFile,cause);repair?.kind==="set_aside"&&this._reportRecovery(repair.recovery),repair?.kind==="deferred"&&(this.tailMayBeTorn=!0,this.tornTailCause=cause)}_persist(entry){if(!this.persist||!this.sessionFile)return;this.writeGuard.assertWritable(this.fileEntries,entry,this.sessionFile),this.writeFence.assertOwned(this.sessionFile),reserveSessionWrite(this.sessionFile);let durable=this.durable;if(this.bindPending&&(this.bindRaced=!0),this.flushed){let bound=durable?this._commitBoundAppend(durable,entry):void 0;if(durable&&bound&&durable.projectionStale())return durable.scheduleRepair(this.sessionFile),bound.line;if(this.tailMayBeTorn)try{let recovery=truncateToLastCompleteLine(this.sessionFile,this.tornTailCause);this.tailMayBeTorn=!1,recovery!==void 0&&this._reportRecovery(recovery)}catch(error){if(!durable||!bound)throw error;return durable.projectionFailed(this.sessionFile,error),bound.line}let bytes2=bound?.line??this._transcriptEntryBytes(entry);try{appendFileSync(this.sessionFile,`${bytes2}
34
34
  `)}catch(error){if(this.tailMayBeTorn=!0,this.tornTailCause=sessionRecoveryCause(error),!durable||!bound)throw error;return durable.projectionFailed(this.sessionFile,error),bytes2}return durable&&bound&&durable.projected(this.sessionFile,bound),bytes2}let durableLifecycle=entry.type==="custom"&&LIFECYCLE_ENTRY_TYPES.has(entry.customType);if(!isConversationEntry(entry)&&!durableLifecycle&&!this._hasConversation())return;if(this.headerWrite&&durableLifecycle)throw new Error("Lifecycle append requires the pending session header write to finish");if(durable&&(durable.commitRewrite(this._headerLine(),this._storedEntries([...this.fileEntries,entry])),durable.projectionStale()))return this.flushed=!0,durable.scheduleRepair(this.sessionFile),this._transcriptEntryBytes(entry);if(this.headerWrite)return;let fd;try{fd=openSync(this.sessionFile,"wx")}catch(error){if(!durable)throw error;return this.flushed=!0,durable.projectionFailed(this.sessionFile,error),this._transcriptEntryBytes(entry)}let bytes;try{for(let e of[...this.fileEntries,entry]){let serialized=this._transcriptEntryBytes(e);writeFileSync2(fd,`${serialized}
35
- `),e===entry&&(bytes=serialized)}}catch(error){durable||discardFailedFirstFlush(this.sessionFile,fd,error);let failure=error;try{discardFailedFirstFlush(this.sessionFile,fd,error)}catch(discarded){failure=discarded}return this.flushed=!0,durable.projectionFailed(this.sessionFile,failure),this._transcriptEntryBytes(entry)}return this.capturesTranscriptBase?this._captureTranscriptBase(captureAndCloseFileIdentity(fd,this.sessionFile)):closeSync(fd),this.flushed=!0,this.capturesTranscriptBase||(this.transcriptBytes=new WeakMap),!isConversationEntry(entry)&&!this._hasConversation()&&(this.ownedHeaderFile=this.sessionFile),durable?.recordWhole(this.sessionFile),bytes}_commitBoundAppend(durable,entry){let stored={key:storeKeyOf(entry.id),line:this._transcriptEntryBytes(entry)};return durable.commitAppend([stored]),stored}async bindDurableStore(binding){let sessionFile=this.sessionFile;if(!this.persist||sessionFile===void 0)throw new Error("only a persisted session with a file path can be bound to the durable store");this.bindPending=!0,this.bindRaced=!1;let opened;try{opened=await DurableSessionBinding.open(binding,sessionFile,this.sessionId,this._headerLine(),warning=>{for(let listener of this.projectionWarningListeners)listener(warning)},{beforeWrite:path=>{this.writeFence.assertOwned(path),reserveSessionWrite(path)},afterReplace:(_path,identity)=>{this.capturesTranscriptBase&&this._captureTranscriptBase(Promise.resolve(identity),this.fileEntries)}})}finally{this.bindPending=!1}if(this.sessionFile!==sessionFile)throw new Error(`the session moved to another file while it was being bound: ${sessionFile} was not bound`);let{session,reprojected}=opened;this.bindRaced?(session.commitRewrite(this._headerLine(),this._storedEntries(this.fileEntries)),reprojected&&session.markProjectionStale(sessionFile)):reprojected&&this.reloadFromDisk(),this.durable=session}settleDurableProjection(){return this.durable?.settled()??Promise.resolve()}onProjectionWarning(listener){return this.projectionWarningListeners.add(listener),()=>{this.projectionWarningListeners.delete(listener)}}_headerLine(){let header=this.fileEntries.find(entry=>entry.type==="session");if(header===void 0)throw new Error("the session has no header to bind");return this._transcriptEntryBytes(header)}_storedEntries(entries){return entries.flatMap(entry=>entry.type==="session"?[]:[{key:storeKeyOf(entry.id),line:this._transcriptEntryBytes(entry)}])}_appendEntry(entry,shareable,recoveryOwner,flow){let residentEntry=this.residentStore.externalize(entry),bytes=this._persist(residentEntry),committed=this._shareMessage(residentEntry,shareable);if(this._commitEntry(committed),this.transcriptJournal){let serialized=bytes??this._transcriptEntryBytes(residentEntry);this.persist&&!this.transcriptFile.unavailable&&(!this.flushed||!this.transcriptFile.identity)&&this.transcriptBytes.set(committed,serialized);let change=flow?.();this.transcriptJournal.record({kind:"append",id:residentEntry.id,type:residentEntry.type,parentId:residentEntry.parentId,entry:serialized,persistence:this._transcriptPersistence(),...recoveryOwner?{owningMessageId:recoveryOwner.messageId,recoveryEpoch:recoveryOwner.epoch}:{},...change?{flow:change}:{}})}}_shareMessage(residentEntry,shareable){if(shareable===void 0||residentEntry.type!=="message"||!this.residentStore.isTokenFree(residentEntry)||!isPlainJson(shareable))return residentEntry;let shared={...residentEntry,message:{...shareable}};return this.residentStore.adoptTokenFree(shared),shared}_commitEntry(residentEntry){this.fileEntries.push(residentEntry),this.byId.set(residentEntry.id,residentEntry),this.entryOrdersById.set(residentEntry.id,this.fileEntries.length-1),this.leafId=residentEntry.id,this.fullEntryCount++,this._accumulateUsage(residentEntry),this.mutationCount++}appendEntry(entry){this._appendEntry(entry);let order=this.entryOrdersById.get(entry.id);entry.type==="message"&&order!==void 0&&this.messageEntryPositions.set(entry.message,{entryId:entry.id,order}),entry.type==="session_info"&&(this.sessionNameCache=entry.name?.trim()||void 0),entry.type==="label"&&(entry.label?(this.labelsById.set(entry.targetId,entry.label),this.labelTimestampsById.set(entry.targetId,entry.timestamp)):(this.labelsById.delete(entry.targetId),this.labelTimestampsById.delete(entry.targetId)))}_materializeEntry(entry){let missingResidentString=!1,materialized=this.residentStore.materialize(entry,()=>{missingResidentString=!0});if(missingResidentString&&this.sessionFile){let persisted=loadEntriesFromFile(this.sessionFile).find(candidate=>candidate.id===entry.id);if(persisted)return this.callKeys.strip(persisted)}if(materialized.type==="message"){let order=this.entryOrdersById.get(materialized.id);order!==void 0&&this.messageEntryPositions.set(materialized.message,{entryId:materialized.id,order})}return materialized}_accumulateUsage(entry){if(entry.type!=="message"||entry.message.role!=="assistant")return;let usage=entry.message.usage;if(!usage)return;this.usageTotals.input+=usage.input,this.usageTotals.output+=usage.output,this.usageTotals.cacheRead+=usage.cacheRead,this.usageTotals.cacheWrite+=usage.cacheWrite,this.usageTotals.cost+=usage.cost?.total??0,usage.costUnknown&&(this.usageTotals.costUnknown=!0);let latestPromptTokens=usage.input+usage.cacheRead+usage.cacheWrite;this.usageTotals.latestCacheHitRate=latestPromptTokens>0?usage.cacheRead/latestPromptTokens*100:void 0}getUsageTotals(){return this.usageTotals}appendMessage(message){return this._appendMessage(message,!1)}appendOwnedMessage(message,options){return this._appendMessage(message,!0,options?.inputSource,options?.recoveryOwner,options?.bridgedCalls)}persistedEntry(entry){return this.callKeys.decorate(entry)}_appendMessage(message,owned,inputSource,recoveryOwner,bridgedCalls){let entry={type:"message",id:generateId(this.idsInUse),parentId:this.leafId,timestamp:new Date().toISOString(),message,...inputSource===void 0?{}:{inputSource}};message.role==="assistant"&&this.callKeys.recordAssistant(entry,recoveryOwner?.messageId,bridgedCalls),message.role==="toolResult"&&this.callKeys.recordResult(entry,this.leafId,id=>this.byId.get(id)),this._appendEntry(entry,owned?message:void 0,recoveryOwner);let order=this.entryOrdersById.get(entry.id);return order!==void 0&&this.messageEntryPositions.set(message,{entryId:entry.id,order}),entry.id}getMessageEntryPosition(message){return this.messageEntryPositions.get(message)}getEntryOrder(entryId){return this.entryOrdersById.get(entryId)}appendThinkingLevelChange(thinkingLevel,thinkingSelection,trigger,model){let entry={type:"thinking_level_change",id:generateId(this.idsInUse),parentId:this.leafId,timestamp:new Date().toISOString(),thinkingLevel,thinkingSelection,...trigger===void 0?{}:{triggerSource:trigger.source},...trigger?.actor===void 0?{}:{triggerActor:trigger.actor},...trigger?.effectId===void 0?{}:{effectId:trigger.effectId},...model===void 0?{}:{provider:model.provider,modelId:model.id}};return this._appendEntry(entry),entry.id}appendConfigurationUpdate(effort){let entry={type:"configuration_update",id:generateId(this.idsInUse),parentId:this.leafId,timestamp:new Date().toISOString(),reasoning:{effort}};return this._appendEntry(entry),entry.id}appendModelChangeRejected(details){let entry={type:"model_change_rejected",id:generateId(this.idsInUse),parentId:this.leafId,timestamp:new Date().toISOString(),...details};return this._appendEntry(entry),entry.id}appendModelChange(provider,modelId,reason,originalProvider,originalModelId,attribution){let entry={type:"model_change",id:generateId(this.idsInUse),parentId:this.leafId,timestamp:new Date().toISOString(),provider,modelId,reason,originalProvider,originalModelId,...attribution===void 0?{}:{source:attribution.origin.source},...attribution?.origin.actor===void 0?{}:{actor:attribution.origin.actor},...attribution?.duringTurn?{duringTurn:!0}:{},...attribution?.origin.effectId===void 0?{}:{effectId:attribution.origin.effectId}};return this._appendEntry(entry),entry.id}appendUsage(kind,provider,model,usage,note){let entry={type:"usage",id:generateId(this.idsInUse),parentId:this.leafId,timestamp:new Date().toISOString(),kind,provider,model,usage,...note?{note}:{}};return this._appendEntry(entry),entry}appendCompaction(summary,firstKeptEntryId,tokensBefore,details,fromHook,usage){let timestamp=new Date().toISOString(),from=this.buildSessionProjection(),systemMessage=getCurrentSystemMessage(from.messages),id=generateId(this.idsInUse),entry={type:"compaction",id,parentId:this.leafId,timestamp,summary,firstKeptEntryId:firstKeptEntryId??id,tokensBefore,details,usage,fromHook,...systemMessage?{systemMessage:{...systemMessage,timestamp:new Date(timestamp).getTime()}}:{}};return this._appendEntry(entry,void 0,void 0,()=>compactionFlow(from.entries,this.buildSessionProjection().entries)),this._trimMirrorAfterCompaction(entry),entry.id}dispose(){this.transcriptFile.reset(),unregisterSessionWriter(this),this._releaseBlobsDirUnlessShared()}_releaseBlobsDirUnlessShared(){let blobsDir=this.residentStore.resolvedBlobsDir();blobsDir&&(this.sessionFile&&hasOtherLiveSessionWriter(this.sessionFile,this)||this._removeBlobsDir(blobsDir))}_removeBlobsDir(dir){try{rmSync2(dir,{force:!0,recursive:!0})}catch{}}_trimMirrorAfterCompaction(compaction){if(!this.persist)return;let firstKeptIndex=this.fileEntries.findIndex(entry=>entry.id===compaction.firstKeptEntryId),compactionIndex=this.fileEntries.findIndex(entry=>entry.id===compaction.id);if(firstKeptIndex<0||compactionIndex<firstKeptIndex)return;let verbatimStart=this.fileEntries.length-(this.fullEntryCount-this.verbatimFromCount),header=this.fileEntries.find(entry=>entry.type==="session"),branchIds=new Set(this.getBranch().map(entry=>entry.id)),firstVerbatimIndex=Math.max(firstKeptIndex,verbatimStart);for(let i=firstVerbatimIndex;i<compactionIndex;i++)branchIds.has(this.fileEntries[i].id)||(firstVerbatimIndex=i+1);this.verbatimFromCount=this.fullEntryCount-(compactionIndex+1-firstVerbatimIndex);let retained=[...this.fileEntries.slice(0,firstKeptIndex).filter(entry=>entry.type!=="message"),...this.fileEntries.slice(firstKeptIndex,compactionIndex+1).filter(entry=>branchIds.has(entry.id))],parentId=null;for(let entry of retained)entry.type!=="session"&&(entry.parentId=parentId),parentId=entry.type==="session"?null:entry.id;let retainedIds=new Set(retained.map(entry=>entry.id));for(let entry of this.fileEntries)entry.type!=="session"&&!retainedIds.has(entry.id)&&this.trimmedIds.add(entry.id);this.residentStore.spillResident(),this.mirrorTrimmed=!0,this.fileEntries=[header,...retained].filter(entry=>entry!==void 0).map(entry=>this.residentStore.externalize(entry)),this._buildIndex(),this.mutationCount++}appendCustomEntry(customType,data,options){let entry={type:"custom",customType,data,...options?.startupBookkeeping===!0?{startupBookkeeping:!0}:{},id:generateId(this.idsInUse),parentId:this.leafId,timestamp:new Date().toISOString()};return this._appendEntry(entry),entry.id}appendSessionInfo(name){let sanitizedName=name.replace(/[\r\n]+/g," ").trim(),entry={type:"session_info",id:generateId(this.idsInUse),parentId:this.leafId,timestamp:new Date().toISOString(),name:sanitizedName};return this._appendEntry(entry),this.sessionNameCache=sanitizedName||void 0,entry.id}getSessionName(){return this.sessionNameCache}appendCustomMessageEntry(customType,content,display,details,options){let entry={type:"custom_message",customType,content,display,details,id:generateId(this.idsInUse),parentId:this.leafId,timestamp:new Date().toISOString()};return this._appendEntry(entry,void 0,options?.recoveryOwner),entry.id}appendContextEdit(targetId,replacement){if(replacement!==null&&(typeof replacement!="object"||!("content"in replacement)||typeof replacement.content!="string"&&!Array.isArray(replacement.content)))throw new Error("Context edit replacement must be null or contain string/array content");let target=this.byId.get(targetId);if(!target)throw new Error(`Entry ${targetId} not found`);if(!this.getBranch().some(entry2=>entry2.id===targetId))throw new Error(`Entry ${targetId} is not on the active branch`);if(!(target.type==="custom_message"||target.type==="message"&&(target.message.role==="user"||target.message.role==="assistant"||target.message.role==="toolResult")))throw new Error(`Entry ${targetId} does not contribute editable model content`);let targetRole=target.type==="message"?target.message.role:"custom",normalizedReplacement=replacement!==null&&(targetRole==="assistant"||targetRole==="toolResult")&&typeof replacement.content=="string"?{content:[{type:"text",text:replacement.content}]}:replacement,entry={type:"context_edit",id:generateId(this.idsInUse),parentId:this.leafId,timestamp:new Date().toISOString(),targetId,replacement:normalizedReplacement};return this._appendEntry(entry,void 0,void 0,()=>{let edited=this.getEntry(targetId);return contextEditFlow(entry,edited&&ownedFlowMessage(projectContextEntry(edited,entry)[0]))}),entry.id}getLeafId(){return this.leafId}getLeafEntry(){let entry=this.leafId?this.byId.get(this.leafId):void 0;return entry?this._materializeEntry(entry):void 0}getEntry(id){let entry=this.byId.get(id);if(entry)return this._materializeEntry(entry);if(this.mirrorTrimmed&&this.sessionFile){let persisted=this._loadFullHistoryEntries().find(candidate=>candidate.id===id);return persisted?this.residentStore.materialize(persisted):void 0}}getChildren(parentId){let children=[];for(let entry of this.byId.values())entry.parentId===parentId&&children.push(this._materializeEntry(entry));return children}getLabel(id){return this.labelsById.get(id)}appendLabelChange(targetId,label){if(!this.byId.has(targetId)&&!this.getEntries().some(entry2=>entry2.id===targetId))throw new Error(`Entry ${targetId} not found`);let entry={type:"label",id:generateId(this.idsInUse),parentId:this.leafId,timestamp:new Date().toISOString(),targetId,label};return this._appendEntry(entry),label?(this.labelsById.set(targetId,label),this.labelTimestampsById.set(targetId,entry.timestamp)):(this.labelsById.delete(targetId),this.labelTimestampsById.delete(targetId)),entry.id}getBranch(fromId){if(fromId===void 0&&this.branchCache!==null&&this.branchCache.leafId===this.leafId&&this.branchCache.mutation===this.mutationCount)return this.branchCache.entries;if(fromId===void 0){let extended=this._extendBranchCache();if(extended!==void 0)return extended}let path=[],startId=fromId??this.leafId,entriesById=this.byId;fromId!==void 0&&!entriesById.has(fromId)&&this.mirrorTrimmed&&this.sessionFile&&(entriesById=new Map(this._loadFullHistoryEntries().filter(entry=>entry.type!=="session").map(entry=>[entry.id,this.residentStore.materialize(entry)])));let current=startId?entriesById.get(startId):void 0,visited=new Set;for(;current&&!visited.has(current);)visited.add(current),path.push(current),current=current.parentId?entriesById.get(current.parentId):void 0;path.reverse();let materializedPath=(entriesById===this.byId?this._fromCompactView(path):void 0)??this._materializeEntries(path);return fromId===void 0&&(this.branchCache={leafId:this.leafId,mutation:this.mutationCount,entries:materializedPath,source:this.fileEntries}),materializedPath}getFullBranch(fromId){if(!this.mirrorTrimmed||!this.sessionFile)return this.getBranch(fromId);let byId=new Map;for(let entry of this.getEntries())byId.set(entry.id,entry);let path=[],visited=new Set,current=byId.get(fromId??this.leafId??"");for(;current&&!visited.has(current.id);)visited.add(current.id),path.push(current),current=current.parentId?byId.get(current.parentId):void 0;return path.reverse()}_extendBranchCache(){let cache2=this.branchCache;if(cache2===null||cache2.source!==this.fileEntries||cache2.leafId===null)return;let added=[],current=this.leafId?this.byId.get(this.leafId):void 0;for(;current&&current.id!==cache2.leafId;){if(added.length>=256)return;added.push(current),current=current.parentId?this.byId.get(current.parentId):void 0}if(current===void 0)return;added.reverse();let entries=[...cache2.entries,...this._fromCompactView(added)??this._materializeEntries(added)];return this.branchCache={leafId:this.leafId,mutation:this.mutationCount,entries,source:this.fileEntries},entries}buildContextEntries(){return buildContextEntries(this._getCompactEntries(),this.leafId)}buildSessionProjection(){let{projection}=this._projectCurrent();return{...projection,messages:[...projection.messages],entries:[...projection.entries]}}_projectCurrent(){let entries=this._getCompactEntries(),memo=this.projectionMemo;if(memo?.source===entries&&memo.leafId===this.leafId)return memo.result;let path=this._extendPath(memo,entries)??buildSessionPath(entries,this.leafId),result=projectSession(entries,this.leafId,void 0,path);return this.projectionMemo={source:entries,leafId:this.leafId,path,result},result}_extendPath(memo,entries){if(!memo||memo.leafId===null||this.leafId===null)return;let previous=memo.source;if(entries.length<=previous.length||entries[previous.length-1]!==previous[previous.length-1])return;let parentId=memo.leafId,appended=[];for(let index=previous.length;index<entries.length;index++){let entry=entries[index];if(entry.parentId!==parentId)return;appended.push(entry),parentId=entry.id}if(parentId===this.leafId)return[...memo.path,...appended]}buildSessionContext(){let{projection,settings}=this._projectCurrent(),{thinkingLevel,thinkingSelection,model,configurationUpdate}=settings;return{messages:[...projection.messages],thinkingLevel,thinkingSelection,model,configurationUpdate}}hasContextMessages(){return this.hasBranchEntry(entry=>entry.type==="message"||entry.type==="custom_message"||entry.type==="compaction"||entry.type==="branch_summary"&&!!entry.summary)}hasThinkingLevelChanges(){return this.hasBranchEntry(entry=>entry.type==="thinking_level_change")}countCompactions(){let count=0;for(let entry of this.fileEntries)entry.type==="compaction"&&count++;return count}hasBranchEntry(predicate){let current=this.leafId?this.byId.get(this.leafId):void 0,visited=new Set;for(;current&&!visited.has(current);){if(predicate(current))return!0;visited.add(current),current=current.parentId?this.byId.get(current.parentId):void 0}return!1}getHeader(){let h=this.fileEntries.find(e=>e.type==="session");return h?this.residentStore.materialize(h):null}getEntries(){if(this.mirrorTrimmed&&this.sessionFile){let extended=this._extendView(this.historyView);if(extended!==void 0)return this.historyView={source:this.fileEntries,length:this.fileEntries.length,entries:extended},extended;let history=this._loadFullHistoryEntries().filter(e=>e.type!=="session").map(entry=>this.residentStore.materialize(entry));return this.historyView={source:this.fileEntries,length:this.fileEntries.length,entries:history},history}if(this.entriesCache!==null&&this.entriesCache.mutation===this.mutationCount)return this.entriesCache.entries;let materializedEntries=this._getCompactEntries();return this.entriesCache={mutation:this.mutationCount,entries:materializedEntries},materializedEntries}getEntryCount(){return this.fullEntryCount}reduceHistory(reducer){return this.historyReductions.reduce(reducer)}_appendedSince(count){if(count<this.verbatimFromCount)return;let wanted=this.fullEntryCount-count,appended=[],missing=!1;for(let index=this.fileEntries.length-1;index>=0&&appended.length<wanted;index--){let entry=this.fileEntries[index];if(entry.type==="session")break;appended.push(this.residentStore.materialize(entry,()=>{missing=!0}))}return missing||appended.length<wanted?void 0:appended.reverse()}_readWholeHistory(){if(!this.mirrorTrimmed||!this.sessionFile)return this._getCompactEntries();let held=this._extendView(this.historyView);return held!==void 0?held:this._loadFullHistoryEntries().filter(entry=>entry.type!=="session").map(entry=>this.residentStore.materialize(entry))}dropMaterializedCaches(){this.entriesCache=null,this.branchCache=null,this.compactEntriesCache=null,this.compactView=null,this.historyView=null,this.compactLookup=null,this.projectionMemo=null}holdsMaterializedHistory(){return this.historyView!==null}_extendView(view){if(view===null||view.source!==this.fileEntries||view.length>this.fileEntries.length)return;if(view.length===this.fileEntries.length)return view.entries;let missing=!1,tail=[];for(let entry of this.fileEntries.slice(view.length)){if(entry.type==="session")continue;let materialized=this.residentStore.materialize(entry,()=>{missing=!0});tail.push(materialized)}if(!missing)return this._bindMessagePositions(tail),[...view.entries,...tail]}_fromCompactView(path){let entries=this._getCompactEntries(),lookup=this.compactLookup;(lookup===null||lookup.length>entries.length||lookup.length>0&&lookup.entries[lookup.length-1]!==entries[lookup.length-1])&&(lookup={entries,length:0,map:new Map});for(let index=lookup.length;index<entries.length;index++){let entry=entries[index];lookup.map.set(entry.id,entry)}this.compactLookup={entries,length:entries.length,map:lookup.map};let shared=[];for(let entry of path){let materialized=lookup.map.get(entry.id);if(materialized===void 0||materialized.parentId!==entry.parentId)return;shared.push(materialized)}return shared}_bindMessagePositions(entries){for(let entry of entries){if(entry.type!=="message")continue;let order=this.entryOrdersById.get(entry.id);order!==void 0&&this.messageEntryPositions.set(entry.message,{entryId:entry.id,order})}}_materializeEntries(entries){return materializeSessionEntries(entries,{residentStore:this.residentStore,loadHistoryEntries:()=>this._loadFullHistoryEntries(),onMaterialized:entry=>{if(entry.type!=="message")return;let order=this.entryOrdersById.get(entry.id);order!==void 0&&this.messageEntryPositions.set(entry.message,{entryId:entry.id,order})}})}_getCompactEntries(){let extended=this._extendView(this.compactView);if(extended!==void 0)return this.compactView={source:this.fileEntries,length:this.fileEntries.length,entries:extended},extended;this.compactEntriesCache?.mutation!==this.mutationCount&&(this.compactEntriesCache={mutation:this.mutationCount,entries:this.fileEntries.filter(e=>e.type!=="session")});let entries=this.compactEntriesCache.entries,missingEntryIds=new Set;for(let entry of entries)this.residentStore.materialize(entry,()=>{missingEntryIds.add(entry.id)});if(missingEntryIds.size>0&&this.sessionFile){let persistedById=new Map(this._loadFullHistoryEntries().map(entry=>[entry.id,entry]));for(let index=0;index<entries.length;index++){let entry=entries[index];if(!missingEntryIds.has(entry.id))continue;let persisted=persistedById.get(entry.id);persisted&&(entries[index]=this.residentStore.externalize(persisted))}}let materialized=entries.map(entry=>this.residentStore.materialize(entry));return this._bindMessagePositions(materialized),this.compactView={source:this.fileEntries,length:this.fileEntries.length,entries:materialized},materialized}_loadFullHistoryEntries(){return this.sessionFile?sessionEntryLoader(this.sessionFile).map(entry=>this.callKeys.strip(entry)):this.fileEntries}getTree(){let entries=this.getEntries(),nodeMap=new Map,roots=[];for(let entry of entries){if(nodeMap.has(entry.id))continue;let label=this.labelsById.get(entry.id),labelTimestamp=this.labelTimestampsById.get(entry.id);nodeMap.set(entry.id,{entry,children:[],label,labelTimestamp})}for(let entry of entries){let node=nodeMap.get(entry.id);if(node.entry===entry)if(entry.parentId===null||entry.parentId===entry.id)roots.push(node);else{let parent=nodeMap.get(entry.parentId);parent?parent.children.push(node):roots.push(node)}}let stack=[...roots];for(;stack.length>0;){let node=stack.pop();node.children.sort((a,b)=>new Date(a.entry.timestamp).getTime()-new Date(b.entry.timestamp).getTime()),stack.push(...node.children)}return roots}branch(branchFromId){if(this._loadFullMirrorFor(branchFromId),!this.byId.has(branchFromId))throw new Error(`Entry ${branchFromId} not found`);let from=this.transcriptJournal&&this.buildSessionProjection().entries;this.leafId=branchFromId,this.mutationCount++,this.transcriptJournal?.record({kind:"leaf",leafId:branchFromId,...this._branchFlow(from)})}resetLeaf(){let from=this.transcriptJournal&&this.buildSessionProjection().entries;this.leafId=null,this.mutationCount++,this.transcriptJournal?.record({kind:"leaf",leafId:null,...this._branchFlow(from)})}branchWithSummary(branchFromId,summary,details,fromHook,usage){if(branchFromId!==null&&this._loadFullMirrorFor(branchFromId),branchFromId!==null&&!this.byId.has(branchFromId))throw new Error(`Entry ${branchFromId} not found`);let fromId=this.leafId??"root",entry={type:"branch_summary",id:generateId(this.idsInUse),parentId:branchFromId,timestamp:new Date().toISOString(),fromId,summary,details,usage,fromHook},from=this.transcriptJournal&&this.buildSessionProjection().entries;return this._appendEntry(entry,void 0,void 0,()=>this._branchFlow(from).flow),entry.id}_branchFlow(from){return from?{flow:branchFlow(from,this.buildSessionProjection().entries)}:{}}createBranchedSession(leafId){let previousSessionFile=this.sessionFile,path=this.getFullBranch(leafId);if(path.length===0)throw new Error(`Entry ${leafId} not found`);this.transcriptFile.reset(),this.transcriptBytes=new WeakMap;let pathWithoutLabels=[],replacementByLabelId=new Map,pendingLabelIds=[],pathParentId=null;for(let entry of path){if(entry.type==="label"){pendingLabelIds.push(entry.id);continue}for(let labelId of pendingLabelIds)replacementByLabelId.set(labelId,entry.id);pendingLabelIds.length=0,pathWithoutLabels.push(entry.type==="compaction"?{...entry,parentId:pathParentId,firstKeptEntryId:entry.firstKeptEntryId===entry.id?entry.id:replacementByLabelId.get(entry.firstKeptEntryId)??entry.firstKeptEntryId}:{...entry,parentId:pathParentId}),pathParentId=entry.id}let newSessionId=createSessionId(),timestamp=new Date().toISOString(),fileTimestamp=timestamp.replace(/[:.]/g,"-"),newSessionFile=join5(this.getSessionDir(),`${fileTimestamp}_${newSessionId}.jsonl`),header={type:"session",version:CURRENT_SESSION_VERSION,id:newSessionId,timestamp,cwd:this.cwd,parentSession:this.persist?previousSessionFile:void 0},pathEntryIds=new Set(pathWithoutLabels.map(e=>e.id)),labelsToWrite=[];for(let[targetId,label]of this.labelsById)pathEntryIds.has(targetId)&&labelsToWrite.push({targetId,label,timestamp:this.labelTimestampsById.get(targetId)});if(this.persist){let parentId2=pathWithoutLabels[pathWithoutLabels.length-1]?.id||null,labelEntries2=[];for(let{targetId,label,timestamp:labelTimestamp}of labelsToWrite){let labelEntry={type:"label",id:generateId(new Set(pathEntryIds)),parentId:parentId2,timestamp:labelTimestamp,targetId,label};pathEntryIds.add(labelEntry.id),labelEntries2.push(labelEntry),parentId2=labelEntry.id}reserveSessionWrite(newSessionFile);let branchedEntries2=this._materializeEntries([...pathWithoutLabels,...labelEntries2]),previousBlobsDir=this.residentStore.resolvedBlobsDir();return this.residentStore.clear(),previousBlobsDir&&this._removeBlobsDir(previousBlobsDir),this.mirrorTrimmed=!1,this.trimmedIds.clear(),this.durable=void 0,this.sessionId=newSessionId,this.sessionFile=newSessionFile,this.fileEntries=[header,...branchedEntries2.map(entry=>this.residentStore.externalize(entry))],this._buildIndex(),this.historyGeneration++,this.mutationCount++,this._hasConversation()?(this._rewriteFile(),this.flushed=!0):this.flushed=!1,this._journalReplace(),newSessionFile}let labelEntries=[],parentId=pathWithoutLabels[pathWithoutLabels.length-1]?.id||null;for(let{targetId,label,timestamp:labelTimestamp}of labelsToWrite){let labelEntry={type:"label",id:generateId(new Set([...pathEntryIds,...labelEntries.map(e=>e.id)])),parentId,timestamp:labelTimestamp,targetId,label};labelEntries.push(labelEntry),parentId=labelEntry.id}let branchedEntries=this._materializeEntries([...pathWithoutLabels,...labelEntries]);this.residentStore.clear(),this.fileEntries=[header,...branchedEntries.map(entry=>this.residentStore.externalize(entry))],this.sessionId=newSessionId,this._buildIndex(),this.historyGeneration++,this.mutationCount++,this._journalReplace()}static create(cwd,sessionDir,options){let dir=sessionDir?normalizePath(sessionDir):getDefaultSessionDir(cwd);return new _SessionManager(cwd,dir,void 0,!0,options)}static open(path,sessionDir,cwdOverride,options){let resolvedPath=resolvePath(path);reserveSessionWrite(resolvedPath);let discovery=discoverOpenHeader(resolvedPath,cwdOverride),preloadedFileEntries=discovery.needsFullLoad?loadEntriesFromFile(resolvedPath,compactUpdatesEnabled()):void 0,header=discovery.header??headerOf(preloadedFileEntries),{cwd,dir}=openLocation(resolvedPath,sessionDir,cwdOverride,header);return new _SessionManager(cwd,dir,resolvedPath,!0,options,preloadedFileEntries)}static async openAsync(path,sessionDir,cwdOverride,options,slicer=new EventLoopSlicer){let resolvedPath=resolvePath(path);reserveSessionWrite(resolvedPath);let discovery=discoverOpenHeader(resolvedPath,cwdOverride),preloadedFileEntries=discovery.needsFullLoad?await loadEntriesFromFileAsync(resolvedPath,slicer,compactUpdatesEnabled()):void 0,header=discovery.header??headerOf(preloadedFileEntries),{cwd,dir}=openLocation(resolvedPath,sessionDir,cwdOverride,header),manager=new _SessionManager(cwd,dir,resolvedPath,!0,options,DEFERRED_FILE_LOAD);try{await manager._setSessionFileAsync(resolvedPath,preloadedFileEntries,options,slicer)}catch(error){throw manager.dispose(),error}return manager}static continueRecent(cwd,sessionDir){let dir=sessionDir?normalizePath(sessionDir):getDefaultSessionDir(cwd),filterCwd=sessionDir!==void 0&&dir!==getDefaultSessionDirPath(cwd),mostRecent=findMostRecentSession(dir,filterCwd?cwd:void 0);return mostRecent?new _SessionManager(cwd,dir,mostRecent,!0):new _SessionManager(cwd,dir,void 0,!0)}static inMemory(cwd=process.cwd(),options,entries){return new _SessionManager(cwd,"",void 0,!1,options,entries)}static forkFrom(sourcePath,targetCwd,sessionDir,options){let resolvedSourcePath=resolvePath(sourcePath),resolvedTargetCwd=resolvePath(targetCwd),source=readForkSource(resolvedSourcePath);if(source.kind==="empty")throw new Error(`Cannot fork: source session file is empty or has no readable entries: ${resolvedSourcePath}`);if(source.kind==="not-a-session")throw new Error(`Cannot fork: source file is not a session file (no entry has a session header or a session entry shape): ${resolvedSourcePath}`);let sourceEntries=source.entries,dir=sessionDir?normalizePath(sessionDir):getDefaultSessionDir(resolvedTargetCwd);existsSync3(dir)||mkdirSync2(dir,{recursive:!0}),options?.id!==void 0&&assertValidSessionId(options.id);let newSessionId=options?.id??createSessionId(),timestamp=new Date().toISOString(),fileTimestamp=timestamp.replace(/[:.]/g,"-"),newSessionFile=join5(dir,`${fileTimestamp}_${newSessionId}.jsonl`),newHeader={type:"session",version:CURRENT_SESSION_VERSION,id:newSessionId,timestamp,cwd:resolvedTargetCwd,parentSession:resolvedSourcePath};reserveSessionWrite(newSessionFile),writeFileSync2(newSessionFile,`${JSON.stringify(newHeader)}
35
+ `),e===entry&&(bytes=serialized)}}catch(error){durable||discardFailedFirstFlush(this.sessionFile,fd,error);let failure=error;try{discardFailedFirstFlush(this.sessionFile,fd,error)}catch(discarded){failure=discarded}return this.flushed=!0,durable.projectionFailed(this.sessionFile,failure),this._transcriptEntryBytes(entry)}return this.capturesTranscriptBase?this._captureTranscriptBase(captureAndCloseFileIdentity(fd,this.sessionFile)):closeSync(fd),this.flushed=!0,this.capturesTranscriptBase||(this.transcriptBytes=new WeakMap),!isConversationEntry(entry)&&!this._hasConversation()&&(this.ownedHeaderFile=this.sessionFile),durable?.recordWhole(this.sessionFile),bytes}_commitBoundAppend(durable,entry){let stored={key:storeKeyOf(entry.id),line:this._transcriptEntryBytes(entry)};return durable.commitAppend([stored]),stored}async bindDurableStore(binding){let sessionFile=this.sessionFile;if(!this.persist||sessionFile===void 0)throw new Error("only a persisted session with a file path can be bound to the durable store");this.bindPending=!0,this.bindRaced=!1;let opened;try{opened=await DurableSessionBinding.open(binding,sessionFile,this.sessionId,this._headerLine(),warning=>{for(let listener of this.projectionWarningListeners)listener(warning)},{beforeWrite:path=>{this.writeFence.assertOwned(path),reserveSessionWrite(path)},afterReplace:(_path,identity)=>{this.capturesTranscriptBase&&this._captureTranscriptBase(Promise.resolve(identity),this.fileEntries)}})}finally{this.bindPending=!1}if(this.sessionFile!==sessionFile)throw new Error(`the session moved to another file while it was being bound: ${sessionFile} was not bound`);let{session,reprojected}=opened;this.bindRaced?(session.commitRewrite(this._headerLine(),this._storedEntries(this.fileEntries)),reprojected&&session.markProjectionStale(sessionFile)):reprojected&&this.reloadFromDisk(),this.durable=session}settleDurableProjection(){return this.durable?.settled()??Promise.resolve()}onProjectionWarning(listener){return this.projectionWarningListeners.add(listener),()=>{this.projectionWarningListeners.delete(listener)}}_headerLine(){let header=this.fileEntries.find(entry=>entry.type==="session");if(header===void 0)throw new Error("the session has no header to bind");return this._transcriptEntryBytes(header)}_storedEntries(entries){return entries.flatMap(entry=>entry.type==="session"?[]:[{key:storeKeyOf(entry.id),line:this._transcriptEntryBytes(entry)}])}_appendEntry(entry,shareable,recoveryOwner,flow){let residentEntry=this.residentStore.externalize(entry),bytes=this._persist(residentEntry),committed=this._shareMessage(residentEntry,shareable);if(this._commitEntry(committed),this.transcriptJournal){let serialized=bytes??this._transcriptEntryBytes(residentEntry);this.persist&&!this.transcriptFile.unavailable&&(!this.flushed||!this.transcriptFile.identity)&&this.transcriptBytes.set(committed,serialized);let change=flow?.();this.transcriptJournal.record({kind:"append",id:residentEntry.id,type:residentEntry.type,parentId:residentEntry.parentId,entry:serialized,persistence:this._transcriptPersistence(),...recoveryOwner?{owningMessageId:recoveryOwner.messageId,recoveryEpoch:recoveryOwner.epoch}:{},...change?{flow:change}:{}})}}_shareMessage(residentEntry,shareable){if(shareable===void 0||residentEntry.type!=="message"||!this.residentStore.isTokenFree(residentEntry)||!isPlainJson(shareable))return residentEntry;let shared={...residentEntry,message:{...shareable}};return this.residentStore.adoptTokenFree(shared),shared}_commitEntry(residentEntry){this.fileEntries.push(residentEntry),this.byId.set(residentEntry.id,residentEntry),this.entryOrdersById.set(residentEntry.id,this.fileEntries.length-1),this.leafId=residentEntry.id,this.fullEntryCount++,this._accumulateUsage(residentEntry),this.mutationCount++}appendEntry(entry){this._appendEntry(entry);let order=this.entryOrdersById.get(entry.id);entry.type==="message"&&order!==void 0&&this.messageEntryPositions.set(entry.message,{entryId:entry.id,order}),entry.type==="session_info"&&(this.sessionNameCache=entry.name?.trim()||void 0),entry.type==="label"&&(entry.label?(this.labelsById.set(entry.targetId,entry.label),this.labelTimestampsById.set(entry.targetId,entry.timestamp)):(this.labelsById.delete(entry.targetId),this.labelTimestampsById.delete(entry.targetId)))}_materializeEntry(entry){let missingResidentString=!1,materialized=this.residentStore.materialize(entry,()=>{missingResidentString=!0});if(missingResidentString&&this.sessionFile){let persisted=loadEntriesFromFile(this.sessionFile).find(candidate=>candidate.id===entry.id);if(persisted)return this.callKeys.strip(persisted)}if(materialized.type==="message"){let order=this.entryOrdersById.get(materialized.id);order!==void 0&&this.messageEntryPositions.set(materialized.message,{entryId:materialized.id,order})}return materialized}_accumulateUsage(entry){if(entry.type!=="message"||entry.message.role!=="assistant")return;let usage=entry.message.usage;if(!usage)return;this.usageTotals.input+=usage.input,this.usageTotals.output+=usage.output,this.usageTotals.cacheRead+=usage.cacheRead,this.usageTotals.cacheWrite+=usage.cacheWrite,this.usageTotals.cost+=usage.cost?.total??0,usage.costUnknown&&(this.usageTotals.costUnknown=!0);let latestPromptTokens=usage.input+usage.cacheRead+usage.cacheWrite;this.usageTotals.latestCacheHitRate=latestPromptTokens>0?usage.cacheRead/latestPromptTokens*100:void 0}getUsageTotals(){return this.usageTotals}appendMessage(message){return this._appendMessage(message,!1)}appendOwnedMessage(message,options){return this._appendMessage(message,!0,options?.inputSource,options?.recoveryOwner,options?.bridgedCalls)}persistedEntry(entry){return this.callKeys.decorate(entry)}_appendMessage(message,owned,inputSource,recoveryOwner,bridgedCalls){let entry={type:"message",id:generateId(this.idsInUse),parentId:this.leafId,timestamp:new Date().toISOString(),message,...inputSource===void 0?{}:{inputSource}};message.role==="assistant"&&this.callKeys.recordAssistant(entry,recoveryOwner?.messageId,bridgedCalls),message.role==="toolResult"&&this.callKeys.recordResult(entry,this.leafId,id=>this.byId.get(id)),this._appendEntry(entry,owned?message:void 0,recoveryOwner);let order=this.entryOrdersById.get(entry.id);return order!==void 0&&this.messageEntryPositions.set(message,{entryId:entry.id,order}),entry.id}getMessageEntryPosition(message){return this.messageEntryPositions.get(message)}getEntryOrder(entryId){return this.entryOrdersById.get(entryId)}appendThinkingLevelChange(thinkingLevel,thinkingSelection,trigger,model){let entry={type:"thinking_level_change",id:generateId(this.idsInUse),parentId:this.leafId,timestamp:new Date().toISOString(),thinkingLevel,thinkingSelection,...trigger===void 0?{}:{triggerSource:trigger.source},...trigger?.actor===void 0?{}:{triggerActor:trigger.actor},...trigger?.effectId===void 0?{}:{effectId:trigger.effectId},...model===void 0?{}:{provider:model.provider,modelId:model.id}};return this._appendEntry(entry),entry.id}appendConfigurationUpdate(effort){let entry={type:"configuration_update",id:generateId(this.idsInUse),parentId:this.leafId,timestamp:new Date().toISOString(),reasoning:{effort}};return this._appendEntry(entry),entry.id}appendModelChangeRejected(details){let entry={type:"model_change_rejected",id:generateId(this.idsInUse),parentId:this.leafId,timestamp:new Date().toISOString(),...details};return this._appendEntry(entry),entry.id}appendModelChange(provider,modelId,reason,originalProvider,originalModelId,attribution){let entry={type:"model_change",id:generateId(this.idsInUse),parentId:this.leafId,timestamp:new Date().toISOString(),provider,modelId,reason,originalProvider,originalModelId,...attribution===void 0?{}:{source:attribution.origin.source},...attribution?.origin.actor===void 0?{}:{actor:attribution.origin.actor},...attribution?.duringTurn?{duringTurn:!0}:{},...attribution?.origin.effectId===void 0?{}:{effectId:attribution.origin.effectId}};return this._appendEntry(entry),entry.id}appendUsage(kind,provider,model,usage,note){let entry={type:"usage",id:generateId(this.idsInUse),parentId:this.leafId,timestamp:new Date().toISOString(),kind,provider,model,usage,...note?{note}:{}};return this._appendEntry(entry),entry}appendCompaction(summary,firstKeptEntryId,tokensBefore,details,fromHook,usage){let timestamp=new Date().toISOString(),from=this.buildSessionProjection(),systemMessage=getCurrentSystemMessage(from.messages),id=generateId(this.idsInUse),entry={type:"compaction",id,parentId:this.leafId,timestamp,summary,firstKeptEntryId:firstKeptEntryId??id,tokensBefore,details,usage,fromHook,...systemMessage?{systemMessage:{...systemMessage,timestamp:new Date(timestamp).getTime()}}:{}};return this._appendEntry(entry,void 0,void 0,()=>compactionFlow(from.entries,this.buildSessionProjection().entries)),this._trimMirrorAfterCompaction(entry),entry.id}dispose(){this.transcriptFile.reset(),unregisterSessionWriter(this),this._releaseBlobsDirUnlessShared()}_releaseBlobsDirUnlessShared(){let blobsDir=this.residentStore.resolvedBlobsDir();blobsDir&&(this.sessionFile&&hasOtherLiveSessionWriter(this.sessionFile,this)||this._removeBlobsDir(blobsDir))}_removeBlobsDir(dir){try{rmSync2(dir,{force:!0,recursive:!0})}catch{}}_trimMirrorAfterCompaction(compaction){if(!this.persist)return;let firstKeptIndex=this.fileEntries.findIndex(entry=>entry.id===compaction.firstKeptEntryId),compactionIndex=this.fileEntries.findIndex(entry=>entry.id===compaction.id);if(firstKeptIndex<0||compactionIndex<firstKeptIndex)return;let verbatimStart=this.fileEntries.length-(this.fullEntryCount-this.verbatimFromCount),header=this.fileEntries.find(entry=>entry.type==="session"),branchIds=new Set(this.getBranch().map(entry=>entry.id)),firstVerbatimIndex=Math.max(firstKeptIndex,verbatimStart);for(let i=firstVerbatimIndex;i<compactionIndex;i++)branchIds.has(this.fileEntries[i].id)||(firstVerbatimIndex=i+1);this.verbatimFromCount=this.fullEntryCount-(compactionIndex+1-firstVerbatimIndex);let retained=[...this.fileEntries.slice(0,firstKeptIndex).filter(entry=>entry.type!=="message"),...this.fileEntries.slice(firstKeptIndex,compactionIndex+1).filter(entry=>branchIds.has(entry.id))],parentId=null;for(let entry of retained)entry.type!=="session"&&(entry.parentId=parentId),parentId=entry.type==="session"?null:entry.id;let retainedIds=new Set(retained.map(entry=>entry.id));for(let entry of this.fileEntries)entry.type!=="session"&&!retainedIds.has(entry.id)&&this.trimmedIds.add(entry.id);this.residentStore.spillResident(),this.mirrorTrimmed=!0,this.fileEntries=[header,...retained].filter(entry=>entry!==void 0).map(entry=>this.residentStore.externalize(entry)),this._buildIndex(),this.mutationCount++}appendCustomEntry(customType,data,options){let entry={type:"custom",customType,data,...options?.startupBookkeeping===!0?{startupBookkeeping:!0}:{},id:generateId(this.idsInUse),parentId:this.leafId,timestamp:new Date().toISOString()};return this._appendEntry(entry),entry.id}appendSessionInfo(name){let sanitizedName=name.replace(/[\r\n]+/g," ").trim(),entry={type:"session_info",id:generateId(this.idsInUse),parentId:this.leafId,timestamp:new Date().toISOString(),name:sanitizedName};return this._appendEntry(entry),this.sessionNameCache=sanitizedName||void 0,entry.id}getSessionName(){return this.sessionNameCache}appendCustomMessageEntry(customType,content,display,details,options){let entry={type:"custom_message",customType,content,display,details,id:generateId(this.idsInUse),parentId:this.leafId,timestamp:new Date().toISOString()};return this._appendEntry(entry,void 0,options?.recoveryOwner),entry.id}appendContextEdit(targetId,replacement){if(replacement!==null&&(typeof replacement!="object"||!("content"in replacement)||typeof replacement.content!="string"&&!Array.isArray(replacement.content)))throw new Error("Context edit replacement must be null or contain string/array content");let target=this.byId.get(targetId);if(!target)throw new Error(`Entry ${targetId} not found`);if(!this.getBranch().some(entry2=>entry2.id===targetId))throw new Error(`Entry ${targetId} is not on the active branch`);if(!(target.type==="custom_message"||target.type==="message"&&(target.message.role==="user"||target.message.role==="assistant"||target.message.role==="toolResult")))throw new Error(`Entry ${targetId} does not contribute editable model content`);let targetRole=target.type==="message"?target.message.role:"custom",normalizedReplacement=replacement!==null&&(targetRole==="assistant"||targetRole==="toolResult")&&typeof replacement.content=="string"?{content:[{type:"text",text:replacement.content}]}:replacement,entry={type:"context_edit",id:generateId(this.idsInUse),parentId:this.leafId,timestamp:new Date().toISOString(),targetId,replacement:normalizedReplacement};return this._appendEntry(entry,void 0,void 0,()=>{let edited=this.getEntry(targetId);return contextEditFlow(entry,edited&&ownedFlowMessage(projectContextEntry(edited,entry)[0]))}),entry.id}getLeafId(){return this.leafId}getLeafEntry(){let entry=this.leafId?this.byId.get(this.leafId):void 0;return entry?this._materializeEntry(entry):void 0}getEntry(id){let entry=this.byId.get(id);if(entry)return this._materializeEntry(entry);if(this.mirrorTrimmed&&this.sessionFile){let persisted=this._loadFullHistoryEntries().find(candidate=>candidate.id===id);return persisted?this.residentStore.materialize(persisted):void 0}}getChildren(parentId){let children=[];for(let entry of this.byId.values())entry.parentId===parentId&&children.push(this._materializeEntry(entry));return children}getLabel(id){return this.labelsById.get(id)}appendLabelChange(targetId,label){if(!this.byId.has(targetId)&&!this.getEntries().some(entry2=>entry2.id===targetId))throw new Error(`Entry ${targetId} not found`);let entry={type:"label",id:generateId(this.idsInUse),parentId:this.leafId,timestamp:new Date().toISOString(),targetId,label};return this._appendEntry(entry),label?(this.labelsById.set(targetId,label),this.labelTimestampsById.set(targetId,entry.timestamp)):(this.labelsById.delete(targetId),this.labelTimestampsById.delete(targetId)),entry.id}getBranch(fromId){if(fromId===void 0&&this.branchCache!==null&&this.branchCache.leafId===this.leafId&&this.branchCache.mutation===this.mutationCount)return this.branchCache.entries;if(fromId===void 0){let extended=this._extendBranchCache();if(extended!==void 0)return extended}let path=[],startId=fromId??this.leafId,entriesById=this.byId;fromId!==void 0&&!entriesById.has(fromId)&&this.mirrorTrimmed&&this.sessionFile&&(entriesById=new Map(this._loadFullHistoryEntries().filter(entry=>entry.type!=="session").map(entry=>[entry.id,this.residentStore.materialize(entry)])));let current=startId?entriesById.get(startId):void 0,visited=new Set;for(;current&&!visited.has(current);)visited.add(current),path.push(current),current=current.parentId?entriesById.get(current.parentId):void 0;path.reverse();let materializedPath=(entriesById===this.byId?this._fromCompactView(path):void 0)??this._materializeEntries(path);return fromId===void 0&&(this.branchCache={leafId:this.leafId,mutation:this.mutationCount,entries:materializedPath,source:this.fileEntries}),materializedPath}getFullBranch(fromId){if(!this.mirrorTrimmed||!this.sessionFile)return this.getBranch(fromId);let byId=new Map;for(let entry of this.getEntries())byId.set(entry.id,entry);let path=[],visited=new Set,current=byId.get(fromId??this.leafId??"");for(;current&&!visited.has(current.id);)visited.add(current.id),path.push(current),current=current.parentId?byId.get(current.parentId):void 0;return path.reverse()}_extendBranchCache(){let cache2=this.branchCache;if(cache2===null||cache2.source!==this.fileEntries||cache2.leafId===null)return;let added=[],current=this.leafId?this.byId.get(this.leafId):void 0;for(;current&&current.id!==cache2.leafId;){if(added.length>=256)return;added.push(current),current=current.parentId?this.byId.get(current.parentId):void 0}if(current===void 0)return;added.reverse();let entries=[...cache2.entries,...this._fromCompactView(added)??this._materializeEntries(added)];return this.branchCache={leafId:this.leafId,mutation:this.mutationCount,entries,source:this.fileEntries},entries}buildContextEntries(){return buildContextEntries(this._getCompactEntries(),this.leafId)}buildSessionProjection(){let{projection}=this._projectCurrent();return{...projection,messages:[...projection.messages],entries:[...projection.entries]}}_projectCurrent(){let entries=this._getCompactEntries(),memo=this.projectionMemo;if(memo?.source===entries&&memo.leafId===this.leafId)return memo.result;let path=this._extendPath(memo,entries)??buildSessionPath(entries,this.leafId),result=projectSession(entries,this.leafId,void 0,path);return this.projectionMemo={source:entries,leafId:this.leafId,path,result},result}_extendPath(memo,entries){if(!memo||memo.leafId===null||this.leafId===null)return;let previous=memo.source;if(entries.length<=previous.length||entries[previous.length-1]!==previous[previous.length-1])return;let parentId=memo.leafId,appended=[];for(let index=previous.length;index<entries.length;index++){let entry=entries[index];if(entry.parentId!==parentId)return;appended.push(entry),parentId=entry.id}if(parentId===this.leafId)return[...memo.path,...appended]}buildSessionContext(){let{projection,settings}=this._projectCurrent(),{thinkingLevel,thinkingSelection,model,configurationUpdate}=settings;return{messages:[...projection.messages],thinkingLevel,thinkingSelection,model,configurationUpdate}}hasContextMessages(){return this.hasBranchEntry(entry=>entry.type==="message"||entry.type==="custom_message"||entry.type==="compaction"||entry.type==="branch_summary"&&!!entry.summary)}hasThinkingLevelChanges(){return this.hasBranchEntry(entry=>entry.type==="thinking_level_change")}countCompactions(){let count=0;for(let entry of this.fileEntries)entry.type==="compaction"&&count++;return count}hasBranchEntry(predicate){let current=this.leafId?this.byId.get(this.leafId):void 0,visited=new Set;for(;current&&!visited.has(current);){if(predicate(current))return!0;visited.add(current),current=current.parentId?this.byId.get(current.parentId):void 0}return!1}getHeader(){let h=this.fileEntries.find(e=>e.type==="session");return h?this.residentStore.materialize(h):null}getEntries(){if(this.mirrorTrimmed&&this.sessionFile){let extended=this._extendView(this.historyView);if(extended!==void 0)return this.historyView={source:this.fileEntries,length:this.fileEntries.length,entries:extended},extended;let history=this._loadFullHistoryEntries().filter(e=>e.type!=="session").map(entry=>this.residentStore.materialize(entry));return this.historyView={source:this.fileEntries,length:this.fileEntries.length,entries:history},history}if(this.entriesCache!==null&&this.entriesCache.mutation===this.mutationCount)return this.entriesCache.entries;let materializedEntries=this._getCompactEntries();return this.entriesCache={mutation:this.mutationCount,entries:materializedEntries},materializedEntries}getEntryCount(){return this.fullEntryCount}reduceHistory(reducer){return this.historyReductions.reduce(reducer)}_appendedSince(count){if(count<this.verbatimFromCount)return;let wanted=this.fullEntryCount-count,appended=[],missing=!1;for(let index=this.fileEntries.length-1;index>=0&&appended.length<wanted;index--){let entry=this.fileEntries[index];if(entry.type==="session")break;appended.push(this.residentStore.materialize(entry,()=>{missing=!0}))}return missing||appended.length<wanted?void 0:appended.reverse()}_readWholeHistory(){if(!this.mirrorTrimmed||!this.sessionFile)return this._getCompactEntries();let held=this._extendView(this.historyView);return held!==void 0?held:this._loadFullHistoryEntries().filter(entry=>entry.type!=="session").map(entry=>this.residentStore.materialize(entry))}dropMaterializedCaches(){this.entriesCache=null,this.branchCache=null,this.compactEntriesCache=null,this.compactView=null,this.historyView=null,this.compactLookup=null,this.projectionMemo=null}holdsMaterializedHistory(){return this.historyView!==null}_extendView(view){if(view===null||view.source!==this.fileEntries||view.length>this.fileEntries.length)return;if(view.length===this.fileEntries.length)return view.entries;let missing=!1,tail=[];for(let entry of this.fileEntries.slice(view.length)){if(entry.type==="session")continue;let materialized=this.residentStore.materialize(entry,()=>{missing=!0});tail.push(materialized)}if(!missing)return this._bindMessagePositions(tail),[...view.entries,...tail]}_fromCompactView(path){let entries=this._getCompactEntries(),lookup=this.compactLookup;(lookup===null||lookup.length>entries.length||lookup.length>0&&lookup.entries[lookup.length-1]!==entries[lookup.length-1])&&(lookup={entries,length:0,map:new Map});for(let index=lookup.length;index<entries.length;index++){let entry=entries[index];lookup.map.set(entry.id,entry)}this.compactLookup={entries,length:entries.length,map:lookup.map};let shared=[];for(let entry of path){let materialized=lookup.map.get(entry.id);if(materialized===void 0||materialized.parentId!==entry.parentId)return;shared.push(materialized)}return shared}_bindMessagePositions(entries){for(let entry of entries){if(entry.type!=="message")continue;let order=this.entryOrdersById.get(entry.id);order!==void 0&&this.messageEntryPositions.set(entry.message,{entryId:entry.id,order})}}_materializeEntries(entries){return materializeSessionEntries(entries,{residentStore:this.residentStore,loadHistoryEntries:()=>this._loadFullHistoryEntries(),onMaterialized:entry=>{if(entry.type!=="message")return;let order=this.entryOrdersById.get(entry.id);order!==void 0&&this.messageEntryPositions.set(entry.message,{entryId:entry.id,order})}})}_getCompactEntries(){let extended=this._extendView(this.compactView);if(extended!==void 0)return this.compactView={source:this.fileEntries,length:this.fileEntries.length,entries:extended},extended;this.compactEntriesCache?.mutation!==this.mutationCount&&(this.compactEntriesCache={mutation:this.mutationCount,entries:this.fileEntries.filter(e=>e.type!=="session")});let entries=this.compactEntriesCache.entries,missingEntryIds=new Set;for(let entry of entries)this.residentStore.materialize(entry,()=>{missingEntryIds.add(entry.id)});if(missingEntryIds.size>0&&this.sessionFile){let persistedById=new Map(this._loadFullHistoryEntries().map(entry=>[entry.id,entry]));for(let index=0;index<entries.length;index++){let entry=entries[index];if(!missingEntryIds.has(entry.id))continue;let persisted=persistedById.get(entry.id);persisted&&(entries[index]=this.residentStore.externalize(persisted))}}let materialized=entries.map(entry=>this.residentStore.materialize(entry));return this._bindMessagePositions(materialized),this.compactView={source:this.fileEntries,length:this.fileEntries.length,entries:materialized},materialized}_loadFullHistoryEntries(){return this.sessionFile?sessionEntryLoader(this.sessionFile).map(entry=>this.callKeys.strip(entry)):this.fileEntries}getTree(){let entries=this.getEntries(),nodeMap=new Map,roots=[];for(let entry of entries){if(nodeMap.has(entry.id))continue;let label=this.labelsById.get(entry.id),labelTimestamp=this.labelTimestampsById.get(entry.id);nodeMap.set(entry.id,{entry,children:[],label,labelTimestamp})}for(let entry of entries){let node=nodeMap.get(entry.id);if(node.entry===entry)if(entry.parentId===null||entry.parentId===entry.id)roots.push(node);else{let parent=nodeMap.get(entry.parentId);parent?parent.children.push(node):roots.push(node)}}let stack=[...roots];for(;stack.length>0;){let node=stack.pop();node.children.sort((a,b)=>new Date(a.entry.timestamp).getTime()-new Date(b.entry.timestamp).getTime()),stack.push(...node.children)}return roots}branch(branchFromId){if(this._loadFullMirrorFor(branchFromId),!this.byId.has(branchFromId))throw new Error(`Entry ${branchFromId} not found`);let from=this.transcriptJournal&&this.buildSessionProjection().entries;this.leafId=branchFromId,this.mutationCount++,this.transcriptJournal?.record({kind:"leaf",leafId:branchFromId,...this._branchFlow(from)})}resetLeaf(){let from=this.transcriptJournal&&this.buildSessionProjection().entries;this.leafId=null,this.mutationCount++,this.transcriptJournal?.record({kind:"leaf",leafId:null,...this._branchFlow(from)})}branchWithSummary(branchFromId,summary,details,fromHook,usage){if(branchFromId!==null&&this._loadFullMirrorFor(branchFromId),branchFromId!==null&&!this.byId.has(branchFromId))throw new Error(`Entry ${branchFromId} not found`);let fromId=this.leafId??"root",entry={type:"branch_summary",id:generateId(this.idsInUse),parentId:branchFromId,timestamp:new Date().toISOString(),fromId,summary,details,usage,fromHook},from=this.transcriptJournal&&this.buildSessionProjection().entries;return this._appendEntry(entry,void 0,void 0,()=>this._branchFlow(from).flow),entry.id}_branchFlow(from){return from?{flow:branchFlow(from,this.buildSessionProjection().entries)}:{}}createBranchedSession(leafId){let previousSessionFile=this.sessionFile,path=this.getFullBranch(leafId);if(path.length===0)throw new Error(`Entry ${leafId} not found`);this.transcriptFile.reset(),this.transcriptBytes=new WeakMap;let pathWithoutLabels=[],replacementByLabelId=new Map,pendingLabelIds=[],pathParentId=null;for(let entry of path){if(entry.type==="label"){pendingLabelIds.push(entry.id);continue}for(let labelId of pendingLabelIds)replacementByLabelId.set(labelId,entry.id);pendingLabelIds.length=0,pathWithoutLabels.push(entry.type==="compaction"?{...entry,parentId:pathParentId,firstKeptEntryId:entry.firstKeptEntryId===entry.id?entry.id:replacementByLabelId.get(entry.firstKeptEntryId)??entry.firstKeptEntryId}:{...entry,parentId:pathParentId}),pathParentId=entry.id}let newSessionId=createSessionId(),timestamp=new Date().toISOString(),fileTimestamp=timestamp.replace(/[:.]/g,"-"),newSessionFile=join5(this.getSessionDir(),`${fileTimestamp}_${newSessionId}.jsonl`),header={type:"session",version:CURRENT_SESSION_VERSION,id:newSessionId,timestamp,cwd:this.cwd,parentSession:this.persist?previousSessionFile:void 0},pathEntryIds=new Set(pathWithoutLabels.map(e=>e.id)),labelsToWrite=[];for(let[targetId,label]of this.labelsById)pathEntryIds.has(targetId)&&labelsToWrite.push({targetId,label,timestamp:this.labelTimestampsById.get(targetId)});if(this.persist){let parentId2=pathWithoutLabels[pathWithoutLabels.length-1]?.id||null,labelEntries2=[];for(let{targetId,label,timestamp:labelTimestamp}of labelsToWrite){let labelEntry={type:"label",id:generateId(new Set(pathEntryIds)),parentId:parentId2,timestamp:labelTimestamp,targetId,label};pathEntryIds.add(labelEntry.id),labelEntries2.push(labelEntry),parentId2=labelEntry.id}reserveSessionWrite(newSessionFile);let branchedEntries2=this._materializeEntries([...pathWithoutLabels,...labelEntries2]),previousBlobsDir=this.residentStore.resolvedBlobsDir();return this.residentStore.clear(),previousBlobsDir&&this._removeBlobsDir(previousBlobsDir),this.mirrorTrimmed=!1,this.trimmedIds.clear(),this.durable=void 0,this.sessionId=newSessionId,this.sessionFile=newSessionFile,this.fileEntries=[header,...branchedEntries2.map(entry=>this.residentStore.externalize(entry))],this._buildIndex(),this.historyGeneration++,this.mutationCount++,this._hasConversation()?(this._rewriteFile(),this.flushed=!0):this.flushed=!1,this._journalReplace(),newSessionFile}let labelEntries=[],parentId=pathWithoutLabels[pathWithoutLabels.length-1]?.id||null;for(let{targetId,label,timestamp:labelTimestamp}of labelsToWrite){let labelEntry={type:"label",id:generateId(new Set([...pathEntryIds,...labelEntries.map(e=>e.id)])),parentId,timestamp:labelTimestamp,targetId,label};labelEntries.push(labelEntry),parentId=labelEntry.id}let branchedEntries=this._materializeEntries([...pathWithoutLabels,...labelEntries]);this.residentStore.clear(),this.fileEntries=[header,...branchedEntries.map(entry=>this.residentStore.externalize(entry))],this.sessionId=newSessionId,this._buildIndex(),this.historyGeneration++,this.mutationCount++,this._journalReplace()}static create(cwd,sessionDir,options){let dir=sessionDir?normalizePath(sessionDir):getDefaultSessionDir(cwd);return new _SessionManager(cwd,dir,void 0,!0,options)}static open(path,sessionDir,cwdOverride,options){let resolvedPath=resolvePath(path);reserveSessionWrite(resolvedPath);let discovery=discoverOpenHeader(resolvedPath,cwdOverride),preloadedFileEntries=discovery.needsFullLoad?loadEntriesFromFile(resolvedPath,compactUpdatesEnabled()):void 0,header=discovery.header??headerOf(preloadedFileEntries),{cwd,dir}=openLocation(resolvedPath,sessionDir,cwdOverride,header);return new _SessionManager(cwd,dir,resolvedPath,!0,options,preloadedFileEntries)}static async openAsync(path,sessionDir,cwdOverride,options,slicer=new EventLoopSlicer){let resolvedPath=resolvePath(path);reserveSessionWrite(resolvedPath);let discovery=discoverOpenHeader(resolvedPath,cwdOverride),preloadedFileEntries=discovery.needsFullLoad?await loadEntriesFromFileAsync(resolvedPath,slicer,compactUpdatesEnabled()):void 0,header=discovery.header??headerOf(preloadedFileEntries),{cwd,dir}=openLocation(resolvedPath,sessionDir,cwdOverride,header),manager=new _SessionManager(cwd,dir,resolvedPath,!0,options,DEFERRED_FILE_LOAD);try{await manager._setSessionFileAsync(resolvedPath,preloadedFileEntries,options,slicer)}catch(error){throw manager.dispose(),error}return manager}static continueRecent(cwd,sessionDir){let dir=sessionDir?normalizePath(sessionDir):getDefaultSessionDir(cwd),mostRecent=_SessionManager.recentSessionFile(cwd,sessionDir);return mostRecent?new _SessionManager(cwd,dir,mostRecent,!0):new _SessionManager(cwd,dir,void 0,!0)}static recentSessionFile(cwd,sessionDir){let dir=sessionDir?normalizePath(sessionDir):getDefaultSessionDir(cwd),filterCwd=sessionDir!==void 0&&dir!==getDefaultSessionDirPath(cwd);return findMostRecentSession(dir,filterCwd?cwd:void 0)}static inMemory(cwd=process.cwd(),options,entries){return new _SessionManager(cwd,"",void 0,!1,options,entries)}static forkFrom(sourcePath,targetCwd,sessionDir,options){let resolvedSourcePath=resolvePath(sourcePath),resolvedTargetCwd=resolvePath(targetCwd),source=readForkSource(resolvedSourcePath);if(source.kind==="empty")throw new Error(`Cannot fork: source session file is empty or has no readable entries: ${resolvedSourcePath}`);if(source.kind==="not-a-session")throw new Error(`Cannot fork: source file is not a session file (no entry has a session header or a session entry shape): ${resolvedSourcePath}`);let sourceEntries=source.entries,dir=sessionDir?normalizePath(sessionDir):getDefaultSessionDir(resolvedTargetCwd);existsSync3(dir)||mkdirSync2(dir,{recursive:!0}),options?.id!==void 0&&assertValidSessionId(options.id);let newSessionId=options?.id??createSessionId(),timestamp=new Date().toISOString(),fileTimestamp=timestamp.replace(/[:.]/g,"-"),newSessionFile=join5(dir,`${fileTimestamp}_${newSessionId}.jsonl`),newHeader={type:"session",version:CURRENT_SESSION_VERSION,id:newSessionId,timestamp,cwd:resolvedTargetCwd,parentSession:resolvedSourcePath};reserveSessionWrite(newSessionFile),writeFileSync2(newSessionFile,`${JSON.stringify(newHeader)}
36
36
  `,{flag:"wx"});for(let entry of sourceEntries)entry.type!=="session"&&appendFileSync(newSessionFile,`${JSON.stringify(entry)}
37
- `);return new _SessionManager(resolvedTargetCwd,dir,newSessionFile,!0)}static findById(cwd,id,sessionDir){let dir=sessionDir?normalizePath(sessionDir):getDefaultSessionDir(cwd),filterCwd=sessionDir!==void 0&&dir!==getDefaultSessionDirPath(cwd),matchesCwd=sessionCwdMatcher(resolvePath(cwd));try{for(let file of readdirSync(dir)){if(!file.endsWith(".jsonl"))continue;let path=join5(dir,file),header=readSessionHeaderForDiscovery(path);if(header?.id===id&&!(filterCwd&&!matchesCwd(getSessionHeaderCwd(header))))return path}}catch{}}static async list(cwd,sessionDir,onProgress,signal){let dir=sessionDir?normalizePath(sessionDir):getDefaultSessionDir(cwd),filterCwd=sessionDir!==void 0&&dir!==getDefaultSessionDirPath(cwd),matchesCwd=sessionCwdMatcher(resolvePath(cwd)),includeSession=session=>!filterCwd||matchesCwd(session.cwd),sessions=(await listSessionsFromDir(dir,onProgress?(loaded,total,partialSessions)=>onProgress(loaded,total,partialSessions?.filter(includeSession)):void 0,signal)).filter(includeSession);return sortSessionInfos(sessions)}static async listAll(sessionDirOrOnProgress,onProgressOrSignal,signal){let customSessionDir=typeof sessionDirOrOnProgress=="string"?normalizePath(sessionDirOrOnProgress):void 0,progress=typeof sessionDirOrOnProgress=="function"?sessionDirOrOnProgress:typeof onProgressOrSignal=="function"?onProgressOrSignal:void 0,abortSignal=typeof sessionDirOrOnProgress=="string"||typeof onProgressOrSignal=="function"?signal:onProgressOrSignal??signal;if(abortSignal?.throwIfAborted(),customSessionDir)return sortSessionInfos(await listSessionsFromDir(customSessionDir,progress,abortSignal));let sessionsDir=getSessionsDir();try{if(!existsSync3(sessionsDir))return[];let dirs=(await readdir2(sessionsDir,{withFileTypes:!0})).filter(entry=>entry.isDirectory()||entry.isSymbolicLink()).map(entry=>join5(sessionsDir,entry.name)),totalFiles=0,dirFiles=[];for(let dir of dirs)try{let files=(await readdir2(dir)).filter(f=>f.endsWith(".jsonl"));dirFiles.push(files.map(f=>join5(dir,f))),totalFiles+=files.length}catch{dirFiles.push([])}let loaded=0,partialSessions=[],onLoaded=info=>{loaded++,info&&partialSessions.push(info);let publish=loaded===1||loaded%ALL_SESSION_LIST_PUBLISH_INTERVAL===0||loaded===totalFiles;progress?.(loaded,totalFiles,publish?sortSessionInfos([...partialSessions]):void 0)},sessions=[];for(let[index,dir]of dirs.entries())sessions.push(...await listSessionFilesInDir(dir,dirFiles[index]??[],onLoaded,abortSignal));return sortSessionInfos(sessions)}catch{return abortSignal?.throwIfAborted(),[]}}};export{VIRTUAL_MODEL_STATE_ENTRY,isVirtualModel,findLatestResponse,getBranchSelection,getVirtualModelState,createVirtualModel,withVirtualModels,hasUnsafeRetainedContent,isSafeBoundedValue,sessionCwdMatcher,REPOSITORY_IDENTITY_ENTRY_TYPE,readRepositoryIdentity,compareRepositoryIdentities,parseRepositoryIdentity,sameRepositoryIdentity,parseEntryLine,readFileLines,listSessionsFromDir,SESSION_RELEASED,SESSION_MOVED_IN,SESSION_MOVED,SESSION_RECLAIMED,ownershipStep,headerSessionId,sessionOwnership,SessionMovedAwayError,reserveSessionWrite,unregisterSessionWriter,resolveEnvironmentContext,environmentContextMessageIfChanged,imageContentId,elidedImageIds,rejectedImageSources,GOAL_CONTINUATION_MESSAGE_TYPE,isContextExcludedCustomMessage,createBranchSummaryMessage,createCompactionSummaryMessage,createCustomMessage,convertToLlm,TRANSPORT_IMAGE_BUDGET_BYTES,convertToLlmForTransport,SESSION_CONTEXT_ENTRY_ID,getSessionContextEntryId,inheritSessionContextEntryId,CURRENT_SESSION_VERSION,sessionFileNameId,assertValidSessionId,migrateSessionEntries,parseSessionEntries,getLatestCompactionEntry,sessionEntryToContextMessages,buildContextEntries,buildSessionProjection,buildSessionContext,getDefaultSessionDir,findMostRecentSession,SessionManager};
37
+ `);return new _SessionManager(resolvedTargetCwd,dir,newSessionFile,!0)}static findById(cwd,id,sessionDir){let dir=sessionDir?normalizePath(sessionDir):getDefaultSessionDir(cwd),filterCwd=sessionDir!==void 0&&dir!==getDefaultSessionDirPath(cwd),matchesCwd=sessionCwdMatcher(resolvePath(cwd));try{for(let file of readdirSync(dir)){if(!file.endsWith(".jsonl"))continue;let path=join5(dir,file),header=readSessionHeaderForDiscovery(path);if(header?.id===id&&!(filterCwd&&!matchesCwd(getSessionHeaderCwd(header))))return path}}catch{}}static async list(cwd,sessionDir,onProgress,signal){let dir=sessionDir?normalizePath(sessionDir):getDefaultSessionDir(cwd),filterCwd=sessionDir!==void 0&&dir!==getDefaultSessionDirPath(cwd),matchesCwd=sessionCwdMatcher(resolvePath(cwd)),includeSession=session=>!filterCwd||matchesCwd(session.cwd),sessions=(await listSessionsFromDir(dir,onProgress?(loaded,total,partialSessions)=>onProgress(loaded,total,partialSessions?.filter(includeSession)):void 0,signal)).filter(includeSession);return sortSessionInfos(sessions)}static async listAll(sessionDirOrOnProgress,onProgressOrSignal,signal){let customSessionDir=typeof sessionDirOrOnProgress=="string"?normalizePath(sessionDirOrOnProgress):void 0,progress=typeof sessionDirOrOnProgress=="function"?sessionDirOrOnProgress:typeof onProgressOrSignal=="function"?onProgressOrSignal:void 0,abortSignal=typeof sessionDirOrOnProgress=="string"||typeof onProgressOrSignal=="function"?signal:onProgressOrSignal??signal;if(abortSignal?.throwIfAborted(),customSessionDir)return sortSessionInfos(await listSessionsFromDir(customSessionDir,progress,abortSignal));let sessionsDir=getSessionsDir();try{if(!existsSync3(sessionsDir))return[];let dirs=(await readdir2(sessionsDir,{withFileTypes:!0})).filter(entry=>entry.isDirectory()||entry.isSymbolicLink()).map(entry=>join5(sessionsDir,entry.name)),totalFiles=0,dirFiles=[];for(let dir of dirs)try{let files=(await readdir2(dir)).filter(f=>f.endsWith(".jsonl"));dirFiles.push(files.map(f=>join5(dir,f))),totalFiles+=files.length}catch{dirFiles.push([])}let loaded=0,partialSessions=[],onLoaded=info=>{loaded++,info&&partialSessions.push(info);let publish=loaded===1||loaded%ALL_SESSION_LIST_PUBLISH_INTERVAL===0||loaded===totalFiles;progress?.(loaded,totalFiles,publish?sortSessionInfos([...partialSessions]):void 0)},sessions=[];for(let[index,dir]of dirs.entries())sessions.push(...await listSessionFilesInDir(dir,dirFiles[index]??[],onLoaded,abortSignal));return sortSessionInfos(sessions)}catch{return abortSignal?.throwIfAborted(),[]}}};export{VIRTUAL_MODEL_STATE_ENTRY,isVirtualModel,findLatestResponse,getBranchSelection,getVirtualModelState,createVirtualModel,withVirtualModels,hasUnsafeRetainedContent,isSafeBoundedValue,sessionCwdMatcher,REPOSITORY_IDENTITY_ENTRY_TYPE,readRepositoryIdentity,compareRepositoryIdentities,parseRepositoryIdentity,sameRepositoryIdentity,readFileLines,listSessionsFromDir,SESSION_RELEASED,SESSION_MOVED_IN,SESSION_MOVED,SESSION_RECLAIMED,ownershipStep,headerSessionId,sessionOwnership,SessionMovedAwayError,reserveSessionWrite,unregisterSessionWriter,resolveEnvironmentContext,environmentContextMessageIfChanged,imageContentId,elidedImageIds,rejectedImageSources,GOAL_CONTINUATION_MESSAGE_TYPE,isContextExcludedCustomMessage,createBranchSummaryMessage,createCompactionSummaryMessage,createCustomMessage,convertToLlm,TRANSPORT_IMAGE_BUDGET_BYTES,convertToLlmForTransport,SESSION_CONTEXT_ENTRY_ID,getSessionContextEntryId,inheritSessionContextEntryId,CURRENT_SESSION_VERSION,sessionFileNameId,assertValidSessionId,migrateSessionEntries,parseSessionEntries,getLatestCompactionEntry,sessionEntryToContextMessages,buildContextEntries,buildSessionProjection,buildSessionContext,getDefaultSessionDir,findMostRecentSession,SessionManager};