@code-yeongyu/senpi 2026.10.10-10 → 2026.10.10-11
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 +34 -0
- package/dist/bundle/chunks/{anthropic-messages-2B35OVB7.js → anthropic-messages-I4Z6VKS3.js} +1 -1
- package/dist/bundle/chunks/{app-server-command-CV6N7JDD.js → app-server-command-HYNHHQJH.js} +1 -1
- package/dist/bundle/chunks/chunk-2KZKVRVC.js +8 -0
- package/dist/bundle/chunks/chunk-4XSQBLXM.js +2 -0
- package/dist/bundle/chunks/{chunk-ZPJHS64R.js → chunk-5BRVRFJI.js} +1 -1
- package/dist/bundle/chunks/{chunk-4WZF7G6N.js → chunk-B2RD7QJJ.js} +6 -6
- package/dist/bundle/chunks/chunk-DRVT7RIO.js +2 -0
- package/dist/bundle/chunks/chunk-FOGXAY3T.js +2 -0
- package/dist/bundle/chunks/{chunk-5AKP2VFB.js → chunk-GNZDD5BK.js} +2 -3
- package/dist/bundle/chunks/{chunk-ZCYTYHDN.js → chunk-IAYFQEXI.js} +1 -1
- package/dist/bundle/chunks/{chunk-HKRW6HT5.js → chunk-KTRCQYDF.js} +2 -2
- package/dist/bundle/chunks/chunk-M4C6Z7UT.js +288 -0
- package/dist/bundle/chunks/chunk-ML3WDDTX.js +2505 -0
- package/dist/bundle/chunks/chunk-NV3IPLK6.js +9 -0
- package/dist/bundle/chunks/chunk-OZ2N2E6U.js +2 -0
- package/dist/bundle/chunks/{chunk-JRGNL6WM.js → chunk-QXREUA5F.js} +1 -1
- package/dist/bundle/chunks/{chunk-QQZREV6B.js → chunk-SSH4CLHJ.js} +1 -1
- package/dist/bundle/chunks/chunk-TOZBUPZP.js +3 -0
- package/dist/bundle/chunks/chunk-WASCMT6Y.js +2 -0
- package/dist/bundle/chunks/chunk-YU4AYH4C.js +2 -0
- package/dist/bundle/chunks/chunk-ZHE7JDBG.js +6 -0
- package/dist/bundle/chunks/{chunk-NTH33AXY.js → chunk-ZJOYLQXK.js} +1 -1
- package/dist/bundle/chunks/cli-main-WTXDD6H5.js +3 -0
- package/dist/bundle/chunks/{help-fast-path-5P73752B.js → help-fast-path-IQAJFO2G.js} +1 -1
- package/dist/bundle/chunks/host-command-7YS2Y6AT.js +2 -0
- package/dist/bundle/chunks/{host-lifecycle-B24G65GD.js → host-lifecycle-UG7RS5EU.js} +1 -1
- package/dist/bundle/chunks/host-lifecycle.js +1 -1
- package/dist/bundle/chunks/interactive-mode-WLMPVMRU.js +2 -0
- package/dist/bundle/chunks/multi-session-host-4SUEFZMU.js +26 -0
- package/dist/bundle/chunks/{package-manager-cli-PXP63ZPT.js → package-manager-cli-XEUK2RUM.js} +1 -1
- package/dist/bundle/chunks/rotation-stream-JXT3JYW5.js +2 -0
- package/dist/bundle/chunks/rpc-mode-G3DAUZCR.js +2 -0
- package/dist/bundle/chunks/runtime-session-6DAEMII3.js +2 -0
- package/dist/bundle/chunks/{schedule-command-MGZLHARF.js → schedule-command-DGLRLVWY.js} +1 -1
- package/dist/bundle/chunks/session-control-endpoint-MCV37VI5.js +3 -0
- package/dist/bundle/chunks/session-picker-WEFWH5O4.js +2 -0
- package/dist/bundle/chunks/session-worker.js +387 -383
- 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/cli/session-opening.d.ts +5 -0
- package/dist/cli/session-opening.js +11 -0
- package/dist/core/agent-session.d.ts +5 -0
- package/dist/core/agent-session.js +46 -1
- package/dist/core/engine-paused.d.ts +6 -0
- package/dist/core/engine-paused.js +50 -0
- package/dist/core/extensions/builtin/goal/continuation.js +2 -0
- package/dist/core/extensions/builtin/goal/direct-input-lifecycle.js +3 -1
- package/dist/core/extensions/builtin/goal/elapsed-ticker.js +2 -0
- package/dist/core/extensions/builtin/goal/index.js +4 -8
- package/dist/core/extensions/builtin/goal/lifecycle-helpers.js +54 -13
- package/dist/core/extensions/builtin/goal/monitor-continuation.js +2 -1
- package/dist/core/extensions/builtin/goal/persistence.js +2 -0
- package/dist/core/extensions/builtin/goal/store.d.ts +5 -0
- package/dist/core/extensions/builtin/goal/store.js +44 -0
- package/dist/core/extensions/builtin/goal/types.d.ts +2 -0
- package/dist/core/extensions/builtin/mcp/service-connection.js +1 -0
- package/dist/core/extensions/builtin/mcp/service-types.d.ts +2 -0
- package/dist/core/extensions/builtin/mcp/service.js +257 -74
- package/dist/core/extensions/builtin/terminal/process-identity.d.ts +1 -3
- package/dist/core/extensions/builtin/terminal/process-identity.js +1 -7
- package/dist/core/extensions/builtin/terminal/process-start-probe.js +11 -7
- package/dist/core/extensions/builtin/ttsr/index.js +19 -0
- package/dist/core/foreign-session-holders.d.ts +7 -0
- package/dist/core/foreign-session-holders.js +63 -0
- package/dist/core/moved-session-cwd.d.ts +7 -0
- package/dist/core/moved-session-cwd.js +23 -0
- package/dist/core/moved-sessions.d.ts +6 -0
- package/dist/core/moved-sessions.js +83 -24
- package/dist/core/resume-target.js +3 -1
- package/dist/core/session-holders.d.ts +2 -1
- package/dist/core/session-holders.js +4 -4
- package/dist/core/session-manager.js +12 -10
- package/dist/core/webview/webview-readiness.d.ts +2 -0
- package/dist/core/webview/webview-readiness.js +9 -0
- package/dist/core/webview/webview-service.d.ts +4 -0
- package/dist/core/webview/webview-service.js +30 -5
- package/dist/main.js +14 -3
- package/dist/modes/app-server/daemon/process.d.ts +4 -0
- package/dist/modes/app-server/daemon/process.js +52 -4
- package/dist/modes/interactive/interactive-mode.js +7 -0
- package/dist/modes/rpc/connection-handler.js +3 -2
- package/dist/modes/rpc/custom-capability.d.ts +2 -0
- package/dist/modes/rpc/custom-capability.js +2 -0
- package/dist/modes/rpc/host-capabilities.js +3 -1
- package/dist/modes/rpc/host-daemon-registration.js +15 -6
- package/dist/modes/rpc/host-legacy.js +8 -1
- package/dist/modes/rpc/host-reservations.d.ts +2 -0
- package/dist/modes/rpc/host-reservations.js +56 -3
- package/dist/modes/rpc/host-supervisor-log.d.ts +1 -0
- package/dist/modes/rpc/host-supervisor-log.js +9 -0
- package/dist/modes/rpc/multi-session-host.js +8 -6
- package/dist/modes/rpc/rpc-mode.d.ts +3 -1
- package/dist/modes/rpc/rpc-mode.js +3 -1
- package/dist/modes/rpc/rpc-types.d.ts +3 -1
- package/dist/modes/rpc/rpc-types.js +2 -0
- package/dist/modes/rpc/session-command-router.d.ts +1 -1
- package/dist/modes/rpc/session-command-router.js +18 -14
- package/dist/modes/rpc/session-held.d.ts +8 -0
- package/dist/modes/rpc/session-held.js +127 -0
- package/dist/modes/rpc/session-registry-types.d.ts +1 -1
- package/dist/modes/rpc/session-registry.d.ts +2 -0
- package/dist/modes/rpc/session-registry.js +4 -0
- package/dist/modes/rpc/session-worker-client.d.ts +3 -3
- package/dist/modes/rpc/session-worker-client.js +24 -12
- package/dist/modes/rpc/worker-session-claims.d.ts +15 -0
- package/dist/modes/rpc/worker-session-claims.js +61 -0
- package/dist/modes/rpc/worker-session-registry.d.ts +4 -0
- package/dist/modes/rpc/worker-session-registry.js +51 -8
- package/dist/utils/shell.d.ts +6 -2
- package/dist/utils/shell.js +20 -6
- package/docs/rpc.md +21 -1
- package/docs/session-format.md +9 -0
- package/package.json +6 -6
- package/dist/bundle/chunks/chunk-6Y7VGPJB.js +0 -9
- package/dist/bundle/chunks/chunk-JEZWV7JW.js +0 -17
- package/dist/bundle/chunks/chunk-LR5EN45D.js +0 -7
- package/dist/bundle/chunks/chunk-MYVBK47X.js +0 -2
- package/dist/bundle/chunks/chunk-O6YOQUVX.js +0 -2773
- package/dist/bundle/chunks/chunk-TJPMB4VH.js +0 -2
- package/dist/bundle/chunks/chunk-U5KVIAHJ.js +0 -2
- package/dist/bundle/chunks/chunk-XMHO4QQN.js +0 -7
- package/dist/bundle/chunks/cli-main-TM4UFZVC.js +0 -3
- package/dist/bundle/chunks/host-command-MWQNTWFA.js +0 -2
- package/dist/bundle/chunks/interactive-mode-CBQW7WRK.js +0 -2
- package/dist/bundle/chunks/multi-session-host-4KXWGRNS.js +0 -25
- package/dist/bundle/chunks/rotation-stream-FQH63DMY.js +0 -2
- package/dist/bundle/chunks/rpc-mode-7WHJHMUP.js +0 -2
- package/dist/bundle/chunks/runtime-session-CWJNFRHY.js +0 -2
- package/dist/bundle/chunks/session-control-endpoint-OH7XV2FN.js +0 -3
- package/dist/bundle/chunks/session-picker-UUSW6YSU.js +0 -2
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url); { const __piWorkerThreads = require("node:worker_threads"); if (typeof __piWorkerThreads.markAsUncloneable !== "function") { __piWorkerThreads.markAsUncloneable = () => {}; } }
|
|
2
|
+
import{engineBuildIdentity}from"./chunk-ZJHRDQCH.js";import{HOST_GENERATION_ENV,HOST_INSTANCE_ID_ENV}from"./chunk-CIRZTP7W.js";import{parseArgs,resolveSessionRuntime}from"./chunk-VE3D74HN.js";import*as crypto from"node:crypto";var CUSTOM_UNSUPPORTED_CAPABILITY="custom_unsupported",EXTENSION_EVENTS_CAPABILITY="extension_events",AUTO_TITLE_SESSIONS_CAPABILITY="auto_title_sessions",CONTINUE_FROM_LEAF_CAPABILITY="continue_from_leaf",SESSION_HELD_CAPABILITY="session_held",MEDIA_PLACEHOLDERS_CAPABILITY="media_placeholders",QUESTION_CAPABILITY="question",RETAIN_ON_DISCONNECT_CAPABILITY="retain_on_disconnect",SESSION_CONTEXT_CAPABILITY="session_context",SESSION_KIND_CAPABILITY="session_kind",AUTO_TITLE_PER_SESSION_CAPABILITY="auto_title_per_session",WARM_CAPABILITY="warm",DURABLE_SESSION_ID_CAPABILITY="durable_session_id",MOVED_PATH_GUARD_CAPABILITY="moved_path_guard",PROMPT_SURFACE_CAPABILITY="prompt_surface",BROWSER_ENGINE_CAPABILITY="browser_engine",RETRY_FALLBACK_PROFILE_CAPABILITY="retry_fallback_profile",RETRY_FALLBACK_COMMAND_CAPABILITY="retry_fallback_command",PROMPT_SURFACE_CHAT_CAPABILITY="prompt_surface_chat",RPC_CLIENT_CAPABILITIES_ENV="SENPI_RPC_CLIENT_CAPABILITIES";function parseClientCapabilities(value){return value?value.split(",").map(part=>part.trim()).filter(part=>part.length>0):[]}var DEFAULT_CUSTOM_EXTENSION_LABEL="custom UI component";function buildCustomUnsupportedRequest(capabilities,extensionName){if(!capabilities?.includes(CUSTOM_UNSUPPORTED_CAPABILITY))return;let name=extensionName.trim()||DEFAULT_CUSTOM_EXTENSION_LABEL;return{type:"extension_ui_request",id:crypto.randomUUID(),method:"custom_unsupported",extensionName:name}}import{createHash,randomUUID as randomUUID2}from"node:crypto";import{resolve}from"node:path";var INSTANCE_ID=resolveInstanceId(process.env[HOST_INSTANCE_ID_ENV]);function resolveInstanceId(value){return value!==void 0&&value.trim()!==""?value:randomUUID2()}function hostInstanceId(){return INSTANCE_ID}var cachedProfile;function hostGeneration(env){let value=env[HOST_GENERATION_ENV];return value!==void 0&&/^\d+$/.test(value)?Number(value):0}function hostLaunchProfile(argv,cwd){let parsed=parseArgs([...argv],{grokNeoEnabled:!1}),core={extensions:[...new Set((parsed.extensions??[]).map(path=>resolve(cwd,path)))].sort(),multi_session:parsed.multiSession===!0,session_runtime:resolveSessionRuntime(parsed)},canonical=JSON.stringify({extensions:core.extensions,multi_session:core.multi_session,session_runtime:core.session_runtime});return{profile_id:createHash("sha256").update(canonical).digest("hex"),core}}function socketHostLaunchProfile(hostArgs,cwd){return hostLaunchProfile(["--mode","rpc","--multi-session","--listen","unix://",...hostArgs],cwd)}function protocolIdentity(){cachedProfile??=hostLaunchProfile(process.argv.slice(2),process.cwd());let build=engineBuildIdentity();return{instanceId:INSTANCE_ID,generation:hostGeneration(process.env),engineVersion:build.text,engineOrdinal:build.ordinal,launch_profile:cachedProfile}}export{CUSTOM_UNSUPPORTED_CAPABILITY,EXTENSION_EVENTS_CAPABILITY,AUTO_TITLE_SESSIONS_CAPABILITY,CONTINUE_FROM_LEAF_CAPABILITY,SESSION_HELD_CAPABILITY,MEDIA_PLACEHOLDERS_CAPABILITY,QUESTION_CAPABILITY,RETAIN_ON_DISCONNECT_CAPABILITY,SESSION_CONTEXT_CAPABILITY,SESSION_KIND_CAPABILITY,AUTO_TITLE_PER_SESSION_CAPABILITY,WARM_CAPABILITY,DURABLE_SESSION_ID_CAPABILITY,MOVED_PATH_GUARD_CAPABILITY,PROMPT_SURFACE_CAPABILITY,BROWSER_ENGINE_CAPABILITY,RETRY_FALLBACK_PROFILE_CAPABILITY,RETRY_FALLBACK_COMMAND_CAPABILITY,PROMPT_SURFACE_CHAT_CAPABILITY,RPC_CLIENT_CAPABILITIES_ENV,parseClientCapabilities,DEFAULT_CUSTOM_EXTENSION_LABEL,buildCustomUnsupportedRequest,hostInstanceId,hostGeneration,hostLaunchProfile,socketHostLaunchProfile,protocolIdentity};
|
|
@@ -1,2 +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{getProviderEnvValue}from"./chunk-5ROMKDLK.js";var CLAUDE_CODE_VERSION_PIN_ENV="PI_CLAUDE_CODE_VERSION",CLAUDE_RELEASE_CHANNEL_URL="https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/latest",CLAUDE_NPM_DIST_TAG_URL="https://registry.npmjs.org/@anthropic-ai/claude-code/latest",REFRESH_INTERVAL_MS=360*60*1e3,FETCH_TIMEOUT_MS=5e3,EXACT_SEMVER=/^(\d+)\.(\d+)\.(\d+)$/,EMBEDDED_SEMVER=/(\d+\.\d+\.\d+)/,TOO_OLD_REJECTION=/claude_code_version_too_old|does not support this model; version (\d+\.\d+\.\d+) or newer/i;function compareClaudeCodeVersions(a,b){let left=a.split(".").map(Number),right=b.split(".").map(Number);for(let i=0;i<3;i++){let diff=(left[i]??0)-(right[i]??0);if(diff!==0)return diff}return 0}function isExactSemver(value){return typeof value=="string"&&EXACT_SEMVER.test(value)}function highest(candidates){let best;for(let candidate of candidates)isExactSemver(candidate)&&(best===void 0||compareClaudeCodeVersions(candidate,best)>0)&&(best=candidate);return best}async function fetchText(fetchImpl,url){try{let response=await fetchImpl(url,{signal:AbortSignal.timeout(FETCH_TIMEOUT_MS)});return response.ok?await response.text():void 0}catch{return}}async function fetchReleaseChannel(fetchImpl){let text=await fetchText(fetchImpl,CLAUDE_RELEASE_CHANNEL_URL);return text===void 0?void 0:EMBEDDED_SEMVER.exec(text.trim())?.[1]}async function fetchNpmDistTag(fetchImpl){let text=await fetchText(fetchImpl,CLAUDE_NPM_DIST_TAG_URL);if(text!==void 0)try{let data=JSON.parse(text),version=typeof data=="object"&&data!==null&&"version"in data?data.version:void 0;return typeof version=="string"?EMBEDDED_SEMVER.exec(version)?.[1]:void 0}catch{return}}async function fetchLatestClaudeCodeVersion(fetchImpl=fetch){return highest(await Promise.all([fetchReleaseChannel(fetchImpl),fetchNpmDistTag(fetchImpl)]))}function requiredClaudeCodeVersionFromError(message){let match=TOO_OLD_REJECTION.exec(message);if(match)return match[1]??/version (\d+\.\d+\.\d+) or newer/i.exec(message)?.[1]}function isClaudeCodeVersionTooOldError(error){return error instanceof Error&&"status"in error&&error.status===400&&TOO_OLD_REJECTION.test(error.message)}function createClaudeCodeVersionResolver(options){let{floor,store}=options,offline=options.offline===!0,fetchImpl=options.fetch??fetch,now=options.now??Date.now,refreshIntervalMs=options.refreshIntervalMs??REFRESH_INTERVAL_MS,pinned=isExactSemver(options.pinned)?options.pinned:void 0,loaded=!1,resolved,checkedAt=0,inflight,current=()=>resolved!==void 0&&compareClaudeCodeVersions(resolved,floor)>0?resolved:floor,loadCache=()=>{if(loaded||store===null)return;loaded=!0;let record=store.load();record&&isExactSemver(record.version)&&Number.isFinite(record.checkedAt)&&(resolved=record.version,checkedAt=record.checkedAt)},persist=()=>{store!==null&&resolved!==void 0&&store.save({version:resolved,checkedAt})},refresh=()=>pinned!==void 0||store===null?Promise.resolve(pinned??current()):(loadCache(),offline?Promise.resolve(current()):(inflight??=(async()=>{try{let latest=await fetchLatestClaudeCodeVersion(fetchImpl);checkedAt=now(),latest!==void 0&&(resolved===void 0||compareClaudeCodeVersions(latest,resolved)>0)&&(resolved=latest),persist()}finally{inflight=void 0}return current()})(),inflight));return{get(){return pinned!==void 0?pinned:(store===null||(loadCache(),!offline&&inflight===void 0&&now()-checkedAt>=refreshIntervalMs&&refresh()),current())},refresh,raise(version){return pinned!==void 0?pinned:(loadCache(),isExactSemver(version)&&compareClaudeCodeVersions(version,current())>0&&(resolved=version,persist()),current())}}}var installedStore=null,installedOffline=!1,defaultResolver,defaultFloor;function installClaudeCodeVersionStore(store,options={}){installedStore=store,installedOffline=options.offline===!0,defaultResolver=void 0}function resolver(floor){return(defaultResolver===void 0||defaultFloor!==floor)&&(defaultFloor=floor,defaultResolver=createClaudeCodeVersionResolver({floor,store:installedStore,offline:installedOffline})),defaultResolver}function pinnedClaudeCodeVersion(env){let pin=getProviderEnvValue(CLAUDE_CODE_VERSION_PIN_ENV,env)?.trim();return isExactSemver(pin)?pin:void 0}function getClaudeCodeVersion(floor,env){return pinnedClaudeCodeVersion(env)??resolver(floor).get()}async function recoverClaudeCodeVersion(error,floor,advertised,env){if(pinnedClaudeCodeVersion(env)!==void 0)return;let required=requiredClaudeCodeVersionFromError(error.message),next=required===void 0?await resolver(floor).refresh():resolver(floor).raise(required);return compareClaudeCodeVersions(next,advertised)>0?next:void 0}function claudeCodeVersionTooOldHint(advertised){return`senpi advertised claude-cli/${advertised}; Anthropic requires a newer Claude Code for this model. senpi refreshes the version automatically when online; set ${CLAUDE_CODE_VERSION_PIN_ENV}=X.Y.Z to advertise a specific one.`}
|
|
2
|
+
import{getProviderEnvValue}from"./chunk-5ROMKDLK.js";var CLAUDE_CODE_VERSION_PIN_ENV="PI_CLAUDE_CODE_VERSION",CLAUDE_RELEASE_CHANNEL_URL="https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases/latest",CLAUDE_NPM_DIST_TAG_URL="https://registry.npmjs.org/@anthropic-ai/claude-code/latest",REFRESH_INTERVAL_MS=360*60*1e3,FETCH_TIMEOUT_MS=5e3,EXACT_SEMVER=/^(\d+)\.(\d+)\.(\d+)$/,EMBEDDED_SEMVER=/(\d+\.\d+\.\d+)/,TOO_OLD_REJECTION=/claude_code_version_too_old|does not support this model; version (\d+\.\d+\.\d+) or newer/i;function compareClaudeCodeVersions(a,b){let left=a.split(".").map(Number),right=b.split(".").map(Number);for(let i=0;i<3;i++){let diff=(left[i]??0)-(right[i]??0);if(diff!==0)return diff}return 0}function isExactSemver(value){return typeof value=="string"&&EXACT_SEMVER.test(value)}function highest(candidates){let best;for(let candidate of candidates)isExactSemver(candidate)&&(best===void 0||compareClaudeCodeVersions(candidate,best)>0)&&(best=candidate);return best}async function fetchText(fetchImpl,url){try{let response=await fetchImpl(url,{signal:AbortSignal.timeout(FETCH_TIMEOUT_MS)});return response.ok?await response.text():void 0}catch{return}}async function fetchReleaseChannel(fetchImpl){let text=await fetchText(fetchImpl,CLAUDE_RELEASE_CHANNEL_URL);return text===void 0?void 0:EMBEDDED_SEMVER.exec(text.trim())?.[1]}async function fetchNpmDistTag(fetchImpl){let text=await fetchText(fetchImpl,CLAUDE_NPM_DIST_TAG_URL);if(text!==void 0)try{let data=JSON.parse(text),version=typeof data=="object"&&data!==null&&"version"in data?data.version:void 0;return typeof version=="string"?EMBEDDED_SEMVER.exec(version)?.[1]:void 0}catch{return}}async function fetchLatestClaudeCodeVersion(fetchImpl=fetch){return highest(await Promise.all([fetchReleaseChannel(fetchImpl),fetchNpmDistTag(fetchImpl)]))}function requiredClaudeCodeVersionFromError(message){let match=TOO_OLD_REJECTION.exec(message);if(match)return match[1]??/version (\d+\.\d+\.\d+) or newer/i.exec(message)?.[1]}function isClaudeCodeVersionTooOldError(error){return error instanceof Error&&"status"in error&&error.status===400&&TOO_OLD_REJECTION.test(error.message)}function createClaudeCodeVersionResolver(options){let{floor,store}=options,offline=options.offline===!0,fetchImpl=options.fetch??fetch,now=options.now??Date.now,refreshIntervalMs=options.refreshIntervalMs??REFRESH_INTERVAL_MS,pinned=isExactSemver(options.pinned)?options.pinned:void 0,loaded=!1,resolved,checkedAt=0,inflight,current=()=>resolved!==void 0&&compareClaudeCodeVersions(resolved,floor)>0?resolved:floor,loadCache=()=>{if(loaded||store===null)return;loaded=!0;let record=store.load();record&&isExactSemver(record.version)&&Number.isFinite(record.checkedAt)&&(resolved=record.version,checkedAt=record.checkedAt)},persist=()=>{store!==null&&resolved!==void 0&&store.save({version:resolved,checkedAt})},refresh=()=>pinned!==void 0||store===null?Promise.resolve(pinned??current()):(loadCache(),offline?Promise.resolve(current()):(inflight??=(async()=>{try{let latest=await fetchLatestClaudeCodeVersion(fetchImpl);checkedAt=now(),latest!==void 0&&(resolved===void 0||compareClaudeCodeVersions(latest,resolved)>0)&&(resolved=latest),persist()}finally{inflight=void 0}return current()})(),inflight));return{get(){return pinned!==void 0?pinned:(store===null||(loadCache(),!offline&&inflight===void 0&&now()-checkedAt>=refreshIntervalMs&&refresh()),current())},refresh,raise(version){return pinned!==void 0?pinned:(loadCache(),isExactSemver(version)&&compareClaudeCodeVersions(version,current())>0&&(resolved=version,persist()),current())}}}var installedStore=null,installedOffline=!1,defaultResolver,defaultFloor;function installClaudeCodeVersionStore(store,options={}){installedStore=store,installedOffline=options.offline===!0,defaultResolver=void 0}function resolver(floor){return(defaultResolver===void 0||defaultFloor!==floor)&&(defaultFloor=floor,defaultResolver=createClaudeCodeVersionResolver({floor,store:installedStore,offline:installedOffline})),defaultResolver}function pinnedClaudeCodeVersion(env){let pin=getProviderEnvValue(CLAUDE_CODE_VERSION_PIN_ENV,env)?.trim();return isExactSemver(pin)?pin:void 0}function getClaudeCodeVersion(floor,env){return pinnedClaudeCodeVersion(env)??resolver(floor).get()}async function recoverClaudeCodeVersion(error,floor,advertised,env){if(pinnedClaudeCodeVersion(env)!==void 0)return;let required=requiredClaudeCodeVersionFromError(error.message),next=required===void 0?await resolver(floor).refresh():resolver(floor).raise(required);return compareClaudeCodeVersions(next,advertised)>0?next:void 0}function claudeCodeVersionTooOldHint(advertised){return`senpi advertised claude-cli/${advertised}; Anthropic requires a newer Claude Code for this model. senpi refreshes the version automatically when online; set ${CLAUDE_CODE_VERSION_PIN_ENV}=X.Y.Z to advertise a specific one.`}export{isClaudeCodeVersionTooOldError,installClaudeCodeVersionStore,getClaudeCodeVersion,recoverClaudeCodeVersion,claudeCodeVersionTooOldHint};
|
|
@@ -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{watchWithErrorHandler}from"./chunk-JABBHOD5.js";import{external_exports}from"./chunk-KUPQO7MC.js";import{ProjectTrustStore}from"./chunk-RRU5LXMS.js";import{modelSupportsAssistantPrefill}from"./chunk-
|
|
2
|
+
import{watchWithErrorHandler}from"./chunk-JABBHOD5.js";import{external_exports}from"./chunk-KUPQO7MC.js";import{ProjectTrustStore}from"./chunk-RRU5LXMS.js";import{modelSupportsAssistantPrefill}from"./chunk-5BRVRFJI.js";import{sanitizeProviderDiagnostic}from"./chunk-YOPVJDSU.js";import{getSupportedThinkingLevels,supportsMax,supportsXhigh}from"./chunk-L4HVJWIF.js";function supportsXhigh2(model){return supportsXhigh(model)}function supportsMax2(model){return supportsMax(model)}function getSupportedThinkingLevels2(model){let supportedLevels=getSupportedThinkingLevels(model);return supportedLevels.length>0?supportedLevels:["off"]}function clampThinkingSelection(selection,requested,level,model){if(selection===void 0)return;let{requested:_staleRequested,clampReason:_staleReason,...base}=selection;return requested===level||model===void 0?{...base,level}:{...base,level,requested,clampReason:model.reasoning?"level-unsupported":"model-not-reasoning"}}function getThinkingClampNotice(selection,model){let clamped=selection;if(!(model===void 0||clamped?.requested===void 0||clamped.clampReason===void 0))return{provider:model.provider,modelId:model.id,requestedLevel:clamped.requested,appliedLevel:clamped.level,reason:clamped.clampReason}}function formatThinkingClampWarning(notice){let model=`${notice.provider}/${notice.modelId}`;return notice.reason==="model-not-reasoning"?`Thinking level "${notice.requestedLevel}" was requested, but ${model} is not marked as a reasoning model, so thinking is "${notice.appliedLevel}". If the model supports reasoning, set "reasoning": true for it in models.json.`:`Thinking level "${notice.requestedLevel}" is not available on ${model}; using "${notice.appliedLevel}".`}function classifyReasoningCapability(model){if(!model.reasoning)return{kind:"none",levels:["off"],nonOffLevels:[]};let levels=getSupportedThinkingLevels2(model),nonOffLevels=levels.filter(level=>level!=="off");return levels.includes("off")?nonOffLevels.length===1?{kind:"on-off",levels,nonOffLevels}:nonOffLevels.length===0?{kind:"none",levels,nonOffLevels}:{kind:"graded",levels,nonOffLevels}:{kind:"always-on",levels,nonOffLevels}}var BROWSER_ENGINES=["connected","builtin","none"];function isBrowserEngine(value){return BROWSER_ENGINES.some(engine=>engine===value)}var clientMessageIdentitySchema=external_exports.object({clientMessageId:external_exports.string().min(1).max(256).optional(),clientTurnId:external_exports.string().min(1).max(256).optional()});function clientMessageIdentity(value={}){return{...value.clientMessageId===void 0?{}:{clientMessageId:value.clientMessageId},...value.clientTurnId===void 0?{}:{clientTurnId:value.clientTurnId}}}function readClientMessageIdentity(value){let parsed=clientMessageIdentitySchema.safeParse(value);return parsed.success?clientMessageIdentity(parsed.data):{}}var MAX_RPC_MESSAGE_CHARACTERS=1e6,SESSION_CONTEXT_LIMITS={keys:32,valueBytes:16*1024,totalBytes:32*1024},SESSION_CONTEXT_KEY_PATTERN=/^[a-z][a-z0-9_]*$/;function validContent(content){return typeof content=="string"?!0:Array.isArray(content)&&content.every(item=>{if(typeof item!="object"||item===null)return!1;let value=item;return value.type==="text"?typeof value.text=="string":value.type==="image"&&typeof value.data=="string"&&typeof value.mimeType=="string"})}function validBaseEntry(entry){return typeof entry.id=="string"&&(entry.parentId===null||typeof entry.parentId=="string")&&typeof entry.timestamp=="string"}function validSessionEntry(entry){if(typeof entry!="object"||entry===null||Array.isArray(entry))return!1;let value=entry;if(!validBaseEntry(value))return!1;switch(value.type){case"message":{let message=value.message;if(typeof message!="object"||message===null)return!1;let item=message;return["user","assistant","tool"].includes(item.role)&&validContent(item.content)}case"thinking_level_change":return typeof value.thinkingLevel=="string";case"model_change":return typeof value.provider=="string"&&typeof value.modelId=="string";case"model_change_rejected":return typeof value.provider=="string"&&typeof value.modelId=="string"&&typeof value.detail=="string";case"compaction":return typeof value.summary=="string"&&typeof value.firstKeptEntryId=="string"&&typeof value.tokensBefore=="number";case"branch_summary":return typeof value.fromId=="string"&&typeof value.summary=="string";case"custom":return typeof value.customType=="string";case"custom_message":return typeof value.customType=="string"&&validContent(value.content)&&typeof value.display=="boolean";case"label":return typeof value.targetId=="string"&&(value.label===void 0||typeof value.label=="string");case"session_info":return value.name===void 0||typeof value.name=="string";default:return!1}}function rpcCommandPayloadError(command){if(rpcCommandShapeError(command))return;let value=command;if((value.type==="prompt"||value.type==="steer"||value.type==="follow_up")&&!clientMessageIdentitySchema.safeParse(value).success)return"clientMessageId and clientTurnId must be non-empty strings of at most 256 characters.";if((value.type==="steer"||value.type==="follow_up")&&value.enqueueOrder!==void 0&&!(typeof value.enqueueOrder=="number"&&Number.isFinite(value.enqueueOrder)))return"enqueueOrder must be a finite number.";if(value.type==="append_user_message"&&!validContent(value.content))return"append_user_message content must be a string or text/image content array.";if(value.type==="append_session_entry"&&!validSessionEntry(value.entry))return"append_session_entry entry is malformed."}function sessionContextError(context){if(context===void 0)return;if(typeof context!="object"||context===null||Array.isArray(context))return"context must be an object of string values.";let entries=Object.entries(context);if(entries.length>SESSION_CONTEXT_LIMITS.keys)return`context has ${entries.length} keys, at most ${SESSION_CONTEXT_LIMITS.keys} are accepted.`;for(let[key,value]of entries){if(!SESSION_CONTEXT_KEY_PATTERN.test(key))return`context key "${key}" must match ${SESSION_CONTEXT_KEY_PATTERN.source}.`;if(typeof value!="string")return`context value for key "${key}" must be a string.`;let valueBytes=Buffer.byteLength(value);if(valueBytes>SESSION_CONTEXT_LIMITS.valueBytes)return`context value for key "${key}" is ${valueBytes} bytes, at most ${SESSION_CONTEXT_LIMITS.valueBytes} bytes are accepted.`}let totalBytes=Buffer.byteLength(JSON.stringify(context));if(totalBytes>SESSION_CONTEXT_LIMITS.totalBytes)return`context is ${totalBytes} bytes of JSON, at most ${SESSION_CONTEXT_LIMITS.totalBytes} bytes are accepted.`}function sessionKindError(kind){if(!(kind===void 0||kind==="interactive"||kind==="worker"))return'kind must be "interactive" or "worker".'}function sessionAutoTitleError(value){if(!(value===void 0||typeof value=="boolean"))return"auto_title must be a boolean."}function sessionPromptSurfaceError(value){if(!(value===void 0||value==="terminal"||value==="app"||value==="chat"))return'promptSurface must be "terminal", "app" or "chat".'}function sessionBrowserEngineError(value){if(!(value===void 0||isBrowserEngine(value)))return'browserEngine must be "connected", "builtin" or "none".'}var MAX_RETRY_FALLBACK_CHAINS=32,MAX_RETRY_FALLBACK_ENTRIES=32,MAX_RETRY_FALLBACK_SELECTOR_LENGTH=512;function sessionRetryFallbackError(value){if(value===void 0)return;let shape="retryFallback must be { modelFallback: boolean, fallbackChains: Record<string, string[]> }.";if(typeof value!="object"||value===null||Array.isArray(value))return shape;let record=value;if(typeof record.modelFallback!="boolean")return shape;let chains=record.fallbackChains;if(typeof chains!="object"||chains===null||Array.isArray(chains))return shape;let entries=Object.entries(chains);if(entries.length>MAX_RETRY_FALLBACK_CHAINS)return`retryFallback allows at most ${MAX_RETRY_FALLBACK_CHAINS} chains.`;for(let[key,selectors]of entries){if(!isSelector(key)||!Array.isArray(selectors)||!selectors.every(isSelector))return shape;if(selectors.length>MAX_RETRY_FALLBACK_ENTRIES)return`retryFallback allows at most ${MAX_RETRY_FALLBACK_ENTRIES} entries per chain.`}}function isSelector(value){return typeof value=="string"&&value.trim().length>0&&value.length<=MAX_RETRY_FALLBACK_SELECTOR_LENGTH}function rpcCommandShapeError(command){if(typeof command!="object"||command===null||Array.isArray(command))return"RPC command must be a JSON object."}function rpcMessageLengthError(command){if(rpcCommandShapeError(command))return;let input=command;if(!(input.type!=="prompt"&&input.type!=="steer"&&input.type!=="follow_up")&&!(typeof input.message!="string"||input.message.length<=MAX_RPC_MESSAGE_CHARACTERS))return`RPC ${input.type} message exceeds ${MAX_RPC_MESSAGE_CHARACTERS} characters.`}import{randomUUID}from"node:crypto";import{mkdir,rm,writeFile}from"node:fs/promises";import{join}from"node:path";import{setTimeout as delay}from"node:timers/promises";import{Worker}from"node:worker_threads";var RECURSIVE_WATCH_WORKER_SOURCE=`
|
|
3
3
|
const { watch } = require("node:fs");
|
|
4
4
|
const { parentPort } = require("node:worker_threads");
|
|
5
5
|
|
|
@@ -0,0 +1,3 @@
|
|
|
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{getAgentDir}from"./chunk-463OK2Y4.js";import{accessSync,existsSync,lstatSync as lstatSync2,realpathSync,statSync}from"node:fs";import{homedir as homedir3}from"node:os";import{basename as basename3,dirname as dirname3,join as join4,resolve as resolve2}from"node:path";import{closeSync,constants,fstatSync,lstatSync,openSync,readSync}from"node:fs";import{lstat,open}from"node:fs/promises";import{join as join2}from"node:path";import path,{posix,win32}from"node:path";var MOVED_BREADCRUMB_FILE="omo-desktop-moved.json",MOVED_BREADCRUMB_KIND="omo-desktop-moved",MOVED_BREADCRUMB_SCHEMA_VERSION=1;function ignored(reason){return{kind:"ignored",reason}}function prefixSegments(prefix){if(typeof prefix!="string"||posix.isAbsolute(prefix)||win32.isAbsolute(prefix))return;let segments=prefix.split(/[\\/]/).filter(segment=>segment.length>0);if(!(segments.length===0||segments.some(segment=>segment==="."||segment==="..")))return segments}function isNormalizedAbsolute(value,host){return!host.isAbsolute(value)||host.normalize(value)!==value?!1:value===host.parse(value).root||!(value.endsWith("/")||value.endsWith(host.sep))}function parseMovedBreadcrumb(raw,host=path){if(typeof raw!="object"||raw===null)return ignored("not an object");let record=raw;if(record.kind!==MOVED_BREADCRUMB_KIND)return ignored("foreign kind");let version=record.schemaVersion;if(typeof version!="number"||!Number.isInteger(version)||version<1)return ignored("invalid schemaVersion");if(version>MOVED_BREADCRUMB_SCHEMA_VERSION)return ignored(`unsupported schemaVersion ${version}`);let movedTo=record.movedTo;if(typeof movedTo!="string"||!isNormalizedAbsolute(movedTo,host))return ignored("movedTo is not a normalized absolute path on this host");let homeId=record.homeId;if(typeof homeId!="string"||homeId.length===0)return ignored("homeId is missing");if(!Array.isArray(record.moved))return ignored("moved is not an array");let moved=[];for(let prefix of record.moved){let segments=prefixSegments(prefix);if(!segments)return ignored(`invalid moved prefix ${JSON.stringify(prefix)}`);moved.push(segments)}return{kind:"valid",breadcrumb:{movedTo,homeId,moved}}}import{appendFile,mkdir,rename,stat}from"node:fs/promises";import{dirname,join}from"node:path";var MAX_GUARD_LOG_BYTES=1024*1024,reported=new Set,pending=Promise.resolve();function guardLogPath(){return join(getAgentDir(),"logs","moved-path-guard.log")}async function append(line){let file=guardLogPath();await mkdir(dirname(file),{recursive:!0,mode:448}),await stat(file).then(stats=>stats.size,()=>0)+Buffer.byteLength(line)>MAX_GUARD_LOG_BYTES&&await rename(file,`${file}.1`),await appendFile(file,line,{mode:384})}function logGuardEvent(level,event,details){let{count:_count,...reason}=details,key=`${event}\0${JSON.stringify(reason)}`;if(reported.has(key))return;reported.add(key);let line=`${JSON.stringify({ts:new Date().toISOString(),level,event,...details})}
|
|
3
|
+
`;pending=pending.then(()=>append(line)).catch(()=>{})}var DESKTOP_HOME_MARKER_FILE="omo-desktop-home.json";function parseDesktopHomeMarker(raw){if(typeof raw!="object"||raw===null)return{kind:"invalid"};let record=raw;return record.kind!=="omo-desktop-data-home"||record.appId!=="com.omo.desktop"?{kind:"invalid"}:typeof record.schemaVersion=="number"&&record.schemaVersion>1?{kind:"newer",schemaVersion:record.schemaVersion}:record.schemaVersion!==1||typeof record.homeId!="string"||record.homeId.length===0?{kind:"invalid"}:{kind:"valid",homeId:record.homeId}}function currentPathPlatform(){return process.platform==="win32"?"win32":process.platform==="darwin"?"darwin":"posix"}function pathSegments(path2,platform){return platform!=="win32"?path2.split("/").filter(segment=>segment.length>0):(path2.startsWith("\\\\?\\UNC\\")?`\\\\${path2.slice(8)}`:path2.startsWith("\\\\?\\")?path2.slice(4):path2).split(/[\\/]/).filter(segment=>segment.length>0)}function sameSegment(a,b,platform){return platform==="posix"?a===b:a.toLowerCase()===b.toLowerCase()}function startsWithSegments(path2,prefix,platform){return prefix.length<=path2.length&&prefix.every((segment,index)=>sameSegment(path2[index]??"",segment,platform))}function matchMovedPrefix(path2,root,moved,platform){let pathParts=pathSegments(path2,platform),rootParts=pathSegments(root,platform);if(!startsWithSegments(pathParts,rootParts,platform))return;let remainder=pathParts.slice(rootParts.length),prefix=moved.find(candidate=>startsWithSegments(remainder,candidate,platform));return prefix?{prefix,remainder}:void 0}var MAX_HOPS=3,MAX_TRUST_FILE_BYTES=64*1024,jsonByFile=new Map;function parseJson(text){try{return JSON.parse(text)}catch{return}}function trustStamp(stats){if(!(!stats.isFile()||stats.size>MAX_TRUST_FILE_BYTES)&&!(process.platform!=="win32"&&(stats.uid!==process.getuid?.()||(stats.mode&18)!==0)))return`${stats.mtimeMs}:${stats.size}:${stats.ino}`}var OPEN_FLAGS=constants.O_RDONLY|(constants.O_NOFOLLOW??0)|(constants.O_NONBLOCK??0),NEEDS_LSTAT_FIRST=constants.O_NONBLOCK===void 0;function remembered(file,stamp,read){let cached=jsonByFile.get(file);if(cached?.stamp===stamp)return cached.value;let value=parseJson(read().toString("utf8"));return jsonByFile.set(file,{stamp,value}),value}function readJsonFileSync(file){let fd;try{if(NEEDS_LSTAT_FIRST&&!lstatSync(file).isFile())return;fd=openSync(file,OPEN_FLAGS)}catch{return}try{let stats=fstatSync(fd),stamp=trustStamp(stats);return stamp===void 0?void 0:remembered(file,stamp,()=>{let buffer=Buffer.alloc(stats.size);return buffer.subarray(0,readSync(fd,buffer,0,stats.size,0))})}finally{closeSync(fd)}}async function readJsonFileAsync(file){if(NEEDS_LSTAT_FIRST&&!await lstat(file).then(stats=>stats.isFile(),()=>!1))return;let handle=await open(file,OPEN_FLAGS).catch(()=>{});if(handle)try{let stats=await handle.stat(),stamp=trustStamp(stats);if(stamp===void 0)return;let cached=jsonByFile.get(file);if(cached?.stamp===stamp)return cached.value;let buffer=Buffer.alloc(stats.size),{bytesRead}=await handle.read(buffer,0,stats.size,0);return remembered(file,stamp,()=>buffer.subarray(0,bytesRead))}finally{await handle.close()}}var breadcrumbFile=dir=>join2(dir,MOVED_BREADCRUMB_FILE),homeMarkerFile=movedTo=>join2(movedTo,DESKTOP_HOME_MARKER_FILE);function ignoreBreadcrumb(file,reason){logGuardEvent("debug","breadcrumb_ignored",{file,reason})}function movedToInHome(dir,breadcrumb,homes,platform){return homes.some(home=>matchMovedPrefix(breadcrumb.movedTo,home,[[]],platform))?!0:(ignoreBreadcrumb(breadcrumbFile(dir),"movedTo is outside the user's home"),!1)}function trustedFolder(dir,stats){return stats===void 0?!1:process.platform==="win32"||stats.isDirectory()&&stats.uid===process.getuid?.()&&(stats.mode&18)===0?!0:(ignoreBreadcrumb(breadcrumbFile(dir),"its folder is shared or not the user's"),!1)}function parsedBreadcrumb(dir,raw){if(raw===void 0)return;let parsed=parseMovedBreadcrumb(raw);return parsed.kind==="valid"?parsed.breadcrumb:ignoreBreadcrumb(breadcrumbFile(dir),parsed.reason)}function trustedBreadcrumb(dir,breadcrumb,markerRaw,platform){if(matchMovedPrefix(breadcrumb.movedTo,dir,[[]],platform))return ignoreBreadcrumb(breadcrumbFile(dir),"movedTo is the breadcrumb's own folder or inside it");let marker=parseDesktopHomeMarker(markerRaw);if(marker.kind==="newer"){logGuardEvent("warn","marker_newer",{file:homeMarkerFile(breadcrumb.movedTo),schemaVersion:String(marker.schemaVersion)});return}return marker.kind!=="valid"||marker.homeId!==breadcrumb.homeId?ignoreBreadcrumb(breadcrumbFile(dir),"movedTo holds no desktop home marker with this homeId"):breadcrumb}function movedMatch(dir,breadcrumb,canonical,platform){let match=matchMovedPrefix(canonical,dir,breadcrumb.moved,platform);if(match)return{prefix:match.prefix,moved:{oldRoot:dir,movedTo:breadcrumb.movedTo,mappedPath:join2(breadcrumb.movedTo,...match.remainder)}}}var gitEntryOf=(oldRoot,prefix)=>prefix.includes("worktrees")?join2(oldRoot,...prefix,".git"):void 0;function movedPathReason(moved){return`This folder moved to ${moved.movedTo}. Use ${moved.mappedPath}.`}import{homedir as homedir2}from"node:os";import{basename as basename2,dirname as dirname2,resolve}from"node:path";import{homedir}from"node:os";import{basename,join as join3}from"node:path";var LEGACY_ROOT_NAMES=[".t3",".omo-app"],legacyRoots=()=>LEGACY_ROOT_NAMES.map(name=>join3(homedir(),name)),isLegacyRoot=(path2,homes,platform)=>homes.some(home=>LEGACY_ROOT_NAMES.some(name=>matchMovedPrefix(path2,join3(home,name),[[]],platform)?.remainder.length===0)),known=new Map,prefixKey=(oldRoot,breadcrumb,prefix)=>[basename(oldRoot).toLowerCase(),breadcrumb.homeId,breadcrumb.movedTo,prefix.join("/")].join("\0");function knownPrefixKeys(path2,platform=currentPathPlatform()){return[...known].flatMap(([spelling,{root,breadcrumb}])=>{let match=matchMovedPrefix(path2,spelling,breadcrumb.moved,platform);return match?[prefixKey(root,breadcrumb,match.prefix)]:[]})}var reusedDecisions=new Map;function rememberReused(key,reused){reusedDecisions.set(key,reused)}function rememberedReused(key){return reusedDecisions.get(key)}function rememberTrustedBreadcrumb(root,called,breadcrumb,homes,platform){let spellings=new Set(called===void 0?[root]:[root,called]);for(let spelling of[...spellings])for(let home of homes){let under=matchMovedPrefix(spelling,home,[[]],platform);if(under)for(let other of homes)spellings.add(join3(other,...under.remainder))}for(let spelling of spellings)known.set(spelling,{root,breadcrumb})}function looksMoved(path2,platform=currentPathPlatform()){return legacyRoots().some(root=>matchMovedPrefix(path2,root,[[]],platform))||[...known].some(([spelling,{breadcrumb}])=>matchMovedPrefix(path2,spelling,breadcrumb.moved,platform))}function knownMove(path2,platform=currentPathPlatform()){for(let[oldRoot,{root,breadcrumb}]of known){let match=matchMovedPrefix(path2,oldRoot,breadcrumb.moved,platform);if(match&&rememberedReused(prefixKey(root,breadcrumb,match.prefix))!==!0)return{oldRoot,movedTo:breadcrumb.movedTo,mappedPath:join3(breadcrumb.movedTo,...match.remainder)}}}function*homeSpellings(){let home=homedir2(),real=yield{op:"home"};return real!==void 0&&real!==home?[home,real]:[home]}function calledSpelling(path2,canonical,dir,homes,platform){let called=resolve(path2);for(let below=canonical;below!==dir;below=dirname2(below)){if(dirname2(called)===called||!sameSegment(basename2(called),basename2(below),platform))return;called=dirname2(called)}return isLegacyRoot(called,homes,platform)?called:void 0}function*movedOnce(path2,platform,onReused){let canonical=(yield{op:"canonical",path:path2})??resolve(path2),stop=dirname2(homedir2());for(let dir=dirname2(canonical);;dir=dirname2(dir)){let breadcrumb=parsedBreadcrumb(dir,yield{op:"json",file:breadcrumbFile(dir)}),match=breadcrumb&&movedMatch(dir,breadcrumb,canonical,platform),homes=match?yield*homeSpellings():[];if(match&&movedToInHome(dir,breadcrumb,homes,platform)&&trustedFolder(dir,yield{op:"folder",path:dir,follow:isLegacyRoot(dir,homes,platform)})&&trustedBreadcrumb(dir,breadcrumb,yield{op:"json",file:homeMarkerFile(breadcrumb.movedTo)},platform)){let gitEntry=gitEntryOf(dir,match.prefix),reused=!1;if(gitEntry!==void 0){let key=prefixKey(dir,breadcrumb,match.prefix),answer2=yield{op:"exists",path:gitEntry};typeof answer2=="boolean"&&rememberReused(key,answer2),reused=typeof answer2=="boolean"?answer2:rememberedReused(key)??!1}if(reused&&onReused?.(dir,breadcrumb,match.prefix),rememberTrustedBreadcrumb(dir,calledSpelling(path2,canonical,dir,homes,platform),breadcrumb,homes,platform),!reused)return match.moved}if(dir===stop||dirname2(dir)===dir)return}}function*movedPathWalk(path2,platform,onReused){let found;for(let hop=0;hop<MAX_HOPS;hop++){let next=yield*movedOnce(found?.mappedPath??path2,platform,onReused);if(!next)break;found=found?{...next,oldRoot:found.oldRoot}:next}return found}function canonicalPath(path2){let missing=[],existing=resolve2(path2);for(;!existsSync(existing);){let parent=dirname3(existing);if(parent===existing)return resolve2(path2);missing.unshift(basename3(existing)),existing=parent}return join4(realpathSync(existing),...missing)}function pathExistsSync(path2){try{return accessSync(path2),!0}catch(error){let code=error?.code;return code==="ENOENT"||code==="ENOTDIR"?!1:void 0}}function answer(step){try{return step.op==="canonical"?canonicalPath(step.path):step.op==="json"?readJsonFileSync(step.file):step.op==="home"?realpathSync(homedir3()):step.op==="folder"?(step.follow?statSync:lstatSync2)(step.path):pathExistsSync(step.path)}catch{return void 0}}function findMovedPath(path2,platform=currentPathPlatform()){let walk=movedPathWalk(path2,platform),step=walk.next();for(;!step.done;)step=walk.next(answer(step.value));return step.value}function resolveMovedPath(path2){return findMovedPath(path2)?.mappedPath??path2}export{logGuardEvent,currentPathPlatform,readJsonFileAsync,movedPathReason,prefixKey,knownPrefixKeys,looksMoved,knownMove,movedPathWalk,resolveMovedPath};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url); { const __piWorkerThreads = require("node:worker_threads"); if (typeof __piWorkerThreads.markAsUncloneable !== "function") { __piWorkerThreads.markAsUncloneable = () => {}; } }
|
|
2
|
+
var GATEWAY_NAMESPACE=/^mcp__(.+)$/i,GATEWAY_DELIMITER=/_{2,}/g,SERVER_NAMESPACE=/^mcp_([^_]+)_(.+)$/i;function foldToolName(name){return name.toLowerCase().replaceAll(/[-_]/g,"")}function toolNameForms(name){let forms=[name],gateway=GATEWAY_NAMESPACE.exec(name);if(gateway){let rest=gateway[1]??"";for(let run of rest.matchAll(GATEWAY_DELIMITER)){let suffix=rest.slice(run.index+run[0].length);run.index>0&&suffix.length>0&&forms.push(suffix)}return forms}let tool=SERVER_NAMESPACE.exec(name)?.[2];return tool!==void 0&&forms.push(tool),forms}function uniqueMatch(names,matches){let found=names.filter(matches);return found.length===1?found[0]:void 0}function resolveToolNameMatch(requested,available){let names=[...new Set(available)];for(let form of toolNameForms(requested)){if(names.includes(form))return form;let key=foldToolName(form),folded=uniqueMatch(names,name=>foldToolName(name)===key);if(folded!==void 0)return folded;let unprefixed=uniqueMatch(names,name=>toolNameForms(name).slice(1).some(registeredForm=>foldToolName(registeredForm)===key));if(unprefixed!==void 0)return unprefixed}}export{resolveToolNameMatch};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url); { const __piWorkerThreads = require("node:worker_threads"); if (typeof __piWorkerThreads.markAsUncloneable !== "function") { __piWorkerThreads.markAsUncloneable = () => {}; } }
|
|
2
|
+
import{__commonJS}from"./chunk-IKOFCODM.js";var require_ignore=__commonJS({"node_modules/ignore/index.js"(exports,module){function makeArray(subject){return Array.isArray(subject)?subject:[subject]}var UNDEFINED=void 0,EMPTY="",SPACE=" ",ESCAPE="\\",REGEX_LITERAL_SPECIAL=/[.*+?()[\]{}^$|\\/]/,REGEX_TEST_BLANK_LINE=/^\uFEFF? *$/,REGEX_INVALID_TRAILING_BACKSLASH=/(?:[^\\]|^)\\$/,REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION=/^\\!/,REGEX_REPLACE_LEADING_EXCAPED_HASH=/^\\#/,REGEX_SPLITALL_CRLF=/\r?\n/g,DOUBLE_SLASH="//",SLASH_CODE=47,DOT_CODE=46,SLASH="/",TMP_KEY_IGNORE="node-ignore";typeof Symbol<"u"&&(TMP_KEY_IGNORE=Symbol.for("node-ignore"));var KEY_IGNORE=TMP_KEY_IGNORE,define=(object,key,value)=>(Object.defineProperty(object,key,{value}),value),RETURN_FALSE=()=>!1,cleanRangeBackSlash=slashes=>{let{length}=slashes;return slashes.slice(0,length-length%2)},POSIX_CLASSES={alnum:"0-9A-Za-z",alpha:"A-Za-z",blank:" \\t",cntrl:"\\x00-\\x1f\\x7f",digit:"0-9",graph:"!-.0-~",lower:"a-z",print:" -.0-~",punct:"!-.:-@\\[-`{-~",space:" \\t\\n\\r",upper:"A-Z",xdigit:"0-9A-Fa-f"},CLASS_MEMBERS_TO_ESCAPE="\\]^-[",escapeMember=char=>CLASS_MEMBERS_TO_ESCAPE.indexOf(char)<0?char:ESCAPE+char,NON_SLASH="(?!\\/)",classSource=(negated,body)=>{if(negated)return`[^\\/${body}]`;let source=`[${body}]`;return new RegExp(source).test("/")?NON_SLASH+source:source},scanBracket=(pattern,start)=>{let{length}=pattern,index=start+1,negated=EMPTY,lead=pattern[index];(lead==="!"||lead==="^")&&(negated="^",index++);let body=EMPTY,prev=EMPTY;for(;;){let char=pattern[index];if(char===UNDEFINED)return null;if(char===ESCAPE){let escaped=pattern[index+1];if(escaped===UNDEFINED)return null;body+=escapeMember(escaped),prev=escaped,index++}else if(char==="-"&&prev&&index+1<length&&pattern[index+1]!=="]"){index++;let to=pattern[index];to===ESCAPE&&(to=pattern[index+=1]),prev<=to&&(body+=`-${escapeMember(to)}`),prev=EMPTY}else if(char==="["&&pattern[index+1]===":"){let nameStart=index+2,end=nameStart;for(;end<length&&pattern[end]!=="]";)end++;if(end===length)return null;if(end>nameStart&&pattern[end-1]===":"){let expanded=POSIX_CLASSES[pattern.slice(nameStart,end-1)];if(expanded===UNDEFINED)return null;body+=expanded,prev=EMPTY,index=end}else body+=escapeMember("["),prev="[",index=nameStart-2}else body+=escapeMember(char),prev=char;if(index++,pattern[index]==="]")return{end:index,source:classSource(negated,body)}}},NEVER_MATCH="[]",PLACEHOLDER="\0",REGEX_RESTORE_PLACEHOLDER=new RegExp(`${PLACEHOLDER}(\\d+)${PLACEHOLDER}`,"g"),TRAILING_WILDCARD="\uE000",extractBrackets=pattern=>{let sources=[],hold=source=>`${PLACEHOLDER}${sources.push(source)-1}${PLACEHOLDER}`,{length}=pattern,out=EMPTY,index=0;for(;index<length;){let char=pattern[index];if(char===ESCAPE){let escaped=pattern[index+1];escaped==="*"||escaped==="["||escaped===SPACE||escaped===ESCAPE?out+=pattern.slice(index,index+2):out+=hold(REGEX_LITERAL_SPECIAL.test(escaped)?ESCAPE+escaped:escaped),index+=2}else if(char===PLACEHOLDER)out+=hold(`[${PLACEHOLDER}]`),index++;else if(char==="["){let scanned=scanBracket(pattern,index);scanned===null?(out+=hold(NEVER_MATCH),index=length):(out+=hold(scanned.source),index=scanned.end+1)}else out+=char,index++}return{source:out,sources}},DIRECT=null,REGEX_INNER_SLASH=/\/(?!$)/,REPLACERS=[[/^\uFEFF/,()=>EMPTY,"\uFEFF"],[/[\r\n]+$/,()=>EMPTY],[/((?:\\\\)*?)(\\? +)$/,(_,m1,m2)=>m1+(m2.indexOf("\\")===0?SPACE:EMPTY)],[/(\\+?) /g,(_,m1)=>{let{length}=m1;return m1.slice(0,length-length%2)+SPACE}],[/[\\$.|*+(){^]/g,match=>`\\${match}`],[/(?!\\)\?/g,()=>"[^/]","?"],[/^\//,()=>"^",SLASH],[/\//g,()=>"\\/",SLASH],[/^\^*(?:\\\*\\\*\\\/)+/,()=>"^(?:.*\\/)?","*"],[DIRECT,(source,pattern)=>!source||source[0]==="^"?source:(REGEX_INNER_SLASH.test(pattern)?"^":"(?:^|\\/)")+source],[/\\\/\\\*\\\*(?=\\\/|$)/g,(_,index,str)=>index+6<str.length?str.slice(index+6)==="\\/"?"(?:\\/[^\\/]+)+":"(?:\\/[^\\/]+)*":"\\/.+","*"],[/(^|[^\\]+)(\\\*)+(?=.+)/g,(_,p1,p2)=>{let unescaped=p2.replace(/\\\*/g,"[^\\/]*");return p1+unescaped},"*"],[/(^|[^\\])((?:\\\\)*)\\\*$/,(match,p1,p2)=>p2.length/2%2===0?p1+p2+TRAILING_WILDCARD:match,"*"],[/\\\\\\(?=[$.|*+(){^])/g,()=>ESCAPE,ESCAPE+ESCAPE],[/\\\\/g,()=>ESCAPE,ESCAPE+ESCAPE],[/\\\[([^\]/]*?)(\\*)($|\])/g,(match,range,endEscape,close)=>`\\[${range}${cleanRangeBackSlash(endEscape)}${close}`,"["],[DIRECT,source=>{let last=source[source.length-1];return!last||last===TRAILING_WILDCARD?source:last===SLASH?`${source}$`:`${source}(?=$|\\/$)`}]],REGEX_REPLACE_TRAILING_WILDCARD=/(^|\\\/)?\uE000$/,MODE_IGNORE="regex",MODE_CHECK_IGNORE="checkRegex",UNDERSCORE="_",TRAILING_WILD_CARD_REPLACERS={[MODE_IGNORE](_,p1){return`${p1?`${p1}[^/]+`:"[^/]*"}(?=$|\\/$)`},[MODE_CHECK_IGNORE](_,p1){return`${p1?`${p1}[^/]*`:"[^/]*"}(?=$|\\/$)`}},WILDCARD="[^\\/]*",pinWildcards=source=>{if(source.indexOf(WILDCARD)<0)return source;let tokens=[],{length}=source,index=0;for(;index<length;){let char=source[index];if(source.startsWith(WILDCARD,index))tokens.push({wildcard:!0}),index+=WILDCARD.length;else if(char==="["){let end=index+1;for(source[end]==="^"&&end++,source[end]==="]"&&end++;end<length&&source[end]!=="]";)end+=source[end]===ESCAPE?2:1;end++,tokens.push({single:source.slice(index,end)}),index=end}else if(char===ESCAPE)tokens.push({single:source.slice(index,index+2)}),index+=2;else if(char==="("){let depth=0,end=index;do source[end]===ESCAPE?end++:source[end]==="("?depth++:source[end]===")"&&depth--,end++;while(end<length&&depth>0);"*+?".indexOf(source[end])>=0&&end++,tokens.push({boundary:source.slice(index,end)}),index=end}else char==="^"||char==="$"?(tokens.push({boundary:char}),index++):(tokens.push({single:char}),index++)}let out=EMPTY,run=[],flush=()=>{let lastWildcard;run.forEach((token,at)=>{token.wildcard&&(lastWildcard=at)}),run.forEach((token,at)=>{if(!token.wildcard){out+=token.single;return}out+=at===lastWildcard?WILDCARD:`(?:(?!${run[at+1].single})[^\\/])*`}),run=[]};return tokens.forEach(token=>{if(token.boundary===void 0){run.push(token);return}flush(),out+=token.boundary}),flush(),out},makeRegexPrefix=pattern=>{let{source,sources}=extractBrackets(pattern),replaced=REPLACERS.reduce((prev,[matcher,replacer,required])=>matcher===DIRECT?replacer(prev,pattern):required!==UNDEFINED&&prev.indexOf(required)<0?prev:matcher.test(prev)?prev.replace(matcher,replacer.bind(pattern)):prev,source);return sources.length?replaced.replace(REGEX_RESTORE_PLACEHOLDER,(match,index)=>sources[index]):replaced},matchesBasename=body=>{let index=body.indexOf(SLASH);return index<0||index===body.length-1},basenameOf=path=>{let end=path.length-1,index=path.lastIndexOf(SLASH,path[end]===SLASH?end-1:end);return index<0?path:path.slice(index+1)},parentOf=path=>{if(path.charCodeAt(0)===SLASH_CODE||path.indexOf(DOUBLE_SLASH)>=0){let slices=path.split(SLASH).filter(Boolean);return slices.pop(),slices.length?slices.join(SLASH)+SLASH:EMPTY}let end=path.length-1,cut=path.lastIndexOf(SLASH,path.charCodeAt(end)===SLASH_CODE?end-1:end);return cut<0?EMPTY:path.slice(0,cut+1)},isString=subject=>typeof subject=="string",checkPattern=pattern=>pattern&&isString(pattern)&&!REGEX_TEST_BLANK_LINE.test(pattern)&&!REGEX_INVALID_TRAILING_BACKSLASH.test(pattern)&&pattern.indexOf("#")!==0,splitPattern=pattern=>pattern.split(REGEX_SPLITALL_CRLF).filter(Boolean),IgnoreRule=class{constructor(pattern,mark,body,ignoreCase,negative,prefix){this.pattern=pattern,this.mark=mark,this.negative=negative,define(this,"body",body),define(this,"ignoreCase",ignoreCase),define(this,"regexPrefix",prefix)}get _basenameOnly(){return define(this,"_basenameOnly",matchesBasename(this.body))}get regex(){let key=UNDERSCORE+MODE_IGNORE;return this[key]?this[key]:this._make(MODE_IGNORE,key)}get checkRegex(){let key=UNDERSCORE+MODE_CHECK_IGNORE;return this[key]?this[key]:this._make(MODE_CHECK_IGNORE,key)}_make(mode,key){let str=pinWildcards(this.regexPrefix.replace(REGEX_REPLACE_TRAILING_WILDCARD,TRAILING_WILD_CARD_REPLACERS[mode])),regex=this.ignoreCase?new RegExp(str,"i"):new RegExp(str);return define(this,key,regex)}},createRule=({pattern,mark},ignoreCase)=>{let negative=!1,body=pattern;body.indexOf("!")===0&&(negative=!0,body=body.substr(1)),body=body.replace(REGEX_REPLACE_LEADING_EXCAPED_EXCLAMATION,"!").replace(REGEX_REPLACE_LEADING_EXCAPED_HASH,"#");let regexPrefix=makeRegexPrefix(body);return new IgnoreRule(pattern,mark,body,ignoreCase,negative,regexPrefix)},RuleManager=class{constructor(ignoreCase){this._ignoreCase=ignoreCase,this._rules=[],this._basenameCount=0}_add(pattern){if(pattern&&pattern[KEY_IGNORE]){this._rules=this._rules.concat(pattern._rules._rules),this._basenameCount+=pattern._rules._basenameCount,this._added=!0;return}if(isString(pattern)&&(pattern={pattern}),checkPattern(pattern.pattern)){let rule=createRule(pattern,this._ignoreCase);this._added=!0,this._rules.push(rule),matchesBasename(rule.body)&&this._basenameCount++}}add(pattern){return this._added=!1,makeArray(isString(pattern)?splitPattern(pattern):pattern).forEach(this._add,this),this._added}test(path,checkUnignored,mode){let ignored=!1,unignored=!1,matchedRule,rules=this._rules,{length}=rules,shortcut=this._basenameCount*2>=length,basename=shortcut?basenameOf(path):path;for(let index=0;index<length;index++){let rule=rules[index],{negative}=rule;!(unignored===negative&&ignored!==unignored||negative&&!ignored&&!unignored&&!checkUnignored)&&rule[mode].test(shortcut&&rule._basenameOnly?basename:path)&&(ignored=!negative,unignored=negative,matchedRule=negative?UNDEFINED:rule)}let ret={ignored,unignored};return matchedRule&&(ret.rule=matchedRule),ret}},throwError=(message,Ctor)=>{throw new Ctor(message)},checkPath=(path,originalPath,doThrow)=>isString(path)?path?checkPath.isNotRelative(path)?doThrow(`path should be a \`path.relative()\`d string, but got "${originalPath}"`,RangeError):!0:doThrow("path must not be empty",TypeError):doThrow(`path must be a string, but got \`${originalPath}\``,TypeError),isNotRelative=path=>{let first=path.charCodeAt(0);if(first===SLASH_CODE)return!0;if(first!==DOT_CODE)return!1;if(path.length===1)return!0;let second=path.charCodeAt(1);return second===SLASH_CODE?!0:second!==DOT_CODE?!1:path.length===2||path.charCodeAt(2)===SLASH_CODE};checkPath.isNotRelative=isNotRelative;checkPath.convert=p=>p;var Ignore=class{constructor({ignorecase=!0,ignoreCase=ignorecase,allowRelativePaths=!1}={}){define(this,KEY_IGNORE,!0),this._rules=new RuleManager(ignoreCase),this._strictPathCheck=!allowRelativePaths,this._initCache()}_initCache(){this._ignoreCache=Object.create(null),this._testCache=Object.create(null)}add(pattern){return this._rules.add(pattern)&&this._initCache(),this}addPattern(pattern){return this.add(pattern)}_test(originalPath,cache,checkUnignored){let path=originalPath&&checkPath.convert(originalPath);return checkPath(path,originalPath,this._strictPathCheck?throwError:RETURN_FALSE),this._t(path,cache,checkUnignored)}checkIgnore(path){if(path.charCodeAt(path.length-1)!==SLASH_CODE)return this.test(path);let parentPath=parentOf(path);if(parentPath){let parent=this._t(parentPath,this._testCache,!0);if(parent.ignored)return parent}return this._rules.test(path,!1,MODE_CHECK_IGNORE)}_t(path,cache,checkUnignored){if(path in cache)return cache[path];let parentPath=parentOf(path),parent=parentPath?this._t(parentPath,cache,checkUnignored):UNDEFINED;return cache[path]=parent&&parent.ignored?parent:this._rules.test(path,checkUnignored,MODE_IGNORE)}ignores(path){return this._test(path,this._ignoreCache,!1).ignored}createFilter(){return path=>!this.ignores(path)}filter(paths){return makeArray(paths).filter(this.createFilter())}test(path){return this._test(path,this._testCache,!0)}},factory=options=>new Ignore(options),isPathValid=path=>checkPath(path&&checkPath.convert(path),path,RETURN_FALSE),setupWindows=()=>{let makePosix=str=>/^\\\\\?\\/.test(str)||/["<>|\u0000-\u001F]+/u.test(str)?str:str.replace(/\\/g,"/");checkPath.convert=makePosix;let REGEX_TEST_WINDOWS_PATH_ABSOLUTE=/^[a-z]:\//i;checkPath.isNotRelative=path=>REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path)||isNotRelative(path)};typeof process<"u"&&process.platform==="win32"&&setupWindows();module.exports=factory;factory.default=factory;module.exports.isPathValid=isPathValid;define(module.exports,Symbol.for("setupWindows"),setupWindows)}});export{require_ignore};
|
|
@@ -0,0 +1,6 @@
|
|
|
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{resolveMovedPath}from"./chunk-TOZBUPZP.js";import{ownProcessStartedAtMs,processBootAtMs,sameBoot}from"./chunk-DRVT7RIO.js";import{processStartTimeMs,sameProcessStartMs}from"./chunk-4XSQBLXM.js";import{APP_NAME}from"./chunk-463OK2Y4.js";import{randomUUID}from"node:crypto";import{mkdir,readdir,readFile,rename,rm,stat,writeFile}from"node:fs/promises";import{dirname,join}from"node:path";var InvalidScheduledJobError=class extends Error{constructor(message){super(message),this.name="InvalidScheduledJobError"}};function isRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function requireString(raw,key){let value=raw[key];if(typeof value!="string"||value.length===0)throw new InvalidScheduledJobError(`scheduled job field "${key}" must be a non-empty string`);return value}function requireCount(raw,key){let value=raw[key];if(typeof value!="number"||!Number.isSafeInteger(value)||value<0)throw new InvalidScheduledJobError(`scheduled job field "${key}" must be a non-negative integer`);return value}function nullableCount(raw,key){return raw[key]===null||raw[key]===void 0?null:requireCount(raw,key)}function nullableString(raw,key){let value=raw[key];if(value==null)return null;if(typeof value!="string")throw new InvalidScheduledJobError(`scheduled job field "${key}" must be a string`);return value}function parseScheduledJob(raw){if(!isRecord(raw))throw new InvalidScheduledJobError("scheduled job must be a JSON object");if(raw.version!==1)throw new InvalidScheduledJobError(`unsupported scheduled job version: ${JSON.stringify(raw.version)}`);let id=requireString(raw,"id");if(!/^sch_[a-z0-9]{12}$/.test(id))throw new InvalidScheduledJobError(`invalid scheduled job id: ${id}`);let everyMs=nullableCount(raw,"everyMs");if(everyMs!==null&&everyMs<60*1e3)throw new InvalidScheduledJobError("scheduled job recurrence must be at least 60s");if(everyMs!==null&&everyMs>316224e5)throw new InvalidScheduledJobError("scheduled job recurrence must be at most 366 days");let prompt=requireString(raw,"prompt");if(Buffer.byteLength(prompt,"utf8")>16384)throw new InvalidScheduledJobError("scheduled job prompt exceeds 16384 bytes");let createdAt=requireCount(raw,"createdAt"),dueAt=requireCount(raw,"dueAt");return{version:1,id,sessionId:requireString(raw,"sessionId"),sessionFile:nullableString(raw,"sessionFile"),cwd:requireString(raw,"cwd"),prompt,createdAt,dueAt,everyMs,fireCount:requireCount(raw,"fireCount"),lastFiredAt:nullableCount(raw,"lastFiredAt"),lastError:nullableString(raw,"lastError")}}function nextRecurringDueAt(dueAt,everyMs,now){if(dueAt>now)return dueAt;let missed=Math.floor((now-dueAt)/everyMs)+1;return dueAt+missed*everyMs}function formatScheduledMessage(job,firedAt){let recurrence=job.everyMs===null?"":`, repeats every ${Math.round(job.everyMs/1e3)}s`;return`[Scheduled prompt ${job.id}: created ${new Date(job.createdAt).toISOString()}, due ${new Date(job.dueAt).toISOString()}, fired ${new Date(firedAt).toISOString()}${recurrence}]
|
|
3
|
+
${job.prompt}`}var STATE_DIRS=["pending","firing","failed"],JOB_ID=/^sch_[a-z0-9]{12}$/,RECORD_FILE=/^(sch_[a-z0-9]{12})(?:@(\d+)(?:~(\d+)-(\d+))?)?\.json$/;function scheduleDir(agentDir){return join(agentDir,"schedule")}function isScheduledJobId(id){return JOB_ID.test(id)}function isFileSystemError(error,code){return error instanceof Error&&"code"in error&&error.code===code}async function ensureDir(dir){await mkdir(dir,{recursive:!0,mode:448})}async function writeAtomic(filePath,contents){await ensureDir(dirname(filePath));let tempPath=join(dirname(filePath),`.schedule-${randomUUID()}.tmp`);try{await writeFile(tempPath,contents,{encoding:"utf8",mode:384}),await rename(tempPath,filePath)}catch(error){throw await rm(tempPath,{force:!0}),error}}function serialize(job){return`${JSON.stringify(job,null,2)}
|
|
4
|
+
`}async function readJobFile(path,expectedId){if((await stat(path)).size>65536)throw new InvalidScheduledJobError(`scheduled job file exceeds ${65536} bytes`);let parsed;try{parsed=JSON.parse(await readFile(path,"utf8"))}catch(error){throw isFileSystemError(error,"ENOENT")?error:new InvalidScheduledJobError("scheduled job file is not valid JSON")}let job=parseScheduledJob(parsed);if(job.id!==expectedId)throw new InvalidScheduledJobError(`scheduled job id ${job.id} does not match its file`);return job}async function listScheduledJobs(dir){let jobs=[],invalid=[];for(let state of STATE_DIRS){let names;try{names=await readdir(join(dir,state))}catch(error){if(isFileSystemError(error,"ENOENT"))continue;throw error}for(let name of names.sort()){let match=RECORD_FILE.exec(name);if(match===null)continue;let[,id,occurrence,pid,startedAt]=match,file=join(state,name);if(!(state==="pending"?occurrence===void 0:state==="firing"?pid!==void 0:occurrence!==void 0&&pid===void 0)||id===void 0){invalid.push({state,file,error:`unexpected record name for ${state}/`});continue}try{let job=await readJobFile(join(dir,file),id);jobs.push({state,job,file,...occurrence===void 0?{}:{occurrence:Number(occurrence)},...pid===void 0||startedAt===void 0?{}:{owner:{pid:Number(pid),processStartedAtMs:Number(startedAt)}}})}catch(error){if(isFileSystemError(error,"ENOENT"))continue;invalid.push({state,file,error:error instanceof Error?error.message:String(error)})}}}return jobs.sort((a,b)=>a.job.dueAt-b.job.dueAt),{jobs,invalid}}async function createScheduledJob(dir,input,now){let job=parseScheduledJob({version:1,id:`sch_${randomUUID().replace(/-/g,"").slice(0,12)}`,...input,createdAt:now,fireCount:0,lastFiredAt:null});return await writeAtomic(join(dir,"pending",`${job.id}.json`),serialize(job)),job}function tombstonePath(dir,id){return join(dir,"cancelled",id)}async function isCancelled(dir,id){try{return await stat(tombstonePath(dir,id)),!0}catch(error){if(isFileSystemError(error,"ENOENT"))return!1;throw error}}function runnersDir(dir){return join(dir,"runners")}import{randomUUID as randomUUID2}from"node:crypto";import{link,readdir as readdir2,rename as rename2,rm as rm2,stat as stat2,writeFile as writeFile2}from"node:fs/promises";import{join as join2}from"node:path";var TOMBSTONE_RETENTION_MS=1440*60*1e3;async function cancelScheduledJob(dir,id,options={}){if(!isScheduledJobId(id))return;let records=(await listScheduledJobs(dir)).jobs.filter(record=>record.job.id===id),representative=records.find(record=>record.state==="pending")??records[0];if(representative===void 0||options.sessionId!==void 0&&representative.job.sessionId!==options.sessionId)return;await writeAtomic(tombstonePath(dir,id),`${new Date().toISOString()}
|
|
5
|
+
`);let inFlight=(await occurrenceNumbers(dir,"firing",id)).length>0;await rm2(join2(dir,"pending",`${id}.json`),{force:!0});let failed=records.filter(record=>record.state==="failed");for(let record of failed)await rm2(join2(dir,record.file),{force:!0});return{job:representative.job,inFlight,removedFailed:failed.length}}function occurrenceFile(id,occurrence,owner){return join2("firing",`${id}@${occurrence}~${owner.pid}-${owner.processStartedAtMs}.json`)}async function restorePending(dir,record,id){let pending=join2(dir,"pending",`${id}.json`);try{await link(join2(dir,record),pending)}catch(error){if(!isFileSystemError(error,"EEXIST"))throw error}await rm2(join2(dir,record),{force:!0}),await isCancelled(dir,id)&&await rm2(pending,{force:!0})}async function claimOccurrence(dir,job,owner){let record=occurrenceFile(job.id,job.fireCount+1,owner);await ensureDir(join2(dir,"firing"));try{await rename2(join2(dir,"pending",`${job.id}.json`),join2(dir,record))}catch(error){if(isFileSystemError(error,"ENOENT"))return;throw error}if(await isCancelled(dir,job.id)){await rm2(join2(dir,record),{force:!0});return}if((await readJobFile(join2(dir,record),job.id)).fireCount!==job.fireCount){await restorePending(dir,record,job.id);return}return record}async function rearmRecurringJob(dir,next){if(await isCancelled(dir,next.id))return;let path=join2(dir,"pending",`${next.id}.json`);await writeAtomic(path,serialize(next)),await isCancelled(dir,next.id)&&await rm2(path,{force:!0})}async function occurrenceNumbers(dir,state,id){let names;try{names=await readdir2(join2(dir,state))}catch(error){if(isFileSystemError(error,"ENOENT"))return[];throw error}let prefix=`${id}@`;return names.filter(name=>name.startsWith(prefix)).map(name=>Number.parseInt(name.slice(prefix.length),10)).filter(occurrence=>Number.isSafeInteger(occurrence))}async function restoreAbandonedSchedule(dir,job,occurrence,now){if(job.everyMs===null||await isCancelled(dir,job.id))return;let pending=join2(dir,"pending",`${job.id}.json`);if(await stat2(pending).then(()=>!0,()=>!1)||[...await occurrenceNumbers(dir,"firing",job.id),...await occurrenceNumbers(dir,"failed",job.id)].some(n=>n>occurrence))return;let next={...job,fireCount:occurrence,dueAt:nextRecurringDueAt(job.dueAt,job.everyMs,now),lastError:null};await ensureDir(join2(dir,"pending"));let temp=join2(dir,"pending",`.schedule-${randomUUID2()}.tmp`);try{await writeFile2(temp,serialize(next),{encoding:"utf8",mode:384}),await link(temp,pending)}catch(error){if(!isFileSystemError(error,"EEXIST"))throw error;return}finally{await rm2(temp,{force:!0})}if(await isCancelled(dir,job.id)){await rm2(pending,{force:!0});return}return next}async function settleOccurrence(dir,record,job,occurrence,outcome){if(!outcome.ok&&!await isCancelled(dir,job.id)){let failed=join2(dir,"failed",`${job.id}@${occurrence}.json`);await writeAtomic(failed,serialize({...job,lastError:outcome.error})),await isCancelled(dir,job.id)&&await rm2(failed,{force:!0});let older=(await occurrenceNumbers(dir,"failed",job.id)).sort((a,b)=>b-a);for(let stale of older.slice(10))await rm2(join2(dir,"failed",`${job.id}@${stale}.json`),{force:!0})}await rm2(join2(dir,record),{force:!0})}async function pruneTombstones(dir,listing,now){let names;try{names=await readdir2(join2(dir,"cancelled"))}catch(error){if(isFileSystemError(error,"ENOENT"))return;throw error}let live=new Set(listing.jobs.filter(record=>record.state!=="failed").map(record=>record.job.id));for(let id of names){if(!isScheduledJobId(id)||live.has(id))continue;let info=await stat2(tombstonePath(dir,id)).catch(()=>{});info!==void 0&&now-info.mtimeMs>TOMBSTONE_RETENTION_MS&&await rm2(tombstonePath(dir,id),{force:!0})}}import{mkdir as mkdir2,readdir as readdir3,stat as stat4}from"node:fs/promises";import{join as join3}from"node:path";import{randomUUID as randomUUID3}from"node:crypto";import{link as link2,open,readFile as readFile3,rename as rename3,stat as stat3,unlink}from"node:fs/promises";import{execFile}from"node:child_process";import{readFile as readFile2}from"node:fs/promises";var LINUX_CLOCK_TICKS_PER_SECOND=100;async function linuxProcessStartMs(pid){let[stat5,systemStat]=await Promise.all([readFile2(`/proc/${pid}/stat`,"utf8"),readFile2("/proc/stat","utf8")]),afterComm=stat5.slice(stat5.lastIndexOf(")")+2).split(" "),startTicks=Number(afterComm[19]),bootSeconds=Number(/^btime (\d+)/m.exec(systemStat)?.[1]);if(!(!Number.isFinite(startTicks)||!Number.isFinite(bootSeconds)))return Math.round((bootSeconds+startTicks/LINUX_CLOCK_TICKS_PER_SECOND)*1e3)}function execText(command,args,env){return new Promise((resolve,reject)=>{execFile(command,[...args],{encoding:"utf8",timeout:5e3,windowsHide:!0,...env===void 0?{}:{env}},(error,stdout)=>{error?reject(error):resolve(stdout)})})}async function darwinProcessStartMs(pid){let text=(await execText("ps",["-o","lstart=","-p",String(pid)],{...process.env,LC_ALL:"C",LANG:"C"})).trim();if(text.length!==0)return processStartTimeMs(text)}async function windowsProcessStartMs(pid){let script=`(Get-Process -Id ${pid} -ErrorAction Stop).StartTime.ToUniversalTime().ToString('o')`,text=(await execText("powershell",["-NoProfile","-NonInteractive","-Command",script])).trim();return processStartTimeMs(text)}async function readProcessStartMs(pid){try{switch(process.platform){case"linux":return await linuxProcessStartMs(pid);case"darwin":return await darwinProcessStartMs(pid);case"win32":return await windowsProcessStartMs(pid);default:return}}catch{return}}function errorCode(error){if(typeof error=="object"&&error!==null&&"code"in error&&typeof error.code=="string")return error.code}async function unlinkIfPresent(path){try{await unlink(path)}catch(error){if(errorCode(error)!=="ENOENT")throw error}}async function readLeaseText(path){try{return await readFile3(path,"utf8")}catch(error){if(errorCode(error)==="ENOENT")return;throw error}}async function writeTemp(path,content,mode){let temp=`${path}.${process.pid}.${randomUUID3().slice(0,8)}.tmp`,file=await open(temp,"wx",mode);try{await file.writeFile(content,"utf8")}finally{await file.close()}return temp}async function publishExclusive(path,content,options={}){let temp=await writeTemp(path,content,options.mode);try{await link2(temp,path)}catch(error){let code=errorCode(error);if(code!=="ENOTSUP"&&code!=="EOPNOTSUPP"&&code!=="EPERM")throw error;let file=await open(path,"wx",options.mode);try{await file.writeFile(content,"utf8")}finally{await file.close()}}finally{await unlinkIfPresent(temp)}}async function publishReplace(path,content,options={}){let temp=await writeTemp(path,content,options.mode);try{await rename3(temp,path)}catch(error){throw await unlinkIfPresent(temp),error}}function pidAlive(pid){try{return process.kill(pid,0),!0}catch(error){return errorCode(error)==="EPERM"}}var UNREADABLE_LOCK_STALE_MS=3e4;function readLockHolder(raw){try{let parsed=JSON.parse(raw);if(typeof parsed!="object"||parsed===null||!("pid"in parsed)||!("bootAtMs"in parsed)||!("processStartedAtMs"in parsed))return;let{pid,bootAtMs,processStartedAtMs}=parsed;return typeof pid!="number"||typeof bootAtMs!="number"||typeof processStartedAtMs!="number"?void 0:{pid,bootAtMs,processStartedAtMs}}catch{return}}async function reclaimLockState(lock,probes={}){let raw=await readLeaseText(lock);if(raw===void 0)return{state:"free"};let holder=readLockHolder(raw);if(holder===void 0)return await stat3(lock).then(info=>Date.now()-info.mtimeMs,()=>0)>UNREADABLE_LOCK_STALE_MS?{state:"stale",raw}:{state:"held"};if(!sameBoot(holder.bootAtMs,processBootAtMs()))return{state:"stale",raw};if(holder.pid===process.pid)return sameProcessStartMs(holder.processStartedAtMs,ownProcessStartedAtMs())?{state:"held",holder}:{state:"stale",raw};if(!(probes.isProcessAlive??pidAlive)(holder.pid))return{state:"stale",raw};let observed=await(probes.readProcessStartMs??readProcessStartMs)(holder.pid).catch(()=>{});return observed===void 0||sameProcessStartMs(holder.processStartedAtMs,observed)?{state:"held",holder}:{state:"stale",raw}}async function breakStaleLock(lock,raw){let aside=`${lock}.${process.pid}.${randomUUID3().slice(0,8)}.broken`;try{await rename3(lock,aside)}catch(error){if(errorCode(error)==="ENOENT")return;throw error}let moved=await readFile3(aside,"utf8");if(moved!==raw)try{await publishExclusive(lock,moved)}catch(error){if(errorCode(error)!=="EEXIST")throw error}await unlinkIfPresent(aside)}async function takeReclaimLock(lock,probes){let mine=JSON.stringify({pid:process.pid,bootAtMs:processBootAtMs(),processStartedAtMs:ownProcessStartedAtMs()});for(let attempt=0;attempt<3;attempt+=1){try{return await publishExclusive(lock,mine),mine}catch(error){if(errorCode(error)!=="EEXIST")throw error}let seen=await reclaimLockState(lock,probes);if(seen.state==="held")return{holder:seen.holder};seen.state==="stale"&&await breakStaleLock(lock,seen.raw)}return{}}async function reclaimInspected(path,inspected,probes={}){let lock=`${path}.lock`,taken=await takeReclaimLock(lock,probes);if(typeof taken!="string")return{outcome:"busy",...taken.holder?{holder:taken.holder}:{}};try{return await readLeaseText(path)!==inspected?{outcome:"changed"}:(await unlinkIfPresent(path),{outcome:"removed"})}finally{await readLeaseText(lock)===taken&&await unlinkIfPresent(lock)}}var RUNNER_HEARTBEAT_STALE_MS=12e4,RUNNER_HEARTBEAT_INTERVAL_MS=3e4,DEFAULT_MAX_DELIVERY_MS=9e5,PRIVATE={mode:384};function ownRunnerIdentity(){return{pid:process.pid,processStartedAtMs:ownProcessStartedAtMs()}}function leasePath(dir,pid){return join3(runnersDir(dir),`${pid}.json`)}async function writeRunnerLease(dir,lease,now){await mkdir2(runnersDir(dir),{recursive:!0,mode:448});let identity=ownRunnerIdentity();await publishReplace(leasePath(dir,identity.pid),JSON.stringify({...identity,bootAtMs:processBootAtMs(),beatAt:now,...lease}),PRIVATE)}async function removeRunnerLease(dir){await unlinkIfPresent(leasePath(dir,process.pid))}function parseLease(raw){try{let parsed=JSON.parse(raw);if(typeof parsed!="object"||parsed===null)return;let beatAt="beatAt"in parsed?parsed.beatAt:void 0;if(typeof beatAt!="number")return;let watch="watch"in parsed&&parsed.watch===!0,exec="exec"in parsed&&typeof parsed.exec=="string"?parsed.exec:null;return{beatAt,watch,exec}}catch{return}}async function liveRunners(dir){let names;try{names=await readdir3(runnersDir(dir))}catch(error){if(error instanceof Error&&"code"in error&&error.code==="ENOENT")return[];throw error}let runners=[];for(let name of names){if(!/^\d+\.json$/.test(name))continue;let path=join3(runnersDir(dir),name),state=await reclaimLockState(path);if(state.state==="stale"&&await breakStaleLock(path,state.raw),state.state!=="held"||state.holder===void 0)continue;let raw=await readLeaseText(path),lease=raw===void 0?void 0:parseLease(raw);lease!==void 0&&runners.push({pid:state.holder.pid,processStartedAtMs:state.holder.processStartedAtMs,...lease})}return runners}async function isWatchRunnerAvailable(dir,now){return(await liveRunners(dir)).some(runner=>runner.watch&&now-runner.beatAt<=RUNNER_HEARTBEAT_STALE_MS)}function isOwnerAmong(owner,runners){return runners.some(runner=>runner.pid===owner.pid&&sameProcessStartMs(runner.processStartedAtMs,owner.processStartedAtMs))}function sessionLockPath(dir,sessionId){return join3(dir,"sessions",`${encodeURIComponent(sessionId)}.lock`)}function isDeliveryGroupAlive(pid){try{return process.kill(process.platform==="win32"?pid:-pid,0),!0}catch(error){return errorCode(error)==="EPERM"}}function isPidAlive(pid){try{return process.kill(pid,0),!0}catch(error){return errorCode(error)==="EPERM"}}async function orphanedDelivery(raw,lockAgeMs,probes){let parsed;try{parsed=JSON.parse(raw)}catch{return}if(typeof parsed!="object"||parsed===null)return;let field=key=>key in parsed?Reflect.get(parsed,key):void 0,boot=field("bootAtMs");if(typeof boot!="number"||!sameBoot(boot,processBootAtMs()))return;let pid=field("deliveryPid"),startedAt=field("deliveryStartedAtMs");if(typeof pid!="number"||typeof startedAt!="number"){let maxDeliveryMs=field("maxDeliveryMs"),runner=field("pid");return field("gated")===!1&&typeof maxDeliveryMs=="number"&&lockAgeMs<=maxDeliveryMs&&typeof runner=="number"?runner:void 0}if(!isDeliveryGroupAlive(pid))return;if(!isPidAlive(pid))return pid;let leaderStart=await(probes.readProcessStartMs??readProcessStartMs)(pid).catch(()=>{});return leaderStart!==void 0&&sameProcessStartMs(startedAt,leaderStart)?pid:void 0}async function acquireSessionDeliveryLock(dir,sessionId,options={}){let probes=options,path=sessionLockPath(dir,sessionId),identity={pid:process.pid,bootAtMs:processBootAtMs(),processStartedAtMs:ownProcessStartedAtMs(),gated:options.gated??process.platform!=="win32",maxDeliveryMs:options.maxDeliveryMs??DEFAULT_MAX_DELIVERY_MS},mine=JSON.stringify(identity);for(let attempt=0;attempt<3;attempt+=1){try{await publishExclusive(path,mine,PRIVATE);let tail=Promise.resolve(),serialized=operation=>{let run=tail.then(operation);return tail=run.catch(()=>{}),run};return{acquired:!0,attachDelivery:pid=>serialized(async()=>{let startedAt=Math.floor(Date.now()/1e3)*1e3;if(await readLeaseText(path)!==mine)throw new Error("session delivery lock was lost");let next=JSON.stringify({...identity,deliveryPid:pid,deliveryStartedAtMs:startedAt});await publishReplace(path,next,PRIVATE),mine=next}),release:()=>serialized(async()=>{await readLeaseText(path)===mine&&await unlinkIfPresent(path)})}}catch(error){let code=errorCode(error);if(code==="ENOENT"){await mkdir2(join3(dir,"sessions"),{recursive:!0,mode:448});continue}if(code!=="EEXIST")throw error}let state=await reclaimLockState(path);if(state.state==="held")return{acquired:!1,heldByPid:state.holder?.pid};if(state.state==="stale"){let lockAgeMs=await stat4(path).then(info=>Date.now()-info.mtimeMs,()=>0),delivering=await orphanedDelivery(state.raw,lockAgeMs,probes);if(delivering!==void 0)return{acquired:!1,heldByPid:delivering};await breakStaleLock(path,state.raw)}}return{acquired:!1,heldByPid:void 0}}import{randomUUID as randomUUID5}from"node:crypto";import{existsSync,mkdirSync,readFileSync,renameSync,rmdirSync,statSync,unlinkSync,writeFileSync}from"node:fs";import{readdir as readdir4}from"node:fs/promises";import{dirname as dirname3,join as join5}from"node:path";var SessionHeldError=class extends Error{constructor(sessionFile,holders){let who=holders.map(h=>h.cwd?`pid ${h.pid} in ${h.cwd}`:`pid ${h.pid}`).join("; ");super(`This session is open in another ${APP_NAME} process (${who}). Quit it there, then try again.`),this.code="ESESSIONHELD",this.name="SessionHeldError",this.sessionFile=sessionFile,this.holders=holders}},SessionMovingError=class extends Error{constructor(sessionFile,moverPid){let who=moverPid===void 0?"another process":`another process (pid ${moverPid})`;super(`Session ${sessionFile} is being moved by ${who}. Try again in a moment.`),this.code="ESESSIONMOVING",this.name="SessionMovingError",this.moverPid=moverPid}},SessionMovedError=class extends Error{constructor(sessionFile){super(`Session ${sessionFile} no longer exists: another process moved it. Resume it from its new location.`),this.code="ESESSIONMOVED",this.name="SessionMovedError"}};import{randomUUID as randomUUID4}from"node:crypto";import{mkdir as mkdir3,readFile as readFile4,rename as rename4,rm as rm3,writeFile as writeFile3}from"node:fs/promises";import{dirname as dirname2,join as join4}from"node:path";var InvalidSidecarStoreError=class extends Error{constructor(message,options){super(message,options),this.name="InvalidSidecarStoreError"}},UnsupportedSidecarStoreVersionError=class extends Error{constructor(message){super(message),this.name="UnsupportedSidecarStoreVersionError"}},mutationTails=new Map,snapshots=new Map;function encodedSessionId(sessionId){return encodeURIComponent(sessionId)}function sidecarFilePath(ref){return join4(ref.baseDir,`${encodedSessionId(ref.sessionId)}.json`)}function createSidecarStore(options){let ref={baseDir:options.baseDir,sessionId:options.sessionId},filePath=sidecarFilePath(ref);async function read(){let raw;try{raw=await readFile4(filePath,"utf8")}catch(error){if(isFileSystemError2(error,"ENOENT"))return null;throw error}let state=parsePayload(raw,options,ref);return snapshots.set(filePath,state),state}async function write(state){await mkdir3(dirname2(filePath),{recursive:!0}),await writeAtomic2(filePath,`${JSON.stringify(state,null,2)}
|
|
6
|
+
`,options.tempPrefix),snapshots.set(filePath,state)}function mutate(fn){return serializeByKey(filePath,async()=>{let next=await fn(await read());return await write(next),next})}return{filePath,read,write,mutate,snapshot:()=>snapshots.get(filePath),clear:()=>{snapshots.delete(filePath)}}}async function writeAtomic2(filePath,contents,tempPrefix){let tempPath=join4(dirname2(filePath),`.${tempPrefix}-${randomUUID4()}.tmp`);try{await writeFile3(tempPath,contents,{encoding:"utf8",mode:384}),await rename4(tempPath,filePath)}catch(error){try{await rm3(tempPath,{force:!0})}catch(cleanupError){throw new AggregateError([error,cleanupError],"sidecar store write failed and its temporary file could not be removed")}throw error}}function parsePayload(raw,options,ref){let parsed;try{parsed=JSON.parse(raw)}catch(error){throw new InvalidSidecarStoreError("sidecar store contains unparseable JSON",{cause:error})}if(!isRecord2(parsed))throw new InvalidSidecarStoreError("sidecar store must be a JSON object");if(parsed.version!==options.version)throw new UnsupportedSidecarStoreVersionError(`unsupported sidecar store version: ${JSON.stringify(parsed.version)} (expected ${options.version})`);if(typeof parsed.sessionId!="string"||parsed.sessionId.length===0)throw new InvalidSidecarStoreError("sidecar store is missing a sessionId");if(parsed.sessionId!==ref.sessionId)throw new InvalidSidecarStoreError(`sidecar store sessionId ${parsed.sessionId} does not match the session it was loaded for`);return options.parse(parsed,ref)}function serializeByKey(key,operation){let run=(mutationTails.get(key)??Promise.resolve()).then(operation),tail=run.then(()=>{},()=>{});return mutationTails.set(key,tail),tail.then(()=>{mutationTails.get(key)===tail&&mutationTails.delete(key)}),run}function isRecord2(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function isFileSystemError2(error,code){return error instanceof Error&&"code"in error&&error.code===code}var HOLDERS_DIR="session-holders",MOVE_LOCK="move.lock",HOLDER_RECORD=/^\d+\.json$/,MOVE_LOCK_STALE_MS=3e4,DEFAULT_MOVE_LOCK_WAIT_MS=5e3,MOVE_LOCK_RETRY_MS=100;function holdersDir(sessionFile,sessionId){return join5(dirname3(resolveMovedPath(sessionFile)),HOLDERS_DIR,encodedSessionId(sessionId))}function identityRecord(cwd){return JSON.stringify({pid:process.pid,bootAtMs:processBootAtMs(),processStartedAtMs:ownProcessStartedAtMs(),...cwd===void 0?{}:{cwd}})}function unlinkIfPresentSync(path){try{unlinkSync(path)}catch(error){if(errorCode(error)!=="ENOENT")throw error}}function removeDirIfEmpty(dir){try{rmdirSync(dir)}catch(error){let code=errorCode(error);if(code!=="ENOENT"&&code!=="ENOTEMPTY"&&code!=="EEXIST")throw error}}var holderRecordRefCounts=new Map,exitCleanupInstalled=!1;function installExitCleanup(){exitCleanupInstalled||(exitCleanupInstalled=!0,process.once("exit",()=>{for(let record of holderRecordRefCounts.keys())unlinkIfPresentSync(record)}))}function pidAlive2(pid){try{return process.kill(pid,0),!0}catch(error){return errorCode(error)==="EPERM"}}function activeMover(lock){let raw,ageMs;try{raw=readFileSync(lock,"utf8"),ageMs=Date.now()-statSync(lock).mtimeMs}catch(error){if(errorCode(error)==="ENOENT")return;throw error}if(ageMs>MOVE_LOCK_STALE_MS)return;let pid=parsePid(raw);return pid===void 0?{pid}:pid===process.pid||pidAlive2(pid)?{pid}:void 0}function parsePid(raw){try{let parsed=JSON.parse(raw);return typeof parsed!="object"||parsed===null||!("pid"in parsed)?void 0:typeof parsed.pid=="number"?parsed.pid:void 0}catch(error){if(error instanceof SyntaxError)return;throw error}}function parseCwd(raw){let parsed=JSON.parse(raw);if(!(typeof parsed!="object"||parsed===null||!("cwd"in parsed)))return typeof parsed.cwd=="string"?parsed.cwd:void 0}function holdSessionFile(sessionFile,sessionId,options){let dir=holdersDir(sessionFile,sessionId),record=join5(dir,`${process.pid}.json`),shared=holderRecordRefCounts.get(record)??0;shared===0&&(publishHolderRecord(dir,record,identityRecord(options.cwd)),installExitCleanup()),holderRecordRefCounts.set(record,shared+1);let released=!1,release=()=>{if(released)return;released=!0;let left=(holderRecordRefCounts.get(record)??1)-1;if(left>0){holderRecordRefCounts.set(record,left);return}holderRecordRefCounts.delete(record),unlinkIfPresentSync(record),removeDirIfEmpty(dir)},mover=activeMover(join5(dir,MOVE_LOCK));if(mover!==void 0)throw release(),new SessionMovingError(sessionFile,mover.pid);if(options.expectExisting&&!existsSync(resolveMovedPath(sessionFile)))throw release(),new SessionMovedError(sessionFile);return{release}}function publishHolderRecord(dir,record,content){for(let attempt=0;;attempt+=1){mkdirSync(dir,{recursive:!0});let temp=`${record}.${randomUUID5().slice(0,8)}.tmp`;try{writeFileSync(temp,content),renameSync(temp,record);return}catch(error){if(errorCode(error)!=="ENOENT"||attempt>0)throw error}}}async function liveHolders(dir,probes={}){let holders=[];for(let name of await readdir4(dir)){if(!HOLDER_RECORD.test(name))continue;let path=join5(dir,name),state=await reclaimLockState(path,probes);if(state.state==="stale"&&await breakStaleLock(path,state.raw),state.state!=="held"||state.holder===void 0)continue;let raw=await readLeaseText(path);holders.push({pid:state.holder.pid,cwd:raw===void 0?void 0:parseCwd(raw)})}return holders}async function liveSessionHolders(sessionFile,sessionId,probes={}){try{return await liveHolders(holdersDir(sessionFile,sessionId),probes)}catch(error){if(errorCode(error)==="ENOENT")return[];throw error}}async function takeMoveLock(sessionFile,lock,waitMs){let mine=identityRecord(),deadline=Date.now()+waitMs;for(;;){try{return await publishExclusive(lock,mine),mine}catch(error){let code=errorCode(error);if(code==="ENOENT"){mkdirSync(dirname3(lock),{recursive:!0});continue}if(code!=="EEXIST")throw error}let state=await reclaimLockState(lock);if(state.state==="stale"){await breakStaleLock(lock,state.raw);continue}if(state.state!=="free"){if(Date.now()>=deadline)throw new SessionMovingError(sessionFile,state.holder?.pid);await new Promise(resolve=>setTimeout(resolve,MOVE_LOCK_RETRY_MS))}}}async function withSessionMoveLock(sessionFile,sessionId,move,options={}){let dir=holdersDir(sessionFile,sessionId),lock=join5(dir,MOVE_LOCK),mine=await takeMoveLock(sessionFile,lock,options.waitMs??DEFAULT_MOVE_LOCK_WAIT_MS);try{let holders=await liveHolders(dir);if(holders.length>0)throw new SessionHeldError(sessionFile,holders);return await move()}finally{await readLeaseText(lock)===mine&&await unlinkIfPresent(lock),removeDirIfEmpty(dir)}}export{InvalidSidecarStoreError,UnsupportedSidecarStoreVersionError,encodedSessionId,sidecarFilePath,createSidecarStore,serializeByKey,nextRecurringDueAt,formatScheduledMessage,scheduleDir,readJobFile,listScheduledJobs,createScheduledJob,isCancelled,cancelScheduledJob,restorePending,claimOccurrence,rearmRecurringJob,restoreAbandonedSchedule,settleOccurrence,pruneTombstones,readProcessStartMs,errorCode,unlinkIfPresent,readLeaseText,publishExclusive,publishReplace,reclaimLockState,breakStaleLock,reclaimInspected,RUNNER_HEARTBEAT_STALE_MS,RUNNER_HEARTBEAT_INTERVAL_MS,ownRunnerIdentity,writeRunnerLease,removeRunnerLease,liveRunners,isWatchRunnerAvailable,isOwnerAmong,acquireSessionDeliveryLock,holdSessionFile,liveSessionHolders,withSessionMoveLock};
|