@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{SessionEventWriter,answerSetSessionContext,answerSubscribeSessions,answerUnsubscribeSessions,notAttachedRefusal,publishedSessionContext,recordLoopBlockedMs,registryStatusSource,socketSink}from"./chunk-DXOSXUVI.js";import{ACCEPT_EDITS_PERMISSION_PRESET_CAPABILITY,AUTO_PERMISSION_PRESET_CAPABILITY,AgentSessionRuntime,HostMcpRegistry,ProviderScope,bindToProviderScope,createAgentSessionRuntime,createRpcConnectionHandler,createWebViewBroker,foreignSessionHolders,parsePermissionPresetName,readCodemodeKernelRows,readMainThreadHeapBytes,runWithProviderScope,startHostChildReaper,subscriptionLimits}from"./chunk-F4ZU4RBE.js";import{readProcessStartMs}from"./chunk-HOXW5IHD.js";import"./chunk-25FRFTSP.js";import{ClientAdmissions,DURABLE_CLIENT_MESSAGE_ID_CAPABILITY,EFFECT_LEDGER_CAPABILITY,EMPTY_SESSION_CONTEXT,EffectLedger,answerEffectFromTranscript,beginEffect,buildRpcSessionState,drainSessionEffects,effectAnswer,installSessionEffectSink,isEffectBegin,latestSessionEffect,rpcCommandShapeError,sessionAutoTitleError,sessionBrowserEngineError,sessionContextError,sessionKindError,sessionPromptSurfaceError,sessionRetryFallbackError}from"./chunk-DY2EM44T.js";import"./chunk-FDCYQYBP.js";import{RPC_ERROR_ATTACHED,RPC_ERROR_HOST_DRAINING,RPC_ERROR_INVALID_LAUNCH_PROFILE,RPC_ERROR_INVALID_PATH,RPC_ERROR_INVALID_RELEASE_REASON,RPC_ERROR_INVALID_SESSION_CONTEXT,RPC_ERROR_INVALID_SESSION_KIND,RPC_ERROR_MISSING_SESSION_ID,RPC_ERROR_OPEN_FAILED,RPC_ERROR_OWNER_CHANGED,RPC_ERROR_RELEASE_FAILED,RPC_ERROR_RELEASE_UNSUPPORTED,RPC_ERROR_SESSION_BUSY,RPC_ERROR_SESSION_CLOSING,RPC_ERROR_SESSION_HELD,RPC_ERROR_TURN_ACTIVE,RPC_ERROR_UNKNOWN_SESSION,RPC_ERROR_WARM_FAILED,STEER_WHEN_IDLE_CAPABILITY}from"./chunk-MF57DS3V.js";import"./chunk-KW6654UH.js";import"./chunk-SR7DBNWN.js";import"./chunk-2MOGCBPT.js";import{flushRawStdout,liveToolMediaScope,takeOverStdout,toolMediaPersister,waitForRawStdoutBackpressure,writeRawStdout}from"./chunk-2RLZXLXS.js";import"./chunk-EFJKVUID.js";import"./chunk-T2EE5G4S.js";import{SessionManager,SessionMovedAwayError,assertValidSessionId}from"./chunk-GX7MTG25.js";import{resolveMovedPath}from"./chunk-ZMS6YEAO.js";import"./chunk-HMK6F3RG.js";import"./chunk-74V6LCWU.js";import"./chunk-QZBH7PDO.js";import{readOwnFootprint}from"./chunk-MTQQ2VQH.js";import{BEGIN_HANDOVER_COMMAND,EXPECTED_RUNTIME_BUILD_ID_ENV,HostIdleHandover,beginHandoverResponse,handoverRefusal,isHandoffBusy,isHostIdle,parseBeginHandover,performIdleHandover,readDrainVerdicts,runAsHostGenerationProcess,withHostIdentity}from"./chunk-Z32CYNHC.js";import{AUTH_KEY_VERIFY_CAPABILITY,AUTO_TITLE_PER_SESSION_CAPABILITY,AUTO_TITLE_SESSIONS_CAPABILITY,BROWSER_ENGINE_CAPABILITY,CONTINUE_FROM_LEAF_CAPABILITY,DETACH_CONNECTION_CAPABILITY,DURABLE_SESSION_ID_CAPABILITY,EVAL_CELLS_CAPABILITY,GENERATION_HANDOFF_CAPABILITY,MEDIA_PLACEHOLDERS_CAPABILITY,MOVED_PATH_GUARD_CAPABILITY,PROMPT_SURFACE_CAPABILITY,PROMPT_SURFACE_CHAT_CAPABILITY,QUEUED_MESSAGE_REVISION_CAPABILITY,RETAIN_ON_DISCONNECT_CAPABILITY,RETRY_FALLBACK_PROFILE_CAPABILITY,RUNTIME_IDENTITY_HANDOVER_CAPABILITY,SESSION_CONTEXT_CAPABILITY,SESSION_HELD_CAPABILITY,SESSION_KIND_CAPABILITY,SESSION_STATUS_CAPABILITY,WARM_CAPABILITY,computeRuntimeBuildId,hostGeneration,hostInstanceId,parseClientCapabilities,protocolIdentity}from"./chunk-YID5W42N.js";import"./chunk-6IWSMXBA.js";import"./chunk-QMRJYMNH.js";import"./chunk-FM7NDZR5.js";import{isHostOwnedToolRuntimeCapability,toolRuntimeCapabilities}from"./chunk-EPQK674G.js";import"./chunk-26UBFF6N.js";import"./chunk-IBDADH5Z.js";import"./chunk-3474DPZK.js";import{ClientOccupancy,armHostWatchdog,loopLagErrorMs,prepareSocketPath,readHostWatchdogConfigFromBrandEnv}from"./chunk-77PVTNLJ.js";import{SESSION_PATH_RETRY_AFTER_MS,createEndpointReservations,hostChildDrainRequestFile,ownGenerationDir,parseIdleExitMs,watchDrainRequest,writeHeartbeat,writeStallEvidence}from"./chunk-DDQJSVIZ.js";import{MAX_RPC_LINE_CHARACTERS,attachJsonlLineReader,canonicalSessionPath,createHostDaemonPaths,sessionDirectoryRemoved}from"./chunk-KUZPBZUK.js";import"./chunk-IQWPR35S.js";import"./chunk-H4QOEVS5.js";import"./chunk-KLAX467B.js";import"./chunk-HB35RBP4.js";import"./chunk-QXJVKVA2.js";import"./chunk-7X72IACK.js";import"./chunk-GZVCRV7I.js";import"./chunk-KUPQO7MC.js";import"./chunk-U3VOXCGP.js";import"./chunk-QXREUA5F.js";import"./chunk-RUGYFYH7.js";import"./chunk-OEFCY46F.js";import"./chunk-KRNXUTZJ.js";import"./chunk-TAV6QZFM.js";import"./chunk-PELNNWGO.js";import"./chunk-4CJJ4SK6.js";import"./chunk-JKNUKBS3.js";import{killTrackedDetachedChildren}from"./chunk-EKDY4H2J.js";import"./chunk-YU4AYH4C.js";import"./chunk-2IK7QUJX.js";import"./chunk-COH5F7QV.js";import"./chunk-RFB5CBW7.js";import"./chunk-2VZJTDUX.js";import"./chunk-XSRM367N.js";import"./chunk-WASCMT6Y.js";import"./chunk-T36LJ6MW.js";import"./chunk-QGJLZ6BI.js";import"./chunk-UAQW2T7G.js";import"./chunk-WHPDEDCC.js";import"./chunk-HK46JMSC.js";import"./chunk-WQLMQGOW.js";import"./chunk-WDTJ6JKE.js";import"./chunk-5ROMKDLK.js";import"./chunk-3W47LTXQ.js";import"./chunk-45SZOLCU.js";import"./chunk-LAWS3FYQ.js";import"./chunk-DMI55M2N.js";import"./chunk-PJ34QVL5.js";import"./chunk-BMX2U22F.js";import"./chunk-YU2P3CAR.js";import"./chunk-ADNKYKU4.js";import"./chunk-ZOFZRJSL.js";import"./chunk-2SOVDETB.js";import"./chunk-RAIZG6HA.js";import{PUBLIC_SOCKET_IDENTITY_FILE,readSocketIdentityFile,shieldSocketDuringClose,socketEntryReplaced,statSocketIdentity,unlinkOwnedSocket,waitForSocketIdentityFile}from"./chunk-HRPMLI7O.js";import{SOCKET_SECRET_FILE_ENV,authenticateSocket,ensureSocketSecret,resolveSocketTransportAddress,socketSecretPath}from"./chunk-QEQG42HL.js";import{VERSION,envValue,isBunBinary}from"./chunk-4J4ABCCL.js";import"./chunk-ATQFN5HI.js";import"./chunk-MIENF2YK.js";import"./chunk-OXNWERO4.js";import{ownProcessStartedAtMs}from"./chunk-QN2BHP3M.js";import"./chunk-WIAXG52U.js";import{processStartTimeMs}from"./chunk-7ASLQ243.js";import"./chunk-IKOFCODM.js";import{chmod}from"node:fs/promises";import{createServer}from"node:net";import{basename,dirname,join as join2}from"node:path";var HostCoreGate=class{constructor(registry,route,hooks){this.inFlight=new Map,this.answering=new Set,this.route=route,this.runtimeBuildId=hooks.runtimeBuildId,this.handover=hooks.handover===void 0?void 0:new HostIdleHandover({...hooks.handover,isIdle:()=>isHostIdle(registry,this.inFlight)})}async intercept(parsed,deliver){if(!isRecord(parsed)||parsed.type!==BEGIN_HANDOVER_COMMAND)return!1;let answering=this.answerBegin(parsed).then(deliver);this.answering.add(answering);try{await answering}finally{this.answering.delete(answering)}return!0}async answerBegin(parsed){if(this.handover===void 0)return beginHandoverResponse(parsed.id,{kind:"refused",reason:"handover_unsupported"});let request=parseBeginHandover(parsed);return beginHandoverResponse(parsed.id,typeof request=="string"?request:await this.handover.begin(request))}async answered(){for(;this.answering.size>0;)await Promise.allSettled([...this.answering])}async dispatch(command){let pending=this.handover?.view();if(pending!==void 0&&this.handover?.admits(command.type)===!1)return handoverRefusal(command,pending);let key="sessionId"in command?command.sessionId:void 0;this.inFlight.set(key,(this.inFlight.get(key)??0)+1);let response;try{response=await this.route(command)}finally{let remaining=(this.inFlight.get(key)??1)-1;remaining>0?this.inFlight.set(key,remaining):this.inFlight.delete(key),this.handover?.observe()}return response===void 0?void 0:withHostIdentity(response,this.runtimeBuildId,this.handover?.view())}};function isRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}import{existsSync as existsSync4}from"node:fs";import{createHash}from"node:crypto";import{existsSync,renameSync}from"node:fs";import{mkdir,readdir,readFile,rm,writeFile}from"node:fs/promises";import{join}from"node:path";var recordDir=daemonDir=>join(daemonDir,"handover-parked"),entryFile=(daemonDir,sessionPath)=>join(recordDir(daemonDir),`${createHash("sha256").update(sessionPath,"utf8").digest("hex").slice(0,16)}.json`),mutationChain=Promise.resolve();function enqueueMutation(mutation){let next=mutationChain.then(mutation,mutation);return mutationChain=next.catch(()=>{}),next}function isEntry(value){if(typeof value!="object"||value===null||Array.isArray(value))return!1;let record=value;return typeof record.sessionPath=="string"&&typeof record.retainOnDisconnect=="boolean"&&(record.durableSessionId===void 0||typeof record.durableSessionId=="string")&&(record.cwd===void 0||typeof record.cwd=="string")&&(record.parkedBy===void 0||typeof record.parkedBy=="string")&&(record.thinkingLevel===void 0||typeof record.thinkingLevel=="string")&&(record.permissionPreset===void 0||typeof record.permissionPreset=="string"&&parsePermissionPresetName(record.permissionPreset)!==void 0)&&sessionPromptSurfaceError(record.promptSurface)===void 0&&sessionBrowserEngineError(record.browserEngine)===void 0&&sessionKindError(record.sessionKind)===void 0&&sessionContextError(record.sessionContext)===void 0&&sessionAutoTitleError(record.autoTitle)===void 0&&sessionRetryFallbackError(record.retryFallback)===void 0&&(record.model===void 0||typeof record.model=="object"&&record.model!==null&&typeof record.model.provider=="string"&&typeof record.model.modelId=="string")}async function writeEntryFile(daemonDir,entry){await mkdir(recordDir(daemonDir),{recursive:!0,mode:448});let file=entryFile(daemonDir,entry.sessionPath),tmp=`${file}.${process.pid}.${Math.random().toString(16).slice(2,10)}.tmp`;await writeFile(tmp,`${JSON.stringify(entry,null,2)}
2
+ import{SessionEventWriter,answerSetSessionContext,answerSubscribeSessions,answerUnsubscribeSessions,notAttachedRefusal,publishedSessionContext,recordLoopBlockedMs,registryStatusSource,socketSink}from"./chunk-3YKKXTJM.js";import{ACCEPT_EDITS_PERMISSION_PRESET_CAPABILITY,AUTO_PERMISSION_PRESET_CAPABILITY,AgentSessionRuntime,HostMcpRegistry,ProviderScope,bindToProviderScope,createAgentSessionRuntime,createRpcConnectionHandler,createWebViewBroker,foreignSessionHolders,parsePermissionPresetName,readCodemodeKernelRows,readMainThreadHeapBytes,runWithProviderScope,startHostChildReaper,subscriptionLimits}from"./chunk-YIRQJCPA.js";import"./chunk-JVLIKUBL.js";import{readProcessStartMs}from"./chunk-FC2YWHEC.js";import{flushRawStdout,liveToolMediaScope,takeOverStdout,toolMediaPersister,waitForRawStdoutBackpressure,writeRawStdout}from"./chunk-2LQZJFKQ.js";import"./chunk-25FRFTSP.js";import"./chunk-EFJKVUID.js";import{ClientAdmissions,DURABLE_CLIENT_MESSAGE_ID_CAPABILITY,EFFECT_LEDGER_CAPABILITY,EMPTY_SESSION_CONTEXT,EffectLedger,answerEffectFromTranscript,beginEffect,buildRpcSessionState,drainSessionEffects,effectAnswer,installSessionEffectSink,isEffectBegin,latestSessionEffect,rpcCommandShapeError,sessionAutoTitleError,sessionBrowserEngineError,sessionContextError,sessionKindError,sessionPromptSurfaceError,sessionRetryFallbackError}from"./chunk-2JGY3V4H.js";import{RPC_ERROR_ATTACHED,RPC_ERROR_HOST_DRAINING,RPC_ERROR_INVALID_LAUNCH_PROFILE,RPC_ERROR_INVALID_PATH,RPC_ERROR_INVALID_RELEASE_REASON,RPC_ERROR_INVALID_SESSION_CONTEXT,RPC_ERROR_INVALID_SESSION_KIND,RPC_ERROR_MISSING_SESSION_ID,RPC_ERROR_OPEN_FAILED,RPC_ERROR_OWNER_CHANGED,RPC_ERROR_RELEASE_FAILED,RPC_ERROR_RELEASE_UNSUPPORTED,RPC_ERROR_SESSION_BUSY,RPC_ERROR_SESSION_CLOSING,RPC_ERROR_SESSION_HELD,RPC_ERROR_TURN_ACTIVE,RPC_ERROR_UNKNOWN_SESSION,RPC_ERROR_WARM_FAILED,STEER_WHEN_IDLE_CAPABILITY}from"./chunk-MF57DS3V.js";import"./chunk-FRFGJC3I.js";import{SessionManager,SessionMovedAwayError,assertValidSessionId}from"./chunk-TK6RKAB4.js";import{resolveMovedPath}from"./chunk-ZMS6YEAO.js";import"./chunk-RPAHOJ6F.js";import"./chunk-SR7DBNWN.js";import"./chunk-2MOGCBPT.js";import"./chunk-HMK6F3RG.js";import"./chunk-6L3H4UVN.js";import"./chunk-QZBH7PDO.js";import"./chunk-SOMFLLPD.js";import{readOwnFootprint}from"./chunk-MTQQ2VQH.js";import{BEGIN_HANDOVER_COMMAND,EXPECTED_RUNTIME_BUILD_ID_ENV,HostIdleHandover,beginHandoverResponse,handoverRefusal,isHandoffBusy,isHostIdle,parseBeginHandover,performIdleHandover,readDrainVerdicts,runAsHostGenerationProcess,withHostIdentity}from"./chunk-F4YDU66P.js";import{AUTH_KEY_VERIFY_CAPABILITY,AUTO_TITLE_PER_SESSION_CAPABILITY,AUTO_TITLE_SESSIONS_CAPABILITY,BROWSER_ENGINE_CAPABILITY,CONTINUE_FROM_LEAF_CAPABILITY,DETACH_CONNECTION_CAPABILITY,DURABLE_SESSION_ID_CAPABILITY,EVAL_CELLS_CAPABILITY,GENERATION_HANDOFF_CAPABILITY,MEDIA_PLACEHOLDERS_CAPABILITY,MOVED_PATH_GUARD_CAPABILITY,PROMPT_SURFACE_CAPABILITY,PROMPT_SURFACE_CHAT_CAPABILITY,QUEUED_MESSAGE_REVISION_CAPABILITY,RETAIN_ON_DISCONNECT_CAPABILITY,RETRY_FALLBACK_PROFILE_CAPABILITY,RUNTIME_IDENTITY_HANDOVER_CAPABILITY,SESSION_CONTEXT_CAPABILITY,SESSION_HELD_CAPABILITY,SESSION_KIND_CAPABILITY,SESSION_STATUS_CAPABILITY,WARM_CAPABILITY,computeRuntimeBuildId,hostGeneration,hostInstanceId,parseClientCapabilities,protocolIdentity}from"./chunk-KXTWMPCP.js";import"./chunk-QMRJYMNH.js";import"./chunk-6IWSMXBA.js";import"./chunk-FM7NDZR5.js";import{isHostOwnedToolRuntimeCapability,toolRuntimeCapabilities}from"./chunk-EPQK674G.js";import"./chunk-26UBFF6N.js";import"./chunk-IBDADH5Z.js";import"./chunk-3474DPZK.js";import{ClientOccupancy,armHostWatchdog,loopLagErrorMs,prepareSocketPath,readHostWatchdogConfigFromBrandEnv}from"./chunk-W557SQYL.js";import{SESSION_PATH_RETRY_AFTER_MS,createEndpointReservations,holderGenerationEnded,hostChildDrainRequestFile,ownGenerationDir,parseIdleExitMs,watchDrainRequest,writeHeartbeat,writeStallEvidence}from"./chunk-DKBJM22C.js";import{HOST_DAEMON_DIR_ENV,MAX_RPC_LINE_CHARACTERS,attachJsonlLineReader,canonicalSessionPath,createHostDaemonPaths,sessionDirectoryRemoved}from"./chunk-KUZPBZUK.js";import"./chunk-IQWPR35S.js";import"./chunk-H4QOEVS5.js";import"./chunk-KLAX467B.js";import"./chunk-HB35RBP4.js";import"./chunk-QXJVKVA2.js";import"./chunk-7X72IACK.js";import"./chunk-GZVCRV7I.js";import"./chunk-KUPQO7MC.js";import"./chunk-U3VOXCGP.js";import"./chunk-QXREUA5F.js";import"./chunk-RUGYFYH7.js";import"./chunk-OEFCY46F.js";import"./chunk-KRNXUTZJ.js";import"./chunk-TAV6QZFM.js";import"./chunk-PELNNWGO.js";import"./chunk-SOWFP3I7.js";import"./chunk-JKNUKBS3.js";import{killTrackedDetachedChildren}from"./chunk-JXCHRJA7.js";import"./chunk-YU4AYH4C.js";import"./chunk-2SM4TR4H.js";import"./chunk-COH5F7QV.js";import"./chunk-RFB5CBW7.js";import"./chunk-2VZJTDUX.js";import"./chunk-XSRM367N.js";import"./chunk-WASCMT6Y.js";import"./chunk-T36LJ6MW.js";import"./chunk-QGJLZ6BI.js";import"./chunk-WHPDEDCC.js";import"./chunk-AA2L2RHH.js";import"./chunk-HK46JMSC.js";import"./chunk-WQLMQGOW.js";import"./chunk-WDTJ6JKE.js";import"./chunk-5ROMKDLK.js";import"./chunk-3W47LTXQ.js";import"./chunk-LAWS3FYQ.js";import"./chunk-45SZOLCU.js";import"./chunk-DMI55M2N.js";import"./chunk-PJ34QVL5.js";import"./chunk-BMX2U22F.js";import"./chunk-YU2P3CAR.js";import"./chunk-RYQ2FFF5.js";import"./chunk-ZOFZRJSL.js";import"./chunk-2SOVDETB.js";import"./chunk-RAIZG6HA.js";import{PUBLIC_SOCKET_IDENTITY_FILE,readSocketIdentityFile,shieldSocketDuringClose,socketEntryReplaced,statSocketIdentity,unlinkOwnedSocket,waitForSocketIdentityFile}from"./chunk-HRPMLI7O.js";import{SOCKET_SECRET_FILE_ENV,authenticateSocket,ensureSocketSecret,resolveSocketTransportAddress,socketSecretPath}from"./chunk-QEQG42HL.js";import{VERSION,envValue,isBunBinary}from"./chunk-4J4ABCCL.js";import"./chunk-ATQFN5HI.js";import"./chunk-MIENF2YK.js";import"./chunk-OXNWERO4.js";import{ownProcessStartedAtMs}from"./chunk-QN2BHP3M.js";import"./chunk-WIAXG52U.js";import{processStartTimeMs}from"./chunk-7ASLQ243.js";import"./chunk-IKOFCODM.js";import{chmod}from"node:fs/promises";import{createServer}from"node:net";import{basename,dirname,join as join2}from"node:path";var HostCoreGate=class{constructor(registry,route,hooks){this.inFlight=new Map,this.answering=new Set,this.route=route,this.runtimeBuildId=hooks.runtimeBuildId,this.handover=hooks.handover===void 0?void 0:new HostIdleHandover({...hooks.handover,isIdle:()=>isHostIdle(registry,this.inFlight)})}async intercept(parsed,deliver){if(!isRecord(parsed)||parsed.type!==BEGIN_HANDOVER_COMMAND)return!1;let answering=this.answerBegin(parsed).then(deliver);this.answering.add(answering);try{await answering}finally{this.answering.delete(answering)}return!0}async answerBegin(parsed){if(this.handover===void 0)return beginHandoverResponse(parsed.id,{kind:"refused",reason:"handover_unsupported"});let request=parseBeginHandover(parsed);return beginHandoverResponse(parsed.id,typeof request=="string"?request:await this.handover.begin(request))}async answered(){for(;this.answering.size>0;)await Promise.allSettled([...this.answering])}async dispatch(command){let pending=this.handover?.view();if(pending!==void 0&&this.handover?.admits(command.type)===!1)return handoverRefusal(command,pending);let key="sessionId"in command?command.sessionId:void 0;this.inFlight.set(key,(this.inFlight.get(key)??0)+1);let response;try{response=await this.route(command)}finally{let remaining=(this.inFlight.get(key)??1)-1;remaining>0?this.inFlight.set(key,remaining):this.inFlight.delete(key),this.handover?.observe()}return response===void 0?void 0:withHostIdentity(response,this.runtimeBuildId,this.handover?.view())}};function isRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}import{existsSync as existsSync4}from"node:fs";import{createHash}from"node:crypto";import{existsSync,renameSync}from"node:fs";import{mkdir,readdir,readFile,rm,writeFile}from"node:fs/promises";import{join}from"node:path";var recordDir=daemonDir=>join(daemonDir,"handover-parked"),entryFile=(daemonDir,sessionPath)=>join(recordDir(daemonDir),`${createHash("sha256").update(sessionPath,"utf8").digest("hex").slice(0,16)}.json`),mutationChain=Promise.resolve();function enqueueMutation(mutation){let next=mutationChain.then(mutation,mutation);return mutationChain=next.catch(()=>{}),next}function isEntry(value){if(typeof value!="object"||value===null||Array.isArray(value))return!1;let record=value;return typeof record.sessionPath=="string"&&typeof record.retainOnDisconnect=="boolean"&&(record.durableSessionId===void 0||typeof record.durableSessionId=="string")&&(record.cwd===void 0||typeof record.cwd=="string")&&(record.parkedBy===void 0||typeof record.parkedBy=="string")&&(record.thinkingLevel===void 0||typeof record.thinkingLevel=="string")&&(record.permissionPreset===void 0||typeof record.permissionPreset=="string"&&parsePermissionPresetName(record.permissionPreset)!==void 0)&&sessionPromptSurfaceError(record.promptSurface)===void 0&&sessionBrowserEngineError(record.browserEngine)===void 0&&sessionKindError(record.sessionKind)===void 0&&sessionContextError(record.sessionContext)===void 0&&sessionAutoTitleError(record.autoTitle)===void 0&&sessionRetryFallbackError(record.retryFallback)===void 0&&(record.model===void 0||typeof record.model=="object"&&record.model!==null&&typeof record.model.provider=="string"&&typeof record.model.modelId=="string")}async function writeEntryFile(daemonDir,entry){await mkdir(recordDir(daemonDir),{recursive:!0,mode:448});let file=entryFile(daemonDir,entry.sessionPath),tmp=`${file}.${process.pid}.${Math.random().toString(16).slice(2,10)}.tmp`;await writeFile(tmp,`${JSON.stringify(entry,null,2)}
3
3
  `,{mode:384}),renameSync(tmp,file)}function recordHandoverParkedSession(daemonDir,entry){return enqueueMutation(()=>writeEntryFile(daemonDir,entry))}async function readHandoverParkedSessions(daemonDir){let names;try{names=(await readdir(recordDir(daemonDir))).filter(name=>name.endsWith(".json"))}catch{return[]}let entries=[];for(let name of names){let file=join(recordDir(daemonDir),name);try{let parsed=JSON.parse(await readFile(file,"utf8"));isEntry(parsed)&&entries.push(parsed)}catch(cause){cause instanceof SyntaxError&&(process.stderr.write(`senpi rpc handover-parked entry ${name} is corrupt; dropping it
4
4
  `),await rm(file,{force:!0}))}}return entries}function clearHandoverParkedSession(daemonDir,sessionPath){return enqueueMutation(()=>rm(entryFile(daemonDir,sessionPath),{force:!0}))}function dropHandoverParkedSessionIfFileGone(daemonDir,sessionPath){return existsSync(sessionPath)?Promise.resolve():clearHandoverParkedSession(daemonDir,sessionPath)}import{isAbsolute as isAbsolute2}from"node:path";import{access}from"node:fs/promises";import{isAbsolute}from"node:path";var MAX_WARM_PROFILES=64;function profileKey(profile){let context=Object.entries(profile.sessionContext??{}).sort(([a],[b])=>a<b?-1:a>b?1:0);return JSON.stringify([profile.cwd,profile.sessionKind??"interactive",context])}var HostWarmer=class{constructor(load){this.warm=new Set,this.loading=new Map,this.load=load}async run(profile){let key=profileKey(profile);if(this.warm.has(key))return"already_warm";let pending=this.loading.get(key);return pending===void 0&&(pending=this.loadOnce(key,profile),this.loading.set(key,pending)),await pending,"warmed"}async loadOnce(key,profile){try{if(await this.load(profile),this.warm.add(key),this.warm.size>MAX_WARM_PROFILES){let oldest=this.warm.values().next().value;oldest!==void 0&&this.warm.delete(oldest)}}finally{this.loading.delete(key)}}};function createRegistryWarm(prepare,host){let warmer=new HostWarmer(async profile=>{await access(profile.cwd);let launchProfile={cwd:profile.cwd,...profile.sessionKind!==void 0?{sessionKind:profile.sessionKind}:{},...profile.sessionContext!==void 0?{sessionContext:Object.freeze({...profile.sessionContext})}:{}},scope=new ProviderScope;try{await runWithProviderScope(scope,()=>prepare({cwd:profile.cwd,agentDir:host.agentDir,launchProfile:Object.freeze(launchProfile),...host.mcpRegistry!==void 0?{mcpRegistry:host.mcpRegistry}:{}}))}finally{scope.close()}});return profile=>warmer.run(profile)}function refusal(command,code){return{id:command.id,type:"response",command:"warm",success:!1,error:code}}async function answerWarm(command,host){if(host.draining)return refusal(command,"host_draining");let kindError=sessionKindError(command.kind);if(kindError)return refusal(command,`${RPC_ERROR_INVALID_SESSION_KIND}: ${kindError}`);let contextError=sessionContextError(command.context);if(contextError)return refusal(command,`${RPC_ERROR_INVALID_SESSION_CONTEXT}: ${contextError}`);if(host.warm===void 0)return{id:command.id,type:"response",command:"warm",success:!0,data:{state:"unsupported"}};let sessionContext=host.hostContext?{...command.context,...host.hostContext}:command.context,cwd=command.cwd??host.cwd;if(!isAbsolute(cwd))return refusal(command,RPC_ERROR_INVALID_PATH);try{let state=await host.warm({cwd,...command.kind!==void 0?{sessionKind:command.kind}:{},...sessionContext!==void 0?{sessionContext}:{}});return{id:command.id,type:"response",command:"warm",success:!0,data:{state}}}catch(cause){return refusal(command,`${RPC_ERROR_WARM_FAILED}: ${cause instanceof Error?cause.message:String(cause)}`)}}var RpcSessionRegistryError=class extends Error{constructor(code,reason,detail){super(code==="open_failed"&&reason?`${code}: ${reason}`:code),this.code=code,this.name="RpcSessionRegistryError",detail&&(this.detail=detail)}};function frozenProfile(profile){return Object.freeze({...profile,...profile.holderEndpoint?{holderEndpoint:Object.freeze({...profile.holderEndpoint})}:{},...profile.creationModel?{creationModel:Object.freeze({...profile.creationModel})}:{},...profile.sessionContext?{sessionContext:Object.freeze({...profile.sessionContext})}:{},...profile.retryFallback?{retryFallback:Object.freeze({modelFallback:profile.retryFallback.modelFallback,fallbackChains:Object.freeze(Object.fromEntries(Object.entries(profile.retryFallback.fallbackChains).map(([key,entries])=>[key,Object.freeze([...entries])])))})}:{}})}function sessionIdentity(profile){return{kind:profile.sessionKind??"interactive",context:profile.sessionContext??EMPTY_SESSION_CONTEXT}}function assertRequestedModelResolved(profile,diagnostics){let requested=profile.creationModel;if(requested===void 0)return;let unresolved=diagnostics.find(diagnostic=>diagnostic.code==="model_unresolved");if(unresolved!==void 0)throw new RpcSessionRegistryError("open_failed",`model_unavailable: ${unresolved.message}`,{reason:"model_unavailable",requestedModel:`${requested.provider}/${requested.modelId}`})}var observations=new Set(["get_state","get_effect_status","get_pending_inputs","get_messages","get_entries","get_tree","get_fork_messages","get_last_assistant_text","get_session_stats","resolve_path","get_steering_messages","get_follow_up_messages","get_available_models","get_available_thinking_levels","get_fast_mode","get_commands","get_loaded_surfaces","get_media","get_auth_providers","get_provider_accounts","memory_report","eval_cells.list","eval_cells.peek"]);function refreshesSessionActivity(command){return!observations.has(command)}var DEFAULT_OPEN_IN_PROGRESS_WAIT_MS=45e3,OPEN_IN_PROGRESS_WAIT_RETRY_MS=2e3;function openInProgressWaitMs(){let override=Number(process.env.SENPI_OPEN_IN_PROGRESS_WAIT_MS);return Number.isFinite(override)&&override>0?override:DEFAULT_OPEN_IN_PROGRESS_WAIT_MS}var OpenInProgressWaitError=class extends Error{};function openingOwner(sessionPath){return{instanceId:hostInstanceId(),pid:process.pid,processStartTime:null,sessionPath,attached:!0,current:!0}}function waitWithDeadline(openCompletion,waitMs){let timer;return Promise.race([openCompletion,new Promise((_resolve,reject)=>{timer=setTimeout(()=>reject(new OpenInProgressWaitError),waitMs)})]).finally(()=>{timer!==void 0&&clearTimeout(timer)})}async function attachToOpenSession(entries,sessionPath,profile,options,pathReservations,now){let existing=[...entries].find(([,entry2])=>entry2.reservationKey===sessionPath&&entry2.state==="open");if(!existing){let inFlight=[...entries].find(([,entry2])=>entry2.reservationKey===sessionPath&&entry2.state==="opening");if(inFlight?.[1].openCompletion!==void 0){try{await waitWithDeadline(inFlight[1].openCompletion,openInProgressWaitMs())}catch(cause){throw cause instanceof OpenInProgressWaitError?new RpcSessionRegistryError("session_path_in_use","the session is still opening",{reason:"open_in_progress",retry_after_ms:OPEN_IN_PROGRESS_WAIT_RETRY_MS,owner:openingOwner(sessionPath)}):new RpcSessionRegistryError("session_path_in_use","the in-flight open failed",{reason:"open_failed",retry_after_ms:OPEN_IN_PROGRESS_WAIT_RETRY_MS})}return attachToOpenSession(entries,sessionPath,profile,options,pathReservations,now)}throw new RpcSessionRegistryError("session_path_in_use","the session is still being released",{reason:"path_still_held",retry_after_ms:OPEN_IN_PROGRESS_WAIT_RETRY_MS})}let[handle,entry]=existing,wasParked=entry.retainOnDisconnect===!0&&entry.attachments===0;if(entry.attachments+=1,entry.detachedAt=void 0,pathReservations?.setAttached(sessionPath,!0),options?.retainOnDisconnect&&(entry.retainOnDisconnect=!0),!entry.durableSessionId)throw new RpcSessionRegistryError("session_path_in_use");return profile.promptSurface!==void 0&&profile.promptSurface!==entry.profile.promptSurface&&(entry.profile=frozenProfile({...entry.profile,promptSurface:profile.promptSurface}),entry.runtime?.setPromptSurface(profile.promptSurface)),profile.browserEngine!==void 0&&profile.browserEngine!==entry.profile.browserEngine&&(entry.profile=frozenProfile({...entry.profile,browserEngine:profile.browserEngine}),entry.runtime?.setBrowserEngine(profile.browserEngine)),profile.permissionPreset!==void 0&&(entry.profile=frozenProfile({...entry.profile,permissionPreset:profile.permissionPreset}),entry.runtime?.setPermissionPreset(profile.permissionPreset)),entry.lastCommandAt=now,wasParked&&(entry.lifecycleMutex=entry.lifecycleMutex.then(()=>entry.runtime?.emitAttachmentEvent("session_resumed")),await entry.lifecycleMutex),{sessionId:handle,durableSessionId:entry.durableSessionId,sessionPath:entry.sessionPath,attached:!0}}function beginPendingClaim(pending,sessionPath){let settled=Promise.withResolvers();return pending.set(sessionPath,settled.promise),()=>{pending.get(sessionPath)===settled.promise&&pending.delete(sessionPath),settled.resolve()}}async function takeCrossGenerationClaim(reservations,pending,pathReservations,sessionPath){let settle=beginPendingClaim(pending,sessionPath),holder;try{holder=await pathReservations.claim(sessionPath)}catch(cause){throw reservations.delete(sessionPath),settle(),cause}if(holder===void 0)return settle;throw reservations.delete(sessionPath),settle(),new RpcSessionRegistryError("session_path_in_use",void 0,{owner:holder,retry_after_ms:SESSION_PATH_RETRY_AFTER_MS})}async function settlePendingClaim(pending,sessionPath,graceMs){let timer,late=new Promise(resolve=>{timer=setTimeout(()=>resolve("late"),graceMs)});try{for(let claim=pending.get(sessionPath);claim!==void 0;claim=pending.get(sessionPath))if(await Promise.race([claim.then(()=>"settled"),late])==="late")throw new RpcSessionRegistryError("session_path_in_use","another open of this path is still taking its claim",{reason:"claim_in_progress",retry_after_ms:SESSION_PATH_RETRY_AFTER_MS})}finally{clearTimeout(timer)}}function syncRuntimeMetadata(entries,reservations,pathReservations){for(let entry of entries){let manager=entry.runtime?.session.sessionManager;if(!manager)continue;let currentPath=manager.getSessionFile(),currentKey=currentPath?canonicalSessionPath(currentPath):void 0;(currentPath!==entry.sessionPath||currentKey!==entry.reservationKey)&&(entry.reservationKey&&(reservations.delete(entry.reservationKey),pathReservations?.release(entry.reservationKey)),currentKey&&(reservations.add(currentKey),pathReservations?.claim(currentKey,entry.attachments>0)),entry.reservationKey=currentKey,entry.sessionPath=currentPath),entry.durableSessionId=manager.getSessionId(),entry.cwd=manager.getCwd()}}async function settleClosingReservation(entries,sessionPath,closeGraceMs){let closing=[...entries].find(entry=>entry.reservationKey===sessionPath&&entry.state==="closing");if(!closing?.closeCompletion)return;let deadline;try{await Promise.race([closing.closeCompletion,new Promise(resolve=>{deadline=setTimeout(resolve,closeGraceMs)})])}finally{deadline&&clearTimeout(deadline)}}import{existsSync as existsSync2}from"node:fs";function resolveMovedProfile(requested){let profile={...requested,cwd:resolveMovedPath(requested.cwd),...requested.sessionPath?{sessionPath:resolveMovedPath(requested.sessionPath)}:{}};if(profile.sessionPath!==requested.sessionPath&&profile.sessionPath&&!existsSync2(profile.sessionPath))throw new RpcSessionRegistryError("open_failed",`moved session file does not exist: ${profile.sessionPath}`);return profile}import{existsSync as existsSync3}from"node:fs";function createEntrySwitchSession(entry,createRuntime,syncRuntimeMetadata2){return(sessionPath,options)=>{let operation=entry.lifecycleMutex.then(async()=>{if(entry.state!=="open"||!entry.runtime)throw new RpcSessionRegistryError("unknown_session");let runtime=entry.runtime,cwdOverride=options?.cwdOverride,cwdChanged=cwdOverride!==void 0&&runtime.session.sessionManager.getCwd()!==cwdOverride,result=await runtime.switchSession(sessionPath,options);if(result.cancelled||!cwdChanged)return result;let replacement=new AgentSessionRuntime(runtime.session,runtime.services,createRuntime,[...runtime.diagnostics],runtime.modelFallbackMessage,runtime.launchProfile);return replacement.setRebindSession(entry.rebindSession),ClientAdmissions.sealQueuedOnReplace(replacement),EffectLedger.sealOnReplace(replacement),runtime.releaseSessionHold(),entry.runtime=replacement,syncRuntimeMetadata2(),result});return entry.lifecycleMutex=operation.then(()=>{},()=>{}),operation}}function buildOpeningEntry(input){let{profile,sessionPath,requestedDurableId,options}=input,isResume=sessionPath!==void 0&&existsSync3(sessionPath),sessionStartEvent=isResume?{type:"session_start",reason:"resume"}:void 0,storedProfile=frozenProfile({...profile,...sessionPath?{sessionPath}:{}}),runtimeProfile=isResume?frozenProfile({...storedProfile,creationModel:void 0,initialThinkingLevel:void 0}):storedProfile,settleOpen,openCompletion=new Promise((resolve,reject)=>{settleOpen={resolve,reject}});openCompletion.catch(()=>{});let entry={state:"opening",scope:new ProviderScope,profile:storedProfile,...sessionIdentity(storedProfile),sessionPath,reservationKey:sessionPath,cwd:storedProfile.cwd,attachments:1,retainOnDisconnect:options?.retainOnDisconnect===!0,lastCommandAt:input.now,lifecycleMutex:Promise.resolve(),openCompletion};return entry.switchSession=createEntrySwitchSession(entry,input.createRuntime,input.sync),requestedDurableId!==void 0&&(entry.durableSessionId=requestedDurableId),{entry,storedProfile,runtimeProfile,sessionStartEvent,settleOpen}}function sessionIsWriting(entry){return entry.worker?.busy===!0||entry.runtime?.session.isSessionBusy===!0}function reportDetachedFailure(handle,cause){process.stderr.write(`senpi rpc session ${handle} teardown failed: ${String(cause)}
5
5
  `)}function beginSessionClose(host,handle,onRole,options){let entry=host.get(handle);if(!entry)throw new RpcSessionRegistryError("unknown_session");if(entry.state==="closing")return onRole?.(!1),entry;if(entry.state!=="open")throw new RpcSessionRegistryError("unknown_session");return entry.attachments-=1,entry.attachments>0?entry:options?.detach&&entry.retainOnDisconnect?(entry.attachments=0,entry.detachedAt??=host.now(),entry.reservationKey&&!sessionIsWriting(entry)&&host.markDetached(entry.reservationKey),entry):(entry.state="closing",onRole?.(!0),entry.closeCompletion=new Promise(resolve=>{entry.closeResolve=resolve}),entry)}async function releaseWithinGrace(host,handle,key){let timer,late=new Promise(resolve=>{timer=setTimeout(()=>resolve("late"),host.closeGraceMs)}),removal=host.releaseReservation(key).then(()=>"removed",cause=>(reportDetachedFailure(handle,cause),"failed")),outcome=await Promise.race([removal,late]);clearTimeout(timer),outcome==="late"&&reportDetachedFailure(handle,new Error(`session path reservation was not removed within ${host.closeGraceMs} ms; closing anyway`))}function closeSession(host,handle){return beginSessionClose(host,handle).state!=="closing"?Promise.resolve():closeMarkedSession(host,handle)}function closeMarkedSession(host,handle){host.sync();let entry=host.get(handle);if(entry?.state!=="closing")throw new RpcSessionRegistryError("unknown_session");let completion=entry.closeCompletion;if(!completion)return Promise.resolve();if(entry.closeStarted)return completion;entry.closeStarted=!0;let previousLifecycle=entry.lifecycleMutex,releaseTimer,released=!1,disposePromise,scopeClosed=!1,disposeOnce=()=>disposePromise||(disposePromise=Promise.resolve(entry.runtime?.dispose()),disposePromise),closeScopeOnce=async()=>{scopeClosed||(scopeClosed=!0,await disposeOnce().catch(()=>{}),await entry.scope.close?.())},release=async()=>{released||(released=!0,releaseTimer&&clearTimeout(releaseTimer),entry.reservationKey&&await releaseWithinGrace(host,handle,entry.reservationKey),entry.state="closed",host.delete(handle))},graceful=(async()=>{await previousLifecycle;try{await entry.runtime?.session.abort()}catch(cause){reportDetachedFailure(handle,cause)}try{await entry.runtime?.session.waitForIdle()}catch(cause){reportDetachedFailure(handle,cause)}try{await disposeOnce()}catch(cause){reportDetachedFailure(handle,cause)}try{await closeScopeOnce()}catch(cause){reportDetachedFailure(handle,cause)}})(),settled=!1,finish=async()=>{settled||(settled=!0,await release(),entry.closeResolve?.())};return releaseTimer=setTimeout(()=>{disposeOnce().catch(cause=>reportDetachedFailure(handle,cause)),closeScopeOnce().catch(cause=>reportDetachedFailure(handle,cause)),graceful.catch(cause=>reportDetachedFailure(handle,cause)),finish()},host.closeGraceMs),graceful.then(finish,cause=>(reportDetachedFailure(handle,cause),finish())),completion}var RpcSessionRegistry=class{constructor(options){this.entries=new Map,this.reservations=new Set,this.pendingClaims=new Map,this.nextHandle=0,options.createRuntime.prepare&&(this.warm=createRegistryWarm(options.createRuntime.prepare,{agentDir:options.agentDir,...options.mcpRegistry!==void 0?{mcpRegistry:options.mcpRegistry}:{}})),this.options=options.mcpRegistry===void 0?options:{...options,createRuntime:runtimeOptions=>options.createRuntime({...runtimeOptions,mcpRegistry:options.mcpRegistry})},this.now=options.now??Date.now,this.closeGraceMs=options.closeGraceMs??1e4,this.teardownHost={closeGraceMs:this.closeGraceMs,get:handle=>this.entries.get(handle),delete:handle=>{let deleted=this.entries.delete(handle);return this.options.onSizeChange?.(this.entries.size),deleted},releaseReservation:async key=>{await this.options.pathReservations?.release(key),this.reservations.delete(key)},markDetached:key=>this.options.pathReservations?.setAttached(key,!1),now:()=>this.now(),sync:()=>this.syncRuntimeMetadata()}}get size(){return this.entries.size}holderPids(observedStarts){return this.options.pathReservations?.holderPids?.(observedStarts)??Promise.resolve([])}async openSession(requested,options){this.validateProfile(requested);let profile=resolveMovedProfile(requested);this.syncRuntimeMetadata();let sessionPath=profile.sessionPath?canonicalSessionPath(profile.sessionPath):void 0,requestedDurableId=profile.durableSessionId;if(requestedDurableId!==void 0){for(let entry2 of this.entries.values())if(entry2.state!=="closed"&&entry2.durableSessionId===requestedDurableId&&!(sessionPath!==void 0&&entry2.reservationKey===sessionPath))throw new RpcSessionRegistryError("session_id_in_use")}if(sessionPath){await settleClosingReservation(this.entries.values(),sessionPath,this.closeGraceMs);let deadline=Date.now()+this.closeGraceMs;for(;this.pendingClaims.has(sessionPath);)await settlePendingClaim(this.pendingClaims,sessionPath,Math.max(0,deadline-Date.now()))}if(sessionPath&&this.reservations.has(sessionPath))return attachToOpenSession(this.entries,sessionPath,profile,options,this.options.pathReservations,this.now());if(options?.attachOnly)throw new RpcSessionRegistryError("session_not_held",void 0,{reason:"session_not_held",action:"rediscover_holder"});let claimSettled;sessionPath&&(this.reservations.add(sessionPath),this.options.pathReservations&&(claimSettled=await takeCrossGenerationClaim(this.reservations,this.pendingClaims,this.options.pathReservations,sessionPath)));let handle=`rpc-${++this.nextHandle}`,opening;try{opening=buildOpeningEntry({profile,sessionPath,requestedDurableId,options,now:this.now(),createRuntime:this.options.createRuntime,sync:()=>this.syncRuntimeMetadata()})}catch(cause){try{sessionPath&&(this.reservations.delete(sessionPath),await this.options.pathReservations?.release(sessionPath))}catch(releaseCause){process.stderr.write(`senpi rpc open of ${sessionPath} could not release its claim: ${String(releaseCause)}
@@ -14,22 +14,22 @@ import{SessionEventWriter,answerSetSessionContext,answerSubscribeSessions,answer
14
14
  `),{type:"open_session",sessionPath:entry.sessionPath,...entry.cwd!==void 0?{cwd:entry.cwd}:{},...entry.durableSessionId!==void 0?{durableSessionId:entry.durableSessionId}:{},...entry.model!==void 0?{provider:entry.model.provider,modelId:entry.model.modelId}:{},...thinkingLevel!==void 0?{thinkingLevel}:{},...entry.permissionPreset!==void 0?{permissionPreset:entry.permissionPreset}:{},...entry.promptSurface!==void 0?{promptSurface:entry.promptSurface}:{},...entry.browserEngine!==void 0?{browserEngine:entry.browserEngine}:{},...entry.sessionKind!==void 0?{kind:entry.sessionKind}:{},...entry.sessionContext!==void 0?{context:entry.sessionContext}:{},...entry.autoTitle!==void 0?{auto_title:entry.autoTitle}:{},...entry.retryFallback!==void 0?{retryFallback:entry.retryFallback}:{},retain_on_disconnect:entry.retainOnDisconnect}}async function createRpcSessionBinding(sessionId,entry,writer,requestClose,options={}){if(entry.worker)return entry.worker.bind(sessionId,writer,requestClose,options);if(!entry.runtime)throw new Error("Session runtime was not created");let toolSpans=createToolAttributionSpans(sessionId),enqueueRecords=chunk=>{for(let line of chunk.split(`
15
15
  `)){if(!line)continue;let record=JSON.parse(line);toolSpans.observe(record),writer.enqueue(sessionId,record)}},runtimeHost=new Proxy({},{get(_target,property){if(property==="switchSession"&&entry.switchSession)return entry.switchSession;if(property==="setRebindSession")return callback=>{entry.rebindSession=callback,entry.runtime?.setRebindSession(callback)};let runtime=entry.runtime;if(!runtime)throw new Error("Session runtime was not created");let value=Reflect.get(runtime,property,runtime);return typeof value=="function"?value.bind(runtime):value}}),droppedAfterClose=!1,handler=await runWithProviderScope(entry.scope,async()=>{let writeInScope=bindToProviderScope(enqueueRecords),taggedSink={writeRaw:chunk=>{if(entry.scope.state==="closed"){droppedAfterClose||process.stderr.write(`senpi rpc host: dropped a record for closed session ${sessionId} at ${new Date().toISOString()}
16
16
  `),droppedAfterClose=!0;return}writeInScope(chunk)},waitForBackpressure:bindToProviderScope(async()=>{})};return createRpcConnectionHandler(runtimeHost,taggedSink,{sessionId,shutdownHandler:bindToProviderScope(requestClose),disposeRuntime:!1,eventFlushScheduler:flush=>flush(),publishLoadedSurfacesChanged:(previous,digest)=>{entry.scope.state!=="closed"&&writer.publishLoadedSurfacesChanged(sessionId,previous,digest)},...options})});return await handler.ready,{handle:command=>runWithProviderScope(entry.scope,()=>handler.handleInputLine(JSON.stringify(command))),cancelPendingExtensionUiRequests:()=>runWithProviderScope(entry.scope,()=>handler.cancelPendingExtensionUiRequests()),pendingPrompts:()=>handler.pendingPrompts(),dispose:()=>(toolSpans.closeAll(),runWithProviderScope(entry.scope,()=>handler.dispose()))}}import{execFile}from"node:child_process";var READ_ONLY_OR_CONTROL=new Set(["get_state","get_effect_status","get_pending_inputs","get_steering_messages","get_follow_up_messages","get_available_models","get_available_thinking_levels","get_fast_mode","get_session_stats","resolve_path","get_fork_messages","get_entries","get_tree","get_last_assistant_text","get_messages","get_media","get_commands","get_loaded_surfaces","get_auth_providers","get_provider_accounts","memory_report","eval_cells.list","eval_cells.peek","eval_cells.stop","export_html","export_jsonl","abort","interrupt","abort_compaction","abort_branch_summary","abort_retry","abort_bash","clear_queue","check_reload_veto","cleanup_bash_output","set_client_info","extension_ui_response","extension_ui_progress"]);function readProcessStarts(){let windows=process.platform==="win32",command=windows?"powershell.exe":"ps",args=windows?["-NoProfile","-NonInteractive","-Command",'Get-CimInstance Win32_Process -ErrorAction Stop | ForEach-Object { if ($null -ne $_.CreationDate) { "{0} {1}" -f $_.ProcessId, $_.CreationDate.ToUniversalTime().ToString("o") } }']:["-axo","pid=,lstart="];return new Promise(resolve=>{execFile(command,args,{timeout:windows?5e3:1e3,maxBuffer:4*1024*1024,windowsHide:!0,...windows?{}:{env:{...process.env,LC_ALL:"C",LANG:"C"}}},(error2,stdout)=>{if(error2)return resolve(void 0);let starts=new Map;for(let line of stdout.split(`
17
- `)){let row=/^\s*(\d+)\s+(.+)$/.exec(line);if(!row)continue;let start=processStartTimeMs(row[2]);start!==void 0&&starts.set(Number(row[1]),start)}resolve(starts)})})}function sessionHeldCheck(resolveDaemonPids){let daemonPids,processStarts,pidStarts=new Map,observedStarts=new Map;return async(sessionFile,sessionId)=>{let holders=await foreignSessionHolders(sessionFile,sessionId,{readProcessStartMs:pid=>{let probe=pidStarts.get(pid);return probe||(probe=(async()=>{process.platform!=="linux"&&(processStarts??=readProcessStarts());let start=(await processStarts)?.get(pid)??await readProcessStartMs(pid);return observedStarts.set(pid,start),start})(),pidStarts.set(pid,probe)),probe}});if(holders.length===0)return;daemonPids??=resolveDaemonPids?.(observedStarts)??Promise.resolve([]);let family=await daemonPids,foreign=holders.filter(holder=>!family.includes(holder.pid));if(foreign.length>0)throw new RpcSessionRegistryError(RPC_ERROR_SESSION_HELD,void 0,{holders:foreign.map(({pid,cwd,host_socket,host_instance})=>({pid,...cwd===void 0?{}:{cwd},...host_socket===void 0?{}:{host_socket},...host_instance===void 0?{}:{host_instance}}))})}}async function dispatchSessionBinding(command,entry,binding,acknowledgePrompt,daemonPids){if(!binding)throw new RpcSessionRegistryError("unknown_session");if(!READ_ONLY_OR_CONTROL.has(command.type)){let assertSessionNotHeld=sessionHeldCheck(daemonPids),state=entry.worker?.snapshot?.state;await assertSessionNotHeld(entry.runtime?.session.sessionFile??state?.sessionFile??entry.sessionPath,entry.runtime?.session.sessionId??state?.sessionId??entry.durableSessionId),"sessionPath"in command&&await assertSessionNotHeld(command.sessionPath)}command.type==="prompt"&&acknowledgePrompt(),await binding.handle(command)}var PLAIN_ID=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;function isPlainId(value){return typeof value=="string"&&PLAIN_ID.test(value)}function isMoveId(value){return isPlainId(value)}var NOTHING_DROPPED={deliveries:[],user_messages:[]};function takeQueuedInput(session){let admittedBefore=session.externalAdmission.list().pending,cleared=session.clearQueue({abortWillFollow:!0}),stillAdmitted=new Set(session.externalAdmission.list().pending);return{deliveries:admittedBefore.filter(deliveryId=>!stillAdmitted.has(deliveryId)),user_messages:cleared.ordered.map(queued=>queued.text)}}async function abortAndSettle(port,sessionId,session){session.abortBash();let stopStarts=session.subscribe(event=>{event.type==="agent_start"&&session.abort()}),deadline,expired=new Promise(resolve=>{deadline=setTimeout(resolve,1e4)});try{await Promise.race([Promise.allSettled([session.abort().then(()=>session.waitForIdle()),port.otherRequestsSettled(sessionId),...port.pendingPrompts(sessionId)]),expired])}finally{clearTimeout(deadline),stopStarts()}}var SESSION_RELEASED_ENTRY_TYPE="session_released",RELEASED_ADMISSION_CLOSED="release_session handed this session to another runtime; deliver there instead (admission is closed here)",RELEASE_QUEUED_HINT="queued user input is still owed a turn; release with interrupt: true to take it out and receive it in dropped.user_messages";async function releaseSession(port,command){let validMove=command.reason==="move"&&isMoveId(command.moveId);if(command.reason!=="takeover"&&!validMove)return refusal2(command.id,RPC_ERROR_INVALID_RELEASE_REASON);if(port.draining())return refusal2(command.id,RPC_ERROR_HOST_DRAINING);let first=releasable(port,command,void 0);if(!("session"in first))return first;if(command.reason==="move"&&!isPlainId(first.session.sessionManager.getSessionId()))return refusal2(command.id,RPC_ERROR_RELEASE_UNSUPPORTED,{detail:"session_id_not_plain"});let busy=busySignals(port,command.sessionId,first.session),interrupted=busy.length>0;if(interrupted&&command.interrupt!==!0)return refusal2(command.id,busyCode(busy),{attachments:first.attachments,...busyData(busy)});let admission=first.session.externalAdmission,dropped=NOTHING_DROPPED,answer2;try{interrupted&&(admission.close(RELEASED_ADMISSION_CLOSED),dropped=takeQueuedInput(first.session),await abortAndSettle(port,command.sessionId,first.session),await first.session.whenQueueClearRecorded());let manager=first.session.sessionManager;return manager.isTranscriptFlushed()||await manager.persistHeaderNow(),answer2=await claimAndRelease(port,command,interrupted,dropped),answer2}catch(cause){return cause instanceof SessionMovedAwayError?(answer2=refusal2(command.id,cause.code,{detail:cause.message,...interrupted?{interrupted:!0,dropped}:{}}),answer2):(answer2=refusal2(command.id,RPC_ERROR_RELEASE_FAILED,{detail:cause instanceof Error?cause.message:String(cause),...interrupted?{interrupted:!0,dropped}:{}}),answer2)}finally{answer2?.success!==!0&&admission.reopen()}}async function claimAndRelease(port,command,interrupted,dropped){let taken=interrupted?{interrupted:!0,dropped}:void 0,ready=releasable(port,command,taken);if(!("session"in ready))return ready;let stillBusy=busySignals(port,command.sessionId,ready.session);if(stillBusy.length>0)return refusal2(command.id,busyCode(stillBusy),{attachments:ready.attachments,...busyData(stillBusy),interrupted,...taken});let admission=ready.session.externalAdmission;admission.close(RELEASED_ADMISSION_CLOSED);try{ready.session.sessionManager.appendCustomEntry(SESSION_RELEASED_ENTRY_TYPE,{reason:command.reason,...command.reason==="move"?{move_id:command.moveId,target:command.target??"",session_id:ready.session.sessionManager.getSessionId()}:{},interrupted,attachments:ready.attachments,host_instance:port.hostInstance??null,released_at:new Date().toISOString()})}catch(cause){throw admission.reopen(),cause}return await port.tearDown(command.sessionId,ready.sessionPath)?{id:command.id,type:"response",command:"release_session",success:!0,data:{released:!0,session_path:ready.sessionPath,attachments:ready.attachments,dropped}}:refusal2(command.id,RPC_ERROR_SESSION_CLOSING,taken)}function busySignals(port,sessionId,session){let activity=session.activitySnapshot,signals=[];return activity.isStreaming&&signals.push("turn"),port.pendingPrompts(sessionId).length>0&&signals.push("prompt"),session.pendingMessageCount>0&&signals.push("queued"),session.externalAdmission.list().pending.length>0&&signals.push("delivery"),activity.isBashRunning&&signals.push("bash"),activity.isCompacting&&signals.push("compaction"),activity.hasSessionWork&&signals.push("session_work"),signals.length===0&&isHandoffBusy(activity)&&signals.push("activity"),port.otherRequests(sessionId)>0&&signals.push("request"),signals}function busyData(signals){return signals.includes("queued")?{busy:signals,retry_with:{interrupt:!0},hint:RELEASE_QUEUED_HINT}:{busy:signals}}function busyCode(signals){return signals.some(signal=>signal==="turn"||signal==="prompt"||signal==="queued"||signal==="delivery")?RPC_ERROR_TURN_ACTIVE:RPC_ERROR_SESSION_BUSY}function releasable(port,command,taken){let refuse=(code,data)=>refusal2(command.id,code,data||taken?{...data,...taken}:void 0),entry;try{entry=port.lookup(command.sessionId)}catch(cause){return refuse(port.code(cause))}if(entry.state!=="open")return refuse(RPC_ERROR_SESSION_CLOSING);let session=entry.runtime?.session;if(session===void 0)return refuse(RPC_ERROR_RELEASE_UNSUPPORTED,{detail:"worker_runtime"});let sessionPath=entry.sessionPath??session.sessionFile;return sessionPath===void 0?refuse(RPC_ERROR_RELEASE_UNSUPPORTED,{detail:"no_session_file"}):entry.attachments>0&&command.force!==!0?refuse(RPC_ERROR_ATTACHED,{attachments:entry.attachments}):{session,sessionPath,attachments:entry.attachments}}function refusal2(id,code,data){return{id,type:"response",command:"release_session",success:!1,error:code,...data&&{errorCode:code,errorData:data}}}var DETACHED_RETIREMENT_GRACE_MS=5e3;function selectSweepEvictions(registry,now,idleEvictionMs,hasPendingRequest=()=>!1){let idle=[],orphaned=[];for(let{sessionId,status,sessionPath}of registry.list()){if(status!=="open")continue;let entry=registry.peek(sessionId);if(!entry)continue;if(entry.attachments===0&&sessionPath!==void 0&&sessionDirectoryRemoved(sessionPath)){orphaned.push(sessionId);continue}if(!Number.isFinite(idleEvictionMs)||hasPendingRequest(sessionId))continue;let session=entry.runtime?.session;if(entry.worker?.busy||session?.isSessionBusy){entry.lastCommandAt=now;continue}if(entry.attachments>0){now-entry.lastCommandAt>=idleEvictionMs&&idle.push(sessionId);continue}if(entry.kind==="worker"&&entry.retainOnDisconnect&&session?.sessionManager.isTranscriptFlushed()){if(session.pendingMessageCount>0||session.externalAdmission.list().pending.length>0)continue;if(entry.detachedAt!==void 0){if(now-entry.detachedAt<DETACHED_RETIREMENT_GRACE_MS)continue;idle.push(sessionId);continue}}now-entry.lastCommandAt>=idleEvictionMs&&idle.push(sessionId)}return{idle,orphaned}}var CHILD_TASK_SOURCE=/^senpi-task/,ACTIONS={extension_work:"let the named work finish, or unload with force: true (it is stopped, not resumed on reopen)",turn_active:"wait for the turn to end, or unload with interrupt: true to stop it first",work_pending:"wait for the work to finish, or unload with interrupt: true",children_live:'wait for the child tasks, or unload with children: "detach" to leave them running',attached:"ask the other clients to detach, or unload with force: true (they receive session_parked)"};async function unloadSession(port,command){if(port.draining())return answer(command,refused({reason:"host_draining",detail:"this host is draining and parks every session itself"}));let first=loaded(port,command.sessionId);if("reason"in first)return answer(command,refused(first));let{effectId}=command;if(effectId!==void 0){let begun=await beginEffect({session:first.session,by:port.by,sessionId:command.sessionId},"unload",{...command,effectId});if(!isEffectBegin(begun))return begun;if("replay"in begun)return answer(command,{outcome:begun.replay.state==="failed"?"refused":"unloaded",...refusalFields(begun.replay.outcome),...effectAnswer(begun.replay,command.sessionId,!0)})}let blocked=blockers(port,command,first.session,first.durableSessionId),standing=blocked.find(refusal3=>!interruptible(refusal3)||command.interrupt!==!0);return standing!==void 0?fail(command,first.session,standing):(blocked.length>0&&await abortAndSettle(port,command.sessionId,first.session),claimAndUnload(port,command))}async function claimAndUnload(port,command){let ready=loaded(port,command.sessionId);if("reason"in ready)return answer(command,refused(ready));let stillBlocked=blockers(port,command,ready.session,ready.durableSessionId);if(stillBlocked.length>0)return fail(command,ready.session,stillBlocked[0]);command.clearQueue===!0&&(ClientAdmissions.clearQueuedFor(ready.session),ready.session.clearQueue());let effect=command.effectId===void 0?void 0:EffectLedger.forSession(ready.session).transition(command.effectId,"done",{disposition:"unloaded"});return await port.tearDown(command.sessionId,ready.sessionPath)?answer(command,{outcome:"unloaded",sessionPath:ready.sessionPath,...effect===void 0?{}:effectAnswer(effect,command.sessionId)}):answer(command,{outcome:"refused",reason:"session_closing",detail:"another close of this session finished first"})}function interruptible(refusal3){return refusal3.reason==="turn_active"||refusal3.reason==="work_pending"}function blockers(port,command,session,durableSessionId){let found=[],activity=session.activitySnapshot,running=[activity.isStreaming&&"an agent run",port.pendingPrompts(command.sessionId).length>0&&"a prompt about to start",activity.isCompacting&&"compaction",activity.hasSessionWork&&"session work"].filter(label=>typeof label=="string");running.length>0&&found.push({reason:"turn_active",detail:running.join(", "),action:ACTIONS.turn_active});let pending=[activity.isBashRunning&&"a bash command",session.externalAdmission.list().pending.length>0&&"an admitted delivery not yet written",port.otherRequests(command.sessionId)>0&&"another request for this session"].filter(label=>typeof label=="string");pending.length>0&&found.push({reason:"work_pending",detail:pending.join(", "),action:ACTIONS.work_pending});let sources=session.activeWakeSources,childSources=sources.filter(source=>CHILD_TASK_SOURCE.test(source)),otherSources=sources.filter(source=>!CHILD_TASK_SOURCE.test(source));otherSources.length>0&&command.force!==!0&&found.push({reason:"extension_work",detail:`work published by ${otherSources.join(", ")}`,action:ACTIONS.extension_work});let childSessions=port.openChildSessions(durableSessionId);if(command.children!=="detach"&&(childSources.length>0||childSessions>0)){let what=childSessions>0?`${childSessions} child session(s) open on this host`:"child tasks still working";found.push({reason:"children_live",detail:what,action:ACTIONS.children_live})}let others=port.otherAttachments(command.sessionId);return others>0&&command.force!==!0&&found.push({reason:"attached",detail:`${others} other client(s) attached`,action:ACTIONS.attached}),found}function loaded(port,sessionId){let entry;try{entry=port.lookup(sessionId)}catch(cause){return{reason:"unsupported",detail:port.code(cause)}}if(entry.state!=="open")return{reason:"session_closing",detail:"the session is already closing"};let session=entry.runtime?.session;if(session===void 0)return{reason:"unsupported",detail:"a worker isolate owns this session's runtime"};let sessionPath=entry.sessionPath??session.sessionFile;return sessionPath===void 0?{reason:"unsupported",detail:"the session has no file to reopen it by",action:"send a prompt first so the session is written, or close it instead"}:{session,sessionPath,durableSessionId:session.sessionManager.getSessionId()}}function fail(command,session,refusal3){if(command.effectId===void 0)return answer(command,refused(refusal3));let status=EffectLedger.forSession(session).transition(command.effectId,"failed",{outcome:{kind:"refused",reason:refusal3.reason,detail:refusal3.detail,...refusal3.action===void 0?{}:{action:refusal3.action}}});return answer(command,{...refused(refusal3),...effectAnswer(status,command.sessionId)})}function refusalFields(outcome){return outcome?.reason===void 0?{}:{reason:outcome.reason,...outcome.detail===void 0?{}:{detail:outcome.detail},...outcome.action===void 0?{}:{action:outcome.action}}}function refused(refusal3){return{outcome:"refused",reason:refusal3.reason,detail:refusal3.detail,...refusal3.action===void 0?{}:{action:refusal3.action}}}function answer(command,data){return{id:command.id,type:"response",command:"unload_session",success:!0,data}}var DRAIN_SWEEP_MS=50;function error(id,command,code,data){return{id,type:"response",command,success:!1,error:code,...data&&{errorCode:code,errorData:data}}}var SessionCommandRouter=class{constructor(registry,writer,defaults,createBinding=createRpcSessionBinding,connectionOptions={},idle){if(this.bindings=new Map,this.sessionsByConnection=new Map,this.opensByConnection=new Map,this.releasedConnections=new Set,this.pendingCapabilities=new Map,this.finalizations=new Map,this.draining=!1,this.handoffParks=0,this.drainExitRequested=!1,this.handoffClosed=new Set,this.activeRequests=new Map,this.requestSettledListeners=new Map,this.memoryPressure=!1,this.stopLimitBroadcast=subscriptionLimits.subscribe(limits=>writer.broadcastHostRecord({type:"subscription_limits",...limits})),this.registry=registry,this.writer=writer,this.defaults=defaults,this.createBinding=createBinding,this.connectionOptions=connectionOptions,this.idleNow=idle?.now??Date.now,this.idleEvictionMs=idle?.idleEvictionMs??Number.POSITIVE_INFINITY,this.emptyExitMs=idle?.emptyExitMs??Number.POSITIVE_INFINITY,this.onEmptyExit=idle?.onEmptyExit,this.onHandoffParked=idle?.onHandoffParked,this.handoverParkedDir=idle?.handoverParkedDir,this.canExitWhenEmpty=idle?.canExitWhenEmpty,writer.status.setSource(registryStatusSource(registry)),writer.status.setLastEffectProvider(sessionId=>{let session=this.registry.peek(sessionId)?.runtime?.session;if(session===void 0)return;let latest=latestSessionEffect(session);return latest===void 0?void 0:{effectId:latest.effectId,kind:latest.kind,state:latest.state}}),writer.afterRecord=sessionId=>{let session=this.registry.peek(sessionId)?.runtime?.session;if(session!==void 0)for(let status of drainSessionEffects(session))this.writer.status.publishEffect(sessionId,status)},this.uninstallEffectSink=installSessionEffectSink({owns:session=>this.routingIdOf(session)!==void 0,flush:(session,statuses)=>{let sessionId=this.routingIdOf(session);if(sessionId!==void 0)for(let status of statuses)this.writer.status.publishEffect(sessionId,status)}}),Number.isFinite(this.idleEvictionMs)||Number.isFinite(this.emptyExitMs)){let tickMs=Math.max(20,Math.min(5e3,Math.min(this.idleEvictionMs,this.emptyExitMs)/4));this.sweepTimer=setInterval(()=>this.sweepIdleSessions(),tickMs),this.sweepTimer.unref?.()}}get sessionCount(){return this.registry.size}setHostMemoryView(view){this.hostMemoryView=view}sessionMemory(sessionId){let view=this.hostMemoryView;if(view===void 0)return{main_heap_bytes:0,kernel_heap_bytes:0,kernel_count:0};let kernels=view.kernels().filter(kernel=>kernel.sessionId===sessionId),kernelHeapBytes=0;for(let kernel of kernels)kernelHeapBytes+=kernel.liveBytes;return{main_heap_bytes:view.mainHeapBytes(),kernel_heap_bytes:kernelHeapBytes,kernel_count:kernels.length}}beginDrain(){this.draining=!0,this.stopSweep(),this.drainTimer===void 0&&!this.drainExitRequested&&(this.drainTimer=setInterval(()=>this.sweepDrain(),DRAIN_SWEEP_MS),this.drainTimer.unref?.()),this.sweepDrain()}sweepDrain(){if(this.activeRequests.has(void 0))return;let verdicts=readDrainVerdicts(this.registry,sessionId=>this.activeRequests.has(sessionId));if(verdicts){for(let sessionId of verdicts.gone)this.parkForHandoff(sessionId,"session_dir_removed");for(let sessionId of verdicts.park)this.parkForHandoff(sessionId,"handoff_parked");this.registry.size>0||this.handoffParks>0||this.finalizations.size>0||(this.drainTimer!==void 0&&(clearInterval(this.drainTimer),this.drainTimer=void 0),this.stopSweep(),!this.drainExitRequested&&(this.drainExitRequested=!0,this.onEmptyExit?.()))}}parkForHandoff(sessionId,reason){this.handoffClosed.add(sessionId),this.handoffParks++,this.evictIdleSession(sessionId,reason).catch(cause=>{process.stderr.write(`senpi rpc handoff park ${sessionId} failed: ${String(cause)}
17
+ `)){let row=/^\s*(\d+)\s+(.+)$/.exec(line);if(!row)continue;let start=processStartTimeMs(row[2]);start!==void 0&&starts.set(Number(row[1]),start)}resolve(starts)})})}function sessionHeldCheck(resolveDaemonPids){let daemonPids,processStarts,pidStarts=new Map,observedStarts=new Map;return async(sessionFile,sessionId)=>{let holders=await foreignSessionHolders(sessionFile,sessionId,{holderEnded:generation=>holderGenerationEnded(generation),readProcessStartMs:pid=>{let probe=pidStarts.get(pid);return probe||(probe=(async()=>{process.platform!=="linux"&&(processStarts??=readProcessStarts());let start=(await processStarts)?.get(pid)??await readProcessStartMs(pid);return observedStarts.set(pid,start),start})(),pidStarts.set(pid,probe)),probe}});if(holders.length===0)return;daemonPids??=resolveDaemonPids?.(observedStarts)??Promise.resolve([]);let family=await daemonPids,foreign=holders.filter(holder=>!family.includes(holder.pid));if(foreign.length>0)throw new RpcSessionRegistryError(RPC_ERROR_SESSION_HELD,void 0,{holders:foreign.map(({pid,cwd,host_socket,host_instance})=>({pid,...cwd===void 0?{}:{cwd},...host_socket===void 0?{}:{host_socket},...host_instance===void 0?{}:{host_instance}}))})}}async function dispatchSessionBinding(command,entry,binding,acknowledgePrompt,daemonPids){if(!binding)throw new RpcSessionRegistryError("unknown_session");if(!READ_ONLY_OR_CONTROL.has(command.type)){let assertSessionNotHeld=sessionHeldCheck(daemonPids),state=entry.worker?.snapshot?.state;await assertSessionNotHeld(entry.runtime?.session.sessionFile??state?.sessionFile??entry.sessionPath,entry.runtime?.session.sessionId??state?.sessionId??entry.durableSessionId),"sessionPath"in command&&await assertSessionNotHeld(command.sessionPath)}command.type==="prompt"&&acknowledgePrompt(),await binding.handle(command)}var PLAIN_ID=/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;function isPlainId(value){return typeof value=="string"&&PLAIN_ID.test(value)}function isMoveId(value){return isPlainId(value)}var NOTHING_DROPPED={deliveries:[],user_messages:[]};function takeQueuedInput(session){let admittedBefore=session.externalAdmission.list().pending,cleared=session.clearQueue({abortWillFollow:!0}),stillAdmitted=new Set(session.externalAdmission.list().pending);return{deliveries:admittedBefore.filter(deliveryId=>!stillAdmitted.has(deliveryId)),user_messages:cleared.ordered.map(queued=>queued.text)}}async function abortAndSettle(port,sessionId,session){session.abortBash();let stopStarts=session.subscribe(event=>{event.type==="agent_start"&&session.abort()}),deadline,expired=new Promise(resolve=>{deadline=setTimeout(resolve,1e4)});try{await Promise.race([Promise.allSettled([session.abort().then(()=>session.waitForIdle()),port.otherRequestsSettled(sessionId),...port.pendingPrompts(sessionId)]),expired])}finally{clearTimeout(deadline),stopStarts()}}var SESSION_RELEASED_ENTRY_TYPE="session_released",RELEASED_ADMISSION_CLOSED="release_session handed this session to another runtime; deliver there instead (admission is closed here)",RELEASE_QUEUED_HINT="queued user input is still owed a turn; release with interrupt: true to take it out and receive it in dropped.user_messages";async function releaseSession(port,command){let validMove=command.reason==="move"&&isMoveId(command.moveId);if(command.reason!=="takeover"&&!validMove)return refusal2(command.id,RPC_ERROR_INVALID_RELEASE_REASON);if(port.draining())return refusal2(command.id,RPC_ERROR_HOST_DRAINING);let first=releasable(port,command,void 0);if(!("session"in first))return first;if(command.reason==="move"&&!isPlainId(first.session.sessionManager.getSessionId()))return refusal2(command.id,RPC_ERROR_RELEASE_UNSUPPORTED,{detail:"session_id_not_plain"});let busy=busySignals(port,command.sessionId,first.session),interrupted=busy.length>0;if(interrupted&&command.interrupt!==!0)return refusal2(command.id,busyCode(busy),{attachments:first.attachments,...busyData(busy)});let admission=first.session.externalAdmission,dropped=NOTHING_DROPPED,answer2;try{interrupted&&(admission.close(RELEASED_ADMISSION_CLOSED),dropped=takeQueuedInput(first.session),await abortAndSettle(port,command.sessionId,first.session),await first.session.whenQueueClearRecorded());let manager=first.session.sessionManager;return manager.isTranscriptFlushed()||await manager.persistHeaderNow(),answer2=await claimAndRelease(port,command,interrupted,dropped),answer2}catch(cause){return cause instanceof SessionMovedAwayError?(answer2=refusal2(command.id,cause.code,{detail:cause.message,...interrupted?{interrupted:!0,dropped}:{}}),answer2):(answer2=refusal2(command.id,RPC_ERROR_RELEASE_FAILED,{detail:cause instanceof Error?cause.message:String(cause),...interrupted?{interrupted:!0,dropped}:{}}),answer2)}finally{answer2?.success!==!0&&admission.reopen()}}async function claimAndRelease(port,command,interrupted,dropped){let taken=interrupted?{interrupted:!0,dropped}:void 0,ready=releasable(port,command,taken);if(!("session"in ready))return ready;let stillBusy=busySignals(port,command.sessionId,ready.session);if(stillBusy.length>0)return refusal2(command.id,busyCode(stillBusy),{attachments:ready.attachments,...busyData(stillBusy),interrupted,...taken});let admission=ready.session.externalAdmission;admission.close(RELEASED_ADMISSION_CLOSED);try{ready.session.sessionManager.appendCustomEntry(SESSION_RELEASED_ENTRY_TYPE,{reason:command.reason,...command.reason==="move"?{move_id:command.moveId,target:command.target??"",session_id:ready.session.sessionManager.getSessionId()}:{},interrupted,attachments:ready.attachments,host_instance:port.hostInstance??null,released_at:new Date().toISOString()})}catch(cause){throw admission.reopen(),cause}return await port.tearDown(command.sessionId,ready.sessionPath)?{id:command.id,type:"response",command:"release_session",success:!0,data:{released:!0,session_path:ready.sessionPath,attachments:ready.attachments,dropped}}:refusal2(command.id,RPC_ERROR_SESSION_CLOSING,taken)}function busySignals(port,sessionId,session){let activity=session.activitySnapshot,signals=[];return activity.isStreaming&&signals.push("turn"),port.pendingPrompts(sessionId).length>0&&signals.push("prompt"),session.pendingMessageCount>0&&signals.push("queued"),session.externalAdmission.list().pending.length>0&&signals.push("delivery"),activity.isBashRunning&&signals.push("bash"),activity.isCompacting&&signals.push("compaction"),activity.hasSessionWork&&signals.push("session_work"),signals.length===0&&isHandoffBusy(activity)&&signals.push("activity"),port.otherRequests(sessionId)>0&&signals.push("request"),signals}function busyData(signals){return signals.includes("queued")?{busy:signals,retry_with:{interrupt:!0},hint:RELEASE_QUEUED_HINT}:{busy:signals}}function busyCode(signals){return signals.some(signal=>signal==="turn"||signal==="prompt"||signal==="queued"||signal==="delivery")?RPC_ERROR_TURN_ACTIVE:RPC_ERROR_SESSION_BUSY}function releasable(port,command,taken){let refuse=(code,data)=>refusal2(command.id,code,data||taken?{...data,...taken}:void 0),entry;try{entry=port.lookup(command.sessionId)}catch(cause){return refuse(port.code(cause))}if(entry.state!=="open")return refuse(RPC_ERROR_SESSION_CLOSING);let session=entry.runtime?.session;if(session===void 0)return refuse(RPC_ERROR_RELEASE_UNSUPPORTED,{detail:"worker_runtime"});let sessionPath=entry.sessionPath??session.sessionFile;return sessionPath===void 0?refuse(RPC_ERROR_RELEASE_UNSUPPORTED,{detail:"no_session_file"}):entry.attachments>0&&command.force!==!0?refuse(RPC_ERROR_ATTACHED,{attachments:entry.attachments}):{session,sessionPath,attachments:entry.attachments}}function refusal2(id,code,data){return{id,type:"response",command:"release_session",success:!1,error:code,...data&&{errorCode:code,errorData:data}}}var DETACHED_RETIREMENT_GRACE_MS=5e3;function selectSweepEvictions(registry,now,idleEvictionMs,hasPendingRequest=()=>!1){let idle=[],orphaned=[];for(let{sessionId,status,sessionPath}of registry.list()){if(status!=="open")continue;let entry=registry.peek(sessionId);if(!entry)continue;if(entry.attachments===0&&sessionPath!==void 0&&sessionDirectoryRemoved(sessionPath)){orphaned.push(sessionId);continue}if(!Number.isFinite(idleEvictionMs)||hasPendingRequest(sessionId))continue;let session=entry.runtime?.session;if(entry.worker?.busy||session?.isSessionBusy){entry.lastCommandAt=now;continue}if(entry.attachments>0){now-entry.lastCommandAt>=idleEvictionMs&&idle.push(sessionId);continue}if(entry.kind==="worker"&&entry.retainOnDisconnect&&session?.sessionManager.isTranscriptFlushed()){if(session.pendingMessageCount>0||session.externalAdmission.list().pending.length>0)continue;if(entry.detachedAt!==void 0){if(now-entry.detachedAt<DETACHED_RETIREMENT_GRACE_MS)continue;idle.push(sessionId);continue}}now-entry.lastCommandAt>=idleEvictionMs&&idle.push(sessionId)}return{idle,orphaned}}var CHILD_TASK_SOURCE=/^senpi-task/,ACTIONS={extension_work:"let the named work finish, or unload with force: true (it is stopped, not resumed on reopen)",turn_active:"wait for the turn to end, or unload with interrupt: true to stop it first",work_pending:"wait for the work to finish, or unload with interrupt: true",children_live:'wait for the child tasks, or unload with children: "detach" to leave them running',attached:"ask the other clients to detach, or unload with force: true (they receive session_parked)"};async function unloadSession(port,command){if(port.draining())return answer(command,refused({reason:"host_draining",detail:"this host is draining and parks every session itself"}));let first=loaded(port,command.sessionId);if("reason"in first)return answer(command,refused(first));let{effectId}=command;if(effectId!==void 0){let begun=await beginEffect({session:first.session,by:port.by,sessionId:command.sessionId},"unload",{...command,effectId});if(!isEffectBegin(begun))return begun;if("replay"in begun)return answer(command,{outcome:begun.replay.state==="failed"?"refused":"unloaded",...refusalFields(begun.replay.outcome),...effectAnswer(begun.replay,command.sessionId,!0)})}let blocked=blockers(port,command,first.session,first.durableSessionId),standing=blocked.find(refusal3=>!interruptible(refusal3)||command.interrupt!==!0);return standing!==void 0?fail(command,first.session,standing):(blocked.length>0&&await abortAndSettle(port,command.sessionId,first.session),claimAndUnload(port,command))}async function claimAndUnload(port,command){let ready=loaded(port,command.sessionId);if("reason"in ready)return answer(command,refused(ready));let stillBlocked=blockers(port,command,ready.session,ready.durableSessionId);if(stillBlocked.length>0)return fail(command,ready.session,stillBlocked[0]);command.clearQueue===!0&&(ClientAdmissions.clearQueuedFor(ready.session),ready.session.clearQueue());let effect=command.effectId===void 0?void 0:EffectLedger.forSession(ready.session).transition(command.effectId,"done",{disposition:"unloaded"});return await port.tearDown(command.sessionId,ready.sessionPath)?answer(command,{outcome:"unloaded",sessionPath:ready.sessionPath,...effect===void 0?{}:effectAnswer(effect,command.sessionId)}):answer(command,{outcome:"refused",reason:"session_closing",detail:"another close of this session finished first"})}function interruptible(refusal3){return refusal3.reason==="turn_active"||refusal3.reason==="work_pending"}function blockers(port,command,session,durableSessionId){let found=[],activity=session.activitySnapshot,running=[activity.isStreaming&&"an agent run",port.pendingPrompts(command.sessionId).length>0&&"a prompt about to start",activity.isCompacting&&"compaction",activity.hasSessionWork&&"session work"].filter(label=>typeof label=="string");running.length>0&&found.push({reason:"turn_active",detail:running.join(", "),action:ACTIONS.turn_active});let pending=[activity.isBashRunning&&"a bash command",session.externalAdmission.list().pending.length>0&&"an admitted delivery not yet written",port.otherRequests(command.sessionId)>0&&"another request for this session"].filter(label=>typeof label=="string");pending.length>0&&found.push({reason:"work_pending",detail:pending.join(", "),action:ACTIONS.work_pending});let sources=session.activeWakeSources,childSources=sources.filter(source=>CHILD_TASK_SOURCE.test(source)),otherSources=sources.filter(source=>!CHILD_TASK_SOURCE.test(source));otherSources.length>0&&command.force!==!0&&found.push({reason:"extension_work",detail:`work published by ${otherSources.join(", ")}`,action:ACTIONS.extension_work});let childSessions=port.openChildSessions(durableSessionId);if(command.children!=="detach"&&(childSources.length>0||childSessions>0)){let what=childSessions>0?`${childSessions} child session(s) open on this host`:"child tasks still working";found.push({reason:"children_live",detail:what,action:ACTIONS.children_live})}let others=port.otherAttachments(command.sessionId);return others>0&&command.force!==!0&&found.push({reason:"attached",detail:`${others} other client(s) attached`,action:ACTIONS.attached}),found}function loaded(port,sessionId){let entry;try{entry=port.lookup(sessionId)}catch(cause){return{reason:"unsupported",detail:port.code(cause)}}if(entry.state!=="open")return{reason:"session_closing",detail:"the session is already closing"};let session=entry.runtime?.session;if(session===void 0)return{reason:"unsupported",detail:"a worker isolate owns this session's runtime"};let sessionPath=entry.sessionPath??session.sessionFile;return sessionPath===void 0?{reason:"unsupported",detail:"the session has no file to reopen it by",action:"send a prompt first so the session is written, or close it instead"}:{session,sessionPath,durableSessionId:session.sessionManager.getSessionId()}}function fail(command,session,refusal3){if(command.effectId===void 0)return answer(command,refused(refusal3));let status=EffectLedger.forSession(session).transition(command.effectId,"failed",{outcome:{kind:"refused",reason:refusal3.reason,detail:refusal3.detail,...refusal3.action===void 0?{}:{action:refusal3.action}}});return answer(command,{...refused(refusal3),...effectAnswer(status,command.sessionId)})}function refusalFields(outcome){return outcome?.reason===void 0?{}:{reason:outcome.reason,...outcome.detail===void 0?{}:{detail:outcome.detail},...outcome.action===void 0?{}:{action:outcome.action}}}function refused(refusal3){return{outcome:"refused",reason:refusal3.reason,detail:refusal3.detail,...refusal3.action===void 0?{}:{action:refusal3.action}}}function answer(command,data){return{id:command.id,type:"response",command:"unload_session",success:!0,data}}var DRAIN_SWEEP_MS=50;function error(id,command,code,data){return{id,type:"response",command,success:!1,error:code,...data&&{errorCode:code,errorData:data}}}var SessionCommandRouter=class{constructor(registry,writer,defaults,createBinding=createRpcSessionBinding,connectionOptions={},idle){if(this.bindings=new Map,this.sessionsByConnection=new Map,this.opensByConnection=new Map,this.releasedConnections=new Set,this.pendingCapabilities=new Map,this.finalizations=new Map,this.draining=!1,this.handoffParks=0,this.drainExitRequested=!1,this.handoffClosed=new Set,this.activeRequests=new Map,this.requestSettledListeners=new Map,this.memoryPressure=!1,this.stopLimitBroadcast=subscriptionLimits.subscribe(limits=>writer.broadcastHostRecord({type:"subscription_limits",...limits})),this.registry=registry,this.writer=writer,this.defaults=defaults,this.createBinding=createBinding,this.connectionOptions=connectionOptions,this.idleNow=idle?.now??Date.now,this.idleEvictionMs=idle?.idleEvictionMs??Number.POSITIVE_INFINITY,this.emptyExitMs=idle?.emptyExitMs??Number.POSITIVE_INFINITY,this.onEmptyExit=idle?.onEmptyExit,this.onHandoffParked=idle?.onHandoffParked,this.handoverParkedDir=idle?.handoverParkedDir,this.canExitWhenEmpty=idle?.canExitWhenEmpty,writer.status.setSource(registryStatusSource(registry)),writer.status.setLastEffectProvider(sessionId=>{let session=this.registry.peek(sessionId)?.runtime?.session;if(session===void 0)return;let latest=latestSessionEffect(session);return latest===void 0?void 0:{effectId:latest.effectId,kind:latest.kind,state:latest.state}}),writer.afterRecord=sessionId=>{let session=this.registry.peek(sessionId)?.runtime?.session;if(session!==void 0)for(let status of drainSessionEffects(session))this.writer.status.publishEffect(sessionId,status)},this.uninstallEffectSink=installSessionEffectSink({owns:session=>this.routingIdOf(session)!==void 0,flush:(session,statuses)=>{let sessionId=this.routingIdOf(session);if(sessionId!==void 0)for(let status of statuses)this.writer.status.publishEffect(sessionId,status)}}),Number.isFinite(this.idleEvictionMs)||Number.isFinite(this.emptyExitMs)){let tickMs=Math.max(20,Math.min(5e3,Math.min(this.idleEvictionMs,this.emptyExitMs)/4));this.sweepTimer=setInterval(()=>this.sweepIdleSessions(),tickMs),this.sweepTimer.unref?.()}}get sessionCount(){return this.registry.size}setHostMemoryView(view){this.hostMemoryView=view}sessionMemory(sessionId){let view=this.hostMemoryView;if(view===void 0)return{main_heap_bytes:0,kernel_heap_bytes:0,kernel_count:0};let kernels=view.kernels().filter(kernel=>kernel.sessionId===sessionId),kernelHeapBytes=0;for(let kernel of kernels)kernelHeapBytes+=kernel.liveBytes;return{main_heap_bytes:view.mainHeapBytes(),kernel_heap_bytes:kernelHeapBytes,kernel_count:kernels.length}}beginDrain(){this.draining=!0,this.stopSweep(),this.drainTimer===void 0&&!this.drainExitRequested&&(this.drainTimer=setInterval(()=>this.sweepDrain(),DRAIN_SWEEP_MS),this.drainTimer.unref?.()),this.sweepDrain()}sweepDrain(){if(this.activeRequests.has(void 0))return;let verdicts=readDrainVerdicts(this.registry,sessionId=>this.activeRequests.has(sessionId));if(verdicts){for(let sessionId of verdicts.gone)this.parkForHandoff(sessionId,"session_dir_removed");for(let sessionId of verdicts.park)this.parkForHandoff(sessionId,"handoff_parked");this.registry.size>0||this.handoffParks>0||this.finalizations.size>0||(this.drainTimer!==void 0&&(clearInterval(this.drainTimer),this.drainTimer=void 0),this.stopSweep(),!this.drainExitRequested&&(this.drainExitRequested=!0,this.onEmptyExit?.()))}}parkForHandoff(sessionId,reason){this.handoffClosed.add(sessionId),this.handoffParks++,this.evictIdleSession(sessionId,reason).catch(cause=>{process.stderr.write(`senpi rpc handoff park ${sessionId} failed: ${String(cause)}
18
18
  `)}).finally(()=>{this.handoffParks--,this.sweepDrain()})}setMemoryPressure(pressure){this.memoryPressure=pressure}handle(command){let sessionId="sessionId"in command?command.sessionId:void 0;return this.draining&&sessionId!==void 0&&this.handoffClosed.has(sessionId)?Promise.resolve(void 0):this.draining&&command.type==="open_session"?Promise.resolve(error(command.id,command.type,"host_draining")):command.type==="warm"?answerWarm(command,{draining:this.draining,warm:this.registry.warm,cwd:this.defaults.cwd,hostContext:this.defaults.hostContext}):(this.activeRequests.set(sessionId,(this.activeRequests.get(sessionId)??0)+1),runWithSessionAttribution({sessionId},()=>this.dispatch(command)).finally(()=>{let remaining=(this.activeRequests.get(sessionId)??1)-1;if(remaining>0?this.activeRequests.set(sessionId,remaining):this.activeRequests.delete(sessionId),sessionId!==void 0)for(let listener of this.requestSettledListeners.get(sessionId)??[])listener();this.draining&&this.sweepDrain()}))}async dispatch(command){if(command.type==="get_protocol_info"){let capabilities=multiSessionHostCapabilities({warm:this.registry.warm!==void 0,toolRuntime:this.defaults.toolRuntime??"in-process",negotiated:this.connectionOptions?.capabilities??[]});return{id:command.id,type:"response",command:"get_protocol_info",success:!0,data:{protocolVersion:1,serverVersion:VERSION,capabilities,mode:"multi",...protocolIdentity(),memory_pressure:this.memoryPressure}}}if(command.type==="get_subscription_limits")return{id:command.id,type:"response",command:"get_subscription_limits",success:!0,data:{accounts:subscriptionLimits.snapshot()}};if(command.type==="list_sessions"){let withMemory=this.registry.list().map(row=>({...row,memory:this.sessionMemory(row.sessionId)})),sessions=command.include_workers===!0?withMemory:withMemory.filter(row=>row.kind!=="worker").map(({context:_context,...row})=>row);return{id:command.id,type:"response",command:"list_sessions",success:!0,data:{sessions}}}if(command.type==="detach_connection")return detachConnection(command,this.writer.currentConnection(),id=>this.releaseConnection(id));if(command.type==="open_session")return this.openWithBarrier(command);if(command.type==="close_session")return this.close(command);if(command.type==="release_session")return releaseSession({draining:()=>this.draining,hostInstance:this.defaults.hostContext?.host_instance,lookup:sessionId2=>this.registry.getForCommand(sessionId2,"release_session"),code:cause=>this.code(cause),otherRequests:sessionId2=>Math.max(0,(this.activeRequests.get(sessionId2)??1)-1),otherRequestsSettled:sessionId2=>this.otherRequestsSettled(sessionId2),pendingPrompts:sessionId2=>this.bindings.get(sessionId2)?.pendingPrompts?.()??[],tearDown:(sessionId2,sessionPath)=>this.tearDownReleased(sessionId2,sessionPath)},command);if(command.type==="unload_session"){let caller=this.writer.currentConnection();return unloadSession({draining:()=>this.draining,by:{connectionId:caller??"host"},lookup:sessionId2=>this.registry.getForCommand(sessionId2,"unload_session"),code:cause=>this.code(cause),otherRequests:sessionId2=>Math.max(0,(this.activeRequests.get(sessionId2)??1)-1),otherRequestsSettled:sessionId2=>this.otherRequestsSettled(sessionId2),pendingPrompts:sessionId2=>this.bindings.get(sessionId2)?.pendingPrompts?.()??[],otherAttachments:sessionId2=>{let attachments=Math.max(0,this.registry.peek(sessionId2)?.attachments??0);return caller!==void 0&&this.sessionsByConnection.get(caller)?.has(sessionId2)===!0?Math.max(0,attachments-1):attachments},openChildSessions:durableSessionId=>this.registry.list().filter(row=>row.durableSessionId!==durableSessionId&&(row.context?.parent_session_id===durableSessionId||row.context?.root_session_id===durableSessionId)).length,tearDown:(sessionId2,sessionPath)=>this.tearDownUnloaded(sessionId2,sessionPath)},command)}if(command.type==="set_client_info"&&!command.sessionId){let connection=this.writer.currentConnection();return connection!==void 0&&(this.pendingCapabilities.set(connection,command.capabilities??[]),this.writer.setConnectionCapabilities(connection,command.capabilities??[])),{id:command.id,type:"response",command:"set_client_info",success:!0}}if(command.type==="subscribe_sessions"){let connection=this.writer.currentConnection(),{answer:answer2,activate}=answerSubscribeSessions(command,connection,this.writer.status);if(activate!==void 0&&connection!==void 0){(async()=>{await this.writer.enqueueControl(answer2,connection),await new Promise(resolve=>queueMicrotask(resolve));try{this.writer.hasConnection(connection)?this.writer.status.activate(activate):this.writer.status.unsubscribe(connection,activate)}catch(cause){process.stderr.write(`senpi rpc subscription activation failed: ${String(cause)}
19
19
  `)}})().catch(cause=>{this.writer.status.unsubscribe(connection,activate),process.stderr.write(`senpi rpc subscribe answer could not be delivered: ${String(cause)}
20
20
  `)});return}return answer2}if(command.type==="unsubscribe_sessions")return answerUnsubscribeSessions(command,this.writer.currentConnection(),this.writer.status);if(command.type==="get_effect_status"&&!command.sessionId&&command.sessionPath!==void 0)return answerEffectFromTranscript(command.id,command.sessionPath,command.effectId);if(!command.sessionId)return error(command.id,command.type,RPC_ERROR_MISSING_SESSION_ID);let sessionId=command.sessionId;if(command.type==="set_session_context")return this.setSessionContext(command);try{let entry=this.registry.getForCommand(sessionId,command.type);await dispatchSessionBinding(command,entry,this.bindings.get(sessionId),()=>this.acknowledgePrompt(command.id,sessionId),observedStarts=>this.registry.holderPids?.(observedStarts)??Promise.resolve([]));return}catch(cause){return error(command.id,command.type,this.code(cause),this.detail(cause))}}setSessionContext(command){let owner=this.writer.currentConnection();if(owner!==void 0&&this.sessionsByConnection.get(owner)?.has(command.sessionId)!==!0)return notAttachedRefusal(command);try{let entry=this.registry.getForCommand(command.sessionId,command.type);return answerSetSessionContext(command,entry,this.writer.status)}catch(cause){return error(command.id,command.type,this.code(cause),this.detail(cause))}}async dispose(){this.stopLimitBroadcast(),this.drainExitRequested=!0,this.stopSweep(),this.drainTimer!==void 0&&clearInterval(this.drainTimer),await Promise.all([...this.bindings.entries()].map(async([sessionId,binding])=>{let claim=this.tryClaimClose(sessionId,{drainAttachments:!0});claim&&(claim.finalizer?await this.finalizeClose(sessionId,binding,()=>this.writer.closeSession(sessionId,{type:"response",command:"close_session",success:!0,data:{}},"host_shutdown")):await this.finalizations.get(sessionId)?.promise,this.writer.forgetSession(sessionId))})),this.bindings.clear(),this.uninstallEffectSink?.(),this.uninstallEffectSink=void 0}sweepIdleSessions(){let now=this.idleNow(),idleEvictionMs=this.memoryPressure?this.idleEvictionMs/2:this.idleEvictionMs,verdicts=selectSweepEvictions(this.registry,now,idleEvictionMs,sessionId=>this.activeRequests.has(sessionId)||(this.bindings.get(sessionId)?.pendingPrompts?.().length??0)>0);for(let sessionId of verdicts.orphaned)this.evictIdleSession(sessionId,"session_dir_removed");for(let sessionId of verdicts.idle)this.evictIdleSession(sessionId);Number.isFinite(this.emptyExitMs)&&(this.registry.size===0&&(this.canExitWhenEmpty?.()??!0)?this.emptySince===void 0?this.emptySince=now:now-this.emptySince>=this.emptyExitMs&&(this.stopSweep(),this.onEmptyExit?.()):this.emptySince=void 0)}async evictIdleSession(sessionId,reason){let retained=this.registry.peek(sessionId),parkedPath=retained?.retainOnDisconnect===!0||reason==="handoff_parked"?retained?.sessionPath:void 0,handoff=reason==="handoff_parked"||reason==="session_dir_removed"&&this.draining,owners=handoff?[...this.sessionsByConnection].filter(([,owned])=>owned.has(sessionId)).map(([connection])=>connection):[],claim=this.tryClaimClose(sessionId,{drainAttachments:!0});if(!claim)return;this.handoverParkedDir!==void 0&&parkedPath!==void 0&&retained?.retainOnDisconnect===!0&&retained.sessionPath!==void 0&&await recordHandoverParkedSession(this.handoverParkedDir,{...parkedEntryFromProfile({sessionPath:retained.sessionPath,...retained.durableSessionId!==void 0?{durableSessionId:retained.durableSessionId}:{}},retained.profile,Object.keys(this.defaults.hostContext??{})),parkedBy:this.defaults.hostContext?.host_instance??hostInstanceId()}).catch(cause=>{process.stderr.write(`senpi rpc handover park record ${sessionId} failed: ${String(cause)}
21
- `)});let binding=this.bindings.get(sessionId);binding?.cancelPendingExtensionUiRequests?.(),handoff||this.forgetSessionOwnership(sessionId),claim.finalizer?await this.finalizeClose(sessionId,binding,()=>parkedPath!==void 0&&reason===void 0?this.writer.parkSession(sessionId,parkedPath,"idle"):this.writer.closeSession(sessionId,{type:"response",command:"close_session",success:!0,data:{}},reason??"idle_evicted",reason==="handoff_parked"?parkedPath:void 0)):await this.finalizations.get(sessionId)?.promise,handoff&&(this.forgetSessionOwnership(sessionId),await this.onHandoffParked?.(owners.filter(connection=>!this.sessionsByConnection.has(connection)))),this.writer.forgetSession(sessionId)}otherRequestsSettled(sessionId){return new Promise(resolve=>{let listeners=this.requestSettledListeners.get(sessionId)??new Set,check=()=>{(this.activeRequests.get(sessionId)??0)>1||(listeners.delete(check),listeners.size===0&&this.requestSettledListeners.delete(sessionId),resolve())};listeners.add(check),this.requestSettledListeners.set(sessionId,listeners),check()})}async tearDownReleased(sessionId,sessionPath){let claim=this.tryClaimClose(sessionId,{drainAttachments:!0});if(!claim)return!1;let binding=this.bindings.get(sessionId);return binding?.cancelPendingExtensionUiRequests?.(),this.forgetSessionOwnership(sessionId),claim.finalizer?await this.finalizeClose(sessionId,binding,()=>this.writer.releaseSession(sessionId,sessionPath)):await this.finalizations.get(sessionId)?.promise,this.writer.forgetSession(sessionId),!0}async tearDownUnloaded(sessionId,sessionPath){let claim=this.tryClaimClose(sessionId,{drainAttachments:!0});if(!claim)return!1;let binding=this.bindings.get(sessionId);return binding?.cancelPendingExtensionUiRequests?.(),this.forgetSessionOwnership(sessionId),claim.finalizer?await this.finalizeClose(sessionId,binding,()=>this.writer.parkSession(sessionId,sessionPath,"unloaded")):await this.finalizations.get(sessionId)?.promise,this.writer.forgetSession(sessionId),!0}forgetSessionOwnership(sessionId){for(let[connection,owned]of this.sessionsByConnection)owned.delete(sessionId),owned.size===0&&this.sessionsByConnection.delete(connection)}routingIdOf(session){for(let row of this.registry.list())if(this.registry.peek(row.sessionId)?.runtime?.session===session)return row.sessionId}stopSweep(){this.sweepTimer!==void 0&&(clearInterval(this.sweepTimer),this.sweepTimer=void 0)}acknowledgePrompt(id,sessionId){let connection=this.writer.currentConnection();if(id===void 0||connection===void 0)return;let inFlight=Math.max(0,(this.activeRequests.get(sessionId)??1)-1);this.writer.sendOpenQueued(connection,{type:"queued",for_request:id,position:inFlight+1,in_flight:inFlight})}openWithBarrier(command){let owner=this.writer.currentConnection();if(owner===void 0)return this.open(command);let resolveBarrier,barrier=new Promise(resolve=>{resolveBarrier=resolve}),opens=this.opensByConnection.get(owner)??new Set,inFlight=0;for(let pending of this.opensByConnection.values())inFlight+=pending.size;opens.add(barrier),this.opensByConnection.set(owner,opens),command.id!==void 0&&this.writer.sendOpenQueued(owner,{type:"queued",for_request:command.id,position:inFlight+1,in_flight:inFlight});let opened=this.open(command,owner);if(command.sessionPath!==void 0&&this.handoverParkedDir!==void 0){let dir=this.handoverParkedDir,sessionPath=command.sessionPath;opened.then(response=>{response===void 0&&clearHandoverParkedSession(dir,sessionPath).catch(()=>{})},()=>{})}return opened.finally(()=>{resolveBarrier(),opens.delete(barrier),opens.size===0&&this.opensByConnection.delete(owner)})}reopenParked(entry){return this.open(parkedOpenCommand(entry),void 0,{reply:!1,defaults:!1})}async open(command,owner,options){let defaults=options?.defaults===!1?void 0:this.defaults,instanceId=this.defaults.hostContext?.host_instance??hostInstanceId();if(command.expectedHostInstance!==void 0){if(typeof command.expectedHostInstance!="string"||command.expectedHostInstance.trim()==="")return error(command.id,"open_session",`${RPC_ERROR_INVALID_LAUNCH_PROFILE}: expectedHostInstance must be a non-empty string`,{reason:"invalid_expected_host_instance",action:"supply_host_instance"});if(command.expectedHostInstance!==instanceId)return error(command.id,"open_session",RPC_ERROR_OWNER_CHANGED,{reason:"host_instance_mismatch",action:"rediscover_holder",expectedHostInstance:command.expectedHostInstance,hostInstance:instanceId})}let kindError=sessionKindError(command.kind);if(kindError)return error(command.id,"open_session",`${RPC_ERROR_INVALID_SESSION_KIND}: ${kindError}`);let contextError=sessionContextError(command.context);if(contextError)return error(command.id,"open_session",`${RPC_ERROR_INVALID_SESSION_CONTEXT}: ${contextError}`);let autoTitleError=sessionAutoTitleError(command.auto_title);if(autoTitleError)return error(command.id,"open_session",`${RPC_ERROR_INVALID_LAUNCH_PROFILE}: ${autoTitleError}`);let promptSurfaceError=sessionPromptSurfaceError(command.promptSurface);if(promptSurfaceError)return error(command.id,"open_session",`${RPC_ERROR_INVALID_LAUNCH_PROFILE}: ${promptSurfaceError}`);let browserEngineError=sessionBrowserEngineError(command.browserEngine);if(browserEngineError)return error(command.id,"open_session",`${RPC_ERROR_INVALID_LAUNCH_PROFILE}: ${browserEngineError}`);if(!command.provider!=!command.modelId)return error(command.id,"open_session",`${RPC_ERROR_INVALID_LAUNCH_PROFILE}: provider and modelId must be given together`);let retryFallbackError=sessionRetryFallbackError(command.retryFallback);if(retryFallbackError)return error(command.id,"open_session",`${RPC_ERROR_INVALID_LAUNCH_PROFILE}: ${retryFallbackError}`);let opened,assertSessionNotHeld=sessionHeldCheck(observedStarts=>this.registry.holderPids?.(observedStarts)??Promise.resolve([]));try{await assertSessionNotHeld(command.sessionPath),opened=await this.registry.openSession({cwd:command.cwd??this.defaults.cwd,sessionPath:command.sessionPath,holderEndpoint:{host_instance:instanceId,...this.defaults.hostContext?.host_socket===void 0?{}:{host_socket:this.defaults.hostContext.host_socket}},permissionPreset:command.permissionPreset??defaults?.permissionPreset,creationModel:command.provider&&command.modelId?{provider:command.provider,modelId:command.modelId}:defaults?.creationModel,initialThinkingLevel:command.thinkingLevel??defaults?.initialThinkingLevel,sessionKind:command.kind,sessionContext:this.defaults.hostContext?{...command.context,...this.defaults.hostContext}:command.context,...command.durableSessionId!==void 0?{durableSessionId:command.durableSessionId}:{},...typeof command.auto_title=="boolean"?{autoTitle:command.auto_title}:{},...command.promptSurface!==void 0?{promptSurface:command.promptSurface}:{},...command.browserEngine!==void 0?{browserEngine:command.browserEngine}:{},...command.retryFallback!==void 0?{retryFallback:command.retryFallback}:{}},{retainOnDisconnect:command.retain_on_disconnect===!0,attachOnly:command.expectedHostInstance!==void 0});let openedSession=opened,entry=this.registry.getForCommand(openedSession.sessionId,"open_session"),state=entry.worker?.snapshot?.state;if(await assertSessionNotHeld(entry.runtime?.session.sessionFile??state?.sessionFile??entry.sessionPath,entry.runtime?.session.sessionId??state?.sessionId??entry.durableSessionId),this.writer.setSessionKind(openedSession.sessionId,entry.kind),this.writer.setSessionMedia(openedSession.sessionId,toolMediaPersister(()=>liveToolMediaScope(entry))),owner!==void 0&&(this.writer.hasRegisteredConnectionCapabilities(owner)||this.writer.setConnectionCapabilities(owner,this.pendingCapabilities.get(owner)??this.connectionOptions?.capabilities??[]),this.writer.attachConnectionToSession(owner,openedSession.sessionId)),owner!==void 0){let owned=this.sessionsByConnection.get(owner)??new Map;owned.set(openedSession.sessionId,(owned.get(openedSession.sessionId)??0)+1),this.sessionsByConnection.set(owner,owned)}if(!this.bindings.has(openedSession.sessionId)){this.bindings.set(openedSession.sessionId,await this.createBinding(openedSession.sessionId,entry,this.writer,()=>{this.close({type:"close_session",sessionId:openedSession.sessionId})},{...this.connectionOptions,capabilities:owner!==void 0?this.pendingCapabilities.get(owner)??this.connectionOptions?.capabilities??[]:this.connectionOptions?.capabilities,clientInfo:{setCapabilities:(connectionId,capabilities)=>{connectionId!==void 0&&(this.writer.setConnectionCapabilities(connectionId,capabilities),this.pendingCapabilities.set(connectionId,[...capabilities]))},connectionId:()=>this.writer.currentConnection()}})),entry.worker&&(entry.worker.bindingReady=!0);let settled=()=>{this.draining&&queueMicrotask(()=>this.sweepDrain())};typeof entry.worker?.subscribeSettled=="function"?entry.worker.subscribeSettled(settled):typeof entry.runtime?.session.subscribe=="function"&&entry.runtime.session.subscribe(event=>{(event.type==="agent_settled"||event.type==="agent_idle")&&settled()}),entry.worker&&entry.worker.exited.then(async()=>{await this.finalizations.get(openedSession.sessionId)?.promise,this.bindings.delete(openedSession.sessionId),this.forgetSessionOwnership(openedSession.sessionId),this.writer.forgetSession(openedSession.sessionId)})}opened.attached?this.writer.status.publish(openedSession.sessionId,"attach","client"):(this.writer.publishSessionOpened({type:"session_opened",sessionId:openedSession.sessionId,durableSessionId:openedSession.durableSessionId,...openedSession.sessionPath!==void 0?{sessionPath:openedSession.sessionPath}:{},kind:entry.kind,cwd:entry.cwd,context:entry.context}),this.writer.status.publish(openedSession.sessionId,"open","client")),!this.draining&&owner!==void 0&&this.releasedConnections.has(owner)&&(this.releaseOwnerAttachment(owner,openedSession.sessionId),await this.releaseOwnedSession(openedSession.sessionId));let replyState=entry.worker?.snapshot?.state??(entry.runtime?buildRpcSessionState(entry.runtime.session):void 0);if(!replyState)throw new Error("Session state was not created");options?.reply!==!1&&this.writer.enqueue(opened.sessionId,{id:command.id,type:"response",command:"open_session",success:!0,data:{sessionId:opened.sessionId,state:replyState,...opened.attached?{attached:!0}:{}}});return}catch(cause){if(opened){if(!opened.attached){let entry=this.registry.peek(opened.sessionId);(entry?.runtime!==void 0||entry?.worker!==void 0)&&this.writer.sealRolledBackOpen(opened.sessionId,entry.sessionPath)}try{opened.attached?await this.releaseOwnedSession(opened.sessionId):await this.registry.close(opened.sessionId)}catch{}this.writer.forgetSession(opened.sessionId)}return error(command.id,"open_session",this.code(cause),this.detail(cause))}}async releaseConnection(connectionId){this.releasedConnections.add(connectionId),this.writer.clearConnectionCapabilities(connectionId);for(let sessionId of this.sessionsByConnection.get(connectionId)?.keys()??[])this.writer.detachConnectionFromSession(connectionId,sessionId);let opens=this.opensByConnection.get(connectionId),owned=this.sessionsByConnection.get(connectionId);if(this.sessionsByConnection.delete(connectionId),this.draining)return opens&&await Promise.all([...opens]),this.releasedConnections.delete(connectionId),[...owned?.keys()??[]];if(owned===void 0)return opens&&await Promise.all([...opens]),this.releasedConnections.delete(connectionId),[];let deferred=new Set;return await Promise.all([...owned].map(async([sessionId,count])=>{for(let attachment=0;attachment<count;attachment++){let live=this.registry.peek(sessionId),endsSession=live?.retainOnDisconnect!==!0&&(live?.attachments??0)<=1,session=live?.state==="open"?live.runtime?.session:void 0;if(endsSession&&live?.state==="open"&&live.worker?.snapshot?.streaming){deferred.add(sessionId);let unsubscribe=live.worker.subscribeSettled(()=>{unsubscribe(),this.releaseOwnedSession(sessionId).catch(cause=>{process.stderr.write(`senpi rpc deferred worker release ${sessionId} failed: ${String(cause)}
21
+ `)});let binding=this.bindings.get(sessionId);binding?.cancelPendingExtensionUiRequests?.(),handoff||this.forgetSessionOwnership(sessionId),claim.finalizer?await this.finalizeClose(sessionId,binding,()=>parkedPath!==void 0&&reason===void 0?this.writer.parkSession(sessionId,parkedPath,"idle"):this.writer.closeSession(sessionId,{type:"response",command:"close_session",success:!0,data:{}},reason??"idle_evicted",reason==="handoff_parked"?parkedPath:void 0)):await this.finalizations.get(sessionId)?.promise,handoff&&(this.forgetSessionOwnership(sessionId),await this.onHandoffParked?.(owners.filter(connection=>!this.sessionsByConnection.has(connection)))),this.writer.forgetSession(sessionId)}otherRequestsSettled(sessionId){return new Promise(resolve=>{let listeners=this.requestSettledListeners.get(sessionId)??new Set,check=()=>{(this.activeRequests.get(sessionId)??0)>1||(listeners.delete(check),listeners.size===0&&this.requestSettledListeners.delete(sessionId),resolve())};listeners.add(check),this.requestSettledListeners.set(sessionId,listeners),check()})}async tearDownReleased(sessionId,sessionPath){let claim=this.tryClaimClose(sessionId,{drainAttachments:!0});if(!claim)return!1;let binding=this.bindings.get(sessionId);return binding?.cancelPendingExtensionUiRequests?.(),this.forgetSessionOwnership(sessionId),claim.finalizer?await this.finalizeClose(sessionId,binding,()=>this.writer.releaseSession(sessionId,sessionPath)):await this.finalizations.get(sessionId)?.promise,this.writer.forgetSession(sessionId),!0}async tearDownUnloaded(sessionId,sessionPath){let claim=this.tryClaimClose(sessionId,{drainAttachments:!0});if(!claim)return!1;let binding=this.bindings.get(sessionId);return binding?.cancelPendingExtensionUiRequests?.(),this.forgetSessionOwnership(sessionId),claim.finalizer?await this.finalizeClose(sessionId,binding,()=>this.writer.parkSession(sessionId,sessionPath,"unloaded")):await this.finalizations.get(sessionId)?.promise,this.writer.forgetSession(sessionId),!0}forgetSessionOwnership(sessionId){for(let[connection,owned]of this.sessionsByConnection)owned.delete(sessionId),owned.size===0&&this.sessionsByConnection.delete(connection)}routingIdOf(session){for(let row of this.registry.list())if(this.registry.peek(row.sessionId)?.runtime?.session===session)return row.sessionId}stopSweep(){this.sweepTimer!==void 0&&(clearInterval(this.sweepTimer),this.sweepTimer=void 0)}acknowledgePrompt(id,sessionId){let connection=this.writer.currentConnection();if(id===void 0||connection===void 0)return;let inFlight=Math.max(0,(this.activeRequests.get(sessionId)??1)-1);this.writer.sendOpenQueued(connection,{type:"queued",for_request:id,position:inFlight+1,in_flight:inFlight})}openWithBarrier(command){let owner=this.writer.currentConnection();if(owner===void 0)return this.open(command);let resolveBarrier,barrier=new Promise(resolve=>{resolveBarrier=resolve}),opens=this.opensByConnection.get(owner)??new Set,inFlight=0;for(let pending of this.opensByConnection.values())inFlight+=pending.size;opens.add(barrier),this.opensByConnection.set(owner,opens),command.id!==void 0&&this.writer.sendOpenQueued(owner,{type:"queued",for_request:command.id,position:inFlight+1,in_flight:inFlight});let opened=this.open(command,owner);if(command.sessionPath!==void 0&&this.handoverParkedDir!==void 0){let dir=this.handoverParkedDir,sessionPath=command.sessionPath;opened.then(response=>{response===void 0&&clearHandoverParkedSession(dir,sessionPath).catch(()=>{})},()=>{})}return opened.finally(()=>{resolveBarrier(),opens.delete(barrier),opens.size===0&&this.opensByConnection.delete(owner)})}reopenParked(entry){return this.open(parkedOpenCommand(entry),void 0,{reply:!1,defaults:!1})}async open(command,owner,options){let defaults=options?.defaults===!1?void 0:this.defaults,instanceId=this.defaults.hostContext?.host_instance??hostInstanceId();if(command.expectedHostInstance!==void 0){if(typeof command.expectedHostInstance!="string"||command.expectedHostInstance.trim()==="")return error(command.id,"open_session",`${RPC_ERROR_INVALID_LAUNCH_PROFILE}: expectedHostInstance must be a non-empty string`,{reason:"invalid_expected_host_instance",action:"supply_host_instance"});if(command.expectedHostInstance!==instanceId)return error(command.id,"open_session",RPC_ERROR_OWNER_CHANGED,{reason:"host_instance_mismatch",action:"rediscover_holder",expectedHostInstance:command.expectedHostInstance,hostInstance:instanceId})}let kindError=sessionKindError(command.kind);if(kindError)return error(command.id,"open_session",`${RPC_ERROR_INVALID_SESSION_KIND}: ${kindError}`);let contextError=sessionContextError(command.context);if(contextError)return error(command.id,"open_session",`${RPC_ERROR_INVALID_SESSION_CONTEXT}: ${contextError}`);let autoTitleError=sessionAutoTitleError(command.auto_title);if(autoTitleError)return error(command.id,"open_session",`${RPC_ERROR_INVALID_LAUNCH_PROFILE}: ${autoTitleError}`);let promptSurfaceError=sessionPromptSurfaceError(command.promptSurface);if(promptSurfaceError)return error(command.id,"open_session",`${RPC_ERROR_INVALID_LAUNCH_PROFILE}: ${promptSurfaceError}`);let browserEngineError=sessionBrowserEngineError(command.browserEngine);if(browserEngineError)return error(command.id,"open_session",`${RPC_ERROR_INVALID_LAUNCH_PROFILE}: ${browserEngineError}`);if(!command.provider!=!command.modelId)return error(command.id,"open_session",`${RPC_ERROR_INVALID_LAUNCH_PROFILE}: provider and modelId must be given together`);let retryFallbackError=sessionRetryFallbackError(command.retryFallback);if(retryFallbackError)return error(command.id,"open_session",`${RPC_ERROR_INVALID_LAUNCH_PROFILE}: ${retryFallbackError}`);let opened,assertSessionNotHeld=sessionHeldCheck(observedStarts=>this.registry.holderPids?.(observedStarts)??Promise.resolve([]));try{await assertSessionNotHeld(command.sessionPath),opened=await this.registry.openSession({cwd:command.cwd??this.defaults.cwd,sessionPath:command.sessionPath,holderEndpoint:{host_instance:instanceId,...process.env[HOST_DAEMON_DIR_ENV]?{host_daemon_dir:process.env[HOST_DAEMON_DIR_ENV]}:{},...this.defaults.hostContext?.host_socket===void 0?{}:{host_socket:this.defaults.hostContext.host_socket}},permissionPreset:command.permissionPreset??defaults?.permissionPreset,creationModel:command.provider&&command.modelId?{provider:command.provider,modelId:command.modelId}:defaults?.creationModel,initialThinkingLevel:command.thinkingLevel??defaults?.initialThinkingLevel,sessionKind:command.kind,sessionContext:this.defaults.hostContext?{...command.context,...this.defaults.hostContext}:command.context,...command.durableSessionId!==void 0?{durableSessionId:command.durableSessionId}:{},...typeof command.auto_title=="boolean"?{autoTitle:command.auto_title}:{},...command.promptSurface!==void 0?{promptSurface:command.promptSurface}:{},...command.browserEngine!==void 0?{browserEngine:command.browserEngine}:{},...command.retryFallback!==void 0?{retryFallback:command.retryFallback}:{}},{retainOnDisconnect:command.retain_on_disconnect===!0,attachOnly:command.expectedHostInstance!==void 0});let openedSession=opened,entry=this.registry.getForCommand(openedSession.sessionId,"open_session"),state=entry.worker?.snapshot?.state;if(await assertSessionNotHeld(entry.runtime?.session.sessionFile??state?.sessionFile??entry.sessionPath,entry.runtime?.session.sessionId??state?.sessionId??entry.durableSessionId),this.writer.setSessionKind(openedSession.sessionId,entry.kind),this.writer.setSessionMedia(openedSession.sessionId,toolMediaPersister(()=>liveToolMediaScope(entry))),owner!==void 0&&(this.writer.hasRegisteredConnectionCapabilities(owner)||this.writer.setConnectionCapabilities(owner,this.pendingCapabilities.get(owner)??this.connectionOptions?.capabilities??[]),this.writer.attachConnectionToSession(owner,openedSession.sessionId)),owner!==void 0){let owned=this.sessionsByConnection.get(owner)??new Map;owned.set(openedSession.sessionId,(owned.get(openedSession.sessionId)??0)+1),this.sessionsByConnection.set(owner,owned)}if(!this.bindings.has(openedSession.sessionId)){this.bindings.set(openedSession.sessionId,await this.createBinding(openedSession.sessionId,entry,this.writer,()=>{this.close({type:"close_session",sessionId:openedSession.sessionId})},{...this.connectionOptions,capabilities:owner!==void 0?this.pendingCapabilities.get(owner)??this.connectionOptions?.capabilities??[]:this.connectionOptions?.capabilities,clientInfo:{setCapabilities:(connectionId,capabilities)=>{connectionId!==void 0&&(this.writer.setConnectionCapabilities(connectionId,capabilities),this.pendingCapabilities.set(connectionId,[...capabilities]))},connectionId:()=>this.writer.currentConnection()}})),entry.worker&&(entry.worker.bindingReady=!0);let settled=()=>{this.draining&&queueMicrotask(()=>this.sweepDrain())};typeof entry.worker?.subscribeSettled=="function"?entry.worker.subscribeSettled(settled):typeof entry.runtime?.session.subscribe=="function"&&entry.runtime.session.subscribe(event=>{(event.type==="agent_settled"||event.type==="agent_idle")&&settled()}),entry.worker&&entry.worker.exited.then(async()=>{await this.finalizations.get(openedSession.sessionId)?.promise,this.bindings.delete(openedSession.sessionId),this.forgetSessionOwnership(openedSession.sessionId),this.writer.forgetSession(openedSession.sessionId)})}opened.attached?this.writer.status.publish(openedSession.sessionId,"attach","client"):(this.writer.publishSessionOpened({type:"session_opened",sessionId:openedSession.sessionId,durableSessionId:openedSession.durableSessionId,...openedSession.sessionPath!==void 0?{sessionPath:openedSession.sessionPath}:{},kind:entry.kind,cwd:entry.cwd,context:entry.context}),this.writer.status.publish(openedSession.sessionId,"open","client")),!this.draining&&owner!==void 0&&this.releasedConnections.has(owner)&&(this.releaseOwnerAttachment(owner,openedSession.sessionId),await this.releaseOwnedSession(openedSession.sessionId));let replyState=entry.worker?.snapshot?.state??(entry.runtime?buildRpcSessionState(entry.runtime.session):void 0);if(!replyState)throw new Error("Session state was not created");options?.reply!==!1&&this.writer.enqueue(opened.sessionId,{id:command.id,type:"response",command:"open_session",success:!0,data:{sessionId:opened.sessionId,state:replyState,...opened.attached?{attached:!0}:{}}});return}catch(cause){if(opened){if(!opened.attached){let entry=this.registry.peek(opened.sessionId);(entry?.runtime!==void 0||entry?.worker!==void 0)&&this.writer.sealRolledBackOpen(opened.sessionId,entry.sessionPath)}try{opened.attached?await this.releaseOwnedSession(opened.sessionId):await this.registry.close(opened.sessionId)}catch{}this.writer.forgetSession(opened.sessionId)}return error(command.id,"open_session",this.code(cause),this.detail(cause))}}async releaseConnection(connectionId){this.releasedConnections.add(connectionId),this.writer.clearConnectionCapabilities(connectionId);for(let sessionId of this.sessionsByConnection.get(connectionId)?.keys()??[])this.writer.detachConnectionFromSession(connectionId,sessionId);let opens=this.opensByConnection.get(connectionId),owned=this.sessionsByConnection.get(connectionId);if(this.sessionsByConnection.delete(connectionId),this.draining)return opens&&await Promise.all([...opens]),this.releasedConnections.delete(connectionId),[...owned?.keys()??[]];if(owned===void 0)return opens&&await Promise.all([...opens]),this.releasedConnections.delete(connectionId),[];let deferred=new Set;return await Promise.all([...owned].map(async([sessionId,count])=>{for(let attachment=0;attachment<count;attachment++){let live=this.registry.peek(sessionId),endsSession=live?.retainOnDisconnect!==!0&&(live?.attachments??0)<=1,session=live?.state==="open"?live.runtime?.session:void 0;if(endsSession&&live?.state==="open"&&live.worker?.snapshot?.streaming){deferred.add(sessionId);let unsubscribe=live.worker.subscribeSettled(()=>{unsubscribe(),this.releaseOwnedSession(sessionId).catch(cause=>{process.stderr.write(`senpi rpc deferred worker release ${sessionId} failed: ${String(cause)}
22
22
  `)})});continue}if(endsSession&&session?.isStreaming){deferred.add(sessionId);let released=!1,unsubscribe=session.subscribe(event=>{event.type!=="agent_settled"&&event.type!=="agent_idle"||released||(released=!0,unsubscribe(),this.releaseOwnedSession(sessionId).catch(cause=>{process.stderr.write(`senpi rpc deferred release for session ${sessionId} failed: ${String(cause)}
23
23
  `)}))});continue}await this.releaseOwnedSession(sessionId)}})),opens&&await Promise.all([...opens]),this.releasedConnections.delete(connectionId),[...deferred]}async releaseOwnedSession(sessionId){let live=this.registry.peek(sessionId),parks=live?.state==="open"&&live.retainOnDisconnect===!0&&live.attachments===1,claim=this.tryClaimClose(sessionId,{drainAttachments:!1,detach:!0});if(!claim)return;if(!claim.finalizer){this.writer.status.publish(sessionId,"detach","client"),parks&&live.runtime&&(live.lifecycleMutex=live.lifecycleMutex.then(()=>live.runtime?.emitAttachmentEvent("session_parked")),await live.lifecycleMutex),await this.finalizations.get(sessionId)?.promise;return}let binding=this.bindings.get(sessionId);binding?.cancelPendingExtensionUiRequests?.(),await this.finalizeClose(sessionId,binding)}claimClose(sessionId,options){let finalizer=!0,onRole=isFinalizer=>{finalizer=isFinalizer,isFinalizer&&!this.finalizations.has(sessionId)&&this.finalizations.set(sessionId,this.createFinalization())},entry=this.registry.beginClose(sessionId,onRole,{detach:options.detach});for(;options.drainAttachments&&entry.state==="open";)entry=this.registry.beginClose(sessionId,onRole);return{finalizer:finalizer&&entry.state==="closing"}}tryClaimClose(sessionId,options){try{return this.claimClose(sessionId,options)}catch{return}}async close(command){let response={id:command.id,type:"response",command:"close_session",success:!0,data:{}},owner=this.writer.currentConnection();if(owner!==void 0&&this.sessionsByConnection.get(owner)?.has(command.sessionId)!==!0)return error(command.id,"close_session",RPC_ERROR_UNKNOWN_SESSION);let reply=this.writer.reserveCloseResponse(command.sessionId,response);if(!reply)return;let claim;try{claim=this.claimClose(command.sessionId,{drainAttachments:!1})}catch(cause){return reply.release(),error(command.id,"close_session",this.code(cause))}try{if(owner!==void 0&&this.releaseOwnerAttachment(owner,command.sessionId),claim.finalizer){let entry=this.registry.peek(command.sessionId);this.handoverParkedDir!==void 0&&entry?.sessionPath!==void 0&&await clearHandoverParkedSession(this.handoverParkedDir,entry.sessionPath).catch(()=>{}),await this.finalizeClose(command.sessionId,this.bindings.get(command.sessionId),()=>reply.complete(!0,"client_close"))}else this.writer.status.publish(command.sessionId,"detach","client"),await this.finalizations.get(command.sessionId)?.promise,reply.complete(!1);return}finally{reply.release()}}releaseOwnerAttachment(owner,sessionId){this.writer.detachConnectionFromSession(owner,sessionId);let owned=this.sessionsByConnection.get(owner),count=owned?.get(sessionId);!owned||count===void 0||(count===1?owned.delete(sessionId):owned.set(sessionId,count-1),owned.size===0&&this.sessionsByConnection.delete(owner))}async finalizeClose(sessionId,binding,terminal){let finalization=this.finalizations.get(sessionId)??this.createFinalization();this.finalizations.set(sessionId,finalization);try{try{await binding?.dispose()}catch(cause){process.stderr.write(`senpi rpc binding dispose for session ${sessionId} failed: ${String(cause)}
24
24
  `)}this.bindings.delete(sessionId);try{await this.registry.closeMarked(sessionId)}catch(cause){process.stderr.write(`senpi rpc close for session ${sessionId} failed: ${String(cause)}
25
25
  `)}await this.registry.peek(sessionId)?.closeCompletion,terminal?.()}finally{finalization.resolve(),this.finalizations.delete(sessionId)}}createFinalization(){let resolveFinalization;return{promise:new Promise(resolve=>{resolveFinalization=resolve}),resolve:()=>resolveFinalization?.()}}detail(cause){return cause instanceof RpcSessionRegistryError?cause.detail:void 0}code(cause){return cause instanceof RpcSessionRegistryError?cause.code===RPC_ERROR_OPEN_FAILED?cause.message:cause.code:cause instanceof Error&&[RPC_ERROR_UNKNOWN_SESSION,RPC_ERROR_SESSION_CLOSING].includes(cause.message)?cause.message:!(cause instanceof Error)||!cause.message?RPC_ERROR_UNKNOWN_SESSION:cause.message.startsWith(`${RPC_ERROR_OPEN_FAILED}: `)?cause.message:`${RPC_ERROR_OPEN_FAILED}: ${cause.message}`}};import{isAbsolute as isAbsolute3}from"node:path";var SESSION_WORKER_LIMITS={workers:20,requests:64,controlRequests:4,controlBytes:1024*1024,requestBytes:16*1024*1024,outputBytes:16*1024*1024,reservations:64,openMs:3e4,controlMs:5e3},WORKER_CREDIT_CODES={granted:1,conflict:2,limit:3};function typedWorkerRefusal(cause){let message=cause instanceof Error?cause.message:String(cause);throw message.startsWith("open_failed: ")?new RpcSessionRegistryError("open_failed",message.slice(13)):cause}var RESERVATION_DENIAL_CODES={conflict:"session_path_in_use",limit:"session_reservation_limit"},SessionPathReservations=class{constructor(){this.owners=new Map}owner(path){return this.owners.get(path)}count(handle){let count=0;for(let owner of this.owners.values())owner===handle&&count++;return count}reserve(handle,path,live){let owner=this.owners.get(path);return owner?owner===handle?"granted":"conflict":this.count(handle)>=SESSION_WORKER_LIMITS.reservations&&(!live||(this.reconcile(handle,live),this.count(handle)>=SESSION_WORKER_LIMITS.reservations))?"limit":(this.owners.set(path,handle),"granted")}reconcile(handle,live){for(let[path,owner]of this.owners)owner!==handle||path===live.sessionPath||live.livePaths.includes(path)||this.owners.delete(path)}releaseAll(handle){for(let[path,owner]of this.owners)owner===handle&&this.owners.delete(path)}};import{fileURLToPath}from"node:url";import{Worker}from"node:worker_threads";var SessionWorkerRequests=class{constructor(send,timeout){this.pending=new Map,this.serial=0,this.closed=!1,this.send=send,this.timeout=timeout}remainingOpenMs(){let now=Date.now();return this.openingDeadline===void 0&&(this.openingDeadline=now+SESSION_WORKER_LIMITS.openMs),Math.max(0,this.openingDeadline-now)}get activeCount(){return this.pending.size}request(message){if(this.closed)return Promise.reject(new Error("session_closing"));let control=message.type==="command"&&"type"in message.command&&typeof message.command.type=="string"&&["abort","abort_bash","extension_ui_response","extension_ui_progress"].includes(message.command.type),bytes=Buffer.byteLength(JSON.stringify(message)),count=0,pendingBytes=0;for(let pending of this.pending.values())pending.control===control&&(count++,pendingBytes+=pending.bytes);let maxCount=control?SESSION_WORKER_LIMITS.controlRequests:SESSION_WORKER_LIMITS.requests,maxBytes=control?SESSION_WORKER_LIMITS.controlBytes:SESSION_WORKER_LIMITS.requestBytes;if(count>=maxCount||pendingBytes+bytes>maxBytes)return Promise.reject(new Error("session_worker_request_limit"));let request=++this.serial;return new Promise((resolve,reject)=>{let timer=message.type==="command"&&!control?void 0:setTimeout(this.timeout,control?SESSION_WORKER_LIMITS.controlMs:this.remainingOpenMs());this.pending.set(request,{resolve,reject,bytes,control,timer});try{this.send({...message,request})}catch(cause){this.pending.delete(request),clearTimeout(timer),reject(cause instanceof Error?cause:new Error(String(cause)))}})}receive(message){let pending=this.pending.get(message.request);pending&&(clearTimeout(pending.timer),this.pending.delete(message.request),message.type==="result"&&message.error?pending.reject(new Error(message.error)):pending.resolve(message))}close(error2){this.closed=!0;for(let pending of this.pending.values())clearTimeout(pending.timer),pending.reject(error2);this.pending.clear()}};function acknowledgeGrant(signal,grant){let state=new Int32Array(signal);Atomics.store(state,0,WORKER_CREDIT_CODES[grant]),Atomics.notify(state,0)}function acknowledge(signal,granted){acknowledgeGrant(signal,granted?"granted":"conflict")}var compiledWorkerEntry=typeof SENPI_RPC_SESSION_WORKER_ENTRY=="string"?SENPI_RPC_SESSION_WORKER_ENTRY:"./src/modes/rpc/session-worker.ts",SessionWorkerClient=class{constructor(callbacks){this.webviewBroker=createWebViewBroker(),this.worker=new Worker(isBunBinary?fileURLToPath(new URL(compiledWorkerEntry,import.meta.url)).replaceAll("\\","/"):new URL(import.meta.url.endsWith(".ts")?"./session-worker.ts":"./session-worker.js",import.meta.url),{workerData:{hostProcessStartedAtMs:ownProcessStartedAtMs(),...this.webviewBroker?{webviewBroker:this.webviewBroker.port}:{}},...this.webviewBroker?{transferList:[this.webviewBroker.port]}:{}}),this.bindingReady=!1,this.requests=new SessionWorkerRequests(message=>this.worker.postMessage(message),()=>this.fail("session_worker_request_timeout")),this.stopped=!1,this.options={},this.listeners=new Set,this.cancelUiPending=!1,this.callbacks=callbacks,this.exited=new Promise((resolve,reject)=>{this.worker.once("exit",()=>{!this.stopped&&!this.closeTimer&&this.fail("session_worker_exited"),this.stopped=!0,this.closeTimer&&clearTimeout(this.closeTimer),this.requests.close(new Error("session_worker_exited")),this.webviewBroker?.dispose(),this.listeners.clear();let released=callbacks.exit();released?released.then(()=>{this.publishTerminalFailure(),resolve()},reject):(this.publishTerminalFailure(),resolve())})}),this.worker.on("message",message=>this.receive(message)),this.worker.on("error",error2=>this.fail(error2 instanceof Error?error2.message:String(error2)))}async prepare(configuration,profile){let result=await this.request({type:"prepare",configuration,profile});if(result.type!=="prepared")throw new Error("Invalid worker prepare response");return result.sessionPath}async setPromptSurface(surface){if((await this.request({type:"prompt_surface",surface})).type!=="result")throw new Error("Invalid worker prompt_surface response")}async setBrowserEngine(engine){if((await this.request({type:"browser_engine",engine})).type!=="result")throw new Error("Invalid worker browser_engine response")}async setPermissionPreset(preset){if((await this.request({type:"permission_preset",preset})).type!=="result")throw new Error("Invalid worker permission_preset response")}async commit(){let result=await this.request({type:"commit"});if(result.type!=="ready")throw new Error("Invalid worker commit response");return this.snapshot=result.snapshot,result.snapshot}async bind(sessionId,writer,requestClose,options){return this.sessionId=sessionId,this.writer=writer,this.requestClose=requestClose,this.options=options,await this.request({type:"bind",sessionId,capabilities:options.capabilities??[],connection:writer.currentConnection()}),{handle:async command=>{await this.request({type:"command",command,connection:writer.currentConnection()})},cancelPendingExtensionUiRequests:()=>this.post({type:"cancel_ui"}),dispose:async()=>{this.post({type:"cancel_ui"})}}}get busy(){return this.requests.activeCount>0||this.snapshot?.busy===!0}get handoffBusy(){return this.requests.activeCount>0||(this.snapshot?.handoffBusy??this.snapshot?.busy)===!0}subscribeSettled(listener){return this.listeners.add(listener),()=>this.listeners.delete(listener)}close(graceMs){return this.stopped||this.closeTimer?this.exited:(this.post({type:"close"}),this.closeTimer=setTimeout(()=>this.quarantine(),graceMs),this.exited)}quarantine(){this.stopped=!0,this.requests.close(new Error("session_closing")),this.worker.terminate()}request(message){return this.requests.request(message)}post(message){if(!this.stopped){if(message.type==="cancel_ui"){if(this.cancelUiPending)return;this.cancelUiPending=!0}this.worker.postMessage(message)}}receive(message){if(this.stopped){"signal"in message&&acknowledge(message.signal,!1);return}switch(message.type){case"prepared":case"ready":case"result":{this.requests.receive(message),this.snapshot&&Promise.resolve(this.callbacks.reconcile(this.snapshot.liveSessionPaths)).catch(()=>this.fail("session_claim_reconcile_failed"));return}case"reserve":Promise.resolve(this.callbacks.reserve(message.path)).then(grant=>acknowledgeGrant(message.signal,this.stopped?"conflict":grant),()=>acknowledgeGrant(message.signal,"conflict"));return;case"snapshot":this.snapshot=message.snapshot,Promise.resolve(this.callbacks.reconcile(message.snapshot.liveSessionPaths)).then(()=>{if(acknowledge(message.signal,!this.stopped),message.settled)for(let listener of[...this.listeners])listener()},()=>{acknowledge(message.signal,!1),this.fail("session_claim_reconcile_failed")});return;case"control_done":this.cancelUiPending=!1;return;case"output":{let writer=this.writer,sessionId=this.sessionId;if(!writer||!sessionId||this.stopped){acknowledge(message.signal,!1);return}message.snapshot?this.snapshot=message.snapshot:this.snapshot&&(this.snapshot={...this.snapshot,...message.activity,state:{...this.snapshot.state,isStreaming:message.activity.streaming}});let enqueue=()=>writer.enqueue(sessionId,message.record)?writer.waitForSessionBackpressure(sessionId):(acknowledge(message.signal,!1),this.fail("session_output_overflow_or_closed"),Promise.reject(new Error("session_output_overflow_or_closed")));Promise.resolve(message.snapshot?this.callbacks.reconcile(message.snapshot.liveSessionPaths):void 0).then(()=>message.connection===void 0?enqueue():writer.withConnection(message.connection,enqueue)).then(()=>acknowledge(message.signal,!0),cause=>{acknowledge(message.signal,!1),this.fail(cause instanceof Error?cause.message:String(cause))});return}case"capabilities":this.options.clientInfo?.setCapabilities(message.connection,message.capabilities),acknowledge(message.signal,!0);return;case"loaded_surfaces":{let writer=this.writer,sessionId=this.sessionId;if(!writer||!sessionId||this.stopped){acknowledge(message.signal,!1);return}writer.publishLoadedSurfacesChanged(sessionId,message.previous,message.digest),acknowledge(message.signal,!0);return}case"request_close":this.requestClose?.();return;case"failure":this.fail(message.error);return}}fail(error2){this.stopped||(this.callbacks.failure(error2),this.terminalFailure=error2,this.writer&&this.sessionId&&this.writer.enqueue(this.sessionId,{type:"session_error",error:error2}),this.quarantine())}publishTerminalFailure(){let error2=this.terminalFailure,writer=this.writer,sessionId=this.sessionId;error2===void 0||!writer||!sessionId||(this.terminalFailure=void 0,writer.closeSession(sessionId,{type:"response",command:"close_session",success:!1,error:error2},"error"))}};var WorkerSessionClaims=class{constructor(reservations){this.paths=new Map,this.releases=new Set,this.closed=!1,this.reservations=reservations}async claim(path,attached=!0){if(this.closed)throw new RpcSessionRegistryError("session_closing");if(!this.reservations)return;let previous=this.paths.get(path);if(previous)return previous.ownership;let record={ownership:this.reservations.claim(path,attached),attached};this.paths.set(path,record);let owner=await record.ownership;return owner&&this.paths.get(path)===record&&this.paths.delete(path),owner}setAttached(attached){for(let[path,record]of this.paths)record.attached!==attached&&(record.attached=attached,record.ownership.then(owner=>{!owner&&this.paths.get(path)===record&&this.reservations?.setAttached(path,record.attached)}))}reconcile(livePaths,attached){let live=new Set(livePaths);for(let path of this.paths.keys())live.has(path)||this.release(path);this.setAttached(attached)}release(path){let record=this.paths.get(path);if(!record)return Promise.resolve();this.paths.delete(path);let removal=record.ownership.then(async owner=>{owner||await this.reservations?.release(path)});return this.releases.add(removal),removal.then(()=>this.releases.delete(removal),()=>this.releases.delete(removal)),removal}async close(){this.closed=!0,await Promise.all([...this.paths.keys()].map(path=>this.release(path)).concat([...this.releases]))}};var WorkerSessionRegistry=class{constructor(options){this.entries=new Map,this.reservations=new SessionPathReservations,this.claims=new Map,this.serial=0,this.options=options,this.closeGraceMs=options.closeGraceMs,this.now=options.now,this.createWorker=options.createWorker??(callbacks=>new SessionWorkerClient(callbacks))}get size(){return this.entries.size}holderPids(observedStarts){return this.options.pathReservations?.holderPids?.(observedStarts)??Promise.resolve([])}async openSession(profile,options){if(!isAbsolute3(profile.cwd)||profile.sessionPath!==void 0&&!isAbsolute3(profile.sessionPath))throw new RpcSessionRegistryError("invalid_path");let requestedDurableId=profile.durableSessionId;if(requestedDurableId!==void 0){try{assertValidSessionId(requestedDurableId)}catch(cause){throw new RpcSessionRegistryError("invalid_session_id",String(cause))}let requestedKey=profile.sessionPath?this.knownReservationKey(profile.sessionPath):void 0;for(let entry2 of this.entries.values())if(entry2.state!=="closed"&&entry2.durableSessionId===requestedDurableId&&!(requestedKey!==void 0&&entry2.reservationKey===requestedKey))throw new RpcSessionRegistryError("session_id_in_use")}if(profile.sessionPath){let key=this.knownReservationKey(profile.sessionPath),owner=key?this.reservations.owner(key):void 0;if(key&&owner)return this.attach(owner,key,options,profile)}if(options?.attachOnly)throw new RpcSessionRegistryError("session_not_held",void 0,{reason:"session_not_held",action:"rediscover_holder"});if(this.size>=SESSION_WORKER_LIMITS.workers)throw new Error("too_many_sessions");let handle=`rpc-${++this.serial}`,claims=new WorkerSessionClaims(this.options.pathReservations);this.claims.set(handle,claims);let storedProfile=frozenProfile(profile),entry={state:"opening",scope:new ProviderScope,profile:storedProfile,...sessionIdentity(storedProfile),cwd:profile.cwd,attachments:1,retainOnDisconnect:options?.retainOnDisconnect===!0,lastCommandAt:this.now(),lifecycleMutex:Promise.resolve(),...requestedDurableId!==void 0?{durableSessionId:requestedDurableId}:{}},workerFailure,worker=this.createWorker({reserve:path=>this.reserve(handle,path),reconcile:livePaths=>this.reconcile(handle,livePaths),exit:()=>{if(this.entries.get(handle)!==entry)return;let finish=()=>{this.entries.get(handle)===entry&&(entry.state="closed",this.entries.delete(handle),this.claims.delete(handle),this.reservations.releaseAll(handle),entry.closeResolve?.())};return releaseWithinGrace({closeGraceMs:this.closeGraceMs,releaseReservation:()=>claims.close()},handle,entry.reservationKey??handle).then(finish)},failure:error2=>{workerFailure=error2,entry.state="quarantined",process.stderr.write(`senpi rpc session ${handle} quarantined: ${error2}
26
- `)}});entry.worker=worker,this.entries.set(handle,entry);try{let path=await worker.prepare(this.options.configuration,profile).catch(typedWorkerRefusal),owner=this.reservations.owner(path);if(owner){let attached=await this.attach(owner,path,options,profile);return entry.state="quarantined",worker.quarantine(),attached}let predecessor=await claims.claim(path);if(predecessor)throw new RpcSessionRegistryError("session_path_in_use",void 0,{owner:predecessor,retry_after_ms:SESSION_PATH_RETRY_AFTER_MS});let grant=await this.reserve(handle,path);if(grant!=="granted")throw new RpcSessionRegistryError(RESERVATION_DENIAL_CODES[grant]);entry.reservationKey=path,entry.requestedPathKey=profile.sessionPath?path:void 0,entry.sessionPath=path;let snapshot=await worker.commit();if(entry.state!=="opening")throw workerFailure===void 0?new RpcSessionRegistryError("session_closing"):new RpcSessionRegistryError("open_failed",workerFailure.replace(/^open_failed: /,""));return entry.durableSessionId=snapshot.state.sessionId,entry.cwd=snapshot.state.cwd,entry.state="open",this.openResult(handle,entry)}catch(cause){throw entry.state="quarantined",worker.quarantine(),cause}}peek(handle){return this.entries.get(handle)}getForCommand(handle,command){let entry=this.entries.get(handle);if(!entry)throw new RpcSessionRegistryError("unknown_session");if(entry.state==="quarantined"||entry.state==="closing"&&!["abort","abort_bash","extension_ui_response","extension_ui_progress"].includes(command))throw new RpcSessionRegistryError("session_closing");if(entry.state!=="open"&&entry.state!=="closing")throw new RpcSessionRegistryError("unknown_session");return(entry.attachments>0||refreshesSessionActivity(command))&&(entry.lastCommandAt=this.now()),entry}beginClose(handle,onRole,options){let entry=this.entries.get(handle);if(!entry)throw new RpcSessionRegistryError("unknown_session");if(entry.state==="closing"||entry.state==="quarantined")return onRole?.(!1),entry;if(entry.state!=="open"&&entry.state!=="opening")throw new RpcSessionRegistryError("unknown_session");return entry.attachments--,entry.attachments>0?entry:options?.detach&&entry.retainOnDisconnect?(entry.attachments=0,entry.detachedAt??=this.now(),entry.worker?.busy||this.claims.get(handle)?.setAttached(!1),entry):(entry.state="closing",entry.closeCompletion=new Promise(resolve=>{entry.closeResolve=resolve}),onRole?.(!0),entry)}close(handle){return this.beginClose(handle).state==="closing"?this.closeMarked(handle):Promise.resolve()}async closeMarked(handle){let entry=this.entries.get(handle);if(entry?.state!=="closing"||!entry.worker)throw new RpcSessionRegistryError("unknown_session");if(entry.closeStarted)return entry.closeCompletion;entry.closeStarted=!0;let timer;await Promise.race([entry.worker.close(this.closeGraceMs),new Promise(resolve=>{timer=setTimeout(()=>{entry.state!=="closed"&&(entry.state="quarantined"),resolve()},this.closeGraceMs)})]),timer&&clearTimeout(timer)}list(){let now=this.now();return[...this.entries].map(([sessionId,entry])=>{let state=entry.worker?.snapshot?.state;return{sessionId,durableSessionId:state?.sessionId??entry.durableSessionId,sessionPath:state?.sessionFile??entry.sessionPath,cwd:state?.cwd??entry.cwd,name:state?.sessionName,kind:entry.kind,context:publishedSessionContext(entry.context,entry.contextOverlay),attachments:Math.max(0,entry.attachments),status:entry.state==="quarantined"?"closing":entry.state,idleMs:Math.max(0,now-entry.lastCommandAt),tool_child:{state:"none"}}})}knownReservationKey(path){if(this.reservations.owner(path))return path;for(let entry of this.entries.values()){if(entry.profile.sessionPath===path&&entry.requestedPathKey&&this.reservations.owner(entry.requestedPathKey))return entry.requestedPathKey;let snapshot=entry.worker?.snapshot;if(snapshot?.state.sessionFile===path)return snapshot.sessionPath}}async attach(owner,path,options,requested={cwd:""}){let{promptSurface,browserEngine,permissionPreset}=requested,entry=this.entries.get(owner);if(entry?.state!=="open"||!entry.worker?.bindingReady||entry.worker.snapshot?.sessionPath!==path)throw new RpcSessionRegistryError("session_path_in_use");promptSurface!==void 0&&promptSurface!==entry.profile.promptSurface&&(entry.profile=frozenProfile({...entry.profile,promptSurface}),await entry.worker.setPromptSurface(promptSurface)),browserEngine!==void 0&&browserEngine!==entry.profile.browserEngine&&(entry.profile=frozenProfile({...entry.profile,browserEngine}),await entry.worker.setBrowserEngine(browserEngine)),permissionPreset!==void 0&&(entry.profile=frozenProfile({...entry.profile,permissionPreset}),await entry.worker.setPermissionPreset(permissionPreset));let result=this.openResult(owner,entry);return entry.attachments++,this.claims.get(owner)?.setAttached(!0),options?.retainOnDisconnect&&(entry.retainOnDisconnect=!0),entry.lastCommandAt=this.now(),{...result,attached:!0}}reservationCount(handle){return this.reservations.count(handle)}async reserve(handle,path){let entry=this.entries.get(handle);if(!entry)return"conflict";if(this.reservations.owner(path)===handle)return"granted";if(entry.state!=="opening"&&entry.state!=="open")return"conflict";let grant=this.reservations.reserve(handle,path,this.liveWorkerPaths(entry));if(grant!=="granted")return grant;if(await this.claims.get(handle)?.claim(path,entry.attachments>0||entry.worker?.busy===!0)||this.entries.get(handle)!==entry||entry.state!=="opening"&&entry.state!=="open"){let live=this.liveWorkerPaths(entry);return this.reservations.reconcile(handle,live??{livePaths:[],sessionPath:entry.reservationKey}),"conflict"}return"granted"}async reconcile(handle,livePaths){let entry=this.entries.get(handle);if(entry?.state!=="open")return;let sessionPath=entry.worker?.snapshot?.sessionPath,attached=entry.attachments>0||entry.worker?.busy===!0;if(sessionPath){if(await this.claims.get(handle)?.claim(sessionPath,attached))throw new RpcSessionRegistryError("session_path_in_use");if(this.entries.get(handle)!==entry||entry.state!=="open")return}this.reservations.reconcile(handle,{livePaths,sessionPath}),this.claims.get(handle)?.reconcile(sessionPath?[...livePaths,sessionPath]:livePaths,attached),sessionPath&&(entry.reservationKey=sessionPath,entry.sessionPath=sessionPath)}liveWorkerPaths(entry){let snapshot=entry.state==="open"?entry.worker?.snapshot:void 0;if(snapshot)return{livePaths:snapshot.liveSessionPaths,sessionPath:snapshot.sessionPath}}openResult(handle,entry){let state=entry.worker?.snapshot?.state;if(!state)throw new RpcSessionRegistryError("open_failed");return{sessionId:handle,durableSessionId:state.sessionId,sessionPath:state.sessionFile}}};var WINDOWS_SHUTDOWN_HARD_EXIT_MS=2e3;async function runMultiSessionHost(options){return runAsHostGenerationProcess(()=>options.listen===void 0||options.listen==="stdio://"?runStdioHost(options):runSocketHost(options,resolveSocketPath(options.listen,options.agentDir)))}function createHostCore(options,writer,capabilities=parseClientCapabilities(envValue("RPC_CLIENT_CAPABILITIES")),idle={},hostContext,hooks={}){let policy=resolveHostIdlePolicy(process.env,idle),endpointSocket=publicEndpointSocket(options),pathReservations=createEndpointReservations({agentDir:options.agentDir,socket:listenSocketPath(options),instanceId:hostInstanceId(),publicSocket:hostContext?.host_socket,onFailure:hostLog}),registry=options.workerConfiguration?new WorkerSessionRegistry({configuration:options.workerConfiguration,now:policy.now,closeGraceMs:idle.closeGraceMs??parseIdleExitMs(process.env[RPC_CLOSE_GRACE_MS_ENV])??1e4,pathReservations}):new RpcSessionRegistry({agentDir:options.agentDir,createRuntime:options.createRuntime,mcpRegistry:new HostMcpRegistry,now:policy.now,closeGraceMs:idle.closeGraceMs??parseIdleExitMs(process.env[RPC_CLOSE_GRACE_MS_ENV])??1e4,...hooks.onSessionCountChange?{onSizeChange:hooks.onSessionCountChange}:{},pathReservations}),router=new SessionCommandRouter(registry,writer,hostContext?{...options,hostContext}:options,options.createBinding,{capabilities},{now:policy.now,idleEvictionMs:policy.idleEvictionMs,emptyExitMs:policy.emptyExitMs,onEmptyExit:idle.onEmptyExit,onHandoffParked:idle.onHandoffParked,...endpointSocket===void 0?{}:{handoverParkedDir:createHostDaemonPaths({socket:endpointSocket,agentDir:options.agentDir}).dir},canExitWhenEmpty:idle.canExitWhenEmpty});endpointSocket!==void 0&&reopenHandoverParkedSessions(async entry=>{let refused2=await router.reopenParked(entry);if(refused2?.success!==!1)return;let detail=typeof refused2.errorData=="object"&&refused2.errorData!==null&&!Array.isArray(refused2.errorData)?Object.fromEntries(Object.entries(refused2.errorData)):void 0;throw refused2.error==="session_path_in_use"?new RpcSessionRegistryError("session_path_in_use",void 0,detail):new RpcSessionRegistryError("open_failed",refused2.error)},options.agentDir,endpointSocket,{hostInstance:hostInstanceId(),hostSocket:endpointSocket,...hooks.shouldReopenParked!==void 0?{shouldReopen:hooks.shouldReopenParked}:{}}).catch(cause=>{process.stderr.write(`senpi rpc successor reopen parked set failed: ${String(cause)}
26
+ `)}});entry.worker=worker,this.entries.set(handle,entry);try{let path=await worker.prepare(this.options.configuration,profile).catch(typedWorkerRefusal),owner=this.reservations.owner(path);if(owner){let attached=await this.attach(owner,path,options,profile);return entry.state="quarantined",worker.quarantine(),attached}let predecessor=await claims.claim(path);if(predecessor)throw new RpcSessionRegistryError("session_path_in_use",void 0,{owner:predecessor,retry_after_ms:SESSION_PATH_RETRY_AFTER_MS});let grant=await this.reserve(handle,path);if(grant!=="granted")throw new RpcSessionRegistryError(RESERVATION_DENIAL_CODES[grant]);entry.reservationKey=path,entry.requestedPathKey=profile.sessionPath?path:void 0,entry.sessionPath=path;let snapshot=await worker.commit();if(entry.state!=="opening")throw workerFailure===void 0?new RpcSessionRegistryError("session_closing"):new RpcSessionRegistryError("open_failed",workerFailure.replace(/^open_failed: /,""));return entry.durableSessionId=snapshot.state.sessionId,entry.cwd=snapshot.state.cwd,entry.state="open",this.openResult(handle,entry)}catch(cause){throw entry.state="quarantined",worker.quarantine(),cause}}peek(handle){return this.entries.get(handle)}getForCommand(handle,command){let entry=this.entries.get(handle);if(!entry)throw new RpcSessionRegistryError("unknown_session");if(entry.state==="quarantined"||entry.state==="closing"&&!["abort","abort_bash","extension_ui_response","extension_ui_progress"].includes(command))throw new RpcSessionRegistryError("session_closing");if(entry.state!=="open"&&entry.state!=="closing")throw new RpcSessionRegistryError("unknown_session");return(entry.attachments>0||refreshesSessionActivity(command))&&(entry.lastCommandAt=this.now()),entry}beginClose(handle,onRole,options){let entry=this.entries.get(handle);if(!entry)throw new RpcSessionRegistryError("unknown_session");if(entry.state==="closing"||entry.state==="quarantined")return onRole?.(!1),entry;if(entry.state!=="open"&&entry.state!=="opening")throw new RpcSessionRegistryError("unknown_session");return entry.attachments--,entry.attachments>0?entry:options?.detach&&entry.retainOnDisconnect?(entry.attachments=0,entry.detachedAt??=this.now(),entry.worker?.busy||this.claims.get(handle)?.setAttached(!1),entry):(entry.state="closing",entry.closeCompletion=new Promise(resolve=>{entry.closeResolve=resolve}),onRole?.(!0),entry)}close(handle){return this.beginClose(handle).state==="closing"?this.closeMarked(handle):Promise.resolve()}async closeMarked(handle){let entry=this.entries.get(handle);if(entry?.state!=="closing"||!entry.worker)throw new RpcSessionRegistryError("unknown_session");if(entry.closeStarted)return entry.closeCompletion;entry.closeStarted=!0;let timer;await Promise.race([entry.worker.close(this.closeGraceMs),new Promise(resolve=>{timer=setTimeout(()=>{entry.state!=="closed"&&(entry.state="quarantined"),resolve()},this.closeGraceMs)})]),timer&&clearTimeout(timer)}list(){let now=this.now();return[...this.entries].map(([sessionId,entry])=>{let state=entry.worker?.snapshot?.state;return{sessionId,durableSessionId:state?.sessionId??entry.durableSessionId,sessionPath:state?.sessionFile??entry.sessionPath,cwd:state?.cwd??entry.cwd,name:state?.sessionName,kind:entry.kind,context:publishedSessionContext(entry.context,entry.contextOverlay),attachments:Math.max(0,entry.attachments),status:entry.state==="quarantined"?"closing":entry.state,idleMs:Math.max(0,now-entry.lastCommandAt),tool_child:{state:"none"}}})}knownReservationKey(path){if(this.reservations.owner(path))return path;for(let entry of this.entries.values()){if(entry.profile.sessionPath===path&&entry.requestedPathKey&&this.reservations.owner(entry.requestedPathKey))return entry.requestedPathKey;let snapshot=entry.worker?.snapshot;if(snapshot?.state.sessionFile===path)return snapshot.sessionPath}}async attach(owner,path,options,requested={cwd:""}){let{promptSurface,browserEngine,permissionPreset}=requested,entry=this.entries.get(owner);if(entry?.state!=="open"||!entry.worker?.bindingReady||entry.worker.snapshot?.sessionPath!==path)throw new RpcSessionRegistryError("session_path_in_use");promptSurface!==void 0&&promptSurface!==entry.profile.promptSurface&&(entry.profile=frozenProfile({...entry.profile,promptSurface}),await entry.worker.setPromptSurface(promptSurface)),browserEngine!==void 0&&browserEngine!==entry.profile.browserEngine&&(entry.profile=frozenProfile({...entry.profile,browserEngine}),await entry.worker.setBrowserEngine(browserEngine)),permissionPreset!==void 0&&(entry.profile=frozenProfile({...entry.profile,permissionPreset}),await entry.worker.setPermissionPreset(permissionPreset));let result=this.openResult(owner,entry);return entry.attachments++,this.claims.get(owner)?.setAttached(!0),options?.retainOnDisconnect&&(entry.retainOnDisconnect=!0),entry.lastCommandAt=this.now(),{...result,attached:!0}}reservationCount(handle){return this.reservations.count(handle)}async reserve(handle,path){let entry=this.entries.get(handle);if(!entry)return"conflict";if(this.reservations.owner(path)===handle)return"granted";if(entry.state!=="opening"&&entry.state!=="open")return"conflict";let grant=this.reservations.reserve(handle,path,this.liveWorkerPaths(entry));if(grant!=="granted")return grant;if(await this.claims.get(handle)?.claim(path,entry.attachments>0||entry.worker?.busy===!0)||this.entries.get(handle)!==entry||entry.state!=="opening"&&entry.state!=="open"){let live=this.liveWorkerPaths(entry);return this.reservations.reconcile(handle,live??{livePaths:[],sessionPath:entry.reservationKey}),"conflict"}return"granted"}async reconcile(handle,livePaths){let entry=this.entries.get(handle);if(entry?.state!=="open")return;let sessionPath=entry.worker?.snapshot?.sessionPath,attached=entry.attachments>0||entry.worker?.busy===!0;if(sessionPath){if(await this.claims.get(handle)?.claim(sessionPath,attached))throw new RpcSessionRegistryError("session_path_in_use");if(this.entries.get(handle)!==entry||entry.state!=="open")return}this.reservations.reconcile(handle,{livePaths,sessionPath}),this.claims.get(handle)?.reconcile(sessionPath?[...livePaths,sessionPath]:livePaths,attached),sessionPath&&(entry.reservationKey=sessionPath,entry.sessionPath=sessionPath)}liveWorkerPaths(entry){let snapshot=entry.state==="open"?entry.worker?.snapshot:void 0;if(snapshot)return{livePaths:snapshot.liveSessionPaths,sessionPath:snapshot.sessionPath}}openResult(handle,entry){let state=entry.worker?.snapshot?.state;if(!state)throw new RpcSessionRegistryError("open_failed");return{sessionId:handle,durableSessionId:state.sessionId,sessionPath:state.sessionFile}}};var WINDOWS_SHUTDOWN_HARD_EXIT_MS=2e3,WINDOWS_SHUTDOWN_DISPOSE_BOUND_MS=1e4;async function runMultiSessionHost(options){return runAsHostGenerationProcess(()=>options.listen===void 0||options.listen==="stdio://"?runStdioHost(options):runSocketHost(options,resolveSocketPath(options.listen,options.agentDir)))}function createHostCore(options,writer,capabilities=parseClientCapabilities(envValue("RPC_CLIENT_CAPABILITIES")),idle={},hostContext,hooks={}){let policy=resolveHostIdlePolicy(process.env,idle),endpointSocket=publicEndpointSocket(options),pathReservations=createEndpointReservations({agentDir:options.agentDir,socket:listenSocketPath(options),instanceId:hostInstanceId(),publicSocket:hostContext?.host_socket,onFailure:hostLog}),registry=options.workerConfiguration?new WorkerSessionRegistry({configuration:options.workerConfiguration,now:policy.now,closeGraceMs:idle.closeGraceMs??parseIdleExitMs(process.env[RPC_CLOSE_GRACE_MS_ENV])??1e4,pathReservations}):new RpcSessionRegistry({agentDir:options.agentDir,createRuntime:options.createRuntime,mcpRegistry:new HostMcpRegistry,now:policy.now,closeGraceMs:idle.closeGraceMs??parseIdleExitMs(process.env[RPC_CLOSE_GRACE_MS_ENV])??1e4,...hooks.onSessionCountChange?{onSizeChange:hooks.onSessionCountChange}:{},pathReservations}),router=new SessionCommandRouter(registry,writer,hostContext?{...options,hostContext}:options,options.createBinding,{capabilities},{now:policy.now,idleEvictionMs:policy.idleEvictionMs,emptyExitMs:policy.emptyExitMs,onEmptyExit:idle.onEmptyExit,onHandoffParked:idle.onHandoffParked,...endpointSocket===void 0?{}:{handoverParkedDir:createHostDaemonPaths({socket:endpointSocket,agentDir:options.agentDir}).dir},canExitWhenEmpty:idle.canExitWhenEmpty});endpointSocket!==void 0&&reopenHandoverParkedSessions(async entry=>{let refused2=await router.reopenParked(entry);if(refused2?.success!==!1)return;let detail=typeof refused2.errorData=="object"&&refused2.errorData!==null&&!Array.isArray(refused2.errorData)?Object.fromEntries(Object.entries(refused2.errorData)):void 0;throw refused2.error==="session_path_in_use"?new RpcSessionRegistryError("session_path_in_use",void 0,detail):new RpcSessionRegistryError("open_failed",refused2.error)},options.agentDir,endpointSocket,{hostInstance:hostInstanceId(),hostSocket:endpointSocket,...hooks.shouldReopenParked!==void 0?{shouldReopen:hooks.shouldReopenParked}:{}}).catch(cause=>{process.stderr.write(`senpi rpc successor reopen parked set failed: ${String(cause)}
27
27
  `)});let gate=new HostCoreGate(registry,command=>router.handle(command),hooks);return{router,handle:async line=>{let parsed;try{parsed=JSON.parse(line)}catch(cause){await writer.enqueueControl(parseError(`Failed to parse command: ${errorMessage(cause)}`));return}if(await gate.intercept(parsed,answer2=>writer.enqueueControl(answer2)))return;let shapeError=rpcCommandShapeError(parsed);if(shapeError){await writer.enqueueControl(parseError(shapeError));return}let response=await gate.dispatch(parsed);response&&await writer.enqueueControl(response)},handover:gate.handover,handoverAnswered:()=>gate.answered()}}async function runStdioHost(options){takeOverStdout();let sink={writeRaw:writeRawStdout,waitForBackpressure:waitForRawStdoutBackpressure},writer=new SessionEventWriter(sink.writeRaw,sink.waitForBackpressure),runtimeBuildId=await startupRuntimeBuildId(),trim=createZeroSessionTrim(writer,()=>router.sessionCount),{router,handle}=createHostCore(options,writer,void 0,{onEmptyExit:()=>{shutdown(0)}},void 0,{...runtimeBuildId===void 0?{}:{runtimeBuildId},onSessionCountChange:size=>trim.observe(size)}),observers=startHostObservers(router,writer,{trim}),shuttingDown=!1,shutdown=async(exitCode=0)=>{shuttingDown&&process.exit(exitCode),shuttingDown=!0,observers.stop(),detach(),await router.dispose(),await writer.flush(),await flushRawStdout(),process.exit(exitCode)},onEnd=()=>{shutdown()};process.stdin.on("end",onEnd);let reportInputFailure=cause=>{process.stderr.write(`senpi rpc stdio request failed: ${errorMessage(cause)}
28
28
  `)},detachReader=attachJsonlLineReader(process.stdin,line=>{handle(line).catch(reportInputFailure)},{maxLineLength:MAX_RPC_LINE_CHARACTERS,onOversizedLine:()=>{writer.enqueueControl(parseError(oversizedLineError())).catch(reportInputFailure)}}),detach=()=>{detachReader(),process.stdin.off("end",onEnd)};return registerShutdownSignals(shutdown),new Promise(()=>{})}async function runSocketHost(options,socketPath){await prepareSocketPath(socketPath);let writer=new SessionEventWriter(()=>{}),connections=new Map,occupancy=new ClientOccupancy(()=>{},hostInstanceId()),draining=!1,handoffAnnounced=!1,hostContext=hostSessionContext(socketPath),runtimeBuildId=await startupRuntimeBuildId(),expected=process.env[EXPECTED_RUNTIME_BUILD_ID_ENV];expected!==void 0&&expected!==runtimeBuildId&&(hostLog(`runtime ${runtimeBuildId??"unreadable"} is not the handover target ${expected}; exiting`),process.exit(1));let canHandOver=runtimeBuildId!==void 0&&process.platform!=="win32",trim=createZeroSessionTrim(writer,()=>router.sessionCount),{router,handle,handover,handoverAnswered}=createHostCore(options,writer,[...parseClientCapabilities(envValue("RPC_CLIENT_CAPABILITIES")),GENERATION_HANDOFF_CAPABILITY,...canHandOver?[RUNTIME_IDENTITY_HANDOVER_CAPABILITY]:[]],{onEmptyExit:()=>{shutdown(0)},canExitWhenEmpty:()=>draining||occupancy.attachedCount===0&&occupancy.unclassifiedCount===0,onHandoffParked:async ids=>{await Promise.all(ids.map(async id=>{await writer.flushConnection(id),connections.get(id)?.close()}))}},hostContext,{onSessionCountChange:size=>trim.observe(size),shouldReopenParked:()=>!draining,...runtimeBuildId!==void 0&&{runtimeBuildId},...canHandOver&&{handover:{identity:()=>({instanceId:hostInstanceId(),generation:hostGeneration(process.env),runtimeBuildId}),perform:request=>performIdleHandover({request,socket:readHostWatchdogConfigFromBrandEnv()?.publicSocket??socketPath,agentDir:options.agentDir}),log:hostLog}}}),observers=startHostObservers(router,writer,{trim,onIdlePressure:({footprintMb,measure,rssMb})=>{hostLog(`memory pressure with no sessions: footprintMb=${footprintMb} (${measure}) rssMb=${rssMb}`),endpointSuperseded().then(superseded=>{superseded&&drainForHandoff()},noop)}}),nextConnection=0,shuttingDown=!1,secret=process.platform==="win32"?await ensureSocketSecret(process.env[SOCKET_SECRET_FILE_ENV]??socketSecretPath(socketPath)):void 0,watchdogConfig=readHostWatchdogConfigFromBrandEnv(),crashCleanupPaths=[...watchdogConfig?.cleanupPaths??[]],supervisorPublicSocketPath=process.platform==="win32"||socketPath.startsWith("\0")?void 0:watchdogConfig?.publicSocket,supervisorPublicOwnerFile=supervisorPublicSocketPath&&watchdogConfig?.scratchDir?join2(watchdogConfig.scratchDir,PUBLIC_SOCKET_IDENTITY_FILE):void 0,boundIdentity,supervisorPublicIdentity,server=createServer(socket=>{let accept=()=>{if(draining||shuttingDown){socket.destroy();return}let id=`socket-${++nextConnection}`,sink=socketSink(socket);writer.registerConnection(id,sink),occupancy.admit(socket);let detachReader=attachJsonlLineReader(socket,line=>{writer.withConnection(id,()=>handle(line)).catch(cause=>{process.stderr.write(`senpi rpc connection ${id} failed: ${errorMessage(cause)}
29
29
  `)})},{maxLineLength:MAX_RPC_LINE_CHARACTERS,onOversizedLine:()=>{writer.withConnection(id,()=>writer.enqueueControl(parseError(oversizedLineError()))).catch(cause=>process.stderr.write(`senpi rpc connection ${id} failed: ${errorMessage(cause)}
30
30
  `))}}),detached=!1,detach=()=>{detached||(detached=!0,detachReader(),writer.unregisterConnection(id),connections.delete(id),occupancy.release(socket),router.releaseConnection(id).catch(cause=>{process.stderr.write(`senpi rpc connection ${id} release failed: ${errorMessage(cause)}
31
31
  `)}))};connections.set(id,{id,sink,detach,close:()=>socket.destroy()}),socket.once("close",detach),socket.once("error",()=>detach())};secret?authenticateSocket(socket,secret,accept):accept()});server.on("error",cause=>{shuttingDown||process.stderr.write(`senpi rpc socket listener failed: ${errorMessage(cause)}
32
- `)});let stopChildReaper=await startHostChildReaper(hostLog),shutdown=async(exitCode=0,watchdogCleanup)=>{shuttingDown&&process.exit(exitCode),shuttingDown=!0,observers.stop(),handover?.dispose(),stopChildReaper(),await handoverAnswered();try{await router.dispose(),await writer.flush();for(let connection of connections.values())connection.detach(),connection.close();await shieldSocketDuringClose(socketPath,()=>process.platform==="win32"?Promise.race([closeServer(server),delay(WINDOWS_SHUTDOWN_HARD_EXIT_MS)]):closeServer(server)),await unlinkOwnedSocket(socketPath,boundIdentity,hostLog),supervisorPublicSocketPath&&await unlinkOwnedSocket(supervisorPublicSocketPath,supervisorPublicIdentity,hostLog),watchdogCleanup&&await watchdogCleanup}finally{process.exit(exitCode)}},drainForHandoff=()=>{if(!shuttingDown){if(draining){handoffAnnounced&&router.beginDrain();return}draining=!0,crashCleanupPaths.length=0,hostLog("draining for a generation handoff"),endpointSuperseded().then(superseded=>{writer.broadcastHostRecord({type:"host_superseded",instanceId:hostInstanceId(),generation:hostGeneration(process.env),successor:superseded?{socket:supervisorPublicSocketPath??socketPath}:null})}).catch(cause=>{hostLog(`handoff announcement failed: ${String(cause)}`)}).finally(()=>{handoffAnnounced=!0,router.beginDrain()})}},endpointSuperseded=()=>supervisorPublicSocketPath===void 0?socketEntryReplaced(socketPath,boundIdentity):socketEntryReplaced(supervisorPublicSocketPath,supervisorPublicIdentity);registerShutdownSignals(shutdown),process.platform!=="win32"&&process.on("SIGUSR1",drainForHandoff);let drainRequestFile=hostChildDrainRequestFile();drainRequestFile!==void 0&&watchDrainRequest(drainRequestFile,drainForHandoff);let watchdog=watchdogConfig&&supervisorPublicOwnerFile?{...watchdogConfig,cleanupPaths:crashCleanupPaths,beforeCleanup:async()=>{supervisorPublicIdentity??=await readSocketIdentityFile(supervisorPublicOwnerFile)}}:watchdogConfig&&{...watchdogConfig,cleanupPaths:crashCleanupPaths};return armHostWatchdog(watchdog,(reason,cleanup)=>{process.stderr.write(`senpi rpc host: ${reason}; shutting down
32
+ `)});let stopChildReaper=await startHostChildReaper(hostLog),shutdown=async(exitCode=0,watchdogCleanup)=>{shuttingDown&&process.exit(exitCode),shuttingDown=!0,observers.stop(),handover?.dispose(),stopChildReaper(),await handoverAnswered();try{await(process.platform==="win32"?Promise.race([router.dispose(),delay(WINDOWS_SHUTDOWN_DISPOSE_BOUND_MS)]):router.dispose()),await writer.flush();for(let connection of connections.values())connection.detach(),connection.close();await shieldSocketDuringClose(socketPath,()=>process.platform==="win32"?Promise.race([closeServer(server),delay(WINDOWS_SHUTDOWN_HARD_EXIT_MS)]):closeServer(server)),await unlinkOwnedSocket(socketPath,boundIdentity,hostLog),supervisorPublicSocketPath&&await unlinkOwnedSocket(supervisorPublicSocketPath,supervisorPublicIdentity,hostLog),watchdogCleanup&&await watchdogCleanup}finally{process.exit(exitCode)}},drainForHandoff=()=>{if(!shuttingDown){if(draining){handoffAnnounced&&router.beginDrain();return}draining=!0,crashCleanupPaths.length=0,hostLog("draining for a generation handoff"),endpointSuperseded().then(superseded=>{writer.broadcastHostRecord({type:"host_superseded",instanceId:hostInstanceId(),generation:hostGeneration(process.env),successor:superseded?{socket:supervisorPublicSocketPath??socketPath}:null})}).catch(cause=>{hostLog(`handoff announcement failed: ${String(cause)}`)}).finally(()=>{handoffAnnounced=!0,router.beginDrain()})}},endpointSuperseded=()=>supervisorPublicSocketPath===void 0?socketEntryReplaced(socketPath,boundIdentity):socketEntryReplaced(supervisorPublicSocketPath,supervisorPublicIdentity);registerShutdownSignals(shutdown),process.platform!=="win32"&&process.on("SIGUSR1",drainForHandoff);let drainRequestFile=hostChildDrainRequestFile();drainRequestFile!==void 0&&watchDrainRequest(drainRequestFile,drainForHandoff);let watchdog=watchdogConfig&&supervisorPublicOwnerFile?{...watchdogConfig,cleanupPaths:crashCleanupPaths,beforeCleanup:async()=>{supervisorPublicIdentity??=await readSocketIdentityFile(supervisorPublicOwnerFile)}}:watchdogConfig&&{...watchdogConfig,cleanupPaths:crashCleanupPaths};return armHostWatchdog(watchdog,(reason,cleanup)=>{process.stderr.write(`senpi rpc host: ${reason}; shutting down
33
33
  `),shutdown(0,cleanup),setImmediate(killTrackedDetachedChildren)}),boundIdentity=await listen(server,socketPath,secret),supervisorPublicOwnerFile&&(supervisorPublicIdentity=await waitForSocketIdentityFile(supervisorPublicOwnerFile)),process.stderr.write(`senpi rpc listening on ${formatSocketAddress(socketPath)}
34
34
  `),new Promise(()=>{})}async function startupRuntimeBuildId(){try{return await computeRuntimeBuildId({profile:protocolIdentity().launch_profile.core})}catch(cause){hostLog(`runtime identity unreadable: ${errorMessage(cause)}`);return}}function delay(ms){return new Promise(resolve=>setTimeout(resolve,ms))}function noop(){}function parseError(error2){return{type:"response",command:"parse",success:!1,error:error2}}function oversizedLineError(){return`RPC input line exceeds ${MAX_RPC_LINE_CHARACTERS} characters.`}function errorMessage(cause){return cause instanceof Error?cause.message:String(cause)}function hostSessionContext(socketPath){let supervised=readHostWatchdogConfigFromBrandEnv(),endpoint=supervised===void 0?socketPath:supervised.publicSocket;if(endpoint===void 0||endpoint.startsWith("\0"))return{host_instance:hostInstanceId()};let directory=canonicalSessionPath(dirname(endpoint));return{host_socket:join2(directory,basename(endpoint)),host_instance:hostInstanceId()}}function listenSocketPath(options){if(!(options.listen===void 0||options.listen==="stdio://"))return resolveSocketPath(options.listen,options.agentDir)}function publicEndpointSocket(options){let supervised=readHostWatchdogConfigFromBrandEnv();return supervised!==void 0?supervised.publicSocket:listenSocketPath(options)}function resolveSocketPath(value,agentDir){if(value==="unix://")return join2(agentDir,"rpc","rpc.sock");if(value.startsWith("unix://")){let path=value.slice(7);return path.length===0?join2(agentDir,"rpc","rpc.sock"):path.startsWith("@")&&process.platform==="linux"?`\0${path.slice(1)}`:path}return value}function formatSocketAddress(socketPath){return socketPath.startsWith("\0")?`unix://@${socketPath.slice(1)}`:`unix://${socketPath}`}function listen(server,socketPath,secret){return new Promise((resolve,reject)=>{server.once("error",reject),server.listen(resolveSocketTransportAddress(socketPath,process.platform,secret),async()=>{server.off("error",reject);try{if(process.platform!=="win32"&&!socketPath.startsWith("\0"))return await chmod(socketPath,384),resolve(await statSocketIdentity(socketPath));resolve(void 0)}catch(cause){reject(cause)}})})}function closeServer(server){return new Promise((resolve,reject)=>{server.close(cause=>cause?reject(cause):resolve())})}function hostLog(message){process.stderr.write(`senpi rpc host: ${message}
35
35
  `)}function registerShutdownSignals(shutdown){for(let signal of process.platform==="win32"?["SIGTERM"]:["SIGTERM","SIGHUP"])process.on(signal,()=>{killTrackedDetachedChildren(),shutdown(signal==="SIGHUP"?129:143)})}export{DEFAULT_HOST_EMPTY_EXIT_MS,DEFAULT_SESSION_IDLE_EVICTION_MS,RPC_HOST_EMPTY_EXIT_MS_ENV,RPC_SESSION_IDLE_EVICTION_MS_ENV,createHostCore,resolveHostIdlePolicy,runMultiSessionHost};
@@ -0,0 +1,10 @@
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{createWebSocketTransportFailure,startWebSocketLiveness}from"./chunk-YT2ZSZOY.js";import{applyChatGptSubscriptionCacheAffinityHeaders,clampOpenAIPromptCacheKey}from"./chunk-AEJUOQ7U.js";import{combineAbortSignals}from"./chunk-SJ5DSOBX.js";import{transportProviderDiagnosticFromError}from"./chunk-V6RY5A6T.js";import{OPENAI_RESPONSES_RESERVED_BODY_KEYS,applyExtraBody,buildBaseOptions,clampMaxForOpenAI}from"./chunk-MVNVDGYF.js";import{formatProviderError,normalizeProviderError}from"./chunk-TAV6QZFM.js";import{appendRetryAfterMsMarker,extract429RetryAfterMs}from"./chunk-PELNNWGO.js";import{extractChatGptSubscriptionAccountId,getWireIdentity,uuidv7}from"./chunk-2VZJTDUX.js";import{convertResponsesMessages,convertResponsesTools,processResponsesStream,resolveResponsesDeferredToolsMode,resolveResponsesToolPlacement}from"./chunk-XSRM367N.js";import{registerSessionResourceCleanup}from"./chunk-WHPDEDCC.js";import{buildProviderDiagnostic,categoryForProviderCode,classifyProviderFailure,isOpaqueProviderCode,isProviderDiagnosticResetsAt,isProviderDiagnosticStatus,readProviderDiagnostic}from"./chunk-AA2L2RHH.js";import"./chunk-HK46JMSC.js";import{createGrammarToolInputProperties}from"./chunk-WQLMQGOW.js";import"./chunk-WDTJ6JKE.js";import{getProviderEnvValue}from"./chunk-5ROMKDLK.js";import"./chunk-3W47LTXQ.js";import{ACCOUNT_LIMIT_NEXT_STEP_LEAD,clampThinkingLevel,getDeclaredTools,getInitialSystemMessage,getSystemMessageText,normalizeContext,resolveTranscript,supportsMax,supportsXhigh}from"./chunk-LAWS3FYQ.js";import{attachProviderDiagnostic}from"./chunk-45SZOLCU.js";import{AssistantMessageEventStream,appendAssistantMessageDiagnostic,createAssistantMessageDiagnostic,formatThrownValue}from"./chunk-DMI55M2N.js";import{headersToRecord}from"./chunk-PJ34QVL5.js";import"./chunk-IKOFCODM.js";var DEFAULT_PROXY_PORTS={ftp:21,gopher:70,http:80,https:443,ws:80,wss:443};function getProxyEnv(key,env){let lowercaseKey=key.toLowerCase(),uppercaseKey=key.toUpperCase();return env?.[lowercaseKey]||env?.[uppercaseKey]||getProviderEnvValue(lowercaseKey)||getProviderEnvValue(uppercaseKey)||""}function parseProxyTargetUrl(targetUrl){if(targetUrl instanceof URL)return targetUrl;try{return new URL(targetUrl)}catch{return}}function stripBrackets(host){return host.startsWith("[")&&host.endsWith("]")?host.slice(1,-1):host}function parseNoProxyEntry(entry){let trimmed=entry.trim().toLowerCase();if(!trimmed)return;if(trimmed.startsWith("[")){let closingBracket=trimmed.indexOf("]");if(closingBracket!==-1){let host=trimmed.slice(1,closingBracket),rest=trimmed.slice(closingBracket+1);if(rest.startsWith(":")){let port=Number.parseInt(rest.slice(1),10);return{host,port:Number.isNaN(port)?0:port}}return{host,port:0}}}if(trimmed.includes(":")&&trimmed.split(":").length>2)return{host:trimmed,port:0};let colonIndex=trimmed.lastIndexOf(":");if(colonIndex!==-1&&colonIndex===trimmed.indexOf(":")){let host=trimmed.slice(0,colonIndex),port=Number.parseInt(trimmed.slice(colonIndex+1),10);if(!Number.isNaN(port))return{host,port}}return{host:trimmed,port:0}}function shouldProxyHostname(hostname,port,env){let noProxy=getProxyEnv("no_proxy",env).toLowerCase();if(!noProxy)return!0;if(noProxy==="*")return!1;let normalizedTargetHost=stripBrackets(hostname.toLowerCase());return noProxy.split(/[,\s]/).every(entry=>{let parsed=parseNoProxyEntry(entry);if(!parsed||parsed.port&&parsed.port!==port)return!0;let domain=stripBrackets(parsed.host);return domain.startsWith("*.")?domain=domain.slice(2):(domain.startsWith(".")||domain.startsWith("*"))&&(domain=domain.slice(1)),domain?!(normalizedTargetHost===domain||normalizedTargetHost.endsWith(`.${domain}`)):!0})}function getProxyForUrl(targetUrl,env){let parsedUrl=parseProxyTargetUrl(targetUrl);if(!parsedUrl?.protocol||!parsedUrl.host)return"";let protocol=parsedUrl.protocol.split(":",1)[0],hostname=stripBrackets(parsedUrl.hostname||parsedUrl.host.replace(/:\d*$/,"")),port=Number.parseInt(parsedUrl.port,10)||DEFAULT_PROXY_PORTS[protocol]||0;if(!shouldProxyHostname(hostname,port,env))return"";let proxy=getProxyEnv(`${protocol}_proxy`,env)||getProxyEnv("all_proxy",env);return proxy&&!proxy.includes("://")&&(proxy=`${protocol}://${proxy}`),proxy}var UNSUPPORTED_PROXY_PROTOCOL_MESSAGE="Unsupported proxy protocol. SOCKS and PAC proxy URLs are not supported; use an HTTP or HTTPS proxy URL.";function resolveHttpProxyUrlForTarget(targetUrl,env){let proxy=getProxyForUrl(targetUrl,env);if(!proxy)return;let proxyUrl;try{proxyUrl=new URL(proxy)}catch(error){throw new Error(`Invalid proxy URL ${JSON.stringify(proxy)}: ${error instanceof Error?error.message:String(error)}`)}if(proxyUrl.protocol!=="http:"&&proxyUrl.protocol!=="https:")throw new Error(`${UNSUPPORTED_PROXY_PROTOCOL_MESSAGE} Got ${proxyUrl.protocol}`);return proxyUrl}var CHATGPT_USAGE_LIMIT_PREFIX="You have hit your ChatGPT usage limit",OTHER_ROUTES=`${ACCOUNT_LIMIT_NEXT_STEP_LEAD}add an OpenAI API key, sign in with another ChatGPT account, or switch providers.`,USAGE_PAGE="https://chatgpt.com/settings/usage",REACHED_TYPE_ADVICE={workspace_owner_credits_depleted:`Your workspace is out of credits: add credits at ${USAGE_PAGE}.`,workspace_member_credits_depleted:"Your workspace is out of credits: ask your workspace owner to add more.",workspace_owner_usage_limit_reached:"You hit the spend cap set for your workspace: raise it to continue.",workspace_member_usage_limit_reached:"You hit the spend cap your workspace owner set: ask an owner to raise it to continue."},PLAN_ADVICE={plus:`Upgrade to Pro, or buy credits at ${USAGE_PAGE}.`,pro:`Buy credits at ${USAGE_PAGE}.`,prolite:`Buy credits at ${USAGE_PAGE}.`,promax:`Buy credits at ${USAGE_PAGE}.`,free:"Upgrade to ChatGPT Plus to continue.",go:"Upgrade to ChatGPT Plus to continue.",team:"Ask your workspace admin for more access.",business:"Ask your workspace admin for more access.",self_serve_business_usage_based:"Ask your workspace admin for more access.",enterprise_cbp_usage_based:"Ask your workspace admin for more access."};function headerBool(value){let raw=value?.trim().toLowerCase();if(raw==="true"||raw==="1")return!0;if(raw==="false"||raw==="0")return!1}function limitAdvice(input,plan){let reachedType=input.header("x-codex-rate-limit-reached-type")?.trim().toLowerCase(),reached=reachedType?REACHED_TYPE_ADVICE[reachedType]:void 0;return reached||(headerBool(input.header("x-codex-credits-has-credits"))===!0?"This account has ChatGPT credits, but ChatGPT did not apply them to this request.":plan?PLAN_ADVICE[plan]:void 0)}var USAGE_LIMIT_CODE=/usage_limit_reached|usage_not_included/i,HTTP_LIMIT_CODE=/usage_limit_reached|usage_not_included|rate_limit_exceeded/i;function asUsageLimitError(value){return value!==null&&typeof value=="object"?value:void 0}function fromError(error,header){return describeChatGptUsageLimit({...typeof error.plan_type=="string"?{planType:error.plan_type}:{},...typeof error.resets_at=="number"?{resetsAt:error.resets_at}:{},header})}function hasCode(error,pattern){let code=typeof error.code=="string"&&error.code?error.code:error.type;return typeof code=="string"&&pattern.test(code)}function describeChatGptUsageLimitResponse(status,body,headers){let container=asUsageLimitError(body),error=container?asUsageLimitError(Reflect.get(container,"error")):void 0;if(!(!error||!(hasCode(error,HTTP_LIMIT_CODE)||status===429)))return fromError(error,name=>headers.get(name)??void 0)}function describeChatGptUsageLimitEvent(event){let error=asUsageLimitError(event.error);if(!error||!hasCode(error,USAGE_LIMIT_CODE))return;let headers=asUsageLimitError(event.headers);return fromError(error,name=>{if(!headers)return;let entry=Object.entries(headers).find(([key])=>key.toLowerCase()===name);return typeof entry?.[1]=="string"?entry[1]:void 0})}function describeChatGptUsageLimit(input){let plan=input.planType?.trim().toLowerCase()||void 0,sentences=[`${CHATGPT_USAGE_LIMIT_PREFIX}${plan?` (${plan} plan)`:""}.`],advice=limitAdvice(input,plan);if(advice&&sentences.push(advice),sentences.push(OTHER_ROUTES),input.resetsAt!==void 0&&Number.isFinite(input.resetsAt)){let mins=Math.max(0,Math.round((input.resetsAt*1e3-(input.nowMs??Date.now()))/6e4));sentences.push(`Try again in ~${mins} min.`)}return sentences.join(" ")}var CODEX_WEBSOCKET_FALLBACK_COOLDOWN_MS=6e4,CODEX_WEBSOCKET_MID_STREAM_FAILURES_BEFORE_FALLBACK=2,websocketDebugStats=new Map,websocketSseFallbackUntil=new Map,consecutiveMidStreamFailures=new Map;function getOrCreateWebSocketDebugStats(sessionId){let stats=websocketDebugStats.get(sessionId);return stats||(stats={requests:0,connectionsCreated:0,connectionsReused:0,cachedContextRequests:0,storeTrueRequests:0,fullContextRequests:0,deltaRequests:0,lastInputItems:0,websocketFailures:0,sseFallbacks:0},websocketDebugStats.set(sessionId,stats)),stats}function getWebSocketDebugStats(sessionId){let stats=websocketDebugStats.get(sessionId);return stats?{...stats}:void 0}function clearWebSocketFallbackState(sessionId){if(sessionId){websocketDebugStats.delete(sessionId),websocketSseFallbackUntil.delete(sessionId),consecutiveMidStreamFailures.delete(sessionId);return}websocketDebugStats.clear(),websocketSseFallbackUntil.clear(),consecutiveMidStreamFailures.clear()}function isWebSocketSseFallbackActive(sessionId){if(!sessionId)return!1;let fallbackUntil=websocketSseFallbackUntil.get(sessionId);if(fallbackUntil===void 0)return!1;let stats=websocketDebugStats.get(sessionId);return fallbackUntil>Date.now()?(stats&&(stats.websocketFallbackActive=!0),!0):(websocketSseFallbackUntil.delete(sessionId),stats&&(stats.websocketFallbackActive=!1),!1)}function recordWebSocketSseFallback(sessionId){if(!sessionId)return;let stats=getOrCreateWebSocketDebugStats(sessionId);stats.sseFallbacks++,stats.websocketFallbackActive=!0}function recordWebSocketFailure(sessionId,error,phase){if(!sessionId)return;let stats=getOrCreateWebSocketDebugStats(sessionId);if(stats.websocketFailures++,stats.lastWebSocketError=formatThrownValue(error),phase==="after_message_stream_start"){let failures=(consecutiveMidStreamFailures.get(sessionId)??0)+1;if(failures<CODEX_WEBSOCKET_MID_STREAM_FAILURES_BEFORE_FALLBACK){consecutiveMidStreamFailures.set(sessionId,failures);return}}consecutiveMidStreamFailures.delete(sessionId),websocketSseFallbackUntil.set(sessionId,Date.now()+CODEX_WEBSOCKET_FALLBACK_COOLDOWN_MS),stats.websocketFallbackActive=!0}function recordWebSocketSuccess(sessionId){sessionId&&consecutiveMidStreamFailures.delete(sessionId)}function asRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)?value:void 0}function nonEmptyString(value){return typeof value=="string"&&value.length>0?value:void 0}function errorCode(error){return nonEmptyString(error?.code)??nonEmptyString(error?.type)}function resetsAtMs(error,nowMs){let absolute=error?.resets_at;if(typeof absolute=="number"&&Number.isFinite(absolute)&&absolute>0){let ms=Math.round(absolute<1e12?absolute*1e3:absolute);return isProviderDiagnosticResetsAt(ms)?ms:void 0}let relative=error?.resets_in_seconds;if(typeof relative=="number"&&Number.isFinite(relative)&&relative>=0){let ms=Math.round(nowMs+relative*1e3);return isProviderDiagnosticResetsAt(ms)?ms:void 0}}function classifyCodexFailure(facts){let status=isProviderDiagnosticStatus(facts.status)?facts.status:void 0,reset=facts.resetsAt===void 0?{}:{resetsAt:facts.resetsAt};if(facts.code!==void 0&&categoryForProviderCode(facts.code)!==void 0){let classified=classifyProviderFailure({status,code:facts.code})??classifyProviderFailure({status:void 0,code:facts.code});return classified===void 0?void 0:buildProviderDiagnostic({...classified,...reset})}let byStatus=status===void 0?void 0:classifyProviderFailure({status,code:void 0});if(byStatus!==void 0&&byStatus.category!=="unknown")return byStatus;let opaque=[facts.code,facts.fallbackCode].find(code=>code!==void 0&&isOpaqueProviderCode(code));return opaque!==void 0?buildProviderDiagnostic({category:"unknown",code:opaque,evidence:"structured_code"}):byStatus}function codexHttpProviderDiagnostic(status,bodyText,nowMs=Date.now()){let error;try{error=asRecord(asRecord(JSON.parse(bodyText))?.error)}catch{error=void 0}return classifyCodexFailure({status,code:errorCode(error),resetsAt:resetsAtMs(error,nowMs)})}function codexEventProviderDiagnostic(event,nowMs=Date.now()){let response=asRecord(event.response),error=asRecord(event.error)??asRecord(response?.error),status=typeof event.status=="number"?event.status:void 0,eventType=nonEmptyString(event.type);return classifyCodexFailure({status,code:errorCode(error)??nonEmptyString(event.code),...eventType===void 0?{}:{fallbackCode:eventType},resetsAt:resetsAtMs(error,nowMs)})}function normalizeCodexReasoningSummary(reasoningSummary){switch(reasoningSummary){case null:case"off":return;case void 0:case"on":return"auto";default:return reasoningSummary}}function buildCodexReasoning(reasoningEffort,reasoningSummary,modelSupportsReasoning,thinkingOff){let effort;if(reasoningEffort!=null)effort=reasoningEffort;else if(reasoningEffort===void 0&&modelSupportsReasoning&&thinkingOff!==null)effort=thinkingOff??"none";else return;let summary=normalizeCodexReasoningSummary(reasoningSummary);return{effort,...summary===void 0?{}:{summary}}}function loadNodeOs(){return typeof process>"u"||!(process.versions?.node||process.versions?.bun)?null:process.getBuiltinModule?.("node:os")??null}var _os=loadNodeOs(),DEFAULT_CODEX_BASE_URL="https://chatgpt.com/backend-api",DEFAULT_MAX_RETRIES=0,BASE_DELAY_MS=1e3,DEFAULT_MAX_RETRY_DELAY_MS=6e4,DEFAULT_WEBSOCKET_CONNECT_TIMEOUT_MS=15e3,REQUEST_COMPRESSION_ZSTD_LEVEL=3,CODEX_TOOL_CALL_PROVIDERS=new Set(["openai","chatgpt-subscription","opencode"]),CODEX_PREVIOUS_RESPONSE_STALE_CODES=new Set(["codex_previous_response_stale"]),WEBSOCKET_CONNECTION_LIMIT_REACHED_CODE="websocket_connection_limit_reached",PREVIOUS_RESPONSE_NOT_FOUND_CODE="previous_response_not_found",CODEX_RESPONSE_STATUSES=new Set(["completed","incomplete","failed","cancelled","queued","in_progress"]);function assertSuccessfulOutput(output){if(output.stopReason==="pending")throw new Error("Codex stream ended without a stop reason");if(output.stopReason==="error"||output.stopReason==="aborted")throw new Error(output.errorMessage||"An unknown error occurred")}function isTerminalRateLimitError(errorText){return/GoUsageLimitError|FreeUsageLimitError|Monthly usage limit reached|available balance|insufficient_quota|out of budget|quota exceeded|billing/i.test(errorText)}function isRetryableError(status,errorText){return status===429&&isTerminalRateLimitError(errorText)?!1:status===429||status===500||status===502||status===503||status===504?!0:/rate.?limit|overloaded|service.?unavailable|upstream.?connect|connection.?refused/i.test(errorText)}var RetryDelayExceededError=class extends Error{};function validateRetryDelayMs(delayMs,options){let maxRetryDelayMs=options?.maxRetryDelayMs??DEFAULT_MAX_RETRY_DELAY_MS;if(maxRetryDelayMs>0&&delayMs>maxRetryDelayMs)throw new RetryDelayExceededError(`Server requested ${Math.ceil(delayMs/1e3)}s retry delay (max: ${Math.ceil(maxRetryDelayMs/1e3)}s)`);return delayMs}function sleep(ms,signal){return new Promise((resolve,reject)=>{if(signal?.aborted){reject(new Error("Request was aborted"));return}let timeout=setTimeout(resolve,ms);signal?.addEventListener("abort",()=>{clearTimeout(timeout),reject(new Error("Request was aborted"))})})}function normalizeTimeoutMs(value){if(value!==void 0){if(!Number.isFinite(value)||value<0)throw new Error(`Invalid timeoutMs: ${String(value)}`);return Math.floor(value)}}function loadNodeZlib(){return typeof process>"u"||!(process.versions?.node||process.versions?.bun)?null:process.getBuiltinModule?.("node:zlib")??null}function compressRequestBodyZstd(bodyJson){let zlib=loadNodeZlib();if(!zlib||typeof zlib.zstdCompressSync!="function")return null;try{let compressed=zlib.zstdCompressSync(bodyJson,{params:{[zlib.constants.ZSTD_c_compressionLevel]:REQUEST_COMPRESSION_ZSTD_LEVEL}});return new Uint8Array(compressed.buffer,compressed.byteOffset,compressed.byteLength)}catch{return null}}function copyBytesToArrayBuffer(bytes){let copy=new Uint8Array(bytes.byteLength);return copy.set(bytes),copy.buffer}var stream=(model,context,options)=>{let stream2=new AssistantMessageEventStream,normalizedContext=resolveTranscript(context,model.compat?.supportsMidConvoSystemMessages);return(async()=>{let output={role:"assistant",content:[],api:"openai-codex-responses",provider:model.provider,model:model.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:"pending",timestamp:Date.now()};try{let apiKey=options?.apiKey;if(!apiKey)throw new Error(`No API key for provider: ${model.provider}`);let accountId=extractAccountId(apiKey),grammarToolInputProperties=createGrammarToolInputProperties(getDeclaredTools(normalizedContext.messages),model.compat?.supportsOpenAIGrammarTools??!1),cacheSessionId=options?.cacheRetention==="none"?void 0:options?.sessionId,codexSessionId=clampOpenAIPromptCacheKey(cacheSessionId),body=buildRequestBody(model,normalizedContext,options,codexSessionId,grammarToolInputProperties),nextBody=await options?.onPayload?.(body,model);nextBody!==void 0&&(body=nextBody);let websocketRequestId=codexSessionId||uuidv7(),routingHint=buildCodexRoutingHint(body.model,body.service_tier),sseHeaders=buildSSEHeaders(model.headers,options?.headers,accountId,apiKey,routingHint,codexSessionId),websocketHeaders=buildWebSocketHeaders(model.headers,options?.headers,accountId,apiKey,routingHint,websocketRequestId),bodyJson=JSON.stringify(body),httpTimeoutMs=normalizeTimeoutMs(options?.timeoutMs),websocketConnectTimeoutMs=normalizeTimeoutMs(options?.websocketConnectTimeoutMs),transport=options?.transport||"auto",startEmitted=!1,websocketDisabledForSession=transport!=="sse"&&isWebSocketSseFallbackActive(cacheSessionId);if(websocketDisabledForSession&&recordWebSocketSseFallback(cacheSessionId),transport!=="sse"&&!websocketDisabledForSession){let websocketStarted=!1,retriedWebSocketConnectionLimit=!1,retriedMissingWebSocketContinuation=!1;for(;;){websocketStarted=!1;try{if(await processWebSocketStream(resolveCodexWebSocketUrl(model.baseUrl),body,websocketHeaders,output,stream2,model,()=>{websocketStarted=!0,startEmitted||(startEmitted=!0,stream2.push({type:"start",partial:output}))},httpTimeoutMs,websocketConnectTimeoutMs,cacheSessionId,accountId??apiKey,grammarToolInputProperties,options),options?.signal?.aborted)throw new Error("Request was aborted");assertSuccessfulOutput(output),recordWebSocketSuccess(cacheSessionId),stream2.push({type:"done",reason:output.stopReason,message:output}),stream2.end();return}catch(error){let aborted=options?.signal?.aborted,connectionLimitBeforeStart=!websocketStarted&&isWebSocketConnectionLimitReachedError(error),previousResponseNotFound=isPreviousResponseNotFoundError(error);if(!aborted&&previousResponseNotFound&&!retriedMissingWebSocketContinuation){retriedMissingWebSocketContinuation=!0;continue}if(!aborted&&connectionLimitBeforeStart&&!retriedWebSocketConnectionLimit){retriedWebSocketConnectionLimit=!0;continue}if(aborted||isCodexNonTransportError(error)&&!connectionLimitBeforeStart)throw error;let phase=websocketStarted?"after_message_stream_start":"before_message_stream_start";if(appendAssistantMessageDiagnostic(output,createAssistantMessageDiagnostic("provider_transport_failure",error,{configuredTransport:transport,...websocketStarted?{}:{fallbackTransport:"sse"},eventsEmitted:websocketStarted,phase,requestBytes:new TextEncoder().encode(bodyJson).byteLength})),recordWebSocketFailure(cacheSessionId,error,phase),websocketStarted)throw error;recordWebSocketSseFallback(cacheSessionId);break}}}let compressedBody=compressRequestBodyZstd(bodyJson);compressedBody&&sseHeaders.set("content-encoding","zstd");let sseBody=compressedBody?copyBytesToArrayBuffer(compressedBody):bodyJson,response,lastError,maxRetries=options?.maxRetries??DEFAULT_MAX_RETRIES;for(let attempt=0;attempt<=maxRetries;attempt++){if(options?.signal?.aborted)throw new Error("Request was aborted");try{let headerTimeoutSignal=httpTimeoutMs!==void 0&&httpTimeoutMs>0?AbortSignal.timeout(httpTimeoutMs):void 0,combinedSignal=combineAbortSignals([options?.signal,headerTimeoutSignal]);try{response=await(options?.fetch??globalThis.fetch)(resolveCodexUrl(model.baseUrl),{method:"POST",headers:sseHeaders,body:sseBody,signal:combinedSignal.signal})}catch(error){throw headerTimeoutSignal?.aborted&&!options?.signal?.aborted?new Error(`Codex SSE response headers timed out after ${httpTimeoutMs}ms`):error}finally{combinedSignal.cleanup()}if(await options?.onResponse?.({status:response.status,headers:headersToRecord(response.headers)},model),response.ok)break;let errorText=await response.text();if(attempt<maxRetries&&isRetryableError(response.status,errorText)){let retryAfterDelayMs=extract429RetryAfterMs({status:429,headers:response.headers,bodyText:""}),delayMs=retryAfterDelayMs===void 0?BASE_DELAY_MS*2**attempt:validateRetryDelayMs(retryAfterDelayMs,options);await sleep(delayMs,options?.signal);continue}let fakeResponse=new Response(errorText,{status:response.status,statusText:response.statusText}),info=await parseErrorResponse(fakeResponse,response.headers),errorMessage=info.friendlyMessage||info.message;if(response.status===429){let hintMs=extract429RetryAfterMs({status:response.status,headers:response.headers,bodyText:errorText});hintMs!==void 0&&(errorMessage=appendRetryAfterMsMarker(errorMessage,hintMs))}throw attachProviderDiagnostic(new Error(errorMessage),codexHttpProviderDiagnostic(response.status,errorText))}catch(error){if(error instanceof Error&&(error.name==="AbortError"||error.message==="Request was aborted"))throw new Error("Request was aborted");if(lastError=error instanceof Error?error:new Error(String(error)),attempt<maxRetries&&!(lastError instanceof RetryDelayExceededError)&&!lastError.message.includes("usage limit")){let delayMs=BASE_DELAY_MS*2**attempt;await sleep(delayMs,options?.signal);continue}throw lastError}}if(!response?.ok)throw lastError??new Error("Failed after retries");if(!response.body)throw new Error("No response body");if(startEmitted||(startEmitted=!0,stream2.push({type:"start",partial:output})),await processStream(response,output,stream2,model,grammarToolInputProperties,options),options?.signal?.aborted)throw new Error("Request was aborted");assertSuccessfulOutput(output),stream2.push({type:"done",reason:output.stopReason,message:output}),stream2.end()}catch(error){for(let block of output.content)delete block.partialJson,delete block.customInput;output.stopReason=options?.signal?.aborted?"aborted":"error",output.errorMessage=formatProviderError(normalizeProviderError(error));let providerDiagnostic=output.stopReason==="error"?readProviderDiagnostic(error)??transportProviderDiagnosticFromError(error):void 0;providerDiagnostic!==void 0&&(output.providerDiagnostic=providerDiagnostic),stream2.push({type:"error",reason:output.stopReason,error:output}),stream2.end()}})(),stream2},streamSimple=(model,context,options)=>{let apiKey=options?.apiKey;if(!apiKey)throw new Error(`No API key for provider: ${model.provider}`);let base={...buildBaseOptions(model,context,options,apiKey),toolChoice:options?.toolChoice,serviceTier:options?.serviceTier},clampedReasoning=options?.reasoning?clampThinkingLevel(model,options.reasoning):void 0,reasoningEffort=clampedReasoning==="off"?void 0:clampedReasoning==="max"&&supportsMax(model)?"max":clampMaxForOpenAI(clampedReasoning,supportsXhigh(model));return stream(model,context,{...base,reasoningEffort})};function buildRequestBody(model,context,options,cacheSessionId,grammarToolInputProperties=createGrammarToolInputProperties(getDeclaredTools(context.messages),model.compat?.supportsOpenAIGrammarTools??!1)){let requestedReasoningEffort=options?.reasoningEffort,mappedReasoningEffort=requestedReasoningEffort===void 0?void 0:requestedReasoningEffort==="none"?model.thinkingLevelMap?.off:model.thinkingLevelMap?.[requestedReasoningEffort],reasoningEffort=mappedReasoningEffort===void 0?requestedReasoningEffort:mappedReasoningEffort,reasoningRequested=requestedReasoningEffort!==void 0&&requestedReasoningEffort!=="none"&&reasoningEffort!==null,supportsStrictMode=model.compat?.supportsStrictMode??!0,supportsOpenAIGrammarTools=model.compat?.supportsOpenAIGrammarTools??!1,supportsAdditionalTools=model.compat?.supportsAdditionalTools??!1,supportsToolSearch=model.compat?.supportsToolSearch??!1,toolPlacement=resolveResponsesToolPlacement(context.messages,resolveResponsesDeferredToolsMode(model.compat)!==void 0),messages=convertResponsesMessages(model,context,CODEX_TOOL_CALL_PROVIDERS,{includeSystemPrompt:!1,preserveThinking:reasoningRequested,preserveTextSignatures:!0,grammarToolInputProperties,supportsMidConvoSystemMessages:model.compat?.supportsMidConvoSystemMessages??!1,supportsAdditionalTools,supportsToolSearch,toolOptions:{strict:null,supportsStrictMode,supportsOpenAIGrammarTools}}),initialSystemMessage=getInitialSystemMessage(context.messages),instructions=initialSystemMessage?getSystemMessageText(initialSystemMessage):"",body={model:model.id,store:!1,stream:!0,instructions:instructions||"You are a helpful assistant.",input:messages,text:{verbosity:options?.textVerbosity||"low"},include:["reasoning.encrypted_content"],prompt_cache_key:cacheSessionId,tool_choice:options?.toolChoice??"auto",parallel_tool_calls:!0};options?.temperature!==void 0&&(body.temperature=options.temperature),options?.serviceTier!==void 0&&(body.service_tier=options.serviceTier),toolPlacement.requestTools.length>0&&(body.tools=convertResponsesTools(toolPlacement.requestTools,{strict:null,supportsStrictMode,supportsOpenAIGrammarTools}));let reasoning=buildCodexReasoning(reasoningEffort,options?.reasoningSummary,model.reasoning,model.thinkingLevelMap?.off);return reasoning&&(body.reasoning=reasoning),applyExtraBody(body,options?.extraBody,OPENAI_RESPONSES_RESERVED_BODY_KEYS),body}function getServiceTierCostMultiplier(model,serviceTier){switch(serviceTier){case"ultrafast":return["gpt-6-astra","gpt-6.1-sol"].includes(model.upstreamModelId??model.id)?8:1;case"flex":return .5;case"priority":case"fast":return 2.5;default:return 1}}function applyServiceTierPricing(usage,serviceTier,model){let multiplier=getServiceTierCostMultiplier(model,serviceTier);multiplier!==1&&(usage.cost.input*=multiplier,usage.cost.output*=multiplier,usage.cost.cacheRead*=multiplier,usage.cost.cacheWrite*=multiplier,usage.cost.total=usage.cost.input+usage.cost.output+usage.cost.cacheRead+usage.cost.cacheWrite)}function resolveCodexServiceTier(responseServiceTier,requestServiceTier){return responseServiceTier==="default"&&(requestServiceTier==="flex"||requestServiceTier==="priority"||requestServiceTier==="fast"||requestServiceTier==="ultrafast")?requestServiceTier:responseServiceTier??requestServiceTier}function resolveCodexUrl(baseUrl){let normalized=(baseUrl&&baseUrl.trim().length>0?baseUrl:DEFAULT_CODEX_BASE_URL).replace(/\/+$/,"");return normalized.endsWith("/codex/responses")?normalized:normalized.endsWith("/codex")?`${normalized}/responses`:`${normalized}/codex/responses`}function resolveCodexWebSocketUrl(baseUrl){let url=new URL(resolveCodexUrl(baseUrl));return url.protocol==="https:"&&(url.protocol="wss:"),url.protocol==="http:"&&(url.protocol="ws:"),url.toString()}async function processStream(response,output,stream2,model,grammarToolInputProperties,options){await processResponsesStream(mapCodexEvents(parseSSE(response,options?.signal),output,model,options?.onProviderStreamEvent),output,stream2,model,{serviceTier:options?.serviceTier,grammarToolInputProperties,resolveServiceTier:resolveCodexServiceTier,applyServiceTierPricing:(usage,serviceTier)=>applyServiceTierPricing(usage,serviceTier,model)})}var CodexApiError=class extends Error{constructor(message,options){super(message),this.name="CodexApiError",this.code=options?.code,this.payload=options?.payload,this.cause=options?.cause}},CodexProtocolError=class extends Error{constructor(message,options){super(message),this.name="CodexProtocolError",this.payload=options?.payload,this.cause=options?.cause}},ProviderStreamEventCallbackError=class extends Error{constructor(cause){super(formatThrownValue(cause)),this.name="ProviderStreamEventCallbackError",this.cause=cause}};function isCodexNonTransportError(error){return error instanceof CodexApiError||error instanceof CodexProtocolError||error instanceof ProviderStreamEventCallbackError}function asRecord2(value){return value&&typeof value=="object"?value:null}function getString(value){return typeof value=="string"?value:void 0}function getCodexEventError(event){let response=asRecord2(event.response);return asRecord2(event.error)??(response?asRecord2(response.error):null)}function getCodexEventErrorCode(event){let error=getCodexEventError(event);return getString(error?.code)??getString(error?.type)??getString(event.code)??""}function getCodexEventErrorMessage(event){let response=asRecord2(event.response),error=getCodexEventError(event);return getString(error?.message)??getString(event.message)??getString(response?.message)??""}function isCodexPreviousResponseStale(error){return error instanceof CodexApiError&&typeof error.code=="string"&&CODEX_PREVIOUS_RESPONSE_STALE_CODES.has(error.code)}function isPreviousResponseNotFoundError(error){return error instanceof CodexApiError&&error.code===PREVIOUS_RESPONSE_NOT_FOUND_CODE}function isWebSocketConnectionLimitReachedError(error){return error instanceof CodexApiError&&error.code===WEBSOCKET_CONNECTION_LIMIT_REACHED_CODE}async function*mapCodexEvents(events,output,model,onProviderStreamEvent){for await(let event of events){try{await onProviderStreamEvent?.(event,model)}catch(error){throw new ProviderStreamEventCallbackError(error)}let type=typeof event.type=="string"?event.type:void 0;if(!type)continue;if(type==="error"){let code=getCodexEventErrorCode(event),message=getCodexEventErrorMessage(event),errorText=describeChatGptUsageLimitEvent(event)??`Codex error: ${message||code||JSON.stringify(event)}`,hintMs=extract429RetryAfterMs({bodyText:JSON.stringify(event)});throw hintMs!==void 0&&(errorText=appendRetryAfterMsMarker(errorText,hintMs)),attachProviderDiagnostic(new CodexApiError(errorText,{code:code||void 0,payload:event}),codexEventProviderDiagnostic(event))}if(type==="response.failed"){let code=getCodexEventErrorCode(event),message=getCodexEventErrorMessage(event),errorText=describeChatGptUsageLimitEvent({...event,error:getCodexEventError(event)})??(message||"Codex response failed"),hintMs=extract429RetryAfterMs({bodyText:JSON.stringify(event)});throw hintMs!==void 0&&(errorText=appendRetryAfterMsMarker(errorText,hintMs)),attachProviderDiagnostic(new CodexApiError(errorText,{code,payload:event}),codexEventProviderDiagnostic(event))}if(type==="response.done"||type==="response.completed"||type==="response.incomplete"){let response=event.response;typeof response?.end_turn=="boolean"&&(output.endTurn=response.end_turn);let normalizedResponse=response&&{...response,status:normalizeCodexStatus(response.status)};yield{...event,type:"response.completed",response:normalizedResponse};return}yield JSON.parse(JSON.stringify(event))}}function normalizeCodexStatus(status){if(typeof status=="string")return CODEX_RESPONSE_STATUSES.has(status)?status:void 0}async function*parseSSE(response,signal){if(!response.body)return;let reader=response.body.getReader(),decoder=new TextDecoder,buffer="",onAbort=()=>{reader.cancel().catch(()=>{})};signal?.addEventListener("abort",onAbort,{once:!0});try{for(;;){if(signal?.aborted)throw new Error("Request was aborted");let{done,value}=await reader.read();if(signal?.aborted)throw new Error("Request was aborted");buffer+=done?decoder.decode():decoder.decode(value,{stream:!0}),done&&buffer.trim()&&(buffer+=`
3
+
4
+ `);let idx=buffer.indexOf(`
5
+
6
+ `);for(;idx!==-1;){let chunk=buffer.slice(0,idx);buffer=buffer.slice(idx+2);let dataLines=chunk.split(`
7
+ `).filter(l=>l.startsWith("data:")).map(l=>l.slice(5).trim());if(dataLines.length>0){let data=dataLines.join(`
8
+ `).trim();if(data&&data!=="[DONE]")try{yield JSON.parse(data)}catch(cause){throw new CodexProtocolError(`Invalid Codex SSE JSON: ${formatThrownValue(cause)}`,{cause,payload:data})}}idx=buffer.indexOf(`
9
+
10
+ `)}if(done)break}}finally{signal?.removeEventListener("abort",onAbort);try{await reader.cancel()}catch{}try{reader.releaseLock()}catch{}}}var OPENAI_BETA_RESPONSES_WEBSOCKETS="responses_websockets=2026-02-06",SESSION_WEBSOCKET_CACHE_TTL_MS=300*1e3,SESSION_WEBSOCKET_MAX_AGE_MS=3300*1e3,websocketSessionCache=new Map;function getChatGptSubscriptionWebSocketDebugStats(sessionId){return getWebSocketDebugStats(sessionId)}function resetChatGptSubscriptionWebSocketDebugStats(sessionId){clearWebSocketFallbackState(sessionId)}function closeChatGptSubscriptionWebSocketSessions(sessionId){let closeEntry=entry=>{unparkSessionWebSocket(entry),closeWebSocketSilently(entry.socket,1e3,"debug_close")};if(sessionId){for(let entry of websocketSessionCache.get(sessionId)?.values()??[])closeEntry(entry);websocketSessionCache.delete(sessionId),clearWebSocketFallbackState(sessionId);return}for(let accountEntries of websocketSessionCache.values())for(let entry of accountEntries.values())closeEntry(entry);websocketSessionCache.clear(),clearWebSocketFallbackState()}registerSessionResourceCleanup(closeChatGptSubscriptionWebSocketSessions);var _cachedWebsocket=null;async function getWebSocketConstructor(env){if(!env&&_cachedWebsocket)return _cachedWebsocket;if(typeof process<"u"&&process.versions?.bun){let WebSocketWithProxy=class{constructor(url,options){let _opts={};Array.isArray(options)||typeof options=="string"?_opts={protocols:options}:_opts={...options};let proxyUrl=resolveHttpProxyUrlForTarget(url.toString().replace(/^wss:/,"https:").replace(/^ws:/,"http:"),env);this.socket=Reflect.construct(WebSocket,[url,{..._opts,...proxyUrl?{proxy:proxyUrl.toString()}:{}}]);let innerPing=this.socket.ping;typeof innerPing=="function"&&(this.ping=data=>innerPing.call(this.socket,data))}get readyState(){return getWebSocketReadyState(this.socket)}close(code,reason){this.socket.close(code,reason)}send(data){this.socket.send(data)}addEventListener(type,listener){this.socket.addEventListener(type,listener)}removeEventListener(type,listener){this.socket.removeEventListener(type,listener)}};return env||(_cachedWebsocket=WebSocketWithProxy),WebSocketWithProxy}let ctor=globalThis.WebSocket;return isWebSocketConstructor(ctor)?ctor:null}function isWebSocketConstructor(value){return typeof value=="function"}function getWebSocketReadyState(socket){let readyState=socket.readyState;return typeof readyState=="number"?readyState:void 0}function isWebSocketReusable(socket){let readyState=getWebSocketReadyState(socket);return readyState===void 0||readyState===1}function isWebSocketSessionExpired(entry){return Date.now()-entry.createdAt>=SESSION_WEBSOCKET_MAX_AGE_MS}function closeWebSocketSilently(socket,code=1e3,reason="done"){try{socket.close(code,reason)}catch{}}function evictSessionWebSocket(sessionId,accountId,entry,reason){unparkSessionWebSocket(entry),closeWebSocketSilently(entry.socket,1e3,reason);let accountEntries=websocketSessionCache.get(sessionId);accountEntries?.get(accountId)===entry&&accountEntries.delete(accountId),accountEntries?.size===0&&websocketSessionCache.delete(sessionId)}function unparkSessionWebSocket(entry){entry.idleTimer&&(clearTimeout(entry.idleTimer),entry.idleTimer=void 0),entry.parkedCloseListener&&(entry.socket.removeEventListener("close",entry.parkedCloseListener),entry.socket.removeEventListener("error",entry.parkedCloseListener),entry.parkedCloseListener=void 0)}function parkSessionWebSocket(sessionId,accountId,entry){unparkSessionWebSocket(entry),entry.busy=!1,entry.idleTimer=setTimeout(()=>{entry.busy||evictSessionWebSocket(sessionId,accountId,entry,"idle_timeout")},SESSION_WEBSOCKET_CACHE_TTL_MS);let onParkedClose=()=>{entry.busy||evictSessionWebSocket(sessionId,accountId,entry,"parked_close")};entry.parkedCloseListener=onParkedClose,entry.socket.addEventListener("close",onParkedClose),entry.socket.addEventListener("error",onParkedClose)}async function connectWebSocket(url,headers,signal,connectTimeoutMs=DEFAULT_WEBSOCKET_CONNECT_TIMEOUT_MS,env){let WebSocketCtor=await getWebSocketConstructor(env);if(!WebSocketCtor)throw new Error("WebSocket transport is not available in this runtime");let wsHeaders=headersToRecord(headers);return delete wsHeaders["OpenAI-Beta"],new Promise((resolve,reject)=>{let settled=!1,timeout,socket;try{socket=new WebSocketCtor(url,{headers:wsHeaders})}catch(error){reject(error instanceof Error?error:new Error(String(error)));return}let cleanup=()=>{timeout&&(clearTimeout(timeout),timeout=void 0),transportFailure.dispose(),socket.removeEventListener("open",onOpen),socket.removeEventListener("error",onError),socket.removeEventListener("close",onClose),signal?.removeEventListener("abort",onAbort)},fail=(error,closeReason)=>{settled||(settled=!0,cleanup(),closeReason&&closeWebSocketSilently(socket,1e3,closeReason),reject(error))},transportFailure=createWebSocketTransportFailure(error=>fail(error)),onOpen=()=>{settled||(settled=!0,cleanup(),resolve(socket))},onError=event=>{transportFailure.onError(event)},onClose=event=>{transportFailure.onClose(event)},onAbort=()=>{fail(new Error("Request was aborted"),"aborted")};socket.addEventListener("open",onOpen),socket.addEventListener("error",onError),socket.addEventListener("close",onClose),signal?.addEventListener("abort",onAbort),connectTimeoutMs>0&&(timeout=setTimeout(()=>{fail(new Error(`WebSocket connect timeout after ${connectTimeoutMs}ms`),"connect_timeout")},connectTimeoutMs)),signal?.aborted&&onAbort()})}async function acquireWebSocket(url,headers,sessionId,accountId,signal,connectTimeoutMs,env){if(!sessionId){let socket2=await connectWebSocket(url,headers,signal,connectTimeoutMs,env);return{socket:socket2,reused:!1,release:()=>closeWebSocketSilently(socket2)}}let accountEntries=websocketSessionCache.get(sessionId),cached=accountEntries?.get(accountId),routingHint=headers.get("x-codex-routing-hint");if(cached&&cached.routingHint!==routingHint&&(closeWebSocketSilently(cached.socket,1e3,"routing_hint_changed"),accountEntries?.delete(accountId),accountEntries?.size===0&&websocketSessionCache.delete(sessionId),cached=void 0),cached){if(unparkSessionWebSocket(cached),!cached.busy&&isWebSocketSessionExpired(cached))closeWebSocketSilently(cached.socket,1e3,"connection_age_limit"),accountEntries?.delete(accountId),accountEntries?.size===0&&websocketSessionCache.delete(sessionId);else if(!cached.busy&&isWebSocketReusable(cached.socket))return cached.busy=!0,{socket:cached.socket,entry:cached,reused:!0,release:({keep}={})=>{if(!keep||!isWebSocketReusable(cached.socket)){closeWebSocketSilently(cached.socket);let currentEntries=websocketSessionCache.get(sessionId);currentEntries?.get(accountId)===cached&&currentEntries.delete(accountId),currentEntries?.size===0&&websocketSessionCache.delete(sessionId);return}parkSessionWebSocket(sessionId,accountId,cached)}};if(cached.busy){let socket2=await connectWebSocket(url,headers,signal,connectTimeoutMs,env);return{socket:socket2,reused:!1,release:()=>{closeWebSocketSilently(socket2)}}}isWebSocketReusable(cached.socket)||(closeWebSocketSilently(cached.socket),accountEntries?.delete(accountId),accountEntries?.size===0&&websocketSessionCache.delete(sessionId))}let socket=await connectWebSocket(url,headers,signal,connectTimeoutMs,env),entry={socket,busy:!0,createdAt:Date.now(),routingHint};return accountEntries=websocketSessionCache.get(sessionId),accountEntries||(accountEntries=new Map,websocketSessionCache.set(sessionId,accountEntries)),accountEntries.set(accountId,entry),{socket,entry,reused:!1,release:({keep}={})=>{if(!keep||!isWebSocketReusable(entry.socket)){closeWebSocketSilently(entry.socket),entry.idleTimer&&clearTimeout(entry.idleTimer);let currentEntries=websocketSessionCache.get(sessionId);currentEntries?.get(accountId)===entry&&currentEntries.delete(accountId),currentEntries?.size===0&&websocketSessionCache.delete(sessionId);return}parkSessionWebSocket(sessionId,accountId,entry)}}}async function decodeWebSocketData(data){if(typeof data=="string")return data;if(data instanceof ArrayBuffer)return new TextDecoder().decode(new Uint8Array(data));if(ArrayBuffer.isView(data)){let view=data;return new TextDecoder().decode(new Uint8Array(view.buffer,view.byteOffset,view.byteLength))}if(data&&typeof data=="object"&&"arrayBuffer"in data){let arrayBuffer=await data.arrayBuffer();return new TextDecoder().decode(new Uint8Array(arrayBuffer))}return null}async function*parseWebSocket(socket,signal,idleTimeoutMs){let queue=[],pending=null,done=!1,failed=null,sawCompletion=!1,wake=()=>{if(!pending)return;let resolve=pending;pending=null,resolve()},liveness=startWebSocketLiveness(socket,error=>{failed=error,done=!0,closeWebSocketSilently(socket,1e3,"liveness_timeout"),wake()}),onMessage=event=>{liveness.noteActivity(),(async()=>{let text=null;try{if(!event||typeof event!="object"||!("data"in event)||(text=await decodeWebSocketData(event.data),!text))return;let parsed=JSON.parse(text),type=typeof parsed.type=="string"?parsed.type:"";(type==="response.completed"||type==="response.done"||type==="response.incomplete")&&(sawCompletion=!0,done=!0),queue.push(parsed),wake()}catch(cause){failed=new CodexProtocolError(`Invalid Codex WebSocket JSON: ${formatThrownValue(cause)}`,{cause,payload:text}),done=!0,wake()}})()},transportFailure=createWebSocketTransportFailure(error=>{failed||(failed=error),done=!0,wake()}),onError=event=>{transportFailure.onError(event)},onClose=event=>{if(sawCompletion){transportFailure.dispose(),done=!0,wake();return}transportFailure.onClose(event)},onAbort=()=>{failed=new Error("Request was aborted"),done=!0,wake()};socket.addEventListener("message",onMessage),socket.addEventListener("error",onError),socket.addEventListener("close",onClose),signal?.addEventListener("abort",onAbort);try{for(;;){if(signal?.aborted)throw new Error("Request was aborted");if(queue.length>0){yield queue.shift();continue}if(done)break;let timeout;await new Promise((resolve,reject)=>{pending=resolve,idleTimeoutMs!==void 0&&idleTimeoutMs>0&&(timeout=setTimeout(()=>{let error=new Error(`WebSocket idle timeout after ${idleTimeoutMs}ms`);failed=error,done=!0,pending=null,closeWebSocketSilently(socket,1e3,"idle_timeout"),reject(error)},idleTimeoutMs))}).finally(()=>{timeout&&clearTimeout(timeout)})}if(failed)throw failed;if(!sawCompletion)throw new Error("WebSocket stream closed before response.completed")}finally{liveness.stop(),transportFailure.dispose(),socket.removeEventListener("message",onMessage),socket.removeEventListener("error",onError),socket.removeEventListener("close",onClose),signal?.removeEventListener("abort",onAbort)}}function requestBodyWithoutInput(body){let{input:_input,previous_response_id:_previousResponseId,...rest}=body;return rest}function responseInputsEqual(a,b){return JSON.stringify(a??[])===JSON.stringify(b??[])}function requestBodiesMatchExceptInput(a,b){return JSON.stringify(requestBodyWithoutInput(a))===JSON.stringify(requestBodyWithoutInput(b))}function getCachedWebSocketInputDelta(body,continuation){if(!requestBodiesMatchExceptInput(body,continuation.lastRequestBody))return;let currentInput=body.input??[],baseline=[...continuation.lastRequestBody.input??[],...continuation.lastResponseItems];if(currentInput.length<baseline.length)return;let prefix=currentInput.slice(0,baseline.length);if(responseInputsEqual(prefix,baseline))return currentInput.slice(baseline.length)}function buildCachedWebSocketRequestBody(entry,body){let continuation=entry.continuation;if(!continuation)return body;let delta=getCachedWebSocketInputDelta(body,continuation);return!delta||!continuation.lastResponseId?(entry.continuation=void 0,body):{...body,previous_response_id:continuation.lastResponseId,input:delta}}function recordWebSocketRequestStats(stats,requestBody,reused,useCachedContext){stats&&(stats.requests++,reused?stats.connectionsReused++:stats.connectionsCreated++,useCachedContext&&stats.cachedContextRequests++,requestBody.store===!0&&stats.storeTrueRequests++,stats.lastInputItems=requestBody.input?.length??0,requestBody.previous_response_id?(stats.deltaRequests++,stats.lastDeltaInputItems=requestBody.input?.length??0,stats.lastPreviousResponseId=requestBody.previous_response_id):(stats.fullContextRequests++,stats.lastDeltaInputItems=void 0,stats.lastPreviousResponseId=void 0))}async function*startWebSocketOutputOnFirstEvent(events,onStart){let started=!1;for await(let event of events)started||(started=!0,onStart()),yield event}async function processWebSocketStream(url,body,headers,output,stream2,model,onStart,idleTimeoutMs,websocketConnectTimeoutMs,cacheSessionId,accountId,grammarToolInputProperties,options){let{socket,entry,reused,release}=await acquireWebSocket(url,headers,cacheSessionId,accountId,options?.signal,websocketConnectTimeoutMs,options?.env),keepConnection=!0,useCachedContext=options?.transport==="websocket-cached"||options?.transport==="auto",fullBody=body,requestBody=useCachedContext&&entry?buildCachedWebSocketRequestBody(entry,fullBody):fullBody,stats=cacheSessionId?getOrCreateWebSocketDebugStats(cacheSessionId):void 0,recoveredStalePreviousResponse=!1;try{for(;;){recordWebSocketRequestStats(stats,requestBody,reused&&!recoveredStalePreviousResponse,useCachedContext);try{socket.send(JSON.stringify({type:"response.create",...requestBody})),await processResponsesStream(startWebSocketOutputOnFirstEvent(mapCodexEvents(parseWebSocket(socket,options?.signal,idleTimeoutMs),output,model,options?.onProviderStreamEvent),onStart),output,stream2,model,{serviceTier:options?.serviceTier,grammarToolInputProperties,resolveServiceTier:resolveCodexServiceTier,applyServiceTierPricing:(usage,serviceTier)=>applyServiceTierPricing(usage,serviceTier,model)});break}catch(error){if(!recoveredStalePreviousResponse&&entry&&requestBody.previous_response_id&&isCodexPreviousResponseStale(error)&&!options?.signal?.aborted){entry.continuation=void 0,requestBody=fullBody,recoveredStalePreviousResponse=!0;continue}throw error}}if(options?.signal?.aborted)keepConnection=!1;else if(useCachedContext&&entry&&output.responseId){let responseItems=convertResponsesMessages(model,normalizeContext({messages:[output]}),CODEX_TOOL_CALL_PROVIDERS,{includeSystemPrompt:!1,grammarToolInputProperties}).filter(item=>item.type!=="function_call_output"&&item.type!=="custom_tool_call_output");entry.continuation={lastRequestBody:fullBody,lastResponseId:output.responseId,lastResponseItems:responseItems}}}catch(error){throw entry&&(entry.continuation=void 0),keepConnection=!1,error}finally{release({keep:keepConnection})}}async function parseErrorResponse(response,headers){let raw=await response.text(),message=raw||response.statusText||"Request failed",friendlyMessage;try{let parsed=JSON.parse(raw);friendlyMessage=describeChatGptUsageLimitResponse(response.status,parsed,headers);let err=parsed?.error;err&&(message=err.message||friendlyMessage||message)}catch{}return{message,friendlyMessage}}function extractAccountId(token){return extractChatGptSubscriptionAccountId(token)}function buildCodexRoutingHint(modelId,serviceTier){return serviceTier?`model=${modelId};tier=${serviceTier}`:`model=${modelId}`}function buildBaseCodexHeaders(initHeaders,additionalHeaders,accountId,token,routingHint){let headers=new Headers(initHeaders);for(let[key,value]of Object.entries(additionalHeaders||{}))value===null?headers.delete(key):headers.set(key,value);headers.set("Authorization",`Bearer ${token}`),accountId?headers.set("chatgpt-account-id",accountId):headers.delete("chatgpt-account-id");let identity=getWireIdentity();headers.set("originator",identity);let userAgent=_os?`${identity} (${_os.platform()} ${_os.release()}; ${_os.arch()})`:`${identity} (browser)`;return headers.set("User-Agent",userAgent),headers.set("x-codex-routing-hint",routingHint),headers}function buildSSEHeaders(initHeaders,additionalHeaders,accountId,token,routingHint,sessionId){let headers=buildBaseCodexHeaders(initHeaders,additionalHeaders,accountId,token,routingHint);return headers.set("OpenAI-Beta","responses=experimental"),headers.set("accept","text/event-stream"),headers.set("content-type","application/json"),applyChatGptSubscriptionCacheAffinityHeaders(headers,sessionId),headers}function buildWebSocketHeaders(initHeaders,additionalHeaders,accountId,token,routingHint,requestId){let headers=buildBaseCodexHeaders(initHeaders,additionalHeaders,accountId,token,routingHint);return headers.delete("accept"),headers.delete("content-type"),headers.delete("OpenAI-Beta"),headers.delete("openai-beta"),headers.set("OpenAI-Beta",OPENAI_BETA_RESPONSES_WEBSOCKETS),applyChatGptSubscriptionCacheAffinityHeaders(headers,requestId),headers}export{closeChatGptSubscriptionWebSocketSessions,getChatGptSubscriptionWebSocketDebugStats,resetChatGptSubscriptionWebSocketDebugStats,stream,streamSimple};