@ai-agent-forge/agent-forge 0.85.8 → 0.85.10
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 +12 -0
- package/dist/bundle/.build-manifest.json +7 -7
- package/dist/bundle/chunks/{chunk-BTBDSCF4.js → chunk-UO4LZHZN.js} +3 -3
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/cli/plugin-command.d.ts +3 -1
- package/dist/cli/plugin-command.d.ts.map +1 -1
- package/dist/cli/plugin-command.js +14 -2
- package/dist/cli/plugin-command.js.map +1 -1
- package/dist/plugins/ecosystem/bootstrap-factory-manifest.d.ts.map +1 -1
- package/dist/plugins/ecosystem/bootstrap-factory-manifest.js +6 -0
- package/dist/plugins/ecosystem/bootstrap-factory-manifest.js.map +1 -1
- package/dist/profile/plugin-profiles.d.ts +1 -1
- package/dist/profile/plugin-profiles.d.ts.map +1 -1
- package/dist/profile/plugin-profiles.js +1 -0
- package/dist/profile/plugin-profiles.js.map +1 -1
- package/package.json +1 -1
|
@@ -505,7 +505,7 @@ File: ${path15}`)}let config=parsed,providers=new Map;for(let[providerId,provide
|
|
|
505
505
|
`)}if(typeof data.profileId=="string"){let selected=Array.isArray(data.selectedPluginIds)?` selected=${data.selectedPluginIds.join(",")}`:"",disabled=Array.isArray(data.disabledPluginIds)?` disabled=${data.disabledPluginIds.join(",")}`:"";return`${status2}: ${command} profile:${data.profileId}${selected}${disabled}`}return`${status2}: ${command}`}function safeError(code){return Object.freeze({code,message:{invalid_command:"The plugin ecosystem command is invalid",unsupported_dependencies:"The plugin ecosystem operation is unavailable on this host",not_found:"The requested plugin was not found",not_installed:"The requested plugin is not installed",registry_failed:"The plugin registry operation failed",acquisition_failed:"The plugin package acquisition failed",distribution_failed:"The plugin distribution operation failed",incompatible:"The requested plugin is incompatible with this host",already_installed:"This plugin version is already installed in the requested scope",installer_failed:"The plugin installer operation failed",uninstall_failed:"The host plugin uninstall operation failed",state_failed:"The plugin state operation failed",selection_failed:"The plugin selection operation failed",cancelled:"Plugin ecosystem operation was cancelled"}[code]})}function invalidCommandError(argv,cause){let genericCauses=new Set(["ecosystem command is invalid","ecosystem command has unsupported arguments"]),causeMessage=cause instanceof Error?cause.message:void 0,reason=causeMessage!==void 0&&!genericCauses.has(causeMessage)?` (${causeMessage})`:"";return Object.freeze({code:"invalid_command",message:`The plugin ecosystem command is invalid: received argv [${argv.join(" ")}]${reason}; valid commands: ${PLUGIN_ECOSYSTEM_CLI_COMMAND_USAGE_V1}`})}function isCancelled(signal){return signal?.aborted===!0}function stateStoreOf(options,scope){return scope==="project"?options.projectStateStore:options.stateStore??options.stateHost}function operationScope(scope){return scope??"global"}function scopeRefOf(options,scope){return scope==="global"?DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1:options.projectScopeRef}function installerSupportsScope(installer,scope){return installer?.supportedScopes?.includes(scope)===!0}function selectionStoreOf(options,scope){return scope==="project"?options.projectSelectionStore:options.selectionStore??options.selectionHost}function stateEntry(record){return Object.freeze({pluginId:record.pluginId,pluginVersion:record.pluginVersion,manifestDigest:record.manifestDigest,scope:record.state.scope,scopeRef:record.state.scopeRef,enabled:record.state.enabled,lifecycle:record.state.lifecycle,...record.source===void 0?{}:{source:record.source}})}function selectionEntry(selection){return Object.freeze({profileId:selection.profileId,selectedPluginIds:Object.freeze([...selection.selectedPluginIds]),disabledPluginIds:Object.freeze([...selection.disabledPluginIds])})}function catalogEntry(entry){return Object.freeze({pluginId:entry.pluginId,pluginVersion:entry.pluginVersion,manifestDigest:entry.manifestDigest,status:entry.resolution.status,diagnosticCodes:Object.freeze(entry.resolution.diagnostics.map(item=>item.code).slice(0,16))})}function findStateRecord(records,pluginId,pluginVersion,scope,scopeRef){return records.find(record=>record.pluginId===pluginId&&(pluginVersion===void 0||record.pluginVersion===pluginVersion)&&(scope===void 0||record.state.scope===scope)&&(scopeRef===void 0||record.state.scopeRef===scopeRef))}function findCurrentStateRecord(records,pluginId,scope,scopeRef){return records.find(record=>record.pluginId===pluginId&&(scope===void 0||record.state.scope===scope)&&(scopeRef===void 0||record.state.scopeRef===scopeRef)&&record.state.lifecycle==="active")??findStateRecord(records,pluginId,void 0,scope,scopeRef)}function requireDependencies(options,scope,scopeRef){let requestedScope=operationScope(scope);if(!options.registry||!options.installer||scopeRef===void 0||!installerSupportsScope(options.installer,requestedScope)||!stateStoreOf(options,requestedScope)||!options.host)throw new Error("unsupported dependencies")}async function listManifests(options,signal){if(options.registry?.list)return await options.registry.list({signal});if(options.manifests)return options.manifests;throw new Error("unsupported dependencies")}function checkSignal(signal){if(isCancelled(signal))throw new Error("cancelled")}function createPluginEcosystemCliV1(options){let installTransactionTail=Promise.resolve();async function acquireInstallTransaction(){let release,turn=new Promise(resolve25=>{release=resolve25}),previous=installTransactionTail;return installTransactionTail=previous.then(()=>turn,()=>turn),await previous,release}async function execute(input){let parsed;try{parsed=parsePluginEcosystemCliCommandV1(input.argv,input.format??"text")}catch(error2){return response("invalid",input.format==="json"?"json":"text","failed",invalidCommandError(input.argv,error2))}let releaseInstallTransaction=parsed.command==="install"||parsed.command==="update"?await acquireInstallTransaction():void 0;try{let signal=input.signal,requestedScope=operationScope(parsed.scope),scopeRef=scopeRefOf(options,requestedScope);if(isCancelled(signal))return response(parsed.command,parsed.format,"cancelled",safeError("cancelled"));if(scopeRef===void 0)return response(parsed.command,parsed.format,"unsupported",safeError("unsupported_dependencies"));let phase="registry";try{if(parsed.command==="catalog-list"){if(!options.host)return response(parsed.command,parsed.format,"unsupported",safeError("unsupported_dependencies"));let manifests2=await listManifests(options,signal);checkSignal(signal);let snapshot2=buildPluginCatalogV1({manifests:manifests2,host:options.host,maxEntries:MAX_PLUGIN_ECOSYSTEM_CLI_LIST_ENTRIES_V1});return response(parsed.command,parsed.format,"succeeded",void 0,{version:snapshot2.version,entries:snapshot2.entries.map(catalogEntry),truncated:snapshot2.truncated})}if(parsed.command==="selection-list"){phase="selection";let selectionStore=selectionStoreOf(options,parsed.scope);if(!selectionStore)return response(parsed.command,parsed.format,"unsupported",safeError("unsupported_dependencies"));let result=await selectionStore.read({signal});return result.status==="cancelled"?response(parsed.command,parsed.format,"cancelled",safeError("cancelled")):result.status==="invalid"?response(parsed.command,parsed.format,"failed",safeError("selection_failed")):response(parsed.command,parsed.format,"succeeded",void 0,{version:result.snapshot.version,scope:parsed.scope??"global",entries:result.snapshot.selections.map(selectionEntry),truncated:!1})}if(parsed.command==="selection-set"){phase="selection";let selectionStore=selectionStoreOf(options,parsed.scope);if(!selectionStore)return response(parsed.command,parsed.format,"unsupported",safeError("unsupported_dependencies"));let selection;try{selection=createPluginSelectionV1({profileId:parsed.profileId,selectedPluginIds:parsed.selectedPluginIds??[],disabledPluginIds:[]})}catch{return response(parsed.command,parsed.format,"failed",safeError("selection_failed"))}let result=await selectionStore.set({selection,signal});return result.status==="cancelled"?response(parsed.command,parsed.format,"cancelled",safeError("cancelled")):result.status!=="ok"?response(parsed.command,parsed.format,"failed",safeError("selection_failed")):response(parsed.command,parsed.format,"succeeded",void 0,{profileId:selection.profileId,scope:parsed.scope??"global",selectedPluginIds:selection.selectedPluginIds,disabledPluginIds:selection.disabledPluginIds,changed:result.changed})}if(parsed.command==="selection-clear"){phase="selection";let selectionStore=selectionStoreOf(options,parsed.scope);if(!selectionStore)return response(parsed.command,parsed.format,"unsupported",safeError("unsupported_dependencies"));let result=await selectionStore.clear({profileId:parsed.profileId,signal});return result.status==="cancelled"?response(parsed.command,parsed.format,"cancelled",safeError("cancelled")):result.status!=="ok"?response(parsed.command,parsed.format,"failed",safeError("selection_failed")):response(parsed.command,parsed.format,"succeeded",void 0,{profileId:parsed.profileId,scope:parsed.scope??"global",changed:result.changed})}if(parsed.command==="state-list"){phase="state";let stateStore2=stateStoreOf(options,requestedScope);if(!stateStore2)return response(parsed.command,parsed.format,"unsupported",safeError("unsupported_dependencies"));let result=await stateStore2.read({signal});if(result.status==="cancelled")return response(parsed.command,parsed.format,"cancelled",safeError("cancelled"));if(result.status==="invalid")return response(parsed.command,parsed.format,"failed",safeError("state_failed"));let records=result.snapshot.records.filter(record=>record.state.scope===requestedScope&&record.state.scopeRef===scopeRef);return response(parsed.command,parsed.format,"succeeded",void 0,{version:result.snapshot.version,entries:records.map(stateEntry),truncated:!1})}if(parsed.command==="enable"||parsed.command==="disable"||parsed.command==="remove"){if(phase="state",parsed.command==="remove"&&requestedScope==="project"&&!installerSupportsScope(options.installer,requestedScope))return response(parsed.command,parsed.format,"unsupported",safeError("unsupported_dependencies"));let stateStore2=stateStoreOf(options,requestedScope);if(!stateStore2)return response(parsed.command,parsed.format,"unsupported",safeError("unsupported_dependencies"));let current=await stateStore2.read({signal});if(current.status==="cancelled")return response(parsed.command,parsed.format,"cancelled",safeError("cancelled"));if(current.status==="invalid")return response(parsed.command,parsed.format,"failed",safeError("state_failed"));let record=parsed.pluginVersion===void 0?findCurrentStateRecord(current.snapshot.records,parsed.pluginId,requestedScope,scopeRef):findStateRecord(current.snapshot.records,parsed.pluginId,parsed.pluginVersion,requestedScope,scopeRef);if(!record)return response(parsed.command,parsed.format,"failed",safeError("not_installed"));if(parsed.command==="remove"){if(options.installer!==void 0){let removedFromHost;try{removedFromHost=await options.installer.remove({installation:{version:1,pluginId:record.pluginId,pluginVersion:record.pluginVersion,manifestDigest:record.manifestDigest,scope:record.state.scope,scopeRef:record.state.scopeRef,installationRef:record.installationRef,state:record.state.lifecycle},scope:requestedScope,scopeRef,signal})}catch{return response(parsed.command,parsed.format,"failed",safeError("uninstall_failed"))}if(removedFromHost.status!=="succeeded")return response(parsed.command,parsed.format,removedFromHost.status==="cancelled"?"cancelled":"failed",safeError(removedFromHost.status==="cancelled"?"cancelled":"uninstall_failed"))}let removed=await stateStore2.remove({pluginId:record.pluginId,pluginVersion:record.pluginVersion,scope:requestedScope,scopeRef,signal});return removed.status==="cancelled"?response(parsed.command,parsed.format,"cancelled",safeError("cancelled")):removed.status!=="ok"?response(parsed.command,parsed.format,"failed",safeError("state_failed")):response(parsed.command,parsed.format,"succeeded",void 0,{pluginId:record.pluginId,pluginVersion:record.pluginVersion,...options.installer===void 0?{}:{hostRemoved:!0},changed:removed.changed})}let enabled=parsed.command==="enable",updated=await stateStore2.upsert({installation:{version:1,pluginId:record.pluginId,pluginVersion:record.pluginVersion,manifestDigest:record.manifestDigest,scope:record.state.scope,scopeRef:record.state.scopeRef,installationRef:record.installationRef,state:record.state.lifecycle},scope:requestedScope,enabled,...record.source===void 0?{}:{source:record.source},signal});return updated.status==="cancelled"?response(parsed.command,parsed.format,"cancelled",safeError("cancelled")):updated.status!=="ok"?response(parsed.command,parsed.format,"failed",safeError("state_failed")):response(parsed.command,parsed.format,"succeeded",void 0,{pluginId:record.pluginId,pluginVersion:record.pluginVersion,enabled,changed:updated.changed})}let stateStore=stateStoreOf(options,requestedScope),installer=options.installer,host=options.host,acquisitionTarget=parsed.command==="install"&&parsed.target!==void 0&&isPluginAcquisitionRefTargetV1(parsed.target)?parsed.target:void 0;if(!stateStore||!installer||!host||!installerSupportsScope(installer,requestedScope)||acquisitionTarget===void 0&&!options.registry)return response(parsed.command,parsed.format,"unsupported",safeError("unsupported_dependencies"));let runInstallFlow=async resolved=>{phase="state";let current=await stateStore.read({signal});if(current.status==="cancelled")return response(parsed.command,parsed.format,"cancelled",safeError("cancelled"));if(current.status==="invalid")return response(parsed.command,parsed.format,"failed",safeError("state_failed"));let previous=findCurrentStateRecord(current.snapshot.records,resolved.manifest.id,requestedScope,scopeRef);if(findStateRecord(current.snapshot.records,resolved.manifest.id,resolved.manifest.pluginVersion,requestedScope,scopeRef)!==void 0)return response(parsed.command,parsed.format,"failed",safeError("already_installed"));if(parsed.command==="update"&&(!previous||previous.state.lifecycle!=="active"))return response(parsed.command,parsed.format,"failed",safeError("not_installed"));phase="installer";let verified=installer.prepare({manifest:resolved.manifest,source:resolved.source,host,...resolved.expectedDigest===void 0?{}:{expectedDigest:resolved.expectedDigest}});if(verified.status!=="verified")return response(parsed.command,parsed.format,"failed",safeError("incompatible"));let artifact=resolved.acquired?.artifact;if(resolved.distribution!==void 0){if(options.distribution===void 0)return response(parsed.command,parsed.format,"unsupported",safeError("unsupported_dependencies"));phase="distribution";let descriptor=options.distribution.validateDescriptor(resolved.distribution);if(descriptor.pluginId!==verified.record.pluginId||descriptor.pluginVersion!==verified.record.pluginVersion||descriptor.manifestDigest!==verified.record.manifestDigest)return response(parsed.command,parsed.format,"failed",safeError("incompatible"));artifact=await options.distribution.acquireArtifact({descriptor,signal})}let artifactReleased=!1,releaseArtifact=async()=>{if(artifact===void 0||artifactReleased)return!0;let previousPhase=phase;phase="distribution";try{return resolved.acquired!==void 0?await resolved.acquired.release()?(artifactReleased=!0,phase=previousPhase,!0):!1:options.distribution===void 0?!1:(await options.distribution.releaseArtifact({artifact}),artifactReleased=!0,phase=previousPhase,!0)}catch{return!1}},transactionResponse,transactionError,artifactCleanupFailed=!1;try{transactionResponse=await(async()=>{checkSignal(signal),phase="installer";let installed=await installer.install({record:verified.record,scope:requestedScope,scopeRef,...artifact===void 0?{}:{artifact},signal});if(installed.status!=="succeeded")return await releaseArtifact()?response(parsed.command,parsed.format,installed.status==="cancelled"?"cancelled":"failed",safeError(installed.status==="cancelled"?"cancelled":"installer_failed")):response(parsed.command,parsed.format,isCancelled(signal)?"cancelled":"failed",safeError(isCancelled(signal)?"cancelled":"distribution_failed"));let activated=await installer.activate({installation:installed.installation,record:verified.record,scope:requestedScope,scopeRef,signal});if(activated.status!=="succeeded")return previous&&previous.state.lifecycle==="active"&&(await installer.rollback({failed:installed.installation,previous:{version:1,pluginId:previous.pluginId,pluginVersion:previous.pluginVersion,manifestDigest:previous.manifestDigest,scope:previous.state.scope,scopeRef:previous.state.scopeRef,installationRef:previous.installationRef,state:"active"},scope:requestedScope,scopeRef,signal:void 0})).status!=="succeeded"||(await installer.remove({installation:installed.installation,scope:requestedScope,scopeRef})).status!=="succeeded"?response(parsed.command,parsed.format,"failed",safeError("installer_failed")):await releaseArtifact()?response(parsed.command,parsed.format,activated.status==="cancelled"?"cancelled":"failed",safeError(activated.status==="cancelled"?"cancelled":"installer_failed")):response(parsed.command,parsed.format,isCancelled(signal)?"cancelled":"failed",safeError(isCancelled(signal)?"cancelled":"distribution_failed"));let restoreActivatedInstallation=async()=>{let replacesPrevious=previous!==void 0&&`${previous.pluginId}@${previous.pluginVersion}`!=`${activated.installation.pluginId}@${activated.installation.pluginVersion}`;return replacesPrevious&&previous.state.lifecycle==="active"&&(await installer.rollback({failed:activated.installation,previous:{version:1,pluginId:previous.pluginId,pluginVersion:previous.pluginVersion,manifestDigest:previous.manifestDigest,scope:previous.state.scope,scopeRef:previous.state.scopeRef,installationRef:previous.installationRef,state:"active"},scope:requestedScope,scopeRef})).status!=="succeeded"?!1:previous!==void 0&&!replacesPrevious?!0:(await installer.remove({installation:activated.installation,scope:requestedScope,scopeRef})).status==="succeeded"},restoreState=async()=>{let replacesPrevious=previous!==void 0&&`${previous.pluginId}@${previous.pluginVersion}`!=`${activated.installation.pluginId}@${activated.installation.pluginVersion}`,restored=!0;if((previous===void 0||replacesPrevious)&&(restored=(await stateStore.remove({pluginId:activated.installation.pluginId,pluginVersion:activated.installation.pluginVersion,scope:requestedScope,scopeRef}).catch(()=>{}))?.status==="ok"),previous!==void 0){let restoredPrevious=await stateStore.upsert({installation:{version:1,pluginId:previous.pluginId,pluginVersion:previous.pluginVersion,manifestDigest:previous.manifestDigest,scope:previous.state.scope,scopeRef:previous.state.scopeRef,installationRef:previous.installationRef,state:"active"},scope:requestedScope,enabled:previous.state.enabled,...previous.source===void 0?{}:{source:previous.source}}).catch(()=>{});restored=restored&&restoredPrevious?.status==="ok"}return restored},stateFailure=async status2=>{let[hostRestored,stateRestored]=await Promise.all([restoreActivatedInstallation().catch(()=>!1),restoreState().catch(()=>!1)]);return response(parsed.command,parsed.format,hostRestored&&stateRestored?status2:"failed",safeError(hostRestored&&stateRestored?status2==="cancelled"?"cancelled":"state_failed":"installer_failed"))};if(!await releaseArtifact()){phase="installer";let restored=await restoreActivatedInstallation().catch(()=>!1);return response(parsed.command,parsed.format,"failed",safeError(restored?"distribution_failed":"installer_failed"))}if(phase="state",previous&&`${previous.pluginId}@${previous.pluginVersion}`!=`${installed.installation.pluginId}@${installed.installation.pluginVersion}`&&(await stateStore.upsert({installation:{version:1,pluginId:previous.pluginId,pluginVersion:previous.pluginVersion,manifestDigest:previous.manifestDigest,scope:previous.state.scope,scopeRef:previous.state.scopeRef,installationRef:previous.installationRef,state:"retained"},scope:requestedScope,enabled:previous.state.enabled,...previous.source===void 0?{}:{source:previous.source},signal:void 0})).status!=="ok")return await stateFailure("failed");let persisted=await stateStore.upsert({installation:activated.installation,scope:requestedScope,enabled:previous?.state.enabled??!0,...resolved.acquired===void 0?{}:{source:resolved.source},signal});return persisted.status==="cancelled"?await stateFailure("cancelled"):persisted.status!=="ok"?await stateFailure("failed"):response(parsed.command,parsed.format,"succeeded",void 0,{pluginId:activated.installation.pluginId,pluginVersion:activated.installation.pluginVersion,lifecycle:"active",changed:persisted.changed,...resolved.acquired===void 0?{}:{source:resolved.source}})})()}catch(error2){transactionError=error2}finally{artifactCleanupFailed=!await releaseArtifact()}if(artifactCleanupFailed)return response(parsed.command,parsed.format,"failed",safeError("distribution_failed"));if(transactionError!==void 0)throw transactionError;if(transactionResponse===void 0)throw new Error("plugin installation transaction did not complete");return transactionResponse};if(acquisitionTarget!==void 0){if(options.acquisition===void 0)return response(parsed.command,parsed.format,"unsupported",safeError("unsupported_dependencies"));phase="distribution";let acquired;try{acquired=await options.acquisition.resolvePackage({ref:acquisitionTarget,signal})}catch(error2){if(isCancelled(signal)||error2 instanceof PluginAcquisitionErrorV1&&error2.code==="cancelled")return response(parsed.command,parsed.format,"cancelled",safeError("cancelled"));if(error2 instanceof PluginAcquisitionErrorV1)return response(parsed.command,parsed.format,"failed",{code:"acquisition_failed",message:error2.message});throw error2}return checkSignal(signal),await runInstallFlow({manifest:acquired.manifest,source:acquired.source,acquired})}try{requireDependencies(options,requestedScope,scopeRef)}catch{return response(parsed.command,parsed.format,"unsupported",safeError("unsupported_dependencies"))}let identity=parsed.pluginId,packageValue=await options.registry.resolve({pluginId:identity,pluginVersion:parsed.pluginVersion,signal});return checkSignal(signal),!packageValue||packageValue.manifest.id!==identity||parsed.pluginVersion!==void 0&&packageValue.manifest.pluginVersion!==parsed.pluginVersion?response(parsed.command,parsed.format,"failed",safeError("not_found")):await runInstallFlow({manifest:packageValue.manifest,source:packageValue.source,...packageValue.expectedDigest===void 0?{}:{expectedDigest:packageValue.expectedDigest},...packageValue.distribution===void 0?{}:{distribution:packageValue.distribution}})}catch(error2){return isCancelled(signal)||error2 instanceof Error&&error2.message==="cancelled"?response(parsed.command,parsed.format,"cancelled",safeError("cancelled")):error2 instanceof Error&&error2.message==="unsupported dependencies"?response(parsed.command,parsed.format,"unsupported",safeError("unsupported_dependencies")):response(parsed.command,parsed.format,"failed",safeError(phase==="registry"?"registry_failed":phase==="distribution"?"distribution_failed":phase==="state"?"state_failed":phase==="selection"?"selection_failed":"installer_failed"))}}finally{releaseInstallTransaction?.()}}return{execute}}async function runPluginEcosystemCliV1(options,input){return await createPluginEcosystemCliV1(options).execute(input)}import{createHash}from"node:crypto";import{join as join13,resolve as resolve4}from"node:path";import{open as open2}from"node:fs/promises";import{isAbsolute as isAbsolute2,join as join11,relative as relative2}from"node:path";var NODE_DISK_REGISTRY_SOURCE_VERSION_V1=1,MAX_NODE_DISK_REGISTRY_INDEX_BYTES_V1=1024*1024,MAX_NODE_DISK_REGISTRY_MANIFEST_BYTES_V1=64*1024,MAX_NODE_DISK_REGISTRY_RECORDS_V1=256,INDEX_FILE_V1="index.v1.json",ECOSYSTEM_MANIFEST_FILE_V1="agent-forge.json",CAPABILITY_MANIFEST_FILE_V1="plugin.json",NODE_PACKAGE_FORMAT_VERSION_V1=1,NodeDiskRegistrySourceErrorV1=class extends Error{code;constructor(code,message){super(message),this.name="NodeDiskRegistrySourceErrorV1",this.code=code}},INDEX_KEYS_V1=["installationRef","directory","pluginId","pluginVersion","manifestDigest","scope","scopeRef","state"];function opaqueField(value,max){return typeof value=="string"&&value.length>0&&value.length<=max&&!/[\u0000-\u001f\u007f]/u.test(value)&&!/\s/u.test(value)&&!/^(?:file:|[a-z]:[\\/]|[\\/]{1,2}|\\\\)/iu.test(value)}function boundedField(value,max){return typeof value=="string"&&value.length>0&&value.length<=max&&!/[\u0000-\u001f\u007f]/u.test(value)}function withinRoot(root,value){if(!isAbsolute2(value))return!1;let relativePath=relative2(root,value);return relativePath!==""&&!relativePath.startsWith("..")&&!isAbsolute2(relativePath)}function validateRecord(root,value,index3){if(value===null||typeof value!="object"||Array.isArray(value))throw new NodeDiskRegistrySourceErrorV1("invalid_index",`Index record ${index3} is not an object`);let record=value,keys=INDEX_KEYS_V1;if(Object.keys(record).length!==keys.length||keys.some(key=>!(key in record)))throw new NodeDiskRegistrySourceErrorV1("invalid_index",`Index record ${index3} has an invalid schema`);if(!opaqueField(record.installationRef,2048)||!boundedField(record.directory,2048)||!boundedField(record.pluginId,256)||!boundedField(record.pluginVersion,256)||!boundedField(record.manifestDigest,512)||!opaqueField(record.scopeRef,2048)||record.scope!=="global"&&record.scope!=="project"||record.state!=="installed"&&record.state!=="active"&&record.state!=="retained"||!withinRoot(root,record.directory))throw new NodeDiskRegistrySourceErrorV1("invalid_index",`Index record ${index3} is invalid`);return{installationRef:record.installationRef,directory:record.directory,pluginId:record.pluginId,pluginVersion:record.pluginVersion,manifestDigest:record.manifestDigest,scope:record.scope,scopeRef:record.scopeRef,state:record.state}}function parseIndex(root,raw){let parsed;try{parsed=JSON.parse(raw)}catch{throw new NodeDiskRegistrySourceErrorV1("invalid_index","Install store index JSON is invalid")}if(parsed===null||typeof parsed!="object"||Array.isArray(parsed))throw new NodeDiskRegistrySourceErrorV1("invalid_index","Install store index is not an object");let value=parsed;if(Object.keys(value).length!==2||value.version!==NODE_DISK_REGISTRY_SOURCE_VERSION_V1||!Array.isArray(value.records))throw new NodeDiskRegistrySourceErrorV1("invalid_index","Install store index schema is unsupported");if(value.records.length>MAX_NODE_DISK_REGISTRY_RECORDS_V1)throw new NodeDiskRegistrySourceErrorV1("too_many_records","Install store index exceeds the record limit");return value.records.map((record,index3)=>validateRecord(root,record,index3))}async function readBoundedFile(path15,maxBytes,label){let handle=await open2(path15,"r");try{let stat5=await handle.stat();if(!stat5.isFile()||stat5.size>maxBytes)throw new NodeDiskRegistrySourceErrorV1(label==="index"?"invalid_index":"invalid_manifest",`${label} exceeds the size limit`);return await handle.readFile("utf8")}finally{await handle.close().catch(()=>{})}}function parseManifest(record,raw){let parsed;try{parsed=JSON.parse(raw)}catch{throw new NodeDiskRegistrySourceErrorV1("invalid_manifest","Installed plugin manifest JSON is invalid")}if(parsed===null||typeof parsed!="object"||Array.isArray(parsed))throw new NodeDiskRegistrySourceErrorV1("invalid_manifest","Installed plugin manifest is not an object");let value={...parsed};if(value.packageFormatVersion!==void 0&&value.packageFormatVersion!==NODE_PACKAGE_FORMAT_VERSION_V1)throw new NodeDiskRegistrySourceErrorV1("invalid_manifest","Installed plugin package format is unsupported");if(delete value.packageFormatVersion,value.id!==record.pluginId||value.pluginVersion!==record.pluginVersion)throw new NodeDiskRegistrySourceErrorV1("identity_mismatch",`Installed plugin manifest identity does not match index record for ${record.pluginId}@${record.pluginVersion}`);return value}async function readIndexRecords(rootDirectory,signal){if(signal?.aborted)throw new NodeDiskRegistrySourceErrorV1("cancelled","Disk registry source read was cancelled");let rawIndex;try{rawIndex=await readBoundedFile(join11(rootDirectory,INDEX_FILE_V1),MAX_NODE_DISK_REGISTRY_INDEX_BYTES_V1,"index")}catch(error2){if(error2 instanceof NodeDiskRegistrySourceErrorV1)throw error2;if(error2 instanceof Error&&"code"in error2&&error2.code==="ENOENT")return;throw new NodeDiskRegistrySourceErrorV1("io_failed","Install store index could not be read")}return parseIndex(rootDirectory,rawIndex)}function createNodeDiskPluginRegistrySourceV1(options){let rootDirectory=options.rootDirectory;if(typeof rootDirectory!="string"||!isAbsolute2(rootDirectory)||rootDirectory.trim()==="")throw new NodeDiskRegistrySourceErrorV1("invalid_configuration","Install store root directory must be absolute");return{version:NODE_DISK_REGISTRY_SOURCE_VERSION_V1,list:async({signal}={})=>{let records=await readIndexRecords(rootDirectory,signal);if(records===void 0)return Object.freeze([]);let envelopes=[];for(let record of records){if(signal?.aborted)throw new NodeDiskRegistrySourceErrorV1("cancelled","Disk registry source read was cancelled");let rawManifest;try{rawManifest=await readBoundedFile(join11(record.directory,ECOSYSTEM_MANIFEST_FILE_V1),MAX_NODE_DISK_REGISTRY_MANIFEST_BYTES_V1,"manifest")}catch(error2){throw error2 instanceof NodeDiskRegistrySourceErrorV1?error2:new NodeDiskRegistrySourceErrorV1("io_failed","Installed plugin manifest could not be read")}let manifest=parseManifest(record,rawManifest);envelopes.push({manifest,source:record.installationRef,manifestDigest:record.manifestDigest})}return Object.freeze(envelopes)},resolveCapabilityManifestPath:async({pluginId,pluginVersion,signal})=>{let records=await readIndexRecords(rootDirectory,signal);if(records===void 0)return;let record=records.find(candidate=>candidate.pluginId===pluginId&&candidate.pluginVersion===pluginVersion);if(record===void 0)return;let manifestPath=join11(record.directory,CAPABILITY_MANIFEST_FILE_V1);try{await(await open2(manifestPath,"r")).close().catch(()=>{})}catch{return}return manifestPath}}}var PLUGIN_DISTRIBUTION_CONTRACT_VERSION_V1=1,MAX_PLUGIN_DISTRIBUTION_DESCRIPTOR_BYTES_V1=16*1024,MAX_PLUGIN_DISTRIBUTION_FIELD_CHARS_V1=2048,MAX_PLUGIN_DISTRIBUTION_METADATA_BYTES_V1=16*1024,MAX_PLUGIN_DISTRIBUTION_ARTIFACT_REF_CHARS_V1=2048,MAX_PLUGIN_DISTRIBUTION_ARTIFACT_BYTES_V1=512*1024*1024,ERROR_MESSAGES={unsupported:"Plugin distribution is unsupported on this host",cancelled:"Plugin distribution operation was cancelled",invalid_descriptor:"Plugin distribution descriptor is invalid",invalid_metadata:"Plugin distribution metadata is invalid",invalid_artifact:"Plugin distribution artifact handle is invalid",source_mismatch:"Plugin distribution source does not match the descriptor",identity_mismatch:"Plugin distribution plugin identity does not match the descriptor",digest_mismatch:"Plugin distribution digest does not match the descriptor",signature_invalid:"Plugin distribution signature was rejected",expired:"Plugin distribution descriptor has expired",size_mismatch:"Plugin distribution size does not match the descriptor",media_type_mismatch:"Plugin distribution media type does not match the descriptor",host_failed:"Plugin distribution host operation failed",release_failed:"Plugin distribution artifact release failed"},PluginDistributionErrorV1=class extends Error{code;constructor(code){super(ERROR_MESSAGES[code]),this.name="PluginDistributionErrorV1",this.code=code}},DESCRIPTOR_KEYS=["version","source","pluginId","pluginVersion","manifestDigest","artifactDigest","signature","expiresAt","sizeBytes","mediaType"],METADATA_KEYS=["version","source","pluginId","pluginVersion","manifestDigest","artifactDigest","expiresAt","sizeBytes","mediaType"],ARTIFACT_KEYS=["artifactRef","artifactDigest","sizeBytes","mediaType"];function reject(code){throw new PluginDistributionErrorV1(code)}function hasExactKeys(value,keys){let expected=new Set(keys);return Object.keys(value).every(key=>expected.has(key)&&expected.size===keys.length)&&keys.every(key=>key in value)}function boundedString(value,code){return(typeof value!="string"||value.trim().length===0||value.length>MAX_PLUGIN_DISTRIBUTION_FIELD_CHARS_V1||/[\u0000-\u001f\u007f]/u.test(value))&&reject(code),value}function identityString(value,code){let result=boundedString(value,code);return/\s/u.test(result)&&reject(code),result}function sourceString(value,code){let source=boundedString(value,code);if((/\s/u.test(source)||/^(?:file:|[a-zA-Z]:[\\/]|[\\/]{1,2}|\\\\)/iu.test(source))&&reject(code),/^https?:\/\//iu.test(source))try{let parsed=new URL(source);(parsed.username!==""||parsed.password!=="")&&(parsed.username="",parsed.password=""),parsed.search="",parsed.hash="";let pathname=parsed.pathname.length>512?`${parsed.pathname.slice(0,509)}...`:parsed.pathname;return`${parsed.origin}${pathname||"/"}`}catch{reject(code)}return source}function digestString(value,code){let digest=identityString(value,code);return/^(?:[a-z][a-z0-9+.-]{0,15}:[A-Za-z0-9._~-]{1,128}|[0-9a-f]{16,128})$/u.test(digest)||reject(code),digest}function signatureString(value){let signature=boundedString(value,"invalid_descriptor");return(signature.length>512||/\s/u.test(signature))&&reject("invalid_descriptor"),signature}function expiryString(value,code){let expiry=boundedString(value,code);/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/u.test(expiry)||reject(code);let timestamp=Date.parse(expiry);return(!Number.isFinite(timestamp)||new Date(timestamp).toISOString()!==expiry)&&reject(code),expiry}function positiveSize(value,code){return(typeof value!="number"||!Number.isSafeInteger(value)||value<1||value>MAX_PLUGIN_DISTRIBUTION_ARTIFACT_BYTES_V1)&&reject(code),value}function mediaTypeString(value,code){let mediaType=boundedString(value,code).toLowerCase();return(mediaType.length>256||!/^[a-z0-9!#$&^_.+-]+\/[a-z0-9!#$&^_.+-]+(?:\s*;\s*[a-z0-9!#$&^_.+-]+=[a-z0-9!#$&^_.+-]+)*$/u.test(mediaType))&&reject(code),mediaType}function serializedBytes(value,code){try{let serialized=JSON.stringify(value);return serialized===void 0&&reject(code),new TextEncoder().encode(serialized).byteLength}catch{reject(code)}}function descriptorValue(value){(!isPlainRecord(value)||!hasExactKeys(value,DESCRIPTOR_KEYS))&&reject("invalid_descriptor"),value.version!==PLUGIN_DISTRIBUTION_CONTRACT_VERSION_V1&&reject("invalid_descriptor");let descriptor={version:PLUGIN_DISTRIBUTION_CONTRACT_VERSION_V1,source:sourceString(value.source,"invalid_descriptor"),pluginId:identityString(value.pluginId,"invalid_descriptor"),pluginVersion:identityString(value.pluginVersion,"invalid_descriptor"),manifestDigest:digestString(value.manifestDigest,"invalid_descriptor"),artifactDigest:digestString(value.artifactDigest,"invalid_descriptor"),signature:signatureString(value.signature),expiresAt:expiryString(value.expiresAt,"invalid_descriptor"),sizeBytes:positiveSize(value.sizeBytes,"invalid_descriptor"),mediaType:mediaTypeString(value.mediaType,"invalid_descriptor")};return serializedBytes(descriptor,"invalid_descriptor")>MAX_PLUGIN_DISTRIBUTION_DESCRIPTOR_BYTES_V1&&reject("invalid_descriptor"),detachedFreeze(descriptor)}function metadataValue(value){(!isPlainRecord(value)||!hasExactKeys(value,METADATA_KEYS))&&reject("invalid_metadata"),value.version!==PLUGIN_DISTRIBUTION_CONTRACT_VERSION_V1&&reject("invalid_metadata");let metadata={version:PLUGIN_DISTRIBUTION_CONTRACT_VERSION_V1,source:sourceString(value.source,"invalid_metadata"),pluginId:identityString(value.pluginId,"invalid_metadata"),pluginVersion:identityString(value.pluginVersion,"invalid_metadata"),manifestDigest:digestString(value.manifestDigest,"invalid_metadata"),artifactDigest:digestString(value.artifactDigest,"invalid_metadata"),expiresAt:expiryString(value.expiresAt,"invalid_metadata"),sizeBytes:positiveSize(value.sizeBytes,"invalid_metadata"),mediaType:mediaTypeString(value.mediaType,"invalid_metadata")};return serializedBytes(metadata,"invalid_metadata")>MAX_PLUGIN_DISTRIBUTION_METADATA_BYTES_V1&&reject("invalid_metadata"),detachedFreeze(metadata)}function artifactHandleValue(value){(!isPlainRecord(value)||!hasExactKeys(value,ARTIFACT_KEYS))&&reject("invalid_artifact");let artifact={artifactRef:boundedString(value.artifactRef,"invalid_artifact"),artifactDigest:digestString(value.artifactDigest,"invalid_artifact"),sizeBytes:positiveSize(value.sizeBytes,"invalid_artifact"),mediaType:mediaTypeString(value.mediaType,"invalid_artifact")};return(/[\s\u0000-\u001f\u007f]/u.test(artifact.artifactRef)||/^(?:file:|[a-zA-Z]:[\\/]|[\\/]{1,2}|\\\\)/iu.test(artifact.artifactRef)||artifact.artifactRef.length>MAX_PLUGIN_DISTRIBUTION_ARTIFACT_REF_CHARS_V1)&&reject("invalid_artifact"),detachedFreeze(artifact)}function assertDescriptorMetadataMatch(descriptor,metadata){metadata.source!==descriptor.source&&reject("source_mismatch"),(metadata.pluginId!==descriptor.pluginId||metadata.pluginVersion!==descriptor.pluginVersion)&&reject("identity_mismatch"),(metadata.manifestDigest!==descriptor.manifestDigest||metadata.artifactDigest!==descriptor.artifactDigest)&&reject("digest_mismatch"),metadata.expiresAt!==descriptor.expiresAt&&reject("expired"),metadata.sizeBytes!==descriptor.sizeBytes&&reject("size_mismatch"),metadata.mediaType!==descriptor.mediaType&&reject("media_type_mismatch")}function assertArtifactMatch(descriptor,artifact){artifact.artifactDigest!==descriptor.artifactDigest&&reject("digest_mismatch"),artifact.sizeBytes!==descriptor.sizeBytes&&reject("size_mismatch"),artifact.mediaType!==descriptor.mediaType&&reject("media_type_mismatch")}function isCancelled2(error2,signal){return signal?.aborted===!0||error2 instanceof Error&&(error2.name==="AbortError"||error2.name==="AbortSignalError")}function assertNotExpired(descriptor,now){let current;try{current=now()}catch{reject("expired")}Number.isFinite(current)||reject("expired"),Date.parse(descriptor.expiresAt)<=current&&reject("expired")}async function verifyDescriptor(descriptor,verifySignature,now,signal){signal?.aborted&&reject("cancelled"),assertNotExpired(descriptor,now),verifySignature===void 0&&reject("unsupported");let verification;try{verification=await verifySignature({descriptor})}catch{reject("signature_invalid")}signal?.aborted&&reject("cancelled"),(!isPlainRecord(verification)||verification.status!=="accepted")&&reject("signature_invalid")}function createPluginDistributionV1(options={}){let verifySignature=options.verifySignature??options.verify,now=options.now??(()=>Date.now()),resolveMetadataForDescriptor=async(descriptor,signal)=>{signal?.aborted&&reject("cancelled"),options.host?.resolveMetadata===void 0&&reject("unsupported");let result;try{result=await options.host.resolveMetadata({descriptor,signal})}catch(error2){isCancelled2(error2,signal)&&reject("cancelled"),reject("host_failed")}signal?.aborted&&reject("cancelled");let metadata=metadataValue(result);return assertDescriptorMetadataMatch(descriptor,metadata),assertNotExpired(descriptor,now),metadata};return{validateDescriptor(input){return descriptorValue(input)},resolveMetadata:async input=>{let descriptor=descriptorValue(input.descriptor);return await verifyDescriptor(descriptor,verifySignature,now,input.signal),resolveMetadataForDescriptor(descriptor,input.signal)},acquireArtifact:async input=>{let descriptor=descriptorValue(input.descriptor);await verifyDescriptor(descriptor,verifySignature,now,input.signal),options.host?.acquireArtifact===void 0&&reject("unsupported");let metadata=input.metadata===void 0?await resolveMetadataForDescriptor(descriptor,input.signal):metadataValue(input.metadata);assertDescriptorMetadataMatch(descriptor,metadata),assertNotExpired(descriptor,now);let result,acquired;try{result=await options.host.acquireArtifact({descriptor,metadata,signal:input.signal});let handle=artifactHandleValue(result);return acquired=detachedFreeze({...metadata,artifactRef:handle.artifactRef}),assertArtifactMatch(descriptor,handle),assertNotExpired(descriptor,now),input.signal?.aborted&&reject("cancelled"),acquired}catch(error2){if(acquired!==void 0&&options.host.releaseArtifact!==void 0&&await options.host.releaseArtifact({artifact:acquired}).catch(()=>{}),error2 instanceof PluginDistributionErrorV1)throw error2;isCancelled2(error2,input.signal)&&reject("cancelled"),reject("host_failed")}},releaseArtifact:async input=>{input.signal?.aborted&&reject("cancelled"),options.host?.releaseArtifact===void 0&&reject("unsupported");let value=input.artifact;(!isPlainRecord(value)||!hasExactKeys(value,[...METADATA_KEYS,"artifactRef"]))&&reject("invalid_artifact");let metadataInput=Object.fromEntries(METADATA_KEYS.map(key=>[key,value[key]])),artifact={...metadataValue(metadataInput),artifactRef:artifactHandleValue({artifactRef:value.artifactRef,artifactDigest:value.artifactDigest,sizeBytes:value.sizeBytes,mediaType:value.mediaType}).artifactRef};try{await options.host.releaseArtifact({artifact:detachedFreeze(artifact),signal:input.signal})}catch(error2){isCancelled2(error2,input.signal)&&reject("cancelled"),reject("release_failed")}input.signal?.aborted&&reject("cancelled")}}}var MAX_PLUGIN_REGISTRY_MANIFEST_BYTES_V1=64*1024,MAX_PLUGIN_REGISTRY_MANIFESTS_V1=256,MAX_PLUGIN_REGISTRY_PAYLOAD_BYTES_V1=4*1024*1024,MAX_PLUGIN_REGISTRY_SOURCE_CHARS_V1=2048,MAX_PLUGIN_REGISTRY_PROOF_CHARS_V1=512,PluginRegistryErrorV1=class extends Error{code;cause;constructor(code,message,cause){super(message,cause===void 0?void 0:{cause}),this.name="PluginRegistryErrorV1",this.code=code,this.cause=cause}};function isAbortLike(error2,signal){return signal?.aborted===!0||error2 instanceof Error&&(error2.name==="AbortError"||error2.name==="AbortSignalError")}function boundedString2(value,label,max,code="invalid_source"){if(typeof value!="string"||value.trim()===""||value.length>max||/[\u0000-\u001f]/u.test(value))throw new PluginRegistryErrorV1(code,`${label} must be a non-empty bounded string`);return value}function assertAllowedKeys2(value,allowed,label){let expected=new Set(allowed);if(Object.keys(value).some(key=>!expected.has(key)))throw new PluginRegistryErrorV1("invalid_manifest",`${label} contains an unsupported field`)}function validateSource(source){let value=boundedString2(source,"source",MAX_PLUGIN_REGISTRY_SOURCE_CHARS_V1);if(/^(?:file:|[a-zA-Z]:[\\/]|[\\/]{1,2}|\\\\)/iu.test(value)||/\s/u.test(value))throw new PluginRegistryErrorV1("invalid_source","Plugin registry source must be an opaque URI, not a local path");if(/^https?:\/\//iu.test(value))try{let parsed=new URL(value),pathname=parsed.pathname.length>512?`${parsed.pathname.slice(0,511)}\u2026`:parsed.pathname;return`${parsed.origin}${pathname||"/"}`}catch(error2){throw new PluginRegistryErrorV1("invalid_source","Plugin registry source URL is invalid",error2)}return value}function validateManifest(manifest){if(typeof manifest!="object"||manifest===null||Array.isArray(manifest))throw new PluginRegistryErrorV1("invalid_manifest","Registry manifest must be an object");let value=manifest;if(assertAllowedKeys2(value,["id","pluginVersion","apiVersion","minHostVersion","maxHostVersion","capabilityRefs","requires","platform","testOnly"],"Registry manifest"),typeof value.id!="string"||value.id.trim()===""||value.id.length>256)throw new PluginRegistryErrorV1("invalid_manifest","Registry manifest id is invalid");if(typeof value.pluginVersion!="string"||value.pluginVersion.trim()===""||value.pluginVersion.length>256)throw new PluginRegistryErrorV1("invalid_manifest","Registry manifest pluginVersion is invalid");if(typeof value.apiVersion!="string"||value.apiVersion.trim()===""||value.apiVersion.length>256)throw new PluginRegistryErrorV1("invalid_manifest","Registry manifest apiVersion is invalid");if(value.minHostVersion===void 0&&value.maxHostVersion===void 0)throw new PluginRegistryErrorV1("invalid_manifest","Published plugins must declare host version compatibility range: set minHostVersion and/or maxHostVersion");let bytes;try{bytes=new TextEncoder().encode(JSON.stringify(manifest)).byteLength}catch(error2){throw new PluginRegistryErrorV1("invalid_manifest","Registry manifest cannot be serialized",error2)}if(bytes>MAX_PLUGIN_REGISTRY_MANIFEST_BYTES_V1)throw new PluginRegistryErrorV1("payload_too_large","Registry manifest exceeds the size limit");return Object.freeze({...value})}function validateEnvelope2(value){if(typeof value!="object"||value===null||Array.isArray(value))throw new PluginRegistryErrorV1("invalid_manifest","Registry response entry must be an object");let entry=value;assertAllowedKeys2(entry,["manifest","source","manifestDigest","signature","distribution"],"Registry response entry");let manifest=validateManifest(entry.manifest),source=validateSource(entry.source),manifestDigest=boundedString2(entry.manifestDigest,"manifestDigest",MAX_PLUGIN_REGISTRY_PROOF_CHARS_V1);entry.signature!==void 0&&boundedString2(entry.signature,"signature",MAX_PLUGIN_REGISTRY_PROOF_CHARS_V1);let distribution;if(entry.distribution!==void 0){try{distribution=createPluginDistributionV1().validateDescriptor(entry.distribution)}catch(error2){throw new PluginRegistryErrorV1("invalid_manifest","Registry distribution descriptor is invalid",error2)}if(distribution.pluginId!==manifest.id||distribution.pluginVersion!==manifest.pluginVersion||distribution.manifestDigest!==manifestDigest)throw new PluginRegistryErrorV1("invalid_manifest","Registry distribution descriptor does not match the manifest identity")}return Object.freeze({manifest,source,manifestDigest,...entry.signature===void 0?{}:{signature:entry.signature},...distribution===void 0?{}:{distribution}})}function validateMax(value){let max=value??MAX_PLUGIN_REGISTRY_MANIFESTS_V1;if(!Number.isSafeInteger(max)||max<1||max>MAX_PLUGIN_REGISTRY_MANIFESTS_V1)throw new PluginRegistryErrorV1("invalid_limit",`maxManifests must be an integer between 1 and ${MAX_PLUGIN_REGISTRY_MANIFESTS_V1}`);return max}async function validateSourceProof(entry,verifier,sourceVerifier){let actualDigest=pluginManifestDigestV1(entry.manifest);if(entry.manifestDigest!==actualDigest)throw new PluginRegistryErrorV1("invalid_digest",`Manifest digest mismatch for ${entry.manifest.id}@${entry.manifest.pluginVersion}`);try{let result2=await verifier.verify({manifest:entry.manifest,source:entry.source,manifestDigest:actualDigest,expectedDigest:entry.manifestDigest,signature:entry.signature});if(result2.status!=="accepted")throw new PluginRegistryErrorV1("source_rejected",result2.reason??"Registry source proof was rejected")}catch(error2){throw error2 instanceof PluginRegistryErrorV1?error2:new PluginRegistryErrorV1("source_rejected","Registry source proof was rejected",error2)}let result;try{result=sourceVerifier({pluginId:entry.manifest.id,pluginVersion:entry.manifest.pluginVersion,source:entry.source,manifestDigest:actualDigest})}catch(error2){throw new PluginRegistryErrorV1("source_rejected","Plugin source verifier failed",error2)}if(result.status!=="accepted")throw new PluginRegistryErrorV1("source_rejected",result.reason??"Plugin source was rejected")}function sourceIdentity(entries){return[...new Set(entries.map(entry=>entry.source))].sort((left,right)=>left.localeCompare(right)).join(",")}function createPluginRegistryV1(options){let maxManifests=validateMax(options.maxManifests);if(options.source===void 0||typeof options.source.list!="function")throw new PluginRegistryErrorV1("invalid_source","Registry source must provide list()");if(options.source.source!==void 0&&validateSource(options.source.source),options.verify===void 0||typeof options.verify.verify!="function")throw new PluginRegistryErrorV1("source_rejected","Registry source/digest verifier is required");if(options.sourceVerifier===void 0||typeof options.sourceVerifier!="function")throw new PluginRegistryErrorV1("source_rejected","Registry source verifier is required");let load=async(input={})=>{if(input.signal?.aborted)throw new PluginRegistryErrorV1("cancelled","Plugin registry operation was cancelled");let raw;try{raw=await options.source.list({signal:input.signal})}catch(error2){throw isAbortLike(error2,input.signal)?new PluginRegistryErrorV1("cancelled","Plugin registry operation was cancelled",error2):new PluginRegistryErrorV1("source_rejected","Plugin registry source failed",error2)}if(input.signal?.aborted)throw new PluginRegistryErrorV1("cancelled","Plugin registry operation was cancelled");if(!Array.isArray(raw))throw new PluginRegistryErrorV1("invalid_manifest","Registry source must return an array");if(raw.length>maxManifests)throw new PluginRegistryErrorV1("too_many_manifests","Registry response contains too many manifests");let entries=raw.map(validateEnvelope2);if(entries.reduce((total,entry)=>{let manifestBytes=new TextEncoder().encode(JSON.stringify(entry.manifest)).byteLength,distributionBytes=entry.distribution===void 0?0:new TextEncoder().encode(JSON.stringify(entry.distribution)).byteLength;return total+manifestBytes+distributionBytes+new TextEncoder().encode(entry.source).byteLength+new TextEncoder().encode(entry.manifestDigest).byteLength+(entry.signature===void 0?0:new TextEncoder().encode(entry.signature).byteLength)},0)>MAX_PLUGIN_REGISTRY_PAYLOAD_BYTES_V1)throw new PluginRegistryErrorV1("payload_too_large","Registry response exceeds the aggregate size limit");let seen=new Set,accepted=[],rejected=[];for(let entry of entries){let identity=`${entry.manifest.id}@${entry.manifest.pluginVersion}`;if(seen.has(identity))throw new PluginRegistryErrorV1("invalid_manifest",`Duplicate registry manifest: ${identity}`);seen.add(identity);try{await validateSourceProof(entry,options.verify,options.sourceVerifier)}catch(error2){if(!(error2 instanceof PluginRegistryErrorV1)||error2.cause!==void 0||error2.code!=="source_rejected"&&error2.code!=="invalid_digest")throw error2;rejected.push({pluginId:entry.manifest.id,pluginVersion:entry.manifest.pluginVersion,code:error2.code==="invalid_digest"?"digest_rejected":"source_rejected",reason:error2.code==="invalid_digest"?"Manifest digest mismatch":"Registry source proof was rejected"});continue}if(input.signal?.aborted)throw new PluginRegistryErrorV1("cancelled","Plugin registry operation was cancelled");accepted.push(entry)}let manifests2=accepted.map(entry=>entry.manifest),catalog=buildPluginCatalogV1({manifests:manifests2,host:options.host,availableCapabilities:options.availableCapabilities,maxEntries:maxManifests}),publicEntries=Object.freeze([...accepted].sort((left,right)=>{let idOrder=left.manifest.id.localeCompare(right.manifest.id);return idOrder===0?comparePluginVersionsV1(right.manifest.pluginVersion,left.manifest.pluginVersion):idOrder}).map(entry=>Object.freeze({pluginId:entry.manifest.id,pluginVersion:entry.manifest.pluginVersion,source:entry.source,manifestDigest:entry.manifestDigest,signed:entry.signature!==void 0}))),catalogByIdentity=new Map(catalog.entries.map(entry=>[`${entry.pluginId}@${entry.pluginVersion}`,entry])),verified=Object.freeze(publicEntries.flatMap(entry=>{let catalogEntry2=catalogByIdentity.get(`${entry.pluginId}@${entry.pluginVersion}`);if(catalogEntry2?.resolution.status==="installed-ready")return[{...entry,resolutionStatus:"installed-ready"}];let reason=catalogEntry2?.resolution.diagnostics[0]?.message??"Plugin is incompatible with this host";return rejected.push({pluginId:entry.pluginId,pluginVersion:entry.pluginVersion,code:"incompatible",reason}),[]}));return{accepted:Object.freeze(accepted),snapshot:Object.freeze({version:1,source:options.source.source===void 0?sourceIdentity(accepted):validateSource(options.source.source),entries:publicEntries,catalog,verified,rejected:Object.freeze(rejected)})}};return{list:async(input={})=>(await load(input)).snapshot,listManifests:async(input={})=>{let loaded=await load(input);return Object.freeze(loaded.snapshot.catalog.entries.flatMap(catalogEntry2=>loaded.accepted.filter(entry=>entry.manifest.id===catalogEntry2.pluginId&&entry.manifest.pluginVersion===catalogEntry2.pluginVersion).map(entry=>entry.manifest)))},resolve:async input=>{let loaded=await load({signal:input.signal}),verified=new Set(loaded.snapshot.verified.map(entry2=>`${entry2.pluginId}@${entry2.pluginVersion}`)),identity=input.pluginVersion===void 0?loaded.snapshot.catalog.entries.find(candidate=>candidate.pluginId===input.pluginId&&candidate.resolution.status==="installed-ready"&&verified.has(`${candidate.pluginId}@${candidate.pluginVersion}`)):loaded.snapshot.catalog.entries.find(candidate=>candidate.pluginId===input.pluginId&&candidate.pluginVersion===input.pluginVersion&&candidate.resolution.status==="installed-ready"&&verified.has(`${candidate.pluginId}@${candidate.pluginVersion}`)),entry=identity===void 0?void 0:loaded.accepted.find(candidate=>candidate.manifest.id===identity.pluginId&&candidate.manifest.pluginVersion===identity.pluginVersion);if(entry!==void 0)return Object.freeze({manifest:entry.manifest,source:entry.source,expectedDigest:entry.manifestDigest,...entry.distribution===void 0?{}:{distribution:entry.distribution}})}}}import{randomUUID as randomUUID3}from"node:crypto";import{mkdir,readFile as readFile3,rename,unlink,writeFile}from"node:fs/promises";import{basename as basename2,dirname as dirname6,isAbsolute as isAbsolute3,join as join12,resolve as resolve3}from"node:path";var PLUGIN_STATE_SNAPSHOT_VERSION_V1=1,MAX_PLUGIN_STATE_RECORDS_V1=256,MAX_PLUGIN_STATE_STRING_CHARS_V1=4096,MAX_PLUGIN_STATE_ID_CHARS_V1=256,MAX_PLUGIN_STATE_INSTALLATION_REF_CHARS_V1=2048,MAX_PLUGIN_STATE_SOURCE_CHARS_V1=128,EMPTY_SNAPSHOT=Object.freeze({version:PLUGIN_STATE_SNAPSHOT_VERSION_V1,records:Object.freeze([])});function diagnostic3(code,message,identity){return Object.freeze(identity===void 0?{code,message}:{code,message,identity})}function isAbortError(error2){return error2 instanceof Error&&(error2.name==="AbortError"||error2.name==="AbortSignalError")}function isMissingError(error2){return typeof error2!="object"||error2===null?!1:"code"in error2&&error2.code==="ENOENT"}function validateFilePath(value){if(typeof value!="string"||value.trim()===""||value.length>MAX_PLUGIN_STATE_STRING_CHARS_V1)throw new Error("invalid plugin state file path");if(value.includes("\0")||/[\u0000-\u001f]/u.test(value))throw new Error("invalid plugin state file path");if(/^file:/iu.test(value)||/^[a-z][a-z\d+.-]*:/iu.test(value)&&!/^[a-z]:[\\/]/iu.test(value))throw new Error("invalid plugin state file path");let normalized=isAbsolute3(value)?value:resolve3(value);if(basename2(normalized).length===0||basename2(normalized)==="."||basename2(normalized)==="..")throw new Error("invalid plugin state file path");return normalized}function validateOpaqueInstallationRef(value){if(typeof value!="string"||value.trim()===""||value.length>MAX_PLUGIN_STATE_INSTALLATION_REF_CHARS_V1)throw new Error("invalid installation reference");if(/^(?:file:|[a-zA-Z]:[\\/]|[\\/]{1,2}|\\\\)/u.test(value)||/\s/u.test(value))throw new Error("invalid installation reference");if(value.includes("\0")||/[\u0000-\u001f]/u.test(value))throw new Error("invalid installation reference");return value}function validateScopeRef(scope,value){if(typeof value!="string"||value.trim()===""||value.length>MAX_PLUGIN_SCOPE_REF_CHARS_V1)throw new Error("invalid plugin scope reference");if(/^(?:file:|[a-zA-Z]:[\\/]|[\\/]{1,2}|\\\\)/u.test(value)||/\s/u.test(value))throw new Error("invalid plugin scope reference");if(value.includes("\0")||/[\u0000-\u001f]/u.test(value))throw new Error("invalid plugin scope reference");if(scope==="global"&&value!==DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1)throw new Error("invalid plugin scope reference");return value}function validateString(value,label,max=MAX_PLUGIN_STATE_STRING_CHARS_V1){if(typeof value!="string"||value.trim().length===0||value.length>max||/[\u0000-\u001f]/u.test(value))throw new Error(`${label} is invalid`);return value}function validateSourceLabel(value){if(typeof value!="string"||value.length===0||value.length>MAX_PLUGIN_STATE_SOURCE_CHARS_V1||!/^[a-z][a-z0-9.:[\]_/@-]*$/u.test(value))throw new Error("record source label is invalid");return value}function identityOf(record){return`${record.state.scope}:${record.state.scopeRef}:${record.pluginId}@${record.pluginVersion}`}function isObject2(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function hasExactKeys2(value,keys){let expected=new Set(keys);return Object.keys(value).length===expected.size&&Object.keys(value).every(key=>expected.has(key))}function validateRecord2(value){let requiredKeys=["pluginId","pluginVersion","manifestDigest","installationRef","state"],allowedKeys=new Set([...requiredKeys,"source"]);if(!isObject2(value)||Object.keys(value).some(key=>!allowedKeys.has(key)))throw new Error("record schema is invalid");for(let key of requiredKeys)if(!(key in value))throw new Error("record schema is invalid");let pluginId=validateString(value.pluginId,"pluginId",MAX_PLUGIN_STATE_ID_CHARS_V1),pluginVersion=validateString(value.pluginVersion,"pluginVersion",MAX_PLUGIN_STATE_ID_CHARS_V1),manifestDigest=validateString(value.manifestDigest,"manifestDigest"),installationRef=validateOpaqueInstallationRef(value.installationRef),source=value.source===void 0?void 0:validateSourceLabel(value.source);if(!isObject2(value.state)||!hasExactKeys2(value.state,["scope","scopeRef","enabled","lifecycle"]))throw new Error("state schema is invalid");if(value.state.scope!=="global"&&value.state.scope!=="project")throw new Error("state scope is invalid");let scopeRef=validateScopeRef(value.state.scope,value.state.scopeRef);if(typeof value.state.enabled!="boolean")throw new Error("state enabled flag is invalid");if(value.state.lifecycle!=="installed"&&value.state.lifecycle!=="active"&&value.state.lifecycle!=="retained")throw new Error("state lifecycle is invalid");return Object.freeze({pluginId,pluginVersion,manifestDigest,installationRef,...source===void 0?{}:{source},state:Object.freeze({scope:value.state.scope,scopeRef,enabled:value.state.enabled,lifecycle:value.state.lifecycle})})}function validateSnapshot(value){if(!isObject2(value)||!hasExactKeys2(value,["version","records"]))throw new Error("snapshot schema is invalid");if(value.version!==PLUGIN_STATE_SNAPSHOT_VERSION_V1)throw new Error("snapshot version is unsupported");if(!Array.isArray(value.records))throw new Error("records must be an array");if(value.records.length>MAX_PLUGIN_STATE_RECORDS_V1)throw new Error("too many plugin state records");let records=value.records.map(validateRecord2),identities=new Set;for(let record of records){let identity=identityOf(record);if(identities.has(identity))throw new Error(`duplicate identity: ${identity}`);identities.add(identity)}return records.sort((left,right)=>identityOf(left).localeCompare(identityOf(right))),Object.freeze({version:PLUGIN_STATE_SNAPSHOT_VERSION_V1,records:Object.freeze(records)})}function invalidFromError(error2){let message=error2 instanceof Error?error2.message:"plugin state schema is invalid",duplicatePrefix="duplicate identity: ";return message.startsWith(duplicatePrefix)?diagnostic3("duplicate_identity",message,message.slice(duplicatePrefix.length)):diagnostic3(message==="too many plugin state records"?"too_many_records":message==="invalid installation reference"?"invalid_installation_ref":"invalid_schema",message)}function defaultFileSystem(){return{readFile:async path15=>await readFile3(path15,"utf8"),mkdir:async path15=>{await mkdir(path15,{recursive:!0})},writeFile:async(path15,data)=>{await writeFile(path15,data,"utf8")},rename,unlink}}function cancelledResult(){return Object.freeze({status:"cancelled",diagnostics:Object.freeze([diagnostic3("cancelled","Plugin state operation was cancelled")])})}function sortRecords(records){return Object.freeze([...records].sort((left,right)=>identityOf(left).localeCompare(identityOf(right))))}function makeRecord(installation,scope,enabled,source){if(installation.version!==1)throw new Error("plugin installation handle is invalid");let pluginId=validateString(installation.pluginId,"pluginId",MAX_PLUGIN_STATE_ID_CHARS_V1),pluginVersion=validateString(installation.pluginVersion,"pluginVersion",MAX_PLUGIN_STATE_ID_CHARS_V1),manifestDigest=validateString(installation.manifestDigest,"manifestDigest"),installationRef=validateOpaqueInstallationRef(installation.installationRef);if(scope!=="global"&&scope!=="project")throw new Error("state scope is invalid");if(installation.scope!==scope)throw new Error("installation scope does not match state scope");let scopeRef=validateScopeRef(scope,scope==="global"?installation.scopeRef??DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1:installation.scopeRef);if(typeof enabled!="boolean")throw new Error("state enabled flag is invalid");let sourceLabel=source===void 0?void 0:validateSourceLabel(source);return Object.freeze({pluginId,pluginVersion,manifestDigest,installationRef,...sourceLabel===void 0?{}:{source:sourceLabel},state:Object.freeze({scope,scopeRef,enabled,lifecycle:installation.state})})}function createPluginStateStoreV1(options){let filePath=validateFilePath(options.filePath),fileSystem=options.fileSystem??defaultFileSystem();async function read(signal){if(signal?.aborted)return cancelledResult();let content;try{content=await fileSystem.readFile(filePath)}catch(error2){if(isMissingError(error2))return Object.freeze({status:"missing",snapshot:EMPTY_SNAPSHOT});if(isAbortError(error2)||signal?.aborted)return cancelledResult();throw error2}if(signal?.aborted)return cancelledResult();let parsed;try{parsed=JSON.parse(content)}catch{return Object.freeze({status:"invalid",diagnostics:Object.freeze([diagnostic3("invalid_json","plugin state JSON is invalid")])})}try{return Object.freeze({status:"ok",snapshot:validateSnapshot(parsed)})}catch(error2){return Object.freeze({status:"invalid",diagnostics:Object.freeze([invalidFromError(error2)])})}}async function write(snapshot2,signal){if(signal?.aborted)return cancelledResult();let parent=dirname6(filePath),temporaryPath=join12(parent,`.${basename2(filePath)}.${randomUUID3()}.tmp`);try{return await fileSystem.mkdir(parent),signal?.aborted||(await fileSystem.writeFile(temporaryPath,`${JSON.stringify(snapshot2)}
|
|
506
506
|
`),signal?.aborted)?cancelledResult():(await fileSystem.rename(temporaryPath,filePath),Object.freeze({status:"ok",snapshot:snapshot2,changed:!0}))}finally{try{await fileSystem.unlink(temporaryPath)}catch{}}}let mutationTail=Promise.resolve();function enqueueMutation(operation){let result=mutationTail.then(operation,operation);return mutationTail=result.then(()=>{},()=>{}),result}return{read:async({signal}={})=>await read(signal),upsert:input=>enqueueMutation(async()=>{let record;try{record=makeRecord(input.installation,input.scope,input.enabled,input.source)}catch(error2){return Object.freeze({status:"invalid",diagnostics:Object.freeze([invalidFromError(error2)])})}let current=await read(input.signal);if(current.status!=="ok"&¤t.status!=="missing")return current;if(input.signal?.aborted)return cancelledResult();let records=current.snapshot.records.filter(candidate=>identityOf(candidate)!==identityOf(record));if(records.length>=MAX_PLUGIN_STATE_RECORDS_V1&&!current.snapshot.records.some(candidate=>identityOf(candidate)===identityOf(record)))return Object.freeze({status:"invalid",diagnostics:Object.freeze([diagnostic3("too_many_records","too many plugin state records")])});let snapshot2=Object.freeze({version:PLUGIN_STATE_SNAPSHOT_VERSION_V1,records:sortRecords([...records,record])});return await write(snapshot2,input.signal)}),remove:input=>enqueueMutation(async()=>{let pluginId,pluginVersion,scope,scopeRef;try{if(pluginId=validateString(input.pluginId,"pluginId",MAX_PLUGIN_STATE_ID_CHARS_V1),pluginVersion=validateString(input.pluginVersion,"pluginVersion",MAX_PLUGIN_STATE_ID_CHARS_V1),input.scope!=="global"&&input.scope!=="project")throw new Error("state scope is invalid");scope=input.scope,scopeRef=validateScopeRef(scope,input.scopeRef)}catch(error2){return Object.freeze({status:"invalid",diagnostics:Object.freeze([invalidFromError(error2)])})}let current=await read(input.signal);if(current.status!=="ok"&¤t.status!=="missing")return current;if(input.signal?.aborted)return cancelledResult();let identity=`${scope}:${scopeRef}:${pluginId}@${pluginVersion}`,records=current.snapshot.records.filter(candidate=>identityOf(candidate)!==identity);if(records.length===current.snapshot.records.length)return Object.freeze({status:"ok",snapshot:current.snapshot,changed:!1});let snapshot2=Object.freeze({version:PLUGIN_STATE_SNAPSHOT_VERSION_V1,records:sortRecords(records)});return await write(snapshot2,input.signal)})}}var DEFAULT_PLUGIN_INSTALL_STORE_DIR_V1="plugin-install-store-v1",DEFAULT_PLUGIN_STATE_FILE_V1="plugin-state.json";function projectPluginScopeRefV1(cwd){let canonicalPath=resolve4(cwd),identityPath=process.platform==="win32"?canonicalPath.toLowerCase():canonicalPath;return`project:sha256:${createHash("sha256").update(identityPath).digest("hex")}`}function defaultPluginInstallStoreDirectoryV1(agentDir){return join13(agentDir,DEFAULT_PLUGIN_INSTALL_STORE_DIR_V1)}function defaultPluginInstallStoreInstanceRootV1(agentDir){return join13(defaultPluginInstallStoreDirectoryV1(agentDir),"agent-forge-plugin-install-store-v1")}function defaultPluginHostFactsV1(){return{os:process.platform==="win32"?"windows":process.platform==="darwin"?"macos":process.platform,arch:process.arch,runtime:[{name:"node",version:process.versions.node}],apiVersion:"1",hostFeatures:[]}}function digestOnlyVerifierV1(){return{verify:({manifestDigest,expectedDigest:expectedDigest2})=>expectedDigest2===void 0||expectedDigest2===manifestDigest?{status:"accepted"}:{status:"rejected",reason:"Manifest digest does not match the expected digest"}}}function installStoreSourceVerifierV1(){return()=>({status:"accepted"})}function createDefaultActivePluginBindingsResolverV1(){return async input=>{let registrySource=createNodeDiskPluginRegistrySourceV1({rootDirectory:defaultPluginInstallStoreInstanceRootV1(input.agentDir)}),registry=createPluginRegistryV1({source:registrySource,host:defaultPluginHostFactsV1(),verify:digestOnlyVerifierV1(),sourceVerifier:installStoreSourceVerifierV1()});return await resolveActivePluginBindingsForScopesV1({registry,...registrySource.resolveCapabilityManifestPath===void 0?{}:{resolveInstallationManifestPath:registrySource.resolveCapabilityManifestPath},project:{stateStore:createPluginStateStoreV1({filePath:join13(input.cwd,CONFIG_DIR_NAME,DEFAULT_PLUGIN_STATE_FILE_V1)}),scope:"project",scopeRef:projectPluginScopeRefV1(input.cwd)},global:{stateStore:createPluginStateStoreV1({filePath:join13(input.agentDir,DEFAULT_PLUGIN_STATE_FILE_V1)}),scope:"global",scopeRef:DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1}})}}import{join as join18}from"node:path";import{createHash as createHash2,randomUUID as randomUUID4}from"node:crypto";import{createReadStream}from"node:fs";import{mkdir as mkdir2,mkdtemp,open as open3,rename as rename2,rm}from"node:fs/promises";import{tmpdir}from"node:os";import{isAbsolute as isAbsolute4,join as join14}from"node:path";import{createPublicKey,verify}from"node:crypto";var NODE_PLUGIN_TRUST_ROOT_VERSION_V1=1,MAX_KEY_ID_CHARS_V1=128,MAX_KEYS_V1=256,SIGNATURE_PREFIX_V1="ed25519-v1";function validKeyId(value){return value.length>0&&value.length<=MAX_KEY_ID_CHARS_V1&&/^[A-Za-z0-9_-]+$/u.test(value)}function parseValidity(value,label){if(value===void 0)return;if(!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/u.test(value))throw new Error(`${label} must be an ISO-8601 UTC timestamp`);let timestamp=Date.parse(value);if(!Number.isFinite(timestamp)||new Date(timestamp).toISOString()!==value)throw new Error(`${label} must be a valid ISO-8601 UTC timestamp`);return timestamp}function parsePublicKey(value){if(value.length===0||value.length>16*1024||/\u0000/u.test(value))throw new Error("publicKeyPem is invalid");let key;try{key=createPublicKey(value)}catch{throw new Error("publicKeyPem is invalid")}if(key.type!=="public"||key.asymmetricKeyType!=="ed25519")throw new Error("publicKeyPem must be an Ed25519 public key");return key}function payload(input){return Buffer.from(`agent-forge-plugin-distribution-v${NODE_PLUGIN_TRUST_ROOT_VERSION_V1}
|
|
507
507
|
${JSON.stringify([input.version,input.source,input.pluginId,input.pluginVersion,input.manifestDigest,input.artifactDigest,input.expiresAt,input.sizeBytes,input.mediaType])}`,"utf8")}function buildNodePluginDistributionSignaturePayloadV1(input){return new Uint8Array(payload(input))}function parseSignature(value){let parts=value.split(".");if(parts.length!==3||parts[0]!==SIGNATURE_PREFIX_V1||!validKeyId(parts[1]??""))return;let encoded=parts[2]??"";if(!/^[A-Za-z0-9_-]+$/u.test(encoded))return;let bytes=Buffer.from(encoded,"base64url");if(bytes.byteLength===64)return{keyId:parts[1],bytes}}function validAt(key,current){return(key.notBefore===void 0||current>=key.notBefore)&&(key.notAfter===void 0||current<key.notAfter)}function createNodePluginTrustRootV1(options){if(!Array.isArray(options.keys)||options.keys.length===0||options.keys.length>MAX_KEYS_V1)throw new Error(`keys must contain between 1 and ${MAX_KEYS_V1} entries`);let revokedKeyIds=new Set(options.revokedKeyIds??[]);if([...revokedKeyIds].some(keyId=>!validKeyId(keyId))||options.revokedKeyIds!==void 0&&revokedKeyIds.size!==options.revokedKeyIds.length)throw new Error("revokedKeyIds is invalid or duplicated");let keys=new Map;for(let input of options.keys){if(!validKeyId(input.keyId)||keys.has(input.keyId))throw new Error("keyId is invalid or duplicated");let notBefore=parseValidity(input.notBefore,"notBefore"),notAfter=parseValidity(input.notAfter,"notAfter");if(notBefore!==void 0&¬After!==void 0&¬Before>=notAfter)throw new Error("notBefore must be earlier than notAfter");keys.set(input.keyId,{keyId:input.keyId,publicKey:parsePublicKey(input.publicKeyPem),...notBefore===void 0?{}:{notBefore},...notAfter===void 0?{}:{notAfter}})}let now=options.now??(()=>Date.now());return({descriptor})=>{let signature=parseSignature(descriptor.signature);if(signature===void 0)return{status:"rejected"};let key=keys.get(signature.keyId);if(key===void 0||revokedKeyIds.has(signature.keyId))return{status:"rejected"};let current;try{current=now()}catch{return{status:"rejected"}}if(!Number.isFinite(current)||!validAt(key,current))return{status:"rejected"};try{return verify(null,payload(descriptor),key.publicKey,signature.bytes)?{status:"accepted"}:{status:"rejected"}}catch{return{status:"rejected"}}}}var NODE_DISTRIBUTION_HOST_VERSION_V1=1,DEFAULT_TIMEOUT_MS_V1=3e4,MAX_TIMEOUT_MS_V1=12e4,DEFAULT_REDIRECTS_V1=3,MAX_REDIRECTS_V1=5,REDIRECT_STATUS=new Set([301,302,303,307,308]);function cancelledRequestError(){let error2=new Error("plugin request was cancelled");return error2.name="AbortError",error2}function throwIfRequestCancelled(request){if(request.timedOut())throw new Error("plugin request timed out");if(request.signal.aborted)throw cancelledRequestError()}function boundedPositive(value,fallback,maximum,label){let result=value??fallback;if(!Number.isSafeInteger(result)||result<=0||result>maximum)throw new Error(`${label} must be a positive integer at most ${maximum}`);return result}function allowedOrigin(value){let parsed;try{parsed=new URL(value)}catch{throw new Error("allowed origin is invalid")}if(parsed.protocol!=="http:"&&parsed.protocol!=="https:"||parsed.username||parsed.password)throw new Error("allowed origin must be an http(s) origin");if(parsed.pathname!=="/"||parsed.search!==""||parsed.hash!=="")throw new Error("allowed origin must not include a path or query");return parsed.origin}function requestUrl(value,origins){let parsed;try{parsed=new URL(value)}catch{throw new Error("plugin source URL is invalid")}if(parsed.protocol!=="http:"&&parsed.protocol!=="https:"||parsed.username||parsed.password)throw new Error("plugin source URL must use http(s) without credentials");if(!origins.has(parsed.origin))throw new Error("plugin source origin is not allowed");return parsed}function requestSignal(parent,timeoutMs){let controller=new AbortController,didTimeout=!1,abort=()=>controller.abort(parent?.reason);parent?.aborted===!0?abort():parent?.addEventListener("abort",abort,{once:!0});let timeout=setTimeout(()=>{didTimeout=!0,controller.abort()},timeoutMs);return{signal:controller.signal,timedOut:()=>didTimeout,cleanup:()=>{clearTimeout(timeout),parent?.removeEventListener("abort",abort)}}}function contentLength(response2){let value=response2.headers.get("content-length");if(value===null)return;if(!/^\d+$/u.test(value))throw new Error("plugin response content length is invalid");let result=Number(value);if(!Number.isSafeInteger(result))throw new Error("plugin response content length is invalid");return result}function contentType(response2){let value=response2.headers.get("content-type");if(value!==null)return value.split(";",1)[0]?.trim().toLowerCase()||void 0}function assertResponseMetadata(response2,descriptor){if(contentLength(response2)!==descriptor.sizeBytes)throw new Error("plugin response size mismatch");if(contentType(response2)!==descriptor.mediaType.toLowerCase())throw new Error("plugin response media type mismatch")}async function cancelBody(response2){response2.body!==null&&await response2.body.cancel().catch(()=>{})}function expectedDigest(value){let prefixed=/^(sha256|sha512):([0-9a-f]+)$/iu.exec(value);if(prefixed!==null){let algorithm=prefixed[1]?.toLowerCase(),hex=prefixed[2]?.toLowerCase();if(algorithm==="sha256"&&hex?.length===64||algorithm==="sha512"&&hex?.length===128)return{algorithm,hex}}if(/^[0-9a-f]{64}$/iu.test(value))return{algorithm:"sha256",hex:value.toLowerCase()};if(/^[0-9a-f]{128}$/iu.test(value))return{algorithm:"sha512",hex:value.toLowerCase()};throw new Error("plugin artifact digest algorithm is unsupported")}function metadataFromDescriptor(descriptor){return{version:1,source:descriptor.source,pluginId:descriptor.pluginId,pluginVersion:descriptor.pluginVersion,manifestDigest:descriptor.manifestDigest,artifactDigest:descriptor.artifactDigest,expiresAt:descriptor.expiresAt,sizeBytes:descriptor.sizeBytes,mediaType:descriptor.mediaType}}function artifactMatchesDescriptor(artifact,descriptor){return artifact.version===1&&artifact.pluginId===descriptor.pluginId&&artifact.pluginVersion===descriptor.pluginVersion&&artifact.manifestDigest===descriptor.manifestDigest&&artifact.artifactDigest===descriptor.artifactDigest&&artifact.sizeBytes===descriptor.sizeBytes&&artifact.mediaType===descriptor.mediaType&&artifact.source===descriptor.source&&artifact.expiresAt===descriptor.expiresAt}async function writeFully(file,chunk){let offset=0;for(;offset<chunk.byteLength;){let result=await file.write(chunk,offset,chunk.byteLength-offset,null);if(result.bytesWritten<=0)throw new Error("plugin artifact file write failed");offset+=result.bytesWritten}}async function createNodeHttpPluginDistributionHostV1(options){let transport=options.fetch??globalThis.fetch;if(typeof transport!="function")throw new Error("Node fetch is unavailable");if(!Array.isArray(options.allowedOrigins)||options.allowedOrigins.length===0)throw new Error("at least one allowed origin is required");let origins=new Set(options.allowedOrigins.map(allowedOrigin)),timeoutMs=boundedPositive(options.requestTimeoutMs,DEFAULT_TIMEOUT_MS_V1,MAX_TIMEOUT_MS_V1,"requestTimeoutMs"),maxRedirects=options.maxRedirects??DEFAULT_REDIRECTS_V1;if(!Number.isSafeInteger(maxRedirects)||maxRedirects<0||maxRedirects>MAX_REDIRECTS_V1)throw new Error(`maxRedirects must be an integer between 0 and ${MAX_REDIRECTS_V1}`);let userAgent=options.userAgent??"agent-forge-plugin-distribution/1";if(userAgent.length===0||userAgent.length>256||/[\r\n]/u.test(userAgent))throw new Error("userAgent is invalid");let configuredDirectory=options.artifactDirectory;if(configuredDirectory!==void 0&&!isAbsolute4(configuredDirectory))throw new Error("artifactDirectory must be absolute");let baseDirectoryPromise=configuredDirectory===void 0?mkdtemp(join14(tmpdir(),"agent-forge-plugin-distribution-")):(async()=>(await mkdir2(configuredDirectory,{recursive:!0}),await mkdtemp(join14(configuredDirectory,"agent-forge-plugin-distribution-"))))(),artifacts=new Map,activeOperations=new Set,operationsDrained,closePromise,closed=!1,assertOpen=()=>{if(closed)throw new Error("plugin distribution host is closed")},beginOperation=()=>{assertOpen();let controller=new AbortController;return activeOperations.add(controller),controller},endOperation=controller=>{activeOperations.delete(controller),activeOperations.size===0&&(operationsDrained?.(),operationsDrained=void 0)},waitForOperations=async()=>{activeOperations.size!==0&&await new Promise(resolve25=>{operationsDrained=resolve25})},fetchResponse=async(value,method,parentSignal,operationSignal2)=>{let current=requestUrl(value,origins);for(let redirect=0;;redirect+=1){if(operationSignal2.aborted)throw cancelledRequestError();assertOpen();let request=requestSignal(AbortSignal.any([parentSignal,operationSignal2].filter(Boolean)),timeoutMs),response2;try{response2=await transport(current.toString(),{method,headers:{accept:"*/*","user-agent":userAgent},redirect:"manual",signal:request.signal})}catch(error2){throw request.cleanup(),throwIfRequestCancelled(request),error2}if(!REDIRECT_STATUS.has(response2.status))return{response:response2,request};let location=response2.headers.get("location");if(await cancelBody(response2),request.cleanup(),location===null||redirect>=maxRedirects)throw new Error("plugin redirect limit exceeded");current=requestUrl(new URL(location,current).toString(),origins)}};return{version:NODE_DISTRIBUTION_HOST_VERSION_V1,host:{resolveMetadata:async input=>{let operation=beginOperation();try{let{response:response2,request}=await fetchResponse(input.descriptor.source,"HEAD",input.signal,operation.signal);try{if(response2.status<200||response2.status>=300)throw new Error("plugin metadata request failed");return assertResponseMetadata(response2,input.descriptor),metadataFromDescriptor(input.descriptor)}finally{await cancelBody(response2),request.cleanup()}}finally{endOperation(operation)}},acquireArtifact:async input=>{let operation=beginOperation(),temporaryPath,finalPath,published=!1;try{let digest=expectedDigest(input.descriptor.artifactDigest),{response:response2,request}=await fetchResponse(input.descriptor.source,"GET",input.signal,operation.signal),file;try{if(response2.status<200||response2.status>=300)throw new Error("plugin artifact request failed");if(assertResponseMetadata(response2,input.descriptor),response2.body===null)throw new Error("plugin artifact response has no body");let directory=await baseDirectoryPromise;temporaryPath=join14(directory,`.partial-${randomUUID4()}`),finalPath=join14(directory,`artifact-${randomUUID4()}`),file=await open3(temporaryPath,"wx");let reader=response2.body.getReader(),hash=createHash2(digest.algorithm),total=0;try{for(;;){throwIfRequestCancelled(request);let item=await reader.read();if(item.done)break;let chunk=item.value;if(total+=chunk.byteLength,total>input.descriptor.sizeBytes)throw new Error("plugin artifact exceeds its size limit");hash.update(chunk),await writeFully(file,chunk)}}finally{reader.releaseLock()}if(throwIfRequestCancelled(request),total!==input.descriptor.sizeBytes)throw new Error("plugin artifact size mismatch");if(hash.digest("hex")!==digest.hex)throw new Error("plugin artifact digest mismatch");await file.close(),file=void 0,await rename2(temporaryPath,finalPath),assertOpen();let artifactRef=`artifact://node-http/${randomUUID4()}`;return artifacts.set(artifactRef,{path:finalPath,descriptor:input.descriptor,readers:0}),published=!0,{artifactRef,artifactDigest:input.descriptor.artifactDigest,sizeBytes:input.descriptor.sizeBytes,mediaType:input.descriptor.mediaType}}catch(error2){throw throwIfRequestCancelled(request),error2}finally{file!==void 0&&await file.close().catch(()=>{}),await cancelBody(response2),request.cleanup()}}finally{temporaryPath!==void 0&&await rm(temporaryPath,{force:!0}).catch(()=>{}),!published&&finalPath!==void 0&&await rm(finalPath,{force:!0}).catch(()=>{}),endOperation(operation)}},releaseArtifact:async input=>{if(assertOpen(),input.signal?.aborted)throw new Error("plugin artifact release was cancelled");let record=artifacts.get(input.artifact.artifactRef);if(record===void 0)throw new Error("plugin artifact reference is unknown");if(record.readers>0)throw new Error("plugin artifact is still being read");await rm(record.path,{force:!1}),artifacts.delete(input.artifact.artifactRef)}},openArtifact:input=>(async function*(){let operation=beginOperation(),stream,acquiredRecord,abort=()=>stream?.destroy(new Error("plugin artifact read was cancelled"));try{if(input.signal?.aborted)throw new Error("plugin artifact read was cancelled");let record=artifacts.get(input.artifact.artifactRef);if(record===void 0||!artifactMatchesDescriptor(input.artifact,record.descriptor))throw new Error("plugin artifact reference is unknown");record.readers+=1,acquiredRecord=record,stream=createReadStream(record.path,{highWaterMark:64*1024}),input.signal?.addEventListener("abort",abort,{once:!0}),operation.signal.addEventListener("abort",abort,{once:!0});for await(let chunk of stream){if(input.signal?.aborted||operation.signal.aborted)throw new Error("plugin artifact read was cancelled");yield new Uint8Array(chunk)}}finally{input.signal?.removeEventListener("abort",abort),operation.signal.removeEventListener("abort",abort),stream?.destroy(),acquiredRecord!==void 0&&acquiredRecord.readers>0&&(acquiredRecord.readers-=1),endOperation(operation)}})(),close:async()=>{if(closePromise!==void 0)return await closePromise;closed=!0;for(let operation of activeOperations)operation.abort();return closePromise=(async()=>{await waitForOperations();let directory=await baseDirectoryPromise;await Promise.all([...artifacts.values()].map(record=>rm(record.path,{force:!0}))),artifacts.clear(),await rm(directory,{recursive:!0,force:!0})})(),await closePromise}}}async function createNodeHttpPluginDistributionStackV1(options){let{trustRoot,now:configuredNow,...hostOptions}=options,host=await createNodeHttpPluginDistributionHostV1(hostOptions);try{let now=configuredNow??trustRoot.now??(()=>Date.now()),verifySignature=createNodePluginTrustRootV1({...trustRoot,now}),distribution=createPluginDistributionV1({host:host.host,verifySignature,now});return Object.freeze({...host,distribution})}catch(error2){throw await host.close().catch(()=>{}),error2}}import{createHash as createHash3,randomUUID as randomUUID6}from"node:crypto";import{mkdir as mkdir4,mkdtemp as mkdtemp2,rename as rename4,rm as rm3,writeFile as writeFile3}from"node:fs/promises";import{tmpdir as tmpdir2}from"node:os";import{isAbsolute as isAbsolute6,join as join16}from"node:path";import{inflateRawSync}from"node:zlib";import{randomUUID as randomUUID5}from"node:crypto";import{mkdir as mkdir3,open as open4,readFile as readFile4,rename as rename3,rm as rm2,writeFile as writeFile2}from"node:fs/promises";import{isAbsolute as isAbsolute5,join as join15,relative as relative3}from"node:path";var PERSISTENCE_VERSION_V1=1,DEFAULT_LOCK_TIMEOUT_MS_V1=5e3,MAX_LOCK_TIMEOUT_MS_V1=6e4,MAX_RECORDS_V1=8192,MAX_FIELD_CHARS_V1=2048,NodePackageInstallPersistenceErrorV1=class extends Error{code;constructor(code){super(`Node package install persistence failed: ${code}`),this.name="NodePackageInstallPersistenceErrorV1",this.code=code}},INDEX_FILE_V12="index.v1.json",LOCK_FILE_V1="index.v1.lock";function positiveLockTimeout(value){let result=value??DEFAULT_LOCK_TIMEOUT_MS_V1;if(!Number.isSafeInteger(result)||result<1||result>MAX_LOCK_TIMEOUT_MS_V1)throw new Error(`lockTimeoutMs must be a positive integer at most ${MAX_LOCK_TIMEOUT_MS_V1}`);return result}function field(value){return typeof value=="string"&&value.length>0&&value.length<=MAX_FIELD_CHARS_V1&&!/[\u0000-\u001f\u007f]/u.test(value)}function opaque(value){return field(value)&&!/\s/u.test(value)&&!/^(?:file:|[a-z]:[\\/]|[\\/]{1,2}|\\\\)/iu.test(value)}function withinRoot2(root,value){if(!isAbsolute5(value))return!1;let relativePath=relative3(root,value);return relativePath!==""&&!relativePath.startsWith("..")&&!isAbsolute5(relativePath)}function recordKey(record){return`${record.scope}\0${record.scopeRef}\0${record.pluginId}`}function validateRecord3(root,value){if(value===null||typeof value!="object"||Array.isArray(value))throw new NodePackageInstallPersistenceErrorV1("invalid_state");let record=value,keys=["installationRef","directory","pluginId","pluginVersion","manifestDigest","scope","scopeRef","state"];if(Object.keys(record).length!==keys.length||keys.some(key=>!(key in record)))throw new NodePackageInstallPersistenceErrorV1("invalid_state");if(!opaque(record.installationRef)||!field(record.directory)||!field(record.pluginId)||!field(record.pluginVersion)||!field(record.manifestDigest)||!opaque(record.scopeRef)||record.scope!=="global"&&record.scope!=="project"||record.state!=="installed"&&record.state!=="active"&&record.state!=="retained"||!withinRoot2(root,record.directory))throw new NodePackageInstallPersistenceErrorV1("invalid_state");return Object.freeze({installationRef:record.installationRef,directory:record.directory,pluginId:record.pluginId,pluginVersion:record.pluginVersion,manifestDigest:record.manifestDigest,scope:record.scope,scopeRef:record.scopeRef,state:record.state})}function snapshot(root,values){if(values.length>MAX_RECORDS_V1)throw new NodePackageInstallPersistenceErrorV1("invalid_state");let byRef=new Set,active=new Set,result=values.map(value=>validateRecord3(root,value));for(let record of result){if(byRef.has(record.installationRef))throw new NodePackageInstallPersistenceErrorV1("invalid_state");if(byRef.add(record.installationRef),record.state==="active"){let key=recordKey(record);if(active.has(key))throw new NodePackageInstallPersistenceErrorV1("invalid_state");active.add(key)}}return Object.freeze(result)}function parseIndex2(root,raw){let parsed;try{parsed=JSON.parse(raw)}catch{throw new NodePackageInstallPersistenceErrorV1("invalid_state")}if(parsed===null||typeof parsed!="object"||Array.isArray(parsed))throw new NodePackageInstallPersistenceErrorV1("invalid_state");let value=parsed;if(Object.keys(value).length!==2||value.version!==PERSISTENCE_VERSION_V1||!Array.isArray(value.records))throw new NodePackageInstallPersistenceErrorV1("invalid_state");return snapshot(root,value.records)}function serialize(root,records){return JSON.stringify({version:PERSISTENCE_VERSION_V1,records:snapshot(root,records)})}function delay(milliseconds,signal){return new Promise((resolve25,reject2)=>{let timer=setTimeout(resolve25,milliseconds);if(signal===void 0)return;let abort=()=>{clearTimeout(timer),reject2(new NodePackageInstallPersistenceErrorV1("cancelled"))};signal.aborted?abort():signal.addEventListener("abort",abort,{once:!0})})}async function createNodePackageInstallPersistenceV1(options){if(!isAbsolute5(options.rootDirectory))throw new Error("rootDirectory must be absolute");let lockTimeoutMs=positiveLockTimeout(options.lockTimeoutMs),rootDirectory=options.rootDirectory,indexPath=join15(rootDirectory,INDEX_FILE_V12),lockPath=join15(rootDirectory,LOCK_FILE_V1);await mkdir3(rootDirectory,{recursive:!0,mode:448});let closed=!1,closePromise,read=async()=>{try{return parseIndex2(rootDirectory,await readFile4(indexPath,"utf8"))}catch(error2){if(error2 instanceof NodePackageInstallPersistenceErrorV1)throw error2;if(error2 instanceof Error&&"code"in error2&&error2.code==="ENOENT")return Object.freeze([]);throw new NodePackageInstallPersistenceErrorV1("io_failed")}},acquire=async signal=>{let deadline=Date.now()+lockTimeoutMs;for(;;){if(signal?.aborted)throw new NodePackageInstallPersistenceErrorV1("cancelled");try{return await open4(lockPath,"wx",384)}catch(error2){if(!(error2 instanceof Error&&"code"in error2&&error2.code==="EEXIST"))throw new NodePackageInstallPersistenceErrorV1("io_failed");if(Date.now()>=deadline)throw new NodePackageInstallPersistenceErrorV1("busy");await delay(10,signal)}}},release=async handle=>{await handle.close().catch(()=>{}),await rm2(lockPath,{force:!0}).catch(()=>{})},write=async records=>{let temporary=`${indexPath}.${randomUUID5()}.tmp`;try{await writeFile2(temporary,serialize(rootDirectory,records),{flag:"wx",mode:384}),await rename3(temporary,indexPath)}catch{throw await rm2(temporary,{force:!0}).catch(()=>{}),new NodePackageInstallPersistenceErrorV1("io_failed")}};return{rootDirectory,load:async(input={})=>{if(closed)throw new NodePackageInstallPersistenceErrorV1("closed");if(input.signal?.aborted)throw new NodePackageInstallPersistenceErrorV1("cancelled");return await read()},mutate:async input=>{if(closed)throw new NodePackageInstallPersistenceErrorV1("closed");if(typeof input.update!="function")throw new NodePackageInstallPersistenceErrorV1("invalid_state");let handle=await acquire(input.signal);try{let current=await read(),records=new Map(current.map(record=>[record.installationRef,record]));await input.update(records);let result=snapshot(rootDirectory,[...records.values()]);return await write(result),result}finally{await release(handle)}},close:async()=>closePromise!==void 0?await closePromise:(closed=!0,closePromise=Promise.resolve(),await closePromise)}}import{createGunzip}from"node:zlib";var TAR_BLOCK_BYTES_V1=512,TAR_NAME_LENGTH_V1=100,TAR_SIZE_OFFSET_V1=124,TAR_SIZE_LENGTH_V1=12,TAR_CHECKSUM_OFFSET_V1=148,TAR_CHECKSUM_LENGTH_V1=8,TAR_TYPEFLAG_OFFSET_V1=156,TAR_MAGIC_OFFSET_V1=257,TAR_PREFIX_OFFSET_V1=345,TAR_PREFIX_LENGTH_V1=155,USTAR_MAGIC_V1=[117,115,116,97,114];function readHeaderString(bytes,offset,length){let end=offset+length,stop=offset;for(;stop<end&&bytes[stop]!==0;)stop+=1;try{return new TextDecoder("utf-8",{fatal:!0}).decode(bytes.subarray(offset,stop))}catch{throw new NodePackageInstallErrorV1("archive_invalid")}}function readOctalHeaderField(header,offset,length){let end=offset+length,start=offset;for(;start<end&&header[start]===32;)start+=1;let stop=end;for(;stop>start&&(header[stop-1]===0||header[stop-1]===32);)stop-=1;let value=0;for(let index3=start;index3<stop;index3+=1){let byte=header[index3];if(byte<48||byte>55)throw new NodePackageInstallErrorV1("archive_invalid");if(value=value*8+(byte-48),value>Number.MAX_SAFE_INTEGER)throw new NodePackageInstallErrorV1("archive_invalid")}return value}function verifyHeaderChecksum(header){let sum=0;for(let index3=0;index3<TAR_BLOCK_BYTES_V1;index3+=1)sum+=index3>=TAR_CHECKSUM_OFFSET_V1&&index3<TAR_CHECKSUM_OFFSET_V1+TAR_CHECKSUM_LENGTH_V1?32:header[index3];if(readOctalHeaderField(header,TAR_CHECKSUM_OFFSET_V1,TAR_CHECKSUM_LENGTH_V1)!==sum)throw new NodePackageInstallErrorV1("archive_invalid")}function headerEntryName(header){for(let index3=0;index3<USTAR_MAGIC_V1.length;index3+=1)if(header[TAR_MAGIC_OFFSET_V1+index3]!==USTAR_MAGIC_V1[index3])throw new NodePackageInstallErrorV1("archive_invalid");let name=readHeaderString(header,0,TAR_NAME_LENGTH_V1),prefix=readHeaderString(header,TAR_PREFIX_OFFSET_V1,TAR_PREFIX_LENGTH_V1);return prefix===""?name:`${prefix}/${name}`}function isZeroBlock(tar,offset){for(let index3=0;index3<TAR_BLOCK_BYTES_V1;index3+=1)if(tar[offset+index3]!==0)return!1;return!0}function verifyZeroPadding(tar,dataEnd,paddedEnd){for(let index3=dataEnd;index3<paddedEnd;index3+=1)if(tar[index3]!==0)throw new NodePackageInstallErrorV1("archive_invalid")}function parsePaxPath(data){let offset=0,path15;for(;offset<data.byteLength;){let space=offset;for(;space<data.byteLength&&data[space]!==32;)space+=1;if(space>=data.byteLength)throw new NodePackageInstallErrorV1("archive_invalid");let recordLength=0;for(let index3=offset;index3<space;index3+=1){let byte=data[index3];if(byte<48||byte>57)throw new NodePackageInstallErrorV1("archive_invalid");if(recordLength=recordLength*10+(byte-48),recordLength>data.byteLength)throw new NodePackageInstallErrorV1("archive_invalid")}if(recordLength<=space-offset+1)throw new NodePackageInstallErrorV1("archive_invalid");let end=offset+recordLength;if(end>data.byteLength||data[end-1]!==10)throw new NodePackageInstallErrorV1("archive_invalid");let equals=space+1;for(;equals<end-1&&data[equals]!==61;)equals+=1;if(equals>=end-1)throw new NodePackageInstallErrorV1("archive_invalid");readHeaderString(data,space+1,equals-space-1)==="path"&&(path15=readHeaderString(data,equals+1,end-1-equals-1)),offset=end}return path15}function readGnuLongName(data){let end=data.byteLength;if(end>0&&data[end-1]===0&&(end-=1),end===0)throw new NodePackageInstallErrorV1("archive_invalid");try{return new TextDecoder("utf-8",{fatal:!0}).decode(data.subarray(0,end))}catch{throw new NodePackageInstallErrorV1("archive_invalid")}}function gunzipBounded(input,maxBytes){return new Promise((resolve25,reject2)=>{let gunzip=createGunzip(),chunks=[],total=0,settled=!1,fail=error2=>{settled||(settled=!0,gunzip.destroy(),reject2(error2))};gunzip.on("data",chunk=>{if(!settled){if(total+=chunk.byteLength,total>maxBytes){fail(new NodePackageInstallErrorV1("archive_budget_exceeded"));return}chunks.push(chunk)}}),gunzip.on("end",()=>{if(settled)return;settled=!0;let result=new Uint8Array(total),offset=0;for(let chunk of chunks)result.set(chunk,offset),offset+=chunk.byteLength;resolve25(result)}),gunzip.on("error",()=>{fail(new NodePackageInstallErrorV1("archive_invalid"))}),gunzip.end(input)})}function parseTarEntries(tar,limits){let entries=[],names2=new Set,extractedBytes=0,offset=0,pendingPath;for(;offset+TAR_BLOCK_BYTES_V1<=tar.byteLength;){let header=tar.subarray(offset,offset+TAR_BLOCK_BYTES_V1);if(isZeroBlock(tar,offset)){if(offset+2*TAR_BLOCK_BYTES_V1>tar.byteLength||!isZeroBlock(tar,offset+TAR_BLOCK_BYTES_V1))throw new NodePackageInstallErrorV1("archive_invalid");if(pendingPath!==void 0)throw new NodePackageInstallErrorV1("archive_invalid");for(let index3=offset+2*TAR_BLOCK_BYTES_V1;index3<tar.byteLength;index3+=1)if(tar[index3]!==0)throw new NodePackageInstallErrorV1("archive_invalid");return Object.freeze(entries)}verifyHeaderChecksum(header);let typeflag=String.fromCharCode(header[TAR_TYPEFLAG_OFFSET_V1]),size=readOctalHeaderField(header,TAR_SIZE_OFFSET_V1,TAR_SIZE_LENGTH_V1);if(size>limits.maxEntryBytes)throw new NodePackageInstallErrorV1("archive_budget_exceeded");let dataStart=offset+TAR_BLOCK_BYTES_V1,dataEnd=dataStart+size;if(dataEnd>tar.byteLength)throw new NodePackageInstallErrorV1("archive_invalid");let paddedEnd=Math.ceil(dataEnd/TAR_BLOCK_BYTES_V1)*TAR_BLOCK_BYTES_V1;verifyZeroPadding(tar,dataEnd,paddedEnd);let data=tar.subarray(dataStart,dataEnd);if(typeflag==="L"){pendingPath=readGnuLongName(data),offset=paddedEnd;continue}if(typeflag==="x"){let paxPath=parsePaxPath(data);paxPath!==void 0&&(pendingPath=paxPath),offset=paddedEnd;continue}if(typeflag==="g"){offset=paddedEnd;continue}if(typeflag==="1"||typeflag==="2")throw new NodePackageInstallErrorV1("archive_invalid");if(typeflag!=="\0"&&typeflag!=="0"&&typeflag!=="5")throw new NodePackageInstallErrorV1("archive_invalid");let rawName=pendingPath??headerEntryName(header);pendingPath=void 0,typeflag==="5"&&!rawName.endsWith("/")&&(rawName+="/");let normalized=normalizedEntryName(rawName);if(normalized.directory&&size!==0)throw new NodePackageInstallErrorV1("archive_invalid");if(names2.has(normalized.name))throw new NodePackageInstallErrorV1("archive_invalid");if(names2.add(normalized.name),entries.length+1>limits.maxEntries)throw new NodePackageInstallErrorV1("archive_budget_exceeded");let bytes=normalized.directory?new Uint8Array:new Uint8Array(data);if(extractedBytes+=bytes.byteLength,extractedBytes>limits.maxExtractedBytes)throw new NodePackageInstallErrorV1("archive_budget_exceeded");entries.push(Object.freeze({name:normalized.name,directory:normalized.directory,bytes})),offset=paddedEnd}throw new NodePackageInstallErrorV1("archive_invalid")}function stripNpmPackageRoot(entries){if(entries.length===0)return entries;let rootSegment=entries[0].name.split("/")[0];if(rootSegment!=="package")return entries;let sharesRoot=entry=>{if(entry.name===rootSegment)return entry.directory;let parts=entry.name.split("/");return parts.length>=2&&parts[0]===rootSegment};if(!entries.every(sharesRoot))return entries;let stripped=[];for(let entry of entries)entry.name!==rootSegment&&stripped.push(Object.freeze({...entry,name:entry.name.slice(rootSegment.length+1)}));return Object.freeze(stripped)}async function parseNodeTarGzPackageV1(input,limitsInput={}){if(!(input instanceof Uint8Array))throw new NodePackageInstallErrorV1("archive_invalid");let limits=resolveNodePackageLimitsV1(limitsInput);if(input.byteLength>limits.maxArchiveBytes)throw new NodePackageInstallErrorV1("archive_budget_exceeded");let tar=await gunzipBounded(input,limits.maxExtractedBytes);return stripNpmPackageRoot(parseTarEntries(tar,limits))}var NODE_PACKAGE_INSTALL_HOST_VERSION_V1=1,NODE_PACKAGE_FORMAT_VERSION_V12=1,DEFAULT_MAX_ARCHIVE_BYTES_V1=128*1024*1024,MAX_ARCHIVE_BYTES_V1=512*1024*1024,DEFAULT_MAX_EXTRACTED_BYTES_V1=256*1024*1024,MAX_EXTRACTED_BYTES_V1=1024*1024*1024,DEFAULT_MAX_ENTRY_BYTES_V1=64*1024*1024,MAX_ENTRY_BYTES_V1=256*1024*1024,DEFAULT_MAX_ENTRIES_V1=2048,MAX_ENTRIES_V1=8192,MAX_PACKAGE_MANIFEST_BYTES_V1=64*1024,ECOSYSTEM_MANIFEST_FILE_V12="agent-forge.json",CAPABILITY_MANIFEST_FILE_V12="plugin.json",LOCAL_FILE_HEADER_V1=67324752,CENTRAL_FILE_HEADER_V1=33639248,END_OF_CENTRAL_DIRECTORY_V1=101010256,ZIP64_END_OF_CENTRAL_DIRECTORY_V1=101075792,ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_V1=117853008,NodePackageInstallErrorV1=class extends Error{code;constructor(code){super(`Node package installation failed: ${code}`),this.name="NodePackageInstallErrorV1",this.code=code}};function createNodePackageInstallSessionLoaderV1(session){return async({manifestPath})=>({dispose:(await session.loadCapabilityPluginManifest(manifestPath)).dispose})}async function createNodePackageInstallHostForSessionV1(options,session){if(options.loadPlugin!==void 0)throw new Error("loadPlugin must be omitted when binding a session");return await createNodePackageInstallHostV1({...options,loadPlugin:createNodePackageInstallSessionLoaderV1(session)})}function positiveLimit(value,fallback,maximum,label){let result=value??fallback;if(!Number.isSafeInteger(result)||result<1||result>maximum)throw new Error(`${label} must be a positive integer at most ${maximum}`);return result}function resolveNodePackageLimitsV1(limitsInput){return{maxArchiveBytes:positiveLimit(limitsInput.maxArchiveBytes,DEFAULT_MAX_ARCHIVE_BYTES_V1,MAX_ARCHIVE_BYTES_V1,"maxArchiveBytes"),maxExtractedBytes:positiveLimit(limitsInput.maxExtractedBytes,DEFAULT_MAX_EXTRACTED_BYTES_V1,MAX_EXTRACTED_BYTES_V1,"maxExtractedBytes"),maxEntryBytes:positiveLimit(limitsInput.maxEntryBytes,DEFAULT_MAX_ENTRY_BYTES_V1,MAX_ENTRY_BYTES_V1,"maxEntryBytes"),maxEntries:positiveLimit(limitsInput.maxEntries,DEFAULT_MAX_ENTRIES_V1,MAX_ENTRIES_V1,"maxEntries")}}function readU16(bytes,offset){if(offset<0||offset+2>bytes.byteLength)throw new NodePackageInstallErrorV1("archive_invalid");return bytes[offset]|bytes[offset+1]<<8}function readU32(bytes,offset){if(offset<0||offset+4>bytes.byteLength)throw new NodePackageInstallErrorV1("archive_invalid");return(bytes[offset]|bytes[offset+1]<<8|bytes[offset+2]<<16|bytes[offset+3]<<24)>>>0}function decodeName(bytes,utf8){try{let value=new TextDecoder("utf-8",{fatal:!0}).decode(bytes);if(!utf8&&/[^\x00-\x7f]/u.test(value))throw new Error("non-ascii zip name");return value}catch{throw new NodePackageInstallErrorV1("archive_invalid")}}function normalizedEntryName(value){if(value.length===0||value.includes("\\")||/[\u0000-\u001f\u007f]/u.test(value))throw new NodePackageInstallErrorV1("archive_invalid");let directory=value.endsWith("/");if(value.startsWith("/")||/^[a-z]:/iu.test(value))throw new NodePackageInstallErrorV1("archive_invalid");let parts=value.split("/");if(directory&&parts.pop(),parts.length===0||parts.some(part=>part===""||part==="."||part===".."||part.includes(":")||/[ .]$/u.test(part)||/^(?:con|prn|aux|nul|com[1-9]|lpt[1-9])(?:\..*)?$/iu.test(part)))throw new NodePackageInstallErrorV1("archive_invalid");return{name:parts.join("/"),directory}}function crcTable(){let table=new Uint32Array(256);for(let index3=0;index3<table.length;index3+=1){let value=index3;for(let bit=0;bit<8;bit+=1)value=(value&1)===0?value>>>1:value>>>1^3988292384;table[index3]=value>>>0}return table}var CRC_TABLE_V1=crcTable();function crc32(bytes){let value=4294967295;for(let byte of bytes)value=value>>>8^CRC_TABLE_V1[(value^byte)&255];return(value^4294967295)>>>0}function findEndOfCentralDirectory(bytes){let minimum=Math.max(0,bytes.byteLength-65535-22);for(let offset=bytes.byteLength-22;offset>=minimum;offset-=1){if(readU32(bytes,offset)!==END_OF_CENTRAL_DIRECTORY_V1)continue;let disk=readU16(bytes,offset+4),centralDisk=readU16(bytes,offset+6),entries=readU16(bytes,offset+10),centralEntries=readU16(bytes,offset+8),size=readU32(bytes,offset+12),start=readU32(bytes,offset+16),commentLength=readU16(bytes,offset+20);if(disk!==0||centralDisk!==0||entries!==centralEntries||offset+22+commentLength!==bytes.byteLength)throw new NodePackageInstallErrorV1("archive_invalid");if(entries===65535||size===4294967295||start===4294967295)throw new NodePackageInstallErrorV1("archive_invalid");if(start+size>offset)throw new NodePackageInstallErrorV1("archive_invalid");return{offset,entries,size,start}}for(let offset=Math.max(0,bytes.byteLength-64);offset<bytes.byteLength-3;offset+=1){let signature=readU32(bytes,offset);if(signature===ZIP64_END_OF_CENTRAL_DIRECTORY_V1||signature===ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_V1)throw new NodePackageInstallErrorV1("archive_invalid")}throw new NodePackageInstallErrorV1("archive_invalid")}function parseCentralDirectory(bytes,limits){let end=findEndOfCentralDirectory(bytes);if(end.entries>limits.maxEntries||end.size>bytes.byteLength||end.start+end.size>end.offset)throw new NodePackageInstallErrorV1("archive_budget_exceeded");let entries=[],names2=new Set,offset=end.start;for(let index3=0;index3<end.entries;index3+=1){if(readU32(bytes,offset)!==CENTRAL_FILE_HEADER_V1)throw new NodePackageInstallErrorV1("archive_invalid");let madeBy=readU16(bytes,offset+4)>>>8,flags=readU16(bytes,offset+8),method=readU16(bytes,offset+10),crc=readU32(bytes,offset+16),compressedSize=readU32(bytes,offset+20),uncompressedSize=readU32(bytes,offset+24),nameLength=readU16(bytes,offset+28),extraLength=readU16(bytes,offset+30),commentLength=readU16(bytes,offset+32),disk=readU16(bytes,offset+34),externalAttributes=readU32(bytes,offset+38),localOffset=readU32(bytes,offset+42),nameStart=offset+46,recordEnd=nameStart+nameLength+extraLength+commentLength;if(recordEnd>end.start+end.size||disk!==0||(flags&-2057)!==0||(flags&1)!==0||(flags&64)!==0)throw new NodePackageInstallErrorV1("archive_invalid");if(method!==0&&method!==8)throw new NodePackageInstallErrorV1("archive_invalid");if(uncompressedSize>limits.maxEntryBytes||compressedSize>limits.maxArchiveBytes)throw new NodePackageInstallErrorV1("archive_budget_exceeded");let name=normalizedEntryName(decodeName(bytes.subarray(nameStart,nameStart+nameLength),(flags&2048)!==0));if(names2.has(name.name))throw new NodePackageInstallErrorV1("archive_invalid");if(names2.add(name.name),((madeBy===3?externalAttributes>>>16&65535:0)&61440)===40960)throw new NodePackageInstallErrorV1("archive_invalid");entries.push({name:name.name,directory:name.directory,flags,method,compressedSize,uncompressedSize,crc32:crc,localOffset}),offset=recordEnd}if(offset!==end.start+end.size)throw new NodePackageInstallErrorV1("archive_invalid");let spans=[];for(let entry of entries){if(entry.localOffset<0||entry.localOffset+30>end.start)throw new NodePackageInstallErrorV1("archive_invalid");if(readU32(bytes,entry.localOffset)!==LOCAL_FILE_HEADER_V1)throw new NodePackageInstallErrorV1("archive_invalid");let localNameLength=readU16(bytes,entry.localOffset+26),localExtraLength=readU16(bytes,entry.localOffset+28),dataStart=entry.localOffset+30+localNameLength+localExtraLength,dataEnd=dataStart+entry.compressedSize;if(dataStart<entry.localOffset+30||dataEnd<dataStart||dataEnd>end.start)throw new NodePackageInstallErrorV1("archive_invalid");spans.push({start:entry.localOffset,end:dataEnd})}spans.sort((left,right)=>left.start-right.start||left.end-right.end);for(let index3=1;index3<spans.length;index3+=1)if(spans[index3-1].end>spans[index3].start)throw new NodePackageInstallErrorV1("archive_invalid");return entries}function extractEntry(bytes,entry,maxEntryBytes){if(entry.directory){if(entry.compressedSize!==0||entry.uncompressedSize!==0)throw new NodePackageInstallErrorV1("archive_invalid");return new Uint8Array}if(entry.localOffset+30>bytes.byteLength)throw new NodePackageInstallErrorV1("archive_invalid");if(readU32(bytes,entry.localOffset)!==LOCAL_FILE_HEADER_V1)throw new NodePackageInstallErrorV1("archive_invalid");let localFlags=readU16(bytes,entry.localOffset+6),localMethod=readU16(bytes,entry.localOffset+8),nameLength=readU16(bytes,entry.localOffset+26),extraLength=readU16(bytes,entry.localOffset+28),localName=decodeName(bytes.subarray(entry.localOffset+30,entry.localOffset+30+nameLength),(entry.flags&2048)!==0);if(normalizedEntryName(localName).name!==entry.name||localFlags!==entry.flags||localMethod!==entry.method)throw new NodePackageInstallErrorV1("archive_invalid");let localCompressedSize=readU32(bytes,entry.localOffset+18),localUncompressedSize=readU32(bytes,entry.localOffset+22);if((entry.flags&8)===0&&(localCompressedSize!==entry.compressedSize||localUncompressedSize!==entry.uncompressedSize))throw new NodePackageInstallErrorV1("archive_invalid");let dataStart=entry.localOffset+30+nameLength+extraLength,dataEnd=dataStart+entry.compressedSize;if(dataStart>bytes.byteLength||dataEnd>bytes.byteLength)throw new NodePackageInstallErrorV1("archive_invalid");let compressed=bytes.subarray(dataStart,dataEnd),output;try{output=entry.method===0?new Uint8Array(compressed):inflateRawSync(compressed,{maxOutputLength:maxEntryBytes})}catch{throw new NodePackageInstallErrorV1("archive_invalid")}if(output.byteLength!==entry.uncompressedSize||output.byteLength>maxEntryBytes||crc32(output)!==entry.crc32)throw new NodePackageInstallErrorV1("archive_invalid");return output}function parseNodeZipPackageV1(input,limitsInput={}){if(!(input instanceof Uint8Array))throw new NodePackageInstallErrorV1("archive_invalid");let limits=resolveNodePackageLimitsV1(limitsInput);if(input.byteLength>limits.maxArchiveBytes)throw new NodePackageInstallErrorV1("archive_budget_exceeded");let descriptors=parseCentralDirectory(input,limits),extractedBytes=0;return Object.freeze(descriptors.map(descriptor=>{let bytes=extractEntry(input,descriptor,limits.maxEntryBytes);if(extractedBytes+=bytes.byteLength,extractedBytes>limits.maxExtractedBytes)throw new NodePackageInstallErrorV1("archive_budget_exceeded");return Object.freeze({name:descriptor.name,directory:descriptor.directory,bytes})}))}function manifestKeys(value){let allowed=new Set(["packageFormatVersion","id","pluginVersion","apiVersion","minHostVersion","maxHostVersion","capabilityRefs","requires","platform","testOnly"]);return Object.keys(value).every(key=>allowed.has(key))}function packageManifest(value,record){if(value===null||typeof value!="object"||Array.isArray(value))throw new NodePackageInstallErrorV1("package_manifest_invalid");let manifest=value;if(!manifestKeys(manifest)||manifest.packageFormatVersion!==NODE_PACKAGE_FORMAT_VERSION_V12||manifest.id!==record.pluginId||manifest.pluginVersion!==record.pluginVersion)throw new NodePackageInstallErrorV1("package_manifest_mismatch");if(typeof manifest.apiVersion!="string"||manifest.apiVersion!==record.manifest.apiVersion)throw new NodePackageInstallErrorV1("package_manifest_mismatch");try{if(pluginManifestDigestV1(manifest)!==record.manifestDigest)throw new NodePackageInstallErrorV1("package_manifest_mismatch")}catch(error2){throw error2 instanceof NodePackageInstallErrorV1?error2:new NodePackageInstallErrorV1("package_manifest_invalid")}}function capabilityManifest(value,record,entries){let manifest;try{manifest=parseCapabilityPluginManifest(value,"<installed plugin.json>")}catch{throw new NodePackageInstallErrorV1("package_manifest_invalid")}if(manifest.id!==record.pluginId||manifest.version!==record.pluginVersion)throw new NodePackageInstallErrorV1("package_manifest_mismatch");let entryValue=manifest.entry.startsWith("./")?manifest.entry.slice(2):manifest.entry,entry=normalizedEntryName(entryValue);if(entry.directory||!entries.some(candidate=>candidate.name===entry.name&&!candidate.directory))throw new NodePackageInstallErrorV1("package_manifest_mismatch")}function opaqueScope(value){if(typeof value!="string"||value.trim()===""||value.length>2048||/\s|[\u0000-\u001f\u007f]/u.test(value))throw new NodePackageInstallErrorV1("installation_identity_mismatch");return value}function installationKey(scope,scopeRef,pluginId){return`${scope}\0${scopeRef}\0${pluginId}`}function identityMatches(record,input){return record.pluginId===input.pluginId&&record.pluginVersion===input.pluginVersion&&record.manifestDigest===input.manifestDigest&&record.scope===input.scope&&record.scopeRef===input.scopeRef}function artifactIdentityMatchesRecord(artifact,record){return artifact.version===1&&artifact.pluginId===record.pluginId&&artifact.pluginVersion===record.pluginVersion&&artifact.manifestDigest===record.manifestDigest}function expectedArtifactDigest(value){let prefixed=/^(sha256|sha512):([0-9a-f]+)$/iu.exec(value);if(prefixed!==null){let algorithm=prefixed[1].toLowerCase(),hex=prefixed[2].toLowerCase();if(algorithm==="sha256"&&hex.length===64||algorithm==="sha512"&&hex.length===128)return{algorithm,hex}}if(/^[0-9a-f]{64}$/iu.test(value))return{algorithm:"sha256",hex:value.toLowerCase()};if(/^[0-9a-f]{128}$/iu.test(value))return{algorithm:"sha512",hex:value.toLowerCase()};throw new NodePackageInstallErrorV1("invalid_artifact")}async function collectArtifact(openArtifact,artifact,maxBytes,signal){let chunks=[],total=0;for await(let chunk of openArtifact({artifact,signal})){if(signal.aborted)throw new NodePackageInstallErrorV1("cancelled");if(!(chunk instanceof Uint8Array))throw new NodePackageInstallErrorV1("invalid_artifact");if(chunk.byteLength>maxBytes-total)throw new NodePackageInstallErrorV1("archive_budget_exceeded");chunks.push(new Uint8Array(chunk)),total+=chunk.byteLength}let result=new Uint8Array(total),offset=0;for(let chunk of chunks)result.set(chunk,offset),offset+=chunk.byteLength;return result}function packagePath(root,key){return join16(root,createHash3("sha256").update(key).digest("hex"))}async function writeEntries(root,entries,signal){await mkdir4(root,{recursive:!0,mode:448});for(let entry of entries){if(signal.aborted)throw new NodePackageInstallErrorV1("cancelled");let target=join16(root,...entry.name.split("/"));if(entry.directory){await mkdir4(target,{recursive:!0,mode:448});continue}let parent=join16(root,...entry.name.split("/").slice(0,-1));await mkdir4(parent,{recursive:!0,mode:448}),await writeFile3(target,entry.bytes,{flag:"wx",mode:384})}}async function createNodePackageInstallHostV1(options){if(typeof options.openArtifact!="function")throw new Error("openArtifact is required");let limits=resolveNodePackageLimitsV1(options),parent=options.installationDirectory??tmpdir2();if(!isAbsolute6(parent))throw new Error("installationDirectory must be absolute");if(options.persistence!==void 0&&options.persistence!=="ephemeral"&&options.persistence!=="persistent")throw new Error("persistence mode is invalid");let supportedScopes=options.supportedScopes??["global","project"];if(!Array.isArray(supportedScopes)||supportedScopes.length===0||new Set(supportedScopes).size!==supportedScopes.length||supportedScopes.some(scope=>scope!=="global"&&scope!=="project"))throw new Error("supportedScopes is invalid");await mkdir4(parent,{recursive:!0,mode:448});let persistent=options.persistence==="persistent",instanceRoot=persistent?join16(parent,"agent-forge-plugin-install-store-v1"):await mkdtemp2(join16(parent,"agent-forge-plugin-install-")),persistence=persistent?await createNodePackageInstallPersistenceV1({rootDirectory:instanceRoot,lockTimeoutMs:options.persistenceLockTimeoutMs}):void 0,records=new Map,activeByKey=new Map;if(persistence!==void 0)for(let record of await persistence.load())records.set(record.installationRef,{...record});for(let record of records.values())record.state==="active"&&activeByKey.set(installationKey(record.scope,record.scopeRef,record.pluginId),record.installationRef);let closed=!1,activeOperations=new Set,runtimeHandles=new Map,applyPersistentSnapshot=snapshot2=>{records.clear(),activeByKey.clear();for(let value of snapshot2)records.set(value.installationRef,{...value});for(let value of records.values())value.state==="active"&&activeByKey.set(installationKey(value.scope,value.scopeRef,value.pluginId),value.installationRef)},commitRecords=async update=>{if(persistence===void 0){await update(records);return}applyPersistentSnapshot(await persistence.mutate({update}))},drained,closePromise,begin=parentSignal=>{if(closed)throw new NodePackageInstallErrorV1("host_closed");let controller=new AbortController;return parentSignal?.aborted?controller.abort(parentSignal.reason):parentSignal?.addEventListener("abort",()=>controller.abort(parentSignal.reason),{once:!0}),activeOperations.add(controller),{controller,signal:controller.signal}},end=controller=>{activeOperations.delete(controller),activeOperations.size===0&&(drained?.(),drained=void 0)},waitDrained=async()=>{activeOperations.size!==0&&await new Promise(resolve25=>{drained=resolve25})},getRecord=(installation,record,scope,scopeRef)=>{let value=records.get(installation.installationRef);if(value===void 0||installation.pluginId!==record.pluginId||installation.pluginVersion!==record.pluginVersion||installation.manifestDigest!==record.manifestDigest||installation.scope!==scope||installation.scopeRef!==scopeRef||!identityMatches(value,{pluginId:record.pluginId,pluginVersion:record.pluginVersion,manifestDigest:record.manifestDigest,scope,scopeRef}))throw new NodePackageInstallErrorV1("installation_identity_mismatch");return value},disposeRuntime=async installationRef=>{let handle=runtimeHandles.get(installationRef);handle!==void 0&&(handle.dispose!==void 0&&await Promise.resolve(handle.dispose()),runtimeHandles.delete(installationRef))},loadRuntime=async(installation,record,directory,signal)=>{if(options.loadPlugin!==void 0)try{return await options.loadPlugin({installation,record,directory,manifestPath:join16(directory,CAPABILITY_MANIFEST_FILE_V12),signal})??void 0}catch(error2){throw error2 instanceof NodePackageInstallErrorV1?error2:new NodePackageInstallErrorV1("installation_io_failed")}},host={version:NODE_PACKAGE_INSTALL_HOST_VERSION_V1,supportedScopes:Object.freeze([...supportedScopes]),getInstallationDirectory(input){let record=records.get(input.installation.installationRef);if(record===void 0||record.pluginId!==input.installation.pluginId||record.pluginVersion!==input.installation.pluginVersion||record.manifestDigest!==input.installation.manifestDigest||record.scope!==input.installation.scope||record.scopeRef!==input.installation.scopeRef)throw new NodePackageInstallErrorV1("installation_unknown");return record.directory},async install(input){let operation=begin(input.signal),staging;try{if(input.artifact===void 0)throw new NodePackageInstallErrorV1("invalid_artifact");if(!artifactIdentityMatchesRecord(input.artifact,input.record))throw new NodePackageInstallErrorV1("invalid_artifact");let mediaType=input.artifact.mediaType.toLowerCase();if(mediaType!=="application/zip"&&mediaType!=="application/gzip")throw new NodePackageInstallErrorV1("unsupported_media_type");let scopeRef=opaqueScope(input.scopeRef),bytes=await collectArtifact(options.openArtifact,input.artifact,limits.maxArchiveBytes,operation.signal);if(input.artifact.sizeBytes!==bytes.byteLength)throw new NodePackageInstallErrorV1("invalid_artifact");let digest=expectedArtifactDigest(input.artifact.artifactDigest);if(createHash3(digest.algorithm).update(bytes).digest("hex")!==digest.hex)throw new NodePackageInstallErrorV1("invalid_artifact");let entries=mediaType==="application/gzip"?await parseNodeTarGzPackageV1(bytes,limits):parseNodeZipPackageV1(bytes,limits),manifestEntry=entries.find(entry=>entry.name===ECOSYSTEM_MANIFEST_FILE_V12&&!entry.directory);if(manifestEntry===void 0)throw new NodePackageInstallErrorV1("package_manifest_missing");if(manifestEntry.bytes.byteLength>MAX_PACKAGE_MANIFEST_BYTES_V1)throw new NodePackageInstallErrorV1("package_manifest_invalid");let manifest;try{manifest=JSON.parse(new TextDecoder("utf-8",{fatal:!0}).decode(manifestEntry.bytes))}catch{throw new NodePackageInstallErrorV1("package_manifest_invalid")}packageManifest(manifest,input.record);let capabilityEntry=entries.find(entry=>entry.name===CAPABILITY_MANIFEST_FILE_V12&&!entry.directory);if(capabilityEntry===void 0)throw new NodePackageInstallErrorV1("package_manifest_missing");if(capabilityEntry.bytes.byteLength>MAX_PACKAGE_MANIFEST_BYTES_V1)throw new NodePackageInstallErrorV1("package_manifest_invalid");let capability;try{capability=JSON.parse(new TextDecoder("utf-8",{fatal:!0}).decode(capabilityEntry.bytes))}catch{throw new NodePackageInstallErrorV1("package_manifest_invalid")}capabilityManifest(capability,input.record,entries);let key=installationKey(input.scope,scopeRef,input.record.pluginId);staging=join16(instanceRoot,`.staging-${randomUUID6()}`),await writeEntries(staging,entries,operation.signal);let installRef=`plugin-install://node-zip/${randomUUID6()}`,destination=packagePath(instanceRoot,`${key}\0${installRef}`);await rename4(staging,destination),staging=void 0;let installedRecord={installationRef:installRef,directory:destination,pluginId:input.record.pluginId,pluginVersion:input.record.pluginVersion,manifestDigest:input.record.manifestDigest,scope:input.scope,scopeRef,state:"installed"};try{await commitRecords(values=>{values.set(installRef,installedRecord)})}catch(error2){throw await rm3(destination,{recursive:!0,force:!0}).catch(()=>{}),error2}return{installationRef:installRef,scope:input.scope,scopeRef}}catch(error2){throw operation.signal.aborted||input.signal?.aborted?new NodePackageInstallErrorV1("cancelled"):error2 instanceof NodePackageInstallErrorV1?error2:new NodePackageInstallErrorV1("installation_io_failed")}finally{staging!==void 0&&await rm3(staging,{recursive:!0,force:!0}).catch(()=>{}),end(operation.controller)}},async activate(input){let operation=begin(input.signal),candidate;try{let scopeRef=opaqueScope(input.scopeRef),record=getRecord(input.installation,input.record,input.scope,scopeRef);if(record.state!=="installed")throw new NodePackageInstallErrorV1("installation_identity_mismatch");candidate=await loadRuntime(input.installation,input.record,record.directory,operation.signal);let key=installationKey(input.scope,scopeRef,input.record.pluginId),previousRef=activeByKey.get(key);previousRef!==void 0&&records.get(previousRef)!==void 0&&await disposeRuntime(previousRef),await commitRecords(values=>{let candidateRecord=values.get(input.installation.installationRef);if(candidateRecord===void 0)throw new NodePackageInstallErrorV1("installation_identity_mismatch");if(previousRef!==void 0){let previousRecord=values.get(previousRef);previousRecord!==void 0&&values.set(previousRef,{...previousRecord,state:"retained"})}values.set(input.installation.installationRef,{...candidateRecord,state:"active"})}),activeByKey.set(key,input.installation.installationRef),candidate!==void 0&&runtimeHandles.set(input.installation.installationRef,candidate),candidate=void 0}catch(error2){throw candidate?.dispose!==void 0&&await Promise.resolve(candidate.dispose()).catch(()=>{}),error2 instanceof NodePackageInstallErrorV1?error2:new NodePackageInstallErrorV1("installation_io_failed")}finally{end(operation.controller)}},async rollback(input){let operation=begin(input.signal),candidate;try{let scopeRef=opaqueScope(input.scopeRef),failed=records.get(input.failed.installationRef);if(failed===void 0||!identityMatches(failed,{pluginId:input.failed.pluginId,pluginVersion:input.failed.pluginVersion,manifestDigest:input.failed.manifestDigest,scope:input.scope,scopeRef}))throw new NodePackageInstallErrorV1("installation_identity_mismatch");let previous=records.get(input.previous.installationRef);if(previous===void 0||!identityMatches(previous,{pluginId:input.previous.pluginId,pluginVersion:input.previous.pluginVersion,manifestDigest:input.previous.manifestDigest,scope:input.scope,scopeRef})||previous.state!=="active"&&previous.state!=="retained"||failed.pluginId!==previous.pluginId)throw new NodePackageInstallErrorV1("installation_identity_mismatch");let previousInstallation={version:1,pluginId:previous.pluginId,pluginVersion:previous.pluginVersion,manifestDigest:previous.manifestDigest,scope:previous.scope,scopeRef:previous.scopeRef,installationRef:input.previous.installationRef,state:"active"};candidate=await loadRuntime(previousInstallation,void 0,previous.directory,operation.signal),await disposeRuntime(input.failed.installationRef),await rm3(failed.directory,{recursive:!0,force:!0}),await commitRecords(values=>{values.delete(input.failed.installationRef);let previousRecord=values.get(input.previous.installationRef);previousRecord!==void 0&&values.set(input.previous.installationRef,{...previousRecord,state:"active"})}),activeByKey.set(installationKey(input.scope,scopeRef,failed.pluginId),input.previous.installationRef),candidate!==void 0&&runtimeHandles.set(input.previous.installationRef,candidate),candidate=void 0}catch(error2){throw candidate?.dispose!==void 0&&await Promise.resolve(candidate.dispose()).catch(()=>{}),error2 instanceof NodePackageInstallErrorV1?error2:new NodePackageInstallErrorV1("installation_io_failed")}finally{end(operation.controller)}},async uninstall(input){let operation=begin(input.signal);try{let scopeRef=opaqueScope(input.scopeRef),record=records.get(input.installation.installationRef);if(record===void 0||!identityMatches(record,{pluginId:input.installation.pluginId,pluginVersion:input.installation.pluginVersion,manifestDigest:input.installation.manifestDigest,scope:input.scope,scopeRef}))throw new NodePackageInstallErrorV1("installation_unknown");await disposeRuntime(input.installation.installationRef),await rm3(record.directory,{recursive:!0,force:!1}),await commitRecords(values=>{values.delete(input.installation.installationRef)});let key=installationKey(input.scope,scopeRef,record.pluginId);activeByKey.get(key)===input.installation.installationRef&&activeByKey.delete(key)}finally{end(operation.controller)}},async close(){if(closePromise!==void 0)return await closePromise;closed=!0;for(let operation of activeOperations)operation.abort();return closePromise=(async()=>{await waitDrained();let disposeError=!1;for(let installationRef of runtimeHandles.keys())try{await disposeRuntime(installationRef)}catch{disposeError=!0}if(persistence===void 0?await rm3(instanceRoot,{recursive:!0,force:!0}):await persistence.close(),records.clear(),activeByKey.clear(),disposeError)throw new NodePackageInstallErrorV1("installation_io_failed")})(),await closePromise}};if(options.loadPlugin!==void 0)try{for(let record of records.values()){if(record.state!=="active")continue;let installation={version:1,pluginId:record.pluginId,pluginVersion:record.pluginVersion,manifestDigest:record.manifestDigest,scope:record.scope,scopeRef:record.scopeRef,installationRef:record.installationRef,state:"active"},runtime=await loadRuntime(installation,void 0,record.directory,new AbortController().signal);runtime!==void 0&&runtimeHandles.set(record.installationRef,runtime)}}catch(error2){throw await host.close().catch(()=>{}),error2 instanceof NodePackageInstallErrorV1?error2:new NodePackageInstallErrorV1("installation_io_failed")}return host}import{createHash as createHash5,randomUUID as randomUUID7}from"node:crypto";import{lstatSync as lstatSync2}from"node:fs";import{lstat,readdir,readFile as readFile5}from"node:fs/promises";import{join as join17}from"node:path";function isMissingError2(error2){return typeof error2!="object"||error2===null?!1:"code"in error2&&error2.code==="ENOENT"}async function collectDirectory(root,relative14,limits,entries,budget,signal){if(signal?.aborted)throw new NodePackageInstallErrorV1("cancelled");let dirents=await readdir(relative14.length===0?root:join17(root,...relative14.split("/")),{withFileTypes:!0});dirents.sort((left,right)=>left.name<right.name?-1:left.name>right.name?1:0);for(let dirent of dirents){if(signal?.aborted)throw new NodePackageInstallErrorV1("cancelled");let childRelative=relative14.length===0?dirent.name:`${relative14}/${dirent.name}`;if(normalizedEntryName(childRelative),dirent.isSymbolicLink())throw new NodePackageInstallErrorV1("archive_invalid");let childPath=join17(root,...childRelative.split("/")),stats=await lstat(childPath);if(stats.isSymbolicLink())throw new NodePackageInstallErrorV1("archive_invalid");if(stats.isDirectory()){await collectDirectory(root,childRelative,limits,entries,budget,signal);continue}if(!stats.isFile())throw new NodePackageInstallErrorV1("archive_invalid");if(entries.length+1>limits.maxEntries)throw new NodePackageInstallErrorV1("archive_budget_exceeded");let bytes=await readFile5(childPath);if(bytes.byteLength>limits.maxEntryBytes)throw new NodePackageInstallErrorV1("archive_budget_exceeded");if(budget.totalBytes+=bytes.byteLength,budget.totalBytes>limits.maxExtractedBytes)throw new NodePackageInstallErrorV1("archive_budget_exceeded");entries.push(Object.freeze({name:childRelative,directory:!1,bytes:new Uint8Array(bytes)}))}}async function collectLocalDirectoryPackageEntriesV1(rootDirectory,limitsInput={},signal){if(typeof rootDirectory!="string"||rootDirectory.trim().length===0)throw new NodePackageInstallErrorV1("archive_invalid");let stats=await lstat(rootDirectory).catch(error2=>{throw isMissingError2(error2)?new NodePackageInstallErrorV1("archive_invalid"):error2});if(!stats.isDirectory()||stats.isSymbolicLink())throw new NodePackageInstallErrorV1("archive_invalid");let limits=resolveNodePackageLimitsV1(limitsInput),entries=[];return await collectDirectory(rootDirectory,"",limits,entries,{totalBytes:0},signal),Object.freeze(entries)}async function readLocalPackageFileV1(path15,limitsInput={},signal){if(signal?.aborted)throw new NodePackageInstallErrorV1("cancelled");if(typeof path15!="string"||path15.trim().length===0)throw new NodePackageInstallErrorV1("archive_invalid");let stats=await lstat(path15).catch(error2=>{throw isMissingError2(error2)?new NodePackageInstallErrorV1("archive_invalid"):error2});if(stats.isSymbolicLink()||!stats.isFile())throw new NodePackageInstallErrorV1("archive_invalid");let limits=resolveNodePackageLimitsV1(limitsInput);if(stats.size>limits.maxArchiveBytes)throw new NodePackageInstallErrorV1("archive_budget_exceeded");let bytes=await readFile5(path15);if(bytes.byteLength!==stats.size||bytes.byteLength>limits.maxArchiveBytes)throw new NodePackageInstallErrorV1("archive_budget_exceeded");return new Uint8Array(bytes)}var DEFAULT_NPM_REGISTRY_V1="https://registry.npmjs.org",DEFAULT_TIMEOUT_MS_V12=15e3,MAX_TIMEOUT_MS_V12=12e4,DEFAULT_MAX_RESPONSE_BYTES_V1=8*1024*1024,MAX_RESPONSE_BYTES_V1=16*1024*1024,DEFAULT_MAX_TARBALL_BYTES_V1=128*1024*1024,MAX_TARBALL_BYTES_V1=512*1024*1024,DEFAULT_REDIRECTS_V12=3,MAX_REDIRECTS_V12=5,REDIRECT_STATUS2=new Set([301,302,303,307,308]),NodeNpmRegistrySourceErrorV1=class extends Error{code;constructor(code,message){super(message),this.name="NodeNpmRegistrySourceErrorV1",this.code=code}};function sriToIntegrityV1(sri){let match2=/^(sha512|sha256)-([A-Za-z0-9+/]+={0,2})$/u.exec(sri.trim());if(match2===null)throw new NodeNpmRegistrySourceErrorV1("integrity_unsupported","npm integrity algorithm is unsupported");let algorithm=match2[1],raw;try{raw=Buffer.from(match2[2],"base64")}catch{throw new NodeNpmRegistrySourceErrorV1("integrity_unsupported","npm integrity encoding is invalid")}if(algorithm==="sha256"&&raw.byteLength!==32||algorithm==="sha512"&&raw.byteLength!==64)throw new NodeNpmRegistrySourceErrorV1("integrity_unsupported","npm integrity length is invalid");let hex=raw.toString("hex").toLowerCase();if(hex.length===0)throw new NodeNpmRegistrySourceErrorV1("integrity_unsupported","npm integrity is invalid");return{algorithm,hex}}function parseVersionTriple(value){let match2=/^(\d+)\.(\d+)\.(\d+)/u.exec(value.replace(/^[vV]/u,""));if(match2===null)return;let major=Number.parseInt(match2[1],10),minor=Number.parseInt(match2[2],10),patch=Number.parseInt(match2[3],10);if(!(!Number.isSafeInteger(major)||!Number.isSafeInteger(minor)||!Number.isSafeInteger(patch)))return[major,minor,patch]}function plainVersion(value){return value.replace(/^[vV]/u,"")}function selectNpmPackageVersionV1(versions,range2){if(!Array.isArray(versions))return;let candidates=versions.filter(value=>typeof value=="string"&&parseVersionTriple(value)!==void 0);if(candidates.length===0)return;if(range2===void 0||range2==="latest")return candidates.reduce((left,right)=>comparePluginVersionsV1(right,left)>0?right:left);let exact=plainVersion(range2.replace(/^[=~^]/u,""));if(!range2.startsWith("^")&&!range2.startsWith("~"))return candidates.find(value=>plainVersion(value)===exact);let bound=parseVersionTriple(exact);if(bound===void 0)return;let[major,minor]=bound,upper=range2.startsWith("^")?`${major+1}.0.0`:`${major}.${minor+1}.0`;if(candidates=candidates.filter(value=>comparePluginVersionsV1(value,exact)>=0&&comparePluginVersionsV1(value,upper)<0),candidates.length!==0)return candidates.reduce((left,right)=>comparePluginVersionsV1(right,left)>0?right:left)}function boundedPositive2(value,fallback,maximum,label){let result=value??fallback;if(!Number.isSafeInteger(result)||result<=0||result>maximum)throw new NodeNpmRegistrySourceErrorV1("invalid_configuration",`${label} must be a positive integer at most ${maximum}`);return result}function registryOrigin(value){let parsed;try{parsed=new URL(value)}catch{throw new NodeNpmRegistrySourceErrorV1("invalid_configuration","npm registry origin is invalid")}if(parsed.protocol!=="http:"&&parsed.protocol!=="https:"||parsed.username!==""||parsed.password!=="")throw new NodeNpmRegistrySourceErrorV1("invalid_configuration","npm registry origin must be http(s) without credentials");if(parsed.pathname!=="/"||parsed.search!==""||parsed.hash!=="")throw new NodeNpmRegistrySourceErrorV1("invalid_configuration","npm registry origin must not include a path, query, or fragment");return parsed.origin}function packumentUrl(registryOriginValue,name){let scopeAt=name.indexOf("/");if(name.startsWith("@")&&scopeAt>0){let scope=name.slice(0,scopeAt),packageName=name.slice(scopeAt+1);return new URL(`${registryOriginValue}/${scope}%2F${encodeURIComponent(packageName)}`)}if(scopeAt>=0)throw new NodeNpmRegistrySourceErrorV1("invalid_configuration","npm package name is invalid");return new URL(`${registryOriginValue}/${encodeURIComponent(name)}`)}function tarballUrl(value){let parsed;try{parsed=new URL(value)}catch{throw new NodeNpmRegistrySourceErrorV1("invalid_response","npm tarball URL is invalid")}if(parsed.protocol!=="http:"&&parsed.protocol!=="https:"||parsed.username!==""||parsed.password!=="")throw new NodeNpmRegistrySourceErrorV1("invalid_response","npm tarball URL must use http(s) without credentials");if(parsed.hash!=="")throw new NodeNpmRegistrySourceErrorV1("invalid_response","npm tarball URL must not include a fragment");return parsed}function isAbortLike2(error2){return error2 instanceof Error&&(error2.name==="AbortError"||error2.name==="AbortSignalError")}function requestSignal2(parent,timeoutMs){let controller=new AbortController,timedOut=!1,abort=()=>controller.abort(parent?.reason);parent?.aborted===!0?abort():parent?.addEventListener("abort",abort,{once:!0});let timeout=setTimeout(()=>{timedOut=!0,controller.abort()},timeoutMs);return{signal:controller.signal,timedOut:()=>timedOut,cleanup:()=>{clearTimeout(timeout),parent?.removeEventListener("abort",abort)}}}function isJsonResponse(response2){let contentType2=response2.headers.get("content-type");if(contentType2===null)return!1;let mediaType=contentType2.split(";",1)[0]?.trim().toLowerCase();return mediaType==="application/json"||mediaType==="application/vnd.npm.install-v1+json"}async function readBody(response2,maxBytes,signal){if(response2.body===null)throw new NodeNpmRegistrySourceErrorV1("invalid_response","npm registry response has no body");let reader=response2.body.getReader(),chunks=[],total=0;try{for(;;){if(signal.aborted)throw new DOMException("aborted","AbortError");let item=await reader.read();if(item.done)break;if(total+=item.value.byteLength,total>maxBytes)throw new NodeNpmRegistrySourceErrorV1("response_too_large","npm registry response exceeds the configured size limit");chunks.push(item.value)}}finally{reader.releaseLock()}let bytes=new Uint8Array(total),offset=0;for(let chunk of chunks)bytes.set(chunk,offset),offset+=chunk.byteLength;return bytes}function parsePackument(bytes){let value;try{value=JSON.parse(new TextDecoder("utf-8",{fatal:!0}).decode(bytes))}catch{throw new NodeNpmRegistrySourceErrorV1("invalid_response","npm registry response is not valid JSON")}if(typeof value!="object"||value===null||Array.isArray(value))throw new NodeNpmRegistrySourceErrorV1("invalid_response","npm packument is invalid");let packument=value;if(typeof packument.versions!="object"||packument.versions===null||Array.isArray(packument.versions))throw new NodeNpmRegistrySourceErrorV1("invalid_response","npm packument has no version table");return packument.versions}function createNodeNpmRegistrySourceV1(options={}){let transport=options.fetch??globalThis.fetch;if(typeof transport!="function")throw new NodeNpmRegistrySourceErrorV1("invalid_configuration","Node fetch is unavailable");let registry=registryOrigin(options.registry??DEFAULT_NPM_REGISTRY_V1);if(options.token!==void 0&&(options.token.length===0||options.token.length>4096||/[\r\n\s]/u.test(options.token)))throw new NodeNpmRegistrySourceErrorV1("invalid_configuration","npm registry token is invalid");let token=options.token,timeoutMs=boundedPositive2(options.requestTimeoutMs,DEFAULT_TIMEOUT_MS_V12,MAX_TIMEOUT_MS_V12,"requestTimeoutMs"),maxResponseBytes=boundedPositive2(options.maxResponseBytes,DEFAULT_MAX_RESPONSE_BYTES_V1,MAX_RESPONSE_BYTES_V1,"maxResponseBytes"),maxTarballBytes=boundedPositive2(options.maxTarballBytes,DEFAULT_MAX_TARBALL_BYTES_V1,MAX_TARBALL_BYTES_V1,"maxTarballBytes"),maxRedirects=options.maxRedirects??DEFAULT_REDIRECTS_V12;if(!Number.isSafeInteger(maxRedirects)||maxRedirects<0||maxRedirects>MAX_REDIRECTS_V12)throw new NodeNpmRegistrySourceErrorV1("invalid_configuration",`maxRedirects must be an integer between 0 and ${MAX_REDIRECTS_V12}`);let userAgent=options.userAgent??"agent-forge-plugin-npm/1";if(userAgent.length===0||userAgent.length>256||/[\r\n]/u.test(userAgent))throw new NodeNpmRegistrySourceErrorV1("invalid_configuration","userAgent is invalid");let fetchFollowingRedirects=async(url,headers,parentSignal)=>{let current=url;for(let redirect=0;;redirect+=1){let request=requestSignal2(parentSignal,timeoutMs),response2;try{response2=await transport(current.toString(),{method:"GET",headers:{accept:"*/*","user-agent":userAgent,...headers},redirect:"manual",signal:request.signal})}catch(error2){throw request.cleanup(),request.timedOut()?new NodeNpmRegistrySourceErrorV1("request_timed_out","npm registry request timed out"):isAbortLike2(error2)?new NodeNpmRegistrySourceErrorV1("cancelled","npm registry request was cancelled"):new NodeNpmRegistrySourceErrorV1("request_failed","npm registry request failed")}if(!REDIRECT_STATUS2.has(response2.status))return{response:response2,request};let location=response2.headers.get("location");if(await response2.body?.cancel().catch(()=>{}),request.cleanup(),location===null||redirect>=maxRedirects)throw new NodeNpmRegistrySourceErrorV1("request_failed","npm registry redirect limit exceeded");current=tarballUrl(new URL(location,current).toString())}};return{version:1,registry,resolveNpmPackage:async input=>{if(input.signal?.aborted===!0)throw new NodeNpmRegistrySourceErrorV1("cancelled","npm registry request was cancelled");let endpoint=packumentUrl(registry,input.name),authorization=token===void 0?{}:{authorization:`Bearer ${token}`},{response:response2,request}=await fetchFollowingRedirects(endpoint,authorization,input.signal);try{if(response2.status===404||response2.status===403)throw new NodeNpmRegistrySourceErrorV1("package_not_found","npm package was not found on the registry");if(response2.status<200||response2.status>=300)throw new NodeNpmRegistrySourceErrorV1("request_failed","npm registry request did not succeed");if(!isJsonResponse(response2))throw new NodeNpmRegistrySourceErrorV1("invalid_response","npm registry response must be JSON");let versions=parsePackument(await readBody(response2,maxResponseBytes,request.signal)),version=selectNpmPackageVersionV1(Object.keys(versions),input.range),dist=version===void 0?void 0:versions[version]?.dist;if(version===void 0||dist===void 0||typeof dist.tarball!="string"||dist.tarball.length===0)throw new NodeNpmRegistrySourceErrorV1("version_not_found","No npm package version matches the requested range");let integrityValue=dist.integrity,integrity=typeof integrityValue=="string"&&integrityValue.length>0?sriToIntegrityV1(integrityValue):void 0;if(integrity===void 0)throw new NodeNpmRegistrySourceErrorV1("invalid_response","npm package version has no integrity field");return{version,tarballUrl:tarballUrl(dist.tarball).toString(),integrity,distInfo:dist}}finally{await response2.body?.cancel().catch(()=>{}),request.cleanup()}},fetchTarball:async input=>{if(input.signal?.aborted===!0)throw new NodeNpmRegistrySourceErrorV1("cancelled","npm tarball download was cancelled");let endpoint=tarballUrl(input.url),authorization=token===void 0?{}:{authorization:`Bearer ${token}`},{response:response2,request}=await fetchFollowingRedirects(endpoint,authorization,input.signal);try{if(response2.status<200||response2.status>=300)throw new NodeNpmRegistrySourceErrorV1("request_failed","npm tarball download did not succeed");return await readBody(response2,maxTarballBytes,request.signal)}finally{await response2.body?.cancel().catch(()=>{}),request.cleanup()}}}}function sniffMagic(bytes){if(bytes.byteLength>=4&&bytes[0]===80&&bytes[1]===75&&(bytes[2]===3||bytes[2]===5||bytes[2]===7))return"application/zip";if(bytes.byteLength>=2&&bytes[0]===31&&bytes[1]===139)return"application/gzip"}function extensionMediaType(fileName){let value=fileName.toLowerCase();if(value.endsWith(".zip"))return"application/zip";if(value.endsWith(".tgz")||value.endsWith(".tar.gz"))return"application/gzip"}function detectPluginPackageMediaTypeV1(bytes,fileName){if(!(bytes instanceof Uint8Array))throw new NodePackageInstallErrorV1("archive_invalid");let magic=sniffMagic(bytes),extension=fileName===void 0?void 0:extensionMediaType(fileName);if(magic===void 0)throw new NodePackageInstallErrorV1("unsupported_media_type");if(extension!==void 0&&extension!==magic)throw new NodePackageInstallErrorV1("unsupported_media_type");return magic}import{createHash as createHash4}from"node:crypto";var DEFAULT_TIMEOUT_MS_V13=3e4,MAX_TIMEOUT_MS_V13=12e4,DEFAULT_MAX_PACKAGE_BYTES_V1=128*1024*1024,MAX_PACKAGE_BYTES_V1=512*1024*1024,DEFAULT_REDIRECTS_V13=3,MAX_REDIRECTS_V13=5,REDIRECT_STATUS3=new Set([301,302,303,307,308]),NodeUrlPackageSourceErrorV1=class extends Error{code;constructor(code,message){super(message),this.name="NodeUrlPackageSourceErrorV1",this.code=code}};function boundedPositive3(value,fallback,maximum,label){let result=value??fallback;if(!Number.isSafeInteger(result)||result<=0||result>maximum)throw new NodeUrlPackageSourceErrorV1("invalid_configuration",`${label} must be a positive integer at most ${maximum}`);return result}function packageUrl(value){let parsed;try{parsed=new URL(value)}catch{throw new NodeUrlPackageSourceErrorV1("invalid_url","plugin package URL is invalid")}if(parsed.protocol!=="http:"&&parsed.protocol!=="https:"||parsed.username!==""||parsed.password!=="")throw new NodeUrlPackageSourceErrorV1("invalid_url","plugin package URL must use http(s) without credentials");if(parsed.hash!=="")throw new NodeUrlPackageSourceErrorV1("invalid_url","plugin package URL must not include a fragment");return parsed}function isAbortLike3(error2){return error2 instanceof Error&&(error2.name==="AbortError"||error2.name==="AbortSignalError")}async function downloadNodeUrlPackageV1(options,input){let transport=options.fetch??globalThis.fetch;if(typeof transport!="function")throw new NodeUrlPackageSourceErrorV1("invalid_configuration","Node fetch is unavailable");let timeoutMs=boundedPositive3(options.requestTimeoutMs,DEFAULT_TIMEOUT_MS_V13,MAX_TIMEOUT_MS_V13,"requestTimeoutMs"),maxPackageBytes=boundedPositive3(options.maxPackageBytes,DEFAULT_MAX_PACKAGE_BYTES_V1,MAX_PACKAGE_BYTES_V1,"maxPackageBytes"),maxRedirects=options.maxRedirects??DEFAULT_REDIRECTS_V13;if(!Number.isSafeInteger(maxRedirects)||maxRedirects<0||maxRedirects>MAX_REDIRECTS_V13)throw new NodeUrlPackageSourceErrorV1("invalid_configuration",`maxRedirects must be an integer between 0 and ${MAX_REDIRECTS_V13}`);let userAgent=options.userAgent??"agent-forge-plugin-url/1";if(userAgent.length===0||userAgent.length>256||/[\r\n]/u.test(userAgent))throw new NodeUrlPackageSourceErrorV1("invalid_configuration","userAgent is invalid");if(input.expectedDigestHex!==void 0&&!/^[0-9a-f]{64}$/u.test(input.expectedDigestHex))throw new NodeUrlPackageSourceErrorV1("invalid_url","expected sha256 digest is invalid");let current=packageUrl(input.url),response2,controller=new AbortController,timedOut=!1,abort=()=>controller.abort(input.signal?.reason);input.signal?.aborted===!0?abort():input.signal?.addEventListener("abort",abort,{once:!0});let timeout=setTimeout(()=>{timedOut=!0,controller.abort()},timeoutMs);try{for(let redirect=0;;redirect+=1){if(controller.signal.aborted)throw new NodeUrlPackageSourceErrorV1("cancelled","plugin package download was cancelled");let hop;try{hop=await transport(current.toString(),{method:"GET",headers:{accept:"*/*","user-agent":userAgent},redirect:"manual",signal:controller.signal})}catch(error2){throw timedOut?new NodeUrlPackageSourceErrorV1("request_timed_out","plugin package download timed out"):isAbortLike3(error2)||input.signal?.aborted===!0?new NodeUrlPackageSourceErrorV1("cancelled","plugin package download was cancelled"):new NodeUrlPackageSourceErrorV1("request_failed","plugin package download failed")}if(!REDIRECT_STATUS3.has(hop.status)){response2=hop;break}let location=hop.headers.get("location");if(await hop.body?.cancel().catch(()=>{}),location===null||redirect>=maxRedirects)throw new NodeUrlPackageSourceErrorV1("request_failed","plugin package redirect limit exceeded");current=packageUrl(new URL(location,current).toString())}if(response2===void 0)throw new NodeUrlPackageSourceErrorV1("request_failed","plugin package download failed");if(response2.status<200||response2.status>=300)throw new NodeUrlPackageSourceErrorV1("request_failed","plugin package download did not succeed");if(response2.body===null)throw new NodeUrlPackageSourceErrorV1("request_failed","plugin package response has no body");let reader=response2.body.getReader(),chunks=[],hash=createHash4("sha256"),total=0;try{for(;;){if(controller.signal.aborted)throw new NodeUrlPackageSourceErrorV1("cancelled","plugin package download was cancelled");let item=await reader.read();if(item.done)break;if(total+=item.value.byteLength,total>maxPackageBytes)throw new NodeUrlPackageSourceErrorV1("response_too_large","plugin package exceeds the configured size limit");hash.update(item.value),chunks.push(item.value)}}finally{reader.releaseLock()}if(controller.signal.aborted)throw new NodeUrlPackageSourceErrorV1("cancelled","plugin package download was cancelled");let bytes=new Uint8Array(total),offset=0;for(let chunk of chunks)bytes.set(chunk,offset),offset+=chunk.byteLength;let digestHex=hash.digest("hex");if(input.expectedDigestHex!==void 0&&digestHex!==input.expectedDigestHex)throw new NodeUrlPackageSourceErrorV1("digest_mismatch","plugin package bytes do not match the expected sha256 digest");let fileName=current.pathname.split("/").pop(),mediaType=detectPluginPackageMediaTypeV1(bytes,fileName===void 0||fileName.length===0?void 0:fileName);return{bytes,mediaType,digestHex}}finally{clearTimeout(timeout),input.signal?.removeEventListener("abort",abort),await response2?.body?.cancel().catch(()=>{})}}var DEFAULT_GITHUB_API_ORIGIN_V1="https://api.github.com",DEFAULT_GITEE_API_ORIGIN_V1="https://gitee.com/api/v5",DEFAULT_TIMEOUT_MS_V14=15e3,MAX_TIMEOUT_MS_V14=12e4,DEFAULT_MAX_RESPONSE_BYTES_V12=8*1024*1024,MAX_RESPONSE_BYTES_V12=16*1024*1024,DEFAULT_MAX_ASSET_BYTES_V1=128*1024*1024,MAX_ASSET_BYTES_V1=512*1024*1024,DEFAULT_REDIRECTS_V14=3,MAX_REDIRECTS_V14=5,REDIRECT_STATUS4=new Set([301,302,303,307,308]),NodeReleasePackageSourceErrorV1=class extends Error{code;resetEpochSeconds;constructor(code,message,options){super(message),this.name="NodeReleasePackageSourceErrorV1",this.code=code,options?.resetEpochSeconds!==void 0&&(this.resetEpochSeconds=options.resetEpochSeconds)}};function boundedPositive4(value,fallback,maximum,label){let result=value??fallback;if(!Number.isSafeInteger(result)||result<=0||result>maximum)throw new NodeReleasePackageSourceErrorV1("invalid_configuration",`${label} must be a positive integer at most ${maximum}`);return result}function boundedToken(value,label){if(value!==void 0){if(value.length===0||value.length>4096||/[\r\n\s]/u.test(value))throw new NodeReleasePackageSourceErrorV1("invalid_configuration",`${label} is invalid`);return value}}function apiOrigin(value,label){let parsed;try{parsed=new URL(value)}catch{throw new NodeReleasePackageSourceErrorV1("invalid_configuration",`${label} is invalid`)}if(parsed.protocol!=="http:"&&parsed.protocol!=="https:"||parsed.username!==""||parsed.password!=="")throw new NodeReleasePackageSourceErrorV1("invalid_configuration",`${label} must be http(s) without credentials`);if(parsed.search!==""||parsed.hash!=="")throw new NodeReleasePackageSourceErrorV1("invalid_configuration",`${label} must not include a query or fragment`);let trimmed=parsed.pathname.replace(/\/+$/u,"");return{origin:parsed.origin,pathPrefix:trimmed===""||trimmed==="/"?"":trimmed.replace(/^\//u,"")}}function jsonBytes(value){try{return JSON.parse(new TextDecoder("utf-8",{fatal:!0}).decode(value))}catch{throw new NodeReleasePackageSourceErrorV1("invalid_response","release API response is not valid JSON")}}function parseReleaseList(bytes){let value=jsonBytes(bytes);if(!Array.isArray(value))throw new NodeReleasePackageSourceErrorV1("invalid_response","release API response is not a release list");return value}function parseReleaseObject(bytes){let value=jsonBytes(bytes);if(typeof value!="object"||value===null||Array.isArray(value))throw new NodeReleasePackageSourceErrorV1("invalid_response","release API response is not a release object");return value}function firstPublishedRelease(releases){let published=releases.find(release=>release.draft!==!0);if(published===void 0)throw new NodeReleasePackageSourceErrorV1("release_not_found","repo has no published release");return published}function namedAssets(release){if(release.assets===void 0)return[];if(!Array.isArray(release.assets))throw new NodeReleasePackageSourceErrorV1("invalid_response","release assets are invalid");let entries=[];for(let asset of release.assets){if(typeof asset!="object"||asset===null)continue;let shape=asset;typeof shape.name!="string"||shape.name.length===0||entries.push({name:shape.name,url:shape.browser_download_url})}return entries}function isPackageAssetName(name){let value=name.toLowerCase();return value.endsWith(".zip")||value.endsWith(".tgz")}function selectPackageAssetUrl(release){let assets=namedAssets(release),candidates=assets.filter(asset=>isPackageAssetName(asset.name)),assetNames=assets.map(asset=>asset.name).join(", ");if(candidates.length===0)throw new NodeReleasePackageSourceErrorV1("release_asset_not_found",assetNames.length===0?"release has no assets":`assets: ${assetNames}`);if(candidates.length>1)throw new NodeReleasePackageSourceErrorV1("release_asset_ambiguous",`candidates: ${candidates.map(asset=>asset.name).join(", ")}`);let chosen=candidates[0];if(typeof chosen.url!="string"||chosen.url.length===0)throw new NodeReleasePackageSourceErrorV1("invalid_response","release asset has no download URL");return chosen.url}function isAbortLike4(error2){return error2 instanceof Error&&(error2.name==="AbortError"||error2.name==="AbortSignalError")}function requestSignal3(parent,timeoutMs){let controller=new AbortController,timedOut=!1,abort=()=>controller.abort(parent?.reason);parent?.aborted===!0?abort():parent?.addEventListener("abort",abort,{once:!0});let timeout=setTimeout(()=>{timedOut=!0,controller.abort()},timeoutMs);return{signal:controller.signal,timedOut:()=>timedOut,cleanup:()=>{clearTimeout(timeout),parent?.removeEventListener("abort",abort)}}}function isJsonResponse2(response2){let contentType2=response2.headers.get("content-type");if(contentType2===null)return!1;let mediaType=contentType2.split(";",1)[0]?.trim().toLowerCase();return mediaType==="application/json"||mediaType==="application/vnd.github+json"}function rateLimitState(response2){if(!(response2.status===429||response2.status===403&&response2.headers.get("x-ratelimit-remaining")==="0"))return{limited:!1};let reset=response2.headers.get("x-ratelimit-reset"),resetValue=reset===null?Number.NaN:Number.parseInt(reset,10);return!Number.isSafeInteger(resetValue)||resetValue<0?{limited:!0}:{limited:!0,resetEpochSeconds:resetValue}}async function readBody2(response2,maxBytes,signal){if(response2.body===null)throw new NodeReleasePackageSourceErrorV1("invalid_response","release API response has no body");let reader=response2.body.getReader(),chunks=[],total=0;try{for(;;){if(signal.aborted)throw new DOMException("aborted","AbortError");let item=await reader.read();if(item.done)break;if(total+=item.value.byteLength,total>maxBytes)throw new NodeReleasePackageSourceErrorV1("response_too_large","release API response exceeds the configured size limit");chunks.push(item.value)}}finally{reader.releaseLock()}let bytes=new Uint8Array(total),offset=0;for(let chunk of chunks)bytes.set(chunk,offset),offset+=chunk.byteLength;return bytes}function createNodeReleasePackageSourceV1(options={}){let transport=options.fetch??globalThis.fetch;if(typeof transport!="function")throw new NodeReleasePackageSourceErrorV1("invalid_configuration","Node fetch is unavailable");let githubOrigin=apiOrigin(options.githubApiOrigin??DEFAULT_GITHUB_API_ORIGIN_V1,"githubApiOrigin"),giteeOrigin=apiOrigin(options.giteeApiOrigin??DEFAULT_GITEE_API_ORIGIN_V1,"giteeApiOrigin"),githubToken=boundedToken(options.githubToken,"githubToken"),giteeToken=boundedToken(options.giteeToken,"giteeToken"),timeoutMs=boundedPositive4(options.requestTimeoutMs,DEFAULT_TIMEOUT_MS_V14,MAX_TIMEOUT_MS_V14,"requestTimeoutMs"),maxResponseBytes=boundedPositive4(options.maxResponseBytes,DEFAULT_MAX_RESPONSE_BYTES_V12,MAX_RESPONSE_BYTES_V12,"maxResponseBytes"),maxAssetBytes=boundedPositive4(options.maxAssetBytes,DEFAULT_MAX_ASSET_BYTES_V1,MAX_ASSET_BYTES_V1,"maxAssetBytes"),maxRedirects=options.maxRedirects??DEFAULT_REDIRECTS_V14;if(!Number.isSafeInteger(maxRedirects)||maxRedirects<0||maxRedirects>MAX_REDIRECTS_V14)throw new NodeReleasePackageSourceErrorV1("invalid_configuration",`maxRedirects must be an integer between 0 and ${MAX_REDIRECTS_V14}`);let userAgent=options.userAgent??"agent-forge-plugin-release/1";if(userAgent.length===0||userAgent.length>256||/[\r\n]/u.test(userAgent))throw new NodeReleasePackageSourceErrorV1("invalid_configuration","userAgent is invalid");let fetchReleaseJson=async(url,headers,parentSignal)=>{let current=url;for(let redirect=0;;redirect+=1){let request=requestSignal3(parentSignal,timeoutMs),response2;try{response2=await transport(current.toString(),{method:"GET",headers:{accept:"application/json","user-agent":userAgent,...headers},redirect:"manual",signal:request.signal})}catch(error2){throw request.cleanup(),request.timedOut()?new NodeReleasePackageSourceErrorV1("request_timed_out","release API request timed out"):isAbortLike4(error2)?new NodeReleasePackageSourceErrorV1("cancelled","release API request was cancelled"):new NodeReleasePackageSourceErrorV1("request_failed","release API request failed")}if(!REDIRECT_STATUS4.has(response2.status))try{if(response2.status===404)throw new NodeReleasePackageSourceErrorV1("release_not_found","repo or release was not found");let limit=rateLimitState(response2);if(limit.limited){let message=limit.resetEpochSeconds===void 0?"rate limit was exceeded":`rate limit resets at ${new Date(limit.resetEpochSeconds*1e3).toISOString()}`;throw new NodeReleasePackageSourceErrorV1("rate_limited",message,{...limit.resetEpochSeconds===void 0?{}:{resetEpochSeconds:limit.resetEpochSeconds}})}if(response2.status<200||response2.status>=300)throw new NodeReleasePackageSourceErrorV1("request_failed","release API request did not succeed");if(!isJsonResponse2(response2))throw new NodeReleasePackageSourceErrorV1("invalid_response","release API response must be JSON");return await readBody2(response2,maxResponseBytes,request.signal)}finally{await response2.body?.cancel().catch(()=>{}),request.cleanup()}let location=response2.headers.get("location");if(await response2.body?.cancel().catch(()=>{}),request.cleanup(),location===null||redirect>=maxRedirects)throw new NodeReleasePackageSourceErrorV1("request_failed","release API redirect limit exceeded");let next;try{next=new URL(location,current)}catch{throw new NodeReleasePackageSourceErrorV1("invalid_response","release API redirect target is invalid")}if(next.protocol!=="http:"&&next.protocol!=="https:"||next.username!==""||next.password!=="")throw new NodeReleasePackageSourceErrorV1("invalid_response","release API redirect must stay http(s)");current=next}};return{version:1,downloadReleaseAsset:async input=>{if(input.signal?.aborted===!0)throw new NodeReleasePackageSourceErrorV1("cancelled","release asset download was cancelled");let sourceLabel=`${input.kind}:${input.owner}/${input.repo}@${input.tag??"latest"}`,base=input.kind==="github"?githubOrigin:giteeOrigin,segments=[base.pathPrefix===""?void 0:base.pathPrefix,"repos",encodeURIComponent(input.owner),encodeURIComponent(input.repo),"releases",...input.tag===void 0?[]:["tags",encodeURIComponent(input.tag)]].filter(segment2=>segment2!==void 0),endpoint=new URL(`${base.origin}/${segments.join("/")}`),headers=input.kind==="github"?{"x-github-api-version":"2022-11-28",...githubToken===void 0?{}:{authorization:`Bearer ${githubToken}`}}:{};input.kind==="gitee"&&giteeToken!==void 0&&endpoint.searchParams.set("access_token",giteeToken);let payload2=await fetchReleaseJson(endpoint,headers,input.signal),release=input.tag===void 0?firstPublishedRelease(parseReleaseList(payload2)):parseReleaseObject(payload2),assetUrl=selectPackageAssetUrl(release),download=await downloadNodeUrlPackageV1({...options.fetch===void 0?{}:{fetch:options.fetch},requestTimeoutMs:timeoutMs,maxPackageBytes:maxAssetBytes,userAgent},{url:assetUrl,...input.expectedDigestHex===void 0?{}:{expectedDigestHex:input.expectedDigestHex},signal:input.signal});return{bytes:download.bytes,mediaType:download.mediaType,sha256Hex:download.digestHex,sourceLabel}}}}import{gzipSync}from"node:zlib";var TAR_BLOCK_BYTES_V12=512,TAR_NAME_LENGTH_V12=100,TAR_MODE_LENGTH_V1=8,TAR_SIZE_LENGTH_V12=12,TAR_CHECKSUM_LENGTH_V12=8,TAR_PREFIX_LENGTH_V12=155,NodeTarWriterErrorV1=class extends Error{code;constructor(code,message){super(message),this.name="NodeTarWriterErrorV1",this.code=code}};function octalField(value,length){let digits=length-1,octal=value.toString(8);if(octal.length>digits)throw new NodeTarWriterErrorV1("invalid_entry","tar header field overflows");return`${octal.padStart(digits,"0")}\0`}function writeHeader(header,entry,nameField,prefixField){header.fill(0);let encode=(value,offset,length)=>{let bytes=new TextEncoder().encode(value);if(bytes.byteLength>length)throw new NodeTarWriterErrorV1("entry_name_too_long","tar header name field overflows");header.set(bytes,offset)};encode(nameField,0,TAR_NAME_LENGTH_V12-1);let contentBytes=entry.directory?0:entry.bytes?.byteLength??0,mode=octalField(entry.directory?493:420,TAR_MODE_LENGTH_V1),encodedMode=new TextEncoder().encode(mode);header.set(encodedMode,100),header.set(new TextEncoder().encode(octalField(0,TAR_MODE_LENGTH_V1)),108),header.set(new TextEncoder().encode(octalField(0,TAR_MODE_LENGTH_V1)),116),header.set(new TextEncoder().encode(octalField(contentBytes,TAR_SIZE_LENGTH_V12)),124),header.set(new TextEncoder().encode(octalField(0,TAR_SIZE_LENGTH_V12)),136),header[156]=entry.directory?53:48;let magic=new TextEncoder().encode("ustar\0");header.set(magic,257),header.set(new TextEncoder().encode("00"),263),prefixField.length>0&&encode(prefixField,345,TAR_PREFIX_LENGTH_V12-1);let checksum=0;for(let index3=148;index3<148+TAR_CHECKSUM_LENGTH_V12;index3+=1)header[index3]=32;for(let byte of header)checksum+=byte;let checksumText=`${checksum.toString(8).padStart(6,"0")}\0 `;header.set(new TextEncoder().encode(checksumText),148)}function entryFields(name){let bytes=new TextEncoder().encode(name);if(bytes.byteLength<=TAR_NAME_LENGTH_V12-1)return{name,prefix:""};let split=-1;for(let index3=Math.min(bytes.byteLength,TAR_PREFIX_LENGTH_V12)-1;index3>=0;index3-=1)if(bytes[index3]===47){split=index3;break}if(split<=0)throw new NodeTarWriterErrorV1("entry_name_too_long","tar entry name cannot be split into ustar fields");let prefix=name.slice(0,split),rest=name.slice(split+1);if(new TextEncoder().encode(rest).byteLength>TAR_NAME_LENGTH_V12-1||new TextEncoder().encode(prefix).byteLength>TAR_PREFIX_LENGTH_V12-1)throw new NodeTarWriterErrorV1("entry_name_too_long","tar entry name cannot be split into ustar fields");return{name:rest,prefix}}function headerBlock(entry){if(typeof entry.name!="string"||entry.name.length===0)throw new NodeTarWriterErrorV1("invalid_entry","tar entry name is invalid");if(normalizedEntryName(entry.directory?`${entry.name}/`:entry.name).name!==entry.name)throw new NodeTarWriterErrorV1("invalid_entry","tar entry name is not normalized");if(entry.directory&&entry.bytes!==void 0&&entry.bytes.byteLength>0)throw new NodeTarWriterErrorV1("invalid_entry","tar directory entry must be empty");if(!entry.directory&&!(entry.bytes instanceof Uint8Array))throw new NodeTarWriterErrorV1("invalid_entry","tar file entry requires bytes");let header=new Uint8Array(TAR_BLOCK_BYTES_V12),fields=entryFields(entry.name);return writeHeader(header,entry,fields.name,fields.prefix),header}function buildNodeTarBytesV1(entries){if(!Array.isArray(entries))throw new NodeTarWriterErrorV1("invalid_entry","tar entries must be an array");let names2=new Set,blocks=[];for(let entry of entries){if(names2.has(entry.name))throw new NodeTarWriterErrorV1("invalid_entry",`duplicate tar entry name: ${entry.name}`);if(names2.add(entry.name),blocks.push(headerBlock(entry)),!entry.directory){let bytes=entry.bytes??new Uint8Array,padding=(TAR_BLOCK_BYTES_V12-bytes.byteLength%TAR_BLOCK_BYTES_V12)%TAR_BLOCK_BYTES_V12;blocks.push(bytes,new Uint8Array(padding))}}blocks.push(new Uint8Array(TAR_BLOCK_BYTES_V12),new Uint8Array(TAR_BLOCK_BYTES_V12));let total=0;for(let block of blocks)total+=block.byteLength;let output=new Uint8Array(total),offset=0;for(let block of blocks)output.set(block,offset),offset+=block.byteLength;return output}function buildNodeTarGzBytesV1(entries){return gzipSync(buildNodeTarBytesV1(entries))}var NODE_PLUGIN_ACQUISITION_HOST_VERSION_V1=1,MAX_PACKAGE_MANIFEST_BYTES_V12=64*1024,ECOSYSTEM_MANIFEST_FILE_V13="agent-forge.json",ACQUISITION_ARTIFACT_EXPIRES_AT_V1="2099-01-01T00:00:00.000Z",ARTIFACT_CHUNK_BYTES_V1=64*1024,AGENT_FORGE_NPM_REGISTRY_ENV_V1="AGENT_FORGE_NPM_REGISTRY",AGENT_FORGE_NPM_TOKEN_ENV_V1="AGENT_FORGE_NPM_TOKEN",AGENT_FORGE_GITHUB_API_ENV_V1="AGENT_FORGE_GITHUB_API",AGENT_FORGE_GITEE_API_ENV_V1="AGENT_FORGE_GITEE_API",GITHUB_TOKEN_ENV_V1="GITHUB_TOKEN",GITEE_TOKEN_ENV_V1="GITEE_TOKEN",LOCAL_PROBE_V1={statLocalRef:path15=>{let stats=lstatSync2(path15,{throwIfNoEntry:!1});return stats===void 0?"missing":stats.isSymbolicLink()?"other":stats.isDirectory()?"directory":stats.isFile()?"file":"other"}};function mapInstallError(error2){return error2 instanceof PluginAcquisitionErrorV1?error2:error2 instanceof NodePackageInstallErrorV1?error2.code==="cancelled"?new PluginAcquisitionErrorV1("cancelled"):error2.code==="archive_budget_exceeded"?new PluginAcquisitionErrorV1("budget_exceeded"):error2.code==="unsupported_media_type"?new PluginAcquisitionErrorV1("unsupported_media_type"):new PluginAcquisitionErrorV1("package_invalid"):new PluginAcquisitionErrorV1("download_failed")}function mapNpmError(error2){return error2 instanceof PluginAcquisitionErrorV1?error2:error2 instanceof NodeNpmRegistrySourceErrorV1?error2.code==="package_not_found"?new PluginAcquisitionErrorV1("package_not_found"):error2.code==="version_not_found"?new PluginAcquisitionErrorV1("version_not_found"):error2.code==="cancelled"?new PluginAcquisitionErrorV1("cancelled"):error2.code==="invalid_response"||error2.code==="integrity_unsupported"?new PluginAcquisitionErrorV1("package_invalid"):new PluginAcquisitionErrorV1("download_failed"):mapInstallError(error2)}function mapUrlError(error2){return error2 instanceof PluginAcquisitionErrorV1?error2:error2 instanceof NodeUrlPackageSourceErrorV1?error2.code==="digest_mismatch"?new PluginAcquisitionErrorV1("digest_mismatch"):error2.code==="cancelled"?new PluginAcquisitionErrorV1("cancelled"):error2.code==="invalid_url"||error2.code==="invalid_configuration"?new PluginAcquisitionErrorV1("invalid_ref"):error2.code==="response_too_large"?new PluginAcquisitionErrorV1("budget_exceeded"):new PluginAcquisitionErrorV1("download_failed"):mapInstallError(error2)}function mapReleaseError(error2){return error2 instanceof PluginAcquisitionErrorV1?error2:error2 instanceof NodeReleasePackageSourceErrorV1?error2.code==="cancelled"?new PluginAcquisitionErrorV1("cancelled"):error2.code==="invalid_configuration"?new PluginAcquisitionErrorV1("invalid_ref"):error2.code==="response_too_large"?new PluginAcquisitionErrorV1("budget_exceeded"):error2.code==="invalid_response"?new PluginAcquisitionErrorV1("package_invalid"):error2.code==="rate_limited"?new PluginAcquisitionErrorV1("rate_limited",error2.resetEpochSeconds===void 0?void 0:`rate limit resets at ${new Date(error2.resetEpochSeconds*1e3).toISOString()}`):error2.code==="release_not_found"||error2.code==="release_asset_not_found"||error2.code==="release_asset_ambiguous"?new PluginAcquisitionErrorV1(error2.code,error2.message):new PluginAcquisitionErrorV1("download_failed"):mapUrlError(error2)}function shaHex(algorithm,bytes){return createHash5(algorithm).update(bytes).digest("hex")}function signalAborted(signal){return signal?.aborted===!0}function pluginAcquisitionManifestFromEntriesV1(entries){let manifestEntry=entries.find(entry=>entry.name===ECOSYSTEM_MANIFEST_FILE_V13&&!entry.directory);if(manifestEntry===void 0||manifestEntry.bytes.byteLength>MAX_PACKAGE_MANIFEST_BYTES_V12)throw new PluginAcquisitionErrorV1("package_invalid");let value;try{value=JSON.parse(new TextDecoder("utf-8",{fatal:!0}).decode(manifestEntry.bytes))}catch{throw new PluginAcquisitionErrorV1("package_invalid")}if(typeof value!="object"||value===null||Array.isArray(value))throw new PluginAcquisitionErrorV1("package_invalid");let record=value,manifestKeys2=new Set(["id","pluginVersion","apiVersion","minHostVersion","maxHostVersion","capabilityRefs","requires","platform","testOnly"]);if(record.packageFormatVersion!==1||Object.keys(record).some(key=>key!=="packageFormatVersion"&&!manifestKeys2.has(key)))throw new PluginAcquisitionErrorV1("package_invalid");let id=record.id,pluginVersion=record.pluginVersion,apiVersion=record.apiVersion;if(typeof id!="string"||id.trim().length===0||id.length>256||typeof pluginVersion!="string"||pluginVersion.trim().length===0||pluginVersion.length>256||typeof apiVersion!="string"||apiVersion.trim().length===0||apiVersion.length>256)throw new PluginAcquisitionErrorV1("package_invalid");if(record.minHostVersion===void 0&&record.maxHostVersion===void 0)throw new PluginAcquisitionErrorV1("package_invalid");let manifest=Object.freeze({id,pluginVersion,apiVersion,...record.minHostVersion===void 0?{}:{minHostVersion:record.minHostVersion},...record.maxHostVersion===void 0?{}:{maxHostVersion:record.maxHostVersion},...record.capabilityRefs===void 0?{}:{capabilityRefs:record.capabilityRefs},...record.requires===void 0?{}:{requires:record.requires},...record.platform===void 0?{}:{platform:record.platform},...record.testOnly===void 0?{}:{testOnly:record.testOnly}});return{manifest,manifestDigest:pluginManifestDigestV1(manifest)}}function createNodePluginAcquisitionHostV1(options={}){let limits=options.limits??{},npmRegistryOption=options.npmRegistry??process.env[AGENT_FORGE_NPM_REGISTRY_ENV_V1]?.trim(),npmTokenOption=options.npmToken??process.env[AGENT_FORGE_NPM_TOKEN_ENV_V1]?.trim(),githubApiOriginOption=options.githubApiOrigin??process.env[AGENT_FORGE_GITHUB_API_ENV_V1]?.trim(),giteeApiOriginOption=options.giteeApiOrigin??process.env[AGENT_FORGE_GITEE_API_ENV_V1]?.trim(),githubTokenOption=options.githubToken??process.env[GITHUB_TOKEN_ENV_V1]?.trim(),giteeTokenOption=options.giteeToken??process.env[GITEE_TOKEN_ENV_V1]?.trim(),npmSource=createNodeNpmRegistrySourceV1({...npmRegistryOption===void 0||npmRegistryOption===""?{}:{registry:npmRegistryOption},...npmTokenOption===void 0||npmTokenOption===""?{}:{token:npmTokenOption},...options.fetch===void 0?{}:{fetch:options.fetch},...options.requestTimeoutMs===void 0?{}:{requestTimeoutMs:options.requestTimeoutMs},...options.maxResponseBytes===void 0?{}:{maxResponseBytes:options.maxResponseBytes},...options.maxTarballBytes===void 0?{}:{maxTarballBytes:options.maxTarballBytes},...options.userAgent===void 0?{}:{userAgent:options.userAgent}}),releaseSource=createNodeReleasePackageSourceV1({...githubApiOriginOption===void 0||githubApiOriginOption===""?{}:{githubApiOrigin:githubApiOriginOption},...giteeApiOriginOption===void 0||giteeApiOriginOption===""?{}:{giteeApiOrigin:giteeApiOriginOption},...githubTokenOption===void 0||githubTokenOption===""?{}:{githubToken:githubTokenOption},...giteeTokenOption===void 0||giteeTokenOption===""?{}:{giteeToken:giteeTokenOption},...options.fetch===void 0?{}:{fetch:options.fetch},...options.requestTimeoutMs===void 0?{}:{requestTimeoutMs:options.requestTimeoutMs},...options.maxResponseBytes===void 0?{}:{maxResponseBytes:options.maxResponseBytes},...options.maxTarballBytes===void 0?{}:{maxAssetBytes:options.maxTarballBytes},...options.userAgent===void 0?{}:{userAgent:options.userAgent}}),artifacts=new Map,closed=!1,acquireBytes=async(ref,signal)=>{if(ref.kind==="github"||ref.kind==="gitee")try{let download=await releaseSource.downloadReleaseAsset({kind:ref.kind,owner:ref.owner,repo:ref.repo,...ref.tag===void 0?{}:{tag:ref.tag},...ref.expectedDigestHex===void 0?{}:{expectedDigestHex:ref.expectedDigestHex},signal});return{bytes:download.bytes,mediaType:download.mediaType,digest:{algorithm:"sha256",hex:download.sha256Hex},source:download.sourceLabel}}catch(error2){throw mapReleaseError(error2)}if(ref.kind==="npm")try{let resolved=await npmSource.resolveNpmPackage({name:ref.name,...ref.range===void 0?{}:{range:ref.range},signal}),bytes=await npmSource.fetchTarball({url:resolved.tarballUrl,signal});if(shaHex(resolved.integrity.algorithm,bytes)!==resolved.integrity.hex)throw new PluginAcquisitionErrorV1("digest_mismatch");return{bytes,mediaType:"application/gzip",digest:resolved.integrity,source:`npm:${new URL(resolved.tarballUrl).host}`}}catch(error2){throw mapNpmError(error2)}if(ref.kind==="url")try{let download=await downloadNodeUrlPackageV1({...options.fetch===void 0?{}:{fetch:options.fetch},...options.requestTimeoutMs===void 0?{}:{requestTimeoutMs:options.requestTimeoutMs},...options.maxTarballBytes===void 0?{}:{maxPackageBytes:options.maxTarballBytes},...options.userAgent===void 0?{}:{userAgent:options.userAgent}},{url:ref.url,...ref.expectedDigestHex===void 0?{}:{expectedDigestHex:ref.expectedDigestHex},signal});return{bytes:download.bytes,mediaType:download.mediaType,digest:{algorithm:"sha256",hex:download.digestHex},source:`url:${new URL(ref.url).host}`}}catch(error2){throw mapUrlError(error2)}if(ref.kind==="local-file")try{let bytes=await readLocalPackageFileV1(ref.path,limits,signal),fileName=ref.path.split(/[\\/]/u).pop(),mediaType=detectPluginPackageMediaTypeV1(bytes,fileName===void 0||fileName.length===0?void 0:fileName);return{bytes,mediaType,digest:{algorithm:"sha256",hex:shaHex("sha256",bytes)},source:"local:file"}}catch(error2){throw mapInstallError(error2)}if(ref.kind==="local-path")try{let entries=await collectLocalDirectoryPackageEntriesV1(ref.path,limits,signal),bytes=buildNodeTarGzBytesV1(entries.map(entry=>({name:entry.name,directory:entry.directory,bytes:entry.bytes})));return{bytes,mediaType:"application/gzip",digest:{algorithm:"sha256",hex:shaHex("sha256",bytes)},source:"local:dir"}}catch(error2){throw mapInstallError(error2)}throw new PluginAcquisitionErrorV1("invalid_ref")},releaseArtifact=async input=>{if(!artifacts.delete(input.artifact.artifactRef))throw new NodePackageInstallErrorV1("invalid_artifact")};return{version:NODE_PLUGIN_ACQUISITION_HOST_VERSION_V1,resolvePackage:async input=>{if(closed||signalAborted(input.signal))throw new PluginAcquisitionErrorV1("cancelled");let ref;try{ref=parsePluginAcquisitionRefV1(input.ref,LOCAL_PROBE_V1)}catch(error2){throw error2 instanceof PluginAcquisitionErrorV1?error2:new PluginAcquisitionErrorV1("invalid_ref")}let acquired=await acquireBytes(ref,input.signal);if(signalAborted(input.signal))throw new PluginAcquisitionErrorV1("cancelled");let entries;try{entries=acquired.mediaType==="application/gzip"?await parseNodeTarGzPackageV1(acquired.bytes,limits):parseNodeZipPackageV1(acquired.bytes,limits)}catch(error2){throw mapInstallError(error2)}let identity=pluginAcquisitionManifestFromEntriesV1(entries);if(closed)throw new PluginAcquisitionErrorV1("cancelled");let artifactRef=`plugin-acquisition://node/${randomUUID7()}`,artifact=Object.freeze({version:1,source:acquired.source,pluginId:identity.manifest.id,pluginVersion:identity.manifest.pluginVersion,manifestDigest:identity.manifestDigest,artifactDigest:acquired.digest.algorithm==="sha512"?`sha512:${acquired.digest.hex}`:`sha256:${acquired.digest.hex}`,expiresAt:ACQUISITION_ARTIFACT_EXPIRES_AT_V1,sizeBytes:acquired.bytes.byteLength,mediaType:acquired.mediaType,artifactRef});return artifacts.set(artifactRef,{bytes:acquired.bytes,artifact}),Object.freeze({manifest:identity.manifest,manifestDigest:identity.manifestDigest,source:acquired.source,artifact,release:async()=>{try{return await releaseArtifact({artifact:{artifactRef}}),!0}catch{return!1}}})},openArtifact(input){return(async function*(){let record=artifacts.get(input.artifact.artifactRef);if(record===void 0)throw new NodePackageInstallErrorV1("invalid_artifact");if(record.artifact.pluginId!==input.artifact.pluginId||record.artifact.pluginVersion!==input.artifact.pluginVersion||record.artifact.manifestDigest!==input.artifact.manifestDigest||record.artifact.artifactDigest!==input.artifact.artifactDigest||record.artifact.sizeBytes!==input.artifact.sizeBytes)throw new NodePackageInstallErrorV1("invalid_artifact");for(let offset=0;offset<record.bytes.byteLength;offset+=ARTIFACT_CHUNK_BYTES_V1){if(input.signal?.aborted===!0)throw new NodePackageInstallErrorV1("cancelled");yield new Uint8Array(record.bytes.subarray(offset,Math.min(offset+ARTIFACT_CHUNK_BYTES_V1,record.bytes.byteLength)))}})()},releaseArtifact,ownsArtifact:input=>artifacts.has(input.artifactRef),async close(){closed=!0,artifacts.clear()}}}var NodeHttpPluginRegistrySourceErrorV1=class extends Error{code;constructor(code,message){super(message),this.name="NodeHttpPluginRegistrySourceErrorV1",this.code=code}};function boundedPositive5(value,fallback,maximum,label){let result=value??fallback;if(!Number.isSafeInteger(result)||result<=0||result>maximum)throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration",`${label} must be a positive integer at most ${maximum}`);return result}function allowedOrigin2(value){let parsed;try{parsed=new URL(value)}catch{throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration","Allowed registry origin is invalid")}if(parsed.protocol!=="http:"&&parsed.protocol!=="https:"||parsed.username||parsed.password)throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration","Allowed registry origin must be an http(s) origin without credentials");if(parsed.pathname!=="/"||parsed.search!==""||parsed.hash!=="")throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration","Allowed registry origin must not include a path, query, or fragment");return parsed.origin}function endpointUrl(value,origins){let parsed;try{parsed=new URL(value)}catch{throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration","Plugin registry URL is invalid")}if(parsed.protocol!=="http:"&&parsed.protocol!=="https:"||parsed.username||parsed.password)throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration","Plugin registry URL must use http(s) without credentials");if(parsed.search!==""||parsed.hash!=="")throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration","Plugin registry URL must not include a query or fragment");if(!origins.has(parsed.origin))throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration","Plugin registry origin is not allowed");return parsed}function responseLength(response2){let raw=response2.headers.get("content-length");if(raw===null)return;if(!/^\d+$/u.test(raw))throw new NodeHttpPluginRegistrySourceErrorV1("invalid_response","Plugin registry response length is invalid");let value=Number(raw);if(!Number.isSafeInteger(value))throw new NodeHttpPluginRegistrySourceErrorV1("invalid_response","Plugin registry response length is invalid");return value}function isJsonResponse3(response2){let contentType2=response2.headers.get("content-type");if(contentType2===null)return!1;let mediaType=contentType2.split(";",1)[0]?.trim().toLowerCase();return mediaType==="application/json"||mediaType==="application/vnd.agent-forge.plugin-registry+json"}function requestController(parent,timeoutMs){let controller=new AbortController,timedOut=!1,abort=()=>controller.abort(parent?.reason);parent?.aborted===!0?abort():parent?.addEventListener("abort",abort,{once:!0});let timeout=setTimeout(()=>{timedOut=!0,controller.abort()},timeoutMs);return{signal:controller.signal,timedOut:()=>timedOut,cleanup:()=>{clearTimeout(timeout),parent?.removeEventListener("abort",abort)}}}function abortPromise(signal){let rejectAbort;return{promise:new Promise((_resolve,reject2)=>{rejectAbort=()=>reject2(new DOMException("aborted","AbortError")),signal.aborted?rejectAbort():signal.addEventListener("abort",rejectAbort,{once:!0})}),cleanup:()=>{rejectAbort!==void 0&&signal.removeEventListener("abort",rejectAbort)}}}async function awaitBeforeAbort(operation,signal){let abort=abortPromise(signal);try{return await Promise.race([operation,abort.promise])}finally{abort.cleanup()}}function discardResponseBody(response2){let responseBody=response2?.body;responseBody?.cancel().catch(()=>{})}async function readBody3(response2,maxBytes,signal){if(response2.body===null)throw new NodeHttpPluginRegistrySourceErrorV1("invalid_response","Plugin registry response has no body");let reader=response2.body.getReader(),chunks=[],total=0;try{for(;;){if(signal.aborted)throw new DOMException("aborted","AbortError");let item=await awaitBeforeAbort(reader.read(),signal);if(item.done)break;if(total+=item.value.byteLength,total>maxBytes)throw new NodeHttpPluginRegistrySourceErrorV1("response_too_large","Plugin registry response exceeds the configured size limit");chunks.push(item.value)}}finally{reader.releaseLock()}let bytes=new Uint8Array(total),offset=0;for(let chunk of chunks)bytes.set(chunk,offset),offset+=chunk.byteLength;return bytes}function parseDocument(bytes){let value;try{value=JSON.parse(new TextDecoder("utf-8",{fatal:!0}).decode(bytes))}catch{throw new NodeHttpPluginRegistrySourceErrorV1("invalid_response","Plugin registry response is not valid JSON")}if(typeof value!="object"||value===null||Array.isArray(value))throw new NodeHttpPluginRegistrySourceErrorV1("invalid_response","Plugin registry document is invalid");let document=value;if(Object.keys(document).some(key=>key!=="version"&&key!=="entries")||document.version!==1||!Array.isArray(document.entries))throw new NodeHttpPluginRegistrySourceErrorV1("invalid_response","Plugin registry document is invalid");return document.entries}function isAbortLike5(error2){return error2 instanceof DOMException&&error2.name==="AbortError"}function isCallerCancelled(signal){return signal?.aborted===!0}function sanitizedSourceError(error2){let code=error2.code;return code!=="cancelled"&&code!=="invalid_configuration"&&code!=="request_failed"&&code!=="request_timed_out"&&code!=="invalid_response"&&code!=="response_too_large"?new NodeHttpPluginRegistrySourceErrorV1("request_failed","Plugin registry request failed"):new NodeHttpPluginRegistrySourceErrorV1(code,"Plugin registry request failed")}function createNodeHttpPluginRegistrySourceV1(options){let transport=options.fetch??globalThis.fetch;if(typeof transport!="function")throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration","Node fetch is unavailable");if(!Array.isArray(options.allowedOrigins)||options.allowedOrigins.length===0)throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration","At least one allowed registry origin is required");let origins=new Set(options.allowedOrigins.map(allowedOrigin2)),endpoint=endpointUrl(options.url,origins),timeoutMs=boundedPositive5(options.requestTimeoutMs,15e3,12e4,"requestTimeoutMs"),maxResponseBytes=boundedPositive5(options.maxResponseBytes,4194304,8388608,"maxResponseBytes"),userAgent=options.userAgent??"agent-forge-plugin-registry/1";if(userAgent.length===0||userAgent.length>256||/[\r\n]/u.test(userAgent))throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration","userAgent is invalid");return{version:1,source:endpoint.origin+endpoint.pathname,list:async({signal}={})=>{if(isCallerCancelled(signal))throw new NodeHttpPluginRegistrySourceErrorV1("cancelled","Plugin registry request was cancelled");let request=requestController(signal,timeoutMs),response2;try{let transportResponse=Promise.resolve().then(()=>{if(request.signal.aborted)throw new DOMException("aborted","AbortError");return transport(endpoint.toString(),{method:"GET",headers:{accept:"application/vnd.agent-forge.plugin-registry+json, application/json","user-agent":userAgent},redirect:"error",signal:request.signal})});transportResponse.then(lateResponse=>{request.signal.aborted&&discardResponseBody(lateResponse)},()=>{});let receivedResponse=await awaitBeforeAbort(transportResponse,request.signal);if(response2=receivedResponse,receivedResponse.status<200||receivedResponse.status>=300)throw new NodeHttpPluginRegistrySourceErrorV1("request_failed","Plugin registry request did not succeed");if(!isJsonResponse3(receivedResponse))throw new NodeHttpPluginRegistrySourceErrorV1("invalid_response","Plugin registry response must be JSON");let length=responseLength(receivedResponse);if(length!==void 0&&length>maxResponseBytes)throw new NodeHttpPluginRegistrySourceErrorV1("response_too_large","Plugin registry response exceeds the configured size limit");return parseDocument(await readBody3(receivedResponse,maxResponseBytes,request.signal))}catch(error2){throw isCallerCancelled(signal)?new NodeHttpPluginRegistrySourceErrorV1("cancelled","Plugin registry request was cancelled"):request.timedOut()?new NodeHttpPluginRegistrySourceErrorV1("request_timed_out","Plugin registry request timed out"):error2 instanceof NodeHttpPluginRegistrySourceErrorV1?sanitizedSourceError(error2):isAbortLike5(error2)?new NodeHttpPluginRegistrySourceErrorV1("cancelled","Plugin registry request was cancelled"):new NodeHttpPluginRegistrySourceErrorV1("request_failed","Plugin registry request failed")}finally{request.cleanup(),discardResponseBody(response2)}}}}function createPluginEcosystemRegistryAdapterV1(registry){if(registry.resolve===void 0)throw new PluginRegistryErrorV1("invalid_source","Registry does not expose a host-side package resolver");let resolve25=registry.resolve,list=registry.listManifests;return{...list===void 0?{}:{list},resolve:resolve25}}var DEFAULT_PLUGIN_REGISTRY_ORIGIN_ENV_V1="AGENT_FORGE_PLUGIN_REGISTRY_ORIGIN",DEFAULT_PLUGIN_TRUST_KEYS_ENV_V1="AGENT_FORGE_PLUGIN_TRUST_KEYS",DEFAULT_PLUGIN_REGISTRY_PATH_V1="/v1/plugin-registry.json";async function createDefaultPluginMarketWiringV1(options){let origin=(options.registryOrigin??process.env[DEFAULT_PLUGIN_REGISTRY_ORIGIN_ENV_V1])?.trim(),effectiveOrigin=origin===""?void 0:origin,storeParent=defaultPluginInstallStoreDirectoryV1(options.agentDir),instanceRoot=defaultPluginInstallStoreInstanceRootV1(options.agentDir),diskSource=createNodeDiskPluginRegistrySourceV1({rootDirectory:instanceRoot}),httpSource=effectiveOrigin===void 0?void 0:createNodeHttpPluginRegistrySourceV1({url:new URL(effectiveOrigin+DEFAULT_PLUGIN_REGISTRY_PATH_V1),allowedOrigins:[effectiveOrigin],...options.fetch===void 0?{}:{fetch:options.fetch}}),source={...httpSource===void 0?{}:{source:httpSource.source},list:async({signal}={})=>{let disk=await diskSource.list({signal});if(httpSource===void 0)return disk;let remote=await httpSource.list({signal});return Object.freeze([...remote,...disk])}},distributionHost=effectiveOrigin===void 0?void 0:await createNodeHttpPluginDistributionHostV1({allowedOrigins:[effectiveOrigin],artifactDirectory:join18(storeParent,"distribution-cache-v1"),...options.fetch===void 0?{}:{fetch:options.fetch}}),trustKeys=options.trustKeys;if(trustKeys===void 0&&effectiveOrigin!==void 0){let raw=process.env[DEFAULT_PLUGIN_TRUST_KEYS_ENV_V1];if(raw!==void 0&&raw.trim()!==""){let parsed;try{parsed=JSON.parse(raw)}catch{throw new Error(`${DEFAULT_PLUGIN_TRUST_KEYS_ENV_V1} must be a JSON array of {keyId, publicKeyPem}`)}if(!Array.isArray(parsed))throw new Error(`${DEFAULT_PLUGIN_TRUST_KEYS_ENV_V1} must be a JSON array`);trustKeys=parsed}}let trustRoot=trustKeys===void 0||distributionHost===void 0?void 0:createNodePluginTrustRootV1({keys:trustKeys}),acquisitionHost=options.acquisition??createNodePluginAcquisitionHostV1({...options.limits===void 0?{}:{limits:options.limits},...options.fetch===void 0?{}:{fetch:options.fetch}}),installHost=await createNodePackageInstallHostV1({openArtifact:input=>{if(acquisitionHost.ownsArtifact(input.artifact))return acquisitionHost.openArtifact(input);let reader=distributionHost?.openArtifact;if(reader===void 0)throw new NodePackageInstallErrorV1("invalid_artifact");return reader(input)},installationDirectory:storeParent,persistence:"persistent",supportedScopes:["global","project"],...options.limits===void 0?{}:{...options.limits}}),registry=createPluginRegistryV1({source,host:defaultPluginHostFactsV1(),verify:{verify:({manifestDigest,expectedDigest:expectedDigest2})=>expectedDigest2===void 0||expectedDigest2===manifestDigest?{status:"accepted"}:{status:"rejected",reason:"Manifest digest does not match the expected digest"}},sourceVerifier:()=>({status:"accepted"})});return{registry,cliRegistry:createPluginEcosystemRegistryAdapterV1(registry),acquisition:acquisitionHost,installer:createPluginInstallerV1({host:installHost}),...distributionHost===void 0||trustRoot===void 0?{}:{distribution:createPluginDistributionV1({host:distributionHost.host,verifySignature:trustRoot})},stateStore:createPluginStateStoreV1({filePath:join18(options.agentDir,DEFAULT_PLUGIN_STATE_FILE_V1)}),projectStateStore:createPluginStateStoreV1({filePath:join18(options.cwd,CONFIG_DIR_NAME,DEFAULT_PLUGIN_STATE_FILE_V1)}),close:async()=>{await installHost.close(),await acquisitionHost.close(),await distributionHost?.close()}}}async function createNodePluginPackageInstallStackV1(options){let distributionHost=await createNodeHttpPluginDistributionStackV1(options.distribution);try{let packageOptions={...options.packageHost,openArtifact:distributionHost.openArtifact},packageHost=options.session===void 0?await createNodePackageInstallHostV1(packageOptions):await createNodePackageInstallHostForSessionV1(packageOptions,options.session);try{let installer=createPluginInstallerV1({host:packageHost,...options.verifier===void 0?{}:{verifier:options.verifier}}),closePromise,close=()=>(closePromise!==void 0||(closePromise=(async()=>{let failure2;try{await packageHost.close()}catch(error2){failure2=error2}try{await distributionHost.close()}catch(error2){failure2===void 0&&(failure2=error2)}if(failure2!==void 0)throw failure2})()),closePromise);return Object.freeze({distributionHost,distribution:distributionHost.distribution,packageHost,installer,close})}catch(error2){throw await packageHost.close().catch(()=>{}),error2}}catch(error2){throw await distributionHost.close().catch(()=>{}),error2}}import{randomUUID as randomUUID8}from"node:crypto";import{mkdir as mkdir5,readFile as readFile6,rename as rename5,unlink as unlink2,writeFile as writeFile4}from"node:fs/promises";import{basename as basename3,dirname as dirname7,isAbsolute as isAbsolute7,join as join19,resolve as resolve5}from"node:path";var PLUGIN_SELECTION_STORE_VERSION_V1=1,MAX_PLUGIN_SELECTION_PROFILES_V1=256,MAX_PLUGIN_SELECTION_STORE_PATH_CHARS_V1=4096,EMPTY_SNAPSHOT2=Object.freeze({version:PLUGIN_SELECTION_STORE_VERSION_V1,selections:Object.freeze([])});function diagnostic4(code,message,profileId){return Object.freeze(profileId===void 0?{code,message}:{code,message,profileId})}function isAbortError2(error2){return error2 instanceof Error&&(error2.name==="AbortError"||error2.name==="AbortSignalError")}function isMissingError3(error2){return typeof error2=="object"&&error2!==null&&"code"in error2&&error2.code==="ENOENT"}function validateFilePath2(value){if(typeof value!="string"||value.trim()===""||value.length>MAX_PLUGIN_SELECTION_STORE_PATH_CHARS_V1)throw new Error("invalid plugin selection file path");if(value.includes("\0")||/[\u0000-\u001f]/u.test(value))throw new Error("invalid plugin selection file path");if(/^file:/iu.test(value)||/^[a-z][a-z\d+.-]*:/iu.test(value)&&!/^[a-z]:[\\/]/iu.test(value))throw new Error("invalid plugin selection file path");let normalized=isAbsolute7(value)?value:resolve5(value);if(basename3(normalized).length===0||basename3(normalized)==="."||basename3(normalized)==="..")throw new Error("invalid plugin selection file path");return normalized}function isObject3(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function hasExactKeys3(value,keys){let expected=new Set(keys);return Object.keys(value).length===expected.size&&Object.keys(value).every(key=>expected.has(key))}function validateProfile(value){if(!isObject3(value)||!hasExactKeys3(value,["profileId","selectedPluginIds","disabledPluginIds"]))throw new Error("selection schema is invalid");if(!Array.isArray(value.selectedPluginIds)||!Array.isArray(value.disabledPluginIds))throw new Error("selection IDs must be arrays");if(value.selectedPluginIds.length>MAX_PLUGIN_SELECTION_IDS_V1||value.disabledPluginIds.length>MAX_PLUGIN_SELECTION_IDS_V1)throw new Error("too many plugin IDs");return createPluginSelectionV1({profileId:value.profileId,selectedPluginIds:value.selectedPluginIds,disabledPluginIds:value.disabledPluginIds})}function validateSnapshot2(value){if(!isObject3(value)||!hasExactKeys3(value,["version","selections"]))throw new Error("snapshot schema is invalid");if(value.version!==PLUGIN_SELECTION_STORE_VERSION_V1)throw new Error("snapshot version is unsupported");if(!Array.isArray(value.selections))throw new Error("selections must be an array");if(value.selections.length>MAX_PLUGIN_SELECTION_PROFILES_V1)throw new Error("too many selection profiles");let selections=value.selections.map(validateProfile),profiles2=new Set;for(let selection of selections){if(profiles2.has(selection.profileId))throw new Error(`duplicate profile: ${selection.profileId}`);profiles2.add(selection.profileId)}return selections.sort((left,right)=>left.profileId.localeCompare(right.profileId)),Object.freeze({version:PLUGIN_SELECTION_STORE_VERSION_V1,selections:Object.freeze(selections)})}function invalidFromError2(error2){let message=error2 instanceof Error?error2.message:"plugin selection schema is invalid";if(message==="too many selection profiles")return diagnostic4("too_many_profiles",message);let duplicatePrefix="duplicate profile: ";if(message.startsWith(duplicatePrefix)){let profileId=message.slice(duplicatePrefix.length);return diagnostic4("duplicate_profile",message,profileId)}return diagnostic4("invalid_schema",message)}function defaultFileSystem2(){return{readFile:async path15=>await readFile6(path15,"utf8"),mkdir:async path15=>{await mkdir5(path15,{recursive:!0})},writeFile:async(path15,data)=>{await writeFile4(path15,data,"utf8")},rename:rename5,unlink:unlink2}}function cancelledResult2(){return Object.freeze({status:"cancelled",diagnostics:Object.freeze([diagnostic4("cancelled","Plugin selection operation was cancelled")])})}function sortSelections(selections){return Object.freeze([...selections].sort((left,right)=>left.profileId.localeCompare(right.profileId)))}function persistedSelection(selection){return Object.freeze({profileId:selection.profileId,selectedPluginIds:selection.selectedPluginIds,disabledPluginIds:selection.disabledPluginIds})}function createPluginSelectionStoreV1(options){let filePath=validateFilePath2(options.filePath),fileSystem=options.fileSystem??defaultFileSystem2();async function read(signal){if(signal?.aborted)return cancelledResult2();let content;try{content=await fileSystem.readFile(filePath)}catch(error2){if(isMissingError3(error2))return Object.freeze({status:"missing",snapshot:EMPTY_SNAPSHOT2});if(isAbortError2(error2)||signal?.aborted)return cancelledResult2();throw error2}if(signal?.aborted)return cancelledResult2();let parsed;try{parsed=JSON.parse(content)}catch{return Object.freeze({status:"invalid",diagnostics:Object.freeze([diagnostic4("invalid_json","plugin selection JSON is invalid")])})}try{return Object.freeze({status:"ok",snapshot:validateSnapshot2(parsed)})}catch(error2){return Object.freeze({status:"invalid",diagnostics:Object.freeze([invalidFromError2(error2)])})}}async function write(snapshot2,signal){if(signal?.aborted)return cancelledResult2();let temporaryPath=join19(dirname7(filePath),`.${basename3(filePath)}.${randomUUID8()}.tmp`);try{return await fileSystem.mkdir(dirname7(filePath)),signal?.aborted||(await fileSystem.writeFile(temporaryPath,`${JSON.stringify({version:snapshot2.version,selections:snapshot2.selections.map(persistedSelection)})}
|
|
508
|
-
`),signal?.aborted)?cancelledResult2():(await fileSystem.rename(temporaryPath,filePath),Object.freeze({status:"ok",snapshot:snapshot2,changed:!0}))}finally{try{await fileSystem.unlink(temporaryPath)}catch{}}}let mutationTail=Promise.resolve();function enqueueMutation(operation){let result=mutationTail.then(operation,operation);return mutationTail=result.then(()=>{},()=>{}),result}return{read:async({signal}={})=>await read(signal),set:input=>enqueueMutation(async()=>{let selection;try{selection=createPluginSelectionV1(input.selection)}catch(error2){return Object.freeze({status:"invalid",diagnostics:Object.freeze([invalidFromError2(error2)])})}let current=await read(input.signal);if(current.status!=="ok"&¤t.status!=="missing")return current;if(input.signal?.aborted)return cancelledResult2();let existing=current.snapshot.selections.find(item=>item.profileId===selection.profileId);if(existing!==void 0&&JSON.stringify(existing)===JSON.stringify(selection))return Object.freeze({status:"ok",snapshot:current.snapshot,changed:!1});if(current.snapshot.selections.length>=MAX_PLUGIN_SELECTION_PROFILES_V1&&existing===void 0)return Object.freeze({status:"invalid",diagnostics:Object.freeze([diagnostic4("too_many_profiles","too many selection profiles")])});let snapshot2=Object.freeze({version:PLUGIN_SELECTION_STORE_VERSION_V1,selections:sortSelections([...current.snapshot.selections.filter(item=>item.profileId!==selection.profileId),selection])});return await write(snapshot2,input.signal)}),clear:input=>enqueueMutation(async()=>{let selection;try{selection=createPluginSelectionV1({profileId:input.profileId,selectedPluginIds:[],disabledPluginIds:[]})}catch(error2){return Object.freeze({status:"invalid",diagnostics:Object.freeze([invalidFromError2(error2)])})}let current=await read(input.signal);if(current.status!=="ok"&¤t.status!=="missing")return current;if(input.signal?.aborted)return cancelledResult2();let selections=current.snapshot.selections.filter(item=>item.profileId!==selection.profileId);return selections.length===current.snapshot.selections.length?Object.freeze({status:"ok",snapshot:current.snapshot,changed:!1}):await write(Object.freeze({version:PLUGIN_SELECTION_STORE_VERSION_V1,selections:sortSelections(selections)}),input.signal)})}}function freezeAssembly(assembly){return Object.freeze({...assembly,plugins:Object.freeze(assembly.plugins.map(plugin=>Object.freeze({...plugin,capabilityRefs:Object.freeze(plugin.capabilityRefs.map(ref=>Object.freeze({...ref}))),...plugin.selectedAdapter===void 0?{}:{selectedAdapter:Object.freeze({...plugin.selectedAdapter})}})))})}function assembleIdentity(input){let identity=buildProfileIdentityV1({profileId:input.profileId,profileVersion:input.profileVersion,resolvedPlugins:input.plugins,capabilityVersions:[...new Set(input.plugins.flatMap(plugin=>plugin.capabilityRefs))].sort((a,b2)=>a.id.localeCompare(b2.id)||a.version-b2.version)});return freezeAssembly({profileId:input.profileId,profileVersion:input.profileVersion,identity,plugins:[...input.plugins]})}function assembleProfile(input){let verified=new Map(input.verifiedPlugins.map(entry=>[`${entry.pluginId}@${entry.version}`,!0])),unverified=input.resolvedPlugins.filter(plugin=>!verified.has(`${plugin.pluginId}@${plugin.pluginVersion}`)).map(plugin=>({pluginId:plugin.pluginId,pluginVersion:plugin.pluginVersion}));return unverified.length>0?{status:"unverified",unverified}:{status:"assembled",assembly:assembleIdentity({profileId:input.profileId,profileVersion:input.profileVersion,plugins:input.resolvedPlugins})}}function replaceProfilePlugin(assembly,input){let fromPlugin=assembly.plugins.find(plugin=>plugin.pluginId===input.fromPluginId);if(!fromPlugin)return{status:"absent",pluginId:input.fromPluginId};if(!new Map(input.verifiedPlugins.map(entry=>[`${entry.pluginId}@${entry.version}`,!0])).has(`${input.replacement.pluginId}@${input.replacement.pluginVersion}`))return{status:"unverified",unverified:[{pluginId:input.replacement.pluginId,pluginVersion:input.replacement.pluginVersion}]};let nextPlugins=assembly.plugins.filter(plugin=>plugin.pluginId!==input.fromPluginId).concat([input.replacement]);return{status:"replaced",assembly:assembleIdentity({profileId:assembly.profileId,profileVersion:assembly.profileVersion,plugins:nextPlugins}),replacement:{from:{pluginId:fromPlugin.pluginId,pluginVersion:fromPlugin.pluginVersion},to:{pluginId:input.replacement.pluginId,pluginVersion:input.replacement.pluginVersion},reason:input.reason}}}var manifests=Object.freeze({}),profiles=Object.freeze([{id:"coding-core",version:"1",pluginIds:[]},{id:"desktop-qa",version:"1",pluginIds:["agent-forge.plugin.desktop-windows-observe","agent-forge.plugin.desktop-windows-input"]},{id:"desktop-observe",version:"1",pluginIds:["agent-forge.plugin.desktop-windows-observe"]},{id:"desktop-control",version:"1",pluginIds:["agent-forge.plugin.desktop-windows-observe","agent-forge.plugin.desktop-windows-input"]},{id:"lsp-diagnostics",version:"1",pluginIds:["agent-forge.plugin.lsp-diagnostics"]},{id:"process-exec",version:"1",pluginIds:["agent-forge.plugin.process-exec"]},{id:"test-runner",version:"1",pluginIds:["agent-forge.plugin.test-runner"]},{id:"workspace-files",version:"1",pluginIds:["agent-forge.plugin.workspace-files"]},{id:"workspace-files-write",version:"1",pluginIds:["agent-forge.plugin.workspace-files-write"]},{id:"formatter-linter",version:"1",pluginIds:["agent-forge.plugin.formatter-linter"]},{id:"git-repository",version:"1",pluginIds:["agent-forge.plugin.git-repository"]}]);function listBuiltinPluginProfilesV1(){return profiles}function listBuiltinPluginManifestsV1(){return Object.freeze(Object.values(manifests).sort((left,right)=>{let idOrder=`${left.id}@${left.pluginVersion}`.localeCompare(`${right.id}@${right.pluginVersion}`);return idOrder===0?comparePluginVersionsV1(left.pluginVersion,right.pluginVersion):idOrder}))}function defaultBuiltinVerifiedPluginsV1(profileId){let profile=profiles.find(candidate=>candidate.id===profileId);return profile===void 0?[]:profile.pluginIds.flatMap(pluginId=>{let manifest=manifests[pluginId];return manifest===void 0?[]:[{pluginId:manifest.id,version:manifest.pluginVersion}]})}function resolveBuiltinPluginProfileV1(input){let profile=profiles.find(candidate=>candidate.id===input.profileId);if(profile===void 0)return{status:"not_found",profileId:input.profileId};let requestedPluginIds=input.selectedPluginIds,requestedDisabledPluginIds=input.disabledPluginIds;if(requestedPluginIds!==void 0||requestedDisabledPluginIds!==void 0){let availablePluginIds=new Set(profile.pluginIds),duplicatePluginIds=[],unknownPluginIds=[];for(let requestedIds of[requestedPluginIds??[],requestedDisabledPluginIds??[]]){let seen=new Set;for(let pluginId of requestedIds)!availablePluginIds.has(pluginId)&&!unknownPluginIds.includes(pluginId)&&unknownPluginIds.push(pluginId),seen.has(pluginId)&&!duplicatePluginIds.includes(pluginId)&&duplicatePluginIds.push(pluginId),seen.add(pluginId)}if(unknownPluginIds.length>0||duplicatePluginIds.length>0)return{status:"invalid_selection",profileId:input.profileId,unknownPluginIds:Object.freeze([...new Set(unknownPluginIds)]),duplicatePluginIds:Object.freeze(duplicatePluginIds)}}let selected=requestedPluginIds===void 0?profile.pluginIds:profile.pluginIds.filter(pluginId=>requestedPluginIds.includes(pluginId)),selectedProfile=requestedPluginIds===void 0?profile:Object.freeze({...profile,pluginIds:Object.freeze([...selected])}),disabled=new Set(input.disabledPluginIds??[]),manifestByPluginId=new Map(selectedProfile.pluginIds.map(pluginId=>[pluginId,manifestFor(pluginId,input.manifestOverrides)])),missingPluginIds=selectedProfile.pluginIds.filter(pluginId=>manifestByPluginId.get(pluginId)===void 0),resolution=resolvePluginProfileV1({profileId:selectedProfile.id,profileVersion:selectedProfile.version,plugins:selectedProfile.pluginIds.flatMap(pluginId=>{let manifest=manifestByPluginId.get(pluginId);return manifest===void 0?[]:[{manifest,required:!disabled.has(pluginId),disabled:disabled.has(pluginId)}]}),host:input.host,hostVersion:VERSION}),merged=mergeMissingPluginResolutionsV1(resolution,missingPluginIds,disabled);if(merged.status!=="ready")return{status:"resolved",profile:selectedProfile,resolution:merged};let resolvedPlugins=merged.resolvedManifest.plugins.map(plugin=>({pluginId:plugin.pluginId,pluginVersion:plugin.pluginVersion,capabilityRefs:plugin.capabilityRefs,...plugin.selectedAdapter===void 0?{}:{selectedAdapter:plugin.selectedAdapter}})),verifiedPlugins=input.verifiedPlugins??[],assembly=assembleProfile({profileId:selectedProfile.id,profileVersion:selectedProfile.version,resolvedPlugins,verifiedPlugins});return{status:"resolved",profile:selectedProfile,resolution:merged,assembly}}function manifestFor(pluginId,overrides){let manifest=overrides?.[pluginId]??manifests[pluginId];if(manifest!==void 0&&manifest.id!==pluginId)throw new Error(`builtin manifest override does not match plugin ${pluginId}`);return manifest}function mergeMissingPluginResolutionsV1(resolution,missingPluginIds,disabled){if(missingPluginIds.length===0)return resolution;let missing=missingPluginIds.map(pluginId=>({pluginId,pluginVersion:"",required:!disabled.has(pluginId),status:"manifest-missing",diagnostics:[{code:"manifest_missing",message:`Plugin ${pluginId} has no builtin manifest and no installed active override; the plugin is omitted from this profile (install it with agent-forge plugin install)`}]})),plugins=[...resolution.plugins,...missing].sort((left,right)=>left.pluginId.localeCompare(right.pluginId));return Object.freeze({...resolution,plugins:Object.freeze(plugins),diagnostics:Object.freeze(plugins.flatMap(plugin=>plugin.diagnostics))})}var plugin_manager_controller_exports={};__export(plugin_manager_controller_exports,{createPluginManagerControllerV1:()=>createPluginManagerControllerV1});var MAX_MANAGER_ENTRIES_V1=128,MAX_MANAGER_DIAGNOSTICS_V1=8,MAX_MANAGER_ID_CHARS_V1=256;function boundedId(value,label){if(typeof value!="string"||value.trim()===""||value.length>MAX_MANAGER_ID_CHARS_V1||/[\u0000-\u001f\s]/u.test(value))throw new Error(`${label} is invalid`);return value}function signalAborted2(signal){return signal?.aborted===!0}function rejectionCodes(registry,pluginId,pluginVersion){return Object.freeze(registry.rejected.filter(entry=>entry.pluginId===pluginId&&entry.pluginVersion===pluginVersion).slice(0,MAX_MANAGER_DIAGNOSTICS_V1).map(entry=>entry.code))}function activeRecord(state2,pluginId){return state2.records.filter(record=>record.pluginId===pluginId&&record.state.lifecycle==="active").sort((left,right)=>comparePluginVersionsV1(right.pluginVersion,left.pluginVersion))[0]}function makeSnapshot(registry,stateStatus,state2){let identities=new Map;for(let entry of registry.entries)identities.set(`${entry.pluginId}@${entry.pluginVersion}`,entry);for(let rejection of registry.rejected){let identity=`${rejection.pluginId}@${rejection.pluginVersion}`;identities.has(identity)||identities.set(identity,{pluginId:rejection.pluginId,pluginVersion:rejection.pluginVersion,signed:!1})}let entries=[...identities.values()].map(entry=>{let installed=activeRecord(state2,entry.pluginId),diagnostics=rejectionCodes(registry,entry.pluginId,entry.pluginVersion),unavailable2=diagnostics.length>0||!registry.verified.some(candidate=>candidate.pluginId===entry.pluginId&&candidate.pluginVersion===entry.pluginVersion),isInstalled=installed?.pluginVersion===entry.pluginVersion;return Object.freeze({pluginId:entry.pluginId,pluginVersion:entry.pluginVersion,status:unavailable2?"unavailable":isInstalled?"installed":installed===void 0?"available":"update-available",signed:entry.signed,...installed===void 0?{}:{installedVersion:installed.pluginVersion,lifecycle:installed.state.lifecycle},diagnosticCodes:diagnostics})}).sort((left,right)=>{let idOrder=left.pluginId.localeCompare(right.pluginId);return idOrder===0?comparePluginVersionsV1(right.pluginVersion,left.pluginVersion):idOrder}),boundedEntries=Object.freeze(entries.slice(0,MAX_MANAGER_ENTRIES_V1));return Object.freeze({version:1,registrySource:registry.source,stateStatus,entries:boundedEntries,truncated:entries.length>boundedEntries.length})}function stateResult(result){if(result.status==="ok"||result.status==="missing")return{status:result.status,snapshot:result.snapshot}}function responseCode(response2){return response2.status==="unsupported"?"manager-operation-unsupported":response2.status==="cancelled"?"manager-operation-cancelled":"manager-operation-failed"}function createPluginManagerControllerV1(options){let getSnapshot=async(input={})=>{if(signalAborted2(input.signal))return{status:"error",code:"cancelled"};let registry;try{registry=await options.registry.list({signal:input.signal})}catch{return signalAborted2(input.signal)?{status:"error",code:"cancelled"}:{status:"error",code:"registry-unavailable"}}if(signalAborted2(input.signal))return{status:"error",code:"cancelled"};let state2;try{state2=await options.stateStore.read({signal:input.signal})}catch{return signalAborted2(input.signal)?{status:"error",code:"cancelled"}:{status:"error",code:"state-unavailable"}}if(signalAborted2(input.signal))return{status:"error",code:"cancelled"};let checkedState=stateResult(state2);return checkedState===void 0?{status:"error",code:state2.status==="cancelled"?"cancelled":"state-invalid"}:{status:"ok",snapshot:makeSnapshot(registry,checkedState.status,checkedState.snapshot)}},run=async input=>{try{boundedId(input.pluginId,"plugin ID"),input.pluginVersion!==void 0&&boundedId(input.pluginVersion,"plugin version")}catch{return{status:"failed",code:"manager-operation-failed"}}if(!input.confirmed)return{status:"needs_confirmation",code:"confirmation-required"};if(signalAborted2(input.signal))return{status:"cancelled",code:"cancelled"};let response2;try{let identity=input.pluginVersion===void 0?input.pluginId:`${input.pluginId}@${input.pluginVersion}`;response2=await options.cli.execute({argv:[input.command,identity,"--json"],signal:input.signal})}catch{return{status:"failed",code:"manager-operation-failed"}}if(response2.status!=="succeeded")return{status:response2.status==="unsupported"?"unsupported":response2.status==="cancelled"?"cancelled":"failed",code:responseCode(response2)};let refreshed=await getSnapshot({signal:input.signal});return refreshed.status==="ok"?{status:"succeeded",snapshot:refreshed.snapshot}:{status:"succeeded"}};return Object.freeze({getSnapshot,install:input=>run({...input,command:"install"}),update:input=>run({...input,command:"update"}),remove:input=>run({...input,command:"remove"})})}import{closeSync as closeSync2,fsyncSync,mkdirSync as mkdirSync3,openSync as openSync2,readFileSync as readFileSync4,statSync as statSync5,unlinkSync,writeFileSync as writeFileSync3,writeSync}from"node:fs";import{dirname as dirname8,join as join20}from"node:path";var lockSleepBuffer=new Int32Array(new SharedArrayBuffer(4));function sleepSync(ms){Atomics.wait(lockSleepBuffer,0,0,ms)}var DurableServiceErrorV1=class extends Error{code;constructor(code,message){super(message),this.name="DurableServiceErrorV1",this.code=code}};function durableLogPath(agentDir,sessionId){return join20(agentDir,"durable",`${sessionId}.jsonl`)}function assertNonEmptyString3(value,label){if(typeof value!="string"||value.trim().length===0)throw new Error(`${label} must be a non-empty string`)}var writeAllSync=(fd,data)=>{let buffer=Buffer.from(data,"utf8"),written=0;for(;written<buffer.length;)written+=writeSync(fd,buffer,written,buffer.length-written)},LOCK_FILE_SUFFIX=".lock",LEASE_FILE_SUFFIX=".lease",LOCK_POLL_INTERVAL_MS=25,DEFAULT_LOCK_TIMEOUT_MS=5e3,DEFAULT_STALE_LOCK_MS=6e4,DEFAULT_LEASE_TTL_MS=3e4;function acquirePersistLock(lockPath,lockTimeoutMs,staleLockMs){let deadline=Date.now()+lockTimeoutMs;for(;;){mkdirSync3(dirname8(lockPath),{recursive:!0});let token=`${process.pid}:${Date.now()}`;try{let fd=openSync2(lockPath,"wx");try{writeFileSync3(fd,token)}finally{closeSync2(fd)}return token}catch(error2){let code=error2.code;if(code==="EPERM"){let vanished=!1;try{statSync5(lockPath)}catch(statError){if(statError.code!=="ENOENT")throw error2;vanished=!0}if(vanished){if(Date.now()>=deadline)throw error2;sleepSync(LOCK_POLL_INTERVAL_MS);continue}}else if(code!=="EEXIST")throw error2;let stale=!1;try{stale=Date.now()-statSync5(lockPath).mtimeMs>staleLockMs}catch{}if(stale){try{unlinkSync(lockPath)}catch{}continue}if(Date.now()>=deadline)throw new Error(`durable store persist lock timeout after ${lockTimeoutMs} ms: ${lockPath} is held by another writer`);sleepSync(LOCK_POLL_INTERVAL_MS)}}}function releasePersistLock(lockPath,token){try{readFileSync4(lockPath,"utf8")===token&&unlinkSync(lockPath)}catch{}}function createFileDurableStoreBackend(options){if(assertNonEmptyString3(options.path,"Durable store path"),options.lockTimeoutMs!==void 0&&(!Number.isFinite(options.lockTimeoutMs)||options.lockTimeoutMs<=0))throw new Error("Durable store lockTimeoutMs must be a positive number");if(options.staleLockMs!==void 0&&(!Number.isFinite(options.staleLockMs)||options.staleLockMs<=0))throw new Error("Durable store staleLockMs must be a positive number");if(options.leaseTtlMs!==void 0&&(!Number.isFinite(options.leaseTtlMs)||options.leaseTtlMs<=0))throw new Error("Durable store leaseTtlMs must be a positive number");let path15=options.path,lockTimeoutMs=options.lockTimeoutMs??DEFAULT_LOCK_TIMEOUT_MS,staleLockMs=options.staleLockMs??DEFAULT_STALE_LOCK_MS,leaseTtlMs=options.leaseTtlMs??DEFAULT_LEASE_TTL_MS,lockPath=`${path15}${LOCK_FILE_SUFFIX}`,leasePath=`${path15}${LEASE_FILE_SUFFIX}`,readLease=()=>{try{let value=JSON.parse(readFileSync4(leasePath,"utf8"));if(typeof value!="object"||value===null||Array.isArray(value))return;let writerId=value.writerId,expiresAt=value.expiresAt;return typeof writerId!="string"||writerId.length===0||typeof expiresAt!="number"||!Number.isFinite(expiresAt)?void 0:{writerId,expiresAt}}catch{return}},writeLease=(writerId,expiresAt)=>{let fd=openSync2(leasePath,"w");try{writeAllSync(fd,JSON.stringify({writerId,expiresAt}))}finally{closeSync2(fd)}},liveForeign=(current,writerId)=>current.writerId!==writerId&&Date.now()<=current.expiresAt;return{persist(operations){if(operations.length===0)return;let lines=operations.map(operation=>`${JSON.stringify(storeOperationEnvelope(operation))}
|
|
508
|
+
`),signal?.aborted)?cancelledResult2():(await fileSystem.rename(temporaryPath,filePath),Object.freeze({status:"ok",snapshot:snapshot2,changed:!0}))}finally{try{await fileSystem.unlink(temporaryPath)}catch{}}}let mutationTail=Promise.resolve();function enqueueMutation(operation){let result=mutationTail.then(operation,operation);return mutationTail=result.then(()=>{},()=>{}),result}return{read:async({signal}={})=>await read(signal),set:input=>enqueueMutation(async()=>{let selection;try{selection=createPluginSelectionV1(input.selection)}catch(error2){return Object.freeze({status:"invalid",diagnostics:Object.freeze([invalidFromError2(error2)])})}let current=await read(input.signal);if(current.status!=="ok"&¤t.status!=="missing")return current;if(input.signal?.aborted)return cancelledResult2();let existing=current.snapshot.selections.find(item=>item.profileId===selection.profileId);if(existing!==void 0&&JSON.stringify(existing)===JSON.stringify(selection))return Object.freeze({status:"ok",snapshot:current.snapshot,changed:!1});if(current.snapshot.selections.length>=MAX_PLUGIN_SELECTION_PROFILES_V1&&existing===void 0)return Object.freeze({status:"invalid",diagnostics:Object.freeze([diagnostic4("too_many_profiles","too many selection profiles")])});let snapshot2=Object.freeze({version:PLUGIN_SELECTION_STORE_VERSION_V1,selections:sortSelections([...current.snapshot.selections.filter(item=>item.profileId!==selection.profileId),selection])});return await write(snapshot2,input.signal)}),clear:input=>enqueueMutation(async()=>{let selection;try{selection=createPluginSelectionV1({profileId:input.profileId,selectedPluginIds:[],disabledPluginIds:[]})}catch(error2){return Object.freeze({status:"invalid",diagnostics:Object.freeze([invalidFromError2(error2)])})}let current=await read(input.signal);if(current.status!=="ok"&¤t.status!=="missing")return current;if(input.signal?.aborted)return cancelledResult2();let selections=current.snapshot.selections.filter(item=>item.profileId!==selection.profileId);return selections.length===current.snapshot.selections.length?Object.freeze({status:"ok",snapshot:current.snapshot,changed:!1}):await write(Object.freeze({version:PLUGIN_SELECTION_STORE_VERSION_V1,selections:sortSelections(selections)}),input.signal)})}}function freezeAssembly(assembly){return Object.freeze({...assembly,plugins:Object.freeze(assembly.plugins.map(plugin=>Object.freeze({...plugin,capabilityRefs:Object.freeze(plugin.capabilityRefs.map(ref=>Object.freeze({...ref}))),...plugin.selectedAdapter===void 0?{}:{selectedAdapter:Object.freeze({...plugin.selectedAdapter})}})))})}function assembleIdentity(input){let identity=buildProfileIdentityV1({profileId:input.profileId,profileVersion:input.profileVersion,resolvedPlugins:input.plugins,capabilityVersions:[...new Set(input.plugins.flatMap(plugin=>plugin.capabilityRefs))].sort((a,b2)=>a.id.localeCompare(b2.id)||a.version-b2.version)});return freezeAssembly({profileId:input.profileId,profileVersion:input.profileVersion,identity,plugins:[...input.plugins]})}function assembleProfile(input){let verified=new Map(input.verifiedPlugins.map(entry=>[`${entry.pluginId}@${entry.version}`,!0])),unverified=input.resolvedPlugins.filter(plugin=>!verified.has(`${plugin.pluginId}@${plugin.pluginVersion}`)).map(plugin=>({pluginId:plugin.pluginId,pluginVersion:plugin.pluginVersion}));return unverified.length>0?{status:"unverified",unverified}:{status:"assembled",assembly:assembleIdentity({profileId:input.profileId,profileVersion:input.profileVersion,plugins:input.resolvedPlugins})}}function replaceProfilePlugin(assembly,input){let fromPlugin=assembly.plugins.find(plugin=>plugin.pluginId===input.fromPluginId);if(!fromPlugin)return{status:"absent",pluginId:input.fromPluginId};if(!new Map(input.verifiedPlugins.map(entry=>[`${entry.pluginId}@${entry.version}`,!0])).has(`${input.replacement.pluginId}@${input.replacement.pluginVersion}`))return{status:"unverified",unverified:[{pluginId:input.replacement.pluginId,pluginVersion:input.replacement.pluginVersion}]};let nextPlugins=assembly.plugins.filter(plugin=>plugin.pluginId!==input.fromPluginId).concat([input.replacement]);return{status:"replaced",assembly:assembleIdentity({profileId:assembly.profileId,profileVersion:assembly.profileVersion,plugins:nextPlugins}),replacement:{from:{pluginId:fromPlugin.pluginId,pluginVersion:fromPlugin.pluginVersion},to:{pluginId:input.replacement.pluginId,pluginVersion:input.replacement.pluginVersion},reason:input.reason}}}var manifests=Object.freeze({}),profiles=Object.freeze([{id:"coding-core",version:"1",pluginIds:[]},{id:"desktop-qa",version:"1",pluginIds:["agent-forge.plugin.desktop-windows-observe","agent-forge.plugin.desktop-windows-input"]},{id:"desktop-observe",version:"1",pluginIds:["agent-forge.plugin.desktop-windows-observe"]},{id:"desktop-control",version:"1",pluginIds:["agent-forge.plugin.desktop-windows-observe","agent-forge.plugin.desktop-windows-input"]},{id:"lsp-diagnostics",version:"1",pluginIds:["agent-forge.plugin.lsp-diagnostics"]},{id:"image-generation",version:"1",pluginIds:["agent-forge.plugin.image-generation"]},{id:"process-exec",version:"1",pluginIds:["agent-forge.plugin.process-exec"]},{id:"test-runner",version:"1",pluginIds:["agent-forge.plugin.test-runner"]},{id:"workspace-files",version:"1",pluginIds:["agent-forge.plugin.workspace-files"]},{id:"workspace-files-write",version:"1",pluginIds:["agent-forge.plugin.workspace-files-write"]},{id:"formatter-linter",version:"1",pluginIds:["agent-forge.plugin.formatter-linter"]},{id:"git-repository",version:"1",pluginIds:["agent-forge.plugin.git-repository"]}]);function listBuiltinPluginProfilesV1(){return profiles}function listBuiltinPluginManifestsV1(){return Object.freeze(Object.values(manifests).sort((left,right)=>{let idOrder=`${left.id}@${left.pluginVersion}`.localeCompare(`${right.id}@${right.pluginVersion}`);return idOrder===0?comparePluginVersionsV1(left.pluginVersion,right.pluginVersion):idOrder}))}function defaultBuiltinVerifiedPluginsV1(profileId){let profile=profiles.find(candidate=>candidate.id===profileId);return profile===void 0?[]:profile.pluginIds.flatMap(pluginId=>{let manifest=manifests[pluginId];return manifest===void 0?[]:[{pluginId:manifest.id,version:manifest.pluginVersion}]})}function resolveBuiltinPluginProfileV1(input){let profile=profiles.find(candidate=>candidate.id===input.profileId);if(profile===void 0)return{status:"not_found",profileId:input.profileId};let requestedPluginIds=input.selectedPluginIds,requestedDisabledPluginIds=input.disabledPluginIds;if(requestedPluginIds!==void 0||requestedDisabledPluginIds!==void 0){let availablePluginIds=new Set(profile.pluginIds),duplicatePluginIds=[],unknownPluginIds=[];for(let requestedIds of[requestedPluginIds??[],requestedDisabledPluginIds??[]]){let seen=new Set;for(let pluginId of requestedIds)!availablePluginIds.has(pluginId)&&!unknownPluginIds.includes(pluginId)&&unknownPluginIds.push(pluginId),seen.has(pluginId)&&!duplicatePluginIds.includes(pluginId)&&duplicatePluginIds.push(pluginId),seen.add(pluginId)}if(unknownPluginIds.length>0||duplicatePluginIds.length>0)return{status:"invalid_selection",profileId:input.profileId,unknownPluginIds:Object.freeze([...new Set(unknownPluginIds)]),duplicatePluginIds:Object.freeze(duplicatePluginIds)}}let selected=requestedPluginIds===void 0?profile.pluginIds:profile.pluginIds.filter(pluginId=>requestedPluginIds.includes(pluginId)),selectedProfile=requestedPluginIds===void 0?profile:Object.freeze({...profile,pluginIds:Object.freeze([...selected])}),disabled=new Set(input.disabledPluginIds??[]),manifestByPluginId=new Map(selectedProfile.pluginIds.map(pluginId=>[pluginId,manifestFor(pluginId,input.manifestOverrides)])),missingPluginIds=selectedProfile.pluginIds.filter(pluginId=>manifestByPluginId.get(pluginId)===void 0),resolution=resolvePluginProfileV1({profileId:selectedProfile.id,profileVersion:selectedProfile.version,plugins:selectedProfile.pluginIds.flatMap(pluginId=>{let manifest=manifestByPluginId.get(pluginId);return manifest===void 0?[]:[{manifest,required:!disabled.has(pluginId),disabled:disabled.has(pluginId)}]}),host:input.host,hostVersion:VERSION}),merged=mergeMissingPluginResolutionsV1(resolution,missingPluginIds,disabled);if(merged.status!=="ready")return{status:"resolved",profile:selectedProfile,resolution:merged};let resolvedPlugins=merged.resolvedManifest.plugins.map(plugin=>({pluginId:plugin.pluginId,pluginVersion:plugin.pluginVersion,capabilityRefs:plugin.capabilityRefs,...plugin.selectedAdapter===void 0?{}:{selectedAdapter:plugin.selectedAdapter}})),verifiedPlugins=input.verifiedPlugins??[],assembly=assembleProfile({profileId:selectedProfile.id,profileVersion:selectedProfile.version,resolvedPlugins,verifiedPlugins});return{status:"resolved",profile:selectedProfile,resolution:merged,assembly}}function manifestFor(pluginId,overrides){let manifest=overrides?.[pluginId]??manifests[pluginId];if(manifest!==void 0&&manifest.id!==pluginId)throw new Error(`builtin manifest override does not match plugin ${pluginId}`);return manifest}function mergeMissingPluginResolutionsV1(resolution,missingPluginIds,disabled){if(missingPluginIds.length===0)return resolution;let missing=missingPluginIds.map(pluginId=>({pluginId,pluginVersion:"",required:!disabled.has(pluginId),status:"manifest-missing",diagnostics:[{code:"manifest_missing",message:`Plugin ${pluginId} has no builtin manifest and no installed active override; the plugin is omitted from this profile (install it with agent-forge plugin install)`}]})),plugins=[...resolution.plugins,...missing].sort((left,right)=>left.pluginId.localeCompare(right.pluginId));return Object.freeze({...resolution,plugins:Object.freeze(plugins),diagnostics:Object.freeze(plugins.flatMap(plugin=>plugin.diagnostics))})}var plugin_manager_controller_exports={};__export(plugin_manager_controller_exports,{createPluginManagerControllerV1:()=>createPluginManagerControllerV1});var MAX_MANAGER_ENTRIES_V1=128,MAX_MANAGER_DIAGNOSTICS_V1=8,MAX_MANAGER_ID_CHARS_V1=256;function boundedId(value,label){if(typeof value!="string"||value.trim()===""||value.length>MAX_MANAGER_ID_CHARS_V1||/[\u0000-\u001f\s]/u.test(value))throw new Error(`${label} is invalid`);return value}function signalAborted2(signal){return signal?.aborted===!0}function rejectionCodes(registry,pluginId,pluginVersion){return Object.freeze(registry.rejected.filter(entry=>entry.pluginId===pluginId&&entry.pluginVersion===pluginVersion).slice(0,MAX_MANAGER_DIAGNOSTICS_V1).map(entry=>entry.code))}function activeRecord(state2,pluginId){return state2.records.filter(record=>record.pluginId===pluginId&&record.state.lifecycle==="active").sort((left,right)=>comparePluginVersionsV1(right.pluginVersion,left.pluginVersion))[0]}function makeSnapshot(registry,stateStatus,state2){let identities=new Map;for(let entry of registry.entries)identities.set(`${entry.pluginId}@${entry.pluginVersion}`,entry);for(let rejection of registry.rejected){let identity=`${rejection.pluginId}@${rejection.pluginVersion}`;identities.has(identity)||identities.set(identity,{pluginId:rejection.pluginId,pluginVersion:rejection.pluginVersion,signed:!1})}let entries=[...identities.values()].map(entry=>{let installed=activeRecord(state2,entry.pluginId),diagnostics=rejectionCodes(registry,entry.pluginId,entry.pluginVersion),unavailable2=diagnostics.length>0||!registry.verified.some(candidate=>candidate.pluginId===entry.pluginId&&candidate.pluginVersion===entry.pluginVersion),isInstalled=installed?.pluginVersion===entry.pluginVersion;return Object.freeze({pluginId:entry.pluginId,pluginVersion:entry.pluginVersion,status:unavailable2?"unavailable":isInstalled?"installed":installed===void 0?"available":"update-available",signed:entry.signed,...installed===void 0?{}:{installedVersion:installed.pluginVersion,lifecycle:installed.state.lifecycle},diagnosticCodes:diagnostics})}).sort((left,right)=>{let idOrder=left.pluginId.localeCompare(right.pluginId);return idOrder===0?comparePluginVersionsV1(right.pluginVersion,left.pluginVersion):idOrder}),boundedEntries=Object.freeze(entries.slice(0,MAX_MANAGER_ENTRIES_V1));return Object.freeze({version:1,registrySource:registry.source,stateStatus,entries:boundedEntries,truncated:entries.length>boundedEntries.length})}function stateResult(result){if(result.status==="ok"||result.status==="missing")return{status:result.status,snapshot:result.snapshot}}function responseCode(response2){return response2.status==="unsupported"?"manager-operation-unsupported":response2.status==="cancelled"?"manager-operation-cancelled":"manager-operation-failed"}function createPluginManagerControllerV1(options){let getSnapshot=async(input={})=>{if(signalAborted2(input.signal))return{status:"error",code:"cancelled"};let registry;try{registry=await options.registry.list({signal:input.signal})}catch{return signalAborted2(input.signal)?{status:"error",code:"cancelled"}:{status:"error",code:"registry-unavailable"}}if(signalAborted2(input.signal))return{status:"error",code:"cancelled"};let state2;try{state2=await options.stateStore.read({signal:input.signal})}catch{return signalAborted2(input.signal)?{status:"error",code:"cancelled"}:{status:"error",code:"state-unavailable"}}if(signalAborted2(input.signal))return{status:"error",code:"cancelled"};let checkedState=stateResult(state2);return checkedState===void 0?{status:"error",code:state2.status==="cancelled"?"cancelled":"state-invalid"}:{status:"ok",snapshot:makeSnapshot(registry,checkedState.status,checkedState.snapshot)}},run=async input=>{try{boundedId(input.pluginId,"plugin ID"),input.pluginVersion!==void 0&&boundedId(input.pluginVersion,"plugin version")}catch{return{status:"failed",code:"manager-operation-failed"}}if(!input.confirmed)return{status:"needs_confirmation",code:"confirmation-required"};if(signalAborted2(input.signal))return{status:"cancelled",code:"cancelled"};let response2;try{let identity=input.pluginVersion===void 0?input.pluginId:`${input.pluginId}@${input.pluginVersion}`;response2=await options.cli.execute({argv:[input.command,identity,"--json"],signal:input.signal})}catch{return{status:"failed",code:"manager-operation-failed"}}if(response2.status!=="succeeded")return{status:response2.status==="unsupported"?"unsupported":response2.status==="cancelled"?"cancelled":"failed",code:responseCode(response2)};let refreshed=await getSnapshot({signal:input.signal});return refreshed.status==="ok"?{status:"succeeded",snapshot:refreshed.snapshot}:{status:"succeeded"}};return Object.freeze({getSnapshot,install:input=>run({...input,command:"install"}),update:input=>run({...input,command:"update"}),remove:input=>run({...input,command:"remove"})})}import{closeSync as closeSync2,fsyncSync,mkdirSync as mkdirSync3,openSync as openSync2,readFileSync as readFileSync4,statSync as statSync5,unlinkSync,writeFileSync as writeFileSync3,writeSync}from"node:fs";import{dirname as dirname8,join as join20}from"node:path";var lockSleepBuffer=new Int32Array(new SharedArrayBuffer(4));function sleepSync(ms){Atomics.wait(lockSleepBuffer,0,0,ms)}var DurableServiceErrorV1=class extends Error{code;constructor(code,message){super(message),this.name="DurableServiceErrorV1",this.code=code}};function durableLogPath(agentDir,sessionId){return join20(agentDir,"durable",`${sessionId}.jsonl`)}function assertNonEmptyString3(value,label){if(typeof value!="string"||value.trim().length===0)throw new Error(`${label} must be a non-empty string`)}var writeAllSync=(fd,data)=>{let buffer=Buffer.from(data,"utf8"),written=0;for(;written<buffer.length;)written+=writeSync(fd,buffer,written,buffer.length-written)},LOCK_FILE_SUFFIX=".lock",LEASE_FILE_SUFFIX=".lease",LOCK_POLL_INTERVAL_MS=25,DEFAULT_LOCK_TIMEOUT_MS=5e3,DEFAULT_STALE_LOCK_MS=6e4,DEFAULT_LEASE_TTL_MS=3e4;function acquirePersistLock(lockPath,lockTimeoutMs,staleLockMs){let deadline=Date.now()+lockTimeoutMs;for(;;){mkdirSync3(dirname8(lockPath),{recursive:!0});let token=`${process.pid}:${Date.now()}`;try{let fd=openSync2(lockPath,"wx");try{writeFileSync3(fd,token)}finally{closeSync2(fd)}return token}catch(error2){let code=error2.code;if(code==="EPERM"){let vanished=!1;try{statSync5(lockPath)}catch(statError){if(statError.code!=="ENOENT")throw error2;vanished=!0}if(vanished){if(Date.now()>=deadline)throw error2;sleepSync(LOCK_POLL_INTERVAL_MS);continue}}else if(code!=="EEXIST")throw error2;let stale=!1;try{stale=Date.now()-statSync5(lockPath).mtimeMs>staleLockMs}catch{}if(stale){try{unlinkSync(lockPath)}catch{}continue}if(Date.now()>=deadline)throw new Error(`durable store persist lock timeout after ${lockTimeoutMs} ms: ${lockPath} is held by another writer`);sleepSync(LOCK_POLL_INTERVAL_MS)}}}function releasePersistLock(lockPath,token){try{readFileSync4(lockPath,"utf8")===token&&unlinkSync(lockPath)}catch{}}function createFileDurableStoreBackend(options){if(assertNonEmptyString3(options.path,"Durable store path"),options.lockTimeoutMs!==void 0&&(!Number.isFinite(options.lockTimeoutMs)||options.lockTimeoutMs<=0))throw new Error("Durable store lockTimeoutMs must be a positive number");if(options.staleLockMs!==void 0&&(!Number.isFinite(options.staleLockMs)||options.staleLockMs<=0))throw new Error("Durable store staleLockMs must be a positive number");if(options.leaseTtlMs!==void 0&&(!Number.isFinite(options.leaseTtlMs)||options.leaseTtlMs<=0))throw new Error("Durable store leaseTtlMs must be a positive number");let path15=options.path,lockTimeoutMs=options.lockTimeoutMs??DEFAULT_LOCK_TIMEOUT_MS,staleLockMs=options.staleLockMs??DEFAULT_STALE_LOCK_MS,leaseTtlMs=options.leaseTtlMs??DEFAULT_LEASE_TTL_MS,lockPath=`${path15}${LOCK_FILE_SUFFIX}`,leasePath=`${path15}${LEASE_FILE_SUFFIX}`,readLease=()=>{try{let value=JSON.parse(readFileSync4(leasePath,"utf8"));if(typeof value!="object"||value===null||Array.isArray(value))return;let writerId=value.writerId,expiresAt=value.expiresAt;return typeof writerId!="string"||writerId.length===0||typeof expiresAt!="number"||!Number.isFinite(expiresAt)?void 0:{writerId,expiresAt}}catch{return}},writeLease=(writerId,expiresAt)=>{let fd=openSync2(leasePath,"w");try{writeAllSync(fd,JSON.stringify({writerId,expiresAt}))}finally{closeSync2(fd)}},liveForeign=(current,writerId)=>current.writerId!==writerId&&Date.now()<=current.expiresAt;return{persist(operations){if(operations.length===0)return;let lines=operations.map(operation=>`${JSON.stringify(storeOperationEnvelope(operation))}
|
|
509
509
|
`),token=acquirePersistLock(lockPath,lockTimeoutMs,staleLockMs);try{let fd=openSync2(path15,"a");try{writeAllSync(fd,lines.join("")),fsyncSync(fd)}finally{closeSync2(fd)}}finally{releasePersistLock(lockPath,token)}},load(){let raw;try{raw=readFileSync4(path15,"utf8")}catch(error2){return error2.code==="ENOENT"?{operations:[],corruptedLines:0,unreadable:!1}:{operations:[],corruptedLines:0,unreadable:!0}}let operations=[],corruptedLines=0;for(let line of raw.split(`
|
|
510
510
|
`)){if(line.trim()==="")continue;let operation=parseStoreOperationLine(line);if(operation===void 0){corruptedLines+=1;continue}operations.push(operation)}return{operations,corruptedLines,unreadable:!1}},close(){},lease:{claim(writerId){let token=acquirePersistLock(lockPath,lockTimeoutMs,staleLockMs);try{let current=readLease();return current!==void 0&&liveForeign(current,writerId)?{status:"held",by:current.writerId}:(writeLease(writerId,Date.now()+leaseTtlMs),{status:"claimed"})}finally{releasePersistLock(lockPath,token)}},release(writerId){let token=acquirePersistLock(lockPath,lockTimeoutMs,staleLockMs);try{let current=readLease();if(current===void 0||current.writerId===writerId){try{unlinkSync(leasePath)}catch{}return{status:"released"}}throw new DurableServiceErrorV1("not_writer",`Writer ${writerId} does not hold the store lease (held by ${current.writerId})`)}finally{releasePersistLock(lockPath,token)}},recover(writerId){let token=acquirePersistLock(lockPath,lockTimeoutMs,staleLockMs);try{let current=readLease();if(current!==void 0&&liveForeign(current,writerId))return{status:"held"};let previousWriter=current!==void 0&¤t.writerId!==writerId?current.writerId:void 0;return writeLease(writerId,Date.now()+leaseTtlMs),previousWriter===void 0?{status:"recovered"}:{status:"recovered",previousWriter}}finally{releasePersistLock(lockPath,token)}},renew(writerId){let token=acquirePersistLock(lockPath,lockTimeoutMs,staleLockMs);try{let current=readLease();if(current===void 0||current.writerId!==writerId||Date.now()>current.expiresAt)throw new DurableServiceErrorV1("not_writer",`Writer ${writerId} lost the store lease (expired or recovered by another writer)`);writeLease(writerId,Date.now()+leaseTtlMs)}finally{releasePersistLock(lockPath,token)}}}}}function storeOperationEnvelope(operation){return{kind:operation.kind,...operation.record}}function parseStoreOperationLine(line){try{let value=JSON.parse(line);if(typeof value!="object"||value===null||Array.isArray(value))return;let record=value;switch(record.kind){case"session":{let base=importRecordBase(record,"sessionId","Durable store session record");return{kind:"session",record:{sessionId:base.id,data:base.data,persistedAt:base.persistedAt}}}case"operation":{let base=importRecordBase(record,"operationId","Durable store operation record");return{kind:"operation",record:{operationId:base.id,sessionId:importOwningSessionId(record,"Durable store operation record"),data:base.data,persistedAt:base.persistedAt}}}case"artifact":{let base=importRecordBase(record,"artifactId","Durable store artifact record");return{kind:"artifact",record:{artifactId:base.id,sessionId:importOwningSessionId(record,"Durable store artifact record"),data:base.data,persistedAt:base.persistedAt}}}default:return}}catch{return}}function assertObject(value,label){if(typeof value!="object"||value===null||Array.isArray(value))throw new Error(`${label} must be an object`)}function importRecordBase(value,idField,label){let id=value[idField];if(typeof id!="string"||id.length===0)throw new Error(`${label} ${idField} must be a non-empty string`);let persistedAt=value.persistedAt;if(typeof persistedAt!="number"||!Number.isFinite(persistedAt))throw new Error(`${label} persistedAt must be a finite number`);return{id,data:value.data,persistedAt}}function importOwningSessionId(value,label){let sessionId=value.sessionId;if(typeof sessionId!="string"||sessionId.length===0)throw new Error(`${label} sessionId must be a non-empty string`);return sessionId}function createDurableService(options={}){let now=options.now??(()=>Date.now()),sessions=new Map,operations=new Map,artifacts=new Map,holder=null,crashPending=null,backend=options.backend,backendLease=backend?.lease,replay={corruptedLines:0,unreadable:!1};if(backend){let loaded=backend.load();for(let operation of loaded.operations)switch(operation.kind){case"session":sessions.set(operation.record.sessionId,operation.record);break;case"operation":operations.set(operation.record.operationId,operation.record);break;case"artifact":artifacts.set(operation.record.artifactId,operation.record);break}replay={corruptedLines:loaded.corruptedLines,unreadable:loaded.unreadable}}let logOperation=operation=>{backend&&backend.persist([operation])};function requireWriter(writerId){if(holder!==writerId)throw new DurableServiceErrorV1("not_writer",`Writer ${writerId} does not hold the writer lease`);backendLease?.renew(writerId)}return{persistSession(input){requireWriter(input.writerId);let record={sessionId:input.sessionId,data:input.data,persistedAt:now()};return logOperation({kind:"session",record}),sessions.set(input.sessionId,record),record},loadSession(input){return sessions.get(input.sessionId)},persistOperation(input){requireWriter(input.writerId);let record={operationId:input.operationId,sessionId:input.sessionId,data:input.data,persistedAt:now()};return logOperation({kind:"operation",record}),operations.set(input.operationId,record),record},loadOperation(input){return operations.get(input.operationId)},persistArtifact(input){requireWriter(input.writerId);let record={artifactId:input.artifactId,sessionId:input.sessionId,data:input.data,persistedAt:now()};return logOperation({kind:"artifact",record}),artifacts.set(input.artifactId,record),record},loadArtifact(input){return artifacts.get(input.artifactId)},listSessions(){return[...sessions.values()].sort((a,b2)=>a.sessionId<b2.sessionId?-1:a.sessionId>b2.sessionId?1:0)},claimWriter(writerId){if(crashPending!==null)return{status:"held",by:crashPending};if(backendLease===void 0)return holder!==null&&holder!==writerId?{status:"held",by:holder}:(holder=writerId,{status:"claimed"});let result=backendLease.claim(writerId);return result.status==="claimed"?(holder=writerId,{status:"claimed"}):{status:"held",by:result.by}},releaseWriter(writerId){if(crashPending!==null)throw new DurableServiceErrorV1("not_writer",`Writer ${writerId} cannot release a crashed lease; recover it instead`);if(backendLease===void 0){if(holder!==null&&holder!==writerId)throw new DurableServiceErrorV1("not_writer",`Writer ${writerId} does not hold the writer lease (held by ${holder})`);return holder=null,{status:"released"}}let result=backendLease.release(writerId);return holder=null,result},recoverWriter(writerId){if(crashPending!==null){let previousWriter=crashPending;return crashPending=null,holder=writerId,{status:"recovered",previousWriter}}if(backendLease===void 0)return holder!==null&&holder!==writerId?{status:"held"}:(holder=writerId,{status:"recovered"});let result=backendLease.recover(writerId);return result.status==="recovered"?(holder=writerId,result.previousWriter===void 0?{status:"recovered"}:{status:"recovered",previousWriter:result.previousWriter}):{status:"held"}},readiness(){return crashPending!==null?{ready:!1,reason:`writer crash is pending recovery: ${crashPending}`}:holder===null?{ready:!1,reason:"no writer has claimed the lease"}:{ready:!0}},exportState(){return{version:1,exportedAt:now(),sessions:[...sessions.values()],operations:[...operations.values()],artifacts:[...artifacts.values()],writer:{holder,crashPending}}},importState(snapshot2){if(assertObject(snapshot2,"Durable snapshot"),snapshot2.version!==1)throw new Error(`Unsupported durable snapshot version: ${String(snapshot2.version)}`);for(let field2 of["sessions","operations","artifacts"])if(!Array.isArray(snapshot2[field2]))throw new Error(`Durable snapshot ${field2} must be an array`);let writer=snapshot2.writer;assertObject(writer,"Durable snapshot writer");let snapshotHolder=writer.holder,snapshotCrashPending=writer.crashPending;if(snapshotHolder!==null&&typeof snapshotHolder!="string")throw new Error("Durable snapshot writer holder must be a string or null");if(snapshotCrashPending!==null&&typeof snapshotCrashPending!="string")throw new Error("Durable snapshot writer crashPending must be a string or null");let importedSessions=new Map;for(let raw of snapshot2.sessions){assertObject(raw,"Durable snapshot session");let record=importRecordBase(raw,"sessionId","Durable snapshot session");importedSessions.set(record.id,{sessionId:record.id,data:record.data,persistedAt:record.persistedAt})}let importedOperations=new Map;for(let raw of snapshot2.operations){assertObject(raw,"Durable snapshot operation");let record=importRecordBase(raw,"operationId","Durable snapshot operation");importedOperations.set(record.id,{operationId:record.id,sessionId:importOwningSessionId(raw,"Durable snapshot operation"),data:record.data,persistedAt:record.persistedAt})}let importedArtifacts=new Map;for(let raw of snapshot2.artifacts){assertObject(raw,"Durable snapshot artifact");let record=importRecordBase(raw,"artifactId","Durable snapshot artifact");importedArtifacts.set(record.id,{artifactId:record.id,sessionId:importOwningSessionId(raw,"Durable snapshot artifact"),data:record.data,persistedAt:record.persistedAt})}sessions.clear();for(let[id,record]of importedSessions)sessions.set(id,record);operations.clear();for(let[id,record]of importedOperations)operations.set(id,record);artifacts.clear();for(let[id,record]of importedArtifacts)artifacts.set(id,record);holder=null,crashPending=snapshotHolder??snapshotCrashPending},replayDiagnostics(){return replay}}}import{Buffer as Buffer5}from"node:buffer";import{randomUUID as randomUUID12}from"node:crypto";var INTERNAL_SERVER_ERROR_MESSAGE="Internal server error",NOT_IMPLEMENTED_MESSAGE="Operation is not implemented",PiServerError=class extends Error{code;details;constructor(code,message,details){super(message),this.name="PiServerError",this.code=code,this.details=details}};var UnauthorizedError=class extends PiServerError{constructor(message="Authentication or authorization failed",details){super("unauthorized",message,details),this.name="UnauthorizedError"}},InternalServerError=class extends Error{constructor(cause){super(INTERNAL_SERVER_ERROR_MESSAGE,{cause}),this.name="InternalServerError"}};import{appendFile,mkdir as mkdir6,readFile as readFile7}from"node:fs/promises";import{dirname as dirname9}from"node:path";function assertCursor(value,label){if(!Number.isSafeInteger(value)||value<0)throw new TypeError(`${label} must be a non-negative integer`)}function assertLimit(value){if(!Number.isSafeInteger(value)||value<1||value>1e3)throw new TypeError("Replay limit must be between 1 and 1000")}var FileDurableSessionEventJournal=class{path;maxEntries;records=new Map;nextCursors=new Map;writeQueue=Promise.resolve();ready;constructor(path15,options={}){if(this.path=path15,this.maxEntries=options.maxEntries??1e4,!Number.isSafeInteger(this.maxEntries)||this.maxEntries<1)throw new TypeError("Journal maxEntries must be a positive safe integer");this.ready=this.load()}async append(sessionId,event){if(sessionId.trim()==="")throw new TypeError("Journal sessionId must be non-empty");let append=this.writeQueue.then(async()=>{await this.ready;let cursor=this.nextCursors.get(sessionId)??1,record={sessionId,cursor,event:structuredClone(event)};await mkdir6(dirname9(this.path),{recursive:!0}),await appendFile(this.path,`${JSON.stringify(record)}
|
|
511
511
|
`,"utf8");let entries=this.records.get(sessionId)??[];for(entries.push(record);entries.length>this.maxEntries;)entries.shift();return this.records.set(sessionId,entries),this.nextCursors.set(sessionId,cursor+1),cursor});return this.writeQueue=append.then(()=>{},()=>{}),append}async replay(sessionId,afterCursor,limit){assertCursor(afterCursor,"Replay afterCursor"),assertLimit(limit),await this.ready,await this.writeQueue;let entries=this.records.get(sessionId)??[],firstCursor=entries[0]?.cursor,gap=firstCursor===void 0?afterCursor>0:afterCursor<firstCursor-1,selected=entries.filter(entry=>entry.cursor>afterCursor).slice(0,limit),nextCursor=selected.at(-1)?.cursor??afterCursor,latestCursor=(this.nextCursors.get(sessionId)??1)-1;return{events:selected.map(({cursor,event})=>({cursor,event:structuredClone(event)})),nextCursor,complete:!gap&&nextCursor>=latestCursor,gap}}async close(){await this.ready,await this.writeQueue}async load(){let contents;try{contents=await readFile7(this.path,"utf8")}catch(error2){if(error2.code==="ENOENT")return;throw error2}let lines=contents.split(/\r?\n/);for(;lines.length>0&&lines.at(-1).trim()==="";)lines.pop();for(let[index3,line]of lines.entries()){if(line.trim()==="")continue;let isTail=index3===lines.length-1,record;try{record=JSON.parse(line)}catch{if(isTail)break;throw new Error("Invalid durable session journal record")}if(!record||typeof record.sessionId!="string"||!Number.isSafeInteger(record.cursor)){if(isTail)break;throw new Error("Invalid durable session journal record")}let entries=this.records.get(record.sessionId)??[];for(entries.push(record);entries.length>this.maxEntries;)entries.shift();this.records.set(record.sessionId,entries),this.nextCursors.set(record.sessionId,Math.max(this.nextCursors.get(record.sessionId)??1,record.cursor+1))}}};function nonNegativeNumber(value){return Number.isFinite(value)?Math.max(0,value):0}function identifier(value,label){if(typeof value!="string"||value.length===0)throw new TypeError(`${label} must be a non-empty string`);return value}function toProtocolModelMetadata(model,authenticated){return{provider:identifier(model.provider,"Model provider"),id:identifier(model.id,"Model id"),name:identifier(model.name,"Model name"),api:identifier(model.api,"Model API"),reasoning:model.reasoning,input:[...model.input],contextWindow:Math.max(1,Math.floor(model.contextWindow)),maxTokens:Math.max(1,Math.floor(model.maxTokens)),cost:{input:nonNegativeNumber(model.cost.input),output:nonNegativeNumber(model.cost.output),cacheRead:nonNegativeNumber(model.cost.cacheRead),cacheWrite:nonNegativeNumber(model.cost.cacheWrite)},supportedThinkingLevels:getSupportedThinkingLevels(model),authenticated}}import{randomUUID as randomUUID9}from"node:crypto";var DEFAULT_READ_TOKEN_TTL_MS=6e4,ReadTokenStore=class{ttlMs;now;tokens=new Map;constructor(options){let ttlMs=options?.ttlMs??DEFAULT_READ_TOKEN_TTL_MS;if(!Number.isSafeInteger(ttlMs)||ttlMs<=0)throw new TypeError("Read token TTL must be a positive safe integer");this.ttlMs=ttlMs,this.now=options?.now??(()=>Date.now())}issue(sessionId,artifactId){this.sweepExpired();let token=randomUUID9(),expiresAt=this.now()+this.ttlMs;return this.tokens.set(token,{sessionId,artifactId,expiresAt}),{token,expiresAt}}consume(token,expected){let entry=this.tokens.get(token);return entry?(this.tokens.delete(token),entry.expiresAt<=this.now()?{ok:!1,reason:"expired"}:entry.sessionId!==expected.sessionId||entry.artifactId!==expected.artifactId?{ok:!1,reason:"binding_mismatch"}:{ok:!0,sessionId:entry.sessionId,artifactId:entry.artifactId}):{ok:!1,reason:"unknown"}}revokeSession(sessionId){let revoked=0;for(let[token,entry]of this.tokens)entry.sessionId===sessionId&&(this.tokens.delete(token),revoked+=1);return revoked}sweepExpired(){let now=this.now();for(let[token,entry]of this.tokens)entry.expiresAt<=now&&this.tokens.delete(token)}};import{randomUUID as randomUUID11}from"node:crypto";var PROTOCOL_VERSION=1,IdSchema=build_default.String({minLength:1}),TimestampSchema=build_default.Integer({minimum:0}),Base64Schema=build_default.String({pattern:"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"}),StrictObject=properties=>build_default.Object(properties,{additionalProperties:!1}),JsonValueRecursiveSchema=build_default.Cyclic({JsonValue:build_default.Union([build_default.Null(),build_default.Boolean(),build_default.Number(),build_default.String(),build_default.Array(build_default.Ref("JsonValue")),build_default.Record(build_default.String(),build_default.Ref("JsonValue"))])},"JsonValue"),JsonValueSchema=build_default.Unsafe(JsonValueRecursiveSchema),ThinkingLevelSchema=build_default.Union([build_default.Literal("off"),build_default.Literal("minimal"),build_default.Literal("low"),build_default.Literal("medium"),build_default.Literal("high"),build_default.Literal("xhigh"),build_default.Literal("max")]),SessionPhaseSchema=build_default.Union([build_default.Literal("idle"),build_default.Literal("turn"),build_default.Literal("compaction"),build_default.Literal("branch_summary"),build_default.Literal("retry")]),ModelRefSchema=StrictObject({provider:IdSchema,id:IdSchema}),ModelCostSchema2=StrictObject({input:build_default.Number({minimum:0}),output:build_default.Number({minimum:0}),cacheRead:build_default.Number({minimum:0}),cacheWrite:build_default.Number({minimum:0})}),ModelMetadataSchema=StrictObject({provider:IdSchema,id:IdSchema,name:build_default.String({minLength:1}),api:IdSchema,reasoning:build_default.Boolean(),input:build_default.Array(build_default.Union([build_default.Literal("text"),build_default.Literal("image")])),contextWindow:build_default.Integer({minimum:1}),maxTokens:build_default.Integer({minimum:1}),cost:ModelCostSchema2,supportedThinkingLevels:build_default.Array(ThinkingLevelSchema,{minItems:1}),authenticated:build_default.Boolean()}),TextContentSchema=StrictObject({type:build_default.Literal("text"),text:build_default.String()}),ThinkingContentSchema=StrictObject({type:build_default.Literal("thinking"),thinking:build_default.String(),redacted:build_default.Optional(build_default.Boolean())}),ImageContentSchema=StrictObject({type:build_default.Literal("image"),data:build_default.String(),mimeType:build_default.String({minLength:1})}),ToolCallContentSchema=StrictObject({type:build_default.Literal("toolCall"),toolCallId:IdSchema,toolName:IdSchema,input:JsonValueSchema}),UserContentSchema=build_default.Union([TextContentSchema,ImageContentSchema]),AssistantContentSchema=build_default.Union([TextContentSchema,ThinkingContentSchema,ToolCallContentSchema]),ToolContentSchema=build_default.Union([TextContentSchema,ImageContentSchema]),UsageSchema=StrictObject({input:build_default.Integer({minimum:0}),output:build_default.Integer({minimum:0}),cacheRead:build_default.Integer({minimum:0}),cacheWrite:build_default.Integer({minimum:0}),reasoning:build_default.Optional(build_default.Integer({minimum:0})),totalTokens:build_default.Integer({minimum:0}),cost:StrictObject({input:build_default.Number({minimum:0}),output:build_default.Number({minimum:0}),cacheRead:build_default.Number({minimum:0}),cacheWrite:build_default.Number({minimum:0}),total:build_default.Number({minimum:0})})}),UserTranscriptItemSchema=StrictObject({id:IdSchema,role:build_default.Literal("user"),content:build_default.Array(UserContentSchema),timestamp:TimestampSchema}),AssistantTranscriptItemProperties={id:IdSchema,role:build_default.Literal("assistant"),content:build_default.Array(AssistantContentSchema),model:ModelRefSchema,responseModel:build_default.Optional(build_default.String({minLength:1})),usage:build_default.Optional(UsageSchema),timestamp:TimestampSchema},StreamingAssistantTranscriptItemSchema=StrictObject({...AssistantTranscriptItemProperties,status:build_default.Literal("streaming")}),CompleteAssistantTranscriptItemSchema=StrictObject({...AssistantTranscriptItemProperties,status:build_default.Literal("complete"),stopReason:build_default.Union([build_default.Literal("stop"),build_default.Literal("length"),build_default.Literal("toolUse")])}),ErrorAssistantTranscriptItemSchema=StrictObject({...AssistantTranscriptItemProperties,status:build_default.Literal("error"),stopReason:build_default.Literal("error"),errorMessage:build_default.Optional(build_default.String({minLength:1}))}),AbortedAssistantTranscriptItemSchema=StrictObject({...AssistantTranscriptItemProperties,status:build_default.Literal("aborted"),stopReason:build_default.Literal("aborted"),errorMessage:build_default.Optional(build_default.String())}),AssistantTranscriptItemSchema=build_default.Union([StreamingAssistantTranscriptItemSchema,CompleteAssistantTranscriptItemSchema,ErrorAssistantTranscriptItemSchema,AbortedAssistantTranscriptItemSchema]),ToolTranscriptItemProperties={id:IdSchema,role:build_default.Literal("tool"),toolCallId:IdSchema,toolName:IdSchema,input:JsonValueSchema,content:build_default.Array(ToolContentSchema),details:build_default.Optional(JsonValueSchema),usage:build_default.Optional(UsageSchema),timestamp:TimestampSchema},RunningToolTranscriptItemSchema=StrictObject({...ToolTranscriptItemProperties,status:build_default.Literal("running"),isError:build_default.Literal(!1)}),CompleteToolTranscriptItemSchema=StrictObject({...ToolTranscriptItemProperties,status:build_default.Literal("complete"),isError:build_default.Literal(!1)}),ErrorToolTranscriptItemSchema=StrictObject({...ToolTranscriptItemProperties,status:build_default.Literal("error"),isError:build_default.Literal(!0)}),ToolTranscriptItemSchema=build_default.Union([RunningToolTranscriptItemSchema,CompleteToolTranscriptItemSchema,ErrorToolTranscriptItemSchema]),NoteTranscriptItemSchema=StrictObject({id:IdSchema,role:build_default.Literal("note"),kind:build_default.Union([build_default.Literal("branchSummary"),build_default.Literal("compactionSummary"),build_default.Literal("custom")]),text:build_default.String(),fromId:build_default.Optional(build_default.String()),tokensBefore:build_default.Optional(build_default.Integer({minimum:0})),customType:build_default.Optional(build_default.String()),display:build_default.Optional(build_default.Boolean()),timestamp:TimestampSchema}),TranscriptItemSchema=build_default.Union([UserTranscriptItemSchema,AssistantTranscriptItemSchema,ToolTranscriptItemSchema,NoteTranscriptItemSchema]),TranscriptProgressSchema=build_default.Union([StrictObject({type:build_default.Literal("item_started"),item:TranscriptItemSchema}),StrictObject({type:build_default.Literal("assistant_delta"),messageId:IdSchema,contentIndex:build_default.Integer({minimum:0}),kind:build_default.Union([build_default.Literal("text"),build_default.Literal("thinking"),build_default.Literal("toolCall")]),delta:build_default.String()}),StrictObject({type:build_default.Literal("item_updated"),item:build_default.Union([AssistantTranscriptItemSchema,ToolTranscriptItemSchema])}),StrictObject({type:build_default.Literal("item_finished"),item:build_default.Union([CompleteAssistantTranscriptItemSchema,ErrorAssistantTranscriptItemSchema,AbortedAssistantTranscriptItemSchema,CompleteToolTranscriptItemSchema,ErrorToolTranscriptItemSchema])})]),SessionMetadataSchema=StrictObject({id:IdSchema,createdAt:TimestampSchema,updatedAt:build_default.Optional(TimestampSchema),parentSessionId:build_default.Optional(IdSchema),sessionName:build_default.Optional(build_default.String()),cwd:build_default.Optional(build_default.String({minLength:1}))}),SessionSnapshotSchema=StrictObject({id:IdSchema,name:build_default.Optional(build_default.String()),cwd:build_default.String({minLength:1}),createdAt:TimestampSchema,updatedAt:TimestampSchema,phase:SessionPhaseSchema,model:ModelRefSchema,thinkingLevel:ThinkingLevelSchema,profileId:build_default.Optional(IdSchema),profileVersion:build_default.Optional(IdSchema),attached:build_default.Boolean(),locked:build_default.Boolean(),revision:build_default.Integer({minimum:0}),transcript:build_default.Array(TranscriptItemSchema),queuedSteer:build_default.Array(UserTranscriptItemSchema),queuedSteerCount:build_default.Integer({minimum:0})}),ServerSnapshotSchema=StrictObject({serverId:IdSchema,protocolVersion:build_default.Literal(PROTOCOL_VERSION),revision:build_default.Integer({minimum:0}),sessions:build_default.Array(SessionMetadataSchema),models:build_default.Array(ModelMetadataSchema)}),ProtocolErrorCodeSchema=build_default.Union([build_default.Literal("version"),build_default.Literal("busy"),build_default.Literal("session_locked"),build_default.Literal("not_found"),build_default.Literal("invalid_request"),build_default.Literal("unauthorized"),build_default.Literal("not_implemented"),build_default.Literal("internal_error"),build_default.Literal("operation_conflict"),build_default.Literal("operation_not_found"),build_default.Literal("durable_unavailable"),build_default.Literal("operation_cancelled")]),ProtocolErrorSchema=StrictObject({code:ProtocolErrorCodeSchema,message:build_default.String(),details:build_default.Optional(JsonValueSchema)}),PromptPayloadProperties={sessionId:IdSchema,text:build_default.String()},OperationIdProperty={operationId:build_default.Optional(IdSchema)},ListCommandSchema=StrictObject({command:build_default.Literal("list")}),CreateCommandSchema=StrictObject({command:build_default.Literal("create"),cwd:build_default.Optional(build_default.String({minLength:1})),name:build_default.Optional(build_default.String()),model:build_default.Optional(ModelRefSchema),thinkingLevel:build_default.Optional(ThinkingLevelSchema),profileId:build_default.Optional(IdSchema),profileVersion:build_default.Optional(IdSchema)}),SessionLeaseModeSchema=build_default.Union([build_default.Literal("shared"),build_default.Literal("exclusive")]),AttachCommandSchema=StrictObject({command:build_default.Literal("attach"),sessionId:IdSchema,mode:build_default.Optional(SessionLeaseModeSchema)}),DetachCommandSchema=StrictObject({command:build_default.Literal("detach"),sessionId:IdSchema}),PromptCommandSchema=StrictObject({command:build_default.Literal("prompt"),...PromptPayloadProperties,...OperationIdProperty}),SteerCommandSchema=StrictObject({command:build_default.Literal("steer"),...PromptPayloadProperties,...OperationIdProperty}),AbortCommandSchema=StrictObject({command:build_default.Literal("abort"),sessionId:IdSchema,...OperationIdProperty}),SetModelCommandSchema=StrictObject({command:build_default.Literal("set_model"),sessionId:IdSchema,model:ModelRefSchema,...OperationIdProperty}),SetThinkingCommandSchema=StrictObject({command:build_default.Literal("set_thinking"),sessionId:IdSchema,thinkingLevel:ThinkingLevelSchema,...OperationIdProperty}),ReplayCommandSchema=StrictObject({command:build_default.Literal("replay"),sessionId:IdSchema,afterCursor:build_default.Integer({minimum:0}),limit:build_default.Integer({minimum:1,maximum:1e3})}),ArtifactStatCommandSchema=StrictObject({command:build_default.Literal("artifact_stat"),sessionId:IdSchema,artifactId:IdSchema}),ArtifactReadCommandSchema=StrictObject({command:build_default.Literal("artifact_read"),sessionId:IdSchema,artifactId:IdSchema,offset:build_default.Integer({minimum:0}),maxBytes:build_default.Integer({minimum:1,maximum:1048576})}),ArtifactTokenIssueCommandSchema=StrictObject({command:build_default.Literal("artifact_token_issue"),sessionId:IdSchema,artifactId:IdSchema}),LeaseRenewCommandSchema=StrictObject({command:build_default.Literal("lease_renew"),sessionId:IdSchema}),LeaseRenewResultSchema=StrictObject({command:build_default.Literal("lease_renew"),sessionId:IdSchema,leaseId:IdSchema,expiresAt:TimestampSchema}),OperationSubmitCommandSchema=StrictObject({command:build_default.Literal("operation_submit"),sessionId:IdSchema,operationType:build_default.String(),input:build_default.Optional(JsonValueSchema),idempotencyKey:build_default.Optional(build_default.String()),expectedRevision:build_default.Optional(build_default.Integer({minimum:0}))}),OperationCancelCommandSchema=StrictObject({command:build_default.Literal("operation_cancel"),sessionId:IdSchema,operationId:build_default.String()}),OperationResultCommandSchema=StrictObject({command:build_default.Literal("operation_result"),sessionId:IdSchema,operationId:build_default.String()}),CommandSchema=build_default.Union([ListCommandSchema,CreateCommandSchema,AttachCommandSchema,DetachCommandSchema,PromptCommandSchema,SteerCommandSchema,AbortCommandSchema,SetModelCommandSchema,SetThinkingCommandSchema,ReplayCommandSchema,ArtifactStatCommandSchema,ArtifactReadCommandSchema,ArtifactTokenIssueCommandSchema,LeaseRenewCommandSchema,OperationSubmitCommandSchema,OperationCancelCommandSchema,OperationResultCommandSchema]),CreateResultSchema=StrictObject({command:build_default.Literal("create"),session:SessionSnapshotSchema,leaseId:build_default.Optional(IdSchema),leaseExpiresAt:build_default.Optional(TimestampSchema)}),AttachResultSchema=StrictObject({command:build_default.Literal("attach"),session:SessionSnapshotSchema,leaseId:build_default.Optional(IdSchema),leaseExpiresAt:build_default.Optional(TimestampSchema)}),PromptResultSchema=StrictObject({command:build_default.Literal("prompt"),session:SessionSnapshotSchema}),SteerResultSchema=StrictObject({command:build_default.Literal("steer"),session:SessionSnapshotSchema}),AbortResultSchema=StrictObject({command:build_default.Literal("abort"),session:SessionSnapshotSchema}),SetModelResultSchema=StrictObject({command:build_default.Literal("set_model"),session:SessionSnapshotSchema}),SetThinkingResultSchema=StrictObject({command:build_default.Literal("set_thinking"),session:SessionSnapshotSchema}),ArtifactRefSchema=StrictObject({sessionId:IdSchema,operationId:IdSchema,artifactId:IdSchema,kind:IdSchema,mediaType:IdSchema,sizeBytes:build_default.Optional(build_default.Integer({minimum:0})),truncated:build_default.Boolean(),createdAt:TimestampSchema}),ArtifactStatResultSchema=StrictObject({command:build_default.Literal("artifact_stat"),artifact:ArtifactRefSchema}),ArtifactReadResultSchema=StrictObject({command:build_default.Literal("artifact_read"),artifact:ArtifactRefSchema,encoding:build_default.Literal("base64"),data:Base64Schema,nextOffset:build_default.Optional(build_default.Integer({minimum:0})),eof:build_default.Boolean()}),ArtifactTokenIssueResultSchema=StrictObject({command:build_default.Literal("artifact_token_issue"),token:IdSchema,expiresAt:TimestampSchema,sessionId:IdSchema,artifactId:IdSchema}),ReplayEventSchema=StrictObject({cursor:build_default.Integer({minimum:1}),event:build_default.Union([StrictObject({type:build_default.Literal("server_snapshot"),snapshot:ServerSnapshotSchema}),StrictObject({type:build_default.Literal("session_snapshot"),snapshot:SessionSnapshotSchema}),StrictObject({type:build_default.Literal("session_progress"),sessionId:IdSchema,progress:TranscriptProgressSchema}),StrictObject({type:build_default.Literal("session_removed"),sessionId:IdSchema})])}),ReplayResultSchema=StrictObject({command:build_default.Literal("replay"),sessionId:IdSchema,afterCursor:build_default.Integer({minimum:0}),nextCursor:build_default.Integer({minimum:0}),complete:build_default.Boolean(),gap:build_default.Boolean(),events:build_default.Array(ReplayEventSchema)}),ListResultSchema=StrictObject({command:build_default.Literal("list"),sessions:build_default.Array(SessionMetadataSchema)}),DetachResultSchema=StrictObject({command:build_default.Literal("detach"),sessionId:IdSchema}),OperationAckResultSchema=StrictObject({command:build_default.Literal("operation_ack"),operationId:IdSchema,status:build_default.Union([build_default.Literal("accepted"),build_default.Literal("completed"),build_default.Literal("rejected")]),result:build_default.Optional(JsonValueSchema),error:build_default.Optional(ProtocolErrorSchema)}),CommandResultSchema=build_default.Union([ListResultSchema,CreateResultSchema,AttachResultSchema,DetachResultSchema,PromptResultSchema,SteerResultSchema,AbortResultSchema,SetModelResultSchema,SetThinkingResultSchema,ReplayResultSchema,LeaseRenewResultSchema,ArtifactStatResultSchema,ArtifactReadResultSchema,ArtifactTokenIssueResultSchema,OperationAckResultSchema]),ClientHelloSchema=StrictObject({type:build_default.Literal("hello"),version:build_default.Integer({minimum:0}),auth:build_default.Optional(JsonValueSchema)}),RequestEnvelopeSchema=StrictObject({type:build_default.Literal("request"),id:IdSchema,request:CommandSchema}),ClientMessageSchema=build_default.Union([ClientHelloSchema,RequestEnvelopeSchema]),ServerEventSchema=build_default.Union([StrictObject({type:build_default.Literal("server_snapshot"),snapshot:ServerSnapshotSchema}),StrictObject({type:build_default.Literal("session_snapshot"),snapshot:SessionSnapshotSchema}),StrictObject({type:build_default.Literal("session_progress"),sessionId:IdSchema,progress:TranscriptProgressSchema}),StrictObject({type:build_default.Literal("session_removed"),sessionId:IdSchema})]),ServerHelloSchema=StrictObject({type:build_default.Literal("hello"),version:build_default.Literal(PROTOCOL_VERSION),connectionId:IdSchema,snapshot:ServerSnapshotSchema}),ServerHelloErrorSchema=StrictObject({type:build_default.Literal("hello_error"),error:ProtocolErrorSchema}),ResponseEnvelopeSchema=build_default.Union([StrictObject({type:build_default.Literal("response"),id:IdSchema,ok:build_default.Literal(!0),result:CommandResultSchema}),StrictObject({type:build_default.Literal("response"),id:IdSchema,ok:build_default.Literal(!1),error:ProtocolErrorSchema})]),EventEnvelopeSchema=StrictObject({type:build_default.Literal("event"),event:ServerEventSchema}),ServerMessageSchema=build_default.Union([ServerHelloSchema,ServerHelloErrorSchema,ResponseEnvelopeSchema,EventEnvelopeSchema]);var ProtocolValidationError=class extends Error{constructor(message,_value){super(message),this.name="ProtocolValidationError"}};function isProtocolValue(value,optionalProperty=!1,ancestors=new Set){if(value===void 0)return optionalProperty;if(value===null||typeof value=="boolean"||typeof value=="number"||typeof value=="string")return!0;if(typeof value!="object"||ancestors.has(value))return!1;ancestors.add(value);try{return Array.isArray(value)?value.every(item=>isProtocolValue(item,!1,ancestors)):Object.getPrototypeOf(value)!==Object.prototype?!1:Object.values(value).every(item=>isProtocolValue(item,!0,ancestors))}finally{ancestors.delete(value)}}function parseClientMessage(value){if(!isProtocolValue(value)||!Check2(ClientMessageSchema,value))throw new ProtocolValidationError("Invalid client protocol message");return value}function parseServerMessage(value){if(!isProtocolValue(value)||!Check2(ServerMessageSchema,value))throw new ProtocolValidationError("Invalid server protocol message");return value}function boundedErrorMessage(error2){return error2 instanceof Error?error2.message.length<=500?error2.message:`${error2.message.slice(0,497)}...`:"Unknown codec error"}function encodeProtocolMessage(value,parse5,kind,options){let validated=parse5(value);try{let maxFrameLength=options?.maxFrameLength??16777216;return encodeFrame(encodeCbor(validated,{maxByteLength:maxFrameLength}))}catch(error2){throw error2 instanceof ProtocolValidationError?error2:new ProtocolValidationError(`Unable to encode ${kind} protocol message: ${boundedErrorMessage(error2)}`)}}function encodeServerMessage(message,options){return encodeProtocolMessage(message,parseServerMessage,"server",options)}var ValidatedMessageDecoder=class{failed=!1;frames;kind;maxFrameLength;parse;constructor(kind,parse5,options){this.frames=new FrameDecoder(options),this.kind=kind,this.maxFrameLength=options?.maxFrameLength??16777216,this.parse=parse5}push(chunk){if(this.failed)throw new ProtocolValidationError(`${this.kind} message decoder has failed`);try{let messages=[];for(let frame of this.frames.push(chunk))messages.push(this.parse(decodeCbor(frame,{maxByteLength:this.maxFrameLength})));return messages}catch(error2){throw this.failed=!0,error2 instanceof ProtocolValidationError?error2:new ProtocolValidationError(`Invalid ${this.kind} protocol frame: ${boundedErrorMessage(error2)}`)}}end(){if(this.failed)throw new ProtocolValidationError(`${this.kind} message decoder has failed`);try{this.frames.end()}catch(error2){throw this.failed=!0,new ProtocolValidationError(`Invalid ${this.kind} protocol framing: ${boundedErrorMessage(error2)}`)}}},ClientMessageDecoder=class{decoder;constructor(options){this.decoder=new ValidatedMessageDecoder("client",parseClientMessage,options)}push(chunk){return this.decoder.push(chunk)}end(){this.decoder.end()}};function isSupportedProtocolVersion(version){return Number.isInteger(version)&&version===PROTOCOL_VERSION}import{Buffer as Buffer4}from"node:buffer";import{Buffer as Buffer3}from"node:buffer";var MISMATCH_MESSAGE="Artifact store returned a mismatched artifact reference",BYTE_LIMIT_MESSAGE="Artifact store exceeded the requested byte limit";async function statValidatedArtifact(artifacts,sessionId,artifactId){let artifact=await artifacts.stat(sessionId,artifactId);if(artifact.sessionId!==sessionId||artifact.artifactId!==artifactId)throw new PiServerError("invalid_request",MISMATCH_MESSAGE);return artifact}async function readValidatedArtifact(artifacts,sessionId,artifactId,options){let chunk=await artifacts.read(sessionId,artifactId,options);if(chunk.artifact.sessionId!==sessionId||chunk.artifact.artifactId!==artifactId)throw new PiServerError("invalid_request",MISMATCH_MESSAGE);if(chunk.data.byteLength>options.maxBytes)throw new PiServerError("invalid_request",BYTE_LIMIT_MESSAGE);return chunk}function toArtifactStatResult(artifact){return{command:"artifact_stat",artifact}}function toArtifactReadResult(chunk){return{command:"artifact_read",artifact:chunk.artifact,encoding:"base64",data:Buffer3.from(chunk.data).toString("base64"),...chunk.nextOffset===void 0?{}:{nextOffset:chunk.nextOffset},eof:chunk.eof}}var MAX_ARTIFACT_READ_BYTES=1048576,MAX_HTTP_BODY_BYTES=65536;function handleArtifactHttpRoutes(dependencies,request,response2){return request.method!=="POST"?!1:request.url==="/artifact/stat"?(serveArtifactStat(dependencies,request,response2),!0):request.url==="/artifact/read"?(serveArtifactRead(dependencies,request,response2),!0):!1}async function serveArtifactStat(dependencies,request,response2){try{let body=await parseArtifactRequestBody(request,!1),consumed=consumeReadToken(dependencies.readTokens,body);if(!consumed.ok){respondTokenRejection(response2,consumed.reason);return}let artifacts=requireArtifacts(dependencies),artifact=await statValidatedArtifact(artifacts,consumed.sessionId,consumed.artifactId);respondJson(response2,200,toArtifactStatResult(artifact))}catch(error2){respondServerError(response2,error2)}}async function serveArtifactRead(dependencies,request,response2){try{let body=await parseArtifactRequestBody(request,!0),consumed=consumeReadToken(dependencies.readTokens,body);if(!consumed.ok){respondTokenRejection(response2,consumed.reason);return}let artifacts=requireArtifacts(dependencies),chunk=await readValidatedArtifact(artifacts,consumed.sessionId,consumed.artifactId,{offset:body.paging.offset,maxBytes:body.paging.maxBytes});respondJson(response2,200,toArtifactReadResult(chunk))}catch(error2){respondServerError(response2,error2)}}async function parseArtifactRequestBody(request,withPaging){let parsed;try{parsed=JSON.parse(await readJsonBody(request))}catch{throw new PiServerError("invalid_request","Artifact request body must be valid JSON")}if(typeof parsed!="object"||parsed===null||Array.isArray(parsed))throw new PiServerError("invalid_request","Artifact request body must be a JSON object");let record=parsed,token=record.token;if(typeof token!="string"||token==="")throw new PiServerError("invalid_request","Artifact request requires a token");let sessionId=record.sessionId,artifactId=record.artifactId;if(typeof sessionId!="string"||sessionId===""||typeof artifactId!="string"||artifactId==="")throw new PiServerError("invalid_request","Artifact request requires sessionId and artifactId");if(!withPaging)return{token,sessionId,artifactId,paging:{offset:0,maxBytes:MAX_ARTIFACT_READ_BYTES}};let rawOffset=record.offset??0;if(typeof rawOffset!="number"||!Number.isSafeInteger(rawOffset)||rawOffset<0)throw new PiServerError("invalid_request","Artifact read offset must be a non-negative safe integer");let rawMaxBytes=record.maxBytes??MAX_ARTIFACT_READ_BYTES;if(typeof rawMaxBytes!="number"||!Number.isSafeInteger(rawMaxBytes)||rawMaxBytes<1||rawMaxBytes>MAX_ARTIFACT_READ_BYTES)throw new PiServerError("invalid_request",`Artifact read maxBytes must be an integer between 1 and ${MAX_ARTIFACT_READ_BYTES}`);return{token,sessionId,artifactId,paging:{offset:rawOffset,maxBytes:rawMaxBytes}}}async function readJsonBody(request){let chunks=[],total=0;for await(let chunk of request){let part=Buffer4.isBuffer(chunk)?chunk:Buffer4.from(chunk);if(total+=part.byteLength,total>MAX_HTTP_BODY_BYTES)throw new PiServerError("invalid_request","Artifact request body exceeds the size limit");chunks.push(part)}return Buffer4.concat(chunks).toString("utf8")}function consumeReadToken(readTokens,body){return readTokens.consume(body.token,{sessionId:body.sessionId,artifactId:body.artifactId})}function requireArtifacts(dependencies){if(!dependencies.artifacts)throw new PiServerError("not_found","Artifact access is not configured");return dependencies.artifacts}function respondTokenRejection(response2,reason){if(reason==="binding_mismatch"){respondError(response2,403,"invalid_request","Read token is not bound to the requested artifact");return}respondError(response2,401,"unauthorized",`Read token rejected: ${reason}`)}function respondServerError(response2,error2){if(error2 instanceof PiServerError){let status2=error2.code==="not_found"?404:error2.code==="invalid_request"?400:500;respondError(response2,status2,error2.code,error2.message);return}respondError(response2,500,"internal_error","Internal server error")}function respondJson(response2,status2,body){let payload2=JSON.stringify(body);response2.writeHead(status2,{"Content-Type":"application/json; charset=utf-8","Content-Length":Buffer4.byteLength(payload2)}),response2.end(payload2)}function respondError(response2,status2,code,message){respondJson(response2,status2,{error:{code,message}})}function isTerminalConnection(state2){return state2.disconnected||state2.stage==="closing"||state2.stage==="closed"}import{randomUUID as randomUUID10}from"node:crypto";function toMetadata(snapshot2){return{id:snapshot2.id,createdAt:snapshot2.createdAt,updatedAt:snapshot2.updatedAt,sessionName:snapshot2.name,cwd:snapshot2.cwd}}var DEFAULT_LEASE_TTL_MS2=3e5,IDEMPOTENT_OPERATION_LIMIT=128;function toOperationAckResult(ack){return{command:"operation_ack",operationId:ack.operationId,status:ack.status,...ack.result===void 0?{}:{result:ack.result},...ack.error===void 0?{}:{error:ack.error}}}var LiveSessionManager=class{options;leaseTtlMs;now;liveSessions=new Map;openingSessions=new Map;constructor(options){this.options=options,this.leaseTtlMs=options.leaseTtlMs??DEFAULT_LEASE_TTL_MS2,this.now=options.now??(()=>Date.now())}async executeCommand(connection,command){try{await this.options.authorize?.({context:connection.principalContext,command})}catch(error2){throw error2 instanceof PiServerError?error2:new UnauthorizedError(error2 instanceof Error?error2.message:"Authorization failed")}switch(command.command){case"list":{let sessions=await this.listMetadata();return{command:"list",sessions:this.options.filterSessions?await this.options.filterSessions({context:connection.principalContext,sessions}):sessions}}case"create":{let id=randomUUID10(),options={id,cwd:command.cwd,name:command.name,model:command.model,thinkingLevel:command.thinkingLevel,profileId:command.profileId,profileVersion:command.profileVersion},live=await this.acquire(id,()=>this.options.service.createSession(options));await this.attach(connection,live,"exclusive");let session=this.forConnection(await this.broadcastSnapshot(live),connection);this.options.broadcastServerSnapshot();let lease=connection.sessionLeases.get(live.id);return{command:"create",session,...lease===void 0?{}:{leaseId:lease.leaseId,leaseExpiresAt:lease.expiresAt}}}case"attach":{let live=await this.acquire(command.sessionId,()=>this.options.service.openSession(command.sessionId));await this.attach(connection,live,command.mode??"shared");let session=this.forConnection(await this.broadcastSnapshot(live),connection);this.options.broadcastServerSnapshot();let lease=connection.sessionLeases.get(live.id);return{command:"attach",session,...lease===void 0?{}:{leaseId:lease.leaseId,leaseExpiresAt:lease.expiresAt}}}case"lease_renew":{let live=this.requireAttached(connection,command.sessionId),lease=connection.sessionLeases.get(command.sessionId);if(!lease)throw new PiServerError("session_locked",`No lease to renew: ${command.sessionId}`);return lease.expiresAt=this.now()+this.leaseTtlMs,{command:"lease_renew",sessionId:live.id,leaseId:lease.leaseId,expiresAt:lease.expiresAt}}case"detach":{let live=this.liveSessions.get(command.sessionId);return connection.sessionIds.has(command.sessionId)&&(connection.sessionIds.delete(command.sessionId),connection.sessionLeaseModes.delete(command.sessionId),connection.sessionLeases.delete(command.sessionId),this.options.readTokens?.revokeSession(command.sessionId),live&&(live.connections.delete(connection),live.connections.size>0&&!live.terminal&&!live.disposing&&await this.broadcastSnapshot(live),await this.maybeDispose(live)),this.options.broadcastServerSnapshot()),{command:"detach",sessionId:command.sessionId}}case"prompt":{let live=this.requireAttached(connection,command.sessionId);return{command:"prompt",session:await this.runIdempotent(live,command.operationId,()=>this.runOperation(connection,live,()=>live.runtime.prompt({text:command.text})))}}case"steer":{let live=this.requireAttached(connection,command.sessionId);return{command:"steer",session:await this.runIdempotent(live,command.operationId,()=>this.runOperation(connection,live,()=>live.runtime.steer({text:command.text})))}}case"abort":{let live=this.requireAttached(connection,command.sessionId);return{command:"abort",session:await this.runIdempotent(live,command.operationId,()=>this.runOperation(connection,live,()=>live.runtime.abort()))}}case"set_model":{let live=this.requireAttached(connection,command.sessionId);return{command:"set_model",session:await this.runIdempotent(live,command.operationId,()=>this.runOperation(connection,live,()=>live.runtime.setModel(command.model)))}}case"set_thinking":{let live=this.requireAttached(connection,command.sessionId);return{command:"set_thinking",session:await this.runIdempotent(live,command.operationId,()=>this.runOperation(connection,live,()=>live.runtime.setThinking(command.thinkingLevel)))}}case"replay":{let live=this.requireAttached(connection,command.sessionId);if(!this.options.journal)throw new PiServerError("not_implemented","Durable replay is not configured");let replay=await this.options.journal.replay(command.sessionId,command.afterCursor,command.limit);return{command:"replay",sessionId:live.id,afterCursor:command.afterCursor,nextCursor:replay.nextCursor,complete:replay.complete,gap:replay.gap,events:[...replay.events]}}case"artifact_stat":{this.requireAttached(connection,command.sessionId);let artifacts=this.options.service.artifacts;if(!artifacts)throw new PiServerError("not_implemented","Artifact access is not configured");return toArtifactStatResult(await statValidatedArtifact(artifacts,command.sessionId,command.artifactId))}case"artifact_read":{this.requireAttached(connection,command.sessionId);let artifacts=this.options.service.artifacts;if(!artifacts)throw new PiServerError("not_implemented","Artifact access is not configured");let chunk=await readValidatedArtifact(artifacts,command.sessionId,command.artifactId,{offset:command.offset,maxBytes:command.maxBytes});return toArtifactReadResult(chunk)}case"artifact_token_issue":{this.requireAttached(connection,command.sessionId);let readTokens=this.options.readTokens;if(!readTokens)throw new PiServerError("not_implemented","Read token issuing is not configured");let issued=readTokens.issue(command.sessionId,command.artifactId);return{command:"artifact_token_issue",token:issued.token,expiresAt:issued.expiresAt,sessionId:command.sessionId,artifactId:command.artifactId}}case"operation_submit":{let live=this.requireAttached(connection,command.sessionId),ack=await this.requireOperations().submit({sessionId:live.id,operationType:command.operationType,...command.input===void 0?{}:{input:command.input},...command.idempotencyKey===void 0?{}:{idempotencyKey:command.idempotencyKey},...command.expectedRevision===void 0?{}:{expectedRevision:command.expectedRevision}});return toOperationAckResult(ack)}case"operation_cancel":{let live=this.requireAttached(connection,command.sessionId),ack=await this.requireOperations().cancel({sessionId:live.id,operationId:command.operationId});return toOperationAckResult(ack)}case"operation_result":{let live=this.requireAttached(connection,command.sessionId),ack=await this.requireOperations().result({sessionId:live.id,operationId:command.operationId});return toOperationAckResult(ack)}}}async disconnect(connection){let sessions=[...connection.sessionIds].map(id=>this.liveSessions.get(id)).filter(live=>live!==void 0);connection.sessionIds.clear(),connection.sessionLeaseModes.clear();for(let live of sessions)live.connections.delete(connection);for(let live of sessions)this.options.readTokens?.revokeSession(live.id);let results=await Promise.allSettled(sessions.map(live=>this.maybeDispose(live)));for(let result of results)result.status==="rejected"&&this.options.reportError(result.reason)}async listMetadata(){let stored=await this.options.service.listSessions(),liveSnapshots=await Promise.all([...this.liveSessions.values()].filter(live=>!live.disposing).map(async live=>[live.id,await this.normalizedSnapshot(live)])),liveById=new Map(liveSnapshots),metadata=stored.map(item=>{let snapshot2=liveById.get(item.id);return snapshot2?(liveById.delete(item.id),{...item,...toMetadata(snapshot2)}):item});for(let snapshot2 of liveById.values())metadata.push(toMetadata(snapshot2));return metadata}async close(){let openingResults=await Promise.allSettled([...this.openingSessions.values()]);for(let result of openingResults)result.status==="rejected"&&this.options.reportError(result.reason);let sessions=[...this.liveSessions.values()];this.liveSessions.clear(),await Promise.all(sessions.map(async live=>{if(live.disposing){await live.disposing;return}live.unsubscribe(),await live.runtime.dispose()}))}async runOperation(connection,live,operation){live.operationCount+=1;try{return await operation(),this.forConnection(await this.broadcastSnapshot(live),connection)}finally{live.operationCount-=1,this.scheduleMaybeDispose(live)}}async runIdempotent(live,operationId,execute){if(operationId===void 0)return execute();let cache=live.idempotentOperations,recorded=cache.get(operationId);if(recorded)return cache.delete(operationId),cache.set(operationId,recorded),recorded;let pending=this.executeRecorded(live.id,operationId,execute);for(cache.set(operationId,pending);cache.size>IDEMPOTENT_OPERATION_LIMIT;){let oldest=cache.keys().next();if(oldest.done)break;cache.delete(oldest.value)}try{return await pending}catch(error2){throw cache.get(operationId)===pending&&cache.delete(operationId),error2}}async executeRecorded(sessionId,operationId,execute){let store=this.options.service.mutationResponses;if(store){let stored;try{stored=await store.load(sessionId,operationId)}catch(error2){this.options.reportError(error2)}if(stored)return stored}let snapshot2=await execute();return store&&store.record(sessionId,operationId,snapshot2).catch(error2=>this.options.reportError(error2)),snapshot2}async acquire(id,acquireRuntime){for(;;){let existing=this.liveSessions.get(id);if(existing){if(existing.terminal)throw new PiServerError("session_locked",`Session runtime is terminating: ${id}`);if(existing.disposing){await existing.disposing;continue}return existing}let opening=this.openingSessions.get(id);if(opening)return opening;let pending=this.create(id,acquireRuntime);this.openingSessions.set(id,pending);try{return await pending}finally{this.openingSessions.get(id)===pending&&this.openingSessions.delete(id)}}}async create(id,acquireRuntime){let runtime=await acquireRuntime();if(this.options.isClosing())throw await runtime.dispose(),new Error("PiServer closed while acquiring a session runtime");let live;try{let snapshot2=await runtime.snapshot();if(snapshot2.id!==id)throw new PiServerError("invalid_request",`Service returned session ${snapshot2.id} for server-assigned session ${id}`);return live={id,runtime,connections:new Set,unsubscribe:()=>{},operationCount:0,ready:!1,terminal:!1,idempotentOperations:new Map},live.unsubscribe=runtime.subscribe(event=>{this.handleRuntimeEvent(live,event).catch(error2=>this.options.reportError(error2))}),this.liveSessions.set(id,live),live.ready=!0,live}catch(error2){live&&live.unsubscribe();try{await runtime.dispose()}catch(disposeError){this.options.reportError(disposeError)}throw error2}}async handleRuntimeEvent(live,event){if(event.type==="error"){this.terminate(live,event.error).catch(error2=>this.options.reportError(error2));return}if(event.type==="progress"){let progressEvent={type:"session_progress",sessionId:live.id,progress:event.progress};await this.options.journal?.append(live.id,progressEvent);let envelope={type:"event",event:progressEvent};for(let connection of live.connections)this.options.sendMessage(connection,envelope)}else this.broadcastSnapshot(live).catch(error2=>this.options.reportError(error2));this.scheduleMaybeDispose(live)}async terminate(live,error2){if(live.terminal)return;live.terminal=!0,this.options.readTokens?.revokeSession(live.id),this.options.reportError(error2);try{await this.options.journal?.append(live.id,{type:"session_removed",sessionId:live.id})}catch(appendError){this.options.reportError(appendError)}live.unsubscribe();let connections=[...live.connections];await Promise.all(connections.map(connection=>this.options.closeConnection(connection.connection))),await Promise.all(connections.map(connection=>this.options.disconnect(connection))),await this.maybeDispose(live)}async normalizedSnapshot(live){let snapshot2=await live.runtime.snapshot();if(snapshot2.id!==live.id)throw new PiServerError("invalid_request",`Runtime session ID changed from ${live.id} to ${snapshot2.id}`);return{...snapshot2,phase:live.runtime.getPhase(),attached:live.connections.size>0,locked:!0}}forConnection(snapshot2,connection){return{...snapshot2,attached:connection.sessionIds.has(snapshot2.id)}}async broadcastSnapshot(live){let snapshot2=await this.normalizedSnapshot(live),event={type:"session_snapshot",snapshot:snapshot2};await this.options.journal?.append(live.id,event);let envelope={type:"event",event};for(let connection of live.connections)this.options.sendMessage(connection,envelope);return snapshot2}async attach(connection,live,mode){if(live.disposing||live.terminal)throw new PiServerError("session_locked",`Session runtime is terminating: ${live.id}`);if(connection.disconnected||connection.stage!=="ready"||connection.connection.closed)throw await this.maybeDispose(live),new PiServerError("invalid_request","Connection closed while attaching to a session");let existingMode=connection.sessionLeaseModes.get(live.id);if(existingMode!==void 0&&existingMode!==mode)throw new PiServerError("session_locked",`Connection already holds a ${existingMode} lease: ${live.id}`);for(let attached of live.connections){let attachedMode=attached.sessionLeaseModes.get(live.id);if(attached===connection)continue;let attachedLease=attached.sessionLeases.get(live.id);if(attachedLease&&attachedLease.expiresAt<=this.now()){this.options.readTokens?.revokeSession(live.id),attached.sessionLeaseModes.delete(live.id),attached.sessionLeases.delete(live.id),attached.sessionIds.delete(live.id),live.connections.delete(attached);continue}if(mode==="exclusive"||attachedMode==="exclusive")throw new PiServerError("session_locked",`Session lease conflict: ${live.id}`)}connection.sessionIds.add(live.id),connection.sessionLeaseModes.set(live.id,mode),connection.sessionLeases.set(live.id,{leaseId:randomUUID10(),expiresAt:this.now()+this.leaseTtlMs}),live.connections.add(connection)}requireAttached(connection,sessionId){if(!connection.sessionIds.has(sessionId))throw new PiServerError("invalid_request",`Connection is not attached to session ${sessionId}`);let lease=connection.sessionLeases.get(sessionId);if(lease&&lease.expiresAt<=this.now()){this.options.readTokens?.revokeSession(sessionId),connection.sessionIds.delete(sessionId),connection.sessionLeaseModes.delete(sessionId),connection.sessionLeases.delete(sessionId);let live2=this.liveSessions.get(sessionId);throw live2&&(live2.connections.delete(connection),this.scheduleMaybeDispose(live2)),new PiServerError("session_locked",`Session lease expired: ${sessionId}`)}let live=this.liveSessions.get(sessionId);if(!live||live.terminal||live.disposing)throw new PiServerError("not_found",`Session is not live: ${sessionId}`);return live}requireOperations(){let operations=this.options.service.operations;if(!operations)throw new PiServerError("durable_unavailable","Durable operation store is not configured");return operations}scheduleMaybeDispose(live){this.maybeDispose(live).catch(error2=>this.options.reportError(error2))}async maybeDispose(live){if(this.options.isClosing()||!live.ready||live.disposing||live.connections.size>0||live.operationCount>0||!live.terminal&&live.runtime.getPhase()!=="idle")return live.disposing;live.unsubscribe(),this.options.readTokens?.revokeSession(live.id),live.disposing=(async()=>{try{await live.runtime.dispose()}finally{this.liveSessions.get(live.id)===live&&this.liveSessions.delete(live.id)}})(),await live.disposing,this.options.isClosing()||this.options.broadcastServerSnapshot()}};var ServerSnapshotPublisher=class{options;revision=0;broadcastQueue=Promise.resolve();constructor(options){this.options=options}get currentRevision(){return this.revision}async get(models,applyFilter){let sessions=applyFilter?await applyFilter(await this.options.listSessions()):await this.options.listSessions();return{serverId:this.options.serverId,protocolVersion:PROTOCOL_VERSION,revision:this.revision,sessions,models:models??await this.options.service.listModels()}}broadcast(){let broadcast=this.broadcastQueue.then(()=>this.performBroadcast());return this.broadcastQueue=broadcast.catch(error2=>this.options.reportError(error2)),broadcast}async performBroadcast(){let readyConnections=[...this.options.connections].filter(connection=>connection.stage==="ready"&&!connection.disconnected);if(readyConnections.length===0||this.options.isClosing())return;let revision=++this.revision,models=await this.options.service.listModels(),filter2=this.options.filterSessions;for(let connection of readyConnections){let sessions=filter2?await filter2({context:connection.principalContext,sessions:await this.options.listSessions()}):await this.options.listSessions(),envelope={type:"event",event:{type:"server_snapshot",snapshot:{serverId:this.options.serverId,protocolVersion:PROTOCOL_VERSION,revision,sessions,models}}};await this.options.sendMessage(connection,envelope)}}};var DEFAULT_HANDSHAKE_TIMEOUT_MS=5e3,DEFAULT_LEASE_TTL_MS3=3e5,MAX_UINT322=4294967295,MAX_TIMER_DELAY_MS=2147483647,PiServer=class{id;listeners;maxFrameLength;handshakeTimeoutMs;onError;journal;authenticate;filterSessions;connections=new Set;service;sessions;readTokens;snapshots;closing=!1;closePromise;startPromise;started=!1;constructor(service,options){let resolved=resolveOptions2(options);this.listeners=options.listeners,this.id=options.serverId??randomUUID11(),this.maxFrameLength=resolved.maxFrameLength,this.handshakeTimeoutMs=resolved.handshakeTimeoutMs,this.onError=options.onError,this.journal=options.journal,this.authenticate=options.authenticate,this.service=service,this.readTokens=new ReadTokenStore({now:options.now}),this.sessions=new LiveSessionManager({service,isClosing:()=>this.closing,sendMessage:(connection,message)=>this.sendMessage(connection,message),closeConnection:connection=>this.closeConnection(connection),disconnect:connection=>this.disconnect(connection),broadcastServerSnapshot:()=>this.scheduleSnapshotBroadcast(),reportError:error2=>this.reportError(error2),journal:options.journal,authorize:options.authorize,filterSessions:options.filterSessions,leaseTtlMs:resolved.leaseTtlMs,readTokens:this.readTokens,now:options.now}),this.filterSessions=options.filterSessions,this.snapshots=new ServerSnapshotPublisher({serverId:this.id,service,connections:this.connections,isClosing:()=>this.closing,listSessions:()=>this.sessions.listMetadata(),filterSessions:options.filterSessions,sendMessage:(connection,message)=>this.sendMessage(connection,message),reportError:error2=>this.reportError(error2)})}get addresses(){return this.listeners.flatMap(listener=>listener.address===void 0?[]:[listener.address])}start(){return this.started?Promise.reject(new Error("PiServer is already started")):this.startPromise?Promise.reject(new Error("PiServer is already starting")):this.closing?Promise.reject(new Error("PiServer is closing or closed")):(this.startPromise=this.startInternal(),this.startPromise)}async startInternal(){let started=[];try{for(let listener of this.listeners)await listener.start(connection=>this.accept(connection)),started.push(listener);return this.started=!0,this}catch(error2){throw this.closing=!0,await Promise.allSettled(started.map(listener=>listener.close())),await this.closeServerState(),error2}finally{this.startPromise=void 0}}handleArtifactHttpRequest(request,response2){return handleArtifactHttpRoutes({readTokens:this.readTokens,artifacts:this.service.artifacts},request,response2)}accept(connection){if(this.closing)return this.closeConnection(connection),{onData:()=>{},onClose:()=>{},onError:error2=>this.reportError(error2)};let state2,handshakeTimeout=setTimeout(()=>{this.failProtocol(state2,{code:"invalid_request",message:"Handshake timeout"})},this.handshakeTimeoutMs);return handshakeTimeout.unref(),state2={id:randomUUID11(),connection,decoder:new ClientMessageDecoder({maxFrameLength:this.maxFrameLength}),sessionIds:new Set,sessionLeaseModes:new Map,sessionLeases:new Map,principalContext:{principalId:"anonymous"},stage:"awaitingHello",disconnected:!1,handshakeComplete:!1,handshakeTimeout},this.connections.add(state2),{onData:chunk=>this.receive(state2,chunk),onClose:()=>this.transportClosed(state2),onError:error2=>{this.reportError(error2),this.closeConnection(connection).then(()=>this.disconnect(state2))}}}async close(){return this.closePromise?this.closePromise:(this.closing=!0,this.closePromise=this.closeInternal(),this.closePromise)}async closeInternal(){let starting=this.startPromise;starting&&await starting.catch(()=>{});try{await Promise.all(this.listeners.map(listener=>listener.close()))}finally{await this.closeServerState(),this.started=!1}}receive(state2,chunk){if(isTerminalConnection(state2))return;let messages;try{messages=state2.decoder.push(chunk)}catch(error2){this.failProtocol(state2,this.toProtocolError(error2));return}for(let message of messages){if(isTerminalConnection(state2))return;this.dispatchMessage(state2,message)}}dispatchMessage(state2,message){if(state2.stage==="awaitingHello"){if(message.type!=="hello"){this.failProtocol(state2,{code:"invalid_request",message:"The first client message must be hello"});return}state2.stage="handshaking",state2.handshake=this.finishHandshake(state2,message).catch(error2=>this.failProtocol(state2,this.toProtocolError(error2)));return}if(message.type==="hello"){this.failProtocol(state2,{code:"invalid_request",message:"hello may only be sent as the first message"});return}if(state2.stage==="ready"){this.handleRequest(state2,message);return}if(state2.stage!=="handshaking")return;let handshake=state2.handshake;handshake&&handshake.then(()=>{state2.stage==="ready"&&!state2.disconnected&&this.handleRequest(state2,message)})}async finishHandshake(state2,hello){if(!isSupportedProtocolVersion(hello.version)){await this.failProtocol(state2,{code:"version",message:`Unsupported protocol version ${hello.version}; expected ${PROTOCOL_VERSION}`});return}try{let principal=this.authenticate?await this.authenticate({connectionId:state2.id,...hello.auth===void 0?{}:{auth:hello.auth}}):{principalId:"anonymous"};if(!principal||principal.principalId.trim()==="")throw new Error("Authenticated principalId is required");state2.principalContext=Object.freeze({...principal})}catch(error2){await this.failProtocol(state2,{code:"unauthorized",message:error2 instanceof Error?error2.message:"Authentication failed"});return}let snapshot2=await this.snapshots.get(void 0,sessions=>this.filterSessions?this.filterSessions({context:state2.principalContext,sessions}):sessions);if(this.closing||state2.disconnected||state2.stage!=="handshaking"||state2.connection.closed)return;if(await this.sendMessage(state2,{type:"hello",version:PROTOCOL_VERSION,connectionId:state2.id,snapshot:snapshot2})&&!state2.disconnected&&state2.stage==="handshaking"&&(state2.handshakeComplete=!0,state2.stage="ready",clearTimeout(state2.handshakeTimeout),snapshot2.revision!==this.snapshots.currentRevision)){let current=await this.snapshots.get();await this.sendMessage(state2,{type:"event",event:{type:"server_snapshot",snapshot:current}})}}async handleRequest(state2,envelope){let response2;try{let result=await this.sessions.executeCommand(state2,envelope.request);response2={type:"response",id:envelope.id,ok:!0,result}}catch(error2){response2={type:"response",id:envelope.id,ok:!1,error:this.toProtocolError(error2)}}let outcome=await this.transmitMessage(state2,response2);outcome!=="sent"&&(outcome==="oversize"&&!state2.disconnected&&await this.transmitMessage(state2,{type:"response",id:envelope.id,ok:!1,error:{code:"invalid_request",message:`Response frame exceeds the configured limit of ${this.maxFrameLength} bytes`}}),outcome!=="closed"&&await this.abandonConnection(state2))}transportClosed(connection){if(!connection.disconnected&&connection.stage!=="closing")try{connection.decoder.end()}catch(error2){this.reportError(error2)}this.disconnect(connection)}async disconnect(connection){if(connection.disconnected)return;let handshakeComplete=connection.handshakeComplete;connection.disconnected=!0,connection.stage="closed",clearTimeout(connection.handshakeTimeout),this.connections.delete(connection),await this.sessions.disconnect(connection),!this.closing&&handshakeComplete&&this.scheduleSnapshotBroadcast()}scheduleSnapshotBroadcast(){this.snapshots.broadcast().catch(()=>{})}async sendMessage(connection,message){let outcome=await this.transmitMessage(connection,message);return outcome==="sent"?!0:(outcome!=="closed"&&await this.abandonConnection(connection),!1)}async transmitMessage(connection,message){if(connection.disconnected||connection.connection.closed)return"closed";let frame;try{frame=encodeServerMessage(message,{maxFrameLength:this.maxFrameLength})}catch(error2){return this.reportError(error2),"oversize"}try{return await connection.connection.send(frame),"sent"}catch(error2){return this.reportError(error2),"failed"}}async abandonConnection(connection){await this.closeConnection(connection.connection),await this.disconnect(connection)}async failProtocol(connection,error2){if(connection.disconnected||connection.stage==="closing"||connection.stage==="closed")return;connection.stage="closing",clearTimeout(connection.handshakeTimeout);let message={type:"hello_error",error:error2},finalFrame;try{finalFrame=encodeServerMessage(message,{maxFrameLength:this.maxFrameLength})}catch(encodeError){this.reportError(encodeError)}await this.closeConnection(connection.connection,finalFrame),await this.disconnect(connection)}async closeServerState(){let connections=[...this.connections];for(let connection of connections)connection.stage="closing",clearTimeout(connection.handshakeTimeout);await Promise.all(connections.map(connection=>this.closeConnection(connection.connection))),await Promise.all(connections.map(connection=>this.disconnect(connection))),await this.sessions.close(),await this.journal?.close(),this.connections.clear()}async closeConnection(connection,finalChunk){try{await connection.close(finalChunk)}catch(error2){this.reportError(error2)}}toProtocolError(error2){return error2 instanceof InternalServerError?(this.reportError(error2.cause),{code:"internal_error",message:INTERNAL_SERVER_ERROR_MESSAGE}):error2 instanceof PiServerError?error2.code==="not_implemented"?{code:"not_implemented",message:NOT_IMPLEMENTED_MESSAGE}:error2.details===void 0?{code:error2.code,message:error2.message}:{code:error2.code,message:error2.message,details:error2.details}:error2 instanceof ProtocolValidationError?{code:"invalid_request",message:error2.message}:(this.reportError(error2),{code:"internal_error",message:INTERNAL_SERVER_ERROR_MESSAGE})}reportError(error2){try{this.onError?.(error2 instanceof Error?error2:new Error(String(error2)))}catch{}}};function resolveOptions2(options){if(!Array.isArray(options.listeners))throw new TypeError("PiServer listeners must be an array");if(options.serverId==="")throw new TypeError("PiServer serverId must not be empty");let maxFrameLength=options.maxFrameLength??16777216;if(!Number.isSafeInteger(maxFrameLength)||maxFrameLength<=0||maxFrameLength>MAX_UINT322)throw new TypeError(`PiServer maxFrameLength must be an integer between 1 and ${MAX_UINT322}`);let leaseTtlMs=options.leaseTtlMs??DEFAULT_LEASE_TTL_MS3;if(!Number.isSafeInteger(leaseTtlMs)||leaseTtlMs<=0||leaseTtlMs>MAX_TIMER_DELAY_MS)throw new TypeError(`PiServer leaseTtlMs must be an integer between 1 and ${MAX_TIMER_DELAY_MS}`);let handshakeTimeoutMs=options.handshakeTimeoutMs??DEFAULT_HANDSHAKE_TIMEOUT_MS;if(!Number.isSafeInteger(handshakeTimeoutMs)||handshakeTimeoutMs<=0||handshakeTimeoutMs>MAX_TIMER_DELAY_MS)throw new TypeError(`PiServer handshakeTimeoutMs must be an integer between 1 and ${MAX_TIMER_DELAY_MS}`);return{maxFrameLength,handshakeTimeoutMs,leaseTtlMs}}var MAX_UNIX_SOCKET_PATH_BYTES=process.platform==="linux"?107:103;function closeNetServer(server,reportError){return server.listening?new Promise(resolve25=>{server.close(error2=>{error2&&reportError(error2),resolve25()})}):Promise.resolve()}function validateTcpPort(port,description="TCP port"){if(!Number.isInteger(port)||port<0||port>65535)throw new TypeError(`${description} must be an integer between 0 and 65535`)}import{createServer as createHttpServer}from"node:http";var DEFAULT_GRACEFUL_CLOSE_TIMEOUT_MS=5e3,DEFAULT_WS_HOST="127.0.0.1",MAX_UINT323=4294967295,MAX_TIMER_DELAY_MS2=2147483647,WsListener=class{options;connections=new Set;httpServer;gateway;boundAddress;closing=!1;closePromise;accept;constructor(options){this.options=resolveWsListenerOptions(options)}get address(){return this.boundAddress}async start(accept){if(this.httpServer)throw new Error("WS listener is already started");if(this.closing)throw new Error("WS listener is closing or closed");this.accept=accept;let httpServer=createHttpServer((request,response2)=>{this.options.httpRequestHandler?.(request,response2)||handleHealthRequest(request,response2,this.boundAddress)||(response2.writeHead(426,{Upgrade:"websocket"}),response2.end("upgrade required"))});httpServer.on("error",error2=>this.reportError(error2));let gateway=new import_websocket_server.default({server:httpServer,maxPayload:this.options.maxPayloadBytes});gateway.on("connection",socket=>this.acceptSocket(socket)),this.httpServer=httpServer,this.gateway=gateway;try{await new Promise((resolve25,reject2)=>{let onError=error2=>{httpServer.off("listening",onListening),reject2(error2)},onListening=()=>{httpServer.off("error",onError),resolve25()};httpServer.once("error",onError),httpServer.once("listening",onListening),httpServer.listen(this.options.port,this.options.host)}),this.boundAddress=formatBindAddress(httpServer.address())}catch(error2){throw gateway.close(),await closeNetServer(httpServer,reportError=>this.reportError(reportError)),this.httpServer=void 0,this.gateway=void 0,error2}}async close(){return this.closePromise?this.closePromise:(this.closing=!0,this.closePromise=this.closeInternal(),this.closePromise)}acceptSocket(socket){if(this.closing){socket.terminate();return}let connection=new WsByteConnection(socket,this.options.gracefulCloseTimeoutMs,this.options.maxPendingBytes);this.connections.add(connection);let accept=this.accept;if(!accept){socket.terminate();return}let handler=accept(connection),onCloseDelivered=!1,deliverClose=()=>{onCloseDelivered||(onCloseDelivered=!0,handler.onClose())};socket.on("message",(data,isBinary)=>{if(!isBinary){connection.markClosed(),socket.close(1003,"binary protocol frames only"),deliverClose();return}handler.onData(toUint8Array(data))}),socket.on("error",error2=>{isWsSizeRejection(error2)||handler.onError(error2)}),socket.once("close",()=>{connection.markClosed(),this.connections.delete(connection),deliverClose()})}async closeInternal(){this.boundAddress=void 0;let connectionsClosed=Promise.all([...this.connections].map(connection=>connection.close())),gateway=this.gateway,httpServer=this.httpServer;this.gateway=void 0,this.httpServer=void 0,await connectionsClosed,gateway?.close(),httpServer&&await closeNetServer(httpServer,error2=>this.reportError(error2)),this.connections.clear()}reportError(error2){try{this.options.onError?.(error2 instanceof Error?error2:new Error(String(error2)))}catch{}}},WsByteConnection=class{socket;gracefulCloseTimeoutMs;maxPendingBytes;pendingBytes=0;closedValue=!1;closing=!1;writeTail=Promise.resolve();closePromise;resolveClose;constructor(socket,gracefulCloseTimeoutMs,maxPendingBytes){this.socket=socket,this.gracefulCloseTimeoutMs=gracefulCloseTimeoutMs,this.maxPendingBytes=maxPendingBytes}get closed(){return this.closedValue||this.socket.readyState!==import_websocket.default.OPEN}send(chunk){if(!(chunk instanceof Uint8Array))return Promise.reject(new TypeError("WS connection chunks must be Uint8Array"));if(this.closedValue||this.closing)return Promise.reject(new Error("WS connection is closed"));if(this.pendingBytes+chunk.byteLength>this.maxPendingBytes)return Promise.reject(new Error("WS connection exceeded its pending byte limit"));this.pendingBytes+=chunk.byteLength;let bytes=chunk.slice(),tracked=this.writeTail.then(()=>this.write(bytes)).finally(()=>{this.pendingBytes-=bytes.byteLength});return this.writeTail=tracked.catch(()=>{}),tracked}close(finalChunk){if(this.closedValue||this.socket.readyState===import_websocket.default.CLOSED)return this.markClosed(),Promise.resolve();if(this.closePromise)return this.closePromise;this.closing=!0;let finalBytes=finalChunk?.slice();return this.closePromise=new Promise(resolve25=>{this.resolveClose=resolve25;let timer=setTimeout(()=>{this.socket.readyState!==import_websocket.default.CLOSED&&this.socket.terminate()},this.gracefulCloseTimeoutMs);timer.unref(),this.socket.once("close",()=>{clearTimeout(timer),this.markClosed(),resolve25()}),this.writeTail.then(()=>{if(!this.closedValue)try{finalBytes&&this.socket.send(finalBytes),this.socket.readyState===import_websocket.default.OPEN&&this.socket.close(1e3,"protocol close")}catch{this.socket.terminate()}})}),this.closePromise}markClosed(){this.closedValue||(this.closedValue=!0,this.closing=!0,this.resolveClose?.(),this.resolveClose=void 0)}write(chunk){return this.closedValue||this.closing||this.socket.readyState!==import_websocket.default.OPEN?Promise.reject(new Error("WS connection is closed")):new Promise((resolve25,reject2)=>{try{this.socket.send(chunk,error2=>{error2?reject2(error2):resolve25()})}catch(error2){reject2(error2 instanceof Error?error2:new Error(String(error2)))}})}};function toUint8Array(data){if(data instanceof ArrayBuffer)return new Uint8Array(data);if(Array.isArray(data)){let joined=Buffer.concat(data);return new Uint8Array(joined.buffer,joined.byteOffset,joined.byteLength)}return new Uint8Array(data.buffer,data.byteOffset,data.byteLength)}function isWsSizeRejection(error2){return error2 instanceof Error&&"code"in error2&&error2.code==="WS_ERR_UNSUPPORTED_MESSAGE_LENGTH"}function handleHealthRequest(request,response2,boundAddress){if(request.method!=="GET"||request.url!=="/healthz")return!1;let body=JSON.stringify({status:"ok",transport:"ws",address:boundAddress});return response2.writeHead(200,{"Content-Type":"application/json; charset=utf-8","Content-Length":Buffer.byteLength(body)}),response2.end(body),!0}function formatBindAddress(address){return address===null?"unknown":typeof address=="string"?address:`${address.address}:${address.port}`}function resolveWsListenerOptions(options){validateTcpPort(options.port,"PiServer WS port");let maxPayloadBytes=options.maxPayloadBytes??16777216;if(!Number.isSafeInteger(maxPayloadBytes)||maxPayloadBytes<=0)throw new TypeError("PiServer WS maxPayloadBytes must be a positive safe integer");let maxFrameLength=options.maxFrameLength??16777216;if(!Number.isSafeInteger(maxFrameLength)||maxFrameLength<=0||maxFrameLength>MAX_UINT323)throw new TypeError(`PiServer maxFrameLength must be an integer between 1 and ${MAX_UINT323}`);let maxPendingBytes=options.maxPendingBytes??maxFrameLength*4;if(!Number.isSafeInteger(maxPendingBytes)||maxPendingBytes<maxFrameLength+4)throw new TypeError("PiServer maxPendingBytes must be a safe integer at least maxFrameLength + 4");let gracefulCloseTimeoutMs=options.gracefulCloseTimeoutMs??DEFAULT_GRACEFUL_CLOSE_TIMEOUT_MS;if(!Number.isSafeInteger(gracefulCloseTimeoutMs)||gracefulCloseTimeoutMs<=0||gracefulCloseTimeoutMs>MAX_TIMER_DELAY_MS2)throw new TypeError(`PiServer gracefulCloseTimeoutMs must be an integer between 1 and ${MAX_TIMER_DELAY_MS2}`);return{port:options.port,host:options.host??DEFAULT_WS_HOST,maxPayloadBytes,maxPendingBytes,gracefulCloseTimeoutMs,httpRequestHandler:options.httpRequestHandler,onError:options.onError}}function createWsServerListener(options){return new WsListener(options)}function requireIdle(session,action){if(!session.isIdle)throw new PiServerError("busy",`Cannot ${action} while the session is busy`)}function toError(error2){if(error2 instanceof PiServerError)return error2;let message=error2 instanceof Error?error2.message:String(error2);return/reload in progress/i.test(message)?new PiServerError("busy",message):/compaction is in progress/i.test(message)?new PiServerError("busy",message):/already processing/i.test(message)?new PiServerError("busy",message):new PiServerError("invalid_request",message)}function jsonSafe(value){return value===null||typeof value=="string"||typeof value=="boolean"?!0:typeof value=="number"?Number.isFinite(value):Array.isArray(value)?value.every(jsonSafe):typeof value!="object"||Object.getPrototypeOf(value)!==Object.prototype?!1:Object.values(value).every(jsonSafe)}function parseOperationPayload(value){if(typeof value!="object"||value===null||Array.isArray(value))return;let record=value;if(record.status!=="pending"&&record.status!=="completed"&&record.status!=="rejected"||typeof record.sessionId!="string"||record.sessionId===""||typeof record.operationType!="string"||typeof record.submittedAt!="number"||!Number.isFinite(record.submittedAt))return;let error2;if(record.error!==void 0){if(typeof record.error!="object"||record.error===null||Array.isArray(record.error))return;let entry=record.error;if(typeof entry.code!="string"||typeof entry.message!="string")return;error2={code:entry.code,message:entry.message}}return{status:record.status,sessionId:record.sessionId,operationType:record.operationType,...typeof record.idempotencyKey=="string"?{idempotencyKey:record.idempotencyKey}:{},...record.result===void 0?{}:{result:record.result},...error2===void 0?{}:{error:error2},submittedAt:record.submittedAt,...typeof record.terminalAt=="number"?{terminalAt:record.terminalAt}:{}}}function parseArtifactPayload(value){if(typeof value!="object"||value===null||Array.isArray(value))return;let record=value,ref=record.ref;if(typeof ref!="object"||ref===null||Array.isArray(ref))return;let entry=ref;if(!(typeof entry.sessionId!="string"||typeof entry.operationId!="string"||typeof entry.artifactId!="string"||typeof entry.kind!="string"||typeof entry.mediaType!="string"||typeof entry.truncated!="boolean"||typeof entry.createdAt!="number"||typeof record.bytes!="string"))return{ref:{sessionId:entry.sessionId,operationId:entry.operationId,artifactId:entry.artifactId,kind:entry.kind,mediaType:entry.mediaType,...typeof entry.sizeBytes=="number"?{sizeBytes:entry.sizeBytes}:{},truncated:entry.truncated,createdAt:entry.createdAt},bytes:record.bytes}}function parseMutationResponsePayload(value,sessionId){if(typeof value!="object"||value===null||Array.isArray(value))return;let record=value;if(!(record.id!==sessionId||typeof record.cwd!="string"||record.cwd===""||typeof record.revision!="number"||!Number.isInteger(record.revision)||record.revision<0||!Array.isArray(record.transcript)))return value}function toProtocolArtifactRef(ref){return{sessionId:ref.sessionId,operationId:ref.operationId,artifactId:ref.artifactId,kind:ref.kind,mediaType:ref.mediaType,...ref.sizeBytes===void 0?{}:{sizeBytes:ref.sizeBytes},truncated:ref.truncated,createdAt:ref.createdAt}}function projectUsage(usage){if(!usage||typeof usage!="object"||Array.isArray(usage))return;let record=usage,readCount=key=>{let value=record[key];return typeof value=="number"&&Number.isFinite(value)?Math.max(0,Math.trunc(value)):void 0},input=readCount("input"),output=readCount("output"),cacheRead=readCount("cacheRead"),cacheWrite=readCount("cacheWrite"),totalTokens=readCount("totalTokens");if(input===void 0||output===void 0||cacheRead===void 0||cacheWrite===void 0||totalTokens===void 0)return;let cost=record.cost;if(!cost||typeof cost!="object"||Array.isArray(cost))return;let costRecord=cost,readCost=key=>{let value=costRecord[key];return typeof value=="number"&&Number.isFinite(value)?value:void 0},costInput=readCost("input"),costOutput=readCost("output"),costCacheRead=readCost("cacheRead"),costCacheWrite=readCost("cacheWrite"),costTotal=readCost("total");if(costInput===void 0||costOutput===void 0||costCacheRead===void 0||costCacheWrite===void 0||costTotal===void 0)return;let reasoning=readCount("reasoning");return{input,output,cacheRead,cacheWrite,...reasoning===void 0?{}:{reasoning},totalTokens,cost:{input:costInput,output:costOutput,cacheRead:costCacheRead,cacheWrite:costCacheWrite,total:costTotal}}}function projectUserContent(content){if(typeof content=="string")return[{type:"text",text:content}];let projected=[];for(let part of content){if(!part||typeof part!="object")continue;let record=part;record.type==="text"&&typeof record.text=="string"?projected.push({type:"text",text:record.text}):record.type==="image"&&typeof record.data=="string"&&typeof record.mimeType=="string"&&projected.push({type:"image",data:record.data,mimeType:record.mimeType})}return projected}function projectToolResultContent(content){return projectUserContent(content)}function projectSessionTranscript(session){let messages=session.messages,toolInputs=new Map;for(let message of messages)if(message.role==="assistant")for(let part of message.content)part.type==="toolCall"&&toolInputs.set(part.id,part.arguments);let items=[];for(let message of messages){let id=`t-${items.length}`,timestamp=Math.max(0,Math.trunc(message.timestamp));if(message.role==="user"){items.push({id,role:"user",content:projectUserContent(message.content),timestamp});continue}if(message.role==="toolResult"){let input=toolInputs.get(message.toolCallId),usage2=projectUsage(message.usage),details=jsonSafe(message.details)?message.details:void 0,base={id,role:"tool",toolCallId:message.toolCallId,toolName:message.toolName,input:input!==void 0&&jsonSafe(input)?input:null,content:projectToolResultContent(message.content),...details===void 0?{}:{details},...usage2===void 0?{}:{usage:usage2},timestamp};if(message.isError){let item={...base,status:"error",isError:!0};items.push(item)}else{let item={...base,status:"complete",isError:!1};items.push(item)}continue}if(message.role==="bashExecution"){let failed=message.cancelled||message.exitCode!==void 0&&message.exitCode!==0,base={id,role:"tool",toolCallId:`bash-${id}`,toolName:"bash",input:{command:message.command},content:[{type:"text",text:message.output}],details:{exitCode:message.exitCode??null,cancelled:message.cancelled,truncated:message.truncated},timestamp};if(failed){let item={...base,status:"error",isError:!0};items.push(item)}else{let item={...base,status:"complete",isError:!1};items.push(item)}continue}if(message.role==="branchSummary"){items.push({id,role:"note",kind:"branchSummary",text:message.summary,fromId:message.fromId,timestamp});continue}if(message.role==="compactionSummary"){items.push({id,role:"note",kind:"compactionSummary",text:message.summary,tokensBefore:Math.max(0,Math.trunc(message.tokensBefore)),timestamp});continue}if(message.role==="custom"){let text=typeof message.content=="string"?message.content:message.content.filter(part=>part.type==="text").map(part=>part.text).join(`
|
|
@@ -1487,7 +1487,7 @@ Auth commands require at least one of --provider or --model. Checks refresh expi
|
|
|
1487
1487
|
${content}
|
|
1488
1488
|
</file>
|
|
1489
1489
|
`}catch(error2){let message=error2 instanceof Error?error2.message:String(error2);console.error(source_default.red(`Error: Could not read file ${absolutePath}: ${message}`)),process.exit(1)}}return{text,images}}function buildInitialMessage({parsed,fileText,fileImages,stdinContent}){let parts=[];return stdinContent!==void 0&&parts.push(stdinContent),fileText&&parts.push(fileText),parsed.messages.length>0&&(parts.push(parsed.messages[0]),parsed.messages.shift()),{initialMessage:parts.length>0?parts.join(""):void 0,initialImages:fileImages&&fileImages.length>0?fileImages:void 0}}function formatTokenCount(count){if(count>=1e6){let millions=count/1e6;return millions%1===0?`${millions}M`:`${millions.toFixed(1)}M`}if(count>=1e3){let thousands=count/1e3;return thousands%1===0?`${thousands}K`:`${thousands.toFixed(1)}K`}return count.toString()}async function listModels(modelRuntime,searchPattern,signal){let loadError=modelRuntime.getError();loadError&&console.error(source_default.yellow(`Warning: errors loading models.json:
|
|
1490
|
-
${loadError}`));let models=[...await modelRuntime.getAvailable(void 0,{signal})];if(models.length===0){console.log(formatNoModelsAvailableMessage());return}let filteredModels=models;if(searchPattern&&(filteredModels=fuzzyFilter(models,searchPattern,m2=>`${m2.provider} ${m2.id}`)),filteredModels.length===0){console.log(`No models matching "${searchPattern}"`);return}filteredModels.sort((a,b2)=>{let providerCmp=a.provider.localeCompare(b2.provider);return providerCmp!==0?providerCmp:a.id.localeCompare(b2.id)});let rows=filteredModels.map(m2=>({provider:m2.provider,model:m2.id,context:formatTokenCount(m2.contextWindow),maxOut:formatTokenCount(m2.maxTokens),thinking:m2.reasoning?"yes":"no",images:m2.input.includes("image")?"yes":"no"})),headers={provider:"provider",model:"model",context:"context",maxOut:"max-out",thinking:"thinking",images:"images"},widths={provider:Math.max(headers.provider.length,...rows.map(r=>r.provider.length)),model:Math.max(headers.model.length,...rows.map(r=>r.model.length)),context:Math.max(headers.context.length,...rows.map(r=>r.context.length)),maxOut:Math.max(headers.maxOut.length,...rows.map(r=>r.maxOut.length)),thinking:Math.max(headers.thinking.length,...rows.map(r=>r.thinking.length)),images:Math.max(headers.images.length,...rows.map(r=>r.images.length))},headerLine=[headers.provider.padEnd(widths.provider),headers.model.padEnd(widths.model),headers.context.padEnd(widths.context),headers.maxOut.padEnd(widths.maxOut),headers.thinking.padEnd(widths.thinking),headers.images.padEnd(widths.images)].join(" ");console.log(headerLine);for(let row of rows){let line=[row.provider.padEnd(widths.provider),row.model.padEnd(widths.model),row.context.padEnd(widths.context),row.maxOut.padEnd(widths.maxOut),row.thinking.padEnd(widths.thinking),row.images.padEnd(widths.images)].join(" ");console.log(line)}}import{join as join59}from"node:path";function printResponse(response2,write){write(response2.text),response2.status!=="succeeded"&&(process.exitCode=1)}function buildMarketCli(options){let{market,overrides}=options;return createPluginEcosystemCliV1({host:overrides?.host??defaultPluginHostFactsV1(),manifests:listBuiltinPluginManifestsV1(),registry:overrides?.registry??market?.cliRegistry,...market?.acquisition===void 0?{}:{acquisition:market
|
|
1490
|
+
${loadError}`));let models=[...await modelRuntime.getAvailable(void 0,{signal})];if(models.length===0){console.log(formatNoModelsAvailableMessage());return}let filteredModels=models;if(searchPattern&&(filteredModels=fuzzyFilter(models,searchPattern,m2=>`${m2.provider} ${m2.id}`)),filteredModels.length===0){console.log(`No models matching "${searchPattern}"`);return}filteredModels.sort((a,b2)=>{let providerCmp=a.provider.localeCompare(b2.provider);return providerCmp!==0?providerCmp:a.id.localeCompare(b2.id)});let rows=filteredModels.map(m2=>({provider:m2.provider,model:m2.id,context:formatTokenCount(m2.contextWindow),maxOut:formatTokenCount(m2.maxTokens),thinking:m2.reasoning?"yes":"no",images:m2.input.includes("image")?"yes":"no"})),headers={provider:"provider",model:"model",context:"context",maxOut:"max-out",thinking:"thinking",images:"images"},widths={provider:Math.max(headers.provider.length,...rows.map(r=>r.provider.length)),model:Math.max(headers.model.length,...rows.map(r=>r.model.length)),context:Math.max(headers.context.length,...rows.map(r=>r.context.length)),maxOut:Math.max(headers.maxOut.length,...rows.map(r=>r.maxOut.length)),thinking:Math.max(headers.thinking.length,...rows.map(r=>r.thinking.length)),images:Math.max(headers.images.length,...rows.map(r=>r.images.length))},headerLine=[headers.provider.padEnd(widths.provider),headers.model.padEnd(widths.model),headers.context.padEnd(widths.context),headers.maxOut.padEnd(widths.maxOut),headers.thinking.padEnd(widths.thinking),headers.images.padEnd(widths.images)].join(" ");console.log(headerLine);for(let row of rows){let line=[row.provider.padEnd(widths.provider),row.model.padEnd(widths.model),row.context.padEnd(widths.context),row.maxOut.padEnd(widths.maxOut),row.thinking.padEnd(widths.thinking),row.images.padEnd(widths.images)].join(" ");console.log(line)}}import{join as join59}from"node:path";var FACTORY_PLUGIN_RANGE=`^${VERSION}`,BOOTSTRAP_FACTORY_PLUGIN_MANIFEST_V1=Object.freeze([{pluginId:"agent-forge.plugin.goal",npmName:"@ai-agent-forge/plugin-goal",range:FACTORY_PLUGIN_RANGE},{pluginId:"agent-forge.plugin.plan",npmName:"@ai-agent-forge/plugin-plan",range:FACTORY_PLUGIN_RANGE},{pluginId:"agent-forge.plugin.todo-set",npmName:"@ai-agent-forge/plugin-todo-set",range:FACTORY_PLUGIN_RANGE},{pluginId:"agent-forge.plugin.session-share",npmName:"@ai-agent-forge/plugin-session-share",range:FACTORY_PLUGIN_RANGE},{pluginId:"agent-forge.plugin.observability",npmName:"@ai-agent-forge/plugin-observability",range:FACTORY_PLUGIN_RANGE},{pluginId:"agent-forge.plugin.subagent-delegate",npmName:"@ai-agent-forge/plugin-subagent-delegate",range:FACTORY_PLUGIN_RANGE},{pluginId:"agent-forge.plugin.memory",npmName:"@ai-agent-forge/plugin-memory",range:FACTORY_PLUGIN_RANGE},{pluginId:"agent-forge.plugin.image-generation",npmName:"@ai-agent-forge/plugin-image-generation",range:FACTORY_PLUGIN_RANGE}]);function printResponse(response2,write){write(response2.text),response2.status!=="succeeded"&&(process.exitCode=1)}function buildMarketCli(options){let{market,overrides}=options;return createPluginEcosystemCliV1({host:overrides?.host??defaultPluginHostFactsV1(),manifests:listBuiltinPluginManifestsV1(),registry:overrides?.registry??market?.cliRegistry,...overrides?.acquisition===void 0&&market?.acquisition===void 0?{}:{acquisition:overrides?.acquisition??market?.acquisition},installer:overrides?.installer??market?.installer,...overrides?.distribution!==void 0||market?.distribution!==void 0?{distribution:overrides?.distribution??market.distribution}:{},stateStore:overrides?.stateStore??market?.stateStore??createPluginStateStoreV1({filePath:join59(options.agentDir,"plugin-state.json")}),projectStateStore:overrides?.projectStateStore??market?.projectStateStore??createPluginStateStoreV1({filePath:join59(options.cwd,CONFIG_DIR_NAME,"plugin-state.json")}),projectScopeRef:projectPluginScopeRefV1(options.cwd),selectionStore:overrides?.selectionStore??createPluginSelectionStoreV1({filePath:join59(options.agentDir,".plugin-selection.json")}),projectSelectionStore:overrides?.projectSelectionStore??createPluginSelectionStoreV1({filePath:join59(options.cwd,CONFIG_DIR_NAME,".plugin-selection.json")})})}async function createDefaultPluginManagerControllerV1(options){let agentDir=options.agentDir??getAgentDir(),cwd=options.cwd??process.cwd(),market=await createDefaultPluginMarketWiringV1({agentDir,cwd}),cli=buildMarketCli({agentDir,cwd,market});return{controller:createPluginManagerControllerV1({registry:market.registry,stateStore:options.scope==="project"?market.projectStateStore:market.stateStore,cli}),close:market.close}}async function handlePluginEcosystemCommand(args,options={}){if(args[0]!=="plugin")return!1;let write=options.write??(line=>console.log(line));if(args[1]==="update"&&args[2]==="--all")return await runBatchUpdate(args.slice(3),options,write),!0;let agentDir=options.agentDir??getAgentDir(),cwd=options.cwd??process.cwd(),market=options.registry===void 0&&options.installer===void 0?await createDefaultPluginMarketWiringV1({agentDir,cwd}):void 0;try{let response2=await buildMarketCli({agentDir,cwd,market,overrides:options}).execute({argv:args.slice(1)});return printResponse(response2,write),!0}finally{await market?.close()}}async function runBatchUpdate(restArgs,options,write){let agentDir=options.agentDir??getAgentDir(),cwd=options.cwd??process.cwd(),scopeIndex=restArgs.indexOf("--scope"),scope=scopeIndex!==-1&&restArgs[scopeIndex+1]==="project"?"project":"global",market=options.registry===void 0&&options.installer===void 0?await createDefaultPluginMarketWiringV1({agentDir,cwd}):void 0;try{let cli=buildMarketCli({agentDir,cwd,market,overrides:options}),listResponse=await cli.execute({argv:["state","list","--scope",scope]});if(listResponse.status!=="succeeded"){printResponse(listResponse,write);return}let entries=(listResponse.data?.entries??[]).filter(entry=>entry.lifecycle==="active"&&entry.scope===scope);if(entries.length===0){write("No active plugins to update.");return}let updated=[],current=[],failed=[];for(let entry of entries){let factoryEntry=BOOTSTRAP_FACTORY_PLUGIN_MANIFEST_V1.find(item=>item.pluginId===entry.pluginId),argv=factoryEntry?["install",`${factoryEntry.npmName}@${factoryEntry.range??"latest"}`,"--scope",scope]:["update",entry.pluginId,"--scope",scope],response2=await cli.execute({argv});response2.status==="succeeded"?(updated.push(entry.pluginId),write(response2.text)):response2.error?.code==="already_installed"?current.push(entry.pluginId):(failed.push(entry.pluginId),write(response2.text))}let summary=[`updated ${updated.length}${updated.length>0?` (${updated.join(", ")})`:""}`,`already up to date ${current.length}${current.length>0?` (${current.join(", ")})`:""}`,`failed ${failed.length}${failed.length>0?` (${failed.join(", ")})`:""}`].join("; ");write(`plugin update --all [${scope}]: ${summary}`),failed.length>0&&(process.exitCode=1)}finally{await market?.close()}}import{join as join60}from"node:path";var DEFAULT_DURABLE_LOG_RELATIVE_PATH=join60("durable","remote-server-ops.jsonl");function isAddrInUse(error2){return typeof error2=="object"&&error2!==null&&error2.code==="EADDRINUSE"}async function runServeMode(port,options){let handle,createListener=options?.createListener??(()=>createWsServerListener({port,httpRequestHandler:(request,response2)=>handle?.server.handleArtifactHttpRequest(request,response2)??!1,onError:error2=>{console.error(`remote-server error: ${error2.message}`)}})),startServer=options?.startServer??startCodingAgentRemoteServer,workspaceRoots=options?.workspaceRoots,sessionDir=options?.sessionDir,durable=options?.durable??createDurableService({backend:createFileDurableStoreBackend({path:join60(getAgentDir(),DEFAULT_DURABLE_LOG_RELATIVE_PATH)})}),writerId=readOrCreateWriterId(getAgentDir());try{handle=await startServer({sessionSourceOptions:{sessionsDir:sessionDir??getSessionsDir(),cwd:process.cwd(),agentDir:getAgentDir(),...workspaceRoots===void 0||workspaceRoots.length===0?{}:{workspaceRoots},agentTaskResults:{store:durable,writerId},subagentPoolFromSelfInvocation:!0,...options?.hostLogger===void 0?{}:{hostLogger:options.hostLogger}},listeners:[createListener()],onError:error2=>{console.error(`remote-server error: ${error2.message}`)},durable,writerId})}catch(error2){throw isAddrInUse(error2)&&(console.error(`Port ${port} is already in use`),process.exit(1)),error2}let closing=!1,shutdown=()=>{closing||(closing=!0,handle.close().then(()=>{process.exit(0)}).catch(error2=>{console.error(`Remote server shutdown failed: ${error2 instanceof Error?error2.message:String(error2)}`),process.exit(1)}))};process.on("SIGINT",shutdown),process.on("SIGTERM",shutdown),console.log(`Remote server listening on ${handle.addresses.join(", ")}`)}import{existsSync as existsSync29}from"fs";var THEME_OPTIONS=[{value:"dark",label:"Dark"},{value:"light",label:"Light"}],ANALYTICS_OPTIONS=[{value:!0,label:"Share anonymous usage data"},{value:!1,label:"Don't share"}],SETUP_LOGO_LINES=["\u2588\u2588\u2588\u2588\u2588\u2588","\u2588\u2588 \u2588\u2588","\u2588\u2588\u2588\u2588 \u2588\u2588","\u2588\u2588 \u2588\u2588"],FirstTimeSetupComponent=class extends Container{step="theme";themeIndex;analyticsIndex=0;options;constructor(options){super(),this.options=options,this.themeIndex=Math.max(0,THEME_OPTIONS.findIndex(option=>option.value===options.detectedTheme)),this.update()}update(){this.clear(),this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("accent",SETUP_LOGO_LINES.join(`
|
|
1491
1491
|
`)),1,0)),this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("accent",theme.bold(`Welcome to ${APP_NAME}, the minimal coding agent.`)),1,0)),this.addChild(new Spacer(1)),this.step==="theme"?(this.addChild(new Text(theme.fg("text","Pick a theme."),1,0)),this.addChild(new Text(theme.fg("muted",`Detected system appearance: ${this.options.detectedTheme}`),1,0)),this.addChild(new Spacer(1)),this.addOptionList(THEME_OPTIONS.map(option=>option.label),this.themeIndex)):(this.addChild(new Text(theme.fg("text","Opt-in to anonymous usage data sharing?"),1,0)),this.addChild(new Text(theme.fg("muted",`Opting in stores a tracking identifier in settings.json and enables anonymous
|
|
1492
1492
|
usage analytics. This helps us to better debug, reproduce, and resolve issues
|
|
1493
1493
|
and bugs within Agent Forge. You can observe what is shared using /privacy and make
|
|
@@ -1503,7 +1503,7 @@ changes anytime in settings.json.`),1,0)),this.addChild(new Spacer(1)),this.addO
|
|
|
1503
1503
|
${value.stack}`}
|
|
1504
1504
|
`}return`${JSON.stringify(toSafeJson(value))}
|
|
1505
1505
|
`}function createHostLogger(options){if(options.level!==void 0&&!HOST_LOG_LEVELS.includes(options.level))throw new Error(`Host logger level must be one of ${HOST_LOG_LEVELS.map(level=>`"${level}"`).join(" | ")}; got ${JSON.stringify(options.level)}`);let minRank=LEVEL_RANK[options.level??"info"],now=options.now??Date.now,maxAgeDays=options.maxAgeDays??DEFAULT_MAX_AGE_DAYS,processHost=options.processHost??NODE_PROCESS_HOST,closed=!1,dirReady=!1,written=0,failed=0,write=(level,src,msg,context)=>{if(closed||LEVEL_RANK[level]<minRank)return;let entry={v:1,t:now(),level,src,msg,sessionId:context?.sessionId,traceId:context?.traceId,fields:context?.fields===void 0?void 0:toSafeJson(context.fields),cause:context?.cause===void 0?void 0:boundCause(context.cause)};try{dirReady||(mkdirSync19(options.dir,{recursive:!0}),dirReady=!0),appendFileSync4(join61(options.dir,logFileName(entry.t)),`${JSON.stringify(entry)}
|
|
1506
|
-
`),written+=1}catch{failed+=1,dirReady=!1}};(()=>{if(maxAgeDays<=0)return;let cutoff=now()-maxAgeDays*DAY_MS,currentName=logFileName(now()),names2;try{names2=readdirSync16(options.dir)}catch(error2){if(error2.code==="ENOENT")return;write("warn","logger","log sweep failed: cannot read log directory",{cause:error2});return}let removed=0,errors=0;for(let name of names2){if(!name.endsWith(".log")||name===currentName)continue;let fullPath=join61(options.dir,name);try{let stats=statSync18(fullPath);if(!stats.isFile()||stats.mtimeMs>=cutoff)continue;unlinkSync4(fullPath),removed+=1}catch{errors+=1}}errors>0&&write("warn","logger","log sweep finished with failures",{fields:{removed,errors}})})();let exit=processHost.exit??NODE_PROCESS_CRASH_HOST.exit,writeStderr=processHost.writeStderr??NODE_PROCESS_CRASH_HOST.writeStderr,deferThrow=processHost.deferThrow??NODE_PROCESS_CRASH_HOST.deferThrow,loggedFatalValues=new WeakSet,isFatalValueLogged=value=>value!==null&&(typeof value=="object"||typeof value=="function")&&loggedFatalValues.has(value),markFatalValueLogged=value=>{value!==null&&(typeof value=="object"||typeof value=="function")&&loggedFatalValues.add(value)};return processHost.onUncaughtException&&processHost.onUncaughtException(error2=>{isFatalValueLogged(error2)||(markFatalValueLogged(error2),write("error","process","uncaughtException",{cause:error2})),writeStderr(fatalStderrText(error2)),exit(1)}),processHost.onUnhandledRejection&&processHost.onUnhandledRejection(reason=>{markFatalValueLogged(reason),write("error","process","unhandledRejection",{cause:reason}),deferThrow(()=>{throw reason})}),{debug:(src,msg,context)=>write("debug",src,msg,context),info:(src,msg,context)=>write("info",src,msg,context),warn:(src,msg,context)=>write("warn",src,msg,context),error:(src,msg,context)=>write("error",src,msg,context),close:()=>(closed=!0,{written,failed})}}function collectSettingsDiagnostics(settingsManager){return settingsManager.drainErrors().map(({scope,path:path15,error:error2})=>({type:"warning",message:path15?`Invalid settings file ${path15}: ${error2.message}`:`Invalid ${scope} settings: ${error2.message}`}))}function deduplicateDiagnostics(diagnostics){let seen=new Set;return diagnostics.filter(diagnostic5=>{let key=`${diagnostic5.type}\0${diagnostic5.message}`;return seen.has(key)?!1:(seen.add(key),!0)})}import{readdirSync as readdirSync17,statSync as statSync19,unlinkSync as unlinkSync5}from"node:fs";import{join as join62}from"node:path";var DAY_MS2=1440*60*1e3,TRACE_FILE_SUFFIX=".trace.jsonl";function sweepTraceFiles(sessionsRoot,options){if(options.maxAgeDays<=0)return{scanned:0,deleted:0,failed:0};let now=options.now??Date.now,unlink4=options.unlink??(path15=>unlinkSync5(path15)),cutoff=now()-options.maxAgeDays*DAY_MS2,scanned=0,deleted=0,failed=0,readEntries=dir=>{try{return readdirSync17(dir,{withFileTypes:!0})}catch{return}},sweepFilesIn=(dir,entries)=>{for(let entry of entries){if(!entry.name.endsWith(TRACE_FILE_SUFFIX))continue;let fullPath=join62(dir,entry.name),isFile=!1,isExpired=!1;try{let stats=statSync19(fullPath);isFile=stats.isFile(),isExpired=isFile&&stats.mtimeMs<cutoff}catch{continue}if(isFile&&(scanned+=1,!!isExpired))try{unlink4(fullPath),deleted+=1}catch{failed+=1}}},rootEntries=readEntries(sessionsRoot);if(rootEntries===void 0)return{scanned:0,deleted:0,failed:0};sweepFilesIn(sessionsRoot,rootEntries);for(let entry of rootEntries){if(!entry.isDirectory())continue;let subdirectory=join62(sessionsRoot,entry.name),subEntries=readEntries(subdirectory);subEntries!==void 0&&sweepFilesIn(subdirectory,subEntries)}return{scanned,deleted,failed}}import{join as join63}from"node:path";var FACTORY_PLUGIN_RANGE=`^${VERSION}`,BOOTSTRAP_FACTORY_PLUGIN_MANIFEST_V1=Object.freeze([{pluginId:"agent-forge.plugin.goal",npmName:"@ai-agent-forge/plugin-goal",range:FACTORY_PLUGIN_RANGE},{pluginId:"agent-forge.plugin.plan",npmName:"@ai-agent-forge/plugin-plan",range:FACTORY_PLUGIN_RANGE},{pluginId:"agent-forge.plugin.todo-set",npmName:"@ai-agent-forge/plugin-todo-set",range:FACTORY_PLUGIN_RANGE},{pluginId:"agent-forge.plugin.session-share",npmName:"@ai-agent-forge/plugin-session-share",range:FACTORY_PLUGIN_RANGE},{pluginId:"agent-forge.plugin.observability",npmName:"@ai-agent-forge/plugin-observability",range:FACTORY_PLUGIN_RANGE},{pluginId:"agent-forge.plugin.subagent-delegate",npmName:"@ai-agent-forge/plugin-subagent-delegate",range:FACTORY_PLUGIN_RANGE},{pluginId:"agent-forge.plugin.memory",npmName:"@ai-agent-forge/plugin-memory",range:FACTORY_PLUGIN_RANGE}]);var PLUGIN_BOOTSTRAP_VERSION_V1=1;function satisfiesRangeV1(version,range2){return selectNpmPackageVersionV1([version],range2)===version}function pluginBootstrapInstallCommandV1(entry){return`agent-forge plugin install ${entry.npmName}@${entry.range??"latest"}`}function errorMessage(error2){return error2 instanceof Error?error2.message:String(error2)}function acquireErrorCode(error2){return error2 instanceof PluginAcquisitionErrorV1?error2.code:"install_failed"}function actionOf(entry,status2,reason){return Object.freeze({pluginId:entry.pluginId,status:status2,reason,npmName:entry.npmName,...entry.range===void 0?{}:{range:entry.range}})}async function runPluginBootstrapV1(input){let now=input.deps.now??Date.now,startedAt=now(),finish=(status3,actions2,diagnostics2)=>Object.freeze({version:PLUGIN_BOOTSTRAP_VERSION_V1,status:status3,actions:Object.freeze([...actions2]),diagnostics:Object.freeze([...diagnostics2]),durationMs:Math.max(0,now()-startedAt)});if(input.manifest.length===0)return finish("succeeded",[],[]);let signal=input.deps.signal,active;try{active=await input.deps.listActive({...signal===void 0?{}:{signal}})}catch(error2){return finish("failed",[],[{code:"list_active_failed",message:`Active plugin state could not be read; bootstrap installed nothing: ${errorMessage(error2)}`}])}let actions=[],diagnostics=[];for(let entry of input.manifest){if(signal?.aborted===!0){diagnostics.push({code:"cancelled",message:"Plugin bootstrap was cancelled before all factory entries were processed"});break}let activeVersion=active.get(entry.pluginId);if(activeVersion!==void 0){if(satisfiesRangeV1(activeVersion,entry.range)){actions.push(Object.freeze({...actionOf(entry,"skipped","satisfies_range"),activeVersion}));continue}actions.push(Object.freeze({...actionOf(entry,"diagnosed","range_not_satisfied"),activeVersion})),diagnostics.push({code:"range_not_satisfied",pluginId:entry.pluginId,message:`Active version ${activeVersion} of ${entry.pluginId} does not satisfy the factory range ${entry.range??"latest"}; bootstrap never replaces active installations. Run \`${pluginBootstrapInstallCommandV1(entry)}\` to install a matching version, or \`agent-forge plugin update --all\` to upgrade every outdated plugin at once.`});continue}try{let installed=await input.deps.installFromNpm({npmName:entry.npmName,...entry.range===void 0?{}:{range:entry.range},...signal===void 0?{}:{signal}});actions.push(Object.freeze({...actionOf(entry,"installed","installed"),installedVersion:installed.pluginVersion,source:installed.source}))}catch(error2){let errorCode2=acquireErrorCode(error2);actions.push(Object.freeze({...actionOf(entry,"failed","install_failed"),errorCode:errorCode2})),diagnostics.push({code:"install_failed",pluginId:entry.pluginId,message:`Bootstrap could not install ${entry.pluginId} from npm (${errorCode2}: ${errorMessage(error2)}). Startup continues without it; its capabilities stay unavailable until installed. Run \`${pluginBootstrapInstallCommandV1(entry)}\` to install it manually.`})}}let status2=actions.some(action=>action.status==="failed")?"failed":actions.some(action=>action.status==="diagnosed")?"degraded":"succeeded";return finish(status2,actions,diagnostics)}var AGENT_FORGE_PLUGIN_BOOTSTRAP_ENV_V1="AGENT_FORGE_PLUGIN_BOOTSTRAP",PLUGIN_BOOTSTRAP_DISABLED_VALUE_V1="off";function readActiveVersions(store,scope,scopeRef,signal){return(async()=>{let result=await store.read({...signal===void 0?{}:{signal}});if(result.status!=="ok"&&result.status!=="missing")throw new Error(`plugin state read failed (${result.diagnostics[0]?.code??result.status}) for the ${scope} scope`);let versions=new Map;for(let record of result.snapshot.records)record.state.scope!==scope||record.state.scopeRef!==scopeRef||record.state.lifecycle==="active"&&versions.set(record.pluginId,record.pluginVersion);return versions})()}async function runNodePluginBootstrapV1(options){if(process.env[AGENT_FORGE_PLUGIN_BOOTSTRAP_ENV_V1]?.trim()===PLUGIN_BOOTSTRAP_DISABLED_VALUE_V1)return Object.freeze({version:1,status:"succeeded",actions:Object.freeze([]),diagnostics:Object.freeze([]),durationMs:0,skipped:"disabled"});if(options.deps!==void 0)return await runPluginBootstrapV1({manifest:options.manifest??BOOTSTRAP_FACTORY_PLUGIN_MANIFEST_V1,deps:options.deps});let session,ensureSession=async()=>{if(session!==void 0)return session;let acquisition=createNodePluginAcquisitionHostV1({...options.npmRegistry===void 0?{}:{npmRegistry:options.npmRegistry},...options.npmToken===void 0?{}:{npmToken:options.npmToken},...options.fetch===void 0?{}:{fetch:options.fetch},...options.limits===void 0?{}:{limits:options.limits}}),installHost=await createNodePackageInstallHostV1({openArtifact:input=>acquisition.openArtifact(input),installationDirectory:defaultPluginInstallStoreDirectoryV1(options.agentDir),persistence:"persistent",supportedScopes:["global","project"],...options.limits===void 0?{}:{...options.limits}});return session={acquisition,installHost,installer:createPluginInstallerV1({host:installHost}),stateStore:createPluginStateStoreV1({filePath:join63(options.agentDir,DEFAULT_PLUGIN_STATE_FILE_V1)})},session},deps={listActive:async({signal})=>{let globalVersions=readActiveVersions(createPluginStateStoreV1({filePath:join63(options.agentDir,DEFAULT_PLUGIN_STATE_FILE_V1)}),"global",DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1,signal),projectVersions=readActiveVersions(createPluginStateStoreV1({filePath:join63(options.cwd,CONFIG_DIR_NAME,DEFAULT_PLUGIN_STATE_FILE_V1)}),"project",projectPluginScopeRefV1(options.cwd),signal),[globalResult,projectResult]=await Promise.all([globalVersions,projectVersions]);return new Map([...globalResult,...projectResult])},installFromNpm:async({npmName,range:range2,signal})=>{let active=await ensureSession(),ref=range2===void 0?npmName:`${npmName}@${range2}`,acquired=await active.acquisition.resolvePackage({ref,...signal===void 0?{}:{signal}}),released=!1,release=async()=>{released||(released=!0,await acquired.release())};try{let verified=active.installer.prepare({manifest:acquired.manifest,source:acquired.source,host:defaultPluginHostFactsV1()});if(verified.status!=="verified")throw new Error(`installer prepare rejected ${acquired.manifest.id}: ${verified.reason}`);let installed=await active.installer.install({record:verified.record,scope:"global",scopeRef:DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1,artifact:acquired.artifact,...signal===void 0?{}:{signal}});if(installed.status!=="succeeded")throw new Error(`plugin install failed (${installed.error.code}) for ${acquired.manifest.id}`);let activated=await active.installer.activate({installation:installed.installation,record:verified.record,scope:"global",scopeRef:DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1,...signal===void 0?{}:{signal}});if(activated.status!=="succeeded")throw await active.installer.remove({installation:installed.installation,scope:"global",scopeRef:DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1}).catch(()=>{}),new Error(`plugin activation failed (${activated.error.code}) for ${acquired.manifest.id}`);let persisted=await active.stateStore.upsert({installation:activated.installation,scope:"global",enabled:!0,source:acquired.source,...signal===void 0?{}:{signal}});if(persisted.status!=="ok")throw await active.installer.remove({installation:activated.installation,scope:"global",scopeRef:DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1}).catch(()=>{}),new Error(`plugin state persist failed (${persisted.status}) for ${acquired.manifest.id}`);return{pluginVersion:activated.installation.pluginVersion,source:acquired.source}}finally{await release()}},...options.signal===void 0?{}:{signal:options.signal}};try{return await runPluginBootstrapV1({manifest:options.manifest??BOOTSTRAP_FACTORY_PLUGIN_MANIFEST_V1,deps})}finally{let active=session;session=void 0,active!==void 0&&(await active.installHost.close().catch(()=>{}),await active.acquisition.close().catch(()=>{}))}}import{existsSync as existsSync31,mkdirSync as mkdirSync20,readdirSync as readdirSync18,readFileSync as readFileSync27,renameSync as renameSync4,rmSync as rmSync6,writeFileSync as writeFileSync17}from"fs";import{dirname as dirname30,join as join64}from"path";var MIGRATION_GUIDE_URL="https://github.com/agent-forge/agent-forge/blob/main/packages/agent-forge/CHANGELOG.md#extensions-migration",EXTENSIONS_DOC_URL="https://github.com/agent-forge/agent-forge/blob/main/packages/agent-forge/docs/extensions.md";function migrateAuthToAuthJson(){let agentDir=getAgentDir(),authPath=join64(agentDir,"auth.json"),oauthPath=join64(agentDir,"oauth.json"),settingsPath=join64(agentDir,"settings.json");if(existsSync31(authPath))return[];let migrated={},providers=[];if(existsSync31(oauthPath))try{let oauth=JSON.parse(stripBom(readFileSync27(oauthPath,"utf-8")));for(let[provider,cred]of Object.entries(oauth))migrated[provider]={type:"oauth",...cred},providers.push(provider);renameSync4(oauthPath,`${oauthPath}.migrated`)}catch{}if(existsSync31(settingsPath))try{let content=readFileSync27(settingsPath,"utf-8"),settings2=JSON.parse(stripBom(content));if(settings2.apiKeys&&typeof settings2.apiKeys=="object"){for(let[provider,key]of Object.entries(settings2.apiKeys))!migrated[provider]&&typeof key=="string"&&(migrated[provider]={type:"api_key",key},providers.push(provider));delete settings2.apiKeys,writeFileSync17(settingsPath,JSON.stringify(settings2,null,2))}}catch{}return Object.keys(migrated).length>0&&(mkdirSync20(dirname30(authPath),{recursive:!0}),writeFileSync17(authPath,JSON.stringify(migrated,null,2),{mode:384})),providers}function migrateSessionsFromAgentRoot(){let agentDir=getAgentDir(),files;try{files=readdirSync18(agentDir).filter(f=>f.endsWith(".jsonl")).map(f=>join64(agentDir,f))}catch{return}if(files.length!==0)for(let file of files)try{let firstLine=readFileSync27(file,"utf8").split(`
|
|
1506
|
+
`),written+=1}catch{failed+=1,dirReady=!1}};(()=>{if(maxAgeDays<=0)return;let cutoff=now()-maxAgeDays*DAY_MS,currentName=logFileName(now()),names2;try{names2=readdirSync16(options.dir)}catch(error2){if(error2.code==="ENOENT")return;write("warn","logger","log sweep failed: cannot read log directory",{cause:error2});return}let removed=0,errors=0;for(let name of names2){if(!name.endsWith(".log")||name===currentName)continue;let fullPath=join61(options.dir,name);try{let stats=statSync18(fullPath);if(!stats.isFile()||stats.mtimeMs>=cutoff)continue;unlinkSync4(fullPath),removed+=1}catch{errors+=1}}errors>0&&write("warn","logger","log sweep finished with failures",{fields:{removed,errors}})})();let exit=processHost.exit??NODE_PROCESS_CRASH_HOST.exit,writeStderr=processHost.writeStderr??NODE_PROCESS_CRASH_HOST.writeStderr,deferThrow=processHost.deferThrow??NODE_PROCESS_CRASH_HOST.deferThrow,loggedFatalValues=new WeakSet,isFatalValueLogged=value=>value!==null&&(typeof value=="object"||typeof value=="function")&&loggedFatalValues.has(value),markFatalValueLogged=value=>{value!==null&&(typeof value=="object"||typeof value=="function")&&loggedFatalValues.add(value)};return processHost.onUncaughtException&&processHost.onUncaughtException(error2=>{isFatalValueLogged(error2)||(markFatalValueLogged(error2),write("error","process","uncaughtException",{cause:error2})),writeStderr(fatalStderrText(error2)),exit(1)}),processHost.onUnhandledRejection&&processHost.onUnhandledRejection(reason=>{markFatalValueLogged(reason),write("error","process","unhandledRejection",{cause:reason}),deferThrow(()=>{throw reason})}),{debug:(src,msg,context)=>write("debug",src,msg,context),info:(src,msg,context)=>write("info",src,msg,context),warn:(src,msg,context)=>write("warn",src,msg,context),error:(src,msg,context)=>write("error",src,msg,context),close:()=>(closed=!0,{written,failed})}}function collectSettingsDiagnostics(settingsManager){return settingsManager.drainErrors().map(({scope,path:path15,error:error2})=>({type:"warning",message:path15?`Invalid settings file ${path15}: ${error2.message}`:`Invalid ${scope} settings: ${error2.message}`}))}function deduplicateDiagnostics(diagnostics){let seen=new Set;return diagnostics.filter(diagnostic5=>{let key=`${diagnostic5.type}\0${diagnostic5.message}`;return seen.has(key)?!1:(seen.add(key),!0)})}import{readdirSync as readdirSync17,statSync as statSync19,unlinkSync as unlinkSync5}from"node:fs";import{join as join62}from"node:path";var DAY_MS2=1440*60*1e3,TRACE_FILE_SUFFIX=".trace.jsonl";function sweepTraceFiles(sessionsRoot,options){if(options.maxAgeDays<=0)return{scanned:0,deleted:0,failed:0};let now=options.now??Date.now,unlink4=options.unlink??(path15=>unlinkSync5(path15)),cutoff=now()-options.maxAgeDays*DAY_MS2,scanned=0,deleted=0,failed=0,readEntries=dir=>{try{return readdirSync17(dir,{withFileTypes:!0})}catch{return}},sweepFilesIn=(dir,entries)=>{for(let entry of entries){if(!entry.name.endsWith(TRACE_FILE_SUFFIX))continue;let fullPath=join62(dir,entry.name),isFile=!1,isExpired=!1;try{let stats=statSync19(fullPath);isFile=stats.isFile(),isExpired=isFile&&stats.mtimeMs<cutoff}catch{continue}if(isFile&&(scanned+=1,!!isExpired))try{unlink4(fullPath),deleted+=1}catch{failed+=1}}},rootEntries=readEntries(sessionsRoot);if(rootEntries===void 0)return{scanned:0,deleted:0,failed:0};sweepFilesIn(sessionsRoot,rootEntries);for(let entry of rootEntries){if(!entry.isDirectory())continue;let subdirectory=join62(sessionsRoot,entry.name),subEntries=readEntries(subdirectory);subEntries!==void 0&&sweepFilesIn(subdirectory,subEntries)}return{scanned,deleted,failed}}import{join as join63}from"node:path";var PLUGIN_BOOTSTRAP_VERSION_V1=1;function satisfiesRangeV1(version,range2){return selectNpmPackageVersionV1([version],range2)===version}function pluginBootstrapInstallCommandV1(entry){return`agent-forge plugin install ${entry.npmName}@${entry.range??"latest"}`}function errorMessage(error2){return error2 instanceof Error?error2.message:String(error2)}function acquireErrorCode(error2){return error2 instanceof PluginAcquisitionErrorV1?error2.code:"install_failed"}function actionOf(entry,status2,reason){return Object.freeze({pluginId:entry.pluginId,status:status2,reason,npmName:entry.npmName,...entry.range===void 0?{}:{range:entry.range}})}async function runPluginBootstrapV1(input){let now=input.deps.now??Date.now,startedAt=now(),finish=(status3,actions2,diagnostics2)=>Object.freeze({version:PLUGIN_BOOTSTRAP_VERSION_V1,status:status3,actions:Object.freeze([...actions2]),diagnostics:Object.freeze([...diagnostics2]),durationMs:Math.max(0,now()-startedAt)});if(input.manifest.length===0)return finish("succeeded",[],[]);let signal=input.deps.signal,active;try{active=await input.deps.listActive({...signal===void 0?{}:{signal}})}catch(error2){return finish("failed",[],[{code:"list_active_failed",message:`Active plugin state could not be read; bootstrap installed nothing: ${errorMessage(error2)}`}])}let actions=[],diagnostics=[];for(let entry of input.manifest){if(signal?.aborted===!0){diagnostics.push({code:"cancelled",message:"Plugin bootstrap was cancelled before all factory entries were processed"});break}let activeVersion=active.get(entry.pluginId);if(activeVersion!==void 0){if(satisfiesRangeV1(activeVersion,entry.range)){actions.push(Object.freeze({...actionOf(entry,"skipped","satisfies_range"),activeVersion}));continue}actions.push(Object.freeze({...actionOf(entry,"diagnosed","range_not_satisfied"),activeVersion})),diagnostics.push({code:"range_not_satisfied",pluginId:entry.pluginId,message:`Active version ${activeVersion} of ${entry.pluginId} does not satisfy the factory range ${entry.range??"latest"}; bootstrap never replaces active installations. Run \`${pluginBootstrapInstallCommandV1(entry)}\` to install a matching version, or \`agent-forge plugin update --all\` to upgrade every outdated plugin at once.`});continue}try{let installed=await input.deps.installFromNpm({npmName:entry.npmName,...entry.range===void 0?{}:{range:entry.range},...signal===void 0?{}:{signal}});actions.push(Object.freeze({...actionOf(entry,"installed","installed"),installedVersion:installed.pluginVersion,source:installed.source}))}catch(error2){let errorCode2=acquireErrorCode(error2);actions.push(Object.freeze({...actionOf(entry,"failed","install_failed"),errorCode:errorCode2})),diagnostics.push({code:"install_failed",pluginId:entry.pluginId,message:`Bootstrap could not install ${entry.pluginId} from npm (${errorCode2}: ${errorMessage(error2)}). Startup continues without it; its capabilities stay unavailable until installed. Run \`${pluginBootstrapInstallCommandV1(entry)}\` to install it manually.`})}}let status2=actions.some(action=>action.status==="failed")?"failed":actions.some(action=>action.status==="diagnosed")?"degraded":"succeeded";return finish(status2,actions,diagnostics)}var AGENT_FORGE_PLUGIN_BOOTSTRAP_ENV_V1="AGENT_FORGE_PLUGIN_BOOTSTRAP",PLUGIN_BOOTSTRAP_DISABLED_VALUE_V1="off";function readActiveVersions(store,scope,scopeRef,signal){return(async()=>{let result=await store.read({...signal===void 0?{}:{signal}});if(result.status!=="ok"&&result.status!=="missing")throw new Error(`plugin state read failed (${result.diagnostics[0]?.code??result.status}) for the ${scope} scope`);let versions=new Map;for(let record of result.snapshot.records)record.state.scope!==scope||record.state.scopeRef!==scopeRef||record.state.lifecycle==="active"&&versions.set(record.pluginId,record.pluginVersion);return versions})()}async function runNodePluginBootstrapV1(options){if(process.env[AGENT_FORGE_PLUGIN_BOOTSTRAP_ENV_V1]?.trim()===PLUGIN_BOOTSTRAP_DISABLED_VALUE_V1)return Object.freeze({version:1,status:"succeeded",actions:Object.freeze([]),diagnostics:Object.freeze([]),durationMs:0,skipped:"disabled"});if(options.deps!==void 0)return await runPluginBootstrapV1({manifest:options.manifest??BOOTSTRAP_FACTORY_PLUGIN_MANIFEST_V1,deps:options.deps});let session,ensureSession=async()=>{if(session!==void 0)return session;let acquisition=createNodePluginAcquisitionHostV1({...options.npmRegistry===void 0?{}:{npmRegistry:options.npmRegistry},...options.npmToken===void 0?{}:{npmToken:options.npmToken},...options.fetch===void 0?{}:{fetch:options.fetch},...options.limits===void 0?{}:{limits:options.limits}}),installHost=await createNodePackageInstallHostV1({openArtifact:input=>acquisition.openArtifact(input),installationDirectory:defaultPluginInstallStoreDirectoryV1(options.agentDir),persistence:"persistent",supportedScopes:["global","project"],...options.limits===void 0?{}:{...options.limits}});return session={acquisition,installHost,installer:createPluginInstallerV1({host:installHost}),stateStore:createPluginStateStoreV1({filePath:join63(options.agentDir,DEFAULT_PLUGIN_STATE_FILE_V1)})},session},deps={listActive:async({signal})=>{let globalVersions=readActiveVersions(createPluginStateStoreV1({filePath:join63(options.agentDir,DEFAULT_PLUGIN_STATE_FILE_V1)}),"global",DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1,signal),projectVersions=readActiveVersions(createPluginStateStoreV1({filePath:join63(options.cwd,CONFIG_DIR_NAME,DEFAULT_PLUGIN_STATE_FILE_V1)}),"project",projectPluginScopeRefV1(options.cwd),signal),[globalResult,projectResult]=await Promise.all([globalVersions,projectVersions]);return new Map([...globalResult,...projectResult])},installFromNpm:async({npmName,range:range2,signal})=>{let active=await ensureSession(),ref=range2===void 0?npmName:`${npmName}@${range2}`,acquired=await active.acquisition.resolvePackage({ref,...signal===void 0?{}:{signal}}),released=!1,release=async()=>{released||(released=!0,await acquired.release())};try{let verified=active.installer.prepare({manifest:acquired.manifest,source:acquired.source,host:defaultPluginHostFactsV1()});if(verified.status!=="verified")throw new Error(`installer prepare rejected ${acquired.manifest.id}: ${verified.reason}`);let installed=await active.installer.install({record:verified.record,scope:"global",scopeRef:DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1,artifact:acquired.artifact,...signal===void 0?{}:{signal}});if(installed.status!=="succeeded")throw new Error(`plugin install failed (${installed.error.code}) for ${acquired.manifest.id}`);let activated=await active.installer.activate({installation:installed.installation,record:verified.record,scope:"global",scopeRef:DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1,...signal===void 0?{}:{signal}});if(activated.status!=="succeeded")throw await active.installer.remove({installation:installed.installation,scope:"global",scopeRef:DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1}).catch(()=>{}),new Error(`plugin activation failed (${activated.error.code}) for ${acquired.manifest.id}`);let persisted=await active.stateStore.upsert({installation:activated.installation,scope:"global",enabled:!0,source:acquired.source,...signal===void 0?{}:{signal}});if(persisted.status!=="ok")throw await active.installer.remove({installation:activated.installation,scope:"global",scopeRef:DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1}).catch(()=>{}),new Error(`plugin state persist failed (${persisted.status}) for ${acquired.manifest.id}`);return{pluginVersion:activated.installation.pluginVersion,source:acquired.source}}finally{await release()}},...options.signal===void 0?{}:{signal:options.signal}};try{return await runPluginBootstrapV1({manifest:options.manifest??BOOTSTRAP_FACTORY_PLUGIN_MANIFEST_V1,deps})}finally{let active=session;session=void 0,active!==void 0&&(await active.installHost.close().catch(()=>{}),await active.acquisition.close().catch(()=>{}))}}import{existsSync as existsSync31,mkdirSync as mkdirSync20,readdirSync as readdirSync18,readFileSync as readFileSync27,renameSync as renameSync4,rmSync as rmSync6,writeFileSync as writeFileSync17}from"fs";import{dirname as dirname30,join as join64}from"path";var MIGRATION_GUIDE_URL="https://github.com/agent-forge/agent-forge/blob/main/packages/agent-forge/CHANGELOG.md#extensions-migration",EXTENSIONS_DOC_URL="https://github.com/agent-forge/agent-forge/blob/main/packages/agent-forge/docs/extensions.md";function migrateAuthToAuthJson(){let agentDir=getAgentDir(),authPath=join64(agentDir,"auth.json"),oauthPath=join64(agentDir,"oauth.json"),settingsPath=join64(agentDir,"settings.json");if(existsSync31(authPath))return[];let migrated={},providers=[];if(existsSync31(oauthPath))try{let oauth=JSON.parse(stripBom(readFileSync27(oauthPath,"utf-8")));for(let[provider,cred]of Object.entries(oauth))migrated[provider]={type:"oauth",...cred},providers.push(provider);renameSync4(oauthPath,`${oauthPath}.migrated`)}catch{}if(existsSync31(settingsPath))try{let content=readFileSync27(settingsPath,"utf-8"),settings2=JSON.parse(stripBom(content));if(settings2.apiKeys&&typeof settings2.apiKeys=="object"){for(let[provider,key]of Object.entries(settings2.apiKeys))!migrated[provider]&&typeof key=="string"&&(migrated[provider]={type:"api_key",key},providers.push(provider));delete settings2.apiKeys,writeFileSync17(settingsPath,JSON.stringify(settings2,null,2))}}catch{}return Object.keys(migrated).length>0&&(mkdirSync20(dirname30(authPath),{recursive:!0}),writeFileSync17(authPath,JSON.stringify(migrated,null,2),{mode:384})),providers}function migrateSessionsFromAgentRoot(){let agentDir=getAgentDir(),files;try{files=readdirSync18(agentDir).filter(f=>f.endsWith(".jsonl")).map(f=>join64(agentDir,f))}catch{return}if(files.length!==0)for(let file of files)try{let firstLine=readFileSync27(file,"utf8").split(`
|
|
1507
1507
|
`)[0];if(!firstLine?.trim())continue;let header=JSON.parse(firstLine);if(header.type!=="session"||!header.cwd)continue;let safePath=`--${header.cwd.replace(/^[/\\]/,"").replace(/[/\\:]/g,"-")}--`,correctDir=join64(agentDir,"sessions",safePath);existsSync31(correctDir)||mkdirSync20(correctDir,{recursive:!0});let fileName=file.split("/").pop()||file.split("\\").pop(),newPath=join64(correctDir,fileName);if(existsSync31(newPath))continue;renameSync4(file,newPath)}catch{}}function migrateCommandsToPrompts(baseDir,label){let commandsDir=join64(baseDir,"commands"),promptsDir=join64(baseDir,"prompts");if(existsSync31(commandsDir)&&!existsSync31(promptsDir))try{return renameSync4(commandsDir,promptsDir),console.log(source_default.green(`Migrated ${label} commands/ \u2192 prompts/`)),!0}catch(err2){console.log(source_default.yellow(`Warning: Could not migrate ${label} commands/ to prompts/: ${err2 instanceof Error?err2.message:err2}`))}return!1}function migrateKeybindingsConfigFile(){let configPath=join64(getAgentDir(),"keybindings.json");if(existsSync31(configPath))try{let parsed=JSON.parse(stripBom(readFileSync27(configPath,"utf-8")));if(typeof parsed!="object"||parsed===null||Array.isArray(parsed))return;let{config,migrated}=migrateKeybindingsConfig(parsed);if(!migrated)return;writeFileSync17(configPath,`${JSON.stringify(config,null,2)}
|
|
1508
1508
|
`,"utf-8")}catch{}}function migrateToolsToBin(){let agentDir=getAgentDir(),toolsDir=join64(agentDir,"tools"),binDir=getBinDir();if(!existsSync31(toolsDir))return;let binaries=["fd","rg","fd.exe","rg.exe"],movedAny=!1;for(let bin of binaries){let oldPath=join64(toolsDir,bin),newPath=join64(binDir,bin);if(existsSync31(oldPath))if(existsSync31(binDir)||mkdirSync20(binDir,{recursive:!0}),existsSync31(newPath))try{rmSync6?.(oldPath,{force:!0})}catch{}else try{renameSync4(oldPath,newPath),movedAny=!0}catch{}}movedAny&&console.log(source_default.green("Migrated managed binaries tools/ \u2192 bin/"))}function checkDeprecatedExtensionDirs(baseDir,label){let hooksDir=join64(baseDir,"hooks"),toolsDir=join64(baseDir,"tools"),warnings=[];if(existsSync31(hooksDir)&&warnings.push(`${label} hooks/ directory found. Hooks have been renamed to extensions.`),existsSync31(toolsDir))try{readdirSync18(toolsDir).filter(e=>{let lower=e.toLowerCase();return lower!=="fd"&&lower!=="rg"&&lower!=="fd.exe"&&lower!=="rg.exe"&&!e.startsWith(".")}).length>0&&warnings.push(`${label} tools/ directory contains custom tools. Custom tools have been merged into extensions.`)}catch{}return warnings}function migrateExtensionSystem(cwd){let agentDir=getAgentDir(),projectDir=join64(cwd,CONFIG_DIR_NAME);return migrateCommandsToPrompts(agentDir,"Global"),migrateCommandsToPrompts(projectDir,"Project"),[...checkDeprecatedExtensionDirs(agentDir,"Global"),...checkDeprecatedExtensionDirs(projectDir,"Project")]}async function showDeprecationWarnings(warnings){if(warnings.length!==0){for(let warning of warnings)console.log(source_default.yellow(`Warning: ${warning}`));console.log(source_default.yellow(`
|
|
1509
1509
|
Move your extensions to the extensions/ directory.`)),console.log(source_default.yellow(`Migration guide: ${MIGRATION_GUIDE_URL}`)),console.log(source_default.yellow(`Documentation: ${EXTENSIONS_DOC_URL}`)),console.log()}}function runMigrations(cwd){let migratedAuthProviders=migrateAuthToAuthJson();migrateSessionsFromAgentRoot(),migrateToolsToBin(),migrateKeybindingsConfigFile();let deprecationWarnings=migrateExtensionSystem(cwd);return{migratedAuthProviders,deprecationWarnings}}import{existsSync as existsSync33,mkdirSync as mkdirSync22,mkdtempSync as mkdtempSync2,readdirSync as readdirSync19,readFileSync as readFileSync28,renameSync as renameSync6,rmSync as rmSync8,writeFileSync as writeFileSync18}from"node:fs";import{join as join67,resolve as resolve24}from"node:path";var import_proper_lockfile3=__toESM(require_proper_lockfile(),1);import{homedir as homedir10}from"node:os";import{basename as basename16,dirname as dirname31,join as join65,relative as relative12}from"node:path";var MAX_PROFILE_ID_CHARS=128,MAX_SELECTION_IDS=128,MAX_CATALOG_ENTRIES=256,MAX_DIAGNOSTIC_CODES2=16;function boundedCount(value,maximum){return value===void 0?{count:0,truncated:!1}:{count:Math.min(value.length,maximum),truncated:value.length>maximum}}function summarizePluginSelectionV1(selection){if(selection===void 0)return Object.freeze({present:!1,selectedCount:0,disabledCount:0,truncated:!1});let selected=boundedCount(selection.selectedPluginIds,MAX_SELECTION_IDS),disabled=boundedCount(selection.disabledPluginIds,MAX_SELECTION_IDS);return Object.freeze({present:!0,selectedCount:selected.count,disabledCount:disabled.count,truncated:selected.truncated||disabled.truncated})}function summarizePluginCatalogV1(catalog){if(catalog===void 0)return Object.freeze({present:!1,entryCount:0,readyCount:0,unavailableCount:0,truncated:!1});let entries=catalog.entries.slice(0,MAX_CATALOG_ENTRIES),readyCount=entries.filter(entry=>entry.resolution.status==="installed-ready").length;return Object.freeze({present:!0,entryCount:entries.length,readyCount,unavailableCount:entries.length-readyCount,truncated:catalog.truncated||catalog.entries.length>MAX_CATALOG_ENTRIES})}function validateProfileId(profileId){if(typeof profileId!="string"||profileId.trim().length===0||profileId.length>MAX_PROFILE_ID_CHARS||/[\u0000-\u001f]/u.test(profileId))throw new Error("invalid plugin selection profile ID");return profileId}function emptySelectionSummary(){return Object.freeze({present:!1,selectedCount:0,disabledCount:0,truncated:!1})}function diagnosticCodes2(result){return result.status==="ok"||result.status==="missing"?Object.freeze([]):Object.freeze(result.diagnostics.slice(0,MAX_DIAGNOSTIC_CODES2).map(item=>item.code))}function selectionForProfile2(result,profileId){return result.snapshot.selections.find(selection=>selection.profileId===profileId)}var PluginSelectionEntryComponent=class{profileId;store;controller;onOpen;onClose;requestRender;selection;catalog;uiProfile;uiPluginIndex=0;_focused=!1;get focused(){return this._focused}set focused(value){this._focused=value}constructor(options){if(this.profileId=validateProfileId(options.profileId),options.selection!==void 0&&options.selection.profileId!==this.profileId)throw new Error("plugin selection profile does not match the entry profile");this.store=options.store,this.controller=options.controller,this.onOpen=options.onOpen,this.onClose=options.onClose,this.requestRender=options.requestRender,this.selection=summarizePluginSelectionV1(options.selection),this.catalog=summarizePluginCatalogV1(options.catalog),this.uiProfile=options.snapshot?.profiles.find(profile=>profile.profileId===this.profileId)}hasHostEntry(){return this.store!==void 0||this.controller!==void 0||this.onOpen!==void 0}render(width){if(!this.hasHostEntry())return[truncateToWidth(theme.fg("dim"," Plugins: unsupported (host selection entry not injected)"),width,"...")];if(this._focused&&this.uiProfile!==void 0){let lines=[truncateToWidth(theme.bold(` Plugins \xB7 ${this.uiProfile.profileId}`),width,"...")];for(let[index3,plugin]of this.uiProfile.plugins.entries()){let cursor=index3===this.uiPluginIndex?">":" ",state2=plugin.state==="selected"?"on":plugin.state==="disabled"?"off":"available",availability=plugin.availability==="ready"?"ready":"unavailable";lines.push(truncateToWidth(` ${cursor} [${state2}] ${plugin.pluginId} (${availability})`,width,"..."))}return lines.push(truncateToWidth(theme.fg("dim"," Enter/Space toggle \xB7 Esc close"),width,"...")),lines}let selectionText=this.selection.present?`selected ${this.selection.selectedCount}, disabled ${this.selection.disabledCount}${this.selection.truncated?", bounded":""}`:this.store===void 0?"selection pending":"selection not loaded",catalogText=this.catalog.present?`catalog ${this.catalog.entryCount} (${this.catalog.readyCount} ready, ${this.catalog.unavailableCount} unavailable${this.catalog.truncated?", bounded":""})`:"catalog unavailable",suffix=this.onOpen===void 0?"host store":"open via host callback";return[truncateToWidth(theme.fg("muted",` Plugins: profile ${this.profileId} \xB7 ${selectionText} \xB7 ${catalogText} \xB7 ${suffix}`),width,"...")]}setUiSnapshot(result){result.status==="ok"&&(this.uiProfile=result.snapshot.profiles.find(profile=>profile.profileId===this.profileId),this.uiProfile!==void 0&&(this.uiPluginIndex=Math.min(this.uiPluginIndex,Math.max(0,this.uiProfile.plugins.length-1))))}currentUiPlugin(){return this.uiProfile?.plugins[this.uiPluginIndex]}handleInput(data){if(!this._focused||this.uiProfile===void 0)return;let keybindings=getKeybindings();if(keybindings.matches(data,"tui.select.up")){this.uiPluginIndex=Math.max(0,this.uiPluginIndex-1),this.requestRender?.();return}if(keybindings.matches(data,"tui.select.down")){this.uiPluginIndex=Math.min(this.uiProfile.plugins.length-1,this.uiPluginIndex+1),this.requestRender?.();return}if(keybindings.matches(data,"tui.select.cancel")){this._focused=!1,this.onClose?.(),this.requestRender?.();return}if(!keybindings.matches(data,"tui.select.confirm")&&data!==" ")return;let plugin=this.currentUiPlugin();plugin===void 0||this.controller===void 0||plugin.state==="disabled"&&plugin.availability!=="ready"||this.controller.toggle({profileId:this.profileId,pluginId:plugin.pluginId}).then(result=>{this.setUiSnapshot(result),this.requestRender?.()}).catch(()=>this.requestRender?.())}async openPluginSelection(){let controllerResult;this.controller!==void 0&&(controllerResult=await this.controller.getSnapshot(),this.setUiSnapshot(controllerResult));let status2=this.hasHostEntry()?"ready":"unsupported",selection=this.selection,codes=Object.freeze([]);if(controllerResult?.status==="error"&&(status2=controllerResult.code==="store-cancelled"?"cancelled":"invalid"),this.store!==void 0){let result=await this.store.read();if(codes=diagnosticCodes2(result),result.status==="ok"||result.status==="missing"){let storedSelection=selectionForProfile2(result,this.profileId);selection=summarizePluginSelectionV1(storedSelection),status2=result.status==="ok"?"ready":"missing"}else selection=emptySelectionSummary(),status2=result.status;this.selection=selection}let context=Object.freeze({profileId:this.profileId,status:status2,selection,catalog:this.catalog,diagnosticCodes:codes});return this.onOpen!==void 0&&await this.onOpen(context),context}invalidate(){}getSelectionSummary(){return this.selection}getCatalogSummary(){return this.catalog}};var RESOURCE_TYPES2=["skills","prompts","themes"],RESOURCE_TYPE_LABELS={skills:"Skills",prompts:"Prompts",themes:"Themes"};function formatBaseDir(baseDir){let homeDir=homedir10(),displayPath;return baseDir===homeDir?displayPath="~":baseDir.startsWith(homeDir)?displayPath=`~${baseDir.slice(homeDir.length).replace(/\\/g,"/")}`:displayPath=baseDir.replace(/\\/g,"/"),displayPath.endsWith("/")?displayPath:`${displayPath}/`}function getGroupLabel(metadata,agentDir){return metadata.origin==="package"?`${metadata.source} (${metadata.scope})`:metadata.source==="auto"?metadata.baseDir?metadata.scope==="user"?`User (${formatBaseDir(metadata.baseDir)})`:`Project (${formatBaseDir(metadata.baseDir)})`:metadata.scope==="user"?`User (${formatBaseDir(agentDir)})`:`Project (${CONFIG_DIR_NAME}/)`:metadata.scope==="user"?"User settings":"Project settings"}function buildGroups(resolved,agentDir){let groupMap=new Map,addToGroup=(resources,resourceType)=>{for(let res of resources){let{path:path15,enabled,metadata}=res,groupKey2=`${metadata.origin}:${metadata.scope}:${metadata.source}:${metadata.baseDir??""}`;groupMap.has(groupKey2)||groupMap.set(groupKey2,{key:groupKey2,label:getGroupLabel(metadata,agentDir),scope:metadata.scope,origin:metadata.origin,source:metadata.source,subgroups:[]});let group=groupMap.get(groupKey2),subgroupKey=`${groupKey2}:${resourceType}`,subgroup=group.subgroups.find(sg=>sg.type===resourceType);subgroup||(subgroup={type:resourceType,label:RESOURCE_TYPE_LABELS[resourceType],items:[]},group.subgroups.push(subgroup));let fileName=basename16(path15),parentFolder=basename16(dirname31(path15)),displayName;resourceType==="skills"&&fileName==="SKILL.md"?displayName=parentFolder:displayName=fileName,subgroup.items.push({path:path15,enabled,metadata,resourceType,displayName,groupKey:groupKey2,subgroupKey})}};addToGroup(resolved.skills,"skills"),addToGroup(resolved.prompts,"prompts"),addToGroup(resolved.themes,"themes");let groups=Array.from(groupMap.values());groups.sort((a,b2)=>a.origin!==b2.origin?a.origin==="package"?-1:1:a.scope!==b2.scope?a.scope==="user"?-1:1:a.source.localeCompare(b2.source));let typeOrder={skills:0,prompts:1,themes:2};for(let group of groups){group.subgroups.sort((a,b2)=>typeOrder[a.type]-typeOrder[b2.type]);for(let subgroup of group.subgroups)subgroup.items.sort((a,b2)=>a.displayName.localeCompare(b2.displayName))}return groups}var ConfigSelectorHeader=class{writeScope;projectModeAvailable;constructor(writeScope,projectModeAvailable){this.writeScope=writeScope,this.projectModeAvailable=projectModeAvailable}setWriteScope(writeScope){this.writeScope=writeScope}invalidate(){}render(width){let title=theme.bold(this.writeScope==="project"?"Project Local Resources":"Global Resources"),sep15=theme.fg("muted"," \xB7 "),switchHint=this.projectModeAvailable?keyHint("tui.input.tab","switch mode")+sep15:"",actionHint=this.writeScope==="project"?rawKeyHint("space","cycle inherit/+/-"):rawKeyHint("space","toggle"),hint=switchHint+actionHint+sep15+rawKeyHint("esc","close"),spacing=Math.max(1,width-visibleWidth(title)-visibleWidth(hint)),scopeHint=this.writeScope==="project"?theme.fg("muted",`${CONFIG_DIR_NAME}/settings.json \xB7 inherited global resources are dimmed`):theme.fg("muted",`~/${CONFIG_DIR_NAME}/agent/settings.json`);return[truncateToWidth(`${title}${" ".repeat(spacing)}${hint}`,width,""),truncateToWidth(scopeHint,width,"")]}},ResourceList=class{groupsByScope;flatItems=[];filteredItems=[];selectedIndex=0;searchInput;maxVisible;settingsManager;cwd;agentDir;writeScope;inheritedEnabledByKey;pluginSelectionEntry;pluginManagerEntry;pluginManagerScope;onCancel;onExit;onToggle;onSwitchMode;_focused=!1;get focused(){return this._focused}set focused(value){this._focused=value,this.searchInput.focused=value}constructor(groupsByScope,settingsManager,cwd,agentDir,terminalHeight,writeScope="global",pluginSelectionEntry,pluginManagerEntry,pluginManagerScope="global"){this.groupsByScope=groupsByScope,this.settingsManager=settingsManager,this.cwd=cwd,this.agentDir=agentDir,this.writeScope=writeScope,this.pluginSelectionEntry=pluginSelectionEntry,this.pluginManagerEntry=pluginManagerEntry,this.pluginManagerScope=pluginManagerScope,this.inheritedEnabledByKey=this.buildInheritedEnabledMap(groupsByScope.global),this.searchInput=new Input;let chrome=8;this.maxVisible=Math.max(5,(terminalHeight??24)-chrome),this.buildFlatList(),this.filteredItems=[...this.flatItems]}setWriteScope(writeScope){this.writeScope=writeScope,this.buildFlatList(),this.filterItems(this.searchInput.getValue())}get groups(){return this.groupsByScope[this.writeScope]}buildInheritedEnabledMap(groups){let result=new Map;for(let group of groups)for(let subgroup of group.subgroups)for(let item of subgroup.items)result.set(this.getResourceItemKey(item),item.enabled);return result}buildFlatList(){this.flatItems=[];for(let group of this.groups){this.flatItems.push({type:"group",group});for(let subgroup of group.subgroups){this.flatItems.push({type:"subgroup",subgroup,group});for(let item of subgroup.items)this.flatItems.push({type:"item",item})}}this.pluginSelectionEntry!==void 0&&this.flatItems.push({type:"plugin",entry:this.pluginSelectionEntry}),this.pluginManagerEntry!==void 0&&this.writeScope===this.pluginManagerScope&&this.flatItems.push({type:"plugin-manager",entry:this.pluginManagerEntry}),this.selectedIndex=this.flatItems.findIndex(e=>e.type==="item"||e.type==="plugin"||e.type==="plugin-manager"),this.selectedIndex<0&&(this.selectedIndex=0)}findNextItem(fromIndex,direction){let idx=fromIndex+direction;for(;idx>=0&&idx<this.filteredItems.length;){if(this.filteredItems[idx].type==="item"||this.filteredItems[idx].type==="plugin"||this.filteredItems[idx].type==="plugin-manager")return idx;idx+=direction}return fromIndex}filterItems(query){if(!query.trim()){this.filteredItems=[...this.flatItems],this.selectFirstItem();return}let lowerQuery=query.toLowerCase(),matchingItems=new Set,matchingSubgroups=new Set,matchingGroups=new Set;for(let entry of this.flatItems)if(entry.type==="item"){let item=entry.item;(item.displayName.toLowerCase().includes(lowerQuery)||item.resourceType.toLowerCase().includes(lowerQuery)||item.path.toLowerCase().includes(lowerQuery))&&matchingItems.add(item)}for(let group of this.groups)for(let subgroup of group.subgroups)for(let item of subgroup.items)matchingItems.has(item)&&(matchingSubgroups.add(subgroup),matchingGroups.add(group));this.filteredItems=[];for(let entry of this.flatItems)entry.type==="group"&&matchingGroups.has(entry.group)?this.filteredItems.push(entry):entry.type==="subgroup"&&matchingSubgroups.has(entry.subgroup)?this.filteredItems.push(entry):entry.type==="item"&&matchingItems.has(entry.item)&&this.filteredItems.push(entry);this.selectFirstItem()}selectFirstItem(){let firstItemIndex=this.filteredItems.findIndex(e=>e.type==="item"||e.type==="plugin"||e.type==="plugin-manager");this.selectedIndex=firstItemIndex>=0?firstItemIndex:0}updateItem(item,enabled){item.enabled=enabled;for(let group of this.groups)for(let subgroup of group.subgroups){let found=subgroup.items.find(i=>i.path===item.path&&i.resourceType===item.resourceType);if(found){found.enabled=enabled;return}}}invalidate(){}render(width){let lines=[];if(lines.push(...this.searchInput.render(width)),lines.push(""),this.filteredItems.length===0)return lines.push(theme.fg("muted"," No resources found")),lines;let startIndex=Math.max(0,Math.min(this.selectedIndex-Math.floor(this.maxVisible/2),this.filteredItems.length-this.maxVisible)),endIndex=Math.min(startIndex+this.maxVisible,this.filteredItems.length);for(let i=startIndex;i<endIndex;i++){let entry=this.filteredItems[i],isSelected=i===this.selectedIndex;if(entry.type==="group"){let inherited=this.writeScope==="project"&&entry.group.scope==="user",label=theme.bold(`${entry.group.label}${inherited?" \xB7 inherited global":""}`),groupLine=theme.fg(inherited?"dim":"accent",label);lines.push(truncateToWidth(` ${groupLine}`,width,""))}else if(entry.type==="subgroup"){let color=this.writeScope==="project"&&entry.group.scope==="user"?"dim":"muted",subgroupLine=theme.fg(color,entry.subgroup.label);lines.push(truncateToWidth(` ${subgroupLine}`,width,""))}else if(entry.type==="plugin"){let prefix=isSelected?"> ":" ";for(let line of entry.entry.render(width))lines.push(truncateToWidth(`${prefix}${line.trimStart()}`,width,"..."))}else if(entry.type==="plugin-manager"){let prefix=isSelected?"> ":" ";for(let line of entry.entry.render(width))lines.push(truncateToWidth(`${prefix}${line.trimStart()}`,width,"..."))}else{let item=entry.item,cursor=isSelected?"> ":" ",dimmed=this.isDimmedItem(item),nameText=isSelected&&!dimmed?theme.bold(item.displayName):item.displayName,name=dimmed?theme.fg("dim",nameText):nameText;lines.push(truncateToWidth(`${cursor} ${this.renderCheckbox(item)} ${name}${this.getItemSuffix(item)}`,width,"..."))}}if(startIndex>0||endIndex<this.filteredItems.length){let itemCount=this.filteredItems.filter(e=>e.type==="item"||e.type==="plugin"||e.type==="plugin-manager").length,currentItemIndex=this.filteredItems.slice(0,this.selectedIndex).filter(e=>e.type==="item"||e.type==="plugin"||e.type==="plugin-manager").length+1;lines.push(theme.fg("dim",` (${currentItemIndex}/${itemCount})`))}return lines}handleInput(data){let kb=getKeybindings();if(this.pluginSelectionEntry?.focused===!0){this.pluginSelectionEntry.handleInput(data);return}if(this.pluginManagerEntry?.focused===!0){this.pluginManagerEntry.handleInput(data);return}if(kb.matches(data,"tui.select.up")){this.selectedIndex=this.findNextItem(this.selectedIndex,-1);return}if(kb.matches(data,"tui.select.down")){this.selectedIndex=this.findNextItem(this.selectedIndex,1);return}if(kb.matches(data,"tui.select.pageUp")){let target=Math.max(0,this.selectedIndex-this.maxVisible);for(;target<this.filteredItems.length&&this.filteredItems[target].type!=="item"&&this.filteredItems[target].type!=="plugin"&&this.filteredItems[target].type!=="plugin-manager";)target++;target<this.filteredItems.length&&(this.selectedIndex=target);return}if(kb.matches(data,"tui.select.pageDown")){let target=Math.min(this.filteredItems.length-1,this.selectedIndex+this.maxVisible);for(;target>=0&&this.filteredItems[target].type!=="item"&&this.filteredItems[target].type!=="plugin"&&this.filteredItems[target].type!=="plugin-manager";)target--;target>=0&&(this.selectedIndex=target);return}if(kb.matches(data,"tui.select.cancel")){this.onCancel?.();return}if(kb.matches(data,"app.config.exit")){this.onExit?.();return}if(kb.matches(data,"tui.input.tab")){this.onSwitchMode?.();return}if(data===" "||kb.matches(data,"tui.select.confirm")){let entry=this.filteredItems[this.selectedIndex];if(entry?.type==="plugin"&&this.writeScope==="global"){entry.entry.focused=!0,entry.entry.openPluginSelection();return}if(entry?.type==="plugin-manager"&&this.writeScope===this.pluginManagerScope){entry.entry.focused=!0,entry.entry.openPluginManager();return}if(entry?.type==="item"&&(this.writeScope==="project"||this.getItemScope(entry.item)==="user")){let newEnabled=this.toggleResource(entry.item);newEnabled!==void 0&&(this.updateItem(entry.item,newEnabled),this.onToggle?.(entry.item,newEnabled))}return}this.searchInput.handleInput(data),this.filterItems(this.searchInput.getValue())}toggleResource(item){if(this.writeScope==="project"){let state2=this.getNextOverrideState(item);return this.setProjectResourceOverride(item,state2)?state2==="inherit"?this.getInheritedEnabled(item):state2==="load":void 0}let enabled=!item.enabled;return item.metadata.origin==="top-level"?this.toggleTopLevelResource(item,enabled):this.togglePackageResource(item,enabled),enabled}toggleTopLevelResource(item,enabled){let scope=item.metadata.scope,settings2=scope==="project"?this.settingsManager.getProjectSettings():this.settingsManager.getGlobalSettings(),arrayKey=item.resourceType,current=settings2[arrayKey]??[],pattern=this.getResourcePattern(item),disablePattern=`-${pattern}`,enablePattern=`+${pattern}`,updated=current.filter(p=>(p.startsWith("!")||p.startsWith("+")||p.startsWith("-")?p.slice(1):p)!==pattern);enabled?updated.push(enablePattern):updated.push(disablePattern),scope==="project"?arrayKey==="skills"?this.settingsManager.setProjectSkillPaths(updated):arrayKey==="prompts"?this.settingsManager.setProjectPromptTemplatePaths(updated):arrayKey==="themes"&&this.settingsManager.setProjectThemePaths(updated):arrayKey==="skills"?this.settingsManager.setSkillPaths(updated):arrayKey==="prompts"?this.settingsManager.setPromptTemplatePaths(updated):arrayKey==="themes"&&this.settingsManager.setThemePaths(updated)}togglePackageResource(item,enabled){let scope=item.metadata.scope,packages=[...(scope==="project"?this.settingsManager.getProjectSettings():this.settingsManager.getGlobalSettings()).packages??[]],pkgIndex=packages.findIndex(pkg3=>(typeof pkg3=="string"?pkg3:pkg3.source)===item.metadata.source);if(pkgIndex===-1)return;let pkg2=packages[pkgIndex];typeof pkg2=="string"&&(pkg2={source:pkg2},packages[pkgIndex]=pkg2);let arrayKey=item.resourceType,current=pkg2[arrayKey]??[],pattern=this.getPackageResourcePattern(item),disablePattern=`-${pattern}`,enablePattern=`+${pattern}`,updated=current.filter(p=>(p.startsWith("!")||p.startsWith("+")||p.startsWith("-")?p.slice(1):p)!==pattern);enabled?updated.push(enablePattern):updated.push(disablePattern),pkg2[arrayKey]=updated.length>0?updated:void 0,["skills","prompts","themes"].some(k=>pkg2[k]!==void 0)||(packages[pkgIndex]=pkg2.source),scope==="project"?this.settingsManager.setProjectPackages(packages):this.settingsManager.setPackages(packages)}renderCheckbox(item){if(this.writeScope==="project"){let state2=this.getProjectOverrideState(item);return state2==="load"?theme.fg("success","[+]"):state2==="unload"?theme.fg("warning","[-]"):theme.fg("dim",item.enabled?"[x]":"[ ]")}return item.enabled?theme.fg("success","[x]"):theme.fg("dim","[ ]")}getItemSuffix(item){if(this.writeScope!=="project")return"";let state2=this.getProjectOverrideState(item);return state2==="load"?theme.fg("muted"," project load"):state2==="unload"?theme.fg("muted"," project unload"):this.isInheritedGlobalItem(item)?theme.fg("dim"," inherited global"):""}isDimmedItem(item){return this.writeScope==="project"&&this.isInheritedGlobalItem(item)&&this.getProjectOverrideState(item)==="inherit"}setProjectResourceOverride(item,state2){return item.metadata.origin==="top-level"?this.setProjectTopLevelOverride(item,state2):this.setProjectPackageOverride(item,state2)}setProjectTopLevelOverride(item,state2){let current=this.settingsManager.getProjectSettings()[item.resourceType]??[],pattern=this.isInheritedGlobalItem(item)?item.path:this.getResourcePatternForScope(item,"project"),patterns=this.getTopLevelOverridePatterns(item,"project"),updated=current.filter(entry=>{let target=this.getPatternEntryTarget(entry);return(entry.startsWith("!")||entry.startsWith("+")||entry.startsWith("-"))&&patterns.has(target)?!1:!(state2==="inherit"&&this.isInheritedGlobalItem(item)&&target===pattern)});return state2!=="inherit"&&(this.isInheritedGlobalItem(item)&&!updated.includes(pattern)&&updated.push(pattern),updated.push(`${state2==="load"?"+":"-"}${pattern}`)),this.setProjectTopLevelPaths(item.resourceType,updated),!0}setProjectTopLevelPaths(key,paths){key==="skills"?this.settingsManager.setProjectSkillPaths(paths):key==="prompts"?this.settingsManager.setProjectPromptTemplatePaths(paths):this.settingsManager.setProjectThemePaths(paths)}setProjectPackageOverride(item,state2){let packages=[...this.settingsManager.getProjectSettings().packages??[]],pkgIndex=packages.findIndex(pkg3=>this.packageSourceStringMatches(item.metadata.source,this.getItemScope(item),typeof pkg3=="string"?pkg3:pkg3.source,"project"));if(pkgIndex===-1){if(state2==="inherit")return!1;packages.push(this.createPackageOverrideSource(item)),pkgIndex=packages.length-1}let pkg2=packages[pkgIndex];if(pkg2===void 0)return!1;typeof pkg2=="string"&&(pkg2={source:pkg2},packages[pkgIndex]=pkg2);let pattern=this.getPackageResourcePattern(item),updated=(pkg2[item.resourceType]??[]).filter(entry=>this.getPatternEntryTarget(entry)!==pattern);return state2!=="inherit"&&updated.push(`${state2==="load"?"+":"-"}${pattern}`),pkg2[item.resourceType]=updated.length>0?updated:void 0,RESOURCE_TYPES2.some(key=>pkg2[key]!==void 0)||(pkg2.autoload===!1?packages.splice(pkgIndex,1):packages[pkgIndex]=pkg2.source),this.settingsManager.setProjectPackages(packages),!0}getNextOverrideState(item){let state2=this.getProjectOverrideState(item),inheritedEnabled=this.getInheritedEnabled(item);return state2==="inherit"?inheritedEnabled?"unload":"load":state2==="unload"?inheritedEnabled?"load":"inherit":inheritedEnabled?"inherit":"unload"}getProjectOverrideState(item){if(this.writeScope!=="project")return"inherit";if(item.metadata.origin==="top-level")return this.getOverrideStateFromEntries(this.settingsManager.getProjectSettings()[item.resourceType]??[],this.getTopLevelOverridePatterns(item,"project"),!1);let pkg2=this.findMatchingPackageSource(item,"project");if(typeof pkg2!="object")return"inherit";let entries=pkg2[item.resourceType];return entries===void 0?"inherit":this.getOverrideStateFromEntries(entries,new Set([this.getPackageResourcePattern(item)]),pkg2.autoload!==!1)}getOverrideStateFromEntries(entries,patterns,emptyArrayIsUnload){if(entries.length===0&&emptyArrayIsUnload)return"unload";let state2="inherit";for(let entry of entries)patterns.has(this.getPatternEntryTarget(entry))&&(entry.startsWith("!")||entry.startsWith("-")?state2="unload":state2="load");return state2}getInheritedEnabled(item){return this.inheritedEnabledByKey.get(this.getResourceItemKey(item))??(this.getItemScope(item)==="user"?item.enabled:!0)}isInheritedGlobalItem(item){return this.getItemScope(item)==="user"||this.inheritedEnabledByKey.has(this.getResourceItemKey(item))}getTopLevelOverridePatterns(item,scope){let baseDir=this.getTopLevelBaseDir(scope),patterns=new Set([this.getResourcePatternForScope(item,scope),item.path,relative12(baseDir,item.path)]);return item.metadata.baseDir&&patterns.add(relative12(item.metadata.baseDir,item.path)),patterns}getResourcePatternForScope(item,scope){let sourceScope=this.getItemScope(item);if(scope!==sourceScope)return item.path;let baseDir=item.metadata.baseDir??this.getTopLevelBaseDir(sourceScope);return relative12(baseDir,item.path)}createPackageOverrideSource(item){let source=item.metadata.source;if(!isLocalPath(source))return{source,autoload:!1};let sourcePath=resolvePath(source,this.getTopLevelBaseDir(this.getItemScope(item)),{trim:!0});return{source:relative12(this.getTopLevelBaseDir("project"),sourcePath)||".",autoload:!1}}packageSourceStringMatches(leftSource,leftScope,rightSource,rightScope){if(leftSource===rightSource)return!0;if(!isLocalPath(leftSource)||!isLocalPath(rightSource))return!1;let left=resolvePath(leftSource,this.getTopLevelBaseDir(leftScope),{trim:!0}),right=resolvePath(rightSource,this.getTopLevelBaseDir(rightScope),{trim:!0});return left===right}findMatchingPackageSource(item,targetScope){return((targetScope==="project"?this.settingsManager.getProjectSettings():this.settingsManager.getGlobalSettings()).packages??[]).find(pkg2=>this.packageSourceStringMatches(item.metadata.source,this.getItemScope(item),typeof pkg2=="string"?pkg2:pkg2.source,targetScope))}getPatternEntryTarget(entry){return entry.startsWith("!")||entry.startsWith("+")||entry.startsWith("-")?entry.slice(1):entry}getResourceItemKey(item){return`${item.resourceType}:${canonicalizePath(item.path)}`}getItemScope(item){return item.metadata.scope==="project"?"project":"user"}getTopLevelBaseDir(scope){return scope==="project"?join65(this.cwd,CONFIG_DIR_NAME):this.agentDir}getResourcePattern(item){let scope=item.metadata.scope,baseDir=item.metadata.baseDir??this.getTopLevelBaseDir(scope);return relative12(baseDir,item.path)}getPackageResourcePattern(item){let baseDir=item.metadata.baseDir??dirname31(item.path);return relative12(baseDir,item.path)}},ConfigSelectorComponent=class extends Container{header;resourceList;pluginSelectionEntry;pluginManagerEntry;writeScope;_focused=!1;get focused(){return this._focused}set focused(value){this._focused=value,this.resourceList.focused=value}constructor(resolvedPaths,settingsManager,cwd,agentDir,onClose,onExit,requestRender,terminalHeight,writeScope="global",projectModeAvailable=!0,pluginSelection,pluginManager,pluginManagerScope="global"){super(),this.writeScope=writeScope;let groupsByScope={global:buildGroups(resolvedPaths.global,agentDir),project:buildGroups(resolvedPaths.project,agentDir)},pluginSelectionEntry=pluginSelection===void 0?void 0:new PluginSelectionEntryComponent({...pluginSelection,onClose:()=>{pluginSelection.onClose?.()},requestRender});this.pluginSelectionEntry=pluginSelectionEntry;let pluginManagerEntry=pluginManager===void 0?void 0:new PluginManagerEntryComponent({...pluginManager,onClose:()=>{pluginManager.onClose?.()},requestRender});this.pluginManagerEntry=pluginManagerEntry,this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.header=new ConfigSelectorHeader(this.writeScope,projectModeAvailable),this.addChild(this.header),this.addChild(new Spacer(1)),this.resourceList=new ResourceList(groupsByScope,settingsManager,cwd,agentDir,terminalHeight===void 0?void 0:Math.max(5,terminalHeight-(pluginSelection===void 0?0:2)-(pluginManager===void 0?0:2)),this.writeScope,pluginSelectionEntry,pluginManagerEntry,pluginManagerScope),this.resourceList.onCancel=onClose,this.resourceList.onExit=onExit,this.resourceList.onToggle=()=>requestRender(),projectModeAvailable&&(this.resourceList.onSwitchMode=()=>{this.switchWriteScope(),requestRender()}),this.addChild(this.resourceList),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder)}switchWriteScope(){this.writeScope=this.writeScope==="global"?"project":"global",this.header.setWriteScope(this.writeScope),this.resourceList.setWriteScope(this.writeScope)}getResourceList(){return this.resourceList}getPluginSelectionEntry(){return this.pluginSelectionEntry}getPluginManagerEntry(){return this.pluginManagerEntry}async openPluginSelection(){return this.pluginSelectionEntry===void 0?void 0:await this.pluginSelectionEntry.openPluginSelection()}async openPluginManager(){return this.pluginManagerEntry===void 0?void 0:await this.pluginManagerEntry.openPluginManager()}};async function selectConfig(options){initTheme(options.settingsManager.getTheme(),!0);let pluginSnapshot=options.pluginSelectionController?await options.pluginSelectionController.getSnapshot():void 0,pluginManagerSnapshot=options.pluginManagerController?await options.pluginManagerController.getSnapshot():void 0;return new Promise(resolve25=>{let ui=new TuiMainScreen(new ProcessTerminal,void 0,options.agentDir),resolved=!1,selector=new ConfigSelectorComponent(options.resolvedPaths,options.settingsManager,options.cwd,options.agentDir,()=>{resolved||(resolved=!0,ui.stop(),stopThemeWatcher(),resolve25())},()=>{ui.stop(),stopThemeWatcher(),process.exit(0)},()=>ui.requestRender(),ui.terminal.rows,options.writeScope,options.projectModeAvailable,options.pluginSelectionController===void 0?void 0:{profileId:options.pluginSelectionProfileId??"coding-core",controller:options.pluginSelectionController,snapshot:pluginSnapshot?.status==="ok"?pluginSnapshot.snapshot:void 0,onOpen:()=>ui.requestRender(),requestRender:()=>ui.requestRender()},options.pluginManagerController===void 0?void 0:{controller:options.pluginManagerController,snapshot:pluginManagerSnapshot?.status==="ok"?pluginManagerSnapshot.snapshot:void 0,requestRender:()=>ui.requestRender()},options.pluginManagerScope);ui.addChild(selector),ui.setFocus(selector.getResourceList()),ui.start()})}import{randomUUID as randomUUID21}from"node:crypto";import{copyFileSync as copyFileSync2,existsSync as existsSync32,mkdirSync as mkdirSync21,renameSync as renameSync5,rmSync as rmSync7}from"node:fs";import{basename as basename17,dirname as dirname32,join as join66,relative as relative13,resolve as resolve23,toNamespacedPath}from"node:path";var QUARANTINE_DIR_NAME=".agent-forge-native-quarantine";function normalizePath2(path15){return toNamespacedPath(resolve23(path15))}function getQuarantineRoot(packageDir){let current=resolve23(packageDir);for(;;){if(basename17(current).toLowerCase()==="node_modules")return join66(current,QUARANTINE_DIR_NAME);let parent=dirname32(current);if(parent===current)return;current=parent}}function getLoadedSharedObjectsInPackageDir(packageDir){let sharedObjects=process.report.getReport().sharedObjects;if(!Array.isArray(sharedObjects))return[];let root=normalizePath2(packageDir).toLowerCase(),seen=new Set,loadedFiles=[];for(let value of sharedObjects){if(typeof value!="string")continue;let filePath=normalizePath2(value),comparisonPath=filePath.toLowerCase();getCwdRelativePath(comparisonPath,root)===void 0||seen.has(comparisonPath)||(seen.add(comparisonPath),loadedFiles.push(filePath))}return loadedFiles}function cleanupWindowsSelfUpdateQuarantine(packageDir){let quarantineRoot=getQuarantineRoot(packageDir);if(quarantineRoot)try{rmSync7(quarantineRoot,{recursive:!0,force:!0})}catch{}}function quarantineWindowsNativeDependencies(packageDir){let resolvedPackageDir=normalizePath2(packageDir),quarantineRoot=getQuarantineRoot(resolvedPackageDir);if(!quarantineRoot)return;let loadedFiles=getLoadedSharedObjectsInPackageDir(resolvedPackageDir);if(loadedFiles.length===0)return;let quarantineRunDir=join66(quarantineRoot,`${Date.now()}-${process.pid}-${randomUUID21()}`);for(let loadedFile of loadedFiles){if(!existsSync32(loadedFile))continue;let quarantinePath=join66(quarantineRunDir,relative13(resolvedPackageDir,loadedFile));mkdirSync21(dirname32(quarantinePath),{recursive:!0}),renameSync5(loadedFile,quarantinePath),copyFileSync2(quarantinePath,loadedFile)}}var MANAGED_INSTALL_MARKER="managed-install.json",MANAGED_RELEASE_VERSION_RE=/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;function getActiveManagedInstallRoot(){let configuredRoot=process.env.AGENT_FORGE_MANAGED_INSTALL_ROOT?.trim();if(!configuredRoot)return;let managedRoot=resolve24(configuredRoot),releasesDir=canonicalizePath(join67(managedRoot,"releases"));if(getCwdRelativePath(canonicalizePath(getPackageDir()),releasesDir)===void 0)return;let markerPath=join67(managedRoot,MANAGED_INSTALL_MARKER);try{let marker=JSON.parse(readFileSync28(markerPath,"utf8"));if(marker.kind!=="agent-forge-managed-install"||marker.schemaVersion!==1||marker.layout!=="releases-v1")throw new Error}catch{throw new Error(`Managed install marker is missing or invalid: ${markerPath}`)}return managedRoot}async function fetchInstallerArtifact(url,label){let response2=await fetch(url,{headers:{"User-Agent":getAgentForgeUserAgent(VERSION)}});if(!response2.ok)throw new Error(`Could not download managed installer ${label} from ${url}: HTTP ${response2.status}`);return await response2.text()}async function runManagedNpmCi(stageDir){let args=["ci","--ignore-scripts","--min-release-age=0","--omit=dev","--include=optional","--no-fund","--no-audit","--loglevel=error","--progress=false"],code=await waitForChildProcess(spawnProcess("npm",args,{cwd:stageDir,stdio:"inherit"}));if(code!==0)throw new Error(`npm ${args.join(" ")} exited with code ${code??"unknown"}`)}function verifyManagedRelease(releaseDir,expectedVersion){let binPath=join67(releaseDir,"node_modules",".bin",process.platform==="win32"?`${APP_NAME}.cmd`:APP_NAME),result=spawnProcessSync(binPath,["--version"],{encoding:"utf8",stdio:["ignore","pipe","pipe"]});if(result.error||result.status!==0){let reason=result.error?.message||result.stderr.trim()||`exit code ${result.status??"unknown"}`;throw new Error(`Could not verify managed ${APP_NAME} ${expectedVersion}: ${reason}`)}let installedVersion=result.stdout.trim();if(installedVersion!==expectedVersion)throw new Error(`Managed ${APP_NAME} smoke test returned version ${installedVersion}; expected ${expectedVersion}.`)}async function activateStagedRelease(stageDir,releaseDir){for(let attempt2=0;;attempt2++)try{renameSync6(stageDir,releaseDir);return}catch(error2){if(attempt2>=9||!existsSync33(stageDir))throw error2;await sleep3(1e3)}}function activateManagedRelease(managedRoot,version){let currentPath=join67(managedRoot,"current-version"),temporaryPath=join67(managedRoot,`current-version.tmp.${process.pid}-${Date.now()}`);try{writeFileSync18(temporaryPath,`${version}
|