@code-yeongyu/senpi 2026.10.25-3 → 2026.10.25-4
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.
- package/CHANGELOG.md +17 -0
- package/dist/bundle/chunks/{chunk-WLHNEUGD.js → chunk-2RB5EL4X.js} +1 -1
- package/dist/bundle/chunks/{chunk-MJ5NNWX4.js → chunk-3QCYBOKN.js} +1 -1
- package/dist/bundle/chunks/{chunk-FFQOEC76.js → chunk-4MOZXOJX.js} +3 -3
- package/dist/bundle/chunks/{chunk-ODTGC6YU.js → chunk-5JJDR6XI.js} +1 -1
- package/dist/bundle/chunks/chunk-6VWIMHMH.js +2 -0
- package/dist/bundle/chunks/{chunk-SWJXRC2I.js → chunk-BZ7726QO.js} +1 -1
- package/dist/bundle/chunks/{chunk-YRF4I43T.js → chunk-C2MQ4QXN.js} +12 -12
- package/dist/bundle/chunks/{chunk-7W7OJDIY.js → chunk-DODH3N6U.js} +4 -4
- package/dist/bundle/chunks/{chunk-EHQXLHRB.js → chunk-E6D4RIT7.js} +2 -2
- package/dist/bundle/chunks/{chunk-6O4SEW2W.js → chunk-J37GRED2.js} +1 -1
- package/dist/bundle/chunks/chunk-JMOUU75H.js +2 -0
- package/dist/bundle/chunks/{chunk-Z3UYNSVR.js → chunk-KKD4CYCI.js} +1 -1
- package/dist/bundle/chunks/{chunk-JA2R2ZSE.js → chunk-KNVNKDER.js} +1 -1
- package/dist/bundle/chunks/{chunk-CNL6QSUB.js → chunk-LOIF6PHI.js} +2 -2
- package/dist/bundle/chunks/{chunk-P3M2PF6K.js → chunk-N7IN46Q5.js} +1 -1
- package/dist/bundle/chunks/{chunk-C5UFJ7B3.js → chunk-PT6JJUN2.js} +1 -1
- package/dist/bundle/chunks/{chunk-O3Q2ET6W.js → chunk-SBGIXMX3.js} +1 -1
- package/dist/bundle/chunks/{chunk-HVJI5T75.js → chunk-STMXIBXF.js} +2 -2
- package/dist/bundle/chunks/{chunk-H3HNMY2W.js → chunk-TBU6VYHN.js} +1 -1
- package/dist/bundle/chunks/{chunk-UQNRW3VU.js → chunk-V2UYXTRR.js} +1 -1
- package/dist/bundle/chunks/chunk-XMJKZK5H.js +2 -0
- package/dist/bundle/chunks/cli-main-YYH3IBC6.js +3 -0
- package/dist/bundle/chunks/{dispatch-NYAULNVW.js → dispatch-MXG5YWLV.js} +1 -1
- package/dist/bundle/chunks/{host-command-Z3WPHJOW.js → host-command-TDLLHXVI.js} +1 -1
- package/dist/bundle/chunks/{host-lifecycle-ONQIMWMX.js → host-lifecycle-3VHHIGDL.js} +1 -1
- package/dist/bundle/chunks/host-lifecycle.js +1 -1
- package/dist/bundle/chunks/{host-session-command-J65ENSV5.js → host-session-command-56XF6ACS.js} +1 -1
- package/dist/bundle/chunks/{host-socket-request-3CWE4265.js → host-socket-request-QL2WEZTN.js} +1 -1
- package/dist/bundle/chunks/interactive-mode-OEPULLZK.js +2 -0
- package/dist/bundle/chunks/{multi-session-host-YI2WZOET.js → multi-session-host-Z2CW4SDM.js} +2 -2
- package/dist/bundle/chunks/{package-manager-cli-GHZPJMRF.js → package-manager-cli-N55U6PEO.js} +1 -1
- package/dist/bundle/chunks/rotation-stream-CBGCBYHV.js +2 -0
- package/dist/bundle/chunks/rpc-mode-ETXQWEB2.js +2 -0
- package/dist/bundle/chunks/{rpc-monitor-source-FFEQS744.js → rpc-monitor-source-AE3C6EQV.js} +1 -1
- package/dist/bundle/chunks/{schedule-command-YWG6D6ZF.js → schedule-command-VS7CZC2J.js} +1 -1
- package/dist/bundle/chunks/session-control-endpoint-4LEIDIVI.js +3 -0
- package/dist/bundle/chunks/session-picker-E4KUJDLO.js +2 -0
- package/dist/bundle/chunks/session-worker.js +45 -45
- package/dist/bundle/cli.js +2 -2
- package/dist/bundle/host-supervisor.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/bundle/runtime-manifest.json +1 -1
- package/dist/core/extensions/builtin/mcp/elicitation.js +2 -4
- package/dist/core/session-control-actions.js +0 -2
- package/dist/modes/interactive/session-control-attach.d.ts +20 -0
- package/dist/modes/interactive/session-control-attach.js +13 -0
- package/dist/modes/interactive/session-control-commands.js +16 -6
- package/dist/modes/interactive/session-control-registry.d.ts +2 -1
- package/dist/modes/interactive/session-control-registry.js +3 -2
- package/dist/modes/interactive/session-control-rpc-commands.d.ts +4 -2
- package/dist/modes/interactive/session-control-rpc-commands.js +114 -4
- package/dist/modes/interactive/session-control-server.js +9 -3
- package/dist/modes/rpc/connection-handler.js +6 -40
- package/dist/modes/rpc/custom-capability.d.ts +6 -0
- package/dist/modes/rpc/custom-capability.js +6 -0
- package/dist/modes/rpc/get-entries-command.d.ts +13 -0
- package/dist/modes/rpc/get-entries-command.js +61 -0
- package/dist/modes/rpc/get-entries-page.d.ts +22 -0
- package/dist/modes/rpc/get-entries-page.js +41 -2
- package/dist/modes/rpc/host-capabilities.js +4 -1
- package/dist/modes/rpc/host-observe-request.d.ts +2 -1
- package/dist/modes/rpc/host-observe-request.js +4 -1
- package/dist/modes/rpc/rpc-read-response-types.d.ts +2 -0
- package/dist/modes/rpc/rpc-session-command-types.d.ts +8 -1
- package/docs/rpc.md +43 -11
- package/package.json +6 -6
- package/dist/bundle/chunks/chunk-3LNSLJ7N.js +0 -2
- package/dist/bundle/chunks/chunk-MSQCTH6V.js +0 -2
- package/dist/bundle/chunks/cli-main-HEKFFB5S.js +0 -3
- package/dist/bundle/chunks/interactive-mode-DEPQC6TX.js +0 -2
- package/dist/bundle/chunks/rotation-stream-ZPVCFOVD.js +0 -2
- package/dist/bundle/chunks/rpc-mode-ORHBGBBV.js +0 -2
- package/dist/bundle/chunks/session-control-endpoint-36HAQSQO.js +0 -3
- package/dist/bundle/chunks/session-picker-25H5KNYP.js +0 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url); { const __piWorkerThreads = require("node:worker_threads"); if (typeof __piWorkerThreads.markAsUncloneable !== "function") { __piWorkerThreads.markAsUncloneable = () => {}; } }
|
|
2
|
-
import{CUSTOM_UNSUPPORTED_CAPABILITY,DEFAULT_PROBE_TIMEOUT_MS,EXTENSION_EVENTS_CAPABILITY,GENERATION_HANDOFF_CAPABILITY,HOST_PROTOCOL_VERSION,HostEnsureRefusedError,REQUIRED_HOST_CAPABILITIES,RPC_CLIENT_CAPABILITIES_ENV,RUNTIME_IDENTITY_HANDOVER_CAPABILITY,acquireHostEnsureLock,anyGenerationLive,busyLegacyHostDetail,computeRuntimeBuildId,decideHostAction,describeSessions,electPointer,engineBuildIdentity,gcEndpoint,gcHostEndpoints,holdProtocolInfo,holdSessionCount,hostEnsureLockOptions,hostEnsureLockTarget,hostLaunchProfile,judgeStaleEngine,observeProtocolInfo,parseHostStopGeneration,probeProtocolInfo,probeSocketReachable,provenLegacyOwner,retireIdleLegacyHost,signalGeneration,socketHostLaunchProfile,staleStopGeneration,stopHost}from"./chunk-HVJI5T75.js";import{endpointKindOfSocket,listHostEndpoints}from"./chunk-C5UFJ7B3.js";import{envSlotVarNames}from"./chunk-4AOMNOGY.js";import{external_exports}from"./chunk-KUPQO7MC.js";import{isSessionRuntimeKind,isToolRuntimeKind,toolRuntimeCapability}from"./chunk-WD6WBYC5.js";import{requestOnSocket}from"./chunk-JA2R2ZSE.js";import{rpcKeyRoot,withRpcKeyRoot}from"./chunk-Z3UYNSVR.js";import{presenterBootstrapStream,relayPresenterBootstrap}from"./chunk-KXB5WIS5.js";import{INTERNAL_HOST_DIR_PREFIX,INTERNAL_SUPERVISOR_FLAG,OWNER_WATCH_FD,internalHostDirRoots,isHostCrash,keepOwnerPipe,loopLagErrorMs,noteEscalatedStop,readHostCrashRecords,resolveCliMainPath,runtimeExecArgv}from"./chunk-CNL6QSUB.js";import{CHILD_KILL_EXIT_TIMEOUT_MS,CHILD_STOP_TIMEOUT_MS,DEFAULT_HOST_IDLE_EXIT_MS,acquireOwnershipSafeLock,activeStopProgress,childStalledStopMaxMs,claimOwnerIsLive,clearHostRegistration,hostChildAlive,hostLoopStalled,provenOwner,pruneDeadGenerations,readGenerationRows,readHostProcessMetrics,readHostRegistration,readSessionPathClaims,readStopIntent,releaseGeneration,stallRefusalWindowMs,writeGenerationRecord,writeHostRegistration,writeStopIntent,writtenByThisProcess}from"./chunk-SWJXRC2I.js";import{HOST_DAEMON_DIR_ENV,HOST_STATE_FILE_MODE,callerHostOwner,claimHostOwner,createDaemonDirectories,createHostDaemonPaths,ensureEndpointIdentity,generationPaths,hostDaemonDirectoryPaths,parseJson,parseShardSocket,readFileOrUndefined,readHostOwner,readHostSettings,sameEndpoint,sameHostOwner,sessionDirectoryRemoved,shardKey,shardSocketPathForKey,writeHostOwner,writeHostSettings,writeStateFile}from"./chunk-4WZRVZNX.js";import{HOST_GENERATION_ENV,HOST_INSTANCE_ID_ENV,OBSERVE_REQUEST_FIELD,gcRpcPublicKeys}from"./chunk-O3Q2ET6W.js";import{providerCredentialEnvNames}from"./chunk-T36LJ6MW.js";import{MAX_SOCKET_PATH_BYTES,generationBindPath,socketEntryListenerState,statSocketIdentity}from"./chunk-VRDU425E.js";import{createSocketSecret,socketSecretPath}from"./chunk-ZGAB7WQA.js";import{APP_NAME,ENV_AGENT_DIR,envValue,getAgentDir,isBunBinary}from"./chunk-7YO7VQZW.js";import{ProcessIdentityUnreadableError,processIsLive,processMatchesPidFile,readProcessStartTime,waitForStartTime}from"./chunk-O5RYI3IW.js";import{writeSync as writeSync2}from"node:fs";import{join as join6,resolve as resolve5}from"node:path";import{readFile,realpath,stat}from"node:fs/promises";import{dirname,isAbsolute,relative,resolve}from"node:path";var SPEC_ENV_NAME=/^(SENPI|OMO|PI)_[A-Z0-9_]+$/u,HostLaunchSpecError=class extends Error{constructor(reason,detail){super(`${reason}: ${detail}`),this.name="HostLaunchSpecError",this.reason=reason,this.detail=detail}},DEFAULT_HOST_LAUNCH_SPEC={hostArgs:[],policy:{},env:{}};async function loadHostLaunchSpec(specPath,platform=process.platform){let absolute=resolve(specPath);await assertTrustedFile(absolute,platform);let spec=parseHostLaunchSpec(await readSpecText(absolute)),env=trustedEnv(spec.env),extensions=await resolveExtensions(spec.core.extensions,dirname(absolute));return{hostArgs:["--session-runtime",spec.core.session_runtime,...extensions.flatMap(path=>["--extension",path])],policy:{...spec.tunables?.idleExitMs!==void 0&&{idleExitMs:spec.tunables.idleExitMs},...spec.tunables?.coldStart!==void 0&&{coldStart:spec.tunables.coldStart}},env}}function parseHostLaunchSpec(text){let parsed;try{parsed=JSON.parse(text)}catch(error){throw new HostLaunchSpecError("launch_spec_invalid",error instanceof Error?error.message:"not JSON")}if(!isRecord(parsed))throw new HostLaunchSpecError("launch_spec_invalid","the spec is not a JSON object");if(parsed.spec_version!==1)throw new HostLaunchSpecError("launch_spec_invalid",`unsupported spec_version ${String(parsed.spec_version)}`);let core=parsed.core;if(!isRecord(core))throw new HostLaunchSpecError("launch_spec_invalid","core must be an object");if(typeof core.session_runtime!="string"||!isSessionRuntimeKind(core.session_runtime))throw new HostLaunchSpecError("launch_spec_invalid","core.session_runtime must be in-process or worker");if(core.multi_session!==!0)throw new HostLaunchSpecError("launch_spec_invalid","core.multi_session must be true");if(!Array.isArray(core.extensions)||!core.extensions.every(entry=>typeof entry=="string"))throw new HostLaunchSpecError("launch_spec_invalid","core.extensions must be an array of strings");let tunables=parsedTunables(parsed.tunables);return{spec_version:1,core:{session_runtime:core.session_runtime,multi_session:!0,extensions:core.extensions},...tunables&&{tunables},...isRecord(parsed.env)&&{env:parsedEnv(parsed.env)}}}async function readSpecText(absolute){try{return await readFile(absolute,"utf8")}catch(error){throw new HostLaunchSpecError("launch_spec_unreadable",error instanceof Error?error.message:absolute)}}async function assertTrustedFile(absolute,platform){if(platform==="win32")return;let stats=await stat(absolute).catch(error=>{throw new HostLaunchSpecError("launch_spec_unreadable",error instanceof Error?error.message:absolute)}),uid=process.getuid?.();if(uid!==void 0&&stats.uid!==uid)throw new HostLaunchSpecError("launch_spec_insecure",`${absolute} is owned by uid ${stats.uid}, not ${uid}`);if((stats.mode&18)!==0)throw new HostLaunchSpecError("launch_spec_insecure",`${absolute} is group/world writable (mode ${(stats.mode&511).toString(8)})`)}function trustedEnv(env){for(let name of Object.keys(env??{}))if(!SPEC_ENV_NAME.test(name))throw new HostLaunchSpecError("launch_spec_env_denied",`${name} is outside ${SPEC_ENV_NAME.source}`);return env??{}}async function resolveExtensions(extensions,specDir){let rootReal=await realpath(specDir).catch(()=>specDir),resolved=[];for(let entry of extensions){let target=resolve(specDir,entry);if(escapes(specDir,target))throw new HostLaunchSpecError("launch_spec_path_escape",`${entry} resolves outside ${specDir}`);let real=await realpath(target).catch(()=>{});if(real===void 0)throw new HostLaunchSpecError("launch_spec_missing_extension",`${target} does not exist`);if(escapes(rootReal,real))throw new HostLaunchSpecError("launch_spec_path_escape",`${entry} links outside ${specDir}`);resolved.push(real)}return resolved}function escapes(root,target){let step=relative(root,target);return step.startsWith("..")||isAbsolute(step)}function parsedTunables(value){if(!isRecord(value))return;let idleExitMs=value.idleExitMs,coldStart=value.coldStart;return{...typeof idleExitMs=="number"&&Number.isFinite(idleExitMs)&&idleExitMs>0&&{idleExitMs},...(coldStart==="transient"||coldStart==="persistent")&&{coldStart}}}function parsedEnv(value){let env={};for(let[name,entry]of Object.entries(value)){if(typeof entry!="string")throw new HostLaunchSpecError("launch_spec_invalid",`env.${name} must be a string`);env[name]=entry}return env}function isRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}import{join}from"node:path";var ALLOWED_ENV_NAMES=[/^(PATH|HOME|USER|LOGNAME|SHELL|TMPDIR|TERM|LANG)$/u,/^(LC|XDG)_/u,/^(SENPI|OMO|PI)_/u,/^BSK_(HOME|BIN)$/u,/^(HTTPS?_PROXY|NO_PROXY)$/u,/^[A-Z0-9_]+_API_KEY$/u,/^(ANTHROPIC|OPENAI|GOOGLE|GEMINI|AZURE|AWS|OPENROUTER|XAI|MISTRAL|DEEPSEEK|GROQ|CEREBRAS|MINIMAX)_/u],PROVIDER_CREDENTIAL_ENV_NAMES=new Set([...providerCredentialEnvNames(),...envSlotVarNames()]),WINDOWS_SYSTEM_ENV_NAMES=new Set(["SYSTEMROOT","SYSTEMDRIVE","WINDIR","COMSPEC","PATHEXT","TEMP","TMP","USERPROFILE","APPDATA","LOCALAPPDATA","PROGRAMFILES","PROGRAMFILES(X86)","PROGRAMDATA","HOMEDRIVE","HOMEPATH","NUMBER_OF_PROCESSORS","PROCESSOR_ARCHITECTURE","OS"]),TRANSIENT_ENV_NAMES=new Set(["PI_SESSION_ID","PI_SESSION_FILE","PI_SESSION_CWD","PI_GOAL_STORE_FILE","PI_PROVIDER","PI_MODEL","PI_REASONING_LEVEL","OMO_BROWSER_ENGINE","PI_PROMPT_CACHE_SAFE_WAIT_SECONDS","SENPI_PY_KERNEL_PARENT_PID","SENPI_RPC_HOST_WATCH_FD","SENPI_RPC_HOST_WATCH_PPID","SENPI_RPC_HOST_SCRATCH_DIR","SENPI_RPC_HOST_CLEANUP_PATHS","SENPI_RPC_HOST_PUBLIC_SOCKET","SENPI_RPC_HOST_INSTANCE_ID","SENPI_RPC_HOST_GENERATION","SENPI_RPC_HOST_DAEMON_DIR","SENPI_RPC_HOST_EXPECTED_RUNTIME_BUILD_ID"]);function daemonEnvIsAllowed(name,platform=process.platform){let upper=name.toUpperCase();return TRANSIENT_ENV_NAMES.has(platform==="win32"?upper:name)?!1:platform!=="win32"?PROVIDER_CREDENTIAL_ENV_NAMES.has(name)||ALLOWED_ENV_NAMES.some(pattern=>pattern.test(name)):WINDOWS_SYSTEM_ENV_NAMES.has(upper)||PROVIDER_CREDENTIAL_ENV_NAMES.has(upper)||ALLOWED_ENV_NAMES.some(pattern=>pattern.test(upper))}function daemonEnvOverrides(processEnv,specEnv={},platform=process.platform){let overrides={};for(let name of Object.keys(processEnv))daemonEnvIsAllowed(name,platform)||(overrides[name]=null);for(let[name,value]of Object.entries(specEnv))daemonEnvIsAllowed(name,platform)&&(overrides[name]=value);return overrides}function daemonEnvironment(processEnv,overrides={},forced={},platform=process.platform){let env={};for(let[name,value]of Object.entries(processEnv))value!==void 0&&daemonEnvIsAllowed(name,platform)&&(env[name]=value);for(let[name,value]of Object.entries(overrides))daemonEnvIsAllowed(name,platform)&&(deleteEnvironmentName(env,name,platform),value!==null&&(env[name]=value));for(let[name,value]of Object.entries(forced))deleteEnvironmentName(env,name,platform),env[name]=value;return env}function daemonEnvKeys(processEnv,specEnv={},platform=process.platform){let kept=Object.keys(processEnv).filter(name=>daemonEnvIsAllowed(name,platform)),explicit=Object.keys(specEnv).filter(name=>daemonEnvIsAllowed(name,platform));return[...new Set([...kept,...explicit])].sort()}async function writeDaemonEnvKeys(paths,keys){await writeStateFile(daemonEnvKeysFile(paths),{env_keys:keys})}async function readDaemonEnvKeys(paths){let keys=parseJson(await readFileOrUndefined(daemonEnvKeysFile(paths)))?.env_keys;return Array.isArray(keys)?keys.filter(key=>typeof key=="string"):[]}function daemonEnvKeysFile(paths){return join(paths.dir,"env-keys.json")}function deleteEnvironmentName(env,name,platform){if(platform!=="win32"){delete env[name];return}let upper=name.toUpperCase();for(let existing of Object.keys(env))existing.toUpperCase()===upper&&delete env[existing]}import{mkdir,writeFile as writeFile3}from"node:fs/promises";import{dirname as dirname4}from"node:path";var hostGenerationScopes=0;function isHostGenerationProcess(){return hostGenerationScopes>0}async function runAsHostGenerationProcess(action){hostGenerationScopes+=1;try{return await action()}finally{hostGenerationScopes-=1}}function decideEnsureAction(options,startedByUs,protocol){if(options.upgrade!=="if-engine-differs"||isHostGenerationProcess())return decideHostAction(ensureClient(options,startedByUs),protocol,"never");let decision=decideHostAction(ensureClient(options,startedByUs),protocol,"upgrade");return decision.action==="fallback"?{action:"reuse",reason:"compatible",upgradeable:!1}:decision}function ensureClient(options,startedByUs){return{protocolVersion:HOST_PROTOCOL_VERSION,requiredCapabilities:[...REQUIRED_HOST_CAPABILITIES,...requestedToolRuntime(options.hostArgs??[])],identity:engineBuildIdentity(),...options.upgrade==="if-engine-differs"?{launchProfile:hostLaunchProfile(hostChildArgv(options.hostArgs??[]),process.cwd())}:{},startedByUs,platform:process.platform}}function requestedToolRuntime(hostArgs){for(let index=0;index<hostArgs.length;index++){let arg=hostArgs[index]??"",value=arg==="--tool-runtime"?hostArgs[index+1]:arg.startsWith("--tool-runtime=")?arg.slice(15):void 0;if(value!==void 0&&isToolRuntimeKind(value))return[toolRuntimeCapability(value)]}return[]}function hostChildArgv(hostArgs){return["--mode","rpc","--multi-session",...hostArgs]}function isCompatible(protocol){return decideHostAction(ensureClient({socket:""},!1),protocol,"never").action==="reuse"}async function refuseIfStalled(paths,instanceId,socket,protocol){let generation=generationPaths(paths,instanceId);if(await hostLoopStalled(generation,{now:Date.now(),errorMs:loopLagErrorMs(),windowMs:stallRefusalWindowMs()})&&await hostChildAlive(generation)!==!1)throw new HostEnsureRefusedError(socket,"host_stalled",protocol)}async function refuseIfForeignHeld(paths,registered,socket,protocol){if(!await publicEndpointAccepts(socket))return;let holder=await readHostHolder(paths,registered);throw new HostEnsureRefusedError(socket,"foreign_writer",protocol,void 0,holder)}async function readHostHolder(paths,registered){let record=parseJson(await readFileOrUndefined(generationPaths(paths,registered.instanceId).pidFile))??{};return{pid:registered.record.pid,instanceId:registered.instanceId,generation:registered.generation,processStartTime:registered.record.processStartTime,engineVersion:typeof record.engineVersion=="string"?record.engineVersion:null,launchProfileId:typeof record.launchProfileId=="string"?record.launchProfileId:null,writerPid:registered.writer?.pid??null}}var FOREIGN_ENDPOINT_PROBE_TIMEOUT_MS=2e3;async function publicEndpointAccepts(socket){if(process.platform==="win32"||socket.startsWith("\0"))return!0;let entry=await statSocketIdentity(socket).then(identity=>identity===void 0?"absent":"present",()=>"unknown");return entry==="absent"?!1:entry==="unknown"?!0:probeSocketReachable(socket,FOREIGN_ENDPOINT_PROBE_TIMEOUT_MS)}async function unregisteredEndpointHeld(socket){if(process.platform==="win32"||socket.startsWith("\0"))return!1;let entry=await statSocketIdentity(socket).then(identity=>identity===void 0?"absent":"present",()=>"unknown");return entry==="absent"?!1:entry==="unknown"?!0:(await socketEntryListenerState(socket)).verdict==="live"}import{spawn}from"node:child_process";import{randomUUID}from"node:crypto";import{open,readFile as readFile2}from"node:fs/promises";var DEFAULT_STOP_TIMEOUT_MS=Math.max(CHILD_STOP_TIMEOUT_MS,childStalledStopMaxMs())+CHILD_KILL_EXIT_TIMEOUT_MS+5e3,SIGKILL_GRACE_MS=2e3,STOP_PROGRESS_FRESH_MS=1e4,AFTER_STALL_WAIT_GRACE_MS=CHILD_KILL_EXIT_TIMEOUT_MS+5e3,STOP_WAIT_BUDGET_MS=Math.max(DEFAULT_STOP_TIMEOUT_MS,childStalledStopMaxMs()+AFTER_STALL_WAIT_GRACE_MS)+SIGKILL_GRACE_MS;function ensureSender(){return{pid:process.pid,kind:"ensure"}}async function announceStop(target,targetPid){let intent={sender:target.sender,targetPid,reason:target.reason,signal:"SIGTERM",at:new Date().toISOString()};return await writeStopIntent(target.generation,intent),intent}async function matchesPidFileOrUnknown(pidFile,probe){try{return await processMatchesPidFile(pidFile,probe)}catch(error){if(error instanceof ProcessIdentityUnreadableError)return!1;throw error}}async function recordEscalation(target,announced){let current=await readStopIntent(target.generation).catch(()=>{});await noteEscalatedStop(target.daemonDir,target.instanceId,current??announced)}async function stopSpawnedChild(child,childExit,termTimeoutMs,target){let exited=()=>child.exitCode!==null||child.signalCode!==null,pid=child.pid;if(exited()||pid===void 0)return;let waitFor=async ms=>{let timer;try{return await Promise.race([childExit.then(()=>!0),new Promise(resolve6=>{timer=setTimeout(()=>resolve6(exited()),ms)})])}finally{clearTimeout(timer)}},announced=await announceStop(target,pid);if(signalPid(pid,"SIGTERM"),!await waitWhileSupervisorReports(target,termTimeoutMs,waitFor)){if(signalPid(pid,"SIGKILL"),!await waitFor(SIGKILL_GRACE_MS))throw new Error(`RPC socket host pid ${pid} remained alive after SIGKILL`);await recordEscalation(target,announced)}}async function stopManagedHost(pidFile,termTimeoutMs,target,readStartTime=readProcessStartTime){let announced=await announceStop(target,pidFile.pid);if(await signalValidated(pidFile,"SIGTERM",readStartTime),!await waitWhileSupervisorReports(target,termTimeoutMs,ms=>waitForGone(pidFile,ms,readStartTime))){if(await signalValidated(pidFile,"SIGKILL",readStartTime),!await waitForGone(pidFile,SIGKILL_GRACE_MS,readStartTime))throw new Error(`RPC socket host pid ${pidFile.pid} remained alive after SIGKILL`);await recordEscalation(target,announced)}}async function waitWhileSupervisorReports(target,termTimeoutMs,waitFor){if(await waitFor(termTimeoutMs))return!0;let extended=!1;for(;;){let untilAt=await activeStopProgress(target.generation,Date.now(),STOP_PROGRESS_FRESH_MS);if(untilAt===void 0)return extended&&await waitFor(AFTER_STALL_WAIT_GRACE_MS);if(extended=!0,await waitFor(Math.min(STOP_PROGRESS_FRESH_MS,Math.max(1,untilAt-Date.now()))))return!0}}async function resolvePidFileOwnership(pidFile,readStartTime=readProcessStartTime){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){await resolvePidFileOwnership(pidFile,readStartTime)==="owns"&&signalPid(pidFile.pid,signal)}async function waitForGone(pidFile,timeoutMs,readStartTime=readProcessStartTime){let deadline=Date.now()+timeoutMs;for(;Date.now()<=deadline;){if(await resolvePidFileOwnership(pidFile,readStartTime)==="gone")return!0;await delay(50)}return await resolvePidFileOwnership(pidFile,readStartTime)==="gone"}function signalPid(pid,signal){try{process.kill(pid,signal)}catch(error){if(!isNodeErrorCode(error,"ESRCH"))throw error}}function delay(ms){return new Promise(resolveDelay=>setTimeout(resolveDelay,ms))}function isNodeErrorCode(error,code){return error instanceof Error&&"code"in error&&error.code===code}import{existsSync}from"node:fs";import{basename,dirname as dirname2,join as join2,resolve as resolve2}from"node:path";import{fileURLToPath}from"node:url";var PINNED_HOST_CLIENT_CAPABILITIES=[EXTENSION_EVENTS_CAPABILITY,CUSTOM_UNSUPPORTED_CAPABILITY];function defaultHostLaunch(supervisorArgs,compiled=isBunBinary,sibling=resolveHostLifecycleEntryPath()??null,bundledSupervisor=resolveBundledSupervisorEntryPath()??null){return compiled?{command:process.execPath,args:[INTERNAL_SUPERVISOR_FLAG,...supervisorArgs]}:sibling!==null?{command:process.execPath,args:[...runtimeExecArgv(),sibling,...supervisorArgs]}:bundledSupervisor!==null?{command:process.execPath,args:[...runtimeExecArgv(),bundledSupervisor,INTERNAL_SUPERVISOR_FLAG,...supervisorArgs]}:{command:process.execPath,args:[...runtimeExecArgv(),resolveCliMainPath(),INTERNAL_SUPERVISOR_FLAG,...supervisorArgs]}}var BUNDLED_SUPERVISOR_ENTRY="host-supervisor.js";function resolveBundledSupervisorEntryPath(){let entry=join2(dirname2(resolveCliMainPath()),BUNDLED_SUPERVISOR_ENTRY);return existsSync(entry)?entry:void 0}function resolveHostLifecycleEntryPath(){let modulePath=fileURLToPath(import.meta.url);if(basename(dirname2(modulePath))==="chunks")return;let extension=modulePath.endsWith(".ts")?".ts":".js",sibling=resolve2(dirname2(modulePath),`host-lifecycle${extension}`);return existsSync(sibling)?sibling:void 0}var SPAWNED_HOST_PROBE_TIMEOUT_MS=1e4;async function pollProtocolInfo(socket,timeoutMs,isCompatible2,childExit){let deadline=Date.now()+timeoutMs,lastProtocol;for(;Date.now()<=deadline;){let probe=holdProtocolInfo(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 held=await probe;if(!held)return{ready:!1,protocol:lastProtocol,exited:raced};if(lastProtocol=held.info,isCompatible2(held.info))return{ready:!0,protocol:held.info,hold:held.hold};held.hold.release()}else if(raced){if(lastProtocol=raced.info,isCompatible2(raced.info))return{ready:!0,protocol:raced.info,hold:raced.hold};raced.hold.release()}await delay2(50)}return{ready:!1,protocol:lastProtocol}}function isChildExit(value){return!!value&&"code"in value&&"signal"in value}function delay2(ms){return new Promise(resolveDelay=>setTimeout(resolveDelay,ms))}var EXPECTED_RUNTIME_BUILD_ID_ENV="SENPI_RPC_HOST_EXPECTED_RUNTIME_BUILD_ID",NEW_WORK_COMMANDS=new Set(["prompt","steer","follow_up","send_custom_message","continue_from_leaf","resume_session","append_user_message","bash","compact","wake","edit_assistant_message","edit_user_message"]),DEFAULT_POLL_MS=200,HostIdleHandover=class{constructor(options){this.options=options}view(){return this.operation?.view}admits(commandType){let state=this.operation?.view.state;return state===void 0||state==="handover_blocked"||!NEW_WORK_COMMANDS.has(commandType)}async begin(request){let current=this.operation;if(current!==void 0&¤t.view.operationId===request.operationId)return sameTerms(current.request,request)?answer(current):{kind:"refused",reason:"operation_conflict",detail:"this operation id names other terms"};if(current!==void 0&¤t.view.state!=="handover_blocked")return current.request.targetRuntimeBuildId===request.targetRuntimeBuildId?answer(current):{kind:"refused",reason:"handover_in_progress",detail:current.view.operationId};let self=this.options.identity();if(self.instanceId!==request.ifInstanceId||self.generation!==request.ifGeneration)return{kind:"refused",reason:"stale_generation",detail:`this host is ${self.instanceId} generation ${self.generation}`};if(self.runtimeBuildId===request.targetRuntimeBuildId)return{kind:"refused",reason:"already_current",detail:self.runtimeBuildId};let operation={request,view:{operationId:request.operationId,state:"handover_pending",targetRuntimeBuildId:request.targetRuntimeBuildId}};return this.operation=operation,this.options.log?.(`handover ${request.operationId} pending: no new work is admitted`),this.idleNow()?(await this.switchOver(operation),answer(operation)):(this.timer=setInterval(()=>this.observe(),this.options.pollMs??DEFAULT_POLL_MS),this.timer.unref?.(),answer(operation))}observe(){let operation=this.operation;operation?.view.state==="handover_pending"&&this.idleNow()&&this.switchOver(operation)}dispose(){this.stopTimer()}idleNow(){try{return this.options.isIdle()}catch(cause){return this.options.log?.(`handover idle check failed, waiting: ${String(cause)}`),!1}}async switchOver(operation){if(operation.view.state!=="handover_pending")return;this.stopTimer(),operation.view={...operation.view,state:"handover_switching"};let outcome=await this.options.perform(operation.request).catch(cause=>({ok:!1,reason:`successor_unavailable: ${String(cause)}`}));operation.view=outcome.ok?{...operation.view,state:"handover_completed",successor:outcome.successor}:{...operation.view,state:"handover_blocked",reason:outcome.reason},this.options.log?.(`handover ${operation.view.operationId} ${operation.view.state}`)}stopTimer(){this.timer!==void 0&&clearInterval(this.timer),this.timer=void 0}};function sameTerms(a,b){return a.targetRuntimeBuildId===b.targetRuntimeBuildId&&a.ifInstanceId===b.ifInstanceId&&a.ifGeneration===b.ifGeneration}function answer(operation){return{kind:"operation",view:operation.view}}function initialHostEnvironment(options){return daemonEnvironment(process.env,options.env,{[ENV_AGENT_DIR]:options.agentDir??getAgentDir(),[RPC_CLIENT_CAPABILITIES_ENV]:PINNED_HOST_CLIENT_CAPABILITIES.join(","),[HOST_INSTANCE_ID_ENV]:options.instanceId,[HOST_GENERATION_ENV]:String(options.generation),[HOST_DAEMON_DIR_ENV]:options.paths.dir})}function successorHostEnvironment(options){return daemonEnvironment(process.env,options.env,{[RPC_CLIENT_CAPABILITIES_ENV]:PINNED_HOST_CLIENT_CAPABILITIES.join(","),...options.agentDir?{[ENV_AGENT_DIR]:options.agentDir}:{},[HOST_INSTANCE_ID_ENV]:options.instanceId,[HOST_GENERATION_ENV]:String(options.generation),[HOST_DAEMON_DIR_ENV]:options.paths.dir,...options.expectedRuntimeBuildId!==void 0&&{[EXPECTED_RUNTIME_BUILD_ID_ENV]:options.expectedRuntimeBuildId}})}var DEFAULT_READINESS_TIMEOUT_MS=1e4;async function startHost(paths,socket,options,generation=0){let testOptions=options._test,lifetimeOwner=options.owner?await callerHostOwner():null,instanceId=randomUUID(),stopTarget=reason=>({daemonDir:paths.dir,generation:generationPaths(paths,instanceId),instanceId,sender:ensureSender(),reason});process.platform==="win32"&&await createSocketSecret(socketSecretPath(socket)),await writeHostSettings(paths,{socket,capabilities:PINNED_HOST_CLIENT_CAPABILITIES,coldStart:options.policy?.coldStart??"transient",idleExitMs:options.policy?.idleExitMs??9e5,generation,instanceId}),await writeHostOwner(generationPaths(paths,instanceId).dir,lifetimeOwner);let stderr=await open(paths.stderrLog,generation===0?"w":"a",384),pidFile,child,exitedEarly,childExit,presenterEnrollment;try{let supervisorArgs=["--socket",socket,...options.owner?["--owner-fd",String(OWNER_WATCH_FD)]:[],...options.presenterBootstrap?["--mcp-presenter-fd","4"]:[],...options.hostArgs??[]],launch=testOptions?.spawn??testOptions?.launch?.(supervisorArgs)??defaultHostLaunch(supervisorArgs);if(child=spawn(launch.command,[...launch.args],{detached:!0,windowsHide:!0,env:initialHostEnvironment({agentDir:options.agentDir,env:options.env,paths,instanceId,generation}),stdio:options.presenterBootstrap?["ignore","ignore",stderr.fd,options.owner?"pipe":"ignore","pipe"]:options.owner?["ignore","ignore",stderr.fd,"pipe"]:["ignore","ignore",stderr.fd]}),options.presenterBootstrap&&(presenterEnrollment=relayPresenterBootstrap(options.presenterBootstrap,child)),childExit=new Promise(resolveExit=>{child.once("exit",(code,signal)=>{exitedEarly={code,signal},resolveExit(exitedEarly)})}),options.owner&&keepOwnerPipe(child),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 writeHostRegistration(paths,{record:pidFile,socket,instanceId,generation,launchProfileId:hostLaunchProfile(hostChildArgv(options.hostArgs??[]),process.cwd()).profile_id,build:engineBuildIdentity()}),child.unref()}catch(error){let exitedBeforeCleanup=exitedEarly;if(!exitedBeforeCleanup&&child?.pid!==void 0&&childExit&&await stopUnregisteredStart(child,childExit,stopTarget("start_failed")),!exitedBeforeCleanup)throw await clearHostRegistration(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 clearHostRegistration(paths),new Error(diagnostic2)}finally{await stderr.close()}let readinessTimeoutMs=testOptions?.readinessTimeoutMs??DEFAULT_READINESS_TIMEOUT_MS,result=await pollProtocolInfo(socket,readinessTimeoutMs,isCompatible,childExit);if(result.ready)return await presenterEnrollment,{pid:pidFile.pid,socket,reused:!1,release:result.hold.release};await testOptions?.beforeReadinessTeardown?.();let stopFailure=await stopSpawnedChild(child,childExit,testOptions?.stopTimeoutMs??DEFAULT_STOP_TIMEOUT_MS,stopTarget("readiness_timeout")).then(()=>{},error=>error instanceof Error?error.message:String(error)),message=result.protocol?`RPC socket host answered get_protocol_info with protocolVersion ${result.protocol.protocolVersion}, serverVersion ${result.protocol.serverVersion} and capabilities ${JSON.stringify(result.protocol.capabilities)}, but is incompatible with protocol version ${HOST_PROTOCOL_VERSION} and required capabilities ${JSON.stringify(REQUIRED_HOST_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 clearHostRegistration(paths),new Error(diagnostic)}async function stopUnregisteredStart(child,childExit,target){let pid=child.pid,running=()=>child.exitCode===null&&child.signalCode===null;if(pid===void 0||!running())return;let announced=await announceStop(target,pid);try{signalPid(pid,"SIGTERM")}catch{}if(await Promise.race([childExit,delay(2e3)]),!running())return;try{signalPid(pid,"SIGKILL")}catch{}await Promise.race([childExit.then(()=>!0),delay(SIGKILL_GRACE_MS).then(()=>!1)])&&await recordEscalation(target,announced)}async function appendStderr(paths,message){try{let stderr=(await readFile2(paths.stderrLog,"utf8")).trim();return stderr?`${message}
|
|
2
|
+
import{CUSTOM_UNSUPPORTED_CAPABILITY,DEFAULT_PROBE_TIMEOUT_MS,EXTENSION_EVENTS_CAPABILITY,GENERATION_HANDOFF_CAPABILITY,HOST_PROTOCOL_VERSION,HostEnsureRefusedError,REQUIRED_HOST_CAPABILITIES,RPC_CLIENT_CAPABILITIES_ENV,RUNTIME_IDENTITY_HANDOVER_CAPABILITY,acquireHostEnsureLock,anyGenerationLive,busyLegacyHostDetail,computeRuntimeBuildId,decideHostAction,describeSessions,electPointer,engineBuildIdentity,gcEndpoint,gcHostEndpoints,holdProtocolInfo,holdSessionCount,hostEnsureLockOptions,hostEnsureLockTarget,hostLaunchProfile,judgeStaleEngine,observeProtocolInfo,parseHostStopGeneration,probeProtocolInfo,probeSocketReachable,provenLegacyOwner,retireIdleLegacyHost,signalGeneration,socketHostLaunchProfile,staleStopGeneration,stopHost}from"./chunk-STMXIBXF.js";import{endpointKindOfSocket,listHostEndpoints}from"./chunk-PT6JJUN2.js";import{envSlotVarNames}from"./chunk-4AOMNOGY.js";import{external_exports}from"./chunk-KUPQO7MC.js";import{isSessionRuntimeKind,isToolRuntimeKind,toolRuntimeCapability}from"./chunk-WD6WBYC5.js";import{requestOnSocket}from"./chunk-KNVNKDER.js";import{rpcKeyRoot,withRpcKeyRoot}from"./chunk-KKD4CYCI.js";import{presenterBootstrapStream,relayPresenterBootstrap}from"./chunk-KXB5WIS5.js";import{INTERNAL_HOST_DIR_PREFIX,INTERNAL_SUPERVISOR_FLAG,OWNER_WATCH_FD,internalHostDirRoots,isHostCrash,keepOwnerPipe,loopLagErrorMs,noteEscalatedStop,readHostCrashRecords,resolveCliMainPath,runtimeExecArgv}from"./chunk-LOIF6PHI.js";import{CHILD_KILL_EXIT_TIMEOUT_MS,CHILD_STOP_TIMEOUT_MS,DEFAULT_HOST_IDLE_EXIT_MS,acquireOwnershipSafeLock,activeStopProgress,childStalledStopMaxMs,claimOwnerIsLive,clearHostRegistration,hostChildAlive,hostLoopStalled,provenOwner,pruneDeadGenerations,readGenerationRows,readHostProcessMetrics,readHostRegistration,readSessionPathClaims,readStopIntent,releaseGeneration,stallRefusalWindowMs,writeGenerationRecord,writeHostRegistration,writeStopIntent,writtenByThisProcess}from"./chunk-BZ7726QO.js";import{HOST_DAEMON_DIR_ENV,HOST_STATE_FILE_MODE,callerHostOwner,claimHostOwner,createDaemonDirectories,createHostDaemonPaths,ensureEndpointIdentity,generationPaths,hostDaemonDirectoryPaths,parseJson,parseShardSocket,readFileOrUndefined,readHostOwner,readHostSettings,sameEndpoint,sameHostOwner,sessionDirectoryRemoved,shardKey,shardSocketPathForKey,writeHostOwner,writeHostSettings,writeStateFile}from"./chunk-4WZRVZNX.js";import{HOST_GENERATION_ENV,HOST_INSTANCE_ID_ENV,OBSERVE_REQUEST_FIELD,gcRpcPublicKeys}from"./chunk-SBGIXMX3.js";import{providerCredentialEnvNames}from"./chunk-T36LJ6MW.js";import{MAX_SOCKET_PATH_BYTES,generationBindPath,socketEntryListenerState,statSocketIdentity}from"./chunk-VRDU425E.js";import{createSocketSecret,socketSecretPath}from"./chunk-ZGAB7WQA.js";import{APP_NAME,ENV_AGENT_DIR,envValue,getAgentDir,isBunBinary}from"./chunk-7YO7VQZW.js";import{ProcessIdentityUnreadableError,processIsLive,processMatchesPidFile,readProcessStartTime,waitForStartTime}from"./chunk-O5RYI3IW.js";import{writeSync as writeSync2}from"node:fs";import{join as join6,resolve as resolve5}from"node:path";import{readFile,realpath,stat}from"node:fs/promises";import{dirname,isAbsolute,relative,resolve}from"node:path";var SPEC_ENV_NAME=/^(SENPI|OMO|PI)_[A-Z0-9_]+$/u,HostLaunchSpecError=class extends Error{constructor(reason,detail){super(`${reason}: ${detail}`),this.name="HostLaunchSpecError",this.reason=reason,this.detail=detail}},DEFAULT_HOST_LAUNCH_SPEC={hostArgs:[],policy:{},env:{}};async function loadHostLaunchSpec(specPath,platform=process.platform){let absolute=resolve(specPath);await assertTrustedFile(absolute,platform);let spec=parseHostLaunchSpec(await readSpecText(absolute)),env=trustedEnv(spec.env),extensions=await resolveExtensions(spec.core.extensions,dirname(absolute));return{hostArgs:["--session-runtime",spec.core.session_runtime,...extensions.flatMap(path=>["--extension",path])],policy:{...spec.tunables?.idleExitMs!==void 0&&{idleExitMs:spec.tunables.idleExitMs},...spec.tunables?.coldStart!==void 0&&{coldStart:spec.tunables.coldStart}},env}}function parseHostLaunchSpec(text){let parsed;try{parsed=JSON.parse(text)}catch(error){throw new HostLaunchSpecError("launch_spec_invalid",error instanceof Error?error.message:"not JSON")}if(!isRecord(parsed))throw new HostLaunchSpecError("launch_spec_invalid","the spec is not a JSON object");if(parsed.spec_version!==1)throw new HostLaunchSpecError("launch_spec_invalid",`unsupported spec_version ${String(parsed.spec_version)}`);let core=parsed.core;if(!isRecord(core))throw new HostLaunchSpecError("launch_spec_invalid","core must be an object");if(typeof core.session_runtime!="string"||!isSessionRuntimeKind(core.session_runtime))throw new HostLaunchSpecError("launch_spec_invalid","core.session_runtime must be in-process or worker");if(core.multi_session!==!0)throw new HostLaunchSpecError("launch_spec_invalid","core.multi_session must be true");if(!Array.isArray(core.extensions)||!core.extensions.every(entry=>typeof entry=="string"))throw new HostLaunchSpecError("launch_spec_invalid","core.extensions must be an array of strings");let tunables=parsedTunables(parsed.tunables);return{spec_version:1,core:{session_runtime:core.session_runtime,multi_session:!0,extensions:core.extensions},...tunables&&{tunables},...isRecord(parsed.env)&&{env:parsedEnv(parsed.env)}}}async function readSpecText(absolute){try{return await readFile(absolute,"utf8")}catch(error){throw new HostLaunchSpecError("launch_spec_unreadable",error instanceof Error?error.message:absolute)}}async function assertTrustedFile(absolute,platform){if(platform==="win32")return;let stats=await stat(absolute).catch(error=>{throw new HostLaunchSpecError("launch_spec_unreadable",error instanceof Error?error.message:absolute)}),uid=process.getuid?.();if(uid!==void 0&&stats.uid!==uid)throw new HostLaunchSpecError("launch_spec_insecure",`${absolute} is owned by uid ${stats.uid}, not ${uid}`);if((stats.mode&18)!==0)throw new HostLaunchSpecError("launch_spec_insecure",`${absolute} is group/world writable (mode ${(stats.mode&511).toString(8)})`)}function trustedEnv(env){for(let name of Object.keys(env??{}))if(!SPEC_ENV_NAME.test(name))throw new HostLaunchSpecError("launch_spec_env_denied",`${name} is outside ${SPEC_ENV_NAME.source}`);return env??{}}async function resolveExtensions(extensions,specDir){let rootReal=await realpath(specDir).catch(()=>specDir),resolved=[];for(let entry of extensions){let target=resolve(specDir,entry);if(escapes(specDir,target))throw new HostLaunchSpecError("launch_spec_path_escape",`${entry} resolves outside ${specDir}`);let real=await realpath(target).catch(()=>{});if(real===void 0)throw new HostLaunchSpecError("launch_spec_missing_extension",`${target} does not exist`);if(escapes(rootReal,real))throw new HostLaunchSpecError("launch_spec_path_escape",`${entry} links outside ${specDir}`);resolved.push(real)}return resolved}function escapes(root,target){let step=relative(root,target);return step.startsWith("..")||isAbsolute(step)}function parsedTunables(value){if(!isRecord(value))return;let idleExitMs=value.idleExitMs,coldStart=value.coldStart;return{...typeof idleExitMs=="number"&&Number.isFinite(idleExitMs)&&idleExitMs>0&&{idleExitMs},...(coldStart==="transient"||coldStart==="persistent")&&{coldStart}}}function parsedEnv(value){let env={};for(let[name,entry]of Object.entries(value)){if(typeof entry!="string")throw new HostLaunchSpecError("launch_spec_invalid",`env.${name} must be a string`);env[name]=entry}return env}function isRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}import{join}from"node:path";var ALLOWED_ENV_NAMES=[/^(PATH|HOME|USER|LOGNAME|SHELL|TMPDIR|TERM|LANG)$/u,/^(LC|XDG)_/u,/^(SENPI|OMO|PI)_/u,/^BSK_(HOME|BIN)$/u,/^(HTTPS?_PROXY|NO_PROXY)$/u,/^[A-Z0-9_]+_API_KEY$/u,/^(ANTHROPIC|OPENAI|GOOGLE|GEMINI|AZURE|AWS|OPENROUTER|XAI|MISTRAL|DEEPSEEK|GROQ|CEREBRAS|MINIMAX)_/u],PROVIDER_CREDENTIAL_ENV_NAMES=new Set([...providerCredentialEnvNames(),...envSlotVarNames()]),WINDOWS_SYSTEM_ENV_NAMES=new Set(["SYSTEMROOT","SYSTEMDRIVE","WINDIR","COMSPEC","PATHEXT","TEMP","TMP","USERPROFILE","APPDATA","LOCALAPPDATA","PROGRAMFILES","PROGRAMFILES(X86)","PROGRAMDATA","HOMEDRIVE","HOMEPATH","NUMBER_OF_PROCESSORS","PROCESSOR_ARCHITECTURE","OS"]),TRANSIENT_ENV_NAMES=new Set(["PI_SESSION_ID","PI_SESSION_FILE","PI_SESSION_CWD","PI_GOAL_STORE_FILE","PI_PROVIDER","PI_MODEL","PI_REASONING_LEVEL","OMO_BROWSER_ENGINE","PI_PROMPT_CACHE_SAFE_WAIT_SECONDS","SENPI_PY_KERNEL_PARENT_PID","SENPI_RPC_HOST_WATCH_FD","SENPI_RPC_HOST_WATCH_PPID","SENPI_RPC_HOST_SCRATCH_DIR","SENPI_RPC_HOST_CLEANUP_PATHS","SENPI_RPC_HOST_PUBLIC_SOCKET","SENPI_RPC_HOST_INSTANCE_ID","SENPI_RPC_HOST_GENERATION","SENPI_RPC_HOST_DAEMON_DIR","SENPI_RPC_HOST_EXPECTED_RUNTIME_BUILD_ID"]);function daemonEnvIsAllowed(name,platform=process.platform){let upper=name.toUpperCase();return TRANSIENT_ENV_NAMES.has(platform==="win32"?upper:name)?!1:platform!=="win32"?PROVIDER_CREDENTIAL_ENV_NAMES.has(name)||ALLOWED_ENV_NAMES.some(pattern=>pattern.test(name)):WINDOWS_SYSTEM_ENV_NAMES.has(upper)||PROVIDER_CREDENTIAL_ENV_NAMES.has(upper)||ALLOWED_ENV_NAMES.some(pattern=>pattern.test(upper))}function daemonEnvOverrides(processEnv,specEnv={},platform=process.platform){let overrides={};for(let name of Object.keys(processEnv))daemonEnvIsAllowed(name,platform)||(overrides[name]=null);for(let[name,value]of Object.entries(specEnv))daemonEnvIsAllowed(name,platform)&&(overrides[name]=value);return overrides}function daemonEnvironment(processEnv,overrides={},forced={},platform=process.platform){let env={};for(let[name,value]of Object.entries(processEnv))value!==void 0&&daemonEnvIsAllowed(name,platform)&&(env[name]=value);for(let[name,value]of Object.entries(overrides))daemonEnvIsAllowed(name,platform)&&(deleteEnvironmentName(env,name,platform),value!==null&&(env[name]=value));for(let[name,value]of Object.entries(forced))deleteEnvironmentName(env,name,platform),env[name]=value;return env}function daemonEnvKeys(processEnv,specEnv={},platform=process.platform){let kept=Object.keys(processEnv).filter(name=>daemonEnvIsAllowed(name,platform)),explicit=Object.keys(specEnv).filter(name=>daemonEnvIsAllowed(name,platform));return[...new Set([...kept,...explicit])].sort()}async function writeDaemonEnvKeys(paths,keys){await writeStateFile(daemonEnvKeysFile(paths),{env_keys:keys})}async function readDaemonEnvKeys(paths){let keys=parseJson(await readFileOrUndefined(daemonEnvKeysFile(paths)))?.env_keys;return Array.isArray(keys)?keys.filter(key=>typeof key=="string"):[]}function daemonEnvKeysFile(paths){return join(paths.dir,"env-keys.json")}function deleteEnvironmentName(env,name,platform){if(platform!=="win32"){delete env[name];return}let upper=name.toUpperCase();for(let existing of Object.keys(env))existing.toUpperCase()===upper&&delete env[existing]}import{mkdir,writeFile as writeFile3}from"node:fs/promises";import{dirname as dirname4}from"node:path";var hostGenerationScopes=0;function isHostGenerationProcess(){return hostGenerationScopes>0}async function runAsHostGenerationProcess(action){hostGenerationScopes+=1;try{return await action()}finally{hostGenerationScopes-=1}}function decideEnsureAction(options,startedByUs,protocol){if(options.upgrade!=="if-engine-differs"||isHostGenerationProcess())return decideHostAction(ensureClient(options,startedByUs),protocol,"never");let decision=decideHostAction(ensureClient(options,startedByUs),protocol,"upgrade");return decision.action==="fallback"?{action:"reuse",reason:"compatible",upgradeable:!1}:decision}function ensureClient(options,startedByUs){return{protocolVersion:HOST_PROTOCOL_VERSION,requiredCapabilities:[...REQUIRED_HOST_CAPABILITIES,...requestedToolRuntime(options.hostArgs??[])],identity:engineBuildIdentity(),...options.upgrade==="if-engine-differs"?{launchProfile:hostLaunchProfile(hostChildArgv(options.hostArgs??[]),process.cwd())}:{},startedByUs,platform:process.platform}}function requestedToolRuntime(hostArgs){for(let index=0;index<hostArgs.length;index++){let arg=hostArgs[index]??"",value=arg==="--tool-runtime"?hostArgs[index+1]:arg.startsWith("--tool-runtime=")?arg.slice(15):void 0;if(value!==void 0&&isToolRuntimeKind(value))return[toolRuntimeCapability(value)]}return[]}function hostChildArgv(hostArgs){return["--mode","rpc","--multi-session",...hostArgs]}function isCompatible(protocol){return decideHostAction(ensureClient({socket:""},!1),protocol,"never").action==="reuse"}async function refuseIfStalled(paths,instanceId,socket,protocol){let generation=generationPaths(paths,instanceId);if(await hostLoopStalled(generation,{now:Date.now(),errorMs:loopLagErrorMs(),windowMs:stallRefusalWindowMs()})&&await hostChildAlive(generation)!==!1)throw new HostEnsureRefusedError(socket,"host_stalled",protocol)}async function refuseIfForeignHeld(paths,registered,socket,protocol){if(!await publicEndpointAccepts(socket))return;let holder=await readHostHolder(paths,registered);throw new HostEnsureRefusedError(socket,"foreign_writer",protocol,void 0,holder)}async function readHostHolder(paths,registered){let record=parseJson(await readFileOrUndefined(generationPaths(paths,registered.instanceId).pidFile))??{};return{pid:registered.record.pid,instanceId:registered.instanceId,generation:registered.generation,processStartTime:registered.record.processStartTime,engineVersion:typeof record.engineVersion=="string"?record.engineVersion:null,launchProfileId:typeof record.launchProfileId=="string"?record.launchProfileId:null,writerPid:registered.writer?.pid??null}}var FOREIGN_ENDPOINT_PROBE_TIMEOUT_MS=2e3;async function publicEndpointAccepts(socket){if(process.platform==="win32"||socket.startsWith("\0"))return!0;let entry=await statSocketIdentity(socket).then(identity=>identity===void 0?"absent":"present",()=>"unknown");return entry==="absent"?!1:entry==="unknown"?!0:probeSocketReachable(socket,FOREIGN_ENDPOINT_PROBE_TIMEOUT_MS)}async function unregisteredEndpointHeld(socket){if(process.platform==="win32"||socket.startsWith("\0"))return!1;let entry=await statSocketIdentity(socket).then(identity=>identity===void 0?"absent":"present",()=>"unknown");return entry==="absent"?!1:entry==="unknown"?!0:(await socketEntryListenerState(socket)).verdict==="live"}import{spawn}from"node:child_process";import{randomUUID}from"node:crypto";import{open,readFile as readFile2}from"node:fs/promises";var DEFAULT_STOP_TIMEOUT_MS=Math.max(CHILD_STOP_TIMEOUT_MS,childStalledStopMaxMs())+CHILD_KILL_EXIT_TIMEOUT_MS+5e3,SIGKILL_GRACE_MS=2e3,STOP_PROGRESS_FRESH_MS=1e4,AFTER_STALL_WAIT_GRACE_MS=CHILD_KILL_EXIT_TIMEOUT_MS+5e3,STOP_WAIT_BUDGET_MS=Math.max(DEFAULT_STOP_TIMEOUT_MS,childStalledStopMaxMs()+AFTER_STALL_WAIT_GRACE_MS)+SIGKILL_GRACE_MS;function ensureSender(){return{pid:process.pid,kind:"ensure"}}async function announceStop(target,targetPid){let intent={sender:target.sender,targetPid,reason:target.reason,signal:"SIGTERM",at:new Date().toISOString()};return await writeStopIntent(target.generation,intent),intent}async function matchesPidFileOrUnknown(pidFile,probe){try{return await processMatchesPidFile(pidFile,probe)}catch(error){if(error instanceof ProcessIdentityUnreadableError)return!1;throw error}}async function recordEscalation(target,announced){let current=await readStopIntent(target.generation).catch(()=>{});await noteEscalatedStop(target.daemonDir,target.instanceId,current??announced)}async function stopSpawnedChild(child,childExit,termTimeoutMs,target){let exited=()=>child.exitCode!==null||child.signalCode!==null,pid=child.pid;if(exited()||pid===void 0)return;let waitFor=async ms=>{let timer;try{return await Promise.race([childExit.then(()=>!0),new Promise(resolve6=>{timer=setTimeout(()=>resolve6(exited()),ms)})])}finally{clearTimeout(timer)}},announced=await announceStop(target,pid);if(signalPid(pid,"SIGTERM"),!await waitWhileSupervisorReports(target,termTimeoutMs,waitFor)){if(signalPid(pid,"SIGKILL"),!await waitFor(SIGKILL_GRACE_MS))throw new Error(`RPC socket host pid ${pid} remained alive after SIGKILL`);await recordEscalation(target,announced)}}async function stopManagedHost(pidFile,termTimeoutMs,target,readStartTime=readProcessStartTime){let announced=await announceStop(target,pidFile.pid);if(await signalValidated(pidFile,"SIGTERM",readStartTime),!await waitWhileSupervisorReports(target,termTimeoutMs,ms=>waitForGone(pidFile,ms,readStartTime))){if(await signalValidated(pidFile,"SIGKILL",readStartTime),!await waitForGone(pidFile,SIGKILL_GRACE_MS,readStartTime))throw new Error(`RPC socket host pid ${pidFile.pid} remained alive after SIGKILL`);await recordEscalation(target,announced)}}async function waitWhileSupervisorReports(target,termTimeoutMs,waitFor){if(await waitFor(termTimeoutMs))return!0;let extended=!1;for(;;){let untilAt=await activeStopProgress(target.generation,Date.now(),STOP_PROGRESS_FRESH_MS);if(untilAt===void 0)return extended&&await waitFor(AFTER_STALL_WAIT_GRACE_MS);if(extended=!0,await waitFor(Math.min(STOP_PROGRESS_FRESH_MS,Math.max(1,untilAt-Date.now()))))return!0}}async function resolvePidFileOwnership(pidFile,readStartTime=readProcessStartTime){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){await resolvePidFileOwnership(pidFile,readStartTime)==="owns"&&signalPid(pidFile.pid,signal)}async function waitForGone(pidFile,timeoutMs,readStartTime=readProcessStartTime){let deadline=Date.now()+timeoutMs;for(;Date.now()<=deadline;){if(await resolvePidFileOwnership(pidFile,readStartTime)==="gone")return!0;await delay(50)}return await resolvePidFileOwnership(pidFile,readStartTime)==="gone"}function signalPid(pid,signal){try{process.kill(pid,signal)}catch(error){if(!isNodeErrorCode(error,"ESRCH"))throw error}}function delay(ms){return new Promise(resolveDelay=>setTimeout(resolveDelay,ms))}function isNodeErrorCode(error,code){return error instanceof Error&&"code"in error&&error.code===code}import{existsSync}from"node:fs";import{basename,dirname as dirname2,join as join2,resolve as resolve2}from"node:path";import{fileURLToPath}from"node:url";var PINNED_HOST_CLIENT_CAPABILITIES=[EXTENSION_EVENTS_CAPABILITY,CUSTOM_UNSUPPORTED_CAPABILITY];function defaultHostLaunch(supervisorArgs,compiled=isBunBinary,sibling=resolveHostLifecycleEntryPath()??null,bundledSupervisor=resolveBundledSupervisorEntryPath()??null){return compiled?{command:process.execPath,args:[INTERNAL_SUPERVISOR_FLAG,...supervisorArgs]}:sibling!==null?{command:process.execPath,args:[...runtimeExecArgv(),sibling,...supervisorArgs]}:bundledSupervisor!==null?{command:process.execPath,args:[...runtimeExecArgv(),bundledSupervisor,INTERNAL_SUPERVISOR_FLAG,...supervisorArgs]}:{command:process.execPath,args:[...runtimeExecArgv(),resolveCliMainPath(),INTERNAL_SUPERVISOR_FLAG,...supervisorArgs]}}var BUNDLED_SUPERVISOR_ENTRY="host-supervisor.js";function resolveBundledSupervisorEntryPath(){let entry=join2(dirname2(resolveCliMainPath()),BUNDLED_SUPERVISOR_ENTRY);return existsSync(entry)?entry:void 0}function resolveHostLifecycleEntryPath(){let modulePath=fileURLToPath(import.meta.url);if(basename(dirname2(modulePath))==="chunks")return;let extension=modulePath.endsWith(".ts")?".ts":".js",sibling=resolve2(dirname2(modulePath),`host-lifecycle${extension}`);return existsSync(sibling)?sibling:void 0}var SPAWNED_HOST_PROBE_TIMEOUT_MS=1e4;async function pollProtocolInfo(socket,timeoutMs,isCompatible2,childExit){let deadline=Date.now()+timeoutMs,lastProtocol;for(;Date.now()<=deadline;){let probe=holdProtocolInfo(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 held=await probe;if(!held)return{ready:!1,protocol:lastProtocol,exited:raced};if(lastProtocol=held.info,isCompatible2(held.info))return{ready:!0,protocol:held.info,hold:held.hold};held.hold.release()}else if(raced){if(lastProtocol=raced.info,isCompatible2(raced.info))return{ready:!0,protocol:raced.info,hold:raced.hold};raced.hold.release()}await delay2(50)}return{ready:!1,protocol:lastProtocol}}function isChildExit(value){return!!value&&"code"in value&&"signal"in value}function delay2(ms){return new Promise(resolveDelay=>setTimeout(resolveDelay,ms))}var EXPECTED_RUNTIME_BUILD_ID_ENV="SENPI_RPC_HOST_EXPECTED_RUNTIME_BUILD_ID",NEW_WORK_COMMANDS=new Set(["prompt","steer","follow_up","send_custom_message","continue_from_leaf","resume_session","append_user_message","bash","compact","wake","edit_assistant_message","edit_user_message"]),DEFAULT_POLL_MS=200,HostIdleHandover=class{constructor(options){this.options=options}view(){return this.operation?.view}admits(commandType){let state=this.operation?.view.state;return state===void 0||state==="handover_blocked"||!NEW_WORK_COMMANDS.has(commandType)}async begin(request){let current=this.operation;if(current!==void 0&¤t.view.operationId===request.operationId)return sameTerms(current.request,request)?answer(current):{kind:"refused",reason:"operation_conflict",detail:"this operation id names other terms"};if(current!==void 0&¤t.view.state!=="handover_blocked")return current.request.targetRuntimeBuildId===request.targetRuntimeBuildId?answer(current):{kind:"refused",reason:"handover_in_progress",detail:current.view.operationId};let self=this.options.identity();if(self.instanceId!==request.ifInstanceId||self.generation!==request.ifGeneration)return{kind:"refused",reason:"stale_generation",detail:`this host is ${self.instanceId} generation ${self.generation}`};if(self.runtimeBuildId===request.targetRuntimeBuildId)return{kind:"refused",reason:"already_current",detail:self.runtimeBuildId};let operation={request,view:{operationId:request.operationId,state:"handover_pending",targetRuntimeBuildId:request.targetRuntimeBuildId}};return this.operation=operation,this.options.log?.(`handover ${request.operationId} pending: no new work is admitted`),this.idleNow()?(await this.switchOver(operation),answer(operation)):(this.timer=setInterval(()=>this.observe(),this.options.pollMs??DEFAULT_POLL_MS),this.timer.unref?.(),answer(operation))}observe(){let operation=this.operation;operation?.view.state==="handover_pending"&&this.idleNow()&&this.switchOver(operation)}dispose(){this.stopTimer()}idleNow(){try{return this.options.isIdle()}catch(cause){return this.options.log?.(`handover idle check failed, waiting: ${String(cause)}`),!1}}async switchOver(operation){if(operation.view.state!=="handover_pending")return;this.stopTimer(),operation.view={...operation.view,state:"handover_switching"};let outcome=await this.options.perform(operation.request).catch(cause=>({ok:!1,reason:`successor_unavailable: ${String(cause)}`}));operation.view=outcome.ok?{...operation.view,state:"handover_completed",successor:outcome.successor}:{...operation.view,state:"handover_blocked",reason:outcome.reason},this.options.log?.(`handover ${operation.view.operationId} ${operation.view.state}`)}stopTimer(){this.timer!==void 0&&clearInterval(this.timer),this.timer=void 0}};function sameTerms(a,b){return a.targetRuntimeBuildId===b.targetRuntimeBuildId&&a.ifInstanceId===b.ifInstanceId&&a.ifGeneration===b.ifGeneration}function answer(operation){return{kind:"operation",view:operation.view}}function initialHostEnvironment(options){return daemonEnvironment(process.env,options.env,{[ENV_AGENT_DIR]:options.agentDir??getAgentDir(),[RPC_CLIENT_CAPABILITIES_ENV]:PINNED_HOST_CLIENT_CAPABILITIES.join(","),[HOST_INSTANCE_ID_ENV]:options.instanceId,[HOST_GENERATION_ENV]:String(options.generation),[HOST_DAEMON_DIR_ENV]:options.paths.dir})}function successorHostEnvironment(options){return daemonEnvironment(process.env,options.env,{[RPC_CLIENT_CAPABILITIES_ENV]:PINNED_HOST_CLIENT_CAPABILITIES.join(","),...options.agentDir?{[ENV_AGENT_DIR]:options.agentDir}:{},[HOST_INSTANCE_ID_ENV]:options.instanceId,[HOST_GENERATION_ENV]:String(options.generation),[HOST_DAEMON_DIR_ENV]:options.paths.dir,...options.expectedRuntimeBuildId!==void 0&&{[EXPECTED_RUNTIME_BUILD_ID_ENV]:options.expectedRuntimeBuildId}})}var DEFAULT_READINESS_TIMEOUT_MS=1e4;async function startHost(paths,socket,options,generation=0){let testOptions=options._test,lifetimeOwner=options.owner?await callerHostOwner():null,instanceId=randomUUID(),stopTarget=reason=>({daemonDir:paths.dir,generation:generationPaths(paths,instanceId),instanceId,sender:ensureSender(),reason});process.platform==="win32"&&await createSocketSecret(socketSecretPath(socket)),await writeHostSettings(paths,{socket,capabilities:PINNED_HOST_CLIENT_CAPABILITIES,coldStart:options.policy?.coldStart??"transient",idleExitMs:options.policy?.idleExitMs??9e5,generation,instanceId}),await writeHostOwner(generationPaths(paths,instanceId).dir,lifetimeOwner);let stderr=await open(paths.stderrLog,generation===0?"w":"a",384),pidFile,child,exitedEarly,childExit,presenterEnrollment;try{let supervisorArgs=["--socket",socket,...options.owner?["--owner-fd",String(OWNER_WATCH_FD)]:[],...options.presenterBootstrap?["--mcp-presenter-fd","4"]:[],...options.hostArgs??[]],launch=testOptions?.spawn??testOptions?.launch?.(supervisorArgs)??defaultHostLaunch(supervisorArgs);if(child=spawn(launch.command,[...launch.args],{detached:!0,windowsHide:!0,env:initialHostEnvironment({agentDir:options.agentDir,env:options.env,paths,instanceId,generation}),stdio:options.presenterBootstrap?["ignore","ignore",stderr.fd,options.owner?"pipe":"ignore","pipe"]:options.owner?["ignore","ignore",stderr.fd,"pipe"]:["ignore","ignore",stderr.fd]}),options.presenterBootstrap&&(presenterEnrollment=relayPresenterBootstrap(options.presenterBootstrap,child)),childExit=new Promise(resolveExit=>{child.once("exit",(code,signal)=>{exitedEarly={code,signal},resolveExit(exitedEarly)})}),options.owner&&keepOwnerPipe(child),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 writeHostRegistration(paths,{record:pidFile,socket,instanceId,generation,launchProfileId:hostLaunchProfile(hostChildArgv(options.hostArgs??[]),process.cwd()).profile_id,build:engineBuildIdentity()}),child.unref()}catch(error){let exitedBeforeCleanup=exitedEarly;if(!exitedBeforeCleanup&&child?.pid!==void 0&&childExit&&await stopUnregisteredStart(child,childExit,stopTarget("start_failed")),!exitedBeforeCleanup)throw await clearHostRegistration(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 clearHostRegistration(paths),new Error(diagnostic2)}finally{await stderr.close()}let readinessTimeoutMs=testOptions?.readinessTimeoutMs??DEFAULT_READINESS_TIMEOUT_MS,result=await pollProtocolInfo(socket,readinessTimeoutMs,isCompatible,childExit);if(result.ready)return await presenterEnrollment,{pid:pidFile.pid,socket,reused:!1,release:result.hold.release};await testOptions?.beforeReadinessTeardown?.();let stopFailure=await stopSpawnedChild(child,childExit,testOptions?.stopTimeoutMs??DEFAULT_STOP_TIMEOUT_MS,stopTarget("readiness_timeout")).then(()=>{},error=>error instanceof Error?error.message:String(error)),message=result.protocol?`RPC socket host answered get_protocol_info with protocolVersion ${result.protocol.protocolVersion}, serverVersion ${result.protocol.serverVersion} and capabilities ${JSON.stringify(result.protocol.capabilities)}, but is incompatible with protocol version ${HOST_PROTOCOL_VERSION} and required capabilities ${JSON.stringify(REQUIRED_HOST_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 clearHostRegistration(paths),new Error(diagnostic)}async function stopUnregisteredStart(child,childExit,target){let pid=child.pid,running=()=>child.exitCode===null&&child.signalCode===null;if(pid===void 0||!running())return;let announced=await announceStop(target,pid);try{signalPid(pid,"SIGTERM")}catch{}if(await Promise.race([childExit,delay(2e3)]),!running())return;try{signalPid(pid,"SIGKILL")}catch{}await Promise.race([childExit.then(()=>!0),delay(SIGKILL_GRACE_MS).then(()=>!1)])&&await recordEscalation(target,announced)}async function appendStderr(paths,message){try{let stderr=(await readFile2(paths.stderrLog,"utf8")).trim();return stderr?`${message}
|
|
3
3
|
${stderr}`:message}catch(error){if(isNodeErrorCode(error,"ENOENT"))return message;throw error}}import{appendFile}from"node:fs/promises";import{basename as basename2,join as join4}from"node:path";import{readFile as readFile3,rename,writeFile}from"node:fs/promises";import{join as join3}from"node:path";var GC_SKIP_INITIAL_BACKOFF_MS=10*6e4,GC_SKIP_MAX_BACKOFF_MS=1440*6e4,skipEntrySchema=external_exports.object({skipUntil:external_exports.number(),backoffMs:external_exports.number()}),markerSchema=external_exports.object({completedAt:external_exports.number(),cursor:external_exports.string().nullable(),examined:external_exports.number(),removed:external_exports.number(),stoppedBy:external_exports.enum(["time","count","exhausted"]),skip:external_exports.record(external_exports.string(),skipEntrySchema)});function hostGcPassMarkerPath(agentDir){return join3(agentDir,"rpc-host-daemon","gc-last-run.json")}function parseHostGcPassMarker(text){try{let parsed=markerSchema.safeParse(JSON.parse(text));return parsed.success?parsed.data:void 0}catch(error){if(error instanceof SyntaxError)return;throw error}}async function readHostGcPassMarker(agentDir){let text=await readFile3(hostGcPassMarkerPath(agentDir),"utf8").catch(error=>{if(!(error instanceof Error&&"code"in error&&error.code==="ENOENT"))throw error});return text===void 0?void 0:parseHostGcPassMarker(text)}async function writeHostGcPassMarker(agentDir,marker){let path=hostGcPassMarkerPath(agentDir),staged=`${path}.${process.pid}.tmp`;await writeFile(staged,`${JSON.stringify(marker)}
|
|
4
4
|
`,{mode:384}),await rename(staged,path)}function nextSkip(previous,now){let backoffMs=previous===void 0?GC_SKIP_INITIAL_BACKOFF_MS:Math.min(previous.backoffMs*2,GC_SKIP_MAX_BACKOFF_MS);return{skipUntil:now+backoffMs,backoffMs}}var OPPORTUNISTIC_GC_BUDGET={budgetMs:1500,maxEndpoints:32,minIntervalMs:3e5};async function gcHostEndpointsOpportunistically(options){let now=options.now??Date.now,budgetMs=options.budgetMs??OPPORTUNISTIC_GC_BUDGET.budgetMs,maxEndpoints=options.maxEndpoints??OPPORTUNISTIC_GC_BUDGET.maxEndpoints,minIntervalMs=options.minIntervalMs??OPPORTUNISTIC_GC_BUDGET.minIntervalMs,previous=await readHostGcPassMarker(options.agentDir),startedAt=now();if(previous!==void 0&&startedAt-previous.completedAt<minIntervalMs)return{ran:!1};process.platform!=="win32"&&await gcRpcPublicKeys(options.agentDir,{deadline:startedAt+budgetMs,maxRecords:maxEndpoints});let candidates=await gcCandidates(options),present=new Set(candidates.map(endpoint=>endpoint.name)),skip={};for(let[name,entry]of Object.entries(previous?.skip??{}))present.has(name)&&(skip[name]=entry);let cursor=previous?.cursor??null,examined=0,removed=0,stoppedBy="exhausted";for(let endpoint of rotateAfter(candidates,cursor)){if((skip[endpoint.name]?.skipUntil??0)>now())continue;if(examined>=maxEndpoints){stoppedBy="count";break}if(now()-startedAt>=budgetMs){stoppedBy="time";break}examined+=1,cursor=endpoint.name;let outcome=await gcEndpoint(endpoint.socket,endpoint.dir,{staleEngine:{}}).catch(()=>({removed:!1}));"stopped"in outcome?delete skip[endpoint.name]:outcome.removed?(removed+=1,delete skip[endpoint.name]):skip[endpoint.name]=nextSkip(skip[endpoint.name],now())}let marker={completedAt:now(),cursor,examined,removed,stoppedBy,skip};return await writeHostGcPassMarker(options.agentDir,marker),{ran:!0,marker}}var passesRunning=new Map;function scheduleOpportunisticHostGc(options){if(passesRunning.has(options.agentDir))return;let pass=new Promise(resolve6=>{setImmediate(()=>{gcHostEndpointsOpportunistically(options).then(()=>{},error=>recordPassFailure(options.agentDir,error)).finally(()=>{passesRunning.delete(options.agentDir),resolve6()})}).unref()});passesRunning.set(options.agentDir,pass)}async function gcCandidates(options){let targetName=basename2(createHostDaemonPaths({socket:options.exclude,agentDir:options.agentDir}).dir),candidates=[];for(let endpoint of await listHostEndpoints(options.agentDir)){let name=basename2(endpoint.dir);endpoint.socket===null||name===targetName||sameEndpoint(endpoint.socket,options.exclude)||candidates.push({...endpoint,socket:endpoint.socket,name})}return candidates}function rotateAfter(endpoints,cursor){if(cursor===null)return endpoints;let start=endpoints.findIndex(endpoint=>endpoint.name>cursor);return start<=0?endpoints:[...endpoints.slice(start),...endpoints.slice(0,start)]}async function recordPassFailure(agentDir,error){let line=`${new Date().toISOString()} gc pass failed: ${error instanceof Error?error.message:String(error)}
|
|
5
5
|
`;await appendFile(join4(agentDir,"rpc-host-daemon","gc-pass.log"),line,{mode:384}).catch(logError=>{logError instanceof Error&&"code"in logError&&logError.code==="ENOENT"||process.emitWarning(`host gc pass failed and could not be recorded: ${String(logError)}`)})}import{realpath as realpath2}from"node:fs/promises";import{basename as basename3,dirname as dirname3,resolve as resolve3}from"node:path";async function foreignAgentDirRefusal(socket,callerAgentDir,host){let hostAgentDir=host.agentDir??await layoutAgentDir(socket);if(hostAgentDir===void 0)return;let detail=await agentDirMismatch(socket,callerAgentDir,hostAgentDir);return detail===void 0?void 0:{action:"refuse",reason:"foreign_agent_dir",upgradeable:!1,detail}}async function agentDirMismatch(socket,callerAgentDir,hostAgentDir){let[ours,theirs]=await Promise.all([canonicalDirectory(callerAgentDir),canonicalDirectory(hostAgentDir)]);if(theirs!==ours)return`${socket} is served by the host of agent dir ${theirs}, and this client's agent dir is ${ours}; a host is only replaced by a client of its own agent dir - run with that agent dir to upgrade it, or use a socket of your own`}async function layoutAgentDir(socket){let rpcDirectory=dirname3(socket);if(basename3(socket)!=="rpc.sock"||basename3(rpcDirectory)!=="rpc")return;let agentDir=dirname3(rpcDirectory),paths=createHostDaemonPaths({socket,agentDir});return await provenOwner(await readHostRegistration(paths),socket)===void 0?void 0:agentDir}async function canonicalDirectory(path){return realpath2(path).catch(()=>resolve3(path))}import{spawn as spawn2}from"node:child_process";import{randomUUID as randomUUID2}from"node:crypto";import{open as open2,rm,writeFile as writeFile2}from"node:fs/promises";var DEFAULT_HANDOFF_READINESS_MS=3e4,SUCCESSOR_EXIT_WAIT_MS=5e3,SUCCESSOR_START_BUDGET_MS=1e4+DEFAULT_HANDOFF_READINESS_MS+2e3+SUCCESSOR_EXIT_WAIT_MS;async function startSuccessor(context){let{options,paths,host,owner,drainGate}=context,generation=(host.generation??0)+1,instanceId=randomUUID2(),bindSocket=generationBindPath(options.socket,generation);if(Buffer.byteLength(bindSocket)>MAX_SOCKET_PATH_BYTES)return{action:"refuse",reason:"socket_path_too_long",upgradeable:!0,detail:bindSocket};let replaced=await statSocketIdentity(options.socket);if(!replaced)return{action:"refuse",reason:"socket_replaced",upgradeable:!0};let running=await readHostSettings(paths),lifetimeOwner=host.instanceId?await readHostOwner(generationPaths(paths,host.instanceId).dir):null,inheritOwnerPipe=lifetimeOwner?.pid===process.pid&&sameHostOwner(lifetimeOwner,await callerHostOwner()),bootSettings=await readFileOrUndefined(paths.settingsFile);await writeHostSettings(paths,{socket:options.socket,capabilities:PINNED_HOST_CLIENT_CAPABILITIES,coldStart:options.policy?.coldStart??running?.coldStart??"transient",idleExitMs:options.policy?.idleExitMs??running?.idleExitMs??9e5,generation,instanceId});let child,exited;try{await writeHostOwner(generationPaths(paths,instanceId).dir,lifetimeOwner??null),await options._test?.beforeSpawn?.();let argv=["--socket",options.socket,"--bind",bindSocket,"--replace",`${replaced.dev}:${replaced.ino}`,...inheritOwnerPipe?["--owner-fd",String(OWNER_WATCH_FD)]:[],...options.presenterBootstrap?["--mcp-presenter-fd","4"]:[],...options.hostArgs??[]],launch=(options._test?.launch??options.launch)?.(argv)??defaultHostLaunch(argv),stderr=await open2(paths.stderrLog,"a",384),spawned=spawn2(launch.command,[...launch.args],{detached:!0,windowsHide:!0,env:successorHostEnvironment({agentDir:options.agentDir,env:options.env,expectedRuntimeBuildId:options.expectedRuntimeBuildId,paths,generation,instanceId}),stdio:options.presenterBootstrap?["ignore","ignore",stderr.fd,inheritOwnerPipe?"pipe":"ignore","pipe"]:inheritOwnerPipe?["ignore","ignore",stderr.fd,"pipe"]:["ignore","ignore",stderr.fd]}),presenterEnrollment=options.presenterBootstrap?relayPresenterBootstrap(options.presenterBootstrap,spawned):void 0;if(child=spawned,exited=new Promise(resolve6=>spawned.once("exit",()=>resolve6())),await stderr.close(),inheritOwnerPipe&&keepOwnerPipe(spawned),child.pid===void 0)throw new Error("failed to spawn the successor generation");let processStartTime=await waitForStartTime(child.pid,1e4).catch(()=>{})??null,registration={record:{pid:child.pid,processStartTime},socket:options.socket,instanceId,generation,launchProfileId:hostLaunchProfile(["--mode","rpc","--multi-session",...options.hostArgs??[]],process.cwd()).profile_id};await writeGenerationRecord(paths,registration),await options._test?.afterSpawn?.(child.pid);let answer2=await awaitSuccessor(options,host,exited);if(!answer2){let reason=await abortReason(options.socket,replaced),cleanupFailure=await abandonSuccessor({child,exited,paths,instanceId,bootSettings,reason:"successor_readiness_timeout"});return{action:"refuse",reason,upgradeable:!0,...cleanupFailure&&{detail:cleanupFailure}}}return await options._test?.beforeRegistration?.(),await writeHostRegistration(paths,{...registration,...successorBuild(answer2)}),await presenterEnrollment,child.unref(),owner!==void 0&&(drainGate===void 0||await drainGate())&&signalGeneration(owner.pid,"SIGUSR1"),{action:"handoff",pid:child.pid,socket:options.socket,generation:answer2.generation??generation,instanceId:answer2.instanceId??""}}catch(cause){let cleanupFailure=await abandonSuccessor({child,exited,paths,instanceId,bootSettings,reason:"successor_start_failed"}),detail=cause instanceof Error?cause.message:String(cause);return{action:"refuse",reason:"successor_unavailable",upgradeable:!0,detail:cleanupFailure?`${detail}; ${cleanupFailure}`:detail}}}async function abandonSuccessor(context){let{child,exited,paths,instanceId,bootSettings}=context,target={daemonDir:paths.dir,generation:generationPaths(paths,instanceId),instanceId,sender:{pid:process.pid,kind:"successor"},reason:context.reason},killed=child?.pid!==void 0&&child.exitCode===null&&child.signalCode===null?await announceStop(target,child.pid):void 0;killed!==void 0&&child?.pid!==void 0&&signalPid(child.pid,"SIGKILL");try{bootSettings===void 0?await rm(paths.settingsFile,{force:!0}):await writeFile2(paths.settingsFile,bootSettings,{mode:HOST_STATE_FILE_MODE}),child?.pid===void 0?await rm(generationPaths(paths,instanceId).dir,{recursive:!0,force:!0}):exited!==void 0&&await exitedWithin(exited,SUCCESSOR_EXIT_WAIT_MS)&&(killed!==void 0&&await recordEscalation(target,killed),await releaseGeneration(paths,{instanceId,pid:child.pid}));return}catch(cause){return`successor cleanup failed: ${cause instanceof Error?cause.message:String(cause)}`}}async function exitedWithin(exited,ms){let timer,timedOut=new Promise(resolve6=>{timer=setTimeout(()=>resolve6(!1),ms)});try{return await Promise.race([exited.then(()=>!0),timedOut])}finally{clearTimeout(timer)}}function successorBuild(answer2){return answer2.engineVersion===void 0||answer2.engineOrdinal===void 0?{}:{build:{text:answer2.engineVersion,ordinal:answer2.engineOrdinal}}}async function awaitSuccessor(options,previous,exited){let deadline=Date.now()+(options._test?.readinessTimeoutMs??DEFAULT_HANDOFF_READINESS_MS),childGone=!1;for(exited.then(()=>{childGone=!0});Date.now()<=deadline;){let answer2=await probeProtocolInfo(options.socket,2e3);if(answer2&&answer2.instanceId!==void 0&&answer2.instanceId!==previous.instanceId)return answer2;if(childGone)return;await delay3(50)}}async function abortReason(socket,replaced){let current=await statSocketIdentity(socket).catch(()=>{});return current===void 0||current.dev!==replaced.dev||current.ino!==replaced.ino?"socket_replaced":"successor_unavailable"}function delay3(ms){return new Promise(resolve6=>setTimeout(resolve6,ms))}var SESSION_COUNT_TIMEOUT_MS=1e4;async function handoffUnregisteredHost(options,paths,host){let counted=await holdSessionCount(options.socket,SESSION_COUNT_TIMEOUT_MS);try{let legacy=await provenLegacyOwner(paths,options.socket),sessions=counted?.sessions;if(sessions!==0)return legacy!==void 0?{action:"refuse",reason:"legacy_host",upgradeable:!0,detail:busyLegacyHostDetail(legacy.pid,options.socket,sessions)}:{action:"refuse",reason:"unknown_owner",upgradeable:!0,detail:`${options.socket} has no provable owner and holds ${describeSessions(sessions)}; it is never signalled - let that work finish, then retry`};let result=await startSuccessor({options,paths,host,owner:legacy,drainGate:async()=>await counted?.recount(SESSION_COUNT_TIMEOUT_MS)===0});return result.action==="handoff"&&legacy===void 0&&warnUnsignalledPredecessor(options.socket,host),result}finally{counted?.close()}}function warnUnsignalledPredecessor(socket,host){process.stderr.write(`generation handoff: no provable owner for ${socket}; the host it replaced (instance ${host.instanceId??"unknown"}, engine ${host.engineVersion??"unknown"}) listed 0 sessions and was not signalled; it drains itself on losing the public socket
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url); { const __piWorkerThreads = require("node:worker_threads"); if (typeof __piWorkerThreads.markAsUncloneable !== "function") { __piWorkerThreads.markAsUncloneable = () => {}; } }
|
|
2
|
-
import{isTuiControlSocket}from"./chunk-
|
|
2
|
+
import{isTuiControlSocket}from"./chunk-KKD4CYCI.js";import{HOST_DAEMON_LAYOUT,createHostDaemonPaths,hostDaemonDirectoryPaths,parseJson,readFileOrUndefined,socketNamesDirectory}from"./chunk-4WZRVZNX.js";import{readdir}from"node:fs/promises";import{basename,join}from"node:path";var ENDPOINT_DIRECTORY_NAME=/^[0-9a-f]{16}$/;async function listHostEndpoints(agentDir){let flatDir=join(agentDir,"rpc-host-daemon");if(parseJson(await readFileOrUndefined(join(flatDir,"layout.json")).catch(()=>{}))?.layout!==HOST_DAEMON_LAYOUT)return[];let dirs=(await readdir(flatDir,{withFileTypes:!0}).catch(()=>[])).filter(entry=>entry.isDirectory()&&ENDPOINT_DIRECTORY_NAME.test(entry.name)).map(entry=>join(flatDir,entry.name)).sort(),endpoints=[];for(let dir of dirs)endpoints.push(await identifyEndpoint(dir));return endpoints}async function identifyEndpoint(dir){let paths=hostDaemonDirectoryPaths(dir),named=await recordNaming(paths.endpointFile,dir);if(named!==void 0)return{socket:named.socket,dir,identity:"endpoint",endpoint_kind:endpointKindOf(named.record)};let booted=await recordNaming(paths.settingsFile,dir);if(booted!==void 0)return{socket:booted.socket,dir,identity:"settings",endpoint_kind:"rpc_host"};let generations=await readdir(paths.generationsDir).catch(()=>[]);for(let instanceId of generations.sort()){let recorded=await recordNaming(join(paths.generationsDir,instanceId,"settings.json"),dir);if(recorded!==void 0)return{socket:recorded.socket,dir,identity:"generation-settings",endpoint_kind:"rpc_host"}}return{socket:null,dir,identity:"unknown",endpoint_kind:"rpc_host"}}async function endpointKindOfSocket(socket,agentDir){if(isTuiControlSocket(socket))return"tui";let paths=createHostDaemonPaths({socket,agentDir}),named=await recordNaming(paths.endpointFile,paths.dir);return named===void 0?"rpc_host":endpointKindOf(named.record)}function endpointKindOf(record){return record.endpoint_kind==="tui"?"tui":"rpc_host"}async function recordNaming(file,dir){let record=parseJson(await readFileOrUndefined(file).catch(()=>{})),socket=record?.socket;if(!(record===void 0||typeof socket!="string"||socket===""))return socketNamesDirectory(socket,basename(dir))?{socket,record}:void 0}export{listHostEndpoints,endpointKindOfSocket};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url); { const __piWorkerThreads = require("node:worker_threads"); if (typeof __piWorkerThreads.markAsUncloneable !== "function") { __piWorkerThreads.markAsUncloneable = () => {}; } }
|
|
2
2
|
import{ProcessIdentityUnreadableError,processMatchesPidFile,readProcessStartTime}from"./chunk-O5RYI3IW.js";var HOST_GENERATION_ENV="SENPI_RPC_HOST_GENERATION",HOST_INSTANCE_ID_ENV="SENPI_RPC_HOST_INSTANCE_ID";import{createHmac,timingSafeEqual}from"node:crypto";var RPC_AUTH_CAPABILITY="socket_auth",RPC_AUTH_HEX=/^[a-f0-9]{64}$/,RPC_LAUNCH_ID=/^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/;function rpcAuthProof(key,label,...parts){return createHmac("sha256",key).update([`senpi-rpc-${label}`,...parts].join(`
|
|
3
3
|
`),"utf8").digest("hex")}function rpcProofMatches(expected,received){return typeof received=="string"&&RPC_AUTH_HEX.test(received)&&timingSafeEqual(Buffer.from(expected,"hex"),Buffer.from(received,"hex"))}var RpcEndpointAuthError=class extends Error{constructor(code,detail,options){super(`${code}: ${detail}`,options),this.code=code,this.name="RpcEndpointAuthError"}};function authRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)?value:void 0}import{randomBytes,randomUUID}from"node:crypto";import{constants,unlinkSync}from"node:fs";import*as fs from"node:fs/promises";import{join}from"node:path";var MAX_KEY_RECORD_BYTES=4096;async function checkRpcKeyDirectory(path,privateKeys=!1){let checked=privateKeys?path:await fs.realpath(path),problem=keyDirectoryProblem(await fs.lstat(checked),checked,privateKeys);if(problem!==void 0)throw new RpcEndpointAuthError("unsafe_key_record",`${checked} ${problem}`)}function keyDirectoryProblem(info,path,privateKeys){if(!info.isDirectory())return"is not a directory";if(info.uid!==process.getuid?.())return"is not owned by this user";let mode=info.mode&4095;return privateKeys?mode===448?void 0:`must be mode 0700 (is 0${mode.toString(8)}); run: chmod 700 ${path}`:(mode&18)===0?void 0:`is writable by group or others; run: chmod go-w ${path}`}async function checkRpcKeyParents(root){await checkRpcKeyDirectory(root),await checkRpcKeyDirectory(join(root,"rpc"))}async function readRpcKeyRecord(root,launchId){if(!RPC_LAUNCH_ID.test(launchId))throw new RpcEndpointAuthError("unsafe_key_record",`invalid launch id under ${root}`);let path=join(root,"rpc","keys",launchId);try{await checkRpcKeyParents(root),await checkRpcKeyDirectory(join(root,"rpc","keys"),!0);let handle=await fs.open(path,constants.O_RDONLY|constants.O_NOFOLLOW|constants.O_NONBLOCK);try{let info=await handle.stat();if(!info.isFile()||info.uid!==process.getuid?.()||(info.mode&4095)!==384||info.size>MAX_KEY_RECORD_BYTES)throw new RpcEndpointAuthError("unsafe_key_record",path);let record=authRecord(JSON.parse(await handle.readFile("utf8")));if(record?.version!==1||record.launch_id!==launchId||typeof record.key!="string"||!RPC_AUTH_HEX.test(record.key))throw new RpcEndpointAuthError("unsafe_key_record",path);return record}finally{await handle.close()}}catch(cause){if(cause instanceof Error&&"code"in cause&&cause.code==="ENOENT")return;throw cause instanceof RpcEndpointAuthError?cause:new RpcEndpointAuthError("unsafe_key_record",path,{cause})}}var RpcPublicEndpoint=class{constructor(agentDir,endpoint){this.key=randomBytes(32),this.launchId=randomUUID(),this.publication=Promise.withResolvers(),this.created=!1,this.exitCleanup=()=>{if(this.created)try{unlinkSync(this.recordPath)}catch(cause){cause instanceof Error&&"code"in cause&&cause.code==="ENOENT"||process.stderr.write(`senpi rpc host: could not remove own endpoint key record
|
|
4
|
-
`)}},this.agentDir=agentDir,this.endpoint=endpoint,this.recordPath=join(agentDir,"rpc","keys",this.launchId),this.ready=this.publication.promise,this.ready.catch(()=>{})}async publish(){try{await fs.mkdir(join(this.agentDir,"rpc"),{recursive:!0,mode:448}),await checkRpcKeyParents(this.agentDir);let keys=join(this.agentDir,"rpc","keys");await fs.mkdir(keys,{recursive:!0,mode:448});let directory=await fs.lstat(keys);if(!directory.isDirectory()||directory.uid!==process.getuid?.())throw new RpcEndpointAuthError("unsafe_key_record",keys);(directory.mode&4095)!==448&&await fs.chmod(keys,448),await checkRpcKeyDirectory(keys,!0);let handle=await fs.open(this.recordPath,constants.O_WRONLY|constants.O_CREAT|constants.O_EXCL|constants.O_NOFOLLOW,384);this.created=!0,process.once("exit",this.exitCleanup);try{await handle.writeFile(JSON.stringify({version:1,launch_id:this.launchId,key:this.key.toString("hex"),pid:process.pid,process_start:await readProcessStartTime(process.pid)??null,endpoint:this.endpoint,created_at:new Date().toISOString()})),await handle.sync();let info=await handle.stat();if(!info.isFile()||info.uid!==process.getuid?.()||(info.mode&4095)!==384)throw new RpcEndpointAuthError("unsafe_key_record",this.recordPath)}finally{await handle.close()}this.publication.resolve()}catch(cause){let error=new RpcEndpointAuthError("key_publication_failed",cause instanceof RpcEndpointAuthError?cause.message:this.recordPath,{cause});throw this.publication.reject(error),error}}async dispose(){process.off("exit",this.exitCleanup),this.created&&(this.created=!1,await fs.unlink(this.recordPath).catch(cause=>{if(!(cause instanceof Error&&"code"in cause&&cause.code==="ENOENT"))throw cause}))}};async function gcRpcPublicKeys(agentDir,budget={}){let keys=join(agentDir,"rpc","keys");try{await checkRpcKeyParents(agentDir),await checkRpcKeyDirectory(keys,!0)}catch(cause){if(cause instanceof RpcEndpointAuthError||cause instanceof Error&&"code"in cause&&cause.code==="ENOENT")return;throw cause}let names=await fs.readdir(keys).catch(cause=>{if(cause instanceof Error&&"code"in cause&&cause.code==="ENOENT")return[];throw cause}),examined=0;for(let name of names){if(Date.now()>=(budget.deadline??1/0)||examined>=(budget.maxRecords??1/0))break;if(RPC_LAUNCH_ID.test(name)){examined++;try{let record=await readRpcKeyRecord(agentDir,name);if(record===void 0||typeof record.pid!="number"||!Number.isSafeInteger(record.pid)||record.pid<=0||!(record.process_start===null||typeof record.process_start=="string")||await processMatchesPidFile({pid:record.pid,processStartTime:record.process_start}))continue;await fs.unlink(join(keys,name))}catch(cause){if(cause instanceof ProcessIdentityUnreadableError||cause instanceof RpcEndpointAuthError||cause instanceof Error&&"code"in cause&&cause.code==="ENOENT")continue;throw cause}}}}var OBSERVE_REQUEST_FIELD="observe",ORIGIN_HOST_INSTANCE_FIELD="origin_host_instance",OBSERVING_COMMANDS=new Set(["get_protocol_info","list_sessions","subscribe_sessions","unsubscribe_sessions","get_effect_status","get_pending_inputs","get_subscription_limits"]);function isObservingRequest(line){let request;try{request=JSON.parse(line)}catch{return!1}if(typeof request!="object"||request===null||Array.isArray(request))return!1;let record=request;return record.type==="warm"||record.type==="authenticate"?!0:record[OBSERVE_REQUEST_FIELD]===!0&&OBSERVING_COMMANDS.has(record.type)}function originHostInstance(env=process.env){let instance=env[HOST_INSTANCE_ID_ENV]?.trim();return instance||void 0}function requestOriginHostInstance(line){let request;try{request=JSON.parse(line)}catch{return}if(typeof request!="object"||request===null||Array.isArray(request))return;let origin=Reflect.get(request,ORIGIN_HOST_INSTANCE_FIELD);return typeof origin=="string"&&origin.length>0?origin:void 0}export{HOST_GENERATION_ENV,HOST_INSTANCE_ID_ENV,OBSERVE_REQUEST_FIELD,ORIGIN_HOST_INSTANCE_FIELD,isObservingRequest,originHostInstance,requestOriginHostInstance,RPC_AUTH_CAPABILITY,RPC_AUTH_HEX,RPC_LAUNCH_ID,rpcAuthProof,rpcProofMatches,RpcEndpointAuthError,authRecord,readRpcKeyRecord,RpcPublicEndpoint,gcRpcPublicKeys};
|
|
4
|
+
`)}},this.agentDir=agentDir,this.endpoint=endpoint,this.recordPath=join(agentDir,"rpc","keys",this.launchId),this.ready=this.publication.promise,this.ready.catch(()=>{})}async publish(){try{await fs.mkdir(join(this.agentDir,"rpc"),{recursive:!0,mode:448}),await checkRpcKeyParents(this.agentDir);let keys=join(this.agentDir,"rpc","keys");await fs.mkdir(keys,{recursive:!0,mode:448});let directory=await fs.lstat(keys);if(!directory.isDirectory()||directory.uid!==process.getuid?.())throw new RpcEndpointAuthError("unsafe_key_record",keys);(directory.mode&4095)!==448&&await fs.chmod(keys,448),await checkRpcKeyDirectory(keys,!0);let handle=await fs.open(this.recordPath,constants.O_WRONLY|constants.O_CREAT|constants.O_EXCL|constants.O_NOFOLLOW,384);this.created=!0,process.once("exit",this.exitCleanup);try{await handle.writeFile(JSON.stringify({version:1,launch_id:this.launchId,key:this.key.toString("hex"),pid:process.pid,process_start:await readProcessStartTime(process.pid)??null,endpoint:this.endpoint,created_at:new Date().toISOString()})),await handle.sync();let info=await handle.stat();if(!info.isFile()||info.uid!==process.getuid?.()||(info.mode&4095)!==384)throw new RpcEndpointAuthError("unsafe_key_record",this.recordPath)}finally{await handle.close()}this.publication.resolve()}catch(cause){let error=new RpcEndpointAuthError("key_publication_failed",cause instanceof RpcEndpointAuthError?cause.message:this.recordPath,{cause});throw this.publication.reject(error),error}}async dispose(){process.off("exit",this.exitCleanup),this.created&&(this.created=!1,await fs.unlink(this.recordPath).catch(cause=>{if(!(cause instanceof Error&&"code"in cause&&cause.code==="ENOENT"))throw cause}))}};async function gcRpcPublicKeys(agentDir,budget={}){let keys=join(agentDir,"rpc","keys");try{await checkRpcKeyParents(agentDir),await checkRpcKeyDirectory(keys,!0)}catch(cause){if(cause instanceof RpcEndpointAuthError||cause instanceof Error&&"code"in cause&&cause.code==="ENOENT")return;throw cause}let names=await fs.readdir(keys).catch(cause=>{if(cause instanceof Error&&"code"in cause&&cause.code==="ENOENT")return[];throw cause}),examined=0;for(let name of names){if(Date.now()>=(budget.deadline??1/0)||examined>=(budget.maxRecords??1/0))break;if(RPC_LAUNCH_ID.test(name)){examined++;try{let record=await readRpcKeyRecord(agentDir,name);if(record===void 0||typeof record.pid!="number"||!Number.isSafeInteger(record.pid)||record.pid<=0||!(record.process_start===null||typeof record.process_start=="string")||await processMatchesPidFile({pid:record.pid,processStartTime:record.process_start}))continue;await fs.unlink(join(keys,name))}catch(cause){if(cause instanceof ProcessIdentityUnreadableError||cause instanceof RpcEndpointAuthError||cause instanceof Error&&"code"in cause&&cause.code==="ENOENT")continue;throw cause}}}}var OBSERVE_REQUEST_FIELD="observe",ORIGIN_HOST_INSTANCE_FIELD="origin_host_instance",OBSERVING_COMMANDS=new Set(["get_protocol_info","list_sessions","subscribe_sessions","unsubscribe_sessions","get_effect_status","get_pending_inputs","get_subscription_limits","get_state","get_entries"]);function isObservingRequest(line){let request;try{request=JSON.parse(line)}catch{return!1}if(typeof request!="object"||request===null||Array.isArray(request))return!1;let record=request;return record.type==="warm"||record.type==="authenticate"?!0:record[OBSERVE_REQUEST_FIELD]===!0&&OBSERVING_COMMANDS.has(record.type)}function originHostInstance(env=process.env){let instance=env[HOST_INSTANCE_ID_ENV]?.trim();return instance||void 0}function requestOriginHostInstance(line){let request;try{request=JSON.parse(line)}catch{return}if(typeof request!="object"||request===null||Array.isArray(request))return;let origin=Reflect.get(request,ORIGIN_HOST_INSTANCE_FIELD);return typeof origin=="string"&&origin.length>0?origin:void 0}export{HOST_GENERATION_ENV,HOST_INSTANCE_ID_ENV,OBSERVE_REQUEST_FIELD,ORIGIN_HOST_INSTANCE_FIELD,isObservingRequest,originHostInstance,requestOriginHostInstance,RPC_AUTH_CAPABILITY,RPC_AUTH_HEX,RPC_LAUNCH_ID,rpcAuthProof,rpcProofMatches,RpcEndpointAuthError,authRecord,readRpcKeyRecord,RpcPublicEndpoint,gcRpcPublicKeys};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url); { const __piWorkerThreads = require("node:worker_threads"); if (typeof __piWorkerThreads.markAsUncloneable !== "function") { __piWorkerThreads.markAsUncloneable = () => {}; } }
|
|
2
|
-
import{BUILTIN_PATH_PREFIX}from"./chunk-QMRJYMNH.js";import{listHostEndpoints}from"./chunk-C5UFJ7B3.js";import{parseArgs,resolveSessionRuntime}from"./chunk-WD6WBYC5.js";import{PROBE_REQUEST_ID,connectAndAsk,isRecord as isRecord2,readAnswer,requestOnSocket}from"./chunk-JA2R2ZSE.js";import{acquireOwnershipSafeLock,claimOwnerIsLive,hostChildAlive,isGenerationId,logUnknownHostIdentity,provenOwner,readDrainWatch,readGenerationRegistration,readHostRegistration,readSessionPathClaims,releaseGeneration,resolveHostPolicy,writeDrainRequest,writeStopIntent}from"./chunk-SWJXRC2I.js";import{HOST_DAEMON_LAYOUT,canonicalEndpointPath,createHostDaemonPaths,generationPaths,hostDaemonDirectoryPaths,isRecord,parseJson,readFileOrUndefined,sameEndpoint,writeStateFile}from"./chunk-4WZRVZNX.js";import{HOST_GENERATION_ENV,HOST_INSTANCE_ID_ENV,OBSERVE_REQUEST_FIELD,gcRpcPublicKeys}from"./chunk-O3Q2ET6W.js";import{readSocketSecret,resolveSocketTransportAddress,socketSecretPath}from"./chunk-ZGAB7WQA.js";import{APP_NAME,VERSION,getAgentDir,isBunBinary}from"./chunk-7YO7VQZW.js";import{ProcessIdentityUnreadableError,parseDaemonPidFile,processIsLive,processMatchesPidFile,processStartTimeMs,readProcessStartTime}from"./chunk-O5RYI3IW.js";var CALVER=/^(\d+)\.(\d+)\.(\d+)(?:-(\d+))?/;function engineBuildIdentityFrom(build){let match=CALVER.exec(build.version),epoch=Number.isSafeInteger(build.epoch)&&build.epoch!==void 0&&build.epoch>0?build.epoch:0,sha7=build.sha7??"";return{text:epoch===0?build.version:`${build.version}+${epoch}${sha7===""?"":`.${sha7}`}`,ordinal:[match?Number(match[1]):0,match?Number(match[2]):0,match?Number(match[3]):0,match?.[4]?Number(match[4]):0,epoch],scheme:epoch===0?"nodef":"epoch"}}var BUILT=engineBuildIdentityFrom({version:VERSION,epoch:typeof SENPI_BUILD_EPOCH=="number"?SENPI_BUILD_EPOCH:0,sha7:typeof SENPI_BUILD_SHA7=="string"?SENPI_BUILD_SHA7:""});function engineBuildIdentity(){return BUILT}function compareEngineOrdinal(a,b){for(let index=0;index<4;index++)if(a.ordinal[index]!==b.ordinal[index])return a.ordinal[index]>b.ordinal[index]?1:-1;return a.scheme!=="epoch"||b.scheme!=="epoch"||a.ordinal[4]===b.ordinal[4]?0:a.ordinal[4]>b.ordinal[4]?1:-1}import*as crypto from"node:crypto";var CUSTOM_UNSUPPORTED_CAPABILITY="custom_unsupported",EXTENSION_EVENTS_CAPABILITY="extension_events",EVAL_CELLS_CAPABILITY="eval_cells",AUTO_TITLE_SESSIONS_CAPABILITY="auto_title_sessions",CONTINUE_FROM_LEAF_CAPABILITY="continue_from_leaf",SESSION_HELD_CAPABILITY="session_held",RESUME_SESSION_CAPABILITY="resume_session",ATTENDED_CAPABILITY="attended",MEDIA_PLACEHOLDERS_CAPABILITY="media_placeholders",QUESTION_CAPABILITY="question",TOOL_BARRIER_CAPABILITY="tool_barrier",SESSION_RELOCATION_CAPABILITY="session_relocation",RETAIN_ON_DISCONNECT_CAPABILITY="retain_on_disconnect",DETACH_CONNECTION_CAPABILITY="detach_connection",INTERACTIVE_USER_CAPABILITY="interactive_user",TASK_PARENT_CAPABILITY="task_parent",SESSION_CONTEXT_CAPABILITY="session_context",SESSION_KIND_CAPABILITY="session_kind",SESSION_STATUS_CAPABILITY="session_status",AUTO_TITLE_PER_SESSION_CAPABILITY="auto_title_per_session",WARM_CAPABILITY="warm",DURABLE_SESSION_ID_CAPABILITY="durable_session_id",MOVED_PATH_GUARD_CAPABILITY="moved_path_guard",PROMPT_SURFACE_CAPABILITY="prompt_surface",BROWSER_ENGINE_CAPABILITY="browser_engine",RETRY_FALLBACK_PROFILE_CAPABILITY="retry_fallback_profile",RETRY_FALLBACK_COMMAND_CAPABILITY="retry_fallback_command",PROMPT_SURFACE_CHAT_CAPABILITY="prompt_surface_chat",RPC_CLIENT_CAPABILITIES_ENV="SENPI_RPC_CLIENT_CAPABILITIES";function parseClientCapabilities(value){return value?value.split(",").map(part=>part.trim()).filter(part=>part.length>0):[]}var DEFAULT_CUSTOM_EXTENSION_LABEL="custom UI component";function buildCustomUnsupportedRequest(capabilities,extensionName){if(!capabilities?.includes(CUSTOM_UNSUPPORTED_CAPABILITY))return;let name=extensionName.trim()||DEFAULT_CUSTOM_EXTENSION_LABEL;return{type:"extension_ui_request",id:crypto.randomUUID(),method:"custom_unsupported",extensionName:name}}var AUTH_KEY_VERIFY_CAPABILITY="auth_key_verify",QUEUED_MESSAGE_REVISION_CAPABILITY="queued_message_revision";import{createHash}from"node:crypto";import{existsSync}from"node:fs";import{readdir,readFile,realpath,stat}from"node:fs/promises";import{basename,dirname,join,relative,sep}from"node:path";import{fileURLToPath}from"node:url";var RUNTIME_IDENTITY_HANDOVER_CAPABILITY="runtime_identity_handover",RUNTIME_BUILD_ID=/^sha256:[0-9a-f]{64}$/,EXCLUDED_FILE=/\.(?:d\.[cm]?ts|map)$/,EXCLUDED_NAMES=new Set(["node_modules","runtime-manifest.json","runtime-snapshot.json"]),READ_CONCURRENCY=32;function parseRuntimeBuildId(value){return typeof value=="string"&&RUNTIME_BUILD_ID.test(value)?value:void 0}async function computeRuntimeBuildId(input){let source=input.source??loadedRuntimeSource(),plugins=await Promise.all(input.profile.extensions.map(path=>extensionDigest(path))),manifest={schema:1,flavour:source.flavour,platform:input.platform??process.platform,arch:input.arch??process.arch,engine:input.engine??engineBuildIdentity().text,runtime:await treeDigest(source.root),plugins:plugins.sort(),profile:{multi_session:input.profile.multi_session,session_runtime:input.profile.session_runtime}};return`sha256:${sha256(JSON.stringify(manifest))}`}function loadedRuntimeSource(){if(isBunBinary)return{flavour:"compiled",root:process.execPath};let moduleDir=dirname(fileURLToPath(import.meta.url)),packageRoot=nearestPackageRoot(moduleDir),[top,next]=relative(packageRoot,moduleDir).split(sep);return top==="dist"?{flavour:"packaged",root:join(packageRoot,next==="bundle"?join("dist","bundle"):"dist")}:{flavour:"dev",root:join(packageRoot,top??"")}}function nearestPackageRoot(start){for(let dir=start;;dir=dirname(dir)){if(existsSync(join(dir,"package.json")))return dir;if(dirname(dir)===dir)return start}}function extensionDigest(path){let name=basename(path);return name.startsWith(BUILTIN_PATH_PREFIX)?Promise.resolve(sha256(name)):treeDigest(path)}async function treeDigest(root){let files=[];(await stat(root)).isFile()?files.push(["",root]):await collect(await realpath(root),"",files,new Set);let digests=await mapLimited(files,READ_CONCURRENCY,async([path,file])=>[path,sha256(await readFile(file))]);return digests.sort(([a],[b])=>a<b?-1:a>b?1:0),sha256(JSON.stringify(digests))}async function collect(dir,prefix,files,seen){if(seen.has(dir))return;seen.add(dir);let entries=(await readdir(dir,{withFileTypes:!0})).sort((a,b)=>a.name<b.name?-1:a.name>b.name?1:0);for(let entry of entries){if(entry.name.startsWith(".")||EXCLUDED_NAMES.has(entry.name))continue;let path=join(dir,entry.name),name=prefix===""?entry.name:`${prefix}/${entry.name}`,kind=entry.isSymbolicLink()?await stat(path).catch(()=>{}):entry;kind!==void 0&&(kind.isDirectory()?await collect(await realpath(path),name,files,seen):kind.isFile()&&!EXCLUDED_FILE.test(entry.name)&&files.push([name,path]))}}async function mapLimited(items,limit,map){let results=new Array(items.length),next=0,worker=async()=>{for(let index=next++;index<items.length;index=next++)results[index]=await map(items[index])};return await Promise.all(Array.from({length:Math.min(limit,items.length)},worker)),results}function sha256(data){return createHash("sha256").update(data).digest("hex")}function parseHostProtocolInfo(data){if(!isRecord3(data)||typeof data.serverVersion!="string"||!Array.isArray(data.capabilities)||!data.capabilities.every(entry=>typeof entry=="string"))return;let ordinal=parseOrdinal(data.engineOrdinal),launchProfile=parseLaunchProfile(data.launch_profile),runtimeBuildId=parseRuntimeBuildId(data.runtimeBuildId);return{protocolVersion:typeof data.protocolVersion=="number"?data.protocolVersion:0,serverVersion:data.serverVersion,capabilities:data.capabilities,...(data.lifecycle==="ready"||data.lifecycle==="stopping")&&{lifecycle:data.lifecycle},...typeof data.instanceId=="string"&&{instanceId:data.instanceId},...typeof data.generation=="number"&&Number.isSafeInteger(data.generation)&&{generation:data.generation},...typeof data.engineVersion=="string"&&{engineVersion:data.engineVersion},...ordinal&&{engineOrdinal:ordinal},...launchProfile&&{launch_profile:launchProfile},...typeof data.memory_pressure=="boolean"&&{memory_pressure:data.memory_pressure},...runtimeBuildId!==void 0&&{runtimeBuildId},...typeof data.agentDir=="string"&&data.agentDir!==""&&{agentDir:data.agentDir},...isRecord3(data.handover)&&{handover:data.handover}}}function parseOrdinal(value){if(!(!Array.isArray(value)||value.length!==5||!value.every(part=>typeof part=="number")))return[value[0],value[1],value[2],value[3],value[4]]}function parseLaunchProfile(value){if(!isRecord3(value)||typeof value.profile_id!="string"||!isRecord3(value.core))return;let{extensions,multi_session,session_runtime}=value.core;if(!(!Array.isArray(extensions)||!extensions.every(entry=>typeof entry=="string"))&&typeof multi_session=="boolean"&&!(session_runtime!=="in-process"&&session_runtime!=="worker"))return{profile_id:value.profile_id,core:{extensions,multi_session,session_runtime}}}function isRecord3(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function describeHostHolder(holder){let engine=holder.engineVersion===null?"an unrecorded engine":`engine ${holder.engineVersion}`,profile=holder.launchProfileId===null?"":`, launch profile ${holder.launchProfileId}`,writer=holder.writerPid===null||holder.writerPid===holder.pid?"":`, started by pid ${holder.writerPid}`;return`pid ${holder.pid}, ${engine}${profile}${writer}`}var HOST_PROTOCOL_VERSION=1,GENERATION_HANDOFF_CAPABILITY="generation_handoff",REQUIRED_HOST_CAPABILITIES=["multi_session",EXTENSION_EVENTS_CAPABILITY,SESSION_CONTEXT_CAPABILITY,SESSION_KIND_CAPABILITY],HostEnsureRefusedError=class extends Error{constructor(socket,reason,host,detail,holder){let heldBy=holder?` (held by ${describeHostHolder(holder)})`:"";super(`RPC socket ${socket} refused: ${reason} - ${refusalDetail(reason,host)}${detail?`: ${detail}`:""}${heldBy}`),this.name="HostEnsureRefusedError",this.socket=socket,this.reason=reason,this.detail=detail,this.holder=holder}};function refusalDetail(reason,host){switch(reason){case"protocol":return`the running host speaks protocol version ${host?.protocolVersion??"unknown"}, this build speaks ${HOST_PROTOCOL_VERSION}`;case"capability":{let missing=REQUIRED_HOST_CAPABILITIES.filter(capability=>!host?.capabilities.includes(capability));return`the running host is missing ${JSON.stringify(missing)}; it owns the socket, so no second host is started`}case"foreign_writer":return"another process registered the host on this socket; it accepts connections but did not answer as a host, and this one may not signal it - stop that host explicitly (host stop --force), then ensure again";case"legacy_host":return"a host from before the per-socket daemon directory is still running; it is drained and replaced only while it holds no session, and no second host is started beside it";case"host_busy":return"its socket accepts connections but did not answer inside the probe budget: a live host under load, which is never ended to make room for a replacement";case"host_stopping":return"this generation is stopping; wait for its exit before launching a successor";case"endpoint_occupied":return"another process accepts connections on this socket but does not answer as a host, and no host registration names it; it is never removed while it listens, so quit the process holding it and ensure again";case"host_stalled":return"nothing reaches its socket, but its process is alive and its own loop-lag watchdog measured a recent stall: a stalled host is still serving its sessions, so it is neither stopped nor replaced";default:return assertNever(reason)}}function decideHostAction(client,host,policy){if(host===void 0)return{action:"start",reason:client.startedByUs?"restart_own_host":"no_host",upgradeable:!1};if(host.lifecycle==="stopping")return{action:"refuse",reason:"host_stopping",upgradeable:!1};if(host.protocolVersion!==client.protocolVersion)return{action:"refuse",reason:"protocol",upgradeable:!1};if(!client.requiredCapabilities.every(capability=>host.capabilities.includes(capability)))return policy==="fallback"?{action:"fallback",reason:"capability",upgradeable:!1}:{action:"refuse",reason:"capability",upgradeable:!1};let upgradeable=client.platform!=="win32"&&host.capabilities.includes(GENERATION_HANDOFF_CAPABILITY);if(policy==="fallback"&&host.engineVersion!==client.identity.text)return{action:"fallback",reason:"engine_mismatch",upgradeable};let warning=profileWarning(client,host);return client.platform==="win32"?{action:"reuse",reason:"win32_attach_only",upgradeable:!1,...warning&&{warning}}:upgradeable?policy==="upgrade"&&client.launchProfile&&host.launch_profile&&supersedes(client,host)?{action:"handoff",reason:sameRelease(client.identity.ordinal,host.engineOrdinal)?"profile":"newer_engine",upgradeable:!0}:{action:"reuse",reason:"compatible",upgradeable,...warning&&{warning}}:{action:"reuse",reason:"handoff_unsupported",upgradeable:!1,...warning&&{warning}}}function supersedes(client,host){if(host.engineOrdinal===void 0)return!1;let hostIdentity={text:host.engineVersion??"",ordinal:host.engineOrdinal,scheme:host.engineOrdinal[4]>0?"epoch":"nodef"};return compareEngineOrdinal(client.identity,hostIdentity)<=0?!1:covers(client.launchProfile,host.launch_profile)}function profileWarning(client,host){if(client.launchProfile===void 0||host.launch_profile===void 0)return"profile_mismatch_attached";if(client.launchProfile.profile_id===host.launch_profile.profile_id)return;let clientCoversHost=covers(client.launchProfile,host.launch_profile);if(!(clientCoversHost&&covers(host.launch_profile,client.launchProfile)))return clientCoversHost?"profile_mismatch_attached":"profile_narrower_attached"}function extensionRole(extension){let segments=extension.split(/[\\/]+/),pluginAt=segments.lastIndexOf("plugin");return pluginAt<0?extension:segments.slice(pluginAt).join("/")}function covers(candidate,running){if(candidate===void 0||running===void 0)return!1;let candidateRoles=new Set(candidate.core.extensions.map(extensionRole));return running.core.extensions.every(extension=>candidateRoles.has(extensionRole(extension)))}function sameRelease(candidate,running){return running!==void 0&&candidate.slice(0,4).every((part,index)=>part===running[index])}function assertNever(value){throw new Error(`unreachable host decision: ${JSON.stringify(value)}`)}import{createHash as createHash2,randomUUID as randomUUID2}from"node:crypto";import{resolve}from"node:path";var INSTANCE_ID=resolveInstanceId(process.env[HOST_INSTANCE_ID_ENV]);function resolveInstanceId(value){return value!==void 0&&value.trim()!==""?value:randomUUID2()}function hostInstanceId(){return INSTANCE_ID}var cachedProfile;function hostGeneration(env){let value=env[HOST_GENERATION_ENV];return value!==void 0&&/^\d+$/.test(value)?Number(value):0}function hostLaunchProfile(argv,cwd){let parsed=parseArgs([...argv],{grokNeoEnabled:!1}),core={extensions:[...new Set((parsed.extensions??[]).map(path=>resolve(cwd,path)))].sort(),multi_session:parsed.multiSession===!0,session_runtime:resolveSessionRuntime(parsed)},canonical=JSON.stringify({extensions:core.extensions,multi_session:core.multi_session,session_runtime:core.session_runtime});return{profile_id:createHash2("sha256").update(canonical).digest("hex"),core}}function socketHostLaunchProfile(hostArgs,cwd){return hostLaunchProfile(["--mode","rpc","--multi-session","--listen","unix://",...hostArgs],cwd)}function protocolIdentity(agentDir=resolve(getAgentDir())){cachedProfile??=hostLaunchProfile(process.argv.slice(2),process.cwd());let build=engineBuildIdentity();return{instanceId:INSTANCE_ID,generation:hostGeneration(process.env),engineVersion:build.text,engineOrdinal:build.ordinal,launch_profile:cachedProfile,agentDir}}function holdAttachment(socket){return socket.removeAllListeners("data"),socket.resume(),socket.on("error",()=>socket.destroy()),socket.unref(),{release:()=>socket.destroy()}}var DEFAULT_PROBE_TIMEOUT_MS=1e4;function probeHost(options){return probeProtocolInfo(options.socket,options.timeoutMs??DEFAULT_PROBE_TIMEOUT_MS,options)}async function probeProtocolInfo(socketPath,timeoutMs,options={}){let reply=await requestOnSocket(socketPath,{type:"get_protocol_info"},timeoutMs,options);return reply===void 0?void 0:parseHostProtocolInfo(reply)}async function observeProtocolInfo(socketPath,timeoutMs,options={}){let reply=await requestOnSocket(socketPath,{type:"get_protocol_info",[OBSERVE_REQUEST_FIELD]:!0},timeoutMs,options);return reply===void 0?void 0:parseHostProtocolInfo(reply)}async function holdProtocolInfo(socketPath,timeoutMs,options={}){let outcome=await connectAndAsk(socketPath,{id:PROBE_REQUEST_ID,type:"get_protocol_info"},timeoutMs,!0,options),info=outcome.answer===void 0?void 0:parseHostProtocolInfo(outcome.answer);if(outcome.kept===void 0)return;let hold=holdAttachment(outcome.kept);if(info!==void 0)return{info,hold};hold.release()}async function probeSocketReachable(socketPath,timeoutMs,options={}){return(await connectAndAsk(socketPath,{id:PROBE_REQUEST_ID,type:"get_protocol_info"},timeoutMs,!1,options)).connected}async function probeSessionCount(socketPath,timeoutMs,options={}){return sessionCountOf(await requestOnSocket(socketPath,{type:"list_sessions",include_workers:!0},timeoutMs,options))}async function holdSessionCount(socketPath,timeoutMs,options={}){let outcome=await connectAndAsk(socketPath,{id:PROBE_REQUEST_ID,type:"list_sessions",include_workers:!0},timeoutMs,!0,options),kept=outcome.kept;if(kept===void 0)return;let sessions=sessionCountOf(outcome.answer);if(sessions===void 0){kept.destroy();return}let asked=0;return{sessions,recount:recountTimeoutMs=>askAgain(kept,`${PROBE_REQUEST_ID}-recount-${++asked}`,recountTimeoutMs),close:()=>kept.destroy()}}function askAgain(socket,id,timeoutMs){return new Promise(resolveCount=>{let buffer="",finish=count=>{clearTimeout(timeout),socket.off("data",onData),socket.off("close",onClose),resolveCount(count)},onClose=()=>finish(void 0),onData=chunk=>{buffer+=chunk.toString("utf8");for(let newline=buffer.indexOf(`
|
|
2
|
+
import{BUILTIN_PATH_PREFIX}from"./chunk-QMRJYMNH.js";import{listHostEndpoints}from"./chunk-PT6JJUN2.js";import{parseArgs,resolveSessionRuntime}from"./chunk-WD6WBYC5.js";import{PROBE_REQUEST_ID,connectAndAsk,isRecord as isRecord2,readAnswer,requestOnSocket}from"./chunk-KNVNKDER.js";import{acquireOwnershipSafeLock,claimOwnerIsLive,hostChildAlive,isGenerationId,logUnknownHostIdentity,provenOwner,readDrainWatch,readGenerationRegistration,readHostRegistration,readSessionPathClaims,releaseGeneration,resolveHostPolicy,writeDrainRequest,writeStopIntent}from"./chunk-BZ7726QO.js";import{HOST_DAEMON_LAYOUT,canonicalEndpointPath,createHostDaemonPaths,generationPaths,hostDaemonDirectoryPaths,isRecord,parseJson,readFileOrUndefined,sameEndpoint,writeStateFile}from"./chunk-4WZRVZNX.js";import{HOST_GENERATION_ENV,HOST_INSTANCE_ID_ENV,OBSERVE_REQUEST_FIELD,gcRpcPublicKeys}from"./chunk-SBGIXMX3.js";import{readSocketSecret,resolveSocketTransportAddress,socketSecretPath}from"./chunk-ZGAB7WQA.js";import{APP_NAME,VERSION,getAgentDir,isBunBinary}from"./chunk-7YO7VQZW.js";import{ProcessIdentityUnreadableError,parseDaemonPidFile,processIsLive,processMatchesPidFile,processStartTimeMs,readProcessStartTime}from"./chunk-O5RYI3IW.js";var CALVER=/^(\d+)\.(\d+)\.(\d+)(?:-(\d+))?/;function engineBuildIdentityFrom(build){let match=CALVER.exec(build.version),epoch=Number.isSafeInteger(build.epoch)&&build.epoch!==void 0&&build.epoch>0?build.epoch:0,sha7=build.sha7??"";return{text:epoch===0?build.version:`${build.version}+${epoch}${sha7===""?"":`.${sha7}`}`,ordinal:[match?Number(match[1]):0,match?Number(match[2]):0,match?Number(match[3]):0,match?.[4]?Number(match[4]):0,epoch],scheme:epoch===0?"nodef":"epoch"}}var BUILT=engineBuildIdentityFrom({version:VERSION,epoch:typeof SENPI_BUILD_EPOCH=="number"?SENPI_BUILD_EPOCH:0,sha7:typeof SENPI_BUILD_SHA7=="string"?SENPI_BUILD_SHA7:""});function engineBuildIdentity(){return BUILT}function compareEngineOrdinal(a,b){for(let index=0;index<4;index++)if(a.ordinal[index]!==b.ordinal[index])return a.ordinal[index]>b.ordinal[index]?1:-1;return a.scheme!=="epoch"||b.scheme!=="epoch"||a.ordinal[4]===b.ordinal[4]?0:a.ordinal[4]>b.ordinal[4]?1:-1}import*as crypto from"node:crypto";var CUSTOM_UNSUPPORTED_CAPABILITY="custom_unsupported",EXTENSION_EVENTS_CAPABILITY="extension_events",EVAL_CELLS_CAPABILITY="eval_cells",AUTO_TITLE_SESSIONS_CAPABILITY="auto_title_sessions",CONTINUE_FROM_LEAF_CAPABILITY="continue_from_leaf",SESSION_HELD_CAPABILITY="session_held",RESUME_SESSION_CAPABILITY="resume_session",ATTENDED_CAPABILITY="attended",MEDIA_PLACEHOLDERS_CAPABILITY="media_placeholders",QUESTION_CAPABILITY="question",TOOL_BARRIER_CAPABILITY="tool_barrier",SESSION_RELOCATION_CAPABILITY="session_relocation",RETAIN_ON_DISCONNECT_CAPABILITY="retain_on_disconnect",DETACH_CONNECTION_CAPABILITY="detach_connection",INTERACTIVE_USER_CAPABILITY="interactive_user",OBSERVE_READS_CAPABILITY="observe_reads",ENTRIES_TAIL_CAPABILITY="entries_tail",TUI_OBSERVER_CAPABILITY="tui_observer",TASK_PARENT_CAPABILITY="task_parent",SESSION_CONTEXT_CAPABILITY="session_context",SESSION_KIND_CAPABILITY="session_kind",SESSION_STATUS_CAPABILITY="session_status",AUTO_TITLE_PER_SESSION_CAPABILITY="auto_title_per_session",WARM_CAPABILITY="warm",DURABLE_SESSION_ID_CAPABILITY="durable_session_id",MOVED_PATH_GUARD_CAPABILITY="moved_path_guard",PROMPT_SURFACE_CAPABILITY="prompt_surface",BROWSER_ENGINE_CAPABILITY="browser_engine",RETRY_FALLBACK_PROFILE_CAPABILITY="retry_fallback_profile",RETRY_FALLBACK_COMMAND_CAPABILITY="retry_fallback_command",PROMPT_SURFACE_CHAT_CAPABILITY="prompt_surface_chat",RPC_CLIENT_CAPABILITIES_ENV="SENPI_RPC_CLIENT_CAPABILITIES";function parseClientCapabilities(value){return value?value.split(",").map(part=>part.trim()).filter(part=>part.length>0):[]}var DEFAULT_CUSTOM_EXTENSION_LABEL="custom UI component";function buildCustomUnsupportedRequest(capabilities,extensionName){if(!capabilities?.includes(CUSTOM_UNSUPPORTED_CAPABILITY))return;let name=extensionName.trim()||DEFAULT_CUSTOM_EXTENSION_LABEL;return{type:"extension_ui_request",id:crypto.randomUUID(),method:"custom_unsupported",extensionName:name}}var AUTH_KEY_VERIFY_CAPABILITY="auth_key_verify",QUEUED_MESSAGE_REVISION_CAPABILITY="queued_message_revision";import{createHash}from"node:crypto";import{existsSync}from"node:fs";import{readdir,readFile,realpath,stat}from"node:fs/promises";import{basename,dirname,join,relative,sep}from"node:path";import{fileURLToPath}from"node:url";var RUNTIME_IDENTITY_HANDOVER_CAPABILITY="runtime_identity_handover",RUNTIME_BUILD_ID=/^sha256:[0-9a-f]{64}$/,EXCLUDED_FILE=/\.(?:d\.[cm]?ts|map)$/,EXCLUDED_NAMES=new Set(["node_modules","runtime-manifest.json","runtime-snapshot.json"]),READ_CONCURRENCY=32;function parseRuntimeBuildId(value){return typeof value=="string"&&RUNTIME_BUILD_ID.test(value)?value:void 0}async function computeRuntimeBuildId(input){let source=input.source??loadedRuntimeSource(),plugins=await Promise.all(input.profile.extensions.map(path=>extensionDigest(path))),manifest={schema:1,flavour:source.flavour,platform:input.platform??process.platform,arch:input.arch??process.arch,engine:input.engine??engineBuildIdentity().text,runtime:await treeDigest(source.root),plugins:plugins.sort(),profile:{multi_session:input.profile.multi_session,session_runtime:input.profile.session_runtime}};return`sha256:${sha256(JSON.stringify(manifest))}`}function loadedRuntimeSource(){if(isBunBinary)return{flavour:"compiled",root:process.execPath};let moduleDir=dirname(fileURLToPath(import.meta.url)),packageRoot=nearestPackageRoot(moduleDir),[top,next]=relative(packageRoot,moduleDir).split(sep);return top==="dist"?{flavour:"packaged",root:join(packageRoot,next==="bundle"?join("dist","bundle"):"dist")}:{flavour:"dev",root:join(packageRoot,top??"")}}function nearestPackageRoot(start){for(let dir=start;;dir=dirname(dir)){if(existsSync(join(dir,"package.json")))return dir;if(dirname(dir)===dir)return start}}function extensionDigest(path){let name=basename(path);return name.startsWith(BUILTIN_PATH_PREFIX)?Promise.resolve(sha256(name)):treeDigest(path)}async function treeDigest(root){let files=[];(await stat(root)).isFile()?files.push(["",root]):await collect(await realpath(root),"",files,new Set);let digests=await mapLimited(files,READ_CONCURRENCY,async([path,file])=>[path,sha256(await readFile(file))]);return digests.sort(([a],[b])=>a<b?-1:a>b?1:0),sha256(JSON.stringify(digests))}async function collect(dir,prefix,files,seen){if(seen.has(dir))return;seen.add(dir);let entries=(await readdir(dir,{withFileTypes:!0})).sort((a,b)=>a.name<b.name?-1:a.name>b.name?1:0);for(let entry of entries){if(entry.name.startsWith(".")||EXCLUDED_NAMES.has(entry.name))continue;let path=join(dir,entry.name),name=prefix===""?entry.name:`${prefix}/${entry.name}`,kind=entry.isSymbolicLink()?await stat(path).catch(()=>{}):entry;kind!==void 0&&(kind.isDirectory()?await collect(await realpath(path),name,files,seen):kind.isFile()&&!EXCLUDED_FILE.test(entry.name)&&files.push([name,path]))}}async function mapLimited(items,limit,map){let results=new Array(items.length),next=0,worker=async()=>{for(let index=next++;index<items.length;index=next++)results[index]=await map(items[index])};return await Promise.all(Array.from({length:Math.min(limit,items.length)},worker)),results}function sha256(data){return createHash("sha256").update(data).digest("hex")}function parseHostProtocolInfo(data){if(!isRecord3(data)||typeof data.serverVersion!="string"||!Array.isArray(data.capabilities)||!data.capabilities.every(entry=>typeof entry=="string"))return;let ordinal=parseOrdinal(data.engineOrdinal),launchProfile=parseLaunchProfile(data.launch_profile),runtimeBuildId=parseRuntimeBuildId(data.runtimeBuildId);return{protocolVersion:typeof data.protocolVersion=="number"?data.protocolVersion:0,serverVersion:data.serverVersion,capabilities:data.capabilities,...(data.lifecycle==="ready"||data.lifecycle==="stopping")&&{lifecycle:data.lifecycle},...typeof data.instanceId=="string"&&{instanceId:data.instanceId},...typeof data.generation=="number"&&Number.isSafeInteger(data.generation)&&{generation:data.generation},...typeof data.engineVersion=="string"&&{engineVersion:data.engineVersion},...ordinal&&{engineOrdinal:ordinal},...launchProfile&&{launch_profile:launchProfile},...typeof data.memory_pressure=="boolean"&&{memory_pressure:data.memory_pressure},...runtimeBuildId!==void 0&&{runtimeBuildId},...typeof data.agentDir=="string"&&data.agentDir!==""&&{agentDir:data.agentDir},...isRecord3(data.handover)&&{handover:data.handover}}}function parseOrdinal(value){if(!(!Array.isArray(value)||value.length!==5||!value.every(part=>typeof part=="number")))return[value[0],value[1],value[2],value[3],value[4]]}function parseLaunchProfile(value){if(!isRecord3(value)||typeof value.profile_id!="string"||!isRecord3(value.core))return;let{extensions,multi_session,session_runtime}=value.core;if(!(!Array.isArray(extensions)||!extensions.every(entry=>typeof entry=="string"))&&typeof multi_session=="boolean"&&!(session_runtime!=="in-process"&&session_runtime!=="worker"))return{profile_id:value.profile_id,core:{extensions,multi_session,session_runtime}}}function isRecord3(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function describeHostHolder(holder){let engine=holder.engineVersion===null?"an unrecorded engine":`engine ${holder.engineVersion}`,profile=holder.launchProfileId===null?"":`, launch profile ${holder.launchProfileId}`,writer=holder.writerPid===null||holder.writerPid===holder.pid?"":`, started by pid ${holder.writerPid}`;return`pid ${holder.pid}, ${engine}${profile}${writer}`}var HOST_PROTOCOL_VERSION=1,GENERATION_HANDOFF_CAPABILITY="generation_handoff",REQUIRED_HOST_CAPABILITIES=["multi_session",EXTENSION_EVENTS_CAPABILITY,SESSION_CONTEXT_CAPABILITY,SESSION_KIND_CAPABILITY],HostEnsureRefusedError=class extends Error{constructor(socket,reason,host,detail,holder){let heldBy=holder?` (held by ${describeHostHolder(holder)})`:"";super(`RPC socket ${socket} refused: ${reason} - ${refusalDetail(reason,host)}${detail?`: ${detail}`:""}${heldBy}`),this.name="HostEnsureRefusedError",this.socket=socket,this.reason=reason,this.detail=detail,this.holder=holder}};function refusalDetail(reason,host){switch(reason){case"protocol":return`the running host speaks protocol version ${host?.protocolVersion??"unknown"}, this build speaks ${HOST_PROTOCOL_VERSION}`;case"capability":{let missing=REQUIRED_HOST_CAPABILITIES.filter(capability=>!host?.capabilities.includes(capability));return`the running host is missing ${JSON.stringify(missing)}; it owns the socket, so no second host is started`}case"foreign_writer":return"another process registered the host on this socket; it accepts connections but did not answer as a host, and this one may not signal it - stop that host explicitly (host stop --force), then ensure again";case"legacy_host":return"a host from before the per-socket daemon directory is still running; it is drained and replaced only while it holds no session, and no second host is started beside it";case"host_busy":return"its socket accepts connections but did not answer inside the probe budget: a live host under load, which is never ended to make room for a replacement";case"host_stopping":return"this generation is stopping; wait for its exit before launching a successor";case"endpoint_occupied":return"another process accepts connections on this socket but does not answer as a host, and no host registration names it; it is never removed while it listens, so quit the process holding it and ensure again";case"host_stalled":return"nothing reaches its socket, but its process is alive and its own loop-lag watchdog measured a recent stall: a stalled host is still serving its sessions, so it is neither stopped nor replaced";default:return assertNever(reason)}}function decideHostAction(client,host,policy){if(host===void 0)return{action:"start",reason:client.startedByUs?"restart_own_host":"no_host",upgradeable:!1};if(host.lifecycle==="stopping")return{action:"refuse",reason:"host_stopping",upgradeable:!1};if(host.protocolVersion!==client.protocolVersion)return{action:"refuse",reason:"protocol",upgradeable:!1};if(!client.requiredCapabilities.every(capability=>host.capabilities.includes(capability)))return policy==="fallback"?{action:"fallback",reason:"capability",upgradeable:!1}:{action:"refuse",reason:"capability",upgradeable:!1};let upgradeable=client.platform!=="win32"&&host.capabilities.includes(GENERATION_HANDOFF_CAPABILITY);if(policy==="fallback"&&host.engineVersion!==client.identity.text)return{action:"fallback",reason:"engine_mismatch",upgradeable};let warning=profileWarning(client,host);return client.platform==="win32"?{action:"reuse",reason:"win32_attach_only",upgradeable:!1,...warning&&{warning}}:upgradeable?policy==="upgrade"&&client.launchProfile&&host.launch_profile&&supersedes(client,host)?{action:"handoff",reason:sameRelease(client.identity.ordinal,host.engineOrdinal)?"profile":"newer_engine",upgradeable:!0}:{action:"reuse",reason:"compatible",upgradeable,...warning&&{warning}}:{action:"reuse",reason:"handoff_unsupported",upgradeable:!1,...warning&&{warning}}}function supersedes(client,host){if(host.engineOrdinal===void 0)return!1;let hostIdentity={text:host.engineVersion??"",ordinal:host.engineOrdinal,scheme:host.engineOrdinal[4]>0?"epoch":"nodef"};return compareEngineOrdinal(client.identity,hostIdentity)<=0?!1:covers(client.launchProfile,host.launch_profile)}function profileWarning(client,host){if(client.launchProfile===void 0||host.launch_profile===void 0)return"profile_mismatch_attached";if(client.launchProfile.profile_id===host.launch_profile.profile_id)return;let clientCoversHost=covers(client.launchProfile,host.launch_profile);if(!(clientCoversHost&&covers(host.launch_profile,client.launchProfile)))return clientCoversHost?"profile_mismatch_attached":"profile_narrower_attached"}function extensionRole(extension){let segments=extension.split(/[\\/]+/),pluginAt=segments.lastIndexOf("plugin");return pluginAt<0?extension:segments.slice(pluginAt).join("/")}function covers(candidate,running){if(candidate===void 0||running===void 0)return!1;let candidateRoles=new Set(candidate.core.extensions.map(extensionRole));return running.core.extensions.every(extension=>candidateRoles.has(extensionRole(extension)))}function sameRelease(candidate,running){return running!==void 0&&candidate.slice(0,4).every((part,index)=>part===running[index])}function assertNever(value){throw new Error(`unreachable host decision: ${JSON.stringify(value)}`)}import{createHash as createHash2,randomUUID as randomUUID2}from"node:crypto";import{resolve}from"node:path";var INSTANCE_ID=resolveInstanceId(process.env[HOST_INSTANCE_ID_ENV]);function resolveInstanceId(value){return value!==void 0&&value.trim()!==""?value:randomUUID2()}function hostInstanceId(){return INSTANCE_ID}var cachedProfile;function hostGeneration(env){let value=env[HOST_GENERATION_ENV];return value!==void 0&&/^\d+$/.test(value)?Number(value):0}function hostLaunchProfile(argv,cwd){let parsed=parseArgs([...argv],{grokNeoEnabled:!1}),core={extensions:[...new Set((parsed.extensions??[]).map(path=>resolve(cwd,path)))].sort(),multi_session:parsed.multiSession===!0,session_runtime:resolveSessionRuntime(parsed)},canonical=JSON.stringify({extensions:core.extensions,multi_session:core.multi_session,session_runtime:core.session_runtime});return{profile_id:createHash2("sha256").update(canonical).digest("hex"),core}}function socketHostLaunchProfile(hostArgs,cwd){return hostLaunchProfile(["--mode","rpc","--multi-session","--listen","unix://",...hostArgs],cwd)}function protocolIdentity(agentDir=resolve(getAgentDir())){cachedProfile??=hostLaunchProfile(process.argv.slice(2),process.cwd());let build=engineBuildIdentity();return{instanceId:INSTANCE_ID,generation:hostGeneration(process.env),engineVersion:build.text,engineOrdinal:build.ordinal,launch_profile:cachedProfile,agentDir}}function holdAttachment(socket){return socket.removeAllListeners("data"),socket.resume(),socket.on("error",()=>socket.destroy()),socket.unref(),{release:()=>socket.destroy()}}var DEFAULT_PROBE_TIMEOUT_MS=1e4;function probeHost(options){return probeProtocolInfo(options.socket,options.timeoutMs??DEFAULT_PROBE_TIMEOUT_MS,options)}async function probeProtocolInfo(socketPath,timeoutMs,options={}){let reply=await requestOnSocket(socketPath,{type:"get_protocol_info"},timeoutMs,options);return reply===void 0?void 0:parseHostProtocolInfo(reply)}async function observeProtocolInfo(socketPath,timeoutMs,options={}){let reply=await requestOnSocket(socketPath,{type:"get_protocol_info",[OBSERVE_REQUEST_FIELD]:!0},timeoutMs,options);return reply===void 0?void 0:parseHostProtocolInfo(reply)}async function holdProtocolInfo(socketPath,timeoutMs,options={}){let outcome=await connectAndAsk(socketPath,{id:PROBE_REQUEST_ID,type:"get_protocol_info"},timeoutMs,!0,options),info=outcome.answer===void 0?void 0:parseHostProtocolInfo(outcome.answer);if(outcome.kept===void 0)return;let hold=holdAttachment(outcome.kept);if(info!==void 0)return{info,hold};hold.release()}async function probeSocketReachable(socketPath,timeoutMs,options={}){return(await connectAndAsk(socketPath,{id:PROBE_REQUEST_ID,type:"get_protocol_info"},timeoutMs,!1,options)).connected}async function probeSessionCount(socketPath,timeoutMs,options={}){return sessionCountOf(await requestOnSocket(socketPath,{type:"list_sessions",include_workers:!0},timeoutMs,options))}async function holdSessionCount(socketPath,timeoutMs,options={}){let outcome=await connectAndAsk(socketPath,{id:PROBE_REQUEST_ID,type:"list_sessions",include_workers:!0},timeoutMs,!0,options),kept=outcome.kept;if(kept===void 0)return;let sessions=sessionCountOf(outcome.answer);if(sessions===void 0){kept.destroy();return}let asked=0;return{sessions,recount:recountTimeoutMs=>askAgain(kept,`${PROBE_REQUEST_ID}-recount-${++asked}`,recountTimeoutMs),close:()=>kept.destroy()}}function askAgain(socket,id,timeoutMs){return new Promise(resolveCount=>{let buffer="",finish=count=>{clearTimeout(timeout),socket.off("data",onData),socket.off("close",onClose),resolveCount(count)},onClose=()=>finish(void 0),onData=chunk=>{buffer+=chunk.toString("utf8");for(let newline=buffer.indexOf(`
|
|
3
3
|
`);newline!==-1;newline=buffer.indexOf(`
|
|
4
4
|
`)){let answer=readAnswer(buffer.slice(0,newline),id);if(buffer=buffer.slice(newline+1),answer!==void 0){finish(sessionCountOf(answer));return}}},timeout=setTimeout(()=>finish(void 0),timeoutMs);if(socket.destroyed){finish(void 0);return}socket.on("data",onData),socket.once("close",onClose),socket.write(`${JSON.stringify({id,type:"list_sessions",include_workers:!0})}
|
|
5
5
|
`)})}function sessionCountOf(reply){return isRecord2(reply)&&Array.isArray(reply.sessions)?reply.sessions.length:void 0}import{createHash as createHash3}from"node:crypto";import{mkdir,writeFile}from"node:fs/promises";import{tmpdir}from"node:os";import{dirname as dirname2,join as join2}from"node:path";var LOCK_BUSY_WAIT_MS=100;function hostEnsureLockTarget(socket){return join2(tmpdir(),"senpi-rpc-host-locks",createSocketLockName(socket))}async function acquireHostEnsureLock(socket,waitMs){let lockTarget=hostEnsureLockTarget(socket);return await mkdir(dirname2(lockTarget),{recursive:!0}),await writeFile(lockTarget,"",{flag:"a",mode:384}),acquireOwnershipSafeLock(`${lockTarget}.lock`,hostEnsureLockOptions(waitMs))}function hostEnsureLockOptions(waitMs){return{retries:{retries:Math.ceil(waitMs/LOCK_BUSY_WAIT_MS),minTimeout:20,maxTimeout:LOCK_BUSY_WAIT_MS}}}function createSocketLockName(socket){return createHash3("sha256").update(socketLockAddress(socket),"utf8").digest("hex").slice(0,32)}function socketLockAddress(socket){return process.platform==="win32"||socket.startsWith("\0")?resolveSocketTransportAddress(socket,process.platform):canonicalEndpointPath(socket)}import{randomUUID as randomUUID3}from"node:crypto";import{access,link,readdir as readdir2,rm}from"node:fs/promises";async function electPointer(paths,options={}){let text=await readFileOrUndefined(paths.pointerFile).catch(()=>{});if(text!==void 0){let instanceId=parseJson(text)?.instance_id;return typeof instanceId=="string"?{state:"current",instanceId,candidates:[]}:{state:"missing",instanceId:null,candidates:[]}}let candidates=await provenLiveGenerations(paths),ids=candidates.map(candidate=>candidate.instanceId),[only]=candidates;return only===void 0||candidates.length>1||options.write===!1?{state:"missing",instanceId:null,candidates:ids}:await linkPointer(paths,only)?{state:"elected",instanceId:only.instanceId,candidates:ids}:electPointer(paths,{write:!1})}async function provenLiveGenerations(paths){let found=[];for(let instanceId of(await readdir2(paths.generationsDir).catch(()=>[])).sort()){let generation=generationPaths(paths,instanceId);if(await exists(generation.stopIntentFile)||await exists(generation.drainRequestFile))continue;let text=await readFileOrUndefined(generation.pidFile).catch(()=>{}),record=text===void 0?void 0:parseDaemonPidFile(text),parsed=parseJson(text);if(record===void 0||record.processStartTime===null||parsed?.instance_id!==instanceId||typeof parsed.socket!="string"||!sameEndpoint(parsed.socket,paths.socket))continue;let identity={pid:record.pid,processStartTime:record.processStartTime};await processMatchesPidFile(identity,readProcessStartTime).catch(()=>!1)&&found.push({instanceId,writer:parsed.writer})}return found}async function linkPointer(paths,candidate){let staged=`${paths.pointerFile}.elect-${process.pid}-${randomUUID3()}.tmp`;try{return await writeStateFile(staged,{layout:HOST_DAEMON_LAYOUT,instance_id:candidate.instanceId,generation_dir:generationPaths(paths,candidate.instanceId).relativeDir,...isRecord(candidate.writer)&&{writer:candidate.writer}}),await link(staged,paths.pointerFile),!0}catch{return!1}finally{await rm(staged,{force:!0}).catch(()=>{})}}async function exists(path){return access(path).then(()=>!0,()=>!1)}import{dirname as dirname3,join as join3}from"node:path";var LEGACY_PROBE_TIMEOUT_MS=1e4,DRAIN_POLL_MS=50;async function retireIdleLegacyHost(paths,probe,drainTimeoutMs=LEGACY_PROBE_TIMEOUT_MS){let judged=await judgeLegacyHost(paths,probe);if(judged.verdict==="absent")return;if(judged.verdict==="held")return judged.detail;let{record,socket}=judged.host;if(!await drainAndWait(record,probe,drainTimeoutMs))return`pid ${record.pid} (${socket}) was asked to drain and is still running after ${drainTimeoutMs}ms; retry once it exits`}async function readLegacyHost(paths){let text=await readFileOrUndefined(paths.legacyPidFile),record=text===void 0?void 0:parseDaemonPidFile(text);if(record===void 0)return;let stamped=parseJson(text)?.socket;return{record,socket:typeof stamped=="string"?stamped:join3(dirname3(paths.flatDir),"rpc","rpc.sock")}}async function provenLegacyOwner(paths,socket){let legacy=await readLegacyHost(paths),startTime=legacy?.record.processStartTime;if(!legacy||startTime===null||startTime===void 0||!sameEndpoint(legacy.socket,socket))return;let identity={pid:legacy.record.pid,processStartTime:startTime};return await processMatchesPidFile(identity,readProcessStartTime).catch(error=>(error instanceof ProcessIdentityUnreadableError&&logUnknownHostIdentity("legacy_host.pid",identity.pid),!1))?identity:void 0}async function judgeLegacyHost(paths,probe,platform=process.platform){let host=await readLegacyHost(paths);if(host===void 0)return{verdict:"absent"};let{pid}=host.record,identity=await processMatchesPidFile(host.record,probe).then(owns=>owns?"proven":"gone",error=>{if(error instanceof ProcessIdentityUnreadableError)return"unreadable";throw error});if(identity==="gone")return{verdict:"absent"};let where=`pid ${pid} (${host.socket})`;if(identity==="unreadable")return logUnknownHostIdentity("legacy_host.pid",pid),{verdict:"held",detail:`${where} cannot be proven to be the process its record names; stop it by hand`};if(platform==="win32")return{verdict:"held",detail:`${where} cannot be drained on win32; it exits once idle, then retry`};let protocol=await probeProtocolInfo(host.socket,LEGACY_PROBE_TIMEOUT_MS);if(!protocol?.capabilities.includes(GENERATION_HANDOFF_CAPABILITY))return{verdict:"held",detail:`${where} ${protocol?"cannot drain":"does not answer"}; it is never signalled - stop it by hand, then retry`};let sessions=await probeSessionCount(host.socket,LEGACY_PROBE_TIMEOUT_MS);return sessions===0?{verdict:"idle",host}:{verdict:"held",detail:busyLegacyHostDetail(pid,host.socket,sessions)}}function busyLegacyHostDetail(pid,socket,sessions){return`pid ${pid} (${socket}) holds ${describeSessions(sessions)}; run \`${APP_NAME} host stop --drain --socket ${socket}\` to let it finish that work and exit, then retry`}function describeSessions(sessions){return sessions===void 0?"an unknown number of sessions":`${sessions} open session${sessions===1?"":"s"}`}async function drainAndWait(record,probe,timeoutMs){try{process.kill(record.pid,"SIGUSR1")}catch(error){if(!(error instanceof Error&&"code"in error&&error.code==="ESRCH"))throw error}let stillRunning=()=>processMatchesPidFile(record,probe,processIsLive,{attempts:1}).catch(error=>{if(error instanceof ProcessIdentityUnreadableError)return!0;throw error}),deadline=Date.now()+timeoutMs;for(;await stillRunning();){if(Date.now()>deadline)return!1;await new Promise(resolve2=>setTimeout(resolve2,DRAIN_POLL_MS))}return!0}var EXIT_POLL_MS=100;async function drainHost(paths,options){let named=options.instanceId;if(named!==void 0&&!isGenerationId(named))return{action:"refuse",reason:"unknown_owner"};let registered=named===void 0?await readHostRegistration(paths):await readGenerationRegistration(paths,named),owner=await provenOwner(registered,options.socket);if(owner!==void 0){let generation=generationPaths(paths,owner.instanceId);if((await readDrainWatch(generation.drainWatchFile))?.pid===owner.pid)return await writeDrainRequest(generation.drainRequestFile,{sender:{pid:process.pid,kind:"stop"},reason:"operator_drain"}).catch(cause=>{if(cause.code!=="ENOENT")throw cause}),drained({...owner},options.waitMs)}if(named!==void 0&&owner===void 0)return{action:"refuse",reason:"unknown_owner"};let pid=owner?.pid??(await provenLegacyOwner(paths,options.socket))?.pid;if(pid===void 0)return{action:"refuse",reason:"unknown_owner"};let host=await probeProtocolInfo(options.socket,options.timeoutMs??1e4),answersAsTarget=named===void 0||host?.instanceId===named;return!host?.capabilities.includes(GENERATION_HANDOFF_CAPABILITY)||!answersAsTarget||process.platform==="win32"?{action:"refuse",reason:"drain_unsupported"}:(signalDrain(pid),drained(owner??{pid,processStartTime:void 0},options.waitMs))}async function drained(owner,waitMs){let base={action:"drained",pid:owner.pid,...owner.instanceId&&{instanceId:owner.instanceId}};return waitMs===void 0?base:{...base,exited:await waitForExit(owner,waitMs)}}async function waitForExit(owner,waitMs){let deadline=Date.now()+waitMs;for(;;){if(await exitedNow(owner))return!0;if(Date.now()>=deadline)return!1;await new Promise(resolve2=>setTimeout(resolve2,EXIT_POLL_MS))}}async function exitedNow(owner){if(!processIsLive(owner.pid))return!0;if(owner.processStartTime===void 0)return!1;let identity={pid:owner.pid,processStartTime:owner.processStartTime};return processMatchesPidFile(identity,readProcessStartTime).then(same=>!same,error=>{if(error instanceof ProcessIdentityUnreadableError)return!1;throw error})}function signalDrain(pid){try{process.kill(pid,"SIGUSR1")}catch(error){if(error instanceof Error&&"code"in error&&error.code==="ESRCH")return;throw error}}import{stat as stat2}from"node:fs/promises";function processStartTimeIsUnreadable(){return process.platform==="win32"}var STOP_START_TIME_BUDGET_MS=1e4;function readLiveStartTime(pid){return readProcessStartTime(pid,process.platform,STOP_START_TIME_BUDGET_MS)}async function startedBeforeRegistration(pid,registrationFile){let live=await readLiveStartTime(pid).catch(()=>{}),startedMs=live===void 0?void 0:processStartTimeMs(live);if(startedMs===void 0)return!1;let written=await stat2(registrationFile).catch(()=>{});return written!==void 0&&startedMs<=written.mtimeMs}function parseHostStopGeneration(text){let value=parseJson(text);if(!(!value||typeof value.instanceId!="string"||value.instanceId.length===0||typeof value.generation!="number"||!Number.isSafeInteger(value.generation)||value.generation<0||typeof value.pid!="number"||!Number.isSafeInteger(value.pid)||value.pid<=0||!(value.processStartTime===null||typeof value.processStartTime=="string"&&value.processStartTime.length>0)))return{instanceId:value.instanceId,generation:value.generation,pid:value.pid,processStartTime:value.processStartTime}}function compareStopGeneration(registered,expected){if(registered?.instanceId!==expected.instanceId||registered.generation!==expected.generation||registered.record.pid!==expected.pid)return"stale";let recorded=registered.record.processStartTime;return recorded!==null&&expected.processStartTime!==null?recorded===expected.processStartTime?"proven":"stale":recorded===null&&expected.processStartTime===null&&processStartTimeIsUnreadable()?"bound_without_start_time":"unprovable"}async function stopHost(options){if(options.expectedGeneration!==void 0&&options.drain===!0)throw new TypeError("stopHost: expectedGeneration binds a hard stop and cannot be combined with drain");if(options.expectedGeneration===void 0)return stopHostLocked(options);let release=await acquireHostEnsureLock(options.socket,3e4);try{return await stopHostLocked(options)}finally{await release()}}async function stopHostLocked(options){let paths=createHostDaemonPaths({socket:options.socket,...options.agentDir?{agentDir:options.agentDir}:{}});await electPointer(paths);let expected=options.expectedGeneration;if(expected!==void 0){let refusal=generationRefusal(compareStopGeneration(await readHostRegistration(paths),expected));if(refusal!==void 0)return refusal}if(options.drain===!0)return drainHost(paths,{socket:options.socket,...options.instanceId!==void 0&&{instanceId:options.instanceId},...options.waitMs!==void 0&&{waitMs:options.waitMs},...options.timeoutMs!==void 0&&{timeoutMs:options.timeoutMs}});let owner=expected===void 0?await provenOwner(await readHostRegistration(paths),options.socket):void 0;if(expected===void 0&&!owner)return{action:"refuse",reason:"unknown_owner"};let host=await probeProtocolInfo(options.socket,options.timeoutMs??1e4),sessions=await probeSessionCount(options.socket,options.timeoutMs??1e4);if(options.force!==!0&&host!==void 0&&sessions!==void 0&&sessions>0)return{action:"refuse",reason:"sessions_live"};if(options.requireAnswer===!0&&(host===void 0||sessions===void 0))return{action:"refuse",reason:"sessions_live"};let target=expected===void 0?owner:await recheckedTarget(paths,options.socket,expected,host);return target===void 0?{action:"refuse",reason:"unknown_owner"}:"action"in target?target:(await writeStopIntent(generationPaths(paths,target.instanceId),{sender:{pid:process.pid,kind:"stop"},targetPid:target.pid,reason:"operator_stop",signal:"SIGTERM",at:new Date().toISOString()}),signalGeneration(target.pid,"SIGTERM")||await releaseGeneration(paths,{instanceId:target.instanceId,pid:target.pid}),{action:"stopped",pid:target.pid})}function generationRefusal(match){if(match==="stale")return{action:"refuse",reason:"stale_generation"};if(match==="unprovable")return{action:"refuse",reason:"unknown_owner"}}async function staleStopGeneration(socket,agentDir,expected){let paths=createHostDaemonPaths({socket,...agentDir?{agentDir}:{}});return generationRefusal(compareStopGeneration(await readHostRegistration(paths),expected))}async function recheckedTarget(paths,socket,expected,host){let current=await readHostRegistration(paths),match=compareStopGeneration(current,expected),refusal=generationRefusal(match);if(refusal!==void 0)return refusal;if(!(match==="proven"&&!await provenOwner(current,socket))){if(match==="bound_without_start_time"){if(current?.socket!==void 0&&!sameEndpoint(current.socket,socket)||!await startedBeforeRegistration(expected.pid,generationPaths(paths,expected.instanceId).pidFile))return;if(host?.instanceId!==void 0&&host.instanceId!==expected.instanceId)return{action:"refuse",reason:"stale_generation"}}return{pid:expected.pid,instanceId:expected.instanceId}}}function signalGeneration(pid,signal){try{return process.kill(pid,signal),!0}catch(error){if(error instanceof Error&&"code"in error&&error.code==="ESRCH")return!1;throw error}}import{lstat as lstat2,rm as rm2}from"node:fs/promises";import{dirname as dirname5,join as join6}from"node:path";import{lstat,readdir as readdir3}from"node:fs/promises";import{createConnection}from"node:net";import{basename as basename2,dirname as dirname4,join as join4}from"node:path";var SOCKET_PROBE_TIMEOUT_MS=2e3;async function endpointInUse(paths,socket){if(await anyGenerationLive(paths))return{inUse:"live_generation"};for(let claim of await readSessionPathClaims(paths.reservationsDir))if(await claimOwnerIsLive(claim.owner))return{inUse:"live_claim"};let silence=await socketSilence(socket);if(silence===void 0)return{inUse:"reachable"};let successors=(await socketSiblings(socket)).filter(name=>name.startsWith(`${basename2(socket)}.next-`));for(let successor of successors)if(await socketSilence(join4(dirname4(socket),successor))===void 0)return{inUse:"reachable"};return{inUse:void 0,silence}}async function socketSiblings(socket){let name=basename2(socket);return(await readdir3(dirname4(socket)).catch(()=>[])).filter(entry=>entry.startsWith(`${name}.next-`)||entry.startsWith(`${name}.shield-`))}async function anyGenerationLive(paths){for(let instanceId of await readdir3(paths.generationsDir).catch(()=>[])){if(await hostChildAlive(generationPaths(paths,instanceId)))return!0;let record=generationRecord(await readFileOrUndefined(generationPaths(paths,instanceId).pidFile));if(record!==void 0&&await recordIsLive(record))return!0}return!1}function generationRecord(text){if(text===void 0)return;let record=parseDaemonPidFile(text);if(record!==void 0)return record;let pid=parseJson(text)?.pid;return typeof pid=="number"&&Number.isInteger(pid)&&pid>0?{pid,processStartTime:null}:void 0}async function recordIsLive(record){try{return await processMatchesPidFile(record)}catch(error){if(error instanceof ProcessIdentityUnreadableError)return!0;throw error}}async function socketSilence(socket){let secret;return process.platform==="win32"&&(secret=await readSocketSecret(socketSecretPath(socket)).catch(()=>{}),secret===void 0)?"socket_absent":new Promise(resolveProbe=>{let connection=createConnection(resolveSocketTransportAddress(socket,process.platform,secret)),finish=value=>{clearTimeout(timeout),connection.destroy(),resolveProbe(value)},timeout=setTimeout(()=>finish(void 0),SOCKET_PROBE_TIMEOUT_MS);connection.once("connect",()=>finish(void 0)),connection.once("error",error=>{error.code==="ECONNREFUSED"?refusedBySocket(socket).then(finish):error.code==="ENOENT"?finish("socket_absent"):finish(void 0)})})}async function refusedBySocket(socket){if(process.platform==="win32"||socket.startsWith("\0"))return"socket_refused";try{return(await lstat(socket)).isSocket()?"socket_refused":void 0}catch(error){return error instanceof Error&&"code"in error&&error.code==="ENOENT"?"socket_absent":void 0}}import{execFile}from"node:child_process";import{readdir as readdir4,readFile as readFile2,readlink,realpath as realpath2}from"node:fs/promises";import{join as join5}from"node:path";var LSOF_TIMEOUT_MS=2e3,LINUX_ACCEPTCON_FLAG=65536;async function countPublicClients(supervisorPid,socket){let names=new Set([socket,await realpath2(socket).catch(()=>socket)]),descriptors=process.platform==="darwin"?await darwinDescriptors(supervisorPid,names):process.platform==="linux"?await linuxDescriptors(supervisorPid,names):void 0;if(!(descriptors===void 0||descriptors.listeners===0))return descriptors.total-descriptors.listeners}function darwinDescriptors(pid,names){return new Promise(resolve2=>{execFile("lsof",["-a","-p",String(pid),"-U","-w","-F","n"],{timeout:LSOF_TIMEOUT_MS},(error,stdout)=>{if(error)return resolve2(void 0);let total=stdout.split(`
|
|
6
6
|
`).filter(line=>line.startsWith("n")&&names.has(line.slice(1))).length;resolve2({total,listeners:total>0?1:0})})})}async function linuxDescriptors(pid,names){try{let inodes=new Set;for(let fd of await readdir4(join5("/proc",String(pid),"fd"))){let target=await readlink(join5("/proc",String(pid),"fd",fd)).catch(()=>""),inode=/^socket:\[(\d+)\]$/.exec(target)?.[1];inode!==void 0&&inodes.add(inode)}let total=0,listeners=0;for(let line of(await readFile2("/proc/net/unix","utf8")).split(`
|
|
7
|
-
`).slice(1)){let fields=line.trim().split(/\s+/),[flags,inode,path]=[fields[3],fields[6],fields[7]];inode===void 0||path===void 0||!inodes.has(inode)||!names.has(path)||(total+=1,(Number.parseInt(flags??"0",16)&LINUX_ACCEPTCON_FLAG)!==0&&(listeners+=1))}return{total,listeners}}catch{return}}var STALE_ENGINE_GRACE_MS=10*6e4,PROBE_TIMEOUT_MS=2e3;async function judgeStaleEngine(socket,agentDir,client,options={}){let paths=createHostDaemonPaths({socket,agentDir}),owner=await provenOwner(await readHostRegistration(paths),socket);if(owner===void 0)return keep("stale_unproven_owner");let clients=await countPublicClients(owner.pid,socket),info=await observeProtocolInfo(socket,PROBE_TIMEOUT_MS);if(info===void 0)return keep("stale_unreachable");let hostOrdinal=info.engineOrdinal,hostIdentity=hostOrdinal===void 0?void 0:{text:info.engineVersion??"",ordinal:hostOrdinal,scheme:hostOrdinal[4]>0?"epoch":"nodef"};if(hostIdentity===void 0||compareEngineOrdinal(hostIdentity,client)!==-1)return keep("stale_not_older");let policy=resolveHostPolicy(parseJson(await readFileOrUndefined(paths.settingsFile)),{});if(policy.coldStart==="persistent")return keep("stale_persistent");if(await observedSessionCount(socket)!==0)return keep("stale_sessions");if((await readSessionPathClaims(paths.reservationsDir)).length>0)return keep("stale_claims");let startedAt=processStartTimeMs(owner.processStartTime),now=(options.now??Date.now)();return startedAt===void 0||now-startedAt<policy.idleExitMs+(options.graceMs??STALE_ENGINE_GRACE_MS)?keep("stale_young"):clients!==0?keep("stale_clients"):{stale:!0,pid:owner.pid}}function keep(reason){return{stale:!1,reason}}async function observedSessionCount(socket){let reply=await requestOnSocket(socket,{type:"list_sessions",include_workers:!0,[OBSERVE_REQUEST_FIELD]:!0},PROBE_TIMEOUT_MS);if(typeof reply!="object"||reply===null)return;let sessions=Reflect.get(reply,"sessions");return Array.isArray(sessions)?sessions.length:void 0}var GC_LOCK_WAIT_MS=2e3;async function gcHostEndpoints(agentDir,options={}){process.platform!=="win32"&&await gcRpcPublicKeys(agentDir);let removed=[],stopped=[],kept=[],wanted=kind=>options.kinds===void 0||options.kinds.includes(kind),legacy=wanted("rpc_host")?await legacyFlatDirectory(agentDir):void 0;legacy!==void 0&&kept.push({socket:null,dir:legacy,reason:"legacy_layout"});for(let endpoint of await listHostEndpoints(agentDir)){if(!wanted(endpoint.endpoint_kind))continue;if(endpoint.socket===null){kept.push({socket:null,dir:endpoint.dir,reason:"unknown_identity"});continue}let entry={socket:endpoint.socket,dir:endpoint.dir};try{let outcome=await gcEndpoint(endpoint.socket,endpoint.dir,options);"stopped"in outcome?stopped.push({...entry,reason:"stale_old_engine",pid:outcome.pid}):outcome.removed?outcome.skipped.length===0?removed.push({...entry,reason:outcome.reason}):removed.push({...entry,reason:outcome.reason,skipped:outcome.skipped}):kept.push({...entry,reason:outcome.reason})}catch(error){kept.push({...entry,reason:"failed",error:error instanceof Error?error.message:String(error)})}}return stopped.length===0?{removed,kept}:{removed,stopped,kept}}async function gcEndpoint(socket,dir,options){let release=await acquireEnsureLock(socket);if(release===void 0)return{removed:!1,reason:"locked"};try{await options._test?.afterLockAcquired?.(socket);let evidence=await endpointInUse(hostDaemonDirectoryPaths(dir),socket);if(evidence.inUse==="live_claim"||evidence.inUse!==void 0&&options.staleEngine===void 0)return{removed:!1,reason:evidence.inUse};if(evidence.inUse!==void 0)return await stopIfStale(socket,dir,evidence.inUse,options.staleEngine??{});let skipped=await removeEndpoint(socket,dir);return{removed:!0,reason:evidence.silence,skipped}}finally{await release()}}var NOT_A_CANDIDATE=new Set(["stale_unproven_owner","stale_unreachable","stale_not_older"]),STALE_STOP_TIMEOUT_MS=2e3;async function stopIfStale(socket,dir,inUse,options){let agentDir=dirname5(dirname5(dir)),verdict=await judgeStaleEngine(socket,agentDir,options.client??engineBuildIdentity(),options);if(!verdict.stale)return{removed:!1,reason:NOT_A_CANDIDATE.has(verdict.reason)?inUse:verdict.reason};let result=await stopHost({socket,agentDir,timeoutMs:STALE_STOP_TIMEOUT_MS,requireAnswer:!0});return result.action==="refuse"?{removed:!1,reason:result.reason==="unknown_owner"?"stale_unproven_owner":"stale_sessions"}:{removed:!1,stopped:!0,pid:result.pid}}async function removeEndpoint(socket,dir){let skipped=[];for(let sibling of await socketSiblings(socket)){let path=join6(dirname5(socket),sibling),entry=await lstat2(path).catch(error=>{if(!(error instanceof Error&&"code"in error&&error.code==="ENOENT"))throw error});entry?.isDirectory()?skipped.push({path,type:"directory"}):entry!==void 0&&await rm2(path,{force:!0})}return await rm2(socket,{force:!0}),await rm2(dir,{recursive:!0,force:!0}),skipped}async function acquireEnsureLock(socket){return acquireHostEnsureLock(socket,GC_LOCK_WAIT_MS).catch(()=>{})}async function legacyFlatDirectory(agentDir){let flatDir=join6(agentDir,"rpc-host-daemon");return parseJson(await readFileOrUndefined(join6(flatDir,"layout.json")).catch(()=>{}))?.layout===HOST_DAEMON_LAYOUT?void 0:await readFileOrUndefined(join6(flatDir,"host.pid")).catch(()=>{})!==void 0?flatDir:void 0}export{engineBuildIdentityFrom,engineBuildIdentity,compareEngineOrdinal,CUSTOM_UNSUPPORTED_CAPABILITY,EXTENSION_EVENTS_CAPABILITY,EVAL_CELLS_CAPABILITY,AUTO_TITLE_SESSIONS_CAPABILITY,CONTINUE_FROM_LEAF_CAPABILITY,SESSION_HELD_CAPABILITY,RESUME_SESSION_CAPABILITY,ATTENDED_CAPABILITY,MEDIA_PLACEHOLDERS_CAPABILITY,QUESTION_CAPABILITY,TOOL_BARRIER_CAPABILITY,SESSION_RELOCATION_CAPABILITY,RETAIN_ON_DISCONNECT_CAPABILITY,DETACH_CONNECTION_CAPABILITY,INTERACTIVE_USER_CAPABILITY,TASK_PARENT_CAPABILITY,SESSION_CONTEXT_CAPABILITY,SESSION_KIND_CAPABILITY,SESSION_STATUS_CAPABILITY,AUTO_TITLE_PER_SESSION_CAPABILITY,WARM_CAPABILITY,DURABLE_SESSION_ID_CAPABILITY,MOVED_PATH_GUARD_CAPABILITY,PROMPT_SURFACE_CAPABILITY,BROWSER_ENGINE_CAPABILITY,RETRY_FALLBACK_PROFILE_CAPABILITY,RETRY_FALLBACK_COMMAND_CAPABILITY,PROMPT_SURFACE_CHAT_CAPABILITY,RPC_CLIENT_CAPABILITIES_ENV,parseClientCapabilities,DEFAULT_CUSTOM_EXTENSION_LABEL,buildCustomUnsupportedRequest,AUTH_KEY_VERIFY_CAPABILITY,QUEUED_MESSAGE_REVISION_CAPABILITY,RUNTIME_IDENTITY_HANDOVER_CAPABILITY,computeRuntimeBuildId,parseHostProtocolInfo,HOST_PROTOCOL_VERSION,GENERATION_HANDOFF_CAPABILITY,REQUIRED_HOST_CAPABILITIES,HostEnsureRefusedError,decideHostAction,hostInstanceId,hostGeneration,hostLaunchProfile,socketHostLaunchProfile,protocolIdentity,DEFAULT_PROBE_TIMEOUT_MS,probeHost,probeProtocolInfo,observeProtocolInfo,holdProtocolInfo,probeSocketReachable,holdSessionCount,hostEnsureLockTarget,acquireHostEnsureLock,hostEnsureLockOptions,anyGenerationLive,judgeStaleEngine,electPointer,retireIdleLegacyHost,provenLegacyOwner,busyLegacyHostDetail,describeSessions,parseHostStopGeneration,stopHost,staleStopGeneration,signalGeneration,gcHostEndpoints,gcEndpoint};
|
|
7
|
+
`).slice(1)){let fields=line.trim().split(/\s+/),[flags,inode,path]=[fields[3],fields[6],fields[7]];inode===void 0||path===void 0||!inodes.has(inode)||!names.has(path)||(total+=1,(Number.parseInt(flags??"0",16)&LINUX_ACCEPTCON_FLAG)!==0&&(listeners+=1))}return{total,listeners}}catch{return}}var STALE_ENGINE_GRACE_MS=10*6e4,PROBE_TIMEOUT_MS=2e3;async function judgeStaleEngine(socket,agentDir,client,options={}){let paths=createHostDaemonPaths({socket,agentDir}),owner=await provenOwner(await readHostRegistration(paths),socket);if(owner===void 0)return keep("stale_unproven_owner");let clients=await countPublicClients(owner.pid,socket),info=await observeProtocolInfo(socket,PROBE_TIMEOUT_MS);if(info===void 0)return keep("stale_unreachable");let hostOrdinal=info.engineOrdinal,hostIdentity=hostOrdinal===void 0?void 0:{text:info.engineVersion??"",ordinal:hostOrdinal,scheme:hostOrdinal[4]>0?"epoch":"nodef"};if(hostIdentity===void 0||compareEngineOrdinal(hostIdentity,client)!==-1)return keep("stale_not_older");let policy=resolveHostPolicy(parseJson(await readFileOrUndefined(paths.settingsFile)),{});if(policy.coldStart==="persistent")return keep("stale_persistent");if(await observedSessionCount(socket)!==0)return keep("stale_sessions");if((await readSessionPathClaims(paths.reservationsDir)).length>0)return keep("stale_claims");let startedAt=processStartTimeMs(owner.processStartTime),now=(options.now??Date.now)();return startedAt===void 0||now-startedAt<policy.idleExitMs+(options.graceMs??STALE_ENGINE_GRACE_MS)?keep("stale_young"):clients!==0?keep("stale_clients"):{stale:!0,pid:owner.pid}}function keep(reason){return{stale:!1,reason}}async function observedSessionCount(socket){let reply=await requestOnSocket(socket,{type:"list_sessions",include_workers:!0,[OBSERVE_REQUEST_FIELD]:!0},PROBE_TIMEOUT_MS);if(typeof reply!="object"||reply===null)return;let sessions=Reflect.get(reply,"sessions");return Array.isArray(sessions)?sessions.length:void 0}var GC_LOCK_WAIT_MS=2e3;async function gcHostEndpoints(agentDir,options={}){process.platform!=="win32"&&await gcRpcPublicKeys(agentDir);let removed=[],stopped=[],kept=[],wanted=kind=>options.kinds===void 0||options.kinds.includes(kind),legacy=wanted("rpc_host")?await legacyFlatDirectory(agentDir):void 0;legacy!==void 0&&kept.push({socket:null,dir:legacy,reason:"legacy_layout"});for(let endpoint of await listHostEndpoints(agentDir)){if(!wanted(endpoint.endpoint_kind))continue;if(endpoint.socket===null){kept.push({socket:null,dir:endpoint.dir,reason:"unknown_identity"});continue}let entry={socket:endpoint.socket,dir:endpoint.dir};try{let outcome=await gcEndpoint(endpoint.socket,endpoint.dir,options);"stopped"in outcome?stopped.push({...entry,reason:"stale_old_engine",pid:outcome.pid}):outcome.removed?outcome.skipped.length===0?removed.push({...entry,reason:outcome.reason}):removed.push({...entry,reason:outcome.reason,skipped:outcome.skipped}):kept.push({...entry,reason:outcome.reason})}catch(error){kept.push({...entry,reason:"failed",error:error instanceof Error?error.message:String(error)})}}return stopped.length===0?{removed,kept}:{removed,stopped,kept}}async function gcEndpoint(socket,dir,options){let release=await acquireEnsureLock(socket);if(release===void 0)return{removed:!1,reason:"locked"};try{await options._test?.afterLockAcquired?.(socket);let evidence=await endpointInUse(hostDaemonDirectoryPaths(dir),socket);if(evidence.inUse==="live_claim"||evidence.inUse!==void 0&&options.staleEngine===void 0)return{removed:!1,reason:evidence.inUse};if(evidence.inUse!==void 0)return await stopIfStale(socket,dir,evidence.inUse,options.staleEngine??{});let skipped=await removeEndpoint(socket,dir);return{removed:!0,reason:evidence.silence,skipped}}finally{await release()}}var NOT_A_CANDIDATE=new Set(["stale_unproven_owner","stale_unreachable","stale_not_older"]),STALE_STOP_TIMEOUT_MS=2e3;async function stopIfStale(socket,dir,inUse,options){let agentDir=dirname5(dirname5(dir)),verdict=await judgeStaleEngine(socket,agentDir,options.client??engineBuildIdentity(),options);if(!verdict.stale)return{removed:!1,reason:NOT_A_CANDIDATE.has(verdict.reason)?inUse:verdict.reason};let result=await stopHost({socket,agentDir,timeoutMs:STALE_STOP_TIMEOUT_MS,requireAnswer:!0});return result.action==="refuse"?{removed:!1,reason:result.reason==="unknown_owner"?"stale_unproven_owner":"stale_sessions"}:{removed:!1,stopped:!0,pid:result.pid}}async function removeEndpoint(socket,dir){let skipped=[];for(let sibling of await socketSiblings(socket)){let path=join6(dirname5(socket),sibling),entry=await lstat2(path).catch(error=>{if(!(error instanceof Error&&"code"in error&&error.code==="ENOENT"))throw error});entry?.isDirectory()?skipped.push({path,type:"directory"}):entry!==void 0&&await rm2(path,{force:!0})}return await rm2(socket,{force:!0}),await rm2(dir,{recursive:!0,force:!0}),skipped}async function acquireEnsureLock(socket){return acquireHostEnsureLock(socket,GC_LOCK_WAIT_MS).catch(()=>{})}async function legacyFlatDirectory(agentDir){let flatDir=join6(agentDir,"rpc-host-daemon");return parseJson(await readFileOrUndefined(join6(flatDir,"layout.json")).catch(()=>{}))?.layout===HOST_DAEMON_LAYOUT?void 0:await readFileOrUndefined(join6(flatDir,"host.pid")).catch(()=>{})!==void 0?flatDir:void 0}export{engineBuildIdentityFrom,engineBuildIdentity,compareEngineOrdinal,CUSTOM_UNSUPPORTED_CAPABILITY,EXTENSION_EVENTS_CAPABILITY,EVAL_CELLS_CAPABILITY,AUTO_TITLE_SESSIONS_CAPABILITY,CONTINUE_FROM_LEAF_CAPABILITY,SESSION_HELD_CAPABILITY,RESUME_SESSION_CAPABILITY,ATTENDED_CAPABILITY,MEDIA_PLACEHOLDERS_CAPABILITY,QUESTION_CAPABILITY,TOOL_BARRIER_CAPABILITY,SESSION_RELOCATION_CAPABILITY,RETAIN_ON_DISCONNECT_CAPABILITY,DETACH_CONNECTION_CAPABILITY,INTERACTIVE_USER_CAPABILITY,OBSERVE_READS_CAPABILITY,ENTRIES_TAIL_CAPABILITY,TUI_OBSERVER_CAPABILITY,TASK_PARENT_CAPABILITY,SESSION_CONTEXT_CAPABILITY,SESSION_KIND_CAPABILITY,SESSION_STATUS_CAPABILITY,AUTO_TITLE_PER_SESSION_CAPABILITY,WARM_CAPABILITY,DURABLE_SESSION_ID_CAPABILITY,MOVED_PATH_GUARD_CAPABILITY,PROMPT_SURFACE_CAPABILITY,BROWSER_ENGINE_CAPABILITY,RETRY_FALLBACK_PROFILE_CAPABILITY,RETRY_FALLBACK_COMMAND_CAPABILITY,PROMPT_SURFACE_CHAT_CAPABILITY,RPC_CLIENT_CAPABILITIES_ENV,parseClientCapabilities,DEFAULT_CUSTOM_EXTENSION_LABEL,buildCustomUnsupportedRequest,AUTH_KEY_VERIFY_CAPABILITY,QUEUED_MESSAGE_REVISION_CAPABILITY,RUNTIME_IDENTITY_HANDOVER_CAPABILITY,computeRuntimeBuildId,parseHostProtocolInfo,HOST_PROTOCOL_VERSION,GENERATION_HANDOFF_CAPABILITY,REQUIRED_HOST_CAPABILITIES,HostEnsureRefusedError,decideHostAction,hostInstanceId,hostGeneration,hostLaunchProfile,socketHostLaunchProfile,protocolIdentity,DEFAULT_PROBE_TIMEOUT_MS,probeHost,probeProtocolInfo,observeProtocolInfo,holdProtocolInfo,probeSocketReachable,holdSessionCount,hostEnsureLockTarget,acquireHostEnsureLock,hostEnsureLockOptions,anyGenerationLive,judgeStaleEngine,electPointer,retireIdleLegacyHost,provenLegacyOwner,busyLegacyHostDetail,describeSessions,parseHostStopGeneration,stopHost,staleStopGeneration,signalGeneration,gcHostEndpoints,gcEndpoint};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url); { const __piWorkerThreads = require("node:worker_threads"); if (typeof __piWorkerThreads.markAsUncloneable !== "function") { __piWorkerThreads.markAsUncloneable = () => {}; } }
|
|
2
2
|
import{McpMrtrError,bindMcpFormPresented,enums,isRecord,privateMcpForms,queuedForm,validValue,validateMrtrForm}from"./chunk-JPGT64RV.js";import{redactResolvedReferenceValues}from"./chunk-DLAY7CIU.js";import{getAgentDir}from"./chunk-7YO7VQZW.js";var McpError=class extends Error{constructor(kind,name,message,options={}){super(message),this.name=name,this.kind=kind,this.phase=options.phase,this.retriable=options.retriable,this.serverName=options.serverName,options.cause!==void 0&&Object.defineProperty(this,"cause",{configurable:!0,value:options.cause,writable:!1}),Object.setPrototypeOf(this,new.target.prototype)}},ConnectError=class extends McpError{constructor(message,options={}){super("connect","ConnectError",message,options)}};var ToolExecError=class extends McpError{constructor(message,options={}){super("tool_exec","ToolExecError",message,options)}},AuthError=class extends McpError{constructor(message,options={}){super("auth","AuthError",message,options)}},TimeoutError=class extends McpError{constructor(message,options={}){super("timeout","TimeoutError",message,options)}},SessionExpiredError=class extends McpError{constructor(message,options={}){super("session_expired","SessionExpiredError",message,options)}},RETRIABLE_STATUS_CODES=new Set([404,502,503]),RETRIABLE_NUMERIC_CODES=new Set([-32001]),RETRIABLE_TEXT=["econnrefused","connection refused","transport closed"];function isRetriableMcpError(error){if(error instanceof McpError&&error.retriable===!0||isMcpSessionExpiredError(error)||hasRetriableNumericSignal(error,new Set))return!0;let text=collectText(error,new Set).join(" ").toLowerCase();return RETRIABLE_TEXT.some(needle=>text.includes(needle))?!0:/\b(?:404|502|503)\b/.test(text)}function isMcpSessionExpiredError(error){if(hasSessionExpiredNumericSignal(error,new Set))return!0;let text=collectText(error,new Set).join(" ").toLowerCase();return/\b404\b/.test(text)||text.includes("-32000")&&text.includes("session")||text.includes("session expired")||text.includes("session not found")||text.includes("mcp-session-id")}function hasRetriableNumericSignal(value,seen){if(typeof value!="object"||value===null||seen.has(value))return!1;seen.add(value);let code=numberFromUnknown(getProperty(value,"code"));if(code!==void 0&&RETRIABLE_NUMERIC_CODES.has(code))return!0;let status=numberFromUnknown(getProperty(value,"status"));if(status!==void 0&&RETRIABLE_STATUS_CODES.has(status))return!0;let statusCode=numberFromUnknown(getProperty(value,"statusCode"));return statusCode!==void 0&&RETRIABLE_STATUS_CODES.has(statusCode)?!0:hasRetriableNumericSignal(getProperty(value,"response"),seen)||hasRetriableNumericSignal(getProperty(value,"cause"),seen)}function hasSessionExpiredNumericSignal(value,seen){if(typeof value!="object"||value===null||seen.has(value))return!1;seen.add(value);let code=numberFromUnknown(getProperty(value,"code"));if(code===-32001)return!0;if(code===-32e3){let message=getProperty(value,"message");if(typeof message=="string"&&message.toLowerCase().includes("session"))return!0}return numberFromUnknown(getProperty(value,"status"))===404||numberFromUnknown(getProperty(value,"statusCode"))===404?!0:hasSessionExpiredNumericSignal(getProperty(value,"response"),seen)||hasSessionExpiredNumericSignal(getProperty(value,"cause"),seen)}function collectText(value,seen){if(typeof value=="string")return[value];if(typeof value=="number")return[String(value)];if(typeof value!="object"||value===null)return[];if(seen.has(value))return[];seen.add(value);let parts=[];value instanceof Error&&parts.push(value.message,value.name);for(let key of["message","code","status","statusCode"]){let property=getProperty(value,key);(typeof property=="string"||typeof property=="number")&&parts.push(String(property))}return parts.push(...collectText(getProperty(value,"response"),seen)),parts.push(...collectText(getProperty(value,"cause"),seen)),parts}function numberFromUnknown(value){if(typeof value=="number")return value;if(typeof value!="string"||value.trim()==="")return;let parsed=Number(value);return Number.isFinite(parsed)?parsed:void 0}function getProperty(value,key){if(!(typeof value!="object"||value===null))return value[key]}import{chmodSync,closeSync,openSync,renameSync,rmSync,statSync}from"node:fs";var LOG_SINK_RETRY_MS=5e3,ROTATION_LOCK_STALE_MS=1e4;function errorCode(error){return typeof error=="object"&&error!==null&&"code"in error&&typeof error.code=="string"?error.code:void 0}function exceedsCap(filePath,incomingBytes,maxBytes){try{return statSync(filePath).size+incomingBytes>maxBytes}catch(error){if(errorCode(error)==="ENOENT")return!1;throw error}}function clearStaleLock(lockPath){try{Date.now()-statSync(lockPath).mtimeMs>ROTATION_LOCK_STALE_MS&&rmSync(lockPath,{force:!0})}catch(error){if(errorCode(error)!=="ENOENT")throw error}}function rotateLogIfNeeded(filePath,incomingBytes,maxBytes){if(!exceedsCap(filePath,incomingBytes,maxBytes))return;let lockPath=`${filePath}.rotate-lock`,lock;try{lock=openSync(lockPath,"wx",384)}catch(error){if(errorCode(error)!=="EEXIST")throw error;clearStaleLock(lockPath);return}try{if(!exceedsCap(filePath,incomingBytes,maxBytes))return;try{renameSync(filePath,`${filePath}.1`)}catch(error){if(errorCode(error)==="ENOENT")return;throw error}chmodSync(`${filePath}.1`,384)}finally{closeSync(lock),rmSync(lockPath,{force:!0})}}import{closeSync as closeSync3,fchmodSync,mkdirSync as mkdirSync2,openSync as openSync3,writeSync as writeSync2}from"node:fs";import{dirname,join as join2}from"node:path";import{createHmac,randomBytes,randomUUID}from"node:crypto";import{closeSync as closeSync2,constants,fstatSync,fsyncSync,linkSync,mkdirSync,openSync as openSync2,readSync,rmSync as rmSync2,writeSync}from"node:fs";import{join}from"node:path";var KEY_FILE="config-identity.key",KEY_BYTES=32,EPHEMERAL_PREFIX="ephemeral:",processKey=randomBytes(KEY_BYTES),installationKeys=new Map,warnedPaths=new Set;function keyedIdentity(agentDir,payload){let key=installationKey(agentDir??getAgentDir());return key===void 0?`${EPHEMERAL_PREFIX}${hmac(processKey,payload)}`:hmac(key,payload)}function isEphemeralIdentity(identity){return identity?.startsWith(EPHEMERAL_PREFIX)===!0}function keyedFingerprint(value){return hmac(installationKey(getAgentDir())??processKey,value).slice(0,8)}function hmac(key,payload){return createHmac("sha256",key).update(payload).digest("hex")}function installationKey(agentDir){return installationKeys.has(agentDir)||installationKeys.set(agentDir,loadOrPublishKey(agentDir)),installationKeys.get(agentDir)}function loadOrPublishKey(agentDir){let path=join(agentDir,KEY_FILE),existing=readKey(path);return existing.kind==="valid"?existing.key:existing.kind==="missing"?publishKey(agentDir,path):void 0}function readKey(path){let fd;try{fd=openSync2(path,constants.O_RDONLY|(constants.O_NOFOLLOW??0))}catch(error){return isErrno(error,"ENOENT")?{kind:"missing"}:invalidKey(path,"cannot open safely","repair access and ensure it is a regular file, not a symlink")}try{let stat=fstatSync(fd);if(!stat.isFile())return invalidKey(path,"not a regular file","restore the original private key file");if(stat.size!==KEY_BYTES)return invalidKey(path,`wrong size (${stat.size} bytes)`,"restore the original 32-byte key from backup");if(process.platform!=="win32"){if(stat.uid!==process.getuid?.())return invalidKey(path,"wrong owner","chown the key file to your current user");if((stat.mode&511)!==384)return invalidKey(path,"wrong mode","chmod 600 the key file")}let key=Buffer.alloc(KEY_BYTES);return readSync(fd,key,0,KEY_BYTES,0)===KEY_BYTES?{kind:"valid",key}:invalidKey(path,"incomplete read","restore the original 32-byte key from backup")}finally{closeSync2(fd)}}function invalidKey(path,problem,repair){return warnedPaths.has(path)||(warnedPaths.add(path),console.warn(`MCP identity key ${path}: ${problem}; persistent catalog cache is disabled. To fix: ${repair}, then restart senpi. The file was left unchanged.`)),{kind:"invalid"}}function publishKey(agentDir,path){let temporary=`${path}.${process.pid}.${randomUUID()}.tmp`;try{mkdirSync(agentDir,{recursive:!0,mode:448});let key=randomBytes(KEY_BYTES),fd=openSync2(temporary,constants.O_CREAT|constants.O_EXCL|constants.O_WRONLY,384);try{writeSync(fd,key),fsyncSync(fd)}finally{closeSync2(fd)}return linkSync(temporary,path),syncDirectory(agentDir),key}catch(error){if(!isErrno(error,"EEXIST"))return;let published=readKey(path);return published.kind==="valid"?published.key:void 0}finally{rmSync2(temporary,{force:!0})}}function syncDirectory(directory){if(process.platform==="win32")return;let fd=openSync2(directory,constants.O_RDONLY);try{fsyncSync(fd)}finally{closeSync2(fd)}}function isErrno(error,code){return error instanceof Error&&"code"in error&&error.code===code}var DEFAULT_MAX_FILE_BYTES=1024*1024,MAX_RING_LINES=200,SENSITIVE_KEY_PATTERN=/(?:^|[_-])(?:api[_-]?key|key|token|secret|password|client_secret|auth|authorization)(?:$|[_-])/i,QUERY_SECRET_PATTERN=/([?&][^=\s&"'<>]*(?:key|token|secret|password|client_secret|auth)[^=\s&"'<>]*=)([^&\s"'<>]+)/gi,AUTHORIZATION_VALUE_PATTERN=/((?:"|')?\bAuthorization(?:"|')?\s*[:=]\s*(?:"|')?(?:[A-Za-z][A-Za-z0-9+.-]*\s+)?)(?!<redacted:)([^"',\s}\]&]+)/gi,BEARER_VALUE_PATTERN=/(\bBearer\s+)(?!<redacted:)([A-Za-z0-9._~+/=-]+)/gi,KEY_VALUE_PATTERN=/((?:"|')?[^"'\s:=,{}]*(?:api[_-]?key|key|token|secret|password|client_secret|auth)[^"'\s:=,{}]*(?:"|')?\s*[:=]\s*(?:"|')?)([^"',\s}\]&]+)/gi,MCP_LOG_LEVELS={emergency:{level:"emergency",severity:0},alert:{level:"alert",severity:1},critical:{level:"critical",severity:2},crit:{level:"critical",severity:2},error:{level:"error",severity:3},err:{level:"error",severity:3},warning:{level:"warning",severity:4},warn:{level:"warning",severity:4},notice:{level:"notice",severity:5},informational:{level:"info",severity:6},info:{level:"info",severity:6},debug:{level:"debug",severity:7}};function createMcpLogger(server,options={}){return new FileMcpLogger(server,options)}function getMcpLogDir(){return join2(getAgentDir(),"logs","mcp")}function fingerprintSecret(secret){return keyedFingerprint(secret)}function redactMcpLogText(text){return redactMcpLogTextWithContext(text,{seen:new WeakSet,secrets:new Set})}function redactMcpLogTextWithContext(text,context){return text.replace(AUTHORIZATION_VALUE_PATTERN,(_match,prefix,secret)=>`${prefix}${redactionForSecret(secret,context)}`).replace(BEARER_VALUE_PATTERN,(_match,prefix,secret)=>`${prefix}${redactionForSecret(secret,context)}`).replace(QUERY_SECRET_PATTERN,(_match,prefix,secret)=>`${prefix}${redactionForSecret(secret,context)}`).replace(KEY_VALUE_PATTERN,(match,prefix,secret)=>secret.startsWith("<redacted:")||/\bAuthorization\b/i.test(prefix)?match:`${prefix}${redactionForSecret(secret,context)}`)}function mapMcpLogLevel(level){return{...MCP_LOG_LEVELS[level]??MCP_LOG_LEVELS.info}}var FileMcpLogger=class{#server;#maxFileBytes;#ring=[];#fileSinkRetryAt=0;constructor(server,options){this.#server=server,this.#maxFileBytes=options.maxFileBytes??DEFAULT_MAX_FILE_BYTES,this.filePath=join2(options.logDir??getMcpLogDir(),`${sanitizeServerName(server)}.log`)}debug(message,data){this.log("debug",message,data)}info(message,data){this.log("info",message,data)}warn(message,data){this.log("warning",message,data)}error(message,data){this.log("error",message,data)}stderr(message,data){this.log("info",message,data,"stderr")}log(level,message,data,channel="server"){let line=this.#formatLine(level,message,data,channel);this.#pushRing(line),this.#writeFile(line)}getRingBuffer(){return[...this.#ring]}#formatLine(level,message,data,channel){let context={seen:new WeakSet,secrets:new Set},mapped=mapMcpLogLevel(level),redactedData=data===void 0?void 0:redactMcpLogData(data,context),entry={timestamp:new Date().toISOString(),server:this.#server,level:mapped.level,severity:mapped.severity,channel,message:redactMcpLogTextWithContext(message,context),data:redactedData};return redactResolvedReferenceValues(redactKnownSecrets(JSON.stringify(entry),context))}#pushRing(line){this.#ring.push(line),this.#ring.length>MAX_RING_LINES&&this.#ring.splice(0,this.#ring.length-MAX_RING_LINES)}#writeFile(line){if(!(Date.now()<this.#fileSinkRetryAt))try{mkdirSync2(dirname(this.filePath),{recursive:!0,mode:448});let bytes=Buffer.byteLength(`${line}
|
|
3
3
|
`);this.#maxFileBytes>0&&rotateLogIfNeeded(this.filePath,bytes,this.#maxFileBytes);let fd=openSync3(this.filePath,"a",384);try{writeSync2(fd,`${line}
|
|
4
|
-
`),fchmodSync(fd,384)}finally{closeSync3(fd)}}catch{this.#fileSinkRetryAt=Date.now()+LOG_SINK_RETRY_MS,this.#pushRing(this.#formatLine("warning","file sink disabled after write failure",void 0,"file"))}}};function redactMcpLogData(value,context){return typeof value=="string"?redactMcpLogTextWithContext(value,context):typeof value=="bigint"?value.toString():typeof value!="object"||value===null?value:context.seen.has(value)?"[Circular]":(context.seen.add(value),value instanceof Error?redactMcpLogError(value,context):Array.isArray(value)?value.map(item=>redactMcpLogData(item,context)):redactMcpLogEntries(value,context))}function redactMcpLogError(error,context){let redacted=redactMcpLogEntries(error,context);return redacted.name=redactMcpLogTextWithContext(error.name,context),redacted.message=redactKnownSecrets(redactMcpLogTextWithContext(error.message,context),context),error.stack!==void 0&&(redacted.stack=redactKnownSecrets(redactMcpLogTextWithContext(error.stack,context),context)),redacted}function redactMcpLogEntries(value,context){let redacted={};for(let[key,item]of Object.entries(value))SENSITIVE_KEY_PATTERN.test(key)?redacted[key]=redactionForSecret(stringifySecretValue(item),context):redacted[key]=redactMcpLogData(item,context);return redacted}function stringifySecretValue(value){if(typeof value=="string")return value;if(typeof value=="number"||typeof value=="boolean"||typeof value=="bigint")return String(value);let seen=new WeakSet;return JSON.stringify(value,(_key,item)=>typeof item=="bigint"?item.toString():typeof item!="object"||item===null?item:seen.has(item)?"[Circular]":(seen.add(item),item))??String(value)}function redactionForSecret(secret,context){return secret.length>0&&!secret.startsWith("<redacted:")&&context.secrets.add(secret),redactionFor(secret)}function redactKnownSecrets(text,context){for(let secret of[...context.secrets].sort((left,right)=>right.length-left.length))text=text.split(secret).join(redactionFor(secret));return text}function redactionFor(secret){return`<redacted:${fingerprintSecret(secret)}>`}function sanitizeServerName(server){return server.replace(/[^A-Za-z0-9._-]+/g,"_")||"server"}var mcpElapsedClock={now:()=>performance.now(),schedule:setTimeout,cancel:clearTimeout};function wrapAsync(scope,fn,sink){return async(...args)=>{try{await fn(...args)}catch(error){let caughtError=error instanceof Error?error:normalizeCaughtError(error);await reportMcpAsyncError(scope,caughtError,sink)}}}function safeTimer(scope,delayMs,fn,sink){let wrapped=wrapAsync(scope,fn,sink),timer=setTimeout(()=>{wrapped()},delayMs);return timer.unref(),timer}function safeInterval(scope,delayMs,fn,sink){let wrapped=wrapAsync(scope,fn,sink),timer=setInterval(()=>{wrapped()},delayMs);return timer.unref(),timer}function safeDelay(delayMs){return new Promise(resolve=>{setTimeout(resolve,delayMs)})}function safeOn(emitter,eventName,scope,listener,sink){let wrapped=wrapAsync(scope,listener,sink);return emitter.on(eventName,wrapped),()=>{emitter.off(eventName,wrapped)}}function safeEventBusOn(bus,channel,handler){return bus.on(channel,handler)}async function reportMcpAsyncError(scope,error,sink){let normalized=normalizeError(error);if(logError(scope,normalized,sink.logger),!!sink.notify)try{await sink.notify(`MCP ${scope} failed: ${normalized.message}`,normalized)}catch(notifyError){let caughtNotifyError=notifyError instanceof Error?notifyError:normalizeCaughtError(notifyError);logError(`${scope}.notify`,caughtNotifyError,sink.logger)}}function logError(scope,error,logger){try{logger.error(scope,serializeError(error))}catch{let redactedScope=redactMcpLogText(scope);console.error(`MCP ${redactedScope} logger failed; suppressed async error details`)}}function serializeError(error){let serialized={name:error.name,message:error.message};return error.stack&&(serialized.stack=error.stack),serialized}function normalizeError(error){return error instanceof Error?error:normalizeCaughtError(error)}function normalizeCaughtError(error){return typeof error=="string"?new Error(error):new Error(safeStringify(error))}function safeStringify(value){try{return JSON.stringify(value)??String(value)}catch{return String(value)}}function memoizeLoader(load){let loaded,loading;return()=>loaded!==void 0?Promise.resolve(loaded):(loading??=load().then(module=>(loaded=module,module)).finally(()=>{loading=void 0}),loading)}var loadMcpSdkClient=memoizeLoader(()=>import("./client-WTYEICLH.js")),loadMcpSdkZodCompat=memoizeLoader(()=>import("./zod-compat-RJDXCU7S.js")),loadMcpSdkStdioTransport=memoizeLoader(()=>import("./stdio-YXDKKKQZ.js")),loadMcpSdkTypes=memoizeLoader(()=>import("./types-BJUEQ4II.js")),authModule,loadMcpSdkAuth=memoizeLoader(async()=>{let module=await import("./auth-C77UQA55.js");return authModule=module,module}),loadMcpSdkStreamableHttpTransport=memoizeLoader(async()=>{let[module]=await Promise.all([import("./streamableHttp-DKIBUWVY.js"),loadMcpSdkAuth()]);return module});function isMcpSdkUnauthorizedError(error){return authModule!==void 0&&error instanceof authModule.UnauthorizedError}var OAuthFlowError=class extends AuthError{constructor(oauthKind,message,options={}){super(message,options),this.name="OAuthFlowError",this.oauthKind=oauthKind,this.terminal=TERMINAL_KINDS.has(oauthKind)}},TERMINAL_KINDS=new Set(["s256_unsupported","needs_auth","invalid_grant","state_mismatch","expired_code","no_verifier","headless","missing_env"]),TERMINAL_OAUTH_CODES=new Set(["invalid_grant","invalid_token","invalid_client","unauthorized_client"]),TRANSIENT_OAUTH_CODES=new Set(["temporarily_unavailable","server_error","slow_down"]);function isInvalidGrant(error){let code=oauthErrorCode(error);if(code!==void 0)return TERMINAL_OAUTH_CODES.has(code);let text=errorText(error).toLowerCase();return text.includes("invalid_grant")||text.includes("invalid_token")}function isTransientTokenError(error){if(isInvalidGrant(error))return!1;let code=oauthErrorCode(error);if(code!==void 0&&TRANSIENT_OAUTH_CODES.has(code))return!0;let text=errorText(error).toLowerCase();return/\b(?:500|502|503|504)\b/.test(text)||text.includes("econnrefused")||text.includes("network")}function oauthErrorCode(error){if(typeof error!="object"||error===null)return;let code=error.errorCode;return typeof code=="string"?code:void 0}function errorText(error){return error instanceof Error?`${error.name} ${error.message}`:String(error)}var MAX_CAUSE_DEPTH=5;function isMcpNeedsAuthError(error,depth=0){return isMcpSdkUnauthorizedError(error)?!0:error instanceof OAuthFlowError?error.terminal:depth<MAX_CAUSE_DEPTH&&error!==null&&typeof error=="object"&&"cause"in error?isMcpNeedsAuthError(error.cause,depth+1):!1}var originOption=Symbol("mcp-request-origin"),origins=new WeakSet,aliases=new WeakMap,physicalMcpClient=client=>aliases.get(client)??client;function registerMcpClientAlias(alias,physical){aliases.set(alias,physical)}var legacyOperations=new WeakMap;function beginLegacyMcpOperation(client,origin,caller){let lifetime=new AbortController,operation={origin,signal:AbortSignal.any([origin.signal,lifetime.signal,...caller?[caller]:[]])},operations=legacyOperations.get(client);return operations||(operations=new Set,legacyOperations.set(client,operations)),operations.add(operation),()=>{operations.delete(operation),lifetime.abort(),operations.size===0&&legacyOperations.delete(client)}}function legacyMcpOperation(client){let operations=legacyOperations.get(client);if(operations&&operations.size>1)return"ambiguous";if(operations?.size!==1)return;let operation=operations.values().next().value;return operation&&!operation.signal.aborted&&operation.origin.isCurrent()?operation:void 0}function createMcpRequestOrigin(origin){return origins.add(origin),origin}function mcpRequestOptions(origin,options={}){return origin===void 0?options:{...options,[originOption]:origin}}function takeMcpRequestOrigin(options,client){let supplied=options,origin=supplied?.[originOption],{[originOption]:_origin,...sdkOptions}=supplied??{};if(origin!==void 0){if(!origins.has(origin)||!origin.isCurrent())throw new McpMrtrError("MCP_MRTR_CONTEXT_CHANGED");let candidate=origin.connection.client;if(physicalMcpClient(candidate)!==client)throw new McpMrtrError("MCP_MRTR_CONTEXT_CHANGED")}return{origin,sdkOptions}}var MCP_CLIENT_ELICITATION_CAPABILITY={elicitation:{}};function mcpClientCapabilities(elicitationEnabled=!0){return elicitationEnabled?MCP_CLIENT_ELICITATION_CAPABILITY:{}}var MCP_ELICITATION_TIMEOUT_MS=300*1e3,legacyUiProvider;async function rejectElicitation(){let{ErrorCode,McpError:McpError2}=await loadMcpSdkTypes();throw new McpError2(ErrorCode.InternalError,"Elicitation cannot be processed")}function legacyMcpFormEligible(provider,enabled){if(!enabled)return!1;if(provider?.eligible)return provider.eligible();let ui=provider?.(),binding=ui===void 0?void 0:privateMcpForms(ui);return binding===void 0||binding.capture()?.ready()===!0}async function rejectPrivateElicitation(){let{ErrorCode,McpError:McpError2}=await loadMcpSdkTypes();throw new McpError2(ErrorCode.InternalError,"Elicitation processing unavailable")}async function privateElicitation(client,params,signal,requestId,timeoutMs){let operation=legacyMcpOperation(client);if(operation==="ambiguous"){let{ErrorCode,McpError:McpError2}=await loadMcpSdkTypes();throw new McpError2(ErrorCode.InternalError,"Elicitation cannot be processed: ambiguous origin from concurrent legacy tools/call requests. Run these calls sequentially or use an MRTR server.",{reason:"ambiguous_legacy_origin"})}let presenter=operation?.origin.privateForm;if(!isRecord(params)||typeof params.message!="string"||params.mode!==void 0&¶ms.mode!=="form"||!operation||!presenter?.ready()||!validateMrtrForm(params.requestedSchema))return rejectPrivateElicitation();let outcome=await presenter.present({operationId:String(requestId),inputId:String(requestId),round:0,server:{label:operation.origin.serverLabel,source:operation.origin.serverSource??"user"},message:params.message,schema:params.requestedSchema,operationSignal:AbortSignal.any([operation.signal,signal]),presentationSignal:presenter.signal,deadlineMs:timeoutMs});return outcome.kind!=="result"||operation.signal.aborted||!operation.origin.isCurrent()?rejectPrivateElicitation():outcome.result}async function configureMcpElicitation(client,owner=legacyUiProvider,timeoutMs=MCP_ELICITATION_TIMEOUT_MS,elicitationEnabled=!0){if(!elicitationEnabled){let{ErrorCode,McpError:McpError2}=await loadMcpSdkTypes();client.fallbackRequestHandler=async request=>{if(request.method==="elicitation/create")return typeof owner=="function"&&owner.enforced?.()?rejectPrivateElicitation():rejectElicitation();throw new McpError2(ErrorCode.MethodNotFound,"Method not found")};return}let{ElicitRequestSchema}=await loadMcpSdkTypes();if(typeof owner=="function"&&owner.enforced?.()){client.setRequestHandler(ElicitRequestSchema.omit({params:!0}).passthrough(),(request,extra)=>privateElicitation(client,request.params,extra.signal,extra.requestId,timeoutMs));return}client.setRequestHandler(ElicitRequestSchema,async(request,extra)=>{let params=request.params;if(!("requestedSchema"in params))return rejectElicitation();let ui=typeof owner=="function"?owner():owner?.getMcpElicitationUi();return typeof owner=="function"&&owner.enforced?.()||ui!==void 0&&privateMcpForms(ui)!==void 0?privateElicitation(client,params,extra.signal,extra.requestId,timeoutMs):ui===void 0?rejectElicitation():await runElicitationForm(ui,params.message,params.requestedSchema,timeoutMs)})}async function runElicitationForm(ui,message,requestedSchema,timeoutMs=MCP_ELICITATION_TIMEOUT_MS){let timer,timeout=new Promise(resolve=>{timer=safeTimer("mcp.elicitation.timeout",timeoutMs,()=>resolve({action:"cancel"}),{logger:createMcpLogger("elicitation")})});try{return await Promise.race([collectForm(ui,message,requestedSchema),timeout])}finally{timer!==void 0&&clearTimeout(timer)}}async function collectForm(ui,message,requestedSchema){let content={},required=new Set(requestedSchema.required??[]);for(let[name,property]of Object.entries(requestedSchema.properties??{})){let title=`${message} - ${property.title??name}`;if(property.type==="boolean"){let picked=await ui.select(property.description?`${title}
|
|
4
|
+
`),fchmodSync(fd,384)}finally{closeSync3(fd)}}catch{this.#fileSinkRetryAt=Date.now()+LOG_SINK_RETRY_MS,this.#pushRing(this.#formatLine("warning","file sink disabled after write failure",void 0,"file"))}}};function redactMcpLogData(value,context){return typeof value=="string"?redactMcpLogTextWithContext(value,context):typeof value=="bigint"?value.toString():typeof value!="object"||value===null?value:context.seen.has(value)?"[Circular]":(context.seen.add(value),value instanceof Error?redactMcpLogError(value,context):Array.isArray(value)?value.map(item=>redactMcpLogData(item,context)):redactMcpLogEntries(value,context))}function redactMcpLogError(error,context){let redacted=redactMcpLogEntries(error,context);return redacted.name=redactMcpLogTextWithContext(error.name,context),redacted.message=redactKnownSecrets(redactMcpLogTextWithContext(error.message,context),context),error.stack!==void 0&&(redacted.stack=redactKnownSecrets(redactMcpLogTextWithContext(error.stack,context),context)),redacted}function redactMcpLogEntries(value,context){let redacted={};for(let[key,item]of Object.entries(value))SENSITIVE_KEY_PATTERN.test(key)?redacted[key]=redactionForSecret(stringifySecretValue(item),context):redacted[key]=redactMcpLogData(item,context);return redacted}function stringifySecretValue(value){if(typeof value=="string")return value;if(typeof value=="number"||typeof value=="boolean"||typeof value=="bigint")return String(value);let seen=new WeakSet;return JSON.stringify(value,(_key,item)=>typeof item=="bigint"?item.toString():typeof item!="object"||item===null?item:seen.has(item)?"[Circular]":(seen.add(item),item))??String(value)}function redactionForSecret(secret,context){return secret.length>0&&!secret.startsWith("<redacted:")&&context.secrets.add(secret),redactionFor(secret)}function redactKnownSecrets(text,context){for(let secret of[...context.secrets].sort((left,right)=>right.length-left.length))text=text.split(secret).join(redactionFor(secret));return text}function redactionFor(secret){return`<redacted:${fingerprintSecret(secret)}>`}function sanitizeServerName(server){return server.replace(/[^A-Za-z0-9._-]+/g,"_")||"server"}var mcpElapsedClock={now:()=>performance.now(),schedule:setTimeout,cancel:clearTimeout};function wrapAsync(scope,fn,sink){return async(...args)=>{try{await fn(...args)}catch(error){let caughtError=error instanceof Error?error:normalizeCaughtError(error);await reportMcpAsyncError(scope,caughtError,sink)}}}function safeTimer(scope,delayMs,fn,sink){let wrapped=wrapAsync(scope,fn,sink),timer=setTimeout(()=>{wrapped()},delayMs);return timer.unref(),timer}function safeInterval(scope,delayMs,fn,sink){let wrapped=wrapAsync(scope,fn,sink),timer=setInterval(()=>{wrapped()},delayMs);return timer.unref(),timer}function safeDelay(delayMs){return new Promise(resolve=>{setTimeout(resolve,delayMs)})}function safeOn(emitter,eventName,scope,listener,sink){let wrapped=wrapAsync(scope,listener,sink);return emitter.on(eventName,wrapped),()=>{emitter.off(eventName,wrapped)}}function safeEventBusOn(bus,channel,handler){return bus.on(channel,handler)}async function reportMcpAsyncError(scope,error,sink){let normalized=normalizeError(error);if(logError(scope,normalized,sink.logger),!!sink.notify)try{await sink.notify(`MCP ${scope} failed: ${normalized.message}`,normalized)}catch(notifyError){let caughtNotifyError=notifyError instanceof Error?notifyError:normalizeCaughtError(notifyError);logError(`${scope}.notify`,caughtNotifyError,sink.logger)}}function logError(scope,error,logger){try{logger.error(scope,serializeError(error))}catch{let redactedScope=redactMcpLogText(scope);console.error(`MCP ${redactedScope} logger failed; suppressed async error details`)}}function serializeError(error){let serialized={name:error.name,message:error.message};return error.stack&&(serialized.stack=error.stack),serialized}function normalizeError(error){return error instanceof Error?error:normalizeCaughtError(error)}function normalizeCaughtError(error){return typeof error=="string"?new Error(error):new Error(safeStringify(error))}function safeStringify(value){try{return JSON.stringify(value)??String(value)}catch{return String(value)}}function memoizeLoader(load){let loaded,loading;return()=>loaded!==void 0?Promise.resolve(loaded):(loading??=load().then(module=>(loaded=module,module)).finally(()=>{loading=void 0}),loading)}var loadMcpSdkClient=memoizeLoader(()=>import("./client-WTYEICLH.js")),loadMcpSdkZodCompat=memoizeLoader(()=>import("./zod-compat-RJDXCU7S.js")),loadMcpSdkStdioTransport=memoizeLoader(()=>import("./stdio-YXDKKKQZ.js")),loadMcpSdkTypes=memoizeLoader(()=>import("./types-BJUEQ4II.js")),authModule,loadMcpSdkAuth=memoizeLoader(async()=>{let module=await import("./auth-C77UQA55.js");return authModule=module,module}),loadMcpSdkStreamableHttpTransport=memoizeLoader(async()=>{let[module]=await Promise.all([import("./streamableHttp-DKIBUWVY.js"),loadMcpSdkAuth()]);return module});function isMcpSdkUnauthorizedError(error){return authModule!==void 0&&error instanceof authModule.UnauthorizedError}var OAuthFlowError=class extends AuthError{constructor(oauthKind,message,options={}){super(message,options),this.name="OAuthFlowError",this.oauthKind=oauthKind,this.terminal=TERMINAL_KINDS.has(oauthKind)}},TERMINAL_KINDS=new Set(["s256_unsupported","needs_auth","invalid_grant","state_mismatch","expired_code","no_verifier","headless","missing_env"]),TERMINAL_OAUTH_CODES=new Set(["invalid_grant","invalid_token","invalid_client","unauthorized_client"]),TRANSIENT_OAUTH_CODES=new Set(["temporarily_unavailable","server_error","slow_down"]);function isInvalidGrant(error){let code=oauthErrorCode(error);if(code!==void 0)return TERMINAL_OAUTH_CODES.has(code);let text=errorText(error).toLowerCase();return text.includes("invalid_grant")||text.includes("invalid_token")}function isTransientTokenError(error){if(isInvalidGrant(error))return!1;let code=oauthErrorCode(error);if(code!==void 0&&TRANSIENT_OAUTH_CODES.has(code))return!0;let text=errorText(error).toLowerCase();return/\b(?:500|502|503|504)\b/.test(text)||text.includes("econnrefused")||text.includes("network")}function oauthErrorCode(error){if(typeof error!="object"||error===null)return;let code=error.errorCode;return typeof code=="string"?code:void 0}function errorText(error){return error instanceof Error?`${error.name} ${error.message}`:String(error)}var MAX_CAUSE_DEPTH=5;function isMcpNeedsAuthError(error,depth=0){return isMcpSdkUnauthorizedError(error)?!0:error instanceof OAuthFlowError?error.terminal:depth<MAX_CAUSE_DEPTH&&error!==null&&typeof error=="object"&&"cause"in error?isMcpNeedsAuthError(error.cause,depth+1):!1}var originOption=Symbol("mcp-request-origin"),origins=new WeakSet,aliases=new WeakMap,physicalMcpClient=client=>aliases.get(client)??client;function registerMcpClientAlias(alias,physical){aliases.set(alias,physical)}var legacyOperations=new WeakMap;function beginLegacyMcpOperation(client,origin,caller){let lifetime=new AbortController,operation={origin,signal:AbortSignal.any([origin.signal,lifetime.signal,...caller?[caller]:[]])},operations=legacyOperations.get(client);return operations||(operations=new Set,legacyOperations.set(client,operations)),operations.add(operation),()=>{operations.delete(operation),lifetime.abort(),operations.size===0&&legacyOperations.delete(client)}}function legacyMcpOperation(client){let operations=legacyOperations.get(client);if(operations&&operations.size>1)return"ambiguous";if(operations?.size!==1)return;let operation=operations.values().next().value;return operation&&!operation.signal.aborted&&operation.origin.isCurrent()?operation:void 0}function createMcpRequestOrigin(origin){return origins.add(origin),origin}function mcpRequestOptions(origin,options={}){return origin===void 0?options:{...options,[originOption]:origin}}function takeMcpRequestOrigin(options,client){let supplied=options,origin=supplied?.[originOption],{[originOption]:_origin,...sdkOptions}=supplied??{};if(origin!==void 0){if(!origins.has(origin)||!origin.isCurrent())throw new McpMrtrError("MCP_MRTR_CONTEXT_CHANGED");let candidate=origin.connection.client;if(physicalMcpClient(candidate)!==client)throw new McpMrtrError("MCP_MRTR_CONTEXT_CHANGED")}return{origin,sdkOptions}}var MCP_CLIENT_ELICITATION_CAPABILITY={elicitation:{}};function mcpClientCapabilities(elicitationEnabled=!0){return elicitationEnabled?MCP_CLIENT_ELICITATION_CAPABILITY:{}}var MCP_ELICITATION_TIMEOUT_MS=300*1e3,legacyUiProvider;async function rejectElicitation(){let{ErrorCode,McpError:McpError2}=await loadMcpSdkTypes();throw new McpError2(ErrorCode.InternalError,"Elicitation cannot be processed")}function legacyMcpFormEligible(provider,enabled){if(!enabled)return!1;if(provider?.eligible)return provider.eligible();let ui=provider?.(),binding=ui===void 0?void 0:privateMcpForms(ui);return binding===void 0||binding.capture()?.ready()===!0}async function rejectPrivateElicitation(){let{ErrorCode,McpError:McpError2}=await loadMcpSdkTypes();throw new McpError2(ErrorCode.InternalError,"Elicitation processing unavailable")}async function privateElicitation(client,params,signal,requestId,timeoutMs){let operation=legacyMcpOperation(client);if(operation==="ambiguous")return rejectPrivateElicitation();let presenter=operation?.origin.privateForm;if(!isRecord(params)||typeof params.message!="string"||params.mode!==void 0&¶ms.mode!=="form"||!operation||!presenter?.ready()||!validateMrtrForm(params.requestedSchema))return rejectPrivateElicitation();let outcome=await presenter.present({operationId:String(requestId),inputId:String(requestId),round:0,server:{label:operation.origin.serverLabel,source:operation.origin.serverSource??"user"},message:params.message,schema:params.requestedSchema,operationSignal:AbortSignal.any([operation.signal,signal]),presentationSignal:presenter.signal,deadlineMs:timeoutMs});return outcome.kind!=="result"||operation.signal.aborted||!operation.origin.isCurrent()?rejectPrivateElicitation():outcome.result}async function configureMcpElicitation(client,owner=legacyUiProvider,timeoutMs=MCP_ELICITATION_TIMEOUT_MS,elicitationEnabled=!0){if(!elicitationEnabled){let{ErrorCode,McpError:McpError2}=await loadMcpSdkTypes();client.fallbackRequestHandler=async request=>{if(request.method==="elicitation/create")return typeof owner=="function"&&owner.enforced?.()?rejectPrivateElicitation():rejectElicitation();throw new McpError2(ErrorCode.MethodNotFound,"Method not found")};return}let{ElicitRequestSchema}=await loadMcpSdkTypes();if(typeof owner=="function"&&owner.enforced?.()){client.setRequestHandler(ElicitRequestSchema.omit({params:!0}).passthrough(),(request,extra)=>privateElicitation(client,request.params,extra.signal,extra.requestId,timeoutMs));return}client.setRequestHandler(ElicitRequestSchema,async(request,extra)=>{let params=request.params;if(!("requestedSchema"in params))return rejectElicitation();let ui=typeof owner=="function"?owner():owner?.getMcpElicitationUi();return typeof owner=="function"&&owner.enforced?.()||ui!==void 0&&privateMcpForms(ui)!==void 0?privateElicitation(client,params,extra.signal,extra.requestId,timeoutMs):ui===void 0?rejectElicitation():await runElicitationForm(ui,params.message,params.requestedSchema,timeoutMs)})}async function runElicitationForm(ui,message,requestedSchema,timeoutMs=MCP_ELICITATION_TIMEOUT_MS){let timer,timeout=new Promise(resolve=>{timer=safeTimer("mcp.elicitation.timeout",timeoutMs,()=>resolve({action:"cancel"}),{logger:createMcpLogger("elicitation")})});try{return await Promise.race([collectForm(ui,message,requestedSchema),timeout])}finally{timer!==void 0&&clearTimeout(timer)}}async function collectForm(ui,message,requestedSchema){let content={},required=new Set(requestedSchema.required??[]);for(let[name,property]of Object.entries(requestedSchema.properties??{})){let title=`${message} - ${property.title??name}`;if(property.type==="boolean"){let picked=await ui.select(property.description?`${title}
|
|
5
5
|
${property.description}`:title,["Yes","No"]);if(picked===void 0)return{action:"cancel"};switch(picked.trim().toLowerCase()){case"yes":case"y":case"true":content[name]=!0;break;case"no":case"n":case"false":content[name]=!1;break;default:return rejectElicitation()}continue}if(Array.isArray(property.enum)&&property.enum.length>0){let picked=await ui.select(title,property.enum.map(String));if(picked===void 0)return{action:"cancel"};content[name]=picked;continue}let answer=await ui.input(title,property.description);if(answer===void 0)return{action:"cancel"};if(answer.length===0){if(required.has(name))return rejectElicitation();continue}if(property.type==="number"||property.type==="integer"){let parsed=Number(answer);if(!Number.isFinite(parsed))return rejectElicitation();content[name]=parsed;continue}content[name]=answer}return Object.keys(content).length===0&&await ui.select(message,["Submit"])!=="Submit"?{action:"cancel"}:{action:"accept",content}}import{stripVTControlCharacters}from"node:util";var own=(value,key)=>Object.hasOwn(value,key),inert=value=>stripVTControlCharacters(value).replace(/[\u0000-\u0008\u000b-\u001f\u007f-\u009f]/g,"");async function collectMrtrForm(presentation,serverLabel,params,signal){if(!validateMrtrForm(params.requestedSchema))throw new McpMrtrError("MCP_MRTR_INVALID_INPUT");let schema=params.requestedSchema,abort=new AbortController,combined=AbortSignal.any([signal,presentation.signal,abort.signal]),opts={signal:combined,ephemeral:!0};bindMcpFormPresented(opts,presentation.presented);let heading=`MCP server: ${inert(serverLabel)}
|
|
6
6
|
${inert(params.message)}`,select=async(title,choices)=>{if(combined.aborted)return;let result=await presentation.ui.select(title,choices,opts);return combined.aborted?void 0:result},content=Object.create(null),finish=result=>(combined.aborted||presentation.admit?.(),result),required=new Set(schema.required??[]),entries=Object.entries(schema.properties),field=async(name,property)=>{let title=`${heading}
|
|
7
7
|
${inert(String(property.title??name))}${typeof property.description=="string"?`
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url); { const __piWorkerThreads = require("node:worker_threads"); if (typeof __piWorkerThreads.markAsUncloneable !== "function") { __piWorkerThreads.markAsUncloneable = () => {}; } }
|
|
2
|
-
import{listHostEndpoints}from"./chunk-
|
|
2
|
+
import{listHostEndpoints}from"./chunk-PT6JJUN2.js";import{randomBytes}from"node:crypto";var MONITOR_ID_ALPHABET="0123456789ABCDEFGHJKMNPQRSTVWXYZ";function allocateMonitorId(){let id="mon_",buffer=0,bits=0;for(let byte of randomBytes(10))for(buffer=buffer<<8|byte,bits+=8;bits>=5;)bits-=5,id+=MONITOR_ID_ALPHABET[buffer>>bits&31];return id}var STATUS_KINDS=new Set(["session_status","effect_status"]);function parseRpcTarget(target,selfDurableId){let trimmed=target.trim();return trimmed===""?{error:'target is empty; pass "children", "all" or a session id, path or st_ task id'}:trimmed==="children"?selfDurableId===void 0?{error:'target "children" needs a session with a durable id; save the session first, or watch "all"'}:{kind:"children",parent:selfDurableId}:trimmed==="all"?{kind:"all"}:trimmed.startsWith("st_")?{kind:"task",taskId:trimmed}:{kind:"id",id:trimmed}}function defaultEvents(target){return target.kind==="children"?["session_status","effect_status"]:["session_status"]}function subscriptionFor(target,events){let sessions=target.kind==="children"?{childrenOf:target.parent}:target.kind==="id"?{ids:[target.id]}:"all",content=events==="all"?"all":events.filter(kind=>!STATUS_KINDS.has(kind)),mirror=content==="all"?"all":content.length===0?void 0:content;return{sessions,include_workers:!0,include_context:target.kind==="children"||target.kind==="task",effects:events==="all"||events.includes("effect_status"),...mirror===void 0?{}:{mirror}}}function wantsRecord(events,exclude,type){return exclude.includes(type)?!1:events==="all"||events.includes(type)}function matchesTask(target,row){return target.kind!=="task"?!0:row.context?.task_id===target.taskId}async function endpointSockets(agentDir){return(await listHostEndpoints(agentDir)).map(endpoint=>endpoint.socket).filter(socket=>socket!==null)}export{allocateMonitorId,parseRpcTarget,defaultEvents,subscriptionFor,wantsRecord,matchesTask,endpointSockets};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url); { const __piWorkerThreads = require("node:worker_threads"); if (typeof __piWorkerThreads.markAsUncloneable !== "function") { __piWorkerThreads.markAsUncloneable = () => {}; } }
|
|
2
|
+
var MONTHS=["jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec"],RESET_AT_KEYS=new Set(["resets_at"]),RESET_AFTER_SECONDS_KEYS=new Set(["reset_after_seconds"]),RELATIVE_RE=/\b(?:resets?|try again|retry)\s+in\s+~?((?:\d+(?:\.\d+)?\s*(?:days?|d|hours?|hrs?|h|minutes?|mins?|m|seconds?|secs?|s)\b(?:\s*,?\s*(?:and\s+)?)?)+)/i,RELATIVE_PART_RE=/(\d+(?:\.\d+)?)\s*(days?|d|hours?|hrs?|h|minutes?|mins?|m|seconds?|secs?|s)\b/gi,CLOCK_RE=/\b(?:resets?|try again)\s+(?:at\s+|on\s+)?(?:([a-z]{3})[a-z]*\.?\s+(\d{1,2}),?\s+(?:at\s+)?)?(\d{1,2})(?::(\d{2}))?\s*([ap])\.?\s?m\b\.?(?:\s*\(([A-Za-z_]+(?:\/[A-Za-z0-9_+-]+)*)\))?/i;function usageLimitResetMs(text,nowMs){return usageLimitReset(text,nowMs)?.ms}function usageLimitReset(text,nowMs){let json=fromJsonFields(text,nowMs);if(json!==void 0)return{ms:json,kind:"absolute"};let relative=fromRelativeProse(text);if(relative!==void 0)return{ms:relative,kind:"relative"};let clock=fromClockProse(text,nowMs);return clock===void 0?void 0:{ms:clock,kind:"absolute"}}function fromJsonFields(text,nowMs){let start=text.indexOf("{");if(start<0)return;let parsed;try{parsed=JSON.parse(text.slice(start))}catch{return}let found;return walk(parsed,(key,value)=>{let ms=RESET_AT_KEYS.has(key)?absoluteFieldMs(value,nowMs):RESET_AFTER_SECONDS_KEYS.has(key)?secondsFieldMs(value):void 0;ms!==void 0&&(found===void 0||ms>found)&&(found=ms)}),found}function walk(value,visit){if(Array.isArray(value)){for(let item of value)walk(item,visit);return}if(!(typeof value!="object"||value===null))for(let[key,entry]of Object.entries(value))visit(key,entry),walk(entry,visit)}function absoluteFieldMs(value,nowMs){if(typeof value=="number"&&Number.isFinite(value)&&value>0){let epochMs=value<1e12?value*1e3:value;return Math.max(0,Math.ceil(epochMs-nowMs))}if(typeof value=="string"&&/\d{4}-\d{2}-\d{2}T/.test(value)){let epochMs=Date.parse(value);return Number.isNaN(epochMs)?void 0:Math.max(0,epochMs-nowMs)}}function secondsFieldMs(value){return typeof value=="number"&&Number.isFinite(value)&&value>=0?Math.ceil(value*1e3):void 0}function fromRelativeProse(text){let phrase=RELATIVE_RE.exec(text)?.[1];if(phrase===void 0)return;let total=0;for(let[,amount,unit]of phrase.matchAll(RELATIVE_PART_RE))total+=Number.parseFloat(amount??"0")*unitMs(unit??"");return Math.ceil(total)}function unitMs(unit){let u=unit.toLowerCase();return u.startsWith("d")?864e5:u.startsWith("h")?36e5:u==="s"||u.startsWith("sec")?1e3:6e4}function fromClockProse(text,nowMs){let match=CLOCK_RE.exec(text);if(!match)return;let[,monthName,dayText,hourText,minuteText,meridiem,zoneText]=match,hour12=Number.parseInt(hourText??"",10),minute=minuteText===void 0?0:Number.parseInt(minuteText,10);if(hour12<1||hour12>12||minute>59)return;let hour=hour12%12+(meridiem?.toLowerCase()==="p"?12:0),zone=zoneText??Intl.DateTimeFormat().resolvedOptions().timeZone;if(!isValidTimeZone(zone))return;let today=zonedParts(zone,nowMs);if(monthName!==void 0){let month=MONTHS.indexOf(monthName.toLowerCase()),day=Number.parseInt(dayText??"",10);if(month<0||day<1||day>31)return;let target2=zonedToEpoch(zone,today.year,month,day,hour,minute);return target2<=nowMs&&(target2=zonedToEpoch(zone,today.year+1,month,day,hour,minute)),target2-nowMs}let target=zonedToEpoch(zone,today.year,today.month,today.day,hour,minute);return target<=nowMs&&(target=zonedToEpoch(zone,today.year,today.month,today.day+1,hour,minute)),target-nowMs}function isValidTimeZone(zone){try{return new Intl.DateTimeFormat("en-US",{timeZone:zone}),!0}catch{return!1}}function zonedParts(zone,epochMs){let parts=new Intl.DateTimeFormat("en-US",{timeZone:zone,hourCycle:"h23",year:"numeric",month:"numeric",day:"numeric",hour:"numeric",minute:"numeric",second:"numeric"}).formatToParts(epochMs),get=type=>Number.parseInt(parts.find(part=>part.type===type)?.value??"0",10);return{year:get("year"),month:get("month")-1,day:get("day"),hour:get("hour"),minute:get("minute"),second:get("second")}}function zoneOffsetMs(zone,epochMs){let p=zonedParts(zone,epochMs);return Date.UTC(p.year,p.month,p.day,p.hour,p.minute,p.second)-Math.floor(epochMs/1e3)*1e3}function zonedToEpoch(zone,year,month,day,hour,minute){let wall=Date.UTC(year,month,day,hour,minute),first=wall-zoneOffsetMs(zone,wall);return wall-zoneOffsetMs(zone,first)}export{usageLimitResetMs,usageLimitReset};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url); { const __piWorkerThreads = require("node:worker_threads"); if (typeof __piWorkerThreads.markAsUncloneable !== "function") { __piWorkerThreads.markAsUncloneable = () => {}; } }
|
|
3
|
+
import"./chunk-MYAENL22.js";import{enableStartupCompileCache}from"./chunk-3QCYBOKN.js";import"./chunk-UFJ2K7Q7.js";import{installStaleExtensionContainment,main}from"./chunk-C2MQ4QXN.js";import"./chunk-5JJDR6XI.js";import"./chunk-FHXR4ZAC.js";import"./chunk-7CNOCJCN.js";import{configureHttpDispatcher}from"./chunk-4MOZXOJX.js";import"./chunk-DXJJP6RP.js";import"./chunk-GXY5JEI5.js";import"./chunk-DODH3N6U.js";import"./chunk-GY5MR5KR.js";import"./chunk-E6D4RIT7.js";import"./chunk-XF3LJC3O.js";import"./chunk-CNPDUC4D.js";import"./chunk-MLVIYDHK.js";import"./chunk-TBU6VYHN.js";import"./chunk-JPGT64RV.js";import"./chunk-V2UYXTRR.js";import"./chunk-N7IN46Q5.js";import"./chunk-STMXIBXF.js";import"./chunk-QMRJYMNH.js";import"./chunk-PT6JJUN2.js";import"./chunk-TIVW4P37.js";import"./chunk-H4QOEVS5.js";import"./chunk-JMOUU75H.js";import"./chunk-XMJKZK5H.js";import"./chunk-6VWIMHMH.js";import"./chunk-4AOMNOGY.js";import"./chunk-KLAX467B.js";import"./chunk-JFFS72FL.js";import"./chunk-ORXZXUMC.js";import"./chunk-GZVCRV7I.js";import"./chunk-KUPQO7MC.js";import"./chunk-SOMFLLPD.js";import"./chunk-WD6WBYC5.js";import"./chunk-26UBFF6N.js";import"./chunk-MTQQ2VQH.js";import"./chunk-KNVNKDER.js";import"./chunk-KKD4CYCI.js";import"./chunk-KXB5WIS5.js";import"./chunk-LOIF6PHI.js";import"./chunk-BZ7726QO.js";import"./chunk-4WZRVZNX.js";import"./chunk-U3VOXCGP.js";import"./chunk-SBGIXMX3.js";import"./chunk-YI7SPFDN.js";import"./chunk-HB35RBP4.js";import"./chunk-Z6WGAK7W.js";import"./chunk-DLAY7CIU.js";import"./chunk-3BTN337S.js";import"./chunk-QXREUA5F.js";import"./chunk-RUGYFYH7.js";import"./chunk-OEFCY46F.js";import"./chunk-KRNXUTZJ.js";import"./chunk-TAV6QZFM.js";import"./chunk-PELNNWGO.js";import"./chunk-TTU2RNVX.js";import"./chunk-FDL4CF6F.js";import"./chunk-BWA4FVFW.js";import"./chunk-YU4AYH4C.js";import"./chunk-E6WYH3ZL.js";import"./chunk-COH5F7QV.js";import"./chunk-RFB5CBW7.js";import"./chunk-2VZJTDUX.js";import"./chunk-E4LBKOZG.js";import"./chunk-GVSBCJFI.js";import"./chunk-WASCMT6Y.js";import"./chunk-T36LJ6MW.js";import"./chunk-QGJLZ6BI.js";import"./chunk-WHPDEDCC.js";import"./chunk-AA2L2RHH.js";import"./chunk-HK46JMSC.js";import"./chunk-4P7WARQZ.js";import"./chunk-WDTJ6JKE.js";import"./chunk-5ROMKDLK.js";import"./chunk-3W47LTXQ.js";import"./chunk-6AOVUTUR.js";import"./chunk-45SZOLCU.js";import"./chunk-DMI55M2N.js";import"./chunk-PJ34QVL5.js";import"./chunk-BMX2U22F.js";import"./chunk-YU2P3CAR.js";import{installEarlyInspectorVmImportRecovery}from"./chunk-2RB5EL4X.js";import"./chunk-ZOFZRJSL.js";import"./chunk-2SOVDETB.js";import"./chunk-V3CK2AVC.js";import"./chunk-VRDU425E.js";import"./chunk-ZGAB7WQA.js";import{APP_NAME,scrubBrandFromEnvironment}from"./chunk-7YO7VQZW.js";import"./chunk-ATQFN5HI.js";import"./chunk-MIENF2YK.js";import"./chunk-OXNWERO4.js";import"./chunk-QN2BHP3M.js";import"./chunk-NTK2MHJ5.js";import"./chunk-O5RYI3IW.js";import"./chunk-IKOFCODM.js";await enableStartupCompileCache();installEarlyInspectorVmImportRecovery();installStaleExtensionContainment();process.title=APP_NAME;scrubBrandFromEnvironment();process.env.PI_CODING_AGENT="true";process.emitWarning=(()=>{});configureHttpDispatcher();await main(process.argv.slice(2));
|