@code-yeongyu/senpi 2026.10.19-2 → 2026.10.20-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/bundle/chunks/{anthropic-messages-VVRTT7O5.js → anthropic-messages-3QYMAEH2.js} +1 -1
  3. package/dist/bundle/chunks/{args-35XTBPC7.js → args-NHDT5JG3.js} +1 -1
  4. package/dist/bundle/chunks/{azure-openai-responses-BUSMTCQ5.js → azure-openai-responses-2DCY6QKO.js} +1 -1
  5. package/dist/bundle/chunks/chunk-2JGY3V4H.js +395 -0
  6. package/dist/bundle/chunks/{chunk-2RLZXLXS.js → chunk-2LQZJFKQ.js} +1 -1
  7. package/dist/bundle/chunks/{chunk-2IK7QUJX.js → chunk-2SM4TR4H.js} +1 -1
  8. package/dist/bundle/chunks/{chunk-DXOSXUVI.js → chunk-3YKKXTJM.js} +1 -1
  9. package/dist/bundle/chunks/chunk-6L3H4UVN.js +2 -0
  10. package/dist/bundle/chunks/{chunk-46NW3UKO.js → chunk-7R4CJDWT.js} +1 -1
  11. package/dist/bundle/chunks/chunk-AA2L2RHH.js +2 -0
  12. package/dist/bundle/chunks/chunk-DKBJM22C.js +5 -0
  13. package/dist/bundle/chunks/{chunk-Z32CYNHC.js → chunk-F4YDU66P.js} +1 -1
  14. package/dist/bundle/chunks/chunk-FC2YWHEC.js +6 -0
  15. package/dist/bundle/chunks/{chunk-T2EE5G4S.js → chunk-FRFGJC3I.js} +1 -1
  16. package/dist/bundle/chunks/{chunk-57RKQONO.js → chunk-GBAS4FFM.js} +1 -1
  17. package/dist/bundle/chunks/{chunk-FDCYQYBP.js → chunk-JVLIKUBL.js} +1 -1
  18. package/dist/bundle/chunks/{chunk-EKDY4H2J.js → chunk-JXCHRJA7.js} +1 -1
  19. package/dist/bundle/chunks/{chunk-YID5W42N.js → chunk-KXTWMPCP.js} +1 -1
  20. package/dist/bundle/chunks/{chunk-ADNKYKU4.js → chunk-RYQ2FFF5.js} +1 -1
  21. package/dist/bundle/chunks/chunk-SOMFLLPD.js +3 -0
  22. package/dist/bundle/chunks/{chunk-4CJJ4SK6.js → chunk-SOWFP3I7.js} +1 -1
  23. package/dist/bundle/chunks/{chunk-GX7MTG25.js → chunk-TK6RKAB4.js} +4 -4
  24. package/dist/bundle/chunks/{chunk-NN44F5QF.js → chunk-V6RY5A6T.js} +1 -1
  25. package/dist/bundle/chunks/{chunk-77PVTNLJ.js → chunk-W557SQYL.js} +2 -2
  26. package/dist/bundle/chunks/{chunk-F4ZU4RBE.js → chunk-YIRQJCPA.js} +45 -46
  27. package/dist/bundle/chunks/cli-main-JCQTFUHO.js +3 -0
  28. package/dist/bundle/chunks/cloudflare-workers-ai-system-one-4QEQ7MGK.js +1 -1
  29. package/dist/bundle/chunks/{dispatch-R37L3FW5.js → dispatch-YPCDRQYI.js} +1 -1
  30. package/dist/bundle/chunks/{google-generative-ai-4UOGH7RT.js → google-generative-ai-3SKUSCIL.js} +1 -1
  31. package/dist/bundle/chunks/{google-vertex-2A6KZ5TX.js → google-vertex-YHSIIE4G.js} +1 -1
  32. package/dist/bundle/chunks/{help-fast-path-Z5JGXNCS.js → help-fast-path-TUCMQOOF.js} +1 -1
  33. package/dist/bundle/chunks/{host-command-IP3QAZYI.js → host-command-WEOS6VD6.js} +1 -1
  34. package/dist/bundle/chunks/{host-lifecycle-FRQK5GAC.js → host-lifecycle-ZDCO62Z4.js} +1 -1
  35. package/dist/bundle/chunks/host-lifecycle.js +6 -6
  36. package/dist/bundle/chunks/host-session-command-IGTNZ4F6.js +20 -0
  37. package/dist/bundle/chunks/interactive-mode-5KYT7LMW.js +2 -0
  38. package/dist/bundle/chunks/{multi-session-host-EMI54PTJ.js → multi-session-host-25XQFXJC.js} +5 -5
  39. package/dist/bundle/chunks/openai-codex-responses-4BIPACKV.js +10 -0
  40. package/dist/bundle/chunks/{openai-completions-AGTH2RRA.js → openai-completions-NHDMDAS7.js} +1 -1
  41. package/dist/bundle/chunks/{openai-images-5UGZHY27.js → openai-images-PNXQDBSP.js} +1 -1
  42. package/dist/bundle/chunks/{openai-responses-KGXDGHPI.js → openai-responses-2UOPEJLP.js} +1 -1
  43. package/dist/bundle/chunks/{package-manager-cli-TK44VHGK.js → package-manager-cli-CF53LR5X.js} +1 -1
  44. package/dist/bundle/chunks/{role-F6IEUF2N.js → role-OK7RKBGF.js} +1 -1
  45. package/dist/bundle/chunks/{rotation-stream-XX2NXYL3.js → rotation-stream-QRRJ7G5Y.js} +1 -1
  46. package/dist/bundle/chunks/rpc-mode-LOODTK3J.js +2 -0
  47. package/dist/bundle/chunks/{schedule-command-DYHRFIX2.js → schedule-command-LKL6DLOT.js} +1 -1
  48. package/dist/bundle/chunks/session-control-endpoint-MLANJVB2.js +3 -0
  49. package/dist/bundle/chunks/session-picker-RQDVWJRL.js +2 -0
  50. package/dist/bundle/chunks/session-worker.js +240 -240
  51. package/dist/bundle/chunks/session-write-fence-66EMOO4Y.js +2 -0
  52. package/dist/bundle/chunks/typesafe-system-one-W2ZTYF7X.js +1 -1
  53. package/dist/bundle/cli.js +2 -2
  54. package/dist/bundle/host-supervisor.js +6 -6
  55. package/dist/bundle/index.js +1 -1
  56. package/dist/bundle/rpc-entry.js +1 -1
  57. package/dist/bundle/runtime-manifest.json +1 -1
  58. package/dist/core/agent-session.d.ts +0 -2
  59. package/dist/core/agent-session.js +4 -13
  60. package/dist/core/credential-pool/classify.d.ts +7 -0
  61. package/dist/core/credential-pool/classify.js +12 -4
  62. package/dist/core/credential-pool/failover.js +16 -1
  63. package/dist/core/credential-pool/rotation-stream.js +2 -0
  64. package/dist/core/extensions/builtin/anthropic-subscription/auth-lane.js +8 -62
  65. package/dist/core/extensions/builtin/anthropic-subscription/context-window.d.ts +25 -0
  66. package/dist/core/extensions/builtin/anthropic-subscription/context-window.js +38 -0
  67. package/dist/core/extensions/builtin/anthropic-subscription/index.d.ts +2 -2
  68. package/dist/core/extensions/builtin/anthropic-subscription/index.js +4 -6
  69. package/dist/core/extensions/builtin/anthropic-subscription/long-context-retry.d.ts +18 -0
  70. package/dist/core/extensions/builtin/anthropic-subscription/long-context-retry.js +74 -0
  71. package/dist/core/extensions/builtin/anthropic-subscription/long-context.js +13 -5
  72. package/dist/core/extensions/builtin/anthropic-subscription/options.d.ts +0 -10
  73. package/dist/core/extensions/builtin/anthropic-subscription/options.js +8 -16
  74. package/dist/core/extensions/builtin/anthropic-subscription/session-registry-wiring.js +1 -1
  75. package/dist/core/extensions/builtin/anthropic-subscription/session-sync.js +3 -0
  76. package/dist/core/extensions/builtin/terminal/lease-file.d.ts +1 -0
  77. package/dist/core/extensions/builtin/terminal/lease-file.js +5 -3
  78. package/dist/core/foreign-session-holders.d.ts +2 -3
  79. package/dist/core/provider-failure.d.ts +2 -0
  80. package/dist/core/provider-failure.js +3 -0
  81. package/dist/core/reserved-keywords.js +1 -1
  82. package/dist/core/session-hold-errors.d.ts +2 -0
  83. package/dist/core/session-holder-records.d.ts +21 -0
  84. package/dist/core/session-holder-records.js +76 -0
  85. package/dist/core/session-holders.d.ts +3 -3
  86. package/dist/core/session-holders.js +4 -41
  87. package/dist/core/session-manager.d.ts +1 -0
  88. package/dist/core/session-manager.js +8 -1
  89. package/dist/core/session-write-fence.d.ts +18 -0
  90. package/dist/core/session-write-fence.js +71 -0
  91. package/dist/core/user-text-blocks.d.ts +11 -0
  92. package/dist/core/user-text-blocks.js +19 -1
  93. package/dist/modes/rpc/host-daemon-registration.js +2 -1
  94. package/dist/modes/rpc/host-generations.d.ts +6 -0
  95. package/dist/modes/rpc/host-generations.js +35 -4
  96. package/dist/modes/rpc/host-lifecycle-scratch.d.ts +9 -2
  97. package/dist/modes/rpc/host-lifecycle-scratch.js +26 -6
  98. package/dist/modes/rpc/host-lifecycle.js +1 -1
  99. package/dist/modes/rpc/host-reservations.d.ts +5 -0
  100. package/dist/modes/rpc/host-reservations.js +54 -12
  101. package/dist/modes/rpc/host-stalled-evidence.d.ts +27 -1
  102. package/dist/modes/rpc/host-stalled-evidence.js +52 -4
  103. package/dist/modes/rpc/multi-session-host.js +10 -1
  104. package/dist/modes/rpc/session-command-router.js +2 -0
  105. package/dist/modes/rpc/session-held.js +2 -0
  106. package/package.json +6 -6
  107. package/dist/bundle/chunks/chunk-74V6LCWU.js +0 -2
  108. package/dist/bundle/chunks/chunk-DDQJSVIZ.js +0 -5
  109. package/dist/bundle/chunks/chunk-DY2EM44T.js +0 -395
  110. package/dist/bundle/chunks/chunk-HOXW5IHD.js +0 -6
  111. package/dist/bundle/chunks/chunk-UAQW2T7G.js +0 -2
  112. package/dist/bundle/chunks/cli-main-RXZVFXK7.js +0 -3
  113. package/dist/bundle/chunks/host-session-command-KGCQPMES.js +0 -20
  114. package/dist/bundle/chunks/interactive-mode-DQOPIZSI.js +0 -2
  115. package/dist/bundle/chunks/openai-codex-responses-I2NSK6AD.js +0 -10
  116. package/dist/bundle/chunks/rpc-mode-X6J3FC3N.js +0 -2
  117. package/dist/bundle/chunks/session-control-endpoint-XN4BAZTU.js +0 -3
  118. package/dist/bundle/chunks/session-picker-US5YPKC7.js +0 -2
  119. /package/dist/bundle/chunks/{chunk-KW6654UH.js → chunk-RPAHOJ6F.js} +0 -0
@@ -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-ZMS6YEAO.js";import{dropFailedAssistantTurns}from"./chunk-2IK7QUJX.js";import{CONTEXT_PROVENANCE_FIELD,contextProvenanceFingerprint,copyContextProvenance,getContextProvenance}from"./chunk-XSRM367N.js";import{getCurrentSystemMessage,isModelType,lazyStream,normalizeProviderId}from"./chunk-LAWS3FYQ.js";import{APP_NAME,getAgentDir,getSessionsDir,normalizePath,resolvePath}from"./chunk-4J4ABCCL.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";function resolveEnvironmentContext(cwd,now=new Date){return{cwd:cwd.replace(/\\/g,"/"),currentDate: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{resolveMovedPath}from"./chunk-ZMS6YEAO.js";import{SessionWriteFence}from"./chunk-SOMFLLPD.js";import{dropFailedAssistantTurns}from"./chunk-2SM4TR4H.js";import{CONTEXT_PROVENANCE_FIELD,contextProvenanceFingerprint,copyContextProvenance,getContextProvenance}from"./chunk-XSRM367N.js";import{getCurrentSystemMessage,isModelType,lazyStream,normalizeProviderId}from"./chunk-LAWS3FYQ.js";import{APP_NAME,getAgentDir,getSessionsDir,normalizePath,resolvePath}from"./chunk-4J4ABCCL.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";function resolveEnvironmentContext(cwd,now=new Date){return{cwd:cwd.replace(/\\/g,"/"),currentDate: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}})}function isUserWord(value){return typeof value=="object"&&value!==null&&"label"in value&&typeof value.label=="string"&&"text"in value&&typeof value.text=="string"}function toolResultUserWords(message){let details=message.details;return typeof details!="object"||details===null||!("userWords"in details)?[]:Array.isArray(details.userWords)?details.userWords.filter(isUserWord):[]}function userWordBlocks(words){return words.flatMap(word=>[{type:"text",text:`[${word.label}]`},{type:"text",text:word.text}])}function appendToolResultUserWords(messages){if(!messages.some(message=>message.role==="toolResult"&&toolResultUserWords(message).length>0))return messages;let result=[],pending=[],source,flush=next=>{source&&!startsWithBlocks(next,pending)&&result.push(wordMessage(pending,source)),pending=[],source=void 0};for(let message of messages){if(message.role!=="toolResult"&&flush(message),result.push(message),message.role!=="toolResult")continue;let blocks=userWordBlocks(toolResultUserWords(message));blocks.length!==0&&(pending.push(...blocks),source=message)}return flush(void 0),result}function wordMessage(content,source){let message={role:"user",content,timestamp:source.timestamp},provenance=getContextProvenance(source);if(!provenance)return message;let{integrity,...owned}=provenance;if(!(integrity===void 0||integrity===contextProvenanceFingerprint(source)))return message;let sealed=integrity===void 0?owned:{...owned,integrity:contextProvenanceFingerprint(message)};return Object.assign(message,{[CONTEXT_PROVENANCE_FIELD]:sealed})}function startsWithBlocks(message,blocks){if(message?.role!=="user"||typeof message.content=="string")return!1;let content=message.content;return blocks.every((block,index)=>{let candidate=content[index];return candidate?.type==="text"&&candidate.text===block.text})}var COMPACTION_SUMMARY_PREFIX=`The conversation history before this point was compacted into the following summary:
4
4
 
5
5
  <summary>
@@ -30,9 +30,9 @@ Command exited with code ${msg.exitCode}`),msg.truncated&&msg.fullOutputPath&&(t
30
30
  `,size)}finally{closeSync(fd)}}function finalSegmentStart(fd,size){let chunk=Buffer.alloc(Math.min(65536,size)),end=size;for(;end>0;){let start=Math.max(0,end-chunk.length),read=readSync(fd,chunk,0,end-start,start),newline=chunk.subarray(0,read).lastIndexOf(10);if(newline>=0)return start+newline+1;end=start}return 0}function materializeSessionEntries(entries,options){let{residentStore,loadHistoryEntries,onMaterialized}=options,missingEntryIds=new Set,materialized=entries.map(entry=>residentStore.materialize(entry,()=>{missingEntryIds.add(entry.id)}));if(missingEntryIds.size===0){for(let entry of materialized)onMaterialized(entry);return materialized}let persistedById=new Map(loadHistoryEntries().filter(entry=>entry.type!=="session").map(entry=>[entry.id,entry])),repaired=materialized.map(entry=>{if(!missingEntryIds.has(entry.id))return entry;let persisted=persistedById.get(entry.id);return persisted===void 0?entry:residentStore.materialize(persisted)});for(let entry of repaired)onMaterialized(entry);return repaired}import{randomUUID}from"node:crypto";import{closeSync as closeSync2,fchmodSync,fsyncSync,openSync as openSync2,realpathSync,renameSync,rmSync,statSync as statSync2,writeFileSync}from"node:fs";import{basename as basename2,dirname,join as join3}from"node:path";var UNSUPPORTED_DIRECTORY_SYNC=new Set(["EINVAL","ENOTSUP","EOPNOTSUPP","EISDIR"]),DIRECTORY_NOT_WRITABLE=new Set(["EACCES","EPERM","EROFS"]);function errnoCode(error){return error instanceof Error&&"code"in error&&typeof error.code=="string"?error.code:void 0}function resolveTarget(filePath){try{let path=realpathSync(filePath);return{path,mode:statSync2(path).mode&4095}}catch(error){if(errnoCode(error)==="ENOENT")return{path:filePath,mode:void 0};throw error}}function openTemp(tempPath){try{return openSync2(tempPath,"wx")}catch(error){let code=errnoCode(error);if(code!==void 0&&DIRECTORY_NOT_WRITABLE.has(code))return;throw error}}function rewriteInPlace(path,chunks){let fd=openSync2(path,"w");try{for(let chunk of chunks)writeFileSync(fd,chunk)}finally{closeSync2(fd)}}function writeDurably(fd,chunks,mode){try{mode!==void 0&&fchmodSync(fd,mode);for(let chunk of chunks)writeFileSync(fd,chunk);fsyncSync(fd)}finally{closeSync2(fd)}}function syncDirectory(directory){if(process.platform==="win32")return;let fd=openSync2(directory,"r");try{fsyncSync(fd)}catch(error){let code=errnoCode(error);if(code===void 0||!UNSUPPORTED_DIRECTORY_SYNC.has(code))throw error}finally{closeSync2(fd)}}function replaceFileAtomically(filePath,chunks){let target=resolveTarget(filePath),tempPath=join3(dirname(target.path),`.${basename2(target.path)}.${randomUUID()}.tmp`),tempFd=openTemp(tempPath);if(tempFd===void 0){rewriteInPlace(target.path,chunks);return}try{writeDurably(tempFd,chunks,target.mode),renameSync(tempPath,target.path)}catch(error){try{rmSync(tempPath,{force:!0})}catch(cleanupError){throw new AggregateError([error,cleanupError],"session file rewrite failed and its temporary file could not be removed")}throw error}syncDirectory(dirname(target.path))}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 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}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.current(entries);if(!ownership.writable&&ownershipStep(ownership,entry,this.sessionId).kind!=="apply")throw new SessionMovedAwayError(sessionFile,ownership)}assertRewritable(entries,sessionFile){let ownership=this.current(entries);if(!ownership.writable)throw new SessionMovedAwayError(sessionFile,ownership)}isWritable(entries){return this.current(entries).writable}current(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 existsSync3,mkdirSync,readFileSync,renameSync as renameSync2,rmSync as rmSync2,writeFileSync as writeFileSync2}from"node:fs";import{join as join4}from"node:path";import{Buffer as Buffer2}from"buffer";var ResidentSizeAccounting=class{constructor(){this.bytes=0,this.evictedCount=0,this.evictedBytes=0}get residentBytes(){return this.bytes}added(text){this.bytes+=Buffer2.byteLength(text,"utf8")}removed(text){this.bytes-=Buffer2.byteLength(text,"utf8")}evicted(text){this.evictedCount++,this.evictedBytes+=Buffer2.byteLength(text,"utf8")}reset(){this.bytes=0,this.evictedCount=0,this.evictedBytes=0}stats(){return{blobBytes:this.bytes,evictedCount:this.evictedCount,evictedBytes:this.evictedBytes}}};var RESIDENT_STRING_MIN_BYTES=32*1024,DEFAULT_RESIDENT_STRING_BUDGET_BYTES=64*1024*1024,RESIDENT_STRING_PREFIX="\0senpi-resident-string:v1:",ResidentStringStore=class{constructor(options={}){this.tokenFree=new WeakSet,this.strings=new Map,this.accounting=new ResidentSizeAccounting,this.maxBytes=options.maxBytes??DEFAULT_RESIDENT_STRING_BUDGET_BYTES,this.blobsDir=options.blobsDir}configure(options){this.blobsDir=options.blobsDir}clear(){this.strings.clear(),this.accounting.reset();let dir=this.blobsDir?.();if(dir)try{rmSync2(dir,{force:!0,recursive:!0})}catch{}}spillResident(){if(this.blobsDir?.())for(let[id,text]of this.strings)this._writeBlob(id,text)&&(this.strings.delete(id),this.accounting.removed(text))}stats(){return{blobCount:this.strings.size,...this.accounting.stats()}}size(){return{entries:this.strings.size,approxBytes:this.accounting.residentBytes}}externalize(value){let tokenized=!1,externalized=transformJson(value,text=>{let stored=this.externalizeString(text);return stored.startsWith(RESIDENT_STRING_PREFIX)&&(tokenized=!0),stored});return!tokenized&&typeof externalized=="object"&&externalized!==null&&this.tokenFree.add(externalized),externalized}materialize(value,onMissing){return typeof value=="object"&&value!==null&&this.tokenFree.has(value)?value:transformJson(value,text=>this.materializeString(text,onMissing))}isTokenFree(value){return this.tokenFree.has(value)}adoptTokenFree(value){this.tokenFree.add(value)}resolvedBlobsDir(){return this.blobsDir?.()}externalizeInPlace(value){this._mutateStringsInPlace(value,new Set,text=>this.externalizeString(text))}materializeInPlace(value){this._mutateStringsInPlace(value,new Set,text=>this.materializeString(text))}_mutateStringsInPlace(value,seen,mutate){if(typeof value!="object"||value===null||seen.has(value))return;seen.add(value);let record=value;for(let key of Object.keys(record)){let current=record[key];if(typeof current=="string"){let next=mutate(current);next!==current&&(record[key]=next)}else typeof current=="object"&&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=join4(dir,`${id}.blob`),temp=`${final}.tmp`;try{mkdirSync(dir,{recursive:!0}),existsSync3(final)||(writeFileSync2(temp,JSON.stringify({v:1,text}),"utf8"),renameSync2(temp,final))}catch{try{rmSync2(temp,{force:!0})}catch{}return!1}return this.accounting.evicted(text),!0}_readBlob(id){let dir=this.blobsDir?.();if(!dir)return;let file=join4(dir,`${id}.blob`);try{let parsed=JSON.parse(readFileSync(file,"utf8"));if(typeof parsed.text=="string")return parsed.text}catch{}try{rmSync2(file,{force:!0})}catch{}}};import{closeSync as closeSync3,fstatSync as fstatSync2,ftruncateSync as ftruncateSync2,openSync as openSync3,readSync as readSync2,rmSync as rmSync3}from"node:fs";import{rm as rm2}from"node:fs/promises";var NEWLINE=10,SCAN_CHUNK_BYTES=64*1024;function truncateToLastCompleteLine(path){let fd=openSync3(path,"r+");try{let size=fstatSync2(fd).size,chunk=Buffer.alloc(Math.min(SCAN_CHUNK_BYTES,size)),end=size;for(;end>0;){let start=Math.max(0,end-chunk.length),read=readSync2(fd,chunk,0,end-start,start),newline=chunk.subarray(0,read).lastIndexOf(NEWLINE);if(newline>=0){let completeLength=start+newline+1;completeLength<size&&ftruncateSync2(fd,completeLength);return}end=start}}finally{closeSync3(fd)}}function discardFailedFirstFlush(path,fd,writeError){let cleanupErrors=[];try{closeSync3(fd)}catch(closeError){cleanupErrors.push(closeError)}try{rmSync3(path,{force:!0})}catch(removeError){cleanupErrors.push(removeError)}throwWriteError(path,writeError,cleanupErrors)}async function discardFailedFirstFlushAsync(path,handle,writeError){let cleanupErrors=[];if(handle!==void 0)try{await handle.close()}catch(closeError){cleanupErrors.push(closeError)}try{await rm2(path,{force:!0})}catch(removeError){cleanupErrors.push(removeError)}throwWriteError(path,writeError,cleanupErrors)}function throwWriteError(path,writeError,cleanupErrors){throw cleanupErrors.length>0?new AggregateError([writeError,...cleanupErrors],`Session file write failed and the partial file ${path} could not be cleaned up`):writeError}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()}function assertValidSessionId(id){if(!/^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/.test(id))throw new Error("Session id must be non-empty, contain only alphanumeric characters, '-', '_', and '.', and start and end with an alphanumeric character")}function generateId(byId){for(let i=0;i<100;i++){let id=randomUUID2().slice(0,8);if(!byId.has(id))return id}return randomUUID2()}function migrateV1ToV2(entries){let ids=new Set,prevId=null;for(let entry of entries){if(entry.type==="session"){entry.version=2;continue}if(entry.id=generateId(ids),entry.parentId=prevId,prevId=entry.id,entry.type==="compaction"){let comp=entry;if(typeof comp.firstKeptEntryIndex=="number"){let targetEntry=entries[comp.firstKeptEntryIndex];targetEntry&&targetEntry.type!=="session"&&(comp.firstKeptEntryId=targetEntry.id),delete comp.firstKeptEntryIndex}}}}function migrateV2ToV3(entries){for(let entry of entries){if(entry.type==="session"){entry.version=3;continue}if(entry.type==="message"){let msgEntry=entry;msgEntry.message&&msgEntry.message.role==="hookMessage"&&(msgEntry.message.role="custom")}}}function migrateToCurrentVersion(entries){let version=entries.find(e=>e.type==="session")?.version??1;return version>=CURRENT_SESSION_VERSION?!1:(version<2&&migrateV1ToV2(entries),version<3&&migrateV2ToV3(entries),!0)}function migrateSessionEntries(entries){migrateToCurrentVersion(entries)}function parseSessionEntries(content){let entries=[],lines=content.trim().split(`
31
31
  `);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 existsSync4(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=openSync4(filePath,"r");try{let decoder=new StringDecoder3("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=readSync3(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(`
32
32
  `,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(`
33
- `,lineStart)}lineChunks.push(chunk.slice(lineStart))}let probe=Buffer.allocUnsafe(1);if(readSync3(fd,probe,0,probe.length,null)===0)return lineChunks.push(decoder.end()),parseSessionHeaderCandidate(lineChunks.join(""))??null;throw new SessionHeaderScanLimitError(filePath)}finally{closeSync4(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||!existsSync4(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):resolve2(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:statSync3(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"]);function isDisposableEntry(entry){return entry.type==="custom"?entry.startupBookkeeping===!0: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.flushed=!1,this.tailMayBeTorn=!1,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.residentStore=new ResidentStringStore,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&&!existsSync4(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||!existsSync4(this.sessionFile))return;let fileEntries=loadEntriesFromFile(this.sessionFile);if(fileEntries.length===0){if(statSync3(this.sessionFile).size===0)return;throw new Error(`Session file is not a valid ${APP_NAME} session: ${this.sessionFile}`)}this._setSessionFile(this.sessionFile,fileEntries)}_loadFullMirrorFor(id){if(!(this.byId.has(id)||!this.sessionFile)){this.loadingFullMirror=!0;try{this.reloadFromDisk()}finally{this.loadingFullMirror=!1}}}setSessionFile(sessionFile){this._setSessionFile(sessionFile)}_setSessionFile(sessionFile,preloadedFileEntries,newSessionOptions){let existingFile=this._beginSessionFile(sessionFile,newSessionOptions);if(existingFile===void 0)return;let entries=preloadedFileEntries??loadEntriesFromFile(existingFile);if(!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);if(!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)}_beginSessionFile(sessionFile,newSessionOptions){let resolvedFile=resolvePath(sessionFile);if(this.persist&&reserveSessionWrite(resolvedFile),this.sessionFile=resolvedFile,this.mirrorTrimmed=!1,this.trimmedIds.clear(),this.residentStore.clear(),existsSync4(resolvedFile))return resolvedFile;this._resetToNewSession(newSessionOptions),newSessionOptions?.id!==void 0&&(this._rewriteFile(),this.flushed=!0)}_adoptFileEntries(sessionFile,entries,newSessionOptions){if(entries.length===0){if(statSync3(sessionFile).size>0)throw new Error(`Session file is not a valid ${APP_NAME} session: ${sessionFile}`);return this._resetToNewSession(newSessionOptions),this._rewriteFile(),this.flushed=!0,!1}this.fileEntries=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){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.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};return this.fileEntries=[header],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.sessionId=header.id,migrateToCurrentVersion(this.fileEntries)&&this._rewriteFile()):(this.newSession(options),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(){!this.persist||!this.sessionFile||(this.writeGuard.assertRewritable(this.fileEntries,this.sessionFile),reserveSessionWrite(this.sessionFile),replaceFileAtomically(this.sessionFile,this._serializedFileEntries()))}*_serializedFileEntries(){for(let entry of this.fileEntries)yield`${JSON.stringify(this.residentStore.materialize(entry))}
34
- `}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}getResidentStore(){return this.residentStore}getResidentStoreStats(){return this.residentStore.stats()}persistHeaderNow(){if(!this.persist||!this.sessionFile||this.flushed)return this.headerWrite??Promise.resolve();let sessionFile=this.sessionFile;return this.headerWrite??=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,!0)}async _writeHeaderAsync(sessionFile){reserveSessionWrite(sessionFile);let entries=this.fileEntries,serialize=batch=>batch.map(e=>`${JSON.stringify(this.residentStore.materialize(e))}
35
- `).join(""),written=0,handle=await open3(sessionFile,"wx");try{for(;written<entries.length;){let batch=entries.slice(written);written+=batch.length,await handle.writeFile(serialize(batch))}let closing=handle;for(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)}this.sessionFile===sessionFile&&this.fileEntries===entries&&written===entries.length&&(this.flushed=!0,this.ownedHeaderFile=sessionFile)}_hasConversation(){return this.fileEntries.some(isConversationEntry)}_persist(entry){if(!this.persist||!this.sessionFile)return;this.writeGuard.assertWritable(this.fileEntries,entry,this.sessionFile),reserveSessionWrite(this.sessionFile);let persistedEntry=this.residentStore.materialize(entry);if(this.flushed){this.tailMayBeTorn&&(truncateToLastCompleteLine(this.sessionFile),this.tailMayBeTorn=!1);try{appendFileSync(this.sessionFile,`${JSON.stringify(persistedEntry)}
33
+ `,lineStart)}lineChunks.push(chunk.slice(lineStart))}let probe=Buffer.allocUnsafe(1);if(readSync3(fd,probe,0,probe.length,null)===0)return lineChunks.push(decoder.end()),parseSessionHeaderCandidate(lineChunks.join(""))??null;throw new SessionHeaderScanLimitError(filePath)}finally{closeSync4(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||!existsSync4(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):resolve2(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:statSync3(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"]);function isDisposableEntry(entry){return entry.type==="custom"?entry.startupBookkeeping===!0: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.flushed=!1,this.tailMayBeTorn=!1,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.residentStore=new ResidentStringStore,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&&!existsSync4(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||!existsSync4(this.sessionFile))return;let fileEntries=loadEntriesFromFile(this.sessionFile);if(fileEntries.length===0){if(statSync3(this.sessionFile).size===0)return;throw new Error(`Session file is not a valid ${APP_NAME} session: ${this.sessionFile}`)}this._setSessionFile(this.sessionFile,fileEntries)}_loadFullMirrorFor(id){if(!(this.byId.has(id)||!this.sessionFile)){this.loadingFullMirror=!0;try{this.reloadFromDisk()}finally{this.loadingFullMirror=!1}}}setSessionFile(sessionFile){this._setSessionFile(sessionFile)}_setSessionFile(sessionFile,preloadedFileEntries,newSessionOptions){let existingFile=this._beginSessionFile(sessionFile,newSessionOptions);if(existingFile===void 0)return;let entries=preloadedFileEntries??loadEntriesFromFile(existingFile);if(!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);if(!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)}_beginSessionFile(sessionFile,newSessionOptions){let resolvedFile=resolvePath(sessionFile);if(this.persist&&(reserveSessionWrite(resolvedFile),this.writeFence.opened(resolvedFile)),this.sessionFile=resolvedFile,this.mirrorTrimmed=!1,this.trimmedIds.clear(),this.residentStore.clear(),existsSync4(resolvedFile))return resolvedFile;this._resetToNewSession(newSessionOptions),newSessionOptions?.id!==void 0&&(this._rewriteFile(),this.flushed=!0)}_adoptFileEntries(sessionFile,entries,newSessionOptions){if(entries.length===0){if(statSync3(sessionFile).size>0)throw new Error(`Session file is not a valid ${APP_NAME} session: ${sessionFile}`);return this._resetToNewSession(newSessionOptions),this._rewriteFile(),this.flushed=!0,!1}this.fileEntries=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){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.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};return this.fileEntries=[header],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.sessionId=header.id,migrateToCurrentVersion(this.fileEntries)&&this._rewriteFile()):(this.newSession(options),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(){!this.persist||!this.sessionFile||(this.writeGuard.assertRewritable(this.fileEntries,this.sessionFile),this.writeFence.assertOwned(this.sessionFile),reserveSessionWrite(this.sessionFile),replaceFileAtomically(this.sessionFile,this._serializedFileEntries()))}*_serializedFileEntries(){for(let entry of this.fileEntries)yield`${JSON.stringify(this.residentStore.materialize(entry))}
34
+ `}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}getResidentStore(){return this.residentStore}getResidentStoreStats(){return this.residentStore.stats()}persistHeaderNow(){if(!this.persist||!this.sessionFile||this.flushed)return this.headerWrite??Promise.resolve();let sessionFile=this.sessionFile;return this.headerWrite??=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,!0)}async _writeHeaderAsync(sessionFile){this.writeFence.assertOwned(sessionFile),reserveSessionWrite(sessionFile);let entries=this.fileEntries,serialize=batch=>batch.map(e=>`${JSON.stringify(this.residentStore.materialize(e))}
35
+ `).join(""),written=0,handle=await open3(sessionFile,"wx");try{for(;written<entries.length;){let batch=entries.slice(written);written+=batch.length,await handle.writeFile(serialize(batch))}let closing=handle;for(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)}this.sessionFile===sessionFile&&this.fileEntries===entries&&written===entries.length&&(this.flushed=!0,this.ownedHeaderFile=sessionFile)}_hasConversation(){return this.fileEntries.some(isConversationEntry)}_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 persistedEntry=this.residentStore.materialize(entry);if(this.flushed){this.tailMayBeTorn&&(truncateToLastCompleteLine(this.sessionFile),this.tailMayBeTorn=!1);try{appendFileSync(this.sessionFile,`${JSON.stringify(persistedEntry)}
36
36
  `)}catch(error){throw this.tailMayBeTorn=!0,error}return}if(!isConversationEntry(entry)&&!this._hasConversation()||this.headerWrite)return;let fd=openSync4(this.sessionFile,"wx");try{for(let e of[...this.fileEntries,entry])writeFileSync3(fd,`${JSON.stringify(this.residentStore.materialize(e))}
37
37
  `)}catch(error){discardFailedFirstFlush(this.sessionFile,fd,error)}closeSync4(fd),this.flushed=!0}_appendEntry(entry,shareable){let residentEntry=this.residentStore.externalize(entry);this._persist(residentEntry),this._commitEntry(this._shareMessage(residentEntry,shareable))}_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 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;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){return this._appendMessage(message,!0)}_appendMessage(message,owned){let entry={type:"message",id:generateId(this.idsInUse),parentId:this.leafId,timestamp:new Date().toISOString(),message};this._appendEntry(entry,owned?message:void 0);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){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}};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(),systemMessage=getCurrentSystemMessage(this.buildSessionProjection().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),this._trimMirrorAfterCompaction(entry),entry.id}dispose(){unregisterSessionWriter(this),this._releaseBlobsDirUnlessShared()}_releaseBlobsDirUnlessShared(){let blobsDir=this.residentStore.resolvedBlobsDir();blobsDir&&(this.sessionFile&&hasOtherLiveSessionWriter(this.sessionFile,this)||this._removeBlobsDir(blobsDir))}_removeBlobsDir(dir){try{rmSync4(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);firstKeptIndex>=verbatimStart&&(this.verbatimFromCount=this.fullEntryCount-(compactionIndex+1-firstKeptIndex));let header=this.fileEntries.find(entry=>entry.type==="session"),retained=[...this.fileEntries.slice(0,firstKeptIndex).filter(entry=>entry.type!=="message"),...this.fileEntries.slice(firstKeptIndex,compactionIndex+1)],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){let entry={type:"custom_message",customType,content,display,details,id:generateId(this.idsInUse),parentId:this.leafId,timestamp:new Date().toISOString()};return this._appendEntry(entry),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),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):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`);this.leafId=branchFromId,this.mutationCount++}resetLeaf(){this.leafId=null,this.mutationCount++}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};return this._appendEntry(entry),entry.id}createBranchedSession(leafId){let previousSessionFile=this.sessionFile,path=this.getFullBranch(leafId);if(path.length===0)throw new Error(`Entry ${leafId} not found`);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.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,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++}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):void 0;terminateFinalSessionLine(resolvedPath);let 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):void 0;terminateFinalSessionLine(resolvedPath);let 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),sourceEntries=loadEntriesFromFile(resolvedSourcePath);if(sourceEntries.length===0)throw new Error(`Cannot fork: source session file is empty or invalid: ${resolvedSourcePath}`);if(!sourceEntries.find(e=>e.type==="session"))throw new Error(`Cannot fork: source session has no header: ${resolvedSourcePath}`);let dir=sessionDir?normalizePath(sessionDir):getDefaultSessionDir(resolvedTargetCwd);existsSync4(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),writeFileSync3(newSessionFile,`${JSON.stringify(newHeader)}
38
38
  `,{flag:"wx"});for(let entry of sourceEntries)entry.type!=="session"&&appendFileSync(newSessionFile,`${JSON.stringify(entry)}
@@ -1,2 +1,2 @@
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{buildProviderDiagnostic,categoryForTransportCode,classifyProviderFailure}from"./chunk-UAQW2T7G.js";import{attachProviderDiagnostic}from"./chunk-45SZOLCU.js";var SSE_ERROR_ENVELOPE_MAX_BYTES=8192;function isRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function optionalString(value){if(value!=null)return typeof value=="string"?value:null}function anthropicProviderDiagnosticFromError(error){try{if(!(error instanceof Error))return;let status=Reflect.get(error,"status"),direct=optionalString(Reflect.get(error,"type")),body=Reflect.get(error,"error"),nested=isRecord(body)&&isRecord(body.error)?optionalString(body.error.type):void 0;if(direct===null||nested===null||direct!==void 0&&nested!==void 0&&direct!==nested)return;let code=direct??nested;return code===void 0&&status==null?void 0:classifyProviderFailure({status,code})}catch{return}}function anthropicProviderDiagnosticFromSseData(data){try{if(new TextEncoder().encode(data).length>SSE_ERROR_ENVELOPE_MAX_BYTES)return;let parsed=JSON.parse(data);if(!isRecord(parsed)||parsed.type!=="error"||!isRecord(parsed.error))return;let code=parsed.error.type;return typeof code!="string"?void 0:classifyProviderFailure({status:void 0,code})}catch{return}}function openAICompatibleProviderDiagnosticFromError(error){try{if(!(error instanceof Error))return;let status=Reflect.get(error,"status"),code=optionalString(Reflect.get(error,"code"));return code===null||code===void 0&&status==null?void 0:classifyProviderFailure({status,code})}catch{return}}var TRANSPORT_CAUSE_DEPTH=4;function transportProviderDiagnosticFromError(error){try{if(!(error instanceof Error))return;let current=error,sdkConnectionError;for(let depth=0;depth<TRANSPORT_CAUSE_DEPTH&&(isRecord(current)||current instanceof Error);depth++){let code=Reflect.get(current,"code");if(typeof code=="string"&&categoryForTransportCode(code)!==void 0)return buildProviderDiagnostic({category:"network",code,evidence:"structured_transport"});for(let name of current instanceof Error?[current.name,current.constructor.name]:[])sdkConnectionError===void 0&&categoryForTransportCode(name)!==void 0&&(sdkConnectionError=name);current=Reflect.get(current,"cause")}return sdkConnectionError===void 0?void 0:buildProviderDiagnostic({category:"network",code:sdkConnectionError,evidence:"structured_transport"})}catch{return}}function classifyWithTransport(classify,error){return classify(error)??transportProviderDiagnosticFromError(error)}async function awaitProviderTransport(request,classify){try{return await request()}catch(error){throw typeof error=="object"&&error!==null&&attachProviderDiagnostic(error,classifyWithTransport(classify,error)),error}}async function*iterateProviderTransport(source,classify){try{yield*source}catch(error){throw typeof error=="object"&&error!==null&&attachProviderDiagnostic(error,classifyWithTransport(classify,error)),error}}export{anthropicProviderDiagnosticFromError,anthropicProviderDiagnosticFromSseData,openAICompatibleProviderDiagnosticFromError,awaitProviderTransport,iterateProviderTransport};
2
+ import{buildProviderDiagnostic,categoryForTransportCode,classifyProviderFailure}from"./chunk-AA2L2RHH.js";import{attachProviderDiagnostic}from"./chunk-45SZOLCU.js";var SSE_ERROR_ENVELOPE_MAX_BYTES=8192;function isRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function optionalString(value){if(value!=null)return typeof value=="string"?value:null}function anthropicProviderDiagnosticFromError(error){try{if(!(error instanceof Error))return;let status=Reflect.get(error,"status"),direct=optionalString(Reflect.get(error,"type")),body=Reflect.get(error,"error"),nested=isRecord(body)&&isRecord(body.error)?optionalString(body.error.type):void 0;if(direct===null||nested===null||direct!==void 0&&nested!==void 0&&direct!==nested)return;let code=direct??nested;return code===void 0&&status==null?void 0:classifyProviderFailure({status,code})}catch{return}}function anthropicProviderDiagnosticFromSseData(data){try{if(new TextEncoder().encode(data).length>SSE_ERROR_ENVELOPE_MAX_BYTES)return;let parsed=JSON.parse(data);if(!isRecord(parsed)||parsed.type!=="error"||!isRecord(parsed.error))return;let code=parsed.error.type;return typeof code!="string"?void 0:classifyProviderFailure({status:void 0,code})}catch{return}}function openAICompatibleProviderDiagnosticFromError(error){try{if(!(error instanceof Error))return;let status=Reflect.get(error,"status"),code=optionalString(Reflect.get(error,"code"));return code===null||code===void 0&&status==null?void 0:classifyProviderFailure({status,code})}catch{return}}var TRANSPORT_CAUSE_DEPTH=4;function transportProviderDiagnosticFromError(error){try{if(!(error instanceof Error))return;let current=error,sdkConnectionError;for(let depth=0;depth<TRANSPORT_CAUSE_DEPTH&&(isRecord(current)||current instanceof Error);depth++){let code=Reflect.get(current,"code");if(typeof code=="string"&&categoryForTransportCode(code)!==void 0)return buildProviderDiagnostic({category:"network",code,evidence:"structured_transport"});for(let name of current instanceof Error?[current.name,current.constructor.name]:[])sdkConnectionError===void 0&&categoryForTransportCode(name)!==void 0&&(sdkConnectionError=name);current=Reflect.get(current,"cause")}return sdkConnectionError===void 0?void 0:buildProviderDiagnostic({category:"network",code:sdkConnectionError,evidence:"structured_transport"})}catch{return}}function classifyWithTransport(classify,error){return classify(error)??transportProviderDiagnosticFromError(error)}async function awaitProviderTransport(request,classify){try{return await request()}catch(error){throw typeof error=="object"&&error!==null&&attachProviderDiagnostic(error,classifyWithTransport(classify,error)),error}}async function*iterateProviderTransport(source,classify){try{yield*source}catch(error){throw typeof error=="object"&&error!==null&&attachProviderDiagnostic(error,classifyWithTransport(classify,error)),error}}export{anthropicProviderDiagnosticFromError,anthropicProviderDiagnosticFromSseData,openAICompatibleProviderDiagnosticFromError,transportProviderDiagnosticFromError,awaitProviderTransport,iterateProviderTransport};
@@ -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{CHILD_KILL_EXIT_TIMEOUT_MS,CHILD_STALLED_STOP_MAX_MS_ENV,CHILD_STOP_TIMEOUT_MS,DEFAULT_HANDOFF_GRACE_MS,HANDOFF_GRACE_MS_ENV,HOST_INSTANCE_ID_ENV,IdleExitDecider,OBSERVE_REQUEST_FIELD,STOP_STALL_EVIDENCE_MAX_AGE_MS,acquireOwnershipSafeLock,childStalledStopMaxMs,clearStopProgress,consumeStopIntent,errorMessage,hostLoopStalled,isObservingRequest,layeredSupervisorIntent,parseIdleExitMs,readStopIntent,recentStall,releaseGeneration,requestOriginHostInstance,resolveHostPolicy,supervisorLog,watchDrainRequest,writeDrainRequest,writeDrainWatch,writeStderrLine,writeStopIntent,writeStopProgress}from"./chunk-DDQJSVIZ.js";import{HOST_DAEMON_DIR_ENV,MAX_RPC_LINE_CHARACTERS,attachJsonlLineReader,createHostDaemonPaths,generationPaths,hostOwnerGone,readHostOwner,sameHostOwner,serializeJsonLine,writeJsonAtomic}from"./chunk-KUZPBZUK.js";import{require_signal_exit}from"./chunk-U3VOXCGP.js";import{MAX_SOCKET_PATH_BYTES,PUBLIC_SOCKET_IDENTITY_FILE,classifyEndpointOwnership,shieldSocketDuringClose,socketEntryListenerState,statSocketIdentity,unlinkOwnedSocket,writeSocketIdentityFile}from"./chunk-HRPMLI7O.js";import{SOCKET_SECRET_FILE_ENV,authenticateSocket,createSocketSecret,ensureSocketSecret,resolveSocketTransportAddress,sendSocketHandshake,socketSecretPath}from"./chunk-QEQG42HL.js";import{DISPLAY_VERSION,VERSION,envValue,getAgentDir,isBunBinary,isBundledNode}from"./chunk-4J4ABCCL.js";import{processIsLive,readProcessIdentity,readProcessStartTime}from"./chunk-7ASLQ243.js";import{__toESM}from"./chunk-IKOFCODM.js";import{randomUUID as randomUUID2}from"node:crypto";import{realpathSync}from"node:fs";import{join as join4}from"node:path";import{fileURLToPath as fileURLToPath2}from"node:url";var HostAdmission=class{constructor(info){this.stopped=!1,this.listeners=new Set,this.replies=Promise.resolve(),this.info=info}get stopping(){return this.stopped}protocol(){return{...this.info,lifecycle:this.stopped?"stopping":"ready"}}observe(info){this.info=info}stop(){this.stopped||(this.stopped=!0,this.replies=Promise.all([...this.listeners].map(listener=>listener())).then(()=>{}))}async flush(){let timer;try{await Promise.race([this.replies,new Promise(resolve2=>{timer=setTimeout(resolve2,2e3)})])}finally{clearTimeout(timer)}}onStop(listener){return this.listeners.add(listener),()=>this.listeners.delete(listener)}};function hostStoppingResponse(id,command,admission){return{...typeof id=="string"?{id}:{},type:"response",command,success:!1,error:"host_stopping",errorCode:"host_stopping",errorData:{instanceId:admission.protocol().instanceId}}}var import_signal_exit=__toESM(require_signal_exit(),1);import{appendFileSync,mkdirSync,readdirSync,readFileSync,renameSync,rmSync,statSync,utimesSync,writeFileSync}from"node:fs";import{join}from"node:path";var PROCESS_CRASH_RECORD_LIMIT=50,PROCESS_MARKER_HEARTBEAT_MS=6e4,FILE_MODE=384,DIR_MODE=448,MARKER_SUFFIX=".json";function processCrashPaths(agentDir){let dir=join(agentDir,"process-crashes");return{dir,liveDir:join(dir,"live"),recordsFile:join(dir,"crashes.jsonl")}}function crashingRuntimeVersions(){return{...process.versions.bun===void 0?{}:{bunVersion:process.versions.bun},senpiVersion:VERSION,...DISPLAY_VERSION===VERSION?{}:{productVersion:DISPLAY_VERSION}}}function recordProcessLifetime(agentDir,kind,options){return sweepDeadProcessMarkers(agentDir,options),options.supervised?()=>{}:installProcessLifetimeMarker(agentDir,kind,options)}function installProcessLifetimeMarker(agentDir,kind,options={}){let pid=options.pid??process.pid,now=options.now??Date.now,file=join(processCrashPaths(agentDir).liveDir,`${pid}${MARKER_SUFFIX}`),marker={kind,pid,startedAt:now(),...crashingRuntimeVersions()};try{mkdirSync(processCrashPaths(agentDir).liveDir,{recursive:!0,mode:DIR_MODE}),writeFileSync(file,`${JSON.stringify(marker)}
2
+ import{CHILD_KILL_EXIT_TIMEOUT_MS,CHILD_STALLED_STOP_MAX_MS_ENV,CHILD_STOP_TIMEOUT_MS,DEFAULT_HANDOFF_GRACE_MS,HANDOFF_GRACE_MS_ENV,HOST_INSTANCE_ID_ENV,IdleExitDecider,OBSERVE_REQUEST_FIELD,STOP_STALL_EVIDENCE_MAX_AGE_MS,acquireOwnershipSafeLock,childStalledStopMaxMs,clearStopProgress,consumeStopIntent,errorMessage,hostLoopStalled,isObservingRequest,layeredSupervisorIntent,parseIdleExitMs,readStopIntent,recentStall,releaseGeneration,requestOriginHostInstance,resolveHostPolicy,supervisorLog,watchDrainRequest,writeDrainRequest,writeDrainWatch,writeStderrLine,writeStopIntent,writeStopProgress}from"./chunk-DKBJM22C.js";import{HOST_DAEMON_DIR_ENV,MAX_RPC_LINE_CHARACTERS,attachJsonlLineReader,createHostDaemonPaths,generationPaths,hostOwnerGone,readHostOwner,sameHostOwner,serializeJsonLine,writeJsonAtomic}from"./chunk-KUZPBZUK.js";import{require_signal_exit}from"./chunk-U3VOXCGP.js";import{MAX_SOCKET_PATH_BYTES,PUBLIC_SOCKET_IDENTITY_FILE,classifyEndpointOwnership,shieldSocketDuringClose,socketEntryListenerState,statSocketIdentity,unlinkOwnedSocket,writeSocketIdentityFile}from"./chunk-HRPMLI7O.js";import{SOCKET_SECRET_FILE_ENV,authenticateSocket,createSocketSecret,ensureSocketSecret,resolveSocketTransportAddress,sendSocketHandshake,socketSecretPath}from"./chunk-QEQG42HL.js";import{DISPLAY_VERSION,VERSION,envValue,getAgentDir,isBunBinary,isBundledNode}from"./chunk-4J4ABCCL.js";import{processIsLive,readProcessIdentity,readProcessStartTime,waitForStartTime}from"./chunk-7ASLQ243.js";import{__toESM}from"./chunk-IKOFCODM.js";import{randomUUID as randomUUID2}from"node:crypto";import{realpathSync}from"node:fs";import{join as join4}from"node:path";import{fileURLToPath as fileURLToPath2}from"node:url";var HostAdmission=class{constructor(info){this.stopped=!1,this.listeners=new Set,this.replies=Promise.resolve(),this.info=info}get stopping(){return this.stopped}protocol(){return{...this.info,lifecycle:this.stopped?"stopping":"ready"}}observe(info){this.info=info}stop(){this.stopped||(this.stopped=!0,this.replies=Promise.all([...this.listeners].map(listener=>listener())).then(()=>{}))}async flush(){let timer;try{await Promise.race([this.replies,new Promise(resolve2=>{timer=setTimeout(resolve2,2e3)})])}finally{clearTimeout(timer)}}onStop(listener){return this.listeners.add(listener),()=>this.listeners.delete(listener)}};function hostStoppingResponse(id,command,admission){return{...typeof id=="string"?{id}:{},type:"response",command,success:!1,error:"host_stopping",errorCode:"host_stopping",errorData:{instanceId:admission.protocol().instanceId}}}var import_signal_exit=__toESM(require_signal_exit(),1);import{appendFileSync,mkdirSync,readdirSync,readFileSync,renameSync,rmSync,statSync,utimesSync,writeFileSync}from"node:fs";import{join}from"node:path";var PROCESS_CRASH_RECORD_LIMIT=50,PROCESS_MARKER_HEARTBEAT_MS=6e4,FILE_MODE=384,DIR_MODE=448,MARKER_SUFFIX=".json";function processCrashPaths(agentDir){let dir=join(agentDir,"process-crashes");return{dir,liveDir:join(dir,"live"),recordsFile:join(dir,"crashes.jsonl")}}function crashingRuntimeVersions(){return{...process.versions.bun===void 0?{}:{bunVersion:process.versions.bun},senpiVersion:VERSION,...DISPLAY_VERSION===VERSION?{}:{productVersion:DISPLAY_VERSION}}}function recordProcessLifetime(agentDir,kind,options){return sweepDeadProcessMarkers(agentDir,options),options.supervised?()=>{}:installProcessLifetimeMarker(agentDir,kind,options)}function installProcessLifetimeMarker(agentDir,kind,options={}){let pid=options.pid??process.pid,now=options.now??Date.now,file=join(processCrashPaths(agentDir).liveDir,`${pid}${MARKER_SUFFIX}`),marker={kind,pid,startedAt:now(),...crashingRuntimeVersions()};try{mkdirSync(processCrashPaths(agentDir).liveDir,{recursive:!0,mode:DIR_MODE}),writeFileSync(file,`${JSON.stringify(marker)}
3
3
  `,{mode:FILE_MODE})}catch{return()=>{}}let heartbeat=setInterval(()=>{try{let at=new Date(now());utimesSync(file,at,at)}catch{}},options.heartbeatMs??PROCESS_MARKER_HEARTBEAT_MS);heartbeat.unref();let disposed=!1,dispose=()=>{disposed||(disposed=!0,clearInterval(heartbeat),process.off("exit",onProcessExit),removeSignalHook(),rmSync(file,{force:!0}))},onProcessExit=()=>{try{dispose()}catch{}};process.on("exit",onProcessExit);let removeSignalHook=(0,import_signal_exit.default)(onProcessExit);return dispose}function sweepDeadProcessMarkers(agentDir,options={}){let paths=processCrashPaths(agentDir),selfPid=options.pid??process.pid,isAlive=options.isAlive??isProcessAlive,names;try{names=readdirSync(paths.liveDir)}catch{return 0}let recorded=0;for(let name of names){if(!name.endsWith(MARKER_SUFFIX))continue;let pid=Number(name.slice(0,-MARKER_SUFFIX.length));if(!Number.isSafeInteger(pid)||pid<=0||pid===selfPid||isAlive(pid))continue;let claimed=join(paths.liveDir,`${name}.${selfPid}.sweep`);try{renameSync(join(paths.liveDir,name),claimed)}catch{continue}try{let record2=crashRecordFromMarker(readFileSync(claimed,"utf8"),statSync(claimed).mtimeMs);record2!==void 0&&(appendProcessCrashRecord(paths,record2),recorded+=1)}catch{}finally{rmSync(claimed,{force:!0})}}return recorded}function isProcessAlive(pid){try{return process.kill(pid,0),!0}catch(error){return error.code==="EPERM"}}function crashRecordFromMarker(raw,lastHeartbeatMs){let value=JSON.parse(raw);if(typeof value!="object"||value===null)return;let kind=Reflect.get(value,"kind"),startedAt=Reflect.get(value,"startedAt"),senpiVersion=Reflect.get(value,"senpiVersion"),bunVersion=Reflect.get(value,"bunVersion"),productVersion=Reflect.get(value,"productVersion");if(!(typeof kind!="string"||typeof startedAt!="number"||typeof senpiVersion!="string"))return{at:new Date(lastHeartbeatMs).toISOString(),kind,detection:"unclean_exit",uptimeMs:Math.max(0,Math.round(lastHeartbeatMs-startedAt)),...typeof bunVersion=="string"?{bunVersion}:{},senpiVersion,...typeof productVersion=="string"?{productVersion}:{}}}function appendProcessCrashRecord(paths,record2){mkdirSync(paths.dir,{recursive:!0,mode:DIR_MODE}),appendFileSync(paths.recordsFile,`${JSON.stringify(record2)}
4
4
  `,{mode:FILE_MODE});let records=readProcessCrashRecordsFrom(paths.recordsFile);if(records.length<=PROCESS_CRASH_RECORD_LIMIT)return;let kept=records.slice(records.length-PROCESS_CRASH_RECORD_LIMIT);writeFileSync(paths.recordsFile,`${kept.join(`
5
5
  `)}
@@ -12,4 +12,4 @@ import{CHILD_KILL_EXIT_TIMEOUT_MS,CHILD_STALLED_STOP_MAX_MS_ENV,CHILD_STOP_TIMEO
12
12
  `).filter(Boolean),publicSocket=env[HOST_PUBLIC_SOCKET_ENV],daemonDir=env[HOST_DAEMON_DIR_ENV],instanceId=env[HOST_INSTANCE_ID_ENV];return{fd,ppid,scratchDir:scratchDir===void 0||scratchDir===""?void 0:scratchDir,cleanupPaths,publicSocket:publicSocket===""?void 0:publicSocket,...daemonDir&&instanceId?{daemonDir,instanceId}:{}}}function readHostWatchdogConfigFromBrandEnv(){return readHostWatchdogConfig({[HOST_WATCH_FD_ENV]:process.env[HOST_WATCH_FD_ENV]??envValue("RPC_HOST_WATCH_FD"),[HOST_WATCH_PPID_ENV]:process.env[HOST_WATCH_PPID_ENV]??envValue("RPC_HOST_WATCH_PPID"),[HOST_SCRATCH_DIR_ENV]:process.env[HOST_SCRATCH_DIR_ENV]??envValue("RPC_HOST_SCRATCH_DIR"),[HOST_PUBLIC_SOCKET_ENV]:process.env[HOST_PUBLIC_SOCKET_ENV]??envValue("RPC_HOST_PUBLIC_SOCKET"),[HOST_CLEANUP_PATHS_ENV]:process.env[HOST_CLEANUP_PATHS_ENV]??envValue("RPC_HOST_CLEANUP_PATHS"),[HOST_DAEMON_DIR_ENV]:process.env[HOST_DAEMON_DIR_ENV],[HOST_INSTANCE_ID_ENV]:process.env[HOST_INSTANCE_ID_ENV]})}function armHostWatchdog(config,onSupervisorGone){if(!config)return()=>{};let fire=reason=>{disarm(),config.daemonDir!==void 0&&config.instanceId!==void 0&&recordHostCrash(config.daemonDir,{at:new Date().toISOString(),uptimeMs:Math.round(process.uptime()*1e3),kind:"rpc-host-watchdog",generation:config.instanceId,reason});let captured=captureBeforeCleanup(config);if(process.platform==="win32"){let cleanup=captured.then(()=>cleanupWatchdogPaths(config));onSupervisorGone(reason,cleanup)}else captured.then(()=>cleanupWatchdogPaths(config)).finally(()=>onSupervisorGone(reason))},disarmers=[],disarm=()=>{for(let stop of disarmers.splice(0))stop()};return config.fd!==void 0&&disarmers.push(watchFdForEof(config.fd,fire)),config.ppid!==void 0&&disarmers.push(watchPpid(config.ppid,fire)),disarm}function watchFdForEof(fd,fire){let stream,streamFailed=!1,fired=!1,fireOnce=reason=>{fired||(fired=!0,fire(reason))};try{stream=new Socket2({fd,readable:!0,writable:!1})}catch{return()=>{}}stream.resume();let onEnd=()=>fireOnce(`supervisor pipe fd ${fd} closed`),onClose=()=>{streamFailed||onEnd()},onError=()=>{streamFailed=!0};return stream.once("end",onEnd),process.platform==="win32"&&stream.once("close",onClose),stream.once("error",onError),()=>{stream.off("end",onEnd),stream.off("close",onClose),stream.off("error",onError),stream.destroy()}}function watchPpid(supervisorPid,fire){if(supervisorPid===process.pid)return()=>{};let timer=setInterval(()=>{if(!processAlive(supervisorPid)){fire(`supervisor pid ${supervisorPid} is gone (ppid=${process.ppid})`);return}process.ppid!==supervisorPid&&fire(`supervisor pid ${supervisorPid} is gone (ppid=${process.ppid})`)},HOST_WATCH_PPID_INTERVAL_MS);return timer.unref?.(),()=>clearInterval(timer)}function processAlive(pid){try{return process.kill(pid,0),!0}catch(cause){return cause instanceof Error&&"code"in cause&&cause.code!=="ESRCH"}}function captureBeforeCleanup(config){return config.beforeCleanup===void 0?Promise.resolve():Promise.resolve().then(config.beforeCleanup).catch(()=>{})}async function cleanupWatchdogPaths(config){let paths=[...config.cleanupPaths??[],...config.scratchDir?[config.scratchDir]:[]];for(let path of paths)try{process.platform==="win32"?rmSync2(path,{recursive:!0,force:!0,maxRetries:10,retryDelay:100}):await rm(path,{recursive:!0,force:!0})}catch{}}var INTERNAL_SUPERVISOR_FLAG="--internal-rpc-host-supervisor",INJECTABLE_PREFIX_FLAGS=new Set(["--extension"]);function findInternalSupervisorArgs(argv){for(let index=0;index<argv.length;index++){let arg=argv[index];if(arg===INTERNAL_SUPERVISOR_FLAG)return argv.slice(index+1);if(!INJECTABLE_PREFIX_FLAGS.has(arg)||index+1>=argv.length)return;index++}}function parseSupervisorArgs(argv){let hostArgs=[],socket,childCommand,childArgs,agentDir,ownerFd,bindSocket,replaceIdentity;for(let index=0;index<argv.length;index++){let arg=argv[index];if(arg==="--owner-fd"&&index+1<argv.length){if(ownerFd=Number(argv[++index]),!Number.isSafeInteger(ownerFd)||ownerFd<3)return;continue}if(arg==="--socket"&&index+1<argv.length){socket=argv[++index];continue}if(arg==="--child-command"&&index+1<argv.length){childCommand=argv[++index];continue}if(arg==="--child-args"&&index+1<argv.length){try{let parsed=JSON.parse(argv[++index]);Array.isArray(parsed)&&parsed.every(value=>typeof value=="string")&&(childArgs=parsed)}catch{return}continue}if(arg==="--agent-dir"&&index+1<argv.length){agentDir=argv[++index];continue}if(arg==="--bind"&&index+1<argv.length){bindSocket=argv[++index];continue}if(arg==="--replace"&&index+1<argv.length){replaceIdentity=parseSocketIdentity(argv[++index]);continue}hostArgs.push(arg)}return socket===void 0?void 0:{socket,hostArgs,childCommand,childArgs,agentDir,ownerFd,bindSocket,replaceIdentity}}var OWNER_WATCH_FD=3,ownerPipes=new Set;function keepOwnerPipe(child){let pipe=child.stdio[OWNER_WATCH_FD];if(!(pipe instanceof Socket3))throw new Error("RPC owner pipe was not inherited");ownerPipes.add(pipe),pipe.on("error",()=>{}),pipe.unref(),child.once("exit",()=>{ownerPipes.delete(pipe),pipe.destroy()})}function parseSocketIdentity(value){let match=/^(\d+):(\d+)$/.exec(value);return match?{dev:Number(match[1]),ino:Number(match[2])}:void 0}function resolveHostChildLaunch(launch,internalSocket,compiled=isBunBinary){return launch.childCommand?{command:launch.childCommand,args:[...launch.childArgs??[],"--listen",`unix://${internalSocket}`]}:{command:process.execPath,args:[...compiled?[]:[...runtimeExecArgv(),resolveCliMainPath()],"--mode","rpc","--multi-session","--listen",`unix://${internalSocket}`,...launch.hostArgs]}}function quoteWindowsShellArg(value){return`"${value.replace(/(\\*)"/g,'$1$1\\"').replace(/(\\*)$/,"$1$1").replace(/([()%!^"<>&|;,])/g,"^$1")}"`}function spawnableChildLaunch(launch,platform=process.platform){let extension=extname(launch.command).toLowerCase();return platform!=="win32"||extension!==".cmd"&&extension!==".bat"?{...launch,shell:!1}:{command:quoteWindowsShellArg(launch.command),args:launch.args.map(quoteWindowsShellArg),shell:!0}}var HOST_CHILD_WATCH_FD=3;function spawnHostChild(options){let{launch,internalSocket,internal,internalSecret,publicSocket}=options,childLaunch=spawnableChildLaunch(resolveHostChildLaunch(launch,internalSocket));return spawn(childLaunch.command,childLaunch.args,{env:{...process.env,...launch.agentDir?{SENPI_CODING_AGENT_DIR:launch.agentDir}:{},[HOST_DAEMON_DIR_ENV]:options.daemonDir,[HOST_INSTANCE_ID_ENV]:options.instanceId,[HOST_WATCH_FD_ENV]:String(HOST_CHILD_WATCH_FD),[HOST_WATCH_PPID_ENV]:String(process.pid),...internal.dir?{[HOST_SCRATCH_DIR_ENV]:internal.dir}:{},...internalSecret?{[SOCKET_SECRET_FILE_ENV]:internal.secretPath}:{},[HOST_CLEANUP_PATHS_ENV]:options.cleanupPaths.join(`
13
13
  `),...process.platform==="win32"?{}:{[HOST_PUBLIC_SOCKET_ENV]:publicSocket}},shell:childLaunch.shell,stdio:["ignore","ignore","inherit","pipe"],windowsHide:!0})}import{chmod,mkdir,rename,stat,unlink}from"node:fs/promises";import{createConnection as createConnection2,createServer}from"node:net";import{dirname as dirname2}from"node:path";import{StringDecoder}from"node:string_decoder";function proxyWithAdmission(client,internal,admission){let pending=[],refused=new Set,protocols=0,refusals=Promise.resolve(),unsubscribe=admission.onStop(()=>(refusals=refusePending(),refusals));async function refusePending(){let ids=pending.splice(0);for(let id of ids)refused.add(id);try{for(let id of ids)await write(client,serializeJsonLine(hostStoppingResponse(id,"open_session",admission)))}catch{fail()}}client.once("close",()=>{unsubscribe(),internal?.destroy()});let fail=()=>{internal?.destroy(),client.destroy()};client.once("error",fail),internal?.once("error",()=>{admission.stopping||fail()}),requests().catch(()=>{admission.stopping||fail()}),internal&&responses(internal).catch(()=>{admission.stopping||fail()});async function requests(){for await(let line of lines(client,MAX_RPC_LINE_CHARACTERS)){if(line===void 0){await write(client,serializeJsonLine({type:"response",command:"parse",success:!1,error:`RPC input line exceeds ${MAX_RPC_LINE_CHARACTERS} characters.`}));continue}let request=record(line);admission.stopping&&request?.type==="get_protocol_info"?await write(client,serializeJsonLine({id:request.id,type:"response",command:request.type,success:!0,data:admission.protocol()})):admission.stopping&&(request?.type==="open_session"||!internal)?await write(client,serializeJsonLine(hostStoppingResponse(request?.id,String(request?.type??"parse"),admission))):internal&&(request?.type==="open_session"&&pending.push(request.id),request?.type==="get_protocol_info"&&protocols++,await write(internal,`${line}
14
14
  `))}internal?.end()}async function responses(source){let fragments=[];for await(let chunk of source){let newline=chunk.lastIndexOf(10);if(newline===-1){fragments.push(chunk);continue}let complete=chunk.subarray(0,newline+1);if(pending.length===0&&protocols===0&&refused.size===0){client.cork();let written;try{for(let fragment of fragments)client.write(fragment);written=write(client,complete)}finally{client.uncork()}await written}else{let batch=fragments.length>0?Buffer.concat([...fragments,complete]):complete;await write(client,filterReplies(batch))}fragments=newline+1<chunk.length?[chunk.subarray(newline+1)]:[]}fragments.length>0&&await write(client,filterReplies(Buffer.concat(fragments))),await refusals,client.end(()=>client.destroy())}function filterReplies(batch){if(pending.length===0&&protocols===0&&refused.size===0)return batch;let output=[],changed=!1;for(let start=0;start<batch.length;){let newline=batch.indexOf(10,start),end=newline===-1?batch.length:newline+1,line=batch.subarray(start,end);start=end;let response=line.includes('"open_session"')||line.includes('"get_protocol_info"')?record(line.toString("utf8")):void 0;if(response?.type==="response"&&response.command==="open_session"){if(refused.has(response.id)){changed=!0;continue}let index=pending.indexOf(response.id);index!==-1&&pending.splice(index,1)}if(response?.type==="response"&&response.command==="get_protocol_info"&&(protocols=Math.max(0,protocols-1),response.success===!0)){isRecord(response.data)&&admission.observe(response.data),output.push(Buffer.from(serializeJsonLine({...response,data:admission.protocol()}))),changed=!0;continue}output.push(line)}return changed?Buffer.concat(output):batch}}async function write(socket,line){await new Promise((resolve2,reject)=>{socket.write(line,error=>error?reject(error):resolve2())})}async function*lines(socket,limit){let decoder=new StringDecoder("utf8"),buffer="",discarding=!1;for await(let chunk of socket){let text=typeof chunk=="string"?chunk:decoder.write(chunk),offset=0;for(;offset<text.length;){let newline=text.indexOf(`
15
- `,offset),end=newline===-1?text.length:newline;if(discarding||(buffer.length+end-offset>limit?(buffer="",discarding=!0,yield void 0):buffer+=text.slice(offset,end)),newline===-1)break;discarding||(yield buffer),buffer="",discarding=!1,offset=newline+1}}buffer+=decoder.end(),!discarding&&buffer.length>0&&(yield buffer)}function record(line){try{let value=JSON.parse(line);return isRecord(value)?value:void 0}catch{return}}function isRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function createPublicProxy(options){let{internalSocket,internalSecret,publicSecret,clients}=options;return createServer(client=>{let accept=()=>{if(!clients.admit(client))return;let internal=options.admission.stopping?void 0:createConnection2(resolveSocketTransportAddress(internalSocket,process.platform,internalSecret));internal&&internalSecret&&sendSocketHandshake(internal,internalSecret);let detach=()=>{clients.release(client)&&options.onAdmit?.(),options.onDetach(),internal?.destroy(),client.destroy()};proxyWithAdmission(client,internal,options.admission),client.once("close",detach),client.once("error",detach)};publicSecret?authenticateSocket(client,publicSecret,accept):accept()})}async function adoptPublicSocket(bindSocket,publicSocket,expected){if(expected===void 0)throw new Error(`${publicSocket}: a generation launch must name the entry it replaces`);let current=await statSocketIdentity(publicSocket);if(current===void 0||current.dev!==expected.dev||current.ino!==expected.ino)throw new Error(`${publicSocket}: owned by another socket entry now; refusing to replace it`);await rename(bindSocket,publicSocket)}async function ensurePublicSocketSecret(publicSocket){let secretPath=socketSecretPath(publicSocket);try{return await ensureSocketSecret(secretPath)}catch(cause){throw new Error(`senpi rpc host supervisor: cannot provision public socket secret ${secretPath}`,{cause})}}async function waitForListener(socketPath,timeoutMs,secret){let deadline=Date.now()+timeoutMs;for(;Date.now()<=deadline;){if(await canConnect(socketPath,secret))return;await new Promise(resolveDelay=>setTimeout(resolveDelay,50))}throw new Error(`${socketPath}: host did not start listening within ${timeoutMs}ms`)}function canConnect(socketPath,secret){return new Promise(resolve2=>{let socket=createConnection2(resolveSocketTransportAddress(socketPath,process.platform,secret));secret&&sendSocketHandshake(socket,secret);let settle=value=>{socket.destroy(),resolve2(value)};socket.once("connect",()=>settle(!0)),socket.once("error",()=>settle(!1))})}async function stampOf(socketPath){try{let entry=await stat(socketPath,{bigint:!0});return{dev:entry.dev,ino:entry.ino,ctimeNs:entry.ctimeNs,socket:entry.isSocket()}}catch(cause){if(cause instanceof Error&&"code"in cause&&cause.code==="ENOENT")return;throw cause}}var sameStamp=(a,b)=>a.dev===b.dev&&a.ino===b.ino&&a.ctimeNs===b.ctimeNs;async function prepareSocketPath(socketPath,hooks={}){if(process.platform==="win32"||socketPath.startsWith("\0"))return;if(Buffer.byteLength(socketPath)>MAX_SOCKET_PATH_BYTES)throw new Error(`${socketPath}: socket path is ${Buffer.byteLength(socketPath)} bytes, over the ${MAX_SOCKET_PATH_BYTES}-byte limit.`);await mkdir(dirname2(socketPath),{recursive:!0,mode:448});let probed=await stampOf(socketPath);if(probed===void 0)return;let inUse=evidence=>new Error(`${socketPath}: address already in use by a live server (${evidence}).`);if(!probed.socket)throw inUse("the entry is not a socket");let state=await(hooks.listenerState??socketEntryListenerState)(socketPath);if(state.verdict==="gone")return;if(state.verdict==="live")throw inUse(state.evidence);await hooks.afterStaleProbe?.();let current=await stampOf(socketPath);if(current!==void 0){if(!sameStamp(probed,current))throw inUse("the entry changed after it was probed");try{await unlink(socketPath)}catch(cause){if(cause instanceof Error&&"code"in cause&&cause.code==="ENOENT")return;throw cause}}}function listen(server,socketPath,secret){return new Promise((resolve2,reject)=>{server.once("error",reject),server.listen({path:resolveSocketTransportAddress(socketPath,process.platform,secret),readableAll:!1,writableAll:!1},async()=>{server.off("error",reject);try{process.platform!=="win32"&&!socketPath.startsWith("\0")&&await chmod(socketPath,384),resolve2()}catch(cause){reject(cause)}})})}function closeServer(server){return new Promise(resolve2=>{server.close(()=>resolve2())})}import{randomUUID}from"node:crypto";import{mkdir as mkdir2,readFile as readFile3,writeFile}from"node:fs/promises";import{tmpdir}from"node:os";import{join as join3}from"node:path";var INTERNAL_HOST_DIR_PREFIX="senpi-rpc-host-internal-",SHORT_TEMP_ROOT="/tmp";function internalHostDirRoots(){let primary=tmpdir();return primary===SHORT_TEMP_ROOT?[primary]:[primary,SHORT_TEMP_ROOT]}function internalHostDirRoot(name){for(let root of internalHostDirRoots())if(Buffer.byteLength(join3(root,name,"host.sock"))<=MAX_SOCKET_PATH_BYTES)return root;throw new Error(`internal_socket_path_too_long: ${join3(tmpdir(),name,"host.sock")} exceeds ${MAX_SOCKET_PATH_BYTES} bytes and /tmp cannot hold it either; set TMPDIR to a shorter directory`)}async function createInternalSocketPath(baseDir=tmpdir(),platform=process.platform){if(platform==="win32"){let dir2=join3(baseDir,`internal-${randomUUID()}`);return await mkdir2(dir2,{recursive:!0,mode:448}),{socket:`\\\\.\\pipe\\senpi-rpc-internal-${randomUUID()}`,dir:dir2,secretPath:join3(dir2,"secret")}}let name=`${INTERNAL_HOST_DIR_PREFIX}${randomUUID().slice(0,8)}`,dir=join3(internalHostDirRoot(name),name);return await mkdir2(dir,{recursive:!1,mode:448}),await writeFile(join3(dir,".owner"),JSON.stringify({pid:process.pid,processStartTime:await readProcessStartTime(process.pid),createdAt:Date.now()}),{mode:384}),{socket:join3(dir,"host.sock"),dir,secretPath:join3(dir,".secret")}}async function recordChildPid(file,pid){try{let identity=await readProcessIdentity(pid,process.platform,1e3,void 0,"UTC"),processStartTime=identity.kind==="present"?identity.identity:null;processStartTime===null&&supervisorLog(`host child pid ${pid} start time unreadable at recording`),await writeJsonAtomic(file,{pid,processStartTime})}catch(cause){supervisorLog(`could not record the host child pid: ${errorMessage(cause)}`)}}async function readSettingsFile(settingsFile){try{return JSON.parse(await readFile3(settingsFile,"utf8"))}catch{return}}import{rm as rm2}from"node:fs/promises";var LOOP_LAG_ERROR_MS_ENV="SENPI_RPC_LOOP_LAG_ERROR_MS",DEFAULT_LOOP_LAG_ERROR_MS=5e3;function loopLagErrorMs(env=process.env){return parseIdleExitMs(env[LOOP_LAG_ERROR_MS_ENV])??DEFAULT_LOOP_LAG_ERROR_MS}var STALL_WAIT_SLICE_MS=5e3;async function waitOutStalledChild(options){let{child,generation,signalledAt}=options,maxMs=childStalledStopMaxMs(),untilAt=signalledAt+maxMs,stalled=()=>hostLoopStalled(generation,{now:Date.now(),errorMs:loopLagErrorMs(),windowMs:STOP_STALL_EVIDENCE_MAX_AGE_MS}).catch(()=>!1),waited=0;try{for(;Date.now()<untilAt&&await stalled();){waited===0&&supervisorLog(`host child is stalled; waiting up to ${maxMs}ms (${CHILD_STALLED_STOP_MAX_MS_ENV})`),await writeStopProgress(generation,{at:new Date().toISOString(),phase:"waiting_stalled_child",untilAt:new Date(untilAt).toISOString()}).catch(()=>{});let slice=Math.min(STALL_WAIT_SLICE_MS,untilAt-Date.now()),exited=await options.waitForExit(child,slice);if(waited+=slice,exited)break}}finally{await clearStopProgress(generation)}return waited}var WINDOWS_SUPERVISOR_SHUTDOWN_HARD_EXIT_MS=2e3;function supervisorSender(instanceId){return{pid:process.pid,kind:"supervisor",generation:instanceId}}function childExited(child){return child.exitCode!==null||child.signalCode!==null}async function performShutdown(context,reason,exitCode){let{state,child}=context;state.shuttingDown=!0,state.shutdownReason=reason,context.admission.stop();let childStopStarted=!1,hardExit;try{context.stopWatchers(),context.drain.stop(),writeStderrLine(`senpi rpc host supervisor: ${reason} shutdown`),childStopStarted=!0,await stopChild(context,reason),await state.childExitRecorded,await context.admission.flush(),context.activity.clients.destroyAll(),process.platform==="win32"&&(hardExit=setTimeout(()=>process.exit(exitCode),WINDOWS_SUPERVISOR_SHUTDOWN_HARD_EXIT_MS)),context.drain.active||await shieldSocketDuringClose(context.publicSocket,()=>closeServer(context.server)),context.internalDir&&await rm2(context.internalDir,{recursive:!0,force:!0}),context.activity.stopObserver(),state.publicSocketOwned&&process.platform!=="win32"&&await unlinkOwnedSocket(context.publicSocket,state.publicSocketIdentity,supervisorLog),await releaseGeneration(context.paths,{instanceId:context.instanceId,pid:process.pid,superseded:state.endpointReplaced})}catch(cause){supervisorLog(`shutdown failed for host child pid ${child.pid??"unknown"}: ${errorMessage(cause)}`),exitCode=1;try{childStopStarted||await reapChildAfterFailure(child),await state.childExitRecorded}catch(reapCause){supervisorLog(`shutdown recovery failed for host child pid ${child.pid??"unknown"}: ${errorMessage(reapCause)}`)}}finally{hardExit&&clearTimeout(hardExit),process.exit(exitCode)}}async function stopChild(context,reason){let{child,generation}=context,pid=child.pid;if(childExited(child)||pid===void 0)return;let termAttempted=!1,killAttempted=!1;try{let outer=await readStopIntent(generation).catch(cause=>{supervisorLog(`cannot read child stop intent: ${errorMessage(cause)}`)}),at=new Date().toISOString(),intent=layeredSupervisorIntent(outer,supervisorSender(context.instanceId),{targetPid:pid,reason,at});await writeStopIntent(generation,intent,supervisorLog);let signalledAt=Date.now();if(termAttempted=!0,signalChild(pid,"SIGTERM"),await waitForChildExit(child,CHILD_STOP_TIMEOUT_MS))return;let stallWaitMs=await waitOutStalledChild({child,generation,signalledAt,waitForExit:waitForChildExit});if(childExited(child))return;if(stallWaitMs>0){let escalated={...intent,reason:`${intent.reason}; escalated_after_stall_wait=${stallWaitMs}`};await writeStopIntent(generation,escalated,supervisorLog)}if(killAttempted=!0,signalChild(pid,"SIGKILL"),!await waitForChildExit(child,CHILD_KILL_EXIT_TIMEOUT_MS))throw new Error(`host child pid ${pid} exit unobserved ${CHILD_KILL_EXIT_TIMEOUT_MS}ms after SIGKILL`)}catch(cause){throw killAttempted||await reapChildAfterFailure(child,termAttempted),cause}}async function reapChildAfterFailure(child,termAttempted=!1){let pid=child.pid;if(!(childExited(child)||pid===void 0)&&!(!termAttempted&&(signalChild(pid,"SIGTERM"),await waitForChildExit(child,CHILD_STOP_TIMEOUT_MS)))&&(signalChild(pid,"SIGKILL"),!await waitForChildExit(child,CHILD_KILL_EXIT_TIMEOUT_MS)))throw new Error(`host child pid ${pid} exit unobserved ${CHILD_KILL_EXIT_TIMEOUT_MS}ms after recovery SIGKILL`)}function signalChild(pid,signal){try{return process.kill(pid,signal),!0}catch{return!1}}function waitForChildExit(child,timeoutMs){return childExited(child)?Promise.resolve(!0):new Promise(resolve2=>{let timer=setTimeout(()=>{child.off("exit",onExit2),resolve2(!1)},timeoutMs),onExit2=()=>{clearTimeout(timer),resolve2(!0)};child.once("exit",onExit2)})}function registerSupervisorSignals(shutdown,drain){for(let signal of process.platform==="win32"?["SIGTERM"]:["SIGTERM","SIGHUP"])process.on(signal,()=>{shutdown(`signal:${signal}`,signal==="SIGHUP"?129:143)});process.platform!=="win32"&&process.on("SIGUSR1",drain)}function startSupervisorTicker(options){let{activity,owner,draining,shuttingDown,shutdown}=options,tickIntervalMs=Math.max(20,Math.min(1e3,options.idleExitMs/4)),ownerCheck=!1,ticker=setInterval(()=>{!draining()&&activity.refresh()==="exit"&&activity.clients.unclassifiedCount===0&&shutdown("idle",0),!ownerCheck&&!shuttingDown()&&!draining()&&(ownerCheck=!0,owner.shouldExit(activity).then(exit=>{exit&&!shuttingDown()&&!draining()&&shutdown("owner_gone",0)}).finally(()=>{ownerCheck=!1}))},tickIntervalMs);return()=>{clearInterval(ticker),owner.stop()}}async function runHostSupervisor(launch){let paths=createHostDaemonPaths({socket:launch.socket,agentDir:launch.agentDir??getAgentDir()}),told=process.env[HOST_INSTANCE_ID_ENV],instanceId=told!==void 0&&told.trim()!==""?told:randomUUID2(),generation=generationPaths(paths,instanceId),policy=resolveHostPolicy(await readSettingsFile(paths.settingsFile),process.env),publicSocket=launch.socket,bindSocket=launch.bindSocket??publicSocket,successor=launch.bindSocket!==void 0,publicSecret=process.platform==="win32"?await ensurePublicSocketSecret(publicSocket):void 0,internal=await createInternalSocketPath(paths.dir),internalSocket=internal.socket,internalSecretPath=internal.secretPath??socketSecretPath(internalSocket),internalSecret=process.platform==="win32"?await createSocketSecret(internalSecretPath):void 0,state={shuttingDown:!1,shutdownReason:void 0,childExitRecorded:Promise.resolve(),publicSocketOwned:!1,publicSocketIdentity:void 0,endpointReplaced:!1},owner=new SupervisorOwner(generation.dir),activity=new SupervisorActivity({idleExitMs:policy.coldStart==="persistent"?Number.POSITIVE_INFINITY:policy.idleExitMs,internalSocket,...internalSecret?{internalSecret}:{},instanceId,settled:()=>state.shuttingDown,onActivity:()=>owner.activity()}),watchers=[],child=spawnHostChild({launch,internalSocket,internal:{...internal,secretPath:internalSecretPath},...internalSecret?{internalSecret}:{},daemonDir:paths.dir,instanceId,cleanupPaths:hostCrashCleanupPaths({pointerFile:paths.pointerFile,generationPidFile:generation.pidFile,settingsFile:paths.settingsFile,publicSocket,successor:!!successor,platform:process.platform}),publicSocket}),childStartedAt=Date.now();child.stdio[HOST_CHILD_WATCH_FD]?.on("error",()=>{}),child.pid!==void 0&&recordChildPid(generation.childPidFile,child.pid),child.once("exit",(code,signal)=>{let reason=state.shutdownReason;if(state.childExitRecorded=noteChildExit({daemonDir:paths.dir,generation,instanceId,code,signal,childStartedAt,...state.shuttingDown&&reason!==void 0?{shutdown:{reason,supervisor:supervisorSender(instanceId)}}:{}}),state.shuttingDown)return;let verdict=classifyChildExit(code,signal);state.childExitRecorded.then(()=>shutdown(verdict.reason,verdict.exitCode))});let admission=new HostAdmission({protocolVersion:1,serverVersion:VERSION,capabilities:[],instanceId}),drain=new SupervisorDrain(child,()=>state.shuttingDown,()=>admission.stop(),{file:generation.childDrainRequestFile,sender:supervisorSender(instanceId)}),server=createPublicProxy({internalSocket,...internalSecret?{internalSecret}:{},...publicSecret?{publicSecret}:{},clients:activity.clients,admission,onDetach:()=>activity.refresh(),onAdmit:()=>owner.activity()});server.once("error",cause=>{state.shuttingDown||shutdown(`public socket listener failed: ${errorMessage(cause)}`,1)}),watchers.push(startSupervisorTicker({idleExitMs:policy.idleExitMs,activity,owner,draining:()=>drain.active,shuttingDown:()=>state.shuttingDown,shutdown}));let teardown={paths,generation,instanceId,publicSocket,server,internalDir:internal.dir,child,activity,drain,admission,state,stopWatchers:()=>{for(let stop of watchers.splice(0))stop()}},shutdownPromise;function shutdown(reason,exitCode){return shutdownPromise??=performShutdown(teardown,reason,exitCode),shutdownPromise}registerSupervisorSignals(shutdown,()=>drain.drain());try{(launch.ownerFd!==void 0||await readSettingsFile(generation.settingsFile))&&await owner.start(launch.ownerFd),await waitForListener(internalSocket,3e4,internalSecret),await activity.openObserver(),await prepareSocketPath(bindSocket),await listen(server,bindSocket,publicSecret),state.publicSocketOwned=!0,successor&&await adoptPublicSocket(bindSocket,publicSocket,launch.replaceIdentity),state.publicSocketIdentity=await statSocketIdentity(publicSocket),state.publicSocketIdentity&&internal.dir&&await writeSocketIdentityFile(join4(internal.dir,PUBLIC_SOCKET_IDENTITY_FILE),state.publicSocketIdentity),watchers.push(drainOnPublicSocketLoss(publicSocket,state.publicSocketIdentity,()=>state.shuttingDown||drain.active,drain,()=>{state.endpointReplaced=!0},{file:paths.pointerFile,instanceId})),watchers.push(await drain.acceptRequests(generation))}catch(cause){await shutdown(`startup failed: ${errorMessage(cause)}`,1)}process.platform==="win32"&&watchers.push(await watchWin32ChildIdentity(child,()=>state.shuttingDown,()=>{shutdown("rpc host child exit observed by identity watchdog",0)})),writeStderrLine(`senpi rpc host ready on unix://${publicSocket} (coldStart=${policy.coldStart}, idleExitMs=${policy.coldStart==="persistent"?"never":String(policy.idleExitMs)})`),await new Promise(()=>{})}function isEntryScript(){let entry=process.argv[1];if(!entry)return!1;try{return fileURLToPath2(import.meta.url)===realpathSync(entry)}catch{return!1}}if(!isBundledNode&&isEntryScript()){let launch=parseSupervisorArgs(process.argv.slice(2));launch||(writeStderrLine("usage: host-lifecycle.ts --socket <path> [host cli args...]"),process.exit(2)),runHostSupervisor(launch)}export{runtimeExecArgv,loopLagErrorMs,recordProcessLifetime,isHostCrash,readHostCrashRecords,classifyChildExit,noteEscalatedStop,ClientOccupancy,resolveCliMainPath,resolveCliMainPathAsync,readHostWatchdogConfigFromBrandEnv,armHostWatchdog,INTERNAL_SUPERVISOR_FLAG,findInternalSupervisorArgs,parseSupervisorArgs,OWNER_WATCH_FD,keepOwnerPipe,resolveHostChildLaunch,spawnableChildLaunch,prepareSocketPath,INTERNAL_HOST_DIR_PREFIX,internalHostDirRoots,createInternalSocketPath,runHostSupervisor};
15
+ `,offset),end=newline===-1?text.length:newline;if(discarding||(buffer.length+end-offset>limit?(buffer="",discarding=!0,yield void 0):buffer+=text.slice(offset,end)),newline===-1)break;discarding||(yield buffer),buffer="",discarding=!1,offset=newline+1}}buffer+=decoder.end(),!discarding&&buffer.length>0&&(yield buffer)}function record(line){try{let value=JSON.parse(line);return isRecord(value)?value:void 0}catch{return}}function isRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function createPublicProxy(options){let{internalSocket,internalSecret,publicSecret,clients}=options;return createServer(client=>{let accept=()=>{if(!clients.admit(client))return;let internal=options.admission.stopping?void 0:createConnection2(resolveSocketTransportAddress(internalSocket,process.platform,internalSecret));internal&&internalSecret&&sendSocketHandshake(internal,internalSecret);let detach=()=>{clients.release(client)&&options.onAdmit?.(),options.onDetach(),internal?.destroy(),client.destroy()};proxyWithAdmission(client,internal,options.admission),client.once("close",detach),client.once("error",detach)};publicSecret?authenticateSocket(client,publicSecret,accept):accept()})}async function adoptPublicSocket(bindSocket,publicSocket,expected){if(expected===void 0)throw new Error(`${publicSocket}: a generation launch must name the entry it replaces`);let current=await statSocketIdentity(publicSocket);if(current===void 0||current.dev!==expected.dev||current.ino!==expected.ino)throw new Error(`${publicSocket}: owned by another socket entry now; refusing to replace it`);await rename(bindSocket,publicSocket)}async function ensurePublicSocketSecret(publicSocket){let secretPath=socketSecretPath(publicSocket);try{return await ensureSocketSecret(secretPath)}catch(cause){throw new Error(`senpi rpc host supervisor: cannot provision public socket secret ${secretPath}`,{cause})}}async function waitForListener(socketPath,timeoutMs,secret){let deadline=Date.now()+timeoutMs;for(;Date.now()<=deadline;){if(await canConnect(socketPath,secret))return;await new Promise(resolveDelay=>setTimeout(resolveDelay,50))}throw new Error(`${socketPath}: host did not start listening within ${timeoutMs}ms`)}function canConnect(socketPath,secret){return new Promise(resolve2=>{let socket=createConnection2(resolveSocketTransportAddress(socketPath,process.platform,secret));secret&&sendSocketHandshake(socket,secret);let settle=value=>{socket.destroy(),resolve2(value)};socket.once("connect",()=>settle(!0)),socket.once("error",()=>settle(!1))})}async function stampOf(socketPath){try{let entry=await stat(socketPath,{bigint:!0});return{dev:entry.dev,ino:entry.ino,ctimeNs:entry.ctimeNs,socket:entry.isSocket()}}catch(cause){if(cause instanceof Error&&"code"in cause&&cause.code==="ENOENT")return;throw cause}}var sameStamp=(a,b)=>a.dev===b.dev&&a.ino===b.ino&&a.ctimeNs===b.ctimeNs;async function prepareSocketPath(socketPath,hooks={}){if(process.platform==="win32"||socketPath.startsWith("\0"))return;if(Buffer.byteLength(socketPath)>MAX_SOCKET_PATH_BYTES)throw new Error(`${socketPath}: socket path is ${Buffer.byteLength(socketPath)} bytes, over the ${MAX_SOCKET_PATH_BYTES}-byte limit.`);await mkdir(dirname2(socketPath),{recursive:!0,mode:448});let probed=await stampOf(socketPath);if(probed===void 0)return;let inUse=evidence=>new Error(`${socketPath}: address already in use by a live server (${evidence}).`);if(!probed.socket)throw inUse("the entry is not a socket");let state=await(hooks.listenerState??socketEntryListenerState)(socketPath);if(state.verdict==="gone")return;if(state.verdict==="live")throw inUse(state.evidence);await hooks.afterStaleProbe?.();let current=await stampOf(socketPath);if(current!==void 0){if(!sameStamp(probed,current))throw inUse("the entry changed after it was probed");try{await unlink(socketPath)}catch(cause){if(cause instanceof Error&&"code"in cause&&cause.code==="ENOENT")return;throw cause}}}function listen(server,socketPath,secret){return new Promise((resolve2,reject)=>{server.once("error",reject),server.listen({path:resolveSocketTransportAddress(socketPath,process.platform,secret),readableAll:!1,writableAll:!1},async()=>{server.off("error",reject);try{process.platform!=="win32"&&!socketPath.startsWith("\0")&&await chmod(socketPath,384),resolve2()}catch(cause){reject(cause)}})})}function closeServer(server){return new Promise(resolve2=>{server.close(()=>resolve2())})}import{randomUUID}from"node:crypto";import{mkdir as mkdir2,readFile as readFile3,writeFile}from"node:fs/promises";import{tmpdir}from"node:os";import{join as join3}from"node:path";var INTERNAL_HOST_DIR_PREFIX="senpi-rpc-host-internal-",SHORT_TEMP_ROOT="/tmp";function internalHostDirRoots(){let primary=tmpdir();return primary===SHORT_TEMP_ROOT?[primary]:[primary,SHORT_TEMP_ROOT]}function internalHostDirRoot(name){for(let root of internalHostDirRoots())if(Buffer.byteLength(join3(root,name,"host.sock"))<=MAX_SOCKET_PATH_BYTES)return root;throw new Error(`internal_socket_path_too_long: ${join3(tmpdir(),name,"host.sock")} exceeds ${MAX_SOCKET_PATH_BYTES} bytes and /tmp cannot hold it either; set TMPDIR to a shorter directory`)}async function createInternalSocketPath(baseDir=tmpdir(),platform=process.platform){if(platform==="win32"){let dir2=join3(baseDir,`internal-${randomUUID()}`);return await mkdir2(dir2,{recursive:!0,mode:448}),{socket:`\\\\.\\pipe\\senpi-rpc-internal-${randomUUID()}`,dir:dir2,secretPath:join3(dir2,"secret")}}let name=`${INTERNAL_HOST_DIR_PREFIX}${randomUUID().slice(0,8)}`,dir=join3(internalHostDirRoot(name),name);return await mkdir2(dir,{recursive:!1,mode:448}),await writeFile(join3(dir,".owner"),JSON.stringify({pid:process.pid,processStartTime:await readProcessStartTime(process.pid),createdAt:Date.now()}),{mode:384}),{socket:join3(dir,"host.sock"),dir,secretPath:join3(dir,".secret")}}var CHILD_START_TIME_WAIT_MS=1e4,CHILD_START_TIME_UNHURRIED_MS=15e3;async function readChildStartTime(pid,timeoutMs){let identity=await readProcessIdentity(pid,process.platform,timeoutMs,void 0,"UTC");if(identity.kind==="error")throw identity.error;return identity.kind==="present"?identity.identity:void 0}async function recordChildPid(file,pid,running){try{await writeJsonAtomic(file,{pid,processStartTime:null});let processStartTime=await waitForStartTime(pid,CHILD_START_TIME_WAIT_MS,p=>readChildStartTime(p,1e3)).catch(()=>{})??await readChildStartTime(pid,CHILD_START_TIME_UNHURRIED_MS).catch(()=>{});if(processStartTime===void 0){supervisorLog(`host child pid ${pid} start time unreadable at recording`);return}if(!running())return;await writeJsonAtomic(file,{pid,processStartTime})}catch(cause){supervisorLog(`could not record the host child pid: ${errorMessage(cause)}`)}}async function readSettingsFile(settingsFile){try{return JSON.parse(await readFile3(settingsFile,"utf8"))}catch{return}}import{rm as rm2}from"node:fs/promises";var LOOP_LAG_ERROR_MS_ENV="SENPI_RPC_LOOP_LAG_ERROR_MS",DEFAULT_LOOP_LAG_ERROR_MS=5e3;function loopLagErrorMs(env=process.env){return parseIdleExitMs(env[LOOP_LAG_ERROR_MS_ENV])??DEFAULT_LOOP_LAG_ERROR_MS}var STALL_WAIT_SLICE_MS=5e3;async function waitOutStalledChild(options){let{child,generation,signalledAt}=options,maxMs=childStalledStopMaxMs(),untilAt=signalledAt+maxMs,stalled=()=>hostLoopStalled(generation,{now:Date.now(),errorMs:loopLagErrorMs(),windowMs:STOP_STALL_EVIDENCE_MAX_AGE_MS}).catch(()=>!1),waited=0;try{for(;Date.now()<untilAt&&await stalled();){waited===0&&supervisorLog(`host child is stalled; waiting up to ${maxMs}ms (${CHILD_STALLED_STOP_MAX_MS_ENV})`),await writeStopProgress(generation,{at:new Date().toISOString(),phase:"waiting_stalled_child",untilAt:new Date(untilAt).toISOString()}).catch(()=>{});let slice=Math.min(STALL_WAIT_SLICE_MS,untilAt-Date.now()),exited=await options.waitForExit(child,slice);if(waited+=slice,exited)break}}finally{await clearStopProgress(generation)}return waited}var WINDOWS_SUPERVISOR_SHUTDOWN_HARD_EXIT_MS=2e3;function supervisorSender(instanceId){return{pid:process.pid,kind:"supervisor",generation:instanceId}}function childExited(child){return child.exitCode!==null||child.signalCode!==null}async function performShutdown(context,reason,exitCode){let{state,child}=context;state.shuttingDown=!0,state.shutdownReason=reason,context.admission.stop();let childStopStarted=!1,hardExit;try{context.stopWatchers(),context.drain.stop(),writeStderrLine(`senpi rpc host supervisor: ${reason} shutdown`),childStopStarted=!0,await stopChild(context,reason),await state.childExitRecorded,await context.admission.flush(),context.activity.clients.destroyAll(),process.platform==="win32"&&(hardExit=setTimeout(()=>process.exit(exitCode),WINDOWS_SUPERVISOR_SHUTDOWN_HARD_EXIT_MS)),context.drain.active||await shieldSocketDuringClose(context.publicSocket,()=>closeServer(context.server)),context.internalDir&&await rm2(context.internalDir,{recursive:!0,force:!0}),context.activity.stopObserver(),state.publicSocketOwned&&process.platform!=="win32"&&await unlinkOwnedSocket(context.publicSocket,state.publicSocketIdentity,supervisorLog),await releaseGeneration(context.paths,{instanceId:context.instanceId,pid:process.pid,superseded:state.endpointReplaced})}catch(cause){supervisorLog(`shutdown failed for host child pid ${child.pid??"unknown"}: ${errorMessage(cause)}`),exitCode=1;try{childStopStarted||await reapChildAfterFailure(child),await state.childExitRecorded}catch(reapCause){supervisorLog(`shutdown recovery failed for host child pid ${child.pid??"unknown"}: ${errorMessage(reapCause)}`)}}finally{hardExit&&clearTimeout(hardExit),process.exit(exitCode)}}async function stopChild(context,reason){let{child,generation}=context,pid=child.pid;if(childExited(child)||pid===void 0)return;let termAttempted=!1,killAttempted=!1;try{let outer=await readStopIntent(generation).catch(cause=>{supervisorLog(`cannot read child stop intent: ${errorMessage(cause)}`)}),at=new Date().toISOString(),intent=layeredSupervisorIntent(outer,supervisorSender(context.instanceId),{targetPid:pid,reason,at});await writeStopIntent(generation,intent,supervisorLog);let signalledAt=Date.now();if(termAttempted=!0,signalChild(pid,"SIGTERM"),await waitForChildExit(child,CHILD_STOP_TIMEOUT_MS))return;let stallWaitMs=await waitOutStalledChild({child,generation,signalledAt,waitForExit:waitForChildExit});if(childExited(child))return;if(stallWaitMs>0){let escalated={...intent,reason:`${intent.reason}; escalated_after_stall_wait=${stallWaitMs}`};await writeStopIntent(generation,escalated,supervisorLog)}if(killAttempted=!0,signalChild(pid,"SIGKILL"),!await waitForChildExit(child,CHILD_KILL_EXIT_TIMEOUT_MS))throw new Error(`host child pid ${pid} exit unobserved ${CHILD_KILL_EXIT_TIMEOUT_MS}ms after SIGKILL`)}catch(cause){throw killAttempted||await reapChildAfterFailure(child,termAttempted),cause}}async function reapChildAfterFailure(child,termAttempted=!1){let pid=child.pid;if(!(childExited(child)||pid===void 0)&&!(!termAttempted&&(signalChild(pid,"SIGTERM"),await waitForChildExit(child,CHILD_STOP_TIMEOUT_MS)))&&(signalChild(pid,"SIGKILL"),!await waitForChildExit(child,CHILD_KILL_EXIT_TIMEOUT_MS)))throw new Error(`host child pid ${pid} exit unobserved ${CHILD_KILL_EXIT_TIMEOUT_MS}ms after recovery SIGKILL`)}function signalChild(pid,signal){try{return process.kill(pid,signal),!0}catch{return!1}}function waitForChildExit(child,timeoutMs){return childExited(child)?Promise.resolve(!0):new Promise(resolve2=>{let timer=setTimeout(()=>{child.off("exit",onExit2),resolve2(!1)},timeoutMs),onExit2=()=>{clearTimeout(timer),resolve2(!0)};child.once("exit",onExit2)})}function registerSupervisorSignals(shutdown,drain){for(let signal of process.platform==="win32"?["SIGTERM"]:["SIGTERM","SIGHUP"])process.on(signal,()=>{shutdown(`signal:${signal}`,signal==="SIGHUP"?129:143)});process.platform!=="win32"&&process.on("SIGUSR1",drain)}function startSupervisorTicker(options){let{activity,owner,draining,shuttingDown,shutdown}=options,tickIntervalMs=Math.max(20,Math.min(1e3,options.idleExitMs/4)),ownerCheck=!1,ticker=setInterval(()=>{!draining()&&activity.refresh()==="exit"&&activity.clients.unclassifiedCount===0&&shutdown("idle",0),!ownerCheck&&!shuttingDown()&&!draining()&&(ownerCheck=!0,owner.shouldExit(activity).then(exit=>{exit&&!shuttingDown()&&!draining()&&shutdown("owner_gone",0)}).finally(()=>{ownerCheck=!1}))},tickIntervalMs);return()=>{clearInterval(ticker),owner.stop()}}async function runHostSupervisor(launch){let paths=createHostDaemonPaths({socket:launch.socket,agentDir:launch.agentDir??getAgentDir()}),told=process.env[HOST_INSTANCE_ID_ENV],instanceId=told!==void 0&&told.trim()!==""?told:randomUUID2(),generation=generationPaths(paths,instanceId),policy=resolveHostPolicy(await readSettingsFile(paths.settingsFile),process.env),publicSocket=launch.socket,bindSocket=launch.bindSocket??publicSocket,successor=launch.bindSocket!==void 0,publicSecret=process.platform==="win32"?await ensurePublicSocketSecret(publicSocket):void 0,internal=await createInternalSocketPath(paths.dir),internalSocket=internal.socket,internalSecretPath=internal.secretPath??socketSecretPath(internalSocket),internalSecret=process.platform==="win32"?await createSocketSecret(internalSecretPath):void 0,state={shuttingDown:!1,shutdownReason:void 0,childExitRecorded:Promise.resolve(),publicSocketOwned:!1,publicSocketIdentity:void 0,endpointReplaced:!1},owner=new SupervisorOwner(generation.dir),activity=new SupervisorActivity({idleExitMs:policy.coldStart==="persistent"?Number.POSITIVE_INFINITY:policy.idleExitMs,internalSocket,...internalSecret?{internalSecret}:{},instanceId,settled:()=>state.shuttingDown,onActivity:()=>owner.activity()}),watchers=[],child=spawnHostChild({launch,internalSocket,internal:{...internal,secretPath:internalSecretPath},...internalSecret?{internalSecret}:{},daemonDir:paths.dir,instanceId,cleanupPaths:hostCrashCleanupPaths({pointerFile:paths.pointerFile,generationPidFile:generation.pidFile,settingsFile:paths.settingsFile,publicSocket,successor:!!successor,platform:process.platform}),publicSocket}),childStartedAt=Date.now();child.stdio[HOST_CHILD_WATCH_FD]?.on("error",()=>{}),child.pid!==void 0&&recordChildPid(generation.childPidFile,child.pid,()=>child.exitCode===null&&child.signalCode===null),child.once("exit",(code,signal)=>{let reason=state.shutdownReason;if(state.childExitRecorded=noteChildExit({daemonDir:paths.dir,generation,instanceId,code,signal,childStartedAt,...state.shuttingDown&&reason!==void 0?{shutdown:{reason,supervisor:supervisorSender(instanceId)}}:{}}),state.shuttingDown)return;let verdict=classifyChildExit(code,signal);state.childExitRecorded.then(()=>shutdown(verdict.reason,verdict.exitCode))});let admission=new HostAdmission({protocolVersion:1,serverVersion:VERSION,capabilities:[],instanceId}),drain=new SupervisorDrain(child,()=>state.shuttingDown,()=>admission.stop(),{file:generation.childDrainRequestFile,sender:supervisorSender(instanceId)}),server=createPublicProxy({internalSocket,...internalSecret?{internalSecret}:{},...publicSecret?{publicSecret}:{},clients:activity.clients,admission,onDetach:()=>activity.refresh(),onAdmit:()=>owner.activity()});server.once("error",cause=>{state.shuttingDown||shutdown(`public socket listener failed: ${errorMessage(cause)}`,1)}),watchers.push(startSupervisorTicker({idleExitMs:policy.idleExitMs,activity,owner,draining:()=>drain.active,shuttingDown:()=>state.shuttingDown,shutdown}));let teardown={paths,generation,instanceId,publicSocket,server,internalDir:internal.dir,child,activity,drain,admission,state,stopWatchers:()=>{for(let stop of watchers.splice(0))stop()}},shutdownPromise;function shutdown(reason,exitCode){return shutdownPromise??=performShutdown(teardown,reason,exitCode),shutdownPromise}registerSupervisorSignals(shutdown,()=>drain.drain());try{(launch.ownerFd!==void 0||await readSettingsFile(generation.settingsFile))&&await owner.start(launch.ownerFd),await waitForListener(internalSocket,3e4,internalSecret),await activity.openObserver(),await prepareSocketPath(bindSocket),await listen(server,bindSocket,publicSecret),state.publicSocketOwned=!0,successor&&await adoptPublicSocket(bindSocket,publicSocket,launch.replaceIdentity),state.publicSocketIdentity=await statSocketIdentity(publicSocket),state.publicSocketIdentity&&internal.dir&&await writeSocketIdentityFile(join4(internal.dir,PUBLIC_SOCKET_IDENTITY_FILE),state.publicSocketIdentity),watchers.push(drainOnPublicSocketLoss(publicSocket,state.publicSocketIdentity,()=>state.shuttingDown||drain.active,drain,()=>{state.endpointReplaced=!0},{file:paths.pointerFile,instanceId})),watchers.push(await drain.acceptRequests(generation))}catch(cause){await shutdown(`startup failed: ${errorMessage(cause)}`,1)}process.platform==="win32"&&watchers.push(await watchWin32ChildIdentity(child,()=>state.shuttingDown,()=>{shutdown("rpc host child exit observed by identity watchdog",0)})),writeStderrLine(`senpi rpc host ready on unix://${publicSocket} (coldStart=${policy.coldStart}, idleExitMs=${policy.coldStart==="persistent"?"never":String(policy.idleExitMs)})`),await new Promise(()=>{})}function isEntryScript(){let entry=process.argv[1];if(!entry)return!1;try{return fileURLToPath2(import.meta.url)===realpathSync(entry)}catch{return!1}}if(!isBundledNode&&isEntryScript()){let launch=parseSupervisorArgs(process.argv.slice(2));launch||(writeStderrLine("usage: host-lifecycle.ts --socket <path> [host cli args...]"),process.exit(2)),runHostSupervisor(launch)}export{runtimeExecArgv,loopLagErrorMs,recordProcessLifetime,isHostCrash,readHostCrashRecords,classifyChildExit,noteEscalatedStop,ClientOccupancy,resolveCliMainPath,resolveCliMainPathAsync,readHostWatchdogConfigFromBrandEnv,armHostWatchdog,INTERNAL_SUPERVISOR_FLAG,findInternalSupervisorArgs,parseSupervisorArgs,OWNER_WATCH_FD,keepOwnerPipe,resolveHostChildLaunch,spawnableChildLaunch,prepareSocketPath,INTERNAL_HOST_DIR_PREFIX,internalHostDirRoots,createInternalSocketPath,runHostSupervisor};