@code-yeongyu/senpi 2026.10.2 → 2026.10.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/dist/bundle/chunks/{app-server-command-SZJAJX5J.js → app-server-command-VSOBULUS.js} +1 -1
- package/dist/bundle/chunks/{chunk-PA7DXEUM.js → chunk-2EYJJDES.js} +13 -30
- package/dist/bundle/chunks/{chunk-LACVPFMM.js → chunk-ATACOV2Q.js} +3 -3
- package/dist/bundle/chunks/{chunk-2NAN2JVY.js → chunk-E6TL3R3I.js} +1 -1
- package/dist/bundle/chunks/chunk-Q23IMPRD.js +6 -0
- package/dist/bundle/chunks/{chunk-GIK2N57G.js → chunk-WIBTUARS.js} +20 -2
- package/dist/bundle/chunks/chunk-XOUTBUAV.js +24 -0
- package/dist/bundle/chunks/{cli-main-B66BJ6WS.js → cli-main-RH4BAWCJ.js} +1 -1
- package/dist/bundle/chunks/{host-command-ESRPUXI2.js → host-command-2ZP7B3DA.js} +1 -1
- package/dist/bundle/chunks/{host-lifecycle-P65B4FWL.js → host-lifecycle-3ZZLFX55.js} +1 -1
- package/dist/bundle/chunks/host-lifecycle.js +2 -2
- package/dist/bundle/chunks/{interactive-mode-LBS4DGTM.js → interactive-mode-LBBIPYPZ.js} +1 -1
- package/dist/bundle/chunks/{multi-session-host-5C2TC4BN.js → multi-session-host-GFWO2JUC.js} +1 -1
- package/dist/bundle/chunks/{package-manager-cli-K3JGGB65.js → package-manager-cli-VHCS5NXO.js} +1 -1
- package/dist/bundle/chunks/{rpc-mode-FJGYYLVG.js → rpc-mode-KAZWRS2K.js} +1 -1
- package/dist/bundle/chunks/{schedule-command-BT36FE6F.js → schedule-command-OUALJDGD.js} +1 -1
- package/dist/bundle/chunks/{session-picker-MMTSHPR5.js → session-picker-UYF62GAF.js} +1 -1
- package/dist/bundle/chunks/session-worker.js +35 -34
- package/dist/bundle/cli.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/agent-session.d.ts +4 -0
- package/dist/core/agent-session.js +60 -27
- package/dist/core/extensions/builtin/mcp/index.js +19 -10
- package/dist/core/extensions/builtin/mcp/service-register.d.ts +1 -0
- package/dist/core/extensions/builtin/mcp/service-register.js +2 -4
- package/dist/core/extensions/builtin/mcp/service-tools-changed.d.ts +11 -2
- package/dist/core/extensions/builtin/mcp/service-tools-changed.js +33 -6
- package/dist/core/extensions/builtin/mcp/service-types.d.ts +0 -2
- package/dist/core/extensions/builtin/mcp/service.d.ts +18 -8
- package/dist/core/extensions/builtin/mcp/service.js +231 -76
- package/dist/core/settings-manager.d.ts +2 -0
- package/dist/core/settings-manager.js +7 -0
- package/dist/core/skill-invocation.d.ts +10 -2
- package/dist/core/skill-invocation.js +13 -3
- package/dist/core/webview/native-webview.d.ts +1 -0
- package/dist/core/webview/webview-client.d.ts +5 -2
- package/dist/core/webview/webview-client.js +1 -1
- package/dist/core/webview/webview-readiness.d.ts +41 -0
- package/dist/core/webview/webview-readiness.js +48 -0
- package/dist/core/webview/webview-service.d.ts +8 -1
- package/dist/core/webview/webview-service.js +56 -16
- package/dist/modes/rpc/host-exec-argv.d.ts +7 -0
- package/dist/modes/rpc/host-exec-argv.js +45 -0
- package/dist/modes/rpc/host-launch.js +3 -2
- package/dist/modes/rpc/host-lifecycle.js +2 -1
- package/docs/rpc.md +2 -0
- package/docs/settings.md +1 -0
- package/docs/skills.md +4 -2
- package/package.json +6 -6
- package/dist/bundle/chunks/chunk-UB2RTUY7.js +0 -24
- package/dist/bundle/chunks/chunk-XOZFAFCS.js +0 -6
|
@@ -0,0 +1,24 @@
|
|
|
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,EXTENSION_EVENTS_CAPABILITY,RPC_CLIENT_CAPABILITIES_ENV,SESSION_CONTEXT_CAPABILITY,SESSION_KIND_CAPABILITY,hostLaunchProfile,socketHostLaunchProfile}from"./chunk-LJWC5IVX.js";import{BUILTIN_PATH_PREFIX}from"./chunk-QMRJYMNH.js";import{acquireHostEnsureLock,acquireOwnershipSafeLock,anyGenerationLive,endpointKindOfSocket,gcHostEndpoints,hostEnsureLockOptions,hostEnsureLockTarget,listHostEndpoints,socketNeedsHandshake}from"./chunk-6KIZRGOT.js";import{DEFAULT_HOST_IDLE_EXIT_MS,INTERNAL_SUPERVISOR_FLAG,OBSERVE_REQUEST_FIELD,readHostCrashRecords,resolveCliMainPath,rpcHostExecArgv}from"./chunk-ATACOV2Q.js";import{HOST_GENERATION_ENV,HOST_INSTANCE_ID_ENV}from"./chunk-CIRZTP7W.js";import{HOST_DAEMON_DIR_ENV,HOST_STATE_FILE_MODE,MAX_SOCKET_PATH_BYTES,ProcessIdentityUnreadableError,claimOwnerIsLive,clearHostRegistration,createDaemonDirectories,createHostDaemonPaths,createSocketSecret,ensureEndpointIdentity,generationBindPath,generationPaths,hostDaemonDirectoryPaths,parseDaemonPidFile,parseJson,parseShardSocket,processIsLive,processMatchesPidFile,provenOwner,pruneDeadGenerations,readFileOrUndefined,readGenerationRows,readHostProcessMetrics,readHostRegistration,readHostSettings,readProcessStartTime,readSessionPathClaims,readSocketSecret,releaseGeneration,resolveSocketTransportAddress,sameEndpoint,sendSocketHandshake,sessionDirectoryRemoved,shardKey,shardSocketPathForKey,socketSecretPath,statSocketIdentity,waitForStartTime,writeGenerationRecord,writeHostRegistration,writeHostSettings,writeStateFile,writtenByThisProcess}from"./chunk-22DAHAHO.js";import{compareEngineOrdinal,engineBuildIdentity}from"./chunk-XYDZ3LIE.js";import{isSessionRuntimeKind}from"./chunk-MH2BFYGN.js";import{APP_NAME,ENV_AGENT_DIR,envValue,getAgentDir,isBunBinary}from"./chunk-463OK2Y4.js";import{writeSync}from"node:fs";import{join as join5,resolve as resolve3}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,/^(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],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","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"?ALLOWED_ENV_NAMES.some(pattern=>pattern.test(name)):WINDOWS_SYSTEM_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{createHash}from"node:crypto";import{existsSync}from"node:fs";import{readdir,readFile as readFile2,realpath as realpath2,stat as stat2}from"node:fs/promises";import{basename,dirname as dirname2,join as join2,relative as relative2,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=dirname2(fileURLToPath(import.meta.url)),packageRoot=nearestPackageRoot(moduleDir),[top,next]=relative2(packageRoot,moduleDir).split(sep);return top==="dist"?{flavour:"packaged",root:join2(packageRoot,next==="bundle"?join2("dist","bundle"):"dist")}:{flavour:"dev",root:join2(packageRoot,top??"")}}function nearestPackageRoot(start){for(let dir=start;;dir=dirname2(dir)){if(existsSync(join2(dir,"package.json")))return dir;if(dirname2(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 stat2(root)).isFile()?files.push(["",root]):await collect(await realpath2(root),"",files,new Set);let digests=await mapLimited(files,READ_CONCURRENCY,async([path,file])=>[path,sha256(await readFile2(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=join2(dir,entry.name),name=prefix===""?entry.name:`${prefix}/${entry.name}`,kind=entry.isSymbolicLink()?await stat2(path).catch(()=>{}):entry;kind!==void 0&&(kind.isDirectory()?await collect(await realpath2(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(!isRecord2(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,...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},...isRecord2(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(!isRecord2(value)||typeof value.profile_id!="string"||!isRecord2(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 isRecord2(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}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){super(`RPC socket ${socket} refused: ${reason} - ${refusalDetail(reason,host)}${detail?`: ${detail}`:""}`),this.name="HostEnsureRefusedError",this.socket=socket,this.reason=reason,this.detail=detail}};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"its pidfile was written by another process, so this one may not signal it; stop that host explicitly instead";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";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.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 covers(client.launchProfile,host.launch_profile)?"profile_mismatch_attached":"profile_narrower_attached"}function covers(candidate,running){return candidate===void 0||running===void 0?!1:running.core.extensions.every(extension=>candidate.core.extensions.includes(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{spawn as spawn2}from"node:child_process";import{randomUUID as randomUUID2}from"node:crypto";import{mkdir,open as open2,readdir as readdir2,readFile as readFile3,rm as rm2,writeFile as writeFile2}from"node:fs/promises";import{tmpdir}from"node:os";import{dirname as dirname5,join as join4}from"node:path";import{createConnection}from"node:net";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,PROBE_REQUEST_ID="ensure-host-probe";function probeHost(options){return probeProtocolInfo(options.socket,options.timeoutMs??DEFAULT_PROBE_TIMEOUT_MS)}async function probeProtocolInfo(socketPath,timeoutMs){let reply=await requestOnSocket(socketPath,{type:"get_protocol_info"},timeoutMs);return reply===void 0?void 0:parseHostProtocolInfo(reply)}async function observeProtocolInfo(socketPath,timeoutMs){let reply=await requestOnSocket(socketPath,{type:"get_protocol_info",[OBSERVE_REQUEST_FIELD]:!0},timeoutMs);return reply===void 0?void 0:parseHostProtocolInfo(reply)}async function holdProtocolInfo(socketPath,timeoutMs){let outcome=await connectAndAsk(socketPath,{id:PROBE_REQUEST_ID,type:"get_protocol_info"},timeoutMs,!0),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){return(await connectAndAsk(socketPath,{id:PROBE_REQUEST_ID,type:"get_protocol_info"},timeoutMs)).connected}async function probeSessionCount(socketPath,timeoutMs){let reply=await requestOnSocket(socketPath,{type:"list_sessions",include_workers:!0},timeoutMs);if(!(!isRecord3(reply)||!Array.isArray(reply.sessions)))return reply.sessions.length}async function requestOnSocket(socketPath,command,timeoutMs){return(await connectAndAsk(socketPath,{id:PROBE_REQUEST_ID,...command},timeoutMs)).answer}async function connectAndAsk(socketPath,request,timeoutMs,keep=!1){let secret;if(socketNeedsHandshake(socketPath))try{secret=await readSocketSecret(socketSecretPath(socketPath))}catch{return{connected:!1,answer:void 0}}return new Promise(resolveProbe=>{let socket=createConnection(resolveSocketTransportAddress(socketPath,process.platform,secret)),buffer="",settled=!1,connected=!1,finish=value=>{if(!settled){if(settled=!0,clearTimeout(timeout),keep&&value!==void 0&&!socket.destroyed){resolveProbe({connected,answer:value,kept:socket});return}socket.destroy(),resolveProbe({connected,answer:value})}},timeout=setTimeout(()=>finish(),timeoutMs);socket.once("connect",()=>{connected=!0,socket.write(`${JSON.stringify(request)}
|
|
3
|
+
`)}),socket.on("data",chunk=>{for(buffer+=chunk.toString("utf8");;){let newline=buffer.indexOf(`
|
|
4
|
+
`);if(newline===-1)return;let line=buffer.slice(0,newline);buffer=buffer.slice(newline+1);let answer2=readAnswer(line);if(answer2!==void 0)return finish(answer2)}}),socket.once("error",()=>finish()),socket.once("close",()=>finish()),secret&&sendSocketHandshake(socket,secret)})}function readAnswer(text){let parsed;try{parsed=JSON.parse(text)}catch{return}if(!(!isRecord3(parsed)||parsed.id!==PROBE_REQUEST_ID||parsed.success!==!0))return parsed.data??{}}function isRecord3(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}import{spawn}from"node:child_process";import{randomUUID}from"node:crypto";import{open,rm,writeFile}from"node:fs/promises";import{existsSync as existsSync2}from"node:fs";import{basename as basename2,dirname as dirname3,resolve as resolve2}from"node:path";import{fileURLToPath as fileURLToPath2}from"node:url";var PINNED_HOST_CLIENT_CAPABILITIES=[EXTENSION_EVENTS_CAPABILITY,CUSTOM_UNSUPPORTED_CAPABILITY];function defaultHostLaunch(supervisorArgs,compiled=isBunBinary,sibling=resolveHostLifecycleEntryPath()??null){return compiled?{command:process.execPath,args:[INTERNAL_SUPERVISOR_FLAG,...supervisorArgs]}:sibling!==null?{command:process.execPath,args:[...rpcHostExecArgv(),sibling,...supervisorArgs]}:{command:process.execPath,args:[...rpcHostExecArgv(),resolveCliMainPath(),INTERNAL_SUPERVISOR_FLAG,...supervisorArgs]}}function resolveHostLifecycleEntryPath(){let modulePath=fileURLToPath2(import.meta.url);if(basename2(dirname3(modulePath))==="chunks")return;let extension=modulePath.endsWith(".ts")?".ts":".js",sibling=resolve2(dirname3(modulePath),`host-lifecycle${extension}`);return existsSync2(sibling)?sibling:void 0}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","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}})}import{dirname as dirname4,join as join3}from"node:path";var LEGACY_PROBE_TIMEOUT_MS=1e4,DRAIN_POLL_MS=50;async function retireIdleLegacyHost(paths,probe,drainTimeoutMs){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(dirname4(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(()=>!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{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);if(sessions===0)return{verdict:"idle",host};let held=sessions===void 0?"an unknown number of sessions":`${sessions} open session${sessions===1?"":"s"}`;return{verdict:"held",detail:`${where} holds ${held}; run \`${APP_NAME} host stop --drain --socket ${host.socket}\` to let it finish that work and exit, then retry`}}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(resolve4=>setTimeout(resolve4,DRAIN_POLL_MS))}return!0}async function stopHost(options){let paths=createHostDaemonPaths({socket:options.socket,...options.agentDir?{agentDir:options.agentDir}:{}}),registered=await readHostRegistration(paths),owner=await provenOwner(registered,options.socket);if(options.drain===!0){let pid=owner?.pid??(await provenLegacyOwner(paths,options.socket))?.pid;return pid===void 0?{action:"refuse",reason:"unknown_owner"}:!(await probeProtocolInfo(options.socket,options.timeoutMs??1e4))?.capabilities.includes(GENERATION_HANDOFF_CAPABILITY)||process.platform==="win32"?{action:"refuse",reason:"drain_unsupported"}:(signalGeneration(pid,"SIGUSR1"),{action:"drained",pid})}if(!owner)return{action:"refuse",reason:"unknown_owner"};let host=await probeProtocolInfo(options.socket,options.timeoutMs??1e4),sessions=await probeSessionCount(options.socket,options.timeoutMs??1e4);return options.force!==!0&&host!==void 0&&sessions!==void 0&&sessions>0?{action:"refuse",reason:"sessions_live"}:(signalGeneration(owner.pid,"SIGTERM"),await releaseGeneration(paths,{instanceId:owner.instanceId,pid:owner.pid}),{action:"stopped",pid:owner.pid})}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}}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}=context,generation=(host.generation??0)+1,instanceId=randomUUID(),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),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 options._test?.beforeSpawn?.();let argv=["--socket",options.socket,"--bind",bindSocket,"--replace",`${replaced.dev}:${replaced.ino}`,...options.hostArgs??[]],launch=(options._test?.launch??options.launch)?.(argv)??defaultHostLaunch(argv),stderr=await open(paths.stderrLog,"a",384),spawned=spawn(launch.command,[...launch.args],{detached:!0,windowsHide:!0,env:successorHostEnvironment({agentDir:options.agentDir,env:options.env,expectedRuntimeBuildId:options.expectedRuntimeBuildId,paths,generation,instanceId}),stdio:["ignore","ignore",stderr.fd]});if(await stderr.close(),child=spawned,exited=new Promise(resolve4=>spawned.once("exit",()=>resolve4())),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});return{action:"refuse",reason,upgradeable:!0,...cleanupFailure&&{detail:cleanupFailure}}}return await options._test?.beforeRegistration?.(),await writeHostRegistration(paths,registration),child.unref(),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}),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;child!==void 0&&child.exitCode===null&&child.signalCode===null&&child.kill("SIGKILL");try{bootSettings===void 0?await rm(paths.settingsFile,{force:!0}):await writeFile(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)&&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(resolve4=>{timer=setTimeout(()=>resolve4(!1),ms)});try{return await Promise.race([exited.then(()=>!0),timedOut])}finally{clearTimeout(timer)}}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 delay(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 delay(ms){return new Promise(resolve4=>setTimeout(resolve4,ms))}var HANDOFF_PROBE_TIMEOUT_MS=1e4,HANDOFF_LOCK_HOLD_MS=HANDOFF_PROBE_TIMEOUT_MS+SUCCESSOR_START_BUDGET_MS,HANDOFF_LOCK_WAIT_MS=HANDOFF_PROBE_TIMEOUT_MS+HANDOFF_LOCK_HOLD_MS+1e4;async function handoffHost(options){if(handoffUnsupported(options))return{action:"refuse",reason:"upgrade_unsupported",upgradeable:!1};let release=await acquireHostEnsureLock(options.socket,HANDOFF_LOCK_WAIT_MS);try{return await handoffHostLocked(options)}finally{await release()}}async function handoffHostLocked(options){if(handoffUnsupported(options))return{action:"refuse",reason:"upgrade_unsupported",upgradeable:!1};let paths=createHostDaemonPaths({socket:options.socket,...options.agentDir?{agentDir:options.agentDir}:{}});await createDaemonDirectories(paths);let host=await probeProtocolInfo(options.socket,HANDOFF_PROBE_TIMEOUT_MS);if(!host)return{action:"refuse",reason:"no_host",upgradeable:!1};if(!host.capabilities.includes(GENERATION_HANDOFF_CAPABILITY))return{action:"refuse",reason:"handoff_unsupported",upgradeable:!1};let registered=await readHostRegistration(paths),owner=await provenOwner(registered,options.socket);return owner?startSuccessor({options,paths,host,owner}):{action:"refuse",reason:"unknown_owner",upgradeable:!0}}function handoffUnsupported(options){return(options._test?.platform??process.platform)==="win32"}var hostGenerationScopes=0;function isHostGenerationProcess(){return hostGenerationScopes>0}async function runAsHostGenerationProcess(action){hostGenerationScopes+=1;try{return await action()}finally{hostGenerationScopes-=1}}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 EXISTING_HOST_PROBE_TIMEOUT_MS=1e4,DEFAULT_READINESS_TIMEOUT_MS=1e4,DEFAULT_STOP_TIMEOUT_MS=1e4,SIGKILL_GRACE_MS=2e3,ENSURE_LOCK_WAIT_MS=EXISTING_HOST_PROBE_TIMEOUT_MS+Math.max(DEFAULT_STOP_TIMEOUT_MS+SIGKILL_GRACE_MS+DEFAULT_READINESS_TIMEOUT_MS,HANDOFF_LOCK_HOLD_MS)+1e4,lockOptions=hostEnsureLockOptions(ENSURE_LOCK_WAIT_MS);async function ensureHost(options){let socket=normalizeSocketPath(options.socket),paths=createHostDaemonPaths({socket,...options.agentDir?{agentDir:options.agentDir}:{}});await createDaemonDirectories(paths);let lockTarget=hostEnsureLockTarget(socket);await mkdir(dirname5(lockTarget),{recursive:!0}),await writeFile2(lockTarget,"",{flag:"a",mode:384}),await reapOrphanedInternalHostDirs();let release=await acquireOwnershipSafeLock(`${lockTarget}.lock`,lockOptions);try{return await options._test?.afterLockAcquired?.(),await ensureHostLocked(paths,socket,options)}finally{await release()}}async function ensureHostLocked(paths,socket,options){await ensureEndpointIdentity(paths,socket,{repair:!0});let testOptions=options._test,registered=await readHostRegistration(paths),registeredHere=registersSocket(registered,socket),held=await holdProtocolInfo(socket,EXISTING_HOST_PROBE_TIMEOUT_MS),protocol=held?.info,startedByUs=registeredHere&&await writtenByThisProcess(registered?.writer,testOptions?.readProcessStartTime),attachedPid=registeredHere?registered?.record.pid??0:0,decision=decide(options,startedByUs,protocol);if(decision.action==="reuse"&&held)return{pid:attachedPid,socket,reused:!0,release:held.hold.release};switch(held?.hold.release(),decision.action){case"reuse":throw new Error(`host at ${socket} was reused without answering its probe`);case"refuse":throw new HostEnsureRefusedError(socket,decision.reason,protocol);case"handoff":return upgradeGeneration(paths,socket,options,attachedPid);case"start":break;default:return assertNever2(decision)}let probe=testOptions?.readProcessStartTime??readProcessStartTime,pidMatches=registeredHere&®istered?await matchesPidFileOrUnknown(registered.record,probe):!1,stranded;if(registered&&pidMatches)if(startedByUs){if(await probeSocketReachable(socket,EXISTING_HOST_PROBE_TIMEOUT_MS))throw new HostEnsureRefusedError(socket,"host_busy",protocol);await stopManagedHost(registered.record,testOptions?.stopTimeoutMs??DEFAULT_STOP_TIMEOUT_MS,probe)}else{if(await publicEndpointAccepts(socket))throw new HostEnsureRefusedError(socket,"foreign_writer",protocol);stranded=registered}let legacyRefusal=await retireIdleLegacyHost(paths,probe,testOptions?.stopTimeoutMs??DEFAULT_STOP_TIMEOUT_MS);if(legacyRefusal!==void 0)throw new HostEnsureRefusedError(socket,"legacy_host",protocol,legacyRefusal);return stranded!==void 0?startHost(paths,socket,options,stranded.generation+1):(registeredHere&&await clearHostRegistration(paths),startHost(paths,socket,options))}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)}function decide(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}async function upgradeGeneration(paths,socket,options,attachedPid){let result=await handoffHostLocked({socket,agentDir:options.agentDir??getAgentDir(),hostArgs:options.hostArgs??[],...options.env?{env:options.env}:{},...options.policy?{policy:options.policy}:{},_test:{...options._test?.launch?{launch:options._test.launch}:{},...options._test?.readinessTimeoutMs?{readinessTimeoutMs:options._test.readinessTimeoutMs}:{}}});return result.action==="handoff"?{pid:result.pid,socket,reused:!1,release:await holdEnsured(socket)}:(await appendStderr(paths,`generation handoff refused: ${result.reason}${result.detail?` (${result.detail})`:""}`),{pid:attachedPid,socket,reused:!0,release:await holdEnsured(socket)})}async function holdEnsured(socket){let held=await holdProtocolInfo(socket,EXISTING_HOST_PROBE_TIMEOUT_MS);if(!held)throw new Error(`RPC socket host at ${socket} stopped answering before this ensure could hold it`);return held.hold.release}function ensureClient(options,startedByUs){return{protocolVersion:HOST_PROTOCOL_VERSION,requiredCapabilities:REQUIRED_HOST_CAPABILITIES,identity:engineBuildIdentity(),...options.upgrade==="if-engine-differs"?{launchProfile:hostLaunchProfile(hostChildArgv(options.hostArgs??[]),process.cwd())}:{},startedByUs,platform:process.platform}}function hostChildArgv(hostArgs){return["--mode","rpc","--multi-session",...hostArgs]}function registersSocket(registered,socket){return registered===void 0?!1:registered.socket===void 0||sameEndpoint(registered.socket,socket)}async function startHost(paths,socket,options,generation=0){let testOptions=options._test,instanceId=randomUUID2();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});let stderr=await open2(paths.stderrLog,generation===0?"w":"a",384),pidFile,child,exitedEarly,childExit;try{let supervisorArgs=["--socket",socket,...options.hostArgs??[]],launch=testOptions?.spawn??testOptions?.launch?.(supervisorArgs)??defaultHostLaunch(supervisorArgs);if(child=spawn2(launch.command,[...launch.args],{detached:!0,windowsHide:!0,env:initialHostEnvironment({agentDir:options.agentDir,env:options.env,paths,instanceId,generation}),stdio:["ignore","ignore",stderr.fd]}),childExit=new Promise(resolveExit=>{child.once("exit",(code,signal)=>{exitedEarly={code,signal},resolveExit(exitedEarly)})}),child.pid===void 0)throw new Error("failed to spawn RPC socket host");let probe=testOptions?.readProcessStartTime??readProcessStartTime,observedStartTime=await Promise.race([waitForStartTime(child.pid,1e4,probe),childExit.then(()=>{throw new Error("RPC socket host exited before its start time could be read")})]),unhurriedProbe=testOptions?.readProcessStartTime?testOptions.readProcessStartTime:pid=>readProcessStartTime(pid,process.platform,15e3),processStartTime=observedStartTime??await unhurriedProbe(child.pid).catch(()=>{});pidFile={pid:child.pid,processStartTime:processStartTime??null},await testOptions?.beforePidFileWrite?.(),await writeHostRegistration(paths,{record:pidFile,socket,instanceId,generation,launchProfileId:hostLaunchProfile(hostChildArgv(options.hostArgs??[]),process.cwd()).profile_id}),child.unref()}catch(error){let exitedBeforeCleanup=exitedEarly;if(!exitedBeforeCleanup&&child&&child.exitCode===null&&child.signalCode===null){try{child.kill("SIGTERM")}catch{}if(childExit&&await Promise.race([childExit,delay3(2e3)]),child.exitCode===null&&child.signalCode===null)try{child.kill("SIGKILL")}catch{}}if(!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{pid:pidFile.pid,socket,reused:!1,release:result.hold.release};let stopFailure=await stopSpawnedChild(child,childExit,testOptions?.stopTimeoutMs??DEFAULT_STOP_TIMEOUT_MS).then(()=>{},error=>error instanceof Error?error.message:String(error)),message=result.protocol?`RPC socket host answered get_protocol_info with 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 matchesPidFileOrUnknown(pidFile,probe){try{return await processMatchesPidFile(pidFile,probe)}catch(error){if(error instanceof ProcessIdentityUnreadableError)return!1;throw error}}async function stopSpawnedChild(child,childExit,termTimeoutMs){let exited=()=>child.exitCode!==null||child.signalCode!==null;if(exited())return;let signal=name=>{try{child.kill(name)}catch(error){if(!isNodeErrorCode(error,"ESRCH"))throw error}},waitFor=ms=>Promise.race([childExit.then(()=>!0),delay3(ms).then(()=>exited())]);if(signal("SIGTERM"),!await waitFor(termTimeoutMs)&&(signal("SIGKILL"),!await waitFor(SIGKILL_GRACE_MS)))throw new Error(`RPC socket host pid ${child.pid??"?"} remained alive after SIGKILL`)}async function stopManagedHost(pidFile,termTimeoutMs,readStartTime=readProcessStartTime){if(await signalValidated(pidFile,"SIGTERM",readStartTime),!await waitForGone(pidFile,termTimeoutMs,readStartTime)&&(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`)}async function resolvePidFileOwnership(pidFile,readStartTime){try{return await processMatchesPidFile(pidFile,readStartTime,processIsLive,{attempts:1})?"owns":"gone"}catch(error){if(error instanceof ProcessIdentityUnreadableError)return"unknown";throw error}}async function signalValidated(pidFile,signal,readStartTime=readProcessStartTime){if(await resolvePidFileOwnership(pidFile,readStartTime)==="owns")try{process.kill(pidFile.pid,signal)}catch(error){if(!isNodeErrorCode(error,"ESRCH"))throw error}}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 delay3(50)}return await resolvePidFileOwnership(pidFile,readStartTime)==="gone"}function isCompatible(protocol){return decideHostAction(ensureClient({socket:""},!1),protocol,"never").action==="reuse"}async function reapOrphanedInternalHostDirs(){try{let entries=await readdir2(tmpdir(),{withFileTypes:!0});await Promise.all(entries.filter(entry=>entry.isDirectory()&&entry.name.startsWith("senpi-rpc-host-internal-")).map(async entry=>{try{let owner=JSON.parse(await readFile3(join4(tmpdir(),entry.name,".owner"),"utf8"));typeof owner.pid=="number"&&typeof owner.processStartTime=="string"&&typeof owner.createdAt=="number"&&owner.processStartTime.length>0&&owner.createdAt<Date.now()-6e4&&(await readdir2(join4(tmpdir(),entry.name))).length===1&&!await processMatchesPidFile({pid:owner.pid,processStartTime:owner.processStartTime}).catch(error=>{if(error instanceof ProcessIdentityUnreadableError)return!0;throw error})&&await rm2(join4(tmpdir(),entry.name),{recursive:!0,force:!0})}catch{}}))}catch{}}async function appendStderr(paths,message){try{let stderr=(await readFile3(paths.stderrLog,"utf8")).trim();return stderr?`${message}
|
|
5
|
+
${stderr}`:message}catch(error){if(isNodeErrorCode(error,"ENOENT"))return message;throw error}}function normalizeSocketPath(value){return value.startsWith("unix://")?value.slice(7):value}function delay3(ms){return new Promise(resolveDelay=>setTimeout(resolveDelay,ms))}function isNodeErrorCode(error,code){return error instanceof Error&&"code"in error&&error.code===code}function assertNever2(value){throw new Error(`unreachable host decision: ${JSON.stringify(value)}`)}var WakeSourceTracker=class{constructor(){this.counts=new Map}observe(data){if(typeof data!="object"||data===null)return;let{source,activeCount}=data;typeof source!="string"||source.length===0||typeof activeCount!="number"||!Number.isFinite(activeCount)||(activeCount>0?this.counts.set(source,activeCount):this.counts.delete(source))}get hasActive(){return this.counts.size>0}get activeSources(){return[...this.counts.keys()]}};function isSessionBusySnapshot(snapshot){return snapshot.isStreaming||snapshot.isBashRunning||snapshot.isCompacting||snapshot.hasSessionWork||snapshot.hasActiveWakeSource}function isHandoffBusy(snapshot){return isSessionBusySnapshot({...snapshot,hasActiveWakeSource:!1})}function selectDrainVerdicts(registry,inFlight,unreadable){let park=[],gone=[];for(let{sessionId,status,sessionPath}of registry.list()){if(status!=="open"||inFlight(sessionId))continue;let entry=registry.peek(sessionId);!entry||handoffBusy(entry,sessionId,unreadable)||(sessionPath!==void 0&&sessionDirectoryRemoved(sessionPath)?gone.push(sessionId):park.push(sessionId))}return{park,gone}}function handoffBusy(entry,sessionId,unreadable){try{let snapshot=entry.runtime?.session.activitySnapshot;return entry.worker?.handoffBusy===!0||snapshot!==void 0&&isHandoffBusy(snapshot)}catch(cause){return unreadable(sessionId,cause),!1}}function readDrainVerdicts(registry,inFlight){try{return selectDrainVerdicts(registry,inFlight,(sessionId,cause)=>{process.stderr.write(`senpi rpc handoff activity of ${sessionId} unreadable, parking: ${String(cause)}
|
|
6
|
+
`)})}catch(cause){process.stderr.write(`senpi rpc handoff drain pass failed, retrying: ${String(cause)}
|
|
7
|
+
`);return}}var BEGIN_HANDOVER_COMMAND="begin_handover",SUCCESSOR_PROBE_TIMEOUT_MS=1e4;function parseBeginHandover(record){let{operation_id,if_instance_id,if_generation,target_runtime_build_id,launch,host_args,env}=record;if(typeof operation_id!="string"||operation_id==="")return"operation_id must be a non-empty string";if(typeof if_instance_id!="string")return"if_instance_id must be a string";if(typeof if_generation!="number"||!Number.isSafeInteger(if_generation))return"if_generation must be an integer";if(typeof target_runtime_build_id!="string")return"target_runtime_build_id must be a string";if(!isRecord4(launch)||typeof launch.command!="string"||!isStringArray(launch.args))return"launch must be { command, args }";if(!isStringArray(host_args))return"host_args must be an array of strings";if(!isRecord4(env)||!Object.values(env).every(value=>typeof value=="string"))return"env must map names to strings";let policy=isRecord4(record.policy)?record.policy:void 0;return{operationId:operation_id,ifInstanceId:if_instance_id,ifGeneration:if_generation,targetRuntimeBuildId:target_runtime_build_id,launch:{command:launch.command,args:launch.args},hostArgs:host_args,env,...policy!==void 0&&{policy}}}function beginHandoverResponse(id,answer2){let data=typeof answer2=="string"?{refused:"invalid_request",detail:answer2}:answer2.kind==="refused"?{refused:answer2.reason,...answer2.detail!==void 0&&{detail:answer2.detail}}:handoverWire(answer2.view);return{...typeof id=="string"&&{id},type:"response",command:BEGIN_HANDOVER_COMMAND,success:!0,data}}function handoverWire(view){return{operation_id:view.operationId,state:view.state,target_runtime_build_id:view.targetRuntimeBuildId,...view.reason!==void 0&&{reason:view.reason},...view.successor!==void 0&&{successor:view.successor}}}function handoverRefusal(command,view){return{...command.id!==void 0&&{id:command.id},type:"response",command:command.type,success:!1,error:`handover_pending: this host is handing over to runtime ${view.targetRuntimeBuildId} (operation ${view.operationId}); new work is admitted by its successor`}}function withHostIdentity(response,runtimeBuildId,handover){return response.command!=="get_protocol_info"||!response.success?response:{...response,data:{...response.data,...runtimeBuildId!==void 0&&{runtimeBuildId},...handover!==void 0&&{handover:handoverWire(handover)}}}}function isHostIdle(registry,inFlight){if((inFlight.get(void 0)??0)>0)return!1;let sessions=registry.list(),verdicts=selectDrainVerdicts(registry,sessionId=>(inFlight.get(sessionId)??0)>0,()=>{});return verdicts.park.length+verdicts.gone.length===sessions.length}async function performIdleHandover(context){let{request,socket,agentDir}=context,env={};for(let name of Object.keys(process.env))env[name]=null;Object.assign(env,request.env);let result=await handoffHost({socket,agentDir,hostArgs:request.hostArgs,env,expectedRuntimeBuildId:request.targetRuntimeBuildId,...request.policy!==void 0&&{policy:request.policy},launch:argv=>({command:request.launch.command,args:[...request.launch.args,...argv]})});if(result.action==="refuse")return{ok:!1,reason:result.detail===void 0?result.reason:`${result.reason}: ${result.detail}`};await writeDaemonEnvKeys(createHostDaemonPaths({socket,agentDir}),Object.keys(request.env).sort()).catch(cause=>{process.stderr.write(`senpi rpc handover: could not record the daemon environment: ${String(cause)}
|
|
8
|
+
`)});let successor=await probeProtocolInfo(socket,SUCCESSOR_PROBE_TIMEOUT_MS);return{ok:!0,successor:{pid:result.pid,instanceId:result.instanceId,generation:result.generation,runtimeBuildId:successor?.runtimeBuildId??null}}}function isRecord4(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function isStringArray(value){return Array.isArray(value)&&value.every(entry=>typeof entry=="string")}function parseSessionRows(reply){return!isRecord5(reply)||!Array.isArray(reply.sessions)?[]:reply.sessions.flatMap(entry=>isRecord5(entry)?[{id:typeof entry.sessionId=="string"?entry.sessionId:"",kind:typeof entry.kind=="string"?entry.kind:"interactive",session_path:typeof entry.sessionPath=="string"?entry.sessionPath:null,cwd:typeof entry.cwd=="string"?entry.cwd:null,name:typeof entry.name=="string"?entry.name:null,attachments:typeof entry.attachments=="number"?entry.attachments:0,context:stringRecord(entry.context)}]:[])}async function readClaimRows(paths,generations){let rows=[];for(let claim of await readSessionPathClaims(paths.reservationsDir)){let owner=claim.owner;rows.push({session_path:owner.sessionPath,owner_pid:owner.pid,instance_id:owner.instanceId,generation:generations.find(row=>row.instanceId===owner.instanceId)?.generation??null,attached:owner.attached??null,live:await claimOwnerIsLive(owner)})}return rows.sort((left,right)=>left.session_path.localeCompare(right.session_path))}function stringRecord(value){return isRecord5(value)?Object.fromEntries(Object.entries(value).filter(entry=>typeof entry[1]=="string")):null}function isRecord5(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}var STATUS_PROBE_TIMEOUT_MS=1e4;async function readHostStatus(options,read={}){return(await probeHostStatus(options,read)).report}async function probeHostStatus(options,read={}){let paths=createHostDaemonPaths({socket:options.socket,...options.agentDir?{agentDir:options.agentDir}:{}}),prune=read.prune!==!1,includeWorkers=options.includeWorkers===!0,timeoutMs=read.timeoutMs??STATUS_PROBE_TIMEOUT_MS,host=await observeProtocolInfo(options.socket,timeoutMs);prune&&await pruneDeadGenerations(paths);let generations=await readGenerationRows(paths,{includeDead:!prune}),current=generations.find(row=>row.current&&row.alive),metrics=current?await readHostProcessMetrics(current.pid):UNOBSERVED_METRICS,listing=host===void 0?[]:await readSessionListing(options.socket,includeWorkers,timeoutMs),claims=await readClaimRows(paths,generations);return{report:{reachable:host!==void 0,socket:options.socket,pid:current?.pid??null,instanceId:host?.instanceId??current?.instanceId??null,generation:host?.generation??current?.generation??null,engineVersion:host?.engineVersion??current?.engineVersion??null,capabilities:host?.capabilities??[],launchProfile:host?.launch_profile??null,runtimeBuildId:host?.runtimeBuildId??null,handover:host?.handover??null,sessions:countSessions(listing),zombies:metrics.zombies,rss_mb:metrics.rss_mb,host_rss_mb:metrics.host_rss_mb,open_fds:metrics.open_fds,memory_pressure:host?.memory_pressure??null,env_keys:await readDaemonEnvKeys(paths),generations,crashes:readHostCrashRecords(paths.dir).length,shard:parseShardSocket(options.socket),session_rows:includeWorkers?listing:[],claims_live:claims.filter(claim=>claim.live).length,claims:includeWorkers?claims:[]},answered:host,listing}}async function readSessionCounts(socket,includeWorkers){return countSessions(await readSessionListing(socket,includeWorkers))}async function readSessionListing(socket,includeWorkers,timeoutMs=STATUS_PROBE_TIMEOUT_MS){let reply=await requestOnSocket(socket,{type:"list_sessions",[OBSERVE_REQUEST_FIELD]:!0,...includeWorkers?{include_workers:!0}:{}},timeoutMs);return parseSessionRows(reply)}function countSessions(rows){let attached=rows.filter(row=>row.attachments>0).length,retained=rows.length-attached;return{total:rows.length,interactive:rows.filter(row=>row.kind!=="worker").length,worker:rows.filter(row=>row.kind==="worker").length,retained,foreign_attached:attached,foreign_retained:retained}}function hostSummary(host){return host===void 0?null:{protocolVersion:host.protocolVersion,serverVersion:host.serverVersion,capabilities:host.capabilities,instanceId:host.instanceId??null,generation:host.generation??null,engineVersion:host.engineVersion??null,launchProfileId:host.launch_profile?.profile_id??null}}var UNOBSERVED_METRICS={rss_mb:null,host_rss_mb:null,open_fds:null,zombies:null};var HOST_EXIT_OK=0,HOST_EXIT_ERROR=1,HOST_EXIT_USAGE=2,HOST_EXIT_REFUSED=3,HOST_EXIT_FALLBACK=4;function identityPayload(socket,pid,host){return{socket,pid,instanceId:host?.instanceId??null,generation:host?.generation??null,engineVersion:host?.engineVersion??null,engineOrdinal:host?.engineOrdinal??null,capabilities:host?.capabilities??[],launchProfileId:host?.launch_profile?.profile_id??null,runtimeBuildId:host?.runtimeBuildId??null,upgradeable:decideHostAction(decisionClient(),host,"upgrade").upgradeable}}async function clientRuntimeBuildId(spec){let profile=socketHostLaunchProfile(spec.hostArgs,process.cwd());return computeRuntimeBuildId({profile:profile.core}).catch(cause=>(process.stderr.write(`senpi host: runtime identity unreadable: ${String(cause)}
|
|
9
|
+
`),null))}function refusal(kind,host,body){return{exitCode:kind==="refuse"?HOST_EXIT_REFUSED:HOST_EXIT_FALLBACK,payload:{action:kind,...body,host:hostSummary(host)}}}function decisionClient(){return{protocolVersion:HOST_PROTOCOL_VERSION,requiredCapabilities:REQUIRED_HOST_CAPABILITIES,identity:engineBuildIdentity(),startedByUs:!1,platform:process.platform}}var PROBE_TIMEOUT_MS=1e4,BEGIN_HANDOVER_TIMEOUT_MS=2*HANDOFF_LOCK_HOLD_MS+2e4;async function idleHandoverOutcome(target,spec,terms){let{socket}=target;if(process.platform==="win32")return refusal("refuse",void 0,{reason:"upgrade_unsupported",socket,operationId:terms.operationId});let before=await probeProtocolInfo(socket,PROBE_TIMEOUT_MS),refuse=(reason,extra={})=>refusal("refuse",before,{reason,socket,operationId:terms.operationId,...extra}),client=await clientRuntimeBuildId(spec);if(client!==terms.targetRuntimeBuildId)return refuse("target_build_mismatch",{detail:`this CLI launches ${client??"a runtime it cannot read"}`,clientRuntimeBuildId:client});if(before===void 0)return refuse("no_host");if(before.runtimeBuildId===terms.targetRuntimeBuildId)return answered(target,"handover_completed",before,terms,null);if(before.instanceId!==terms.ifInstanceId||before.generation!==terms.ifGeneration)return refuse("stale_generation",{detail:`the socket is served by ${before.instanceId??"an unnamed host"} generation ${before.generation??"?"}`});if(!before.capabilities.includes(RUNTIME_IDENTITY_HANDOVER_CAPABILITY))return refuse("handover_unsupported");let reply=await requestOnSocket(socket,beginHandoverCommand(spec,terms),BEGIN_HANDOVER_TIMEOUT_MS);return isRecord6(reply)?typeof reply.refused=="string"?refuse(reply.refused,typeof reply.detail=="string"?{detail:reply.detail}:{}):reply.state==="handover_blocked"?refuse("handover_blocked",{detail:reply.reason??null,handover:reply}):reply.state==="handover_completed"?answered(target,"handover_completed",await probeProtocolInfo(socket,PROBE_TIMEOUT_MS),terms,reply):answered(target,"handover_pending",before,terms,reply):reconcileLostReply(target,terms,before)}function beginHandoverCommand(spec,terms){let env={};for(let[name,value]of Object.entries(daemonEnvironment(process.env,daemonEnvOverrides(process.env,spec.env))))value!==void 0&&(env[name]=value);let launch=defaultHostLaunch([]);return{type:BEGIN_HANDOVER_COMMAND,operation_id:terms.operationId,if_instance_id:terms.ifInstanceId,if_generation:terms.ifGeneration,target_runtime_build_id:terms.targetRuntimeBuildId,launch:{command:launch.command,args:launch.args},host_args:spec.hostArgs,env,...spec.policy!==void 0&&{policy:spec.policy}}}async function reconcileLostReply(target,terms,before){let now=await probeProtocolInfo(target.socket,PROBE_TIMEOUT_MS);return now?.runtimeBuildId===terms.targetRuntimeBuildId?answered(target,"handover_completed",now,terms,null):{exitCode:HOST_EXIT_ERROR,payload:{action:"error",reason:"handover_reply_lost",operationId:terms.operationId,...identityPayload(target.socket,await servingPid(target),now??before)}}}async function answered(target,action,host,terms,handover){return{exitCode:HOST_EXIT_OK,payload:{action,...identityPayload(target.socket,await servingPid(target),host),operationId:typeof handover?.operation_id=="string"?handover.operation_id:terms.operationId,clientRuntimeBuildId:terms.targetRuntimeBuildId,handover}}}async function servingPid(target){return(await readHostRegistration(createHostDaemonPaths(target)))?.record.pid??0}function isRecord6(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}import{readdir as readdir3}from"node:fs/promises";var TUI_PROBE_TIMEOUT_MS=1500;function endpointProbeTimeoutMs(kind,requestedMs){return kind==="tui"?Math.min(requestedMs??TUI_PROBE_TIMEOUT_MS,TUI_PROBE_TIMEOUT_MS):requestedMs??DEFAULT_PROBE_TIMEOUT_MS}async function classifyEndpointLiveness(entry,options={}){let host=entry.socket===null?void 0:await observeProtocolInfo(entry.socket,endpointProbeTimeoutMs(entry.endpoint_kind,options.timeoutMs));return judgeEndpointLiveness(hostDaemonDirectoryPaths(entry.dir),host===void 0?void 0:host.instanceId??null)}async function judgeEndpointLiveness(paths,answered2){return typeof answered2=="string"&&await recordsInstance(paths,answered2)?"routable":answered2!==void 0||await anyGenerationLive(paths)?"live_unresponsive":"dead"}async function recordsInstance(paths,instanceId){return(await readdir3(paths.generationsDir).catch(()=>[])).includes(instanceId)?await readFileOrUndefined(generationPaths(paths,instanceId).pidFile).catch(()=>{})!==void 0:!1}var STATUS_ALL_MAX_IN_FLIGHT=64;async function readAllHostStatus(options){let endpoints=await listHostEndpoints(options.agentDir),read=options._test?.readEndpoint??(endpoint=>endpointStatus(endpoint,options)),rows=new Array(endpoints.length),next=0,worker=async()=>{for(let index=next++;index<endpoints.length;index=next++){let endpoint=endpoints[index];endpoint!==void 0&&(rows[index]=await read(endpoint))}};return await Promise.all(Array.from({length:Math.min(STATUS_ALL_MAX_IN_FLIGHT,endpoints.length)},worker)),rows}async function endpointStatus(endpoint,options){let located={dir:endpoint.dir,identity:endpoint.identity,endpoint_kind:endpoint.endpoint_kind},paths=hostDaemonDirectoryPaths(endpoint.dir);if(endpoint.socket===null){let verdict2=livenessFields(await judgeEndpointLiveness(paths,void 0)),status=await unaddressableStatus(endpoint.dir),owner2=endpoint.endpoint_kind==="tui"?tuiOwner(status,[]):null;return{...status,socket:null,...located,...verdict2,owner:owner2}}let{report,answered:answered2,listing}=await probeHostStatus({socket:endpoint.socket,agentDir:options.agentDir,includeWorkers:options.includeWorkers},{prune:!1,timeoutMs:endpointProbeTimeoutMs(endpoint.endpoint_kind,options.timeoutMs)}),verdict=await judgeEndpointLiveness(paths,answered2===void 0?void 0:answered2.instanceId??null),owner=endpoint.endpoint_kind==="tui"?tuiOwner(report,listing):null;return{...report,...located,...livenessFields(verdict),owner}}function tuiOwner(status,listing){let row=listing[0];return{pid:status.generations.find(generation=>generation.current)?.pid??null,cwd:row?.cwd??null,session:row===void 0?null:{id:row.id,path:row.session_path,name:row.name}}}function livenessFields(verdict){return verdict==="routable"?{alive:!0,reason:null}:{alive:!1,reason:verdict}}async function unaddressableStatus(dir){let paths=hostDaemonDirectoryPaths(dir),generations=await readGenerationRows(paths,{includeDead:!0}),claims=await readClaimRows(paths,generations);return{reachable:!1,pid:null,instanceId:null,generation:null,engineVersion:null,capabilities:[],launchProfile:null,runtimeBuildId:null,handover:null,sessions:{total:0,interactive:0,worker:0,retained:0,foreign_attached:0,foreign_retained:0},zombies:null,rss_mb:null,host_rss_mb:null,open_fds:null,memory_pressure:null,env_keys:[],generations,crashes:readHostCrashRecords(dir).length,shard:null,session_rows:[],claims_live:claims.filter(claim=>claim.live).length,claims:[]}}var PROBE_TIMEOUT_MS2=1e4;async function runHostRequest(request){if(request.action==="ensure"||request.action==="handoff"||request.action==="stop"){let{socket,agentDir}=request.target;if(await endpointKindOfSocket(socket,agentDir)==="tui")return refusal("refuse",void 0,{reason:"unsupported_endpoint_kind",socket,endpoint_kind:"tui"})}switch(request.action){case"ensure":return ensureOutcome(request.target,request.spec,request.policy);case"status":return request.all===!0?statusAllOutcome(request.target,request.includeWorkers):statusOutcome(request.target,request.includeWorkers);case"stop":return stopOutcome(request.target,request.drain,request.force);case"handoff":return request.handover===void 0?handoffOutcome(request.target,request.spec):idleHandoverOutcome(request.target,request.spec,request.handover);case"shard_path":return shardPathOutcome(request.kind,request.owner,request.root);case"gc":return{exitCode:HOST_EXIT_OK,payload:{...await gcHostEndpoints(request.agentDir)}};default:return assertNever3(request)}}async function ensureOutcome(target,spec,policy){let before=await probeProtocolInfo(target.socket,PROBE_TIMEOUT_MS2);if(policy==="fallback"){let decision=decideHostAction(decisionClient(),before,"fallback");if(decision.action==="fallback")return refusal("fallback",before,{reason:decision.reason,socket:target.socket})}let ensured;try{ensured=await ensureHost({socket:target.socket,agentDir:target.agentDir,hostArgs:spec.hostArgs,env:daemonEnvOverrides(process.env,spec.env),policy:spec.policy,upgrade:policy==="upgrade"?"if-engine-differs":"never"})}catch(error){if(!(error instanceof HostEnsureRefusedError))throw error;return refusal("refuse",before,{reason:error.reason,socket:target.socket,...error.detail!==void 0&&{detail:error.detail}})}let host=await probeProtocolInfo(target.socket,PROBE_TIMEOUT_MS2).finally(ensured.release);return ensured.reused||await recordEnvScope(target,spec),{exitCode:HOST_EXIT_OK,payload:{action:ensureAction(ensured.reused,before,host),...identityPayload(target.socket,ensured.pid,host),clientRuntimeBuildId:await clientRuntimeBuildId(spec),reused:ensured.reused}}}function ensureAction(reused,before,after){return reused?"reuse":before!==void 0&&before.instanceId!==after?.instanceId?"handoff":"start"}async function statusOutcome(target,includeWorkers){let status=await readHostStatus({socket:target.socket,agentDir:target.agentDir,includeWorkers});return{exitCode:status.reachable?HOST_EXIT_OK:HOST_EXIT_REFUSED,payload:{...status}}}async function statusAllOutcome(target,includeWorkers){let endpoints=await readAllHostStatus({agentDir:target.agentDir,includeWorkers});return{exitCode:endpoints.some(endpoint=>endpoint.reachable)?HOST_EXIT_OK:HOST_EXIT_REFUSED,payload:{endpoints}}}function shardPathOutcome(kind,owner,root){let key=shardKey(kind,owner);return{exitCode:HOST_EXIT_OK,payload:{kind,key,socket:shardSocketPathForKey(root,kind,key)}}}async function stopOutcome(target,drain,force){let host=await probeProtocolInfo(target.socket,PROBE_TIMEOUT_MS2),sessions=await readSessionCounts(target.socket,!0),occupied=sessions.foreign_attached+sessions.foreign_retained>0;if(!drain&&!force&&occupied)return refusal("refuse",host,{reason:"sessions_live",socket:target.socket,sessions});let result=await stopHost({socket:target.socket,agentDir:target.agentDir,drain,force});return result.action==="refuse"?refusal("refuse",host,{reason:result.reason,socket:target.socket,sessions}):{exitCode:HOST_EXIT_OK,payload:{action:result.action,socket:target.socket,pid:result.pid,sessions}}}async function handoffOutcome(target,spec){let before=await probeProtocolInfo(target.socket,PROBE_TIMEOUT_MS2),result=await handoffHost({socket:target.socket,agentDir:target.agentDir,hostArgs:spec.hostArgs,env:daemonEnvOverrides(process.env,spec.env),policy:spec.policy});if(result.action==="refuse")return refusal("refuse",before,{reason:upgradeRefusal(result.reason),socket:target.socket,detail:result.reason,upgradeable:result.upgradeable});await recordEnvScope(target,spec);let host=await probeProtocolInfo(target.socket,PROBE_TIMEOUT_MS2);return{exitCode:HOST_EXIT_OK,payload:{action:"handoff",...identityPayload(target.socket,result.pid,host),clientRuntimeBuildId:await clientRuntimeBuildId(spec),reused:!1}}}function upgradeRefusal(reason){return reason==="handoff_unsupported"?"upgrade_unsupported":reason}async function recordEnvScope(target,spec){let paths=createHostDaemonPaths({socket:target.socket,agentDir:target.agentDir});await writeDaemonEnvKeys(paths,daemonEnvKeys(process.env,spec.env))}function assertNever3(value){throw new Error(`unreachable host request: ${JSON.stringify(value)}`)}var SUBCOMMANDS=["ensure","status","stop","handoff","shard-path","gc"],POLICIES=["upgrade","fallback","never"],USAGE=`usage: ${APP_NAME} host <ensure|status|stop|handoff|shard-path|gc> [options]
|
|
10
|
+
|
|
11
|
+
ensure [--launch-spec <file>] [--policy upgrade|fallback|never] [--socket <path>]
|
|
12
|
+
status [--include-workers] [--all] [--socket <path>] (--all: every endpoint, ignores --socket)
|
|
13
|
+
stop [--drain] [--force] [--socket <path>]
|
|
14
|
+
handoff [--launch-spec <file>] [--socket <path>]
|
|
15
|
+
[--when idle --operation <id> --if-instance <id> --if-generation <n> --target-build <sha256:...>]
|
|
16
|
+
(--when idle: the running host hands over to THIS runtime at its next safe idle point)
|
|
17
|
+
shard-path --kind <p|i> --owner <id> [--root <dir>] [--json] (no host contact)
|
|
18
|
+
gc [--agent-dir <dir>] [--json] (removes provably dead endpoints only; ignores --socket)
|
|
19
|
+
|
|
20
|
+
--json the answer is one JSON line on stdout (always, except shard-path's bare path)`;async function runHostCommand(args){let parsed=parseHostArgs(args);if(typeof parsed=="string")return process.stderr.write(`${parsed}
|
|
21
|
+
${USAGE}
|
|
22
|
+
`),HOST_EXIT_USAGE;try{let outcome=await runHostRequest(await hostRequest(parsed));return parsed.subcommand==="shard-path"&&!parsed.json?writeSync(1,`${String(outcome.payload.socket)}
|
|
23
|
+
`):emit(outcome.payload),outcome.exitCode}catch(error){return error instanceof HostLaunchSpecError?(emit({action:"error",reason:error.reason,detail:error.detail}),HOST_EXIT_USAGE):(emit({action:"error",reason:"host_error",detail:error instanceof Error?error.message:String(error)}),HOST_EXIT_ERROR)}}async function hostRequest(parsed){let agentDir=getAgentDir(),target={socket:resolveHostSocket(parsed.socket,agentDir),agentDir};switch(parsed.subcommand){case"ensure":return{action:"ensure",target,spec:await launchSpec(parsed.specPath),policy:parsed.policy};case"status":return{action:"status",target,includeWorkers:parsed.includeWorkers,all:parsed.all};case"stop":return{action:"stop",target,drain:parsed.drain,force:parsed.force};case"handoff":return{action:"handoff",target,spec:await launchSpec(parsed.specPath),...parsed.handover!==void 0&&{handover:parsed.handover}};case"shard-path":return{action:"shard_path",kind:parsed.kind??"p",owner:parsed.owner??"",root:resolve3(parsed.root??join5(agentDir,"rpc","shards"))};case"gc":return{action:"gc",agentDir:resolve3(parsed.agentDir??agentDir)};default:return assertNever4(parsed.subcommand)}}function launchSpec(specPath){return specPath===void 0?DEFAULT_HOST_LAUNCH_SPEC:loadHostLaunchSpec(specPath)}function resolveHostSocket(explicit,agentDir){return explicit??envValue("RPC_SOCKET")??resolve3(agentDir,"rpc","rpc.sock")}function parseHostArgs(args){let[subcommand,...rest]=args;if(subcommand===void 0||!isSubcommand(subcommand))return`Error: unknown host command "${subcommand??""}".`;let specPath,policy="upgrade",socket,includeWorkers=!1,all=!1,drain=!1,force=!1,json=!1,kind,owner,root,agentDir,handover={};for(let index=0;index<rest.length;index++){let flag=rest[index],value=rest[index+1];if(flag==="--json")json=!0;else if(flag==="--include-workers")includeWorkers=!0;else if(flag==="--all"&&subcommand==="status")all=!0;else if(flag==="--kind"&&subcommand==="shard-path"&&(value==="p"||value==="i"))kind=value,index++;else if(flag==="--owner"&&subcommand==="shard-path"&&value!==void 0)owner=value,index++;else if(flag==="--root"&&subcommand==="shard-path"&&value!==void 0)root=value,index++;else if(flag==="--agent-dir"&&subcommand==="gc"&&value!==void 0)agentDir=value,index++;else if(subcommand==="handoff"&&value!==void 0&&HANDOVER_FLAGS.has(flag??""))handover[flag??""]=value,index++;else if(flag==="--drain")drain=!0;else if(flag==="--force")force=!0;else if(flag==="--launch-spec"&&value!==void 0)specPath=value,index++;else if(flag==="--socket"&&value!==void 0)socket=value,index++;else if(flag==="--policy"&&value!==void 0&&isPolicy(value))policy=value,index++;else return`Error: unknown option "${flag}" for "${APP_NAME} host ${subcommand}".`}if(subcommand==="shard-path"&&(kind===void 0||owner===void 0))return`Error: "${APP_NAME} host shard-path" needs --kind <p|i> and --owner <id>.`;let terms=Object.keys(handover).length===0?void 0:handoverTerms(handover);return typeof terms=="string"?terms:{subcommand,...specPath!==void 0&&{specPath},policy,...socket!==void 0&&{socket},includeWorkers,all,drain,force,json,...kind!==void 0&&{kind},...owner!==void 0&&{owner},...root!==void 0&&{root},...agentDir!==void 0&&{agentDir},...terms!==void 0&&{handover:terms}}}var HANDOVER_FLAGS=new Set(["--when","--operation","--if-instance","--if-generation","--target-build"]);function handoverTerms(flags){let when=flags["--when"],operationId=flags["--operation"],ifInstanceId=flags["--if-instance"],generation=flags["--if-generation"],targetRuntimeBuildId=flags["--target-build"];if(when!=="idle")return`Error: "${APP_NAME} host handoff" supports only --when idle.`;if(!operationId||!ifInstanceId||!generation||!targetRuntimeBuildId)return`Error: "${APP_NAME} host handoff --when idle" needs --operation, --if-instance, --if-generation and --target-build.`;let ifGeneration=Number(generation);return!/^\d+$/.test(generation)||!Number.isSafeInteger(ifGeneration)?"Error: --if-generation must be a non-negative integer.":{operationId,ifInstanceId,ifGeneration,targetRuntimeBuildId}}function emit(payload){writeSync(1,`${JSON.stringify(payload)}
|
|
24
|
+
`)}function isSubcommand(value){return SUBCOMMANDS.includes(value)}function isPolicy(value){return POLICIES.includes(value)}function assertNever4(value){throw new Error(`unreachable host subcommand: ${JSON.stringify(value)}`)}export{HostLaunchSpecError,DEFAULT_HOST_LAUNCH_SPEC,loadHostLaunchSpec,parseHostLaunchSpec,RUNTIME_IDENTITY_HANDOVER_CAPABILITY,computeRuntimeBuildId,parseHostProtocolInfo,HOST_PROTOCOL_VERSION,GENERATION_HANDOFF_CAPABILITY,REQUIRED_HOST_CAPABILITIES,HostEnsureRefusedError,decideHostAction,probeHost,PINNED_HOST_CLIENT_CAPABILITIES,EXPECTED_RUNTIME_BUILD_ID_ENV,HostIdleHandover,stopHost,handoffHost,runAsHostGenerationProcess,ensureHost,WakeSourceTracker,isSessionBusySnapshot,isHandoffBusy,readDrainVerdicts,BEGIN_HANDOVER_COMMAND,parseBeginHandover,beginHandoverResponse,handoverRefusal,withHostIdentity,isHostIdle,performIdleHandover,readHostStatus,HOST_EXIT_OK,HOST_EXIT_ERROR,HOST_EXIT_USAGE,HOST_EXIT_REFUSED,HOST_EXIT_FALLBACK,TUI_PROBE_TIMEOUT_MS,endpointProbeTimeoutMs,classifyEndpointLiveness,readAllHostStatus,runHostRequest,runHostCommand,parseHostArgs};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url); { const __piWorkerThreads = require("node:worker_threads"); if (typeof __piWorkerThreads.markAsUncloneable !== "function") { __piWorkerThreads.markAsUncloneable = () => {}; } }
|
|
3
|
-
import{enableStartupCompileCache}from"./chunk-F73COJ7R.js";import{main}from"./chunk-
|
|
3
|
+
import{enableStartupCompileCache}from"./chunk-F73COJ7R.js";import{main}from"./chunk-2EYJJDES.js";import"./chunk-Q23IMPRD.js";import"./chunk-QNAG7FYM.js";import"./chunk-E6TL3R3I.js";import{configureHttpDispatcher}from"./chunk-WIBTUARS.js";import"./chunk-LYYI74CY.js";import"./chunk-PPX4BWTM.js";import"./chunk-5N4ZSDFS.js";import"./chunk-WIAXG52U.js";import"./chunk-U5KVIAHJ.js";import"./chunk-KL7ZUB7X.js";import"./chunk-JABBHOD5.js";import"./chunk-XOUTBUAV.js";import"./chunk-LJWC5IVX.js";import"./chunk-QMRJYMNH.js";import"./chunk-6KIZRGOT.js";import"./chunk-UWYQPA26.js";import"./chunk-H4QOEVS5.js";import"./chunk-U45BOWV5.js";import"./chunk-F6EQ7EV3.js";import"./chunk-JEZWV7JW.js";import"./chunk-S2TCHQTE.js";import"./chunk-7X72IACK.js";import"./chunk-KUPQO7MC.js";import"./chunk-YU2P3CAR.js";import"./chunk-BMX2U22F.js";import"./chunk-ATACOV2Q.js";import"./chunk-CIRZTP7W.js";import"./chunk-22DAHAHO.js";import"./chunk-XYDZ3LIE.js";import"./chunk-HB35RBP4.js";import"./chunk-7Q3EY6HH.js";import"./chunk-6SMU7ANE.js";import"./chunk-MH2BFYGN.js";import"./chunk-26UBFF6N.js";import"./chunk-F4Y75Q3Q.js";import"./chunk-GZVCRV7I.js";import"./chunk-U3VOXCGP.js";import"./chunk-RFB5CBW7.js";import"./chunk-2VZJTDUX.js";import"./chunk-KC5TT7DH.js";import{installEarlyInspectorVmImportRecovery}from"./chunk-KEMQXWPY.js";import"./chunk-ZOFZRJSL.js";import"./chunk-2SOVDETB.js";import{APP_NAME,scrubBrandFromEnvironment}from"./chunk-463OK2Y4.js";import"./chunk-ATQFN5HI.js";import"./chunk-RBCQOIAD.js";import"./chunk-JRGNL6WM.js";import"./chunk-RKJNJ3GI.js";import"./chunk-CWLCGRUS.js";import"./chunk-6WCOSBI7.js";import"./chunk-LHYG7TK7.js";import"./chunk-KRNXUTZJ.js";import"./chunk-YOPVJDSU.js";import"./chunk-WHPDEDCC.js";import"./chunk-HK46JMSC.js";import"./chunk-2WEI2XTZ.js";import"./chunk-WDTJ6JKE.js";import"./chunk-5ROMKDLK.js";import"./chunk-3W47LTXQ.js";import"./chunk-45SZOLCU.js";import"./chunk-BBK6SSYT.js";import"./chunk-BPX6QWPD.js";import"./chunk-XL5KIYQF.js";import"./chunk-DMI55M2N.js";import"./chunk-PJ34QVL5.js";import"./chunk-IKOFCODM.js";enableStartupCompileCache();installEarlyInspectorVmImportRecovery();process.title=APP_NAME;scrubBrandFromEnvironment();process.env.PI_CODING_AGENT="true";process.emitWarning=(()=>{});configureHttpDispatcher();await main(process.argv.slice(2));
|
|
@@ -1,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{parseHostArgs,runHostCommand}from"./chunk-
|
|
2
|
+
import{parseHostArgs,runHostCommand}from"./chunk-XOUTBUAV.js";import"./chunk-LJWC5IVX.js";import"./chunk-QMRJYMNH.js";import"./chunk-6KIZRGOT.js";import"./chunk-ATACOV2Q.js";import"./chunk-CIRZTP7W.js";import"./chunk-22DAHAHO.js";import"./chunk-XYDZ3LIE.js";import"./chunk-MH2BFYGN.js";import"./chunk-26UBFF6N.js";import"./chunk-F4Y75Q3Q.js";import"./chunk-U3VOXCGP.js";import"./chunk-RFB5CBW7.js";import"./chunk-2VZJTDUX.js";import"./chunk-KC5TT7DH.js";import"./chunk-463OK2Y4.js";import"./chunk-ATQFN5HI.js";import"./chunk-RBCQOIAD.js";import"./chunk-RKJNJ3GI.js";import"./chunk-6WCOSBI7.js";import"./chunk-YOPVJDSU.js";import"./chunk-WHPDEDCC.js";import"./chunk-HK46JMSC.js";import"./chunk-2WEI2XTZ.js";import"./chunk-WDTJ6JKE.js";import"./chunk-5ROMKDLK.js";import"./chunk-3W47LTXQ.js";import"./chunk-45SZOLCU.js";import"./chunk-XL5KIYQF.js";import"./chunk-DMI55M2N.js";import"./chunk-PJ34QVL5.js";import"./chunk-IKOFCODM.js";export{parseHostArgs,runHostCommand};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url); { const __piWorkerThreads = require("node:worker_threads"); if (typeof __piWorkerThreads.markAsUncloneable !== "function") { __piWorkerThreads.markAsUncloneable = () => {}; } }
|
|
3
|
-
import{DEFAULT_HANDOFF_GRACE_MS,DEFAULT_HOST_IDLE_EXIT_MS,HANDOFF_GRACE_MS_ENV,HOST_COLD_START_ENV,HOST_IDLE_EXIT_MS_ENV,INTERNAL_SUPERVISOR_FLAG,IdleExitDecider,classifyChildExit,createInternalSocketPath,findInternalSupervisorArgs,parseColdStart,parseIdleExitMs,parseSupervisorArgs,resolveCliMainPath,resolveHostChildLaunch,resolveHostPolicy,runHostSupervisor,spawnableChildLaunch}from"./chunk-
|
|
3
|
+
import{DEFAULT_HANDOFF_GRACE_MS,DEFAULT_HOST_IDLE_EXIT_MS,HANDOFF_GRACE_MS_ENV,HOST_COLD_START_ENV,HOST_IDLE_EXIT_MS_ENV,INTERNAL_SUPERVISOR_FLAG,IdleExitDecider,classifyChildExit,createInternalSocketPath,findInternalSupervisorArgs,parseColdStart,parseIdleExitMs,parseSupervisorArgs,resolveCliMainPath,resolveHostChildLaunch,resolveHostPolicy,runHostSupervisor,spawnableChildLaunch}from"./chunk-ATACOV2Q.js";import"./chunk-CIRZTP7W.js";import"./chunk-22DAHAHO.js";import"./chunk-XYDZ3LIE.js";import"./chunk-U3VOXCGP.js";import"./chunk-463OK2Y4.js";import"./chunk-ATQFN5HI.js";import"./chunk-IKOFCODM.js";export{DEFAULT_HANDOFF_GRACE_MS,DEFAULT_HOST_IDLE_EXIT_MS,HANDOFF_GRACE_MS_ENV,HOST_COLD_START_ENV,HOST_IDLE_EXIT_MS_ENV,INTERNAL_SUPERVISOR_FLAG,IdleExitDecider,classifyChildExit,createInternalSocketPath,findInternalSupervisorArgs,parseColdStart,parseIdleExitMs,parseSupervisorArgs,resolveCliMainPath,resolveHostChildLaunch,resolveHostPolicy,runHostSupervisor,spawnableChildLaunch};
|
|
@@ -16,9 +16,9 @@ renameSync(temporary, launcher);
|
|
|
16
16
|
`,{mode:CRASH_RECORD_FILE_MODE}),pruneHostCrashRecords(daemonDir)}catch{}}function readHostCrashRecords(daemonDir){let raw;try{raw=readFileSync2(hostCrashRecordFile(daemonDir),"utf8")}catch{return[]}let records=[];for(let line of raw.split(`
|
|
17
17
|
`))if(line.trim()!=="")try{let value=JSON.parse(line);typeof value=="object"&&value!==null&&typeof Reflect.get(value,"at")=="string"&&records.push(value)}catch{}return records}function pruneHostCrashRecords(daemonDir){let records=readHostCrashRecords(daemonDir);if(records.length<=HOST_CRASH_RECORD_LIMIT)return;let kept=records.slice(records.length-HOST_CRASH_RECORD_LIMIT);writeFileSync(hostCrashRecordFile(daemonDir),`${kept.map(r=>JSON.stringify(r)).join(`
|
|
18
18
|
`)}
|
|
19
|
-
`,{mode:CRASH_RECORD_FILE_MODE})}function classifyChildExit(code,signal){return code===0&&signal===null?{reason:"rpc host exited on its own idle policy",exitCode:0}:{reason:`rpc host process exited unexpectedly (${code??signal})`,exitCode:1}}function noteChildExit(daemonDir,code,signal,childStartedAt,now=Date.now()){classifyChildExit(code,signal).exitCode!==0&&recordHostCrash(daemonDir,{at:new Date(now).toISOString(),...signal===null?{code:code??void 0}:{signal},uptimeMs:Math.max(0,now-childStartedAt),kind:"rpc-host",detection:"supervisor",...crashingRuntimeVersions()})}var OBSERVE_REQUEST_FIELD="observe",OBSERVING_COMMANDS=new Set(["get_protocol_info","list_sessions"]);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"?!0:record[OBSERVE_REQUEST_FIELD]===!0&&OBSERVING_COMMANDS.has(record.type)}var MAX_CLASSIFIED_LINE_BYTES=64*1024,NEWLINE=10,ClientOccupancy=class{constructor(onAttach){this.clients=new Set,this.observers=new Set,this.attached=new Set,this.onAttach=onAttach}get attachedCount(){return this.attached.size}get unclassifiedCount(){return this.clients.size-this.observers.size-this.attached.size}admit(client){this.clients.add(client);let pending=Buffer.alloc(0),attach=()=>{client.off("data",classify),pending=Buffer.alloc(0),this.observers.delete(client),this.attached.add(client),this.onAttach()},classify=chunk=>{pending=Buffer.concat([pending,chunk]);for(let newline=pending.indexOf(NEWLINE);newline!==-1;newline=pending.indexOf(NEWLINE)){let line=pending.subarray(0,newline).toString("utf8");if(pending=pending.subarray(newline+1),!isObservingRequest(line)){attach();return}this.observers.add(client)}pending.length>MAX_CLASSIFIED_LINE_BYTES&&attach()};client.on("data",classify)}release(client){this.clients.delete(client),this.observers.delete(client),this.attached.delete(client)}destroyAll(){for(let client of this.clients)client.destroy()}};var HOST_COLD_START_ENV="SENPI_RPC_HOST_COLD_START",HOST_IDLE_EXIT_MS_ENV="SENPI_RPC_HOST_IDLE_EXIT_MS",DEFAULT_HOST_IDLE_EXIT_MS=9e5,HANDOFF_GRACE_MS_ENV="SENPI_RPC_HANDOFF_GRACE_MS",DEFAULT_HANDOFF_GRACE_MS=6e5;function parseColdStart(value){return value==="transient"||value==="persistent"?value:void 0}function parseIdleExitMs(value){if(value===void 0||!/^\d+$/.test(value.trim()))return;let parsed=Number(value.trim());return Number.isFinite(parsed)&&parsed>0?parsed:void 0}function resolveHostPolicy(settings,env){let record=isRecord2(settings)?settings:{},coldStart=parseColdStart(env[HOST_COLD_START_ENV])??parseColdStart(asOptionalString(record.coldStart))??"transient",idleExitMs=parseIdleExitMs(env[HOST_IDLE_EXIT_MS_ENV])??parseIdleExitMs(asOptionalString(record.idleExitMs))??9e5;return{coldStart,idleExitMs}}var IdleExitDecider=class{constructor(idleExitMs,now=Date.now){this.idleExitMs=idleExitMs,this.now=now}update(activity){return activity.connections>0||activity.activeTurns>0?(this.idleSince=void 0,"active"):this.idleExitMs===Number.POSITIVE_INFINITY?"idle":this.idleSince===void 0?(this.idleSince=this.now(),"idle"):this.now()-this.idleSince>=this.idleExitMs?"exit":"idle"}};function isRecord2(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function asOptionalString(value){return typeof value=="string"?value:typeof value=="number"?String(value):void 0}function hostCrashCleanupPaths(targets){let publicEntry=targets.platform==="win32"?[targets.publicSocket]:[];return targets.successor?publicEntry:[targets.generationPidFile,targets.settingsFile,...publicEntry,targets.pointerFile]}import{createHash,randomUUID}from"node:crypto";import{basename as basename3,dirname as dirname4,join as join6,win32 as win322}from"node:path";import{existsSync as existsSync2,realpathSync as realpathSync2}from"node:fs";import{basename as basename2,dirname as dirname3,join as join5,resolve as resolve2}from"node:path";function canonicalSessionPath(path){let absolutePath=resolve2(path),missing=[],existing=absolutePath;for(;!existsSync2(existing);){let parent=dirname3(existing);if(parent===existing)return absolutePath;missing.unshift(basename2(existing)),existing=parent}try{return join5(realpathSync2(existing),...missing)}catch{return absolutePath}}var HOST_DAEMON_DIR_ENV="SENPI_RPC_HOST_DAEMON_DIR";function canonicalEndpointPath(socket,platform=process.platform){return platform==="win32"?win322.normalize(socket).toLowerCase():socket.startsWith("\0")?socket:join6(canonicalSessionPath(dirname4(socket)),basename3(socket))}function daemonDirectoryName(socket,platform=process.platform){return directoryNameOf(canonicalEndpointPath(socket,platform))}function directoryNameOf(endpoint){return createHash("sha256").update(endpoint,"utf8").digest("hex").slice(0,16)}function createHostDaemonPaths(target){let flatDir=join6(target.agentDir??getAgentDir(),"rpc-host-daemon");return{socket:target.socket,flatDir,layoutMarker:join6(flatDir,"layout.json"),legacyPidFile:join6(flatDir,"host.pid"),...hostDaemonDirectoryPaths(join6(flatDir,daemonDirectoryName(target.socket)))}}function hostDaemonDirectoryPaths(dir){return{dir,endpointFile:join6(dir,"endpoint.json"),pointerFile:join6(dir,"host.pid"),lockFile:join6(dir,"daemon.lock"),settingsFile:join6(dir,"settings.json"),stderrLog:join6(dir,"stderr.log"),generationsDir:join6(dir,"generations"),reservationsDir:join6(dir,"reservations")}}function generationPaths(paths,instanceId){let dir=join6(paths.generationsDir,instanceId);return{dir,relativeDir:`generations/${instanceId}`,pidFile:join6(dir,"host.pid"),settingsFile:join6(dir,"settings.json"),scratchDir:join6(dir,"scratch")}}import{rename,rm}from"node:fs/promises";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:""});import{readFile,writeFile}from"node:fs/promises";async function readFileOrUndefined(path){try{return await readFile(path,"utf8")}catch(error){if(isNodeErrorCode2(error,"ENOENT")||isNodeErrorCode2(error,"ENOTDIR"))return;throw error}}function parseJson(text){if(text!==void 0)try{let parsed=JSON.parse(text);return isRecord3(parsed)?parsed:void 0}catch{return}}function isRecord3(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function isNodeErrorCode2(error,code){return error instanceof Error&&"code"in error&&error.code===code}var TABLE_START_BYTES=1<<20,TABLE_MAX_BYTES=32<<20;async function releaseGeneration(paths,owner){let generation=generationPaths(paths,owner.instanceId),record=parseDaemonPidFile(await readFileOrUndefined(generation.pidFile)??"");if(record!==void 0&&record.pid!==owner.pid)return;if(owner.superseded===!0){await rm(generation.dir,{recursive:!0,force:!0});return}let ownsPointer=parseJson(await readFileOrUndefined(paths.pointerFile))?.instance_id===owner.instanceId;ownsPointer&&await rm(paths.settingsFile,{force:!0}),await rm(generation.dir,{recursive:!0,force:!0}),ownsPointer&&await rm(paths.pointerFile,{force:!0})}var HOST_INSTANCE_ID_ENV="SENPI_RPC_HOST_INSTANCE_ID";import{mkdir,readFile as readFile2,rename as rename2,stat,unlink,writeFile as writeFile2}from"node:fs/promises";import{dirname as dirname5}from"node:path";var PUBLIC_SOCKET_IDENTITY_FILE="public-socket.owner";var MAX_SOCKET_PATH_BYTES=103;function sameSocketIdentity(a,b){return a.dev===b.dev&&a.ino===b.ino}async function statSocketIdentity(socketPath){try{let{dev,ino}=await stat(socketPath);return{dev,ino}}catch(cause){if(isNodeErrorCode3(cause,"ENOENT"))return;throw cause}}async function classifyEndpointOwnership(socketPath,identity){if(identity===void 0||process.platform==="win32"||socketPath.startsWith("\0"))return"unknown";let current;try{current=await statSocketIdentity(socketPath)}catch{return"unknown"}return current===void 0?"absent":sameSocketIdentity(current,identity)?"held":"replaced"}async function writeSocketIdentityFile(path,identity){await mkdir(dirname5(path),{recursive:!0,mode:448});let tmpPath=`${path}.${process.pid}.tmp`;await writeFile2(tmpPath,`${JSON.stringify(identity)}
|
|
19
|
+
`,{mode:CRASH_RECORD_FILE_MODE})}function classifyChildExit(code,signal){return code===0&&signal===null?{reason:"rpc host exited on its own idle policy",exitCode:0}:{reason:`rpc host process exited unexpectedly (${code??signal})`,exitCode:1}}function noteChildExit(daemonDir,code,signal,childStartedAt,now=Date.now()){classifyChildExit(code,signal).exitCode!==0&&recordHostCrash(daemonDir,{at:new Date(now).toISOString(),...signal===null?{code:code??void 0}:{signal},uptimeMs:Math.max(0,now-childStartedAt),kind:"rpc-host",detection:"supervisor",...crashingRuntimeVersions()})}var OBSERVE_REQUEST_FIELD="observe",OBSERVING_COMMANDS=new Set(["get_protocol_info","list_sessions"]);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"?!0:record[OBSERVE_REQUEST_FIELD]===!0&&OBSERVING_COMMANDS.has(record.type)}var MAX_CLASSIFIED_LINE_BYTES=64*1024,NEWLINE=10,ClientOccupancy=class{constructor(onAttach){this.clients=new Set,this.observers=new Set,this.attached=new Set,this.onAttach=onAttach}get attachedCount(){return this.attached.size}get unclassifiedCount(){return this.clients.size-this.observers.size-this.attached.size}admit(client){this.clients.add(client);let pending=Buffer.alloc(0),attach=()=>{client.off("data",classify),pending=Buffer.alloc(0),this.observers.delete(client),this.attached.add(client),this.onAttach()},classify=chunk=>{pending=Buffer.concat([pending,chunk]);for(let newline=pending.indexOf(NEWLINE);newline!==-1;newline=pending.indexOf(NEWLINE)){let line=pending.subarray(0,newline).toString("utf8");if(pending=pending.subarray(newline+1),!isObservingRequest(line)){attach();return}this.observers.add(client)}pending.length>MAX_CLASSIFIED_LINE_BYTES&&attach()};client.on("data",classify)}release(client){this.clients.delete(client),this.observers.delete(client),this.attached.delete(client)}destroyAll(){for(let client of this.clients)client.destroy()}};function rpcHostExecArgv(execArgv=process.execArgv,bun=process.versions.bun!==void 0){let args=[];for(let index=0;index<execArgv.length;index++){let arg=execArgv[index];if(bun){if(arg==="-e"||arg==="--eval"||arg==="-p"||arg==="--print"||arg==="-pe"){index++;continue}if(arg.startsWith("-e")||arg.startsWith("-p"))continue}if(arg==="-e"||arg==="--eval"||arg==="-pe"||arg==="--input-type"||arg==="--input_type"){index++;continue}if(arg==="-p"||arg==="--print"){execArgv[index+1]!==void 0&&!execArgv[index+1].startsWith("-")&&index++;continue}arg==="-i"||arg==="--interactive"||arg.startsWith("--interactive=")||arg.startsWith("--eval=")||arg.startsWith("--print=")||arg.startsWith("--input-type=")||arg.startsWith("--input_type=")||args.push(arg)}return args}var HOST_COLD_START_ENV="SENPI_RPC_HOST_COLD_START",HOST_IDLE_EXIT_MS_ENV="SENPI_RPC_HOST_IDLE_EXIT_MS",DEFAULT_HOST_IDLE_EXIT_MS=9e5,HANDOFF_GRACE_MS_ENV="SENPI_RPC_HANDOFF_GRACE_MS",DEFAULT_HANDOFF_GRACE_MS=6e5;function parseColdStart(value){return value==="transient"||value==="persistent"?value:void 0}function parseIdleExitMs(value){if(value===void 0||!/^\d+$/.test(value.trim()))return;let parsed=Number(value.trim());return Number.isFinite(parsed)&&parsed>0?parsed:void 0}function resolveHostPolicy(settings,env){let record=isRecord2(settings)?settings:{},coldStart=parseColdStart(env[HOST_COLD_START_ENV])??parseColdStart(asOptionalString(record.coldStart))??"transient",idleExitMs=parseIdleExitMs(env[HOST_IDLE_EXIT_MS_ENV])??parseIdleExitMs(asOptionalString(record.idleExitMs))??9e5;return{coldStart,idleExitMs}}var IdleExitDecider=class{constructor(idleExitMs,now=Date.now){this.idleExitMs=idleExitMs,this.now=now}update(activity){return activity.connections>0||activity.activeTurns>0?(this.idleSince=void 0,"active"):this.idleExitMs===Number.POSITIVE_INFINITY?"idle":this.idleSince===void 0?(this.idleSince=this.now(),"idle"):this.now()-this.idleSince>=this.idleExitMs?"exit":"idle"}};function isRecord2(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function asOptionalString(value){return typeof value=="string"?value:typeof value=="number"?String(value):void 0}function hostCrashCleanupPaths(targets){let publicEntry=targets.platform==="win32"?[targets.publicSocket]:[];return targets.successor?publicEntry:[targets.generationPidFile,targets.settingsFile,...publicEntry,targets.pointerFile]}import{createHash,randomUUID}from"node:crypto";import{basename as basename3,dirname as dirname4,join as join6,win32 as win322}from"node:path";import{existsSync as existsSync2,realpathSync as realpathSync2}from"node:fs";import{basename as basename2,dirname as dirname3,join as join5,resolve as resolve2}from"node:path";function canonicalSessionPath(path){let absolutePath=resolve2(path),missing=[],existing=absolutePath;for(;!existsSync2(existing);){let parent=dirname3(existing);if(parent===existing)return absolutePath;missing.unshift(basename2(existing)),existing=parent}try{return join5(realpathSync2(existing),...missing)}catch{return absolutePath}}var HOST_DAEMON_DIR_ENV="SENPI_RPC_HOST_DAEMON_DIR";function canonicalEndpointPath(socket,platform=process.platform){return platform==="win32"?win322.normalize(socket).toLowerCase():socket.startsWith("\0")?socket:join6(canonicalSessionPath(dirname4(socket)),basename3(socket))}function daemonDirectoryName(socket,platform=process.platform){return directoryNameOf(canonicalEndpointPath(socket,platform))}function directoryNameOf(endpoint){return createHash("sha256").update(endpoint,"utf8").digest("hex").slice(0,16)}function createHostDaemonPaths(target){let flatDir=join6(target.agentDir??getAgentDir(),"rpc-host-daemon");return{socket:target.socket,flatDir,layoutMarker:join6(flatDir,"layout.json"),legacyPidFile:join6(flatDir,"host.pid"),...hostDaemonDirectoryPaths(join6(flatDir,daemonDirectoryName(target.socket)))}}function hostDaemonDirectoryPaths(dir){return{dir,endpointFile:join6(dir,"endpoint.json"),pointerFile:join6(dir,"host.pid"),lockFile:join6(dir,"daemon.lock"),settingsFile:join6(dir,"settings.json"),stderrLog:join6(dir,"stderr.log"),generationsDir:join6(dir,"generations"),reservationsDir:join6(dir,"reservations")}}function generationPaths(paths,instanceId){let dir=join6(paths.generationsDir,instanceId);return{dir,relativeDir:`generations/${instanceId}`,pidFile:join6(dir,"host.pid"),settingsFile:join6(dir,"settings.json"),scratchDir:join6(dir,"scratch")}}import{rename,rm}from"node:fs/promises";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:""});import{readFile,writeFile}from"node:fs/promises";async function readFileOrUndefined(path){try{return await readFile(path,"utf8")}catch(error){if(isNodeErrorCode2(error,"ENOENT")||isNodeErrorCode2(error,"ENOTDIR"))return;throw error}}function parseJson(text){if(text!==void 0)try{let parsed=JSON.parse(text);return isRecord3(parsed)?parsed:void 0}catch{return}}function isRecord3(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function isNodeErrorCode2(error,code){return error instanceof Error&&"code"in error&&error.code===code}var TABLE_START_BYTES=1<<20,TABLE_MAX_BYTES=32<<20;async function releaseGeneration(paths,owner){let generation=generationPaths(paths,owner.instanceId),record=parseDaemonPidFile(await readFileOrUndefined(generation.pidFile)??"");if(record!==void 0&&record.pid!==owner.pid)return;if(owner.superseded===!0){await rm(generation.dir,{recursive:!0,force:!0});return}let ownsPointer=parseJson(await readFileOrUndefined(paths.pointerFile))?.instance_id===owner.instanceId;ownsPointer&&await rm(paths.settingsFile,{force:!0}),await rm(generation.dir,{recursive:!0,force:!0}),ownsPointer&&await rm(paths.pointerFile,{force:!0})}var HOST_INSTANCE_ID_ENV="SENPI_RPC_HOST_INSTANCE_ID";import{mkdir,readFile as readFile2,rename as rename2,stat,unlink,writeFile as writeFile2}from"node:fs/promises";import{dirname as dirname5}from"node:path";var PUBLIC_SOCKET_IDENTITY_FILE="public-socket.owner";var MAX_SOCKET_PATH_BYTES=103;function sameSocketIdentity(a,b){return a.dev===b.dev&&a.ino===b.ino}async function statSocketIdentity(socketPath){try{let{dev,ino}=await stat(socketPath);return{dev,ino}}catch(cause){if(isNodeErrorCode3(cause,"ENOENT"))return;throw cause}}async function classifyEndpointOwnership(socketPath,identity){if(identity===void 0||process.platform==="win32"||socketPath.startsWith("\0"))return"unknown";let current;try{current=await statSocketIdentity(socketPath)}catch{return"unknown"}return current===void 0?"absent":sameSocketIdentity(current,identity)?"held":"replaced"}async function writeSocketIdentityFile(path,identity){await mkdir(dirname5(path),{recursive:!0,mode:448});let tmpPath=`${path}.${process.pid}.tmp`;await writeFile2(tmpPath,`${JSON.stringify(identity)}
|
|
20
20
|
`,{mode:384}),await rename2(tmpPath,path)}async function unlinkOwnedSocket(socketPath,identity,log){if(process.platform==="win32"||socketPath.startsWith("\0"))return;let current;try{current=await statSocketIdentity(socketPath)}catch(cause){log(`socket ${socketPath} ownership could not be verified (${errorMessage(cause)}); leaving it`);return}if(current!==void 0){if(identity===void 0){log(`socket path ${socketPath} ownership unknown; leaving it`);return}if(!sameSocketIdentity(current,identity)){log(`socket path ${socketPath} now owned by another host; leaving it`);return}try{await unlink(socketPath)}catch(cause){isNodeErrorCode3(cause,"ENOENT")||log(`socket ${socketPath} removal failed (${errorMessage(cause)})`)}}}async function shieldSocketDuringClose(socketPath,close){if(process.platform==="win32"||socketPath.startsWith("\0"))return close();let shieldPath=`${socketPath}.shield-${process.pid}`,shielded=!1;try{await statSocketIdentity(socketPath)!==void 0&&(await rename2(socketPath,shieldPath),shielded=!0)}catch{}try{await close()}finally{if(shielded)try{await rename2(shieldPath,socketPath)}catch{}}}function errorMessage(cause){return cause instanceof Error?cause.message:String(cause)}function isNodeErrorCode3(cause,code){return cause instanceof Error&&"code"in cause&&cause.code===code}var SUPERSESSION_POLL_MS=1e3,ABSENT_CONFIRMATIONS=3;function watchForSupersession(endpoint,onLost){if(endpoint.identity===void 0||process.platform==="win32")return()=>{};let absentPolls=0,lost=!1,lose=loss=>{lost||(lost=!0,stop(),onLost(loss))},timer=setInterval(()=>{endpoint.settled?.()!==!0&&classifyEndpointOwnership(endpoint.path,endpoint.identity).then(ownership=>{if(endpoint.settled?.()!==!0)switch(ownership){case"replaced":lose("replaced");return;case"absent":if(absentPolls+=1,absentPolls<ABSENT_CONFIRMATIONS)return;lose("absent");return;case"held":case"unknown":absentPolls=0;return}},ignore)},SUPERSESSION_POLL_MS);timer.unref?.();let stop=()=>clearInterval(timer);return stop}function ignore(){}var HOST_WATCH_FD_ENV="SENPI_RPC_HOST_WATCH_FD",HOST_SCRATCH_DIR_ENV="SENPI_RPC_HOST_SCRATCH_DIR",HOST_PUBLIC_SOCKET_ENV="SENPI_RPC_HOST_PUBLIC_SOCKET",HOST_WATCH_PPID_ENV="SENPI_RPC_HOST_WATCH_PPID";var HOST_CLEANUP_PATHS_ENV="SENPI_RPC_HOST_CLEANUP_PATHS";import{StringDecoder}from"node:string_decoder";var MAX_RPC_LINE_CHARACTERS=16*1024*1024;function attachJsonlLineReader(stream,onLine,options={}){let decoder=new StringDecoder("utf8"),maxLineLength=options.maxLineLength??Number.POSITIVE_INFINITY;if(!(maxLineLength>0))throw new Error("maxLineLength must be greater than zero.");let buffer="",discardingOversizedLine=!1,consume=text=>{let offset=0;for(;offset<text.length;){if(discardingOversizedLine){let newlineIndex2=text.indexOf(`
|
|
21
21
|
`,offset);if(newlineIndex2===-1)return;discardingOversizedLine=!1,offset=newlineIndex2+1;continue}let newlineIndex=text.indexOf(`
|
|
22
|
-
`,offset);if(newlineIndex===-1){let remainder=text.slice(offset);buffer.length+remainder.length>maxLineLength?(buffer="",discardingOversizedLine=!0,options.onOversizedLine?.()):buffer+=remainder;return}let segment=text.slice(offset,newlineIndex);if(buffer.length+segment.length>maxLineLength)options.onOversizedLine?.();else{let line=buffer+segment;onLine(line.endsWith("\r")?line.slice(0,-1):line)}buffer="",offset=newlineIndex+1}},onData=chunk=>{consume(typeof chunk=="string"?chunk:decoder.write(chunk))},onEnd=()=>{consume(decoder.end()),!discardingOversizedLine&&buffer.length>0&&onLine(buffer.endsWith("\r")?buffer.slice(0,-1):buffer),buffer="",discardingOversizedLine=!1};return stream.on("data",onData),stream.on("end",onEnd),()=>{stream.off("data",onData),stream.off("end",onEnd)}}function activeTurnsForIdleDecision(input){return input.healthy?input.observedBusy:input.unhealthySince===void 0||input.now-input.unhealthySince<input.unknownGraceMs?1:0}function createObserverLink(options){let current,healthy=!1,unhealthySince,retry,armRetry=()=>{retry!==void 0||options.settled()||(retry=options.setTimer(()=>{retry=void 0,open().catch(armRetry)},options.retryDelayMs))};async function open(){let socket=await options.open();current=socket,healthy=!0,unhealthySince=void 0,socket.onLost(()=>{current!==socket||options.settled()||(healthy=!1,unhealthySince??=options.now(),current=void 0,armRetry())})}return{open,healthy:()=>healthy,unhealthySince:()=>unhealthySince,stop:()=>{retry?.cancel(),retry=void 0,current=void 0}}}import{createHash as createHash2,randomBytes,timingSafeEqual}from"node:crypto";import{chmod,mkdir as mkdir2,readFile as readFile3,writeFile as writeFile3}from"node:fs/promises";import{dirname as dirname6,win32 as win323}from"node:path";var WINDOWS_PIPE_PREFIX="\\\\.\\pipe\\senpi-rpc-",SOCKET_SECRET_BYTES=32,SOCKET_SECRET_SUFFIX=".secret",SOCKET_SECRET_FILE_ENV="SENPI_RPC_SOCKET_SECRET_FILE",SOCKET_HANDSHAKE_TIMEOUT_MS=2e3;function socketSecretPath(logicalPath){if(logicalPath.toLowerCase().startsWith("\\\\.\\pipe\\"))throw new Error(`Windows RPC named-pipe addresses need a logical filesystem path for their secret: ${logicalPath}`);return`${logicalPath}${SOCKET_SECRET_SUFFIX}`}async function ensureSocketSecret(path){try{let existing=await readFile3(path);if(existing.length===SOCKET_SECRET_BYTES)return existing}catch(error){if(!isNodeErrorCode4(error,"ENOENT"))throw error}return createSocketSecret(path)}async function createSocketSecret(path){await mkdir2(dirname6(path),{recursive:!0});let secret=randomBytes(SOCKET_SECRET_BYTES);return await writeFile3(path,secret,{mode:384}),await chmod(path,384),secret}function resolveSocketTransportAddress(socketPath,platform,secret){if(platform!=="win32"||socketPath.toLowerCase().startsWith("\\\\.\\pipe\\"))return socketPath;if(!/^[a-zA-Z]:[\\/]/.test(socketPath)&&!/^\\\\[^/]/.test(socketPath))throw new Error(`Windows RPC socket path must be drive-qualified or UNC: ${socketPath}`);let canonical=win323.normalize(socketPath).toLowerCase(),identity=Buffer.concat([Buffer.from(canonical,"utf8"),Buffer.from(secret??[])]),name=createHash2("sha256").update(identity).digest("hex").slice(0,32);return`${WINDOWS_PIPE_PREFIX}${name}`}function authenticateSocket(socket,secret,onAuthenticated){let received=Buffer.alloc(0),finish=()=>{clearTimeout(timer),socket.off("data",onData),socket.off("error",onError)},onError=()=>{finish(),socket.destroy()},timer=setTimeout(()=>{finish(),socket.destroy()},SOCKET_HANDSHAKE_TIMEOUT_MS),onData=chunk=>{if(received=Buffer.concat([received,chunk]),received.length<secret.length)return;if(finish(),!timingSafeEqual(received.subarray(0,secret.length),Buffer.from(secret))){socket.destroy();return}let remainder=received.subarray(secret.length);remainder.length>0&&socket.unshift(remainder),onAuthenticated()};socket.on("data",onData),socket.once("error",onError),socket.once("close",finish)}function sendSocketHandshake(socket,secret){socket.write(Buffer.from(secret))}function isNodeErrorCode4(error,code){return error instanceof Error&&"code"in error&&error.code===code}var CHILD_STOP_TIMEOUT_MS=5e3,WINDOWS_SUPERVISOR_SHUTDOWN_HARD_EXIT_MS=2e3,CHILD_WATCH_FD=3;async function createInternalSocketPath(baseDir=tmpdir(),platform=process.platform){if(platform==="win32"){let dir2=join7(baseDir,`internal-${randomUUID2()}`);return await mkdir3(dir2,{recursive:!0,mode:448}),{socket:`\\\\.\\pipe\\senpi-rpc-internal-${randomUUID2()}`,dir:dir2,secretPath:join7(dir2,"secret")}}let dir=join7(tmpdir(),`senpi-rpc-host-internal-${randomUUID2().slice(0,8)}`);return await mkdir3(dir,{recursive:!1,mode:448}),await writeFile4(join7(dir,".owner"),JSON.stringify({pid:process.pid,processStartTime:await readProcessStartTime(process.pid),createdAt:Date.now()}),{mode:384}),{socket:join7(dir,"host.sock"),dir,secretPath:join7(dir,".secret")}}var INTERNAL_SUPERVISOR_FLAG="--internal-rpc-host-supervisor",INJECTABLE_PREFIX_FLAGS=new Set(["--extension"]);function findInternalSupervisorArgs(argv){for(let index=0;index<argv.length;index++){let arg=argv[index];if(arg===INTERNAL_SUPERVISOR_FLAG)return argv.slice(index+1);if(!INJECTABLE_PREFIX_FLAGS.has(arg)||index+1>=argv.length)return;index++}}function parseSupervisorArgs(argv){let hostArgs=[],socket,childCommand,childArgs,agentDir,bindSocket,replaceIdentity;for(let index=0;index<argv.length;index++){let arg=argv[index];if(arg==="--socket"&&index+1<argv.length){socket=argv[++index];continue}if(arg==="--child-command"&&index+1<argv.length){childCommand=argv[++index];continue}if(arg==="--child-args"&&index+1<argv.length){try{let parsed=JSON.parse(argv[++index]);Array.isArray(parsed)&&parsed.every(value=>typeof value=="string")&&(childArgs=parsed)}catch{return}continue}if(arg==="--agent-dir"&&index+1<argv.length){agentDir=argv[++index];continue}if(arg==="--bind"&&index+1<argv.length){bindSocket=argv[++index];continue}if(arg==="--replace"&&index+1<argv.length){replaceIdentity=parseSocketIdentity(argv[++index]);continue}hostArgs.push(arg)}return socket===void 0?void 0:{socket,hostArgs,childCommand,childArgs,agentDir,bindSocket,replaceIdentity}}function parseSocketIdentity(value){let match=/^(\d+):(\d+)$/.exec(value);return match?{dev:Number(match[1]),ino:Number(match[2])}:void 0}function resolveCliMainPath(modulePath=fileURLToPath3(import.meta.url),bundled=isBundledNode){let declared=bundled?resolveDeclaredCliEntry(modulePath):void 0;if(declared!==void 0)return declared;let extension=modulePath.endsWith(".ts")?".ts":".js",unbundled=resolve3(dirname7(modulePath),"..","..",`cli-main${extension}`);return existsSync3(unbundled)?unbundled:resolveDeclaredCliEntry(modulePath)??unbundled}function resolveDeclaredCliEntry(modulePath){let dir=dirname7(modulePath);for(let depth=0;depth<8;depth+=1){let manifestPath=resolve3(dir,"package.json");if(existsSync3(manifestPath)){try{let declared=JSON.parse(readFileSync3(manifestPath,"utf8")).bin,candidates=typeof declared=="string"?[declared]:Object.values(declared??{});for(let candidate of candidates){let entry=resolve3(dir,candidate);if(existsSync3(entry))return entry}}catch{}return}let parent=dirname7(dir);if(parent===dir)return;dir=parent}}function resolveHostChildLaunch(launch,internalSocket,compiled=isBunBinary){return launch.childCommand?{command:launch.childCommand,args:[...launch.childArgs??[],"--listen",`unix://${internalSocket}`]}:{command:process.execPath,args:[...compiled?[]:[...process.execArgv,resolveCliMainPath()],"--mode","rpc","--multi-session","--listen",`unix://${internalSocket}`,...launch.hostArgs]}}function quoteWindowsShellArg(value){return`"${value.replace(/(\\*)"/g,'$1$1\\"').replace(/(\\*)$/,"$1$1").replace(/([()%!^"<>&|;,])/g,"^$1")}"`}function spawnableChildLaunch(launch,platform=process.platform){let extension=extname(launch.command).toLowerCase();return platform!=="win32"||extension!==".cmd"&&extension!==".bat"?{...launch,shell:!1}:{command:quoteWindowsShellArg(launch.command),args:launch.args.map(quoteWindowsShellArg),shell:!0}}async function runHostSupervisor(launch){let paths=createHostDaemonPaths({socket:launch.socket,agentDir:launch.agentDir??getAgentDir()}),told=process.env[HOST_INSTANCE_ID_ENV],instanceId=told!==void 0&&told.trim()!==""?told:randomUUID2(),generation=generationPaths(paths,instanceId),policy=resolveHostPolicy(await readSettingsFile(paths.settingsFile),process.env),publicSocket=launch.socket,bindSocket=launch.bindSocket??publicSocket,successor=launch.bindSocket!==void 0,publicSecret=process.platform==="win32"?await ensurePublicSocketSecret(publicSocket):void 0,internal=await createInternalSocketPath(paths.dir),internalSocket=internal.socket,internalSecretPath=internal.secretPath??socketSecretPath(internalSocket),internalSecret=process.platform==="win32"?await createSocketSecret(internalSecretPath):void 0,clients=new ClientOccupancy(()=>decider.update(currentActivity())),busySessions=new Map,observerSocket,observerLink=createObserverLink({open:async()=>{let secret=internalSecret,next=createConnection(resolveSocketTransportAddress(internalSocket,process.platform,secret));return secret&&sendSocketHandshake(next,secret),await waitForConnect(next,5e3),observerSocket=next,attachJsonlLineReader(next,observeHostEvent,{maxLineLength:MAX_RPC_LINE_CHARACTERS}),{onLost:handler=>{next.once("close",handler),next.once("error",handler)}}},settled:()=>shuttingDown,retryDelayMs:250,now:Date.now,setTimer:(run,ms)=>{let timer=setTimeout(run,ms);return timer.unref?.(),{cancel:()=>clearTimeout(timer)}}}),childExitWatchTimer,stopSupersessionWatch,shuttingDown=!1,draining=!1,endpointReplaced=!1,handoffGraceTimer,shutdownPromise,childLaunch=spawnableChildLaunch(resolveHostChildLaunch(launch,internalSocket)),child=spawn(childLaunch.command,childLaunch.args,{env:{...process.env,...launch.agentDir?{SENPI_CODING_AGENT_DIR:launch.agentDir}:{},[HOST_DAEMON_DIR_ENV]:paths.dir,[HOST_INSTANCE_ID_ENV]:instanceId,[HOST_WATCH_FD_ENV]:String(CHILD_WATCH_FD),[HOST_WATCH_PPID_ENV]:String(process.pid),...internal.dir?{[HOST_SCRATCH_DIR_ENV]:internal.dir}:{},...internalSecret?{[SOCKET_SECRET_FILE_ENV]:internalSecretPath}:{},[HOST_CLEANUP_PATHS_ENV]:hostCrashCleanupPaths({pointerFile:paths.pointerFile,generationPidFile:generation.pidFile,settingsFile:paths.settingsFile,publicSocket,successor:!!successor,platform:process.platform}).join(`
|
|
22
|
+
`,offset);if(newlineIndex===-1){let remainder=text.slice(offset);buffer.length+remainder.length>maxLineLength?(buffer="",discardingOversizedLine=!0,options.onOversizedLine?.()):buffer+=remainder;return}let segment=text.slice(offset,newlineIndex);if(buffer.length+segment.length>maxLineLength)options.onOversizedLine?.();else{let line=buffer+segment;onLine(line.endsWith("\r")?line.slice(0,-1):line)}buffer="",offset=newlineIndex+1}},onData=chunk=>{consume(typeof chunk=="string"?chunk:decoder.write(chunk))},onEnd=()=>{consume(decoder.end()),!discardingOversizedLine&&buffer.length>0&&onLine(buffer.endsWith("\r")?buffer.slice(0,-1):buffer),buffer="",discardingOversizedLine=!1};return stream.on("data",onData),stream.on("end",onEnd),()=>{stream.off("data",onData),stream.off("end",onEnd)}}function activeTurnsForIdleDecision(input){return input.healthy?input.observedBusy:input.unhealthySince===void 0||input.now-input.unhealthySince<input.unknownGraceMs?1:0}function createObserverLink(options){let current,healthy=!1,unhealthySince,retry,armRetry=()=>{retry!==void 0||options.settled()||(retry=options.setTimer(()=>{retry=void 0,open().catch(armRetry)},options.retryDelayMs))};async function open(){let socket=await options.open();current=socket,healthy=!0,unhealthySince=void 0,socket.onLost(()=>{current!==socket||options.settled()||(healthy=!1,unhealthySince??=options.now(),current=void 0,armRetry())})}return{open,healthy:()=>healthy,unhealthySince:()=>unhealthySince,stop:()=>{retry?.cancel(),retry=void 0,current=void 0}}}import{createHash as createHash2,randomBytes,timingSafeEqual}from"node:crypto";import{chmod,mkdir as mkdir2,readFile as readFile3,writeFile as writeFile3}from"node:fs/promises";import{dirname as dirname6,win32 as win323}from"node:path";var WINDOWS_PIPE_PREFIX="\\\\.\\pipe\\senpi-rpc-",SOCKET_SECRET_BYTES=32,SOCKET_SECRET_SUFFIX=".secret",SOCKET_SECRET_FILE_ENV="SENPI_RPC_SOCKET_SECRET_FILE",SOCKET_HANDSHAKE_TIMEOUT_MS=2e3;function socketSecretPath(logicalPath){if(logicalPath.toLowerCase().startsWith("\\\\.\\pipe\\"))throw new Error(`Windows RPC named-pipe addresses need a logical filesystem path for their secret: ${logicalPath}`);return`${logicalPath}${SOCKET_SECRET_SUFFIX}`}async function ensureSocketSecret(path){try{let existing=await readFile3(path);if(existing.length===SOCKET_SECRET_BYTES)return existing}catch(error){if(!isNodeErrorCode4(error,"ENOENT"))throw error}return createSocketSecret(path)}async function createSocketSecret(path){await mkdir2(dirname6(path),{recursive:!0});let secret=randomBytes(SOCKET_SECRET_BYTES);return await writeFile3(path,secret,{mode:384}),await chmod(path,384),secret}function resolveSocketTransportAddress(socketPath,platform,secret){if(platform!=="win32"||socketPath.toLowerCase().startsWith("\\\\.\\pipe\\"))return socketPath;if(!/^[a-zA-Z]:[\\/]/.test(socketPath)&&!/^\\\\[^/]/.test(socketPath))throw new Error(`Windows RPC socket path must be drive-qualified or UNC: ${socketPath}`);let canonical=win323.normalize(socketPath).toLowerCase(),identity=Buffer.concat([Buffer.from(canonical,"utf8"),Buffer.from(secret??[])]),name=createHash2("sha256").update(identity).digest("hex").slice(0,32);return`${WINDOWS_PIPE_PREFIX}${name}`}function authenticateSocket(socket,secret,onAuthenticated){let received=Buffer.alloc(0),finish=()=>{clearTimeout(timer),socket.off("data",onData),socket.off("error",onError)},onError=()=>{finish(),socket.destroy()},timer=setTimeout(()=>{finish(),socket.destroy()},SOCKET_HANDSHAKE_TIMEOUT_MS),onData=chunk=>{if(received=Buffer.concat([received,chunk]),received.length<secret.length)return;if(finish(),!timingSafeEqual(received.subarray(0,secret.length),Buffer.from(secret))){socket.destroy();return}let remainder=received.subarray(secret.length);remainder.length>0&&socket.unshift(remainder),onAuthenticated()};socket.on("data",onData),socket.once("error",onError),socket.once("close",finish)}function sendSocketHandshake(socket,secret){socket.write(Buffer.from(secret))}function isNodeErrorCode4(error,code){return error instanceof Error&&"code"in error&&error.code===code}var CHILD_STOP_TIMEOUT_MS=5e3,WINDOWS_SUPERVISOR_SHUTDOWN_HARD_EXIT_MS=2e3,CHILD_WATCH_FD=3;async function createInternalSocketPath(baseDir=tmpdir(),platform=process.platform){if(platform==="win32"){let dir2=join7(baseDir,`internal-${randomUUID2()}`);return await mkdir3(dir2,{recursive:!0,mode:448}),{socket:`\\\\.\\pipe\\senpi-rpc-internal-${randomUUID2()}`,dir:dir2,secretPath:join7(dir2,"secret")}}let dir=join7(tmpdir(),`senpi-rpc-host-internal-${randomUUID2().slice(0,8)}`);return await mkdir3(dir,{recursive:!1,mode:448}),await writeFile4(join7(dir,".owner"),JSON.stringify({pid:process.pid,processStartTime:await readProcessStartTime(process.pid),createdAt:Date.now()}),{mode:384}),{socket:join7(dir,"host.sock"),dir,secretPath:join7(dir,".secret")}}var INTERNAL_SUPERVISOR_FLAG="--internal-rpc-host-supervisor",INJECTABLE_PREFIX_FLAGS=new Set(["--extension"]);function findInternalSupervisorArgs(argv){for(let index=0;index<argv.length;index++){let arg=argv[index];if(arg===INTERNAL_SUPERVISOR_FLAG)return argv.slice(index+1);if(!INJECTABLE_PREFIX_FLAGS.has(arg)||index+1>=argv.length)return;index++}}function parseSupervisorArgs(argv){let hostArgs=[],socket,childCommand,childArgs,agentDir,bindSocket,replaceIdentity;for(let index=0;index<argv.length;index++){let arg=argv[index];if(arg==="--socket"&&index+1<argv.length){socket=argv[++index];continue}if(arg==="--child-command"&&index+1<argv.length){childCommand=argv[++index];continue}if(arg==="--child-args"&&index+1<argv.length){try{let parsed=JSON.parse(argv[++index]);Array.isArray(parsed)&&parsed.every(value=>typeof value=="string")&&(childArgs=parsed)}catch{return}continue}if(arg==="--agent-dir"&&index+1<argv.length){agentDir=argv[++index];continue}if(arg==="--bind"&&index+1<argv.length){bindSocket=argv[++index];continue}if(arg==="--replace"&&index+1<argv.length){replaceIdentity=parseSocketIdentity(argv[++index]);continue}hostArgs.push(arg)}return socket===void 0?void 0:{socket,hostArgs,childCommand,childArgs,agentDir,bindSocket,replaceIdentity}}function parseSocketIdentity(value){let match=/^(\d+):(\d+)$/.exec(value);return match?{dev:Number(match[1]),ino:Number(match[2])}:void 0}function resolveCliMainPath(modulePath=fileURLToPath3(import.meta.url),bundled=isBundledNode){let declared=bundled?resolveDeclaredCliEntry(modulePath):void 0;if(declared!==void 0)return declared;let extension=modulePath.endsWith(".ts")?".ts":".js",unbundled=resolve3(dirname7(modulePath),"..","..",`cli-main${extension}`);return existsSync3(unbundled)?unbundled:resolveDeclaredCliEntry(modulePath)??unbundled}function resolveDeclaredCliEntry(modulePath){let dir=dirname7(modulePath);for(let depth=0;depth<8;depth+=1){let manifestPath=resolve3(dir,"package.json");if(existsSync3(manifestPath)){try{let declared=JSON.parse(readFileSync3(manifestPath,"utf8")).bin,candidates=typeof declared=="string"?[declared]:Object.values(declared??{});for(let candidate of candidates){let entry=resolve3(dir,candidate);if(existsSync3(entry))return entry}}catch{}return}let parent=dirname7(dir);if(parent===dir)return;dir=parent}}function resolveHostChildLaunch(launch,internalSocket,compiled=isBunBinary){return launch.childCommand?{command:launch.childCommand,args:[...launch.childArgs??[],"--listen",`unix://${internalSocket}`]}:{command:process.execPath,args:[...compiled?[]:[...rpcHostExecArgv(),resolveCliMainPath()],"--mode","rpc","--multi-session","--listen",`unix://${internalSocket}`,...launch.hostArgs]}}function quoteWindowsShellArg(value){return`"${value.replace(/(\\*)"/g,'$1$1\\"').replace(/(\\*)$/,"$1$1").replace(/([()%!^"<>&|;,])/g,"^$1")}"`}function spawnableChildLaunch(launch,platform=process.platform){let extension=extname(launch.command).toLowerCase();return platform!=="win32"||extension!==".cmd"&&extension!==".bat"?{...launch,shell:!1}:{command:quoteWindowsShellArg(launch.command),args:launch.args.map(quoteWindowsShellArg),shell:!0}}async function runHostSupervisor(launch){let paths=createHostDaemonPaths({socket:launch.socket,agentDir:launch.agentDir??getAgentDir()}),told=process.env[HOST_INSTANCE_ID_ENV],instanceId=told!==void 0&&told.trim()!==""?told:randomUUID2(),generation=generationPaths(paths,instanceId),policy=resolveHostPolicy(await readSettingsFile(paths.settingsFile),process.env),publicSocket=launch.socket,bindSocket=launch.bindSocket??publicSocket,successor=launch.bindSocket!==void 0,publicSecret=process.platform==="win32"?await ensurePublicSocketSecret(publicSocket):void 0,internal=await createInternalSocketPath(paths.dir),internalSocket=internal.socket,internalSecretPath=internal.secretPath??socketSecretPath(internalSocket),internalSecret=process.platform==="win32"?await createSocketSecret(internalSecretPath):void 0,clients=new ClientOccupancy(()=>decider.update(currentActivity())),busySessions=new Map,observerSocket,observerLink=createObserverLink({open:async()=>{let secret=internalSecret,next=createConnection(resolveSocketTransportAddress(internalSocket,process.platform,secret));return secret&&sendSocketHandshake(next,secret),await waitForConnect(next,5e3),observerSocket=next,attachJsonlLineReader(next,observeHostEvent,{maxLineLength:MAX_RPC_LINE_CHARACTERS}),{onLost:handler=>{next.once("close",handler),next.once("error",handler)}}},settled:()=>shuttingDown,retryDelayMs:250,now:Date.now,setTimer:(run,ms)=>{let timer=setTimeout(run,ms);return timer.unref?.(),{cancel:()=>clearTimeout(timer)}}}),childExitWatchTimer,stopSupersessionWatch,shuttingDown=!1,draining=!1,endpointReplaced=!1,handoffGraceTimer,shutdownPromise,childLaunch=spawnableChildLaunch(resolveHostChildLaunch(launch,internalSocket)),child=spawn(childLaunch.command,childLaunch.args,{env:{...process.env,...launch.agentDir?{SENPI_CODING_AGENT_DIR:launch.agentDir}:{},[HOST_DAEMON_DIR_ENV]:paths.dir,[HOST_INSTANCE_ID_ENV]:instanceId,[HOST_WATCH_FD_ENV]:String(CHILD_WATCH_FD),[HOST_WATCH_PPID_ENV]:String(process.pid),...internal.dir?{[HOST_SCRATCH_DIR_ENV]:internal.dir}:{},...internalSecret?{[SOCKET_SECRET_FILE_ENV]:internalSecretPath}:{},[HOST_CLEANUP_PATHS_ENV]:hostCrashCleanupPaths({pointerFile:paths.pointerFile,generationPidFile:generation.pidFile,settingsFile:paths.settingsFile,publicSocket,successor:!!successor,platform:process.platform}).join(`
|
|
23
23
|
`),...process.platform==="win32"?{}:{[HOST_PUBLIC_SOCKET_ENV]:publicSocket}},shell:childLaunch.shell,stdio:["ignore","ignore","inherit","pipe"],windowsHide:!0}),childStartedAt=Date.now();child.stdio[CHILD_WATCH_FD]?.on("error",()=>{}),child.once("exit",(code,signal)=>{if(shuttingDown)return;let{reason,exitCode}=classifyChildExit(code,signal);noteChildExit(paths.dir,code,signal,childStartedAt),shutdown(reason,exitCode)});let server=createServer(client=>{let accept=()=>{if(shuttingDown||draining){client.destroy();return}let internal2=createConnection(resolveSocketTransportAddress(internalSocket,process.platform,internalSecret));internalSecret&&sendSocketHandshake(internal2,internalSecret),clients.admit(client);let detach=()=>{clients.release(client),decider.update(currentActivity()),internal2.destroy(),client.destroy()};client.pipe(internal2),internal2.pipe(client),client.once("close",detach),client.once("error",detach),internal2.once("end",()=>client.end(()=>client.destroy())),internal2.once("close",()=>{internal2.readableEnded||detach()}),internal2.once("error",detach)};publicSecret?authenticateSocket(client,publicSecret,accept):accept()});server.once("error",cause=>{shuttingDown||shutdown(`public socket listener failed: ${errorMessage2(cause)}`,1)});let decider=new IdleExitDecider(policy.coldStart==="persistent"?Number.POSITIVE_INFINITY:policy.idleExitMs),tickIntervalMs=Math.max(20,Math.min(1e3,policy.idleExitMs/4)),ticker=setInterval(()=>{!draining&&decider.update(currentActivity())==="exit"&&clients.unclassifiedCount===0&&shutdown("idle",0)},tickIntervalMs);function currentActivity(){return{connections:clients.attachedCount,activeTurns:activeTurnsForIdleDecision({healthy:observerLink.healthy(),unhealthySince:observerLink.unhealthySince(),now:Date.now(),unknownGraceMs:decider.idleExitMs,observedBusy:countBusySessions()})}}function countBusySessions(){let busy=0;for(let count of busySessions.values())count>0&&busy++;return busy}function observeHostEvent(line){let event;try{event=JSON.parse(line)}catch{return}if(typeof event!="object"||event===null)return;let{type,sessionId}=event;if(typeof sessionId=="string"){if(type==="agent_start")busySessions.set(sessionId,(busySessions.get(sessionId)??0)+1);else if(type==="agent_settled")busySessions.set(sessionId,Math.max(0,(busySessions.get(sessionId)??1)-1));else return;decider.update(currentActivity())}}async function shutdown(reason,exitCode){return shutdownPromise??=performShutdown(reason,exitCode),shutdownPromise}async function performShutdown(reason,exitCode){shuttingDown&&process.exit(exitCode),shuttingDown=!0,clearInterval(ticker),handoffGraceTimer&&clearTimeout(handoffGraceTimer),childExitWatchTimer&&clearInterval(childExitWatchTimer),stopSupersessionWatch?.();let hardExit=process.platform==="win32"?setTimeout(()=>process.exit(exitCode),WINDOWS_SUPERVISOR_SHUTDOWN_HARD_EXIT_MS):void 0;try{writeStderrLine(`senpi rpc host supervisor: ${reason} shutdown`),clients.destroyAll(),draining||await shieldSocketDuringClose(publicSocket,()=>closeServer(server)),internal.dir&&await rm2(internal.dir,{recursive:!0,force:!0}),await stopChild(child),observerLink.stop(),observerSocket?.destroy(),publicSocketOwned&&process.platform!=="win32"&&await unlinkOwnedSocket(publicSocket,publicSocketIdentity,supervisorLog),await releaseGeneration(paths,{instanceId,pid:process.pid,superseded:endpointReplaced})}finally{hardExit&&clearTimeout(hardExit),process.exit(exitCode)}}let publicSocketOwned=!1,publicSocketIdentity;function supervisorLog(message){writeStderrLine(`senpi rpc host supervisor: ${message}`)}function drainForHandoff(){if(draining||shuttingDown)return;draining=!0,supervisorLog("draining into the next generation");let graceMs=parseIdleExitMs(process.env[HANDOFF_GRACE_MS_ENV])??6e5;handoffGraceTimer=setTimeout(()=>{supervisorLog(JSON.stringify({event:"handoff_grace_expired",graceMs})),requestChildDrain()},graceMs),handoffGraceTimer.unref(),requestChildDrain()}function requestChildDrain(){if(child.pid!==void 0&&child.exitCode===null&&child.signalCode===null)try{process.kill(child.pid,"SIGUSR1")}catch(cause){supervisorLog(`could not ask the host to drain: ${errorMessage2(cause)}`)}}registerSupervisorSignals(shutdown,drainForHandoff);try{await waitForListener(internalSocket,3e4,internalSecret),await observerLink.open(),await prepareSocketPath(bindSocket),await listen(server,bindSocket,publicSecret),publicSocketOwned=!0,successor&&await adoptPublicSocket(bindSocket,publicSocket,launch.replaceIdentity),publicSocketIdentity=await statSocketIdentity(publicSocket),publicSocketIdentity&&internal.dir&&await writeSocketIdentityFile(join7(internal.dir,PUBLIC_SOCKET_IDENTITY_FILE),publicSocketIdentity),stopSupersessionWatch=watchForSupersession({path:publicSocket,identity:publicSocketIdentity,settled:()=>shuttingDown||draining},loss=>{loss==="replaced"&&(endpointReplaced=!0),supervisorLog(loss==="absent"?"the public socket entry is gone; nothing can reach this generation; draining":"another generation owns the public socket; draining this one"),drainForHandoff()})}catch(cause){await shutdown(`startup failed: ${errorMessage2(cause)}`,1)}if(process.platform==="win32"&&child.pid!==void 0){let childStartTime=await readProcessStartTime(child.pid,process.platform,1e3).catch(()=>{}),missingIdentityChecks=0,checkingChildIdentity=!1;childExitWatchTimer=setInterval(()=>{shuttingDown||checkingChildIdentity||child.exitCode!==null||child.signalCode!==null||(checkingChildIdentity=!0,readProcessStartTime(child.pid,process.platform,1e3).then(currentStartTime=>{currentStartTime===void 0&&!processIsLive(child.pid)?missingIdentityChecks++:currentStartTime!==void 0&&(missingIdentityChecks=0),(childStartTime!==void 0&¤tStartTime!==void 0&¤tStartTime!==childStartTime||missingIdentityChecks>=2)&&shutdown("rpc host child exit observed by identity watchdog",0)}).catch(()=>{}).finally(()=>{checkingChildIdentity=!1}))},500),childExitWatchTimer.unref?.()}writeStderrLine(`senpi rpc host ready on unix://${publicSocket} (coldStart=${policy.coldStart}, idleExitMs=${policy.coldStart==="persistent"?"never":String(policy.idleExitMs)})`),await new Promise(()=>{})}function registerSupervisorSignals(shutdown,drain){for(let signal of process.platform==="win32"?["SIGTERM"]:["SIGTERM","SIGHUP"])process.on(signal,()=>{shutdown(`signal:${signal}`,signal==="SIGHUP"?129:143)});process.platform!=="win32"&&process.on("SIGUSR1",drain)}async function adoptPublicSocket(bindSocket,publicSocket,expected){if(expected===void 0)throw new Error(`${publicSocket}: a generation launch must name the entry it replaces`);let current=await statSocketIdentity(publicSocket);if(current===void 0||current.dev!==expected.dev||current.ino!==expected.ino)throw new Error(`${publicSocket}: owned by another socket entry now; refusing to replace it`);await rename3(bindSocket,publicSocket)}async function ensurePublicSocketSecret(publicSocket){let secretPath=socketSecretPath(publicSocket);try{return await ensureSocketSecret(secretPath)}catch(cause){throw new Error(`senpi rpc host supervisor: cannot provision public socket secret ${secretPath}`,{cause})}}async function readSettingsFile(settingsFile){try{return JSON.parse(await readFile4(settingsFile,"utf8"))}catch{return}}async function stopChild(child){if(!(child.exitCode!==null||child.signalCode!==null)){try{child.kill("SIGTERM")}catch{return}if(!await waitForChildExit(child,CHILD_STOP_TIMEOUT_MS)){try{child.kill("SIGKILL")}catch{return}await waitForChildExit(child,2e3)}}}function waitForChildExit(child,timeoutMs){return child.exitCode!==null||child.signalCode!==null?Promise.resolve(!0):new Promise(resolve4=>{let timer=setTimeout(()=>{child.off("exit",onExit2),resolve4(!1)},timeoutMs),onExit2=()=>{clearTimeout(timer),resolve4(!0)};child.once("exit",onExit2)})}async function waitForListener(socketPath,timeoutMs,secret){let deadline=Date.now()+timeoutMs;for(;Date.now()<=deadline;){if(await canConnect(socketPath,secret))return;await delay(50)}throw new Error(`${socketPath}: host did not start listening within ${timeoutMs}ms`)}function canConnect(socketPath,secret){return new Promise(resolve4=>{let socket=createConnection(resolveSocketTransportAddress(socketPath,process.platform,secret));secret&&sendSocketHandshake(socket,secret);let settle=value=>{socket.destroy(),resolve4(value)};socket.once("connect",()=>settle(!0)),socket.once("error",()=>settle(!1))})}function waitForConnect(socket,timeoutMs){return new Promise((resolve4,reject)=>{let timer=setTimeout(()=>{cleanup(),reject(new Error(`observer connection to internal host timed out after ${timeoutMs}ms`))},timeoutMs),onConnect=()=>{cleanup(),resolve4()},onError=cause=>{cleanup(),reject(cause)},cleanup=()=>{clearTimeout(timer),socket.off("connect",onConnect),socket.off("error",onError)};socket.once("connect",onConnect),socket.once("error",onError)})}async function prepareSocketPath(socketPath){if(process.platform!=="win32"){if(Buffer.byteLength(socketPath)>MAX_SOCKET_PATH_BYTES)throw new Error(`${socketPath}: socket path is ${Buffer.byteLength(socketPath)} bytes, over the ${MAX_SOCKET_PATH_BYTES}-byte limit.`);await mkdir3(dirname7(socketPath),{recursive:!0,mode:448});try{await access(socketPath)}catch(cause){if(isNodeErrorCode5(cause,"ENOENT"))return;throw cause}if(await canConnect(socketPath))throw new Error(`${socketPath}: address already in use by a live server.`);await unlink2(socketPath)}}function listen(server,socketPath,secret){return new Promise((resolve4,reject)=>{server.once("error",reject),server.listen({path:resolveSocketTransportAddress(socketPath,process.platform,secret),readableAll:!1,writableAll:!1},async()=>{server.off("error",reject);try{process.platform!=="win32"&&!socketPath.startsWith("\0")&&await chmod2(socketPath,384),resolve4()}catch(cause){reject(cause)}})})}function closeServer(server){return new Promise(resolve4=>{server.close(()=>resolve4())})}function writeStderrLine(text){try{writeSync(2,`${text}
|
|
24
24
|
`)}catch{}}function delay(ms){return new Promise(resolveDelay=>setTimeout(resolveDelay,ms))}function errorMessage2(cause){return cause instanceof Error?cause.message:String(cause)}function isNodeErrorCode5(cause,code){return cause instanceof Error&&"code"in cause&&cause.code===code}function isEntryScript(){let entry=process.argv[1];if(!entry)return!1;try{return fileURLToPath3(import.meta.url)===realpathSync3(entry)}catch{return!1}}if(!isBundledNode&&isEntryScript()){let launch=parseSupervisorArgs(process.argv.slice(2));launch||(writeStderrLine("usage: host-lifecycle.ts --socket <path> [host cli args...]"),process.exit(2)),runHostSupervisor(launch)}export{DEFAULT_HANDOFF_GRACE_MS,DEFAULT_HOST_IDLE_EXIT_MS,HANDOFF_GRACE_MS_ENV,HOST_COLD_START_ENV,HOST_IDLE_EXIT_MS_ENV,INTERNAL_SUPERVISOR_FLAG,IdleExitDecider,classifyChildExit,createInternalSocketPath,findInternalSupervisorArgs,parseColdStart,parseIdleExitMs,parseSupervisorArgs,resolveCliMainPath,resolveHostChildLaunch,resolveHostPolicy,runHostSupervisor,spawnableChildLaunch};
|
|
@@ -1,2 +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{InteractiveMode,OptimisticUserEchoController,createInteractiveTui,createInteractiveTuiReference,formatCrashExtensionHint,formatResumeCommand,shouldShowRetryIndicator,showsStartupDetails,showsStartupHeader}from"./chunk-
|
|
2
|
+
import{InteractiveMode,OptimisticUserEchoController,createInteractiveTui,createInteractiveTuiReference,formatCrashExtensionHint,formatResumeCommand,shouldShowRetryIndicator,showsStartupDetails,showsStartupHeader}from"./chunk-2EYJJDES.js";import{isApiKeyLoginProvider}from"./chunk-Q23IMPRD.js";import"./chunk-QNAG7FYM.js";import"./chunk-E6TL3R3I.js";import"./chunk-WIBTUARS.js";import"./chunk-LYYI74CY.js";import"./chunk-PPX4BWTM.js";import"./chunk-5N4ZSDFS.js";import"./chunk-WIAXG52U.js";import"./chunk-U5KVIAHJ.js";import"./chunk-KL7ZUB7X.js";import"./chunk-JABBHOD5.js";import"./chunk-XOUTBUAV.js";import"./chunk-LJWC5IVX.js";import"./chunk-QMRJYMNH.js";import"./chunk-6KIZRGOT.js";import"./chunk-UWYQPA26.js";import"./chunk-H4QOEVS5.js";import"./chunk-U45BOWV5.js";import"./chunk-F6EQ7EV3.js";import"./chunk-JEZWV7JW.js";import"./chunk-S2TCHQTE.js";import"./chunk-7X72IACK.js";import"./chunk-KUPQO7MC.js";import"./chunk-YU2P3CAR.js";import"./chunk-BMX2U22F.js";import"./chunk-ATACOV2Q.js";import"./chunk-CIRZTP7W.js";import"./chunk-22DAHAHO.js";import"./chunk-XYDZ3LIE.js";import"./chunk-HB35RBP4.js";import"./chunk-7Q3EY6HH.js";import"./chunk-6SMU7ANE.js";import"./chunk-MH2BFYGN.js";import"./chunk-26UBFF6N.js";import"./chunk-F4Y75Q3Q.js";import"./chunk-GZVCRV7I.js";import"./chunk-U3VOXCGP.js";import"./chunk-RFB5CBW7.js";import"./chunk-2VZJTDUX.js";import"./chunk-KC5TT7DH.js";import"./chunk-KEMQXWPY.js";import"./chunk-ZOFZRJSL.js";import"./chunk-2SOVDETB.js";import"./chunk-463OK2Y4.js";import"./chunk-ATQFN5HI.js";import"./chunk-RBCQOIAD.js";import"./chunk-JRGNL6WM.js";import"./chunk-RKJNJ3GI.js";import"./chunk-CWLCGRUS.js";import"./chunk-6WCOSBI7.js";import"./chunk-LHYG7TK7.js";import"./chunk-KRNXUTZJ.js";import"./chunk-YOPVJDSU.js";import"./chunk-WHPDEDCC.js";import"./chunk-HK46JMSC.js";import"./chunk-2WEI2XTZ.js";import"./chunk-WDTJ6JKE.js";import"./chunk-5ROMKDLK.js";import"./chunk-3W47LTXQ.js";import"./chunk-45SZOLCU.js";import"./chunk-BBK6SSYT.js";import"./chunk-BPX6QWPD.js";import"./chunk-XL5KIYQF.js";import"./chunk-DMI55M2N.js";import"./chunk-PJ34QVL5.js";import"./chunk-IKOFCODM.js";export{InteractiveMode,OptimisticUserEchoController,createInteractiveTui,createInteractiveTuiReference,formatCrashExtensionHint,formatResumeCommand,isApiKeyLoginProvider,shouldShowRetryIndicator,showsStartupDetails,showsStartupHeader};
|
package/dist/bundle/chunks/{multi-session-host-5C2TC4BN.js → multi-session-host-GFWO2JUC.js}
RENAMED
|
@@ -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{ACCEPT_EDITS_PERMISSION_PRESET_CAPABILITY,AgentSessionRuntime,EMPTY_SESSION_CONTEXT,HostMcpRegistry,ProviderScope,SessionManager,assertValidSessionId,bindToProviderScope,createAgentSessionRuntime,createWebViewBroker,readOwnFootprint,runWithProviderScope,startHostChildReaper}from"./chunk-
|
|
2
|
+
import{ACCEPT_EDITS_PERMISSION_PRESET_CAPABILITY,AgentSessionRuntime,EMPTY_SESSION_CONTEXT,HostMcpRegistry,ProviderScope,SessionManager,assertValidSessionId,bindToProviderScope,createAgentSessionRuntime,createWebViewBroker,readOwnFootprint,runWithProviderScope,startHostChildReaper}from"./chunk-2EYJJDES.js";import{DURABLE_CLIENT_MESSAGE_ID_CAPABILITY,RPC_ERROR_ATTACHED,RPC_ERROR_HOST_DRAINING,RPC_ERROR_INVALID_LAUNCH_PROFILE,RPC_ERROR_INVALID_PATH,RPC_ERROR_INVALID_RELEASE_REASON,RPC_ERROR_INVALID_SESSION_CONTEXT,RPC_ERROR_INVALID_SESSION_KIND,RPC_ERROR_MISSING_SESSION_ID,RPC_ERROR_OPEN_FAILED,RPC_ERROR_RELEASE_FAILED,RPC_ERROR_RELEASE_UNSUPPORTED,RPC_ERROR_SESSION_BUSY,RPC_ERROR_SESSION_CLOSING,RPC_ERROR_TURN_ACTIVE,RPC_ERROR_UNKNOWN_SESSION,RPC_ERROR_WARM_FAILED,createRpcConnectionHandler}from"./chunk-Q23IMPRD.js";import"./chunk-QNAG7FYM.js";import"./chunk-E6TL3R3I.js";import{flushRawStdout,takeOverStdout,waitForRawStdoutBackpressure,writeRawStdout}from"./chunk-WIBTUARS.js";import"./chunk-LYYI74CY.js";import"./chunk-PPX4BWTM.js";import"./chunk-5N4ZSDFS.js";import"./chunk-WIAXG52U.js";import"./chunk-U5KVIAHJ.js";import{buildRpcSessionState,rpcCommandShapeError,sessionAutoTitleError,sessionContextError,sessionKindError,sessionPromptSurfaceError}from"./chunk-KL7ZUB7X.js";import"./chunk-JABBHOD5.js";import{BEGIN_HANDOVER_COMMAND,EXPECTED_RUNTIME_BUILD_ID_ENV,GENERATION_HANDOFF_CAPABILITY,HostIdleHandover,RUNTIME_IDENTITY_HANDOVER_CAPABILITY,beginHandoverResponse,computeRuntimeBuildId,handoverRefusal,isHandoffBusy,isHostIdle,parseBeginHandover,performIdleHandover,readDrainVerdicts,runAsHostGenerationProcess,withHostIdentity}from"./chunk-XOUTBUAV.js";import{AUTO_TITLE_PER_SESSION_CAPABILITY,AUTO_TITLE_SESSIONS_CAPABILITY,DURABLE_SESSION_ID_CAPABILITY,MEDIA_PLACEHOLDERS_CAPABILITY,PROMPT_SURFACE_CAPABILITY,PROMPT_SURFACE_CHAT_CAPABILITY,RETAIN_ON_DISCONNECT_CAPABILITY,SESSION_CONTEXT_CAPABILITY,SESSION_KIND_CAPABILITY,WARM_CAPABILITY,hostGeneration,hostInstanceId,parseClientCapabilities,protocolIdentity}from"./chunk-LJWC5IVX.js";import"./chunk-QMRJYMNH.js";import"./chunk-6KIZRGOT.js";import"./chunk-UWYQPA26.js";import"./chunk-H4QOEVS5.js";import"./chunk-U45BOWV5.js";import"./chunk-F6EQ7EV3.js";import{killTrackedDetachedChildren}from"./chunk-JEZWV7JW.js";import"./chunk-S2TCHQTE.js";import"./chunk-7X72IACK.js";import"./chunk-KUPQO7MC.js";import"./chunk-YU2P3CAR.js";import"./chunk-BMX2U22F.js";import{ClientOccupancy,armHostWatchdog,parseIdleExitMs,readHostWatchdogConfigFromBrandEnv}from"./chunk-ATACOV2Q.js";import"./chunk-CIRZTP7W.js";import{PUBLIC_SOCKET_IDENTITY_FILE,SESSION_PATH_RETRY_AFTER_MS,SOCKET_SECRET_FILE_ENV,authenticateSocket,canonicalSessionPath,createEndpointReservations,ensureSocketSecret,readSocketIdentityFile,resolveSocketTransportAddress,sessionDirectoryRemoved,shieldSocketDuringClose,socketEntryReplaced,socketSecretPath,statSocketIdentity,unlinkOwnedSocket,waitForSocketIdentityFile}from"./chunk-22DAHAHO.js";import{MAX_RPC_LINE_CHARACTERS,attachJsonlLineReader,serializeJsonLine}from"./chunk-XYDZ3LIE.js";import"./chunk-HB35RBP4.js";import"./chunk-7Q3EY6HH.js";import"./chunk-6SMU7ANE.js";import"./chunk-MH2BFYGN.js";import"./chunk-26UBFF6N.js";import"./chunk-F4Y75Q3Q.js";import"./chunk-GZVCRV7I.js";import"./chunk-U3VOXCGP.js";import"./chunk-RFB5CBW7.js";import"./chunk-2VZJTDUX.js";import"./chunk-KC5TT7DH.js";import"./chunk-KEMQXWPY.js";import"./chunk-ZOFZRJSL.js";import"./chunk-2SOVDETB.js";import{VERSION,envValue,isBunBinary}from"./chunk-463OK2Y4.js";import"./chunk-ATQFN5HI.js";import"./chunk-RBCQOIAD.js";import"./chunk-JRGNL6WM.js";import"./chunk-RKJNJ3GI.js";import"./chunk-CWLCGRUS.js";import"./chunk-6WCOSBI7.js";import"./chunk-LHYG7TK7.js";import"./chunk-KRNXUTZJ.js";import"./chunk-YOPVJDSU.js";import"./chunk-WHPDEDCC.js";import"./chunk-HK46JMSC.js";import"./chunk-2WEI2XTZ.js";import"./chunk-WDTJ6JKE.js";import"./chunk-5ROMKDLK.js";import"./chunk-3W47LTXQ.js";import"./chunk-45SZOLCU.js";import"./chunk-BBK6SSYT.js";import"./chunk-BPX6QWPD.js";import"./chunk-XL5KIYQF.js";import"./chunk-DMI55M2N.js";import"./chunk-PJ34QVL5.js";import"./chunk-IKOFCODM.js";import{access as access2,chmod,mkdir,unlink}from"node:fs/promises";import{createConnection,createServer}from"node:net";import{basename,dirname,join}from"node:path";var HostCoreGate=class{constructor(registry,route,hooks){this.inFlight=new Map,this.answering=new Set,this.route=route,this.runtimeBuildId=hooks.runtimeBuildId,this.handover=hooks.handover===void 0?void 0:new HostIdleHandover({...hooks.handover,isIdle:()=>isHostIdle(registry,this.inFlight)})}async intercept(parsed,deliver){if(!isRecord(parsed)||parsed.type!==BEGIN_HANDOVER_COMMAND)return!1;let answering=this.answerBegin(parsed).then(deliver);this.answering.add(answering);try{await answering}finally{this.answering.delete(answering)}return!0}async answerBegin(parsed){if(this.handover===void 0)return beginHandoverResponse(parsed.id,{kind:"refused",reason:"handover_unsupported"});let request=parseBeginHandover(parsed);return beginHandoverResponse(parsed.id,typeof request=="string"?request:await this.handover.begin(request))}async answered(){for(;this.answering.size>0;)await Promise.allSettled([...this.answering])}async dispatch(command){let pending=this.handover?.view();if(pending!==void 0&&this.handover?.admits(command.type)===!1)return handoverRefusal(command,pending);let key="sessionId"in command?command.sessionId:void 0;this.inFlight.set(key,(this.inFlight.get(key)??0)+1);let response;try{response=await this.route(command)}finally{let remaining=(this.inFlight.get(key)??1)-1;remaining>0?this.inFlight.set(key,remaining):this.inFlight.delete(key),this.handover?.observe()}return response===void 0?void 0:withHostIdentity(response,this.runtimeBuildId,this.handover?.view())}};function isRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}var RPC_SESSION_IDLE_EVICTION_MS_ENV="SENPI_RPC_SESSION_IDLE_EVICTION_MS",RPC_HOST_EMPTY_EXIT_MS_ENV="SENPI_RPC_HOST_EMPTY_EXIT_MS",RPC_CLOSE_GRACE_MS_ENV="SENPI_RPC_CLOSE_GRACE_MS",DEFAULT_SESSION_IDLE_EVICTION_MS=30*6e4,DEFAULT_HOST_EMPTY_EXIT_MS=15*6e4;function resolveHostIdlePolicy(env,overrides={}){return{now:overrides.now??Date.now,idleEvictionMs:overrides.idleEvictionMs??parseIdleExitMs(env[RPC_SESSION_IDLE_EVICTION_MS_ENV])??DEFAULT_SESSION_IDLE_EVICTION_MS,emptyExitMs:overrides.emptyExitMs??parseIdleExitMs(env[RPC_HOST_EMPTY_EXIT_MS_ENV])??DEFAULT_HOST_EMPTY_EXIT_MS}}var HOST_RSS_WARN_MB_ENV="SENPI_RPC_HOST_RSS_WARN_MB",DEFAULT_HOST_RSS_WARN_MB=4096,HOST_MEMORY_SAMPLE_MS=3e4,HOST_MEMORY_STDERR_INTERVAL_MS=5*6e4,BYTES_PER_MEGABYTE=1024*1024;function parsePositiveInteger(value){if(value===void 0||!/^\d+$/.test(value.trim()))return;let parsed=Number(value.trim());return Number.isFinite(parsed)&&parsed>0?parsed:void 0}var HostMemorySampler=class{constructor(options){this.pressure=!1,this.idleReported=!1;let env=options.env??process.env;this.emit=options.emit,this.sessions=options.sessions,this.onPressure=options.onPressure,options.onIdlePressure&&(this.onIdlePressure=options.onIdlePressure),this.log=options.log??(message=>{process.stderr.write(message)}),this.now=options.now??Date.now,this.readFootprint=options.readFootprint??readOwnFootprint,this.readRssBytes=options.readRssBytes??(()=>process.memoryUsage.rss()),this.warnMb=parsePositiveInteger(env[HOST_RSS_WARN_MB_ENV])??DEFAULT_HOST_RSS_WARN_MB}start(){this.timer===void 0&&(this.timer=setInterval(()=>this.sample(),HOST_MEMORY_SAMPLE_MS),this.timer.unref?.())}stop(){this.timer!==void 0&&(clearInterval(this.timer),this.timer=void 0)}sample(){let footprint=this.readFootprint(),reading={footprintMb:Math.round(footprint.bytes/BYTES_PER_MEGABYTE),measure:footprint.measure,rssMb:Math.round(this.readRssBytes()/BYTES_PER_MEGABYTE)};if(reading.footprintMb<=this.warnMb){if(this.idleReported=!1,!this.pressure)return;this.pressure=!1,this.onPressure(!1);return}this.pressure||(this.pressure=!0,this.onPressure(!0));let sessions=this.sessions();sessions>0?this.idleReported=!1:this.idleReported||(this.idleReported=!0,this.onIdlePressure?.(reading));let{footprintMb,measure,rssMb}=reading;this.emit({type:"host_memory_pressure",rssMb,footprintMb,measure,sessions});let now=this.now();this.lastLoggedAt!==void 0&&now-this.lastLoggedAt<HOST_MEMORY_STDERR_INTERVAL_MS||(this.lastLoggedAt=now,this.log(`senpi rpc host memory pressure: footprintMb=${footprintMb} (${measure}) rssMb=${rssMb} sessions=${sessions} (idle parking halved)
|
|
3
3
|
`))}};var blockedMsTotal=0;function recordLoopBlockedMs(driftMs){driftMs>0&&(blockedMsTotal+=driftMs)}function loopBlockedMark(){return blockedMsTotal}function loopBlockedMsSince(mark){return blockedMsTotal-mark}import{AsyncLocalStorage}from"node:async_hooks";var attributionStore=new AsyncLocalStorage,sequence=0,openActivities=new Map,lastFinished;function runWithSessionAttribution(attribution,task){let mark=++sequence;openActivities.set(mark,attribution);let finish=()=>{openActivities.delete(mark)&&(lastFinished={sequence:++sequence,attribution})},awaited=!1;try{let result=attributionStore.run(attribution,task);return isPromiseLike(result)&&(awaited=!0,Promise.resolve(result).then(finish,finish)),result}finally{awaited||finish()}}function isPromiseLike(value){return typeof value=="object"&&value!==null&&"then"in value&&typeof value.then=="function"}function openSessionAttributionSpan(attribution){let ambient=attributionStore.getStore(),merged={sessionId:attribution.sessionId??ambient?.sessionId,tool:attribution.tool},mark=++sequence;return openActivities.set(mark,merged),()=>{openActivities.delete(mark)&&(lastFinished={sequence:++sequence,attribution:merged})}}function sessionActivityMark(){return sequence}function sessionActivitySince(mark){if(lastFinished!==void 0&&lastFinished.sequence>mark)return lastFinished.attribution;let newest;for(let attribution of openActivities.values())newest=attribution;return newest}function toolRecord(record){if(!(!("type"in record)||typeof record.type!="string"))return{type:record.type,toolCallId:"toolCallId"in record&&typeof record.toolCallId=="string"?record.toolCallId:void 0,toolName:"toolName"in record&&typeof record.toolName=="string"?record.toolName:void 0}}function createToolAttributionSpans(sessionId){let spans=new Map,closeAll=()=>{for(let close of spans.values())close();spans.clear()};return{closeAll,observe:record=>{let parsed=toolRecord(record);if(parsed!==void 0){if(parsed.type==="tool_execution_start"&&parsed.toolCallId!==void 0){spans.get(parsed.toolCallId)?.(),spans.set(parsed.toolCallId,openSessionAttributionSpan({sessionId,tool:parsed.toolName}));return}if(parsed.type==="tool_execution_end"&&parsed.toolCallId!==void 0){spans.get(parsed.toolCallId)?.(),spans.delete(parsed.toolCallId);return}(parsed.type==="agent_settled"||parsed.type==="agent_idle")&&closeAll()}}}}var LOOP_LAG_WARN_MS_ENV="SENPI_RPC_LOOP_LAG_WARN_MS",LOOP_LAG_ERROR_MS_ENV="SENPI_RPC_LOOP_LAG_ERROR_MS",DEFAULT_LOOP_LAG_WARN_MS=500,DEFAULT_LOOP_LAG_ERROR_MS=5e3,LOOP_LAG_TICK_MS=200,LOOP_LAG_WARN_INTERVAL_MS=1e4,BYTES_PER_MB=1024*1024;function describeWindow(processCpuMs,heapDeltaMb){return`cpu=${processCpuMs}ms heap=${heapDeltaMb>=0?"+":""}${heapDeltaMb}MB`}function describeAttribution(attribution){return attribution?.sessionId===void 0&&attribution?.tool===void 0?"no attributed session":`sessionId=${attribution.sessionId??"unknown"}${attribution.tool?` tool=${attribution.tool}`:""}`}var LoopLagWatchdog=class{constructor(options){this.activityMark=0,this.cpuMicrosAtTick=0,this.heapBytesAtTick=0;let env=options.env??process.env;this.emit=options.emit,this.log=options.log??(message=>{process.stderr.write(message)}),this.now=options.now??Date.now,this.cpuUsage=options.cpuUsage??(()=>process.cpuUsage()),this.heapUsed=options.heapUsed??(()=>process.memoryUsage().heapUsed),this.warnMs=parseIdleExitMs(env[LOOP_LAG_WARN_MS_ENV])??DEFAULT_LOOP_LAG_WARN_MS,this.errorMs=parseIdleExitMs(env[LOOP_LAG_ERROR_MS_ENV])??DEFAULT_LOOP_LAG_ERROR_MS}start(){if(this.timer!==void 0)return;this.expectedTickAt=this.now()+LOOP_LAG_TICK_MS,this.activityMark=sessionActivityMark();let cpu=this.cpuUsage();this.cpuMicrosAtTick=cpu.user+cpu.system,this.heapBytesAtTick=this.heapUsed(),this.timer=setInterval(()=>this.tick(),LOOP_LAG_TICK_MS),this.timer.unref?.()}stop(){this.timer!==void 0&&(clearInterval(this.timer),this.timer=void 0,this.expectedTickAt=void 0)}tick(){let now=this.now(),expectedAt=this.expectedTickAt??now,previousMark=this.activityMark;this.expectedTickAt=now+LOOP_LAG_TICK_MS,this.activityMark=sessionActivityMark();let cpu=this.cpuUsage(),cpuMicros=cpu.user+cpu.system,heapBytes=this.heapUsed(),previousCpuMicros=this.cpuMicrosAtTick,previousHeapBytes=this.heapBytesAtTick;this.cpuMicrosAtTick=cpuMicros,this.heapBytesAtTick=heapBytes;let driftMs=Math.round(now-expectedAt);if(recordLoopBlockedMs(driftMs),driftMs<=this.warnMs)return;let attribution=sessionActivitySince(previousMark),processCpuMs=Math.round((cpuMicros-previousCpuMicros)/1e3),heapDeltaMb=Math.round((heapBytes-previousHeapBytes)/BYTES_PER_MB);driftMs>this.errorMs&&this.emit({type:"host_stalled",driftMs,sessionId:attribution?.sessionId,tool:attribution?.tool,processCpuMs,heapDeltaMb}),!(this.lastWarnAt!==void 0&&now-this.lastWarnAt<LOOP_LAG_WARN_INTERVAL_MS)&&(this.lastWarnAt=now,this.log(`senpi rpc host stall: event loop blocked ${driftMs}ms (${describeAttribution(attribution)}; ${describeWindow(processCpuMs,heapDeltaMb)})
|
|
4
4
|
`))}};import{access}from"node:fs/promises";import{isAbsolute}from"node:path";var MAX_WARM_PROFILES=64;function profileKey(profile){let context=Object.entries(profile.sessionContext??{}).sort(([a],[b])=>a<b?-1:a>b?1:0);return JSON.stringify([profile.cwd,profile.sessionKind??"interactive",context])}var HostWarmer=class{constructor(load){this.warm=new Set,this.loading=new Map,this.load=load}async run(profile){let key=profileKey(profile);if(this.warm.has(key))return"already_warm";let pending=this.loading.get(key);return pending===void 0&&(pending=this.loadOnce(key,profile),this.loading.set(key,pending)),await pending,"warmed"}async loadOnce(key,profile){try{if(await this.load(profile),this.warm.add(key),this.warm.size>MAX_WARM_PROFILES){let oldest=this.warm.values().next().value;oldest!==void 0&&this.warm.delete(oldest)}}finally{this.loading.delete(key)}}};function createRegistryWarm(prepare,host){let warmer=new HostWarmer(async profile=>{await access(profile.cwd);let launchProfile={cwd:profile.cwd,...profile.sessionKind!==void 0?{sessionKind:profile.sessionKind}:{},...profile.sessionContext!==void 0?{sessionContext:Object.freeze({...profile.sessionContext})}:{}},scope=new ProviderScope;try{await runWithProviderScope(scope,()=>prepare({cwd:profile.cwd,agentDir:host.agentDir,launchProfile:Object.freeze(launchProfile),...host.mcpRegistry!==void 0?{mcpRegistry:host.mcpRegistry}:{}}))}finally{scope.close()}});return profile=>warmer.run(profile)}function refusal(command,code){return{id:command.id,type:"response",command:"warm",success:!1,error:code}}async function answerWarm(command,host){if(host.draining)return refusal(command,"host_draining");let kindError=sessionKindError(command.kind);if(kindError)return refusal(command,`${RPC_ERROR_INVALID_SESSION_KIND}: ${kindError}`);let contextError=sessionContextError(command.context);if(contextError)return refusal(command,`${RPC_ERROR_INVALID_SESSION_CONTEXT}: ${contextError}`);if(host.warm===void 0)return{id:command.id,type:"response",command:"warm",success:!0,data:{state:"unsupported"}};let sessionContext=host.hostContext?{...command.context,...host.hostContext}:command.context,cwd=command.cwd??host.cwd;if(!isAbsolute(cwd))return refusal(command,RPC_ERROR_INVALID_PATH);try{let state=await host.warm({cwd,...command.kind!==void 0?{sessionKind:command.kind}:{},...sessionContext!==void 0?{sessionContext}:{}});return{id:command.id,type:"response",command:"warm",success:!0,data:{state}}}catch(cause){return refusal(command,`${RPC_ERROR_WARM_FAILED}: ${cause instanceof Error?cause.message:String(cause)}`)}}async function createRpcSessionBinding(sessionId,entry,writer,requestClose,options={}){if(entry.worker)return entry.worker.bind(sessionId,writer,requestClose,options);if(!entry.runtime)throw new Error("Session runtime was not created");let toolSpans=createToolAttributionSpans(sessionId),enqueueRecords=chunk=>{for(let line of chunk.split(`
|
|
5
5
|
`)){if(!line)continue;let record=JSON.parse(line);toolSpans.observe(record),writer.enqueue(sessionId,record)}},runtimeHost=new Proxy({},{get(_target,property){if(property==="switchSession"&&entry.switchSession)return entry.switchSession;if(property==="setRebindSession")return callback=>{entry.rebindSession=callback,entry.runtime?.setRebindSession(callback)};let runtime=entry.runtime;if(!runtime)throw new Error("Session runtime was not created");let value=Reflect.get(runtime,property,runtime);return typeof value=="function"?value.bind(runtime):value}}),handler=await runWithProviderScope(entry.scope,async()=>{let taggedSink={writeRaw:bindToProviderScope(enqueueRecords),waitForBackpressure:bindToProviderScope(async()=>{})};return createRpcConnectionHandler(runtimeHost,taggedSink,{sessionId,shutdownHandler:bindToProviderScope(requestClose),disposeRuntime:!1,eventFlushScheduler:flush=>flush(),...options})});return await handler.ready,{handle:command=>runWithProviderScope(entry.scope,()=>handler.handleInputLine(JSON.stringify(command))),cancelPendingExtensionUiRequests:()=>runWithProviderScope(entry.scope,()=>handler.cancelPendingExtensionUiRequests()),pendingPrompts:()=>handler.pendingPrompts(),dispose:()=>(toolSpans.closeAll(),runWithProviderScope(entry.scope,()=>handler.dispose()))}}import{existsSync}from"node:fs";import{isAbsolute as isAbsolute2}from"node:path";function sessionIsWriting(entry){return entry.worker?.busy===!0||entry.runtime?.session.isSessionBusy===!0}function reportDetachedFailure(handle,cause){process.stderr.write(`senpi rpc session ${handle} teardown failed: ${String(cause)}
|
package/dist/bundle/chunks/{package-manager-cli-K3JGGB65.js → package-manager-cli-VHCS5NXO.js}
RENAMED
|
@@ -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{DefaultResourceLoader,LEGACY_PI_CONFIG_FILES,ModelRuntime,cleanupWindowsSelfUpdateQuarantine,createProjectTrustContext,importLegacyPiConfig,isBuiltinExtension,quarantineWindowsNativeDependencies,resolveProjectTrusted}from"./chunk-
|
|
2
|
+
import{DefaultResourceLoader,LEGACY_PI_CONFIG_FILES,ModelRuntime,cleanupWindowsSelfUpdateQuarantine,createProjectTrustContext,importLegacyPiConfig,isBuiltinExtension,quarantineWindowsNativeDependencies,resolveProjectTrusted}from"./chunk-2EYJJDES.js";import"./chunk-Q23IMPRD.js";import"./chunk-QNAG7FYM.js";import{DefaultPackageManager,DynamicBorder,keyHint,rawKeyHint}from"./chunk-E6TL3R3I.js";import{SettingsManager,appendHiddenTuiStdout,initTheme,stopThemeWatcher,theme}from"./chunk-WIBTUARS.js";import"./chunk-LYYI74CY.js";import"./chunk-PPX4BWTM.js";import{Container,Input,Markdown,ProcessTerminal,Spacer,TUI,getKeybindings,matchesKey,truncateToWidth,visibleWidth}from"./chunk-5N4ZSDFS.js";import"./chunk-WIAXG52U.js";import"./chunk-U5KVIAHJ.js";import"./chunk-KL7ZUB7X.js";import"./chunk-JABBHOD5.js";import"./chunk-XOUTBUAV.js";import"./chunk-LJWC5IVX.js";import{BUILTIN_PATH_PREFIX}from"./chunk-QMRJYMNH.js";import"./chunk-6KIZRGOT.js";import"./chunk-UWYQPA26.js";import"./chunk-H4QOEVS5.js";import"./chunk-U45BOWV5.js";import"./chunk-F6EQ7EV3.js";import{killProcessTree}from"./chunk-JEZWV7JW.js";import"./chunk-S2TCHQTE.js";import"./chunk-7X72IACK.js";import"./chunk-KUPQO7MC.js";import"./chunk-YU2P3CAR.js";import"./chunk-BMX2U22F.js";import"./chunk-ATACOV2Q.js";import"./chunk-CIRZTP7W.js";import"./chunk-22DAHAHO.js";import"./chunk-XYDZ3LIE.js";import"./chunk-HB35RBP4.js";import"./chunk-7Q3EY6HH.js";import{ProjectTrustStore,hasTrustRequiringProjectResources}from"./chunk-6SMU7ANE.js";import"./chunk-MH2BFYGN.js";import{source_default}from"./chunk-26UBFF6N.js";import"./chunk-F4Y75Q3Q.js";import{require_proper_lockfile}from"./chunk-GZVCRV7I.js";import"./chunk-U3VOXCGP.js";import"./chunk-RFB5CBW7.js";import"./chunk-2VZJTDUX.js";import"./chunk-KC5TT7DH.js";import{formatVersionCheckError,getLatestPiRelease,getPiUserAgent,isNewerPackageVersion}from"./chunk-KEMQXWPY.js";import"./chunk-ZOFZRJSL.js";import"./chunk-2SOVDETB.js";import{APP_COMMAND,APP_NAME,CONFIG_DIR_NAME,DISPLAY_VERSION,PACKAGE_NAME,VERSION,brandProfile,canonicalizePath,detectInstallMethod,getAgentDir,getCwdRelativePath,getInstallPackageDir,getSelfUpdateCommand,getSelfUpdateUnavailableInstruction,isLocalPath,resolvePath,spawnProcess,spawnProcessSync,waitForChildProcess}from"./chunk-463OK2Y4.js";import"./chunk-ATQFN5HI.js";import"./chunk-RBCQOIAD.js";import"./chunk-JRGNL6WM.js";import"./chunk-RKJNJ3GI.js";import"./chunk-CWLCGRUS.js";import"./chunk-6WCOSBI7.js";import"./chunk-LHYG7TK7.js";import"./chunk-KRNXUTZJ.js";import"./chunk-YOPVJDSU.js";import"./chunk-WHPDEDCC.js";import"./chunk-HK46JMSC.js";import"./chunk-2WEI2XTZ.js";import"./chunk-WDTJ6JKE.js";import"./chunk-5ROMKDLK.js";import"./chunk-3W47LTXQ.js";import"./chunk-45SZOLCU.js";import"./chunk-BBK6SSYT.js";import"./chunk-BPX6QWPD.js";import"./chunk-XL5KIYQF.js";import"./chunk-DMI55M2N.js";import"./chunk-PJ34QVL5.js";import{__toESM}from"./chunk-IKOFCODM.js";import{existsSync as existsSync3,mkdirSync as mkdirSync3,mkdtempSync,readdirSync as readdirSync2,readFileSync as readFileSync2,renameSync as renameSync2,rmSync as rmSync2,writeFileSync as writeFileSync2}from"node:fs";import{join as join5,resolve as resolve3}from"node:path";var import_proper_lockfile=__toESM(require_proper_lockfile(),1);import{randomUUID}from"node:crypto";import{cpSync,existsSync as existsSync2,mkdirSync as mkdirSync2,readFileSync,renameSync,rmSync,writeFileSync}from"node:fs";import{homedir}from"node:os";import{dirname as dirname2,join as join3,relative as relative2,resolve as resolve2}from"node:path";import{existsSync,readdirSync}from"node:fs";import{join,relative,sep}from"node:path";var REQUIRED_BUILD_ARTIFACTS=["extensions/omo.js","runtime/lsp-daemon/dist/cli.js","runtime/lsp-daemon/dist/index.js","runtime/lsp-daemon/dist/.omo-runtime-manifest.json","scripts/install.mjs"];function walkFiles(rootDir){let files=[],pending=[rootDir];for(;pending.length>0;){let dir=pending.pop();if(dir===void 0)continue;let entries;try{entries=readdirSync(dir,{withFileTypes:!0})}catch(error){if(error instanceof Error)continue;throw error}for(let entry of entries){let full=join(dir,entry.name);entry.isDirectory()?pending.push(full):entry.isFile()&&files.push(full)}}return files}function collectArtifactInventory(pluginPath){let inventory=[],collectUnder=(relativeDir,filter)=>{for(let filePath of walkFiles(join(pluginPath,relativeDir))){let posixPath=relative(pluginPath,filePath).split(sep).join("/");(filter===void 0||filter(posixPath))&&inventory.push(posixPath)}};return collectUnder("extensions"),collectUnder(join("runtime","lsp-daemon","dist")),collectUnder("skills",posixPath=>posixPath.endsWith("/SKILL.md")),existsSync(join(pluginPath,"scripts","install.mjs"))&&inventory.push("scripts/install.mjs"),inventory.sort(),inventory}function currentRequiredBuildArtifactsExist(pluginPath){return findMissingBuildArtifacts(pluginPath).length===0}function findMissingBuildArtifacts(pluginPath){let missing=[];for(let required of REQUIRED_BUILD_ARTIFACTS)existsSync(join(pluginPath,required))||missing.push(required);let skillCount=0;try{for(let entry of readdirSync(join(pluginPath,"skills"),{withFileTypes:!0}))entry.isDirectory()&&existsSync(join(pluginPath,"skills",entry.name,"SKILL.md"))&&skillCount++}catch(error){if(!(error instanceof Error))throw error}return skillCount===0&&missing.push("skills/*/SKILL.md"),missing}import{createHash}from"node:crypto";var EXCLUDED_ROOT_PATHS=new Set([".agents",".claude",".codex",".cursor",".devcontainer",".env.example",".gitattributes",".github",".idea",".mcp.json",".omo",".opencode",".vscode","AGENTS.md","CHANGELOG.md","CLA.md","CLAUDE.md","CONTRIBUTING.md","LICENSE","LICENSE.md","ROADMAP.md","THIRD-PARTY-NOTICES.md","assets","docs"]);function isBuildInputRootPath(name){return!EXCLUDED_ROOT_PATHS.has(name)&&!name.startsWith("README")}function computeBuildInputsHashFromLsTree(lsTreeOutput){let hash=createHash("sha256");for(let entry of lsTreeOutput.split("\0")){let tabIndex=entry.indexOf(" ");if(tabIndex===-1)continue;let name=entry.slice(tabIndex+1);if(!isBuildInputRootPath(name))continue;let objectHash=entry.slice(0,tabIndex).split(" ")[2]??"";hash.update(`${objectHash} ${name}
|
|
3
3
|
`)}return hash.digest("hex")}import{spawn}from"node:child_process";import{closeSync,mkdirSync,openSync}from"node:fs";import{dirname,join as join2,resolve}from"node:path";import{fileURLToPath}from"node:url";function omoLocalUpdateWorkerLogPath(agentDir){return join2(agentDir,"omo-local-update","worker.log")}function workerCommandArgs(force){let updateArgs=["update","--omo-local-update-worker",...force?["--force"]:[]];if(detectInstallMethod()==="bun-binary")return updateArgs;let modulePath=fileURLToPath(import.meta.url),extension=modulePath.endsWith(".ts")?".ts":".js",cliMainPath=resolve(dirname(modulePath),"..",`cli-main${extension}`);return[...process.execArgv,cliMainPath,...updateArgs]}var defaultSpawnWorker=request=>{let logPath=omoLocalUpdateWorkerLogPath(request.agentDir);try{mkdirSync(dirname(logPath),{recursive:!0});let logFd=openSync(logPath,"w");try{let child=spawn(process.execPath,workerCommandArgs(request.force),{detached:!0,env:process.env,stdio:["ignore",logFd,logFd]});return child.unref(),{ok:!0,pid:child.pid,logPath}}finally{closeSync(logFd)}}catch(error){return{ok:!1,message:error instanceof Error?error.message:String(error)}}};async function defaultRun(command,args,options){let child=spawnProcess(command,args,{cwd:options.cwd,stdio:["ignore","pipe","pipe"],env:{...process.env,...options.env},detached:process.platform!=="win32",windowsHide:!0}),stdout="",stderr="";child.stdout.on("data",chunk=>{stdout+=chunk.toString()}),child.stderr.on("data",chunk=>{stderr+=chunk.toString()});let abort=new AbortController,timedOut=!1,pid=child.pid,timer=options.timeoutMs===void 0?void 0:setTimeout(()=>{timedOut=!0,pid!==void 0&&killProcessTree(pid),abort.abort()},options.timeoutMs);try{return{code:await waitForChildProcess(child,{signal:abort.signal}),stdout,stderr,timedOut}}finally{timer!==void 0&&clearTimeout(timer)}}function isKillSwitched(env){return env.SENPI_OMO_LOCAL_UPDATE==="0"}function defaultReadJson(path){try{return JSON.parse(readFileSync(path,"utf-8"))}catch{return}}function packageNameOf(json){if(typeof json!="object"||json===null)return;let name=json.name;return typeof name=="string"?name:void 0}function homeDir(){return process.env.HOME||homedir()}async function detectOmoLocalInstall(options){let readJson=options.readJson??defaultReadJson,exists=options.exists??existsSync2;if(options.packages)for(let entry of options.packages){let source=typeof entry=="string"?entry:entry.source;if(!isLocalPath(source))continue;let pluginPath=resolvePath(source,options.agentDir,{homeDir:homeDir(),trim:!0});if(packageNameOf(readJson(join3(pluginPath,"package.json")))!=="@code-yeongyu/omo-senpi")continue;let repoRoot=resolve2(pluginPath,"..","..",".."),omoSenpiPkgPath=join3(repoRoot,"packages","omo-senpi","package.json"),senpiTaskPkgPath=join3(repoRoot,"packages","senpi-task","package.json");if(!exists(omoSenpiPkgPath)||packageNameOf(readJson(omoSenpiPkgPath))!=="@oh-my-opencode/omo-senpi"||!exists(senpiTaskPkgPath)||packageNameOf(readJson(senpiTaskPkgPath))!=="@oh-my-opencode/senpi-task")continue;let topLevel;try{let result=await options.run("git",["-C",repoRoot,"rev-parse","--show-toplevel"],{});if(result.code!==0)continue;topLevel=result.stdout.trim()}catch{continue}if(!(topLevel===""||canonicalizePath(topLevel)!==canonicalizePath(repoRoot)))return{pluginPath,repoRoot}}}function omoLocalUpdateStampPath(agentDir){return join3(agentDir,"omo-local-update-state.json")}function readStamp(agentDir){let json=defaultReadJson(omoLocalUpdateStampPath(agentDir));if(typeof json!="object"||json===null)return;let candidate=json;if(typeof candidate.repoRoot!="string"||typeof candidate.sha!="string"||typeof candidate.omoSenpiTree!="string"||typeof candidate.senpiTaskTree!="string"||typeof candidate.buildInputsHash!="string"||typeof candidate.installedAt!="string"||!Array.isArray(candidate.artifacts))return;let artifacts=[];for(let artifact of candidate.artifacts){if(typeof artifact!="string")return;artifacts.push(artifact)}return{repoRoot:candidate.repoRoot,sha:candidate.sha,omoSenpiTree:candidate.omoSenpiTree,senpiTaskTree:candidate.senpiTaskTree,buildInputsHash:candidate.buildInputsHash,installedAt:candidate.installedAt,artifacts}}function writeStamp(agentDir,stamp){mkdirSync2(agentDir,{recursive:!0}),writeFileSync(omoLocalUpdateStampPath(agentDir),`${JSON.stringify(stamp,null,2)}
|
|
4
4
|
`,"utf-8")}function shouldSkipUpdate(options){if(options.force)return!1;let stamp=options.stamp;return!stamp||stamp.repoRoot!==options.repoRoot||stamp.sha!==options.remoteSha&&stamp.buildInputsHash!==options.remoteBuildInputsHash||stamp.artifacts.length===0?!1:options.stampArtifactsExist}var OmoLocalStepError=class extends Error{constructor(stage,message,output){super(message),this.name="OmoLocalStepError",this.stage=stage,this.output=output}};function firstErrorLine(result){for(let text of[result.stderr,result.stdout])for(let line of text.split(`
|
|
5
5
|
`)){let trimmed=line.trim();if(trimmed!=="")return trimmed}return"unknown error"}async function computeRemoteState(options){let{repoRoot,run}=options,git=(args,timeoutMs)=>run("git",args,{cwd:repoRoot,timeoutMs}),requireOk=async(args,timeoutMs)=>{let result=await git(args,timeoutMs);if(result.timedOut)throw new OmoLocalStepError("fetch",`git ${args.join(" ")} timed out`);if(result.code!==0)throw new OmoLocalStepError("fetch",`git ${args.join(" ")}: ${firstErrorLine(result)}`,`${result.stdout}${result.stderr}`);return result.stdout.trim()};await requireOk(["fetch","origin","dev"],12e4);let sha=await requireOk(["rev-parse","origin/dev"]);if(sha==="")throw new OmoLocalStepError("fetch","git rev-parse origin/dev: empty output");let subject=await requireOk(["log","-1","--format=%s","origin/dev"]),omoSenpiTree=await requireOk(["rev-parse","origin/dev:packages/omo-senpi"]),senpiTaskTree=await requireOk(["rev-parse","origin/dev:packages/senpi-task"]),buildInputsHash=computeBuildInputsHashFromLsTree(await requireOk(["ls-tree","-z","origin/dev"]));return{sha,subject,omoSenpiTree,senpiTaskTree,buildInputsHash}}function omoLocalUpdateLockPath(agentDir){return join3(agentDir,"omo-local-update.lock")}function omoLocalUpdateBuildWorktreePath(agentDir){return join3(agentDir,"omo-local-update","build-worktree")}function readLockFile(path){try{let json=JSON.parse(readFileSync(path,"utf-8"));return typeof json.pid!="number"||typeof json.nonce!="string"?void 0:{pid:json.pid,nonce:json.nonce}}catch{return}}function pidIsAlive(pid){try{return process.kill(pid,0),!0}catch(error){return error.code==="EPERM"}}function acquireOmoLocalLock(agentDir,log){mkdirSync2(agentDir,{recursive:!0});let path=omoLocalUpdateLockPath(agentDir),lock={path,pid:process.pid,nonce:randomUUID()},payload=JSON.stringify({pid:lock.pid,nonce:lock.nonce,startedAt:new Date().toISOString()}),tryCreate=()=>{try{return writeFileSync(path,payload,{flag:"wx"}),!0}catch(error){if(error.code==="EEXIST")return!1;throw error}},reportBusy=()=>{let existing2=readLockFile(path);log(source_default.dim(`OMO local plugin update already running (pid ${existing2?.pid??"unknown"}); skipping.`))};if(tryCreate())return lock;let existing=readLockFile(path);if(existing!==void 0&&pidIsAlive(existing.pid))return reportBusy();try{rmSync(path)}catch{}return tryCreate()?lock:reportBusy()}function releaseOmoLocalLock(lock){try{let existing=readLockFile(lock.path);existing!==void 0&&existing.pid===lock.pid&&existing.nonce===lock.nonce&&rmSync(lock.path)}catch{}}var OmoLocalBunMissingError=class extends Error{constructor(){super("bun not found on PATH"),this.name="OmoLocalBunMissingError"}};async function runBunStep(stage,args,worktree,run,timeoutMs){let result;try{result=await run("bun",args,{cwd:worktree,timeoutMs})}catch(error){throw error.code==="ENOENT"?new OmoLocalBunMissingError:new OmoLocalStepError(stage,`bun ${args.join(" ")} failed to start: ${error instanceof Error?error.message:String(error)}`)}let output=`${result.stdout}${result.stderr}`;if(result.timedOut)throw new OmoLocalStepError(stage,`bun ${args.join(" ")} timed out after ${Math.round(timeoutMs/1e3)}s`,output);if(result.code!==0)throw new OmoLocalStepError(stage,`bun ${args.join(" ")} exited with code ${result.code??"unknown"}`,output)}async function ensureBuildWorktree(options){let{worktree,repoRoot,sha,run}=options;if(existsSync2(worktree)){let commonDir=await run("git",["-C",worktree,"rev-parse","--git-common-dir"],{});if(commonDir.code===0&&commonDir.stdout.trim()!==""&&canonicalizePath(resolve2(worktree,commonDir.stdout.trim()))===canonicalizePath(join3(repoRoot,".git"))){let checkout=await run("git",["-C",worktree,"checkout","--detach","--force",sha],{});if(checkout.code!==0)throw new OmoLocalStepError("worktree",`git checkout --detach --force: ${firstErrorLine(checkout)}`,`${checkout.stdout}${checkout.stderr}`);return}((await run("git",["-C",repoRoot,"worktree","remove","--force",worktree],{})).code!==0||existsSync2(worktree))&&rmSync(worktree,{recursive:!0,force:!0})}mkdirSync2(dirname2(worktree),{recursive:!0});let add=await run("git",["-C",repoRoot,"worktree","add","--detach",worktree,sha],{});if(add.code===0)return;await run("git",["-C",repoRoot,"worktree","prune"],{});let retry=await run("git",["-C",repoRoot,"worktree","add","--detach",worktree,sha],{});if(retry.code!==0)throw new OmoLocalStepError("worktree",`git worktree add: ${firstErrorLine(retry)}`,`${add.stdout}${add.stderr}${retry.stdout}${retry.stderr}`)}var defaultFsSeam={cpSync:(source,destination)=>{cpSync(source,destination,{recursive:!0})},renameSync:(oldPath,newPath)=>{renameSync(oldPath,newPath)},rmSync:path=>{rmSync(path,{recursive:!0,force:!0})}},swapCounter=0;function swapPluginDir(options){let seam=options.fs??defaultFsSeam;swapCounter+=1;let tag=`${Date.now()}-${process.pid}-${swapCounter}`,staging=`${options.pluginPath}.staging-${tag}`,prev=`${options.pluginPath}.prev-${tag}`;seam.cpSync(options.sourceDir,staging),seam.renameSync(options.pluginPath,prev);try{seam.renameSync(staging,options.pluginPath)}catch(error){throw seam.renameSync(prev,options.pluginPath),seam.rmSync(staging),error}seam.rmSync(prev)}function firstLine(text){for(let line of text.split(`
|
|
@@ -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{runRpcMode}from"./chunk-
|
|
2
|
+
import{runRpcMode}from"./chunk-Q23IMPRD.js";import"./chunk-WIBTUARS.js";import"./chunk-5N4ZSDFS.js";import"./chunk-KL7ZUB7X.js";import"./chunk-JABBHOD5.js";import"./chunk-LJWC5IVX.js";import"./chunk-F6EQ7EV3.js";import"./chunk-JEZWV7JW.js";import"./chunk-S2TCHQTE.js";import"./chunk-7X72IACK.js";import"./chunk-KUPQO7MC.js";import"./chunk-YU2P3CAR.js";import"./chunk-CIRZTP7W.js";import"./chunk-XYDZ3LIE.js";import"./chunk-HB35RBP4.js";import"./chunk-6SMU7ANE.js";import"./chunk-MH2BFYGN.js";import"./chunk-26UBFF6N.js";import"./chunk-F4Y75Q3Q.js";import"./chunk-GZVCRV7I.js";import"./chunk-U3VOXCGP.js";import"./chunk-RFB5CBW7.js";import"./chunk-2VZJTDUX.js";import"./chunk-KC5TT7DH.js";import"./chunk-463OK2Y4.js";import"./chunk-ATQFN5HI.js";import"./chunk-RBCQOIAD.js";import"./chunk-RKJNJ3GI.js";import"./chunk-CWLCGRUS.js";import"./chunk-6WCOSBI7.js";import"./chunk-KRNXUTZJ.js";import"./chunk-YOPVJDSU.js";import"./chunk-WHPDEDCC.js";import"./chunk-HK46JMSC.js";import"./chunk-2WEI2XTZ.js";import"./chunk-WDTJ6JKE.js";import"./chunk-5ROMKDLK.js";import"./chunk-3W47LTXQ.js";import"./chunk-45SZOLCU.js";import"./chunk-BPX6QWPD.js";import"./chunk-XL5KIYQF.js";import"./chunk-DMI55M2N.js";import"./chunk-PJ34QVL5.js";import"./chunk-IKOFCODM.js";export{runRpcMode};
|