@code-yeongyu/senpi 2026.10.10-10 → 2026.10.10-12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/dist/bundle/chunks/{anthropic-messages-2B35OVB7.js → anthropic-messages-I4Z6VKS3.js} +1 -1
  3. package/dist/bundle/chunks/{app-server-command-CV6N7JDD.js → app-server-command-EGTBOL5W.js} +2 -2
  4. package/dist/bundle/chunks/bun-extension-importer-QSQHKXVG.js +20 -0
  5. package/dist/bundle/chunks/{chunk-4WZF7G6N.js → chunk-2AYAOU6W.js} +12 -10
  6. package/dist/bundle/chunks/chunk-2ZGQRUGM.js +2506 -0
  7. package/dist/bundle/chunks/{chunk-ZPJHS64R.js → chunk-5BRVRFJI.js} +1 -1
  8. package/dist/bundle/chunks/chunk-6SBY4ZWC.js +2 -0
  9. package/dist/bundle/chunks/chunk-DRVT7RIO.js +2 -0
  10. package/dist/bundle/chunks/chunk-E75RO54O.js +14 -0
  11. package/dist/bundle/chunks/{chunk-ZCYTYHDN.js → chunk-IAYFQEXI.js} +1 -1
  12. package/dist/bundle/chunks/chunk-M4C6Z7UT.js +288 -0
  13. package/dist/bundle/chunks/chunk-N6HU6BEY.js +9 -0
  14. package/dist/bundle/chunks/chunk-NEFNNQSV.js +9 -0
  15. package/dist/bundle/chunks/{chunk-YI7SPFDN.js → chunk-Q3R44CGT.js} +2 -2
  16. package/dist/bundle/chunks/chunk-QKU6JOA4.js +2 -0
  17. package/dist/bundle/chunks/{chunk-JRGNL6WM.js → chunk-QXREUA5F.js} +1 -1
  18. package/dist/bundle/chunks/chunk-SIIACSBE.js +30 -0
  19. package/dist/bundle/chunks/{chunk-QQZREV6B.js → chunk-SSH4CLHJ.js} +1 -1
  20. package/dist/bundle/chunks/chunk-TOZBUPZP.js +3 -0
  21. package/dist/bundle/chunks/chunk-WASCMT6Y.js +2 -0
  22. package/dist/bundle/chunks/chunk-YU4AYH4C.js +2 -0
  23. package/dist/bundle/chunks/chunk-ZGCPUGLT.js +6 -0
  24. package/dist/bundle/chunks/{chunk-NTH33AXY.js → chunk-ZJOYLQXK.js} +1 -1
  25. package/dist/bundle/chunks/chunk-ZRWOLP4E.js +2 -0
  26. package/dist/bundle/chunks/cli-main-PANLBILV.js +3 -0
  27. package/dist/bundle/chunks/{help-fast-path-5P73752B.js → help-fast-path-IQAJFO2G.js} +1 -1
  28. package/dist/bundle/chunks/{host-command-MWQNTWFA.js → host-command-MWSVX37K.js} +1 -1
  29. package/dist/bundle/chunks/host-lifecycle-X2J5FTJL.js +3 -0
  30. package/dist/bundle/chunks/host-lifecycle.js +8 -8
  31. package/dist/bundle/chunks/interactive-mode-TQJU6K27.js +2 -0
  32. package/dist/bundle/chunks/multi-session-host-GBSMDUMG.js +26 -0
  33. package/dist/bundle/chunks/{package-manager-cli-PXP63ZPT.js → package-manager-cli-IBPABDGR.js} +1 -1
  34. package/dist/bundle/chunks/rotation-stream-JXT3JYW5.js +2 -0
  35. package/dist/bundle/chunks/rpc-mode-PFIAS2E5.js +2 -0
  36. package/dist/bundle/chunks/runtime-session-I4NDNGC5.js +2 -0
  37. package/dist/bundle/chunks/{schedule-command-MGZLHARF.js → schedule-command-Q4W37FAP.js} +1 -1
  38. package/dist/bundle/chunks/session-control-endpoint-YYFCJZXZ.js +3 -0
  39. package/dist/bundle/chunks/session-picker-YLDBGXTR.js +2 -0
  40. package/dist/bundle/chunks/session-worker.js +455 -448
  41. package/dist/bundle/cli.js +1 -1
  42. package/dist/bundle/index.js +1 -1
  43. package/dist/bundle/rpc-entry.js +1 -1
  44. package/dist/bundle/runtime-manifest.json +1 -1
  45. package/dist/cli/session-opening.d.ts +5 -0
  46. package/dist/cli/session-opening.js +11 -0
  47. package/dist/core/agent-session.d.ts +5 -0
  48. package/dist/core/agent-session.js +56 -33
  49. package/dist/core/engine-paused.d.ts +6 -0
  50. package/dist/core/engine-paused.js +50 -0
  51. package/dist/core/extensions/builtin/compaction/deterministic-fallback.d.ts +9 -2
  52. package/dist/core/extensions/builtin/compaction/deterministic-fallback.js +22 -45
  53. package/dist/core/extensions/builtin/compaction/index.js +55 -9
  54. package/dist/core/extensions/builtin/compaction/rejected-recovery.d.ts +11 -0
  55. package/dist/core/extensions/builtin/compaction/rejected-recovery.js +73 -0
  56. package/dist/core/extensions/builtin/compaction/retained-message-projection.d.ts +10 -0
  57. package/dist/core/extensions/builtin/compaction/retained-message-projection.js +102 -0
  58. package/dist/core/extensions/builtin/goal/continuation.js +2 -0
  59. package/dist/core/extensions/builtin/goal/direct-input-lifecycle.js +3 -1
  60. package/dist/core/extensions/builtin/goal/elapsed-ticker.js +2 -0
  61. package/dist/core/extensions/builtin/goal/format.d.ts +1 -1
  62. package/dist/core/extensions/builtin/goal/format.js +19 -4
  63. package/dist/core/extensions/builtin/goal/index.js +16 -9
  64. package/dist/core/extensions/builtin/goal/lifecycle-helpers.d.ts +1 -0
  65. package/dist/core/extensions/builtin/goal/lifecycle-helpers.js +57 -13
  66. package/dist/core/extensions/builtin/goal/monitor-continuation.js +2 -1
  67. package/dist/core/extensions/builtin/goal/persistence.js +2 -0
  68. package/dist/core/extensions/builtin/goal/renderers.js +9 -4
  69. package/dist/core/extensions/builtin/goal/store.d.ts +5 -0
  70. package/dist/core/extensions/builtin/goal/store.js +44 -0
  71. package/dist/core/extensions/builtin/goal/types.d.ts +10 -0
  72. package/dist/core/extensions/builtin/goal/types.js +4 -0
  73. package/dist/core/extensions/builtin/goal/ui.js +6 -3
  74. package/dist/core/extensions/builtin/mcp/index.js +4 -2
  75. package/dist/core/extensions/builtin/mcp/service-connection.js +1 -0
  76. package/dist/core/extensions/builtin/mcp/service-types.d.ts +2 -0
  77. package/dist/core/extensions/builtin/mcp/service.js +257 -74
  78. package/dist/core/extensions/builtin/terminal/process-identity.d.ts +1 -3
  79. package/dist/core/extensions/builtin/terminal/process-identity.js +1 -7
  80. package/dist/core/extensions/builtin/terminal/process-start-probe.js +11 -7
  81. package/dist/core/extensions/builtin/ttsr/index.js +19 -0
  82. package/dist/core/extensions/bun-extension-importer.d.ts +1 -1
  83. package/dist/core/extensions/bun-extension-importer.js +7 -3
  84. package/dist/core/extensions/extension-module-cache.d.ts +4 -3
  85. package/dist/core/extensions/extension-module-cache.js +8 -22
  86. package/dist/core/foreign-session-holders.d.ts +7 -0
  87. package/dist/core/foreign-session-holders.js +63 -0
  88. package/dist/core/moved-session-cwd.d.ts +7 -0
  89. package/dist/core/moved-session-cwd.js +23 -0
  90. package/dist/core/moved-sessions.d.ts +6 -0
  91. package/dist/core/moved-sessions.js +83 -24
  92. package/dist/core/resource-loader.js +5 -6
  93. package/dist/core/resume-target.js +3 -1
  94. package/dist/core/session-holders.d.ts +2 -1
  95. package/dist/core/session-holders.js +4 -4
  96. package/dist/core/session-manager.js +29 -10
  97. package/dist/core/webview/webview-readiness.d.ts +2 -0
  98. package/dist/core/webview/webview-readiness.js +9 -0
  99. package/dist/core/webview/webview-service.d.ts +4 -0
  100. package/dist/core/webview/webview-service.js +30 -5
  101. package/dist/main.js +14 -3
  102. package/dist/modes/app-server/daemon/process.d.ts +7 -1
  103. package/dist/modes/app-server/daemon/process.js +58 -6
  104. package/dist/modes/app-server/threads/goal-wire.js +2 -1
  105. package/dist/modes/interactive/interactive-mode.js +7 -0
  106. package/dist/modes/rpc/connection-handler.js +3 -2
  107. package/dist/modes/rpc/custom-capability.d.ts +2 -0
  108. package/dist/modes/rpc/custom-capability.js +2 -0
  109. package/dist/modes/rpc/host-capabilities.js +3 -1
  110. package/dist/modes/rpc/host-client-occupancy.d.ts +2 -1
  111. package/dist/modes/rpc/host-client-occupancy.js +3 -0
  112. package/dist/modes/rpc/host-daemon-registration.js +20 -6
  113. package/dist/modes/rpc/host-daemon-state.d.ts +17 -0
  114. package/dist/modes/rpc/host-daemon-state.js +60 -0
  115. package/dist/modes/rpc/host-ensure-start.js +13 -3
  116. package/dist/modes/rpc/host-ensure-stop.d.ts +1 -1
  117. package/dist/modes/rpc/host-ensure-stop.js +17 -4
  118. package/dist/modes/rpc/host-ensure-types.d.ts +2 -0
  119. package/dist/modes/rpc/host-ensure.js +20 -2
  120. package/dist/modes/rpc/host-gc-evidence.js +3 -0
  121. package/dist/modes/rpc/host-generations.js +4 -1
  122. package/dist/modes/rpc/host-legacy.d.ts +1 -1
  123. package/dist/modes/rpc/host-legacy.js +11 -2
  124. package/dist/modes/rpc/host-lifecycle-activity.d.ts +30 -0
  125. package/dist/modes/rpc/host-lifecycle-activity.js +136 -4
  126. package/dist/modes/rpc/host-lifecycle-launch.d.ts +4 -0
  127. package/dist/modes/rpc/host-lifecycle-launch.js +24 -1
  128. package/dist/modes/rpc/host-lifecycle-proxy.d.ts +2 -0
  129. package/dist/modes/rpc/host-lifecycle-proxy.js +4 -1
  130. package/dist/modes/rpc/host-lifecycle-scratch.js +5 -2
  131. package/dist/modes/rpc/host-lifecycle-shutdown.d.ts +1 -1
  132. package/dist/modes/rpc/host-lifecycle-shutdown.js +81 -37
  133. package/dist/modes/rpc/host-lifecycle.js +23 -1
  134. package/dist/modes/rpc/host-reservations.d.ts +2 -0
  135. package/dist/modes/rpc/host-reservations.js +61 -3
  136. package/dist/modes/rpc/host-stalled-evidence.js +17 -3
  137. package/dist/modes/rpc/host-stop-intent.d.ts +3 -0
  138. package/dist/modes/rpc/host-stop-intent.js +3 -0
  139. package/dist/modes/rpc/host-stop.js +4 -9
  140. package/dist/modes/rpc/host-successor.js +10 -3
  141. package/dist/modes/rpc/host-supervisor-log.d.ts +1 -0
  142. package/dist/modes/rpc/host-supervisor-log.js +9 -0
  143. package/dist/modes/rpc/multi-session-host.js +8 -6
  144. package/dist/modes/rpc/rpc-mode.d.ts +3 -1
  145. package/dist/modes/rpc/rpc-mode.js +3 -1
  146. package/dist/modes/rpc/rpc-types.d.ts +3 -1
  147. package/dist/modes/rpc/rpc-types.js +2 -0
  148. package/dist/modes/rpc/session-command-router.d.ts +1 -1
  149. package/dist/modes/rpc/session-command-router.js +18 -14
  150. package/dist/modes/rpc/session-held.d.ts +8 -0
  151. package/dist/modes/rpc/session-held.js +127 -0
  152. package/dist/modes/rpc/session-registry-types.d.ts +1 -1
  153. package/dist/modes/rpc/session-registry.d.ts +2 -0
  154. package/dist/modes/rpc/session-registry.js +4 -0
  155. package/dist/modes/rpc/session-worker-client.d.ts +3 -3
  156. package/dist/modes/rpc/session-worker-client.js +24 -12
  157. package/dist/modes/rpc/worker-session-claims.d.ts +15 -0
  158. package/dist/modes/rpc/worker-session-claims.js +61 -0
  159. package/dist/modes/rpc/worker-session-registry.d.ts +4 -0
  160. package/dist/modes/rpc/worker-session-registry.js +51 -8
  161. package/dist/utils/shell.d.ts +6 -2
  162. package/dist/utils/shell.js +20 -6
  163. package/docs/app-server.md +1 -1
  164. package/docs/rpc.md +75 -2
  165. package/docs/session-format.md +19 -0
  166. package/package.json +6 -6
  167. package/dist/bundle/chunks/bun-extension-importer-3TEDTSKJ.js +0 -20
  168. package/dist/bundle/chunks/chunk-5AKP2VFB.js +0 -16
  169. package/dist/bundle/chunks/chunk-6Y7VGPJB.js +0 -9
  170. package/dist/bundle/chunks/chunk-CIRZTP7W.js +0 -2
  171. package/dist/bundle/chunks/chunk-HKRW6HT5.js +0 -30
  172. package/dist/bundle/chunks/chunk-JEZWV7JW.js +0 -17
  173. package/dist/bundle/chunks/chunk-LR5EN45D.js +0 -7
  174. package/dist/bundle/chunks/chunk-MYVBK47X.js +0 -2
  175. package/dist/bundle/chunks/chunk-O6YOQUVX.js +0 -2773
  176. package/dist/bundle/chunks/chunk-TJPMB4VH.js +0 -2
  177. package/dist/bundle/chunks/chunk-U5KVIAHJ.js +0 -2
  178. package/dist/bundle/chunks/chunk-XMHO4QQN.js +0 -7
  179. package/dist/bundle/chunks/cli-main-TM4UFZVC.js +0 -3
  180. package/dist/bundle/chunks/host-lifecycle-B24G65GD.js +0 -3
  181. package/dist/bundle/chunks/interactive-mode-CBQW7WRK.js +0 -2
  182. package/dist/bundle/chunks/multi-session-host-4KXWGRNS.js +0 -25
  183. package/dist/bundle/chunks/rotation-stream-FQH63DMY.js +0 -2
  184. package/dist/bundle/chunks/rpc-mode-7WHJHMUP.js +0 -2
  185. package/dist/bundle/chunks/runtime-session-CWJNFRHY.js +0 -2
  186. package/dist/bundle/chunks/session-control-endpoint-OH7XV2FN.js +0 -3
  187. package/dist/bundle/chunks/session-picker-UUSW6YSU.js +0 -2
@@ -1,2 +0,0 @@
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{engineBuildIdentity}from"./chunk-ZJHRDQCH.js";import{HOST_GENERATION_ENV,HOST_INSTANCE_ID_ENV}from"./chunk-CIRZTP7W.js";import{parseArgs,resolveSessionRuntime}from"./chunk-VE3D74HN.js";import*as crypto from"node:crypto";var CUSTOM_UNSUPPORTED_CAPABILITY="custom_unsupported",EXTENSION_EVENTS_CAPABILITY="extension_events",AUTO_TITLE_SESSIONS_CAPABILITY="auto_title_sessions",CONTINUE_FROM_LEAF_CAPABILITY="continue_from_leaf",MEDIA_PLACEHOLDERS_CAPABILITY="media_placeholders",QUESTION_CAPABILITY="question",RETAIN_ON_DISCONNECT_CAPABILITY="retain_on_disconnect",SESSION_CONTEXT_CAPABILITY="session_context",SESSION_KIND_CAPABILITY="session_kind",AUTO_TITLE_PER_SESSION_CAPABILITY="auto_title_per_session",WARM_CAPABILITY="warm",DURABLE_SESSION_ID_CAPABILITY="durable_session_id",MOVED_PATH_GUARD_CAPABILITY="moved_path_guard",PROMPT_SURFACE_CAPABILITY="prompt_surface",BROWSER_ENGINE_CAPABILITY="browser_engine",RETRY_FALLBACK_PROFILE_CAPABILITY="retry_fallback_profile",RETRY_FALLBACK_COMMAND_CAPABILITY="retry_fallback_command",PROMPT_SURFACE_CHAT_CAPABILITY="prompt_surface_chat",RPC_CLIENT_CAPABILITIES_ENV="SENPI_RPC_CLIENT_CAPABILITIES";function parseClientCapabilities(value){return value?value.split(",").map(part=>part.trim()).filter(part=>part.length>0):[]}var DEFAULT_CUSTOM_EXTENSION_LABEL="custom UI component";function buildCustomUnsupportedRequest(capabilities,extensionName){if(!capabilities?.includes(CUSTOM_UNSUPPORTED_CAPABILITY))return;let name=extensionName.trim()||DEFAULT_CUSTOM_EXTENSION_LABEL;return{type:"extension_ui_request",id:crypto.randomUUID(),method:"custom_unsupported",extensionName:name}}import{createHash,randomUUID as randomUUID2}from"node:crypto";import{resolve}from"node:path";var INSTANCE_ID=resolveInstanceId(process.env[HOST_INSTANCE_ID_ENV]);function resolveInstanceId(value){return value!==void 0&&value.trim()!==""?value:randomUUID2()}function hostInstanceId(){return INSTANCE_ID}var cachedProfile;function hostGeneration(env){let value=env[HOST_GENERATION_ENV];return value!==void 0&&/^\d+$/.test(value)?Number(value):0}function hostLaunchProfile(argv,cwd){let parsed=parseArgs([...argv],{grokNeoEnabled:!1}),core={extensions:[...new Set((parsed.extensions??[]).map(path=>resolve(cwd,path)))].sort(),multi_session:parsed.multiSession===!0,session_runtime:resolveSessionRuntime(parsed)},canonical=JSON.stringify({extensions:core.extensions,multi_session:core.multi_session,session_runtime:core.session_runtime});return{profile_id:createHash("sha256").update(canonical).digest("hex"),core}}function socketHostLaunchProfile(hostArgs,cwd){return hostLaunchProfile(["--mode","rpc","--multi-session","--listen","unix://",...hostArgs],cwd)}function protocolIdentity(){cachedProfile??=hostLaunchProfile(process.argv.slice(2),process.cwd());let build=engineBuildIdentity();return{instanceId:INSTANCE_ID,generation:hostGeneration(process.env),engineVersion:build.text,engineOrdinal:build.ordinal,launch_profile:cachedProfile}}export{CUSTOM_UNSUPPORTED_CAPABILITY,EXTENSION_EVENTS_CAPABILITY,AUTO_TITLE_SESSIONS_CAPABILITY,CONTINUE_FROM_LEAF_CAPABILITY,MEDIA_PLACEHOLDERS_CAPABILITY,QUESTION_CAPABILITY,RETAIN_ON_DISCONNECT_CAPABILITY,SESSION_CONTEXT_CAPABILITY,SESSION_KIND_CAPABILITY,AUTO_TITLE_PER_SESSION_CAPABILITY,WARM_CAPABILITY,DURABLE_SESSION_ID_CAPABILITY,MOVED_PATH_GUARD_CAPABILITY,PROMPT_SURFACE_CAPABILITY,BROWSER_ENGINE_CAPABILITY,RETRY_FALLBACK_PROFILE_CAPABILITY,RETRY_FALLBACK_COMMAND_CAPABILITY,PROMPT_SURFACE_CHAT_CAPABILITY,RPC_CLIENT_CAPABILITIES_ENV,parseClientCapabilities,DEFAULT_CUSTOM_EXTENSION_LABEL,buildCustomUnsupportedRequest,hostInstanceId,hostGeneration,hostLaunchProfile,socketHostLaunchProfile,protocolIdentity};
@@ -1,2 +0,0 @@
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{uptime as osUptimeSeconds}from"node:os";var BOOT_INSTANT_TOLERANCE_MS=12e4,PROCESS_START_TOLERANCE_MS=3e3,wholeSeconds=ms=>Math.round(ms/1e3)*1e3;function processBootAtMs(now=Date.now){return wholeSeconds(now()-osUptimeSeconds()*1e3)}var floorToSecond=ms=>Math.floor(ms/1e3)*1e3,OWN_START_AT_LOAD=floorToSecond(Date.now()-process.uptime()*1e3);function ownProcessStartedAtMs(now){return now===void 0?OWN_START_AT_LOAD:floorToSecond(now()-process.uptime()*1e3)}function sameBoot(bootAtMs,otherBootAtMs){return otherBootAtMs===void 0||!Number.isFinite(otherBootAtMs)?!1:Math.abs(bootAtMs-otherBootAtMs)<=BOOT_INSTANT_TOLERANCE_MS}function sameProcessStart(startedAtMs,otherStartedAtMs){return otherStartedAtMs===void 0||!Number.isFinite(otherStartedAtMs)?!1:Math.abs(startedAtMs-otherStartedAtMs)<=PROCESS_START_TOLERANCE_MS}export{PROCESS_START_TOLERANCE_MS,processBootAtMs,ownProcessStartedAtMs,sameBoot,sameProcessStart};
@@ -1,7 +0,0 @@
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{ownProcessStartedAtMs,processBootAtMs,sameBoot,sameProcessStart}from"./chunk-U5KVIAHJ.js";import{APP_NAME,getAgentDir}from"./chunk-463OK2Y4.js";import{randomUUID}from"node:crypto";import{mkdir,readdir,readFile,rename,rm,stat,writeFile}from"node:fs/promises";import{dirname,join}from"node:path";var InvalidScheduledJobError=class extends Error{constructor(message){super(message),this.name="InvalidScheduledJobError"}};function isRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function requireString(raw,key){let value=raw[key];if(typeof value!="string"||value.length===0)throw new InvalidScheduledJobError(`scheduled job field "${key}" must be a non-empty string`);return value}function requireCount(raw,key){let value=raw[key];if(typeof value!="number"||!Number.isSafeInteger(value)||value<0)throw new InvalidScheduledJobError(`scheduled job field "${key}" must be a non-negative integer`);return value}function nullableCount(raw,key){return raw[key]===null||raw[key]===void 0?null:requireCount(raw,key)}function nullableString(raw,key){let value=raw[key];if(value==null)return null;if(typeof value!="string")throw new InvalidScheduledJobError(`scheduled job field "${key}" must be a string`);return value}function parseScheduledJob(raw){if(!isRecord(raw))throw new InvalidScheduledJobError("scheduled job must be a JSON object");if(raw.version!==1)throw new InvalidScheduledJobError(`unsupported scheduled job version: ${JSON.stringify(raw.version)}`);let id=requireString(raw,"id");if(!/^sch_[a-z0-9]{12}$/.test(id))throw new InvalidScheduledJobError(`invalid scheduled job id: ${id}`);let everyMs=nullableCount(raw,"everyMs");if(everyMs!==null&&everyMs<60*1e3)throw new InvalidScheduledJobError("scheduled job recurrence must be at least 60s");if(everyMs!==null&&everyMs>316224e5)throw new InvalidScheduledJobError("scheduled job recurrence must be at most 366 days");let prompt=requireString(raw,"prompt");if(Buffer.byteLength(prompt,"utf8")>16384)throw new InvalidScheduledJobError("scheduled job prompt exceeds 16384 bytes");let createdAt=requireCount(raw,"createdAt"),dueAt=requireCount(raw,"dueAt");return{version:1,id,sessionId:requireString(raw,"sessionId"),sessionFile:nullableString(raw,"sessionFile"),cwd:requireString(raw,"cwd"),prompt,createdAt,dueAt,everyMs,fireCount:requireCount(raw,"fireCount"),lastFiredAt:nullableCount(raw,"lastFiredAt"),lastError:nullableString(raw,"lastError")}}function nextRecurringDueAt(dueAt,everyMs,now){if(dueAt>now)return dueAt;let missed=Math.floor((now-dueAt)/everyMs)+1;return dueAt+missed*everyMs}function formatScheduledMessage(job,firedAt){let recurrence=job.everyMs===null?"":`, repeats every ${Math.round(job.everyMs/1e3)}s`;return`[Scheduled prompt ${job.id}: created ${new Date(job.createdAt).toISOString()}, due ${new Date(job.dueAt).toISOString()}, fired ${new Date(firedAt).toISOString()}${recurrence}]
3
- ${job.prompt}`}var STATE_DIRS=["pending","firing","failed"],JOB_ID=/^sch_[a-z0-9]{12}$/,RECORD_FILE=/^(sch_[a-z0-9]{12})(?:@(\d+)(?:~(\d+)-(\d+))?)?\.json$/;function scheduleDir(agentDir){return join(agentDir,"schedule")}function isScheduledJobId(id){return JOB_ID.test(id)}function isFileSystemError(error,code){return error instanceof Error&&"code"in error&&error.code===code}async function ensureDir(dir){await mkdir(dir,{recursive:!0,mode:448})}async function writeAtomic(filePath,contents){await ensureDir(dirname(filePath));let tempPath=join(dirname(filePath),`.schedule-${randomUUID()}.tmp`);try{await writeFile(tempPath,contents,{encoding:"utf8",mode:384}),await rename(tempPath,filePath)}catch(error){throw await rm(tempPath,{force:!0}),error}}function serialize(job){return`${JSON.stringify(job,null,2)}
4
- `}async function readJobFile(path2,expectedId){if((await stat(path2)).size>65536)throw new InvalidScheduledJobError(`scheduled job file exceeds ${65536} bytes`);let parsed;try{parsed=JSON.parse(await readFile(path2,"utf8"))}catch(error){throw isFileSystemError(error,"ENOENT")?error:new InvalidScheduledJobError("scheduled job file is not valid JSON")}let job=parseScheduledJob(parsed);if(job.id!==expectedId)throw new InvalidScheduledJobError(`scheduled job id ${job.id} does not match its file`);return job}async function listScheduledJobs(dir){let jobs=[],invalid=[];for(let state of STATE_DIRS){let names;try{names=await readdir(join(dir,state))}catch(error){if(isFileSystemError(error,"ENOENT"))continue;throw error}for(let name of names.sort()){let match=RECORD_FILE.exec(name);if(match===null)continue;let[,id,occurrence,pid,startedAt]=match,file=join(state,name);if(!(state==="pending"?occurrence===void 0:state==="firing"?pid!==void 0:occurrence!==void 0&&pid===void 0)||id===void 0){invalid.push({state,file,error:`unexpected record name for ${state}/`});continue}try{let job=await readJobFile(join(dir,file),id);jobs.push({state,job,file,...occurrence===void 0?{}:{occurrence:Number(occurrence)},...pid===void 0||startedAt===void 0?{}:{owner:{pid:Number(pid),processStartedAtMs:Number(startedAt)}}})}catch(error){if(isFileSystemError(error,"ENOENT"))continue;invalid.push({state,file,error:error instanceof Error?error.message:String(error)})}}}return jobs.sort((a,b)=>a.job.dueAt-b.job.dueAt),{jobs,invalid}}async function createScheduledJob(dir,input,now){let job=parseScheduledJob({version:1,id:`sch_${randomUUID().replace(/-/g,"").slice(0,12)}`,...input,createdAt:now,fireCount:0,lastFiredAt:null});return await writeAtomic(join(dir,"pending",`${job.id}.json`),serialize(job)),job}function tombstonePath(dir,id){return join(dir,"cancelled",id)}async function isCancelled(dir,id){try{return await stat(tombstonePath(dir,id)),!0}catch(error){if(isFileSystemError(error,"ENOENT"))return!1;throw error}}function runnersDir(dir){return join(dir,"runners")}import{randomUUID as randomUUID2}from"node:crypto";import{link,readdir as readdir2,rename as rename2,rm as rm2,stat as stat2,writeFile as writeFile2}from"node:fs/promises";import{join as join2}from"node:path";var TOMBSTONE_RETENTION_MS=1440*60*1e3;async function cancelScheduledJob(dir,id,options={}){if(!isScheduledJobId(id))return;let records=(await listScheduledJobs(dir)).jobs.filter(record=>record.job.id===id),representative=records.find(record=>record.state==="pending")??records[0];if(representative===void 0||options.sessionId!==void 0&&representative.job.sessionId!==options.sessionId)return;await writeAtomic(tombstonePath(dir,id),`${new Date().toISOString()}
5
- `);let inFlight=(await occurrenceNumbers(dir,"firing",id)).length>0;await rm2(join2(dir,"pending",`${id}.json`),{force:!0});let failed=records.filter(record=>record.state==="failed");for(let record of failed)await rm2(join2(dir,record.file),{force:!0});return{job:representative.job,inFlight,removedFailed:failed.length}}function occurrenceFile(id,occurrence,owner){return join2("firing",`${id}@${occurrence}~${owner.pid}-${owner.processStartedAtMs}.json`)}async function restorePending(dir,record,id){let pending2=join2(dir,"pending",`${id}.json`);try{await link(join2(dir,record),pending2)}catch(error){if(!isFileSystemError(error,"EEXIST"))throw error}await rm2(join2(dir,record),{force:!0}),await isCancelled(dir,id)&&await rm2(pending2,{force:!0})}async function claimOccurrence(dir,job,owner){let record=occurrenceFile(job.id,job.fireCount+1,owner);await ensureDir(join2(dir,"firing"));try{await rename2(join2(dir,"pending",`${job.id}.json`),join2(dir,record))}catch(error){if(isFileSystemError(error,"ENOENT"))return;throw error}if(await isCancelled(dir,job.id)){await rm2(join2(dir,record),{force:!0});return}if((await readJobFile(join2(dir,record),job.id)).fireCount!==job.fireCount){await restorePending(dir,record,job.id);return}return record}async function rearmRecurringJob(dir,next){if(await isCancelled(dir,next.id))return;let path2=join2(dir,"pending",`${next.id}.json`);await writeAtomic(path2,serialize(next)),await isCancelled(dir,next.id)&&await rm2(path2,{force:!0})}async function occurrenceNumbers(dir,state,id){let names;try{names=await readdir2(join2(dir,state))}catch(error){if(isFileSystemError(error,"ENOENT"))return[];throw error}let prefix=`${id}@`;return names.filter(name=>name.startsWith(prefix)).map(name=>Number.parseInt(name.slice(prefix.length),10)).filter(occurrence=>Number.isSafeInteger(occurrence))}async function restoreAbandonedSchedule(dir,job,occurrence,now){if(job.everyMs===null||await isCancelled(dir,job.id))return;let pending2=join2(dir,"pending",`${job.id}.json`);if(await stat2(pending2).then(()=>!0,()=>!1)||[...await occurrenceNumbers(dir,"firing",job.id),...await occurrenceNumbers(dir,"failed",job.id)].some(n=>n>occurrence))return;let next={...job,fireCount:occurrence,dueAt:nextRecurringDueAt(job.dueAt,job.everyMs,now),lastError:null};await ensureDir(join2(dir,"pending"));let temp=join2(dir,"pending",`.schedule-${randomUUID2()}.tmp`);try{await writeFile2(temp,serialize(next),{encoding:"utf8",mode:384}),await link(temp,pending2)}catch(error){if(!isFileSystemError(error,"EEXIST"))throw error;return}finally{await rm2(temp,{force:!0})}if(await isCancelled(dir,job.id)){await rm2(pending2,{force:!0});return}return next}async function settleOccurrence(dir,record,job,occurrence,outcome){if(!outcome.ok&&!await isCancelled(dir,job.id)){let failed=join2(dir,"failed",`${job.id}@${occurrence}.json`);await writeAtomic(failed,serialize({...job,lastError:outcome.error})),await isCancelled(dir,job.id)&&await rm2(failed,{force:!0});let older=(await occurrenceNumbers(dir,"failed",job.id)).sort((a,b)=>b-a);for(let stale of older.slice(10))await rm2(join2(dir,"failed",`${job.id}@${stale}.json`),{force:!0})}await rm2(join2(dir,record),{force:!0})}async function pruneTombstones(dir,listing,now){let names;try{names=await readdir2(join2(dir,"cancelled"))}catch(error){if(isFileSystemError(error,"ENOENT"))return;throw error}let live=new Set(listing.jobs.filter(record=>record.state!=="failed").map(record=>record.job.id));for(let id of names){if(!isScheduledJobId(id)||live.has(id))continue;let info=await stat2(tombstonePath(dir,id)).catch(()=>{});info!==void 0&&now-info.mtimeMs>TOMBSTONE_RETENTION_MS&&await rm2(tombstonePath(dir,id),{force:!0})}}import{mkdir as mkdir2,readdir as readdir3,stat as stat4}from"node:fs/promises";import{join as join3}from"node:path";import{randomUUID as randomUUID3}from"node:crypto";import{link as link2,open,readFile as readFile3,rename as rename3,stat as stat3,unlink}from"node:fs/promises";import{execFile}from"node:child_process";import{readFile as readFile2}from"node:fs/promises";var LINUX_CLOCK_TICKS_PER_SECOND=100;async function linuxProcessStartMs(pid){let[stat6,systemStat]=await Promise.all([readFile2(`/proc/${pid}/stat`,"utf8"),readFile2("/proc/stat","utf8")]),afterComm=stat6.slice(stat6.lastIndexOf(")")+2).split(" "),startTicks=Number(afterComm[19]),bootSeconds=Number(/^btime (\d+)/m.exec(systemStat)?.[1]);if(!(!Number.isFinite(startTicks)||!Number.isFinite(bootSeconds)))return Math.round((bootSeconds+startTicks/LINUX_CLOCK_TICKS_PER_SECOND)*1e3)}function execText(command,args){return new Promise((resolve3,reject)=>{execFile(command,[...args],{encoding:"utf8",timeout:5e3,windowsHide:!0},(error,stdout)=>{error?reject(error):resolve3(stdout)})})}async function darwinProcessStartMs(pid){let text=(await execText("ps",["-o","lstart=","-p",String(pid)])).trim();if(text.length===0)return;let parsed=new Date(text).getTime();return Number.isFinite(parsed)?parsed:void 0}async function windowsProcessStartMs(pid){let script=`(Get-Process -Id ${pid} -ErrorAction Stop).StartTime.ToUniversalTime().ToString('o')`,text=(await execText("powershell",["-NoProfile","-NonInteractive","-Command",script])).trim(),parsed=new Date(text).getTime();return Number.isFinite(parsed)?parsed:void 0}async function readProcessStartMs(pid){try{switch(process.platform){case"linux":return await linuxProcessStartMs(pid);case"darwin":return await darwinProcessStartMs(pid);case"win32":return await windowsProcessStartMs(pid);default:return}}catch{return}}function errorCode(error){if(typeof error=="object"&&error!==null&&"code"in error&&typeof error.code=="string")return error.code}async function unlinkIfPresent(path2){try{await unlink(path2)}catch(error){if(errorCode(error)!=="ENOENT")throw error}}async function readLeaseText(path2){try{return await readFile3(path2,"utf8")}catch(error){if(errorCode(error)==="ENOENT")return;throw error}}async function writeTemp(path2,content,mode){let temp=`${path2}.${process.pid}.${randomUUID3().slice(0,8)}.tmp`,file=await open(temp,"wx",mode);try{await file.writeFile(content,"utf8")}finally{await file.close()}return temp}async function publishExclusive(path2,content,options={}){let temp=await writeTemp(path2,content,options.mode);try{await link2(temp,path2)}catch(error){let code=errorCode(error);if(code!=="ENOTSUP"&&code!=="EOPNOTSUPP"&&code!=="EPERM")throw error;let file=await open(path2,"wx",options.mode);try{await file.writeFile(content,"utf8")}finally{await file.close()}}finally{await unlinkIfPresent(temp)}}async function publishReplace(path2,content,options={}){let temp=await writeTemp(path2,content,options.mode);try{await rename3(temp,path2)}catch(error){throw await unlinkIfPresent(temp),error}}function pidAlive(pid){try{return process.kill(pid,0),!0}catch(error){return errorCode(error)==="EPERM"}}var UNREADABLE_LOCK_STALE_MS=3e4;function readLockHolder(raw){try{let parsed=JSON.parse(raw);if(typeof parsed!="object"||parsed===null||!("pid"in parsed)||!("bootAtMs"in parsed)||!("processStartedAtMs"in parsed))return;let{pid,bootAtMs,processStartedAtMs}=parsed;return typeof pid!="number"||typeof bootAtMs!="number"||typeof processStartedAtMs!="number"?void 0:{pid,bootAtMs,processStartedAtMs}}catch{return}}async function reclaimLockState(lock,probes={}){let raw=await readLeaseText(lock);if(raw===void 0)return{state:"free"};let holder=readLockHolder(raw);if(holder===void 0)return await stat3(lock).then(info=>Date.now()-info.mtimeMs,()=>0)>UNREADABLE_LOCK_STALE_MS?{state:"stale",raw}:{state:"held"};if(!sameBoot(holder.bootAtMs,processBootAtMs()))return{state:"stale",raw};if(holder.pid===process.pid)return sameProcessStart(holder.processStartedAtMs,ownProcessStartedAtMs())?{state:"held",holder}:{state:"stale",raw};if(!(probes.isProcessAlive??pidAlive)(holder.pid))return{state:"stale",raw};let observed=await(probes.readProcessStartMs??readProcessStartMs)(holder.pid).catch(()=>{});return observed===void 0||sameProcessStart(holder.processStartedAtMs,observed)?{state:"held",holder}:{state:"stale",raw}}async function breakStaleLock(lock,raw){let aside=`${lock}.${process.pid}.${randomUUID3().slice(0,8)}.broken`;try{await rename3(lock,aside)}catch(error){if(errorCode(error)==="ENOENT")return;throw error}let moved=await readFile3(aside,"utf8");if(moved!==raw)try{await publishExclusive(lock,moved)}catch(error){if(errorCode(error)!=="EEXIST")throw error}await unlinkIfPresent(aside)}async function takeReclaimLock(lock,probes){let mine=JSON.stringify({pid:process.pid,bootAtMs:processBootAtMs(),processStartedAtMs:ownProcessStartedAtMs()});for(let attempt=0;attempt<3;attempt+=1){try{return await publishExclusive(lock,mine),mine}catch(error){if(errorCode(error)!=="EEXIST")throw error}let seen=await reclaimLockState(lock,probes);if(seen.state==="held")return{holder:seen.holder};seen.state==="stale"&&await breakStaleLock(lock,seen.raw)}return{}}async function reclaimInspected(path2,inspected,probes={}){let lock=`${path2}.lock`,taken=await takeReclaimLock(lock,probes);if(typeof taken!="string")return{outcome:"busy",...taken.holder?{holder:taken.holder}:{}};try{return await readLeaseText(path2)!==inspected?{outcome:"changed"}:(await unlinkIfPresent(path2),{outcome:"removed"})}finally{await readLeaseText(lock)===taken&&await unlinkIfPresent(lock)}}var RUNNER_HEARTBEAT_STALE_MS=12e4,RUNNER_HEARTBEAT_INTERVAL_MS=3e4,DEFAULT_MAX_DELIVERY_MS=9e5,PRIVATE={mode:384};function ownRunnerIdentity(){return{pid:process.pid,processStartedAtMs:ownProcessStartedAtMs()}}function leasePath(dir,pid){return join3(runnersDir(dir),`${pid}.json`)}async function writeRunnerLease(dir,lease,now){await mkdir2(runnersDir(dir),{recursive:!0,mode:448});let identity=ownRunnerIdentity();await publishReplace(leasePath(dir,identity.pid),JSON.stringify({...identity,bootAtMs:processBootAtMs(),beatAt:now,...lease}),PRIVATE)}async function removeRunnerLease(dir){await unlinkIfPresent(leasePath(dir,process.pid))}function parseLease(raw){try{let parsed=JSON.parse(raw);if(typeof parsed!="object"||parsed===null)return;let beatAt="beatAt"in parsed?parsed.beatAt:void 0;if(typeof beatAt!="number")return;let watch="watch"in parsed&&parsed.watch===!0,exec="exec"in parsed&&typeof parsed.exec=="string"?parsed.exec:null;return{beatAt,watch,exec}}catch{return}}async function liveRunners(dir){let names;try{names=await readdir3(runnersDir(dir))}catch(error){if(error instanceof Error&&"code"in error&&error.code==="ENOENT")return[];throw error}let runners=[];for(let name of names){if(!/^\d+\.json$/.test(name))continue;let path2=join3(runnersDir(dir),name),state=await reclaimLockState(path2);if(state.state==="stale"&&await breakStaleLock(path2,state.raw),state.state!=="held"||state.holder===void 0)continue;let raw=await readLeaseText(path2),lease=raw===void 0?void 0:parseLease(raw);lease!==void 0&&runners.push({pid:state.holder.pid,processStartedAtMs:state.holder.processStartedAtMs,...lease})}return runners}async function isWatchRunnerAvailable(dir,now){return(await liveRunners(dir)).some(runner=>runner.watch&&now-runner.beatAt<=RUNNER_HEARTBEAT_STALE_MS)}function isOwnerAmong(owner,runners){return runners.some(runner=>runner.pid===owner.pid&&sameProcessStart(runner.processStartedAtMs,owner.processStartedAtMs))}function sessionLockPath(dir,sessionId){return join3(dir,"sessions",`${encodeURIComponent(sessionId)}.lock`)}function isDeliveryGroupAlive(pid){try{return process.kill(process.platform==="win32"?pid:-pid,0),!0}catch(error){return errorCode(error)==="EPERM"}}function isPidAlive(pid){try{return process.kill(pid,0),!0}catch(error){return errorCode(error)==="EPERM"}}async function orphanedDelivery(raw,lockAgeMs,probes){let parsed;try{parsed=JSON.parse(raw)}catch{return}if(typeof parsed!="object"||parsed===null)return;let field=key=>key in parsed?Reflect.get(parsed,key):void 0,boot=field("bootAtMs");if(typeof boot!="number"||!sameBoot(boot,processBootAtMs()))return;let pid=field("deliveryPid"),startedAt=field("deliveryStartedAtMs");if(typeof pid!="number"||typeof startedAt!="number"){let maxDeliveryMs=field("maxDeliveryMs"),runner=field("pid");return field("gated")===!1&&typeof maxDeliveryMs=="number"&&lockAgeMs<=maxDeliveryMs&&typeof runner=="number"?runner:void 0}if(!isDeliveryGroupAlive(pid))return;if(!isPidAlive(pid))return pid;let leaderStart=await(probes.readProcessStartMs??readProcessStartMs)(pid).catch(()=>{});return leaderStart!==void 0&&sameProcessStart(startedAt,leaderStart)?pid:void 0}async function acquireSessionDeliveryLock(dir,sessionId,options={}){let probes=options,path2=sessionLockPath(dir,sessionId),identity={pid:process.pid,bootAtMs:processBootAtMs(),processStartedAtMs:ownProcessStartedAtMs(),gated:options.gated??process.platform!=="win32",maxDeliveryMs:options.maxDeliveryMs??DEFAULT_MAX_DELIVERY_MS},mine=JSON.stringify(identity);for(let attempt=0;attempt<3;attempt+=1){try{await publishExclusive(path2,mine,PRIVATE);let tail=Promise.resolve(),serialized=operation=>{let run=tail.then(operation);return tail=run.catch(()=>{}),run};return{acquired:!0,attachDelivery:pid=>serialized(async()=>{let startedAt=Math.floor(Date.now()/1e3)*1e3;if(await readLeaseText(path2)!==mine)throw new Error("session delivery lock was lost");let next=JSON.stringify({...identity,deliveryPid:pid,deliveryStartedAtMs:startedAt});await publishReplace(path2,next,PRIVATE),mine=next}),release:()=>serialized(async()=>{await readLeaseText(path2)===mine&&await unlinkIfPresent(path2)})}}catch(error){let code=errorCode(error);if(code==="ENOENT"){await mkdir2(join3(dir,"sessions"),{recursive:!0,mode:448});continue}if(code!=="EEXIST")throw error}let state=await reclaimLockState(path2);if(state.state==="held")return{acquired:!1,heldByPid:state.holder?.pid};if(state.state==="stale"){let lockAgeMs=await stat4(path2).then(info=>Date.now()-info.mtimeMs,()=>0),delivering=await orphanedDelivery(state.raw,lockAgeMs,probes);if(delivering!==void 0)return{acquired:!1,heldByPid:delivering};await breakStaleLock(path2,state.raw)}}return{acquired:!1,heldByPid:void 0}}import{randomUUID as randomUUID5}from"node:crypto";import{existsSync as existsSync2,mkdirSync,readFileSync,renameSync,rmdirSync,statSync as statSync2,unlinkSync,writeFileSync}from"node:fs";import{readdir as readdir4}from"node:fs/promises";import{dirname as dirname6,join as join9}from"node:path";import{accessSync,existsSync,lstatSync as lstatSync2,realpathSync,statSync}from"node:fs";import{homedir as homedir3}from"node:os";import{basename as basename3,dirname as dirname4,join as join7,resolve as resolve2}from"node:path";import{closeSync,constants,fstatSync,lstatSync,openSync,readSync}from"node:fs";import{lstat,open as open2}from"node:fs/promises";import{join as join5}from"node:path";import path,{posix,win32}from"node:path";var MOVED_BREADCRUMB_FILE="omo-desktop-moved.json",MOVED_BREADCRUMB_KIND="omo-desktop-moved",MOVED_BREADCRUMB_SCHEMA_VERSION=1;function ignored(reason){return{kind:"ignored",reason}}function prefixSegments(prefix){if(typeof prefix!="string"||posix.isAbsolute(prefix)||win32.isAbsolute(prefix))return;let segments=prefix.split(/[\\/]/).filter(segment=>segment.length>0);if(!(segments.length===0||segments.some(segment=>segment==="."||segment==="..")))return segments}function isNormalizedAbsolute(value,host){return!host.isAbsolute(value)||host.normalize(value)!==value?!1:value===host.parse(value).root||!(value.endsWith("/")||value.endsWith(host.sep))}function parseMovedBreadcrumb(raw,host=path){if(typeof raw!="object"||raw===null)return ignored("not an object");let record=raw;if(record.kind!==MOVED_BREADCRUMB_KIND)return ignored("foreign kind");let version=record.schemaVersion;if(typeof version!="number"||!Number.isInteger(version)||version<1)return ignored("invalid schemaVersion");if(version>MOVED_BREADCRUMB_SCHEMA_VERSION)return ignored(`unsupported schemaVersion ${version}`);let movedTo=record.movedTo;if(typeof movedTo!="string"||!isNormalizedAbsolute(movedTo,host))return ignored("movedTo is not a normalized absolute path on this host");let homeId=record.homeId;if(typeof homeId!="string"||homeId.length===0)return ignored("homeId is missing");if(!Array.isArray(record.moved))return ignored("moved is not an array");let moved=[];for(let prefix of record.moved){let segments=prefixSegments(prefix);if(!segments)return ignored(`invalid moved prefix ${JSON.stringify(prefix)}`);moved.push(segments)}return{kind:"valid",breadcrumb:{movedTo,homeId,moved}}}import{appendFile,mkdir as mkdir3,rename as rename4,stat as stat5}from"node:fs/promises";import{dirname as dirname2,join as join4}from"node:path";var MAX_GUARD_LOG_BYTES=1024*1024,reported=new Set,pending=Promise.resolve();function guardLogPath(){return join4(getAgentDir(),"logs","moved-path-guard.log")}async function append(line){let file=guardLogPath();await mkdir3(dirname2(file),{recursive:!0,mode:448}),await stat5(file).then(stats=>stats.size,()=>0)+Buffer.byteLength(line)>MAX_GUARD_LOG_BYTES&&await rename4(file,`${file}.1`),await appendFile(file,line,{mode:384})}function logGuardEvent(level,event,details){let{count:_count,...reason}=details,key=`${event}\0${JSON.stringify(reason)}`;if(reported.has(key))return;reported.add(key);let line=`${JSON.stringify({ts:new Date().toISOString(),level,event,...details})}
6
- `;pending=pending.then(()=>append(line)).catch(()=>{})}var DESKTOP_HOME_MARKER_FILE="omo-desktop-home.json";function parseDesktopHomeMarker(raw){if(typeof raw!="object"||raw===null)return{kind:"invalid"};let record=raw;return record.kind!=="omo-desktop-data-home"||record.appId!=="com.omo.desktop"?{kind:"invalid"}:typeof record.schemaVersion=="number"&&record.schemaVersion>1?{kind:"newer",schemaVersion:record.schemaVersion}:record.schemaVersion!==1||typeof record.homeId!="string"||record.homeId.length===0?{kind:"invalid"}:{kind:"valid",homeId:record.homeId}}function currentPathPlatform(){return process.platform==="win32"?"win32":process.platform==="darwin"?"darwin":"posix"}function pathSegments(path2,platform){return platform!=="win32"?path2.split("/").filter(segment=>segment.length>0):(path2.startsWith("\\\\?\\UNC\\")?`\\\\${path2.slice(8)}`:path2.startsWith("\\\\?\\")?path2.slice(4):path2).split(/[\\/]/).filter(segment=>segment.length>0)}function sameSegment(a,b,platform){return platform==="posix"?a===b:a.toLowerCase()===b.toLowerCase()}function startsWithSegments(path2,prefix,platform){return prefix.length<=path2.length&&prefix.every((segment,index)=>sameSegment(path2[index]??"",segment,platform))}function matchMovedPrefix(path2,root,moved,platform){let pathParts=pathSegments(path2,platform),rootParts=pathSegments(root,platform);if(!startsWithSegments(pathParts,rootParts,platform))return;let remainder=pathParts.slice(rootParts.length),prefix=moved.find(candidate=>startsWithSegments(remainder,candidate,platform));return prefix?{prefix,remainder}:void 0}var MAX_HOPS=3,MAX_TRUST_FILE_BYTES=64*1024,jsonByFile=new Map;function parseJson(text){try{return JSON.parse(text)}catch{return}}function trustStamp(stats){if(!(!stats.isFile()||stats.size>MAX_TRUST_FILE_BYTES)&&!(process.platform!=="win32"&&(stats.uid!==process.getuid?.()||(stats.mode&18)!==0)))return`${stats.mtimeMs}:${stats.size}:${stats.ino}`}var OPEN_FLAGS=constants.O_RDONLY|(constants.O_NOFOLLOW??0)|(constants.O_NONBLOCK??0),NEEDS_LSTAT_FIRST=constants.O_NONBLOCK===void 0;function remembered(file,stamp,read){let cached=jsonByFile.get(file);if(cached?.stamp===stamp)return cached.value;let value=parseJson(read().toString("utf8"));return jsonByFile.set(file,{stamp,value}),value}function readJsonFileSync(file){let fd;try{if(NEEDS_LSTAT_FIRST&&!lstatSync(file).isFile())return;fd=openSync(file,OPEN_FLAGS)}catch{return}try{let stats=fstatSync(fd),stamp=trustStamp(stats);return stamp===void 0?void 0:remembered(file,stamp,()=>{let buffer=Buffer.alloc(stats.size);return buffer.subarray(0,readSync(fd,buffer,0,stats.size,0))})}finally{closeSync(fd)}}async function readJsonFileAsync(file){if(NEEDS_LSTAT_FIRST&&!await lstat(file).then(stats=>stats.isFile(),()=>!1))return;let handle=await open2(file,OPEN_FLAGS).catch(()=>{});if(handle)try{let stats=await handle.stat(),stamp=trustStamp(stats);if(stamp===void 0)return;let cached=jsonByFile.get(file);if(cached?.stamp===stamp)return cached.value;let buffer=Buffer.alloc(stats.size),{bytesRead}=await handle.read(buffer,0,stats.size,0);return remembered(file,stamp,()=>buffer.subarray(0,bytesRead))}finally{await handle.close()}}var breadcrumbFile=dir=>join5(dir,MOVED_BREADCRUMB_FILE),homeMarkerFile=movedTo=>join5(movedTo,DESKTOP_HOME_MARKER_FILE);function ignoreBreadcrumb(file,reason){logGuardEvent("debug","breadcrumb_ignored",{file,reason})}function movedToInHome(dir,breadcrumb,homes,platform){return homes.some(home=>matchMovedPrefix(breadcrumb.movedTo,home,[[]],platform))?!0:(ignoreBreadcrumb(breadcrumbFile(dir),"movedTo is outside the user's home"),!1)}function trustedFolder(dir,stats){return stats===void 0?!1:process.platform==="win32"||stats.isDirectory()&&stats.uid===process.getuid?.()&&(stats.mode&18)===0?!0:(ignoreBreadcrumb(breadcrumbFile(dir),"its folder is shared or not the user's"),!1)}function parsedBreadcrumb(dir,raw){if(raw===void 0)return;let parsed=parseMovedBreadcrumb(raw);return parsed.kind==="valid"?parsed.breadcrumb:ignoreBreadcrumb(breadcrumbFile(dir),parsed.reason)}function trustedBreadcrumb(dir,breadcrumb,markerRaw,platform){if(matchMovedPrefix(breadcrumb.movedTo,dir,[[]],platform))return ignoreBreadcrumb(breadcrumbFile(dir),"movedTo is the breadcrumb's own folder or inside it");let marker=parseDesktopHomeMarker(markerRaw);if(marker.kind==="newer"){logGuardEvent("warn","marker_newer",{file:homeMarkerFile(breadcrumb.movedTo),schemaVersion:String(marker.schemaVersion)});return}return marker.kind!=="valid"||marker.homeId!==breadcrumb.homeId?ignoreBreadcrumb(breadcrumbFile(dir),"movedTo holds no desktop home marker with this homeId"):breadcrumb}function movedMatch(dir,breadcrumb,canonical,platform){let match=matchMovedPrefix(canonical,dir,breadcrumb.moved,platform);if(match)return{prefix:match.prefix,moved:{oldRoot:dir,movedTo:breadcrumb.movedTo,mappedPath:join5(breadcrumb.movedTo,...match.remainder)}}}var gitEntryOf=(oldRoot,prefix)=>prefix.includes("worktrees")?join5(oldRoot,...prefix,".git"):void 0;function movedPathReason(moved){return`This folder moved to ${moved.movedTo}. Use ${moved.mappedPath}.`}import{homedir as homedir2}from"node:os";import{basename as basename2,dirname as dirname3,resolve}from"node:path";import{homedir}from"node:os";import{basename,join as join6}from"node:path";var LEGACY_ROOT_NAMES=[".t3",".omo-app"],legacyRoots=()=>LEGACY_ROOT_NAMES.map(name=>join6(homedir(),name)),isLegacyRoot=(path2,homes,platform)=>homes.some(home=>LEGACY_ROOT_NAMES.some(name=>matchMovedPrefix(path2,join6(home,name),[[]],platform)?.remainder.length===0)),known=new Map,prefixKey=(oldRoot,breadcrumb,prefix)=>[basename(oldRoot).toLowerCase(),breadcrumb.homeId,breadcrumb.movedTo,prefix.join("/")].join("\0");function knownPrefixKeys(path2,platform=currentPathPlatform()){return[...known].flatMap(([spelling,{root,breadcrumb}])=>{let match=matchMovedPrefix(path2,spelling,breadcrumb.moved,platform);return match?[prefixKey(root,breadcrumb,match.prefix)]:[]})}var reusedDecisions=new Map;function rememberReused(key,reused){reusedDecisions.set(key,reused)}function rememberedReused(key){return reusedDecisions.get(key)}function rememberTrustedBreadcrumb(root,called,breadcrumb,homes,platform){let spellings=new Set(called===void 0?[root]:[root,called]);for(let spelling of[...spellings])for(let home of homes){let under=matchMovedPrefix(spelling,home,[[]],platform);if(under)for(let other of homes)spellings.add(join6(other,...under.remainder))}for(let spelling of spellings)known.set(spelling,{root,breadcrumb})}function looksMoved(path2,platform=currentPathPlatform()){return legacyRoots().some(root=>matchMovedPrefix(path2,root,[[]],platform))||[...known].some(([spelling,{breadcrumb}])=>matchMovedPrefix(path2,spelling,breadcrumb.moved,platform))}function knownMove(path2,platform=currentPathPlatform()){for(let[oldRoot,{root,breadcrumb}]of known){let match=matchMovedPrefix(path2,oldRoot,breadcrumb.moved,platform);if(match&&rememberedReused(prefixKey(root,breadcrumb,match.prefix))!==!0)return{oldRoot,movedTo:breadcrumb.movedTo,mappedPath:join6(breadcrumb.movedTo,...match.remainder)}}}function*homeSpellings(){let home=homedir2(),real=yield{op:"home"};return real!==void 0&&real!==home?[home,real]:[home]}function calledSpelling(path2,canonical,dir,homes,platform){let called=resolve(path2);for(let below=canonical;below!==dir;below=dirname3(below)){if(dirname3(called)===called||!sameSegment(basename2(called),basename2(below),platform))return;called=dirname3(called)}return isLegacyRoot(called,homes,platform)?called:void 0}function*movedOnce(path2,platform,onReused){let canonical=(yield{op:"canonical",path:path2})??resolve(path2),stop=dirname3(homedir2());for(let dir=dirname3(canonical);;dir=dirname3(dir)){let breadcrumb=parsedBreadcrumb(dir,yield{op:"json",file:breadcrumbFile(dir)}),match=breadcrumb&&movedMatch(dir,breadcrumb,canonical,platform),homes=match?yield*homeSpellings():[];if(match&&movedToInHome(dir,breadcrumb,homes,platform)&&trustedFolder(dir,yield{op:"folder",path:dir,follow:isLegacyRoot(dir,homes,platform)})&&trustedBreadcrumb(dir,breadcrumb,yield{op:"json",file:homeMarkerFile(breadcrumb.movedTo)},platform)){let gitEntry=gitEntryOf(dir,match.prefix),reused=!1;if(gitEntry!==void 0){let key=prefixKey(dir,breadcrumb,match.prefix),answer2=yield{op:"exists",path:gitEntry};typeof answer2=="boolean"&&rememberReused(key,answer2),reused=typeof answer2=="boolean"?answer2:rememberedReused(key)??!1}if(reused&&onReused?.(dir,breadcrumb,match.prefix),rememberTrustedBreadcrumb(dir,calledSpelling(path2,canonical,dir,homes,platform),breadcrumb,homes,platform),!reused)return match.moved}if(dir===stop||dirname3(dir)===dir)return}}function*movedPathWalk(path2,platform,onReused){let found;for(let hop=0;hop<MAX_HOPS;hop++){let next=yield*movedOnce(found?.mappedPath??path2,platform,onReused);if(!next)break;found=found?{...next,oldRoot:found.oldRoot}:next}return found}function canonicalPath(path2){let missing=[],existing=resolve2(path2);for(;!existsSync(existing);){let parent=dirname4(existing);if(parent===existing)return resolve2(path2);missing.unshift(basename3(existing)),existing=parent}return join7(realpathSync(existing),...missing)}function pathExistsSync(path2){try{return accessSync(path2),!0}catch(error){let code=error?.code;return code==="ENOENT"||code==="ENOTDIR"?!1:void 0}}function answer(step){try{return step.op==="canonical"?canonicalPath(step.path):step.op==="json"?readJsonFileSync(step.file):step.op==="home"?realpathSync(homedir3()):step.op==="folder"?(step.follow?statSync:lstatSync2)(step.path):pathExistsSync(step.path)}catch{return void 0}}function findMovedPath(path2,platform=currentPathPlatform()){let walk=movedPathWalk(path2,platform),step=walk.next();for(;!step.done;)step=walk.next(answer(step.value));return step.value}function resolveMovedPath(path2){return findMovedPath(path2)?.mappedPath??path2}var SessionHeldError=class extends Error{constructor(sessionFile,holders){let who=holders.map(h=>h.cwd?`pid ${h.pid} in ${h.cwd}`:`pid ${h.pid}`).join("; ");super(`This session is open in another ${APP_NAME} process (${who}). Quit it there, then try again.`),this.code="ESESSIONHELD",this.name="SessionHeldError",this.sessionFile=sessionFile,this.holders=holders}},SessionMovingError=class extends Error{constructor(sessionFile,moverPid){let who=moverPid===void 0?"another process":`another process (pid ${moverPid})`;super(`Session ${sessionFile} is being moved by ${who}. Try again in a moment.`),this.code="ESESSIONMOVING",this.name="SessionMovingError",this.moverPid=moverPid}},SessionMovedError=class extends Error{constructor(sessionFile){super(`Session ${sessionFile} no longer exists: another process moved it. Resume it from its new location.`),this.code="ESESSIONMOVED",this.name="SessionMovedError"}};import{randomUUID as randomUUID4}from"node:crypto";import{mkdir as mkdir4,readFile as readFile4,rename as rename5,rm as rm3,writeFile as writeFile3}from"node:fs/promises";import{dirname as dirname5,join as join8}from"node:path";var InvalidSidecarStoreError=class extends Error{constructor(message,options){super(message,options),this.name="InvalidSidecarStoreError"}},UnsupportedSidecarStoreVersionError=class extends Error{constructor(message){super(message),this.name="UnsupportedSidecarStoreVersionError"}},mutationTails=new Map,snapshots=new Map;function encodedSessionId(sessionId){return encodeURIComponent(sessionId)}function sidecarFilePath(ref){return join8(ref.baseDir,`${encodedSessionId(ref.sessionId)}.json`)}function createSidecarStore(options){let ref={baseDir:options.baseDir,sessionId:options.sessionId},filePath=sidecarFilePath(ref);async function read(){let raw;try{raw=await readFile4(filePath,"utf8")}catch(error){if(isFileSystemError2(error,"ENOENT"))return null;throw error}let state=parsePayload(raw,options,ref);return snapshots.set(filePath,state),state}async function write(state){await mkdir4(dirname5(filePath),{recursive:!0}),await writeAtomic2(filePath,`${JSON.stringify(state,null,2)}
7
- `,options.tempPrefix),snapshots.set(filePath,state)}function mutate(fn){return serializeByKey(filePath,async()=>{let next=await fn(await read());return await write(next),next})}return{filePath,read,write,mutate,snapshot:()=>snapshots.get(filePath),clear:()=>{snapshots.delete(filePath)}}}async function writeAtomic2(filePath,contents,tempPrefix){let tempPath=join8(dirname5(filePath),`.${tempPrefix}-${randomUUID4()}.tmp`);try{await writeFile3(tempPath,contents,{encoding:"utf8",mode:384}),await rename5(tempPath,filePath)}catch(error){try{await rm3(tempPath,{force:!0})}catch(cleanupError){throw new AggregateError([error,cleanupError],"sidecar store write failed and its temporary file could not be removed")}throw error}}function parsePayload(raw,options,ref){let parsed;try{parsed=JSON.parse(raw)}catch(error){throw new InvalidSidecarStoreError("sidecar store contains unparseable JSON",{cause:error})}if(!isRecord2(parsed))throw new InvalidSidecarStoreError("sidecar store must be a JSON object");if(parsed.version!==options.version)throw new UnsupportedSidecarStoreVersionError(`unsupported sidecar store version: ${JSON.stringify(parsed.version)} (expected ${options.version})`);if(typeof parsed.sessionId!="string"||parsed.sessionId.length===0)throw new InvalidSidecarStoreError("sidecar store is missing a sessionId");if(parsed.sessionId!==ref.sessionId)throw new InvalidSidecarStoreError(`sidecar store sessionId ${parsed.sessionId} does not match the session it was loaded for`);return options.parse(parsed,ref)}function serializeByKey(key,operation){let run=(mutationTails.get(key)??Promise.resolve()).then(operation),tail=run.then(()=>{},()=>{});return mutationTails.set(key,tail),tail.then(()=>{mutationTails.get(key)===tail&&mutationTails.delete(key)}),run}function isRecord2(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function isFileSystemError2(error,code){return error instanceof Error&&"code"in error&&error.code===code}var HOLDERS_DIR="session-holders",MOVE_LOCK="move.lock",HOLDER_RECORD=/^\d+\.json$/,MOVE_LOCK_STALE_MS=3e4,DEFAULT_MOVE_LOCK_WAIT_MS=5e3,MOVE_LOCK_RETRY_MS=100;function holdersDir(sessionFile,sessionId){return join9(dirname6(resolveMovedPath(sessionFile)),HOLDERS_DIR,encodedSessionId(sessionId))}function identityRecord(cwd){return JSON.stringify({pid:process.pid,bootAtMs:processBootAtMs(),processStartedAtMs:ownProcessStartedAtMs(),...cwd===void 0?{}:{cwd}})}function unlinkIfPresentSync(path2){try{unlinkSync(path2)}catch(error){if(errorCode(error)!=="ENOENT")throw error}}function removeDirIfEmpty(dir){try{rmdirSync(dir)}catch(error){let code=errorCode(error);if(code!=="ENOENT"&&code!=="ENOTEMPTY"&&code!=="EEXIST")throw error}}var holderRecordRefCounts=new Map,exitCleanupInstalled=!1;function installExitCleanup(){exitCleanupInstalled||(exitCleanupInstalled=!0,process.once("exit",()=>{for(let record of holderRecordRefCounts.keys())unlinkIfPresentSync(record)}))}function pidAlive2(pid){try{return process.kill(pid,0),!0}catch(error){return errorCode(error)==="EPERM"}}function activeMover(lock){let raw,ageMs;try{raw=readFileSync(lock,"utf8"),ageMs=Date.now()-statSync2(lock).mtimeMs}catch(error){if(errorCode(error)==="ENOENT")return;throw error}if(ageMs>MOVE_LOCK_STALE_MS)return;let pid=parsePid(raw);return pid===void 0?{pid}:pid===process.pid||pidAlive2(pid)?{pid}:void 0}function parsePid(raw){try{let parsed=JSON.parse(raw);return typeof parsed!="object"||parsed===null||!("pid"in parsed)?void 0:typeof parsed.pid=="number"?parsed.pid:void 0}catch(error){if(error instanceof SyntaxError)return;throw error}}function parseCwd(raw){let parsed=JSON.parse(raw);if(!(typeof parsed!="object"||parsed===null||!("cwd"in parsed)))return typeof parsed.cwd=="string"?parsed.cwd:void 0}function holdSessionFile(sessionFile,sessionId,options){let dir=holdersDir(sessionFile,sessionId),record=join9(dir,`${process.pid}.json`),shared=holderRecordRefCounts.get(record)??0;shared===0&&(publishHolderRecord(dir,record,identityRecord(options.cwd)),installExitCleanup()),holderRecordRefCounts.set(record,shared+1);let released=!1,release=()=>{if(released)return;released=!0;let left=(holderRecordRefCounts.get(record)??1)-1;if(left>0){holderRecordRefCounts.set(record,left);return}holderRecordRefCounts.delete(record),unlinkIfPresentSync(record),removeDirIfEmpty(dir)},mover=activeMover(join9(dir,MOVE_LOCK));if(mover!==void 0)throw release(),new SessionMovingError(sessionFile,mover.pid);if(options.expectExisting&&!existsSync2(resolveMovedPath(sessionFile)))throw release(),new SessionMovedError(sessionFile);return{release}}function publishHolderRecord(dir,record,content){for(let attempt=0;;attempt+=1){mkdirSync(dir,{recursive:!0});let temp=`${record}.${randomUUID5().slice(0,8)}.tmp`;try{writeFileSync(temp,content),renameSync(temp,record);return}catch(error){if(errorCode(error)!=="ENOENT"||attempt>0)throw error}}}async function liveHolders(dir){let holders=[];for(let name of await readdir4(dir)){if(!HOLDER_RECORD.test(name))continue;let path2=join9(dir,name),state=await reclaimLockState(path2);if(state.state==="stale"&&await breakStaleLock(path2,state.raw),state.state!=="held"||state.holder===void 0)continue;let raw=await readLeaseText(path2);holders.push({pid:state.holder.pid,cwd:raw===void 0?void 0:parseCwd(raw)})}return holders}async function liveSessionHolders(sessionFile,sessionId){try{return await liveHolders(holdersDir(sessionFile,sessionId))}catch(error){if(errorCode(error)==="ENOENT")return[];throw error}}async function takeMoveLock(sessionFile,lock,waitMs){let mine=identityRecord(),deadline=Date.now()+waitMs;for(;;){try{return await publishExclusive(lock,mine),mine}catch(error){let code=errorCode(error);if(code==="ENOENT"){mkdirSync(dirname6(lock),{recursive:!0});continue}if(code!=="EEXIST")throw error}let state=await reclaimLockState(lock);if(state.state==="stale"){await breakStaleLock(lock,state.raw);continue}if(state.state!=="free"){if(Date.now()>=deadline)throw new SessionMovingError(sessionFile,state.holder?.pid);await new Promise(resolve3=>setTimeout(resolve3,MOVE_LOCK_RETRY_MS))}}}async function withSessionMoveLock(sessionFile,sessionId,move,options={}){let dir=holdersDir(sessionFile,sessionId),lock=join9(dir,MOVE_LOCK),mine=await takeMoveLock(sessionFile,lock,options.waitMs??DEFAULT_MOVE_LOCK_WAIT_MS);try{let holders=await liveHolders(dir);if(holders.length>0)throw new SessionHeldError(sessionFile,holders);return await move()}finally{await readLeaseText(lock)===mine&&await unlinkIfPresent(lock),removeDirIfEmpty(dir)}}export{InvalidSidecarStoreError,UnsupportedSidecarStoreVersionError,encodedSessionId,sidecarFilePath,createSidecarStore,serializeByKey,logGuardEvent,currentPathPlatform,readJsonFileAsync,movedPathReason,prefixKey,knownPrefixKeys,looksMoved,knownMove,movedPathWalk,nextRecurringDueAt,formatScheduledMessage,scheduleDir,readJobFile,listScheduledJobs,createScheduledJob,isCancelled,cancelScheduledJob,restorePending,claimOccurrence,rearmRecurringJob,restoreAbandonedSchedule,settleOccurrence,pruneTombstones,readProcessStartMs,errorCode,unlinkIfPresent,readLeaseText,publishExclusive,publishReplace,reclaimLockState,breakStaleLock,reclaimInspected,RUNNER_HEARTBEAT_STALE_MS,RUNNER_HEARTBEAT_INTERVAL_MS,ownRunnerIdentity,writeRunnerLease,removeRunnerLease,liveRunners,isWatchRunnerAvailable,isOwnerAmong,acquireSessionDeliveryLock,resolveMovedPath,holdSessionFile,liveSessionHolders,withSessionMoveLock};
@@ -1,3 +0,0 @@
1
- #!/usr/bin/env node
2
- 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 = () => {}; } }
3
- import{enableStartupCompileCache}from"./chunk-F73COJ7R.js";import{main}from"./chunk-O6YOQUVX.js";import"./chunk-6Y7VGPJB.js";import"./chunk-XMHO4QQN.js";import"./chunk-4WZF7G6N.js";import{configureHttpDispatcher}from"./chunk-NTH33AXY.js";import"./chunk-LYYI74CY.js";import"./chunk-4GPJOGXZ.js";import"./chunk-KCVSSFOV.js";import"./chunk-WIAXG52U.js";import"./chunk-U5KVIAHJ.js";import"./chunk-QQZREV6B.js";import"./chunk-JABBHOD5.js";import"./chunk-HKRW6HT5.js";import"./chunk-TJPMB4VH.js";import"./chunk-QMRJYMNH.js";import"./chunk-MYVBK47X.js";import"./chunk-ZJHRDQCH.js";import"./chunk-UWYQPA26.js";import"./chunk-H4QOEVS5.js";import"./chunk-ZCYTYHDN.js";import"./chunk-JMYO34RK.js";import"./chunk-JEZWV7JW.js";import"./chunk-S2TCHQTE.js";import"./chunk-7X72IACK.js";import"./chunk-KUPQO7MC.js";import"./chunk-YU2P3CAR.js";import"./chunk-BMX2U22F.js";import"./chunk-5AKP2VFB.js";import"./chunk-CIRZTP7W.js";import"./chunk-LR5EN45D.js";import"./chunk-YI7SPFDN.js";import"./chunk-HB35RBP4.js";import"./chunk-G2XAU4BX.js";import"./chunk-RRU5LXMS.js";import"./chunk-VE3D74HN.js";import"./chunk-26UBFF6N.js";import"./chunk-ZPJHS64R.js";import"./chunk-GZVCRV7I.js";import"./chunk-U3VOXCGP.js";import"./chunk-RFB5CBW7.js";import"./chunk-2VZJTDUX.js";import"./chunk-2JKDZXIY.js";import{installEarlyInspectorVmImportRecovery}from"./chunk-5PB3SNZ7.js";import"./chunk-ZOFZRJSL.js";import"./chunk-2SOVDETB.js";import{APP_NAME,scrubBrandFromEnvironment}from"./chunk-463OK2Y4.js";import"./chunk-ATQFN5HI.js";import"./chunk-RBCQOIAD.js";import"./chunk-JRGNL6WM.js";import"./chunk-RKJNJ3GI.js";import"./chunk-CWLCGRUS.js";import"./chunk-6WCOSBI7.js";import"./chunk-I5HLTDT4.js";import"./chunk-KRNXUTZJ.js";import"./chunk-YOPVJDSU.js";import"./chunk-WHPDEDCC.js";import"./chunk-HK46JMSC.js";import"./chunk-VYKBN4MR.js";import"./chunk-WDTJ6JKE.js";import"./chunk-5ROMKDLK.js";import"./chunk-3W47LTXQ.js";import"./chunk-45SZOLCU.js";import"./chunk-TAV6QZFM.js";import"./chunk-PELNNWGO.js";import"./chunk-L4HVJWIF.js";import"./chunk-DMI55M2N.js";import"./chunk-PJ34QVL5.js";import"./chunk-IKOFCODM.js";enableStartupCompileCache();installEarlyInspectorVmImportRecovery();process.title=APP_NAME;scrubBrandFromEnvironment();process.env.PI_CODING_AGENT="true";process.emitWarning=(()=>{});configureHttpDispatcher();await main(process.argv.slice(2));
@@ -1,3 +0,0 @@
1
- #!/usr/bin/env node
2
- 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 = () => {}; } }
3
- import{DEFAULT_HANDOFF_GRACE_MS,DEFAULT_HOST_IDLE_EXIT_MS,HANDOFF_GRACE_MS_ENV,HOST_COLD_START_ENV,HOST_IDLE_EXIT_MS_ENV,INTERNAL_SUPERVISOR_FLAG,IdleExitDecider,classifyChildExit,createInternalSocketPath,findInternalSupervisorArgs,parseColdStart,parseIdleExitMs,parseSupervisorArgs,resolveCliMainPath,resolveHostChildLaunch,resolveHostPolicy,runHostSupervisor,spawnableChildLaunch}from"./chunk-5AKP2VFB.js";import"./chunk-CIRZTP7W.js";import"./chunk-LR5EN45D.js";import"./chunk-YI7SPFDN.js";import"./chunk-U3VOXCGP.js";import"./chunk-463OK2Y4.js";import"./chunk-ATQFN5HI.js";import"./chunk-IKOFCODM.js";export{DEFAULT_HANDOFF_GRACE_MS,DEFAULT_HOST_IDLE_EXIT_MS,HANDOFF_GRACE_MS_ENV,HOST_COLD_START_ENV,HOST_IDLE_EXIT_MS_ENV,INTERNAL_SUPERVISOR_FLAG,IdleExitDecider,classifyChildExit,createInternalSocketPath,findInternalSupervisorArgs,parseColdStart,parseIdleExitMs,parseSupervisorArgs,resolveCliMainPath,resolveHostChildLaunch,resolveHostPolicy,runHostSupervisor,spawnableChildLaunch};
@@ -1,2 +0,0 @@
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{InteractiveMode,OptimisticUserEchoController,createInteractiveTui,createInteractiveTuiReference,formatCrashExtensionHint,formatResumeCommand,shouldShowRetryIndicator,showsStartupDetails,showsStartupHeader}from"./chunk-O6YOQUVX.js";import{isApiKeyLoginProvider}from"./chunk-6Y7VGPJB.js";import"./chunk-XMHO4QQN.js";import"./chunk-4WZF7G6N.js";import"./chunk-NTH33AXY.js";import"./chunk-LYYI74CY.js";import"./chunk-4GPJOGXZ.js";import"./chunk-KCVSSFOV.js";import"./chunk-WIAXG52U.js";import"./chunk-U5KVIAHJ.js";import"./chunk-QQZREV6B.js";import"./chunk-JABBHOD5.js";import"./chunk-HKRW6HT5.js";import"./chunk-TJPMB4VH.js";import"./chunk-QMRJYMNH.js";import"./chunk-MYVBK47X.js";import"./chunk-ZJHRDQCH.js";import"./chunk-UWYQPA26.js";import"./chunk-H4QOEVS5.js";import"./chunk-ZCYTYHDN.js";import"./chunk-JMYO34RK.js";import"./chunk-JEZWV7JW.js";import"./chunk-S2TCHQTE.js";import"./chunk-7X72IACK.js";import"./chunk-KUPQO7MC.js";import"./chunk-YU2P3CAR.js";import"./chunk-BMX2U22F.js";import"./chunk-5AKP2VFB.js";import"./chunk-CIRZTP7W.js";import"./chunk-LR5EN45D.js";import"./chunk-YI7SPFDN.js";import"./chunk-HB35RBP4.js";import"./chunk-G2XAU4BX.js";import"./chunk-RRU5LXMS.js";import"./chunk-VE3D74HN.js";import"./chunk-26UBFF6N.js";import"./chunk-ZPJHS64R.js";import"./chunk-GZVCRV7I.js";import"./chunk-U3VOXCGP.js";import"./chunk-RFB5CBW7.js";import"./chunk-2VZJTDUX.js";import"./chunk-2JKDZXIY.js";import"./chunk-5PB3SNZ7.js";import"./chunk-ZOFZRJSL.js";import"./chunk-2SOVDETB.js";import"./chunk-463OK2Y4.js";import"./chunk-ATQFN5HI.js";import"./chunk-RBCQOIAD.js";import"./chunk-JRGNL6WM.js";import"./chunk-RKJNJ3GI.js";import"./chunk-CWLCGRUS.js";import"./chunk-6WCOSBI7.js";import"./chunk-I5HLTDT4.js";import"./chunk-KRNXUTZJ.js";import"./chunk-YOPVJDSU.js";import"./chunk-WHPDEDCC.js";import"./chunk-HK46JMSC.js";import"./chunk-VYKBN4MR.js";import"./chunk-WDTJ6JKE.js";import"./chunk-5ROMKDLK.js";import"./chunk-3W47LTXQ.js";import"./chunk-45SZOLCU.js";import"./chunk-TAV6QZFM.js";import"./chunk-PELNNWGO.js";import"./chunk-L4HVJWIF.js";import"./chunk-DMI55M2N.js";import"./chunk-PJ34QVL5.js";import"./chunk-IKOFCODM.js";export{InteractiveMode,OptimisticUserEchoController,createInteractiveTui,createInteractiveTuiReference,formatCrashExtensionHint,formatResumeCommand,isApiKeyLoginProvider,shouldShowRetryIndicator,showsStartupDetails,showsStartupHeader};
@@ -1,25 +0,0 @@
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{ACCEPT_EDITS_PERMISSION_PRESET_CAPABILITY,AUTO_PERMISSION_PRESET_CAPABILITY,AgentSessionRuntime,EMPTY_SESSION_CONTEXT,HostMcpRegistry,ProviderScope,bindToProviderScope,createAgentSessionRuntime,createWebViewBroker,runWithProviderScope,startHostChildReaper}from"./chunk-O6YOQUVX.js";import{DURABLE_CLIENT_MESSAGE_ID_CAPABILITY,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_RELEASE_FAILED,RPC_ERROR_RELEASE_UNSUPPORTED,RPC_ERROR_SESSION_BUSY,RPC_ERROR_SESSION_CLOSING,RPC_ERROR_TURN_ACTIVE,RPC_ERROR_UNKNOWN_SESSION,RPC_ERROR_WARM_FAILED,createRpcConnectionHandler,readCodemodeKernelRows,readMainThreadHeapBytes,readOwnFootprint}from"./chunk-6Y7VGPJB.js";import{resolveMovedPath}from"./chunk-XMHO4QQN.js";import{SessionManager,assertValidSessionId,liveToolMediaScope,omitInlineMedia,toolMediaPersister}from"./chunk-4WZF7G6N.js";import{flushRawStdout,takeOverStdout,waitForRawStdoutBackpressure,writeRawStdout}from"./chunk-NTH33AXY.js";import"./chunk-LYYI74CY.js";import"./chunk-4GPJOGXZ.js";import"./chunk-KCVSSFOV.js";import"./chunk-WIAXG52U.js";import"./chunk-U5KVIAHJ.js";import{buildRpcSessionState,rpcCommandShapeError,sessionAutoTitleError,sessionBrowserEngineError,sessionContextError,sessionKindError,sessionPromptSurfaceError,sessionRetryFallbackError}from"./chunk-QQZREV6B.js";import"./chunk-JABBHOD5.js";import{BEGIN_HANDOVER_COMMAND,EXPECTED_RUNTIME_BUILD_ID_ENV,GENERATION_HANDOFF_CAPABILITY,HostIdleHandover,RUNTIME_IDENTITY_HANDOVER_CAPABILITY,beginHandoverResponse,computeRuntimeBuildId,handoverRefusal,isHandoffBusy,isHostIdle,parseBeginHandover,performIdleHandover,readDrainVerdicts,runAsHostGenerationProcess,withHostIdentity}from"./chunk-HKRW6HT5.js";import{AUTO_TITLE_PER_SESSION_CAPABILITY,AUTO_TITLE_SESSIONS_CAPABILITY,BROWSER_ENGINE_CAPABILITY,CONTINUE_FROM_LEAF_CAPABILITY,DURABLE_SESSION_ID_CAPABILITY,MEDIA_PLACEHOLDERS_CAPABILITY,MOVED_PATH_GUARD_CAPABILITY,PROMPT_SURFACE_CAPABILITY,PROMPT_SURFACE_CHAT_CAPABILITY,RETAIN_ON_DISCONNECT_CAPABILITY,RETRY_FALLBACK_PROFILE_CAPABILITY,SESSION_CONTEXT_CAPABILITY,SESSION_KIND_CAPABILITY,WARM_CAPABILITY,hostGeneration,hostInstanceId,parseClientCapabilities,protocolIdentity}from"./chunk-TJPMB4VH.js";import"./chunk-QMRJYMNH.js";import"./chunk-MYVBK47X.js";import"./chunk-ZJHRDQCH.js";import"./chunk-UWYQPA26.js";import"./chunk-H4QOEVS5.js";import"./chunk-ZCYTYHDN.js";import"./chunk-JMYO34RK.js";import{killTrackedDetachedChildren}from"./chunk-JEZWV7JW.js";import"./chunk-S2TCHQTE.js";import"./chunk-7X72IACK.js";import"./chunk-KUPQO7MC.js";import"./chunk-YU2P3CAR.js";import"./chunk-BMX2U22F.js";import{ClientOccupancy,armHostWatchdog,loopLagErrorMs,ownGenerationDir,parseIdleExitMs,readHostWatchdogConfigFromBrandEnv,writeHeartbeat,writeStallEvidence}from"./chunk-5AKP2VFB.js";import"./chunk-CIRZTP7W.js";import{PUBLIC_SOCKET_IDENTITY_FILE,SESSION_PATH_RETRY_AFTER_MS,SOCKET_SECRET_FILE_ENV,authenticateSocket,canonicalSessionPath,createEndpointReservations,ensureSocketSecret,readSocketIdentityFile,resolveSocketTransportAddress,sessionDirectoryRemoved,shieldSocketDuringClose,socketEntryReplaced,socketSecretPath,statSocketIdentity,unlinkOwnedSocket,waitForSocketIdentityFile}from"./chunk-LR5EN45D.js";import{MAX_RPC_LINE_CHARACTERS,attachJsonlLineReader,serializeJsonLine}from"./chunk-YI7SPFDN.js";import"./chunk-HB35RBP4.js";import"./chunk-G2XAU4BX.js";import"./chunk-RRU5LXMS.js";import"./chunk-VE3D74HN.js";import"./chunk-26UBFF6N.js";import"./chunk-ZPJHS64R.js";import"./chunk-GZVCRV7I.js";import"./chunk-U3VOXCGP.js";import"./chunk-RFB5CBW7.js";import"./chunk-2VZJTDUX.js";import"./chunk-2JKDZXIY.js";import"./chunk-5PB3SNZ7.js";import"./chunk-ZOFZRJSL.js";import"./chunk-2SOVDETB.js";import{VERSION,envValue,isBunBinary}from"./chunk-463OK2Y4.js";import"./chunk-ATQFN5HI.js";import"./chunk-RBCQOIAD.js";import"./chunk-JRGNL6WM.js";import"./chunk-RKJNJ3GI.js";import"./chunk-CWLCGRUS.js";import"./chunk-6WCOSBI7.js";import"./chunk-I5HLTDT4.js";import"./chunk-KRNXUTZJ.js";import"./chunk-YOPVJDSU.js";import"./chunk-WHPDEDCC.js";import"./chunk-HK46JMSC.js";import"./chunk-VYKBN4MR.js";import"./chunk-WDTJ6JKE.js";import"./chunk-5ROMKDLK.js";import"./chunk-3W47LTXQ.js";import"./chunk-45SZOLCU.js";import"./chunk-TAV6QZFM.js";import"./chunk-PELNNWGO.js";import"./chunk-L4HVJWIF.js";import"./chunk-DMI55M2N.js";import"./chunk-PJ34QVL5.js";import"./chunk-IKOFCODM.js";import{access as access2,chmod,mkdir,unlink}from"node:fs/promises";import{createConnection,createServer}from"node:net";import{basename,dirname,join}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)}var RPC_SESSION_IDLE_EVICTION_MS_ENV="SENPI_RPC_SESSION_IDLE_EVICTION_MS",RPC_HOST_EMPTY_EXIT_MS_ENV="SENPI_RPC_HOST_EMPTY_EXIT_MS",RPC_CLOSE_GRACE_MS_ENV="SENPI_RPC_CLOSE_GRACE_MS",DEFAULT_SESSION_IDLE_EVICTION_MS=30*6e4,DEFAULT_HOST_EMPTY_EXIT_MS=15*6e4;function resolveHostIdlePolicy(env,overrides={}){return{now:overrides.now??Date.now,idleEvictionMs:overrides.idleEvictionMs??parseIdleExitMs(env[RPC_SESSION_IDLE_EVICTION_MS_ENV])??DEFAULT_SESSION_IDLE_EVICTION_MS,emptyExitMs:overrides.emptyExitMs??parseIdleExitMs(env[RPC_HOST_EMPTY_EXIT_MS_ENV])??DEFAULT_HOST_EMPTY_EXIT_MS}}var HOST_RSS_WARN_MB_ENV="SENPI_RPC_HOST_RSS_WARN_MB",DEFAULT_HOST_RSS_WARN_MB=4096,HOST_MEMORY_SAMPLE_MS=3e4,HOST_MEMORY_STDERR_INTERVAL_MS=5*6e4,BYTES_PER_MEGABYTE=1024*1024;function parsePositiveInteger(value){if(value===void 0||!/^\d+$/.test(value.trim()))return;let parsed=Number(value.trim());return Number.isFinite(parsed)&&parsed>0?parsed:void 0}var HostMemorySampler=class{constructor(options){this.pressure=!1,this.idleReported=!1;let env=options.env??process.env;this.emit=options.emit,this.sessions=options.sessions,this.onPressure=options.onPressure,options.onIdlePressure&&(this.onIdlePressure=options.onIdlePressure),this.log=options.log??(message=>{process.stderr.write(message)}),this.now=options.now??Date.now,this.readFootprint=options.readFootprint??readOwnFootprint,this.readRssBytes=options.readRssBytes??(()=>process.memoryUsage.rss()),this.readKernels=options.readKernels??readCodemodeKernelRows,this.readMainHeap=options.readMainHeap??readMainThreadHeapBytes,this.warnMb=parsePositiveInteger(env[HOST_RSS_WARN_MB_ENV])??DEFAULT_HOST_RSS_WARN_MB}start(){this.timer===void 0&&(this.timer=setInterval(()=>this.sample(),HOST_MEMORY_SAMPLE_MS),this.timer.unref?.())}stop(){this.timer!==void 0&&(clearInterval(this.timer),this.timer=void 0)}sample(){let footprint=this.readFootprint(),reading={footprintMb:Math.round(footprint.bytes/BYTES_PER_MEGABYTE),measure:footprint.measure,rssMb:Math.round(this.readRssBytes()/BYTES_PER_MEGABYTE),main:{heapBytes:this.readMainHeap()},kernels:this.readKernels()};if(reading.footprintMb<=this.warnMb){if(this.idleReported=!1,!this.pressure)return;this.pressure=!1,this.onPressure(!1);return}this.pressure||(this.pressure=!0,this.onPressure(!0));let sessions=this.sessions();sessions>0?this.idleReported=!1:this.idleReported||(this.idleReported=!0,this.onIdlePressure?.(reading));let{footprintMb,measure,rssMb}=reading;this.emit({type:"host_memory_pressure",rssMb,footprintMb,measure,sessions,main:reading.main,kernels:reading.kernels});let now=this.now();this.lastLoggedAt!==void 0&&now-this.lastLoggedAt<HOST_MEMORY_STDERR_INTERVAL_MS||(this.lastLoggedAt=now,this.log(`senpi rpc host memory pressure: footprintMb=${footprintMb} (${measure}) rssMb=${rssMb} sessions=${sessions} (idle parking halved)
3
- `))}};var ZERO_SESSION_TRIM_TICK_MS=1e3,ZERO_SESSION_TRIM_MIN_INTERVAL_MS=6e4,BYTES_PER_MEGABYTE2=1024*1024,ZeroSessionTrimmer=class{constructor(options){this.heldSessions=!1,this.options=options,this.now=options.now??Date.now}start(){this.timer===void 0&&(this.timer=setInterval(()=>this.check(),ZERO_SESSION_TRIM_TICK_MS),this.timer.unref?.())}stop(){this.timer!==void 0&&(clearInterval(this.timer),this.timer=void 0)}observe(size){size>0&&(this.heldSessions=!0)}check(){if(this.pending!==void 0&&this.report(this.pending),this.options.sessions()>0){this.heldSessions=!0;return}this.heldSessions&&(this.heldSessions=!1,!(this.lastTrimAt!==void 0&&this.now()-this.lastTrimAt<ZERO_SESSION_TRIM_MIN_INTERVAL_MS)&&this.trim())}trim(){let beforeBytes=this.readFootprint().bytes;this.pending={beforeBytes,collected:(this.options.collect??collectFully)()},this.lastTrimAt=this.now()}report(pending){this.pending=void 0;let after=this.readFootprint();this.options.emit({type:"host_trimmed",footprintBeforeMb:Math.round(pending.beforeBytes/BYTES_PER_MEGABYTE2),footprintAfterMb:Math.round(after.bytes/BYTES_PER_MEGABYTE2),measure:after.measure,collected:pending.collected})}readFootprint(){return(this.options.readFootprint??readOwnFootprint)()}};function collectFully(){let bun=Reflect.get(globalThis,"Bun"),bunGc=typeof bun=="object"&&bun!==null?Reflect.get(bun,"gc"):void 0;if(typeof bunGc=="function")return Reflect.apply(bunGc,bun,[!0]),!0;let nodeGc=Reflect.get(globalThis,"gc");return typeof nodeGc!="function"?!1:(Reflect.apply(nodeGc,globalThis,[]),!0)}var blockedMsTotal=0;function recordLoopBlockedMs(driftMs){driftMs>0&&(blockedMsTotal+=driftMs)}function loopBlockedMark(){return blockedMsTotal}function loopBlockedMsSince(mark){return blockedMsTotal-mark}import{AsyncLocalStorage}from"node:async_hooks";var attributionStore=new AsyncLocalStorage,sequence=0,openActivities=new Map,lastFinished;function runWithSessionAttribution(attribution,task){let mark=++sequence;openActivities.set(mark,attribution);let finish=()=>{openActivities.delete(mark)&&(lastFinished={sequence:++sequence,attribution})},awaited=!1;try{let result=attributionStore.run(attribution,task);return isPromiseLike(result)&&(awaited=!0,Promise.resolve(result).then(finish,finish)),result}finally{awaited||finish()}}function isPromiseLike(value){return typeof value=="object"&&value!==null&&"then"in value&&typeof value.then=="function"}function openSessionAttributionSpan(attribution){let ambient=attributionStore.getStore(),merged={sessionId:attribution.sessionId??ambient?.sessionId,tool:attribution.tool},mark=++sequence;return openActivities.set(mark,merged),()=>{openActivities.delete(mark)&&(lastFinished={sequence:++sequence,attribution:merged})}}function sessionActivityMark(){return sequence}function sessionActivitySince(mark){if(lastFinished!==void 0&&lastFinished.sequence>mark)return lastFinished.attribution;let newest;for(let attribution of openActivities.values())newest=attribution;return newest}function toolRecord(record){if(!(!("type"in record)||typeof record.type!="string"))return{type:record.type,toolCallId:"toolCallId"in record&&typeof record.toolCallId=="string"?record.toolCallId:void 0,toolName:"toolName"in record&&typeof record.toolName=="string"?record.toolName:void 0}}function createToolAttributionSpans(sessionId){let spans=new Map,closeAll=()=>{for(let close of spans.values())close();spans.clear()};return{closeAll,observe:record=>{let parsed=toolRecord(record);if(parsed!==void 0){if(parsed.type==="tool_execution_start"&&parsed.toolCallId!==void 0){spans.get(parsed.toolCallId)?.(),spans.set(parsed.toolCallId,openSessionAttributionSpan({sessionId,tool:parsed.toolName}));return}if(parsed.type==="tool_execution_end"&&parsed.toolCallId!==void 0){spans.get(parsed.toolCallId)?.(),spans.delete(parsed.toolCallId);return}(parsed.type==="agent_settled"||parsed.type==="agent_idle")&&closeAll()}}}}var LOOP_LAG_WARN_MS_ENV="SENPI_RPC_LOOP_LAG_WARN_MS",DEFAULT_LOOP_LAG_WARN_MS=500,LOOP_LAG_TICK_MS=200,LOOP_LAG_WARN_INTERVAL_MS=1e4,HEARTBEAT_THRESHOLD_FRACTION=5,BYTES_PER_MB=1024*1024;function describeWindow(processCpuMs,heapDeltaMb){return`cpu=${processCpuMs}ms heap=${heapDeltaMb>=0?"+":""}${heapDeltaMb}MB`}function describeAttribution(attribution){return attribution?.sessionId===void 0&&attribution?.tool===void 0?"no attributed session":`sessionId=${attribution.sessionId??"unknown"}${attribution.tool?` tool=${attribution.tool}`:""}`}var LoopLagWatchdog=class{constructor(options){this.activityMark=0,this.cpuMicrosAtTick=0,this.heapBytesAtTick=0,this.heartbeatInFlight=!1,this.launchParentPid=process.ppid,this.evidenceFailureLogged=!1;let env=options.env??process.env;this.emit=options.emit,this.log=options.log??(message=>{process.stderr.write(message)}),this.now=options.now??Date.now,this.cpuUsage=options.cpuUsage??(()=>process.cpuUsage()),this.heapUsed=options.heapUsed??(()=>process.memoryUsage().heapUsed),this.writeHeartbeat=options.writeHeartbeat??writeHeartbeat,this.warnMs=parseIdleExitMs(env[LOOP_LAG_WARN_MS_ENV])??DEFAULT_LOOP_LAG_WARN_MS,this.errorMs=loopLagErrorMs(env),this.heartbeatIntervalMs=Math.max(LOOP_LAG_TICK_MS,Math.floor(this.errorMs/HEARTBEAT_THRESHOLD_FRACTION)),this.evidenceDir=ownGenerationDir(env)}start(){if(this.timer!==void 0)return;this.expectedTickAt=this.now()+LOOP_LAG_TICK_MS,this.activityMark=sessionActivityMark();let cpu=this.cpuUsage();this.cpuMicrosAtTick=cpu.user+cpu.system,this.heapBytesAtTick=this.heapUsed(),this.timer=setInterval(()=>this.tick(),LOOP_LAG_TICK_MS),this.timer.unref?.()}stop(){this.timer!==void 0&&(clearInterval(this.timer),this.timer=void 0,this.expectedTickAt=void 0)}tick(){let now=this.now(),expectedAt=this.expectedTickAt??now,previousMark=this.activityMark;this.expectedTickAt=now+LOOP_LAG_TICK_MS,this.activityMark=sessionActivityMark();let cpu=this.cpuUsage(),cpuMicros=cpu.user+cpu.system,heapBytes=this.heapUsed(),previousCpuMicros=this.cpuMicrosAtTick,previousHeapBytes=this.heapBytesAtTick;this.cpuMicrosAtTick=cpuMicros,this.heapBytesAtTick=heapBytes;let driftMs=Math.round(now-expectedAt);if(recordLoopBlockedMs(driftMs),driftMs<=this.warnMs){this.beat(now);return}let attribution=sessionActivitySince(previousMark),processCpuMs=Math.round((cpuMicros-previousCpuMicros)/1e3),heapDeltaMb=Math.round((heapBytes-previousHeapBytes)/BYTES_PER_MB);if(driftMs>this.errorMs){let record={type:"host_stalled",driftMs,sessionId:attribution?.sessionId,tool:attribution?.tool,processCpuMs,heapDeltaMb};this.emit(record),this.persistStall(now,record)}this.lastWarnAt!==void 0&&now-this.lastWarnAt<LOOP_LAG_WARN_INTERVAL_MS||(this.lastWarnAt=now,this.log(`senpi rpc host stall: event loop blocked ${driftMs}ms (${describeAttribution(attribution)}; ${describeWindow(processCpuMs,heapDeltaMb)})
4
- `))}beat(now){!this.ownsEvidenceDir()||this.evidenceDir===void 0||this.heartbeatInFlight||this.lastHeartbeatAt!==void 0&&now-this.lastHeartbeatAt<this.heartbeatIntervalMs||(this.lastHeartbeatAt=now,this.heartbeatInFlight=!0,this.writeHeartbeat(this.evidenceDir,new Date(now).toISOString()).catch(cause=>this.evidenceFailed(cause)).finally(()=>{this.heartbeatInFlight=!1}))}persistStall(now,record){!this.ownsEvidenceDir()||this.evidenceDir===void 0||writeStallEvidence(this.evidenceDir,{at:new Date(now).toISOString(),driftMs:record.driftMs,processCpuMs:record.processCpuMs??0,heapDeltaMb:record.heapDeltaMb??0,...record.sessionId?{sessionId:record.sessionId}:{},...record.tool?{tool:record.tool}:{}}).catch(cause=>this.evidenceFailed(cause))}ownsEvidenceDir(){return process.ppid===this.launchParentPid}evidenceFailed(cause){this.evidenceFailureLogged||(this.evidenceFailureLogged=!0,this.log(`senpi rpc host stall evidence not written: ${cause instanceof Error?cause.message:String(cause)}
5
- `))}};function startHostObservers(router,writer,options){let loopLag=new LoopLagWatchdog({emit:record=>writer.broadcastHostRecord(record)}),kernels=readCodemodeKernelRows,memory=new HostMemorySampler({emit:record=>writer.broadcastHostRecord(record),sessions:()=>router.sessionCount,onPressure:pressure=>router.setMemoryPressure(pressure),readKernels:kernels,...options.onIdlePressure?{onIdlePressure:options.onIdlePressure}:{}});router.setHostMemoryView({mainHeapBytes:readMainThreadHeapBytes,kernels});let{trim}=options;return loopLag.start(),memory.start(),trim.start(),{stop:()=>{loopLag.stop(),memory.stop(),trim.stop()}}}function createZeroSessionTrim(writer,sessions){return new ZeroSessionTrimmer({emit:record=>writer.broadcastHostRecord(record),sessions})}function multiSessionHostCapabilities(options){return[...new Set(["multi_session",AUTO_TITLE_SESSIONS_CAPABILITY,MEDIA_PLACEHOLDERS_CAPABILITY,DURABLE_CLIENT_MESSAGE_ID_CAPABILITY,CONTINUE_FROM_LEAF_CAPABILITY,RETAIN_ON_DISCONNECT_CAPABILITY,SESSION_CONTEXT_CAPABILITY,SESSION_KIND_CAPABILITY,AUTO_TITLE_PER_SESSION_CAPABILITY,DURABLE_SESSION_ID_CAPABILITY,MOVED_PATH_GUARD_CAPABILITY,PROMPT_SURFACE_CAPABILITY,PROMPT_SURFACE_CHAT_CAPABILITY,BROWSER_ENGINE_CAPABILITY,RETRY_FALLBACK_PROFILE_CAPABILITY,ACCEPT_EDITS_PERMISSION_PRESET_CAPABILITY,AUTO_PERMISSION_PRESET_CAPABILITY,...options.warm?[WARM_CAPABILITY]:[],...options.negotiated])]}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)}`)}}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(`
6
- `)){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()}
7
- `),droppedAfterClose=!0;return}writeInScope(chunk)},waitForBackpressure:bindToProviderScope(async()=>{})};return createRpcConnectionHandler(runtimeHost,taggedSink,{sessionId,shutdownHandler:bindToProviderScope(requestClose),disposeRuntime:!1,eventFlushScheduler:flush=>flush(),...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{existsSync as existsSync2}from"node:fs";import{isAbsolute as isAbsolute2}from"node:path";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.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_messages","get_entries","get_tree","get_fork_messages","get_last_assistant_text","get_session_stats","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"]);function refreshesSessionActivity(command){return!observations.has(command)}async function attachToOpenSession(entries,sessionPath,profile,options,pathReservations,now){let existing=[...entries].find(([,entry2])=>entry2.reservationKey===sessionPath&&entry2.state==="open");if(!existing)throw new RpcSessionRegistryError("session_path_in_use");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 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}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&&!existsSync(profile.sessionPath))throw new RpcSessionRegistryError("open_failed",`moved session file does not exist: ${profile.sessionPath}`);return profile}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),runtime.releaseSessionHold(),entry.runtime=replacement,syncRuntimeMetadata2(),result});return entry.lifecycleMutex=operation.then(()=>{},()=>{}),operation}}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)}
8
- `)}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.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}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),sessionPath&&this.reservations.has(sessionPath))return attachToOpenSession(this.entries,sessionPath,profile,options,this.options.pathReservations,this.now());if(sessionPath){this.reservations.add(sessionPath);let holder=this.options.pathReservations?await this.options.pathReservations.claim(sessionPath):void 0;if(holder)throw this.reservations.delete(sessionPath),new RpcSessionRegistryError("session_path_in_use",void 0,{owner:holder,retry_after_ms:SESSION_PATH_RETRY_AFTER_MS})}let isResume=sessionPath!==void 0&&existsSync2(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,handle=`rpc-${++this.nextHandle}`,entry={state:"opening",scope:new ProviderScope,profile:storedProfile,...sessionIdentity(storedProfile),sessionPath,reservationKey:sessionPath,cwd:storedProfile.cwd,attachments:1,retainOnDisconnect:options?.retainOnDisconnect===!0,lastCommandAt:this.now(),lifecycleMutex:Promise.resolve()};entry.switchSession=createEntrySwitchSession(entry,this.options.createRuntime,()=>this.syncRuntimeMetadata()),requestedDurableId!==void 0&&(entry.durableSessionId=requestedDurableId),this.entries.set(handle,entry),this.options.onSizeChange?.(this.entries.size);try{let newSessionOptions=requestedDurableId!==void 0?{id:requestedDurableId}:void 0,manager=sessionPath?SessionManager.open(sessionPath,void 0,storedProfile.cwd,newSessionOptions):SessionManager.create(storedProfile.cwd,void 0,newSessionOptions);return entry.runtime=await runWithProviderScope(entry.scope,()=>createAgentSessionRuntime(this.options.createRuntime,{cwd:manager.getCwd(),agentDir:this.options.agentDir,sessionManager:manager,sessionStartEvent,launchProfile:runtimeProfile})),assertRequestedModelResolved(runtimeProfile,entry.runtime.diagnostics),entry.durableSessionId=manager.getSessionId(),entry.sessionPath??=manager.getSessionFile(),entry.state="open",{sessionId:handle,durableSessionId:entry.durableSessionId,sessionPath:entry.sessionPath}}catch(error2){try{await entry.runtime?.dispose()}catch{}finally{try{await entry.scope.close?.()}finally{this.entries.delete(handle),this.options.onSizeChange?.(this.entries.size),sessionPath&&await releaseWithinGrace(this.teardownHost,handle,sessionPath)}}throw error2 instanceof RpcSessionRegistryError?error2:new RpcSessionRegistryError("open_failed",error2 instanceof Error?error2.message:void 0)}}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==="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){return beginSessionClose(this.teardownHost,handle,onRole,options)}async close(handle){return closeSession(this.teardownHost,handle)}async closeMarked(handle){return closeMarkedSession(this.teardownHost,handle)}list(){return this.syncRuntimeMetadata(),[...this.entries].map(([sessionId,entry])=>({sessionId,durableSessionId:entry.durableSessionId,sessionPath:entry.sessionPath,cwd:entry.cwd,name:entry.runtime?.session.sessionManager.getSessionName(),kind:entry.kind,context:entry.context,attachments:Math.max(0,entry.attachments),status:entry.state==="quarantined"?"closing":entry.state}))}syncRuntimeMetadata(){syncRuntimeMetadata(this.entries.values(),this.reservations,this.options.pathReservations)}validateProfile(profile){if(!isAbsolute2(profile.cwd)||profile.sessionPath!==void 0&&!isAbsolute2(profile.sessionPath))throw new RpcSessionRegistryError("invalid_path");if(profile.durableSessionId!==void 0)try{assertValidSessionId(profile.durableSessionId)}catch(cause){throw new RpcSessionRegistryError("invalid_session_id",String(cause))}}};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){if(command.reason!=="takeover")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;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,answer;try{interrupted&&(admission.close(RELEASED_ADMISSION_CLOSED),dropped=takeQueuedInput(first.session),await abortAndSettle(port,command.sessionId,first.session));let manager=first.session.sessionManager;return manager.isTranscriptFlushed()||await manager.persistHeaderNow(),answer=await claimAndRelease(port,command,interrupted,dropped),answer}catch(cause){return answer=refusal2(command.id,RPC_ERROR_RELEASE_FAILED,{detail:cause instanceof Error?cause.message:String(cause),...interrupted?{interrupted:!0,dropped}:{}}),answer}finally{answer?.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,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 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.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.canExitWhenEmpty=idle?.canExitWhenEmpty,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)}
9
- `)}).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,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==="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==="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:sessionId=>this.registry.getForCommand(sessionId,"release_session"),code:cause=>this.code(cause),otherRequests:sessionId=>Math.max(0,(this.activeRequests.get(sessionId)??1)-1),otherRequestsSettled:sessionId=>this.otherRequestsSettled(sessionId),pendingPrompts:sessionId=>this.bindings.get(sessionId)?.pendingPrompts?.()??[],tearDown:(sessionId,sessionPath)=>this.tearDownReleased(sessionId,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.sessionId)return error(command.id,command.type,RPC_ERROR_MISSING_SESSION_ID);try{this.registry.getForCommand(command.sessionId,command.type);let binding=this.bindings.get(command.sessionId);if(!binding)return error(command.id,command.type,RPC_ERROR_UNKNOWN_SESSION);command.type==="prompt"&&this.acknowledgePrompt(command.id,command.sessionId),await binding.handle(command);return}catch(cause){return error(command.id,command.type,this.code(cause))}}async dispose(){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()}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;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):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}forgetSessionOwnership(sessionId){for(let[connection,owned]of this.sessionsByConnection)owned.delete(sessionId),owned.size===0&&this.sessionsByConnection.delete(connection)}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;return 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}),this.open(command,owner).finally(()=>{resolveBarrier(),opens.delete(barrier),opens.size===0&&this.opensByConnection.delete(owner)})}async open(command,owner){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;try{opened=await this.registry.openSession({cwd:command.cwd??this.defaults.cwd,sessionPath:command.sessionPath,permissionPreset:command.permissionPreset??this.defaults.permissionPreset,creationModel:command.provider&&command.modelId?{provider:command.provider,modelId:command.modelId}:this.defaults.creationModel,initialThinkingLevel:command.thinkingLevel??this.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});let openedSession=opened,entry=this.registry.getForCommand(openedSession.sessionId,"open_session");if(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)})}!this.draining&&owner!==void 0&&this.releasedConnections.has(owner)&&(this.releaseOwnerAttachment(owner,openedSession.sessionId),await this.releaseOwnedSession(openedSession.sessionId));let state=entry.worker?.snapshot?.state??(entry.runtime?buildRpcSessionState(entry.runtime.session):void 0);if(!state)throw new Error("Session state was not created");this.writer.enqueue(opened.sessionId,{id:command.id,type:"response",command:"open_session",success:!0,data:{sessionId:opened.sessionId,state,...opened.attached?{attached:!0}:{}}});return}catch(cause){if(opened)try{await this.registry.close(opened.sessionId)}catch{}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){opens&&await Promise.all([...opens]),this.releasedConnections.delete(connectionId);return}if(owned===void 0){opens&&await Promise.all([...opens]),this.releasedConnections.delete(connectionId);return}await Promise.all([...owned].map(async([sessionId,count])=>{for(let attachment=0;attachment<count;attachment++){let live=this.registry.peek(sessionId),retained=live?.retainOnDisconnect===!0,session=live?.state==="open"?live.runtime?.session:void 0;if(!retained&&live?.state==="open"&&live.worker?.snapshot?.streaming){let unsubscribe=live.worker.subscribeSettled(()=>{unsubscribe(),this.releaseOwnedSession(sessionId).catch(cause=>{process.stderr.write(`senpi rpc deferred worker release ${sessionId} failed: ${String(cause)}
10
- `)})});continue}if(!retained&&session?.isStreaming){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)}
11
- `)}))});continue}await this.releaseOwnedSession(sessionId)}})),opens&&await Promise.all([...opens]),this.releasedConnections.delete(connectionId)}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){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{owner!==void 0&&this.releaseOwnerAttachment(owner,command.sessionId),claim.finalizer?await this.finalizeClose(command.sessionId,this.bindings.get(command.sessionId),()=>reply.complete(!0,"client_close")):(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)}
12
- `)}this.bindings.delete(sessionId);try{await this.registry.closeMarked(sessionId)}catch(cause){process.stderr.write(`senpi rpc close for session ${sessionId} failed: ${String(cause)}
13
- `)}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{AsyncLocalStorage as AsyncLocalStorage2}from"node:async_hooks";var DEFAULT_QUEUE_BYTES=64*1024*1024,DEFAULT_STALL_MS=3e4,SocketEventQueueStallError=class extends Error{constructor(pendingBytes,stallMs){super(`socket event queue stalled: peer did not drain ${pendingBytes} queued bytes within ${stallMs}ms`),this.name="SocketEventQueueStallError",this.pendingBytes=pendingBytes,this.stallMs=stallMs}},SocketEventQueueOverflowError=class extends Error{constructor(queuedBytes,incomingBytes,maxQueueBytes,incomingPreview){super(`socket event queue overflow: ${queuedBytes} queued + ${incomingBytes} incoming > ${maxQueueBytes} (incoming: ${incomingPreview})`),this.name="SocketEventQueueOverflowError",this.queuedBytes=queuedBytes,this.incomingBytes=incomingBytes,this.maxQueueBytes=maxQueueBytes,this.incomingPreview=incomingPreview}},SocketEventSinkActor=class{constructor(sink,onFailure,maxQueueBytes=DEFAULT_QUEUE_BYTES,stallMs=DEFAULT_STALL_MS){this.queue=[],this.queuedBytes=0,this.closed=!1,this.sink=sink,this.onFailure=onFailure,this.maxQueueBytes=maxQueueBytes,this.stallMs=stallMs}enqueue(line,key,onWritten,demotedLine){if(this.closed)return;let bytes=Buffer.byteLength(line);if(key!==void 0){let existing=this.queue.find(entry=>entry.key===key);existing&&(existing.demotedLine!==void 0&&(this.queuedBytes-=existing.bytes,existing.line=existing.demotedLine,existing.bytes=Buffer.byteLength(existing.line),this.queuedBytes+=existing.bytes,existing.demotedLine=void 0),existing.key=void 0)}if(this.queuedBytes+bytes>this.maxQueueBytes){let overflow=new SocketEventQueueOverflowError(this.queuedBytes,bytes,this.maxQueueBytes,line.slice(0,120));this.closed=!0,this.queue.length=0,this.queuedBytes=0;try{this.sink.writeRaw(`${JSON.stringify({type:"overflow",error:"overflow, resync required"})}
14
- `)}catch(cause){this.onFailure(cause)}this.onFailure(overflow);return}this.queue.push({line,bytes,key,demotedLine,onWritten}),this.queuedBytes+=bytes,this.drain()}async flush(){for(;this.draining;)await this.draining;if(this.failure!==void 0)throw this.failure}waitForAcceptance(){return Promise.resolve()}close(){this.closed=!0,this.queue.length=0,this.queuedBytes=0}waitForDrainOrStall(writtenBytes){return new Promise((resolve,reject)=>{let timer,blockedMark=loopBlockedMark(),onDeadline=()=>{let blockedMs=loopBlockedMsSince(blockedMark);if(blockedMs>0){blockedMark=loopBlockedMark(),timer=setTimeout(onDeadline,Math.min(blockedMs,this.stallMs));return}let stall=new SocketEventQueueStallError(this.queuedBytes+writtenBytes,this.stallMs);try{this.sink.writeRaw(`${JSON.stringify({type:"overflow",error:"stalled, resync required"})}
15
- `)}catch{}reject(stall)};timer=setTimeout(onDeadline,this.stallMs),this.sink.waitForBackpressure().then(()=>{clearTimeout(timer),resolve()},cause=>{clearTimeout(timer),reject(cause)})})}drain(){return this.draining?this.draining:(this.draining=(async()=>{try{for(;!this.closed&&this.queue.length>0;){let entry=this.queue.shift();this.queuedBytes-=entry.bytes,this.sink.writeRaw(entry.line),await this.waitForDrainOrStall(entry.bytes),entry.onWritten?.()}}catch(cause){this.failure=cause,this.closed=!0,this.queue.length=0,this.queuedBytes=0,this.onFailure(cause)}})().finally(()=>{this.draining=void 0,!this.closed&&this.queue.length>0&&this.drain()}),this.draining)}};var BROADCAST_LIFECYCLE_RECORDS=new Set(["agent_start","agent_settled","agent_idle","session_opened","session_closed"]);function snapshotPlaceholderLine(record){if(record.placeholderLine!==void 0)return record.placeholderLine;let redacted=record.source===void 0?void 0:omitInlineMedia(record.source);return record.placeholderLine=redacted===void 0||redacted===record.source?record.line:serializeJsonLine(redacted),record.placeholderLine}var SessionEventFanout=class{constructor(){this.connections=new Map,this.sessionSnapshots=new Map,this.pendingQuestions=new Map,this.connectionCapabilities=new Map,this.connectionSessions=new Map,this.registeredCapabilityConnections=new Set}registerConnection(id,connection,options={}){let actor=new SocketEventSinkActor(connection,cause=>{this.connections.get(id)?.actor===actor&&(this.connections.delete(id),this.connectionCapabilities.delete(id),this.connectionSessions.delete(id),this.registeredCapabilityConnections.delete(id)),process.stderr.write(`senpi rpc connection ${id} event queue failed; closing: ${cause instanceof Error?cause.message:String(cause)}
16
- `),connection.close?.()},options.maxQueueBytes,options.stallMs);this.connections.set(id,{connection,actor}),this.connectionCapabilities.set(id,new Set),this.connectionSessions.set(id,new Set)}unregisterConnection(id){let registered=this.connections.get(id);registered&&(registered.actor.close(),this.connections.delete(id),this.connectionCapabilities.delete(id),this.connectionSessions.delete(id),this.registeredCapabilityConnections.delete(id))}attachConnectionToSession(id,sessionId){if(!this.connections.has(id))return;let sessions=this.connectionSessions.get(id)??new Set;if(!sessions.has(sessionId)){sessions.add(sessionId),this.connectionSessions.set(id,sessions),this.replaySnapshot(id,sessionId);for(let frame of this.pendingQuestions.get(sessionId)?.values()??[])this.connections.get(id)?.actor.enqueue(serializeJsonLine({...frame,remainingMs:typeof frame.deadlineAtMs=="number"?Math.max(0,frame.deadlineAtMs-Date.now()):0}))}}detachConnectionFromSession(id,sessionId){this.connectionSessions.get(id)?.delete(sessionId)}setConnectionCapabilities(id,capabilities){this.connections.get(id)&&(this.connectionCapabilities.set(id,new Set(capabilities)),this.registeredCapabilityConnections.add(id))}clearConnectionCapabilities(id){this.connections.has(id)&&(this.connectionCapabilities.set(id,new Set),this.registeredCapabilityConnections.delete(id))}hasRegisteredConnectionCapabilities(id){return this.registeredCapabilityConnections.has(id)}getConnectionCapabilities(id){if(this.registeredCapabilityConnections.has(id))return[...this.connectionCapabilities.get(id)??[]]}connectionHas(id,capability){return id===void 0?!1:this.connectionCapabilities.get(id)?.has(capability)??!1}targets(sessionId,targetId,isTargeted,recordType){return isTargeted?[targetId]:typeof recordType=="string"&&BROADCAST_LIFECYCLE_RECORDS.has(recordType)?this.connections.size>0?[...this.connections.keys()]:[void 0]:this.connections.size>0?[...this.connections.keys()].filter(id=>this.connectionSessions.get(id)?.has(sessionId)):[void 0]}get(id){return this.connections.get(id)}values(){return this.connections.values()}isEmpty(){return this.connections.size===0}broadcast(line){for(let{actor}of this.connections.values())actor.enqueue(line)}deliverToSession(sessionId,line){for(let[id,{actor}]of this.connections)this.connectionSessions.get(id)?.has(sessionId)&&actor.enqueue(line)}rememberSnapshot(sessionId,value,line,placeholderLine,source){if(value.type==="extension_ui_request"&&value.method==="question"&&typeof value.id=="string"){let pending=this.pendingQuestions.get(sessionId)??new Map;pending.set(value.id,{...value}),this.pendingQuestions.set(sessionId,pending);return}if(value.type==="question_resolved"&&typeof value.id=="string"){this.pendingQuestions.get(sessionId)?.delete(value.id);return}if(value.type==="question_updated"&&typeof value.id=="string"){let frame=this.pendingQuestions.get(sessionId)?.get(value.id);frame&&Object.assign(frame,{deadlineAtMs:value.deadlineAtMs,remainingMs:value.remainingMs});return}let event=value.assistantMessageEvent,record={line,placeholderLine,source};value.type==="message_start"||value.type==="message_update"&&event?.type==="text_start"?this.sessionSnapshots.set(sessionId,[record]):this.sessionSnapshots.has(sessionId)&&this.sessionSnapshots.get(sessionId)?.push(record),value.type==="message_end"&&this.sessionSnapshots.delete(sessionId)}forgetSession(sessionId){this.pendingQuestions.delete(sessionId),this.sessionSnapshots.delete(sessionId)}replaySnapshot(id,sessionId){let actor=this.connections.get(id)?.actor;if(!actor)return;let placeholders=this.connectionHas(id,MEDIA_PLACEHOLDERS_CAPABILITY);for(let record of this.sessionSnapshots.get(sessionId)??[])actor.enqueue(placeholders?snapshotPlaceholderLine(record):record.line)}};var SessionOpenTurns=class{constructor(){this.open=new Map}note(sessionId,type){if(type==="agent_start")this.open.set(sessionId,(this.open.get(sessionId)??0)+1);else if(type==="agent_settled"){let left=(this.open.get(sessionId)??0)-1;left>0?this.open.set(sessionId,left):this.open.delete(sessionId)}}take(sessionId){let owed=this.open.get(sessionId)??0;return this.open.delete(sessionId),owed}};var settleActors=actors=>Promise.all(actors.map(actor=>actor.flush().catch(()=>{}))).then(()=>{}),acceptActors=actors=>Promise.all(actors.map(actor=>actor.waitForAcceptance())).then(()=>{}),MAX_SHARED_STDIO_QUEUE_BYTES=64*1024*1024,MAX_SHARED_STDIO_QUEUE_RECORDS=4096,MESSAGE_KEY="message",COMPACT_DELTA_TYPES=new Set(["text_delta","thinking_delta","toolcall_delta"]);function compactDelta(value){if(value.type!=="message_update"||!Object.hasOwn(value,"message"))return;let event=value.assistantMessageEvent;if(typeof event!="object"||event===null)return;let typedEvent=event;if(!(typeof typedEvent.type!="string"||!COMPACT_DELTA_TYPES.has(typedEvent.type)||typeof typedEvent.contentIndex!="number"||typeof typedEvent.delta!="string"))return{type:typedEvent.type,contentIndex:typedEvent.contentIndex,delta:typedEvent.delta}}function demoteToDeltaOnly(value){let event=value.assistantMessageEvent;return{...value,message:null,assistantMessageEvent:{...event,partial:null}}}function toolUpdateKey(value){return value.type==="tool_execution_update"&&typeof value.toolCallId=="string"?`tool:${value.toolCallId}`:void 0}var SessionEventWriter=class{get pendingCloseRecordCount(){return this.reservedCloseRecords}get pendingCloseByteLength(){return this.reservedCloseBytes}constructor(writeRaw,waitOrSchedule,scheduleFlush){this.queues=new Map,this.fanout=new SessionEventFanout,this.connectionContext=new AsyncLocalStorage2,this.controlQueue={latestByKey:new Map,ready:!1},this.readyQueues=[],this.sealedSessions=new Set,this.workerSessions=new Set,this.openTurns=new SessionOpenTurns,this.mediaPersisters=new Map,this.flushScheduled=!1,this.controlOverflowReported=!1,this.closeOverflowReported=!1,this.closeOverflowActors=new WeakSet,this.reservedCloseRecords=0,this.reservedCloseBytes=0,this.writeRaw=writeRaw,waitOrSchedule&&scheduleFlush===void 0&&waitOrSchedule.length>0?this.scheduleFlush=waitOrSchedule:(this.waitForBackpressure=waitOrSchedule,this.scheduleFlush=scheduleFlush??(flush=>queueMicrotask(()=>{flush()})))}get bufferedRecordCount(){let count=this.inFlight?1:0;for(let queue of this.allQueues())for(let node=queue.head;node;node=node.next)count++;return count}get bufferedByteLength(){let bytes=this.inFlight?Buffer.byteLength(serializeJsonLine(this.inFlight.node.value)):0;for(let queue of this.allQueues())for(let node=queue.head;node;node=node.next)bytes+=Buffer.byteLength(serializeJsonLine(node.value));return bytes}registerConnection(id,connection,options={}){this.fanout.registerConnection(id,connection,options)}unregisterConnection(id){this.fanout.unregisterConnection(id)}attachConnectionToSession(id,sessionId){this.fanout.attachConnectionToSession(id,sessionId)}detachConnectionFromSession(id,sessionId){this.fanout.detachConnectionFromSession(id,sessionId)}setConnectionCapabilities(id,capabilities){this.fanout.setConnectionCapabilities(id,capabilities)}clearConnectionCapabilities(id){this.fanout.clearConnectionCapabilities(id)}hasRegisteredConnectionCapabilities(id){return this.fanout.hasRegisteredConnectionCapabilities(id)}getConnectionCapabilities(id){return this.fanout.getConnectionCapabilities(id)}setSessionMedia(sessionId,persister){persister===void 0?this.mediaPersisters.delete(sessionId):this.mediaPersisters.set(sessionId,persister)}setSessionKind(sessionId,kind){kind==="worker"?this.workerSessions.add(sessionId):this.workerSessions.delete(sessionId)}async flushConnection(id){let target=this.fanout.get(id);target&&await settleActors([target.actor])}withConnection(id,task){return this.connectionContext.run(id,task)}currentConnection(){return this.connectionContext.getStore()}enqueue(sessionId,value){if(this.sealedSessions.has(sessionId))return!1;let targetId=this.connectionContext.getStore(),record=value,isTargeted=record.type==="response"||record.type==="bash_execution_update"||record.type==="extension_ui_request"&&["select","confirm","input","editor"].includes(String(record.method)),tagged={...value,sessionId},line=serializeJsonLine(tagged);if(this.fanout.isEmpty()&&this.exceedsStdioCapacity(line))return this.closeSession(sessionId,{type:"response",command:"close_session",success:!1,error:"session_output_overflow, resync required"},"error"),!1;this.openTurns.note(sessionId,record.type);let targets=this.fanout.targets(sessionId,targetId,isTargeted,record.type),redacted=targets.some(target=>this.fanout.connectionHas(target,MEDIA_PLACEHOLDERS_CAPABILITY))?omitInlineMedia(tagged,this.mediaPersisters.get(sessionId)):tagged,placeholderLine=redacted===tagged?void 0:serializeJsonLine(redacted);isTargeted||this.fanout.rememberSnapshot(sessionId,tagged,line,placeholderLine,tagged);for(let target of targets){if(target!==void 0&&!this.fanout.get(target))continue;let registered=target===void 0?void 0:this.fanout.get(target),wants=placeholderLine!==void 0&&this.fanout.connectionHas(target,MEDIA_PLACEHOLDERS_CAPABILITY);if(registered){let keyed=compactDelta(tagged)!==void 0&&tagged.message!==null;registered.actor.enqueue(wants?placeholderLine:line,keyed?MESSAGE_KEY:void 0,void 0,keyed?serializeJsonLine(demoteToDeltaOnly(tagged)):void 0)}else this.appendSessionRecord(sessionId,wants?redacted:tagged,target)}return this.requestFlush(),!0}waitForSessionBackpressure(sessionId){return this.fanout.isEmpty()?this.flush():acceptActors(this.sessionActors(sessionId))}sessionActors(sessionId){return[...new Set([...this.fanout.targets(sessionId,this.currentConnection(),!1,void 0),this.currentConnection()])].flatMap(target=>{let registered=target===void 0?void 0:this.fanout.get(target);return registered?[registered.actor]:[]})}enqueueControl(value){if(this.failure!==void 0)return Promise.reject(this.failure);let targetId=this.connectionContext.getStore(),registered=targetId===void 0?void 0:this.fanout.get(targetId);if(registered)return registered.actor.enqueue(serializeJsonLine(value)),Promise.resolve();if(this.exceedsStdioCapacity(serializeJsonLine(value)))return this.controlOverflowReported||(this.controlOverflowReported=!0,this.append(this.controlQueue,{type:"overflow",error:"rpc_control_output_overflow, resync required"}),this.markReady(this.controlQueue),this.requestFlush()),Promise.reject(new Error("rpc_control_output_overflow, resync required"));let queue=targetId===void 0?this.controlQueue:this.connectionQueue(targetId),completion=new Promise((resolve,reject)=>{this.append(queue,{...value},void 0,resolve,reject)});return this.markReady(queue),this.requestFlush(),completion}sendOpenQueued(connection,record){let wire={type:"queued",for_request:record.for_request,position:record.position,in_flight:record.in_flight},target=this.fanout.get(connection);target!==void 0&&(target.actor.enqueue(serializeJsonLine(wire)),this.requestFlush())}broadcastHostRecord(record){let wire;switch(record.type){case"host_superseded":wire={type:"host_superseded",instanceId:record.instanceId,generation:record.generation,successor:record.successor};break;case"host_stalled":wire={type:"host_stalled",driftMs:record.driftMs,...record.sessionId!==void 0?{sessionId:record.sessionId}:{},...record.tool!==void 0?{tool:record.tool}:{}};break;case"host_memory_pressure":wire={type:"host_memory_pressure",rssMb:record.rssMb,...record.footprintMb!==void 0?{footprintMb:record.footprintMb}:{},...record.measure!==void 0?{measure:record.measure}:{},sessions:record.sessions,...record.main!==void 0?{main:record.main}:{},...record.kernels!==void 0?{kernels:record.kernels}:{}};break;case"host_trimmed":wire={type:"host_trimmed",footprintBeforeMb:record.footprintBeforeMb,footprintAfterMb:record.footprintAfterMb,measure:record.measure,collected:record.collected};break;default:{let exhaustive=record;throw new Error(`unexpected host record ${exhaustive}`)}}this.fanout.isEmpty()?(this.append(this.controlQueue,wire),this.markReady(this.controlQueue)):this.fanout.broadcast(serializeJsonLine(wire)),this.requestFlush()}closeSession(sessionId,response,reason,sessionPath){if(!this.settleBeforeSeal(sessionId))return;this.sealedSessions.add(sessionId),this.fanout.forgetSession(sessionId),this.mediaPersisters.delete(sessionId);let targetId=this.connectionContext.getStore(),lifecycle={type:"session_closed",sessionId,...reason&&{reason},...sessionPath&&{sessionPath}};this.fanout.isEmpty()?this.appendSessionRecord(sessionId,lifecycle):this.workerSessions.has(sessionId)?this.fanout.deliverToSession(sessionId,serializeJsonLine(lifecycle)):this.fanout.broadcast(serializeJsonLine(lifecycle));let taggedResponse={...response,sessionId},registered=targetId===void 0?void 0:this.fanout.get(targetId);registered?registered.actor.enqueue(serializeJsonLine(taggedResponse)):this.appendSessionRecord(sessionId,taggedResponse,targetId),this.requestFlush()}parkSession(sessionId,sessionPath){this.sealWithLifecycle(sessionId,{type:"session_parked",sessionId,sessionPath})}releaseSession(sessionId,sessionPath){this.sealWithLifecycle(sessionId,{type:"session_closed",sessionId,reason:"released",sessionPath})}sealWithLifecycle(sessionId,lifecycle){this.settleBeforeSeal(sessionId)&&(this.sealedSessions.add(sessionId),this.fanout.forgetSession(sessionId),this.mediaPersisters.delete(sessionId),this.fanout.isEmpty()?this.appendSessionRecord(sessionId,lifecycle):this.workerSessions.has(sessionId)?this.fanout.deliverToSession(sessionId,serializeJsonLine(lifecycle)):this.fanout.broadcast(serializeJsonLine(lifecycle)),this.requestFlush())}reserveCloseResponse(sessionId,response,records=2){let bytes=Buffer.byteLength(serializeJsonLine({...response,sessionId}))+(records===2?Buffer.byteLength(serializeJsonLine({type:"session_closed",sessionId,reason:"client_close"})):0);if(this.bufferedRecordCount+this.reservedCloseRecords+records>MAX_SHARED_STDIO_QUEUE_RECORDS||this.bufferedByteLength+this.reservedCloseBytes+bytes>MAX_SHARED_STDIO_QUEUE_BYTES){let overflow={type:"overflow",command:"close_session",error:"rpc_close_output_overflow, resync required"},targetId=this.currentConnection();if(targetId!==void 0){let actor=this.fanout.get(targetId)?.actor;actor&&!this.closeOverflowActors.has(actor)&&(this.closeOverflowActors.add(actor),actor.enqueue(serializeJsonLine(overflow),void 0,()=>this.closeOverflowActors.delete(actor)))}else this.closeOverflowReported||(this.closeOverflowReported=!0,this.append(this.controlQueue,overflow),this.markReady(this.controlQueue),this.requestFlush());return}this.reservedCloseRecords+=records,this.reservedCloseBytes+=bytes;let active=!0,release=()=>{active&&(active=!1,this.reservedCloseRecords-=records,this.reservedCloseBytes-=bytes)};return{release,complete:(terminal,reason)=>{active&&(release(),terminal?this.closeSession(sessionId,response,reason):this.appendClosedResponse(sessionId,response))}}}enqueueClosedResponse(sessionId,response){this.reserveCloseResponse(sessionId,response,1)?.complete(!1)}appendClosedResponse(sessionId,response){let targetId=this.connectionContext.getStore(),taggedResponse={...response,sessionId},registered=targetId===void 0?void 0:this.fanout.get(targetId);registered?registered.actor.enqueue(serializeJsonLine(taggedResponse)):this.appendSessionRecord(sessionId,taggedResponse,targetId),this.requestFlush()}settleBeforeSeal(sessionId){if(this.sealedSessions.has(sessionId))return!1;for(let owed=this.openTurns.take(sessionId);owed>0;owed-=1)this.enqueue(sessionId,{type:"agent_settled",reason:"session_closed"});return!this.sealedSessions.has(sessionId)}forgetSession(sessionId){this.sealedSessions.delete(sessionId),this.openTurns.take(sessionId),this.workerSessions.delete(sessionId),this.fanout.forgetSession(sessionId),this.mediaPersisters.delete(sessionId)}flush(){if(this.failure!==void 0)return Promise.reject(this.failure);if(this.flushScheduled=!1,this.drainPromise)return this.drainPromise;if(this.readyQueues.length===0)return settleActors([...this.fanout.values()].map(({actor})=>actor));let resolveDrain,rejectDrain,drain=new Promise((resolve,reject)=>{resolveDrain=resolve,rejectDrain=reject});return this.drainPromise=drain,this.drainUntilEmpty().then(resolveDrain,rejectDrain),drain.then(()=>{this.drainPromise===drain&&(this.drainPromise=void 0),this.readyQueues.length>0&&this.requestFlush()},cause=>{this.drainPromise===drain&&(this.drainPromise=void 0),this.fail(cause)}),drain}async drainUntilEmpty(){do await this.drainReadyQueues();while(this.readyQueues.length>0);await settleActors([...this.fanout.values()].map(({actor})=>actor)),this.controlOverflowReported=!1,this.reservedCloseRecords===0&&(this.closeOverflowReported=!1)}async drainReadyQueues(){for(;this.readyQueues.length>0;){let queue=this.readyQueues.shift();queue.ready=!1;let node=queue.head;if(node){this.unlink(queue,node),this.inFlight={queue,node};try{let connection=queue.targetId?this.fanout.get(queue.targetId)?.connection:void 0,writeRaw=connection?.writeRaw??this.writeRaw,waitForBackpressure=connection?.waitForBackpressure??this.waitForBackpressure;!connection&&queue.targetId||(writeRaw(serializeJsonLine(node.value)),waitForBackpressure&&await waitForBackpressure()),node.resolve?.()}catch(cause){throw node.reject?.(cause),cause}finally{this.inFlight=void 0}if(queue.head)this.markReady(queue);else if(queue.sessionId||queue.targetId)for(let[key,candidate]of this.queues)candidate===queue&&this.queues.delete(key)}}}exceedsStdioCapacity(line){return this.bufferedRecordCount+this.reservedCloseRecords>=MAX_SHARED_STDIO_QUEUE_RECORDS||this.bufferedByteLength+this.reservedCloseBytes+Buffer.byteLength(line)>MAX_SHARED_STDIO_QUEUE_BYTES}connectionQueue(targetId){let key=`connection:${targetId}`,queue=this.queues.get(key);return queue||(queue={targetId,latestByKey:new Map,ready:!1},this.queues.set(key,queue)),queue}appendSessionRecord(sessionId,value,targetId){let key=`${targetId??"default"}:${sessionId}`,queue=this.queues.get(key);if(queue||(queue={sessionId,targetId,latestByKey:new Map,ready:!1},this.queues.set(key,queue)),compactDelta(value)){let previousFull=queue.latestByKey.get(MESSAGE_KEY);previousFull&&this.demoteAndMerge(queue,previousFull);let node=this.append(queue,value,MESSAGE_KEY);queue.latestByKey.set(MESSAGE_KEY,node),this.markReady(queue);return}let toolKey=toolUpdateKey(value);if(toolKey){let previous=queue.latestByKey.get(toolKey);previous&&this.unlink(queue,previous);let node=this.append(queue,value,toolKey);queue.latestByKey.set(toolKey,node),this.markReady(queue);return}queue.latestByKey.clear(),this.append(queue,value),this.markReady(queue)}demoteAndMerge(queue,node){node.value=demoteToDeltaOnly(node.value);let current=compactDelta(node.value),preceding=node.previous,previous=preceding?compactDelta(preceding.value):void 0;if(preceding&&previous&&current&&preceding.value.message===null&&previous.type===current.type&&previous.contentIndex===current.contentIndex){let precedingEvent=preceding.value.assistantMessageEvent;preceding.value={...preceding.value,assistantMessageEvent:{...precedingEvent,delta:previous.delta+current.delta}},this.unlink(queue,node)}}append(queue,value,key,resolve,reject){let node={value,key,previous:queue.tail,resolve,reject};return queue.tail?queue.tail.next=node:queue.head=node,queue.tail=node,node}unlink(queue,node){node.previous?node.previous.next=node.next:queue.head=node.next,node.next?node.next.previous=node.previous:queue.tail=node.previous,node.key&&queue.latestByKey.get(node.key)===node&&queue.latestByKey.delete(node.key),node.previous=void 0,node.next=void 0}markReady(queue){queue.ready||this.inFlight?.queue===queue||!queue.head||(queue.ready=!0,this.readyQueues.push(queue))}requestFlush(){this.failure!==void 0||this.flushScheduled||this.drainPromise||(this.flushScheduled=!0,this.scheduleFlush(()=>this.flush()))}fail(cause){if(this.failure===void 0){this.failure=cause;for(let queue of this.allQueues())for(let node=queue.head;node;node=node.next)node.reject?.(cause)}}*allQueues(){yield*this.queues.values(),yield this.controlQueue}};function socketSink(socket){let needsDrain=!1,cut=!1;return{writeRaw(chunk){!cut&&!socket.destroyed&&(needsDrain=!socket.write(chunk))},close(){if(cut||(cut=!0,socket.destroyed))return;socket.end();let grace=setTimeout(()=>socket.destroy(),5e3);grace.unref(),socket.once("close",()=>clearTimeout(grace))},waitForBackpressure(){return socket.destroyed||!needsDrain?Promise.resolve():(needsDrain=!1,new Promise(resolve=>{let done=()=>{socket.off("drain",done),socket.off("close",done),resolve()};socket.once("drain",done),socket.once("close",done)}))}}}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),this.webviewBroker?{workerData:{webviewBroker:this.webviewBroker.port},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=>{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(),callbacks.exit(),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);return}case"reserve":acknowledgeGrant(message.signal,this.callbacks.reserve(message.path));return;case"snapshot":if(this.snapshot=message.snapshot,this.callbacks.reconcile(message.snapshot.liveSessionPaths),acknowledge(message.signal,!0),message.settled)for(let listener of[...this.listeners])listener();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.callbacks.reconcile(message.snapshot.liveSessionPaths)):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")));(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"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 WorkerSessionRegistry=class{constructor(options){this.entries=new Map,this.reservations=new SessionPathReservations,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}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(this.size>=SESSION_WORKER_LIMITS.workers)throw new Error("too_many_sessions");let handle=`rpc-${++this.serial}`,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:()=>{this.entries.get(handle)===entry&&(entry.state="closed",this.entries.delete(handle),this.reservations.releaseAll(handle),entry.closeResolve?.())},failure:error2=>{workerFailure=error2,entry.state="quarantined",process.stderr.write(`senpi rpc session ${handle} quarantined: ${error2}
17
- `)}});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 grant=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):(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(){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:entry.context,attachments:Math.max(0,entry.attachments),status:entry.state==="quarantined"?"closing":entry.state}})}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++,options?.retainOnDisconnect&&(entry.retainOnDisconnect=!0),entry.lastCommandAt=this.now(),{...result,attached:!0}}reservationCount(handle){return this.reservations.count(handle)}reserve(handle,path){let entry=this.entries.get(handle);return entry?this.reservations.owner(path)===handle?"granted":entry.state!=="opening"&&entry.state!=="open"?"conflict":this.reservations.reserve(handle,path,this.liveWorkerPaths(entry)):"conflict"}reconcile(handle,livePaths){let entry=this.entries.get(handle);if(entry?.state!=="open")return;let sessionPath=entry.worker?.snapshot?.sessionPath;this.reservations.reconcile(handle,{livePaths,sessionPath}),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),registry=options.workerConfiguration?new WorkerSessionRegistry({configuration:options.workerConfiguration,now:policy.now,closeGraceMs:idle.closeGraceMs??parseIdleExitMs(process.env[RPC_CLOSE_GRACE_MS_ENV])??1e4}):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:createEndpointReservations({agentDir:options.agentDir,socket:listenSocketPath(options),instanceId:hostInstanceId(),onFailure:hostLog})}),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,canExitWhenEmpty:idle.canExitWhenEmpty}),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,answer=>writer.enqueueControl(answer)))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)}
18
- `)},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(()=>{}),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),...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?join(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)}
19
- `)})},{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)}
20
- `))}}),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)}
21
- `)}))};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)}
22
- `)});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 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
23
- `),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)}
24
- `),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:join(directory,basename(endpoint)),host_instance:hostInstanceId()}}function listenSocketPath(options){if(!(options.listen===void 0||options.listen==="stdio://"))return resolveSocketPath(options.listen,options.agentDir)}function resolveSocketPath(value,agentDir){if(value==="unix://")return join(agentDir,"rpc","rpc.sock");if(value.startsWith("unix://")){let path=value.slice(7);return path.length===0?join(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}`}async function prepareSocketPath(socketPath){if(!(process.platform==="win32"||socketPath.startsWith("\0"))){await mkdir(dirname(socketPath),{recursive:!0,mode:448});try{await access2(socketPath)}catch(cause){if(isNodeErrorCode(cause,"ENOENT"))return;throw cause}if(await probeSocket(socketPath))throw new Error(`${socketPath}: address already in use by a live server.`);await unlink(socketPath)}}function probeSocket(socketPath){return new Promise(resolve=>{let socket=createConnection(resolveSocketTransportAddress(socketPath,process.platform)),settle=live=>{socket.destroy(),resolve(live)};socket.once("connect",()=>settle(!0)),socket.once("error",()=>settle(!1)),socket.setTimeout(1e3,()=>settle(!1))})}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}
25
- `)}function isNodeErrorCode(cause,code){return cause instanceof Error&&"code"in cause&&cause.code===code}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};
@@ -1,2 +0,0 @@
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{classifyCredentialFailure,isCommittedRotationOutput,isRotationStreamStart,rendezvousOrder,resolveConfigValue,rotationErrorFromEvent,runCredentialFailover}from"./chunk-ZCYTYHDN.js";import{activeModelBlockUntil,discoverEnvSlots,modelBlockKey,pruneModelBlocks,withModelBlock}from"./chunk-JMYO34RK.js";import"./chunk-JEZWV7JW.js";import{acquireHalfOpenLease}from"./chunk-S2TCHQTE.js";import"./chunk-7X72IACK.js";import"./chunk-KUPQO7MC.js";import"./chunk-ZPJHS64R.js";import"./chunk-GZVCRV7I.js";import"./chunk-U3VOXCGP.js";import"./chunk-RFB5CBW7.js";import"./chunk-2VZJTDUX.js";import"./chunk-2JKDZXIY.js";import"./chunk-463OK2Y4.js";import"./chunk-ATQFN5HI.js";import"./chunk-RBCQOIAD.js";import"./chunk-RKJNJ3GI.js";import"./chunk-6WCOSBI7.js";import"./chunk-YOPVJDSU.js";import"./chunk-WHPDEDCC.js";import"./chunk-HK46JMSC.js";import"./chunk-VYKBN4MR.js";import"./chunk-WDTJ6JKE.js";import"./chunk-5ROMKDLK.js";import"./chunk-3W47LTXQ.js";import"./chunk-45SZOLCU.js";import"./chunk-TAV6QZFM.js";import"./chunk-PELNNWGO.js";import{listSlots}from"./chunk-L4HVJWIF.js";import"./chunk-DMI55M2N.js";import"./chunk-PJ34QVL5.js";import"./chunk-IKOFCODM.js";import{createHash,randomUUID}from"node:crypto";async function releaseLeaseIfModelBlocked(repository,providerId,lane,slotName,leaseId,until){until!==void 0&&await repository.mutateSlotState(providerId,lane,slotName,current=>{if(current?.lease?.id!==leaseId)return current;let{lease:_released,...rest}=current;return rest})}function overlayState(slot,state){return state?{...slot,...state.blockedUntil===void 0?{}:{blockedUntil:state.blockedUntil},...state.blockReason===void 0?{}:{blockReason:state.blockReason},...state.failureCount===void 0?{}:{failureCount:state.failureCount},...state.lease===void 0?{}:{lease:state.lease}}:slot}function overlayModelBlock(slot,until){return until===void 0||slot.blockedUntil!==void 0&&slot.blockedUntil>=until?slot:{...slot,blockedUntil:until,blockReason:slot.blockReason??"rate_limit"}}async function listRotationSlots(sources,options={}){let acquireLeases=options.acquireLeases!==!1,modelId=options.modelId,now=sources.now??Date.now,{providerId,credential,env,repository}=sources,policySlots=[];for(let[name,ref]of Object.entries(sources.policy?.slots??{})){let envVarName=ref.env??`models.json:${name}`,key=ref.env!==void 0?env(ref.env):ref.value!==void 0?await resolveConfigValue(ref.value,{}):void 0;key&&policySlots.push({name,envVarName,key,source:"env"})}if(credential){let state=await repository.listSlots(providerId,"stored"),slots=[];for(let slot of listSlots(credential)){let persisted=state[slot.name],storedRevision=await repository.storedCredentialRevision(providerId,slot.name,{key:slot.key,access:slot.access,refresh:slot.refresh}),applicable=persisted?.credentialRevision===storedRevision?persisted:void 0,modelUntil=activeModelBlockUntil(applicable?.modelBlocks,modelId,now());if(acquireLeases&&modelUntil===void 0&&applicable?.blockedUntil!==void 0&&applicable.blockedUntil<=now()){let lease=await acquireHalfOpenLease(repository,providerId,"stored",slot.name,{now:(sources.now??Date.now)()});if(!lease)continue;let leasedState=(await repository.listSlots(providerId,"stored"))[slot.name],leasedApplicable=leasedState?.credentialRevision===storedRevision?leasedState:void 0,leasedModelUntil=activeModelBlockUntil(leasedApplicable?.modelBlocks,modelId,now());await releaseLeaseIfModelBlocked(repository,providerId,"stored",slot.name,lease.leaseId,leasedModelUntil),slots.push(overlayModelBlock(overlayState({name:slot.name,lane:"stored",pinned:credential.pinned===slot.name,storedRevision},leasedApplicable),leasedModelUntil));continue}slots.push(overlayModelBlock(overlayState({name:slot.name,lane:"stored",pinned:credential.pinned===slot.name,storedRevision},applicable),modelUntil))}if(policySlots.length===0)return slots;let namedSources={...sources,credential:void 0,policy:{...sources.policy,slots:{}}},namedSlots=await listEnvRotationSlots(namedSources,policySlots,acquireLeases,modelId);return[...slots,...namedSlots]}let envSlots=[...discoverEnvSlots(providerId,env),...policySlots];return listEnvRotationSlots(sources,envSlots,acquireLeases,modelId)}async function listEnvRotationSlots(sources,envSlots,acquireLeases,modelId){if(envSlots.length===0)return[];let{providerId,repository}=sources,now=sources.now??Date.now,state=await repository.listSlots(providerId,"env"),slots=[];for(let slot of envSlots){let persisted=state[slot.name],revision=await repository.envCredentialRevision(slot.envVarName,slot.key),applicable=persisted?.credentialRevision===revision?persisted:void 0,modelUntil=activeModelBlockUntil(applicable?.modelBlocks,modelId,now());if(acquireLeases&&modelUntil===void 0&&applicable?.blockedUntil!==void 0&&applicable.blockedUntil<=now()){let lease=await acquireHalfOpenLease(repository,providerId,"env",slot.name,{now:(sources.now??Date.now)()});if(!lease)continue;let leasedState=(await repository.listSlots(providerId,"env"))[slot.name];applicable=leasedState?.credentialRevision===revision?leasedState:void 0,modelUntil=activeModelBlockUntil(applicable?.modelBlocks,modelId,now()),await releaseLeaseIfModelBlocked(repository,providerId,"env",slot.name,lease.leaseId,modelUntil)}slots.push(overlayModelBlock(overlayState({name:slot.name,lane:"env",envKey:slot.key,envVarName:slot.envVarName},applicable),modelUntil))}return slots}var sha256SlotHasher=input=>createHash("sha256").update(input).digest().readBigUInt64BE(0);function modelBlockPatch(family,modelId,blockedUntil,current,now,credentialRevision){let sameMaterial=current!==void 0&&current.credentialRevision===credentialRevision,{stateVersion:_stateVersion,...kept}=sameMaterial?current:{stateVersion:0};return{...kept,lease:void 0,...credentialRevision===void 0?{}:{credentialRevision},modelBlocks:withModelBlock(sameMaterial?current.modelBlocks:void 0,modelBlockKey(family,modelId),blockedUntil,now)}}function blockPatch(block,current,now,credentialRevision,policy,modelId){if(block.reason==="rate_limit"&&block.modelFamily!==void 0&&modelId!==void 0){let blockedUntil=now+Math.min(policy?.cooldownCapMs??block.cooldownMs,block.cooldownMs);return modelBlockPatch(block.modelFamily,modelId,blockedUntil,current,now,credentialRevision)}let failureCount=(current?.failureCount??0)+1,liveModelBlocks=current?.credentialRevision===credentialRevision?pruneModelBlocks(current?.modelBlocks,now):void 0,base={failureCount,...credentialRevision===void 0?{}:{credentialRevision},...current?.lastSuccessAt===void 0?{}:{lastSuccessAt:current.lastSuccessAt},...liveModelBlocks===void 0?{}:{modelBlocks:liveModelBlocks}};return block.reason==="rate_limit"?{...base,blockedUntil:now+Math.min(policy?.cooldownCapMs??block.cooldownMs,block.cooldownMs),blockReason:"rate_limit"}:{...base,blockReason:block.reason}}function streamWithCredentialRotation(options){let{sources,runAttempt}=options,hasher=options.hasher??sha256SlotHasher,affinityKey=options.affinityKey??randomUUID(),useAffinity=sources.policy?.affinity!==!1,now=sources.now??Date.now;return runCredentialFailover({listSlots:()=>listRotationSlots(sources,options.modelId===void 0?{}:{modelId:options.modelId}),select:candidates=>{let pinned=candidates.find(candidate=>candidate.pinned===!0);if(pinned)return pinned;let winner=(useAffinity?rendezvousOrder(affinityKey,candidates,hasher):candidates)[0];if(!winner)throw new Error("credential rotation selected from an empty candidate set");return winner},runAttempt,isCommittedOutput:isCommittedRotationOutput,isStreamStart:isRotationStreamStart,errorFromEvent:rotationErrorFromEvent,classify:(error,context)=>classifyCredentialFailure(error,{...context,nowMs:now(),cooldownBaseMs:sources.policy?.cooldownBaseMs,cooldownCapMs:sources.policy?.cooldownCapMs}),onSuccess:async slot=>{await sources.repository.mutateSlotState(sources.providerId,slot.lane,slot.name,current=>current?{...current,lastSuccessAt:now(),lease:void 0,blockedUntil:void 0,blockReason:void 0,modelBlocks:pruneModelBlocks(current.modelBlocks,now(),options.modelId)}:void 0)},persistBlock:async(slot,block)=>{let revision=slot.lane==="env"&&slot.envVarName!==void 0&&slot.envKey!==void 0?await sources.repository.envCredentialRevision(slot.envVarName,slot.envKey):slot.storedRevision;await sources.repository.mutateSlotState(sources.providerId,slot.lane,slot.name,current=>blockPatch(block,current,now(),revision,sources.policy,options.modelId))},now})}export{listRotationSlots,sha256SlotHasher,streamWithCredentialRotation};
@@ -1,2 +0,0 @@
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{runRpcMode}from"./chunk-6Y7VGPJB.js";import"./chunk-NTH33AXY.js";import"./chunk-KCVSSFOV.js";import"./chunk-QQZREV6B.js";import"./chunk-JABBHOD5.js";import"./chunk-TJPMB4VH.js";import"./chunk-ZJHRDQCH.js";import"./chunk-JMYO34RK.js";import"./chunk-JEZWV7JW.js";import"./chunk-S2TCHQTE.js";import"./chunk-7X72IACK.js";import"./chunk-KUPQO7MC.js";import"./chunk-YU2P3CAR.js";import"./chunk-CIRZTP7W.js";import"./chunk-YI7SPFDN.js";import"./chunk-HB35RBP4.js";import"./chunk-RRU5LXMS.js";import"./chunk-VE3D74HN.js";import"./chunk-26UBFF6N.js";import"./chunk-ZPJHS64R.js";import"./chunk-GZVCRV7I.js";import"./chunk-U3VOXCGP.js";import"./chunk-RFB5CBW7.js";import"./chunk-2VZJTDUX.js";import"./chunk-2JKDZXIY.js";import"./chunk-463OK2Y4.js";import"./chunk-ATQFN5HI.js";import"./chunk-RBCQOIAD.js";import"./chunk-RKJNJ3GI.js";import"./chunk-CWLCGRUS.js";import"./chunk-6WCOSBI7.js";import"./chunk-KRNXUTZJ.js";import"./chunk-YOPVJDSU.js";import"./chunk-WHPDEDCC.js";import"./chunk-HK46JMSC.js";import"./chunk-VYKBN4MR.js";import"./chunk-WDTJ6JKE.js";import"./chunk-5ROMKDLK.js";import"./chunk-3W47LTXQ.js";import"./chunk-45SZOLCU.js";import"./chunk-PELNNWGO.js";import"./chunk-L4HVJWIF.js";import"./chunk-DMI55M2N.js";import"./chunk-PJ34QVL5.js";import"./chunk-IKOFCODM.js";export{runRpcMode};
@@ -1,2 +0,0 @@
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{DEFAULT_SCROLLBACK,MAX_SESSION_OUTPUT_CHARS,loadPty}from"./chunk-WIAXG52U.js";import{processBootAtMs}from"./chunk-U5KVIAHJ.js";import"./chunk-IKOFCODM.js";var pty=await loadPty(),TerminalRuntimeSession=class{constructor(command,options){this.decoder=new TextDecoder("utf-8",{fatal:!1}),this.buffer="",this.droppedChars=0,this.consumed=0,this.outputListeners=new Set,this.unsubscribeData=null,this.lastScreenWrite=null,this.command=command,this.argv=[options.command??command,...options.args??[]],this.screen=new pty.TerminalScreen({cols:options.cols,rows:options.rows,scrollback:options.scrollback??DEFAULT_SCROLLBACK}),this.session=new pty.TerminalSession(options),this.unsubscribeData=this.session.onData(chunk=>{let text=this.ingest(chunk);if(text.length!==0)for(let listener of this.outputListeners)try{listener(text)}catch{}}),this.session.start(),this.startedAtMs=Date.now()}get backend(){return this.session.backend}identity(){let pid=this.session.pid;if(pid===void 0)return;let processGroupId=this.session.processGroupId;return{pid,...processGroupId===void 0?{}:{processGroupId},startedAtMs:this.startedAtMs,bootAtMs:processBootAtMs(),argv:this.argv}}get exited(){return this.session.exited}get exitResult(){return this.session.exitResult}get totalChars(){return this.droppedChars+this.buffer.length}ingest(chunk){let text=this.decoder.decode(chunk,{stream:!0});if(text.length===0)return text;if(this.ownScreenWrite(this.screen.feed(text)),this.buffer+=text,this.buffer.length>MAX_SESSION_OUTPUT_CHARS){let overflow=this.buffer.length-MAX_SESSION_OUTPUT_CHARS;this.buffer=this.buffer.slice(overflow),this.droppedChars+=overflow}return text}onOutput(listener){return this.outputListeners.add(listener),()=>this.outputListeners.delete(listener)}readDelta(){let start=Math.max(this.consumed,this.droppedChars),dropped=Math.max(0,this.droppedChars-this.consumed),text=this.buffer.slice(start-this.droppedChars);return this.consumed=this.totalChars,{text,droppedChars:dropped}}fullOutput(){return this.buffer}snapshot(){return this.screen.snapshot()}resizeScreen(cols,rows){this.ownScreenWrite(this.screen.resize(cols,rows))}ownScreenWrite(written){written!==this.lastScreenWrite&&(this.lastScreenWrite=written,written.catch(()=>{}))}dispose(){this.unsubscribeData?.(),this.unsubscribeData=null,this.outputListeners.clear(),this.screen.dispose()}};export{TerminalRuntimeSession};
@@ -1,3 +0,0 @@
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{WakeScheduler,answeredUiRequestId,availableModelsData,buildRpcSessionState,interruptRunningTurn,onProcessContinue,rpcCommandShapeError,settledQuestionStatus,unansweredQuestionIds,unsupportedThinkingLevel,watchInbox}from"./chunk-QQZREV6B.js";import"./chunk-JABBHOD5.js";import{acquireHostEnsureLock,gcHostEndpoints,tuiSocketName}from"./chunk-MYVBK47X.js";import{engineBuildIdentity}from"./chunk-ZJHRDQCH.js";import"./chunk-KUPQO7MC.js";import{MAX_SOCKET_PATH_BYTES,authenticateSocket,createDaemonDirectories,createHostDaemonPaths,createSocketSecret,socketSecretPath,thisProcessStartTime,writeHostRegistration}from"./chunk-LR5EN45D.js";import{MAX_RPC_LINE_CHARACTERS,attachJsonlLineReader,serializeJsonLine}from"./chunk-YI7SPFDN.js";import"./chunk-RRU5LXMS.js";import"./chunk-ZPJHS64R.js";import"./chunk-GZVCRV7I.js";import"./chunk-U3VOXCGP.js";import"./chunk-RFB5CBW7.js";import"./chunk-2VZJTDUX.js";import"./chunk-2JKDZXIY.js";import{VERSION}from"./chunk-463OK2Y4.js";import"./chunk-ATQFN5HI.js";import"./chunk-RBCQOIAD.js";import"./chunk-RKJNJ3GI.js";import"./chunk-6WCOSBI7.js";import"./chunk-YOPVJDSU.js";import"./chunk-WHPDEDCC.js";import"./chunk-HK46JMSC.js";import"./chunk-VYKBN4MR.js";import"./chunk-WDTJ6JKE.js";import"./chunk-5ROMKDLK.js";import"./chunk-3W47LTXQ.js";import"./chunk-45SZOLCU.js";import"./chunk-L4HVJWIF.js";import"./chunk-DMI55M2N.js";import"./chunk-PJ34QVL5.js";import"./chunk-IKOFCODM.js";import{randomUUID}from"node:crypto";import{rm as rm2}from"node:fs/promises";import{chmod}from"node:fs/promises";import{createServer}from"node:net";async function listenControlSocket(socketPath,secret,handlers){let clients=new Set,nextConnection=0,server=createServer(socket=>{clients.add(socket),socket.once("close",()=>clients.delete(socket)),socket.on("error",()=>socket.destroy()),authenticateSocket(socket,secret,()=>acceptConnection(socket,++nextConnection,handlers))});return await new Promise((resolve,reject)=>{server.once("error",reject),server.listen(socketPath,()=>{server.off("error",reject),resolve()})}),server.on("error",error=>handlers.listenerError(error)),await chmod(socketPath,384),{close:()=>closeServer(server,clients)}}function acceptConnection(socket,id,handlers){let connection={id,send:record=>{socket.destroyed||socket.write(serializeJsonLine(record))}},detach=attachJsonlLineReader(socket,line=>{answer(connection,line,handlers)},{maxLineLength:MAX_RPC_LINE_CHARACTERS,onOversizedLine:()=>connection.send(failure(void 0,"parse","RPC line exceeds the size limit."))});socket.once("close",()=>{detach(),handlers.closed(connection)})}async function answer(connection,line,handlers){let parsed;try{parsed=JSON.parse(line)}catch{connection.send(failure(void 0,"parse","Invalid JSON."));return}let shapeError=rpcCommandShapeError(parsed);if(shapeError!==void 0||!isCommand(parsed)){connection.send(failure(void 0,"parse",shapeError??"RPC command needs a string `type`."));return}connection.send(await handlers.command(connection,parsed))}function isCommand(value){return typeof value=="object"&&value!==null&&"type"in value&&typeof value.type=="string"}function failure(id,command,error){return{...id===void 0?{}:{id},type:"response",command,success:!1,error}}function success(id,command,data){return{...id===void 0?{}:{id},type:"response",command,success:!0,...data===void 0?{}:{data}}}function closeServer(server,clients){for(let client of clients)client.destroy();return new Promise(resolve=>server.close(()=>resolve()))}var SESSION_CONTROL_COMMANDS=["get_available_models","get_available_thinking_levels","set_model","set_thinking_level","interrupt"];async function runSessionControlCommand(session,controls,command){let{id,type}=command;switch(type){case"get_available_models":return success(id,type,await availableModelsData(session));case"get_available_thinking_levels":return success(id,type,{levels:session.getAvailableThinkingLevels()});case"set_model":return await setModel(session,controls,command);case"set_thinking_level":{let level=session.getAvailableThinkingLevels().find(candidate=>candidate===command.level);return level===void 0?failure(id,type,unsupportedThinkingLevel(command.level)):(controls.selectThinkingLevel(level,command.scope!=="turn"),success(id,type))}case"interrupt":return success(id,type,await interruptRunningTurn(session,command.turnId,()=>controls.interruptTurn()));default:return}}async function setModel(session,controls,command){let{id,type}=command,model=(await session.modelRegistry.getAvailable()).find(candidate=>candidate.provider===command.provider&&candidate.id===command.modelId);if(model===void 0)return failure(id,type,`Model not found: ${String(command.provider)}/${String(command.modelId)}`);try{let change=await controls.selectModel(model);return success(id,type,{...model,systemPromptName:change?.systemPromptName})}catch(error){return failure(id,type,error instanceof Error?error.message:String(error))}}var TUI_CONTROL_CAPABILITY="tui_control",TUI_CONTROL_COMMANDS=["get_protocol_info","list_sessions","get_state","get_messages","set_session_name","subscribe","wake","extension_ui_response",...SESSION_CONTROL_COMMANDS];async function runControlCommand(context,connection,command){let{id,type}=command,{session}=context;switch(type){case"get_protocol_info":{let build=engineBuildIdentity();return success(id,type,{protocolVersion:1,serverVersion:VERSION,capabilities:[TUI_CONTROL_CAPABILITY],mode:"tui",instanceId:context.instanceId,generation:0,engineVersion:build.text,engineOrdinal:build.ordinal,commands:TUI_CONTROL_COMMANDS})}case"list_sessions":return success(id,type,{sessions:[sessionRow(session)]});case"get_state":return success(id,type,{...buildRpcSessionState(session),turn_epoch:session.externalAdmission.turnEpoch,blocking_question:context.surface.blockingQuestion(),compacting:session.isCompacting,editor_has_draft:context.surface.draftHold()!==void 0,state_version:context.feed.stateVersion});case"get_messages":return success(id,type,{messages:session.messages});case"set_session_name":{let name=typeof command.name=="string"?command.name.trim():"";return name===""?failure(id,type,"Session name cannot be empty"):(session.setSessionName(name),success(id,type))}case"subscribe":{let cursor=typeof command.cursor=="number"?command.cursor:void 0;return success(id,type,{cursor:context.feed.subscribe(connection.id,cursor,connection.send)})}case"wake":{let ids=Array.isArray(command.delivery_ids)?command.delivery_ids.filter(entry=>typeof entry=="string"):void 0,result=await context.wake(ids);return success(id,type,{admitted:result.admitted??[]})}case"extension_ui_response":return answerQuestion(context.surface,command);default:return await runSessionControlCommand(session,context.surface,command)??failure(id,type,"unsupported")}}function sessionRow(session){let manager=session.sessionManager,created=manager.getHeader()?.timestamp??null,last=manager.getEntries().at(-1);return{sessionId:session.sessionId,sessionPath:session.sessionFile??null,session_file:session.sessionFile??null,kind:"interactive",surface:"tui",cwd:manager.getCwd(),name:session.sessionName??null,created_at:created,updated_at:last?.timestamp??created,attachments:1}}function answerQuestion(surface,command){let frameId=command.id,requestId=answeredUiRequestId(command),request=requestId===void 0?void 0:surface.pendingQuestion(requestId);if(requestId===void 0||request===void 0)return failure(frameId,"extension_ui_response","unknown_request");let response=questionResponse(command,request.questions);return response==="question_incomplete"?failure(frameId,"extension_ui_response",response):response===void 0||!surface.answerQuestion(requestId,response)?failure(frameId,"extension_ui_response","invalid_response"):success(frameId,"extension_ui_response")}function questionResponse(command,questions){if(command.cancelled===!0)return{status:"cancelled",answers:{},unanswered:[]};let answers=command.answers;if(typeof answers!="object"||answers===null||Array.isArray(answers))return;let parsed={};for(let[question,value]of Object.entries(answers)){if(typeof value!="object"||value===null||!("selected"in value)||!Array.isArray(value.selected))return;let selected=value.selected.filter(entry=>typeof entry=="string"),text="text"in value&&typeof value.text=="string"?value.text:void 0;parsed[question]=text===void 0?{selected}:{selected,text}}let comment=typeof command.comment=="string"?command.comment:void 0,status=settledQuestionStatus(parsed,comment);if(status===void 0)return"question_incomplete";let unanswered=unansweredQuestionIds(questions,parsed);return{status,resolvedBy:"control_endpoint",answers:parsed,unanswered,...comment===void 0?{}:{comment}}}var ControlFeed=class{constructor(){this.seq=0,this.stateVersionValue=0,this.ring=[],this.subscribers=new Map}get stateVersion(){return this.stateVersionValue}publish(kind,data={}){kind==="state"&&(this.stateVersionValue+=1);let event={type:"session_control_event",seq:++this.seq,kind,data:kind==="state"?{...data,state_version:this.stateVersionValue}:data};this.ring.push(event),this.ring.length>256&&this.ring.shift();for(let send of this.subscribers.values())send(event)}subscribe(connection,cursor,send){if(this.subscribers.set(connection,send),cursor!==void 0)for(let event of this.ring)event.seq>cursor&&send(event);return this.seq}unsubscribe(connection){this.subscribers.delete(connection)}clear(){this.subscribers.clear()}};import{createHash}from"node:crypto";import{rmSync}from"node:fs";import{chmod as chmod2,lstat,mkdir,realpath,rm}from"node:fs/promises";import{dirname,join}from"node:path";var PRIVATE_DIRECTORY_MODE=448,REGISTRY_LOCK_WAIT_MS=5e3;async function resolveTuiSocket(agentDir,instanceId){let name=tuiSocketName(instanceId),primary=join(agentDir,"rpc","tui",name);if(Buffer.byteLength(primary)<=MAX_SOCKET_PATH_BYTES)return await makePrivateDirectory(dirname(primary)),primary;let root=join("/tmp",`senpi-rpc-${createHash("sha256").update(agentDir).digest("hex").slice(0,8)}`),tuiRoot=join(root,"tui");await makePrivateDirectory(tuiRoot);for(let directory of[root,tuiRoot])await assertPrivateDirectory(directory);let fallback=join(tuiRoot,name);if(Buffer.byteLength(fallback)>MAX_SOCKET_PATH_BYTES)throw new Error(`socket path ${fallback} exceeds ${MAX_SOCKET_PATH_BYTES} bytes`);return fallback}async function makePrivateDirectory(directory){await mkdir(directory,{recursive:!0,mode:PRIVATE_DIRECTORY_MODE}),await chmod2(directory,PRIVATE_DIRECTORY_MODE)}async function assertPrivateDirectory(directory){let stat=await lstat(await realpath(directory)),ownedByUs=process.getuid===void 0||stat.uid===process.getuid();if(!stat.isDirectory()||!ownedByUs||(stat.mode&63)!==0)throw new Error(`alt_root_unsafe: ${directory} is not a private directory of this user`)}async function registerTuiEndpoint(options){let paths=createHostDaemonPaths({socket:options.socket,agentDir:options.agentDir}),release=await acquireHostEnsureLock(options.socket,REGISTRY_LOCK_WAIT_MS);try{await writeHostRegistration(paths,{record:{pid:process.pid,processStartTime:await thisProcessStartTime()},socket:options.socket,instanceId:options.instanceId,generation:0,launchProfileId:"tui",build:engineBuildIdentity()},{fresh:!0}),await createDaemonDirectories(paths,{kind:"tui"})}finally{await release()}return{paths,socket:options.socket}}async function unregisterTuiEndpoint(entry){let release=await acquireHostEnsureLock(entry.socket,REGISTRY_LOCK_WAIT_MS).catch(()=>{});try{await rm(entry.socket,{force:!0}),await rm(socketSecretPath(entry.socket),{force:!0}),await rm(entry.paths.dir,{recursive:!0,force:!0})}finally{await release?.()}}function unregisterTuiEndpointSync(entry){rmSync(entry.socket,{force:!0}),rmSync(socketSecretPath(entry.socket),{force:!0}),rmSync(entry.paths.dir,{recursive:!0,force:!0})}var REPORT_TEXT_LIMIT=4e3;function activateControlEndpoint(parts){let{context,feed,wake}=parts,{session,surface}=context;session.externalAdmission.setEditorSource(()=>editorHold(context));let unsubscribeSession=session.subscribe(event=>{event.type==="agent_start"?feed.publish("state"):event.type==="agent_idle"?(feed.publish("completion",{turn_epoch:session.externalAdmission.turnEpoch}),feed.publish("state"),wake("idle")):event.type==="agent_end"||event.type==="queue_update"||event.type==="compaction_start"||event.type==="compaction_end"?feed.publish("state"):event.type==="message_end"&&event.message.role==="assistant"&&feed.publish("report",{text:assistantText(event.message).slice(0,REPORT_TEXT_LIMIT)})}),unsubscribeEmitted=session.externalAdmission.onEmitted(()=>{wake("emitted")}),unsubscribeInputs=session.externalAdmission.onInputsSettled(()=>queueMicrotask(()=>{wake("submission")})),stopContinue=onProcessContinue(()=>{wake("continue")}),exitCleanup=()=>unregisterTuiEndpointSync(parts.entry);process.once("exit",exitCleanup);let disposing,dispose=()=>(disposing??=(async()=>{process.removeListener("exit",exitCleanup),unsubscribeSession(),unsubscribeEmitted(),unsubscribeInputs(),stopContinue(),parts.stopInbox(),parts.scheduler.dispose(),feed.clear(),session.externalAdmission.setEditorSource(void 0),await parts.server.close(),await sessionReferenced(parts.options,surface)||await session.sessionManager.discardHeaderOnlyFile(),await unregisterTuiEndpoint(parts.entry)})(),disposing);return{socket:parts.entry.socket,wake:reason=>{wake(reason)},noteState:()=>feed.publish("state"),noteQuestions:()=>feed.publish("question",{pending:[...surface.pendingQuestionIds()]}),dispose}}function editorHold(context){let hold=context.surface.draftHold(),revision=context.editorRevision();return hold===void 0?{revision}:{hold_reason:hold,revision}}async function sessionReferenced(options,surface){if(options.isSessionReferenced===void 0)return!1;try{return await options.isSessionReferenced()}catch(error){return surface.notice(`control endpoint kept the session file: ${error instanceof Error?error.message:String(error)}`),!0}}function assistantText(message){return message.role!=="assistant"?"":message.content.flatMap(part=>part.type==="text"?[part.text]:[]).join(`
3
- `)}async function registerSessionControlEndpoint(context,options){let cleanups=[];try{let endpoint=await openEndpoint(context,options,cleanups);return{registration:{status:"registered",socket:endpoint.socket,dispose:endpoint.dispose},endpoint}}catch(error){for(let cleanup of cleanups.reverse())await Promise.resolve(cleanup()).catch(()=>{});let reason=errorText(error);return context.surface.notice(`control endpoint unavailable: ${reason}`),{registration:{status:"failed",reason}}}}async function openEndpoint(context,options,cleanups){let{session,agentDir,surface}=context;thisProcessStartTime();let headerDurable=session.sessionManager.persistHeaderNow();headerDurable.catch(()=>{});let instanceId=randomUUID(),socket=await resolveTuiSocket(agentDir,instanceId);cleanups.push(()=>rm2(socket,{force:!0}),()=>rm2(socketSecretPath(socket),{force:!0}));let secret=await createSocketSecret(socketSecretPath(socket)),feed=new ControlFeed,scheduler=new WakeScheduler(async event=>(await session.extensionRunner.emit(event),await options.drain(event)??{admitted:[]}),error=>surface.notice(`control endpoint drain failed: ${errorText(error)}`));cleanups.push(()=>scheduler.dispose());let wake=(reason,ids)=>scheduler.request(reason,ids),commandContext={instanceId,session,surface,feed,wake:ids=>wake("command",ids)},server=await listenControlSocket(socket,secret,{command:(connection,command)=>runControlCommand(commandContext,connection,command),closed:connection=>feed.unsubscribe(connection.id),listenerError:error=>surface.notice(`control endpoint listener failed: ${error.message}`)});cleanups.push(()=>server.close()),await headerDurable;let entry=await registerTuiEndpoint({agentDir,socket,instanceId});cleanups.push(()=>unregisterTuiEndpoint(entry));let inbox=await watchInbox(options.inboxDir,()=>{wake("inbox")},error=>surface.notice(`control endpoint inbox watch failed: ${errorText(error)}`));cleanups.push(()=>inbox.stop());let endpoint=activateControlEndpoint({context,options,entry,server,scheduler,feed,stopInbox:inbox.stop,wake});return endpoint.wake("inbox"),inbox.armed.then(()=>endpoint.wake("inbox")),setImmediate(()=>{gcHostEndpoints(agentDir,{kinds:["tui"]}).catch(error=>surface.notice(`control endpoint gc of dead terminals failed: ${errorText(error)}`))}),endpoint}function errorText(error){return error instanceof Error?error.message:String(error)}export{registerSessionControlEndpoint};
@@ -1,2 +0,0 @@
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{SessionSelectorComponent,createStartupTui,startStartupTui}from"./chunk-4WZF7G6N.js";import"./chunk-NTH33AXY.js";import{KeybindingsManager}from"./chunk-4GPJOGXZ.js";import{setKeybindings}from"./chunk-KCVSSFOV.js";import"./chunk-JABBHOD5.js";import"./chunk-QMRJYMNH.js";import"./chunk-7X72IACK.js";import"./chunk-YU2P3CAR.js";import"./chunk-26UBFF6N.js";import"./chunk-ZPJHS64R.js";import"./chunk-GZVCRV7I.js";import"./chunk-U3VOXCGP.js";import"./chunk-RFB5CBW7.js";import"./chunk-2VZJTDUX.js";import"./chunk-2JKDZXIY.js";import"./chunk-ZOFZRJSL.js";import"./chunk-463OK2Y4.js";import"./chunk-ATQFN5HI.js";import"./chunk-RBCQOIAD.js";import"./chunk-RKJNJ3GI.js";import"./chunk-6WCOSBI7.js";import"./chunk-YOPVJDSU.js";import"./chunk-WHPDEDCC.js";import"./chunk-HK46JMSC.js";import"./chunk-VYKBN4MR.js";import"./chunk-WDTJ6JKE.js";import"./chunk-5ROMKDLK.js";import"./chunk-3W47LTXQ.js";import"./chunk-45SZOLCU.js";import"./chunk-PELNNWGO.js";import"./chunk-L4HVJWIF.js";import"./chunk-DMI55M2N.js";import"./chunk-PJ34QVL5.js";import"./chunk-IKOFCODM.js";async function selectSession(currentSessionsLoader,allSessionsLoader,settingsManager){let ui=await createStartupTui(settingsManager);return new Promise(resolve=>{let keybindings=KeybindingsManager.create();setKeybindings(keybindings);let resolved=!1,selector=new SessionSelectorComponent(currentSessionsLoader,allSessionsLoader,path=>{resolved||(resolved=!0,ui.stop(),resolve(path))},()=>{resolved||(resolved=!0,ui.stop(),resolve(null))},()=>{ui.stop(),process.exit(0)},()=>ui.requestRender(),{showRenameHint:!1,keybindings});ui.addChild(selector),ui.setFocus(selector.getSessionList()),startStartupTui(ui,settingsManager)})}export{selectSession};