@code-yeongyu/senpi 2026.9.17-2 → 2026.9.17-3

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 (176) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/dist/bundle/chunks/{app-server-command-XSPV6BRF.js → app-server-command-HDTNYVSW.js} +1 -1
  3. package/dist/bundle/chunks/{chunk-PLUQUK3T.js → chunk-CUBEOOBJ.js} +15 -15
  4. package/dist/bundle/chunks/{chunk-ESZHT7IE.js → chunk-IMTGM3RJ.js} +1 -1
  5. package/dist/bundle/chunks/chunk-OQGI752B.js +2 -0
  6. package/dist/bundle/chunks/{chunk-Z56RXBL6.js → chunk-QDR3GME3.js} +2 -2
  7. package/dist/bundle/chunks/{chunk-ZPO5FWHM.js → chunk-QILSJ5PQ.js} +2 -2
  8. package/dist/bundle/chunks/chunk-V6IBT2QS.js +8 -0
  9. package/dist/bundle/chunks/{chunk-IGKWKAMN.js → chunk-XHTF6VKZ.js} +4 -3
  10. package/dist/bundle/chunks/{cli-main-L7WQP5V6.js → cli-main-IPY5CCRP.js} +1 -1
  11. package/dist/bundle/chunks/{help-fast-path-O6MBSNMK.js → help-fast-path-LFGHCIWO.js} +1 -1
  12. package/dist/bundle/chunks/{host-lifecycle-AI7NH6ZO.js → host-lifecycle-YPVGQSGS.js} +1 -1
  13. package/dist/bundle/chunks/{interactive-host-runtime-DKJKH5DU.js → interactive-host-runtime-KZLF3AZD.js} +1 -1
  14. package/dist/bundle/chunks/{interactive-mode-FUW5LNKL.js → interactive-mode-HFE7ROP2.js} +1 -1
  15. package/dist/bundle/chunks/multi-session-host-VMVADJFM.js +20 -0
  16. package/dist/bundle/chunks/{package-manager-cli-J26DB6GM.js → package-manager-cli-AX4WQCCG.js} +1 -1
  17. package/dist/bundle/chunks/rotation-stream-FSZVBG2T.js +2 -0
  18. package/dist/bundle/chunks/{rpc-mode-A3U63XX7.js → rpc-mode-PDYLQ5BZ.js} +1 -1
  19. package/dist/bundle/chunks/session-worker.js +71 -68
  20. package/dist/bundle/cli.js +1 -1
  21. package/dist/bundle/index.js +1 -1
  22. package/dist/bundle/rpc-entry.js +1 -1
  23. package/dist/cli/args.d.ts +19 -1
  24. package/dist/cli/args.d.ts.map +1 -1
  25. package/dist/cli/args.js +27 -1
  26. package/dist/cli/args.js.map +1 -1
  27. package/dist/core/agent-session-runtime.d.ts +14 -1
  28. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  29. package/dist/core/agent-session-runtime.js.map +1 -1
  30. package/dist/core/auth-storage.js +2 -2
  31. package/dist/core/auth-storage.js.map +1 -1
  32. package/dist/core/credential-pool/rotation-stream.d.ts.map +1 -1
  33. package/dist/core/credential-pool/rotation-stream.js +10 -5
  34. package/dist/core/credential-pool/rotation-stream.js.map +1 -1
  35. package/dist/core/extensions/builtin/mcp/index.d.ts.map +1 -1
  36. package/dist/core/extensions/builtin/mcp/index.js +11 -0
  37. package/dist/core/extensions/builtin/mcp/index.js.map +1 -1
  38. package/dist/core/extensions/builtin/mcp/service.d.ts +9 -0
  39. package/dist/core/extensions/builtin/mcp/service.d.ts.map +1 -1
  40. package/dist/core/extensions/builtin/mcp/service.js +14 -1
  41. package/dist/core/extensions/builtin/mcp/service.js.map +1 -1
  42. package/dist/core/extensions/builtin/mcp/startup-race.d.ts +20 -0
  43. package/dist/core/extensions/builtin/mcp/startup-race.d.ts.map +1 -1
  44. package/dist/core/extensions/builtin/mcp/startup-race.js +38 -1
  45. package/dist/core/extensions/builtin/mcp/startup-race.js.map +1 -1
  46. package/dist/core/extensions/index.d.ts +2 -2
  47. package/dist/core/extensions/index.d.ts.map +1 -1
  48. package/dist/core/extensions/index.js +1 -1
  49. package/dist/core/extensions/index.js.map +1 -1
  50. package/dist/core/extensions/loader.d.ts +9 -4
  51. package/dist/core/extensions/loader.d.ts.map +1 -1
  52. package/dist/core/extensions/loader.js +20 -9
  53. package/dist/core/extensions/loader.js.map +1 -1
  54. package/dist/core/extensions/types.d.ts +37 -0
  55. package/dist/core/extensions/types.d.ts.map +1 -1
  56. package/dist/core/extensions/types.js +8 -0
  57. package/dist/core/extensions/types.js.map +1 -1
  58. package/dist/core/footer-data-provider.d.ts +2 -1
  59. package/dist/core/footer-data-provider.d.ts.map +1 -1
  60. package/dist/core/footer-data-provider.js +21 -35
  61. package/dist/core/footer-data-provider.js.map +1 -1
  62. package/dist/core/model-registry.d.ts.map +1 -1
  63. package/dist/core/model-registry.js +3 -2
  64. package/dist/core/model-registry.js.map +1 -1
  65. package/dist/core/model-runtime.d.ts +4 -2
  66. package/dist/core/model-runtime.d.ts.map +1 -1
  67. package/dist/core/model-runtime.js +9 -5
  68. package/dist/core/model-runtime.js.map +1 -1
  69. package/dist/core/provider-api-key-auth.js +3 -3
  70. package/dist/core/provider-api-key-auth.js.map +1 -1
  71. package/dist/core/provider-composer.d.ts +9 -3
  72. package/dist/core/provider-composer.d.ts.map +1 -1
  73. package/dist/core/provider-composer.js +7 -4
  74. package/dist/core/provider-composer.js.map +1 -1
  75. package/dist/core/resolve-config-command.d.ts +10 -0
  76. package/dist/core/resolve-config-command.d.ts.map +1 -0
  77. package/dist/core/resolve-config-command.js +106 -0
  78. package/dist/core/resolve-config-command.js.map +1 -0
  79. package/dist/core/resolve-config-value.d.ts +4 -8
  80. package/dist/core/resolve-config-value.d.ts.map +1 -1
  81. package/dist/core/resolve-config-value.js +16 -105
  82. package/dist/core/resolve-config-value.js.map +1 -1
  83. package/dist/core/resource-loader.d.ts +7 -1
  84. package/dist/core/resource-loader.d.ts.map +1 -1
  85. package/dist/core/resource-loader.js +13 -9
  86. package/dist/core/resource-loader.js.map +1 -1
  87. package/dist/main.d.ts +5 -3
  88. package/dist/main.d.ts.map +1 -1
  89. package/dist/main.js +25 -11
  90. package/dist/main.js.map +1 -1
  91. package/dist/modes/rpc/child-reaper-syscalls.d.ts +18 -0
  92. package/dist/modes/rpc/child-reaper-syscalls.d.ts.map +1 -0
  93. package/dist/modes/rpc/child-reaper-syscalls.js +136 -0
  94. package/dist/modes/rpc/child-reaper-syscalls.js.map +1 -0
  95. package/dist/modes/rpc/child-reaper.d.ts +56 -0
  96. package/dist/modes/rpc/child-reaper.d.ts.map +1 -0
  97. package/dist/modes/rpc/child-reaper.js +140 -0
  98. package/dist/modes/rpc/child-reaper.js.map +1 -0
  99. package/dist/modes/rpc/custom-capability.d.ts +16 -0
  100. package/dist/modes/rpc/custom-capability.d.ts.map +1 -1
  101. package/dist/modes/rpc/custom-capability.js +16 -0
  102. package/dist/modes/rpc/custom-capability.js.map +1 -1
  103. package/dist/modes/rpc/host-memory-sampler.d.ts +48 -0
  104. package/dist/modes/rpc/host-memory-sampler.d.ts.map +1 -0
  105. package/dist/modes/rpc/host-memory-sampler.js +72 -0
  106. package/dist/modes/rpc/host-memory-sampler.js.map +1 -0
  107. package/dist/modes/rpc/loop-lag-watchdog.d.ts +51 -0
  108. package/dist/modes/rpc/loop-lag-watchdog.d.ts.map +1 -0
  109. package/dist/modes/rpc/loop-lag-watchdog.js +78 -0
  110. package/dist/modes/rpc/loop-lag-watchdog.js.map +1 -0
  111. package/dist/modes/rpc/multi-session-host.d.ts.map +1 -1
  112. package/dist/modes/rpc/multi-session-host.js +34 -0
  113. package/dist/modes/rpc/multi-session-host.js.map +1 -1
  114. package/dist/modes/rpc/rpc-client.d.ts +4 -2
  115. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  116. package/dist/modes/rpc/rpc-client.js +2 -1
  117. package/dist/modes/rpc/rpc-client.js.map +1 -1
  118. package/dist/modes/rpc/rpc-input-validation.d.ts +28 -0
  119. package/dist/modes/rpc/rpc-input-validation.d.ts.map +1 -1
  120. package/dist/modes/rpc/rpc-input-validation.js +63 -0
  121. package/dist/modes/rpc/rpc-input-validation.js.map +1 -1
  122. package/dist/modes/rpc/rpc-mode.d.ts +18 -5
  123. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  124. package/dist/modes/rpc/rpc-mode.js +18 -5
  125. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  126. package/dist/modes/rpc/rpc-types.d.ts +79 -2
  127. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  128. package/dist/modes/rpc/rpc-types.js +6 -0
  129. package/dist/modes/rpc/rpc-types.js.map +1 -1
  130. package/dist/modes/rpc/session-attribution.d.ts +57 -0
  131. package/dist/modes/rpc/session-attribution.d.ts.map +1 -0
  132. package/dist/modes/rpc/session-attribution.js +132 -0
  133. package/dist/modes/rpc/session-attribution.js.map +1 -0
  134. package/dist/modes/rpc/session-binding.d.ts.map +1 -1
  135. package/dist/modes/rpc/session-binding.js +19 -8
  136. package/dist/modes/rpc/session-binding.js.map +1 -1
  137. package/dist/modes/rpc/session-command-router.d.ts +26 -3
  138. package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
  139. package/dist/modes/rpc/session-command-router.js +95 -19
  140. package/dist/modes/rpc/session-command-router.js.map +1 -1
  141. package/dist/modes/rpc/session-event-fanout.d.ts +2 -0
  142. package/dist/modes/rpc/session-event-fanout.d.ts.map +1 -1
  143. package/dist/modes/rpc/session-event-fanout.js +6 -0
  144. package/dist/modes/rpc/session-event-fanout.js.map +1 -1
  145. package/dist/modes/rpc/session-event-writer.d.ts +29 -0
  146. package/dist/modes/rpc/session-event-writer.d.ts.map +1 -1
  147. package/dist/modes/rpc/session-event-writer.js +57 -0
  148. package/dist/modes/rpc/session-event-writer.js.map +1 -1
  149. package/dist/modes/rpc/session-registry.d.ts +42 -9
  150. package/dist/modes/rpc/session-registry.d.ts.map +1 -1
  151. package/dist/modes/rpc/session-registry.js +49 -3
  152. package/dist/modes/rpc/session-registry.js.map +1 -1
  153. package/dist/modes/rpc/worker-session-registry.d.ts +2 -10
  154. package/dist/modes/rpc/worker-session-registry.d.ts.map +1 -1
  155. package/dist/modes/rpc/worker-session-registry.js +6 -2
  156. package/dist/modes/rpc/worker-session-registry.js.map +1 -1
  157. package/docs/rpc.md +126 -20
  158. package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +12 -0
  159. package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
  160. package/node_modules/@earendil-works/pi-agent-core/assets/tree-sitter/javascript.wasm +0 -0
  161. package/node_modules/@earendil-works/pi-agent-core/assets/tree-sitter/provenance.json +22 -0
  162. package/node_modules/@earendil-works/pi-agent-core/assets/tree-sitter/web-tree-sitter.wasm +0 -0
  163. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  164. package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
  165. package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-ai-gateway.json +1 -1
  166. package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
  167. package/node_modules/@earendil-works/pi-ai/dist/providers/data/zai-coding-cn.json +1 -1
  168. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  169. package/node_modules/@earendil-works/pi-pty/package.json +1 -1
  170. package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
  171. package/node_modules/@earendil-works/pi-tui/package.json +1 -1
  172. package/package.json +7 -7
  173. package/dist/bundle/chunks/chunk-3Q5PD4KW.js +0 -8
  174. package/dist/bundle/chunks/chunk-YLYLKL7X.js +0 -2
  175. package/dist/bundle/chunks/multi-session-host-SMNZXFPT.js +0 -18
  176. package/dist/bundle/chunks/rotation-stream-SCVFIQ2O.js +0 -2
@@ -1,5 +1,5 @@
1
1
  import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url);
2
- import{CUSTOM_UNSUPPORTED_CAPABILITY,EXTENSION_EVENTS_CAPABILITY,MAX_RPC_LINE_CHARACTERS,RPC_CLIENT_CAPABILITIES_ENV,attachJsonlLineReader}from"./chunk-ZPO5FWHM.js";import{ENV_AGENT_DIR,VERSION,envValue,getAgentDir,isBunBinary,isBundledNode}from"./chunk-PW6XRLS6.js";import{spawn as spawn2}from"node:child_process";import{randomUUID}from"node:crypto";import{realpathSync,writeSync}from"node:fs";import{access,chmod as chmod2,mkdir as mkdir4,readFile as readFile4,rm as rm3,unlink as unlink2,writeFile as writeFile4}from"node:fs/promises";import{createConnection as createConnection2,createServer}from"node:net";import{tmpdir as tmpdir2}from"node:os";import{dirname as dirname4,extname,join as join2,resolve as resolve2}from"node:path";import{fileURLToPath as fileURLToPath2}from"node:url";import{execFile}from"node:child_process";function parseDaemonPidFile(text){let parsed;try{parsed=JSON.parse(text)}catch(error){if(error instanceof SyntaxError)return;throw error}let unguarded=parsed!==null&&isRecord(parsed)&&parsed.processStartTime===null;if(!(!isRecord(parsed)||typeof parsed.pid!="number"||!unguarded&&typeof parsed.processStartTime!="string")&&!(!Number.isInteger(parsed.pid)||parsed.pid<=0)){if(unguarded)return{pid:parsed.pid,processStartTime:null};if(!(typeof parsed.processStartTime!="string"||parsed.processStartTime.trim()===""))return{pid:parsed.pid,processStartTime:parsed.processStartTime}}}var ProcessIdentityUnreadableError=class extends Error{constructor(pid,attempts,cause){super(`process identity for live pid ${pid} stayed unreadable after ${attempts} probe attempt(s): ${cause instanceof Error?cause.message:String(cause)}`),this.name="ProcessIdentityUnreadableError",this.pid=pid,this.attempts=attempts,this.cause=cause}};async function processMatchesPidFile(pidFile,readStartTime=readProcessStartTime,isLive=processIsLive,retry={}){if(pidFile.processStartTime===null){if(!isLive(pidFile.pid))return!1;throw new ProcessIdentityUnreadableError(pidFile.pid,0,new Error("pidfile carries no process identity guard"))}let attempts=Math.max(1,retry.attempts??5),delayMs=retry.delayMs??200,lastError;for(let attempt=1;attempt<=attempts;attempt++)try{let current=await readStartTime(pidFile.pid);if(current!==void 0)return current===pidFile.processStartTime;if(!isLive(pidFile.pid))return!1;lastError=new Error("process identity probe returned no identity for a live process"),attempt<attempts&&await new Promise(resolve3=>setTimeout(resolve3,delayMs))}catch(error){if(!isLive(pidFile.pid))return!1;lastError=error,attempt<attempts&&await new Promise(resolve3=>setTimeout(resolve3,delayMs))}throw new ProcessIdentityUnreadableError(pidFile.pid,attempts,lastError)}async function readProcessIdentity(pid,platform=process.platform,timeoutMs,isLive=processIsLive){let command=platform==="win32"?{executable:"powershell.exe",args:["-NoProfile","-NonInteractive","-Command",`$process = Get-CimInstance Win32_Process -Filter "ProcessId=${String(pid)}" -ErrorAction Stop; if ($null -eq $process) { Write-Output '__SENPI_ABSENT__'; exit 0 }; $process.CreationDate.ToFileTimeUtc().ToString("D", [Globalization.CultureInfo]::InvariantCulture)`]}:{executable:"ps",args:["-o","lstart=","-p",String(pid)]};return new Promise(resolve3=>{let effectiveTimeoutMs=timeoutMs??(platform==="win32"?1e3:void 0);execFile(command.executable,command.args,{windowsHide:!0,...effectiveTimeoutMs===void 0?{}:{timeout:effectiveTimeoutMs}},(error,stdout)=>{if(error){let code="code"in error?error.code:void 0;if(platform!=="win32"&&code===1||!isLive(pid)){resolve3({kind:"absent"});return}resolve3({kind:"error",error});return}let output=stdout.trim();if(output==="__SENPI_ABSENT__")return resolve3({kind:"absent"});if(!output||platform==="win32"&&!/^\d+$/.test(output))return resolve3({kind:"error",error:new Error("invalid process identity output")});resolve3({kind:"present",identity:output})}).once("error",error=>resolve3({kind:"error",error}))})}async function stopValidatedPid(pidFile,signal){if(await processMatchesPidFile(pidFile)){try{process.kill(pidFile.pid,signal)}catch(error){if(!isNodeErrorCode(error,"ESRCH"))throw error}signal==="SIGTERM"&&await waitForGone(pidFile,1e4),signal==="SIGKILL"&&await waitForGone(pidFile,2e3)}}async function waitForGone(pidFile,timeoutMs){let deadline=Date.now()+timeoutMs;for(;Date.now()<=deadline;){if(!await processMatchesPidFile(pidFile))return!0;await delay(100)}return!await processMatchesPidFile(pidFile)}async function readProcessStartTime(pid,platform=process.platform,timeoutMs){return readProcessIdentity(pid,platform,timeoutMs).then(result=>{if(result.kind==="error")throw result.error;return result.kind==="present"?result.identity:void 0})}function processIsLive(pid){try{return process.kill(pid,0),!0}catch(error){if(isNodeErrorCode(error,"ESRCH"))return!1;if(isNodeErrorCode(error,"EPERM"))return!0;throw error}}async function waitForStartTime(pid,timeoutMs,readStartTime=readProcessStartTime,isLive=processIsLive){let deadline=Date.now()+timeoutMs;for(;Date.now()<=deadline;){let startTime;try{startTime=await readStartTime(pid)}catch{}if(startTime)return startTime;await delay(20)}if(!isLive(pid))throw new Error(`spawned daemon pid ${pid} had no process start time`)}function delay(ms){return new Promise(resolveDelay=>setTimeout(resolveDelay,ms))}function isRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function isNodeErrorCode(error,code){return error instanceof Error&&"code"in error&&error.code===code}import{spawn}from"node:child_process";import{createHash as createHash2}from"node:crypto";import{mkdir as mkdir2,open,readdir,readFile as readFile2,rm,writeFile as writeFile2}from"node:fs/promises";import{createConnection}from"node:net";import{tmpdir}from"node:os";import{dirname as dirname2,join,resolve}from"node:path";import{fileURLToPath}from"node:url";import{stat}from"node:fs/promises";var LegacyLockArtifactError=class extends Error{constructor(lockPath){super(`Legacy lock directory is present at ${lockPath}`),this.code="ELEGACY_LOCK_ARTIFACT",this.name="LegacyLockArtifactError",this.lockPath=lockPath}},DEFAULT_RETRIES={retries:100,minTimeout:20,maxTimeout:100};async function openLockDatabase(lockPath){if(typeof globalThis.Bun<"u"){let{Database}=await import("bun:sqlite"),database2=new Database(lockPath,{create:!0});return{exec:sql=>database2.exec(sql),close:()=>database2.close(!1)}}let{DatabaseSync}=await import("node:sqlite"),database=new DatabaseSync(lockPath);return{exec:sql=>database.exec(sql),close:()=>database.close()}}async function acquireOwnershipSafeLock(lockPath,options={}){let retries=options.retries??DEFAULT_RETRIES,deadline=Date.now()+retries.retries*retries.maxTimeout;for(;;){await rejectLegacyDirectory(lockPath);let busyMs=Math.max(1,Math.min(retries.maxTimeout,deadline-Date.now())),database;try{database=await openLockDatabase(lockPath),database.exec(`PRAGMA busy_timeout = ${busyMs}; BEGIN EXCLUSIVE;`);let released=!1,held=database;return async()=>{if(!released){released=!0;try{held.exec("COMMIT;")}finally{held.close()}}}}catch(error){try{database?.close()}catch{}if(await rejectLegacyDirectory(lockPath),isBusy(error)&&Date.now()<deadline){await new Promise(resolve3=>setTimeout(resolve3,Math.min(retries.minTimeout,Math.max(1,deadline-Date.now()))));continue}throw error}}}async function rejectLegacyDirectory(lockPath){try{if((await stat(lockPath)).isDirectory())throw new LegacyLockArtifactError(lockPath)}catch(error){if(error instanceof LegacyLockArtifactError||error.code!=="ENOENT")throw error}}function isBusy(error){let message=error instanceof Error?error.message:String(error);return/busy|locked/i.test(message)||error?.code==="SQLITE_BUSY"}import{createHash,randomBytes,timingSafeEqual}from"node:crypto";import{chmod,mkdir,readFile,writeFile}from"node:fs/promises";import{dirname,win32}from"node:path";var WINDOWS_PIPE_PREFIX="\\\\.\\pipe\\senpi-rpc-",SOCKET_SECRET_BYTES=32,SOCKET_SECRET_SUFFIX=".secret",SOCKET_SECRET_FILE_ENV="SENPI_RPC_SOCKET_SECRET_FILE",SOCKET_HANDSHAKE_TIMEOUT_MS=2e3;function socketSecretPath(logicalPath){if(logicalPath.toLowerCase().startsWith("\\\\.\\pipe\\"))throw new Error(`Windows RPC named-pipe addresses need a logical filesystem path for their secret: ${logicalPath}`);return`${logicalPath}${SOCKET_SECRET_SUFFIX}`}async function ensureSocketSecret(path){try{let existing=await readFile(path);if(existing.length===SOCKET_SECRET_BYTES)return existing}catch(error){if(!isNodeErrorCode2(error,"ENOENT"))throw error}return createSocketSecret(path)}async function createSocketSecret(path){await mkdir(dirname(path),{recursive:!0});let secret=randomBytes(SOCKET_SECRET_BYTES);return await writeFile(path,secret,{mode:384}),await chmod(path,384),secret}async function readSocketSecret(path){let secret=await readFile(path);if(secret.length!==SOCKET_SECRET_BYTES)throw new Error(`invalid RPC socket secret: ${path}`);return secret}function resolveSocketTransportAddress(socketPath,platform,secret){if(platform!=="win32"||socketPath.toLowerCase().startsWith("\\\\.\\pipe\\"))return socketPath;if(!/^[a-zA-Z]:[\\/]/.test(socketPath)&&!/^\\\\[^/]/.test(socketPath))throw new Error(`Windows RPC socket path must be drive-qualified or UNC: ${socketPath}`);let canonical=win32.normalize(socketPath).toLowerCase(),identity=Buffer.concat([Buffer.from(canonical,"utf8"),Buffer.from(secret??[])]),name=createHash("sha256").update(identity).digest("hex").slice(0,32);return`${WINDOWS_PIPE_PREFIX}${name}`}function authenticateSocket(socket,secret,onAuthenticated){let received=Buffer.alloc(0),finish=()=>{clearTimeout(timer),socket.off("data",onData),socket.off("error",onError)},onError=()=>{finish(),socket.destroy()},timer=setTimeout(()=>{finish(),socket.destroy()},SOCKET_HANDSHAKE_TIMEOUT_MS),onData=chunk=>{if(received=Buffer.concat([received,chunk]),received.length<secret.length)return;if(finish(),!timingSafeEqual(received.subarray(0,secret.length),Buffer.from(secret))){socket.destroy();return}let remainder=received.subarray(secret.length);remainder.length>0&&socket.unshift(remainder),onAuthenticated()};socket.on("data",onData),socket.once("error",onError),socket.once("close",finish)}function sendSocketHandshake(socket,secret){socket.write(Buffer.from(secret))}function isNodeErrorCode2(error,code){return error instanceof Error&&"code"in error&&error.code===code}var REQUIRED_CAPABILITIES=["multi_session",EXTENSION_EVENTS_CAPABILITY],SPAWNED_HOST_PROBE_TIMEOUT_MS=1e4,EXISTING_HOST_PROBE_TIMEOUT_MS=1e4,DEFAULT_READINESS_TIMEOUT_MS=1e4,DEFAULT_STOP_TIMEOUT_MS=1e4,SIGKILL_GRACE_MS=2e3,ENSURE_LOCK_WAIT_MS=EXISTING_HOST_PROBE_TIMEOUT_MS+DEFAULT_STOP_TIMEOUT_MS+SIGKILL_GRACE_MS+DEFAULT_READINESS_TIMEOUT_MS+1e4,LOCK_BUSY_WAIT_MS=100,lockOptions={retries:{retries:ENSURE_LOCK_WAIT_MS/LOCK_BUSY_WAIT_MS,minTimeout:20,maxTimeout:LOCK_BUSY_WAIT_MS}},PINNED_HOST_CLIENT_CAPABILITIES=[EXTENSION_EVENTS_CAPABILITY,CUSTOM_UNSUPPORTED_CAPABILITY];function createHostDaemonPaths(agentDir=getAgentDir()){let dir=join(agentDir,"rpc-host-daemon");return{dir,pidFile:join(dir,"host.pid"),lockFile:join(dir,"daemon.lock"),settingsFile:join(dir,"settings.json"),stderrLog:join(dir,"stderr.log")}}async function ensureHost(options){let socket=normalizeSocketPath(options.socket),paths=createHostDaemonPaths(options.agentDir);await mkdir2(paths.dir,{recursive:!0});let lockTarget=join(tmpdir(),"senpi-rpc-host-locks",createSocketLockName(socket));await mkdir2(dirname2(lockTarget),{recursive:!0}),await writeFile2(lockTarget,"",{flag:"a",mode:384}),await reapOrphanedInternalHostDirs();let release=await acquireOwnershipSafeLock(`${lockTarget}.lock`,lockOptions);try{return await options._test?.afterLockAcquired?.(),await ensureHostLocked(paths,socket,options.agentDir??getAgentDir(),options.policy,options._test)}finally{await release()}}async function ensureHostLocked(paths,socket,agentDir,policy,testOptions){let pidFile=await readPidFile(paths),protocol=await probeProtocolInfo(socket,EXISTING_HOST_PROBE_TIMEOUT_MS);if(isCompatible(protocol))return{pid:pidFile?.pid??0,socket,reused:!0};let probe=testOptions?.readProcessStartTime??readProcessStartTime,pidMatches=pidFile?await matchesPidFileOrUnknown(pidFile,probe):!1;if(protocol&&!pidMatches)throw new Error(`RPC socket ${socket} is owned by an unmanaged host`);return pidFile&&pidMatches&&await stopManagedHost(pidFile,testOptions?.stopTimeoutMs??DEFAULT_STOP_TIMEOUT_MS,probe),await cleanupState(paths),startHost(paths,socket,agentDir,policy,testOptions)}async function startHost(paths,socket,agentDir,policy,testOptions){process.platform==="win32"&&await createSocketSecret(socketSecretPath(socket)),await writeFile2(paths.settingsFile,`${JSON.stringify({socket,capabilities:PINNED_HOST_CLIENT_CAPABILITIES,coldStart:policy?.coldStart??"transient",idleExitMs:policy?.idleExitMs??DEFAULT_HOST_IDLE_EXIT_MS})}
2
+ import{CUSTOM_UNSUPPORTED_CAPABILITY,EXTENSION_EVENTS_CAPABILITY,MAX_RPC_LINE_CHARACTERS,RPC_CLIENT_CAPABILITIES_ENV,attachJsonlLineReader}from"./chunk-QILSJ5PQ.js";import{ENV_AGENT_DIR,VERSION,envValue,getAgentDir,isBunBinary,isBundledNode}from"./chunk-PW6XRLS6.js";import{spawn as spawn2}from"node:child_process";import{randomUUID}from"node:crypto";import{realpathSync,writeSync}from"node:fs";import{access,chmod as chmod2,mkdir as mkdir4,readFile as readFile4,rm as rm3,unlink as unlink2,writeFile as writeFile4}from"node:fs/promises";import{createConnection as createConnection2,createServer}from"node:net";import{tmpdir as tmpdir2}from"node:os";import{dirname as dirname4,extname,join as join2,resolve as resolve2}from"node:path";import{fileURLToPath as fileURLToPath2}from"node:url";import{execFile}from"node:child_process";function parseDaemonPidFile(text){let parsed;try{parsed=JSON.parse(text)}catch(error){if(error instanceof SyntaxError)return;throw error}let unguarded=parsed!==null&&isRecord(parsed)&&parsed.processStartTime===null;if(!(!isRecord(parsed)||typeof parsed.pid!="number"||!unguarded&&typeof parsed.processStartTime!="string")&&!(!Number.isInteger(parsed.pid)||parsed.pid<=0)){if(unguarded)return{pid:parsed.pid,processStartTime:null};if(!(typeof parsed.processStartTime!="string"||parsed.processStartTime.trim()===""))return{pid:parsed.pid,processStartTime:parsed.processStartTime}}}var ProcessIdentityUnreadableError=class extends Error{constructor(pid,attempts,cause){super(`process identity for live pid ${pid} stayed unreadable after ${attempts} probe attempt(s): ${cause instanceof Error?cause.message:String(cause)}`),this.name="ProcessIdentityUnreadableError",this.pid=pid,this.attempts=attempts,this.cause=cause}};async function processMatchesPidFile(pidFile,readStartTime=readProcessStartTime,isLive=processIsLive,retry={}){if(pidFile.processStartTime===null){if(!isLive(pidFile.pid))return!1;throw new ProcessIdentityUnreadableError(pidFile.pid,0,new Error("pidfile carries no process identity guard"))}let attempts=Math.max(1,retry.attempts??5),delayMs=retry.delayMs??200,lastError;for(let attempt=1;attempt<=attempts;attempt++)try{let current=await readStartTime(pidFile.pid);if(current!==void 0)return current===pidFile.processStartTime;if(!isLive(pidFile.pid))return!1;lastError=new Error("process identity probe returned no identity for a live process"),attempt<attempts&&await new Promise(resolve3=>setTimeout(resolve3,delayMs))}catch(error){if(!isLive(pidFile.pid))return!1;lastError=error,attempt<attempts&&await new Promise(resolve3=>setTimeout(resolve3,delayMs))}throw new ProcessIdentityUnreadableError(pidFile.pid,attempts,lastError)}async function readProcessIdentity(pid,platform=process.platform,timeoutMs,isLive=processIsLive){let command=platform==="win32"?{executable:"powershell.exe",args:["-NoProfile","-NonInteractive","-Command",`$process = Get-CimInstance Win32_Process -Filter "ProcessId=${String(pid)}" -ErrorAction Stop; if ($null -eq $process) { Write-Output '__SENPI_ABSENT__'; exit 0 }; $process.CreationDate.ToFileTimeUtc().ToString("D", [Globalization.CultureInfo]::InvariantCulture)`]}:{executable:"ps",args:["-o","lstart=","-p",String(pid)]};return new Promise(resolve3=>{let effectiveTimeoutMs=timeoutMs??(platform==="win32"?1e3:void 0);execFile(command.executable,command.args,{windowsHide:!0,...effectiveTimeoutMs===void 0?{}:{timeout:effectiveTimeoutMs}},(error,stdout)=>{if(error){let code="code"in error?error.code:void 0;if(platform!=="win32"&&code===1||!isLive(pid)){resolve3({kind:"absent"});return}resolve3({kind:"error",error});return}let output=stdout.trim();if(output==="__SENPI_ABSENT__")return resolve3({kind:"absent"});if(!output||platform==="win32"&&!/^\d+$/.test(output))return resolve3({kind:"error",error:new Error("invalid process identity output")});resolve3({kind:"present",identity:output})}).once("error",error=>resolve3({kind:"error",error}))})}async function stopValidatedPid(pidFile,signal){if(await processMatchesPidFile(pidFile)){try{process.kill(pidFile.pid,signal)}catch(error){if(!isNodeErrorCode(error,"ESRCH"))throw error}signal==="SIGTERM"&&await waitForGone(pidFile,1e4),signal==="SIGKILL"&&await waitForGone(pidFile,2e3)}}async function waitForGone(pidFile,timeoutMs){let deadline=Date.now()+timeoutMs;for(;Date.now()<=deadline;){if(!await processMatchesPidFile(pidFile))return!0;await delay(100)}return!await processMatchesPidFile(pidFile)}async function readProcessStartTime(pid,platform=process.platform,timeoutMs){return readProcessIdentity(pid,platform,timeoutMs).then(result=>{if(result.kind==="error")throw result.error;return result.kind==="present"?result.identity:void 0})}function processIsLive(pid){try{return process.kill(pid,0),!0}catch(error){if(isNodeErrorCode(error,"ESRCH"))return!1;if(isNodeErrorCode(error,"EPERM"))return!0;throw error}}async function waitForStartTime(pid,timeoutMs,readStartTime=readProcessStartTime,isLive=processIsLive){let deadline=Date.now()+timeoutMs;for(;Date.now()<=deadline;){let startTime;try{startTime=await readStartTime(pid)}catch{}if(startTime)return startTime;await delay(20)}if(!isLive(pid))throw new Error(`spawned daemon pid ${pid} had no process start time`)}function delay(ms){return new Promise(resolveDelay=>setTimeout(resolveDelay,ms))}function isRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function isNodeErrorCode(error,code){return error instanceof Error&&"code"in error&&error.code===code}import{spawn}from"node:child_process";import{createHash as createHash2}from"node:crypto";import{mkdir as mkdir2,open,readdir,readFile as readFile2,rm,writeFile as writeFile2}from"node:fs/promises";import{createConnection}from"node:net";import{tmpdir}from"node:os";import{dirname as dirname2,join,resolve}from"node:path";import{fileURLToPath}from"node:url";import{stat}from"node:fs/promises";var LegacyLockArtifactError=class extends Error{constructor(lockPath){super(`Legacy lock directory is present at ${lockPath}`),this.code="ELEGACY_LOCK_ARTIFACT",this.name="LegacyLockArtifactError",this.lockPath=lockPath}},DEFAULT_RETRIES={retries:100,minTimeout:20,maxTimeout:100};async function openLockDatabase(lockPath){if(typeof globalThis.Bun<"u"){let{Database}=await import("bun:sqlite"),database2=new Database(lockPath,{create:!0});return{exec:sql=>database2.exec(sql),close:()=>database2.close(!1)}}let{DatabaseSync}=await import("node:sqlite"),database=new DatabaseSync(lockPath);return{exec:sql=>database.exec(sql),close:()=>database.close()}}async function acquireOwnershipSafeLock(lockPath,options={}){let retries=options.retries??DEFAULT_RETRIES,deadline=Date.now()+retries.retries*retries.maxTimeout;for(;;){await rejectLegacyDirectory(lockPath);let busyMs=Math.max(1,Math.min(retries.maxTimeout,deadline-Date.now())),database;try{database=await openLockDatabase(lockPath),database.exec(`PRAGMA busy_timeout = ${busyMs}; BEGIN EXCLUSIVE;`);let released=!1,held=database;return async()=>{if(!released){released=!0;try{held.exec("COMMIT;")}finally{held.close()}}}}catch(error){try{database?.close()}catch{}if(await rejectLegacyDirectory(lockPath),isBusy(error)&&Date.now()<deadline){await new Promise(resolve3=>setTimeout(resolve3,Math.min(retries.minTimeout,Math.max(1,deadline-Date.now()))));continue}throw error}}}async function rejectLegacyDirectory(lockPath){try{if((await stat(lockPath)).isDirectory())throw new LegacyLockArtifactError(lockPath)}catch(error){if(error instanceof LegacyLockArtifactError||error.code!=="ENOENT")throw error}}function isBusy(error){let message=error instanceof Error?error.message:String(error);return/busy|locked/i.test(message)||error?.code==="SQLITE_BUSY"}import{createHash,randomBytes,timingSafeEqual}from"node:crypto";import{chmod,mkdir,readFile,writeFile}from"node:fs/promises";import{dirname,win32}from"node:path";var WINDOWS_PIPE_PREFIX="\\\\.\\pipe\\senpi-rpc-",SOCKET_SECRET_BYTES=32,SOCKET_SECRET_SUFFIX=".secret",SOCKET_SECRET_FILE_ENV="SENPI_RPC_SOCKET_SECRET_FILE",SOCKET_HANDSHAKE_TIMEOUT_MS=2e3;function socketSecretPath(logicalPath){if(logicalPath.toLowerCase().startsWith("\\\\.\\pipe\\"))throw new Error(`Windows RPC named-pipe addresses need a logical filesystem path for their secret: ${logicalPath}`);return`${logicalPath}${SOCKET_SECRET_SUFFIX}`}async function ensureSocketSecret(path){try{let existing=await readFile(path);if(existing.length===SOCKET_SECRET_BYTES)return existing}catch(error){if(!isNodeErrorCode2(error,"ENOENT"))throw error}return createSocketSecret(path)}async function createSocketSecret(path){await mkdir(dirname(path),{recursive:!0});let secret=randomBytes(SOCKET_SECRET_BYTES);return await writeFile(path,secret,{mode:384}),await chmod(path,384),secret}async function readSocketSecret(path){let secret=await readFile(path);if(secret.length!==SOCKET_SECRET_BYTES)throw new Error(`invalid RPC socket secret: ${path}`);return secret}function resolveSocketTransportAddress(socketPath,platform,secret){if(platform!=="win32"||socketPath.toLowerCase().startsWith("\\\\.\\pipe\\"))return socketPath;if(!/^[a-zA-Z]:[\\/]/.test(socketPath)&&!/^\\\\[^/]/.test(socketPath))throw new Error(`Windows RPC socket path must be drive-qualified or UNC: ${socketPath}`);let canonical=win32.normalize(socketPath).toLowerCase(),identity=Buffer.concat([Buffer.from(canonical,"utf8"),Buffer.from(secret??[])]),name=createHash("sha256").update(identity).digest("hex").slice(0,32);return`${WINDOWS_PIPE_PREFIX}${name}`}function authenticateSocket(socket,secret,onAuthenticated){let received=Buffer.alloc(0),finish=()=>{clearTimeout(timer),socket.off("data",onData),socket.off("error",onError)},onError=()=>{finish(),socket.destroy()},timer=setTimeout(()=>{finish(),socket.destroy()},SOCKET_HANDSHAKE_TIMEOUT_MS),onData=chunk=>{if(received=Buffer.concat([received,chunk]),received.length<secret.length)return;if(finish(),!timingSafeEqual(received.subarray(0,secret.length),Buffer.from(secret))){socket.destroy();return}let remainder=received.subarray(secret.length);remainder.length>0&&socket.unshift(remainder),onAuthenticated()};socket.on("data",onData),socket.once("error",onError),socket.once("close",finish)}function sendSocketHandshake(socket,secret){socket.write(Buffer.from(secret))}function isNodeErrorCode2(error,code){return error instanceof Error&&"code"in error&&error.code===code}var REQUIRED_CAPABILITIES=["multi_session",EXTENSION_EVENTS_CAPABILITY],SPAWNED_HOST_PROBE_TIMEOUT_MS=1e4,EXISTING_HOST_PROBE_TIMEOUT_MS=1e4,DEFAULT_READINESS_TIMEOUT_MS=1e4,DEFAULT_STOP_TIMEOUT_MS=1e4,SIGKILL_GRACE_MS=2e3,ENSURE_LOCK_WAIT_MS=EXISTING_HOST_PROBE_TIMEOUT_MS+DEFAULT_STOP_TIMEOUT_MS+SIGKILL_GRACE_MS+DEFAULT_READINESS_TIMEOUT_MS+1e4,LOCK_BUSY_WAIT_MS=100,lockOptions={retries:{retries:ENSURE_LOCK_WAIT_MS/LOCK_BUSY_WAIT_MS,minTimeout:20,maxTimeout:LOCK_BUSY_WAIT_MS}},PINNED_HOST_CLIENT_CAPABILITIES=[EXTENSION_EVENTS_CAPABILITY,CUSTOM_UNSUPPORTED_CAPABILITY];function createHostDaemonPaths(agentDir=getAgentDir()){let dir=join(agentDir,"rpc-host-daemon");return{dir,pidFile:join(dir,"host.pid"),lockFile:join(dir,"daemon.lock"),settingsFile:join(dir,"settings.json"),stderrLog:join(dir,"stderr.log")}}async function ensureHost(options){let socket=normalizeSocketPath(options.socket),paths=createHostDaemonPaths(options.agentDir);await mkdir2(paths.dir,{recursive:!0});let lockTarget=join(tmpdir(),"senpi-rpc-host-locks",createSocketLockName(socket));await mkdir2(dirname2(lockTarget),{recursive:!0}),await writeFile2(lockTarget,"",{flag:"a",mode:384}),await reapOrphanedInternalHostDirs();let release=await acquireOwnershipSafeLock(`${lockTarget}.lock`,lockOptions);try{return await options._test?.afterLockAcquired?.(),await ensureHostLocked(paths,socket,options.agentDir??getAgentDir(),options.policy,options._test)}finally{await release()}}async function ensureHostLocked(paths,socket,agentDir,policy,testOptions){let pidFile=await readPidFile(paths),protocol=await probeProtocolInfo(socket,EXISTING_HOST_PROBE_TIMEOUT_MS);if(isCompatible(protocol))return{pid:pidFile?.pid??0,socket,reused:!0};let probe=testOptions?.readProcessStartTime??readProcessStartTime,pidMatches=pidFile?await matchesPidFileOrUnknown(pidFile,probe):!1;if(protocol&&!pidMatches)throw new Error(`RPC socket ${socket} is owned by an unmanaged host`);return pidFile&&pidMatches&&await stopManagedHost(pidFile,testOptions?.stopTimeoutMs??DEFAULT_STOP_TIMEOUT_MS,probe),await cleanupState(paths),startHost(paths,socket,agentDir,policy,testOptions)}async function startHost(paths,socket,agentDir,policy,testOptions){process.platform==="win32"&&await createSocketSecret(socketSecretPath(socket)),await writeFile2(paths.settingsFile,`${JSON.stringify({socket,capabilities:PINNED_HOST_CLIENT_CAPABILITIES,coldStart:policy?.coldStart??"transient",idleExitMs:policy?.idleExitMs??DEFAULT_HOST_IDLE_EXIT_MS})}
3
3
  `,{mode:384});let stderr=await open(paths.stderrLog,"w",384),pidFile,child,exitedEarly,childExit;try{let launch=testOptions?.spawn??defaultHostLaunch(socket,testOptions?.hostArgs??[]);if(child=spawn(launch.command,[...launch.args],{detached:!0,windowsHide:!0,env:{...process.env,...testOptions?.env??{},[ENV_AGENT_DIR]:agentDir,[RPC_CLIENT_CAPABILITIES_ENV]:PINNED_HOST_CLIENT_CAPABILITIES.join(",")},stdio:["ignore","ignore",stderr.fd]}),childExit=new Promise(resolveExit=>{child.once("exit",(code,signal)=>{exitedEarly={code,signal},resolveExit(exitedEarly)})}),child.pid===void 0)throw new Error("failed to spawn RPC socket host");let probe=testOptions?.readProcessStartTime??readProcessStartTime,observedStartTime=await Promise.race([waitForStartTime(child.pid,1e4,probe),childExit.then(()=>{throw new Error("RPC socket host exited before its start time could be read")})]),unhurriedProbe=testOptions?.readProcessStartTime?testOptions.readProcessStartTime:pid=>readProcessStartTime(pid,process.platform,15e3),processStartTime=observedStartTime??await unhurriedProbe(child.pid).catch(()=>{});pidFile={pid:child.pid,processStartTime:processStartTime??null},await testOptions?.beforePidFileWrite?.(),await writeFile2(paths.pidFile,`${JSON.stringify(pidFile)}
4
4
  `,{mode:384}),child.unref()}catch(error){let exitedBeforeCleanup=exitedEarly;if(!exitedBeforeCleanup&&child&&child.exitCode===null&&child.signalCode===null){try{child.kill("SIGTERM")}catch{}if(childExit&&await Promise.race([childExit,delay2(2e3)]),child.exitCode===null&&child.signalCode===null)try{child.kill("SIGKILL")}catch{}}if(!exitedBeforeCleanup)throw await cleanupState(paths),error;let diagnostic2=await appendStderr(paths,`RPC socket host exited with code ${exitedBeforeCleanup.code??"null"}${exitedBeforeCleanup.signal?` (${exitedBeforeCleanup.signal})`:""} before answering get_protocol_info`);throw await cleanupState(paths),new Error(diagnostic2)}finally{await stderr.close()}let readinessTimeoutMs=testOptions?.readinessTimeoutMs??DEFAULT_READINESS_TIMEOUT_MS,result=await pollProtocolInfo(socket,readinessTimeoutMs,childExit);if(isCompatible(result.protocol))return{pid:pidFile.pid,socket,reused:!1};let stopFailure=await stopSpawnedChild(child,childExit,testOptions?.stopTimeoutMs??DEFAULT_STOP_TIMEOUT_MS).then(()=>{},error=>error instanceof Error?error.message:String(error)),message=result.protocol?`RPC socket host answered get_protocol_info with serverVersion ${result.protocol.serverVersion} and capabilities ${JSON.stringify(result.protocol.capabilities)}, but is incompatible with serverVersion ${VERSION} and required capabilities ${JSON.stringify(REQUIRED_CAPABILITIES)}`:result.exited?`RPC socket host exited with code ${result.exited.code??"null"}${result.exited.signal?` (${result.exited.signal})`:""} before answering get_protocol_info`:`spawned RPC socket host did not answer get_protocol_info within ${readinessTimeoutMs}ms`,diagnostic=await appendStderr(paths,stopFailure===void 0?message:`${message} (teardown also reported: ${stopFailure})`);throw await cleanupState(paths),new Error(diagnostic)}async function matchesPidFileOrUnknown(pidFile,probe){try{return await processMatchesPidFile(pidFile,probe)}catch(error){if(error instanceof ProcessIdentityUnreadableError)return!1;throw error}}async function stopSpawnedChild(child,childExit,termTimeoutMs){let exited=()=>child.exitCode!==null||child.signalCode!==null;if(exited())return;let signal=name=>{try{child.kill(name)}catch(error){if(!isNodeErrorCode3(error,"ESRCH"))throw error}},waitFor=ms=>Promise.race([childExit.then(()=>!0),delay2(ms).then(()=>exited())]);if(signal("SIGTERM"),!await waitFor(termTimeoutMs)&&(signal("SIGKILL"),!await waitFor(SIGKILL_GRACE_MS)))throw new Error(`RPC socket host pid ${child.pid??"?"} remained alive after SIGKILL`)}async function stopManagedHost(pidFile,termTimeoutMs,readStartTime=readProcessStartTime){if(await signalValidated(pidFile,"SIGTERM",readStartTime),!await waitForGone2(pidFile,termTimeoutMs,readStartTime)&&(await signalValidated(pidFile,"SIGKILL",readStartTime),!await waitForGone2(pidFile,SIGKILL_GRACE_MS,readStartTime)))throw new Error(`RPC socket host pid ${pidFile.pid} remained alive after SIGKILL`)}async function resolvePidFileOwnership(pidFile,readStartTime){try{return await processMatchesPidFile(pidFile,readStartTime,processIsLive,{attempts:1})?"owns":"gone"}catch(error){if(error instanceof ProcessIdentityUnreadableError)return"unknown";throw error}}async function signalValidated(pidFile,signal,readStartTime=readProcessStartTime){if(await resolvePidFileOwnership(pidFile,readStartTime)==="owns")try{process.kill(pidFile.pid,signal)}catch(error){if(!isNodeErrorCode3(error,"ESRCH"))throw error}}async function waitForGone2(pidFile,timeoutMs,readStartTime=readProcessStartTime){let deadline=Date.now()+timeoutMs;for(;Date.now()<=deadline;){if(await resolvePidFileOwnership(pidFile,readStartTime)==="gone")return!0;await delay2(50)}return await resolvePidFileOwnership(pidFile,readStartTime)==="gone"}async function pollProtocolInfo(socket,timeoutMs,childExit){let deadline=Date.now()+timeoutMs,lastProtocol;for(;Date.now()<=deadline;){let probe=probeProtocolInfo(socket,Math.min(SPAWNED_HOST_PROBE_TIMEOUT_MS,Math.max(1,deadline-Date.now()))),raced=childExit?await Promise.race([probe,childExit]):await probe;if(isChildExit(raced)){let info=await probe;if(info){if(lastProtocol=info,isCompatible(info))return{protocol:info}}else return{protocol:lastProtocol,exited:raced}}else if(raced&&(lastProtocol=raced,isCompatible(raced)))return{protocol:raced};await delay2(50)}return{protocol:lastProtocol}}function isChildExit(value){return!!value&&"code"in value&&"signal"in value}async function probeProtocolInfo(socketPath,timeoutMs){let secret;if(process.platform==="win32")try{secret=await readSocketSecret(socketSecretPath(socketPath))}catch{return}return new Promise(resolveProbe=>{let socket=createConnection(resolveSocketTransportAddress(socketPath,process.platform,secret)),buffer="",settled=!1,finish=value=>{settled||(settled=!0,clearTimeout(timeout),socket.destroy(),resolveProbe(value))},timeout=setTimeout(()=>finish(),timeoutMs);socket.once("connect",()=>{socket.write(`{"id":"ensure-host-probe","type":"get_protocol_info"}
5
5
  `)}),socket.on("data",chunk=>{buffer+=chunk.toString("utf8");let newline=buffer.indexOf(`
@@ -0,0 +1,2 @@
1
+ import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url);
2
+ import{getShellConfig}from"./chunk-KPSJKRO6.js";import{getOverflowPatterns}from"./chunk-WHS3V662.js";import{normalizeProviderError}from"./chunk-TEPMHNKQ.js";import{PROVIDER_NOT_CONFIGURED_PREFIX}from"./chunk-B2F5G2RY.js";import{extract429RetryAfterMs}from"./chunk-7DGJYBYJ.js";import{spawn}from"child_process";function sleep(ms,signal){return new Promise((resolve,reject)=>{if(signal?.aborted){reject(new Error("Aborted"));return}let timeout=setTimeout(resolve,ms);signal?.addEventListener("abort",()=>{clearTimeout(timeout),reject(new Error("Aborted"))})})}var COMMAND_EXECUTION_MAX_ATTEMPTS=3,COMMAND_EXECUTION_BACKOFF_MS=[250,1e3],COMMAND_TIMEOUT_MS=1e4,COMMAND_MAX_OUTPUT_BYTES=1024*1024;function runCommandProcess(file,args,options){return new Promise(resolveOutcome=>{let spawnOptions={shell:options.shell,windowsHide:!0,...options.env===void 0?{}:{env:{...process.env,...options.env}}},child=options.stdin===void 0?spawn(file,[...args],{...spawnOptions,stdio:["ignore","pipe","ignore"]}):spawn(file,[...args],{...spawnOptions,stdio:["pipe","pipe","ignore"]}),stdout="",settled=!1,finish=outcome=>{settled||(settled=!0,clearTimeout(timer),resolveOutcome(outcome))},timer=setTimeout(()=>{child.kill("SIGTERM"),child.unref(),finish({executed:!0,value:void 0})},COMMAND_TIMEOUT_MS);child.stdout.setEncoding("utf-8"),child.stdout.on("data",chunk=>{stdout+=chunk,!(stdout.length<=COMMAND_MAX_OUTPUT_BYTES)&&(child.kill("SIGTERM"),finish({executed:!0,value:void 0}))}),child.on("error",error=>finish({executed:error.code!=="ENOENT",value:void 0})),child.on("close",code=>{let value=stdout.trim();finish({executed:!0,value:code===0&&value?value:void 0})}),child.stdin?.end(options.stdin)})}async function executeWithConfiguredShell(command,env){try{let{shell,args,commandTransport}=getShellConfig(),commandFromStdin=commandTransport==="stdin";return await runCommandProcess(shell,commandFromStdin?args:[...args,command],{shell:!1,...commandFromStdin?{stdin:command}:{},...env===void 0?{}:{env}})}catch{return{executed:!1,value:void 0}}}async function executeCommandOnce(command,env){if(process.platform==="win32"){let configured=await executeWithConfiguredShell(command,env);if(configured.executed)return configured.value}return(await runCommandProcess(command,[],{shell:!0,...env===void 0?{}:{env}})).value}async function runConfigCommand(commandConfig,env){let command=commandConfig.slice(1);for(let attempt=0;attempt<COMMAND_EXECUTION_MAX_ATTEMPTS;attempt++){let value=await executeCommandOnce(command,env);if(value!==void 0)return value;let backoffMs=COMMAND_EXECUTION_BACKOFF_MS[attempt];backoffMs!==void 0&&await sleep(backoffMs)}}var commandResultCache=new Map,ENV_VAR_NAME_RE=/^[A-Za-z_][A-Za-z0-9_]*$/,ENV_VAR_NAME_PREFIX_RE=/^[A-Za-z_][A-Za-z0-9_]*/;function appendLiteral(parts,value){if(!value)return;let previousPart=parts[parts.length-1];if(previousPart?.type==="literal"){previousPart.value+=value;return}parts.push({type:"literal",value})}function parseConfigValueTemplate(config){let parts=[],index=0;for(;index<config.length;){let dollarIndex=config.indexOf("$",index);if(dollarIndex<0){appendLiteral(parts,config.slice(index));break}appendLiteral(parts,config.slice(index,dollarIndex));let nextChar=config[dollarIndex+1];if(nextChar==="$"||nextChar==="!"){appendLiteral(parts,nextChar),index=dollarIndex+2;continue}if(nextChar==="{"){let endIndex=config.indexOf("}",dollarIndex+2);if(endIndex<0){appendLiteral(parts,"$"),index=dollarIndex+1;continue}let name=config.slice(dollarIndex+2,endIndex);ENV_VAR_NAME_RE.test(name)?parts.push({type:"env",name}):appendLiteral(parts,config.slice(dollarIndex,endIndex+1)),index=endIndex+1;continue}let match=config.slice(dollarIndex+1).match(ENV_VAR_NAME_PREFIX_RE);if(match){parts.push({type:"env",name:match[0]}),index=dollarIndex+1+match[0].length;continue}appendLiteral(parts,"$"),index=dollarIndex+1}return parts}function parseConfigValueReference(config){return config.startsWith("!")?{type:"command",config}:{type:"template",parts:parseConfigValueTemplate(config)}}function resolveEnvConfigValue(name,env){return env?.[name]||process.env[name]||void 0}function getTemplateEnvVarNames(parts){let names=[];for(let part of parts)part.type!=="env"||names.includes(part.name)||names.push(part.name);return names}function resolveTemplate(parts,env){let resolved="";for(let part of parts){if(part.type==="literal"){resolved+=part.value;continue}let envValue=resolveEnvConfigValue(part.name,env);if(envValue===void 0)return;resolved+=envValue}return resolved}function getConfigValueEnvVarNames(config){let reference=parseConfigValueReference(config);return reference.type==="template"?getTemplateEnvVarNames(reference.parts):[]}function getMissingConfigValueEnvVarNames(config,env){return getConfigValueEnvVarNames(config).filter(name=>resolveEnvConfigValue(name,env)===void 0)}function isCommandConfigValue(config){return parseConfigValueReference(config).type==="command"}function isConfigValueConfigured(config,env){return getMissingConfigValueEnvVarNames(config,env).length===0}function resolveConfigValue(config,env){let reference=parseConfigValueReference(config);return reference.type==="command"?env===void 0?executeCommand(reference.config):runConfigCommand(reference.config,env):Promise.resolve(resolveTemplate(reference.parts,env))}function executeCommand(commandConfig){let cached=commandResultCache.get(commandConfig);if(cached)return cached;let result=runConfigCommand(commandConfig);return commandResultCache.set(commandConfig,result),result}function resolveConfigValueUncached(config,env){let reference=parseConfigValueReference(config);return reference.type==="command"?runConfigCommand(reference.config,env):Promise.resolve(resolveTemplate(reference.parts,env))}async function resolveConfigValueOrThrow(config,description,env){let resolvedValue=await resolveConfigValueUncached(config,env);if(resolvedValue!==void 0)return resolvedValue;let reference=parseConfigValueReference(config);if(reference.type==="command")throw new Error(`Failed to resolve ${description} from shell command: ${reference.config.slice(1)}`);if(reference.type==="template"){let missingEnvVars=getMissingConfigValueEnvVarNames(config,env);if(missingEnvVars.length===1)throw new Error(`Failed to resolve ${description} from environment variable: ${missingEnvVars[0]}`);if(missingEnvVars.length>1)throw new Error(`Failed to resolve ${description} from environment variables: ${missingEnvVars.join(", ")}`)}throw new Error(`Failed to resolve ${description}`)}async function resolveHeadersOrThrow(headers,description,env){if(!headers)return;let resolved={};for(let[key,value]of Object.entries(headers))resolved[key]=await resolveConfigValueOrThrow(value,`${description} header "${key}"`,env);return Object.keys(resolved).length>0?resolved:void 0}function rendezvousOrder(key,slots,hasher){return[...slots].map(slot=>({slot,score:hasher(`${key}\0${slot.name}`)})).sort((left,right)=>right.score>left.score?1:right.score<left.score?-1:0).map(({slot})=>slot)}var TURN_RETRY_SUPPRESSION_PREFIX="senpi:no-turn-retry:",DEFAULT_SLOT_BLOCK_MS=6e4,MAX_SLOT_BLOCK_MS=2880*60*1e3;var COOLDOWN_BASE_MS=DEFAULT_SLOT_BLOCK_MS,COOLDOWN_CAP_MS=MAX_SLOT_BLOCK_MS,RETRY_SAME_MAX_ATTEMPTS=2;function rateLimitCooldown(failureCount,serverHintMs,policy={}){let cap=policy.capMs??COOLDOWN_CAP_MS,base=policy.baseMs??COOLDOWN_BASE_MS,backoff=Math.min(cap,base*2**Math.max(0,failureCount)),floored=serverHintMs===void 0?backoff:Math.max(backoff,serverHintMs);return{cooldownMs:Math.min(cap,floored),retryAfterWasCapped:floored>cap}}var INVALID_KEY_TEXT=/invalid[ _-]?(?:api[ _-]?)?key|authentication[_ ]?error|invalid x-api-key|unauthorized/i,ACCOUNT_SCOPED_403_TEXT=/account|credential|token|api[ _-]?key|organization|subscription/i,RATE_LIMIT_TEXT=/rate[ _-]?limit|too many requests|resource_exhausted/i,BILLING_TEXT=/billing|credits?[ _-]?(?:required|exhausted|balance)|insufficient[ _-]?(?:funds|quota|credit)|payment[ _-]?required|quota[ _-]?exhausted/i,OVERLOAD_TEXT=/overloaded/i,NETWORK_TEXT=/econnreset|econnrefused|etimedout|enotfound|socket hang up|fetch failed|network error|request timed out/i,FAIL_FAST_TEXT=/context[ _-]?(?:length|window)|maximum context|invalid[ _-]?model|model[ _-]?not[ _-]?found|malformed[ _-]?stream|premature[ _-]?(?:close|stream)/i,ABORT_TEXT=/\baborted?\b/i;function isAbort(error,message){return error instanceof Error&&error.name==="AbortError"?!0:ABORT_TEXT.test(message)}function isOverflowText(text){return getOverflowPatterns().some(pattern=>pattern.test(text))}function classifyCredentialFailure(error,context={}){let normalized=normalizeProviderError(error),text=normalized.messageCarriesBody?normalized.message:`${normalized.message} ${normalized.body??""}`,status=normalized.status,failureCount=context.failureCount??0;if(isAbort(error,text))return{kind:"fail_request"};if(text.includes(PROVIDER_NOT_CONFIGURED_PREFIX))return{kind:"failover",block:{reason:"auth_error"}};if(status===401||INVALID_KEY_TEXT.test(text))return{kind:"failover",block:{reason:"auth_error"}};if(status===403)return ACCOUNT_SCOPED_403_TEXT.test(text)?{kind:"failover",block:{reason:"auth_error"}}:{kind:"fail_request"};if(status===402||BILLING_TEXT.test(text))return{kind:"failover",block:{reason:"account_disabled"}};if(status===429||RATE_LIMIT_TEXT.test(text)){let hint=extract429RetryAfterMs({status:status??429,bodyText:text});return{kind:"failover",block:{reason:"rate_limit",...rateLimitCooldown(failureCount,hint,{baseMs:context.cooldownBaseMs,capMs:context.cooldownCapMs})}}}return isOverflowText(text)||status===400||status===404||FAIL_FAST_TEXT.test(text)?{kind:"fail_request"}:status===529||OVERLOAD_TEXT.test(text)||status!==void 0&&status>=500&&status<600?{kind:"retry_same",maxAttempts:RETRY_SAME_MAX_ATTEMPTS}:status===408||NETWORK_TEXT.test(text)?{kind:"retry_same",maxAttempts:RETRY_SAME_MAX_ATTEMPTS}:{kind:"fail_request"}}var CredentialFailoverError=class extends Error{constructor(action,original,options){let detail=original instanceof Error?original.message:String(original);super(`${options.suppressTurnRetry?TURN_RETRY_SUPPRESSION_PREFIX:""}${detail}`,{cause:original}),this.name="CredentialFailoverError",this.action=action,this.original=original,this.suppressTurnRetry=options.suppressTurnRetry,this.retryAt=options.retryAt}};function isAvailable(slot,now){return!(slot.blockReason==="auth_error"||slot.blockReason==="account_disabled"||slot.blockedUntil!==void 0&&slot.blockedUntil>now)}function soonestRetryAt(slots,now){let deadlines=slots.map(slot=>slot.blockedUntil).filter(value=>value!==void 0&&value>now);return deadlines.length===0?void 0:Math.min(...deadlines)}async function settle(stream){let iterator=stream[Symbol.asyncIterator]();try{await iterator.return?.(void 0)}catch{}}async function*runCredentialFailover(options){let now=options.now??Date.now,classify=options.classify??classifyCredentialFailure,attempted=new Set,retriesBySlot=new Map,lastError,lastOriginal;for(;;){let slots=await options.listSlots(),candidates=slots.filter(slot2=>!attempted.has(slot2.name)&&isAvailable(slot2,now()));if(candidates.length===0){let retryAt=soonestRetryAt(slots,now());throw lastError!==void 0&&lastOriginal!==void 0?new CredentialFailoverError(lastError.action,lastOriginal,{suppressTurnRetry:lastError.suppressTurnRetry,...retryAt===void 0?{}:{retryAt}}):new CredentialFailoverError({kind:"fail_request"},new Error("No credential slots available"),{suppressTurnRetry:!1,...retryAt===void 0?{}:{retryAt}})}let slot=options.select(candidates),committedOutput=!1,attemptStream;try{attemptStream=await options.runAttempt(slot);for await(let event of attemptStream){let failure=options.errorFromEvent?.(event);if(failure!==void 0)throw failure;committedOutput||=options.isCommittedOutput(event),yield event}await options.onSuccess?.(slot);return}catch(error){attemptStream&&await settle(attemptStream);let failureCount=(slot.failureCount??0)+(retriesBySlot.get(slot.name)??0),action=classify(error,{failureCount});if(lastOriginal=error,action.kind==="retry_same"&&!committedOutput){let used=(retriesBySlot.get(slot.name)??0)+1;if(retriesBySlot.set(slot.name,used),used<action.maxAttempts)continue;throw new CredentialFailoverError(action,error,{suppressTurnRetry:!1})}if(action.kind!=="failover")throw new CredentialFailoverError(action,error,{suppressTurnRetry:committedOutput});await options.persistBlock(slot,action.block),attempted.add(slot.name);let failure=new CredentialFailoverError(action,error,{suppressTurnRetry:committedOutput});if(lastError=failure,await options.onRotate?.({slot,block:action.block,attempt:attempted.size,committedOutput}),committedOutput)throw failure}}}export{sleep,getConfigValueEnvVarNames,isCommandConfigValue,isConfigValueConfigured,resolveConfigValue,resolveConfigValueOrThrow,resolveHeadersOrThrow,TURN_RETRY_SUPPRESSION_PREFIX,rendezvousOrder,classifyCredentialFailure,CredentialFailoverError,runCredentialFailover};
@@ -1,5 +1,5 @@
1
1
  import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url);
2
- import{readSocketSecret,resolveSocketTransportAddress,sendSocketHandshake,socketSecretPath}from"./chunk-ESZHT7IE.js";import{attachJsonlLineReader,serializeJsonLine}from"./chunk-ZPO5FWHM.js";import{sanitizeBinaryOutput}from"./chunk-KPSJKRO6.js";import{dropFailedAssistantTurns}from"./chunk-WHS3V662.js";import{copyContextProvenance}from"./chunk-EFXPIEEC.js";import{APP_NAME,getAgentDir,getSessionsDir,normalizePath,resolvePath}from"./chunk-PW6XRLS6.js";var COMPACTION_SUMMARY_PREFIX=`The conversation history before this point was compacted into the following summary:
2
+ import{readSocketSecret,resolveSocketTransportAddress,sendSocketHandshake,socketSecretPath}from"./chunk-IMTGM3RJ.js";import{attachJsonlLineReader,serializeJsonLine}from"./chunk-QILSJ5PQ.js";import{sanitizeBinaryOutput}from"./chunk-KPSJKRO6.js";import{dropFailedAssistantTurns}from"./chunk-WHS3V662.js";import{copyContextProvenance}from"./chunk-EFXPIEEC.js";import{APP_NAME,getAgentDir,getSessionsDir,normalizePath,resolvePath}from"./chunk-PW6XRLS6.js";var COMPACTION_SUMMARY_PREFIX=`The conversation history before this point was compacted into the following summary:
3
3
 
4
4
  <summary>
5
5
  `,COMPACTION_SUMMARY_SUFFIX=`
@@ -37,4 +37,4 @@ Current working directory: ${issue.fallbackCwd}`}function formatMissingSessionCw
37
37
  ${issue.sessionCwd}
38
38
 
39
39
  continue in current cwd
40
- ${issue.fallbackCwd}`}var MissingSessionCwdError=class extends Error{constructor(issue){super(formatMissingSessionCwdError(issue)),this.name="MissingSessionCwdError",this.issue=issue}};function assertSessionCwdExists(sessionManager,fallbackCwd){let issue=getMissingSessionCwdIssue(sessionManager,fallbackCwd);if(issue)throw new MissingSessionCwdError(issue)}import{spawn}from"node:child_process";import{createConnection}from"node:net";var RpcCommandError=class extends Error{constructor(message,errorCode,errorData){super(message),this.name="RpcCommandError",this.errorCode=errorCode,this.errorData=errorData}};function isProviderAccountEvent(event){return event.type==="auth_accounts_changed"||event.type==="account_failover"}var RpcTransportGoneError=class extends Error{constructor(message="Shared RPC host is unavailable"){super(message),this.code="rpc_transport_gone",this.name="RpcTransportGoneError"}};function isTransportGoneError(error){return error instanceof RpcTransportGoneError||error instanceof Error&&(error.message==="Client not started"||error.message.startsWith("RPC transport is not writable.")||error.message==="RPC socket closed")}var RpcClientOpenInFlightError=class extends Error{constructor(){super("An open_session request is already in flight"),this.code="open_session_in_flight",this.name="RpcClientOpenInFlightError"}},MAX_PENDING_SESSION_EVENTS=512,MAX_PENDING_SESSION_EVENT_BYTES=1024*1024,RpcClient=class{constructor(options={}){this.process=null,this.socket=null,this.stopReadingStdout=null,this.eventListeners=[],this.pendingRequests=new Map,this.requestId=0,this.pendingOpenSession=!1,this.pendingSessionEvents=[],this.pendingSessionEventBytes=0,this.stderr="",this.exitError=null,this.disconnectNotified=!1,this.stopping=!1,this.options=options}async start(){if(this.process||this.socket)throw new Error("Client already started");if(this.exitError=null,this.stopping=!1,this.disconnectNotified=!1,this.options.socketPath){await this.startSocket(this.options.socketPath);return}let cliPath=this.options.cliPath??"dist/cli.js",args=["--mode","rpc"];this.options.provider&&args.push("--provider",this.options.provider),this.options.model&&args.push("--model",this.options.model),this.options.args&&args.push(...this.options.args);let childProcess=spawn("node",[cliPath,...args],{cwd:this.options.cwd,env:{...process.env,SENPI_RUNTIME:"node",...this.options.env},stdio:["pipe","pipe","pipe"],windowsHide:!0});if(this.process=childProcess,childProcess.stderr?.on("data",data=>{this.stderr+=data.toString(),process.stderr.write(data)}),childProcess.once("exit",(code,signal)=>{if(this.process!==childProcess)return;let error=this.createProcessExitError(code,signal);this.exitError=error,this.rejectPendingRequests(error)}),childProcess.once("error",error=>{if(this.process!==childProcess)return;let processError=new Error(`Agent process error: ${error.message}. Stderr: ${this.stderr}`);this.exitError=processError,this.rejectPendingRequests(processError)}),childProcess.stdin?.on("error",error=>{if(this.process!==childProcess)return;let stdinError=this.exitError??new Error(`Agent process stdin error: ${error.message}. Stderr: ${this.stderr}`);this.exitError=stdinError,this.rejectPendingRequests(stdinError)}),this.stopReadingStdout=attachJsonlLineReader(childProcess.stdout,line=>{this.handleLine(line)}),await new Promise(resolve3=>setTimeout(resolve3,100)),this.process.exitCode!==null){let error=this.exitError??this.createProcessExitError(this.process.exitCode,this.process.signalCode);throw this.exitError=error,error}}async stop(){if(this.pendingOpenSession=!1,this.pendingSessionEvents=[],this.pendingSessionEventBytes=0,this.socket){this.stopping=!0,this.stopReadingStdout?.(),this.stopReadingStdout=null,this.socket.destroy(),this.socket=null,this.sessionId=void 0,this.pendingOpenSession=!1,this.pendingSessionEvents=[],this.notifyDisconnect(new RpcTransportGoneError);return}this.process&&(this.stopReadingStdout?.(),this.stopReadingStdout=null,this.process.kill("SIGTERM"),await new Promise(resolve3=>{let timeout=setTimeout(()=>{this.process?.kill("SIGKILL"),resolve3()},1e3);this.process?.on("exit",()=>{clearTimeout(timeout),resolve3()})}),this.process=null,this.pendingRequests.clear())}async startSocket(path){let secret=process.platform==="win32"?await readSocketSecret(socketSecretPath(path)):void 0,socket=createConnection(resolveSocketTransportAddress(path,process.platform,secret));this.socket=socket,await new Promise((resolve3,reject)=>{let onConnect=()=>{cleanup(),resolve3()},onError=error=>{cleanup(),this.socket=null,reject(error)},cleanup=()=>{socket.off("connect",onConnect),socket.off("error",onError)};socket.once("connect",onConnect),socket.once("error",onError)}),secret&&sendSocketHandshake(socket,secret),this.stopReadingStdout=attachJsonlLineReader(socket,line=>this.handleLine(line)),socket.once("close",()=>{this.socket===socket&&(this.socket=null,this.notifyDisconnect(new RpcTransportGoneError))}),socket.once("error",error=>{this.socket===socket&&this.notifyDisconnect(new RpcTransportGoneError)})}onEvent(listener){return this.eventListeners.push(listener),()=>{let index=this.eventListeners.indexOf(listener);index!==-1&&this.eventListeners.splice(index,1)}}getStderr(){return this.stderr}async setClientInfo(width,capabilities){await this.send({type:"set_client_info",width,capabilities},this.sessionId!==void 0)}async openSession(options){if(this.pendingOpenSession)throw new RpcClientOpenInFlightError;this.pendingOpenSession=!0;try{let response=await this.send({type:"open_session",...options},!1),opened=this.getData(response);return this.sessionId=opened.sessionId,this.pendingOpenSession=!1,this.flushPendingSessionEvents(),opened}catch(error){throw this.pendingOpenSession=!1,this.pendingSessionEvents=[],this.pendingSessionEventBytes=0,error}}async sendExtensionUIResponse(response){await this.send(response,!0,void 0,!1)}async sendExtensionUIProgress(progress){await this.send(progress,!0,void 0,!1)}async closeSession(sessionId=this.sessionId){if(sessionId){try{await this.send({type:"close_session",sessionId},!1)}catch(error){if(!isTransportGoneError(error))throw error}this.sessionId===sessionId&&(this.sessionId=void 0)}}async listSessions(){let response=await this.send({type:"list_sessions"},!1);return this.getData(response).sessions}async prompt(message,optionsOrImages){let options=Array.isArray(optionsOrImages)?{images:optionsOrImages}:optionsOrImages??{},response=await this.send({type:"prompt",message,...options.images?{images:options.images}:{},...options.streamingBehavior?{streamingBehavior:options.streamingBehavior}:{},...options.thinkingLevel?{thinkingLevel:options.thinkingLevel}:{},...options.sessionTitlePrompt!==void 0?{sessionTitlePrompt:options.sessionTitlePrompt}:{},...options.expandPromptTemplates!==void 0?{expandPromptTemplates:options.expandPromptTemplates}:{}},!0,{onResponse:wireResponse=>{if(!wireResponse.success){options?.preflightResult?.(!1);return}let data=wireResponse.data;options?.promptDisposition?.(data?.disposition??"handled"),options?.preflightResult?.(!0)},onReject:()=>{options?.preflightResult?.(!1)}});if(!response.success)throw new Error(response.error)}async appendUserMessage(content){await this.send({type:"append_user_message",content})}async appendSessionEntry(entry){await this.send({type:"append_session_entry",entry})}async sendCustomMessage(message,options){await this.send({type:"send_custom_message",...message,...options})}async steer(message,images,recovery){await this.send({type:"steer",message,images,enqueueOrder:recovery?.enqueueOrder})}async followUp(message,images,recovery){await this.send({type:"follow_up",message,images,enqueueOrder:recovery?.enqueueOrder})}async abort(){try{await this.send({type:"abort"})}catch(error){if(!isTransportGoneError(error))throw error}}async abortCompaction(){await this.send({type:"abort_compaction"})}async reload(){let response=await this.send({type:"reload"});return this.getData(response)}async checkReloadVeto(){let response=await this.send({type:"check_reload_veto"});return this.getData(response)}async clearQueue(options){let response=await this.send({type:"clear_queue",abortWillFollow:options?.abortWillFollow});return this.getData(response)}async getSteeringMessages(){let response=await this.send({type:"get_steering_messages"});return this.getData(response).messages}async getFollowUpMessages(){let response=await this.send({type:"get_follow_up_messages"});return this.getData(response).messages}async abortBranchSummary(){await this.send({type:"abort_branch_summary"})}async recordBashResult(command,result,excludeFromContext){await this.send({type:"record_bash_result",command,result,excludeFromContext})}async setLabel(entryId,label){await this.send({type:"set_label",entryId,label})}async newSession(parentSession){let response=await this.send({type:"new_session",parentSession});return this.getData(response)}async getState(){let response=await this.send({type:"get_state"});return this.getData(response)}async setModel(provider,modelId){let response=await this.send({type:"set_model",provider,modelId});return this.getData(response)}async setFavoriteModels(models){await this.send({type:"set_favorite_models",models})}async setScopedModels(models){await this.send({type:"set_scoped_models",models})}async cycleModel(direction="forward"){let response=await this.send({type:"cycle_model",direction});return this.getData(response)}async getAvailableModels(){let response=await this.send({type:"get_available_models"});return this.getData(response).models}async setThinkingLevel(level,options){let response=await this.send({type:"set_thinking_level",level,scope:options?.scope});if(!response.success)throw new Error(response.error)}async cycleThinkingLevel(){let response=await this.send({type:"cycle_thinking_level"});return this.getData(response)}async getAvailableThinkingLevels(){let response=await this.send({type:"get_available_thinking_levels"});return this.getData(response).levels}async setFastMode(enabled){let response=await this.send({type:"set_fast_mode",enabled});return this.getData(response)}async getFastMode(){let response=await this.send({type:"get_fast_mode"});return this.getData(response)}async setSteeringMode(mode){await this.send({type:"set_steering_mode",mode})}async setFollowUpMode(mode){await this.send({type:"set_follow_up_mode",mode})}async compact(customInstructions){let response=await this.send({type:"compact",customInstructions});return this.getData(response)}async setAutoCompaction(enabled){await this.send({type:"set_auto_compaction",enabled})}async setAutoRetry(enabled){await this.send({type:"set_auto_retry",enabled})}async abortRetry(){await this.send({type:"abort_retry"})}async bash(command,options){let response=await this.send({type:"bash",command,excludeFromContext:options?.excludeFromContext,executionId:options?.executionId,operations:options?.operations});return this.getData(response)}async navigateTree(targetId,options){let response=await this.send({type:"navigate_tree",targetId,...options});return this.getData(response)}async abortBash(){await this.send({type:"abort_bash"})}async cleanupBashOutput(path){await this.send({type:"cleanup_bash_output",path})}async getSessionStats(){let response=await this.send({type:"get_session_stats"});return this.getData(response)}async exportHtml(outputPath,themeName){let response=await this.send({type:"export_html",outputPath,themeName});return this.getData(response)}async exportJsonl(outputPath){let response=await this.send({type:"export_jsonl",outputPath});return this.getData(response)}async switchSession(sessionPath,options){let response=await this.send({type:"switch_session",sessionPath,cwdOverride:options?.cwdOverride});return this.getData(response)}async fork(entryId,options){let response=await this.send({type:"fork",entryId,position:options?.position});return this.getData(response)}async clone(){let response=await this.send({type:"clone"});return this.getData(response)}async getForkMessages(){let response=await this.send({type:"get_fork_messages"});return this.getData(response).messages}async getEntries(since){let response=await this.send({type:"get_entries",since});return this.getData(response)}async getTree(){let response=await this.send({type:"get_tree"});return this.getData(response)}async editAssistantMessage(entryId,text,options={}){let response=await this.send({type:"edit_assistant_message",entryId,text,expectedLeafId:options.expectedLeafId,summarize:options.summarize,customInstructions:options.customInstructions});return this.getData(response)}async getLastAssistantText(){let response=await this.send({type:"get_last_assistant_text"});return this.getData(response).text}async setSessionName(name){await this.send({type:"set_session_name",name})}async importJsonl(inputPath,cwdOverride){let response=await this.send({type:"import_jsonl",inputPath,cwdOverride});return this.getData(response)}async getMessages(){let response=await this.send({type:"get_messages"});return this.getData(response).messages}async getMedia(toolCallId,contentIndex){let response=await this.send({type:"get_media",toolCallId,contentIndex});return this.getData(response).content}async getCommands(){let response=await this.send({type:"get_commands"});return this.getData(response).commands}async requestExtension(name,data){let response=await this.send({type:"extension_request",name,...data===void 0?{}:{data}});return this.getData(response)}async getProviderAccounts(provider){let response=await this.send({type:"get_provider_accounts",provider});return this.getData(response).accounts}async pinProviderAccount(provider,name){await this.send({type:"account_pin",provider,name})}async removeProviderAccount(provider,name){await this.send({type:"account_remove",provider,name})}waitForIdle(timeout=6e4){return new Promise((resolve3,reject)=>{let timer=setTimeout(()=>{unsubscribe(),reject(new Error(`Timeout waiting for agent to become idle. Stderr: ${this.stderr}`))},timeout),unsubscribe=this.onEvent(event=>{event.type==="agent_settled"&&(clearTimeout(timer),unsubscribe(),resolve3())})})}collectEvents(timeout=6e4){return new Promise((resolve3,reject)=>{let events=[],timer=setTimeout(()=>{unsubscribe(),reject(new Error(`Timeout collecting events. Stderr: ${this.stderr}`))},timeout),unsubscribe=this.onEvent(event=>{isProviderAccountEvent(event)||event.type==="extension_event"||event.type==="bash_start"||event.type==="bash_end"||event.type==="extension_ui_request"||event.type==="session_replaced"||(events.push(event),event.type==="agent_settled"&&(clearTimeout(timer),unsubscribe(),resolve3(events)))})})}async promptAndWait(message,images,timeout=6e4){let eventsPromise=this.collectEvents(timeout);return await this.prompt(message,images?{images}:void 0),eventsPromise}handleLine(line){try{let data=JSON.parse(line);if(data.type==="response"&&data.id&&this.pendingRequests.has(data.id)){let pending=this.pendingRequests.get(data.id);this.pendingRequests.delete(data.id),pending.onResponse?.(data),pending.resolve(data);return}if(typeof data.sessionId=="string"&&data.sessionId!==this.sessionId){if(this.pendingOpenSession){let bytes=Buffer.byteLength(line);for(this.pendingSessionEvents.push({sessionId:data.sessionId,event:data,bytes}),this.pendingSessionEventBytes+=bytes;this.pendingSessionEvents.length>MAX_PENDING_SESSION_EVENTS||this.pendingSessionEventBytes>MAX_PENDING_SESSION_EVENT_BYTES;){let oldest=this.pendingSessionEvents.shift();if(!oldest)break;this.pendingSessionEventBytes-=oldest.bytes}}return}for(let listener of this.eventListeners)listener(data)}catch{}}flushPendingSessionEvents(){let pending=this.pendingSessionEvents;this.pendingSessionEvents=[],this.pendingSessionEventBytes=0;for(let{sessionId,event}of pending)if(sessionId===this.sessionId)for(let listener of this.eventListeners)listener(event)}createProcessExitError(code,signal){return new Error(`Agent process exited (code=${code} signal=${signal}). Stderr: ${this.stderr}`)}notifyDisconnect(error){this.rejectPendingRequests(error),!this.disconnectNotified&&!this.stopping&&(this.disconnectNotified=!0,this.options.onDisconnect?.(error))}rejectPendingRequests(error){for(let pending of this.pendingRequests.values())pending.onReject?.(error),pending.reject(error);this.pendingRequests.clear()}async send(command,route=!0,hooks,expectResponse=!0){let childProcess=this.process,stream=this.socket??childProcess?.stdin;if(!stream)throw new RpcTransportGoneError;if(this.exitError)throw this.exitError;if(childProcess?.exitCode!==null&&childProcess?.exitCode!==void 0){let error=this.createProcessExitError(childProcess.exitCode,childProcess.signalCode);throw this.exitError=error,error}if(stream.destroyed||!stream.writable){let error=new RpcTransportGoneError;throw this.notifyDisconnect(error),error}let ownId=command.type==="extension_ui_response"||command.type==="extension_ui_progress"?command.id:void 0,id=ownId??`req_${++this.requestId}`,fullCommand={...command,...route&&this.sessionId&&!("sessionId"in command)?{sessionId:this.sessionId}:{},...ownId===void 0?{id}:{}};return expectResponse?new Promise((resolve3,reject)=>{let timeout=setTimeout(()=>{let pending=this.pendingRequests.get(id);this.pendingRequests.delete(id);let timeoutError=new Error(`Timeout waiting for response to ${command.type}. Stderr: ${this.stderr}`);pending?.onReject?.(timeoutError),reject(timeoutError)},3e4);this.pendingRequests.set(id,{resolve:response=>{clearTimeout(timeout),resolve3(response)},reject:error=>{clearTimeout(timeout),reject(error)},...hooks?.onResponse?{onResponse:hooks.onResponse}:{},...hooks?.onReject?{onReject:hooks.onReject}:{}});try{stream.write(serializeJsonLine(fullCommand))}catch(error){let writeError=error instanceof Error?error:new Error(String(error)),pending=this.pendingRequests.get(id);this.pendingRequests.delete(id),pending?.onReject?.(writeError),pending?.reject(writeError)}}):(stream.write(serializeJsonLine(fullCommand)),Promise.resolve({type:"response",command:command.type,success:!0}))}getData(response){if(!response.success){let errorResponse=response;throw errorResponse.errorCode==="missing_session_cwd"&&errorResponse.errorData?new MissingSessionCwdError(errorResponse.errorData):new RpcCommandError(errorResponse.error,errorResponse.errorCode,errorResponse.errorData)}return response.data}};export{stripAnsi,reserveSessionWrite,unregisterSessionWriter,GOAL_CONTINUATION_MESSAGE_TYPE,isContextExcludedCustomMessage,createBranchSummaryMessage,createCompactionSummaryMessage,createCustomMessage,convertToLlm,TRANSPORT_IMAGE_BUDGET_BYTES,convertToLlmForTransport,SESSION_CONTEXT_ENTRY_ID,getSessionContextEntryId,CURRENT_SESSION_VERSION,assertValidSessionId,migrateSessionEntries,parseSessionEntries,getLatestCompactionEntry,sessionEntryToContextMessages,buildContextEntries,buildSessionContext,getDefaultSessionDir,loadEntriesFromFile,SessionManager,DEFAULT_MAX_LINES,DEFAULT_MAX_BYTES,formatSize,truncateHead,truncateTail,truncateLine,executeBashWithOperations,getMissingSessionCwdIssue,formatMissingSessionCwdPrompt,MissingSessionCwdError,assertSessionCwdExists,RpcTransportGoneError,isTransportGoneError,RpcClientOpenInFlightError,RpcClient};
40
+ ${issue.fallbackCwd}`}var MissingSessionCwdError=class extends Error{constructor(issue){super(formatMissingSessionCwdError(issue)),this.name="MissingSessionCwdError",this.issue=issue}};function assertSessionCwdExists(sessionManager,fallbackCwd){let issue=getMissingSessionCwdIssue(sessionManager,fallbackCwd);if(issue)throw new MissingSessionCwdError(issue)}import{spawn}from"node:child_process";import{createConnection}from"node:net";var RpcCommandError=class extends Error{constructor(message,errorCode,errorData){super(message),this.name="RpcCommandError",this.errorCode=errorCode,this.errorData=errorData}};function isProviderAccountEvent(event){return event.type==="auth_accounts_changed"||event.type==="account_failover"}var RpcTransportGoneError=class extends Error{constructor(message="Shared RPC host is unavailable"){super(message),this.code="rpc_transport_gone",this.name="RpcTransportGoneError"}};function isTransportGoneError(error){return error instanceof RpcTransportGoneError||error instanceof Error&&(error.message==="Client not started"||error.message.startsWith("RPC transport is not writable.")||error.message==="RPC socket closed")}var RpcClientOpenInFlightError=class extends Error{constructor(){super("An open_session request is already in flight"),this.code="open_session_in_flight",this.name="RpcClientOpenInFlightError"}},MAX_PENDING_SESSION_EVENTS=512,MAX_PENDING_SESSION_EVENT_BYTES=1024*1024,RpcClient=class{constructor(options={}){this.process=null,this.socket=null,this.stopReadingStdout=null,this.eventListeners=[],this.pendingRequests=new Map,this.requestId=0,this.pendingOpenSession=!1,this.pendingSessionEvents=[],this.pendingSessionEventBytes=0,this.stderr="",this.exitError=null,this.disconnectNotified=!1,this.stopping=!1,this.options=options}async start(){if(this.process||this.socket)throw new Error("Client already started");if(this.exitError=null,this.stopping=!1,this.disconnectNotified=!1,this.options.socketPath){await this.startSocket(this.options.socketPath);return}let cliPath=this.options.cliPath??"dist/cli.js",args=["--mode","rpc"];this.options.provider&&args.push("--provider",this.options.provider),this.options.model&&args.push("--model",this.options.model),this.options.args&&args.push(...this.options.args);let childProcess=spawn("node",[cliPath,...args],{cwd:this.options.cwd,env:{...process.env,SENPI_RUNTIME:"node",...this.options.env},stdio:["pipe","pipe","pipe"],windowsHide:!0});if(this.process=childProcess,childProcess.stderr?.on("data",data=>{this.stderr+=data.toString(),process.stderr.write(data)}),childProcess.once("exit",(code,signal)=>{if(this.process!==childProcess)return;let error=this.createProcessExitError(code,signal);this.exitError=error,this.rejectPendingRequests(error)}),childProcess.once("error",error=>{if(this.process!==childProcess)return;let processError=new Error(`Agent process error: ${error.message}. Stderr: ${this.stderr}`);this.exitError=processError,this.rejectPendingRequests(processError)}),childProcess.stdin?.on("error",error=>{if(this.process!==childProcess)return;let stdinError=this.exitError??new Error(`Agent process stdin error: ${error.message}. Stderr: ${this.stderr}`);this.exitError=stdinError,this.rejectPendingRequests(stdinError)}),this.stopReadingStdout=attachJsonlLineReader(childProcess.stdout,line=>{this.handleLine(line)}),await new Promise(resolve3=>setTimeout(resolve3,100)),this.process.exitCode!==null){let error=this.exitError??this.createProcessExitError(this.process.exitCode,this.process.signalCode);throw this.exitError=error,error}}async stop(){if(this.pendingOpenSession=!1,this.pendingSessionEvents=[],this.pendingSessionEventBytes=0,this.socket){this.stopping=!0,this.stopReadingStdout?.(),this.stopReadingStdout=null,this.socket.destroy(),this.socket=null,this.sessionId=void 0,this.pendingOpenSession=!1,this.pendingSessionEvents=[],this.notifyDisconnect(new RpcTransportGoneError);return}this.process&&(this.stopReadingStdout?.(),this.stopReadingStdout=null,this.process.kill("SIGTERM"),await new Promise(resolve3=>{let timeout=setTimeout(()=>{this.process?.kill("SIGKILL"),resolve3()},1e3);this.process?.on("exit",()=>{clearTimeout(timeout),resolve3()})}),this.process=null,this.pendingRequests.clear())}async startSocket(path){let secret=process.platform==="win32"?await readSocketSecret(socketSecretPath(path)):void 0,socket=createConnection(resolveSocketTransportAddress(path,process.platform,secret));this.socket=socket,await new Promise((resolve3,reject)=>{let onConnect=()=>{cleanup(),resolve3()},onError=error=>{cleanup(),this.socket=null,reject(error)},cleanup=()=>{socket.off("connect",onConnect),socket.off("error",onError)};socket.once("connect",onConnect),socket.once("error",onError)}),secret&&sendSocketHandshake(socket,secret),this.stopReadingStdout=attachJsonlLineReader(socket,line=>this.handleLine(line)),socket.once("close",()=>{this.socket===socket&&(this.socket=null,this.notifyDisconnect(new RpcTransportGoneError))}),socket.once("error",error=>{this.socket===socket&&this.notifyDisconnect(new RpcTransportGoneError)})}onEvent(listener){return this.eventListeners.push(listener),()=>{let index=this.eventListeners.indexOf(listener);index!==-1&&this.eventListeners.splice(index,1)}}getStderr(){return this.stderr}async setClientInfo(width,capabilities){await this.send({type:"set_client_info",width,capabilities},this.sessionId!==void 0)}async openSession(options){if(this.pendingOpenSession)throw new RpcClientOpenInFlightError;this.pendingOpenSession=!0;try{let response=await this.send({type:"open_session",...options},!1),opened=this.getData(response);return this.sessionId=opened.sessionId,this.pendingOpenSession=!1,this.flushPendingSessionEvents(),opened}catch(error){throw this.pendingOpenSession=!1,this.pendingSessionEvents=[],this.pendingSessionEventBytes=0,error}}async sendExtensionUIResponse(response){await this.send(response,!0,void 0,!1)}async sendExtensionUIProgress(progress){await this.send(progress,!0,void 0,!1)}async closeSession(sessionId=this.sessionId){if(sessionId){try{await this.send({type:"close_session",sessionId},!1)}catch(error){if(!isTransportGoneError(error))throw error}this.sessionId===sessionId&&(this.sessionId=void 0)}}async listSessions(){let response=await this.send({type:"list_sessions"},!1);return this.getData(response).sessions}async prompt(message,optionsOrImages){let options=Array.isArray(optionsOrImages)?{images:optionsOrImages}:optionsOrImages??{},response=await this.send({type:"prompt",message,...options.images?{images:options.images}:{},...options.streamingBehavior?{streamingBehavior:options.streamingBehavior}:{},...options.thinkingLevel?{thinkingLevel:options.thinkingLevel}:{},...options.sessionTitlePrompt!==void 0?{sessionTitlePrompt:options.sessionTitlePrompt}:{},...options.expandPromptTemplates!==void 0?{expandPromptTemplates:options.expandPromptTemplates}:{}},!0,{onResponse:wireResponse=>{if(!wireResponse.success){options?.preflightResult?.(!1);return}let data=wireResponse.data;options?.promptDisposition?.(data?.disposition??"handled"),options?.preflightResult?.(!0)},onReject:()=>{options?.preflightResult?.(!1)}});if(!response.success)throw new Error(response.error)}async appendUserMessage(content){await this.send({type:"append_user_message",content})}async appendSessionEntry(entry){await this.send({type:"append_session_entry",entry})}async sendCustomMessage(message,options){await this.send({type:"send_custom_message",...message,...options})}async steer(message,images,recovery){await this.send({type:"steer",message,images,enqueueOrder:recovery?.enqueueOrder})}async followUp(message,images,recovery){await this.send({type:"follow_up",message,images,enqueueOrder:recovery?.enqueueOrder})}async abort(){try{await this.send({type:"abort"})}catch(error){if(!isTransportGoneError(error))throw error}}async abortCompaction(){await this.send({type:"abort_compaction"})}async reload(){let response=await this.send({type:"reload"});return this.getData(response)}async checkReloadVeto(){let response=await this.send({type:"check_reload_veto"});return this.getData(response)}async clearQueue(options){let response=await this.send({type:"clear_queue",abortWillFollow:options?.abortWillFollow});return this.getData(response)}async getSteeringMessages(){let response=await this.send({type:"get_steering_messages"});return this.getData(response).messages}async getFollowUpMessages(){let response=await this.send({type:"get_follow_up_messages"});return this.getData(response).messages}async abortBranchSummary(){await this.send({type:"abort_branch_summary"})}async recordBashResult(command,result,excludeFromContext){await this.send({type:"record_bash_result",command,result,excludeFromContext})}async setLabel(entryId,label){await this.send({type:"set_label",entryId,label})}async newSession(parentSession){let response=await this.send({type:"new_session",parentSession});return this.getData(response)}async getState(){let response=await this.send({type:"get_state"});return this.getData(response)}async setModel(provider,modelId){let response=await this.send({type:"set_model",provider,modelId});return this.getData(response)}async setFavoriteModels(models){await this.send({type:"set_favorite_models",models})}async setScopedModels(models){await this.send({type:"set_scoped_models",models})}async cycleModel(direction="forward"){let response=await this.send({type:"cycle_model",direction});return this.getData(response)}async getAvailableModels(){let response=await this.send({type:"get_available_models"});return this.getData(response).models}async setThinkingLevel(level,options){let response=await this.send({type:"set_thinking_level",level,scope:options?.scope});if(!response.success)throw new Error(response.error)}async cycleThinkingLevel(){let response=await this.send({type:"cycle_thinking_level"});return this.getData(response)}async getAvailableThinkingLevels(){let response=await this.send({type:"get_available_thinking_levels"});return this.getData(response).levels}async setFastMode(enabled){let response=await this.send({type:"set_fast_mode",enabled});return this.getData(response)}async getFastMode(){let response=await this.send({type:"get_fast_mode"});return this.getData(response)}async setSteeringMode(mode){await this.send({type:"set_steering_mode",mode})}async setFollowUpMode(mode){await this.send({type:"set_follow_up_mode",mode})}async compact(customInstructions){let response=await this.send({type:"compact",customInstructions});return this.getData(response)}async setAutoCompaction(enabled){await this.send({type:"set_auto_compaction",enabled})}async setAutoRetry(enabled){await this.send({type:"set_auto_retry",enabled})}async abortRetry(){await this.send({type:"abort_retry"})}async bash(command,options){let response=await this.send({type:"bash",command,excludeFromContext:options?.excludeFromContext,executionId:options?.executionId,operations:options?.operations});return this.getData(response)}async navigateTree(targetId,options){let response=await this.send({type:"navigate_tree",targetId,...options});return this.getData(response)}async abortBash(){await this.send({type:"abort_bash"})}async cleanupBashOutput(path){await this.send({type:"cleanup_bash_output",path})}async getSessionStats(){let response=await this.send({type:"get_session_stats"});return this.getData(response)}async exportHtml(outputPath,themeName){let response=await this.send({type:"export_html",outputPath,themeName});return this.getData(response)}async exportJsonl(outputPath){let response=await this.send({type:"export_jsonl",outputPath});return this.getData(response)}async switchSession(sessionPath,options){let response=await this.send({type:"switch_session",sessionPath,cwdOverride:options?.cwdOverride});return this.getData(response)}async fork(entryId,options){let response=await this.send({type:"fork",entryId,position:options?.position});return this.getData(response)}async clone(){let response=await this.send({type:"clone"});return this.getData(response)}async getForkMessages(){let response=await this.send({type:"get_fork_messages"});return this.getData(response).messages}async getEntries(since){let response=await this.send({type:"get_entries",since});return this.getData(response)}async getTree(){let response=await this.send({type:"get_tree"});return this.getData(response)}async editAssistantMessage(entryId,text,options={}){let response=await this.send({type:"edit_assistant_message",entryId,text,expectedLeafId:options.expectedLeafId,summarize:options.summarize,customInstructions:options.customInstructions});return this.getData(response)}async getLastAssistantText(){let response=await this.send({type:"get_last_assistant_text"});return this.getData(response).text}async setSessionName(name){await this.send({type:"set_session_name",name})}async importJsonl(inputPath,cwdOverride){let response=await this.send({type:"import_jsonl",inputPath,cwdOverride});return this.getData(response)}async getMessages(){let response=await this.send({type:"get_messages"});return this.getData(response).messages}async getMedia(toolCallId,contentIndex){let response=await this.send({type:"get_media",toolCallId,contentIndex});return this.getData(response).content}async getCommands(){let response=await this.send({type:"get_commands"});return this.getData(response).commands}async requestExtension(name,data){let response=await this.send({type:"extension_request",name,...data===void 0?{}:{data}});return this.getData(response)}async getProviderAccounts(provider){let response=await this.send({type:"get_provider_accounts",provider});return this.getData(response).accounts}async pinProviderAccount(provider,name){await this.send({type:"account_pin",provider,name})}async removeProviderAccount(provider,name){await this.send({type:"account_remove",provider,name})}waitForIdle(timeout=6e4){return new Promise((resolve3,reject)=>{let timer=setTimeout(()=>{unsubscribe(),reject(new Error(`Timeout waiting for agent to become idle. Stderr: ${this.stderr}`))},timeout),unsubscribe=this.onEvent(event=>{event.type==="agent_settled"&&(clearTimeout(timer),unsubscribe(),resolve3())})})}collectEvents(timeout=6e4){return new Promise((resolve3,reject)=>{let events=[],timer=setTimeout(()=>{unsubscribe(),reject(new Error(`Timeout collecting events. Stderr: ${this.stderr}`))},timeout),unsubscribe=this.onEvent(event=>{isProviderAccountEvent(event)||event.type==="extension_event"||event.type==="bash_start"||event.type==="bash_end"||event.type==="extension_ui_request"||event.type==="session_replaced"||event.type==="session_parked"||(events.push(event),event.type==="agent_settled"&&(clearTimeout(timer),unsubscribe(),resolve3(events)))})})}async promptAndWait(message,images,timeout=6e4){let eventsPromise=this.collectEvents(timeout);return await this.prompt(message,images?{images}:void 0),eventsPromise}handleLine(line){try{let data=JSON.parse(line);if(data.type==="response"&&data.id&&this.pendingRequests.has(data.id)){let pending=this.pendingRequests.get(data.id);this.pendingRequests.delete(data.id),pending.onResponse?.(data),pending.resolve(data);return}if(typeof data.sessionId=="string"&&data.sessionId!==this.sessionId){if(this.pendingOpenSession){let bytes=Buffer.byteLength(line);for(this.pendingSessionEvents.push({sessionId:data.sessionId,event:data,bytes}),this.pendingSessionEventBytes+=bytes;this.pendingSessionEvents.length>MAX_PENDING_SESSION_EVENTS||this.pendingSessionEventBytes>MAX_PENDING_SESSION_EVENT_BYTES;){let oldest=this.pendingSessionEvents.shift();if(!oldest)break;this.pendingSessionEventBytes-=oldest.bytes}}return}for(let listener of this.eventListeners)listener(data)}catch{}}flushPendingSessionEvents(){let pending=this.pendingSessionEvents;this.pendingSessionEvents=[],this.pendingSessionEventBytes=0;for(let{sessionId,event}of pending)if(sessionId===this.sessionId)for(let listener of this.eventListeners)listener(event)}createProcessExitError(code,signal){return new Error(`Agent process exited (code=${code} signal=${signal}). Stderr: ${this.stderr}`)}notifyDisconnect(error){this.rejectPendingRequests(error),!this.disconnectNotified&&!this.stopping&&(this.disconnectNotified=!0,this.options.onDisconnect?.(error))}rejectPendingRequests(error){for(let pending of this.pendingRequests.values())pending.onReject?.(error),pending.reject(error);this.pendingRequests.clear()}async send(command,route=!0,hooks,expectResponse=!0){let childProcess=this.process,stream=this.socket??childProcess?.stdin;if(!stream)throw new RpcTransportGoneError;if(this.exitError)throw this.exitError;if(childProcess?.exitCode!==null&&childProcess?.exitCode!==void 0){let error=this.createProcessExitError(childProcess.exitCode,childProcess.signalCode);throw this.exitError=error,error}if(stream.destroyed||!stream.writable){let error=new RpcTransportGoneError;throw this.notifyDisconnect(error),error}let ownId=command.type==="extension_ui_response"||command.type==="extension_ui_progress"?command.id:void 0,id=ownId??`req_${++this.requestId}`,fullCommand={...command,...route&&this.sessionId&&!("sessionId"in command)?{sessionId:this.sessionId}:{},...ownId===void 0?{id}:{}};return expectResponse?new Promise((resolve3,reject)=>{let timeout=setTimeout(()=>{let pending=this.pendingRequests.get(id);this.pendingRequests.delete(id);let timeoutError=new Error(`Timeout waiting for response to ${command.type}. Stderr: ${this.stderr}`);pending?.onReject?.(timeoutError),reject(timeoutError)},3e4);this.pendingRequests.set(id,{resolve:response=>{clearTimeout(timeout),resolve3(response)},reject:error=>{clearTimeout(timeout),reject(error)},...hooks?.onResponse?{onResponse:hooks.onResponse}:{},...hooks?.onReject?{onReject:hooks.onReject}:{}});try{stream.write(serializeJsonLine(fullCommand))}catch(error){let writeError=error instanceof Error?error:new Error(String(error)),pending=this.pendingRequests.get(id);this.pendingRequests.delete(id),pending?.onReject?.(writeError),pending?.reject(writeError)}}):(stream.write(serializeJsonLine(fullCommand)),Promise.resolve({type:"response",command:command.type,success:!0}))}getData(response){if(!response.success){let errorResponse=response;throw errorResponse.errorCode==="missing_session_cwd"&&errorResponse.errorData?new MissingSessionCwdError(errorResponse.errorData):new RpcCommandError(errorResponse.error,errorResponse.errorCode,errorResponse.errorData)}return response.data}};export{stripAnsi,reserveSessionWrite,unregisterSessionWriter,GOAL_CONTINUATION_MESSAGE_TYPE,isContextExcludedCustomMessage,createBranchSummaryMessage,createCompactionSummaryMessage,createCustomMessage,convertToLlm,TRANSPORT_IMAGE_BUDGET_BYTES,convertToLlmForTransport,SESSION_CONTEXT_ENTRY_ID,getSessionContextEntryId,CURRENT_SESSION_VERSION,assertValidSessionId,migrateSessionEntries,parseSessionEntries,getLatestCompactionEntry,sessionEntryToContextMessages,buildContextEntries,buildSessionContext,getDefaultSessionDir,loadEntriesFromFile,SessionManager,DEFAULT_MAX_LINES,DEFAULT_MAX_BYTES,formatSize,truncateHead,truncateTail,truncateLine,executeBashWithOperations,getMissingSessionCwdIssue,formatMissingSessionCwdPrompt,MissingSessionCwdError,assertSessionCwdExists,RpcTransportGoneError,isTransportGoneError,RpcClientOpenInFlightError,RpcClient};
@@ -1,5 +1,5 @@
1
1
  import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url);
2
- import*as crypto from"node:crypto";var CUSTOM_UNSUPPORTED_CAPABILITY="custom_unsupported",EXTENSION_EVENTS_CAPABILITY="extension_events",RENDERED_COMPONENTS_CAPABILITY="rendered_components",AUTO_TITLE_SESSIONS_CAPABILITY="auto_title_sessions",MEDIA_PLACEHOLDERS_CAPABILITY="media_placeholders",QUESTION_CAPABILITY="question",RETAIN_ON_DISCONNECT_CAPABILITY="retain_on_disconnect",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{StringDecoder}from"node:string_decoder";function serializeJsonLine(value){return`${JSON.stringify(value)}
2
+ import*as crypto from"node:crypto";var CUSTOM_UNSUPPORTED_CAPABILITY="custom_unsupported",EXTENSION_EVENTS_CAPABILITY="extension_events",RENDERED_COMPONENTS_CAPABILITY="rendered_components",AUTO_TITLE_SESSIONS_CAPABILITY="auto_title_sessions",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",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{StringDecoder}from"node:string_decoder";function serializeJsonLine(value){return`${JSON.stringify(value)}
3
3
  `}var MAX_RPC_LINE_CHARACTERS=16*1024*1024;function attachJsonlLineReader(stream,onLine,options={}){let decoder=new StringDecoder("utf8"),maxLineLength=options.maxLineLength??Number.POSITIVE_INFINITY;if(!(maxLineLength>0))throw new Error("maxLineLength must be greater than zero.");let buffer="",discardingOversizedLine=!1,consume=text=>{let offset=0;for(;offset<text.length;){if(discardingOversizedLine){let newlineIndex2=text.indexOf(`
4
4
  `,offset);if(newlineIndex2===-1)return;discardingOversizedLine=!1,offset=newlineIndex2+1;continue}let newlineIndex=text.indexOf(`
5
- `,offset);if(newlineIndex===-1){let remainder=text.slice(offset);buffer.length+remainder.length>maxLineLength?(buffer="",discardingOversizedLine=!0,options.onOversizedLine?.()):buffer+=remainder;return}let segment=text.slice(offset,newlineIndex);if(buffer.length+segment.length>maxLineLength)options.onOversizedLine?.();else{let line=buffer+segment;onLine(line.endsWith("\r")?line.slice(0,-1):line)}buffer="",offset=newlineIndex+1}},onData=chunk=>{consume(typeof chunk=="string"?chunk:decoder.write(chunk))},onEnd=()=>{consume(decoder.end()),!discardingOversizedLine&&buffer.length>0&&onLine(buffer.endsWith("\r")?buffer.slice(0,-1):buffer),buffer="",discardingOversizedLine=!1};return stream.on("data",onData),stream.on("end",onEnd),()=>{stream.off("data",onData),stream.off("end",onEnd)}}export{CUSTOM_UNSUPPORTED_CAPABILITY,EXTENSION_EVENTS_CAPABILITY,RENDERED_COMPONENTS_CAPABILITY,AUTO_TITLE_SESSIONS_CAPABILITY,MEDIA_PLACEHOLDERS_CAPABILITY,QUESTION_CAPABILITY,RETAIN_ON_DISCONNECT_CAPABILITY,RPC_CLIENT_CAPABILITIES_ENV,parseClientCapabilities,DEFAULT_CUSTOM_EXTENSION_LABEL,buildCustomUnsupportedRequest,serializeJsonLine,MAX_RPC_LINE_CHARACTERS,attachJsonlLineReader};
5
+ `,offset);if(newlineIndex===-1){let remainder=text.slice(offset);buffer.length+remainder.length>maxLineLength?(buffer="",discardingOversizedLine=!0,options.onOversizedLine?.()):buffer+=remainder;return}let segment=text.slice(offset,newlineIndex);if(buffer.length+segment.length>maxLineLength)options.onOversizedLine?.();else{let line=buffer+segment;onLine(line.endsWith("\r")?line.slice(0,-1):line)}buffer="",offset=newlineIndex+1}},onData=chunk=>{consume(typeof chunk=="string"?chunk:decoder.write(chunk))},onEnd=()=>{consume(decoder.end()),!discardingOversizedLine&&buffer.length>0&&onLine(buffer.endsWith("\r")?buffer.slice(0,-1):buffer),buffer="",discardingOversizedLine=!1};return stream.on("data",onData),stream.on("end",onEnd),()=>{stream.off("data",onData),stream.off("end",onEnd)}}export{CUSTOM_UNSUPPORTED_CAPABILITY,EXTENSION_EVENTS_CAPABILITY,RENDERED_COMPONENTS_CAPABILITY,AUTO_TITLE_SESSIONS_CAPABILITY,MEDIA_PLACEHOLDERS_CAPABILITY,QUESTION_CAPABILITY,RETAIN_ON_DISCONNECT_CAPABILITY,SESSION_CONTEXT_CAPABILITY,SESSION_KIND_CAPABILITY,AUTO_TITLE_PER_SESSION_CAPABILITY,RPC_CLIENT_CAPABILITIES_ENV,parseClientCapabilities,DEFAULT_CUSTOM_EXTENSION_LABEL,buildCustomUnsupportedRequest,serializeJsonLine,MAX_RPC_LINE_CHARACTERS,attachJsonlLineReader};