@ai-agent-forge/agent-forge 0.88.3 → 0.88.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/bundled-plugins/agent-loop-policy/agent-forge.json +1 -1
- package/bundled-plugins/agent-loop-policy/plugin.json +1 -1
- package/bundled-plugins/coding-tools/agent-forge.json +1 -1
- package/bundled-plugins/coding-tools/plugin.json +1 -1
- package/bundled-plugins/compaction-policy/agent-forge.json +1 -1
- package/bundled-plugins/compaction-policy/plugin.json +1 -1
- package/bundled-plugins/overflow-policy/agent-forge.json +1 -1
- package/bundled-plugins/overflow-policy/plugin.json +1 -1
- package/bundled-plugins/provider-failover/agent-forge.json +1 -1
- package/bundled-plugins/provider-failover/plugin.json +1 -1
- package/bundled-plugins/retry-policy/agent-forge.json +1 -1
- package/bundled-plugins/retry-policy/plugin.json +1 -1
- package/dist/bundle/.build-manifest.json +7 -7
- package/dist/bundle/chunks/{chunk-B42Y2VME.js → chunk-HEL6TAWE.js} +8 -8
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/core/extensions/capability-plugin.d.ts.map +1 -1
- package/dist/core/extensions/capability-plugin.js +15 -8
- package/dist/core/extensions/capability-plugin.js.map +1 -1
- package/dist/core/extensions/virtual-modules.d.ts.map +1 -1
- package/dist/core/extensions/virtual-modules.js +8 -5
- package/dist/core/extensions/virtual-modules.js.map +1 -1
- package/dist/plugins/ecosystem/node-package-install-host.d.ts +9 -1
- package/dist/plugins/ecosystem/node-package-install-host.d.ts.map +1 -1
- package/dist/plugins/ecosystem/node-package-install-host.js +79 -0
- package/dist/plugins/ecosystem/node-package-install-host.js.map +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/extensions/with-deps/plugin.json +1 -1
- package/package.json +1 -1
|
@@ -214,7 +214,7 @@ File: ${path8}`)}let providers=new Map;for(let[providerId,provider]of Object.ent
|
|
|
214
214
|
[output truncated]`,lower=0,upper=value.length;for(;lower<upper;){let middle=Math.ceil((lower+upper)/2);Buffer2.byteLength(`${value.slice(0,middle)}${suffix}`,"utf8")<=MAX_PLUGIN_ECOSYSTEM_CLI_OUTPUT_BYTES_V1?lower=middle:upper=middle-1}return`${value.slice(0,lower)}${suffix}`}function boundData(data){let list=data.entries;return!Array.isArray(list)||list.length<=MAX_PLUGIN_ECOSYSTEM_CLI_LIST_ENTRIES_V1?Object.freeze({...data}):Object.freeze({...data,entries:Object.freeze(list.slice(0,MAX_PLUGIN_ECOSYSTEM_CLI_LIST_ENTRIES_V1)),truncated:!0})}function formatText(command,status,data){if(data===void 0)return`${status}: ${command}`;let entries=data.entries;if(Array.isArray(entries)){let lines=entries.map(entry=>{if(typeof entry!="object"||entry===null)return String(entry);let item=entry,id=typeof item.profileId=="string"?`profile:${item.profileId}`:typeof item.pluginId=="string"?item.pluginId:"plugin",version=typeof item.pluginVersion=="string"?`@${item.pluginVersion}`:"",state=typeof item.status=="string"?` ${item.status}`:typeof item.lifecycle=="string"?` ${item.lifecycle}`:"",visibility=item.enabled===!1?" disabled":"";return`${id}${version}${state}${visibility}`});return[`${status}: ${command}`,...lines,...data.truncated===!0?["[output truncated]"]:[]].join(`
|
|
215
215
|
`)}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`${status}: ${command} profile:${data.profileId}${selected}${disabled}`}let note=typeof data.note=="string"?` ${data.note}`:"";return`${status}: ${command}${note}`}function safeError(code,cause){let messages={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"};return Object.freeze({code,message:cause!==void 0&&cause!==""?`${messages[code]} (${cause})`:messages[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(resolve22=>{release=resolve22}),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(error){return response("invalid",input.format==="json"?"json":"text","failed",invalidCommandError(input.argv,error))}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});if(updated.status==="cancelled")return response(parsed.command,parsed.format,"cancelled",safeError("cancelled"));if(updated.status!=="ok")return response(parsed.command,parsed.format,"failed",safeError("state_failed"));let retainedNote=parsed.command==="enable"&&record.state.lifecycle!=="active"?t("only toggles the enabled flag; the record lifecycle is {lifecycle} and the runtime will not load it",{lifecycle:record.state.lifecycle}):void 0;return response(parsed.command,parsed.format,"succeeded",void 0,{pluginId:record.pluginId,pluginVersion:record.pluginVersion,enabled,changed:updated.changed,...retainedNote===void 0?{}:{note:retainedNote}})}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",installed.status==="failed"?installed.error.message:void 0)):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 status=>{let[hostRestored,stateRestored]=await Promise.all([restoreActivatedInstallation().catch(()=>!1),restoreState().catch(()=>!1)]);return response(parsed.command,parsed.format,hostRestored&&stateRestored?status:"failed",safeError(hostRestored&&stateRestored?status==="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(error){transactionError=error}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(t("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(error){if(isCancelled(signal)||error instanceof PluginAcquisitionErrorV1&&error.code==="cancelled")return response(parsed.command,parsed.format,"cancelled",safeError("cancelled"));if(error instanceof PluginAcquisitionErrorV1)return response(parsed.command,parsed.format,"failed",{code:"acquisition_failed",message:error.message});throw error}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(error){return isCancelled(signal)||error instanceof Error&&error.message==="cancelled"?response(parsed.command,parsed.format,"cancelled",safeError("cancelled")):error instanceof Error&&error.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 join8,resolve as resolve3}from"node:path";import{open}from"node:fs/promises";import{isAbsolute as isAbsolute2,join as join6}from"node:path";import{realpathSync as realpathSync2}from"node:fs";import{basename,dirname as dirname4,isAbsolute,join as join5,relative}from"node:path";var stripDevicePrefix=value=>value.replace(/^\\\\\?\\/,""),normalizePath2=value=>{try{return stripDevicePrefix(realpathSync2.native(value))}catch{return}},normalizeWithAncestry=value=>{let missing=[],current=value;for(;;){let normalized=normalizePath2(current);if(normalized!==void 0)return missing.length===0?normalized:join5(normalized,...missing.reverse());let parent=dirname4(current);if(parent===current)return;missing.push(basename(current)),current=parent}};function withinInstallStoreRoot(root,value){if(!isAbsolute(value))return!1;let normalizedRoot=normalizeWithAncestry(root),normalizedValue=normalizeWithAncestry(value),relativePath=relative(normalizedRoot!==void 0&&normalizedValue!==void 0?normalizedRoot:root,normalizedRoot!==void 0&&normalizedValue!==void 0?normalizedValue:value);return relativePath!==""&&!relativePath.startsWith("..")&&!isAbsolute(relativePath)}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 validateRecord(root,value,index){if(value===null||typeof value!="object"||Array.isArray(value))throw new NodeDiskRegistrySourceErrorV1("invalid_index",t("Index record {index} is not an object",{index}));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",t("Index record {index} has an invalid schema",{index}));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"||!withinInstallStoreRoot(root,record.directory))throw new NodeDiskRegistrySourceErrorV1("invalid_index",t("Index record {index} is invalid",{index}));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",t("Install store index JSON is invalid"))}if(parsed===null||typeof parsed!="object"||Array.isArray(parsed))throw new NodeDiskRegistrySourceErrorV1("invalid_index",t("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",t("Install store index schema is unsupported"));if(value.records.length>MAX_NODE_DISK_REGISTRY_RECORDS_V1)throw new NodeDiskRegistrySourceErrorV1("too_many_records",t("Install store index exceeds the record limit"));return value.records.map((record,index)=>validateRecord(root,record,index))}async function readBoundedFile(path8,maxBytes,label){let handle=await open(path8,"r");try{let stat5=await handle.stat();if(!stat5.isFile()||stat5.size>maxBytes)throw new NodeDiskRegistrySourceErrorV1(label==="index"?"invalid_index":"invalid_manifest",t("{label} exceeds the size limit",{label}));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",t("Installed plugin manifest JSON is invalid"))}if(parsed===null||typeof parsed!="object"||Array.isArray(parsed))throw new NodeDiskRegistrySourceErrorV1("invalid_manifest",t("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",t("Installed plugin package format is unsupported"));if(delete value.packageFormatVersion,value.id!==record.pluginId||value.pluginVersion!==record.pluginVersion)throw new NodeDiskRegistrySourceErrorV1("identity_mismatch",t("Installed plugin manifest identity does not match index record for {identity}",{identity:`${record.pluginId}@${record.pluginVersion}`}));return value}async function readIndexRecords(rootDirectory,signal){if(signal?.aborted)throw new NodeDiskRegistrySourceErrorV1("cancelled",t("Disk registry source read was cancelled"));let rawIndex;try{rawIndex=await readBoundedFile(join6(rootDirectory,INDEX_FILE_V1),MAX_NODE_DISK_REGISTRY_INDEX_BYTES_V1,"index")}catch(error){if(error instanceof NodeDiskRegistrySourceErrorV1)throw error;if(error instanceof Error&&"code"in error&&error.code==="ENOENT")return;throw new NodeDiskRegistrySourceErrorV1("io_failed",t("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",t("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",t("Disk registry source read was cancelled"));let rawManifest;try{rawManifest=await readBoundedFile(join6(record.directory,ECOSYSTEM_MANIFEST_FILE_V1),MAX_NODE_DISK_REGISTRY_MANIFEST_BYTES_V1,"manifest")}catch(error){throw error instanceof NodeDiskRegistrySourceErrorV1?error:new NodeDiskRegistrySourceErrorV1("io_failed",t("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=join6(record.directory,CAPABILITY_MANIFEST_FILE_V1);try{await(await open(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(t(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(error,signal){return signal?.aborted===!0||error instanceof Error&&(error.name==="AbortError"||error.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(error){isCancelled2(error,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(error){if(acquired!==void 0&&options.host.releaseArtifact!==void 0&&await options.host.releaseArtifact({artifact:acquired}).catch(()=>{}),error instanceof PluginDistributionErrorV1)throw error;isCancelled2(error,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(error){isCancelled2(error,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(error,signal){return signal?.aborted===!0||error instanceof Error&&(error.name==="AbortError"||error.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,t("{label} must be a non-empty bounded string",{label}));return value}function assertAllowedKeys(value,allowed,label){let expected=new Set(allowed);if(Object.keys(value).some(key=>!expected.has(key)))throw new PluginRegistryErrorV1("invalid_manifest",t("{label} contains an unsupported field",{label}))}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",t("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(error){throw new PluginRegistryErrorV1("invalid_source",t("Plugin registry source URL is invalid"),error)}return value}function validateManifest(manifest){if(typeof manifest!="object"||manifest===null||Array.isArray(manifest))throw new PluginRegistryErrorV1("invalid_manifest",t("Registry manifest must be an object"));let value=manifest;if(assertAllowedKeys(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",t("Registry manifest id is invalid"));if(typeof value.pluginVersion!="string"||value.pluginVersion.trim()===""||value.pluginVersion.length>256)throw new PluginRegistryErrorV1("invalid_manifest",t("Registry manifest pluginVersion is invalid"));if(typeof value.apiVersion!="string"||value.apiVersion.trim()===""||value.apiVersion.length>256)throw new PluginRegistryErrorV1("invalid_manifest",t("Registry manifest apiVersion is invalid"));if(value.minHostVersion===void 0&&value.maxHostVersion===void 0)throw new PluginRegistryErrorV1("invalid_manifest",t("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(error){throw new PluginRegistryErrorV1("invalid_manifest",t("Registry manifest cannot be serialized"),error)}if(bytes>MAX_PLUGIN_REGISTRY_MANIFEST_BYTES_V1)throw new PluginRegistryErrorV1("payload_too_large",t("Registry manifest exceeds the size limit"));return Object.freeze({...value})}function validateEnvelope(value){if(typeof value!="object"||value===null||Array.isArray(value))throw new PluginRegistryErrorV1("invalid_manifest",t("Registry response entry must be an object"));let entry=value;assertAllowedKeys(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(error){throw new PluginRegistryErrorV1("invalid_manifest",t("Registry distribution descriptor is invalid"),error)}if(distribution.pluginId!==manifest.id||distribution.pluginVersion!==manifest.pluginVersion||distribution.manifestDigest!==manifestDigest)throw new PluginRegistryErrorV1("invalid_manifest",t("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",t("maxManifests must be an integer between 1 and {max}",{max: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",t("Manifest digest mismatch for {identity}",{identity:`${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??t("Registry source proof was rejected"))}catch(error){throw error instanceof PluginRegistryErrorV1?error:new PluginRegistryErrorV1("source_rejected",t("Registry source proof was rejected"),error)}let result;try{result=sourceVerifier({pluginId:entry.manifest.id,pluginVersion:entry.manifest.pluginVersion,source:entry.source,manifestDigest:actualDigest})}catch(error){throw new PluginRegistryErrorV1("source_rejected",t("Plugin source verifier failed"),error)}if(result.status!=="accepted")throw new PluginRegistryErrorV1("source_rejected",result.reason??t("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",t("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",t("Registry source/digest verifier is required"));if(options.sourceVerifier===void 0||typeof options.sourceVerifier!="function")throw new PluginRegistryErrorV1("source_rejected",t("Registry source verifier is required"));let load=async(input={})=>{if(input.signal?.aborted)throw new PluginRegistryErrorV1("cancelled",t("Plugin registry operation was cancelled"));let raw;try{raw=await options.source.list({signal:input.signal})}catch(error){throw isAbortLike(error,input.signal)?new PluginRegistryErrorV1("cancelled",t("Plugin registry operation was cancelled"),error):new PluginRegistryErrorV1("source_rejected",t("Plugin registry source failed"),error)}if(input.signal?.aborted)throw new PluginRegistryErrorV1("cancelled",t("Plugin registry operation was cancelled"));if(!Array.isArray(raw))throw new PluginRegistryErrorV1("invalid_manifest",t("Registry source must return an array"));if(raw.length>maxManifests)throw new PluginRegistryErrorV1("too_many_manifests",t("Registry response contains too many manifests"));let entries=raw.map(validateEnvelope);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",t("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",t("Duplicate registry manifest: {identity}",{identity}));seen.add(identity);try{await validateSourceProof(entry,options.verify,options.sourceVerifier)}catch(error){if(!(error instanceof PluginRegistryErrorV1)||error.cause!==void 0||error.code!=="source_rejected"&&error.code!=="invalid_digest")throw error;rejected.push({pluginId:entry.manifest.id,pluginVersion:entry.manifest.pluginVersion,code:error.code==="invalid_digest"?"digest_rejected":"source_rejected",reason:error.code==="invalid_digest"?"Manifest digest mismatch":"Registry source proof was rejected"});continue}if(input.signal?.aborted)throw new PluginRegistryErrorV1("cancelled",t("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}from"node:crypto";import{mkdir,readFile as readFile3,rename,unlink,writeFile}from"node:fs/promises";import{basename as basename2,dirname as dirname5,isAbsolute as isAbsolute3,join as join7,resolve as resolve2}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(error){return error instanceof Error&&(error.name==="AbortError"||error.name==="AbortSignalError")}function isMissingError(error){return typeof error!="object"||error===null?!1:"code"in error&&error.code==="ENOENT"}function validateFilePath(value){if(typeof value!="string"||value.trim()===""||value.length>MAX_PLUGIN_STATE_STRING_CHARS_V1)throw new Error(t("invalid plugin state file path"));if(value.includes("\0")||/[\u0000-\u001f]/u.test(value))throw new Error(t("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(t("invalid plugin state file path"));let normalized=isAbsolute3(value)?value:resolve2(value);if(basename2(normalized).length===0||basename2(normalized)==="."||basename2(normalized)==="..")throw new Error(t("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(t("invalid plugin scope reference"));if(/^(?:file:|[a-zA-Z]:[\\/]|[\\/]{1,2}|\\\\)/u.test(value)||/\s/u.test(value))throw new Error(t("invalid plugin scope reference"));if(value.includes("\0")||/[\u0000-\u001f]/u.test(value))throw new Error(t("invalid plugin scope reference"));if(scope==="global"&&value!==DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1)throw new Error(t("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(t("{label} is invalid",{label}));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(t("record source label is invalid"));return value}function identityOf(record){return`${record.state.scope}:${record.state.scopeRef}:${record.pluginId}@${record.pluginVersion}`}function isObject(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(!isObject(value)||Object.keys(value).some(key=>!allowedKeys.has(key)))throw new Error(t("record schema is invalid"));for(let key of requiredKeys)if(!(key in value))throw new Error(t("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(!isObject(value.state)||!hasExactKeys2(value.state,["scope","scopeRef","enabled","lifecycle"]))throw new Error(t("state schema is invalid"));if(value.state.scope!=="global"&&value.state.scope!=="project")throw new Error(t("state scope is invalid"));let scopeRef=validateScopeRef(value.state.scope,value.state.scopeRef);if(typeof value.state.enabled!="boolean")throw new Error(t("state enabled flag is invalid"));if(value.state.lifecycle!=="installed"&&value.state.lifecycle!=="active"&&value.state.lifecycle!=="retained")throw new Error(t("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(!isObject(value)||!hasExactKeys2(value,["version","records"]))throw new Error(t("snapshot schema is invalid"));if(value.version!==PLUGIN_STATE_SNAPSHOT_VERSION_V1)throw new Error(t("snapshot version is unsupported"));if(!Array.isArray(value.records))throw new Error(t("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(error){let message=error instanceof Error?error.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 path8=>await readFile3(path8,"utf8"),mkdir:async path8=>{await mkdir(path8,{recursive:!0})},writeFile:async(path8,data)=>{await writeFile(path8,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(t("state scope is invalid"));if(installation.scope!==scope)throw new Error(t("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(t("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(error){if(isMissingError(error))return Object.freeze({status:"missing",snapshot:EMPTY_SNAPSHOT});if(isAbortError(error)||signal?.aborted)return cancelledResult();throw error}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(error){return Object.freeze({status:"invalid",diagnostics:Object.freeze([invalidFromError(error)])})}}async function write(snapshot2,signal){if(signal?.aborted)return cancelledResult();let parent=dirname5(filePath),temporaryPath=join7(parent,`.${basename2(filePath)}.${randomUUID()}.tmp`);try{return await fileSystem.mkdir(parent),signal?.aborted||(await fileSystem.writeFile(temporaryPath,`${JSON.stringify(snapshot2)}
|
|
216
216
|
`),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(error){return Object.freeze({status:"invalid",diagnostics:Object.freeze([invalidFromError(error)])})}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(t("state scope is invalid"));scope=input.scope,scopeRef=validateScopeRef(scope,input.scopeRef)}catch(error){return Object.freeze({status:"invalid",diagnostics:Object.freeze([invalidFromError(error)])})}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=resolve3(cwd),identityPath=process.platform==="win32"?canonicalPath.toLowerCase():canonicalPath;return`project:sha256:${createHash("sha256").update(identityPath).digest("hex")}`}function defaultPluginInstallStoreDirectoryV1(agentDir){return join8(agentDir,DEFAULT_PLUGIN_INSTALL_STORE_DIR_V1)}function defaultPluginInstallStoreInstanceRootV1(agentDir){return join8(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:join8(input.cwd,CONFIG_DIR_NAME,DEFAULT_PLUGIN_STATE_FILE_V1)}),scope:"project",scopeRef:projectPluginScopeRefV1(input.cwd)},global:{stateStore:createPluginStateStoreV1({filePath:join8(input.agentDir,DEFAULT_PLUGIN_STATE_FILE_V1)}),scope:"global",scopeRef:DEFAULT_GLOBAL_PLUGIN_SCOPE_REF_V1}})}}import{join as join13}from"node:path";import{createHash as createHash2,randomUUID as randomUUID2}from"node:crypto";import{createReadStream}from"node:fs";import{mkdir as mkdir2,mkdtemp,open as open2,rename as rename2,rm}from"node:fs/promises";import{tmpdir}from"node:os";import{isAbsolute as isAbsolute4,join as join9}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(t("{label} must be an ISO-8601 UTC timestamp",{label}));let timestamp=Date.parse(value);if(!Number.isFinite(timestamp)||new Date(timestamp).toISOString()!==value)throw new Error(t("{label} must be a valid ISO-8601 UTC timestamp",{label}));return timestamp}function parsePublicKey(value){if(value.length===0||value.length>16*1024||/\u0000/u.test(value))throw new Error(t("publicKeyPem is invalid"));let key;try{key=createPublicKey(value)}catch{throw new Error(t("publicKeyPem is invalid"))}if(key.type!=="public"||key.asymmetricKeyType!=="ed25519")throw new Error(t("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}
|
|
217
|
-
${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(t("keys must contain between 1 and {max} entries",{max:MAX_KEYS_V1}));let revokedKeyIds=new Set(options.revokedKeyIds??[]);if([...revokedKeyIds].some(keyId=>!validKeyId(keyId))||options.revokedKeyIds!==void 0&&revokedKeyIds.size!==options.revokedKeyIds.length)throw new Error(t("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(t("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(t("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 error=new Error(t("plugin request was cancelled"));return error.name="AbortError",error}function throwIfRequestCancelled(request){if(request.timedOut())throw new Error(t("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(t("{label} must be a positive integer at most {maximum}",{label,maximum}));return result}function allowedOrigin(value){let parsed;try{parsed=new URL(value)}catch{throw new Error(t("allowed origin is invalid"))}if(parsed.protocol!=="http:"&&parsed.protocol!=="https:"||parsed.username||parsed.password)throw new Error(t("allowed origin must be an http(s) origin"));if(parsed.pathname!=="/"||parsed.search!==""||parsed.hash!=="")throw new Error(t("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(t("plugin source URL is invalid"))}if(parsed.protocol!=="http:"&&parsed.protocol!=="https:"||parsed.username||parsed.password)throw new Error(t("plugin source URL must use http(s) without credentials"));if(!origins.has(parsed.origin))throw new Error(t("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(t("plugin response content length is invalid"));let result=Number(value);if(!Number.isSafeInteger(result))throw new Error(t("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(t("plugin response size mismatch"));if(contentType(response2)!==descriptor.mediaType.toLowerCase())throw new Error(t("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(t("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(t("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(t("Node fetch is unavailable"));if(!Array.isArray(options.allowedOrigins)||options.allowedOrigins.length===0)throw new Error(t("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(t("maxRedirects must be an integer between 0 and {max}",{max: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(t("userAgent is invalid"));let configuredDirectory=options.artifactDirectory;if(configuredDirectory!==void 0&&!isAbsolute4(configuredDirectory))throw new Error(t("artifactDirectory must be absolute"));let baseDirectoryPromise=configuredDirectory===void 0?mkdtemp(join9(tmpdir(),"agent-forge-plugin-distribution-")):(async()=>(await mkdir2(configuredDirectory,{recursive:!0}),await mkdtemp(join9(configuredDirectory,"agent-forge-plugin-distribution-"))))(),artifacts=new Map,activeOperations=new Set,operationsDrained,closePromise,closed=!1,assertOpen=()=>{if(closed)throw new Error(t("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(resolve22=>{operationsDrained=resolve22})},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(error){throw request.cleanup(),throwIfRequestCancelled(request),error}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(t("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(t("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(t("plugin artifact request failed"));if(assertResponseMetadata(response2,input.descriptor),response2.body===null)throw new Error(t("plugin artifact response has no body"));let directory=await baseDirectoryPromise;temporaryPath=join9(directory,`.partial-${randomUUID2()}`),finalPath=join9(directory,`artifact-${randomUUID2()}`),file=await open2(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(t("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(t("plugin artifact size mismatch"));if(hash.digest("hex")!==digest.hex)throw new Error(t("plugin artifact digest mismatch"));await file.close(),file=void 0,await rename2(temporaryPath,finalPath),assertOpen();let artifactRef=`artifact://node-http/${randomUUID2()}`;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(error){throw throwIfRequestCancelled(request),error}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(t("plugin artifact release was cancelled"));let record=artifacts.get(input.artifact.artifactRef);if(record===void 0)throw new Error(t("plugin artifact reference is unknown"));if(record.readers>0)throw new Error(t("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(t("plugin artifact read was cancelled"));let record=artifacts.get(input.artifact.artifactRef);if(record===void 0||!artifactMatchesDescriptor(input.artifact,record.descriptor))throw new Error(t("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(t("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(error){throw await host.close().catch(()=>{}),error}}import{createHash as createHash3,randomUUID as randomUUID4}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 join11}from"node:path";import{inflateRawSync}from"node:zlib";import{randomUUID as randomUUID3}from"node:crypto";import{mkdir as mkdir3,open as open3,readFile as readFile4,rename as rename3,rm as rm2,writeFile as writeFile2}from"node:fs/promises";import{isAbsolute as isAbsolute5,join as join10}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(t("Node package install persistence failed: {code}",{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(t("lockTimeoutMs must be a positive integer at most {max}",{max: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 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"||!withinInstallStoreRoot(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((resolve22,reject2)=>{let timer=setTimeout(resolve22,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(t("rootDirectory must be absolute"));let lockTimeoutMs=positiveLockTimeout(options.lockTimeoutMs),rootDirectory=options.rootDirectory,indexPath=join10(rootDirectory,INDEX_FILE_V12),lockPath=join10(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(error){if(error instanceof NodePackageInstallPersistenceErrorV1)throw error;if(error instanceof Error&&"code"in error&&error.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 open3(lockPath,"wx",384)}catch(error){if(!(error instanceof Error&&"code"in error&&error.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}.${randomUUID3()}.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 index=start;index<stop;index+=1){let byte=header[index];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 index=0;index<TAR_BLOCK_BYTES_V1;index+=1)sum+=index>=TAR_CHECKSUM_OFFSET_V1&&index<TAR_CHECKSUM_OFFSET_V1+TAR_CHECKSUM_LENGTH_V1?32:header[index];if(readOctalHeaderField(header,TAR_CHECKSUM_OFFSET_V1,TAR_CHECKSUM_LENGTH_V1)!==sum)throw new NodePackageInstallErrorV1("archive_invalid")}function headerEntryName(header){for(let index=0;index<USTAR_MAGIC_V1.length;index+=1)if(header[TAR_MAGIC_OFFSET_V1+index]!==USTAR_MAGIC_V1[index])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 index=0;index<TAR_BLOCK_BYTES_V1;index+=1)if(tar[offset+index]!==0)return!1;return!0}function verifyZeroPadding(tar,dataEnd,paddedEnd){for(let index=dataEnd;index<paddedEnd;index+=1)if(tar[index]!==0)throw new NodePackageInstallErrorV1("archive_invalid")}function parsePaxPath(data){let offset=0,path8;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 index=offset;index<space;index+=1){let byte=data[index];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"&&(path8=readHeaderString(data,equals+1,end-1-equals-1)),offset=end}return path8}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((resolve22,reject2)=>{let gunzip=createGunzip(),chunks=[],total=0,settled=!1,fail=error=>{settled||(settled=!0,gunzip.destroy(),reject2(error))};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;resolve22(result)}),gunzip.on("error",()=>{fail(new NodePackageInstallErrorV1("archive_invalid"))}),gunzip.end(input)})}function parseTarEntries(tar,limits){let entries=[],names=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 index=offset+2*TAR_BLOCK_BYTES_V1;index<tar.byteLength;index+=1)if(tar[index]!==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(names.has(normalized.name))throw new NodePackageInstallErrorV1("archive_invalid");if(names.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(t("Node package installation failed: {code}",{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(t("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(t("{label} must be a positive integer at most {maximum}",{label,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(t("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 index=0;index<table.length;index+=1){let value=index;for(let bit=0;bit<8;bit+=1)value=(value&1)===0?value>>>1:value>>>1^3988292384;table[index]=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=[],names=new Set,offset=end.start;for(let index=0;index<end.entries;index+=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(names.has(name.name))throw new NodePackageInstallErrorV1("archive_invalid");if(names.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 index=1;index<spans.length;index+=1)if(spans[index-1].end>spans[index].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(error){throw error instanceof NodePackageInstallErrorV1?error: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 join11(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=join11(root,...entry.name.split("/"));if(entry.directory){await mkdir4(target,{recursive:!0,mode:448});continue}let parent=join11(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(t("openArtifact is required"));let limits=resolveNodePackageLimitsV1(options),parent=options.installationDirectory??tmpdir2();if(!isAbsolute6(parent))throw new Error(t("installationDirectory must be absolute"));if(options.persistence!==void 0&&options.persistence!=="ephemeral"&&options.persistence!=="persistent")throw new Error(t("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(t("supportedScopes is invalid"));await mkdir4(parent,{recursive:!0,mode:448});let persistent=options.persistence==="persistent",instanceRoot=persistent?join11(parent,"agent-forge-plugin-install-store-v1"):await mkdtemp2(join11(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(resolve22=>{drained=resolve22})},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:join11(directory,CAPABILITY_MANIFEST_FILE_V12),signal})??void 0}catch(error){throw error instanceof NodePackageInstallErrorV1?error: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=join11(instanceRoot,`.staging-${randomUUID4()}`),await writeEntries(staging,entries,operation.signal);let installRef=`plugin-install://node-zip/${randomUUID4()}`,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(error){throw await rm3(destination,{recursive:!0,force:!0}).catch(()=>{}),error}return{installationRef:installRef,scope:input.scope,scopeRef}}catch(error){throw operation.signal.aborted||input.signal?.aborted?new NodePackageInstallErrorV1("cancelled"):error instanceof NodePackageInstallErrorV1?error: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(error){throw candidate?.dispose!==void 0&&await Promise.resolve(candidate.dispose()).catch(()=>{}),error instanceof NodePackageInstallErrorV1?error: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(error){throw candidate?.dispose!==void 0&&await Promise.resolve(candidate.dispose()).catch(()=>{}),error instanceof NodePackageInstallErrorV1?error: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}).catch(error=>{if(error.code!=="ENOENT")throw error}),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(error){throw await host.close().catch(()=>{}),error instanceof NodePackageInstallErrorV1?error:new NodePackageInstallErrorV1("installation_io_failed")}return host}import{createHash as createHash5,randomUUID as randomUUID5}from"node:crypto";import{lstatSync as lstatSync2}from"node:fs";import{lstat,readdir,readFile as readFile5}from"node:fs/promises";import{join as join12}from"node:path";function isMissingError2(error){return typeof error!="object"||error===null?!1:"code"in error&&error.code==="ENOENT"}async function collectDirectory(root,relative11,limits,entries,budget,signal){if(signal?.aborted)throw new NodePackageInstallErrorV1("cancelled");let dirents=await readdir(relative11.length===0?root:join12(root,...relative11.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=relative11.length===0?dirent.name:`${relative11}/${dirent.name}`;if(normalizedEntryName(childRelative),dirent.isSymbolicLink())throw new NodePackageInstallErrorV1("archive_invalid");let childPath=join12(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(error=>{throw isMissingError2(error)?new NodePackageInstallErrorV1("archive_invalid"):error});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(path8,limitsInput={},signal){if(signal?.aborted)throw new NodePackageInstallErrorV1("cancelled");if(typeof path8!="string"||path8.trim().length===0)throw new NodePackageInstallErrorV1("archive_invalid");let stats=await lstat(path8).catch(error=>{throw isMissingError2(error)?new NodePackageInstallErrorV1("archive_invalid"):error});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(path8);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;retryAfterSeconds;constructor(code,message,options){super(message,options?.cause===void 0?void 0:{cause:options.cause}),this.name="NodeNpmRegistrySourceErrorV1",this.code=code,options?.retryAfterSeconds!==void 0&&(this.retryAfterSeconds=options.retryAfterSeconds)}};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",t("npm integrity algorithm is unsupported"));let algorithm=match2[1],raw;try{raw=Buffer.from(match2[2],"base64")}catch{throw new NodeNpmRegistrySourceErrorV1("integrity_unsupported",t("npm integrity encoding is invalid"))}if(algorithm==="sha256"&&raw.byteLength!==32||algorithm==="sha512"&&raw.byteLength!==64)throw new NodeNpmRegistrySourceErrorV1("integrity_unsupported",t("npm integrity length is invalid"));let hex=raw.toString("hex").toLowerCase();if(hex.length===0)throw new NodeNpmRegistrySourceErrorV1("integrity_unsupported",t("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",t("{label} must be a positive integer at most {maximum}",{label,maximum}));return result}function registryOrigin(value){let parsed;try{parsed=new URL(value)}catch{throw new NodeNpmRegistrySourceErrorV1("invalid_configuration",t("npm registry origin is invalid"))}if(parsed.protocol!=="http:"&&parsed.protocol!=="https:"||parsed.username!==""||parsed.password!=="")throw new NodeNpmRegistrySourceErrorV1("invalid_configuration",t("npm registry origin must be http(s) without credentials"));if(parsed.pathname!=="/"||parsed.search!==""||parsed.hash!=="")throw new NodeNpmRegistrySourceErrorV1("invalid_configuration",t("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",t("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",t("npm tarball URL is invalid"))}if(parsed.protocol!=="http:"&&parsed.protocol!=="https:"||parsed.username!==""||parsed.password!=="")throw new NodeNpmRegistrySourceErrorV1("invalid_response",t("npm tarball URL must use http(s) without credentials"));if(parsed.hash!=="")throw new NodeNpmRegistrySourceErrorV1("invalid_response",t("npm tarball URL must not include a fragment"));return parsed}function isAbortLike2(error){return error instanceof Error&&(error.name==="AbortError"||error.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"}function rateLimitState(response2){if(!(response2.status===429||response2.status===403&&response2.headers.get("x-ratelimit-remaining")==="0"))return{limited:!1};let retryAfter=response2.headers.get("retry-after"),seconds=retryAfter===null?Number.NaN:Number.parseInt(retryAfter,10);return!Number.isSafeInteger(seconds)||seconds<0?{limited:!0}:{limited:!0,retryAfterSeconds:seconds}}function rateLimitError(limit){let message=limit.retryAfterSeconds===void 0?t("npm registry rate limit was exceeded"):`${t("npm registry rate limit was exceeded")} (retry after ${limit.retryAfterSeconds}s)`;return new NodeNpmRegistrySourceErrorV1("rate_limited",message,{...limit.retryAfterSeconds===void 0?{}:{retryAfterSeconds:limit.retryAfterSeconds}})}async function readBody(response2,maxBytes,request){if(response2.body===null)throw new NodeNpmRegistrySourceErrorV1("invalid_response",t("npm registry response has no body"));let reader=response2.body.getReader(),chunks=[],total=0,abortError2=()=>request.timedOut()?new NodeNpmRegistrySourceErrorV1("request_timed_out",t("npm registry request timed out")):new NodeNpmRegistrySourceErrorV1("cancelled",t("npm registry request was cancelled"));try{for(;;){if(request.signal.aborted)throw abortError2();let item;try{item=await reader.read()}catch(error){throw request.signal.aborted?abortError2():error}if(item.done)break;if(total+=item.value.byteLength,total>maxBytes)throw new NodeNpmRegistrySourceErrorV1("response_too_large",t("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",t("npm registry response is not valid JSON"))}if(typeof value!="object"||value===null||Array.isArray(value))throw new NodeNpmRegistrySourceErrorV1("invalid_response",t("npm packument is invalid"));let packument=value;if(typeof packument.versions!="object"||packument.versions===null||Array.isArray(packument.versions))throw new NodeNpmRegistrySourceErrorV1("invalid_response",t("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",t("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",t("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",t("maxRedirects must be an integer between 0 and {max}",{max: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",t("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(error){throw request.cleanup(),request.timedOut()?new NodeNpmRegistrySourceErrorV1("request_timed_out",t("npm registry request timed out")):isAbortLike2(error)?new NodeNpmRegistrySourceErrorV1("cancelled",t("npm registry request was cancelled")):new NodeNpmRegistrySourceErrorV1("request_failed",t("npm registry request failed"),{cause:error})}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",t("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",t("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{let limit=rateLimitState(response2);if(limit.limited)throw rateLimitError(limit);if(response2.status===404||response2.status===403)throw new NodeNpmRegistrySourceErrorV1("package_not_found",t("npm package was not found on the registry"));if(response2.status<200||response2.status>=300)throw new NodeNpmRegistrySourceErrorV1("request_failed",t("npm registry request did not succeed"));if(!isJsonResponse(response2))throw new NodeNpmRegistrySourceErrorV1("invalid_response",t("npm registry response must be JSON"));let versions=parsePackument(await readBody(response2,maxResponseBytes,request)),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",t("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",t("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",t("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{let limit=rateLimitState(response2);if(limit.limited)throw rateLimitError(limit);if(response2.status<200||response2.status>=300)throw new NodeNpmRegistrySourceErrorV1("request_failed",t("npm tarball download did not succeed"));return await readBody(response2,maxTarballBytes,request)}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",t("{label} must be a positive integer at most {maximum}",{label,maximum}));return result}function packageUrl(value){let parsed;try{parsed=new URL(value)}catch{throw new NodeUrlPackageSourceErrorV1("invalid_url",t("plugin package URL is invalid"))}if(parsed.protocol!=="http:"&&parsed.protocol!=="https:"||parsed.username!==""||parsed.password!=="")throw new NodeUrlPackageSourceErrorV1("invalid_url",t("plugin package URL must use http(s) without credentials"));if(parsed.hash!=="")throw new NodeUrlPackageSourceErrorV1("invalid_url",t("plugin package URL must not include a fragment"));return parsed}function isAbortLike3(error){return error instanceof Error&&(error.name==="AbortError"||error.name==="AbortSignalError")}async function downloadNodeUrlPackageV1(options,input){let transport=options.fetch??globalThis.fetch;if(typeof transport!="function")throw new NodeUrlPackageSourceErrorV1("invalid_configuration",t("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",t("maxRedirects must be an integer between 0 and {max}",{max: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",t("userAgent is invalid"));if(input.expectedDigestHex!==void 0&&!/^[0-9a-f]{64}$/u.test(input.expectedDigestHex))throw new NodeUrlPackageSourceErrorV1("invalid_url",t("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",t("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(error){throw timedOut?new NodeUrlPackageSourceErrorV1("request_timed_out",t("plugin package download timed out")):isAbortLike3(error)||input.signal?.aborted===!0?new NodeUrlPackageSourceErrorV1("cancelled",t("plugin package download was cancelled")):new NodeUrlPackageSourceErrorV1("request_failed",t("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",t("plugin package redirect limit exceeded"));current=packageUrl(new URL(location,current).toString())}if(response2===void 0)throw new NodeUrlPackageSourceErrorV1("request_failed",t("plugin package download failed"));if(response2.status<200||response2.status>=300)throw new NodeUrlPackageSourceErrorV1("request_failed",t("plugin package download did not succeed"));if(response2.body===null)throw new NodeUrlPackageSourceErrorV1("request_failed",t("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",t("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",t("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",t("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",t("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",t("{label} must be a positive integer at most {maximum}",{label,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",t("{label} is invalid",{label}));return value}}function apiOrigin(value,label){let parsed;try{parsed=new URL(value)}catch{throw new NodeReleasePackageSourceErrorV1("invalid_configuration",t("{label} is invalid",{label}))}if(parsed.protocol!=="http:"&&parsed.protocol!=="https:"||parsed.username!==""||parsed.password!=="")throw new NodeReleasePackageSourceErrorV1("invalid_configuration",t("{label} must be http(s) without credentials",{label}));if(parsed.search!==""||parsed.hash!=="")throw new NodeReleasePackageSourceErrorV1("invalid_configuration",t("{label} must not include a query or fragment",{label}));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",t("release API response is not valid JSON"))}}function parseReleaseList(bytes){let value=jsonBytes(bytes);if(!Array.isArray(value))throw new NodeReleasePackageSourceErrorV1("invalid_response",t("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",t("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",t("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",t("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?t("release has no assets"):t("assets: {names}",{names:assetNames}));if(candidates.length>1)throw new NodeReleasePackageSourceErrorV1("release_asset_ambiguous",t("candidates: {names}",{names:candidates.map(asset=>asset.name).join(", ")}));let chosen=candidates[0];if(typeof chosen.url!="string"||chosen.url.length===0)throw new NodeReleasePackageSourceErrorV1("invalid_response",t("release asset has no download URL"));return chosen.url}function isAbortLike4(error){return error instanceof Error&&(error.name==="AbortError"||error.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 rateLimitState2(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",t("release API response has no body"));let reader=response2.body.getReader(),chunks=[],total=0;try{for(;;){if(signal.aborted)throw new DOMException(t("aborted"),"AbortError");let item=await reader.read();if(item.done)break;if(total+=item.value.byteLength,total>maxBytes)throw new NodeReleasePackageSourceErrorV1("response_too_large",t("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",t("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",t("maxRedirects must be an integer between 0 and {max}",{max: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",t("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(error){throw request.cleanup(),request.timedOut()?new NodeReleasePackageSourceErrorV1("request_timed_out",t("release API request timed out")):isAbortLike4(error)?new NodeReleasePackageSourceErrorV1("cancelled",t("release API request was cancelled")):new NodeReleasePackageSourceErrorV1("request_failed",t("release API request failed"))}if(!REDIRECT_STATUS4.has(response2.status))try{if(response2.status===404)throw new NodeReleasePackageSourceErrorV1("release_not_found",t("repo or release was not found"));let limit=rateLimitState2(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",t("release API request did not succeed"));if(!isJsonResponse2(response2))throw new NodeReleasePackageSourceErrorV1("invalid_response",t("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",t("release API redirect limit exceeded"));let next;try{next=new URL(location,current)}catch{throw new NodeReleasePackageSourceErrorV1("invalid_response",t("release API redirect target is invalid"))}if(next.protocol!=="http:"&&next.protocol!=="https:"||next.username!==""||next.password!=="")throw new NodeReleasePackageSourceErrorV1("invalid_response",t("release API redirect must stay http(s)"));current=next}};return{version:1,downloadReleaseAsset:async input=>{if(input.signal?.aborted===!0)throw new NodeReleasePackageSourceErrorV1("cancelled",t("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(segment=>segment!==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",t("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",t("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 index=148;index<148+TAR_CHECKSUM_LENGTH_V12;index+=1)header[index]=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 index=Math.min(bytes.byteLength,TAR_PREFIX_LENGTH_V12)-1;index>=0;index-=1)if(bytes[index]===47){split=index;break}if(split<=0)throw new NodeTarWriterErrorV1("entry_name_too_long",t("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",t("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",t("tar entry name is invalid"));if(normalizedEntryName(entry.directory?`${entry.name}/`:entry.name).name!==entry.name)throw new NodeTarWriterErrorV1("invalid_entry",t("tar entry name is not normalized"));if(entry.directory&&entry.bytes!==void 0&&entry.bytes.byteLength>0)throw new NodeTarWriterErrorV1("invalid_entry",t("tar directory entry must be empty"));if(!entry.directory&&!(entry.bytes instanceof Uint8Array))throw new NodeTarWriterErrorV1("invalid_entry",t("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",t("tar entries must be an array"));let names=new Set,blocks=[];for(let entry of entries){if(names.has(entry.name))throw new NodeTarWriterErrorV1("invalid_entry",t("duplicate tar entry name: {name}",{name:entry.name}));if(names.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:path8=>{let stats=lstatSync2(path8,{throwIfNoEntry:!1});return stats===void 0?"missing":stats.isSymbolicLink()?"other":stats.isDirectory()?"directory":stats.isFile()?"file":"other"}};function mapInstallError(error){return error instanceof PluginAcquisitionErrorV1?error:error instanceof NodePackageInstallErrorV1?error.code==="cancelled"?new PluginAcquisitionErrorV1("cancelled"):error.code==="archive_budget_exceeded"?new PluginAcquisitionErrorV1("budget_exceeded"):error.code==="unsupported_media_type"?new PluginAcquisitionErrorV1("unsupported_media_type"):new PluginAcquisitionErrorV1("package_invalid"):new PluginAcquisitionErrorV1("download_failed")}function mapNpmError(error){return error instanceof PluginAcquisitionErrorV1?error:error instanceof NodeNpmRegistrySourceErrorV1?error.code==="package_not_found"?new PluginAcquisitionErrorV1("package_not_found"):error.code==="version_not_found"?new PluginAcquisitionErrorV1("version_not_found"):error.code==="cancelled"?new PluginAcquisitionErrorV1("cancelled"):error.code==="rate_limited"?new PluginAcquisitionErrorV1("rate_limited",error.retryAfterSeconds===void 0?void 0:`retry after ${error.retryAfterSeconds}s`):error.code==="response_too_large"?new PluginAcquisitionErrorV1("budget_exceeded"):error.code==="request_timed_out"?new PluginAcquisitionErrorV1("download_failed","request timed out"):error.code==="invalid_response"||error.code==="integrity_unsupported"?new PluginAcquisitionErrorV1("package_invalid"):new PluginAcquisitionErrorV1("download_failed"):mapInstallError(error)}function mapUrlError(error){return error instanceof PluginAcquisitionErrorV1?error:error instanceof NodeUrlPackageSourceErrorV1?error.code==="digest_mismatch"?new PluginAcquisitionErrorV1("digest_mismatch"):error.code==="cancelled"?new PluginAcquisitionErrorV1("cancelled"):error.code==="invalid_url"||error.code==="invalid_configuration"?new PluginAcquisitionErrorV1("invalid_ref"):error.code==="response_too_large"?new PluginAcquisitionErrorV1("budget_exceeded"):new PluginAcquisitionErrorV1("download_failed"):mapInstallError(error)}function mapReleaseError(error){return error instanceof PluginAcquisitionErrorV1?error:error instanceof NodeReleasePackageSourceErrorV1?error.code==="cancelled"?new PluginAcquisitionErrorV1("cancelled"):error.code==="invalid_configuration"?new PluginAcquisitionErrorV1("invalid_ref"):error.code==="response_too_large"?new PluginAcquisitionErrorV1("budget_exceeded"):error.code==="invalid_response"?new PluginAcquisitionErrorV1("package_invalid"):error.code==="rate_limited"?new PluginAcquisitionErrorV1("rate_limited",error.resetEpochSeconds===void 0?void 0:`rate limit resets at ${new Date(error.resetEpochSeconds*1e3).toISOString()}`):error.code==="release_not_found"||error.code==="release_asset_not_found"||error.code==="release_asset_ambiguous"?new PluginAcquisitionErrorV1(error.code,error.message):new PluginAcquisitionErrorV1("download_failed"):mapUrlError(error)}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(error){throw mapReleaseError(error)}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(error){throw mapNpmError(error)}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(error){throw mapUrlError(error)}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(error){throw mapInstallError(error)}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(error){throw mapInstallError(error)}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(error){throw error instanceof PluginAcquisitionErrorV1?error: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(error){throw mapInstallError(error)}let identity=pluginAcquisitionManifestFromEntriesV1(entries);if(closed)throw new PluginAcquisitionErrorV1("cancelled");let artifactRef=`plugin-acquisition://node/${randomUUID5()}`,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 NODE_HTTP_PLUGIN_REGISTRY_SOURCE_VERSION_V1=1,DEFAULT_TIMEOUT_MS_V15=15e3,MAX_TIMEOUT_MS_V15=12e4,DEFAULT_MAX_RESPONSE_BYTES_V13=4*1024*1024,MAX_RESPONSE_BYTES_V13=8*1024*1024,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",t("{label} must be a positive integer at most {maximum}",{label,maximum}));return result}function allowedOrigin2(value){let parsed;try{parsed=new URL(value)}catch{throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration",t("Allowed registry origin is invalid"))}if(parsed.protocol!=="http:"&&parsed.protocol!=="https:"||parsed.username||parsed.password)throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration",t("Allowed registry origin must be an http(s) origin without credentials"));if(parsed.pathname!=="/"||parsed.search!==""||parsed.hash!=="")throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration",t("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",t("Plugin registry URL is invalid"))}if(parsed.protocol!=="http:"&&parsed.protocol!=="https:"||parsed.username||parsed.password)throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration",t("Plugin registry URL must use http(s) without credentials"));if(parsed.search!==""||parsed.hash!=="")throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration",t("Plugin registry URL must not include a query or fragment"));if(!origins.has(parsed.origin))throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration",t("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",t("Plugin registry response length is invalid"));let value=Number(raw);if(!Number.isSafeInteger(value))throw new NodeHttpPluginRegistrySourceErrorV1("invalid_response",t("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",t("Plugin registry response has no body"));let reader=response2.body.getReader(),chunks=[],total=0;try{for(;;){if(signal.aborted)throw new DOMException(t("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",t("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",t("Plugin registry response is not valid JSON"))}if(typeof value!="object"||value===null||Array.isArray(value))throw new NodeHttpPluginRegistrySourceErrorV1("invalid_response",t("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",t("Plugin registry document is invalid"));return document.entries}function isAbortLike5(error){return error instanceof DOMException&&error.name==="AbortError"}function isCallerCancelled(signal){return signal?.aborted===!0}function sanitizedSourceError(error){let code=error.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",t("Plugin registry request failed")):new NodeHttpPluginRegistrySourceErrorV1(code,t("Plugin registry request failed"))}function createNodeHttpPluginRegistrySourceV1(options){let transport=options.fetch??globalThis.fetch;if(typeof transport!="function")throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration",t("Node fetch is unavailable"));if(!Array.isArray(options.allowedOrigins)||options.allowedOrigins.length===0)throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration",t("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,DEFAULT_TIMEOUT_MS_V15,MAX_TIMEOUT_MS_V15,"requestTimeoutMs"),maxResponseBytes=boundedPositive5(options.maxResponseBytes,DEFAULT_MAX_RESPONSE_BYTES_V13,MAX_RESPONSE_BYTES_V13,"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",t("userAgent is invalid"));let source=endpoint.origin+endpoint.pathname;return{version:NODE_HTTP_PLUGIN_REGISTRY_SOURCE_VERSION_V1,source,list:async({signal}={})=>{if(isCallerCancelled(signal))throw new NodeHttpPluginRegistrySourceErrorV1("cancelled",t("Plugin registry request was cancelled"));let request=requestController(signal,timeoutMs),response2;try{let transportResponse=Promise.resolve().then(()=>{if(request.signal.aborted)throw new DOMException(t("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",t("Plugin registry request did not succeed"));if(!isJsonResponse3(receivedResponse))throw new NodeHttpPluginRegistrySourceErrorV1("invalid_response",t("Plugin registry response must be JSON"));let length=responseLength(receivedResponse);if(length!==void 0&&length>maxResponseBytes)throw new NodeHttpPluginRegistrySourceErrorV1("response_too_large",t("Plugin registry response exceeds the configured size limit"));return parseDocument(await readBody3(receivedResponse,maxResponseBytes,request.signal))}catch(error){throw isCallerCancelled(signal)?new NodeHttpPluginRegistrySourceErrorV1("cancelled",t("Plugin registry request was cancelled")):request.timedOut()?new NodeHttpPluginRegistrySourceErrorV1("request_timed_out",t("Plugin registry request timed out")):error instanceof NodeHttpPluginRegistrySourceErrorV1?sanitizedSourceError(error):isAbortLike5(error)?new NodeHttpPluginRegistrySourceErrorV1("cancelled",t("Plugin registry request was cancelled")):new NodeHttpPluginRegistrySourceErrorV1("request_failed",t("Plugin registry request failed"))}finally{request.cleanup(),discardResponseBody(response2)}}}}function createPluginEcosystemRegistryAdapterV1(registry){if(registry.resolve===void 0)throw new PluginRegistryErrorV1("invalid_source",t("Registry does not expose a host-side package resolver"));let resolve22=registry.resolve,list=registry.listManifests;return{...list===void 0?{}:{list},resolve:resolve22}}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:join13(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(t("{env} must be a JSON array of {keyId, publicKeyPem}",{env:DEFAULT_PLUGIN_TRUST_KEYS_ENV_V1}))}if(!Array.isArray(parsed))throw new Error(t("{env} must be a JSON array",{env:DEFAULT_PLUGIN_TRUST_KEYS_ENV_V1}));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:join13(options.agentDir,DEFAULT_PLUGIN_STATE_FILE_V1)}),projectStateStore:createPluginStateStoreV1({filePath:join13(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(error){failure2=error}try{await distributionHost.close()}catch(error){failure2===void 0&&(failure2=error)}if(failure2!==void 0)throw failure2})()),closePromise);return Object.freeze({distributionHost,distribution:distributionHost.distribution,packageHost,installer,close})}catch(error){throw await packageHost.close().catch(()=>{}),error}}catch(error){throw await distributionHost.close().catch(()=>{}),error}}import{randomUUID as randomUUID6}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 dirname6,isAbsolute as isAbsolute7,join as join14,resolve as resolve4}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(error){return error instanceof Error&&(error.name==="AbortError"||error.name==="AbortSignalError")}function isMissingError3(error){return typeof error=="object"&&error!==null&&"code"in error&&error.code==="ENOENT"}function validateFilePath2(value){if(typeof value!="string"||value.trim()===""||value.length>MAX_PLUGIN_SELECTION_STORE_PATH_CHARS_V1)throw new Error(t("invalid plugin selection file path"));if(value.includes("\0")||/[\u0000-\u001f]/u.test(value))throw new Error(t("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(t("invalid plugin selection file path"));let normalized=isAbsolute7(value)?value:resolve4(value);if(basename3(normalized).length===0||basename3(normalized)==="."||basename3(normalized)==="..")throw new Error(t("invalid plugin selection file path"));return normalized}function isObject2(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(!isObject2(value)||!hasExactKeys3(value,["profileId","selectedPluginIds","disabledPluginIds"]))throw new Error(t("selection schema is invalid"));if(!Array.isArray(value.selectedPluginIds)||!Array.isArray(value.disabledPluginIds))throw new Error(t("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(t("too many plugin IDs"));return createPluginSelectionV1({profileId:value.profileId,selectedPluginIds:value.selectedPluginIds,disabledPluginIds:value.disabledPluginIds})}function validateSnapshot2(value){if(!isObject2(value)||!hasExactKeys3(value,["version","selections"]))throw new Error(t("snapshot schema is invalid"));if(value.version!==PLUGIN_SELECTION_STORE_VERSION_V1)throw new Error(t("snapshot version is unsupported"));if(!Array.isArray(value.selections))throw new Error(t("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(error){let message=error instanceof Error?error.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 path8=>await readFile6(path8,"utf8"),mkdir:async path8=>{await mkdir5(path8,{recursive:!0})},writeFile:async(path8,data)=>{await writeFile4(path8,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(error){if(isMissingError3(error))return Object.freeze({status:"missing",snapshot:EMPTY_SNAPSHOT2});if(isAbortError2(error)||signal?.aborted)return cancelledResult2();throw error}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(error){return Object.freeze({status:"invalid",diagnostics:Object.freeze([invalidFromError2(error)])})}}async function write(snapshot2,signal){if(signal?.aborted)return cancelledResult2();let temporaryPath=join14(dirname6(filePath),`.${basename3(filePath)}.${randomUUID6()}.tmp`);try{return await fileSystem.mkdir(dirname6(filePath)),signal?.aborted||(await fileSystem.writeFile(temporaryPath,`${JSON.stringify({version:snapshot2.version,selections:snapshot2.selections.map(persistedSelection)})}
|
|
217
|
+
${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(t("keys must contain between 1 and {max} entries",{max:MAX_KEYS_V1}));let revokedKeyIds=new Set(options.revokedKeyIds??[]);if([...revokedKeyIds].some(keyId=>!validKeyId(keyId))||options.revokedKeyIds!==void 0&&revokedKeyIds.size!==options.revokedKeyIds.length)throw new Error(t("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(t("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(t("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 error=new Error(t("plugin request was cancelled"));return error.name="AbortError",error}function throwIfRequestCancelled(request){if(request.timedOut())throw new Error(t("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(t("{label} must be a positive integer at most {maximum}",{label,maximum}));return result}function allowedOrigin(value){let parsed;try{parsed=new URL(value)}catch{throw new Error(t("allowed origin is invalid"))}if(parsed.protocol!=="http:"&&parsed.protocol!=="https:"||parsed.username||parsed.password)throw new Error(t("allowed origin must be an http(s) origin"));if(parsed.pathname!=="/"||parsed.search!==""||parsed.hash!=="")throw new Error(t("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(t("plugin source URL is invalid"))}if(parsed.protocol!=="http:"&&parsed.protocol!=="https:"||parsed.username||parsed.password)throw new Error(t("plugin source URL must use http(s) without credentials"));if(!origins.has(parsed.origin))throw new Error(t("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(t("plugin response content length is invalid"));let result=Number(value);if(!Number.isSafeInteger(result))throw new Error(t("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(t("plugin response size mismatch"));if(contentType(response2)!==descriptor.mediaType.toLowerCase())throw new Error(t("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(t("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(t("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(t("Node fetch is unavailable"));if(!Array.isArray(options.allowedOrigins)||options.allowedOrigins.length===0)throw new Error(t("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(t("maxRedirects must be an integer between 0 and {max}",{max: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(t("userAgent is invalid"));let configuredDirectory=options.artifactDirectory;if(configuredDirectory!==void 0&&!isAbsolute4(configuredDirectory))throw new Error(t("artifactDirectory must be absolute"));let baseDirectoryPromise=configuredDirectory===void 0?mkdtemp(join9(tmpdir(),"agent-forge-plugin-distribution-")):(async()=>(await mkdir2(configuredDirectory,{recursive:!0}),await mkdtemp(join9(configuredDirectory,"agent-forge-plugin-distribution-"))))(),artifacts=new Map,activeOperations=new Set,operationsDrained,closePromise,closed=!1,assertOpen=()=>{if(closed)throw new Error(t("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(resolve22=>{operationsDrained=resolve22})},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(error){throw request.cleanup(),throwIfRequestCancelled(request),error}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(t("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(t("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(t("plugin artifact request failed"));if(assertResponseMetadata(response2,input.descriptor),response2.body===null)throw new Error(t("plugin artifact response has no body"));let directory=await baseDirectoryPromise;temporaryPath=join9(directory,`.partial-${randomUUID2()}`),finalPath=join9(directory,`artifact-${randomUUID2()}`),file=await open2(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(t("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(t("plugin artifact size mismatch"));if(hash.digest("hex")!==digest.hex)throw new Error(t("plugin artifact digest mismatch"));await file.close(),file=void 0,await rename2(temporaryPath,finalPath),assertOpen();let artifactRef=`artifact://node-http/${randomUUID2()}`;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(error){throw throwIfRequestCancelled(request),error}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(t("plugin artifact release was cancelled"));let record=artifacts.get(input.artifact.artifactRef);if(record===void 0)throw new Error(t("plugin artifact reference is unknown"));if(record.readers>0)throw new Error(t("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(t("plugin artifact read was cancelled"));let record=artifacts.get(input.artifact.artifactRef);if(record===void 0||!artifactMatchesDescriptor(input.artifact,record.descriptor))throw new Error(t("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(t("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(error){throw await host.close().catch(()=>{}),error}}import{spawn}from"node:child_process";import{createHash as createHash3,randomUUID as randomUUID4}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 join11}from"node:path";import{inflateRawSync}from"node:zlib";import{randomUUID as randomUUID3}from"node:crypto";import{mkdir as mkdir3,open as open3,readFile as readFile4,rename as rename3,rm as rm2,writeFile as writeFile2}from"node:fs/promises";import{isAbsolute as isAbsolute5,join as join10}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(t("Node package install persistence failed: {code}",{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(t("lockTimeoutMs must be a positive integer at most {max}",{max: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 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"||!withinInstallStoreRoot(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((resolve22,reject2)=>{let timer=setTimeout(resolve22,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(t("rootDirectory must be absolute"));let lockTimeoutMs=positiveLockTimeout(options.lockTimeoutMs),rootDirectory=options.rootDirectory,indexPath=join10(rootDirectory,INDEX_FILE_V12),lockPath=join10(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(error){if(error instanceof NodePackageInstallPersistenceErrorV1)throw error;if(error instanceof Error&&"code"in error&&error.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 open3(lockPath,"wx",384)}catch(error){if(!(error instanceof Error&&"code"in error&&error.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}.${randomUUID3()}.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 index=start;index<stop;index+=1){let byte=header[index];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 index=0;index<TAR_BLOCK_BYTES_V1;index+=1)sum+=index>=TAR_CHECKSUM_OFFSET_V1&&index<TAR_CHECKSUM_OFFSET_V1+TAR_CHECKSUM_LENGTH_V1?32:header[index];if(readOctalHeaderField(header,TAR_CHECKSUM_OFFSET_V1,TAR_CHECKSUM_LENGTH_V1)!==sum)throw new NodePackageInstallErrorV1("archive_invalid")}function headerEntryName(header){for(let index=0;index<USTAR_MAGIC_V1.length;index+=1)if(header[TAR_MAGIC_OFFSET_V1+index]!==USTAR_MAGIC_V1[index])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 index=0;index<TAR_BLOCK_BYTES_V1;index+=1)if(tar[offset+index]!==0)return!1;return!0}function verifyZeroPadding(tar,dataEnd,paddedEnd){for(let index=dataEnd;index<paddedEnd;index+=1)if(tar[index]!==0)throw new NodePackageInstallErrorV1("archive_invalid")}function parsePaxPath(data){let offset=0,path8;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 index=offset;index<space;index+=1){let byte=data[index];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"&&(path8=readHeaderString(data,equals+1,end-1-equals-1)),offset=end}return path8}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((resolve22,reject2)=>{let gunzip=createGunzip(),chunks=[],total=0,settled=!1,fail=error=>{settled||(settled=!0,gunzip.destroy(),reject2(error))};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;resolve22(result)}),gunzip.on("error",()=>{fail(new NodePackageInstallErrorV1("archive_invalid"))}),gunzip.end(input)})}function parseTarEntries(tar,limits){let entries=[],names=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 index=offset+2*TAR_BLOCK_BYTES_V1;index<tar.byteLength;index+=1)if(tar[index]!==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(names.has(normalized.name))throw new NodePackageInstallErrorV1("archive_invalid");if(names.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",HOST_SUPPLIED_DEPENDENCY_PREFIXES_V1=["@agent-forge/","@ai-agent-forge/"],HOST_SUPPLIED_DEPENDENCIES_V1=new Set(["typebox"]),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(t("Node package installation failed: {code}",{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(t("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(t("{label} must be a positive integer at most {maximum}",{label,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(t("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 index=0;index<table.length;index+=1){let value=index;for(let bit=0;bit<8;bit+=1)value=(value&1)===0?value>>>1:value>>>1^3988292384;table[index]=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=[],names=new Set,offset=end.start;for(let index=0;index<end.entries;index+=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(names.has(name.name))throw new NodePackageInstallErrorV1("archive_invalid");if(names.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 index=1;index<spans.length;index+=1)if(spans[index-1].end>spans[index].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(error){throw error instanceof NodePackageInstallErrorV1?error: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 join11(root,createHash3("sha256").update(key).digest("hex"))}function isHostSuppliedDependencyV1(name){return HOST_SUPPLIED_DEPENDENCIES_V1.has(name)||HOST_SUPPLIED_DEPENDENCY_PREFIXES_V1.some(prefix=>name.startsWith(prefix))}async function installStagingRuntimeDependencies(staging,entries,signal){let packageEntry=entries.find(entry=>entry.name==="package.json"&&!entry.directory);if(packageEntry===void 0)return;let manifest;try{manifest=JSON.parse(new TextDecoder("utf-8",{fatal:!0}).decode(packageEntry.bytes))}catch{return}if(typeof manifest!="object"||manifest===null||Array.isArray(manifest))return;let record=manifest,dependencies=record.dependencies;if(typeof dependencies!="object"||dependencies===null||Array.isArray(dependencies))return;let runtime=Object.fromEntries(Object.entries(dependencies).filter(([name])=>!isHostSuppliedDependencyV1(name)));if(Object.keys(runtime).length===0)return;await writeFile3(join11(staging,"package.json"),JSON.stringify({...record,dependencies:runtime,devDependencies:void 0}),{flag:"w",mode:384});let win32=process.platform==="win32";await new Promise((resolve22,reject2)=>{let child=spawn(win32?"npm.cmd":"npm",["install","--omit=dev","--ignore-scripts","--no-audit","--no-fund","--loglevel=error"],{cwd:staging,signal,shell:win32,stdio:"ignore"});child.once("error",reject2),child.once("close",code=>{if(code===0){resolve22();return}reject2(new NodePackageInstallErrorV1("dependency_install_failed"))})})}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=join11(root,...entry.name.split("/"));if(entry.directory){await mkdir4(target,{recursive:!0,mode:448});continue}let parent=join11(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(t("openArtifact is required"));let limits=resolveNodePackageLimitsV1(options),parent=options.installationDirectory??tmpdir2();if(!isAbsolute6(parent))throw new Error(t("installationDirectory must be absolute"));if(options.persistence!==void 0&&options.persistence!=="ephemeral"&&options.persistence!=="persistent")throw new Error(t("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(t("supportedScopes is invalid"));await mkdir4(parent,{recursive:!0,mode:448});let persistent=options.persistence==="persistent",instanceRoot=persistent?join11(parent,"agent-forge-plugin-install-store-v1"):await mkdtemp2(join11(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(resolve22=>{drained=resolve22})},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:join11(directory,CAPABILITY_MANIFEST_FILE_V12),signal})??void 0}catch(error){throw error instanceof NodePackageInstallErrorV1?error: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=join11(instanceRoot,`.staging-${randomUUID4()}`),await writeEntries(staging,entries,operation.signal),options.dependencyMaterialization!=="skip"&&await installStagingRuntimeDependencies(staging,entries,operation.signal);let installRef=`plugin-install://node-zip/${randomUUID4()}`,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(error){throw await rm3(destination,{recursive:!0,force:!0}).catch(()=>{}),error}return{installationRef:installRef,scope:input.scope,scopeRef}}catch(error){throw operation.signal.aborted||input.signal?.aborted?new NodePackageInstallErrorV1("cancelled"):error instanceof NodePackageInstallErrorV1?error: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(error){throw candidate?.dispose!==void 0&&await Promise.resolve(candidate.dispose()).catch(()=>{}),error instanceof NodePackageInstallErrorV1?error: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(error){throw candidate?.dispose!==void 0&&await Promise.resolve(candidate.dispose()).catch(()=>{}),error instanceof NodePackageInstallErrorV1?error: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}).catch(error=>{if(error.code!=="ENOENT")throw error}),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(error){throw await host.close().catch(()=>{}),error instanceof NodePackageInstallErrorV1?error:new NodePackageInstallErrorV1("installation_io_failed")}return host}import{createHash as createHash5,randomUUID as randomUUID5}from"node:crypto";import{lstatSync as lstatSync2}from"node:fs";import{lstat,readdir,readFile as readFile5}from"node:fs/promises";import{join as join12}from"node:path";function isMissingError2(error){return typeof error!="object"||error===null?!1:"code"in error&&error.code==="ENOENT"}async function collectDirectory(root,relative11,limits,entries,budget,signal){if(signal?.aborted)throw new NodePackageInstallErrorV1("cancelled");let dirents=await readdir(relative11.length===0?root:join12(root,...relative11.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=relative11.length===0?dirent.name:`${relative11}/${dirent.name}`;if(normalizedEntryName(childRelative),dirent.isSymbolicLink())throw new NodePackageInstallErrorV1("archive_invalid");let childPath=join12(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(error=>{throw isMissingError2(error)?new NodePackageInstallErrorV1("archive_invalid"):error});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(path8,limitsInput={},signal){if(signal?.aborted)throw new NodePackageInstallErrorV1("cancelled");if(typeof path8!="string"||path8.trim().length===0)throw new NodePackageInstallErrorV1("archive_invalid");let stats=await lstat(path8).catch(error=>{throw isMissingError2(error)?new NodePackageInstallErrorV1("archive_invalid"):error});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(path8);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;retryAfterSeconds;constructor(code,message,options){super(message,options?.cause===void 0?void 0:{cause:options.cause}),this.name="NodeNpmRegistrySourceErrorV1",this.code=code,options?.retryAfterSeconds!==void 0&&(this.retryAfterSeconds=options.retryAfterSeconds)}};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",t("npm integrity algorithm is unsupported"));let algorithm=match2[1],raw;try{raw=Buffer.from(match2[2],"base64")}catch{throw new NodeNpmRegistrySourceErrorV1("integrity_unsupported",t("npm integrity encoding is invalid"))}if(algorithm==="sha256"&&raw.byteLength!==32||algorithm==="sha512"&&raw.byteLength!==64)throw new NodeNpmRegistrySourceErrorV1("integrity_unsupported",t("npm integrity length is invalid"));let hex=raw.toString("hex").toLowerCase();if(hex.length===0)throw new NodeNpmRegistrySourceErrorV1("integrity_unsupported",t("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",t("{label} must be a positive integer at most {maximum}",{label,maximum}));return result}function registryOrigin(value){let parsed;try{parsed=new URL(value)}catch{throw new NodeNpmRegistrySourceErrorV1("invalid_configuration",t("npm registry origin is invalid"))}if(parsed.protocol!=="http:"&&parsed.protocol!=="https:"||parsed.username!==""||parsed.password!=="")throw new NodeNpmRegistrySourceErrorV1("invalid_configuration",t("npm registry origin must be http(s) without credentials"));if(parsed.pathname!=="/"||parsed.search!==""||parsed.hash!=="")throw new NodeNpmRegistrySourceErrorV1("invalid_configuration",t("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",t("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",t("npm tarball URL is invalid"))}if(parsed.protocol!=="http:"&&parsed.protocol!=="https:"||parsed.username!==""||parsed.password!=="")throw new NodeNpmRegistrySourceErrorV1("invalid_response",t("npm tarball URL must use http(s) without credentials"));if(parsed.hash!=="")throw new NodeNpmRegistrySourceErrorV1("invalid_response",t("npm tarball URL must not include a fragment"));return parsed}function isAbortLike2(error){return error instanceof Error&&(error.name==="AbortError"||error.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"}function rateLimitState(response2){if(!(response2.status===429||response2.status===403&&response2.headers.get("x-ratelimit-remaining")==="0"))return{limited:!1};let retryAfter=response2.headers.get("retry-after"),seconds=retryAfter===null?Number.NaN:Number.parseInt(retryAfter,10);return!Number.isSafeInteger(seconds)||seconds<0?{limited:!0}:{limited:!0,retryAfterSeconds:seconds}}function rateLimitError(limit){let message=limit.retryAfterSeconds===void 0?t("npm registry rate limit was exceeded"):`${t("npm registry rate limit was exceeded")} (retry after ${limit.retryAfterSeconds}s)`;return new NodeNpmRegistrySourceErrorV1("rate_limited",message,{...limit.retryAfterSeconds===void 0?{}:{retryAfterSeconds:limit.retryAfterSeconds}})}async function readBody(response2,maxBytes,request){if(response2.body===null)throw new NodeNpmRegistrySourceErrorV1("invalid_response",t("npm registry response has no body"));let reader=response2.body.getReader(),chunks=[],total=0,abortError2=()=>request.timedOut()?new NodeNpmRegistrySourceErrorV1("request_timed_out",t("npm registry request timed out")):new NodeNpmRegistrySourceErrorV1("cancelled",t("npm registry request was cancelled"));try{for(;;){if(request.signal.aborted)throw abortError2();let item;try{item=await reader.read()}catch(error){throw request.signal.aborted?abortError2():error}if(item.done)break;if(total+=item.value.byteLength,total>maxBytes)throw new NodeNpmRegistrySourceErrorV1("response_too_large",t("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",t("npm registry response is not valid JSON"))}if(typeof value!="object"||value===null||Array.isArray(value))throw new NodeNpmRegistrySourceErrorV1("invalid_response",t("npm packument is invalid"));let packument=value;if(typeof packument.versions!="object"||packument.versions===null||Array.isArray(packument.versions))throw new NodeNpmRegistrySourceErrorV1("invalid_response",t("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",t("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",t("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",t("maxRedirects must be an integer between 0 and {max}",{max: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",t("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(error){throw request.cleanup(),request.timedOut()?new NodeNpmRegistrySourceErrorV1("request_timed_out",t("npm registry request timed out")):isAbortLike2(error)?new NodeNpmRegistrySourceErrorV1("cancelled",t("npm registry request was cancelled")):new NodeNpmRegistrySourceErrorV1("request_failed",t("npm registry request failed"),{cause:error})}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",t("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",t("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{let limit=rateLimitState(response2);if(limit.limited)throw rateLimitError(limit);if(response2.status===404||response2.status===403)throw new NodeNpmRegistrySourceErrorV1("package_not_found",t("npm package was not found on the registry"));if(response2.status<200||response2.status>=300)throw new NodeNpmRegistrySourceErrorV1("request_failed",t("npm registry request did not succeed"));if(!isJsonResponse(response2))throw new NodeNpmRegistrySourceErrorV1("invalid_response",t("npm registry response must be JSON"));let versions=parsePackument(await readBody(response2,maxResponseBytes,request)),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",t("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",t("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",t("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{let limit=rateLimitState(response2);if(limit.limited)throw rateLimitError(limit);if(response2.status<200||response2.status>=300)throw new NodeNpmRegistrySourceErrorV1("request_failed",t("npm tarball download did not succeed"));return await readBody(response2,maxTarballBytes,request)}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",t("{label} must be a positive integer at most {maximum}",{label,maximum}));return result}function packageUrl(value){let parsed;try{parsed=new URL(value)}catch{throw new NodeUrlPackageSourceErrorV1("invalid_url",t("plugin package URL is invalid"))}if(parsed.protocol!=="http:"&&parsed.protocol!=="https:"||parsed.username!==""||parsed.password!=="")throw new NodeUrlPackageSourceErrorV1("invalid_url",t("plugin package URL must use http(s) without credentials"));if(parsed.hash!=="")throw new NodeUrlPackageSourceErrorV1("invalid_url",t("plugin package URL must not include a fragment"));return parsed}function isAbortLike3(error){return error instanceof Error&&(error.name==="AbortError"||error.name==="AbortSignalError")}async function downloadNodeUrlPackageV1(options,input){let transport=options.fetch??globalThis.fetch;if(typeof transport!="function")throw new NodeUrlPackageSourceErrorV1("invalid_configuration",t("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",t("maxRedirects must be an integer between 0 and {max}",{max: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",t("userAgent is invalid"));if(input.expectedDigestHex!==void 0&&!/^[0-9a-f]{64}$/u.test(input.expectedDigestHex))throw new NodeUrlPackageSourceErrorV1("invalid_url",t("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",t("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(error){throw timedOut?new NodeUrlPackageSourceErrorV1("request_timed_out",t("plugin package download timed out")):isAbortLike3(error)||input.signal?.aborted===!0?new NodeUrlPackageSourceErrorV1("cancelled",t("plugin package download was cancelled")):new NodeUrlPackageSourceErrorV1("request_failed",t("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",t("plugin package redirect limit exceeded"));current=packageUrl(new URL(location,current).toString())}if(response2===void 0)throw new NodeUrlPackageSourceErrorV1("request_failed",t("plugin package download failed"));if(response2.status<200||response2.status>=300)throw new NodeUrlPackageSourceErrorV1("request_failed",t("plugin package download did not succeed"));if(response2.body===null)throw new NodeUrlPackageSourceErrorV1("request_failed",t("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",t("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",t("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",t("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",t("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",t("{label} must be a positive integer at most {maximum}",{label,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",t("{label} is invalid",{label}));return value}}function apiOrigin(value,label){let parsed;try{parsed=new URL(value)}catch{throw new NodeReleasePackageSourceErrorV1("invalid_configuration",t("{label} is invalid",{label}))}if(parsed.protocol!=="http:"&&parsed.protocol!=="https:"||parsed.username!==""||parsed.password!=="")throw new NodeReleasePackageSourceErrorV1("invalid_configuration",t("{label} must be http(s) without credentials",{label}));if(parsed.search!==""||parsed.hash!=="")throw new NodeReleasePackageSourceErrorV1("invalid_configuration",t("{label} must not include a query or fragment",{label}));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",t("release API response is not valid JSON"))}}function parseReleaseList(bytes){let value=jsonBytes(bytes);if(!Array.isArray(value))throw new NodeReleasePackageSourceErrorV1("invalid_response",t("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",t("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",t("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",t("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?t("release has no assets"):t("assets: {names}",{names:assetNames}));if(candidates.length>1)throw new NodeReleasePackageSourceErrorV1("release_asset_ambiguous",t("candidates: {names}",{names:candidates.map(asset=>asset.name).join(", ")}));let chosen=candidates[0];if(typeof chosen.url!="string"||chosen.url.length===0)throw new NodeReleasePackageSourceErrorV1("invalid_response",t("release asset has no download URL"));return chosen.url}function isAbortLike4(error){return error instanceof Error&&(error.name==="AbortError"||error.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 rateLimitState2(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",t("release API response has no body"));let reader=response2.body.getReader(),chunks=[],total=0;try{for(;;){if(signal.aborted)throw new DOMException(t("aborted"),"AbortError");let item=await reader.read();if(item.done)break;if(total+=item.value.byteLength,total>maxBytes)throw new NodeReleasePackageSourceErrorV1("response_too_large",t("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",t("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",t("maxRedirects must be an integer between 0 and {max}",{max: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",t("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(error){throw request.cleanup(),request.timedOut()?new NodeReleasePackageSourceErrorV1("request_timed_out",t("release API request timed out")):isAbortLike4(error)?new NodeReleasePackageSourceErrorV1("cancelled",t("release API request was cancelled")):new NodeReleasePackageSourceErrorV1("request_failed",t("release API request failed"))}if(!REDIRECT_STATUS4.has(response2.status))try{if(response2.status===404)throw new NodeReleasePackageSourceErrorV1("release_not_found",t("repo or release was not found"));let limit=rateLimitState2(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",t("release API request did not succeed"));if(!isJsonResponse2(response2))throw new NodeReleasePackageSourceErrorV1("invalid_response",t("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",t("release API redirect limit exceeded"));let next;try{next=new URL(location,current)}catch{throw new NodeReleasePackageSourceErrorV1("invalid_response",t("release API redirect target is invalid"))}if(next.protocol!=="http:"&&next.protocol!=="https:"||next.username!==""||next.password!=="")throw new NodeReleasePackageSourceErrorV1("invalid_response",t("release API redirect must stay http(s)"));current=next}};return{version:1,downloadReleaseAsset:async input=>{if(input.signal?.aborted===!0)throw new NodeReleasePackageSourceErrorV1("cancelled",t("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(segment=>segment!==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",t("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",t("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 index=148;index<148+TAR_CHECKSUM_LENGTH_V12;index+=1)header[index]=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 index=Math.min(bytes.byteLength,TAR_PREFIX_LENGTH_V12)-1;index>=0;index-=1)if(bytes[index]===47){split=index;break}if(split<=0)throw new NodeTarWriterErrorV1("entry_name_too_long",t("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",t("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",t("tar entry name is invalid"));if(normalizedEntryName(entry.directory?`${entry.name}/`:entry.name).name!==entry.name)throw new NodeTarWriterErrorV1("invalid_entry",t("tar entry name is not normalized"));if(entry.directory&&entry.bytes!==void 0&&entry.bytes.byteLength>0)throw new NodeTarWriterErrorV1("invalid_entry",t("tar directory entry must be empty"));if(!entry.directory&&!(entry.bytes instanceof Uint8Array))throw new NodeTarWriterErrorV1("invalid_entry",t("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",t("tar entries must be an array"));let names=new Set,blocks=[];for(let entry of entries){if(names.has(entry.name))throw new NodeTarWriterErrorV1("invalid_entry",t("duplicate tar entry name: {name}",{name:entry.name}));if(names.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:path8=>{let stats=lstatSync2(path8,{throwIfNoEntry:!1});return stats===void 0?"missing":stats.isSymbolicLink()?"other":stats.isDirectory()?"directory":stats.isFile()?"file":"other"}};function mapInstallError(error){return error instanceof PluginAcquisitionErrorV1?error:error instanceof NodePackageInstallErrorV1?error.code==="cancelled"?new PluginAcquisitionErrorV1("cancelled"):error.code==="archive_budget_exceeded"?new PluginAcquisitionErrorV1("budget_exceeded"):error.code==="unsupported_media_type"?new PluginAcquisitionErrorV1("unsupported_media_type"):new PluginAcquisitionErrorV1("package_invalid"):new PluginAcquisitionErrorV1("download_failed")}function mapNpmError(error){return error instanceof PluginAcquisitionErrorV1?error:error instanceof NodeNpmRegistrySourceErrorV1?error.code==="package_not_found"?new PluginAcquisitionErrorV1("package_not_found"):error.code==="version_not_found"?new PluginAcquisitionErrorV1("version_not_found"):error.code==="cancelled"?new PluginAcquisitionErrorV1("cancelled"):error.code==="rate_limited"?new PluginAcquisitionErrorV1("rate_limited",error.retryAfterSeconds===void 0?void 0:`retry after ${error.retryAfterSeconds}s`):error.code==="response_too_large"?new PluginAcquisitionErrorV1("budget_exceeded"):error.code==="request_timed_out"?new PluginAcquisitionErrorV1("download_failed","request timed out"):error.code==="invalid_response"||error.code==="integrity_unsupported"?new PluginAcquisitionErrorV1("package_invalid"):new PluginAcquisitionErrorV1("download_failed"):mapInstallError(error)}function mapUrlError(error){return error instanceof PluginAcquisitionErrorV1?error:error instanceof NodeUrlPackageSourceErrorV1?error.code==="digest_mismatch"?new PluginAcquisitionErrorV1("digest_mismatch"):error.code==="cancelled"?new PluginAcquisitionErrorV1("cancelled"):error.code==="invalid_url"||error.code==="invalid_configuration"?new PluginAcquisitionErrorV1("invalid_ref"):error.code==="response_too_large"?new PluginAcquisitionErrorV1("budget_exceeded"):new PluginAcquisitionErrorV1("download_failed"):mapInstallError(error)}function mapReleaseError(error){return error instanceof PluginAcquisitionErrorV1?error:error instanceof NodeReleasePackageSourceErrorV1?error.code==="cancelled"?new PluginAcquisitionErrorV1("cancelled"):error.code==="invalid_configuration"?new PluginAcquisitionErrorV1("invalid_ref"):error.code==="response_too_large"?new PluginAcquisitionErrorV1("budget_exceeded"):error.code==="invalid_response"?new PluginAcquisitionErrorV1("package_invalid"):error.code==="rate_limited"?new PluginAcquisitionErrorV1("rate_limited",error.resetEpochSeconds===void 0?void 0:`rate limit resets at ${new Date(error.resetEpochSeconds*1e3).toISOString()}`):error.code==="release_not_found"||error.code==="release_asset_not_found"||error.code==="release_asset_ambiguous"?new PluginAcquisitionErrorV1(error.code,error.message):new PluginAcquisitionErrorV1("download_failed"):mapUrlError(error)}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(error){throw mapReleaseError(error)}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(error){throw mapNpmError(error)}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(error){throw mapUrlError(error)}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(error){throw mapInstallError(error)}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(error){throw mapInstallError(error)}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(error){throw error instanceof PluginAcquisitionErrorV1?error: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(error){throw mapInstallError(error)}let identity=pluginAcquisitionManifestFromEntriesV1(entries);if(closed)throw new PluginAcquisitionErrorV1("cancelled");let artifactRef=`plugin-acquisition://node/${randomUUID5()}`,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 NODE_HTTP_PLUGIN_REGISTRY_SOURCE_VERSION_V1=1,DEFAULT_TIMEOUT_MS_V15=15e3,MAX_TIMEOUT_MS_V15=12e4,DEFAULT_MAX_RESPONSE_BYTES_V13=4*1024*1024,MAX_RESPONSE_BYTES_V13=8*1024*1024,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",t("{label} must be a positive integer at most {maximum}",{label,maximum}));return result}function allowedOrigin2(value){let parsed;try{parsed=new URL(value)}catch{throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration",t("Allowed registry origin is invalid"))}if(parsed.protocol!=="http:"&&parsed.protocol!=="https:"||parsed.username||parsed.password)throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration",t("Allowed registry origin must be an http(s) origin without credentials"));if(parsed.pathname!=="/"||parsed.search!==""||parsed.hash!=="")throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration",t("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",t("Plugin registry URL is invalid"))}if(parsed.protocol!=="http:"&&parsed.protocol!=="https:"||parsed.username||parsed.password)throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration",t("Plugin registry URL must use http(s) without credentials"));if(parsed.search!==""||parsed.hash!=="")throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration",t("Plugin registry URL must not include a query or fragment"));if(!origins.has(parsed.origin))throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration",t("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",t("Plugin registry response length is invalid"));let value=Number(raw);if(!Number.isSafeInteger(value))throw new NodeHttpPluginRegistrySourceErrorV1("invalid_response",t("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",t("Plugin registry response has no body"));let reader=response2.body.getReader(),chunks=[],total=0;try{for(;;){if(signal.aborted)throw new DOMException(t("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",t("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",t("Plugin registry response is not valid JSON"))}if(typeof value!="object"||value===null||Array.isArray(value))throw new NodeHttpPluginRegistrySourceErrorV1("invalid_response",t("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",t("Plugin registry document is invalid"));return document.entries}function isAbortLike5(error){return error instanceof DOMException&&error.name==="AbortError"}function isCallerCancelled(signal){return signal?.aborted===!0}function sanitizedSourceError(error){let code=error.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",t("Plugin registry request failed")):new NodeHttpPluginRegistrySourceErrorV1(code,t("Plugin registry request failed"))}function createNodeHttpPluginRegistrySourceV1(options){let transport=options.fetch??globalThis.fetch;if(typeof transport!="function")throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration",t("Node fetch is unavailable"));if(!Array.isArray(options.allowedOrigins)||options.allowedOrigins.length===0)throw new NodeHttpPluginRegistrySourceErrorV1("invalid_configuration",t("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,DEFAULT_TIMEOUT_MS_V15,MAX_TIMEOUT_MS_V15,"requestTimeoutMs"),maxResponseBytes=boundedPositive5(options.maxResponseBytes,DEFAULT_MAX_RESPONSE_BYTES_V13,MAX_RESPONSE_BYTES_V13,"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",t("userAgent is invalid"));let source=endpoint.origin+endpoint.pathname;return{version:NODE_HTTP_PLUGIN_REGISTRY_SOURCE_VERSION_V1,source,list:async({signal}={})=>{if(isCallerCancelled(signal))throw new NodeHttpPluginRegistrySourceErrorV1("cancelled",t("Plugin registry request was cancelled"));let request=requestController(signal,timeoutMs),response2;try{let transportResponse=Promise.resolve().then(()=>{if(request.signal.aborted)throw new DOMException(t("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",t("Plugin registry request did not succeed"));if(!isJsonResponse3(receivedResponse))throw new NodeHttpPluginRegistrySourceErrorV1("invalid_response",t("Plugin registry response must be JSON"));let length=responseLength(receivedResponse);if(length!==void 0&&length>maxResponseBytes)throw new NodeHttpPluginRegistrySourceErrorV1("response_too_large",t("Plugin registry response exceeds the configured size limit"));return parseDocument(await readBody3(receivedResponse,maxResponseBytes,request.signal))}catch(error){throw isCallerCancelled(signal)?new NodeHttpPluginRegistrySourceErrorV1("cancelled",t("Plugin registry request was cancelled")):request.timedOut()?new NodeHttpPluginRegistrySourceErrorV1("request_timed_out",t("Plugin registry request timed out")):error instanceof NodeHttpPluginRegistrySourceErrorV1?sanitizedSourceError(error):isAbortLike5(error)?new NodeHttpPluginRegistrySourceErrorV1("cancelled",t("Plugin registry request was cancelled")):new NodeHttpPluginRegistrySourceErrorV1("request_failed",t("Plugin registry request failed"))}finally{request.cleanup(),discardResponseBody(response2)}}}}function createPluginEcosystemRegistryAdapterV1(registry){if(registry.resolve===void 0)throw new PluginRegistryErrorV1("invalid_source",t("Registry does not expose a host-side package resolver"));let resolve22=registry.resolve,list=registry.listManifests;return{...list===void 0?{}:{list},resolve:resolve22}}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:join13(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(t("{env} must be a JSON array of {keyId, publicKeyPem}",{env:DEFAULT_PLUGIN_TRUST_KEYS_ENV_V1}))}if(!Array.isArray(parsed))throw new Error(t("{env} must be a JSON array",{env:DEFAULT_PLUGIN_TRUST_KEYS_ENV_V1}));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:join13(options.agentDir,DEFAULT_PLUGIN_STATE_FILE_V1)}),projectStateStore:createPluginStateStoreV1({filePath:join13(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(error){failure2=error}try{await distributionHost.close()}catch(error){failure2===void 0&&(failure2=error)}if(failure2!==void 0)throw failure2})()),closePromise);return Object.freeze({distributionHost,distribution:distributionHost.distribution,packageHost,installer,close})}catch(error){throw await packageHost.close().catch(()=>{}),error}}catch(error){throw await distributionHost.close().catch(()=>{}),error}}import{randomUUID as randomUUID6}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 dirname6,isAbsolute as isAbsolute7,join as join14,resolve as resolve4}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(error){return error instanceof Error&&(error.name==="AbortError"||error.name==="AbortSignalError")}function isMissingError3(error){return typeof error=="object"&&error!==null&&"code"in error&&error.code==="ENOENT"}function validateFilePath2(value){if(typeof value!="string"||value.trim()===""||value.length>MAX_PLUGIN_SELECTION_STORE_PATH_CHARS_V1)throw new Error(t("invalid plugin selection file path"));if(value.includes("\0")||/[\u0000-\u001f]/u.test(value))throw new Error(t("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(t("invalid plugin selection file path"));let normalized=isAbsolute7(value)?value:resolve4(value);if(basename3(normalized).length===0||basename3(normalized)==="."||basename3(normalized)==="..")throw new Error(t("invalid plugin selection file path"));return normalized}function isObject2(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(!isObject2(value)||!hasExactKeys3(value,["profileId","selectedPluginIds","disabledPluginIds"]))throw new Error(t("selection schema is invalid"));if(!Array.isArray(value.selectedPluginIds)||!Array.isArray(value.disabledPluginIds))throw new Error(t("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(t("too many plugin IDs"));return createPluginSelectionV1({profileId:value.profileId,selectedPluginIds:value.selectedPluginIds,disabledPluginIds:value.disabledPluginIds})}function validateSnapshot2(value){if(!isObject2(value)||!hasExactKeys3(value,["version","selections"]))throw new Error(t("snapshot schema is invalid"));if(value.version!==PLUGIN_SELECTION_STORE_VERSION_V1)throw new Error(t("snapshot version is unsupported"));if(!Array.isArray(value.selections))throw new Error(t("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(error){let message=error instanceof Error?error.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 path8=>await readFile6(path8,"utf8"),mkdir:async path8=>{await mkdir5(path8,{recursive:!0})},writeFile:async(path8,data)=>{await writeFile4(path8,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(error){if(isMissingError3(error))return Object.freeze({status:"missing",snapshot:EMPTY_SNAPSHOT2});if(isAbortError2(error)||signal?.aborted)return cancelledResult2();throw error}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(error){return Object.freeze({status:"invalid",diagnostics:Object.freeze([invalidFromError2(error)])})}}async function write(snapshot2,signal){if(signal?.aborted)return cancelledResult2();let temporaryPath=join14(dirname6(filePath),`.${basename3(filePath)}.${randomUUID6()}.tmp`);try{return await fileSystem.mkdir(dirname6(filePath)),signal?.aborted||(await fileSystem.writeFile(temporaryPath,`${JSON.stringify({version:snapshot2.version,selections:snapshot2.selections.map(persistedSelection)})}
|
|
218
218
|
`),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(error){return Object.freeze({status:"invalid",diagnostics:Object.freeze([invalidFromError2(error)])})}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(error){return Object.freeze({status:"invalid",diagnostics:Object.freeze([invalidFromError2(error)])})}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,b)=>a.id.localeCompare(b.id)||a.version-b.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"]},{id:"desktop-observe-macos",version:"1",pluginIds:["agent-forge.plugin.desktop-macos-observe"]},{id:"desktop-control-macos",version:"1",pluginIds:["agent-forge.plugin.desktop-macos-observe","agent-forge.plugin.desktop-macos-input"]},{id:"desktop-qa-macos",version:"1",pluginIds:["agent-forge.plugin.desktop-macos-observe","agent-forge.plugin.desktop-macos-input"]}]);function listBuiltinPluginProfilesV1(){return profiles}function isBuiltinPluginProfileIdV1(value){return profiles.some(profile=>profile.id===value)}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(t("builtin manifest override does not match plugin {pluginId}",{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(t("{label} is invalid",{label}));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(state,pluginId){return state.records.filter(record=>record.pluginId===pluginId&&record.state.lifecycle==="active").sort((left,right)=>comparePluginVersionsV1(right.pluginVersion,left.pluginVersion))[0]}function makeSnapshot(registry,stateStatus,state){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(state,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 state;try{state=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(state);return checkedState===void 0?{status:"error",code:state.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,fsyncSync,mkdirSync as mkdirSync2,openSync,readFileSync as readFileSync2,statSync as statSync2,unlinkSync,writeFileSync as writeFileSync2,writeSync}from"node:fs";import{dirname as dirname7,join as join15}from"node:path";var DurableServiceErrorV1=class extends Error{code;constructor(code,message){super(message),this.name="DurableServiceErrorV1",this.code=code}};function durableLogPath(agentDir,sessionId){return join15(agentDir,"durable",`${sessionId}.jsonl`)}function assertNonEmptyString2(value,label){if(typeof value!="string"||value.trim().length===0)throw new Error(t("{label} must be a non-empty string",{label}))}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(;;){mkdirSync2(dirname7(lockPath),{recursive:!0});let token=`${process.pid}:${Date.now()}`;try{let fd=openSync(lockPath,"wx");try{writeFileSync2(fd,token)}finally{closeSync(fd)}return token}catch(error){let code=error.code;if(code==="EPERM"){let vanished=!1;try{statSync2(lockPath)}catch(statError){if(statError.code!=="ENOENT")throw error;vanished=!0}if(vanished){if(Date.now()>=deadline)throw error;sleepSync(LOCK_POLL_INTERVAL_MS);continue}}else if(code!=="EEXIST")throw error;let stale=!1;try{stale=Date.now()-statSync2(lockPath).mtimeMs>staleLockMs}catch{}if(stale){try{unlinkSync(lockPath)}catch{}continue}if(Date.now()>=deadline)throw new Error(t("durable store persist lock timeout after {timeoutMs} ms: {lockPath} is held by another writer",{timeoutMs:lockTimeoutMs,lockPath}));sleepSync(LOCK_POLL_INTERVAL_MS)}}}function releasePersistLock(lockPath,token){try{readFileSync2(lockPath,"utf8")===token&&unlinkSync(lockPath)}catch{}}function createFileDurableStoreBackend(options){if(assertNonEmptyString2(options.path,"Durable store path"),options.lockTimeoutMs!==void 0&&(!Number.isFinite(options.lockTimeoutMs)||options.lockTimeoutMs<=0))throw new Error(t("Durable store lockTimeoutMs must be a positive number"));if(options.staleLockMs!==void 0&&(!Number.isFinite(options.staleLockMs)||options.staleLockMs<=0))throw new Error(t("Durable store staleLockMs must be a positive number"));if(options.leaseTtlMs!==void 0&&(!Number.isFinite(options.leaseTtlMs)||options.leaseTtlMs<=0))throw new Error(t("Durable store leaseTtlMs must be a positive number"));let path8=options.path,lockTimeoutMs=options.lockTimeoutMs??DEFAULT_LOCK_TIMEOUT_MS,staleLockMs=options.staleLockMs??DEFAULT_STALE_LOCK_MS,leaseTtlMs=options.leaseTtlMs??DEFAULT_LEASE_TTL_MS,lockPath=`${path8}${LOCK_FILE_SUFFIX}`,leasePath=`${path8}${LEASE_FILE_SUFFIX}`,readLease=()=>{try{let value=JSON.parse(readFileSync2(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=openSync(leasePath,"w");try{writeAllSync(fd,JSON.stringify({writerId,expiresAt}))}finally{closeSync(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))}
|
|
219
219
|
`),token=acquirePersistLock(lockPath,lockTimeoutMs,staleLockMs);try{let fd=openSync(path8,"a");try{writeAllSync(fd,lines.join("")),fsyncSync(fd)}finally{closeSync(fd)}}finally{releasePersistLock(lockPath,token)}},load(){let raw;try{raw=readFileSync2(path8,"utf8")}catch(error){return error.code==="ENOENT"?{operations:[],corruptedLines:0,unreadable:!1}:{operations:[],corruptedLines:0,unreadable:!0}}let operations=[],corruptedLines=0;for(let line of raw.split(`
|
|
220
220
|
`)){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",t("Writer {writerId} does not hold the store lease (held by {holder})",{writerId,holder: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",t("Writer {writerId} lost the store lease (expired or recovered by another writer)",{writerId}));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(t("{label} must be an object",{label}))}function importRecordBase(value,idField,label){let id=value[idField];if(typeof id!="string"||id.length===0)throw new Error(t("{label} {idField} must be a non-empty string",{label,idField}));let persistedAt=value.persistedAt;if(typeof persistedAt!="number"||!Number.isFinite(persistedAt))throw new Error(t("{label} persistedAt must be a finite number",{label}));return{id,data:value.data,persistedAt}}function importOwningSessionId(value,label){let sessionId=value.sessionId;if(typeof sessionId!="string"||sessionId.length===0)throw new Error(t("{label} sessionId must be a non-empty string",{label}));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",t("Writer {writerId} does not hold the writer lease",{writerId}));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,b)=>a.sessionId<b.sessionId?-1:a.sessionId>b.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",t("Writer {writerId} cannot release a crashed lease; recover it instead",{writerId}));if(backendLease===void 0){if(holder!==null&&holder!==writerId)throw new DurableServiceErrorV1("not_writer",t("Writer {writerId} does not hold the writer lease (held by {holder})",{writerId,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(t("Unsupported durable snapshot version: {version}",{version:String(snapshot2.version)}));for(let field2 of["sessions","operations","artifacts"])if(!Array.isArray(snapshot2[field2]))throw new Error(t("Durable snapshot {field} must be an array",{field:field2}));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(t("Durable snapshot writer holder must be a string or null"));if(snapshotCrashPending!==null&&typeof snapshotCrashPending!="string")throw new Error(t("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 randomUUID10}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 dirname8}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(path8,options={}){if(this.path=path8,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(dirname8(this.path),{recursive:!0}),await appendFile(this.path,`${JSON.stringify(record)}
|
|
@@ -586,9 +586,9 @@ export default function createMcpStdioServerPlugin(config) {
|
|
|
586
586
|
`)[0]??stderr),parts.length===0?null:`trash: ${parts.join(" \xB7 ").slice(0,200)}`};if(trashResult.status===0||!existsSync19(sessionPath))return{ok:!0,method:"trash"};try{return await unlink3(sessionPath),{ok:!0,method:"unlink"}}catch(err){let unlinkError=err instanceof Error?err.message:String(err),trashErrorHint=getTrashErrorHint();return{ok:!1,method:"unlink",error:trashErrorHint?`${unlinkError} (${trashErrorHint})`:unlinkError}}}var SessionSelectorComponent=class extends Container{handleInput(data){if(this.mode==="rename"){if(getKeybindings().matches(data,"tui.select.cancel")){this.exitRenameMode();return}this.renameInput.handleInput(data);return}this.sessionList.handleInput(data)}canRename=!0;sessionList;header;keybindings;scope="current";sortMode="threaded";nameFilter="all";suiteFilterOptions=void 0;suiteFilter="current";currentSessions=null;allSessions=null;currentSessionsLoader;allSessionsLoader;requestRender;renameSession;currentLoad=null;allLoad=null;mode="list";renameInput=new Input;renameTargetPath=null;_focused=!1;get focused(){return this._focused}set focused(value){this._focused=value,this.sessionList.focused=value,this.renameInput.focused=value,value&&this.mode==="rename"&&(this.renameInput.focused=!0)}buildBaseLayout(content,options){this.clear(),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder(s=>theme.fg("accent",s))),this.addChild(new Spacer(1)),(options?.showHeader??!0)&&(this.addChild(this.header),this.addChild(new Spacer(1))),this.addChild(content),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder(s=>theme.fg("accent",s)))}constructor(currentSessionsLoader,allSessionsLoader,onSelect,onCancel,onExit,requestRender,options,currentSessionFilePath){super(),this.keybindings=options?.keybindings??KeybindingsManager2.create(),this.currentSessionsLoader=currentSessionsLoader,this.allSessionsLoader=allSessionsLoader,this.requestRender=requestRender,this.suiteFilterOptions=options?.suiteFilter,this.header=new SessionSelectorHeader(this.scope,this.sortMode,this.nameFilter,this.requestRender),this.suiteFilterOptions&&this.header.setSuiteTitle(this.suiteTitle());let renameSession=options?.renameSession;this.renameSession=renameSession,this.canRename=!!renameSession,this.header.setShowRenameHint(options?.showRenameHint??this.canRename),this.sessionList=new SessionList([],!1,this.sortMode,this.nameFilter,this.keybindings,currentSessionFilePath),this.suiteFilterOptions&&this.sessionList.setSuiteFilterContext(this.suiteFilterOptions),this.sessionList.onToggleSuiteFilter=()=>this.toggleSuiteFilter(),this.buildBaseLayout(this.sessionList),this.renameInput.onSubmit=value=>{this.confirmRename(value)};let clearStatusMessage=()=>this.header.setStatusMessage(null);this.sessionList.onSelect=sessionPath=>{clearStatusMessage(),this.cancelLoads(),onSelect(sessionPath)},this.sessionList.onCancel=()=>{clearStatusMessage(),this.cancelLoads(),onCancel()},this.sessionList.onExit=()=>{clearStatusMessage(),this.cancelLoads(),onExit()},this.sessionList.onToggleScope=()=>this.toggleScope(),this.sessionList.onToggleSort=()=>this.toggleSortMode(),this.sessionList.onToggleNameFilter=()=>this.toggleNameFilter(),this.sessionList.onRenameSession=sessionPath=>{if(!renameSession||(this.scope==="current"?this.currentLoad:this.allLoad))return;let session=(this.scope==="all"?this.allSessions??[]:this.currentSessions??[]).find(s=>s.path===sessionPath);this.enterRenameMode(sessionPath,session?.name)},this.sessionList.onTogglePath=showPath=>{this.header.setShowPath(showPath),this.requestRender()},this.sessionList.onDeleteConfirmationChange=path8=>{this.header.setConfirmingDeletePath(path8),this.requestRender()},this.sessionList.onError=msg=>{this.header.setStatusMessage({type:"error",message:msg},3e3),this.requestRender()},this.sessionList.onDeleteSession=async sessionPath=>{let result=await deleteSessionFile(sessionPath);if(result.ok){try{removeSessionFromIndex(sessionPath)}catch{}this.currentSessions&&(this.currentSessions=this.currentSessions.filter(s=>s.path!==sessionPath)),this.allSessions&&(this.allSessions=this.allSessions.filter(s=>s.path!==sessionPath));let sessions=this.scope==="all"?this.allSessions??[]:this.currentSessions??[],showCwd=this.scope==="all";this.sessionList.setSessions(sessions,showCwd);let msg=result.method==="trash"?t("Session moved to trash"):t("Session deleted");this.header.setStatusMessage({type:"info",message:msg},2e3),await this.refreshSessionsAfterMutation()}else{let errorMessage2=result.error??t("Unknown error");this.header.setStatusMessage({type:"error",message:t("Failed to delete: {error}",{error:errorMessage2})},3e3)}this.requestRender()},this.loadScope("current")}cancelLoads(){this.currentLoad&&(this.currentLoad.abort(),this.currentLoad=null,this.currentSessions=null),this.allLoad&&(this.allLoad.abort(),this.allLoad=null,this.allSessions=null)}enterRenameMode(sessionPath,currentName){this.mode="rename",this.renameTargetPath=sessionPath,this.renameInput.setValue(currentName??""),this.renameInput.focused=!0;let panel=new Container;panel.addChild(new Text(theme.bold(t("Rename Session")),1,0)),panel.addChild(new Spacer(1)),panel.addChild(this.renameInput),panel.addChild(new Spacer(1)),panel.addChild(new Text(theme.fg("muted",t("{confirm} to save \xB7 {cancel} to cancel",{confirm:keyText("tui.select.confirm"),cancel:keyText("tui.select.cancel")})),1,0)),this.buildBaseLayout(panel,{showHeader:!1}),this.requestRender()}exitRenameMode(){this.mode="list",this.renameTargetPath=null,this.buildBaseLayout(this.sessionList),this.requestRender()}async confirmRename(value){let next=value.trim();if(!next)return;let target=this.renameTargetPath;if(!target){this.exitRenameMode();return}let renameSession=this.renameSession;if(!renameSession){this.exitRenameMode();return}try{await renameSession(target,next),await this.refreshSessionsAfterMutation()}catch(error){this.header.setStatusMessage({type:"error",message:error instanceof Error?error.message:String(error)},3e3),this.requestRender()}finally{this.exitRenameMode()}}async loadScope(scope){if(scope==="current"?this.currentLoad:this.allLoad)return;let showCwd=scope==="all",controller=new AbortController;scope==="current"?this.currentLoad=controller:this.allLoad=controller,this.header.setScope(scope),this.header.setLoading(!0),this.requestRender();let isActive=()=>(scope==="current"?this.currentLoad:this.allLoad)===controller,onProgress=(loaded,total,partialSessions)=>{if(isActive()){if(partialSessions){let sessions=[...partialSessions];scope==="current"?this.currentSessions=sessions:this.allSessions=sessions,scope===this.scope&&this.sessionList.setSessions(sessions,showCwd)}scope===this.scope&&(this.header.setProgress(loaded,total),this.requestRender())}};try{let sessions=await(scope==="current"?this.currentSessionsLoader(onProgress,controller.signal):this.allSessionsLoader(onProgress,controller.signal));if(!isActive()||(scope==="current"?(this.currentSessions=sessions,this.currentLoad=null):(this.allSessions=sessions,this.allLoad=null),scope!==this.scope))return;this.header.setLoading(!1),this.sessionList.setSessions(sessions,showCwd),this.requestRender()}catch(err){if(!isActive()||(scope==="current"?(this.currentLoad=null,this.currentSessions=null):(this.allLoad=null,this.allSessions=null),scope!==this.scope))return;let message=err instanceof Error?err.message:String(err);this.header.setLoading(!1),this.header.setStatusMessage({type:"error",message:t("Failed to load sessions: {message}",{message})},4e3),this.sessionList.setSessions([],showCwd),this.requestRender()}}toggleSortMode(){this.sortMode=this.sortMode==="threaded"?"recent":this.sortMode==="recent"?"relevance":"threaded",this.header.setSortMode(this.sortMode),this.sessionList.setSortMode(this.sortMode),this.requestRender()}toggleNameFilter(){this.nameFilter=this.nameFilter==="all"?"named":"all",this.header.setNameFilter(this.nameFilter),this.sessionList.setNameFilter(this.nameFilter),this.requestRender()}suiteTitle(){return this.suiteFilter==="all"?t("Resume Session (All Suites)"):t("Resume Session (Suite: {suite})",{suite:this.suiteFilterOptions?.currentSuiteId??"unbound"})}toggleSuiteFilter(){this.suiteFilterOptions&&(this.suiteFilter=this.suiteFilter==="current"?"all":"current",this.header.setSuiteTitle(this.suiteTitle()),this.sessionList.setSuiteFilter(this.suiteFilter),this.requestRender())}async refreshSessionsAfterMutation(){this.cancelLoads(),this.currentSessions=null,this.allSessions=null,await this.loadScope(this.scope)}toggleScope(){this.scope=this.scope==="current"?"all":"current";let sessions=this.scope==="current"?this.currentSessions:this.allSessions,loading=(this.scope==="current"?this.currentLoad:this.allLoad)!==null;this.header.setScope(this.scope),this.header.setLoading(loading),this.sessionList.setSessions(sessions??[],this.scope==="all"),this.requestRender(),sessions===null&&!loading&&this.loadScope(this.scope)}getSessionList(){return this.sessionList}};var CountdownTimer=class{intervalId;remainingSeconds;tui;onTick;onExpire;constructor(timeoutMs,tui,onTick,onExpire){this.tui=tui,this.onTick=onTick,this.onExpire=onExpire,this.remainingSeconds=Math.ceil(timeoutMs/1e3),this.onTick(this.remainingSeconds),this.intervalId=setInterval(()=>{this.remainingSeconds--,this.onTick(this.remainingSeconds),this.tui?.requestRender(),this.remainingSeconds<=0&&(this.dispose(),this.onExpire())},1e3)}dispose(){this.intervalId&&(clearInterval(this.intervalId),this.intervalId=void 0)}};var DialogInputComponent=class extends Container{input;onSubmitCallback;onCancelCallback;titleText;baseTitle;countdown;_focused=!1;get focused(){return this._focused}set focused(value){this._focused=value,this.input.focused=value}constructor(title,_placeholder,onSubmit,onCancel,opts){super(),this.onSubmitCallback=onSubmit,this.onCancelCallback=onCancel,this.baseTitle=title,this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.titleText=new Text(theme.fg("accent",title),1,0),this.addChild(this.titleText),this.addChild(new Spacer(1)),opts?.timeout&&opts.timeout>0&&opts.tui&&(this.countdown=new CountdownTimer(opts.timeout,opts.tui,s=>this.titleText.setText(theme.fg("accent",`${this.baseTitle} (${s}s)`)),()=>this.onCancelCallback())),this.input=new Input,this.addChild(this.input),this.addChild(new Spacer(1)),this.addChild(new Text(`${keyHint("tui.select.confirm",t("submit"))} ${keyHint("tui.select.cancel",t("cancel"))}`,1,0)),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder)}handleInput(keyData){let kb=getKeybindings();kb.matches(keyData,"tui.select.confirm")||keyData===`
|
|
587
587
|
`?this.onSubmitCallback(this.input.getValue()):kb.matches(keyData,"tui.select.cancel")?this.onCancelCallback():this.input.handleInput(keyData)}dispose(){this.countdown?.dispose()}};var DialogSelectorComponent=class extends Container{options;selectedIndex=0;listContainer;onSelectCallback;onCancelCallback;titleText;baseTitle;countdown;onToggleToolsExpanded;constructor(title,options,onSelect,onCancel,opts){super(),this.options=options,this.onSelectCallback=onSelect,this.onCancelCallback=onCancel,this.onToggleToolsExpanded=opts?.onToggleToolsExpanded,this.baseTitle=title,this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.titleText=new Text(theme.fg("accent",theme.bold(title)),1,0),this.addChild(this.titleText),this.addChild(new Spacer(1)),opts?.timeout&&opts.timeout>0&&opts.tui&&(this.countdown=new CountdownTimer(opts.timeout,opts.tui,s=>this.titleText.setText(theme.fg("accent",theme.bold(`${this.baseTitle} (${s}s)`))),()=>this.onCancelCallback())),this.listContainer=new Container,this.addChild(this.listContainer),this.addChild(new Spacer(1)),this.addChild(new Text(rawKeyHint("\u2191\u2193",t("navigate"))+" "+keyHint("tui.select.confirm",t("select"))+" "+keyHint("tui.select.cancel",t("cancel")),1,0)),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),this.updateList()}updateList(){this.listContainer.clear();for(let i=0;i<this.options.length;i++){let text=i===this.selectedIndex?theme.fg("accent","\u2192 ")+theme.fg("accent",this.options[i]):` ${theme.fg("text",this.options[i])}`;this.listContainer.addChild(new Text(text,1,0))}}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"app.tools.expand"))this.onToggleToolsExpanded?.();else if(kb.matches(keyData,"tui.select.up")||keyData==="k")this.selectedIndex=Math.max(0,this.selectedIndex-1),this.updateList();else if(kb.matches(keyData,"tui.select.down")||keyData==="j")this.selectedIndex=Math.min(this.options.length-1,this.selectedIndex+1),this.updateList();else if(kb.matches(keyData,"tui.select.confirm")||keyData===`
|
|
588
588
|
`){let selected=this.options[this.selectedIndex];selected&&this.onSelectCallback(selected)}else kb.matches(keyData,"tui.select.cancel")&&this.onCancelCallback()}dispose(){this.countdown?.dispose()}};function createProfileMigrationPolicy(){return{planMigration({lock,current}){return current.manifestDigest===lock.identity.manifestDigest&¤t.profileVersion===lock.identity.profileVersion?{status:"current",fromProfileVersion:lock.identity.profileVersion,toProfileVersion:current.profileVersion,needsExplicitMigration:!1}:current.profileVersion!==lock.identity.profileVersion?{status:"migration_required",fromProfileVersion:lock.identity.profileVersion,toProfileVersion:current.profileVersion,needsExplicitMigration:!0,reason:`Profile version changed from ${lock.identity.profileVersion} to ${current.profileVersion}`}:{status:"drift",fromProfileVersion:lock.identity.profileVersion,toProfileVersion:current.profileVersion,needsExplicitMigration:!0,reason:"Resolved manifest digest differs from the locked profile identity"}},applyMigration({lock,current,authorizedBy,now}){if(authorizedBy.trim().length===0)return{status:"failed",lock,reason:"Migration requires a non-empty authorizedBy"};if(this.planMigration({lock,current}).status==="current")return{status:"current",lock};let nextLock;try{nextLock=createProfileLock(current,{lockedBy:authorizedBy,...now===void 0?{}:{now}})}catch(error){return{status:"failed",lock,reason:error instanceof Error?error.message:String(error)}}return{status:"migrated",lock:nextLock}}}}import{randomUUID as randomUUID14}from"node:crypto";import{closeSync as closeSync3,cpSync,existsSync as existsSync20,mkdirSync as mkdirSync11,openSync as openSync3,readdirSync as readdirSync10,readFileSync as readFileSync19,readSync as readSync2,renameSync,statSync as statSync11,writeFileSync as writeFileSync11}from"node:fs";import{readdir as readdir2,rm as rm4,stat as stat2}from"node:fs/promises";import{basename as basename12,join as join36}from"node:path";import{StringDecoder as StringDecoder2}from"node:string_decoder";var SUITE_TRASH_DIR_NAME=".trash",DEFAULT_SUITE_TRASH_RETENTION_MS=10080*60*1e3,SUITE_DELETE_CONFIRM_TOKEN="suite-delete",SUITE_RESET_AUTHORIZED_BY="suite-reset",SuiteLifecycleError=class extends Error{operation;suiteId;reasons;constructor(operation,suiteId,reasons){super(`Suite ${operation} failed for "${suiteId}": ${reasons.join("; ")}`),this.name="SuiteLifecycleError",this.operation=operation,this.suiteId=suiteId,this.reasons=Object.freeze([...reasons])}};function createSuite(options){let{agentDir,id}=options,suiteDir=getSuiteWorkspaceDir(agentDir,id),suiteJsonPath=join36(suiteDir,SUITE_MANIFEST_FILENAME),reasons=[];if(isValidSuiteId(id)||reasons.push(`id must be a suite id (^[a-z0-9-]+$, no leading/trailing hyphen, Windows reserved names rejected), found ${JSON.stringify(id)}`),isBuiltinSuiteId(id)&&reasons.push(`"${id}" is a builtin suite id; builtin workspaces are provisioned automatically and cannot be created`),existsSync20(suiteDir)&&reasons.push(`workspace directory ${suiteDir} already exists`),reasons.length>0)throw new SuiteLifecycleError("create",id,reasons);let definition;if(options.cloneFrom===void 0)definition={schemaVersion:1,id,name:options.name??id,builtin:!1,tools:BUILTIN_SUITE_TOOLS,capabilities:BUILTIN_SUITE_CAPABILITIES,associations:{skills:[],mcp:[],plugins:[],roles:DEFAULT_ROLE_ASSOCIATIONS},inheritSystemAgentsMd:!1,memory:"assistant",orientation:"assistant",model:null,thinking:null,clonedFrom:null,factoryRevision:7},mkdirSync11(suiteDir,{recursive:!0}),writeFileSync11(suiteJsonPath,serializeSuiteJson(definition),"utf8"),writeFileSync11(join36(suiteDir,SUITE_AGENTS_MD_FILENAME),"","utf8");else{let source=loadEffectiveSourceWorkspace(agentDir,options.cloneFrom);definition={...source.suite,id,name:options.name??`${source.suite.name} clone`,builtin:!1,clonedFrom:{id:source.suite.id,digest:suiteManifestDigest(source.suite),at:options.now?.()??Date.now()},factoryRevision:7},cpSync(source.suiteDir,suiteDir,{recursive:!0,filter:sourcePath=>basename12(sourcePath)!==SUITE_LOCK_FILENAME}),writeFileSync11(suiteJsonPath,serializeSuiteJson(definition),"utf8")}return{suiteId:id,suiteDir,suiteJsonPath,definition}}function loadEffectiveSourceWorkspace(agentDir,cloneFrom){try{return loadSuiteWorkspace({agentDir,suiteId:cloneFrom})}catch(error){throw error instanceof SuiteResolutionError?new SuiteLifecycleError("create",cloneFrom,[`clone source "${cloneFrom}" does not exist`]):new SuiteLifecycleError("create",cloneFrom,[`clone source "${cloneFrom}" is unusable: ${error instanceof Error?error.message:String(error)}`])}}var SUITE_REF_SCAN_LIMIT_BYTES=1024*1024,SUITE_REF_READ_BUFFER_SIZE=64*1024;function findSuiteSessionRefs(agentDir,suiteId){let sessionsDir=join36(agentDir,"sessions");if(!existsSync20(sessionsDir))return[];let refs=[];for(let projectEntry of readdirSync10(sessionsDir,{withFileTypes:!0})){if(!projectEntry.isDirectory())continue;let projectDir=join36(sessionsDir,projectEntry.name),files;try{files=readdirSync10(projectDir).filter(file=>file.endsWith(".jsonl"))}catch{continue}for(let file of files){let path8=join36(projectDir,file);try{let outcome=scanSessionFileForSuiteBinding(path8,suiteId);outcome.bound&&outcome.sessionId!==void 0&&refs.push({path:path8,sessionId:outcome.sessionId,cwd:outcome.cwd,modified:statSync11(path8).mtime})}catch{}}}return refs}function scanSessionFileForSuiteBinding(path8,suiteId){let fd=openSync3(path8,"r");try{let decoder=new StringDecoder2("utf8"),buffer=Buffer.allocUnsafe(SUITE_REF_READ_BUFFER_SIZE),scannedBytes=0,sessionId,cwd,leftover="",bound=!1,bindingDecided=!1;for(;scannedBytes<SUITE_REF_SCAN_LIMIT_BYTES&&!bindingDecided;){let readLength=Math.min(buffer.length,SUITE_REF_SCAN_LIMIT_BYTES-scannedBytes),bytesRead=readSync2(fd,buffer,0,readLength,null);if(bytesRead===0)break;scannedBytes+=bytesRead;let lines=(leftover+decoder.write(buffer.subarray(0,bytesRead))).split(`
|
|
589
|
-
`);leftover=lines.pop()??"";for(let line of lines){let entry=parseSuiteRefLine(line);if(entry!==void 0&&(entry.header!==void 0&&sessionId===void 0&&(sessionId=entry.header.id,cwd=entry.header.cwd),entry.boundToSuite!==void 0)){bound=entry.boundToSuite===suiteId,bindingDecided=!0;break}}}return{sessionId,cwd,bound}}finally{closeSync3(fd)}}function parseSuiteRefLine(line){let trimmed=line.trim();if(trimmed.length===0)return;let value;try{value=JSON.parse(trimmed)}catch{return}if(value===null||typeof value!="object"||Array.isArray(value))return;let record=value;if(record.type==="session"&&typeof record.id=="string")return{header:{id:record.id,cwd:typeof record.cwd=="string"?record.cwd:void 0}};if(record.type==="custom"&&record.customType===SUITE_SESSION_ENTRY_TYPE){let data=record.data,suiteId=data!==null&&typeof data=="object"&&typeof data.suiteId=="string"?data.suiteId:void 0;return suiteId===void 0?{}:{boundToSuite:suiteId}}return{}}function deleteSuite(options){let{agentDir,id}=options;if(options.confirmToken!==void 0&&options.confirmToken!==SUITE_DELETE_CONFIRM_TOKEN)throw new SuiteLifecycleError("delete",id,[`confirmToken must be "${SUITE_DELETE_CONFIRM_TOKEN}" when provided`]);let reasons=[];isBuiltinSuiteId(id)&&reasons.push(`builtin suite "${id}" cannot be deleted`);let suiteDir=getSuiteWorkspaceDir(agentDir,id),suiteJsonPath=join36(suiteDir,SUITE_MANIFEST_FILENAME);if(existsSync20(suiteDir)?existsSync20(suiteJsonPath)||reasons.push(`${suiteJsonPath} does not exist`):reasons.push(`workspace directory ${suiteDir} does not exist`),reasons.length>0)throw new SuiteLifecycleError("delete",id,reasons);if(options.refs.length>0)throw new SuiteLifecycleError("delete",id,options.refs.map(ref=>`session ${ref.sessionId} at ${ref.path} references this suite`));let trashRoot=join36(getSuitesRootDir(agentDir),SUITE_TRASH_DIR_NAME);mkdirSync11(trashRoot,{recursive:!0});let trashPath=join36(trashRoot,`${id}-${formatTrashTimestamp(options.now?.()??Date.now())}-${randomUUID14().replaceAll("-","").slice(0,6)}`);return renameSync(suiteDir,trashPath),options.purgeMemories?.(id),{trashPath}}function formatTrashTimestamp(ms){return new Date(ms).toISOString().replace(/[-:]/g,"").replace(".","")}function releaseTrashedSuite(trashPath){rm4(trashPath,{recursive:!0,force:!0,maxRetries:5,retryDelay:100}).catch(()=>{})}async function sweepSuiteTrash(agentDir,options={}){let trashRoot=join36(getSuitesRootDir(agentDir),SUITE_TRASH_DIR_NAME),retentionMs=options.retentionMs??DEFAULT_SUITE_TRASH_RETENTION_MS,cutoffMs=(options.now?.()??Date.now())-retentionMs,removed=[],kept=[],entryNames;try{entryNames=await readdir2(trashRoot)}catch{return{removed:Object.freeze(removed),kept:Object.freeze(kept)}}for(let name of entryNames){let entryPath=join36(trashRoot,name);try{(await stat2(entryPath)).mtimeMs<=cutoffMs?(await rm4(entryPath,{recursive:!0,force:!0}),removed.push(name)):kept.push(name)}catch{kept.push(name)}}return{removed:Object.freeze(removed),kept:Object.freeze(kept)}}function resetSuite(options){let{agentDir,id}=options,factory=getBuiltinSuite(id);if(factory===void 0)throw new SuiteLifecycleError("reset",id,[isBuiltinSuiteId(id)?`builtin suite "${id}" has no factory declaration`:`suite "${id}" is not builtin; only builtin suites can be reset \u2014 delete user suites instead`]);let suiteDir=getSuiteWorkspaceDir(agentDir,id),suiteJsonPath=join36(suiteDir,SUITE_MANIFEST_FILENAME),lockPath=join36(suiteDir,SUITE_LOCK_FILENAME),factoryJson=serializeSuiteJson(factory),currentRaw=existsSync20(suiteJsonPath)?readFileSync19(suiteJsonPath,"utf8"):"",apply=()=>{let identity=buildSuiteProfileIdentity(factory),previousLock;if(existsSync20(lockPath))try{previousLock=parseSuiteProfileLockFile(readFileSync19(lockPath,"utf8"))}catch{previousLock=void 0}let lock,previousGeneration,replaced=!1;if(previousLock!==void 0){let migration=createProfileMigrationPolicy().applyMigration({lock:previousLock,current:identity,authorizedBy:SUITE_RESET_AUTHORIZED_BY,...options.now===void 0?{}:{now:options.now}});if(migration.status==="failed")throw new SuiteLifecycleError("reset",id,[migration.reason]);if(migration.status==="current")lock=previousLock;else{let swap=replaceProfileLock(previousLock,identity,{authorizedBy:SUITE_RESET_AUTHORIZED_BY},options.now===void 0?{}:{now:options.now});lock=swap.lock,previousGeneration=swap.previousGeneration,replaced=!0}}else lock=createProfileLock(identity,{lockedBy:SUITE_RESET_AUTHORIZED_BY,...options.now===void 0?{}:{now:options.now}}),replaced=!0;return mkdirSync11(suiteDir,{recursive:!0}),writeFileSync11(suiteJsonPath,factoryJson,"utf8"),(replaced||previousLock===void 0)&&writeFileSync11(lockPath,serializeSuiteProfileLockFile(lock),"utf8"),{suiteId:id,wroteFactory:currentRaw!==factoryJson,lock,...previousGeneration===void 0?{}:{previousGeneration}}};return{suiteId:id,factory,suiteJsonPath,lockPath,diffText:generateDiffString(currentRaw,factoryJson).diff,apply}}function clearDanglingSuiteSettings(settingsManager,id){let clearedScopes=[];return settingsManager.getProjectSettings().suite===id&&(settingsManager.setProjectSuite(void 0),clearedScopes.push("project")),settingsManager.getGlobalSettings().suite===id&&(settingsManager.setSuite(void 0),clearedScopes.push("global")),{clearedScopes:Object.freeze(clearedScopes)}}import{execFile as execFile2,execFileSync,execSync as execSync2,spawn}from"child_process";import{randomUUID as randomUUID16}from"crypto";import{unlinkSync as unlinkSync3,writeFileSync as writeFileSync12}from"fs";import{platform,tmpdir as tmpdir5}from"os";import{join as join39}from"path";import{spawnSync as spawnSync4}from"child_process";import{randomUUID as randomUUID15}from"crypto";import{readFileSync as readFileSync21,unlinkSync as unlinkSync2}from"fs";import{tmpdir as tmpdir4}from"os";import{join as join38}from"path";import{createRequire as createRequire2}from"module";import{dirname as dirname23,join as join37}from"path";import{pathToFileURL}from"url";var moduleRequire=createRequire2(import.meta.url),executableDirRequire=createRequire2(pathToFileURL(join37(dirname23(process.execPath),"package.json")).href),hasDisplay=process.platform!=="linux"||!!(process.env.DISPLAY||process.env.WAYLAND_DISPLAY);function loadClipboardNative(requires=[moduleRequire,executableDirRequire]){for(let requireClipboard of requires)try{return requireClipboard("@mariozechner/clipboard")}catch{}return null}var clipboard=!process.env.TERMUX_VERSION&&hasDisplay?loadClipboardNative():null;import{readFileSync as readFileSync20}from"fs";function isWSL(env=process.env){if(env.WSL_DISTRO_NAME||env.WSLENV)return!0;try{let release=readFileSync20("/proc/version","utf8");return/microsoft|wsl/i.test(release)}catch{return!1}}var SUPPORTED_IMAGE_MIME_TYPES=["image/png","image/jpeg","image/webp","image/gif"],DEFAULT_LIST_TIMEOUT_MS=1e3,DEFAULT_READ_TIMEOUT_MS=3e3,DEFAULT_POWERSHELL_TIMEOUT_MS=5e3,DEFAULT_MAX_BUFFER_BYTES=50*1024*1024;function isWaylandSession(env=process.env){return!!env.WAYLAND_DISPLAY||env.XDG_SESSION_TYPE==="wayland"}function baseMimeType(mimeType){return mimeType.split(";")[0]?.trim().toLowerCase()??mimeType.toLowerCase()}function extensionForImageMimeType(mimeType){switch(baseMimeType(mimeType)){case"image/png":return"png";case"image/jpeg":return"jpg";case"image/webp":return"webp";case"image/gif":return"gif";default:return null}}function selectPreferredImageMimeType(mimeTypes){let normalized=mimeTypes.map(t2=>t2.trim()).filter(Boolean).map(t2=>({raw:t2,base:baseMimeType(t2)}));for(let preferred of SUPPORTED_IMAGE_MIME_TYPES){let match2=normalized.find(t2=>t2.base===preferred);if(match2)return match2.raw}return normalized.find(t2=>t2.base.startsWith("image/"))?.raw??null}function isSupportedImageMimeType(mimeType){let base=baseMimeType(mimeType);return SUPPORTED_IMAGE_MIME_TYPES.some(t2=>t2===base)}async function convertToPng2(bytes){let photon=await loadPhoton();if(!photon)return null;try{let image=photon.PhotonImage.new_from_byteslice(bytes);try{return image.get_bytes()}finally{image.free()}}catch{return null}}function runCommand(command,args,options){let timeoutMs=options?.timeoutMs??DEFAULT_READ_TIMEOUT_MS,maxBufferBytes=options?.maxBufferBytes??DEFAULT_MAX_BUFFER_BYTES,result=spawnSync4(command,args,{timeout:timeoutMs,maxBuffer:maxBufferBytes,env:options?.env});return result.error?{ok:!1,stdout:Buffer.alloc(0)}:result.status!==0?{ok:!1,stdout:Buffer.alloc(0)}:{ok:!0,stdout:Buffer.isBuffer(result.stdout)?result.stdout:Buffer.from(result.stdout??"",typeof result.stdout=="string"?"utf-8":void 0)}}function readClipboardImageViaWlPaste(){let list=runCommand("wl-paste",["--list-types"],{timeoutMs:DEFAULT_LIST_TIMEOUT_MS});if(!list.ok)return null;let types2=list.stdout.toString("utf-8").split(/\r?\n/).map(t2=>t2.trim()).filter(Boolean),selectedType=selectPreferredImageMimeType(types2);if(!selectedType)return null;let data=runCommand("wl-paste",["--type",selectedType,"--no-newline"]);return!data.ok||data.stdout.length===0?null:{bytes:data.stdout,mimeType:baseMimeType(selectedType)}}function readClipboardImageViaPowerShell(){let tmpFile=join38(tmpdir4(),`pi-wsl-clip-${randomUUID15()}.png`);try{let winPathResult=runCommand("wslpath",["-w",tmpFile],{timeoutMs:DEFAULT_LIST_TIMEOUT_MS});if(!winPathResult.ok)return null;let winPath=winPathResult.stdout.toString("utf-8").trim();if(!winPath)return null;let psScript=["Add-Type -AssemblyName System.Windows.Forms","Add-Type -AssemblyName System.Drawing",`$path = '${winPath.replaceAll("'","''")}'`,"$img = [System.Windows.Forms.Clipboard]::GetImage()","if ($img) { $img.Save($path, [System.Drawing.Imaging.ImageFormat]::Png); Write-Output 'ok' } else { Write-Output 'empty' }"].join("; "),result=runCommand("powershell.exe",["-NoProfile","-Command",psScript],{timeoutMs:DEFAULT_POWERSHELL_TIMEOUT_MS});if(!result.ok||result.stdout.toString("utf-8").trim()!=="ok")return null;let bytes=readFileSync21(tmpFile);return bytes.length===0?null:{bytes:new Uint8Array(bytes),mimeType:"image/png"}}catch{return null}finally{try{unlinkSync2(tmpFile)}catch{}}}function readClipboardImageViaXclip(){let targets=runCommand("xclip",["-selection","clipboard","-t","TARGETS","-o"],{timeoutMs:DEFAULT_LIST_TIMEOUT_MS}),candidateTypes=[];targets.ok&&(candidateTypes=targets.stdout.toString("utf-8").split(/\r?\n/).map(t2=>t2.trim()).filter(Boolean));let preferred=candidateTypes.length>0?selectPreferredImageMimeType(candidateTypes):null,tryTypes=preferred?[preferred,...SUPPORTED_IMAGE_MIME_TYPES]:[...SUPPORTED_IMAGE_MIME_TYPES];for(let mimeType of tryTypes){let data=runCommand("xclip",["-selection","clipboard","-t",mimeType,"-o"]);if(data.ok&&data.stdout.length>0)return{bytes:data.stdout,mimeType:baseMimeType(mimeType)}}return null}async function readClipboardImageViaNativeClipboard(){if(!clipboard||!clipboard.hasImage())return null;let imageData=await clipboard.getImageBinary();return!imageData||imageData.length===0?null:{bytes:imageData instanceof Uint8Array?imageData:Uint8Array.from(imageData),mimeType:"image/png"}}async function readClipboardImage(options){let env=options?.env??process.env,platform2=options?.platform??process.platform;if(env.TERMUX_VERSION)return null;let image=null;if(platform2==="linux"){let wsl=isWSL(env),wayland=isWaylandSession(env);(wayland||wsl)&&(image=readClipboardImageViaWlPaste()??readClipboardImageViaXclip()),!image&&wsl&&(image=readClipboardImageViaPowerShell()),!image&&!wayland&&(image=await readClipboardImageViaNativeClipboard()??readClipboardImageViaXclip())}else image=await readClipboardImageViaNativeClipboard();if(!image)return null;if(!isSupportedImageMimeType(image.mimeType)){let pngBytes=await convertToPng2(image.bytes);return pngBytes?{bytes:pngBytes,mimeType:"image/png"}:null}return image}function copyToX11Clipboard(options){try{execSync2("xclip -selection clipboard",options)}catch{execSync2("xsel --clipboard --input",options)}}var MAX_OSC52_ENCODED_LENGTH=1e5;function isRemoteSession(env){return!!(env.SSH_CONNECTION||env.SSH_CLIENT||env.MOSH_CONNECTION)}function emitOsc52(text){let encoded=Buffer.from(text).toString("base64");return encoded.length>MAX_OSC52_ENCODED_LENGTH?!1:(process.stdout.write(`\x1B]52;c;${encoded}\x07`),!0)}function runWslCommand(command,args,timeout){return new Promise(resolve22=>{execFile2(command,args,{timeout,encoding:"buffer"},(error,stdout)=>{resolve22(error?null:stdout)})})}async function copyViaWindowsClipboard(text){let tmpFile=join39(tmpdir5(),`pi-wsl-clip-${randomUUID16()}.txt`);try{writeFileSync12(tmpFile,text,{encoding:"utf8",mode:384});let winPath=(await runWslCommand("wslpath",["-w",tmpFile],1e3))?.toString("utf8").trim();if(!winPath)return!1;let script=`Set-Clipboard -Value ([System.IO.File]::ReadAllText('${winPath.replaceAll("'","''")}', [System.Text.Encoding]::UTF8))`;return await runWslCommand("powershell.exe",["-NoProfile","-Command",script],5e3)!==null}catch{return!1}finally{try{unlinkSync3(tmpFile)}catch{}}}var READ_CLIPBOARD_OPTIONS={encoding:"utf8",maxBuffer:50*1024*1024,timeout:5e3};function readWaylandClipboardText(){try{return{ok:!0,text:execFileSync("wl-paste",["--no-newline","--type","text"],READ_CLIPBOARD_OPTIONS)||null}}catch{return{ok:!1}}}async function readClipboardText(){if(platform()==="linux"&&isWaylandSession()&&process.env.WAYLAND_DISPLAY){let result=readWaylandClipboardText();if(result.ok)return result.text}if(!clipboard)return null;try{return await clipboard.getText()||null}catch{return null}}async function copyToClipboard(text){let copied=!1,p=platform(),env=process.env;try{clipboard&&p!=="linux"&&(await clipboard.setText(text),copied=!0)}catch{}let remote=isRemoteSession(env);if(copied&&!remote)return;let options={input:text,timeout:5e3,stdio:["pipe","ignore","ignore"]};if(!copied)try{if(p==="darwin")execSync2("pbcopy",options),copied=!0;else if(p==="win32")execSync2("clip",options),copied=!0;else{if(env.TERMUX_VERSION)try{execSync2("termux-clipboard-set",options),copied=!0}catch{}if(!copied){let hasWaylandDisplay=!!env.WAYLAND_DISPLAY,hasX11Display=!!env.DISPLAY;if(isWaylandSession()&&hasWaylandDisplay){let x11Attempted=!1;try{execSync2("which wl-copy",{stdio:"ignore"}),await new Promise(resolve22=>{let proc=spawn("wl-copy",[],{stdio:["pipe","ignore","ignore"]});proc.on("error",()=>resolve22(1)),proc.on("close",code=>resolve22(code??1)),proc.stdin.on("error",()=>{}),proc.stdin.write(text),proc.stdin.end()})===0?copied=!0:hasX11Display&&(x11Attempted=!0,copyToX11Clipboard(options),copied=!0)}catch{hasX11Display&&!x11Attempted&&(copyToX11Clipboard(options),copied=!0)}}else hasX11Display&&(copyToX11Clipboard(options),copied=!0)}}}catch{}let osc52Emitted=!1;!copied&&p==="linux"&&isWSL(env)&&(env.WT_SESSION&&(osc52Emitted=emitOsc52(text)),copied=osc52Emitted||await copyViaWindowsClipboard(text));let headless=p==="linux"&&!env.DISPLAY&&!env.WAYLAND_DISPLAY&&!env.TERMUX_VERSION,oversized=!1;if(!osc52Emitted&&(remote||!copied&&headless)&&(emitOsc52(text)?copied=!0:oversized=!0),!copied){if(oversized)throw new Error(t("Clipboard unavailable: text exceeds the OSC 52 size limit"));if(p==="linux"){if(env.TERMUX_VERSION)throw new Error(t("Clipboard unavailable: install the Termux:API app and `termux-api` package"));if(env.WAYLAND_DISPLAY)throw new Error(t("Clipboard unavailable: install `wl-clipboard` (`wl-copy`) or check Wayland access"));if(env.DISPLAY)throw new Error(t("Clipboard unavailable: install `xclip` or `xsel`, or check X11 access"))}throw p==="win32"?new Error(t("Clipboard unavailable: ensure the built-in `clip` command is on PATH")):new Error(t("Clipboard unavailable"))}}function createMarkdownTransform(messageType,isStreaming,transformers){return(markdown,availableWidth)=>applyMarkdownTransformers(markdown,{messageType,isStreaming,availableWidth},transformers)}function applyMarkdownTransformers(markdown,context,transformers){let transformedMarkdown=markdown;for(let transformer of transformers)try{let transformed=transformer(transformedMarkdown,context);typeof transformed=="string"&&(transformedMarkdown=transformed)}catch{}return transformedMarkdown}var OSC133_ZONE_START="\x1B]133;A\x07",OSC133_ZONE_END="\x1B]133;B\x07",OSC133_ZONE_FINAL="\x1B]133;C\x07",AssistantMessageComponent=class extends Container{contentContainer;hideThinkingBlock;markdownTheme;hiddenThinkingLabel;outputPad;markdownTransformers;lastMessage;hasToolCalls=!1;isStreaming=!1;thinkingExpanded=!1;contentSegments;constructor(message,hideThinkingBlock=!1,markdownTheme=getMarkdownTheme(),hiddenThinkingLabel=t("Thinking..."),outputPad=1,markdownTransformers=[]){super(),this.hideThinkingBlock=hideThinkingBlock,this.markdownTheme=markdownTheme,this.hiddenThinkingLabel=hiddenThinkingLabel,this.outputPad=outputPad,this.markdownTransformers=markdownTransformers,this.contentContainer=new Container,this.addChild(this.contentContainer),message&&this.updateContent(message)}invalidate(){super.invalidate(),this.lastMessage&&(this.contentSegments=void 0,this.updateContent(this.lastMessage))}setHideThinkingBlock(hide){this.hideThinkingBlock=hide,this.lastMessage&&(this.contentSegments=void 0,this.updateContent(this.lastMessage))}setExpanded(expanded){expanded!==this.thinkingExpanded&&(this.thinkingExpanded=expanded,this.lastMessage&&(this.contentSegments=void 0,this.updateContent(this.lastMessage)))}setHiddenThinkingLabel(label){this.hiddenThinkingLabel=label,this.lastMessage&&(this.contentSegments=void 0,this.updateContent(this.lastMessage))}setOutputPad(padding){this.outputPad=padding,this.lastMessage&&(this.contentSegments=void 0,this.updateContent(this.lastMessage))}render(width){let lines=super.render(width);return this.hasToolCalls||lines.length===0||(lines[0]=OSC133_ZONE_START+lines[0],lines[lines.length-1]=OSC133_ZONE_END+OSC133_ZONE_FINAL+lines[lines.length-1]),lines}updateContent(message,isStreaming=this.isStreaming){this.lastMessage=message,this.isStreaming=isStreaming;let specs=this.buildContentSegments(message,isStreaming),previous=this.contentSegments,reuseCount=0;if(previous&&previous.isStreaming===isStreaming){let shared=Math.min(previous.specs.length,specs.length);for(;reuseCount<shared&&previous.specs[reuseCount].kind===specs[reuseCount].kind;)reuseCount++;for(let i=0;i<reuseCount;i++){if(specs[i].text===previous.specs[i].text)continue;let component=this.contentContainer.children[i];(component instanceof Markdown||component instanceof Text)&&component.setText(specs[i].text)}}let reused=this.contentContainer.children.slice(0,reuseCount);this.contentContainer.clear();for(let component of reused)this.contentContainer.addChild(component);for(let i=reuseCount;i<specs.length;i++)this.contentContainer.addChild(this.createSegmentComponent(specs[i],isStreaming));this.contentSegments={specs,isStreaming},this.hasToolCalls=message.content.some(c=>c.type==="toolCall")}createSegmentComponent(spec,isStreaming){switch(spec.kind){case"spacer":return new Spacer(1);case"text":return new Markdown(spec.text,this.outputPad,0,this.markdownTheme,void 0,{transform:createMarkdownTransform("assistant",isStreaming,this.markdownTransformers)});case"thinking":return new Markdown(spec.text,this.outputPad,0,this.markdownTheme,{color:text=>theme.fg("thinkingText",text),italic:!0},{transform:createMarkdownTransform("assistant-thinking",isStreaming,this.markdownTransformers)});case"thinking-summary":case"status":return new Text(spec.text,this.outputPad,0)}}buildContentSegments(message,isStreaming){let specs=[];message.content.some(c=>c.type==="text"&&c.text.trim()||c.type==="thinking"&&c.thinking.trim())&&specs.push({kind:"spacer",text:""});for(let i=0;i<message.content.length;i++){let content=message.content[i];if(content.type==="text"&&content.text.trim())specs.push({kind:"text",text:content.text.trim()});else if(content.type==="thinking"){let thinkingBlocks=[];for(;i<message.content.length;i++){let thinkingContent=message.content[i];if(thinkingContent.type!=="thinking")break;let thinking=thinkingContent.thinking.trim();thinking&&thinkingBlocks.push(thinking)}if(i--,thinkingBlocks.length===0)continue;let hasVisibleContentAfter=message.content.slice(i+1).some(c=>c.type==="text"&&c.text.trim()||c.type==="thinking"&&c.thinking.trim());isStreaming||!this.hideThinkingBlock&&this.thinkingExpanded?specs.push({kind:"thinking",text:thinkingBlocks.join(`
|
|
589
|
+
`);leftover=lines.pop()??"";for(let line of lines){let entry=parseSuiteRefLine(line);if(entry!==void 0&&(entry.header!==void 0&&sessionId===void 0&&(sessionId=entry.header.id,cwd=entry.header.cwd),entry.boundToSuite!==void 0)){bound=entry.boundToSuite===suiteId,bindingDecided=!0;break}}}return{sessionId,cwd,bound}}finally{closeSync3(fd)}}function parseSuiteRefLine(line){let trimmed=line.trim();if(trimmed.length===0)return;let value;try{value=JSON.parse(trimmed)}catch{return}if(value===null||typeof value!="object"||Array.isArray(value))return;let record=value;if(record.type==="session"&&typeof record.id=="string")return{header:{id:record.id,cwd:typeof record.cwd=="string"?record.cwd:void 0}};if(record.type==="custom"&&record.customType===SUITE_SESSION_ENTRY_TYPE){let data=record.data,suiteId=data!==null&&typeof data=="object"&&typeof data.suiteId=="string"?data.suiteId:void 0;return suiteId===void 0?{}:{boundToSuite:suiteId}}return{}}function deleteSuite(options){let{agentDir,id}=options;if(options.confirmToken!==void 0&&options.confirmToken!==SUITE_DELETE_CONFIRM_TOKEN)throw new SuiteLifecycleError("delete",id,[`confirmToken must be "${SUITE_DELETE_CONFIRM_TOKEN}" when provided`]);let reasons=[];isBuiltinSuiteId(id)&&reasons.push(`builtin suite "${id}" cannot be deleted`);let suiteDir=getSuiteWorkspaceDir(agentDir,id),suiteJsonPath=join36(suiteDir,SUITE_MANIFEST_FILENAME);if(existsSync20(suiteDir)?existsSync20(suiteJsonPath)||reasons.push(`${suiteJsonPath} does not exist`):reasons.push(`workspace directory ${suiteDir} does not exist`),reasons.length>0)throw new SuiteLifecycleError("delete",id,reasons);if(options.refs.length>0)throw new SuiteLifecycleError("delete",id,options.refs.map(ref=>`session ${ref.sessionId} at ${ref.path} references this suite`));let trashRoot=join36(getSuitesRootDir(agentDir),SUITE_TRASH_DIR_NAME);mkdirSync11(trashRoot,{recursive:!0});let trashPath=join36(trashRoot,`${id}-${formatTrashTimestamp(options.now?.()??Date.now())}-${randomUUID14().replaceAll("-","").slice(0,6)}`);return renameSync(suiteDir,trashPath),options.purgeMemories?.(id),{trashPath}}function formatTrashTimestamp(ms){return new Date(ms).toISOString().replace(/[-:]/g,"").replace(".","")}function releaseTrashedSuite(trashPath){rm4(trashPath,{recursive:!0,force:!0,maxRetries:5,retryDelay:100}).catch(()=>{})}async function sweepSuiteTrash(agentDir,options={}){let trashRoot=join36(getSuitesRootDir(agentDir),SUITE_TRASH_DIR_NAME),retentionMs=options.retentionMs??DEFAULT_SUITE_TRASH_RETENTION_MS,cutoffMs=(options.now?.()??Date.now())-retentionMs,removed=[],kept=[],entryNames;try{entryNames=await readdir2(trashRoot)}catch{return{removed:Object.freeze(removed),kept:Object.freeze(kept)}}for(let name of entryNames){let entryPath=join36(trashRoot,name);try{(await stat2(entryPath)).mtimeMs<=cutoffMs?(await rm4(entryPath,{recursive:!0,force:!0}),removed.push(name)):kept.push(name)}catch{kept.push(name)}}return{removed:Object.freeze(removed),kept:Object.freeze(kept)}}function resetSuite(options){let{agentDir,id}=options,factory=getBuiltinSuite(id);if(factory===void 0)throw new SuiteLifecycleError("reset",id,[isBuiltinSuiteId(id)?`builtin suite "${id}" has no factory declaration`:`suite "${id}" is not builtin; only builtin suites can be reset \u2014 delete user suites instead`]);let suiteDir=getSuiteWorkspaceDir(agentDir,id),suiteJsonPath=join36(suiteDir,SUITE_MANIFEST_FILENAME),lockPath=join36(suiteDir,SUITE_LOCK_FILENAME),factoryJson=serializeSuiteJson(factory),currentRaw=existsSync20(suiteJsonPath)?readFileSync19(suiteJsonPath,"utf8"):"",apply=()=>{let identity=buildSuiteProfileIdentity(factory),previousLock;if(existsSync20(lockPath))try{previousLock=parseSuiteProfileLockFile(readFileSync19(lockPath,"utf8"))}catch{previousLock=void 0}let lock,previousGeneration,replaced=!1;if(previousLock!==void 0){let migration=createProfileMigrationPolicy().applyMigration({lock:previousLock,current:identity,authorizedBy:SUITE_RESET_AUTHORIZED_BY,...options.now===void 0?{}:{now:options.now}});if(migration.status==="failed")throw new SuiteLifecycleError("reset",id,[migration.reason]);if(migration.status==="current")lock=previousLock;else{let swap=replaceProfileLock(previousLock,identity,{authorizedBy:SUITE_RESET_AUTHORIZED_BY},options.now===void 0?{}:{now:options.now});lock=swap.lock,previousGeneration=swap.previousGeneration,replaced=!0}}else lock=createProfileLock(identity,{lockedBy:SUITE_RESET_AUTHORIZED_BY,...options.now===void 0?{}:{now:options.now}}),replaced=!0;return mkdirSync11(suiteDir,{recursive:!0}),writeFileSync11(suiteJsonPath,factoryJson,"utf8"),(replaced||previousLock===void 0)&&writeFileSync11(lockPath,serializeSuiteProfileLockFile(lock),"utf8"),{suiteId:id,wroteFactory:currentRaw!==factoryJson,lock,...previousGeneration===void 0?{}:{previousGeneration}}};return{suiteId:id,factory,suiteJsonPath,lockPath,diffText:generateDiffString(currentRaw,factoryJson).diff,apply}}function clearDanglingSuiteSettings(settingsManager,id){let clearedScopes=[];return settingsManager.getProjectSettings().suite===id&&(settingsManager.setProjectSuite(void 0),clearedScopes.push("project")),settingsManager.getGlobalSettings().suite===id&&(settingsManager.setSuite(void 0),clearedScopes.push("global")),{clearedScopes:Object.freeze(clearedScopes)}}import{execFile as execFile2,execFileSync,execSync as execSync2,spawn as spawn2}from"child_process";import{randomUUID as randomUUID16}from"crypto";import{unlinkSync as unlinkSync3,writeFileSync as writeFileSync12}from"fs";import{platform,tmpdir as tmpdir5}from"os";import{join as join39}from"path";import{spawnSync as spawnSync4}from"child_process";import{randomUUID as randomUUID15}from"crypto";import{readFileSync as readFileSync21,unlinkSync as unlinkSync2}from"fs";import{tmpdir as tmpdir4}from"os";import{join as join38}from"path";import{createRequire as createRequire2}from"module";import{dirname as dirname23,join as join37}from"path";import{pathToFileURL}from"url";var moduleRequire=createRequire2(import.meta.url),executableDirRequire=createRequire2(pathToFileURL(join37(dirname23(process.execPath),"package.json")).href),hasDisplay=process.platform!=="linux"||!!(process.env.DISPLAY||process.env.WAYLAND_DISPLAY);function loadClipboardNative(requires=[moduleRequire,executableDirRequire]){for(let requireClipboard of requires)try{return requireClipboard("@mariozechner/clipboard")}catch{}return null}var clipboard=!process.env.TERMUX_VERSION&&hasDisplay?loadClipboardNative():null;import{readFileSync as readFileSync20}from"fs";function isWSL(env=process.env){if(env.WSL_DISTRO_NAME||env.WSLENV)return!0;try{let release=readFileSync20("/proc/version","utf8");return/microsoft|wsl/i.test(release)}catch{return!1}}var SUPPORTED_IMAGE_MIME_TYPES=["image/png","image/jpeg","image/webp","image/gif"],DEFAULT_LIST_TIMEOUT_MS=1e3,DEFAULT_READ_TIMEOUT_MS=3e3,DEFAULT_POWERSHELL_TIMEOUT_MS=5e3,DEFAULT_MAX_BUFFER_BYTES=50*1024*1024;function isWaylandSession(env=process.env){return!!env.WAYLAND_DISPLAY||env.XDG_SESSION_TYPE==="wayland"}function baseMimeType(mimeType){return mimeType.split(";")[0]?.trim().toLowerCase()??mimeType.toLowerCase()}function extensionForImageMimeType(mimeType){switch(baseMimeType(mimeType)){case"image/png":return"png";case"image/jpeg":return"jpg";case"image/webp":return"webp";case"image/gif":return"gif";default:return null}}function selectPreferredImageMimeType(mimeTypes){let normalized=mimeTypes.map(t2=>t2.trim()).filter(Boolean).map(t2=>({raw:t2,base:baseMimeType(t2)}));for(let preferred of SUPPORTED_IMAGE_MIME_TYPES){let match2=normalized.find(t2=>t2.base===preferred);if(match2)return match2.raw}return normalized.find(t2=>t2.base.startsWith("image/"))?.raw??null}function isSupportedImageMimeType(mimeType){let base=baseMimeType(mimeType);return SUPPORTED_IMAGE_MIME_TYPES.some(t2=>t2===base)}async function convertToPng2(bytes){let photon=await loadPhoton();if(!photon)return null;try{let image=photon.PhotonImage.new_from_byteslice(bytes);try{return image.get_bytes()}finally{image.free()}}catch{return null}}function runCommand(command,args,options){let timeoutMs=options?.timeoutMs??DEFAULT_READ_TIMEOUT_MS,maxBufferBytes=options?.maxBufferBytes??DEFAULT_MAX_BUFFER_BYTES,result=spawnSync4(command,args,{timeout:timeoutMs,maxBuffer:maxBufferBytes,env:options?.env});return result.error?{ok:!1,stdout:Buffer.alloc(0)}:result.status!==0?{ok:!1,stdout:Buffer.alloc(0)}:{ok:!0,stdout:Buffer.isBuffer(result.stdout)?result.stdout:Buffer.from(result.stdout??"",typeof result.stdout=="string"?"utf-8":void 0)}}function readClipboardImageViaWlPaste(){let list=runCommand("wl-paste",["--list-types"],{timeoutMs:DEFAULT_LIST_TIMEOUT_MS});if(!list.ok)return null;let types2=list.stdout.toString("utf-8").split(/\r?\n/).map(t2=>t2.trim()).filter(Boolean),selectedType=selectPreferredImageMimeType(types2);if(!selectedType)return null;let data=runCommand("wl-paste",["--type",selectedType,"--no-newline"]);return!data.ok||data.stdout.length===0?null:{bytes:data.stdout,mimeType:baseMimeType(selectedType)}}function readClipboardImageViaPowerShell(){let tmpFile=join38(tmpdir4(),`pi-wsl-clip-${randomUUID15()}.png`);try{let winPathResult=runCommand("wslpath",["-w",tmpFile],{timeoutMs:DEFAULT_LIST_TIMEOUT_MS});if(!winPathResult.ok)return null;let winPath=winPathResult.stdout.toString("utf-8").trim();if(!winPath)return null;let psScript=["Add-Type -AssemblyName System.Windows.Forms","Add-Type -AssemblyName System.Drawing",`$path = '${winPath.replaceAll("'","''")}'`,"$img = [System.Windows.Forms.Clipboard]::GetImage()","if ($img) { $img.Save($path, [System.Drawing.Imaging.ImageFormat]::Png); Write-Output 'ok' } else { Write-Output 'empty' }"].join("; "),result=runCommand("powershell.exe",["-NoProfile","-Command",psScript],{timeoutMs:DEFAULT_POWERSHELL_TIMEOUT_MS});if(!result.ok||result.stdout.toString("utf-8").trim()!=="ok")return null;let bytes=readFileSync21(tmpFile);return bytes.length===0?null:{bytes:new Uint8Array(bytes),mimeType:"image/png"}}catch{return null}finally{try{unlinkSync2(tmpFile)}catch{}}}function readClipboardImageViaXclip(){let targets=runCommand("xclip",["-selection","clipboard","-t","TARGETS","-o"],{timeoutMs:DEFAULT_LIST_TIMEOUT_MS}),candidateTypes=[];targets.ok&&(candidateTypes=targets.stdout.toString("utf-8").split(/\r?\n/).map(t2=>t2.trim()).filter(Boolean));let preferred=candidateTypes.length>0?selectPreferredImageMimeType(candidateTypes):null,tryTypes=preferred?[preferred,...SUPPORTED_IMAGE_MIME_TYPES]:[...SUPPORTED_IMAGE_MIME_TYPES];for(let mimeType of tryTypes){let data=runCommand("xclip",["-selection","clipboard","-t",mimeType,"-o"]);if(data.ok&&data.stdout.length>0)return{bytes:data.stdout,mimeType:baseMimeType(mimeType)}}return null}async function readClipboardImageViaNativeClipboard(){if(!clipboard||!clipboard.hasImage())return null;let imageData=await clipboard.getImageBinary();return!imageData||imageData.length===0?null:{bytes:imageData instanceof Uint8Array?imageData:Uint8Array.from(imageData),mimeType:"image/png"}}async function readClipboardImage(options){let env=options?.env??process.env,platform2=options?.platform??process.platform;if(env.TERMUX_VERSION)return null;let image=null;if(platform2==="linux"){let wsl=isWSL(env),wayland=isWaylandSession(env);(wayland||wsl)&&(image=readClipboardImageViaWlPaste()??readClipboardImageViaXclip()),!image&&wsl&&(image=readClipboardImageViaPowerShell()),!image&&!wayland&&(image=await readClipboardImageViaNativeClipboard()??readClipboardImageViaXclip())}else image=await readClipboardImageViaNativeClipboard();if(!image)return null;if(!isSupportedImageMimeType(image.mimeType)){let pngBytes=await convertToPng2(image.bytes);return pngBytes?{bytes:pngBytes,mimeType:"image/png"}:null}return image}function copyToX11Clipboard(options){try{execSync2("xclip -selection clipboard",options)}catch{execSync2("xsel --clipboard --input",options)}}var MAX_OSC52_ENCODED_LENGTH=1e5;function isRemoteSession(env){return!!(env.SSH_CONNECTION||env.SSH_CLIENT||env.MOSH_CONNECTION)}function emitOsc52(text){let encoded=Buffer.from(text).toString("base64");return encoded.length>MAX_OSC52_ENCODED_LENGTH?!1:(process.stdout.write(`\x1B]52;c;${encoded}\x07`),!0)}function runWslCommand(command,args,timeout){return new Promise(resolve22=>{execFile2(command,args,{timeout,encoding:"buffer"},(error,stdout)=>{resolve22(error?null:stdout)})})}async function copyViaWindowsClipboard(text){let tmpFile=join39(tmpdir5(),`pi-wsl-clip-${randomUUID16()}.txt`);try{writeFileSync12(tmpFile,text,{encoding:"utf8",mode:384});let winPath=(await runWslCommand("wslpath",["-w",tmpFile],1e3))?.toString("utf8").trim();if(!winPath)return!1;let script=`Set-Clipboard -Value ([System.IO.File]::ReadAllText('${winPath.replaceAll("'","''")}', [System.Text.Encoding]::UTF8))`;return await runWslCommand("powershell.exe",["-NoProfile","-Command",script],5e3)!==null}catch{return!1}finally{try{unlinkSync3(tmpFile)}catch{}}}var READ_CLIPBOARD_OPTIONS={encoding:"utf8",maxBuffer:50*1024*1024,timeout:5e3};function readWaylandClipboardText(){try{return{ok:!0,text:execFileSync("wl-paste",["--no-newline","--type","text"],READ_CLIPBOARD_OPTIONS)||null}}catch{return{ok:!1}}}async function readClipboardText(){if(platform()==="linux"&&isWaylandSession()&&process.env.WAYLAND_DISPLAY){let result=readWaylandClipboardText();if(result.ok)return result.text}if(!clipboard)return null;try{return await clipboard.getText()||null}catch{return null}}async function copyToClipboard(text){let copied=!1,p=platform(),env=process.env;try{clipboard&&p!=="linux"&&(await clipboard.setText(text),copied=!0)}catch{}let remote=isRemoteSession(env);if(copied&&!remote)return;let options={input:text,timeout:5e3,stdio:["pipe","ignore","ignore"]};if(!copied)try{if(p==="darwin")execSync2("pbcopy",options),copied=!0;else if(p==="win32")execSync2("clip",options),copied=!0;else{if(env.TERMUX_VERSION)try{execSync2("termux-clipboard-set",options),copied=!0}catch{}if(!copied){let hasWaylandDisplay=!!env.WAYLAND_DISPLAY,hasX11Display=!!env.DISPLAY;if(isWaylandSession()&&hasWaylandDisplay){let x11Attempted=!1;try{execSync2("which wl-copy",{stdio:"ignore"}),await new Promise(resolve22=>{let proc=spawn2("wl-copy",[],{stdio:["pipe","ignore","ignore"]});proc.on("error",()=>resolve22(1)),proc.on("close",code=>resolve22(code??1)),proc.stdin.on("error",()=>{}),proc.stdin.write(text),proc.stdin.end()})===0?copied=!0:hasX11Display&&(x11Attempted=!0,copyToX11Clipboard(options),copied=!0)}catch{hasX11Display&&!x11Attempted&&(copyToX11Clipboard(options),copied=!0)}}else hasX11Display&&(copyToX11Clipboard(options),copied=!0)}}}catch{}let osc52Emitted=!1;!copied&&p==="linux"&&isWSL(env)&&(env.WT_SESSION&&(osc52Emitted=emitOsc52(text)),copied=osc52Emitted||await copyViaWindowsClipboard(text));let headless=p==="linux"&&!env.DISPLAY&&!env.WAYLAND_DISPLAY&&!env.TERMUX_VERSION,oversized=!1;if(!osc52Emitted&&(remote||!copied&&headless)&&(emitOsc52(text)?copied=!0:oversized=!0),!copied){if(oversized)throw new Error(t("Clipboard unavailable: text exceeds the OSC 52 size limit"));if(p==="linux"){if(env.TERMUX_VERSION)throw new Error(t("Clipboard unavailable: install the Termux:API app and `termux-api` package"));if(env.WAYLAND_DISPLAY)throw new Error(t("Clipboard unavailable: install `wl-clipboard` (`wl-copy`) or check Wayland access"));if(env.DISPLAY)throw new Error(t("Clipboard unavailable: install `xclip` or `xsel`, or check X11 access"))}throw p==="win32"?new Error(t("Clipboard unavailable: ensure the built-in `clip` command is on PATH")):new Error(t("Clipboard unavailable"))}}function createMarkdownTransform(messageType,isStreaming,transformers){return(markdown,availableWidth)=>applyMarkdownTransformers(markdown,{messageType,isStreaming,availableWidth},transformers)}function applyMarkdownTransformers(markdown,context,transformers){let transformedMarkdown=markdown;for(let transformer of transformers)try{let transformed=transformer(transformedMarkdown,context);typeof transformed=="string"&&(transformedMarkdown=transformed)}catch{}return transformedMarkdown}var OSC133_ZONE_START="\x1B]133;A\x07",OSC133_ZONE_END="\x1B]133;B\x07",OSC133_ZONE_FINAL="\x1B]133;C\x07",AssistantMessageComponent=class extends Container{contentContainer;hideThinkingBlock;markdownTheme;hiddenThinkingLabel;outputPad;markdownTransformers;lastMessage;hasToolCalls=!1;isStreaming=!1;thinkingExpanded=!1;contentSegments;constructor(message,hideThinkingBlock=!1,markdownTheme=getMarkdownTheme(),hiddenThinkingLabel=t("Thinking..."),outputPad=1,markdownTransformers=[]){super(),this.hideThinkingBlock=hideThinkingBlock,this.markdownTheme=markdownTheme,this.hiddenThinkingLabel=hiddenThinkingLabel,this.outputPad=outputPad,this.markdownTransformers=markdownTransformers,this.contentContainer=new Container,this.addChild(this.contentContainer),message&&this.updateContent(message)}invalidate(){super.invalidate(),this.lastMessage&&(this.contentSegments=void 0,this.updateContent(this.lastMessage))}setHideThinkingBlock(hide){this.hideThinkingBlock=hide,this.lastMessage&&(this.contentSegments=void 0,this.updateContent(this.lastMessage))}setExpanded(expanded){expanded!==this.thinkingExpanded&&(this.thinkingExpanded=expanded,this.lastMessage&&(this.contentSegments=void 0,this.updateContent(this.lastMessage)))}setHiddenThinkingLabel(label){this.hiddenThinkingLabel=label,this.lastMessage&&(this.contentSegments=void 0,this.updateContent(this.lastMessage))}setOutputPad(padding){this.outputPad=padding,this.lastMessage&&(this.contentSegments=void 0,this.updateContent(this.lastMessage))}render(width){let lines=super.render(width);return this.hasToolCalls||lines.length===0||(lines[0]=OSC133_ZONE_START+lines[0],lines[lines.length-1]=OSC133_ZONE_END+OSC133_ZONE_FINAL+lines[lines.length-1]),lines}updateContent(message,isStreaming=this.isStreaming){this.lastMessage=message,this.isStreaming=isStreaming;let specs=this.buildContentSegments(message,isStreaming),previous=this.contentSegments,reuseCount=0;if(previous&&previous.isStreaming===isStreaming){let shared=Math.min(previous.specs.length,specs.length);for(;reuseCount<shared&&previous.specs[reuseCount].kind===specs[reuseCount].kind;)reuseCount++;for(let i=0;i<reuseCount;i++){if(specs[i].text===previous.specs[i].text)continue;let component=this.contentContainer.children[i];(component instanceof Markdown||component instanceof Text)&&component.setText(specs[i].text)}}let reused=this.contentContainer.children.slice(0,reuseCount);this.contentContainer.clear();for(let component of reused)this.contentContainer.addChild(component);for(let i=reuseCount;i<specs.length;i++)this.contentContainer.addChild(this.createSegmentComponent(specs[i],isStreaming));this.contentSegments={specs,isStreaming},this.hasToolCalls=message.content.some(c=>c.type==="toolCall")}createSegmentComponent(spec,isStreaming){switch(spec.kind){case"spacer":return new Spacer(1);case"text":return new Markdown(spec.text,this.outputPad,0,this.markdownTheme,void 0,{transform:createMarkdownTransform("assistant",isStreaming,this.markdownTransformers)});case"thinking":return new Markdown(spec.text,this.outputPad,0,this.markdownTheme,{color:text=>theme.fg("thinkingText",text),italic:!0},{transform:createMarkdownTransform("assistant-thinking",isStreaming,this.markdownTransformers)});case"thinking-summary":case"status":return new Text(spec.text,this.outputPad,0)}}buildContentSegments(message,isStreaming){let specs=[];message.content.some(c=>c.type==="text"&&c.text.trim()||c.type==="thinking"&&c.thinking.trim())&&specs.push({kind:"spacer",text:""});for(let i=0;i<message.content.length;i++){let content=message.content[i];if(content.type==="text"&&content.text.trim())specs.push({kind:"text",text:content.text.trim()});else if(content.type==="thinking"){let thinkingBlocks=[];for(;i<message.content.length;i++){let thinkingContent=message.content[i];if(thinkingContent.type!=="thinking")break;let thinking=thinkingContent.thinking.trim();thinking&&thinkingBlocks.push(thinking)}if(i--,thinkingBlocks.length===0)continue;let hasVisibleContentAfter=message.content.slice(i+1).some(c=>c.type==="text"&&c.text.trim()||c.type==="thinking"&&c.thinking.trim());isStreaming||!this.hideThinkingBlock&&this.thinkingExpanded?specs.push({kind:"thinking",text:thinkingBlocks.join(`
|
|
590
590
|
|
|
591
|
-
`)}):this.hideThinkingBlock||specs.push({kind:"thinking-summary",text:theme.italic(theme.fg("thinkingText",t("\u273B thinking")))}),hasVisibleContentAfter&&specs.push({kind:"spacer",text:""})}}let hasToolCalls=message.content.some(c=>c.type==="toolCall");if(message.stopReason==="length")specs.push({kind:"spacer",text:""}),specs.push({kind:"status",text:theme.fg("error",t("Response was truncated before completion."))});else if(!hasToolCalls){if(message.stopReason==="aborted"){let abortMessage=message.errorMessage&&message.errorMessage!=="Request was aborted"?message.errorMessage:t("Operation aborted");specs.push({kind:"spacer",text:""}),specs.push({kind:"status",text:theme.fg("error",abortMessage)})}else if(message.stopReason==="error"){let errorMsg=message.errorMessage||t("Unknown error");specs.push({kind:"spacer",text:""}),specs.push({kind:"status",text:theme.fg("error",t("Error: {message}",{message:errorMsg}))})}}return specs}};var CustomEditor=class extends Editor{keybindings;actionHandlers=new Map;onEscape;onCtrlD;onPasteImage;constructor(tui,theme2,keybindings,options){super(tui,theme2,options),this.keybindings=keybindings}onAction(action,handler){this.actionHandlers.set(action,handler)}handleInput(data){if(this.keybindings.matches(data,"app.clipboard.pasteImage")){this.onPasteImage?.();return}if(this.keybindings.matches(data,"app.interrupt")){if(!this.isShowingAutocomplete()){let handler=this.onEscape??this.actionHandlers.get("app.interrupt");if(handler){handler();return}}super.handleInput(data);return}if(this.keybindings.matches(data,"app.exit")&&this.getText().length===0){let handler=this.onCtrlD??this.actionHandlers.get("app.exit");handler&&handler();return}if(this.keybindings.matches(data,"tui.editor.historyPrevious")||this.keybindings.matches(data,"tui.editor.historyNext")){super.handleInput(data);return}for(let[action,handler]of this.actionHandlers)if(action!=="app.interrupt"&&action!=="app.exit"&&this.keybindings.matches(data,action)){handler();return}super.handleInput(data)}};import{isAbsolute as isAbsolute10,relative as relative7,resolve as resolve17,sep as sep10}from"node:path";function areExperimentalFeaturesEnabled(){return process.env.AGENT_FORGE_EXPERIMENTAL==="1"}function sanitizeStatusText(text){return text.replace(/[\r\n\t]/g," ").replace(/ +/g," ").trim()}function formatTokens(count){return count<1e3?count.toString():count<1e4?`${(count/1e3).toFixed(1)}k`:count<1e6?`${Math.round(count/1e3)}k`:count<1e7?`${(count/1e6).toFixed(1)}M`:`${Math.round(count/1e6)}M`}function formatCwdForFooter(cwd,home){if(!home)return cwd;let resolvedCwd=resolve17(cwd),resolvedHome=resolve17(home),relativeToHome=relative7(resolvedHome,resolvedCwd);return relativeToHome===""||relativeToHome!==".."&&!relativeToHome.startsWith(`..${sep10}`)&&!isAbsolute10(relativeToHome)?relativeToHome===""?"~":`~${sep10}${relativeToHome}`:cwd}function summarizeFailoverState(state,nowMs){if(state?.status!=="open"||typeof state.chainId!="string"||state.chainId==="")return;let parts=[`failover: \u4E3B ${state.chainId} \u4E0D\u53EF\u7528`];typeof state.backupProvider=="string"&&state.backupProvider!==""&&parts.push(`\u7ECF ${state.backupProvider}`);let probeAtMs=typeof state.probeAtMs=="number"?state.probeAtMs:0;return probeAtMs-nowMs<=0?parts.push("\u7B49\u5F85\u8BD5\u63A2"):parts.push(`\u4E0B\u6B21\u8BD5\u63A2 ${Math.ceil((probeAtMs-nowMs)/1e3)}s`),parts.join(" \u2022 ")}function summarizeWorkflowState(state){let workflows=state?.workflows,records=Array.isArray(workflows)?workflows:[],record=[...records].reverse().find(item=>item?.status==="draft"||item?.status==="running")??records.at(-1);if(record===void 0||typeof record.title!="string")return;let stages=Array.isArray(record.runtime)?record.runtime:[],done=stages.filter(stage=>stage?.status==="completed"||stage?.status==="skipped").length,activeCount=stages.filter(stage=>stage?.status==="active").length,parts=[`wf: ${record.title} ${done}/${stages.length}`];return activeCount>=2&&parts.push(`\u25B6${activeCount}`),stages.some(stage=>stage?.status==="awaiting_review")&&parts.push("\u23F8"),Array.isArray(record.diagnostics)&&record.diagnostics.length>0&&parts.push("\u26A0"),record.status==="failed"&&parts.push("\u2717"),parts.join(" ")}var FooterComponent=class{session;footerData;sessionStats;constructor(session,footerData){this.session=session,this.footerData=footerData}setSession(session){this.session=session}get facade(){return createCodingAgentFacade(this.session)}invalidate(){}dispose(){}getSessionStats(){let facade=this.facade,sessionId=facade.getSessionId(),leafId=facade.getLeafId(),model=facade.getModel(),cached=this.sessionStats;if(cached&&cached.session===this.session&&cached.sessionId===sessionId&&cached.leafId===leafId&&cached.model===model)return cached;let usageTotals=createUsageTotals(),latestCacheHitRate,goalTitle,todoDone=0,todoTotal=0,workflowState,failoverState;for(let entry of facade.getEntries())if(entry.type==="message"&&entry.message.role==="assistant"){addUsageToTotals(usageTotals,entry.message.usage);let latestPromptTokens=entry.message.usage.input+entry.message.usage.cacheRead+entry.message.usage.cacheWrite;latestCacheHitRate=latestPromptTokens>0?entry.message.usage.cacheRead/latestPromptTokens*100:void 0}else if(entry.type==="message"&&entry.message.role==="toolResult"&&entry.message.usage)addUsageToTotals(usageTotals,entry.message.usage);else if((entry.type==="branch_summary"||entry.type==="compaction")&&entry.usage)addUsageToTotals(usageTotals,entry.usage);else if(entry.type==="custom"&&entry.customType==="goal.state"){let goals=entry.data?.goals,current=Array.isArray(goals)?goals.at(-1):void 0;current&&typeof current.title=="string"&&(goalTitle=current.title)}else if(entry.type==="custom"&&entry.customType==="todo.state"){let todos=entry.data?.todos;Array.isArray(todos)&&(todoDone=todos.filter(item=>item?.status==="done").length,todoTotal=todos.length)}else entry.type==="custom"&&entry.customType==="workflow.state"?workflowState=entry.data:entry.type==="custom"&&entry.customType==="provider.failover.state"&&(failoverState=entry.data);let contextUsage=facade.getContextUsage();return this.sessionStats={session:this.session,sessionId,leafId,model,usageTotals,latestCacheHitRate,goalTitle,todoDone,todoTotal,workflowState,failoverState,contextUsage},this.sessionStats}isProviderFailoverOpen(){return this.getSessionStats().failoverState?.status==="open"}render(width){let state=this.facade.getState(),{usageTotals,latestCacheHitRate,contextUsage,goalTitle,todoDone,todoTotal,workflowState,failoverState}=this.getSessionStats(),contextWindow=contextUsage?.contextWindow??state.model?.contextWindow??0,contextPercentValue=contextUsage?.percent??0,contextPercent=contextUsage?.percent!==null?contextPercentValue.toFixed(1):"?",pwd=formatCwdForFooter(this.facade.getCwd(),process.env.HOME||process.env.USERPROFILE),branch=this.footerData.getGitBranch();branch&&(pwd=`${pwd} (${branch})`);let sessionName=this.facade.getSessionName();sessionName&&(pwd=`${pwd} \u2022 ${sessionName}`);let statsParts=[];usageTotals.input&&statsParts.push(`\u2191${formatTokens(usageTotals.input)}`),usageTotals.output&&statsParts.push(`\u2193${formatTokens(usageTotals.output)}`),usageTotals.cacheRead&&statsParts.push(`R${formatTokens(usageTotals.cacheRead)}`),usageTotals.cacheWrite&&statsParts.push(`W${formatTokens(usageTotals.cacheWrite)}`),(usageTotals.cacheRead>0||usageTotals.cacheWrite>0)&&latestCacheHitRate!==void 0&&statsParts.push(`CH${latestCacheHitRate.toFixed(1)}%`);let usingSubscription=state.model?state.model.provider==="kimi-coding"||this.facade.isUsingSubscription(state.model.provider):!1;if(usageTotals.cost||usingSubscription){let costStr=`$${usageTotals.cost.toFixed(3)}${usingSubscription?` ${t("(sub)")}`:""}`;statsParts.push(costStr)}let contextPercentStr,contextPercentDisplay=contextPercent==="?"?`?/${formatTokens(contextWindow)}`:`${contextPercent}%/${formatTokens(contextWindow)}`;contextPercentValue>90?contextPercentStr=theme.fg("error",contextPercentDisplay):contextPercentValue>70?contextPercentStr=theme.fg("warning",contextPercentDisplay):contextPercentStr=contextPercentDisplay,statsParts.push(contextPercentStr),areExperimentalFeaturesEnabled()&&statsParts.push(`${theme.fg("dim","\u2022")} ${theme.bold(theme.fg("warning","xp"))}`);let statsLeft=statsParts.join(" "),modelName=state.model?.id||t("no-model"),statsLeftWidth=visibleWidth(statsLeft);statsLeftWidth>width&&(statsLeft=truncateToWidth(statsLeft,width,"..."),statsLeftWidth=visibleWidth(statsLeft));let minPadding=2,rightSideWithoutProvider=modelName;if(state.model?.reasoning){let thinkingLevel=state.thinkingLevel||"off";rightSideWithoutProvider=thinkingLevel==="off"?t("{model} \u2022 thinking off",{model:modelName}):`${modelName} \u2022 ${thinkingLevel}`}let rightSide=rightSideWithoutProvider;this.footerData.getAvailableProviderCount()>1&&state.model&&(rightSide=`(${state.model.provider}) ${rightSideWithoutProvider}`,statsLeftWidth+minPadding+visibleWidth(rightSide)>width&&(rightSide=rightSideWithoutProvider));let rightSideWidth=visibleWidth(rightSide),totalNeeded=statsLeftWidth+minPadding+rightSideWidth,statsLine;if(totalNeeded<=width){let padding=" ".repeat(width-statsLeftWidth-rightSideWidth);statsLine=statsLeft+padding+rightSide}else{let availableForRight=width-statsLeftWidth-minPadding;if(availableForRight>0){let truncatedRight=truncateToWidth(rightSide,availableForRight,""),truncatedRightWidth=visibleWidth(truncatedRight),padding=" ".repeat(Math.max(0,width-statsLeftWidth-truncatedRightWidth));statsLine=statsLeft+padding+truncatedRight}else statsLine=statsLeft}let dimStatsLeft=theme.fg("dim",statsLeft),remainder=statsLine.slice(statsLeft.length),dimRemainder=theme.fg("dim",remainder),lines=[truncateToWidth(theme.fg("dim",pwd),width,theme.fg("dim","...")),dimStatsLeft+dimRemainder];if(goalTitle!==void 0||todoTotal>0){let goalParts=[];goalTitle!==void 0&&goalParts.push(`goal: ${goalTitle}`),todoTotal>0&&goalParts.push(`todo ${todoDone}/${todoTotal}`);let goalLine=theme.fg("dim",sanitizeStatusText(goalParts.join(" \u2022 ")));lines.push(truncateToWidth(goalLine,width,theme.fg("dim","...")))}let workflowSummary=summarizeWorkflowState(workflowState);if(workflowSummary!==void 0){let workflowLine=theme.fg("dim",sanitizeStatusText(workflowSummary));lines.push(truncateToWidth(workflowLine,width,theme.fg("dim","...")))}let failoverSummary=summarizeFailoverState(failoverState,Date.now());if(failoverSummary!==void 0){let failoverLine=theme.fg("warning",sanitizeStatusText(failoverSummary));lines.push(truncateToWidth(failoverLine,width,theme.fg("warning","...")))}return lines}};import{spawn as spawn2}from"node:child_process";function openBrowser(target){let[cmd,args]=process.platform==="darwin"?["open",[target]]:process.platform==="win32"?["rundll32",["url.dll,FileProtocolHandler",target]]:["xdg-open",[target]];spawn2(cmd,args,{stdio:"ignore",detached:!0}).on("error",()=>{}).unref()}var LoginDialogComponent=class extends Container{contentContainer;input;tui;abortController=new AbortController;inputResolver;inputRejecter;onComplete;_focused=!1;get focused(){return this._focused}set focused(value){this._focused=value,this.input.focused=value}constructor(tui,providerId,onComplete,providerNameOverride,titleOverride){super(),this.tui=tui,this.onComplete=onComplete;let title=titleOverride??t("Login to {provider}",{provider:providerNameOverride||providerId});this.addChild(new DynamicBorder),this.addChild(new Text(theme.fg("accent",theme.bold(title)),1,0)),this.contentContainer=new Container,this.addChild(this.contentContainer),this.input=new Input,this.input.onSubmit=()=>{if(this.inputResolver){let value=this.input.getValue();this.replaceInputWithSubmittedText(value),this.inputResolver(value),this.inputResolver=void 0,this.inputRejecter=void 0}},this.input.onEscape=()=>{this.cancel()},this.addChild(new DynamicBorder)}get signal(){return this.abortController.signal}replaceInputWithSubmittedText(value){this.contentContainer.children=this.contentContainer.children.map(child=>child===this.input?new Text(`> ${value}`,0,0):child)}cancel(){this.abortController.abort(),this.inputRejecter&&(this.inputRejecter(new Error(t("Login cancelled"))),this.inputResolver=void 0,this.inputRejecter=void 0),this.onComplete(!1,t("Login cancelled"))}showAuth(url,instructions){this.contentContainer.clear(),this.contentContainer.addChild(new Spacer(1));let linkedUrl=`\x1B]8;;${url}\x07${url}\x1B]8;;\x07`;this.contentContainer.addChild(new Text(theme.fg("accent",linkedUrl),1,0));let clickHint=process.platform==="darwin"?t("Cmd+click to open"):t("Ctrl+click to open"),hyperlink2=`\x1B]8;;${url}\x07${clickHint}\x1B]8;;\x07`;this.contentContainer.addChild(new Text(theme.fg("dim",hyperlink2),1,0)),instructions&&(this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("warning",instructions),1,0))),openBrowser(url),this.tui.requestRender()}showDeviceCode(info){this.contentContainer.clear(),this.contentContainer.addChild(new Spacer(1));let linkedUrl=`\x1B]8;;${info.verificationUri}\x07${info.verificationUri}\x1B]8;;\x07`;this.contentContainer.addChild(new Text(theme.fg("accent",linkedUrl),1,0));let clickHint=process.platform==="darwin"?t("Cmd+click to open"):t("Ctrl+click to open"),hyperlink2=`\x1B]8;;${info.verificationUri}\x07${clickHint}\x1B]8;;\x07`;this.contentContainer.addChild(new Text(theme.fg("dim",hyperlink2),1,0)),this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("warning",t("Enter code: {code}",{code:info.userCode})),1,0)),this.tui.requestRender()}showManualInput(prompt){return this.input.setValue(""),this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("dim",prompt),1,0)),this.contentContainer.addChild(this.input),this.contentContainer.addChild(new Text(`(${keyHint("tui.select.cancel",t("to cancel"))})`,1,0)),this.tui.requestRender(),new Promise((resolve22,reject2)=>{this.inputResolver=resolve22,this.inputRejecter=reject2})}showPrompt(message,placeholder){return this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("text",message),1,0)),placeholder&&this.contentContainer.addChild(new Text(theme.fg("dim",t("e.g., {placeholder}",{placeholder})),1,0)),this.contentContainer.addChild(this.input),this.contentContainer.addChild(new Text(`(${keyHint("tui.select.cancel",t("to cancel,"))} ${keyHint("tui.select.confirm",t("to submit"))})`,1,0)),this.input.setValue(""),this.tui.requestRender(),new Promise((resolve22,reject2)=>{this.inputResolver=resolve22,this.inputRejecter=reject2})}showDetails(lines){this.contentContainer.clear(),this.contentContainer.addChild(new Spacer(1));for(let line of lines)this.contentContainer.addChild(new Text(line,1,0));this.tui.requestRender()}showInfo(message,links=[],showCloseHint=!1){this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("text",message),1,0));for(let link of links){let text=link.label?`${link.label}: ${link.url}`:link.url,hyperlink2=`\x1B]8;;${link.url}\x07${text}\x1B]8;;\x07`;this.contentContainer.addChild(new Text(theme.fg("accent",hyperlink2),1,0))}showCloseHint&&(this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(`(${keyHint("tui.select.cancel",t("to close"))})`,1,0))),this.tui.requestRender()}showWaiting(message){this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("dim",message),1,0)),this.contentContainer.addChild(new Text(`(${keyHint("tui.select.cancel",t("to cancel"))})`,1,0)),this.tui.requestRender()}showProgress(message){this.contentContainer.addChild(new Text(theme.fg("dim",message),1,0)),this.tui.requestRender()}handleInput(data){if(getKeybindings().matches(data,"tui.select.cancel")){this.cancel();return}this.input.handleInput(data)}};function formatAuthSelectorProviderType(authType){return authType==="oauth"?t("subscription"):t("API key")}var OAuthSelectorComponent=class extends Container{searchInput;_focused=!1;get focused(){return this._focused}set focused(value){this._focused=value,this.searchInput.focused=value}listContainer;allProviders;filteredProviders;selectedIndex=0;mode;onSelectCallback;onCancelCallback;showAuthTypeLabels;constructor(mode,providers,onSelect,onCancel,initialSearchInput){super(),this.mode=mode,this.allProviders=providers,this.filteredProviders=providers,this.showAuthTypeLabels=new Set(providers.map(provider=>provider.authType)).size>1,this.onSelectCallback=onSelect,this.onCancelCallback=onCancel,this.addChild(new DynamicBorder),this.addChild(new Spacer(1));let title=mode==="login"?t("Select provider to configure:"):t("Select provider to logout:");this.addChild(new TruncatedText(theme.fg("accent",theme.bold(title)),1,0)),this.addChild(new Spacer(1)),this.searchInput=new Input,initialSearchInput&&this.searchInput.setValue(initialSearchInput),this.searchInput.onSubmit=()=>{let selectedProvider=this.filteredProviders[this.selectedIndex];selectedProvider&&this.onSelectCallback(selectedProvider.id,selectedProvider.authType)},this.addChild(this.searchInput),this.addChild(new Spacer(1)),this.listContainer=new Container,this.addChild(this.listContainer),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),this.filterProviders(initialSearchInput??"")}filterProviders(query){this.filteredProviders=query?fuzzyFilter(this.allProviders,query,provider=>`${provider.name} ${provider.id} ${provider.authType} ${provider.method?.name??""}`):this.allProviders,this.selectedIndex=Math.max(0,Math.min(this.selectedIndex,Math.max(0,this.filteredProviders.length-1))),this.updateList()}updateList(){this.listContainer.clear();let maxVisible=8,startIndex=Math.max(0,Math.min(this.selectedIndex-Math.floor(maxVisible/2),this.filteredProviders.length-maxVisible)),endIndex=Math.min(startIndex+maxVisible,this.filteredProviders.length);for(let i=startIndex;i<endIndex;i++){let provider=this.filteredProviders[i];if(!provider)continue;let isSelected=i===this.selectedIndex,statusIndicator=this.formatStatusIndicator(provider),authTypeLabel=this.showAuthTypeLabels?theme.fg("muted",` [${formatAuthSelectorProviderType(provider.authType)}]`):"",line="";if(isSelected){let prefix=theme.fg("accent","\u2192 "),text=theme.fg("accent",provider.name);line=prefix+text+authTypeLabel+statusIndicator}else line=` ${theme.fg("text",provider.name)}`+authTypeLabel+statusIndicator;this.listContainer.addChild(new TruncatedText(line,1,0))}if(startIndex>0||endIndex<this.filteredProviders.length){let scrollInfo=theme.fg("muted",` (${this.selectedIndex+1}/${this.filteredProviders.length})`);this.listContainer.addChild(new TruncatedText(scrollInfo,1,0))}if(this.filteredProviders.length===0){let message=this.allProviders.length===0?this.mode==="login"?t("No providers available"):t("No providers logged in. Use /login first."):t("No matching providers");this.listContainer.addChild(new TruncatedText(theme.fg("muted",` ${message}`),1,0))}}formatStatusIndicator(provider){if(!provider.status)return theme.fg("muted",` \u2022 ${t("unconfigured")}`);if(provider.status.type!==provider.authType){let label=provider.status.type==="oauth"?t("subscription configured"):t("API key configured");return theme.fg("muted"," \u2022 ")+theme.fg("warning",label)}if(!provider.status.source||provider.status.source==="OAuth"||provider.status.source==="stored credential")return theme.fg("success",` \u2713 ${t("configured")}`);let source=/^[A-Z][A-Z0-9_]*(?:, [A-Z][A-Z0-9_]*)*$/.test(provider.status.source)?t("env: {source}",{source:provider.status.source}):provider.status.source;return theme.fg("success",` \u2713 ${source}`)}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"tui.select.up")){if(this.filteredProviders.length===0)return;this.selectedIndex=Math.max(0,this.selectedIndex-1),this.updateList()}else if(kb.matches(keyData,"tui.select.down")){if(this.filteredProviders.length===0)return;this.selectedIndex=Math.min(this.filteredProviders.length-1,this.selectedIndex+1),this.updateList()}else if(kb.matches(keyData,"tui.select.confirm")){let selectedProvider=this.filteredProviders[this.selectedIndex];selectedProvider&&this.onSelectCallback(selectedProvider.id,selectedProvider.authType)}else kb.matches(keyData,"tui.select.cancel")?this.onCancelCallback():(this.searchInput.handleInput(keyData),this.filterProviders(this.searchInput.getValue()))}};var WIDTH=31,HEIGHT=36,BITS=[255,255,255,127,255,240,255,127,255,237,255,127,255,219,255,127,255,183,255,127,255,119,254,127,63,248,254,127,223,255,254,127,223,63,252,127,159,195,251,127,111,252,244,127,247,15,247,127,247,255,247,127,247,255,227,127,247,7,232,127,239,248,103,112,15,255,187,111,241,0,208,91,253,63,236,83,193,255,239,87,159,253,238,95,159,252,174,95,31,120,172,95,63,0,80,108,127,0,220,119,255,192,63,120,255,1,248,127,255,3,156,120,255,7,140,124,255,15,206,120,255,255,207,127,255,255,207,120,255,255,223,120,255,255,223,125,255,255,63,126,255,255,255,127],BYTES_PER_ROW=Math.ceil(WIDTH/8),DISPLAY_HEIGHT=Math.ceil(HEIGHT/2),EFFECTS=["typewriter","scanline","rain","fade","crt","glitch","dissolve"];function getPixel(x,y){if(y>=HEIGHT)return!1;let byteIndex=y*BYTES_PER_ROW+Math.floor(x/8),bitIndex=x%8;return(BITS[byteIndex]>>bitIndex&1)===0}function getChar(x,row){let upper=getPixel(x,row*2),lower=getPixel(x,row*2+1);return upper&&lower?"\u2588":upper?"\u2580":lower?"\u2584":" "}function buildFinalGrid(){let grid=[];for(let row=0;row<DISPLAY_HEIGHT;row++){let line=[];for(let x=0;x<WIDTH;x++)line.push(getChar(x,row));grid.push(line)}return grid}var ArminComponent=class{ui;interval=null;effect;finalGrid;currentGrid;effectState={};cachedLines=[];cachedWidth=0;gridVersion=0;cachedVersion=-1;constructor(ui){this.ui=ui,this.effect=EFFECTS[Math.floor(Math.random()*EFFECTS.length)],this.finalGrid=buildFinalGrid(),this.currentGrid=this.createEmptyGrid(),this.initEffect(),this.startAnimation()}invalidate(){this.cachedWidth=0}render(width){if(width===this.cachedWidth&&this.cachedVersion===this.gridVersion)return this.cachedLines;let padding=1,availableWidth=width-padding;this.cachedLines=this.currentGrid.map(row=>{let clipped=row.slice(0,availableWidth).join(""),padRight=Math.max(0,width-padding-clipped.length);return` ${theme.fg("accent",clipped)}${" ".repeat(padRight)}`});let message="ARMIN SAYS HI",msgPadRight=Math.max(0,width-padding-message.length);return this.cachedLines.push(` ${theme.fg("accent",message)}${" ".repeat(msgPadRight)}`),this.cachedWidth=width,this.cachedVersion=this.gridVersion,this.cachedLines}createEmptyGrid(){return Array.from({length:DISPLAY_HEIGHT},()=>Array(WIDTH).fill(" "))}initEffect(){switch(this.effect){case"typewriter":this.effectState={pos:0};break;case"scanline":this.effectState={row:0};break;case"rain":this.effectState={drops:Array.from({length:WIDTH},()=>({y:-Math.floor(Math.random()*DISPLAY_HEIGHT*2),settled:0}))};break;case"fade":{let positions=[];for(let row=0;row<DISPLAY_HEIGHT;row++)for(let x=0;x<WIDTH;x++)positions.push([row,x]);for(let i=positions.length-1;i>0;i--){let j=Math.floor(Math.random()*(i+1));[positions[i],positions[j]]=[positions[j],positions[i]]}this.effectState={positions,idx:0};break}case"crt":this.effectState={expansion:0};break;case"glitch":this.effectState={phase:0,glitchFrames:8};break;case"dissolve":{this.currentGrid=Array.from({length:DISPLAY_HEIGHT},()=>Array.from({length:WIDTH},()=>{let chars=[" ","\u2591","\u2592","\u2593","\u2588","\u2580","\u2584"];return chars[Math.floor(Math.random()*chars.length)]}));let dissolvePositions=[];for(let row=0;row<DISPLAY_HEIGHT;row++)for(let x=0;x<WIDTH;x++)dissolvePositions.push([row,x]);for(let i=dissolvePositions.length-1;i>0;i--){let j=Math.floor(Math.random()*(i+1));[dissolvePositions[i],dissolvePositions[j]]=[dissolvePositions[j],dissolvePositions[i]]}this.effectState={positions:dissolvePositions,idx:0};break}}}startAnimation(){let fps=this.effect==="glitch"?60:30;this.interval=setInterval(()=>{let done=this.tickEffect();this.updateDisplay(),this.ui.requestRender(),done&&this.stopAnimation()},1e3/fps)}stopAnimation(){this.interval&&(clearInterval(this.interval),this.interval=null)}tickEffect(){switch(this.effect){case"typewriter":return this.tickTypewriter();case"scanline":return this.tickScanline();case"rain":return this.tickRain();case"fade":return this.tickFade();case"crt":return this.tickCrt();case"glitch":return this.tickGlitch();case"dissolve":return this.tickDissolve();default:return!0}}tickTypewriter(){let state=this.effectState,pixelsPerFrame=3;for(let i=0;i<pixelsPerFrame;i++){let row=Math.floor(state.pos/WIDTH),x=state.pos%WIDTH;if(row>=DISPLAY_HEIGHT)return!0;this.currentGrid[row][x]=this.finalGrid[row][x],state.pos++}return!1}tickScanline(){let state=this.effectState;if(state.row>=DISPLAY_HEIGHT)return!0;for(let x=0;x<WIDTH;x++)this.currentGrid[state.row][x]=this.finalGrid[state.row][x];return state.row++,!1}tickRain(){let state=this.effectState,allSettled=!0;this.currentGrid=this.createEmptyGrid();for(let x=0;x<WIDTH;x++){let drop=state.drops[x];for(let row=DISPLAY_HEIGHT-1;row>=DISPLAY_HEIGHT-drop.settled;row--)row>=0&&(this.currentGrid[row][x]=this.finalGrid[row][x]);if(drop.settled>=DISPLAY_HEIGHT)continue;allSettled=!1;let targetRow=-1;for(let row=DISPLAY_HEIGHT-1-drop.settled;row>=0;row--)if(this.finalGrid[row][x]!==" "){targetRow=row;break}drop.y++,drop.y>=0&&drop.y<DISPLAY_HEIGHT&&(targetRow>=0&&drop.y>=targetRow?(drop.settled=DISPLAY_HEIGHT-targetRow,drop.y=-Math.floor(Math.random()*5)-1):this.currentGrid[drop.y][x]="\u2593")}return allSettled}tickFade(){let state=this.effectState,pixelsPerFrame=15;for(let i=0;i<pixelsPerFrame;i++){if(state.idx>=state.positions.length)return!0;let[row,x]=state.positions[state.idx];this.currentGrid[row][x]=this.finalGrid[row][x],state.idx++}return!1}tickCrt(){let state=this.effectState,midRow=Math.floor(DISPLAY_HEIGHT/2);this.currentGrid=this.createEmptyGrid();let top=midRow-state.expansion,bottom=midRow+state.expansion;for(let row=Math.max(0,top);row<=Math.min(DISPLAY_HEIGHT-1,bottom);row++)for(let x=0;x<WIDTH;x++)this.currentGrid[row][x]=this.finalGrid[row][x];return state.expansion++,state.expansion>DISPLAY_HEIGHT}tickGlitch(){let state=this.effectState;return state.phase<state.glitchFrames?(this.currentGrid=this.finalGrid.map(row=>{let offset=Math.floor(Math.random()*7)-3,glitchRow=[...row];if(Math.random()<.3)return glitchRow.slice(offset).concat(glitchRow.slice(0,offset)).slice(0,WIDTH);if(Math.random()<.2){let swapRow=Math.floor(Math.random()*DISPLAY_HEIGHT);return[...this.finalGrid[swapRow]]}return glitchRow}),state.phase++,!1):(this.currentGrid=this.finalGrid.map(row=>[...row]),!0)}tickDissolve(){let state=this.effectState,pixelsPerFrame=20;for(let i=0;i<pixelsPerFrame;i++){if(state.idx>=state.positions.length)return!0;let[row,x]=state.positions[state.idx];this.currentGrid[row][x]=this.finalGrid[row][x],state.idx++}return!1}updateDisplay(){this.gridVersion++}dispose(){this.stopAnimation()}};var PREVIEW_LINES=20,BashExecutionComponent=class extends Container{command;outputLines=[];status="running";exitCode=void 0;loader;truncationResult;fullOutputPath;expanded=!1;contentContainer;constructor(command,ui,excludeFromContext=!1){super(),this.command=command;let colorKey=excludeFromContext?"dim":"bashMode",borderColor=str=>theme.fg(colorKey,str);this.addChild(new Spacer(1)),this.addChild(new DynamicBorder(borderColor)),this.contentContainer=new Container,this.addChild(this.contentContainer);let header=new Text(theme.fg(colorKey,theme.bold(`$ ${command}`)),1,0);this.contentContainer.addChild(header),this.loader=new Loader(ui,spinner=>theme.fg(colorKey,spinner),text=>theme.fg("muted",text),t("Running... ({key} to cancel)",{key:keyText("tui.select.cancel")})),this.contentContainer.addChild(this.loader),this.addChild(new DynamicBorder(borderColor))}setExpanded(expanded){this.expanded=expanded,this.updateDisplay()}invalidate(){super.invalidate(),this.updateDisplay()}appendOutput(chunk){let newLines=stripAnsi(chunk).replace(/\r\n/g,`
|
|
591
|
+
`)}):this.hideThinkingBlock||specs.push({kind:"thinking-summary",text:theme.italic(theme.fg("thinkingText",t("\u273B thinking")))}),hasVisibleContentAfter&&specs.push({kind:"spacer",text:""})}}let hasToolCalls=message.content.some(c=>c.type==="toolCall");if(message.stopReason==="length")specs.push({kind:"spacer",text:""}),specs.push({kind:"status",text:theme.fg("error",t("Response was truncated before completion."))});else if(!hasToolCalls){if(message.stopReason==="aborted"){let abortMessage=message.errorMessage&&message.errorMessage!=="Request was aborted"?message.errorMessage:t("Operation aborted");specs.push({kind:"spacer",text:""}),specs.push({kind:"status",text:theme.fg("error",abortMessage)})}else if(message.stopReason==="error"){let errorMsg=message.errorMessage||t("Unknown error");specs.push({kind:"spacer",text:""}),specs.push({kind:"status",text:theme.fg("error",t("Error: {message}",{message:errorMsg}))})}}return specs}};var CustomEditor=class extends Editor{keybindings;actionHandlers=new Map;onEscape;onCtrlD;onPasteImage;constructor(tui,theme2,keybindings,options){super(tui,theme2,options),this.keybindings=keybindings}onAction(action,handler){this.actionHandlers.set(action,handler)}handleInput(data){if(this.keybindings.matches(data,"app.clipboard.pasteImage")){this.onPasteImage?.();return}if(this.keybindings.matches(data,"app.interrupt")){if(!this.isShowingAutocomplete()){let handler=this.onEscape??this.actionHandlers.get("app.interrupt");if(handler){handler();return}}super.handleInput(data);return}if(this.keybindings.matches(data,"app.exit")&&this.getText().length===0){let handler=this.onCtrlD??this.actionHandlers.get("app.exit");handler&&handler();return}if(this.keybindings.matches(data,"tui.editor.historyPrevious")||this.keybindings.matches(data,"tui.editor.historyNext")){super.handleInput(data);return}for(let[action,handler]of this.actionHandlers)if(action!=="app.interrupt"&&action!=="app.exit"&&this.keybindings.matches(data,action)){handler();return}super.handleInput(data)}};import{isAbsolute as isAbsolute10,relative as relative7,resolve as resolve17,sep as sep10}from"node:path";function areExperimentalFeaturesEnabled(){return process.env.AGENT_FORGE_EXPERIMENTAL==="1"}function sanitizeStatusText(text){return text.replace(/[\r\n\t]/g," ").replace(/ +/g," ").trim()}function formatTokens(count){return count<1e3?count.toString():count<1e4?`${(count/1e3).toFixed(1)}k`:count<1e6?`${Math.round(count/1e3)}k`:count<1e7?`${(count/1e6).toFixed(1)}M`:`${Math.round(count/1e6)}M`}function formatCwdForFooter(cwd,home){if(!home)return cwd;let resolvedCwd=resolve17(cwd),resolvedHome=resolve17(home),relativeToHome=relative7(resolvedHome,resolvedCwd);return relativeToHome===""||relativeToHome!==".."&&!relativeToHome.startsWith(`..${sep10}`)&&!isAbsolute10(relativeToHome)?relativeToHome===""?"~":`~${sep10}${relativeToHome}`:cwd}function summarizeFailoverState(state,nowMs){if(state?.status!=="open"||typeof state.chainId!="string"||state.chainId==="")return;let parts=[`failover: \u4E3B ${state.chainId} \u4E0D\u53EF\u7528`];typeof state.backupProvider=="string"&&state.backupProvider!==""&&parts.push(`\u7ECF ${state.backupProvider}`);let probeAtMs=typeof state.probeAtMs=="number"?state.probeAtMs:0;return probeAtMs-nowMs<=0?parts.push("\u7B49\u5F85\u8BD5\u63A2"):parts.push(`\u4E0B\u6B21\u8BD5\u63A2 ${Math.ceil((probeAtMs-nowMs)/1e3)}s`),parts.join(" \u2022 ")}function summarizeWorkflowState(state){let workflows=state?.workflows,records=Array.isArray(workflows)?workflows:[],record=[...records].reverse().find(item=>item?.status==="draft"||item?.status==="running")??records.at(-1);if(record===void 0||typeof record.title!="string")return;let stages=Array.isArray(record.runtime)?record.runtime:[],done=stages.filter(stage=>stage?.status==="completed"||stage?.status==="skipped").length,activeCount=stages.filter(stage=>stage?.status==="active").length,parts=[`wf: ${record.title} ${done}/${stages.length}`];return activeCount>=2&&parts.push(`\u25B6${activeCount}`),stages.some(stage=>stage?.status==="awaiting_review")&&parts.push("\u23F8"),Array.isArray(record.diagnostics)&&record.diagnostics.length>0&&parts.push("\u26A0"),record.status==="failed"&&parts.push("\u2717"),parts.join(" ")}var FooterComponent=class{session;footerData;sessionStats;constructor(session,footerData){this.session=session,this.footerData=footerData}setSession(session){this.session=session}get facade(){return createCodingAgentFacade(this.session)}invalidate(){}dispose(){}getSessionStats(){let facade=this.facade,sessionId=facade.getSessionId(),leafId=facade.getLeafId(),model=facade.getModel(),cached=this.sessionStats;if(cached&&cached.session===this.session&&cached.sessionId===sessionId&&cached.leafId===leafId&&cached.model===model)return cached;let usageTotals=createUsageTotals(),latestCacheHitRate,goalTitle,todoDone=0,todoTotal=0,workflowState,failoverState;for(let entry of facade.getEntries())if(entry.type==="message"&&entry.message.role==="assistant"){addUsageToTotals(usageTotals,entry.message.usage);let latestPromptTokens=entry.message.usage.input+entry.message.usage.cacheRead+entry.message.usage.cacheWrite;latestCacheHitRate=latestPromptTokens>0?entry.message.usage.cacheRead/latestPromptTokens*100:void 0}else if(entry.type==="message"&&entry.message.role==="toolResult"&&entry.message.usage)addUsageToTotals(usageTotals,entry.message.usage);else if((entry.type==="branch_summary"||entry.type==="compaction")&&entry.usage)addUsageToTotals(usageTotals,entry.usage);else if(entry.type==="custom"&&entry.customType==="goal.state"){let goals=entry.data?.goals,current=Array.isArray(goals)?goals.at(-1):void 0;current&&typeof current.title=="string"&&(goalTitle=current.title)}else if(entry.type==="custom"&&entry.customType==="todo.state"){let todos=entry.data?.todos;Array.isArray(todos)&&(todoDone=todos.filter(item=>item?.status==="done").length,todoTotal=todos.length)}else entry.type==="custom"&&entry.customType==="workflow.state"?workflowState=entry.data:entry.type==="custom"&&entry.customType==="provider.failover.state"&&(failoverState=entry.data);let contextUsage=facade.getContextUsage();return this.sessionStats={session:this.session,sessionId,leafId,model,usageTotals,latestCacheHitRate,goalTitle,todoDone,todoTotal,workflowState,failoverState,contextUsage},this.sessionStats}isProviderFailoverOpen(){return this.getSessionStats().failoverState?.status==="open"}render(width){let state=this.facade.getState(),{usageTotals,latestCacheHitRate,contextUsage,goalTitle,todoDone,todoTotal,workflowState,failoverState}=this.getSessionStats(),contextWindow=contextUsage?.contextWindow??state.model?.contextWindow??0,contextPercentValue=contextUsage?.percent??0,contextPercent=contextUsage?.percent!==null?contextPercentValue.toFixed(1):"?",pwd=formatCwdForFooter(this.facade.getCwd(),process.env.HOME||process.env.USERPROFILE),branch=this.footerData.getGitBranch();branch&&(pwd=`${pwd} (${branch})`);let sessionName=this.facade.getSessionName();sessionName&&(pwd=`${pwd} \u2022 ${sessionName}`);let statsParts=[];usageTotals.input&&statsParts.push(`\u2191${formatTokens(usageTotals.input)}`),usageTotals.output&&statsParts.push(`\u2193${formatTokens(usageTotals.output)}`),usageTotals.cacheRead&&statsParts.push(`R${formatTokens(usageTotals.cacheRead)}`),usageTotals.cacheWrite&&statsParts.push(`W${formatTokens(usageTotals.cacheWrite)}`),(usageTotals.cacheRead>0||usageTotals.cacheWrite>0)&&latestCacheHitRate!==void 0&&statsParts.push(`CH${latestCacheHitRate.toFixed(1)}%`);let usingSubscription=state.model?state.model.provider==="kimi-coding"||this.facade.isUsingSubscription(state.model.provider):!1;if(usageTotals.cost||usingSubscription){let costStr=`$${usageTotals.cost.toFixed(3)}${usingSubscription?` ${t("(sub)")}`:""}`;statsParts.push(costStr)}let contextPercentStr,contextPercentDisplay=contextPercent==="?"?`?/${formatTokens(contextWindow)}`:`${contextPercent}%/${formatTokens(contextWindow)}`;contextPercentValue>90?contextPercentStr=theme.fg("error",contextPercentDisplay):contextPercentValue>70?contextPercentStr=theme.fg("warning",contextPercentDisplay):contextPercentStr=contextPercentDisplay,statsParts.push(contextPercentStr),areExperimentalFeaturesEnabled()&&statsParts.push(`${theme.fg("dim","\u2022")} ${theme.bold(theme.fg("warning","xp"))}`);let statsLeft=statsParts.join(" "),modelName=state.model?.id||t("no-model"),statsLeftWidth=visibleWidth(statsLeft);statsLeftWidth>width&&(statsLeft=truncateToWidth(statsLeft,width,"..."),statsLeftWidth=visibleWidth(statsLeft));let minPadding=2,rightSideWithoutProvider=modelName;if(state.model?.reasoning){let thinkingLevel=state.thinkingLevel||"off";rightSideWithoutProvider=thinkingLevel==="off"?t("{model} \u2022 thinking off",{model:modelName}):`${modelName} \u2022 ${thinkingLevel}`}let rightSide=rightSideWithoutProvider;this.footerData.getAvailableProviderCount()>1&&state.model&&(rightSide=`(${state.model.provider}) ${rightSideWithoutProvider}`,statsLeftWidth+minPadding+visibleWidth(rightSide)>width&&(rightSide=rightSideWithoutProvider));let rightSideWidth=visibleWidth(rightSide),totalNeeded=statsLeftWidth+minPadding+rightSideWidth,statsLine;if(totalNeeded<=width){let padding=" ".repeat(width-statsLeftWidth-rightSideWidth);statsLine=statsLeft+padding+rightSide}else{let availableForRight=width-statsLeftWidth-minPadding;if(availableForRight>0){let truncatedRight=truncateToWidth(rightSide,availableForRight,""),truncatedRightWidth=visibleWidth(truncatedRight),padding=" ".repeat(Math.max(0,width-statsLeftWidth-truncatedRightWidth));statsLine=statsLeft+padding+truncatedRight}else statsLine=statsLeft}let dimStatsLeft=theme.fg("dim",statsLeft),remainder=statsLine.slice(statsLeft.length),dimRemainder=theme.fg("dim",remainder),lines=[truncateToWidth(theme.fg("dim",pwd),width,theme.fg("dim","...")),dimStatsLeft+dimRemainder];if(goalTitle!==void 0||todoTotal>0){let goalParts=[];goalTitle!==void 0&&goalParts.push(`goal: ${goalTitle}`),todoTotal>0&&goalParts.push(`todo ${todoDone}/${todoTotal}`);let goalLine=theme.fg("dim",sanitizeStatusText(goalParts.join(" \u2022 ")));lines.push(truncateToWidth(goalLine,width,theme.fg("dim","...")))}let workflowSummary=summarizeWorkflowState(workflowState);if(workflowSummary!==void 0){let workflowLine=theme.fg("dim",sanitizeStatusText(workflowSummary));lines.push(truncateToWidth(workflowLine,width,theme.fg("dim","...")))}let failoverSummary=summarizeFailoverState(failoverState,Date.now());if(failoverSummary!==void 0){let failoverLine=theme.fg("warning",sanitizeStatusText(failoverSummary));lines.push(truncateToWidth(failoverLine,width,theme.fg("warning","...")))}return lines}};import{spawn as spawn3}from"node:child_process";function openBrowser(target){let[cmd,args]=process.platform==="darwin"?["open",[target]]:process.platform==="win32"?["rundll32",["url.dll,FileProtocolHandler",target]]:["xdg-open",[target]];spawn3(cmd,args,{stdio:"ignore",detached:!0}).on("error",()=>{}).unref()}var LoginDialogComponent=class extends Container{contentContainer;input;tui;abortController=new AbortController;inputResolver;inputRejecter;onComplete;_focused=!1;get focused(){return this._focused}set focused(value){this._focused=value,this.input.focused=value}constructor(tui,providerId,onComplete,providerNameOverride,titleOverride){super(),this.tui=tui,this.onComplete=onComplete;let title=titleOverride??t("Login to {provider}",{provider:providerNameOverride||providerId});this.addChild(new DynamicBorder),this.addChild(new Text(theme.fg("accent",theme.bold(title)),1,0)),this.contentContainer=new Container,this.addChild(this.contentContainer),this.input=new Input,this.input.onSubmit=()=>{if(this.inputResolver){let value=this.input.getValue();this.replaceInputWithSubmittedText(value),this.inputResolver(value),this.inputResolver=void 0,this.inputRejecter=void 0}},this.input.onEscape=()=>{this.cancel()},this.addChild(new DynamicBorder)}get signal(){return this.abortController.signal}replaceInputWithSubmittedText(value){this.contentContainer.children=this.contentContainer.children.map(child=>child===this.input?new Text(`> ${value}`,0,0):child)}cancel(){this.abortController.abort(),this.inputRejecter&&(this.inputRejecter(new Error(t("Login cancelled"))),this.inputResolver=void 0,this.inputRejecter=void 0),this.onComplete(!1,t("Login cancelled"))}showAuth(url,instructions){this.contentContainer.clear(),this.contentContainer.addChild(new Spacer(1));let linkedUrl=`\x1B]8;;${url}\x07${url}\x1B]8;;\x07`;this.contentContainer.addChild(new Text(theme.fg("accent",linkedUrl),1,0));let clickHint=process.platform==="darwin"?t("Cmd+click to open"):t("Ctrl+click to open"),hyperlink2=`\x1B]8;;${url}\x07${clickHint}\x1B]8;;\x07`;this.contentContainer.addChild(new Text(theme.fg("dim",hyperlink2),1,0)),instructions&&(this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("warning",instructions),1,0))),openBrowser(url),this.tui.requestRender()}showDeviceCode(info){this.contentContainer.clear(),this.contentContainer.addChild(new Spacer(1));let linkedUrl=`\x1B]8;;${info.verificationUri}\x07${info.verificationUri}\x1B]8;;\x07`;this.contentContainer.addChild(new Text(theme.fg("accent",linkedUrl),1,0));let clickHint=process.platform==="darwin"?t("Cmd+click to open"):t("Ctrl+click to open"),hyperlink2=`\x1B]8;;${info.verificationUri}\x07${clickHint}\x1B]8;;\x07`;this.contentContainer.addChild(new Text(theme.fg("dim",hyperlink2),1,0)),this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("warning",t("Enter code: {code}",{code:info.userCode})),1,0)),this.tui.requestRender()}showManualInput(prompt){return this.input.setValue(""),this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("dim",prompt),1,0)),this.contentContainer.addChild(this.input),this.contentContainer.addChild(new Text(`(${keyHint("tui.select.cancel",t("to cancel"))})`,1,0)),this.tui.requestRender(),new Promise((resolve22,reject2)=>{this.inputResolver=resolve22,this.inputRejecter=reject2})}showPrompt(message,placeholder){return this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("text",message),1,0)),placeholder&&this.contentContainer.addChild(new Text(theme.fg("dim",t("e.g., {placeholder}",{placeholder})),1,0)),this.contentContainer.addChild(this.input),this.contentContainer.addChild(new Text(`(${keyHint("tui.select.cancel",t("to cancel,"))} ${keyHint("tui.select.confirm",t("to submit"))})`,1,0)),this.input.setValue(""),this.tui.requestRender(),new Promise((resolve22,reject2)=>{this.inputResolver=resolve22,this.inputRejecter=reject2})}showDetails(lines){this.contentContainer.clear(),this.contentContainer.addChild(new Spacer(1));for(let line of lines)this.contentContainer.addChild(new Text(line,1,0));this.tui.requestRender()}showInfo(message,links=[],showCloseHint=!1){this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("text",message),1,0));for(let link of links){let text=link.label?`${link.label}: ${link.url}`:link.url,hyperlink2=`\x1B]8;;${link.url}\x07${text}\x1B]8;;\x07`;this.contentContainer.addChild(new Text(theme.fg("accent",hyperlink2),1,0))}showCloseHint&&(this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(`(${keyHint("tui.select.cancel",t("to close"))})`,1,0))),this.tui.requestRender()}showWaiting(message){this.contentContainer.addChild(new Spacer(1)),this.contentContainer.addChild(new Text(theme.fg("dim",message),1,0)),this.contentContainer.addChild(new Text(`(${keyHint("tui.select.cancel",t("to cancel"))})`,1,0)),this.tui.requestRender()}showProgress(message){this.contentContainer.addChild(new Text(theme.fg("dim",message),1,0)),this.tui.requestRender()}handleInput(data){if(getKeybindings().matches(data,"tui.select.cancel")){this.cancel();return}this.input.handleInput(data)}};function formatAuthSelectorProviderType(authType){return authType==="oauth"?t("subscription"):t("API key")}var OAuthSelectorComponent=class extends Container{searchInput;_focused=!1;get focused(){return this._focused}set focused(value){this._focused=value,this.searchInput.focused=value}listContainer;allProviders;filteredProviders;selectedIndex=0;mode;onSelectCallback;onCancelCallback;showAuthTypeLabels;constructor(mode,providers,onSelect,onCancel,initialSearchInput){super(),this.mode=mode,this.allProviders=providers,this.filteredProviders=providers,this.showAuthTypeLabels=new Set(providers.map(provider=>provider.authType)).size>1,this.onSelectCallback=onSelect,this.onCancelCallback=onCancel,this.addChild(new DynamicBorder),this.addChild(new Spacer(1));let title=mode==="login"?t("Select provider to configure:"):t("Select provider to logout:");this.addChild(new TruncatedText(theme.fg("accent",theme.bold(title)),1,0)),this.addChild(new Spacer(1)),this.searchInput=new Input,initialSearchInput&&this.searchInput.setValue(initialSearchInput),this.searchInput.onSubmit=()=>{let selectedProvider=this.filteredProviders[this.selectedIndex];selectedProvider&&this.onSelectCallback(selectedProvider.id,selectedProvider.authType)},this.addChild(this.searchInput),this.addChild(new Spacer(1)),this.listContainer=new Container,this.addChild(this.listContainer),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),this.filterProviders(initialSearchInput??"")}filterProviders(query){this.filteredProviders=query?fuzzyFilter(this.allProviders,query,provider=>`${provider.name} ${provider.id} ${provider.authType} ${provider.method?.name??""}`):this.allProviders,this.selectedIndex=Math.max(0,Math.min(this.selectedIndex,Math.max(0,this.filteredProviders.length-1))),this.updateList()}updateList(){this.listContainer.clear();let maxVisible=8,startIndex=Math.max(0,Math.min(this.selectedIndex-Math.floor(maxVisible/2),this.filteredProviders.length-maxVisible)),endIndex=Math.min(startIndex+maxVisible,this.filteredProviders.length);for(let i=startIndex;i<endIndex;i++){let provider=this.filteredProviders[i];if(!provider)continue;let isSelected=i===this.selectedIndex,statusIndicator=this.formatStatusIndicator(provider),authTypeLabel=this.showAuthTypeLabels?theme.fg("muted",` [${formatAuthSelectorProviderType(provider.authType)}]`):"",line="";if(isSelected){let prefix=theme.fg("accent","\u2192 "),text=theme.fg("accent",provider.name);line=prefix+text+authTypeLabel+statusIndicator}else line=` ${theme.fg("text",provider.name)}`+authTypeLabel+statusIndicator;this.listContainer.addChild(new TruncatedText(line,1,0))}if(startIndex>0||endIndex<this.filteredProviders.length){let scrollInfo=theme.fg("muted",` (${this.selectedIndex+1}/${this.filteredProviders.length})`);this.listContainer.addChild(new TruncatedText(scrollInfo,1,0))}if(this.filteredProviders.length===0){let message=this.allProviders.length===0?this.mode==="login"?t("No providers available"):t("No providers logged in. Use /login first."):t("No matching providers");this.listContainer.addChild(new TruncatedText(theme.fg("muted",` ${message}`),1,0))}}formatStatusIndicator(provider){if(!provider.status)return theme.fg("muted",` \u2022 ${t("unconfigured")}`);if(provider.status.type!==provider.authType){let label=provider.status.type==="oauth"?t("subscription configured"):t("API key configured");return theme.fg("muted"," \u2022 ")+theme.fg("warning",label)}if(!provider.status.source||provider.status.source==="OAuth"||provider.status.source==="stored credential")return theme.fg("success",` \u2713 ${t("configured")}`);let source=/^[A-Z][A-Z0-9_]*(?:, [A-Z][A-Z0-9_]*)*$/.test(provider.status.source)?t("env: {source}",{source:provider.status.source}):provider.status.source;return theme.fg("success",` \u2713 ${source}`)}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"tui.select.up")){if(this.filteredProviders.length===0)return;this.selectedIndex=Math.max(0,this.selectedIndex-1),this.updateList()}else if(kb.matches(keyData,"tui.select.down")){if(this.filteredProviders.length===0)return;this.selectedIndex=Math.min(this.filteredProviders.length-1,this.selectedIndex+1),this.updateList()}else if(kb.matches(keyData,"tui.select.confirm")){let selectedProvider=this.filteredProviders[this.selectedIndex];selectedProvider&&this.onSelectCallback(selectedProvider.id,selectedProvider.authType)}else kb.matches(keyData,"tui.select.cancel")?this.onCancelCallback():(this.searchInput.handleInput(keyData),this.filterProviders(this.searchInput.getValue()))}};var WIDTH=31,HEIGHT=36,BITS=[255,255,255,127,255,240,255,127,255,237,255,127,255,219,255,127,255,183,255,127,255,119,254,127,63,248,254,127,223,255,254,127,223,63,252,127,159,195,251,127,111,252,244,127,247,15,247,127,247,255,247,127,247,255,227,127,247,7,232,127,239,248,103,112,15,255,187,111,241,0,208,91,253,63,236,83,193,255,239,87,159,253,238,95,159,252,174,95,31,120,172,95,63,0,80,108,127,0,220,119,255,192,63,120,255,1,248,127,255,3,156,120,255,7,140,124,255,15,206,120,255,255,207,127,255,255,207,120,255,255,223,120,255,255,223,125,255,255,63,126,255,255,255,127],BYTES_PER_ROW=Math.ceil(WIDTH/8),DISPLAY_HEIGHT=Math.ceil(HEIGHT/2),EFFECTS=["typewriter","scanline","rain","fade","crt","glitch","dissolve"];function getPixel(x,y){if(y>=HEIGHT)return!1;let byteIndex=y*BYTES_PER_ROW+Math.floor(x/8),bitIndex=x%8;return(BITS[byteIndex]>>bitIndex&1)===0}function getChar(x,row){let upper=getPixel(x,row*2),lower=getPixel(x,row*2+1);return upper&&lower?"\u2588":upper?"\u2580":lower?"\u2584":" "}function buildFinalGrid(){let grid=[];for(let row=0;row<DISPLAY_HEIGHT;row++){let line=[];for(let x=0;x<WIDTH;x++)line.push(getChar(x,row));grid.push(line)}return grid}var ArminComponent=class{ui;interval=null;effect;finalGrid;currentGrid;effectState={};cachedLines=[];cachedWidth=0;gridVersion=0;cachedVersion=-1;constructor(ui){this.ui=ui,this.effect=EFFECTS[Math.floor(Math.random()*EFFECTS.length)],this.finalGrid=buildFinalGrid(),this.currentGrid=this.createEmptyGrid(),this.initEffect(),this.startAnimation()}invalidate(){this.cachedWidth=0}render(width){if(width===this.cachedWidth&&this.cachedVersion===this.gridVersion)return this.cachedLines;let padding=1,availableWidth=width-padding;this.cachedLines=this.currentGrid.map(row=>{let clipped=row.slice(0,availableWidth).join(""),padRight=Math.max(0,width-padding-clipped.length);return` ${theme.fg("accent",clipped)}${" ".repeat(padRight)}`});let message="ARMIN SAYS HI",msgPadRight=Math.max(0,width-padding-message.length);return this.cachedLines.push(` ${theme.fg("accent",message)}${" ".repeat(msgPadRight)}`),this.cachedWidth=width,this.cachedVersion=this.gridVersion,this.cachedLines}createEmptyGrid(){return Array.from({length:DISPLAY_HEIGHT},()=>Array(WIDTH).fill(" "))}initEffect(){switch(this.effect){case"typewriter":this.effectState={pos:0};break;case"scanline":this.effectState={row:0};break;case"rain":this.effectState={drops:Array.from({length:WIDTH},()=>({y:-Math.floor(Math.random()*DISPLAY_HEIGHT*2),settled:0}))};break;case"fade":{let positions=[];for(let row=0;row<DISPLAY_HEIGHT;row++)for(let x=0;x<WIDTH;x++)positions.push([row,x]);for(let i=positions.length-1;i>0;i--){let j=Math.floor(Math.random()*(i+1));[positions[i],positions[j]]=[positions[j],positions[i]]}this.effectState={positions,idx:0};break}case"crt":this.effectState={expansion:0};break;case"glitch":this.effectState={phase:0,glitchFrames:8};break;case"dissolve":{this.currentGrid=Array.from({length:DISPLAY_HEIGHT},()=>Array.from({length:WIDTH},()=>{let chars=[" ","\u2591","\u2592","\u2593","\u2588","\u2580","\u2584"];return chars[Math.floor(Math.random()*chars.length)]}));let dissolvePositions=[];for(let row=0;row<DISPLAY_HEIGHT;row++)for(let x=0;x<WIDTH;x++)dissolvePositions.push([row,x]);for(let i=dissolvePositions.length-1;i>0;i--){let j=Math.floor(Math.random()*(i+1));[dissolvePositions[i],dissolvePositions[j]]=[dissolvePositions[j],dissolvePositions[i]]}this.effectState={positions:dissolvePositions,idx:0};break}}}startAnimation(){let fps=this.effect==="glitch"?60:30;this.interval=setInterval(()=>{let done=this.tickEffect();this.updateDisplay(),this.ui.requestRender(),done&&this.stopAnimation()},1e3/fps)}stopAnimation(){this.interval&&(clearInterval(this.interval),this.interval=null)}tickEffect(){switch(this.effect){case"typewriter":return this.tickTypewriter();case"scanline":return this.tickScanline();case"rain":return this.tickRain();case"fade":return this.tickFade();case"crt":return this.tickCrt();case"glitch":return this.tickGlitch();case"dissolve":return this.tickDissolve();default:return!0}}tickTypewriter(){let state=this.effectState,pixelsPerFrame=3;for(let i=0;i<pixelsPerFrame;i++){let row=Math.floor(state.pos/WIDTH),x=state.pos%WIDTH;if(row>=DISPLAY_HEIGHT)return!0;this.currentGrid[row][x]=this.finalGrid[row][x],state.pos++}return!1}tickScanline(){let state=this.effectState;if(state.row>=DISPLAY_HEIGHT)return!0;for(let x=0;x<WIDTH;x++)this.currentGrid[state.row][x]=this.finalGrid[state.row][x];return state.row++,!1}tickRain(){let state=this.effectState,allSettled=!0;this.currentGrid=this.createEmptyGrid();for(let x=0;x<WIDTH;x++){let drop=state.drops[x];for(let row=DISPLAY_HEIGHT-1;row>=DISPLAY_HEIGHT-drop.settled;row--)row>=0&&(this.currentGrid[row][x]=this.finalGrid[row][x]);if(drop.settled>=DISPLAY_HEIGHT)continue;allSettled=!1;let targetRow=-1;for(let row=DISPLAY_HEIGHT-1-drop.settled;row>=0;row--)if(this.finalGrid[row][x]!==" "){targetRow=row;break}drop.y++,drop.y>=0&&drop.y<DISPLAY_HEIGHT&&(targetRow>=0&&drop.y>=targetRow?(drop.settled=DISPLAY_HEIGHT-targetRow,drop.y=-Math.floor(Math.random()*5)-1):this.currentGrid[drop.y][x]="\u2593")}return allSettled}tickFade(){let state=this.effectState,pixelsPerFrame=15;for(let i=0;i<pixelsPerFrame;i++){if(state.idx>=state.positions.length)return!0;let[row,x]=state.positions[state.idx];this.currentGrid[row][x]=this.finalGrid[row][x],state.idx++}return!1}tickCrt(){let state=this.effectState,midRow=Math.floor(DISPLAY_HEIGHT/2);this.currentGrid=this.createEmptyGrid();let top=midRow-state.expansion,bottom=midRow+state.expansion;for(let row=Math.max(0,top);row<=Math.min(DISPLAY_HEIGHT-1,bottom);row++)for(let x=0;x<WIDTH;x++)this.currentGrid[row][x]=this.finalGrid[row][x];return state.expansion++,state.expansion>DISPLAY_HEIGHT}tickGlitch(){let state=this.effectState;return state.phase<state.glitchFrames?(this.currentGrid=this.finalGrid.map(row=>{let offset=Math.floor(Math.random()*7)-3,glitchRow=[...row];if(Math.random()<.3)return glitchRow.slice(offset).concat(glitchRow.slice(0,offset)).slice(0,WIDTH);if(Math.random()<.2){let swapRow=Math.floor(Math.random()*DISPLAY_HEIGHT);return[...this.finalGrid[swapRow]]}return glitchRow}),state.phase++,!1):(this.currentGrid=this.finalGrid.map(row=>[...row]),!0)}tickDissolve(){let state=this.effectState,pixelsPerFrame=20;for(let i=0;i<pixelsPerFrame;i++){if(state.idx>=state.positions.length)return!0;let[row,x]=state.positions[state.idx];this.currentGrid[row][x]=this.finalGrid[row][x],state.idx++}return!1}updateDisplay(){this.gridVersion++}dispose(){this.stopAnimation()}};var PREVIEW_LINES=20,BashExecutionComponent=class extends Container{command;outputLines=[];status="running";exitCode=void 0;loader;truncationResult;fullOutputPath;expanded=!1;contentContainer;constructor(command,ui,excludeFromContext=!1){super(),this.command=command;let colorKey=excludeFromContext?"dim":"bashMode",borderColor=str=>theme.fg(colorKey,str);this.addChild(new Spacer(1)),this.addChild(new DynamicBorder(borderColor)),this.contentContainer=new Container,this.addChild(this.contentContainer);let header=new Text(theme.fg(colorKey,theme.bold(`$ ${command}`)),1,0);this.contentContainer.addChild(header),this.loader=new Loader(ui,spinner=>theme.fg(colorKey,spinner),text=>theme.fg("muted",text),t("Running... ({key} to cancel)",{key:keyText("tui.select.cancel")})),this.contentContainer.addChild(this.loader),this.addChild(new DynamicBorder(borderColor))}setExpanded(expanded){this.expanded=expanded,this.updateDisplay()}invalidate(){super.invalidate(),this.updateDisplay()}appendOutput(chunk){let newLines=stripAnsi(chunk).replace(/\r\n/g,`
|
|
592
592
|
`).replace(/\r/g,`
|
|
593
593
|
`).split(`
|
|
594
594
|
`);this.outputLines.length>0&&newLines.length>0?(this.outputLines[this.outputLines.length-1]+=newLines[0],this.outputLines.push(...newLines.slice(1))):this.outputLines.push(...newLines),this.updateDisplay()}setComplete(exitCode,cancelled2,truncationResult,fullOutputPath){this.exitCode=exitCode,this.status=cancelled2?"cancelled":exitCode!==0&&exitCode!==void 0&&exitCode!==null?"error":"complete",this.truncationResult=truncationResult,this.fullOutputPath=fullOutputPath,this.loader.stop(),this.updateDisplay()}updateDisplay(){let fullOutput=this.outputLines.join(`
|
|
@@ -600,9 +600,9 @@ ${previewLogicalLines.map(line=>theme.fg("muted",line)).join(`
|
|
|
600
600
|
`)}`,cachedWidth,cachedLines;this.contentContainer.addChild({render:width=>((cachedLines===void 0||cachedWidth!==width)&&(cachedLines=truncateToVisualLines(styledInput,PREVIEW_LINES,width,1).visualLines,cachedWidth=width),cachedLines??[]),invalidate:()=>{cachedWidth=void 0,cachedLines=void 0}})}if(this.status==="running")this.contentContainer.addChild(this.loader);else{let statusParts=[];hiddenLineCount>0&&(this.expanded?statusParts.push(theme.fg("muted",t("({key} to collapse)",{key:keyText("app.tools.expand")}))):statusParts.push(theme.fg("muted",t("... {count} more lines ({key} to expand)",{count:hiddenLineCount,key:keyText("app.tools.expand")})))),this.status==="cancelled"?statusParts.push(theme.fg("warning",t("(cancelled)"))):this.status==="error"&&statusParts.push(theme.fg("error",t("(exit {code})",{code:this.exitCode??"unknown"}))),(this.truncationResult?.truncated||contextTruncation.truncated)&&this.fullOutputPath&&statusParts.push(theme.fg("warning",t("Output truncated. Full output: {path}",{path:this.fullOutputPath}))),statusParts.length>0&&this.contentContainer.addChild(new Text(`
|
|
601
601
|
${statusParts.join(`
|
|
602
602
|
`)}`,1,0))}}getOutput(){return this.outputLines.join(`
|
|
603
|
-
`)}getCommand(){return this.command}};import{spawn as
|
|
603
|
+
`)}getCommand(){return this.command}};import{spawn as spawn4}from"node:child_process";import{mkdtempSync,readFileSync as readFileSync22,rmSync as rmSync3,writeFileSync as writeFileSync13}from"node:fs";import{tmpdir as tmpdir6}from"node:os";import{join as join40}from"node:path";async function editInExternalEditor(options){let directory=mkdtempSync(join40(tmpdir6(),"agent-forge-editor-")),filePath=join40(directory,"prompt.md");try{writeFileSync13(filePath,options.content,"utf-8");let[editor,...editorArgs]=options.command.split(" ");return process.stdout.write(`${t("Launching external editor: {command}",{command:options.command})}
|
|
604
604
|
${t("Agent Forge will resume when the editor exits.")}
|
|
605
|
-
`),await new Promise(resolve22=>{let child=
|
|
605
|
+
`),await new Promise(resolve22=>{let child=spawn4(editor,[...editorArgs,filePath],{stdio:"inherit",shell:process.platform==="win32"});child.on("error",()=>resolve22(null)),child.on("close",code=>resolve22(code))})!==0?{status:"failed"}:{status:"complete",content:stripBom(readFileSync22(filePath,"utf-8")).replace(/\n$/,"")}}finally{try{rmSync3(directory,{recursive:!0,force:!0})}catch{}}}var DialogEditorComponent=class extends Container{editor;onSubmitCallback;onCancelCallback;tui;keybindings;externalEditorCommand;_focused=!1;get focused(){return this._focused}set focused(value){this._focused=value,this.editor.focused=value}constructor(tui,keybindings,title,prefill,onSubmit,onCancel,options,externalEditorCommand){super(),this.tui=tui,this.keybindings=keybindings,this.externalEditorCommand=externalEditorCommand||process.env.VISUAL||process.env.EDITOR||(process.platform==="win32"?"notepad":"nano"),this.onSubmitCallback=onSubmit,this.onCancelCallback=onCancel,this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("accent",title),1,0)),this.addChild(new Spacer(1)),this.editor=new Editor(tui,getEditorTheme(),options),prefill&&this.editor.setText(prefill),this.editor.onSubmit=text=>{this.onSubmitCallback(text)},this.addChild(this.editor),this.addChild(new Spacer(1));let hint=keyHint("tui.select.confirm",t("submit"))+" "+keyHint("tui.input.newLine",t("newline"))+" "+keyHint("tui.select.cancel",t("cancel"))+` ${keyHint("app.editor.external",t("external editor"))}`;this.addChild(new Text(hint,1,0)),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder)}handleInput(keyData){if(getKeybindings().matches(keyData,"tui.select.cancel")){this.onCancelCallback();return}if(this.keybindings.matches(keyData,"app.editor.external")){this.handleOpenExternalEditor();return}this.editor.handleInput(keyData)}async handleOpenExternalEditor(){let content=this.editor.getText();this.tui.stop();try{let result=await editInExternalEditor({command:this.externalEditorCommand,content});result.status==="complete"&&this.editor.setText(result.content)}finally{this.tui.start(),this.tui.requestRender(!0)}}};var BranchSummaryMessageComponent=class extends Box{expanded=!1;message;markdownTheme;constructor(message,markdownTheme=getMarkdownTheme()){super(1,1,t2=>theme.bg("customMessageBg",t2)),this.message=message,this.markdownTheme=markdownTheme,this.updateDisplay()}setExpanded(expanded){this.expanded=expanded,this.updateDisplay()}invalidate(){super.invalidate(),this.updateDisplay()}updateDisplay(){this.clear();let label=theme.fg("customMessageLabel",`\x1B[1m${t("[branch]")}\x1B[22m`);if(this.addChild(new Text(label,0,0)),this.addChild(new Spacer(1)),this.expanded){let header=`${t("**Branch Summary**")}
|
|
606
606
|
|
|
607
607
|
`;this.addChild(new Markdown(header+this.message.summary,0,0,this.markdownTheme,{color:text=>theme.fg("customMessageText",text)}))}else this.addChild(new Text(theme.fg("customMessageText",t("Branch summary ({key} to expand)",{key:keyText("app.tools.expand")})),0,0))}};var CompactionSummaryMessageComponent=class extends Box{expanded=!1;message;markdownTheme;constructor(message,markdownTheme=getMarkdownTheme()){super(1,1,t2=>theme.bg("customMessageBg",t2)),this.message=message,this.markdownTheme=markdownTheme,this.updateDisplay()}setExpanded(expanded){this.expanded=expanded,this.updateDisplay()}invalidate(){super.invalidate(),this.updateDisplay()}updateDisplay(){this.clear();let tokenStr=this.message.tokensBefore.toLocaleString(),label=theme.fg("customMessageLabel",`\x1B[1m${t("[compaction]")}\x1B[22m`);if(this.addChild(new Text(label,0,0)),this.addChild(new Spacer(1)),this.expanded){let header=`${t("**Compacted from {tokens} tokens**",{tokens:tokenStr})}
|
|
608
608
|
|
|
@@ -734,7 +734,7 @@ ${theme.fg("muted",debugLogPath)}`,1,1)),host.ui.requestRender()}function handle
|
|
|
734
734
|
`);event.result.status==="error"?host.showError(message):host.showStatus(message),host.ui.requestRender();break}case"agent_end":host.settingsManager.getShowTerminalProgress()&&host.ui.terminal.setProgress(!1),host.clearStatusIndicator("working"),host.streamingComponent&&(host.chatContainer.removeChild(host.streamingComponent),host.streamingComponent=void 0,host.streamingMessage=void 0),host.pendingTools.clear(),host.activeToolRunGroup?.markRunComplete(),host.activeToolRunGroup=void 0,host.ui.requestRender();break;case"agent_settled":await host.checkShutdownRequested();break;case"compaction_start":{host.settingsManager.getShowTerminalProgress()&&host.ui.terminal.setProgress(!0),host.autoCompactionEscapeHandler=host.defaultEditor.onEscape,host.defaultEditor.onEscape=()=>{host.facade.abortCompaction()},host.showStatusIndicator(new CompactionStatusIndicator(host.ui,event.reason)),host.ui.requestRender();break}case"compaction_end":{if(host.settingsManager.getShowTerminalProgress()&&host.ui.terminal.setProgress(!1),host.autoCompactionEscapeHandler&&(host.defaultEditor.onEscape=host.autoCompactionEscapeHandler,host.autoCompactionEscapeHandler=void 0),host.clearStatusIndicator("compaction"),event.aborted)event.reason==="manual"?host.showError(t("Compaction cancelled")):host.showStatus(t("Auto-compaction cancelled"));else if(event.result){let entries=host.facade.getContextEntries();if(entries[0]?.type!=="compaction")throw new Error(t("Completed compaction is missing from the session context"));host.chatContainer.clear(),host.renderSessionEntries(entries.slice(1)),host.addMessageToChat(createCompactionSummaryMessage(event.result.summary,event.result.tokensBefore,new Date().toISOString())),event.result.usage&&host.addCompactionCostNotice({type:"compaction_cost",kind:"compaction",usage:event.result.usage}),host.footer.invalidate()}else event.errorMessage&&(event.reason==="manual"?host.showError(event.errorMessage):(host.chatContainer.addChild(new Spacer(1)),host.chatContainer.addChild(new Text(theme.fg("error",event.errorMessage),1,0))));host.flushCompactionQueue({willRetry:event.willRetry}),host.ui.requestRender();break}case"compaction_skipped":{host.showStatus(t("Auto-compaction skipped: nothing to compact")),host.ui.requestRender();break}case"auto_retry_start":{host.retryEscapeHandler=host.defaultEditor.onEscape,host.defaultEditor.onEscape=()=>{host.facade.abortRetry()},host.showStatusIndicator(new RetryStatusIndicator(host.ui,event.attempt,event.maxAttempts,event.delayMs)),host.ui.requestRender();break}case"auto_retry_end":{host.retryEscapeHandler&&(host.defaultEditor.onEscape=host.retryEscapeHandler,host.retryEscapeHandler=void 0),host.clearStatusIndicator("retry"),event.success||host.showError(t("Retry failed after {count} attempts: {error}",{count:event.attempt,error:event.finalError||t("Unknown error")})),host.ui.requestRender();break}case"summarization_retry_scheduled":{host.showError(event.errorMessage),host.showStatusIndicator(new RetryStatusIndicator(host.ui,event.attempt,event.maxAttempts,event.delayMs)),host.ui.requestRender();break}case"summarization_retry_attempt_start":{host.clearStatusIndicator("retry"),event.source==="branchSummary"?host.showStatusIndicator(new BranchSummaryStatusIndicator(host.ui)):host.showStatusIndicator(new CompactionStatusIndicator(host.ui,event.reason)),host.ui.requestRender();break}case"summarization_retry_finished":{host.clearStatusIndicator("retry"),host.ui.requestRender();break}}}function getUserMessageText(message){return message.role!=="user"?"":(typeof message.content=="string"?[{type:"text",text:message.content}]:message.content.filter(c=>c.type==="text")).map(c=>c.text).join("")}function addMessageToChat(host,message,options){switch(message.role){case"bashExecution":{let component=new BashExecutionComponent(message.command,host.ui,message.excludeFromContext);message.output&&component.appendOutput(message.output),component.setComplete(message.exitCode,message.cancelled,message.truncated?{truncated:!0}:void 0,message.fullOutputPath),host.chatContainer.addChild(component);break}case"custom":{if(message.display){let component=new CustomMessageComponent(message,void 0,host.getMarkdownThemeWithSettings(),host.outputPad);component.setExpanded(host.toolOutputExpanded),host.chatContainer.addChild(component)}break}case"compactionSummary":{host.chatContainer.addChild(new Spacer(1));let component=new CompactionSummaryMessageComponent(message,host.getMarkdownThemeWithSettings());component.setExpanded(host.toolOutputExpanded),host.chatContainer.addChild(component);break}case"branchSummary":{host.chatContainer.addChild(new Spacer(1));let component=new BranchSummaryMessageComponent(message,host.getMarkdownThemeWithSettings());component.setExpanded(host.toolOutputExpanded),host.chatContainer.addChild(component);break}case"user":{let textContent=host.getUserMessageText(message);if(textContent){host.chatContainer.children.length>0&&host.chatContainer.addChild(new Spacer(1));let skillBlock=parseSkillBlock(textContent);if(skillBlock){let component=new SkillInvocationMessageComponent(skillBlock,host.getMarkdownThemeWithSettings());if(component.setExpanded(host.toolOutputExpanded),host.chatContainer.addChild(component),skillBlock.userMessage){host.chatContainer.addChild(new Spacer(1));let userComponent=new UserMessageComponent(skillBlock.userMessage,host.getMarkdownThemeWithSettings(),host.outputPad,host.getMarkdownTransformers());host.chatContainer.addChild(userComponent)}}else{let userComponent=new UserMessageComponent(textContent,host.getMarkdownThemeWithSettings(),host.outputPad,host.getMarkdownTransformers());host.chatContainer.addChild(userComponent)}options?.populateHistory&&host.editor.addToHistory?.(textContent)}break}case"assistant":{let assistantComponent=new AssistantMessageComponent(message,host.hideThinkingBlock,host.getMarkdownThemeWithSettings(),host.hiddenThinkingLabel,host.outputPad,host.getMarkdownTransformers());host.toolOutputExpanded&&assistantComponent.setExpanded(!0),host.chatContainer.addChild(assistantComponent);break}case"toolResult":break;default:{let _exhaustive=message}}}function renderSessionItems(host,items,options={}){host.pendingTools.clear();let renderedPendingTools=new Map,cacheMisses=host.settingsManager.getShowCacheMissNotices()?collectCacheMisses(host.facade.getEntries(),host.facade.getModelPriceSource()):new Map;options.updateFooter&&(host.footer.invalidate(),host.updateEditorBorderColor());for(let item of items){if(isCustomSessionEntry(item))continue;if(isCompactionCostNotice(item)){host.addCompactionCostNotice(item);continue}let message=item;if(message.role==="assistant"){host.addMessageToChat(message),host.activeToolRunGroup=void 0;for(let content of message.content)if(content.type==="toolCall"){let component=new ToolExecutionComponent(content.name,content.id,content.arguments,{showImages:host.settingsManager.getShowImages(),imageWidthCells:host.settingsManager.getImageWidthCells()},host.getRegisteredToolDefinition(content.name),host.ui,host.facade.getCwd());if(component.setExpanded(host.toolOutputExpanded),host.addToolToRunGroup(component),message.stopReason==="aborted"||message.stopReason==="error"){let errorMessage2;if(message.stopReason==="aborted"){let retryAttempt=host.facade.getRetryAttempt();errorMessage2=retryAttempt>0?retryAttempt===1?t("Aborted after {count} retry attempt",{count:retryAttempt}):t("Aborted after {count} retry attempts",{count:retryAttempt}):t("Operation aborted")}else errorMessage2=message.errorMessage||t("Error");component.updateResult({content:[{type:"text",text:errorMessage2}],isError:!0}),host.noteResultInActiveToolRunGroup(!0)}else renderedPendingTools.set(content.id,component)}if(host.markActiveToolRunGroupComplete(),message.stopReason!=="aborted"&&message.stopReason!=="error"){let miss=cacheMisses.get(message);miss&&host.addCacheMissNotice(miss)}}else if(message.role==="toolResult"){let component=renderedPendingTools.get(message.toolCallId);component&&(component.updateResult(message),host.noteResultInActiveToolRunGroup(message.isError),renderedPendingTools.delete(message.toolCallId))}else host.addMessageToChat(message,options)}for(let[toolCallId,component]of renderedPendingTools)host.pendingTools.set(toolCallId,component);host.activeToolRunGroup=void 0,host.ui.requestRender()}function renderSessionEntries(host,entries,options={}){let items=entries.flatMap(entry=>{if(entry.type==="custom")return[entry];let messages=sessionEntryToContextMessages(entry);return(entry.type==="compaction"||entry.type==="branch_summary")&&entry.usage&&messages.length>0?[...messages,{type:"compaction_cost",kind:entry.type,usage:entry.usage}]:messages});host.renderSessionItems(items,options)}function addCompactionCostNotice(host,notice){if(!host.settingsManager.getShowCacheMissNotices())return;let{usage}=notice,tokens=usage.input+usage.output+usage.cacheRead+usage.cacheWrite,cost=usage.cost.total>=.01?` (~$${usage.cost.total.toFixed(2)})`:"",label=notice.kind==="compaction"?t("Compaction"):t("Branch summary");host.chatContainer.addChild(new Spacer(1)),host.chatContainer.addChild(new Text(theme.fg("warning",`${label}: ${t("{tokens} tokens billed{cost}",{tokens:formatTokens(tokens),cost})}`),1,0))}function countDroppedThinkingBlocks(message){let count=0;for(let diagnostic5 of message.diagnostics??[]){if(diagnostic5.type!=="anthropic_input_transformations")continue;let transformations=diagnostic5.details?.transformations;Array.isArray(transformations)&&(count+=transformations.filter(transformation=>typeof transformation=="object"&&transformation!==null&&transformation.type==="thinking_dropped").length)}return count}function maybeShowThinkingDropNotice(host,message){if(!host.settingsManager.getShowCacheMissNotices())return;let droppedCount=countDroppedThinkingBlocks(message);if(droppedCount===0)return;let previousDroppedCount=0,entries=host.facade.getEntries();for(let i=entries.length-1;i>=0;i--){let entry=entries[i];if(entry.type==="message"&&entry.message.role==="assistant"){previousDroppedCount=countDroppedThinkingBlocks(entry.message);break}}droppedCount<=previousDroppedCount||(host.chatContainer.addChild(new Spacer(1)),host.chatContainer.addChild(new Text(theme.fg("warning",t("Anthropic dropped {count} thinking blocks (details in session)",{count:droppedCount})),1,0)))}function maybeShowCacheMissNotice(host,message){if(!host.settingsManager.getShowCacheMissNotices())return;let miss=detectCacheMiss(host.facade.getEntries(),message,host.facade.getModelPriceSource());miss&&host.addCacheMissNotice(miss)}function addCacheMissNotice(host,miss){if(miss.missedTokens<2e4&&miss.missedCost<.1)return;let cost=miss.missedCost>=.01?` (~$${miss.missedCost.toFixed(2)})`:"",reBilled=t("{tokens} tokens re-billed{cost}",{tokens:formatTokens(miss.missedTokens),cost}),label=t("Cache miss");miss.modelChanged?label=t("Cache miss after model switch"):miss.idleMs>=3e5&&(label=t("Cache miss after {minutes}m idle",{minutes:Math.round(miss.idleMs/6e4)}));let text=theme.fg("warning",`${label}: ${reBilled}`);host.chatContainer.addChild(new Spacer(1)),host.chatContainer.addChild(new Text(text,1,0))}function renderInitialMessages(host){let entries=host.facade.getContextEntries();host.renderSessionEntries(entries,{updateFooter:!0,populateHistory:!0});let compactionCount=host.facade.getEntries().filter(e=>e.type==="compaction").length;compactionCount>0&&host.showStatus(compactionCount===1?t("Session compacted {count} time",{count:compactionCount}):t("Session compacted {count} times",{count:compactionCount}))}function rebuildChatFromMessages(host){host.chatContainer.clear(),host.renderSessionEntries(host.facade.getContextEntries())}function getRegisteredToolDefinition(host,toolName){return host.facade.getToolDefinition(toolName)}function getMarkdownTransformers(host){return[host.mermaidMarkdownTransformer]}function addToolToRunGroup(host,component){host.activeToolRunGroup||(host.activeToolRunGroup=new ToolRunGroupComponent,host.activeToolRunGroup.setExpanded(host.toolOutputExpanded),host.chatContainer.addChild(host.activeToolRunGroup)),host.activeToolRunGroup.addTool(component)}function noteResultInActiveToolRunGroup(host,isError){host.activeToolRunGroup?.noteResult(isError)}function markActiveToolRunGroupComplete(host){host.activeToolRunGroup?.markRunComplete()}function handleCtrlC(host){let now=Date.now();now-host.lastSigintTime<500?host.shutdown():(host.clearEditor(),host.lastSigintTime=now)}function handleCtrlD(host){host.shutdown()}async function shutdown(host,options){if(host.isShuttingDown)return;host.isShuttingDown=!0,options?.fromSignal&&(await host.runtimeFacade.dispose(),host.themeController.disableAutoSync(),await host.ui.terminal.drainInput(1e3),host.stop(),process.exit(0)),host.themeController.disableAutoSync(),await host.ui.terminal.drainInput(1e3),host.stop(),await host.runtimeFacade.dispose();let resumeCommand=host.formatResumeCommand(host.runtimeFacade);resumeCommand&&process.stdout.write(`${source_default.dim(t("To resume this session:"))} ${resumeCommand}
|
|
735
735
|
`),process.exit(0)}function emergencyTerminalExit(host){host.isShuttingDown=!0,host.unregisterSignalHandlers(),killTrackedDetachedChildren(),process.exit(129)}function uncaughtCrash(host,error){host.isShuttingDown&&process.exit(1),host.isShuttingDown=!0;try{host.unregisterSignalHandlers()}catch{}try{killTrackedDetachedChildren()}catch{}try{host.ui.stop()}catch{}console.error(t("{app} exiting due to uncaughtException:",{app:APP_NAME})),console.error(error),process.exit(1)}async function checkShutdownRequested(host){host.shutdownRequested&&await host.shutdown()}function registerSignalHandlers(host){host.unregisterSignalHandlers();let signals=["SIGTERM"];process.platform!=="win32"&&signals.push("SIGHUP");for(let signal of signals){let handler=()=>{killTrackedDetachedChildren(),host.shutdown({fromSignal:!0})};process.prependListener(signal,handler),host.signalCleanupHandlers.push(()=>process.off(signal,handler))}let terminalErrorHandler=error=>{throw isDeadTerminalError(error)&&host.emergencyTerminalExit(),error};process.stdout.on("error",terminalErrorHandler),process.stderr.on("error",terminalErrorHandler),host.signalCleanupHandlers.push(()=>process.stdout.off("error",terminalErrorHandler)),host.signalCleanupHandlers.push(()=>process.stderr.off("error",terminalErrorHandler));let uncaughtExceptionHandler=error=>host.uncaughtCrash(error);process.prependListener("uncaughtException",uncaughtExceptionHandler),host.signalCleanupHandlers.push(()=>process.off("uncaughtException",uncaughtExceptionHandler))}function unregisterSignalHandlers(host){for(let cleanup of host.signalCleanupHandlers)cleanup();host.signalCleanupHandlers=[]}function handleCtrlZ(host){if(process.platform==="win32"){host.showStatus(t("Suspend to background is not supported on Windows"));return}let suspendKeepAlive=setInterval(()=>{},2**30),ignoreSigint=()=>{};process.on("SIGINT",ignoreSigint),process.once("SIGCONT",()=>{clearInterval(suspendKeepAlive),process.removeListener("SIGINT",ignoreSigint),host.ui.start(),host.ui.requestRender(!0)});try{host.ui.stop(),process.kill(0,"SIGTSTP")}catch(error){throw clearInterval(suspendKeepAlive),process.removeListener("SIGINT",ignoreSigint),error}}async function handleFollowUp(host,explicitText){let text=(explicitText??host.editor.getExpandedText?.()??host.editor.getText()).trim();if(text){if(host.facade.isCompacting()){host.queueCompactionMessage(text,"followUp");return}host.facade.isStreaming()?(explicitText===void 0&&(host.editor.addToHistory?.(text),host.editor.setText("")),await host.facade.prompt(text,{streamingBehavior:"followUp"}),host.updatePendingMessagesDisplay(),host.ui.requestRender()):host.editor.onSubmit&&(explicitText===void 0&&host.editor.setText(""),host.editor.onSubmit(text))}}function handleDequeue(host){let restored=host.restoreQueuedMessagesToEditor();restored===0?host.showStatus(t("No queued messages to restore")):restored===1?host.showStatus(t("Restored {count} queued message to editor",{count:restored})):host.showStatus(t("Restored {count} queued messages to editor",{count:restored}))}function handleQueueCommand(host,text){return text===void 0||text.trim()===""?(host.showStatus(t("Usage: /queue <text>")),Promise.resolve()):host.handleFollowUp(text)}function handleDequeueCommand(host){host.handleDequeue()}function handleQueueListCommand(host){let steering=host.facade.getSteeringMessages(),followUp=host.facade.getFollowUpMessages();if(steering.length===0&&followUp.length===0){host.showStatus(t("No queued messages to manage"));return}host.showQueueManagerSelector()}function getAllQueuedMessages(host){return{steering:[...host.facade.getSteeringMessages(),...host.compactionQueuedMessages.filter(msg=>msg.mode==="steer").map(msg=>msg.text)],followUp:[...host.facade.getFollowUpMessages(),...host.compactionQueuedMessages.filter(msg=>msg.mode==="followUp").map(msg=>msg.text)]}}function clearAllQueues(host){let{steering,followUp}=host.facade.clearQueue(),compactionSteering=host.compactionQueuedMessages.filter(msg=>msg.mode==="steer").map(msg=>msg.text),compactionFollowUp=host.compactionQueuedMessages.filter(msg=>msg.mode==="followUp").map(msg=>msg.text);return host.compactionQueuedMessages=[],{steering:[...steering,...compactionSteering],followUp:[...followUp,...compactionFollowUp]}}function updatePendingMessagesDisplay(host){host.pendingMessagesContainer.clear();let{steering:steeringMessages,followUp:followUpMessages}=host.getAllQueuedMessages();if(steeringMessages.length>0||followUpMessages.length>0){host.pendingMessagesContainer.addChild(new Spacer(1));for(let message of steeringMessages){let text=theme.fg("dim",t("Steering: {message}",{message}));host.pendingMessagesContainer.addChild(new TruncatedText(text,1,0))}for(let message of followUpMessages){let text=theme.fg("dim",t("Follow-up: {message}",{message}));host.pendingMessagesContainer.addChild(new TruncatedText(text,1,0))}let dequeueHint=host.getAppKeyDisplay("app.message.dequeue")||"/dequeue",hintText=theme.fg("dim",t("\u21B3 {key} to edit all queued messages",{key:dequeueHint}));host.pendingMessagesContainer.addChild(new TruncatedText(hintText,1,0))}}function queueCompactionMessage(host,text,mode){host.compactionQueuedMessages.push({text,mode}),host.editor.addToHistory?.(text),host.editor.setText(""),host.updatePendingMessagesDisplay(),host.showStatus(t("Queued message for after compaction"))}async function flushCompactionQueue(host,options){if(host.compactionQueuedMessages.length===0)return;let queuedMessages=[...host.compactionQueuedMessages];host.compactionQueuedMessages=[],host.updatePendingMessagesDisplay();let restoreQueue=error=>{host.facade.clearQueue(),host.compactionQueuedMessages=queuedMessages,host.updatePendingMessagesDisplay(),host.showError(queuedMessages.length>1?t("Failed to send queued messages: {error}",{error:error instanceof Error?error.message:String(error)}):t("Failed to send queued message: {error}",{error:error instanceof Error?error.message:String(error)}))};try{if(options?.willRetry){for(let message of queuedMessages)message.mode==="followUp"?await host.facade.followUp(message.text):await host.facade.steer(message.text);host.updatePendingMessagesDisplay();return}let[firstPrompt,...rest]=queuedMessages,promptPromise=host.facade.prompt(firstPrompt.text,{streamingBehavior:firstPrompt.mode}).catch(error=>{restoreQueue(error)});for(let message of rest)message.mode==="followUp"?await host.facade.followUp(message.text):await host.facade.steer(message.text);host.updatePendingMessagesDisplay()}catch(error){restoreQueue(error)}}var ENTRY_LINE_MAX_CHARS=160;function isRecord(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function messageText(message){let content=message.content;if(typeof content=="string")return content;if(Array.isArray(content))return content.filter(block=>isRecord(block)&&block.type==="text").map(block=>typeof block.text=="string"?block.text:"").join(" ")}function truncateLine2(text){return text.length>ENTRY_LINE_MAX_CHARS?`${text.slice(0,ENTRY_LINE_MAX_CHARS-1)}\u2026`:text}function formatAgentSessionEntries(entries){let lines=[];for(let entry of entries){if(isRecord(entry)&&entry.type==="message"&&isRecord(entry.message)){let role=typeof entry.message.role=="string"?entry.message.role:"message",text=messageText(entry.message);lines.push(truncateLine2(text===void 0||text.length===0?`[${role}]`:`[${role}] ${text}`));continue}let type=isRecord(entry)&&typeof entry.type=="string"?entry.type:"entry",json=JSON.stringify(entry);lines.push(truncateLine2(json===void 0?`[${type}]`:`[${type}] ${json}`))}return Object.freeze(lines)}var AgentsRowsView=class{view;constructor(view){this.view=view}invalidate(){}render(width){return this.view.renderRows(width)}},AgentsViewComponent=class extends Container{onClose;config;mode="list";rows=[];selectedIndex=0;offset=0;detail;titleText;modeHintText;helpText;constructor(config){super(),this.config=config,this.titleText=new Text(theme.fg("accent",theme.bold(` ${t("Subagent Sessions")}`)),1,0),this.modeHintText=new Text("",1,0),this.helpText=new Text("",1,0),this.updateModeTexts(),this.addChild(new DynamicBorder),this.addChild(this.titleText),this.addChild(this.modeHintText),this.addChild(new AgentsRowsView(this)),this.addChild(this.helpText),this.addChild(new DynamicBorder)}updateModeTexts(){let label=this.mode==="list"?t("this session's subagents (newest first)"):t("transcript (read-only)");this.modeHintText.setText(theme.fg("dim",` ${label}`)),this.helpText.setText(this.buildHelpLine())}buildHelpLine(){let parts=[rawKeyHint("\u2191\u2193",t("move"))];return this.mode==="list"?parts.push(rawKeyHint("tab/l",t("detail")),keyHint("tui.select.confirm",t("open"))):parts.push(rawKeyHint("tab/l",t("list"))),parts.push(keyHint("tui.select.cancel",this.mode==="list"?t("close"):t("back"))),` ${parts.join(" ")}`}formatSummaryRow(summary){let role=summary.agentRole??"-",id=summary.sessionId.slice(0,8),modified=new Date(summary.modifiedAt).toLocaleString();return` ${role} ${id} ${modified} ${summary.bytes}B`}buildDetailHeader(view){let identity=[t("session {sessionId}",{sessionId:view.sessionId})];view.agentRole!==void 0&&identity.push(t("role {role}",{role:view.agentRole}));let facts=[];return view.createdAt!==void 0&&facts.push(t("created {createdAt}",{createdAt:view.createdAt})),facts.push(`${view.bytes}B`,t("{count} entries",{count:view.entryCount})),view.truncated&&facts.push(theme.fg("warning",t("truncated"))),[` ${identity.join(" \xB7 ")}`,` ${facts.join(" \xB7 ")}`]}buildRows(){if(this.mode==="detail"){if(this.detail===void 0)return[` ${t("no session selected")}`];let view=this.detail.view;if(view===void 0){let sessionId=this.config.sessions[this.detail.listIndex]?.sessionId??"?";return[` ${t("session {sessionId}",{sessionId})} \u2014 ${theme.fg("error",t("transcript unavailable (missing or unreadable)"))}`]}return[...this.buildDetailHeader(view),...formatAgentSessionEntries(view.entries)]}return this.config.sessions.length===0?[` ${t("no subagent sessions in this session")}`]:this.config.sessions.map(summary=>this.formatSummaryRow(summary))}clampOffset(){let maxRows=Math.max(1,this.config.maxRows);this.selectedIndex<this.offset&&(this.offset=this.selectedIndex),this.selectedIndex>=this.offset+maxRows&&(this.offset=this.selectedIndex-maxRows+1),this.offset<0&&(this.offset=0)}syncRows(){this.rows=this.buildRows(),this.selectedIndex>=this.rows.length&&(this.selectedIndex=Math.max(0,this.rows.length-1)),this.clampOffset()}renderRows(width){this.syncRows();let maxRows=Math.max(1,this.config.maxRows),lines=[];for(let index=this.offset;index<Math.min(this.rows.length,this.offset+maxRows);index++){let row=this.rows[index];if(row===void 0)continue;let prefix=index===this.selectedIndex?theme.fg("accent","\u2192 "):" ";lines.push(truncateToWidth(`${prefix}${row}`,width))}let hiddenAbove=this.offset,hiddenBelow=this.rows.length-this.offset-maxRows,hidden=[];for(hiddenAbove>0&&hidden.push(`\u2191${hiddenAbove}`),hiddenBelow>0&&hidden.push(`\u2193${hiddenBelow}`);lines.length<maxRows;)lines.push(truncateToWidth(" ",width));return lines.push(truncateToWidth(hidden.length>0?theme.fg("dim",` ${hidden.join(" ")}`):" ",width)),lines}move(delta){this.rows.length!==0&&(this.selectedIndex=Math.min(this.rows.length-1,Math.max(0,this.selectedIndex+delta)),this.clampOffset())}enterDetail(){let summary=this.config.sessions[this.selectedIndex];summary!==void 0&&(this.detail={view:this.config.loadEntries(summary.sessionId),listIndex:this.selectedIndex},this.mode="detail",this.selectedIndex=0,this.offset=0,this.updateModeTexts(),this.config.requestRender?.())}exitDetail(){let restore=this.detail?.listIndex??0;this.detail=void 0,this.mode="list",this.selectedIndex=restore,this.clampOffset(),this.updateModeTexts(),this.config.requestRender?.()}handleInput(keyData){let kb=getKeybindings();kb.matches(keyData,"tui.select.cancel")?this.mode==="detail"?this.exitDetail():this.onClose?.():kb.matches(keyData,"tui.input.tab")||keyData==="l"?this.mode==="list"?this.enterDetail():this.exitDetail():kb.matches(keyData,"tui.select.confirm")?this.mode==="list"&&this.enterDetail():kb.matches(keyData,"tui.select.up")||keyData==="k"?this.move(-1):kb.matches(keyData,"tui.select.down")||keyData==="j"?this.move(1):kb.matches(keyData,"tui.select.pageUp")?this.move(-Math.max(1,this.config.maxRows)):kb.matches(keyData,"tui.select.pageDown")&&this.move(Math.max(1,this.config.maxRows))}};function flatten(snapshot2){return[...snapshot2.steering.map(text=>({queue:"steer",text})),...snapshot2.followUp.map(text=>({queue:"followUp",text}))]}var QueueManagerList=class{entries=[];steeringCount=0;selectedIndex=0;callbacks;constructor(snapshot2,callbacks){this.callbacks=callbacks,this.applySnapshot(snapshot2)}invalidate(){}render(width){let lines=[];if(this.entries.length===0)return lines;this.steeringCount>0&&lines.push(theme.fg("muted",` ${t("Steering")}`));for(let i=0;i<this.entries.length;i++){let entry=this.entries[i];entry.queue==="followUp"&&(i===0||this.entries[i-1]?.queue==="steer")&&(i>0&&lines.push(""),lines.push(theme.fg("muted",` ${t("Follow-up")}`)));let isSelected=i===this.selectedIndex,cursor=isSelected?theme.fg("accent","\u203A "):" ",normalized=entry.text.replace(/\n/g," ").trim(),truncated=truncateToWidth(normalized,width-2);lines.push(cursor+(isSelected?theme.bold(truncated):truncated))}return lines}handleInput(keyData){let kb=getKeybindings();if(kb.matches(keyData,"tui.select.up")){if(this.entries.length===0)return;this.selectedIndex=this.selectedIndex===0?this.entries.length-1:this.selectedIndex-1;return}if(kb.matches(keyData,"tui.select.down")){if(this.entries.length===0)return;this.selectedIndex=this.selectedIndex===this.entries.length-1?0:this.selectedIndex+1;return}let moveUp=kb.matches(keyData,"app.queue.moveUp"),moveDown=kb.matches(keyData,"app.queue.moveDown");if(moveUp||moveDown){if(this.entries.length===0)return;let{queue,index}=this.selectedLocation();if(index===void 0)return;let target=index+(moveUp?-1:1);if(target<0||target>=this.groupLength(queue))return;this.callbacks.onReorder(queue,index,target)&&(this.applySnapshot(this.callbacks.refresh()),this.selectedIndex=Math.min(Math.max(this.selectedIndex+(moveUp?-1:1),0),this.entries.length-1));return}if(kb.matches(keyData,"app.queue.remove")){if(this.entries.length===0)return;let{queue,index}=this.selectedLocation();if(index===void 0)return;this.callbacks.onRemove(queue,index)!==null&&(this.applySnapshot(this.callbacks.refresh()),this.selectedIndex=Math.min(this.selectedIndex,this.entries.length-1),this.entries.length===0&&this.callbacks.onClose());return}if(kb.matches(keyData,"tui.select.confirm")){if(this.entries.length===0)return;let{queue,index}=this.selectedLocation();if(index===void 0)return;this.callbacks.onRestore(queue,index)&&this.callbacks.onClose();return}if(kb.matches(keyData,"tui.select.cancel")){this.callbacks.onClose();return}}applySnapshot(snapshot2){this.entries=flatten(snapshot2),this.steeringCount=snapshot2.steering.length,this.selectedIndex=Math.min(this.selectedIndex,this.entries.length-1),this.selectedIndex<0&&(this.selectedIndex=0)}selectedLocation(){let entry=this.entries[this.selectedIndex];return entry?{queue:entry.queue,index:entry.queue==="steer"?this.selectedIndex:this.selectedIndex-this.steeringCount}:{queue:"steer",index:void 0}}groupLength(queue){return this.entries.filter(entry=>entry.queue===queue).length}},QueueManagerSelectorComponent=class extends Container{list;constructor(snapshot2,callbacks){super(),this.addChild(new Spacer(1)),this.addChild(new Text(theme.bold(t("Queued Messages")),1,0)),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.list=new QueueManagerList(snapshot2,callbacks),this.addChild(this.list),this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("muted",t("alt+up/alt+down move \xB7 delete remove \xB7 enter restore \xB7 esc close")),1,0)),this.addChild(new Spacer(1)),this.addChild(new DynamicBorder),snapshot2.steering.length===0&&snapshot2.followUp.length===0&&setTimeout(()=>callbacks.onClose(),100)}getMessageList(){return this.list}};function isEnabled(enabledIds,id){return enabledIds===null||enabledIds.includes(id)}function toggle(enabledIds,id){if(enabledIds===null)return[id];let index=enabledIds.indexOf(id);return index>=0?[...enabledIds.slice(0,index),...enabledIds.slice(index+1)]:[...enabledIds,id]}function enableAll(enabledIds,allIds,targetIds){if(enabledIds===null)return null;let targets=targetIds??allIds,result=[...enabledIds];for(let id of targets)result.includes(id)||result.push(id);return result.length===allIds.length&&result.every(id=>allIds.includes(id))?null:result}function clearAll(enabledIds,allIds,targetIds){if(enabledIds===null)return targetIds?allIds.filter(id=>!targetIds.includes(id)):[];let targets=new Set(targetIds??enabledIds);return enabledIds.filter(id=>!targets.has(id))}function move(enabledIds,id,delta){if(enabledIds===null)return null;let list=[...enabledIds],index=list.indexOf(id);if(index<0)return list;let newIndex=index+delta;if(newIndex<0||newIndex>=list.length)return list;let result=[...list];return[result[index],result[newIndex]]=[result[newIndex],result[index]],result}function getSortedIds(enabledIds,allIds){if(enabledIds===null)return allIds;let enabledSet=new Set(enabledIds);return[...enabledIds,...allIds.filter(id=>!enabledSet.has(id))]}var ScopedModelsSelectorComponent=class extends Container{modelsById=new Map;allIds=[];enabledIds=null;filteredItems=[];selectedIndex=0;searchInput;_focused=!1;get focused(){return this._focused}set focused(value){this._focused=value,this.searchInput.focused=value}listContainer;footerText;callbacks;maxVisible=8;isDirty=!1;refreshStatusText;constructor(config,callbacks){super(),this.callbacks=callbacks;for(let model of config.allModels){let fullId=`${model.provider}/${model.id}`;this.modelsById.set(fullId,model),this.allIds.push(fullId)}this.enabledIds=config.enabledModelIds===null?null:[...config.enabledModelIds],this.filteredItems=this.buildItems(),this.addChild(new DynamicBorder),this.addChild(new Spacer(1)),this.addChild(new Text(theme.fg("accent",theme.bold(t("Model Configuration"))),0,0)),this.addChild(new Text(theme.fg("muted",t("Session-only. {key} to save to settings.",{key:keyDisplayText("app.models.save")})),0,0)),this.addChild(new Spacer(1)),this.searchInput=new Input,this.addChild(this.searchInput),this.addChild(new Spacer(1)),this.listContainer=new Container,this.addChild(this.listContainer),this.addChild(new Spacer(1)),config.refreshStatus&&(this.refreshStatusText=new Text(theme.fg("muted",` ${config.refreshStatus}`),0,0),this.addChild(this.refreshStatusText)),this.footerText=new Text(this.getFooterText(),0,0),this.addChild(this.footerText),this.addChild(new DynamicBorder),this.updateList()}updateModels(models,enabledModelIds){let selectedId=this.filteredItems[this.selectedIndex]?.fullId;enabledModelIds!==void 0&&(this.enabledIds=enabledModelIds===null?null:[...enabledModelIds]),this.modelsById.clear(),this.allIds=[];for(let model of models){let fullId=`${model.provider}/${model.id}`;this.modelsById.set(fullId,model),this.allIds.push(fullId)}this.refresh();let refreshedIndex=selectedId?this.filteredItems.findIndex(item=>item.fullId===selectedId):-1;refreshedIndex>=0&&(this.selectedIndex=refreshedIndex,this.updateList())}setRefreshStatus(message,kind){this.refreshStatusText?.setText(theme.fg(kind,` ${message}`))}buildItems(){return getSortedIds(this.enabledIds,this.allIds).map(id=>({fullId:id,model:this.modelsById.get(id),enabled:isEnabled(this.enabledIds,id)}))}getFooterText(){let enabledCount=this.enabledIds?.filter(id=>this.modelsById.has(id)).length??this.allIds.length,unavailableCount=this.enabledIds?.filter(id=>!this.modelsById.has(id)).length??0,countText=this.enabledIds===null?t("all enabled"):t("{enabled}/{total} enabled",{enabled:enabledCount,total:this.allIds.length})+(unavailableCount?` \xB7 ${t("{count} unavailable",{count:unavailableCount})}`:""),parts=[`${keyDisplayText("tui.select.confirm")} ${t("toggle")}`,`${keyDisplayText("app.models.enableAll")} ${t("all")}`,`${keyDisplayText("app.models.clearAll")} ${t("clear")}`,`${keyDisplayText("app.models.toggleProvider")} ${t("provider")}`,`${keyDisplayText("app.models.reorderUp")}/${keyDisplayText("app.models.reorderDown")} ${t("reorder")}`,`${keyDisplayText("app.models.save")} ${t("save")}`,countText];return this.isDirty?theme.fg("dim",` ${parts.join(" \xB7 ")} `)+theme.fg("warning",t("(unsaved)")):theme.fg("dim",` ${parts.join(" \xB7 ")}`)}refresh(){let query=this.searchInput.getValue(),items=this.buildItems();this.filteredItems=query?fuzzyFilter(items,query,item=>item.model?getModelSearchText({id:item.model.id,provider:item.model.provider,name:item.model.name}):item.fullId):items,this.selectedIndex=Math.min(this.selectedIndex,Math.max(0,this.filteredItems.length-1)),this.updateList(),this.footerText.setText(this.getFooterText())}notifyChange(){this.callbacks.onChange(this.enabledIds===null?null:[...this.enabledIds])}updateList(){if(this.listContainer.clear(),this.filteredItems.length===0){this.listContainer.addChild(new Text(theme.fg("muted",` ${t("No matching models")}`),0,0));return}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),allEnabled=this.enabledIds===null;for(let i=startIndex;i<endIndex;i++){let item=this.filteredItems[i],isSelected=i===this.selectedIndex,prefix=isSelected?theme.fg("accent","\u2192 "):" ",id=item.model?.id??item.fullId,modelText=isSelected?theme.fg("accent",id):id,providerBadge=theme.fg("muted",item.model?` [${item.model.provider}]`:` ${t("[unavailable]")}`),status=item.model?allEnabled?"":item.enabled?theme.fg("success"," \u2713"):theme.fg("dim"," \u2717"):theme.fg("dim"," \u2717");this.listContainer.addChild(new Text(`${prefix}${modelText}${providerBadge}${status}`,0,0))}if((startIndex>0||endIndex<this.filteredItems.length)&&this.listContainer.addChild(new Text(theme.fg("muted",` (${this.selectedIndex+1}/${this.filteredItems.length})`),0,0)),this.filteredItems.length>0){let selected=this.filteredItems[this.selectedIndex];this.listContainer.addChild(new Spacer(1)),this.listContainer.addChild(new Text(theme.fg("muted",` ${selected.model?t("Model Name: {name}",{name:selected.model.name}):t("Model unavailable")}`),0,0))}}handleInput(data){let kb=getKeybindings();if(kb.matches(data,"tui.select.up")){if(this.filteredItems.length===0)return;this.selectedIndex=this.selectedIndex===0?this.filteredItems.length-1:this.selectedIndex-1,this.updateList();return}if(kb.matches(data,"tui.select.down")){if(this.filteredItems.length===0)return;this.selectedIndex=this.selectedIndex===this.filteredItems.length-1?0:this.selectedIndex+1,this.updateList();return}let reorderUp=kb.matches(data,"app.models.reorderUp"),reorderDown=kb.matches(data,"app.models.reorderDown");if(reorderUp||reorderDown){if(this.enabledIds===null)return;let item=this.filteredItems[this.selectedIndex];if(item&&isEnabled(this.enabledIds,item.fullId)){let delta=reorderUp?-1:1,newIndex=this.enabledIds.indexOf(item.fullId)+delta;newIndex>=0&&newIndex<this.enabledIds.length&&(this.enabledIds=move(this.enabledIds,item.fullId,delta),this.isDirty=!0,this.selectedIndex+=delta,this.refresh(),this.notifyChange())}return}if(kb.matches(data,"tui.select.confirm")){let item=this.filteredItems[this.selectedIndex];item&&(this.enabledIds=toggle(this.enabledIds,item.fullId),this.isDirty=!0,this.refresh(),this.notifyChange());return}if(kb.matches(data,"app.models.enableAll")){let targetIds=this.searchInput.getValue()?this.filteredItems.map(i=>i.fullId):void 0;this.enabledIds=enableAll(this.enabledIds,this.allIds,targetIds),this.isDirty=!0,this.refresh(),this.notifyChange();return}if(kb.matches(data,"app.models.clearAll")){let targetIds=this.searchInput.getValue()?this.filteredItems.map(i=>i.fullId):void 0;this.enabledIds=clearAll(this.enabledIds,this.allIds,targetIds),this.isDirty=!0,this.refresh(),this.notifyChange();return}if(kb.matches(data,"app.models.toggleProvider")){let item=this.filteredItems[this.selectedIndex];if(item?.model){let provider=item.model.provider,providerIds=this.allIds.filter(id=>this.modelsById.get(id).provider===provider),allEnabled=providerIds.every(id=>isEnabled(this.enabledIds,id));this.enabledIds=allEnabled?clearAll(this.enabledIds,this.allIds,providerIds):enableAll(this.enabledIds,this.allIds,providerIds),this.isDirty=!0,this.refresh(),this.notifyChange()}return}if(kb.matches(data,"app.models.save")){this.callbacks.onPersist(this.enabledIds===null?null:[...this.enabledIds]),this.isDirty=!1,this.footerText.setText(this.getFooterText());return}if(kb.matches(data,"app.models.cancel")){this.searchInput.getValue()?(this.searchInput.setValue(""),this.refresh()):this.callbacks.onCancel();return}if(kb.matches(data,"tui.select.cancel")){this.callbacks.onCancel();return}this.searchInput.handleInput(data),this.refresh()}getSearchInput(){return this.searchInput}};var STAGE_STATUSES=["pending","active","awaiting_review","completed","failed","skipped"];function isRecord2(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function stringOrUndefined(value){return typeof value=="string"?value:void 0}function parseStageSpec(value){if(!isRecord2(value))return;let id=stringOrUndefined(value.id);if(id===void 0)return;let dependsOn=Array.isArray(value.dependsOn)?value.dependsOn.filter(isString):[],acceptance=isRecord2(value.objective)&&Array.isArray(value.objective.acceptance)?value.objective.acceptance:[],scope=Array.isArray(value.scope)?value.scope.filter(isString):void 0;return{id,title:stringOrUndefined(value.title)??id,dependsOn,planId:stringOrUndefined(value.planId),kind:value.kind==="read"?"read":"write",scope:scope!==void 0&&scope.length>0?scope:void 0,acceptanceIds:acceptance.map(item=>isRecord2(item)?stringOrUndefined(item.id):void 0).filter(item=>item!==void 0)}}function isString(value){return typeof value=="string"}function parseStageRuntime(value){if(!isRecord2(value))return;let stageId=stringOrUndefined(value.stageId),status=stringOrUndefined(value.status);if(stageId===void 0||status===void 0||!STAGE_STATUSES.includes(status))return;let evidence=Array.isArray(value.evidence)?value.evidence:[],covered=new Set,evidenceCount=0;for(let item of evidence){if(!isRecord2(item))continue;evidenceCount++;let acceptanceId=stringOrUndefined(item.acceptanceId);acceptanceId!==void 0&&covered.add(acceptanceId)}return{stageId,status,attempts:typeof value.attempts=="number"?value.attempts:0,evidenceCount,coveredAcceptanceIds:covered}}function parseWorkflowRecord(value){if(!isRecord2(value))return;let id=stringOrUndefined(value.id),title=stringOrUndefined(value.title),status=stringOrUndefined(value.status);if(id===void 0||title===void 0||status===void 0)return;let stages=[];for(let item of Array.isArray(value.stages)?value.stages:[]){let spec=parseStageSpec(item);spec!==void 0&&stages.push(spec)}let runtime=new Map;for(let item of Array.isArray(value.runtime)?value.runtime:[]){let parsed=parseStageRuntime(item);parsed!==void 0&&runtime.set(parsed.stageId,parsed)}let diagnostics=Array.isArray(value.diagnostics)?value.diagnostics.filter(isString):[];return{id,title,status,revision:typeof value.revision=="number"?value.revision:0,goalId:stringOrUndefined(value.goalId),maxActiveStages:typeof value.maxActiveStages=="number"?value.maxActiveStages:4,maxRetreats:typeof value.maxRetreats=="number"?value.maxRetreats:3,retreatCount:typeof value.retreatCount=="number"?value.retreatCount:0,diagnostics,stages,runtime}}function parsePlanStatuses(data){let statuses=new Map;if(!isRecord2(data)||!Array.isArray(data.plans))return statuses;for(let item of data.plans){if(!isRecord2(item))continue;let id=stringOrUndefined(item.id),status=stringOrUndefined(item.status);id!==void 0&&status!==void 0&&statuses.set(id,status)}return statuses}function parseTransition2(value){if(!isRecord2(value))return;let workflowId=stringOrUndefined(value.workflowId),from=stringOrUndefined(value.from),to=stringOrUndefined(value.to),reason=isRecord2(value.reason)?value.reason:void 0,code=reason!==void 0?stringOrUndefined(reason.code):void 0;if(!(workflowId===void 0||from===void 0||to===void 0||code===void 0||typeof value.revision!="number"))return{revision:value.revision,workflowId,stageId:stringOrUndefined(value.stageId),from,to,trigger:stringOrUndefined(value.trigger)??"tool",code,message:reason!==void 0?stringOrUndefined(reason.message)??"":"",detail:reason!==void 0?stringOrUndefined(reason.detail):void 0}}function scopesIntersect(a,b){return a===void 0||a.length===0||b===void 0||b.length===0?!0:a.some(tag=>b.includes(tag))}function findScopeConflict(workflow,spec){if(spec.kind!=="write")return null;for(let other of workflow.stages)if(!(other.id===spec.id||other.kind!=="write")&&workflow.runtime.get(other.id)?.status==="active"&&scopesIntersect(spec.scope,other.scope))return other.id;return null}function uncoveredAcceptanceIds(spec,runtime){return runtime===void 0?[...spec.acceptanceIds]:spec.acceptanceIds.filter(id=>!runtime.coveredAcceptanceIds.has(id))}function computeWaitingOn(workflow,spec,runtime,planStatuses){let status=runtime?.status??"pending";if(status==="awaiting_review")return"review";if(status==="pending"){if(workflow.status==="draft")return"not-yet-active";if((runtime?.attempts??0)>0)return spec.acceptanceIds.length===0?"retry-wait":`acceptance-missing:[${uncoveredAcceptanceIds(spec,runtime).join(", ")}]`;let incomplete=spec.dependsOn.filter(dep=>{let dependency=workflow.runtime.get(dep)?.status;return dependency!=="completed"&&dependency!=="skipped"});if(incomplete.length>0)return`deps-incomplete:[${incomplete.join(", ")}]`;if(spec.planId!==void 0&&!planStatuses.has(spec.planId))return"plan-dangling";if([...workflow.runtime.values()].filter(item=>item.status==="active").length>=workflow.maxActiveStages)return"active-limit";let conflict=findScopeConflict(workflow,spec);return conflict!==null?`write-scope-conflict:[${conflict}]`:"not-yet-active"}if(status==="active"){if(spec.planId===void 0)return null;let planStatus=planStatuses.get(spec.planId);return planStatus===void 0?"plan-dangling":planStatus!=="completed"?"plan-incomplete":null}return null}function buildStageRows(workflow,planStatuses){let rows=[],visited=new Set,walk=(spec,depth)=>{if(visited.has(spec.id)){rows.push({workflowId:workflow.id,stageId:spec.id,title:spec.title,depth,status:workflow.runtime.get(spec.id)?.status??"pending",waitingOn:null,attempts:0,evidenceCount:0,scopeConflict:null,backReference:!0});return}visited.add(spec.id);let runtime=workflow.runtime.get(spec.id);rows.push({workflowId:workflow.id,stageId:spec.id,title:spec.title,depth,status:runtime?.status??"pending",waitingOn:computeWaitingOn(workflow,spec,runtime,planStatuses),attempts:runtime?.attempts??0,evidenceCount:runtime?.evidenceCount??0,scopeConflict:findScopeConflict(workflow,spec),backReference:!1});for(let child of workflow.stages.filter(item=>item.dependsOn.includes(spec.id)))walk(child,depth+1)};for(let root of workflow.stages.filter(item=>item.dependsOn.length===0))walk(root,0);for(let spec of workflow.stages)visited.has(spec.id)||walk(spec,0);return rows}function buildWorkflowViewModel(entries,transitionLimit=30){let stateData,hasStateEntry=!1,planData,transitions=[];for(let entry of entries)if(entry.type==="custom"){if(entry.customType==="workflow.state")hasStateEntry=!0,stateData=entry.data;else if(entry.customType==="plan.state")planData=entry.data;else if(entry.customType==="workflow.transition"){let parsed=parseTransition2(entry.data);parsed!==void 0&&transitions.push(parsed)}}let planStatuses=parsePlanStatuses(planData),blocks;hasStateEntry&&(blocks=(isRecord2(stateData)&&Array.isArray(stateData.workflows)?stateData.workflows:[]).map(item=>{let parsed=parseWorkflowRecord(item);if(parsed!==void 0)return{workflowId:parsed.id,title:parsed.title,status:parsed.status,revision:parsed.revision,goalId:parsed.goalId,activeCount:[...parsed.runtime.values()].filter(item2=>item2.status==="active").length,maxActiveStages:parsed.maxActiveStages,retreatCount:parsed.retreatCount,maxRetreats:parsed.maxRetreats,diagnostics:[...parsed.diagnostics],stages:buildStageRows(parsed,planStatuses)}}).filter(block=>block!==void 0));let activeWorkflowId=blocks?.filter(block=>block.status==="draft"||block.status==="running").at(-1)?.workflowId??blocks?.at(-1)?.workflowId;return{panorama:blocks,transitions:transitions.slice(-transitionLimit).reverse(),activeWorkflowId}}function buildWorkflowActionText(action,workflowId,stageId){return action==="cancel"||stageId===void 0?`cancel workflow ${workflowId}`:`${action} stage ${stageId}`}function stageStatusColor(status){switch(status){case"active":return text=>theme.fg("accent",text);case"awaiting_review":return text=>theme.fg("warning",text);case"completed":return text=>theme.fg("success",text);case"failed":return text=>theme.fg("error",text);case"skipped":return text=>theme.fg("dim",text);case"pending":return text=>theme.fg("muted",text)}}function workflowStatusColor(status){return status==="running"?text=>theme.fg("accent",text):status==="completed"?text=>theme.fg("success",text):status==="failed"?text=>theme.fg("error",text):text=>theme.fg("dim",text)}function transitionCodeColor(code){return code.includes("failed")||code.includes("retreat")||code.includes("error")||code.includes("limit")?text=>theme.fg("error",text):code.includes("held")||code.includes("retry")||code.includes("amended")?text=>theme.fg("warning",text):text=>theme.fg("muted",text)}var WorkflowRowsView=class{view;constructor(view){this.view=view}invalidate(){}render(width){return this.view.renderRows(width)}},WorkflowViewComponent=class extends Container{onClose;onForwardAction;config;mode="panorama";rows=[];selectedIndex=0;offset=0;titleText;modeHintText;helpText;flashText;cache;flashTimeout=null;constructor(config){super(),this.config=config,this.titleText=new Text(theme.fg("accent",theme.bold(` ${t("Workflow Overview")}`)),1,0),this.modeHintText=new Text("",1,0),this.helpText=new Text("",1,0),this.flashText=new Text("",1,0),this.updateModeTexts(),this.addChild(new DynamicBorder),this.addChild(this.titleText),this.addChild(this.modeHintText),this.addChild(new WorkflowRowsView(this)),this.addChild(this.flashText),this.addChild(this.helpText),this.addChild(new DynamicBorder)}dispose(){this.flashTimeout!==null&&(clearTimeout(this.flashTimeout),this.flashTimeout=null)}updateModeTexts(){let label=this.mode==="panorama"?t("panorama"):t("transition log (newest first)");this.modeHintText.setText(theme.fg("dim",` ${label}`)),this.helpText.setText(this.buildHelpLine())}buildHelpLine(){let parts=[rawKeyHint("\u2191\u2193",t("move"))];return this.mode==="panorama"?parts.push(rawKeyHint("tab/l",t("log")),rawKeyHint("a",t("approve")),rawKeyHint("r",t("reject")),rawKeyHint("s",t("skip")),rawKeyHint("c",t("cancel"))):parts.push(rawKeyHint("tab/l",t("panorama"))),parts.push(keyHint("tui.select.cancel",t("close"))),` ${parts.join(" ")}`}getModel(){let entries=this.config.getEntries();if(this.cache&&this.cache.entries===entries&&this.cache.length===entries.length)return this.cache.model;let model=buildWorkflowViewModel(entries);return this.cache={entries,length:entries.length,model},model}buildRows(model){let rows=[];if(this.mode==="log"){if(model.transitions.length===0)return rows.push({text:` ${t("no workflow transitions recorded")}`,stage:void 0}),rows;for(let transition of model.transitions){let stage=transition.stageId!==void 0?`/${transition.stageId}`:"",detail=transition.detail!==void 0?` \u2014 ${transition.detail}`:"",code=transitionCodeColor(transition.code)(transition.code);rows.push({text:` #${transition.revision} ${transition.workflowId}${stage} ${transition.from} -> ${transition.to} [${transition.trigger}] ${code}: ${transition.message}${detail}`,stage:void 0})}return rows}let blocks=model.panorama;if(blocks===void 0)return rows.push({text:` ${t("no workflow.state entry in this session")}`,stage:void 0}),rows;if(blocks.length===0)return rows.push({text:` ${t("no workflows in this session; create one with workflow_set")}`,stage:void 0}),rows;for(let block of blocks){let status=workflowStatusColor(block.status)(block.status);rows.push({text:` ${t('workflow "{title}" ({workflowId}) \u2014 {status} \xB7 revision {revision} \xB7 active {activeCount}/{maxActiveStages} \xB7 retreats {retreatCount}/{maxRetreats}',{title:block.title,workflowId:block.workflowId,status,revision:block.revision,activeCount:block.activeCount,maxActiveStages:block.maxActiveStages,retreatCount:block.retreatCount,maxRetreats:block.maxRetreats})}`,stage:void 0}),block.goalId!==void 0&&rows.push({text:` ${t("goal: {goalId}",{goalId:block.goalId})}`,stage:void 0});for(let stage of block.stages)rows.push({text:this.formatStageRow(stage),stage:{workflowId:block.workflowId,stageId:stage.stageId}});if(block.diagnostics.length>0){rows.push({text:` ${t("diagnostics:")}`,stage:void 0});for(let diagnostic5 of block.diagnostics)rows.push({text:theme.fg("warning",` - ${diagnostic5}`),stage:void 0})}rows.push({text:"",stage:void 0})}return rows}formatStageRow(stage){let pad=" ".repeat(stage.depth+1);if(stage.backReference)return`${pad} -> ${stage.stageId} ${t("(shown above)")}`;let bits=[`- ${stage.stageId} [${stageStatusColor(stage.status)(stage.status)}] ${stage.title}`];return stage.waitingOn!==null&&bits.push(theme.fg("dim",`\u2014 ${t("waiting: {condition}",{condition:stage.waitingOn})}`)),stage.attempts>0&&bits.push(theme.fg("dim",t("\xB7 attempts {count}",{count:stage.attempts}))),stage.evidenceCount>0&&bits.push(theme.fg("dim",t("\xB7 evidence {count}",{count:stage.evidenceCount}))),stage.scopeConflict!==null&&bits.push(theme.fg("warning",`\u26A0 ${t("scope:{conflict}",{conflict:stage.scopeConflict})}`)),`${pad}${bits.join(" ")}`}syncRows(){let model=this.getModel(),previous=this.rows[this.selectedIndex]?.stage;if(this.rows=this.buildRows(model),previous!==void 0){let restored=this.rows.findIndex(row=>row.stage?.stageId===previous.stageId);restored!==-1&&(this.selectedIndex=restored)}this.selectedIndex>=this.rows.length&&(this.selectedIndex=Math.max(0,this.rows.length-1)),this.clampOffset()}clampOffset(){let maxRows=Math.max(1,this.config.maxRows);this.selectedIndex<this.offset&&(this.offset=this.selectedIndex),this.selectedIndex>=this.offset+maxRows&&(this.offset=this.selectedIndex-maxRows+1),this.offset<0&&(this.offset=0)}renderRows(width){this.syncRows();let maxRows=Math.max(1,this.config.maxRows),lines=[];for(let index=this.offset;index<Math.min(this.rows.length,this.offset+maxRows);index++){let row=this.rows[index];if(row===void 0)continue;let prefix=index===this.selectedIndex?theme.fg("accent","\u2192 "):" ";lines.push(truncateToWidth(`${prefix}${row.text}`,width))}let hiddenAbove=this.offset,hiddenBelow=this.rows.length-this.offset-maxRows,hidden=[];for(hiddenAbove>0&&hidden.push(`\u2191${hiddenAbove}`),hiddenBelow>0&&hidden.push(`\u2193${hiddenBelow}`);lines.length<maxRows;)lines.push(truncateToWidth(" ",width));return lines.push(truncateToWidth(hidden.length>0?theme.fg("dim",` ${hidden.join(" ")}`):" ",width)),lines}move(delta){this.rows.length!==0&&(this.selectedIndex=Math.min(this.rows.length-1,Math.max(0,this.selectedIndex+delta)),this.clampOffset())}flash(message){this.flashText.setText(theme.fg("warning",` ${message}`)),this.flashTimeout!==null&&clearTimeout(this.flashTimeout),this.flashTimeout=setTimeout(()=>{this.flashText.setText(""),this.flashTimeout=null,this.config.requestRender?.()},2500),this.config.requestRender?.()}toggleMode(){this.mode=this.mode==="panorama"?"log":"panorama",this.selectedIndex=0,this.offset=0,this.updateModeTexts(),this.config.requestRender?.()}forward(action){let selected=this.rows[this.selectedIndex];if(selected?.stage===void 0){if(action==="cancel"){let workflowId=this.getModel().activeWorkflowId;if(workflowId===void 0){this.flash(t("No workflow to cancel"));return}this.onForwardAction?.(buildWorkflowActionText(action,workflowId,void 0));return}this.flash(t("Select a stage row first"));return}this.onForwardAction?.(buildWorkflowActionText(action,selected.stage.workflowId,selected.stage.stageId))}handleInput(keyData){let kb=getKeybindings();kb.matches(keyData,"tui.select.cancel")?this.onClose?.():kb.matches(keyData,"tui.input.tab")||keyData==="l"?this.toggleMode():kb.matches(keyData,"tui.select.up")||keyData==="k"?this.move(-1):kb.matches(keyData,"tui.select.down")||keyData==="j"?this.move(1):kb.matches(keyData,"tui.select.pageUp")?this.move(-Math.max(1,this.config.maxRows)):kb.matches(keyData,"tui.select.pageDown")?this.move(Math.max(1,this.config.maxRows)):keyData==="a"?this.forward("approve"):keyData==="r"?this.forward("reject"):keyData==="s"?this.forward("skip"):keyData==="c"&&this.forward("cancel")}};function handleSuiteCommand(host,suiteId){let availableSuites=listSuiteIds(getAgentDir());if(!suiteId){showSuiteSelector(host,availableSuites);return}if(!availableSuites.includes(suiteId)){host.showError(t('Unknown suite "{suiteId}". Available suites: {suites}.',{suiteId,suites:availableSuites.join(", ")}));return}host.settingsManager.setProjectSuite(suiteId),host.showStatus(t("Suite set to {suiteId} \u2014 applies to the next new session (/new); an explicit --suite or AGENT_FORGE_SUITE startup keeps overriding it",{suiteId}))}function showSuiteSelector(host,availableSuites){openSuiteListSelector(host,{availableSuites,onSelect:suiteId=>handleSuiteCommand(host,suiteId),onCancel:()=>host.ui.requestRender()})}function openSuiteListSelector(host,callbacks){host.showSelector(done=>{let currentSuiteId=host.getCurrentSessionSuiteId(),container=new Container;container.addChild(new Spacer(1)),container.addChild(new Text(theme.bold(t("Select Suite")),1,0)),container.addChild(new Text(theme.fg("muted",callbacks.note??t("The next new session (/new) uses the selected suite; this session keeps its current suite")),1,0)),container.addChild(new Spacer(1)),container.addChild(new DynamicBorder);let list=new SelectList(callbacks.availableSuites.map(id=>({value:id,label:id,...id===currentSuiteId?{description:t("current session")}:{}})),10,getSelectListTheme());if(currentSuiteId!==void 0){let currentIndex=callbacks.availableSuites.indexOf(currentSuiteId);currentIndex>=0&&list.setSelectedIndex(currentIndex)}return list.onSelect=item=>{done(),callbacks.onSelect(item.value)},list.onCancel=()=>{done(),callbacks.onCancel()},container.addChild(list),container.addChild(new DynamicBorder),{component:container,focus:list}})}function handleThinkingCommand(host,searchTerm){let availableLevels=host.getAvailableThinkingLevels();if(!searchTerm){showThinkingSelector(host);return}let normalized=searchTerm.trim().toLowerCase(),level=availableLevels.find(candidate=>candidate.toLowerCase()===normalized);if(!level){host.showError(t('Unknown thinking level "{level}". Available levels: {levels}.',{level:searchTerm,levels:availableLevels.join(", ")}));return}selectThinkingLevel(host,level,!1)}function selectThinkingLevel(host,level,persist){try{host.facade.setThinkingLevel(level,{persist}),host.footer.invalidate(),host.updateEditorBorderColor(),host.showStatus(persist?t("Default thinking level: {level}",{level}):t("Thinking level: {level}",{level}))}catch(error){host.showError(error instanceof Error?error.message:String(error))}}function showThinkingSelector(host){host.showSelector(done=>{let selectLevel=(level,persist)=>{selectThinkingLevel(host,level,persist),done()},selector=new ThinkingSelectorComponent(host.facade.getState().thinkingLevel??DEFAULT_THINKING_LEVEL,host.getAvailableThinkingLevels(),level=>selectLevel(level,!1),()=>{done(),host.ui.requestRender()},level=>selectLevel(level,!0),host.settingsManager.getDefaultThinkingLevel()??DEFAULT_THINKING_LEVEL);return{component:selector,focus:selector}})}async function handleModelCommand(host,searchTerm){if(!searchTerm){showModelSelector(host);return}let model=await findExactModelMatch(host,searchTerm);if(model){try{await host.facade.setModel(model,{persist:!1}),host.footer.invalidate(),host.updateEditorBorderColor(),host.showStatus(t("Model: {id}",{id:model.id})),host.maybeWarnAboutAnthropicSubscriptionAuth(model),host.checkDaxnutsEasterEgg(model)}catch(error){host.showError(error instanceof Error?error.message:String(error))}return}showModelSelector(host,searchTerm)}async function findExactModelMatch(host,searchTerm){let cachedModels=host.facade.getScopedModels().length>0?host.facade.getScopedModels().map(scoped=>scoped.model):[...host.getAvailableModels()],cachedMatch=findExactModelReferenceMatch(searchTerm,cachedModels);if(cachedMatch||host.facade.getScopedModels().length>0)return cachedMatch;host.showStatus(t("Refreshing model catalogs\u2026"));let controller=new AbortController,timedOut=!1,timeout=setTimeout(()=>{timedOut=!0,controller.abort()},15e3);try{let result=await refreshModelCatalogs(host.getModelCatalog(),controller.signal);result.aborted&&timedOut?host.showWarning(t("Model refresh timed out; searching cached models.")):result.errors.size>0&&host.showWarning(t("Could not refresh {providers}; searching cached models.",{providers:[...result.errors.keys()].join(", ")}))}catch(error){host.showWarning(timedOut?t("Model refresh timed out; searching cached models."):t("Could not refresh model catalogs: {message}",{message:error instanceof Error?error.message:String(error)}))}finally{clearTimeout(timeout)}return findExactModelReferenceMatch(searchTerm,[...host.getAvailableModels()])}function showModelSelector(host,initialSearchInput){host.showSelector(done=>{let selectModel=async(model,persist)=>{try{await host.facade.setModel(model,{persist}),host.updateAvailableProviderCount(),host.footer.invalidate(),host.updateEditorBorderColor(),done(),host.showStatus(persist?t("Default model: {provider}/{id}",{provider:model.provider,id:model.id}):t("Model: {id}",{id:model.id})),host.maybeWarnAboutAnthropicSubscriptionAuth(model),host.checkDaxnutsEasterEgg(model)}catch(error){done(),host.showError(error instanceof Error?error.message:String(error))}},defaultProvider=host.settingsManager.getDefaultProvider(),defaultModel=host.settingsManager.getDefaultModel(),selector=new ModelSelectorComponent(host.ui,host.facade.getModel(),{getAvailableSnapshot:()=>host.getAvailableModels(),getError:()=>host.facade.getModelsError(),refresh:options=>host.getModelCatalog().refresh(options)},host.facade.getScopedModels(),model=>selectModel(model,!1),()=>{done(),host.ui.requestRender()},initialSearchInput,model=>selectModel(model,!0),defaultProvider&&defaultModel?{provider:defaultProvider,id:defaultModel}:void 0);return{component:selector,focus:selector,dispose:()=>selector.dispose()}})}function showModelsSelector(host){let availableModels=[...host.getAvailableModels()],availableModelIds=new Set(availableModels.map(model=>`${model.provider}/${model.id}`)),configuredPatterns=host.settingsManager.getEnabledModels(),sessionScopedModels=host.facade.getScopedModels(),configuredEnabledIds=models=>{if(!configuredPatterns?.length)return null;let resolved=resolveModelScopeFromModels(configuredPatterns,models),ids=resolved.scopedModels.map(scoped=>`${scoped.model.provider}/${scoped.model.id}`);for(let diagnostic5 of resolved.diagnostics)diagnostic5.code==="no-match"&&!ids.includes(diagnostic5.pattern)&&ids.push(diagnostic5.pattern);return ids},currentEnabledIds=sessionScopedModels.length>0?sessionScopedModels.map(scoped=>`${scoped.model.provider}/${scoped.model.id}`):configuredEnabledIds(availableModels),selectionChanged=!1,updateSessionModels=enabledIds=>{currentEnabledIds=enabledIds===null?null:[...enabledIds];let hasEnabledAvailableModel=enabledIds?.some(id=>availableModelIds.has(id))??!1,allAvailableModelsEnabled=enabledIds!==null&&[...availableModelIds].every(id=>enabledIds.includes(id));if(enabledIds&&hasEnabledAvailableModel&&!allAvailableModelsEnabled){let newScopedModels=resolveModelScopeFromModels(enabledIds,availableModels).scopedModels;host.facade.setScopedModels(newScopedModels.map(scoped=>({model:scoped.model,thinkingLevel:scoped.thinkingLevel})))}else host.facade.setScopedModels([]);host.updateAvailableProviderCount(),host.ui.requestRender()};host.showSelector(done=>{let disposed=!1,timedOut=!1,controller=new AbortController,timeout=setTimeout(()=>{timedOut=!0,controller.abort()},15e3),selector=new ScopedModelsSelectorComponent({allModels:availableModels,enabledModelIds:currentEnabledIds,refreshStatus:t("Refreshing model catalogs\u2026")},{onChange:enabledIds=>{selectionChanged=!0,updateSessionModels(enabledIds)},onPersist:enabledIds=>{let allEnabled=enabledIds!==null&&enabledIds.length===availableModels.length&&enabledIds.every(id=>availableModelIds.has(id)),newPatterns=enabledIds===null||allEnabled?void 0:enabledIds;host.settingsManager.setEnabledModels(newPatterns?[...newPatterns]:void 0),host.showStatus(t("Model selection saved to settings"))},onCancel:()=>{done(),host.ui.requestRender()}});return refreshModelCatalogs(host.getModelCatalog(),controller.signal).then(result=>{disposed||(availableModels=[...host.getAvailableModels()],availableModelIds=new Set(availableModels.map(model=>`${model.provider}/${model.id}`)),!selectionChanged&&sessionScopedModels.length===0?(currentEnabledIds=configuredEnabledIds(availableModels),selector.updateModels(availableModels,currentEnabledIds)):selector.updateModels(availableModels),currentEnabledIds!==null&&updateSessionModels(currentEnabledIds),result.aborted&&timedOut?selector.setRefreshStatus(t("Model refresh timed out; showing cached models."),"warning"):result.errors.size>0?selector.setRefreshStatus(t("Could not refresh {providers}; showing cached models.",{providers:[...result.errors.keys()].join(", ")}),"warning"):selector.setRefreshStatus(t("Model catalogs refreshed."),"success"),host.ui.requestRender())}).catch(error=>{disposed||(selector.setRefreshStatus(timedOut?t("Model refresh timed out; showing cached models."):t("Could not refresh model catalogs: {message}",{message:error instanceof Error?error.message:String(error)}),"warning"),host.ui.requestRender())}).finally(()=>clearTimeout(timeout)),{component:selector,focus:selector,dispose:()=>{disposed=!0,clearTimeout(timeout),controller.abort()}}})}function showUserMessageSelector(host){let userMessages=host.getUserMessagesForForking();if(userMessages.length===0){host.showStatus(t("No messages to fork from"));return}let initialSelectedId=userMessages[userMessages.length-1]?.entryId;host.showSelector(done=>{let selector=new UserMessageSelectorComponent(userMessages.map(m=>({id:m.entryId,text:m.text,...m.replySummary===void 0?{}:{replySummary:m.replySummary}})),async entryId=>{done();let fallbackText=userMessages.find(m=>m.entryId===entryId)?.text??"";try{let result=await host.runtimeFacade.fork(entryId);if(result.cancelled){host.ui.requestRender();return}host.editor.setText(result.selectedText??""),host.showStatus(t("Forked to new session"))}catch(error){host.editor.setText(fallbackText),host.showError(error instanceof Error?error.message:String(error))}},()=>{done(),host.ui.requestRender()},initialSelectedId);return{component:selector,focus:selector.getMessageList()}})}function showQueueManagerSelector(host){host.showSelector(done=>{let readQueues=()=>({steering:[...host.facade.getSteeringMessages()],followUp:[...host.facade.getFollowUpMessages()]}),selector=new QueueManagerSelectorComponent(readQueues(),{refresh:readQueues,onReorder:(queue,from,to)=>host.facade.reorderQueuedMessages(queue,from,to),onRemove:(queue,index)=>host.facade.removeQueuedMessageAt(queue,index),onRestore:(queue,index)=>{let text=host.facade.removeQueuedMessageAt(queue,index);if(text===null)return!1;let currentText=host.editor.getText(),combinedText=[text,currentText].filter(part=>part.trim()).join(`
|
|
736
736
|
|
|
737
|
-
`);return host.editor.setText(combinedText),!0},onClose:()=>{done(),host.updatePendingMessagesDisplay(),host.ui.requestRender()}});return{component:selector,focus:selector.getMessageList()}})}async function handleCloneCommand(host){let leafId=host.facade.getLeafId();if(!leafId){host.showStatus(t("Nothing to clone yet"));return}try{if((await host.runtimeFacade.fork(leafId,{position:"at"})).cancelled){host.ui.requestRender();return}host.editor.setText(""),host.showStatus(t("Cloned to new session"))}catch(error){host.showError(error instanceof Error?error.message:String(error))}}function showSettingsSelector(host){host.showSelector(done=>{let selector,defaultProvider=host.settingsManager.getDefaultProvider(),defaultModelId=host.settingsManager.getDefaultModel(),defaultModel=defaultProvider&&defaultModelId?`${defaultProvider}/${defaultModelId}`:t("not set");return selector=new SettingsSelectorComponent({defaultModel,currentModel:host.facade.getModel(),availableDefaultModels:host.facade.getAvailableModels(),showImages:host.settingsManager.getShowImages(),imageWidthCells:host.settingsManager.getImageWidthCells(),autoResizeImages:host.settingsManager.getImageAutoResize(),blockImages:host.settingsManager.getBlockImages(),steeringMode:host.facade.getSteeringMode(),followUpMode:host.facade.getFollowUpMode(),transport:host.settingsManager.getTransport(),httpIdleTimeoutMs:host.settingsManager.getHttpIdleTimeoutMs(),thinkingLevel:host.settingsManager.getDefaultThinkingLevel()??DEFAULT_THINKING_LEVEL,availableThinkingLevels:[...THINKING_LEVEL_OPTIONS],modelThinkingLevels:host.settingsManager.getAllModelThinkingLevels(),currentTheme:host.themeController.getThemeSelection()||"dark",terminalTheme:host.themeController.getTerminalTheme(),availableThemes:getAvailableThemes(),hideThinkingBlock:host.hideThinkingBlock,mermaidRenderingMode:host.settingsManager.getMermaidRenderingMode(),collapseChangelog:host.settingsManager.getCollapseChangelog(),doubleEscapeAction:host.settingsManager.getDoubleEscapeAction(),uiLanguage:host.settingsManager.getUiLanguage(),treeFilterMode:host.settingsManager.getTreeFilterMode(),showHardwareCursor:host.settingsManager.getShowHardwareCursor(),showCacheMissNotices:host.settingsManager.getShowCacheMissNotices(),editorPaddingX:host.settingsManager.getEditorPaddingX(),outputPad:host.settingsManager.getOutputPad(),autocompleteMaxVisible:host.settingsManager.getAutocompleteMaxVisible(),quietStartup:host.settingsManager.getQuietStartup(),clearOnShrink:host.settingsManager.getClearOnShrink(),showTerminalProgress:host.settingsManager.getShowTerminalProgress(),tuiMode:host.ui.mode,fullscreenExitOutput:host.settingsManager.getFullscreenExitOutput(),fullscreenScrollbar:host.settingsManager.getFullscreenScrollbar(),fullscreenCopyOnSelect:host.settingsManager.getFullscreenCopyOnSelect(),fullscreenWheelScrollLines:host.settingsManager.getFullscreenWheelScrollLines(),warnings:host.settingsManager.getWarnings()},{onShowImagesChange:enabled=>{host.settingsManager.setShowImages(enabled);for(let child of host.chatContainer.children)child instanceof ToolExecutionComponent&&child.setShowImages(enabled)},onImageWidthCellsChange:width=>{host.settingsManager.setImageWidthCells(width);for(let child of host.chatContainer.children)child instanceof ToolExecutionComponent&&child.setImageWidthCells(width)},onAutoResizeImagesChange:enabled=>{host.settingsManager.setImageAutoResize(enabled)},onBlockImagesChange:blocked=>{host.settingsManager.setBlockImages(blocked)},onSteeringModeChange:mode=>{host.facade.setSteeringMode(mode)},onFollowUpModeChange:mode=>{host.facade.setFollowUpMode(mode)},onTransportChange:transport=>{host.settingsManager.setTransport(transport),host.session.host.setTransport(transport)},onHttpIdleTimeoutMsChange:timeoutMs=>{host.settingsManager.setHttpIdleTimeoutMs(timeoutMs),configureHttpDispatcher(timeoutMs),host.showStatus(t("HTTP idle timeout: {value}",{value:formatHttpIdleTimeoutMs(timeoutMs)}))},onModelThinkingLevelChange:(provider,modelId,level)=>{host.settingsManager.setModelThinkingLevel(provider,modelId,level);let current=host.facade.getModel();current&¤t.provider===provider&¤t.id===modelId&&(host.facade.setThinkingLevel(level),host.footer.invalidate(),host.updateEditorBorderColor())},onModelThinkingLevelRemove:(provider,modelId)=>{host.settingsManager.removeModelThinkingLevel(provider,modelId);let current=host.facade.getModel();if(current&¤t.provider===provider&¤t.id===modelId){let globalDefault=host.settingsManager.getDefaultThinkingLevel()??DEFAULT_THINKING_LEVEL;host.facade.setThinkingLevel(globalDefault),host.footer.invalidate(),host.updateEditorBorderColor()}},onThemeChange:themeSetting=>{host.settingsManager.setTheme(themeSetting),host.themeController.setThemeSetting(themeSetting)},onThemePreview:themeName=>host.themeController.preview(themeName),onHideThinkingBlockChange:hidden=>{host.hideThinkingBlock=hidden,host.settingsManager.setHideThinkingBlock(hidden),host.updateThinkingBlockVisibility()},onMermaidRenderingModeChange:mode=>{host.settingsManager.setMermaidRenderingMode(mode),host.chatContainer.invalidate(),host.ui.requestRender()},onShowCacheMissNoticesChange:shown=>{host.settingsManager.setShowCacheMissNotices(shown),host.rebuildChatFromMessages()},onCollapseChangelogChange:collapsed=>{host.settingsManager.setCollapseChangelog(collapsed)},onQuietStartupChange:enabled=>{host.settingsManager.setQuietStartup(enabled)},onDoubleEscapeActionChange:action=>{host.settingsManager.setDoubleEscapeAction(action)},onUiLanguageChange:language=>{host.settingsManager.setUiLanguage(language),setI18nLanguage(language),host.ui.requestRender()},onTreeFilterModeChange:mode=>{host.settingsManager.setTreeFilterMode(mode)},onShowHardwareCursorChange:enabled=>{host.settingsManager.setShowHardwareCursor(enabled),host.ui.setShowHardwareCursor(enabled)},onEditorPaddingXChange:padding=>{host.settingsManager.setEditorPaddingX(padding),host.defaultEditor.setPaddingX(padding),host.editor!==host.defaultEditor&&host.editor.setPaddingX!==void 0&&host.editor.setPaddingX(padding)},onOutputPadChange:padding=>{if(host.settingsManager.setOutputPad(padding),host.outputPad=padding,host.streamingComponent||host.facade.isStreaming()){for(let child of host.chatContainer.children)(child instanceof AssistantMessageComponent||child instanceof CustomMessageComponent||child instanceof UserMessageComponent)&&child.setOutputPad(padding);host.streamingComponent&&host.streamingComponent.setOutputPad(padding),host.ui.requestRender();return}host.rebuildChatFromMessages()},onAutocompleteMaxVisibleChange:maxVisible=>{host.settingsManager.setAutocompleteMaxVisible(maxVisible),host.defaultEditor.setAutocompleteMaxVisible(maxVisible),host.editor!==host.defaultEditor&&host.editor.setAutocompleteMaxVisible!==void 0&&host.editor.setAutocompleteMaxVisible(maxVisible)},onClearOnShrinkChange:enabled=>{host.settingsManager.setClearOnShrink(enabled),host.ui.setClearOnShrink(enabled),!enabled&&!host.activeStatusIndicator&&host.statusContainer.clear()},onShowTerminalProgressChange:enabled=>{host.settingsManager.setShowTerminalProgress(enabled)},onTuiModeChange:mode=>{if(!host.switchTuiMode(mode)){selector?.getSettingsList().updateValue("tui-mode",host.ui.mode),host.showStatus(t("Close active overlays before changing TUI mode"));return}host.settingsManager.setTuiMode(mode),host.activeStatusIndicator||host.statusContainer.clear(),host.showStatus(t("TUI mode: {mode}",{mode}))},onFullscreenExitOutputChange:output=>{host.settingsManager.setFullscreenExitOutput(output)},onFullscreenScrollbarChange:mode=>{host.settingsManager.setFullscreenScrollbar(mode),host.applyFullscreenScrollbarSetting()},onFullscreenCopyOnSelectChange:enabled=>{host.settingsManager.setFullscreenCopyOnSelect(enabled),host.renderer instanceof TuiAltScreen&&host.renderer.setCopyOnSelect(enabled)},onFullscreenWheelScrollLinesChange:lines=>{host.settingsManager.setFullscreenWheelScrollLines(lines),host.renderer instanceof TuiAltScreen&&host.renderer.setWheelScrollLines(lines)},onWarningsChange:warnings=>{host.settingsManager.setWarnings(warnings)},onCancel:()=>{done(),host.ui.requestRender()}}),{component:selector,focus:selector.getSettingsList()}})}function showWorkflowView(host){if(!host.facade.getEntries().some(entry=>entry.type==="custom"&&entry.customType==="workflow.state")){host.showStatus(t("No workflow in this session"));return}host.showSelector(done=>{let view=new WorkflowViewComponent({getEntries:()=>host.facade.getEntries(),maxRows:Math.max(6,Math.floor(host.ui.terminal.rows/2)),requestRender:()=>host.ui.requestRender()});return view.onClose=done,view.onForwardAction=text=>{done(),host.editor.setText(text),host.ui.requestRender(),host.showStatus(t("Workflow action staged \u2014 review in the editor and submit"))},{component:view,focus:view,dispose:()=>view.dispose()}})}function showAgentsView(host){let agentDir=getAgentDir(),sessions=listAgentSessions({agentDir,parentAgentSession:host.facade.getSessionId()});if(sessions.length===0){host.showStatus(t("No subagent sessions in this session"));return}host.showSelector(done=>{let view=new AgentsViewComponent({sessions,loadEntries:sessionId=>readAgentSession({agentDir,sessionId}),maxRows:Math.max(6,Math.floor(host.ui.terminal.rows/2)),requestRender:()=>host.ui.requestRender()});return view.onClose=done,{component:view,focus:view}})}function showTreeSelector(host,initialSelectedId){let tree=host.facade.getTree(),realLeafId=host.facade.getLeafId(),initialFilterMode=host.settingsManager.getTreeFilterMode();if(tree.length===0){host.showStatus(t("No entries in session"));return}host.showSelector(done=>{let selector=new TreeSelectorComponent(tree,realLeafId,host.ui.terminal.rows,async entryId=>{if(entryId===host.facade.getLeafId()){done(),host.showStatus(t("Already at this point"));return}done();let wantsSummary=!1,customInstructions;if(!host.settingsManager.getBranchSummarySkipPrompt())for(;;){let summaryChoice=await host.showDialogSelector(t("Summarize branch?"),[t("No summary"),t("Summarize"),t("Summarize with custom prompt")]);if(summaryChoice===void 0){showTreeSelector(host,entryId);return}if(wantsSummary=summaryChoice!==t("No summary"),!(summaryChoice===t("Summarize with custom prompt")&&(customInstructions=await host.showDialogEditor(t("Custom summarization instructions")),customInstructions===void 0)))break}host.facade.isStreaming()&&(host.restoreQueuedMessagesToEditor(),await host.facade.abort({cancelAgentTasks:!1}));let showingSummaryIndicator=!1,originalOnEscape=host.defaultEditor.onEscape;wantsSummary&&(host.defaultEditor.onEscape=()=>{host.facade.abortBranchSummary()},host.chatContainer.addChild(new Spacer(1)),host.showStatusIndicator(new BranchSummaryStatusIndicator(host.ui)),showingSummaryIndicator=!0,host.ui.requestRender());try{let result=await host.facade.navigateTree(entryId,{summarize:wantsSummary,customInstructions});if(result.aborted){host.showStatus(t("Branch summarization cancelled")),showTreeSelector(host,entryId);return}if(result.cancelled){host.showStatus(t("Navigation cancelled"));return}host.chatContainer.clear(),host.renderInitialMessages(),result.editorText&&!host.editor.getText().trim()&&host.editor.setText(result.editorText),host.showStatus(t("Navigated to selected point")),host.flushCompactionQueue({willRetry:!1})}catch(error){host.showError(error instanceof Error?error.message:String(error))}finally{showingSummaryIndicator&&host.clearStatusIndicator("branchSummary"),host.defaultEditor.onEscape=originalOnEscape}},()=>{done(),host.ui.requestRender()},(entryId,label)=>{host.facade.appendLabelChange(entryId,label),host.ui.requestRender()},initialSelectedId,initialFilterMode);return selector.onCopy=async text=>{if(!text){host.showError(t("Selected entry has no text to copy"));return}try{await copyToClipboard(text),host.showStatus(t("Copied selected message to clipboard"))}catch(error){host.showError(error instanceof Error?error.message:String(error))}},{component:selector,focus:selector}})}function showSessionSelector(host){host.showSelector(done=>{let selector=new SessionSelectorComponent((onProgress,signal)=>host.runtimeFacade.listSessions(onProgress,signal),(onProgress,signal)=>host.runtimeFacade.listAllSessions(onProgress,signal),async sessionPath=>{done(),await handleResumeSession(host,sessionPath)},()=>{done(),host.ui.requestRender()},()=>{host.shutdown()},()=>host.ui.requestRender(),{renameSession:async(sessionFilePath,nextName)=>{let next=(nextName??"").trim();if(!next)return;SessionManager.open(sessionFilePath).appendSessionInfo(next)},showRenameHint:!0,keybindings:host.keybindings,suiteFilter:{currentSuiteId:host.getCurrentSessionSuiteId(),getSessionSuiteId:session=>host.readSessionSuiteId(session.path)}},host.runtimeFacade.getSessionFile());return{component:selector,focus:selector}})}async function handleResumeSession(host,sessionPath,options){host.clearStatusIndicator();try{let result=await host.runtimeFacade.switchSession(sessionPath,{withSession:options?.withSession});return result.cancelled||(host.showStatus(t("Resumed session")),host.detectCrossSuiteResume()),result}catch(error){if(error instanceof MissingSessionCwdError){let selectedCwd=await host.promptForMissingSessionCwd(error);if(!selectedCwd)return host.showStatus(t("Resume cancelled")),{cancelled:!0};let result=await host.runtimeFacade.switchSession(sessionPath,{cwdOverride:selectedCwd,withSession:options?.withSession});return result.cancelled||(host.showStatus(t("Resumed session in current cwd")),host.detectCrossSuiteResume()),result}return host.handleFatalRuntimeError(t("Failed to resume session"),error)}}async function showStartupSuiteSelector(host,pending){let selected=await new Promise(resolve22=>{openSuiteListSelector(host,{availableSuites:pending.available,note:t('Suite "{id}" was not found. The selected suite applies to the new session.',{id:pending.requestedId}),onSelect:suiteId=>resolve22(suiteId),onCancel:()=>resolve22(void 0)})});if(selected===void 0){host.showWarning(t('Suite "{id}" was not found \u2014 continuing without a suite. Use /suite to choose one.',{id:pending.requestedId}));return}host.settingsManager.setProjectSuite(selected);try{await host.runtimeFacade.newSession(),host.showStatus(t("Suite set to {id} \u2014 new session started",{id:selected}))}catch(error){await host.handleFatalRuntimeError(t("Failed to create session"),error)}}import{spawn as spawn4}from"child_process";var import_semver5=__toESM(require_semver(),1);var DEFAULT_VERSION_CHECK_TIMEOUT_MS=1e4,EXPECTED_PACKAGE_NAME="@ai-agent-forge/agent-forge";function formatVersionCheckError(error){let rootMessage=error instanceof Error&&error.message?error.message:String(error),cause=error instanceof Error?error.cause:void 0,causes=cause instanceof AggregateError?cause.errors:cause===void 0?[]:[cause],codes=causes.map(value=>typeof value=="object"&&value!==null&&"code"in value&&typeof value.code=="string"?value.code:void 0).filter(code=>code!==void 0);if(codes.length>0)return`${rootMessage} (${[...new Set(codes)].join(", ")})`;let causeMessage=causes.find(value=>value instanceof Error&&!!value.message)?.message;return causeMessage?`${rootMessage} (cause: ${causeMessage})`:rootMessage}function comparePackageVersions(leftVersion,rightVersion){let left=(0,import_semver5.valid)(leftVersion.trim()),right=(0,import_semver5.valid)(rightVersion.trim());if(!(!left||!right))return(0,import_semver5.compare)(left,right)}function isNewerPackageVersion(candidateVersion,currentVersion){let comparison=comparePackageVersions(candidateVersion,currentVersion);return comparison!==void 0?comparison>0:candidateVersion.trim()!==currentVersion.trim()}async function getLatestRelease(currentVersion,options={}){if(process.env.AGENT_FORGE_OFFLINE)return;let versionCheckUrl=process.env.AGENT_FORGE_VERSION_CHECK_URL?.trim();if(!versionCheckUrl)return;let response2=await fetchWithRetry(versionCheckUrl,{headers:{"User-Agent":getAgentForgeUserAgent(currentVersion),accept:"application/json"}},{maxRetries:options.retry?2:0,timeoutMs:options.timeoutMs??DEFAULT_VERSION_CHECK_TIMEOUT_MS});if(!response2.ok)return;let data=await response2.json();if(typeof data.version!="string"||!data.version.trim())return;let packageName=typeof data.packageName=="string"&&data.packageName.trim()?data.packageName.trim():void 0;if(packageName!==void 0&&packageName!==EXPECTED_PACKAGE_NAME)throw new Error(t("Version service returned an unexpected package name: {actual}. Expected {expected}.",{actual:packageName,expected:EXPECTED_PACKAGE_NAME}));let note=typeof data.note=="string"&&data.note.trim()?data.note.trim():void 0;return{version:data.version.trim(),packageName,...note?{note}:{}}}async function checkForNewVersion(currentVersion){if(!process.env.AGENT_FORGE_SKIP_VERSION_CHECK)try{let latestRelease=await getLatestRelease(currentVersion);return latestRelease&&isNewerPackageVersion(latestRelease.version,currentVersion)?latestRelease:void 0}catch{return}}function startStartupBackgroundChecks(host){if(!process.env.AGENT_FORGE_OFFLINE){let controller=new AbortController,timeout=setTimeout(()=>controller.abort(),15e3);refreshModelCatalogs(host.getModelCatalog(),controller.signal).then(()=>host.updateAvailableProviderCount()).catch(()=>{}).finally(()=>clearTimeout(timeout))}checkForNewVersion(host.getVersion()).then(newRelease=>{newRelease&&host.showNewVersionNotification(newRelease)}),checkForPackageUpdates(host).then(updates=>{updates.length>0&&host.showPackageUpdateNotification(updates)}).finally(()=>{process.platform==="win32"&&host.hasInitialized()&&host.updateTerminalTitle()}),checkTmuxKeyboardSetup().then(warning=>{warning&&host.showWarning(warning)})}async function checkForPackageUpdates(host){if(process.env.AGENT_FORGE_OFFLINE)return[];try{return(await new DefaultPackageManager({cwd:host.getCwd(),agentDir:getAgentDir(),settingsManager:host.settingsManager}).checkForAvailableUpdates()).map(update=>update.displayName)}catch{return[]}}async function checkTmuxKeyboardSetup(){if(!process.env.TMUX)return;let runTmuxShow=option=>new Promise(resolve22=>{let proc=spawn4("tmux",["show","-gv",option],{stdio:["ignore","pipe","ignore"]}),stdout="",timer=setTimeout(()=>{proc.kill(),resolve22(void 0)},2e3);proc.stdout?.on("data",data=>{stdout+=data.toString()}),proc.on("error",()=>{clearTimeout(timer),resolve22(void 0)}),proc.on("close",code=>{clearTimeout(timer),resolve22(code===0?stdout.trim():void 0)})}),[extendedKeys,extendedKeysFormat]=await Promise.all([runTmuxShow("extended-keys"),runTmuxShow("extended-keys-format")]);if(extendedKeys!==void 0){if(extendedKeys!=="on"&&extendedKeys!=="always")return t("tmux extended-keys is off. Modified Enter keys may not work. Add `set -g extended-keys on` to ~/.tmux.conf and restart tmux.");if(extendedKeysFormat==="xterm")return t("tmux extended-keys-format is xterm. Agent Forge works best with csi-u. Add `set -g extended-keys-format csi-u` to ~/.tmux.conf and restart tmux.")}}var ExpandableText=class extends Text{getCollapsedText;getExpandedText;constructor(getCollapsedText,getExpandedText,expanded=!1,paddingX=0,paddingY=0){super(expanded?getExpandedText():getCollapsedText(),paddingX,paddingY),this.getCollapsedText=getCollapsedText,this.getExpandedText=getExpandedText}setExpanded(expanded){this.setText(expanded?this.getExpandedText():this.getCollapsedText())}},EMPTY_REPLY_RETRY_PROMPT="Your previous reply was empty. Continue the user's task now.",ANTHROPIC_SUBSCRIPTION_AUTH_WARNING="Anthropic subscription auth is active. Third-party harness usage draws from extra usage and is billed per token, not your Claude plan limits. Manage extra usage at https://claude.ai/settings/usage. Disable this warning in /settings.";function formatResumeCommand(session){if(!process.stdout.isTTY||!session.isPersisted())return;let sessionFile=session.getSessionFile();if(!sessionFile||!fs2.existsSync(sessionFile))return;let args=[APP_NAME];return session.usesDefaultSessionDir()||args.push("--session-dir",quoteIfNeeded(session.getSessionDir())),args.push("--session",session.getSessionId()),args.join(" ")}function createInteractiveTui(options){let terminal=options.terminal??new ProcessTerminal;if(options.tuiMode==="fullscreen"){let styleSearchMatch=text=>theme.bg("searchMatchBg",theme.fg("searchMatchText",text));return new TuiAltScreen(terminal,options.showHardwareCursor,options.logDirectory,{searchMatchStyle:text=>theme.underline(styleSearchMatch(text)),searchCurrentMatchStyle:text=>theme.bold(theme.inverse(styleSearchMatch(text))),openUrl:openBrowser,onRightClickPaste:options.onRightClickPaste,copyOnSelect:options.fullscreenCopyOnSelect,wheelScrollLines:options.fullscreenWheelScrollLines??1,copySelection:async text=>{try{return await copyToClipboard(text),!0}catch(error){return error instanceof Error?error.message:String(error)}},labels:{searchTitle:` ${t("Find transcript")}`,searchNoMatches:`${t("No matches")} `,copied:t("Copied!"),copyFailed:t("Copy failed")}})}return new TuiMainScreen(terminal,options.showHardwareCursor,options.logDirectory)}function createInteractiveTuiReference(getTui){return new Proxy({},{get:(_target,property)=>{let tui=getTui(),value=Reflect.get(tui,property,tui);if(typeof value!="function")return value;let methodTui=tui,method=value;return(...args)=>{let currentTui=getTui();if(currentTui!==methodTui){let currentMethod=Reflect.get(currentTui,property,currentTui);if(typeof currentMethod!="function")throw new TypeError(t("TUI property {property} is not callable",{property:String(property)}));methodTui=currentTui,method=currentMethod}return Reflect.apply(method,methodTui,args)}},set:(_target,property,value)=>{let tui=getTui();return Reflect.set(tui,property,value,tui)},has:(_target,property)=>Reflect.has(getTui(),property),getPrototypeOf:()=>Reflect.getPrototypeOf(getTui())})}var ProviderFailoverTicker=class{intervalId;isOpen;requestRender;constructor(isOpen,requestRender){this.isOpen=isOpen,this.requestRender=requestRender}refresh(){if(this.isOpen()){this.intervalId===void 0&&(this.intervalId=setInterval(()=>{this.requestRender(),this.refresh()},1e3));return}this.dispose()}dispose(){this.intervalId!==void 0&&(clearInterval(this.intervalId),this.intervalId=void 0)}},InteractiveMode=class{runtimeHost;renderer;ui;mainScreenRenderState;loadedResourcesContainer;chatContainer;documentContainer;transcriptScrollView;fullscreenLayoutRoot;pendingMessagesContainer;statusContainer;defaultEditor;editor;autocompleteProvider;fdPath;editorContainer;activeSelectorToken;activeSelectorDispose;footer;failoverTicker;footerContainer;footerDataProvider;keybindings;version;isInitialized=!1;onInputCallback;pendingUserInputs=[];activeStatusIndicator=void 0;idleStatus=new IdleStatus;workingMessage=void 0;workingVisible=!0;workingIndicatorOptions=void 0;defaultWorkingMessage=t("Working...");defaultHiddenThinkingLabel=t("Thinking...");hiddenThinkingLabel=this.defaultHiddenThinkingLabel;lastSigintTime=0;lastEscapeTime=0;changelogMarkdown=void 0;startupNoticesShown=!1;anthropicSubscriptionWarningShown=!1;lastStatusSpacer=void 0;lastStatusText=void 0;managedToolStatusStarted=!1;streamingComponent=void 0;streamingMessage=void 0;pendingTools=new Map;activeToolRunGroup=void 0;toolOutputExpanded=!1;hideThinkingBlock=!1;outputPad=1;mermaidMarkdownTransformer=createMermaidMarkdownTransformer({getMode:()=>this.settingsManager.getMermaidRenderingMode(),theme});unsubscribe;signalCleanupHandlers=[];isBashMode=!1;bashComponent=void 0;pendingBashComponents=[];autoCompactionEscapeHandler;retryEscapeHandler;compactionQueuedMessages=[];shutdownRequested=!1;isShuttingDown=!1;dialogSelector=void 0;dialogInput=void 0;dialogSelectorReplaced=void 0;dialogInputReplaced=void 0;dialogEditor=void 0;widgetContainerAbove;widgetContainerBelow;headerContainer;builtInHeader=void 0;options;onRightClickPaste=()=>{this.handleRightClickPaste()};themeController;get session(){return this.runtimeHost.session}get settingsManager(){return this.options.settingsManager}get facade(){return createCodingAgentFacade(this.session)}get runtimeFacade(){return createCodingAgentRuntimeFacade(this.runtimeHost)}constructor(runtimeHost,options){this.options={...options},this.runtimeHost=runtimeHost,setI18nLanguage(this.settingsManager.getUiLanguage()),setCapabilityOverrides(this.settingsManager.getTerminalCapabilityOverrides());let tuiMode=options.tuiMode??this.settingsManager.getTuiMode();this.options.tuiMode=tuiMode,this.runtimeFacade.setBeforeSessionInvalidate(()=>{this.resetDialogUI()}),this.runtimeFacade.setRebindSession(async()=>{await this.rebindCurrentSession({renderBeforeBind:!0}),await this.themeController.applyFromSettings()}),this.version=VERSION,this.renderer=createInteractiveTui({tuiMode,showHardwareCursor:this.settingsManager.getShowHardwareCursor(),logDirectory:getAgentDir(),onRightClickPaste:this.onRightClickPaste,fullscreenCopyOnSelect:this.settingsManager.getFullscreenCopyOnSelect(),fullscreenWheelScrollLines:this.settingsManager.getFullscreenWheelScrollLines()}),this.ui=createInteractiveTuiReference(()=>this.renderer),this.ui.setClearOnShrink(this.settingsManager.getClearOnShrink()),this.headerContainer=new Container,this.loadedResourcesContainer=new Container,this.chatContainer=new Container,this.documentContainer=new Container,this.documentContainer.addChild(this.headerContainer),this.documentContainer.addChild(this.loadedResourcesContainer),this.documentContainer.addChild(this.chatContainer),this.pendingMessagesContainer=new Container,this.statusContainer=new Container,this.widgetContainerAbove=new Container,this.widgetContainerAbove.addChild(new Spacer(1)),this.widgetContainerBelow=new Container,this.keybindings=KeybindingsManager2.create(),setKeybindings(this.keybindings);let editorPaddingX=this.settingsManager.getEditorPaddingX(),autocompleteMaxVisible=this.settingsManager.getAutocompleteMaxVisible();this.defaultEditor=new CustomEditor(this.ui,getEditorTheme(),this.keybindings,{paddingX:editorPaddingX,autocompleteMaxVisible}),this.editor=this.defaultEditor,this.editorContainer=new Container,this.editorContainer.addChild(this.editor),this.footerDataProvider=new FooterDataProvider(this.facade.getCwd()),this.footer=new FooterComponent(this.session,this.footerDataProvider),this.footerContainer=new Container,this.footerContainer.addChild(this.footer),this.failoverTicker=new ProviderFailoverTicker(()=>this.footer.isProviderFailoverOpen(),()=>this.ui.requestRender()),this.hideThinkingBlock=this.settingsManager.getHideThinkingBlock(),this.outputPad=this.settingsManager.getOutputPad(),setRegisteredThemes(buildRegisteredThemes(this.facade.getThemes().themes)),this.themeController=new InteractiveThemeController(this.ui,{getSettingsManager:()=>this.settingsManager,showError:message=>this.showError(message),onChanged:()=>this.updateEditorBorderColor(),initialThemeSetting:options.initialThemeSetting})}getAutocompleteSourceTag(sourceInfo){if(!sourceInfo)return;let scopePrefix=sourceInfo.scope==="user"?"u":sourceInfo.scope==="project"?"p":"t",source=sourceInfo.source.trim();if(source==="auto"||source==="local"||source==="cli")return scopePrefix;if(source.startsWith("npm:"))return`${scopePrefix}:${source}`;let gitSource=parseGitUrl(source);if(gitSource){let ref=gitSource.ref?`@${gitSource.ref}`:"";return`${scopePrefix}:git:${gitSource.host}/${gitSource.path}${ref}`}return scopePrefix}prefixAutocompleteDescription(description,sourceInfo){let sourceTag=this.getAutocompleteSourceTag(sourceInfo);return sourceTag?description?`[${sourceTag}] ${description}`:`[${sourceTag}]`:description}createBaseAutocompleteProvider(){let slashCommands=BUILTIN_SLASH_COMMANDS.map(command=>({name:command.name,description:command.description,...command.argumentHint&&{argumentHint:command.argumentHint}})),modelCommand=slashCommands.find(command=>command.name==="model");modelCommand&&(modelCommand.getArgumentCompletions=prefix=>{let models=this.facade.getScopedModels().length>0?this.facade.getScopedModels().map(s=>s.model):this.facade.getAvailableModels();if(models.length===0)return null;let items=models.map(m=>({id:m.id,provider:m.provider,name:m.name,label:`${m.provider}/${m.id}`}));return createFuzzyAutocompleteItems(items,prefix,getModelSearchText,item=>({value:item.label,label:item.id,description:item.provider}))});let thinkingCommand=slashCommands.find(command=>command.name==="thinking");thinkingCommand&&(thinkingCommand.getArgumentCompletions=prefix=>createFuzzyAutocompleteItems(this.facade.getAvailableThinkingLevels(),prefix,level=>level,level=>({value:level,label:level})));let suiteCommand=slashCommands.find(command=>command.name==="suite");suiteCommand&&(suiteCommand.getArgumentCompletions=prefix=>createFuzzyAutocompleteItems(listSuiteIds(getAgentDir()),prefix,id=>id,id=>({value:id,label:id})));let loginCommand=slashCommands.find(command=>command.name==="login");loginCommand&&(loginCommand.getArgumentCompletions=prefix=>{let providers=getLoginProviderCompletionOptions(this.getLoginProviderOptions());return createFuzzyAutocompleteItems(providers,prefix,getLoginProviderSearchText,provider=>({value:provider.id,label:provider.id,description:formatLoginProviderCompletionDescription(provider)}))});let capabilityRegistrations=this.session.getCapabilityRuntime().listCommands(),capabilityCommandNames=new Set(capabilityRegistrations.map(({definition})=>definition.name)),templateCommands=this.facade.getPromptTemplates().filter(cmd=>!capabilityCommandNames.has(cmd.name)).map(cmd=>({name:cmd.name,description:this.prefixAutocompleteDescription(cmd.description,cmd.sourceInfo),...cmd.argumentHint&&{argumentHint:cmd.argumentHint}})),builtinCommandNames=new Set(slashCommands.map(c=>c.name)),templateCommandNames=new Set(this.facade.getPromptTemplates().map(cmd=>cmd.name)),resourceSkillCommandNames=new Set(this.facade.getSkills().skills.map(skill=>`skill:${skill.name}`)),capabilityCommands=filterCapabilityCommandsForCompletions(capabilityRegistrations.map(({definition})=>({name:definition.name,description:definition.description,...definition.argumentHint&&{argumentHint:definition.argumentHint}})),[builtinCommandNames,templateCommandNames,[...resourceSkillCommandNames]]),skillCommandList=[];for(let skill of this.facade.getSkills().skills){let commandName=`skill:${skill.name}`;capabilityCommandNames.has(commandName)||skillCommandList.push({name:commandName,description:this.prefixAutocompleteDescription(skill.description,skill.sourceInfo)})}return new CombinedAutocompleteProvider([...slashCommands,...templateCommands,...capabilityCommands,...skillCommandList],this.facade.getCwd(),this.fdPath)}setupAutocompleteProvider(){let provider=this.createBaseAutocompleteProvider();this.autocompleteProvider=provider,this.defaultEditor.setAutocompleteProvider(provider),this.editor!==this.defaultEditor&&this.editor.setAutocompleteProvider?.(provider)}showStartupNoticesIfNeeded(){if(!this.startupNoticesShown&&(this.startupNoticesShown=!0,!!this.changelogMarkdown)){if(this.chatContainer.children.length>0&&this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new DynamicBorder),this.settingsManager.getCollapseChangelog()){let versionMatch=this.changelogMarkdown.match(/##\s+\[?(\d+\.\d+\.\d+)\]?/),latestVersion=versionMatch?versionMatch[1]:this.version,condensedText=t("Updated to v{version}. Use {command} to view full changelog.",{version:latestVersion,command:theme.bold("/changelog")});this.chatContainer.addChild(new Text(condensedText,1,0))}else this.chatContainer.addChild(new Text(theme.bold(theme.fg("accent",t("What's New"))),1,0)),this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Markdown(this.changelogMarkdown.trim(),1,0,this.getMarkdownThemeWithSettings())),this.chatContainer.addChild(new Spacer(1));this.chatContainer.addChild(new DynamicBorder)}}mountInteractiveTui(tui,components){for(let component of components)tui.addChild(component);if(isViewportTUI(tui)){if(!this.fullscreenLayoutRoot)throw new Error(t("Fullscreen layout is not initialized"));tui.setLayoutRoot(this.fullscreenLayoutRoot)}}stopInteractiveTui(fullscreenExitOutput){if(this.renderer.mode==="fullscreen"&&fullscreenExitOutput==="transcript"){for(;this.renderer.hasOverlayEntries;)this.renderer.hideOverlay();this.switchTuiMode("regular",!1,!1),this.renderer.renderNow()}this.ui.stop({preserveScreen:this.renderer.mode==="fullscreen"})}switchTuiMode(mode,restoreProgress=!0,startRenderer=!0){let previousUi=this.renderer;if(mode===previousUi.mode)return!0;if(previousUi.hasOverlayEntries)return!1;let components=[...previousUi.children],focus=previousUi.getFocusedComponent(),terminal=previousUi.terminal,showHardwareCursor=previousUi.getShowHardwareCursor(),clearOnShrink=previousUi.getClearOnShrink(),onDebug=previousUi.onDebug;previousUi instanceof TuiMainScreen&&(this.mainScreenRenderState=previousUi.captureRenderState()),previousUi.stop({preserveScreen:!0}),previousUi.setFocus(null),previousUi.clear(),isViewportTUI(previousUi)&&previousUi.setLayoutRoot(void 0);let nextUi=createInteractiveTui({tuiMode:mode,showHardwareCursor,logDirectory:getAgentDir(),terminal,onRightClickPaste:this.onRightClickPaste,fullscreenCopyOnSelect:this.settingsManager.getFullscreenCopyOnSelect(),fullscreenWheelScrollLines:this.settingsManager.getFullscreenWheelScrollLines()});return nextUi.setClearOnShrink(clearOnShrink),nextUi.onDebug=onDebug,nextUi instanceof TuiMainScreen&&this.mainScreenRenderState&&nextUi.restoreRenderState(this.mainScreenRenderState),this.renderer=nextUi,this.options.tuiMode=mode,this.mountInteractiveTui(nextUi,components),nextUi.invalidate(),nextUi.setFocus(focus),startRenderer&&(nextUi.start(),this.themeController.rebindTui(),restoreProgress&&this.settingsManager.getShowTerminalProgress()&&(this.facade.isStreaming()||this.facade.isCompacting())&&terminal.setProgress(!0)),!0}async init(){if(this.isInitialized)return;if(this.registerSignalHandlers(),this.changelogMarkdown=this.getChangelogForDisplay(),this.facade.getScopedModels().length>0&&(this.options.verbose||!this.settingsManager.getQuietStartup())){let modelList=this.facade.getScopedModels().map(sm=>{let thinkingStr=sm.thinkingLevel?`:${sm.thinkingLevel}`:"";return`${sm.model.id}${thinkingStr}`}).join(", "),cycleKeys=this.keybindings.getKeys("app.model.cycleForward"),cycleHint=cycleKeys.length>0?theme.fg("muted",` ${t("({key} to cycle)",{key:formatKeyText(cycleKeys.join("/"),{capitalize:!0})})}`):"";console.log(theme.fg("dim",t("Model scope: {models}{hint}",{models:modelList,hint:cycleHint})))}this.transcriptScrollView=new ScrollView(this.documentContainer,{follow:"end",primary:!0,overscroll:"chain",scrollbar:this.settingsManager.getFullscreenScrollbar(),scrollbarStyle:text=>theme.bg("scrollbarThumb",text)});let dock=new VStack([{component:this.pendingMessagesContainer,shrink:1,minSize:0},{component:this.statusContainer,shrink:1,minSize:0},{component:this.widgetContainerAbove,shrink:1,minSize:0},{component:this.editorContainer,shrink:1,minSize:3},{component:this.widgetContainerBelow,shrink:1,minSize:0},{component:this.footerContainer,shrink:1,minSize:1}]);if(this.fullscreenLayoutRoot=new VStack([{component:this.transcriptScrollView,basis:0,grow:1,shrink:1,minSize:1},{component:dock,basis:"auto",grow:0,shrink:1,minSize:1}]),this.mountInteractiveTui(this.renderer,[this.documentContainer,this.pendingMessagesContainer,this.statusContainer,this.widgetContainerAbove,this.editorContainer,this.widgetContainerBelow,this.footerContainer]),this.defaultEditor.onAction("app.clear",()=>this.handleCtrlC()),this.defaultEditor.onCtrlD=()=>this.handleCtrlD(),this.defaultEditor.onSubmit=text=>this.handleStartupSubmit(text),this.ui.setFocus(this.editor),this.ui.start(),this.isInitialized=!0,await this.themeController.applyFromSettings(),this.options.verbose||!this.settingsManager.getQuietStartup()){let logo=theme.bold(theme.fg("accent",APP_NAME))+theme.fg("dim",` v${this.version}`),hint=(keybinding,description)=>keyHint(keybinding,description),expandedInstructions=[hint("app.interrupt",t("to interrupt")),hint("app.clear",t("to clear")),rawKeyHint(t("{key} twice",{key:keyText("app.clear")}),t("to exit")),hint("app.exit",t("to exit (empty)")),hint("app.suspend",t("to suspend")),keyHint("tui.editor.deleteToLineEnd",t("to delete to end")),hint("app.tools.expand",t("to expand tools")),hint("app.thinking.toggle",t("to expand thinking")),hint("app.editor.external",t("for external editor")),rawKeyHint("/",t("for commands")),rawKeyHint("!",t("to run bash")),rawKeyHint("!!",t("to run bash (no context)")),hint("app.clipboard.pasteImage",t("to paste image (with text fallback)")),rawKeyHint("drop files",t("to attach"))].join(`
|
|
737
|
+
`);return host.editor.setText(combinedText),!0},onClose:()=>{done(),host.updatePendingMessagesDisplay(),host.ui.requestRender()}});return{component:selector,focus:selector.getMessageList()}})}async function handleCloneCommand(host){let leafId=host.facade.getLeafId();if(!leafId){host.showStatus(t("Nothing to clone yet"));return}try{if((await host.runtimeFacade.fork(leafId,{position:"at"})).cancelled){host.ui.requestRender();return}host.editor.setText(""),host.showStatus(t("Cloned to new session"))}catch(error){host.showError(error instanceof Error?error.message:String(error))}}function showSettingsSelector(host){host.showSelector(done=>{let selector,defaultProvider=host.settingsManager.getDefaultProvider(),defaultModelId=host.settingsManager.getDefaultModel(),defaultModel=defaultProvider&&defaultModelId?`${defaultProvider}/${defaultModelId}`:t("not set");return selector=new SettingsSelectorComponent({defaultModel,currentModel:host.facade.getModel(),availableDefaultModels:host.facade.getAvailableModels(),showImages:host.settingsManager.getShowImages(),imageWidthCells:host.settingsManager.getImageWidthCells(),autoResizeImages:host.settingsManager.getImageAutoResize(),blockImages:host.settingsManager.getBlockImages(),steeringMode:host.facade.getSteeringMode(),followUpMode:host.facade.getFollowUpMode(),transport:host.settingsManager.getTransport(),httpIdleTimeoutMs:host.settingsManager.getHttpIdleTimeoutMs(),thinkingLevel:host.settingsManager.getDefaultThinkingLevel()??DEFAULT_THINKING_LEVEL,availableThinkingLevels:[...THINKING_LEVEL_OPTIONS],modelThinkingLevels:host.settingsManager.getAllModelThinkingLevels(),currentTheme:host.themeController.getThemeSelection()||"dark",terminalTheme:host.themeController.getTerminalTheme(),availableThemes:getAvailableThemes(),hideThinkingBlock:host.hideThinkingBlock,mermaidRenderingMode:host.settingsManager.getMermaidRenderingMode(),collapseChangelog:host.settingsManager.getCollapseChangelog(),doubleEscapeAction:host.settingsManager.getDoubleEscapeAction(),uiLanguage:host.settingsManager.getUiLanguage(),treeFilterMode:host.settingsManager.getTreeFilterMode(),showHardwareCursor:host.settingsManager.getShowHardwareCursor(),showCacheMissNotices:host.settingsManager.getShowCacheMissNotices(),editorPaddingX:host.settingsManager.getEditorPaddingX(),outputPad:host.settingsManager.getOutputPad(),autocompleteMaxVisible:host.settingsManager.getAutocompleteMaxVisible(),quietStartup:host.settingsManager.getQuietStartup(),clearOnShrink:host.settingsManager.getClearOnShrink(),showTerminalProgress:host.settingsManager.getShowTerminalProgress(),tuiMode:host.ui.mode,fullscreenExitOutput:host.settingsManager.getFullscreenExitOutput(),fullscreenScrollbar:host.settingsManager.getFullscreenScrollbar(),fullscreenCopyOnSelect:host.settingsManager.getFullscreenCopyOnSelect(),fullscreenWheelScrollLines:host.settingsManager.getFullscreenWheelScrollLines(),warnings:host.settingsManager.getWarnings()},{onShowImagesChange:enabled=>{host.settingsManager.setShowImages(enabled);for(let child of host.chatContainer.children)child instanceof ToolExecutionComponent&&child.setShowImages(enabled)},onImageWidthCellsChange:width=>{host.settingsManager.setImageWidthCells(width);for(let child of host.chatContainer.children)child instanceof ToolExecutionComponent&&child.setImageWidthCells(width)},onAutoResizeImagesChange:enabled=>{host.settingsManager.setImageAutoResize(enabled)},onBlockImagesChange:blocked=>{host.settingsManager.setBlockImages(blocked)},onSteeringModeChange:mode=>{host.facade.setSteeringMode(mode)},onFollowUpModeChange:mode=>{host.facade.setFollowUpMode(mode)},onTransportChange:transport=>{host.settingsManager.setTransport(transport),host.session.host.setTransport(transport)},onHttpIdleTimeoutMsChange:timeoutMs=>{host.settingsManager.setHttpIdleTimeoutMs(timeoutMs),configureHttpDispatcher(timeoutMs),host.showStatus(t("HTTP idle timeout: {value}",{value:formatHttpIdleTimeoutMs(timeoutMs)}))},onModelThinkingLevelChange:(provider,modelId,level)=>{host.settingsManager.setModelThinkingLevel(provider,modelId,level);let current=host.facade.getModel();current&¤t.provider===provider&¤t.id===modelId&&(host.facade.setThinkingLevel(level),host.footer.invalidate(),host.updateEditorBorderColor())},onModelThinkingLevelRemove:(provider,modelId)=>{host.settingsManager.removeModelThinkingLevel(provider,modelId);let current=host.facade.getModel();if(current&¤t.provider===provider&¤t.id===modelId){let globalDefault=host.settingsManager.getDefaultThinkingLevel()??DEFAULT_THINKING_LEVEL;host.facade.setThinkingLevel(globalDefault),host.footer.invalidate(),host.updateEditorBorderColor()}},onThemeChange:themeSetting=>{host.settingsManager.setTheme(themeSetting),host.themeController.setThemeSetting(themeSetting)},onThemePreview:themeName=>host.themeController.preview(themeName),onHideThinkingBlockChange:hidden=>{host.hideThinkingBlock=hidden,host.settingsManager.setHideThinkingBlock(hidden),host.updateThinkingBlockVisibility()},onMermaidRenderingModeChange:mode=>{host.settingsManager.setMermaidRenderingMode(mode),host.chatContainer.invalidate(),host.ui.requestRender()},onShowCacheMissNoticesChange:shown=>{host.settingsManager.setShowCacheMissNotices(shown),host.rebuildChatFromMessages()},onCollapseChangelogChange:collapsed=>{host.settingsManager.setCollapseChangelog(collapsed)},onQuietStartupChange:enabled=>{host.settingsManager.setQuietStartup(enabled)},onDoubleEscapeActionChange:action=>{host.settingsManager.setDoubleEscapeAction(action)},onUiLanguageChange:language=>{host.settingsManager.setUiLanguage(language),setI18nLanguage(language),host.ui.requestRender()},onTreeFilterModeChange:mode=>{host.settingsManager.setTreeFilterMode(mode)},onShowHardwareCursorChange:enabled=>{host.settingsManager.setShowHardwareCursor(enabled),host.ui.setShowHardwareCursor(enabled)},onEditorPaddingXChange:padding=>{host.settingsManager.setEditorPaddingX(padding),host.defaultEditor.setPaddingX(padding),host.editor!==host.defaultEditor&&host.editor.setPaddingX!==void 0&&host.editor.setPaddingX(padding)},onOutputPadChange:padding=>{if(host.settingsManager.setOutputPad(padding),host.outputPad=padding,host.streamingComponent||host.facade.isStreaming()){for(let child of host.chatContainer.children)(child instanceof AssistantMessageComponent||child instanceof CustomMessageComponent||child instanceof UserMessageComponent)&&child.setOutputPad(padding);host.streamingComponent&&host.streamingComponent.setOutputPad(padding),host.ui.requestRender();return}host.rebuildChatFromMessages()},onAutocompleteMaxVisibleChange:maxVisible=>{host.settingsManager.setAutocompleteMaxVisible(maxVisible),host.defaultEditor.setAutocompleteMaxVisible(maxVisible),host.editor!==host.defaultEditor&&host.editor.setAutocompleteMaxVisible!==void 0&&host.editor.setAutocompleteMaxVisible(maxVisible)},onClearOnShrinkChange:enabled=>{host.settingsManager.setClearOnShrink(enabled),host.ui.setClearOnShrink(enabled),!enabled&&!host.activeStatusIndicator&&host.statusContainer.clear()},onShowTerminalProgressChange:enabled=>{host.settingsManager.setShowTerminalProgress(enabled)},onTuiModeChange:mode=>{if(!host.switchTuiMode(mode)){selector?.getSettingsList().updateValue("tui-mode",host.ui.mode),host.showStatus(t("Close active overlays before changing TUI mode"));return}host.settingsManager.setTuiMode(mode),host.activeStatusIndicator||host.statusContainer.clear(),host.showStatus(t("TUI mode: {mode}",{mode}))},onFullscreenExitOutputChange:output=>{host.settingsManager.setFullscreenExitOutput(output)},onFullscreenScrollbarChange:mode=>{host.settingsManager.setFullscreenScrollbar(mode),host.applyFullscreenScrollbarSetting()},onFullscreenCopyOnSelectChange:enabled=>{host.settingsManager.setFullscreenCopyOnSelect(enabled),host.renderer instanceof TuiAltScreen&&host.renderer.setCopyOnSelect(enabled)},onFullscreenWheelScrollLinesChange:lines=>{host.settingsManager.setFullscreenWheelScrollLines(lines),host.renderer instanceof TuiAltScreen&&host.renderer.setWheelScrollLines(lines)},onWarningsChange:warnings=>{host.settingsManager.setWarnings(warnings)},onCancel:()=>{done(),host.ui.requestRender()}}),{component:selector,focus:selector.getSettingsList()}})}function showWorkflowView(host){if(!host.facade.getEntries().some(entry=>entry.type==="custom"&&entry.customType==="workflow.state")){host.showStatus(t("No workflow in this session"));return}host.showSelector(done=>{let view=new WorkflowViewComponent({getEntries:()=>host.facade.getEntries(),maxRows:Math.max(6,Math.floor(host.ui.terminal.rows/2)),requestRender:()=>host.ui.requestRender()});return view.onClose=done,view.onForwardAction=text=>{done(),host.editor.setText(text),host.ui.requestRender(),host.showStatus(t("Workflow action staged \u2014 review in the editor and submit"))},{component:view,focus:view,dispose:()=>view.dispose()}})}function showAgentsView(host){let agentDir=getAgentDir(),sessions=listAgentSessions({agentDir,parentAgentSession:host.facade.getSessionId()});if(sessions.length===0){host.showStatus(t("No subagent sessions in this session"));return}host.showSelector(done=>{let view=new AgentsViewComponent({sessions,loadEntries:sessionId=>readAgentSession({agentDir,sessionId}),maxRows:Math.max(6,Math.floor(host.ui.terminal.rows/2)),requestRender:()=>host.ui.requestRender()});return view.onClose=done,{component:view,focus:view}})}function showTreeSelector(host,initialSelectedId){let tree=host.facade.getTree(),realLeafId=host.facade.getLeafId(),initialFilterMode=host.settingsManager.getTreeFilterMode();if(tree.length===0){host.showStatus(t("No entries in session"));return}host.showSelector(done=>{let selector=new TreeSelectorComponent(tree,realLeafId,host.ui.terminal.rows,async entryId=>{if(entryId===host.facade.getLeafId()){done(),host.showStatus(t("Already at this point"));return}done();let wantsSummary=!1,customInstructions;if(!host.settingsManager.getBranchSummarySkipPrompt())for(;;){let summaryChoice=await host.showDialogSelector(t("Summarize branch?"),[t("No summary"),t("Summarize"),t("Summarize with custom prompt")]);if(summaryChoice===void 0){showTreeSelector(host,entryId);return}if(wantsSummary=summaryChoice!==t("No summary"),!(summaryChoice===t("Summarize with custom prompt")&&(customInstructions=await host.showDialogEditor(t("Custom summarization instructions")),customInstructions===void 0)))break}host.facade.isStreaming()&&(host.restoreQueuedMessagesToEditor(),await host.facade.abort({cancelAgentTasks:!1}));let showingSummaryIndicator=!1,originalOnEscape=host.defaultEditor.onEscape;wantsSummary&&(host.defaultEditor.onEscape=()=>{host.facade.abortBranchSummary()},host.chatContainer.addChild(new Spacer(1)),host.showStatusIndicator(new BranchSummaryStatusIndicator(host.ui)),showingSummaryIndicator=!0,host.ui.requestRender());try{let result=await host.facade.navigateTree(entryId,{summarize:wantsSummary,customInstructions});if(result.aborted){host.showStatus(t("Branch summarization cancelled")),showTreeSelector(host,entryId);return}if(result.cancelled){host.showStatus(t("Navigation cancelled"));return}host.chatContainer.clear(),host.renderInitialMessages(),result.editorText&&!host.editor.getText().trim()&&host.editor.setText(result.editorText),host.showStatus(t("Navigated to selected point")),host.flushCompactionQueue({willRetry:!1})}catch(error){host.showError(error instanceof Error?error.message:String(error))}finally{showingSummaryIndicator&&host.clearStatusIndicator("branchSummary"),host.defaultEditor.onEscape=originalOnEscape}},()=>{done(),host.ui.requestRender()},(entryId,label)=>{host.facade.appendLabelChange(entryId,label),host.ui.requestRender()},initialSelectedId,initialFilterMode);return selector.onCopy=async text=>{if(!text){host.showError(t("Selected entry has no text to copy"));return}try{await copyToClipboard(text),host.showStatus(t("Copied selected message to clipboard"))}catch(error){host.showError(error instanceof Error?error.message:String(error))}},{component:selector,focus:selector}})}function showSessionSelector(host){host.showSelector(done=>{let selector=new SessionSelectorComponent((onProgress,signal)=>host.runtimeFacade.listSessions(onProgress,signal),(onProgress,signal)=>host.runtimeFacade.listAllSessions(onProgress,signal),async sessionPath=>{done(),await handleResumeSession(host,sessionPath)},()=>{done(),host.ui.requestRender()},()=>{host.shutdown()},()=>host.ui.requestRender(),{renameSession:async(sessionFilePath,nextName)=>{let next=(nextName??"").trim();if(!next)return;SessionManager.open(sessionFilePath).appendSessionInfo(next)},showRenameHint:!0,keybindings:host.keybindings,suiteFilter:{currentSuiteId:host.getCurrentSessionSuiteId(),getSessionSuiteId:session=>host.readSessionSuiteId(session.path)}},host.runtimeFacade.getSessionFile());return{component:selector,focus:selector}})}async function handleResumeSession(host,sessionPath,options){host.clearStatusIndicator();try{let result=await host.runtimeFacade.switchSession(sessionPath,{withSession:options?.withSession});return result.cancelled||(host.showStatus(t("Resumed session")),host.detectCrossSuiteResume()),result}catch(error){if(error instanceof MissingSessionCwdError){let selectedCwd=await host.promptForMissingSessionCwd(error);if(!selectedCwd)return host.showStatus(t("Resume cancelled")),{cancelled:!0};let result=await host.runtimeFacade.switchSession(sessionPath,{cwdOverride:selectedCwd,withSession:options?.withSession});return result.cancelled||(host.showStatus(t("Resumed session in current cwd")),host.detectCrossSuiteResume()),result}return host.handleFatalRuntimeError(t("Failed to resume session"),error)}}async function showStartupSuiteSelector(host,pending){let selected=await new Promise(resolve22=>{openSuiteListSelector(host,{availableSuites:pending.available,note:t('Suite "{id}" was not found. The selected suite applies to the new session.',{id:pending.requestedId}),onSelect:suiteId=>resolve22(suiteId),onCancel:()=>resolve22(void 0)})});if(selected===void 0){host.showWarning(t('Suite "{id}" was not found \u2014 continuing without a suite. Use /suite to choose one.',{id:pending.requestedId}));return}host.settingsManager.setProjectSuite(selected);try{await host.runtimeFacade.newSession(),host.showStatus(t("Suite set to {id} \u2014 new session started",{id:selected}))}catch(error){await host.handleFatalRuntimeError(t("Failed to create session"),error)}}import{spawn as spawn5}from"child_process";var import_semver5=__toESM(require_semver(),1);var DEFAULT_VERSION_CHECK_TIMEOUT_MS=1e4,EXPECTED_PACKAGE_NAME="@ai-agent-forge/agent-forge";function formatVersionCheckError(error){let rootMessage=error instanceof Error&&error.message?error.message:String(error),cause=error instanceof Error?error.cause:void 0,causes=cause instanceof AggregateError?cause.errors:cause===void 0?[]:[cause],codes=causes.map(value=>typeof value=="object"&&value!==null&&"code"in value&&typeof value.code=="string"?value.code:void 0).filter(code=>code!==void 0);if(codes.length>0)return`${rootMessage} (${[...new Set(codes)].join(", ")})`;let causeMessage=causes.find(value=>value instanceof Error&&!!value.message)?.message;return causeMessage?`${rootMessage} (cause: ${causeMessage})`:rootMessage}function comparePackageVersions(leftVersion,rightVersion){let left=(0,import_semver5.valid)(leftVersion.trim()),right=(0,import_semver5.valid)(rightVersion.trim());if(!(!left||!right))return(0,import_semver5.compare)(left,right)}function isNewerPackageVersion(candidateVersion,currentVersion){let comparison=comparePackageVersions(candidateVersion,currentVersion);return comparison!==void 0?comparison>0:candidateVersion.trim()!==currentVersion.trim()}async function getLatestRelease(currentVersion,options={}){if(process.env.AGENT_FORGE_OFFLINE)return;let versionCheckUrl=process.env.AGENT_FORGE_VERSION_CHECK_URL?.trim();if(!versionCheckUrl)return;let response2=await fetchWithRetry(versionCheckUrl,{headers:{"User-Agent":getAgentForgeUserAgent(currentVersion),accept:"application/json"}},{maxRetries:options.retry?2:0,timeoutMs:options.timeoutMs??DEFAULT_VERSION_CHECK_TIMEOUT_MS});if(!response2.ok)return;let data=await response2.json();if(typeof data.version!="string"||!data.version.trim())return;let packageName=typeof data.packageName=="string"&&data.packageName.trim()?data.packageName.trim():void 0;if(packageName!==void 0&&packageName!==EXPECTED_PACKAGE_NAME)throw new Error(t("Version service returned an unexpected package name: {actual}. Expected {expected}.",{actual:packageName,expected:EXPECTED_PACKAGE_NAME}));let note=typeof data.note=="string"&&data.note.trim()?data.note.trim():void 0;return{version:data.version.trim(),packageName,...note?{note}:{}}}async function checkForNewVersion(currentVersion){if(!process.env.AGENT_FORGE_SKIP_VERSION_CHECK)try{let latestRelease=await getLatestRelease(currentVersion);return latestRelease&&isNewerPackageVersion(latestRelease.version,currentVersion)?latestRelease:void 0}catch{return}}function startStartupBackgroundChecks(host){if(!process.env.AGENT_FORGE_OFFLINE){let controller=new AbortController,timeout=setTimeout(()=>controller.abort(),15e3);refreshModelCatalogs(host.getModelCatalog(),controller.signal).then(()=>host.updateAvailableProviderCount()).catch(()=>{}).finally(()=>clearTimeout(timeout))}checkForNewVersion(host.getVersion()).then(newRelease=>{newRelease&&host.showNewVersionNotification(newRelease)}),checkForPackageUpdates(host).then(updates=>{updates.length>0&&host.showPackageUpdateNotification(updates)}).finally(()=>{process.platform==="win32"&&host.hasInitialized()&&host.updateTerminalTitle()}),checkTmuxKeyboardSetup().then(warning=>{warning&&host.showWarning(warning)})}async function checkForPackageUpdates(host){if(process.env.AGENT_FORGE_OFFLINE)return[];try{return(await new DefaultPackageManager({cwd:host.getCwd(),agentDir:getAgentDir(),settingsManager:host.settingsManager}).checkForAvailableUpdates()).map(update=>update.displayName)}catch{return[]}}async function checkTmuxKeyboardSetup(){if(!process.env.TMUX)return;let runTmuxShow=option=>new Promise(resolve22=>{let proc=spawn5("tmux",["show","-gv",option],{stdio:["ignore","pipe","ignore"]}),stdout="",timer=setTimeout(()=>{proc.kill(),resolve22(void 0)},2e3);proc.stdout?.on("data",data=>{stdout+=data.toString()}),proc.on("error",()=>{clearTimeout(timer),resolve22(void 0)}),proc.on("close",code=>{clearTimeout(timer),resolve22(code===0?stdout.trim():void 0)})}),[extendedKeys,extendedKeysFormat]=await Promise.all([runTmuxShow("extended-keys"),runTmuxShow("extended-keys-format")]);if(extendedKeys!==void 0){if(extendedKeys!=="on"&&extendedKeys!=="always")return t("tmux extended-keys is off. Modified Enter keys may not work. Add `set -g extended-keys on` to ~/.tmux.conf and restart tmux.");if(extendedKeysFormat==="xterm")return t("tmux extended-keys-format is xterm. Agent Forge works best with csi-u. Add `set -g extended-keys-format csi-u` to ~/.tmux.conf and restart tmux.")}}var ExpandableText=class extends Text{getCollapsedText;getExpandedText;constructor(getCollapsedText,getExpandedText,expanded=!1,paddingX=0,paddingY=0){super(expanded?getExpandedText():getCollapsedText(),paddingX,paddingY),this.getCollapsedText=getCollapsedText,this.getExpandedText=getExpandedText}setExpanded(expanded){this.setText(expanded?this.getExpandedText():this.getCollapsedText())}},EMPTY_REPLY_RETRY_PROMPT="Your previous reply was empty. Continue the user's task now.",ANTHROPIC_SUBSCRIPTION_AUTH_WARNING="Anthropic subscription auth is active. Third-party harness usage draws from extra usage and is billed per token, not your Claude plan limits. Manage extra usage at https://claude.ai/settings/usage. Disable this warning in /settings.";function formatResumeCommand(session){if(!process.stdout.isTTY||!session.isPersisted())return;let sessionFile=session.getSessionFile();if(!sessionFile||!fs2.existsSync(sessionFile))return;let args=[APP_NAME];return session.usesDefaultSessionDir()||args.push("--session-dir",quoteIfNeeded(session.getSessionDir())),args.push("--session",session.getSessionId()),args.join(" ")}function createInteractiveTui(options){let terminal=options.terminal??new ProcessTerminal;if(options.tuiMode==="fullscreen"){let styleSearchMatch=text=>theme.bg("searchMatchBg",theme.fg("searchMatchText",text));return new TuiAltScreen(terminal,options.showHardwareCursor,options.logDirectory,{searchMatchStyle:text=>theme.underline(styleSearchMatch(text)),searchCurrentMatchStyle:text=>theme.bold(theme.inverse(styleSearchMatch(text))),openUrl:openBrowser,onRightClickPaste:options.onRightClickPaste,copyOnSelect:options.fullscreenCopyOnSelect,wheelScrollLines:options.fullscreenWheelScrollLines??1,copySelection:async text=>{try{return await copyToClipboard(text),!0}catch(error){return error instanceof Error?error.message:String(error)}},labels:{searchTitle:` ${t("Find transcript")}`,searchNoMatches:`${t("No matches")} `,copied:t("Copied!"),copyFailed:t("Copy failed")}})}return new TuiMainScreen(terminal,options.showHardwareCursor,options.logDirectory)}function createInteractiveTuiReference(getTui){return new Proxy({},{get:(_target,property)=>{let tui=getTui(),value=Reflect.get(tui,property,tui);if(typeof value!="function")return value;let methodTui=tui,method=value;return(...args)=>{let currentTui=getTui();if(currentTui!==methodTui){let currentMethod=Reflect.get(currentTui,property,currentTui);if(typeof currentMethod!="function")throw new TypeError(t("TUI property {property} is not callable",{property:String(property)}));methodTui=currentTui,method=currentMethod}return Reflect.apply(method,methodTui,args)}},set:(_target,property,value)=>{let tui=getTui();return Reflect.set(tui,property,value,tui)},has:(_target,property)=>Reflect.has(getTui(),property),getPrototypeOf:()=>Reflect.getPrototypeOf(getTui())})}var ProviderFailoverTicker=class{intervalId;isOpen;requestRender;constructor(isOpen,requestRender){this.isOpen=isOpen,this.requestRender=requestRender}refresh(){if(this.isOpen()){this.intervalId===void 0&&(this.intervalId=setInterval(()=>{this.requestRender(),this.refresh()},1e3));return}this.dispose()}dispose(){this.intervalId!==void 0&&(clearInterval(this.intervalId),this.intervalId=void 0)}},InteractiveMode=class{runtimeHost;renderer;ui;mainScreenRenderState;loadedResourcesContainer;chatContainer;documentContainer;transcriptScrollView;fullscreenLayoutRoot;pendingMessagesContainer;statusContainer;defaultEditor;editor;autocompleteProvider;fdPath;editorContainer;activeSelectorToken;activeSelectorDispose;footer;failoverTicker;footerContainer;footerDataProvider;keybindings;version;isInitialized=!1;onInputCallback;pendingUserInputs=[];activeStatusIndicator=void 0;idleStatus=new IdleStatus;workingMessage=void 0;workingVisible=!0;workingIndicatorOptions=void 0;defaultWorkingMessage=t("Working...");defaultHiddenThinkingLabel=t("Thinking...");hiddenThinkingLabel=this.defaultHiddenThinkingLabel;lastSigintTime=0;lastEscapeTime=0;changelogMarkdown=void 0;startupNoticesShown=!1;anthropicSubscriptionWarningShown=!1;lastStatusSpacer=void 0;lastStatusText=void 0;managedToolStatusStarted=!1;streamingComponent=void 0;streamingMessage=void 0;pendingTools=new Map;activeToolRunGroup=void 0;toolOutputExpanded=!1;hideThinkingBlock=!1;outputPad=1;mermaidMarkdownTransformer=createMermaidMarkdownTransformer({getMode:()=>this.settingsManager.getMermaidRenderingMode(),theme});unsubscribe;signalCleanupHandlers=[];isBashMode=!1;bashComponent=void 0;pendingBashComponents=[];autoCompactionEscapeHandler;retryEscapeHandler;compactionQueuedMessages=[];shutdownRequested=!1;isShuttingDown=!1;dialogSelector=void 0;dialogInput=void 0;dialogSelectorReplaced=void 0;dialogInputReplaced=void 0;dialogEditor=void 0;widgetContainerAbove;widgetContainerBelow;headerContainer;builtInHeader=void 0;options;onRightClickPaste=()=>{this.handleRightClickPaste()};themeController;get session(){return this.runtimeHost.session}get settingsManager(){return this.options.settingsManager}get facade(){return createCodingAgentFacade(this.session)}get runtimeFacade(){return createCodingAgentRuntimeFacade(this.runtimeHost)}constructor(runtimeHost,options){this.options={...options},this.runtimeHost=runtimeHost,setI18nLanguage(this.settingsManager.getUiLanguage()),setCapabilityOverrides(this.settingsManager.getTerminalCapabilityOverrides());let tuiMode=options.tuiMode??this.settingsManager.getTuiMode();this.options.tuiMode=tuiMode,this.runtimeFacade.setBeforeSessionInvalidate(()=>{this.resetDialogUI()}),this.runtimeFacade.setRebindSession(async()=>{await this.rebindCurrentSession({renderBeforeBind:!0}),await this.themeController.applyFromSettings()}),this.version=VERSION,this.renderer=createInteractiveTui({tuiMode,showHardwareCursor:this.settingsManager.getShowHardwareCursor(),logDirectory:getAgentDir(),onRightClickPaste:this.onRightClickPaste,fullscreenCopyOnSelect:this.settingsManager.getFullscreenCopyOnSelect(),fullscreenWheelScrollLines:this.settingsManager.getFullscreenWheelScrollLines()}),this.ui=createInteractiveTuiReference(()=>this.renderer),this.ui.setClearOnShrink(this.settingsManager.getClearOnShrink()),this.headerContainer=new Container,this.loadedResourcesContainer=new Container,this.chatContainer=new Container,this.documentContainer=new Container,this.documentContainer.addChild(this.headerContainer),this.documentContainer.addChild(this.loadedResourcesContainer),this.documentContainer.addChild(this.chatContainer),this.pendingMessagesContainer=new Container,this.statusContainer=new Container,this.widgetContainerAbove=new Container,this.widgetContainerAbove.addChild(new Spacer(1)),this.widgetContainerBelow=new Container,this.keybindings=KeybindingsManager2.create(),setKeybindings(this.keybindings);let editorPaddingX=this.settingsManager.getEditorPaddingX(),autocompleteMaxVisible=this.settingsManager.getAutocompleteMaxVisible();this.defaultEditor=new CustomEditor(this.ui,getEditorTheme(),this.keybindings,{paddingX:editorPaddingX,autocompleteMaxVisible}),this.editor=this.defaultEditor,this.editorContainer=new Container,this.editorContainer.addChild(this.editor),this.footerDataProvider=new FooterDataProvider(this.facade.getCwd()),this.footer=new FooterComponent(this.session,this.footerDataProvider),this.footerContainer=new Container,this.footerContainer.addChild(this.footer),this.failoverTicker=new ProviderFailoverTicker(()=>this.footer.isProviderFailoverOpen(),()=>this.ui.requestRender()),this.hideThinkingBlock=this.settingsManager.getHideThinkingBlock(),this.outputPad=this.settingsManager.getOutputPad(),setRegisteredThemes(buildRegisteredThemes(this.facade.getThemes().themes)),this.themeController=new InteractiveThemeController(this.ui,{getSettingsManager:()=>this.settingsManager,showError:message=>this.showError(message),onChanged:()=>this.updateEditorBorderColor(),initialThemeSetting:options.initialThemeSetting})}getAutocompleteSourceTag(sourceInfo){if(!sourceInfo)return;let scopePrefix=sourceInfo.scope==="user"?"u":sourceInfo.scope==="project"?"p":"t",source=sourceInfo.source.trim();if(source==="auto"||source==="local"||source==="cli")return scopePrefix;if(source.startsWith("npm:"))return`${scopePrefix}:${source}`;let gitSource=parseGitUrl(source);if(gitSource){let ref=gitSource.ref?`@${gitSource.ref}`:"";return`${scopePrefix}:git:${gitSource.host}/${gitSource.path}${ref}`}return scopePrefix}prefixAutocompleteDescription(description,sourceInfo){let sourceTag=this.getAutocompleteSourceTag(sourceInfo);return sourceTag?description?`[${sourceTag}] ${description}`:`[${sourceTag}]`:description}createBaseAutocompleteProvider(){let slashCommands=BUILTIN_SLASH_COMMANDS.map(command=>({name:command.name,description:command.description,...command.argumentHint&&{argumentHint:command.argumentHint}})),modelCommand=slashCommands.find(command=>command.name==="model");modelCommand&&(modelCommand.getArgumentCompletions=prefix=>{let models=this.facade.getScopedModels().length>0?this.facade.getScopedModels().map(s=>s.model):this.facade.getAvailableModels();if(models.length===0)return null;let items=models.map(m=>({id:m.id,provider:m.provider,name:m.name,label:`${m.provider}/${m.id}`}));return createFuzzyAutocompleteItems(items,prefix,getModelSearchText,item=>({value:item.label,label:item.id,description:item.provider}))});let thinkingCommand=slashCommands.find(command=>command.name==="thinking");thinkingCommand&&(thinkingCommand.getArgumentCompletions=prefix=>createFuzzyAutocompleteItems(this.facade.getAvailableThinkingLevels(),prefix,level=>level,level=>({value:level,label:level})));let suiteCommand=slashCommands.find(command=>command.name==="suite");suiteCommand&&(suiteCommand.getArgumentCompletions=prefix=>createFuzzyAutocompleteItems(listSuiteIds(getAgentDir()),prefix,id=>id,id=>({value:id,label:id})));let loginCommand=slashCommands.find(command=>command.name==="login");loginCommand&&(loginCommand.getArgumentCompletions=prefix=>{let providers=getLoginProviderCompletionOptions(this.getLoginProviderOptions());return createFuzzyAutocompleteItems(providers,prefix,getLoginProviderSearchText,provider=>({value:provider.id,label:provider.id,description:formatLoginProviderCompletionDescription(provider)}))});let capabilityRegistrations=this.session.getCapabilityRuntime().listCommands(),capabilityCommandNames=new Set(capabilityRegistrations.map(({definition})=>definition.name)),templateCommands=this.facade.getPromptTemplates().filter(cmd=>!capabilityCommandNames.has(cmd.name)).map(cmd=>({name:cmd.name,description:this.prefixAutocompleteDescription(cmd.description,cmd.sourceInfo),...cmd.argumentHint&&{argumentHint:cmd.argumentHint}})),builtinCommandNames=new Set(slashCommands.map(c=>c.name)),templateCommandNames=new Set(this.facade.getPromptTemplates().map(cmd=>cmd.name)),resourceSkillCommandNames=new Set(this.facade.getSkills().skills.map(skill=>`skill:${skill.name}`)),capabilityCommands=filterCapabilityCommandsForCompletions(capabilityRegistrations.map(({definition})=>({name:definition.name,description:definition.description,...definition.argumentHint&&{argumentHint:definition.argumentHint}})),[builtinCommandNames,templateCommandNames,[...resourceSkillCommandNames]]),skillCommandList=[];for(let skill of this.facade.getSkills().skills){let commandName=`skill:${skill.name}`;capabilityCommandNames.has(commandName)||skillCommandList.push({name:commandName,description:this.prefixAutocompleteDescription(skill.description,skill.sourceInfo)})}return new CombinedAutocompleteProvider([...slashCommands,...templateCommands,...capabilityCommands,...skillCommandList],this.facade.getCwd(),this.fdPath)}setupAutocompleteProvider(){let provider=this.createBaseAutocompleteProvider();this.autocompleteProvider=provider,this.defaultEditor.setAutocompleteProvider(provider),this.editor!==this.defaultEditor&&this.editor.setAutocompleteProvider?.(provider)}showStartupNoticesIfNeeded(){if(!this.startupNoticesShown&&(this.startupNoticesShown=!0,!!this.changelogMarkdown)){if(this.chatContainer.children.length>0&&this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new DynamicBorder),this.settingsManager.getCollapseChangelog()){let versionMatch=this.changelogMarkdown.match(/##\s+\[?(\d+\.\d+\.\d+)\]?/),latestVersion=versionMatch?versionMatch[1]:this.version,condensedText=t("Updated to v{version}. Use {command} to view full changelog.",{version:latestVersion,command:theme.bold("/changelog")});this.chatContainer.addChild(new Text(condensedText,1,0))}else this.chatContainer.addChild(new Text(theme.bold(theme.fg("accent",t("What's New"))),1,0)),this.chatContainer.addChild(new Spacer(1)),this.chatContainer.addChild(new Markdown(this.changelogMarkdown.trim(),1,0,this.getMarkdownThemeWithSettings())),this.chatContainer.addChild(new Spacer(1));this.chatContainer.addChild(new DynamicBorder)}}mountInteractiveTui(tui,components){for(let component of components)tui.addChild(component);if(isViewportTUI(tui)){if(!this.fullscreenLayoutRoot)throw new Error(t("Fullscreen layout is not initialized"));tui.setLayoutRoot(this.fullscreenLayoutRoot)}}stopInteractiveTui(fullscreenExitOutput){if(this.renderer.mode==="fullscreen"&&fullscreenExitOutput==="transcript"){for(;this.renderer.hasOverlayEntries;)this.renderer.hideOverlay();this.switchTuiMode("regular",!1,!1),this.renderer.renderNow()}this.ui.stop({preserveScreen:this.renderer.mode==="fullscreen"})}switchTuiMode(mode,restoreProgress=!0,startRenderer=!0){let previousUi=this.renderer;if(mode===previousUi.mode)return!0;if(previousUi.hasOverlayEntries)return!1;let components=[...previousUi.children],focus=previousUi.getFocusedComponent(),terminal=previousUi.terminal,showHardwareCursor=previousUi.getShowHardwareCursor(),clearOnShrink=previousUi.getClearOnShrink(),onDebug=previousUi.onDebug;previousUi instanceof TuiMainScreen&&(this.mainScreenRenderState=previousUi.captureRenderState()),previousUi.stop({preserveScreen:!0}),previousUi.setFocus(null),previousUi.clear(),isViewportTUI(previousUi)&&previousUi.setLayoutRoot(void 0);let nextUi=createInteractiveTui({tuiMode:mode,showHardwareCursor,logDirectory:getAgentDir(),terminal,onRightClickPaste:this.onRightClickPaste,fullscreenCopyOnSelect:this.settingsManager.getFullscreenCopyOnSelect(),fullscreenWheelScrollLines:this.settingsManager.getFullscreenWheelScrollLines()});return nextUi.setClearOnShrink(clearOnShrink),nextUi.onDebug=onDebug,nextUi instanceof TuiMainScreen&&this.mainScreenRenderState&&nextUi.restoreRenderState(this.mainScreenRenderState),this.renderer=nextUi,this.options.tuiMode=mode,this.mountInteractiveTui(nextUi,components),nextUi.invalidate(),nextUi.setFocus(focus),startRenderer&&(nextUi.start(),this.themeController.rebindTui(),restoreProgress&&this.settingsManager.getShowTerminalProgress()&&(this.facade.isStreaming()||this.facade.isCompacting())&&terminal.setProgress(!0)),!0}async init(){if(this.isInitialized)return;if(this.registerSignalHandlers(),this.changelogMarkdown=this.getChangelogForDisplay(),this.facade.getScopedModels().length>0&&(this.options.verbose||!this.settingsManager.getQuietStartup())){let modelList=this.facade.getScopedModels().map(sm=>{let thinkingStr=sm.thinkingLevel?`:${sm.thinkingLevel}`:"";return`${sm.model.id}${thinkingStr}`}).join(", "),cycleKeys=this.keybindings.getKeys("app.model.cycleForward"),cycleHint=cycleKeys.length>0?theme.fg("muted",` ${t("({key} to cycle)",{key:formatKeyText(cycleKeys.join("/"),{capitalize:!0})})}`):"";console.log(theme.fg("dim",t("Model scope: {models}{hint}",{models:modelList,hint:cycleHint})))}this.transcriptScrollView=new ScrollView(this.documentContainer,{follow:"end",primary:!0,overscroll:"chain",scrollbar:this.settingsManager.getFullscreenScrollbar(),scrollbarStyle:text=>theme.bg("scrollbarThumb",text)});let dock=new VStack([{component:this.pendingMessagesContainer,shrink:1,minSize:0},{component:this.statusContainer,shrink:1,minSize:0},{component:this.widgetContainerAbove,shrink:1,minSize:0},{component:this.editorContainer,shrink:1,minSize:3},{component:this.widgetContainerBelow,shrink:1,minSize:0},{component:this.footerContainer,shrink:1,minSize:1}]);if(this.fullscreenLayoutRoot=new VStack([{component:this.transcriptScrollView,basis:0,grow:1,shrink:1,minSize:1},{component:dock,basis:"auto",grow:0,shrink:1,minSize:1}]),this.mountInteractiveTui(this.renderer,[this.documentContainer,this.pendingMessagesContainer,this.statusContainer,this.widgetContainerAbove,this.editorContainer,this.widgetContainerBelow,this.footerContainer]),this.defaultEditor.onAction("app.clear",()=>this.handleCtrlC()),this.defaultEditor.onCtrlD=()=>this.handleCtrlD(),this.defaultEditor.onSubmit=text=>this.handleStartupSubmit(text),this.ui.setFocus(this.editor),this.ui.start(),this.isInitialized=!0,await this.themeController.applyFromSettings(),this.options.verbose||!this.settingsManager.getQuietStartup()){let logo=theme.bold(theme.fg("accent",APP_NAME))+theme.fg("dim",` v${this.version}`),hint=(keybinding,description)=>keyHint(keybinding,description),expandedInstructions=[hint("app.interrupt",t("to interrupt")),hint("app.clear",t("to clear")),rawKeyHint(t("{key} twice",{key:keyText("app.clear")}),t("to exit")),hint("app.exit",t("to exit (empty)")),hint("app.suspend",t("to suspend")),keyHint("tui.editor.deleteToLineEnd",t("to delete to end")),hint("app.tools.expand",t("to expand tools")),hint("app.thinking.toggle",t("to expand thinking")),hint("app.editor.external",t("for external editor")),rawKeyHint("/",t("for commands")),rawKeyHint("!",t("to run bash")),rawKeyHint("!!",t("to run bash (no context)")),hint("app.clipboard.pasteImage",t("to paste image (with text fallback)")),rawKeyHint("drop files",t("to attach"))].join(`
|
|
738
738
|
`),compactInstructions=[hint("app.interrupt",t("interrupt")),rawKeyHint(`${keyText("app.clear")}/${keyText("app.exit")}`,t("clear/exit")),rawKeyHint("/",t("commands")),rawKeyHint("!",t("bash")),hint("app.tools.expand",t("more"))].join(theme.fg("muted"," \xB7 ")),compactOnboarding=theme.fg("dim",t("Press {key} to show full startup help and loaded resources.",{key:keyText("app.tools.expand")})),onboarding=theme.fg("dim",t("Agent Forge can explain its own features and look up its docs. Ask it how to use or extend Agent Forge."));this.builtInHeader=new ExpandableText(()=>`${logo}
|
|
739
739
|
${compactInstructions}
|
|
740
740
|
${compactOnboarding}
|
|
@@ -764,9 +764,9 @@ ${packageLines}`,1,0)),this.chatContainer.addChild(new DynamicBorder(text=>theme
|
|
|
764
764
|
`)}await rebindSession();let autoContinue=mode!=="json",promptWithAutoContinue=async(text,images)=>{let seen=facade.getState().messages.length;if(images===void 0?await facade.prompt(text):await facade.prompt(text,{images}),!autoContinue)return;let messagesThisTurn=facade.getState().messages.slice(seen);if(messagesThisTurn.length===0||messagesThisTurn.some(m=>m.role==="assistant"&&m.stopReason==="aborted"))return;let lastAssistant=[...messagesThisTurn].reverse().find(m=>m.role==="assistant");(lastAssistant===void 0?"":typeof lastAssistant.content=="string"?lastAssistant.content:lastAssistant.content.filter(part=>part.type==="text").map(part=>part.text).join("")).trim().length>0||(currentTraceId=nextTraceId(),await facade.prompt("Your previous reply was empty. Continue the user's task now with tool calls and summarise the result."))};initialMessage&&(currentTraceId=nextTraceId(),await promptWithAutoContinue(initialMessage,initialImages));for(let message of messages)currentTraceId=nextTraceId(),await promptWithAutoContinue(message);if(mode==="text"){for(let result of commandResults){let links=result.links?.map(link=>t("{label}: {url}",{label:link.label,url:link.url}))??[],message=[result.message,...links].filter(Boolean).join(`
|
|
765
765
|
`);result.status==="error"?(console.error(message),exitCode=1):writeRawStdout(`${message}
|
|
766
766
|
`)}let state=facade.getState(),lastMessage=state.messages[state.messages.length-1];if(lastMessage?.role==="assistant"){let assistantMsg=lastMessage;if(assistantMsg.stopReason==="error"||assistantMsg.stopReason==="aborted")console.error(assistantMsg.errorMessage||t("Request {stopReason}",{stopReason:assistantMsg.stopReason})),exitCode=1;else for(let content of assistantMsg.content)content.type==="text"&&writeRawStdout(`${content.text}
|
|
767
|
-
`)}}return exitCode}catch(error){return console.error(error instanceof Error?error.message:String(error)),1}finally{for(let cleanup of signalCleanupHandlers)cleanup();await disposeRuntime(),await flushRawStdout()}}import{spawn as
|
|
767
|
+
`)}}return exitCode}catch(error){return console.error(error instanceof Error?error.message:String(error)),1}finally{for(let cleanup of signalCleanupHandlers)cleanup();await disposeRuntime(),await flushRawStdout()}}import{spawn as spawn6}from"node:child_process";import{StringDecoder as StringDecoder3}from"node:string_decoder";function serializeJsonLine(value){return`${JSON.stringify(value)}
|
|
768
768
|
`}function attachJsonlLineReader(stream,onLine){let decoder=new StringDecoder3("utf8"),buffer="",emitLine=line=>{onLine(line.endsWith("\r")?line.slice(0,-1):line)},onData=chunk=>{for(buffer+=typeof chunk=="string"?chunk:decoder.write(chunk);;){let newlineIndex=buffer.indexOf(`
|
|
769
|
-
`);if(newlineIndex===-1)return;emitLine(buffer.slice(0,newlineIndex)),buffer=buffer.slice(newlineIndex+1)}},onEnd=()=>{buffer+=decoder.end(),buffer.length>0&&(emitLine(buffer),buffer="")};return stream.on("data",onData),stream.on("end",onEnd),()=>{stream.off("data",onData),stream.off("end",onEnd)}}var RpcClient=class{process=null;stopReadingStdout=null;eventListeners=[];pendingRequests=new Map;requestId=0;stderr="";exitError=null;options;constructor(options={}){this.options=options}async start(){if(this.process)throw new Error(t("Client already started"));this.exitError=null;let cliPath=this.options.cliPath??"dist/cli.js",args=["--mode","rpc"];this.options.provider&&args.push("--provider",this.options.provider),this.options.model&&args.push("--model",this.options.model),this.options.args&&args.push(...this.options.args);let childProcess=spawn5("node",[cliPath,...args],{cwd:this.options.cwd,env:{...process.env,...this.options.env},stdio:["pipe","pipe","pipe"]});if(this.process=childProcess,childProcess.stderr?.on("data",data=>{this.stderr+=data.toString(),process.stderr.write(data)}),childProcess.once("exit",(code,signal)=>{if(this.process!==childProcess)return;let error=this.createProcessExitError(code,signal);this.exitError=error,this.rejectPendingRequests(error)}),childProcess.once("error",error=>{if(this.process!==childProcess)return;let processError=new Error(`Agent process error: ${error.message}. Stderr: ${this.stderr}`);this.exitError=processError,this.rejectPendingRequests(processError)}),childProcess.stdin?.on("error",error=>{if(this.process!==childProcess)return;let stdinError=this.exitError??new Error(`Agent process stdin error: ${error.message}. Stderr: ${this.stderr}`);this.exitError=stdinError,this.rejectPendingRequests(stdinError)}),this.stopReadingStdout=attachJsonlLineReader(childProcess.stdout,line=>{this.handleLine(line)}),await new Promise(resolve22=>setTimeout(resolve22,100)),this.process.exitCode!==null){let error=this.exitError??this.createProcessExitError(this.process.exitCode,this.process.signalCode);throw this.exitError=error,error}}async stop(){this.process&&(this.stopReadingStdout?.(),this.stopReadingStdout=null,this.process.kill("SIGTERM"),await new Promise(resolve22=>{let timeout=setTimeout(()=>{this.process?.kill("SIGKILL"),resolve22()},1e3);this.process?.on("exit",()=>{clearTimeout(timeout),resolve22()})}),this.process=null,this.pendingRequests.clear())}onEvent(listener){return this.eventListeners.push(listener),()=>{let index=this.eventListeners.indexOf(listener);index!==-1&&this.eventListeners.splice(index,1)}}getStderr(){return this.stderr}async prompt(message,images,streamingBehavior){let response2=await this.send({type:"prompt",message,images,streamingBehavior});return this.getData(response2)?.disposition}async steer(message,images){let response2=await this.send({type:"steer",message,images});return this.getData(response2)?.disposition}async followUp(message,images){let response2=await this.send({type:"follow_up",message,images});return this.getData(response2)?.disposition}async abort(){await this.send({type:"abort"})}async clearQueue(){let response2=await this.send({type:"clear_queue"});return this.getData(response2)}async newSession(parentSession){let response2=await this.send({type:"new_session",parentSession});return this.getData(response2)}async getState(){let response2=await this.send({type:"get_state"});return this.getData(response2)}async setModel(provider,modelId){let response2=await this.send({type:"set_model",provider,modelId});return this.getData(response2)}async cycleModel(){let response2=await this.send({type:"cycle_model"});return this.getData(response2)}async getAvailableModels(){let response2=await this.send({type:"get_available_models"});return this.getData(response2).models}async setThinkingLevel(level){await this.send({type:"set_thinking_level",level})}async cycleThinkingLevel(){let response2=await this.send({type:"cycle_thinking_level"});return this.getData(response2)}async getAvailableThinkingLevels(){let response2=await this.send({type:"get_available_thinking_levels"});return this.getData(response2).levels}async setSteeringMode(mode){await this.send({type:"set_steering_mode",mode})}async setFollowUpMode(mode){await this.send({type:"set_follow_up_mode",mode})}async compact(customInstructions){let response2=await this.send({type:"compact",customInstructions});return this.getData(response2)}async abortRetry(){await this.send({type:"abort_retry"})}async bash(command){let response2=await this.send({type:"bash",command});return this.getData(response2)}async abortBash(){await this.send({type:"abort_bash"})}async getSessionStats(){let response2=await this.send({type:"get_session_stats"});return this.getData(response2)}async exportHtml(outputPath){let response2=await this.send({type:"export_html",outputPath});return this.getData(response2)}async switchSession(sessionPath){let response2=await this.send({type:"switch_session",sessionPath});return this.getData(response2)}async fork(entryId){let response2=await this.send({type:"fork",entryId});return this.getData(response2)}async clone(){let response2=await this.send({type:"clone"});return this.getData(response2)}async getForkMessages(){let response2=await this.send({type:"get_fork_messages"});return this.getData(response2).messages}async getEntries(since){let response2=await this.send({type:"get_entries",since});return this.getData(response2)}async getTree(){let response2=await this.send({type:"get_tree"});return this.getData(response2)}async getLastAssistantText(){let response2=await this.send({type:"get_last_assistant_text"});return this.getData(response2).text}async setSessionName(name){await this.send({type:"set_session_name",name})}async getMessages(){let response2=await this.send({type:"get_messages"});return this.getData(response2).messages}async getCommands(){let response2=await this.send({type:"get_commands"});return this.getData(response2).commands}waitForIdle(timeout=6e4){return new Promise((resolve22,reject2)=>{let timer=setTimeout(()=>{unsubscribe(),reject2(new Error(`Timeout waiting for agent to become idle. Stderr: ${this.stderr}`))},timeout),unsubscribe=this.onEvent(event=>{event.type==="agent_settled"&&(clearTimeout(timer),unsubscribe(),resolve22())})})}collectEvents(timeout=6e4){return new Promise((resolve22,reject2)=>{let events=[],timer=setTimeout(()=>{unsubscribe(),reject2(new Error(`Timeout collecting events. Stderr: ${this.stderr}`))},timeout),unsubscribe=this.onEvent(event=>{events.push(event),event.type==="agent_settled"&&(clearTimeout(timer),unsubscribe(),resolve22(events))})})}async promptAndWait(message,images,timeout=6e4){let events=[],finish,fail,settled=new Promise((resolve22,reject2)=>{finish=resolve22,fail=reject2}),timer=setTimeout(()=>{fail?.(new Error(`Timeout collecting events. Stderr: ${this.stderr}`))},timeout),unsubscribe=this.onEvent(event=>{events.push(event),event.type==="agent_settled"&&finish?.()});try{await this.prompt(message,images)==="handled"&&finish?.(),await settled}finally{clearTimeout(timer),unsubscribe()}return events}handleLine(line){try{let data=JSON.parse(line);if(data.type==="response"&&data.id&&this.pendingRequests.has(data.id)){let pending=this.pendingRequests.get(data.id);this.pendingRequests.delete(data.id),pending.resolve(data);return}for(let listener of[...this.eventListeners])listener(data)}catch{}}createProcessExitError(code,signal){return new Error(`Agent process exited (code=${code} signal=${signal}). Stderr: ${this.stderr}`)}rejectPendingRequests(error){for(let pending of this.pendingRequests.values())pending.reject(error);this.pendingRequests.clear()}async send(command){let childProcess=this.process,stdin=childProcess?.stdin;if(!childProcess||!stdin)throw new Error(t("Client not started"));if(this.exitError)throw this.exitError;if(childProcess.exitCode!==null){let error=this.createProcessExitError(childProcess.exitCode,childProcess.signalCode);throw this.exitError=error,error}if(stdin.destroyed||!stdin.writable){let error=new Error(`Agent process stdin is not writable. Stderr: ${this.stderr}`);throw this.exitError=error,error}let id=`req_${++this.requestId}`,fullCommand={...command,id};return new Promise((resolve22,reject2)=>{let timeout=setTimeout(()=>{this.pendingRequests.delete(id),reject2(new Error(`Timeout waiting for response to ${command.type}. Stderr: ${this.stderr}`))},3e4);this.pendingRequests.set(id,{resolve:response2=>{clearTimeout(timeout),resolve22(response2)},reject:error=>{clearTimeout(timeout),reject2(error)}});try{stdin.write(serializeJsonLine(fullCommand))}catch(error){let writeError=error instanceof Error?error:new Error(String(error)),pending=this.pendingRequests.get(id);this.pendingRequests.delete(id),pending?.reject(writeError)}})}getData(response2){if(!response2.success){let errorResponse=response2;throw new Error(errorResponse.error)}return response2.data}};import*as crypto2 from"node:crypto";function mapRpcDialogResponseToOutcome(response2){return"cancelled"in response2&&response2.cancelled?{status:"cancelled"}:"confirmed"in response2?{status:"answered",value:response2.confirmed}:"value"in response2?{status:"answered",value:response2.value}:{status:"cancelled"}}async function runRpcMode(runtimeHost,options={}){takeOverStdout();let session=runtimeHost.session,facade=createCodingAgentFacade(session),runtimeFacade=createCodingAgentRuntimeFacade(runtimeHost),unsubscribe,unsubscribeBackpressure,output=obj=>{writeRawStdout(serializeJsonLine(obj))},success=(id,command,data)=>data===void 0?{id,type:"response",command,success:!0}:{id,type:"response",command,success:!0,data},error=(id,command,message)=>({id,type:"response",command,success:!1,error:message}),pendingExtensionRequests=new Map,shuttingDown=!1,signalCleanupHandlers=[];function createDialogPromise(opts,defaultValue,request,parseResponse){if(opts?.signal?.aborted)return Promise.resolve(defaultValue);let id=crypto2.randomUUID();return new Promise((resolve22,reject2)=>{let timeoutId,cleanup=()=>{timeoutId&&clearTimeout(timeoutId),opts?.signal?.removeEventListener("abort",onAbort),pendingExtensionRequests.delete(id)},onAbort=()=>{cleanup(),resolve22(defaultValue)};opts?.signal?.addEventListener("abort",onAbort,{once:!0}),opts?.timeout&&(timeoutId=setTimeout(()=>{cleanup(),resolve22(defaultValue)},opts.timeout)),pendingExtensionRequests.set(id,{resolve:response2=>{cleanup(),resolve22(parseResponse(response2))},reject:reject2}),output({type:"extension_ui_request",id,...request})})}let emitInteractionNotify=request=>{output({type:"extension_ui_request",id:crypto2.randomUUID(),method:"notify",message:request.message,notifyType:request.level??"info"})},createInteractionHostV12=()=>({notify:emitInteractionNotify,prompt:(request,context)=>{let opts={signal:context.signal};switch(request.kind){case"notify":return emitInteractionNotify(request),Promise.resolve({status:"delivered"});case"select":return createDialogPromise(opts,{status:"cancelled"},{method:"select",title:request.title,options:[...request.options]},mapRpcDialogResponseToOutcome);case"confirm":return createDialogPromise(opts,{status:"cancelled"},{method:"confirm",title:request.title,message:request.message},mapRpcDialogResponseToOutcome);case"input":return createDialogPromise(opts,{status:"cancelled"},{method:"input",title:request.title,placeholder:request.placeholder},mapRpcDialogResponseToOutcome)}}});options.interactionHostSlot?.setTarget(createInteractionHostV12()),runtimeFacade.setRebindSession(async()=>{await rebindSession()});let rebindSession=async()=>{session=runtimeHost.session,facade=createCodingAgentFacade(session),await session.startSession(),kickMemoryModelPreheat(session),unsubscribe?.(),unsubscribeBackpressure?.(),unsubscribe=facade.subscribe(event=>{output(toJsonEvent(event))}),unsubscribeBackpressure=facade.subscribeRawEventGate(async()=>{await waitForRawStdoutBackpressure()})},registerSignalHandlers2=()=>{let signals=["SIGTERM"];process.platform!=="win32"&&signals.push("SIGHUP");for(let signal of signals){let handler=()=>{killTrackedDetachedChildren(),shutdown2(signal==="SIGHUP"?129:143,signal)};process.on(signal,handler),signalCleanupHandlers.push(()=>process.off(signal,handler))}};await rebindSession(),registerSignalHandlers2();let handleCommand=async command=>{let id=command.id;switch(command.type){case"prompt":{let preflightSucceeded=!1;facade.prompt(command.message,{images:command.images,streamingBehavior:command.streamingBehavior,source:"rpc",preflightResult:disposition=>{preflightSucceeded=!0,output(success(id,"prompt",{disposition}))}}).catch(e=>{preflightSucceeded||output(error(id,"prompt",e.message))});return}case"steer":{let disposition=await facade.steer(command.message,command.images,{source:"rpc"});return success(id,"steer",{disposition})}case"follow_up":{let disposition=await facade.followUp(command.message,command.images,{source:"rpc"});return success(id,"follow_up",{disposition})}case"abort":return await facade.abort(),success(id,"abort");case"clear_queue":return success(id,"clear_queue",facade.clearQueue());case"new_session":{let options2=command.parentSession?{parentSession:command.parentSession}:void 0,result=await runtimeFacade.newSession(options2);return result.cancelled||await rebindSession(),success(id,"new_session",result)}case"get_state":{let suiteId=readSessionSuiteId(facade.getEntries()),state={model:facade.getModel(),thinkingLevel:facade.getThinkingLevel(),isStreaming:facade.isStreaming(),isCompacting:facade.isCompacting(),steeringMode:facade.getSteeringMode(),followUpMode:facade.getFollowUpMode(),sessionFile:facade.getSessionFile(),sessionId:facade.getSessionId(),sessionName:facade.getSessionName(),...suiteId===void 0?{}:{suiteId},messageCount:facade.getState().messages.length,pendingMessageCount:facade.getPendingMessageCount()};return success(id,"get_state",state)}case"set_model":{let model=facade.getAvailableModels().find(m=>m.provider===command.provider&&m.id===command.modelId);return model?(await facade.setModel(model),success(id,"set_model",model)):error(id,"set_model",`Model not found: ${command.provider}/${command.modelId}`)}case"cycle_model":{let result=await facade.cycleModel();return result?success(id,"cycle_model",result):success(id,"cycle_model",null)}case"get_available_models":{let models=facade.getAvailableModels();return success(id,"get_available_models",{models})}case"set_thinking_level":return facade.setThinkingLevel(command.level),success(id,"set_thinking_level");case"cycle_thinking_level":{let level=facade.cycleThinkingLevel();return level?success(id,"cycle_thinking_level",{level}):success(id,"cycle_thinking_level",null)}case"get_available_thinking_levels":{let levels=facade.getAvailableThinkingLevels();return success(id,"get_available_thinking_levels",{levels})}case"set_steering_mode":return facade.setSteeringMode(command.mode),success(id,"set_steering_mode");case"set_follow_up_mode":return facade.setFollowUpMode(command.mode),success(id,"set_follow_up_mode");case"compact":{let result=await facade.compact(command.customInstructions);return success(id,"compact",result)}case"abort_retry":return facade.abortRetry(),success(id,"abort_retry");case"bash":{facade.emitUserBash(command.excludeFromContext??!1);let result=await facade.executeBash(command.command,void 0,{excludeFromContext:command.excludeFromContext,id});return success(id,"bash",result)}case"abort_bash":return facade.abortBash(),success(id,"abort_bash");case"get_session_stats":{let stats=facade.getSessionStats();return success(id,"get_session_stats",stats)}case"export_html":{let path8=await facade.exportToHtml(command.outputPath);return success(id,"export_html",{path:path8})}case"switch_session":{let result=await runtimeFacade.switchSession(command.sessionPath);return result.cancelled||await rebindSession(),success(id,"switch_session",result)}case"fork":{let result=await runtimeFacade.fork(command.entryId);return result.cancelled||await rebindSession(),success(id,"fork",{text:result.selectedText,cancelled:result.cancelled})}case"clone":{let leafId=facade.getLeafId();if(!leafId)return error(id,"clone","Cannot clone session: no current entry selected");let result=await runtimeFacade.fork(leafId,{position:"at"});return result.cancelled||await rebindSession(),success(id,"clone",{cancelled:result.cancelled})}case"get_fork_messages":{let messages=facade.getUserMessagesForForking();return success(id,"get_fork_messages",{messages})}case"get_entries":{let entries=facade.getEntries();if(command.since!==void 0){let sinceIndex=entries.findIndex(e=>e.id===command.since);if(sinceIndex===-1)return error(id,"get_entries",`Entry not found: ${command.since}`);entries=entries.slice(sinceIndex+1)}return success(id,"get_entries",{entries,leafId:facade.getLeafId()})}case"get_tree":return success(id,"get_tree",{tree:facade.getTree(),leafId:facade.getLeafId()});case"get_last_assistant_text":{let text=facade.getLastAssistantText();return success(id,"get_last_assistant_text",{text})}case"set_session_name":{let name=command.name.trim();return name?(facade.setSessionName(name),success(id,"set_session_name")):error(id,"set_session_name","Session name cannot be empty")}case"get_messages":return success(id,"get_messages",{messages:facade.getState().messages});case"get_metrics":{let snapshot2=options.getMetrics?.(command.windowTurns===void 0?void 0:{windowTurns:command.windowTurns});return snapshot2?success(id,"get_metrics",snapshot2):error(id,"get_metrics","Metrics are not available: the observability plugin is not mounted in this session")}case"get_commands":{let commands=[];for(let template of facade.getPromptTemplates())commands.push({name:template.name,description:template.description,source:"prompt",sourceInfo:template.sourceInfo});for(let skill of facade.getSkills().skills)commands.push({name:`skill:${skill.name}`,description:skill.description,source:"skill",sourceInfo:skill.sourceInfo});let capabilityRuntime=session.getCapabilityRuntime();for(let{definition,source}of capabilityRuntime.listCommands())commands.some(command2=>command2.name===definition.name)||commands.push({name:definition.name,description:definition.description,source:"capability",sourceInfo:createSyntheticSourceInfo(`<plugin:${source}:${definition.name}>`,{source})});return success(id,"get_commands",{commands})}default:{let unknownCommand=command;if(options.capabilities?.hasRpcMethod(unknownCommand.type)){let data=await options.capabilities.dispatchRpc(unknownCommand.type,command);return{id,type:"response",command:unknownCommand.type,success:!0,data}}return error(id,unknownCommand.type,`Unknown command: ${unknownCommand.type}`)}}},detachInput=()=>{};async function shutdown2(exitCode=0,signal){shuttingDown&&process.exit(exitCode),shuttingDown=!0;for(let cleanup of signalCleanupHandlers)cleanup();unsubscribe?.(),unsubscribeBackpressure?.(),await runtimeHost.dispose(),detachInput(),process.stdin.pause(),signal!=="SIGTERM"&&await flushRawStdout(),process.exit(exitCode)}let handleInputLine=async line=>{let parsed;try{parsed=JSON.parse(line)}catch(parseError){output(error(void 0,"parse",`Failed to parse command: ${parseError instanceof Error?parseError.message:String(parseError)}`)),await waitForRawStdoutBackpressure();return}if(typeof parsed=="object"&&parsed!==null&&"type"in parsed&&parsed.type==="extension_ui_response"){let response2=parsed,pending=pendingExtensionRequests.get(response2.id);pending&&(pendingExtensionRequests.delete(response2.id),pending.resolve(response2));return}let command=parsed;try{let response2=await handleCommand(command);response2&&(output(response2),await waitForRawStdoutBackpressure())}catch(commandError){output(error(command.id,command.type,commandError instanceof Error?commandError.message:String(commandError))),await waitForRawStdoutBackpressure()}},onInputEnd=()=>{shutdown2()};return process.stdin.on("end",onInputEnd),detachInput=(()=>{let detachJsonl=attachJsonlLineReader(process.stdin,line=>{handleInputLine(line)});return()=>{detachJsonl(),process.stdin.off("end",onInputEnd)}})(),new Promise(()=>{})}var MAX_PLUGIN_ENTRIES_V1=128,MAX_DISPLAY_CHARS_V1=256,MAX_DIAGNOSTIC_CODES_V1=8;function safeDisplay(value){return value.replace(/\u001b\[[0-?]*[ -/]*[@-~]/gu,"").replace(/[\u0000-\u001f\u007f]/gu,"\uFFFD").slice(0,MAX_DISPLAY_CHARS_V1)}function projectSnapshot(snapshot2){let entries=snapshot2.entries.slice(0,MAX_PLUGIN_ENTRIES_V1).map(entry=>Object.freeze({pluginId:entry.pluginId,pluginVersion:entry.pluginVersion,status:entry.status,...entry.installedVersion===void 0?{}:{installedVersion:entry.installedVersion},...entry.lifecycle===void 0?{}:{lifecycle:entry.lifecycle},diagnosticCodes:Object.freeze(entry.diagnosticCodes.slice(0,MAX_DIAGNOSTIC_CODES_V1).map(code=>safeDisplay(code)))}));return Object.freeze({entries:Object.freeze(entries),truncated:snapshot2.truncated||snapshot2.entries.length>MAX_PLUGIN_ENTRIES_V1})}function actionsFor(entry){switch(entry.status){case"available":return["install"];case"update-available":return["update","remove"];case"installed":return["remove"];case"unavailable":return[]}}function actionTargetVersion(entry,action){return action==="remove"?entry.installedVersion??entry.pluginVersion:entry.pluginVersion}function errorCode(result){return result.code??"manager-operation-failed"}var PluginManagerEntryComponent=class{controller;onClose;requestRender;entries=Object.freeze([]);truncated=!1;selectedIndex=0;selectedActionIndex=0;confirmation;busy=!1;status=Object.freeze({status:"error",entryCount:0,truncated:!1});_focused=!1;get focused(){return this._focused}set focused(value){this._focused=value}constructor(options){this.controller=options.controller,this.onClose=options.onClose,this.requestRender=options.requestRender,options.snapshot!==void 0&&this.setSnapshot(options.snapshot)}setSnapshot(snapshot2){let projected=projectSnapshot(snapshot2);this.entries=projected.entries,this.truncated=projected.truncated,this.selectedIndex=Math.min(this.selectedIndex,Math.max(0,this.entries.length-1)),this.selectedActionIndex=Math.min(this.selectedActionIndex,Math.max(0,this.currentActions().length-1)),this.status=Object.freeze({status:"ready",entryCount:this.entries.length,truncated:this.truncated})}currentEntry(){return this.entries[this.selectedIndex]}currentActions(){let entry=this.currentEntry();return entry===void 0?[]:actionsFor(entry)}currentAction(){return this.currentActions()[this.selectedActionIndex]}request(){this.requestRender?.()}render(width){if(!this._focused){let state=this.status.status==="ready"?t("catalog {count}",{count:this.status.entryCount}):t("catalog unavailable"),bounded=this.truncated?t(", bounded"):"";return[truncateToWidth(theme.fg("muted",` ${t("Plugin manager \xB7 {state}{bounded} \xB7 Enter open",{state,bounded})}`),width,"...")]}let lines=[truncateToWidth(theme.bold(` ${t("Plugin manager")}`),width,"...")];if(this.busy)lines.push(truncateToWidth(theme.fg("accent",` ${t("Working\u2026")}`),width,"..."));else if(this.confirmation!==void 0){let entry=this.currentEntry(),action=this.currentAction();if(entry!==void 0&&action!==void 0){let targetVersion=actionTargetVersion(entry,action)??entry.pluginVersion;lines.push(truncateToWidth(theme.fg("error",` ${t("Confirm {action} {plugin}@{version}? Enter confirm \xB7 Esc cancel",{action,plugin:safeDisplay(entry.pluginId),version:safeDisplay(targetVersion)})}`),width,"..."))}}else this.status.status==="error"&&this.status.diagnosticCode!==void 0&&lines.push(truncateToWidth(theme.fg("error",` ${t("Error: {code}",{code:this.status.diagnosticCode})}`),width,"..."));if(this.entries.length===0)lines.push(theme.fg("dim",` ${t("No plugins available")}`));else for(let[index,entry]of this.entries.entries()){let cursor=index===this.selectedIndex?">":" ",status=entry.status,installed=entry.installedVersion===void 0?"":` ${t("installed {version}",{version:safeDisplay(entry.installedVersion)})}`,diagnostics=entry.diagnosticCodes.length===0?"":` [${entry.diagnosticCodes.join(", ")}]`;lines.push(truncateToWidth(`${cursor} ${safeDisplay(entry.pluginId)}@${safeDisplay(entry.pluginVersion)} \xB7 ${status}${installed}${diagnostics}`,width,"..."))}if(this.currentActions().length>0&&!this.busy){let action=this.currentAction();lines.push(truncateToWidth(theme.fg("muted",` ${t("Action: {action} \xB7 Tab switch action \xB7 Enter confirm",{action:action??"install"})}`),width,"..."))}else this.entries.length>0&&!this.busy&&lines.push(truncateToWidth(theme.fg("dim",` ${t("Selected plugin is unavailable")}`),width,"..."));return this.truncated&&lines.push(theme.fg("dim",` ${t("(list bounded)")}`)),lines.push(truncateToWidth(theme.fg("dim",` ${t("\u2191\u2193 navigate \xB7 Esc close")}`),width,"...")),lines}async refresh(){try{let result=await this.controller.getSnapshot();return result.status==="ok"?(this.setSnapshot(result.snapshot),this.request(),this.status):(this.status=Object.freeze({status:"error",entryCount:0,truncated:!1,diagnosticCode:result.code}),this.entries=Object.freeze([]),this.truncated=!1,this.request(),this.status)}catch{return this.status=Object.freeze({status:"error",entryCount:0,truncated:!1,diagnosticCode:"manager-operation-failed"}),this.entries=Object.freeze([]),this.truncated=!1,this.request(),this.status}}async perform(action){let entry=this.currentEntry();if(entry===void 0)return;this.busy=!0,this.confirmation=void 0,this.request();let result;try{let input={pluginId:entry.pluginId,pluginVersion:actionTargetVersion(entry,action),confirmed:!0};result=await this.controller[action](input)}catch{result={status:"failed",code:"manager-operation-failed"}}result.snapshot!==void 0&&this.setSnapshot(result.snapshot);let mutationCode=result.status==="succeeded"?void 0:errorCode(result),refreshed=result.snapshot===void 0?await this.refresh():this.status;mutationCode!==void 0&&(this.status=Object.freeze({...refreshed,status:"error",diagnosticCode:mutationCode})),this.busy=!1,this.selectedActionIndex=Math.min(this.selectedActionIndex,Math.max(0,this.currentActions().length-1)),this.request()}async openPluginManager(){return await this.refresh()}handleInput(data){if(!this._focused)return;let kb=getKeybindings();if(!this.busy){if(this.confirmation!==void 0){if(kb.matches(data,"tui.select.cancel")){this.confirmation=void 0,this.request();return}if(kb.matches(data,"tui.select.confirm")){let action=this.currentAction();action!==void 0&&this.perform(action);return}return}if(kb.matches(data,"tui.select.cancel")){this._focused=!1,this.onClose?.(),this.request();return}if(kb.matches(data,"tui.select.up")){this.selectedIndex=Math.max(0,this.selectedIndex-1),this.selectedActionIndex=0,this.request();return}if(kb.matches(data,"tui.select.down")){this.selectedIndex=Math.min(Math.max(0,this.entries.length-1),this.selectedIndex+1),this.selectedActionIndex=0,this.request();return}if(kb.matches(data,"tui.input.tab")){let actions=this.currentActions();actions.length>0&&(this.selectedActionIndex=(this.selectedActionIndex+1)%actions.length),this.request();return}if(kb.matches(data,"tui.select.confirm")){let entry=this.currentEntry(),action=this.currentAction();entry!==void 0&&action!==void 0&&(this.confirmation={pluginId:entry.pluginId,action},this.request())}}}invalidate(){}getSelectedPluginId(){return this.currentEntry()?.pluginId}getSelectedAction(){return this.currentAction()}getStatus(){return this.status}};var plugin_selection_controller_exports={};__export(plugin_selection_controller_exports,{createPluginSelectionControllerV1:()=>createPluginSelectionControllerV1});var MAX_PROFILES=32,MAX_PLUGINS_PER_PROFILE=128,MAX_DIAGNOSTIC_CODES=8;function diagnosticCodes(resolution,pluginId){if(resolution.status!=="resolved")return Object.freeze([]);let plugin=resolution.resolution.plugins.find(candidate=>candidate.pluginId===pluginId);return Object.freeze((plugin?.diagnostics??[]).slice(0,MAX_DIAGNOSTIC_CODES).map(item=>item.code))}function profileById(profileId){return listBuiltinPluginProfilesV1().find(profile=>profile.id===profileId)}function selectionForProfile(snapshot2,profileId){return snapshot2.selections.find(selection=>selection.profileId===profileId)}function pluginState(pluginId,selection){return selection?.disabledPluginIds.includes(pluginId)===!0?"disabled":selection===void 0||selection.selectedPluginIds.includes(pluginId)?"selected":"available"}function makeSnapshot2(storeStatus,storeSnapshot,host,scope,verifiedPlugins,manifestOverrides){let manifests2=new Set(listBuiltinPluginManifestsV1().map(manifest=>manifest.id)),profiles2=listBuiltinPluginProfilesV1().slice(0,MAX_PROFILES).map(profile=>{let selection=selectionForProfile(storeSnapshot,profile.id),resolution;try{resolution=resolveBuiltinPluginProfileV1({profileId:profile.id,host,verifiedPlugins,manifestOverrides})}catch{resolution={status:"host_facts_required",profileId:profile.id}}let plugins=profile.pluginIds.slice(0,MAX_PLUGINS_PER_PROFILE).map(pluginId=>{let known=manifests2.has(pluginId)||manifestOverrides?.[pluginId]!==void 0,ready=known&&resolution.status==="resolved"&&resolution.resolution.plugins.some(candidate=>candidate.pluginId===pluginId&&candidate.status==="installed-ready");return Object.freeze({pluginId,state:pluginState(pluginId,selection),availability:ready?"ready":"unavailable",diagnosticCodes:known?diagnosticCodes(resolution,pluginId):Object.freeze([])})});return Object.freeze({profileId:profile.id,version:profile.version,plugins:Object.freeze(plugins)})});return Object.freeze({version:1,scope,storeStatus,profiles:Object.freeze(profiles2)})}function resultFromRead(result,host,scope,verifiedPlugins,manifestOverrides){return result.status==="ok"||result.status==="missing"?{status:"ok",snapshot:makeSnapshot2(result.status,result.snapshot,host,scope,verifiedPlugins,manifestOverrides)}:{status:"error",code:result.status==="cancelled"?"store-cancelled":"store-invalid"}}function createPluginSelectionControllerV1(options){let scope=options.scope??"global",getSnapshot=async(input={})=>{try{return resultFromRead(await options.store.read(input),options.host,scope,options.verifiedPlugins,options.manifestOverrides)}catch{return{status:"error",code:"store-error"}}},setState=async input=>{let profile=profileById(input.profileId);if(profile===void 0)return{status:"error",code:"unknown-profile"};if(!profile.pluginIds.includes(input.pluginId))return{status:"error",code:"unknown-plugin"};let current=await getSnapshot({signal:input.signal});if(current.status!=="ok")return current;let currentSelectionResult=await options.store.read({signal:input.signal});if(currentSelectionResult.status!=="ok"&¤tSelectionResult.status!=="missing")return{status:"error",code:currentSelectionResult.status==="cancelled"?"write-cancelled":"store-invalid"};let existing=selectionForProfile(currentSelectionResult.snapshot,profile.id),disabled=new Set(existing?.disabledPluginIds??[]),selected=new Set(existing?.selectedPluginIds??profile.pluginIds);if(input.state==="disabled")selected.delete(input.pluginId),disabled.add(input.pluginId);else{if(current.snapshot.profiles.find(candidate=>candidate.profileId===profile.id)?.plugins.find(candidate=>candidate.pluginId===input.pluginId)?.availability!=="ready")return{status:"error",code:"unavailable-plugin",snapshot:current.snapshot};selected.add(input.pluginId),disabled.delete(input.pluginId)}let selection=createPluginSelectionV1({profileId:profile.id,selectedPluginIds:[...selected],disabledPluginIds:[...disabled]}),mutation;try{mutation=await options.store.set({selection,signal:input.signal})}catch{return{status:"error",code:"write-error",snapshot:current.snapshot}}return mutation.status!=="ok"?{status:"error",code:mutation.status==="cancelled"?"write-cancelled":"write-invalid",snapshot:current.snapshot}:{status:"ok",snapshot:makeSnapshot2("ok",mutation.snapshot,options.host,scope,options.verifiedPlugins,options.manifestOverrides)}};return Object.freeze({getSnapshot,setState,toggle:async input=>{let snapshot2=await getSnapshot({signal:input.signal});if(snapshot2.status!=="ok")return snapshot2;let profile=snapshot2.snapshot.profiles.find(candidate=>candidate.profileId===input.profileId),plugin=profile?.plugins.find(candidate=>candidate.pluginId===input.pluginId);return profile===void 0?{status:"error",code:"unknown-profile"}:plugin===void 0?{status:"error",code:"unknown-plugin"}:plugin.state==="disabled"&&plugin.availability!=="ready"?{status:"error",code:"unavailable-plugin",snapshot:snapshot2.snapshot}:await setState({...input,state:plugin.state==="disabled"?"selected":"disabled"})}})}import{existsSync as existsSync28}from"node:fs";import{join as join53}from"node:path";import{createInterface}from"node:readline";var AuthCommandError=class extends Error{},AUTH_COMMAND_USAGE={check:`${APP_NAME} auth check --provider <provider> [--json] [--credentials] [--no-refresh]`,api_key:`${APP_NAME} auth print-api-key --provider <provider> [--model <model>]`,bearer_token:`${APP_NAME} auth print-bearer-token --provider <provider> [--model <model>] [--min-expiry <duration>]`};function getAuthCommandName(kind){return kind==="check"?"auth check":kind==="api_key"?"auth print-api-key":"auth print-bearer-token"}function getAuthCommandUsage(kind){return AUTH_COMMAND_USAGE[kind]}function isAuthCommandHelp(args){return args[0]==="auth"&&(args[1]===void 0||args[1]==="help"||args.includes("--help")||args.includes("-h"))}function printAuthCommandHelp(){console.log(`${t("Usage:")}
|
|
769
|
+
`);if(newlineIndex===-1)return;emitLine(buffer.slice(0,newlineIndex)),buffer=buffer.slice(newlineIndex+1)}},onEnd=()=>{buffer+=decoder.end(),buffer.length>0&&(emitLine(buffer),buffer="")};return stream.on("data",onData),stream.on("end",onEnd),()=>{stream.off("data",onData),stream.off("end",onEnd)}}var RpcClient=class{process=null;stopReadingStdout=null;eventListeners=[];pendingRequests=new Map;requestId=0;stderr="";exitError=null;options;constructor(options={}){this.options=options}async start(){if(this.process)throw new Error(t("Client already started"));this.exitError=null;let cliPath=this.options.cliPath??"dist/cli.js",args=["--mode","rpc"];this.options.provider&&args.push("--provider",this.options.provider),this.options.model&&args.push("--model",this.options.model),this.options.args&&args.push(...this.options.args);let childProcess=spawn6("node",[cliPath,...args],{cwd:this.options.cwd,env:{...process.env,...this.options.env},stdio:["pipe","pipe","pipe"]});if(this.process=childProcess,childProcess.stderr?.on("data",data=>{this.stderr+=data.toString(),process.stderr.write(data)}),childProcess.once("exit",(code,signal)=>{if(this.process!==childProcess)return;let error=this.createProcessExitError(code,signal);this.exitError=error,this.rejectPendingRequests(error)}),childProcess.once("error",error=>{if(this.process!==childProcess)return;let processError=new Error(`Agent process error: ${error.message}. Stderr: ${this.stderr}`);this.exitError=processError,this.rejectPendingRequests(processError)}),childProcess.stdin?.on("error",error=>{if(this.process!==childProcess)return;let stdinError=this.exitError??new Error(`Agent process stdin error: ${error.message}. Stderr: ${this.stderr}`);this.exitError=stdinError,this.rejectPendingRequests(stdinError)}),this.stopReadingStdout=attachJsonlLineReader(childProcess.stdout,line=>{this.handleLine(line)}),await new Promise(resolve22=>setTimeout(resolve22,100)),this.process.exitCode!==null){let error=this.exitError??this.createProcessExitError(this.process.exitCode,this.process.signalCode);throw this.exitError=error,error}}async stop(){this.process&&(this.stopReadingStdout?.(),this.stopReadingStdout=null,this.process.kill("SIGTERM"),await new Promise(resolve22=>{let timeout=setTimeout(()=>{this.process?.kill("SIGKILL"),resolve22()},1e3);this.process?.on("exit",()=>{clearTimeout(timeout),resolve22()})}),this.process=null,this.pendingRequests.clear())}onEvent(listener){return this.eventListeners.push(listener),()=>{let index=this.eventListeners.indexOf(listener);index!==-1&&this.eventListeners.splice(index,1)}}getStderr(){return this.stderr}async prompt(message,images,streamingBehavior){let response2=await this.send({type:"prompt",message,images,streamingBehavior});return this.getData(response2)?.disposition}async steer(message,images){let response2=await this.send({type:"steer",message,images});return this.getData(response2)?.disposition}async followUp(message,images){let response2=await this.send({type:"follow_up",message,images});return this.getData(response2)?.disposition}async abort(){await this.send({type:"abort"})}async clearQueue(){let response2=await this.send({type:"clear_queue"});return this.getData(response2)}async newSession(parentSession){let response2=await this.send({type:"new_session",parentSession});return this.getData(response2)}async getState(){let response2=await this.send({type:"get_state"});return this.getData(response2)}async setModel(provider,modelId){let response2=await this.send({type:"set_model",provider,modelId});return this.getData(response2)}async cycleModel(){let response2=await this.send({type:"cycle_model"});return this.getData(response2)}async getAvailableModels(){let response2=await this.send({type:"get_available_models"});return this.getData(response2).models}async setThinkingLevel(level){await this.send({type:"set_thinking_level",level})}async cycleThinkingLevel(){let response2=await this.send({type:"cycle_thinking_level"});return this.getData(response2)}async getAvailableThinkingLevels(){let response2=await this.send({type:"get_available_thinking_levels"});return this.getData(response2).levels}async setSteeringMode(mode){await this.send({type:"set_steering_mode",mode})}async setFollowUpMode(mode){await this.send({type:"set_follow_up_mode",mode})}async compact(customInstructions){let response2=await this.send({type:"compact",customInstructions});return this.getData(response2)}async abortRetry(){await this.send({type:"abort_retry"})}async bash(command){let response2=await this.send({type:"bash",command});return this.getData(response2)}async abortBash(){await this.send({type:"abort_bash"})}async getSessionStats(){let response2=await this.send({type:"get_session_stats"});return this.getData(response2)}async exportHtml(outputPath){let response2=await this.send({type:"export_html",outputPath});return this.getData(response2)}async switchSession(sessionPath){let response2=await this.send({type:"switch_session",sessionPath});return this.getData(response2)}async fork(entryId){let response2=await this.send({type:"fork",entryId});return this.getData(response2)}async clone(){let response2=await this.send({type:"clone"});return this.getData(response2)}async getForkMessages(){let response2=await this.send({type:"get_fork_messages"});return this.getData(response2).messages}async getEntries(since){let response2=await this.send({type:"get_entries",since});return this.getData(response2)}async getTree(){let response2=await this.send({type:"get_tree"});return this.getData(response2)}async getLastAssistantText(){let response2=await this.send({type:"get_last_assistant_text"});return this.getData(response2).text}async setSessionName(name){await this.send({type:"set_session_name",name})}async getMessages(){let response2=await this.send({type:"get_messages"});return this.getData(response2).messages}async getCommands(){let response2=await this.send({type:"get_commands"});return this.getData(response2).commands}waitForIdle(timeout=6e4){return new Promise((resolve22,reject2)=>{let timer=setTimeout(()=>{unsubscribe(),reject2(new Error(`Timeout waiting for agent to become idle. Stderr: ${this.stderr}`))},timeout),unsubscribe=this.onEvent(event=>{event.type==="agent_settled"&&(clearTimeout(timer),unsubscribe(),resolve22())})})}collectEvents(timeout=6e4){return new Promise((resolve22,reject2)=>{let events=[],timer=setTimeout(()=>{unsubscribe(),reject2(new Error(`Timeout collecting events. Stderr: ${this.stderr}`))},timeout),unsubscribe=this.onEvent(event=>{events.push(event),event.type==="agent_settled"&&(clearTimeout(timer),unsubscribe(),resolve22(events))})})}async promptAndWait(message,images,timeout=6e4){let events=[],finish,fail,settled=new Promise((resolve22,reject2)=>{finish=resolve22,fail=reject2}),timer=setTimeout(()=>{fail?.(new Error(`Timeout collecting events. Stderr: ${this.stderr}`))},timeout),unsubscribe=this.onEvent(event=>{events.push(event),event.type==="agent_settled"&&finish?.()});try{await this.prompt(message,images)==="handled"&&finish?.(),await settled}finally{clearTimeout(timer),unsubscribe()}return events}handleLine(line){try{let data=JSON.parse(line);if(data.type==="response"&&data.id&&this.pendingRequests.has(data.id)){let pending=this.pendingRequests.get(data.id);this.pendingRequests.delete(data.id),pending.resolve(data);return}for(let listener of[...this.eventListeners])listener(data)}catch{}}createProcessExitError(code,signal){return new Error(`Agent process exited (code=${code} signal=${signal}). Stderr: ${this.stderr}`)}rejectPendingRequests(error){for(let pending of this.pendingRequests.values())pending.reject(error);this.pendingRequests.clear()}async send(command){let childProcess=this.process,stdin=childProcess?.stdin;if(!childProcess||!stdin)throw new Error(t("Client not started"));if(this.exitError)throw this.exitError;if(childProcess.exitCode!==null){let error=this.createProcessExitError(childProcess.exitCode,childProcess.signalCode);throw this.exitError=error,error}if(stdin.destroyed||!stdin.writable){let error=new Error(`Agent process stdin is not writable. Stderr: ${this.stderr}`);throw this.exitError=error,error}let id=`req_${++this.requestId}`,fullCommand={...command,id};return new Promise((resolve22,reject2)=>{let timeout=setTimeout(()=>{this.pendingRequests.delete(id),reject2(new Error(`Timeout waiting for response to ${command.type}. Stderr: ${this.stderr}`))},3e4);this.pendingRequests.set(id,{resolve:response2=>{clearTimeout(timeout),resolve22(response2)},reject:error=>{clearTimeout(timeout),reject2(error)}});try{stdin.write(serializeJsonLine(fullCommand))}catch(error){let writeError=error instanceof Error?error:new Error(String(error)),pending=this.pendingRequests.get(id);this.pendingRequests.delete(id),pending?.reject(writeError)}})}getData(response2){if(!response2.success){let errorResponse=response2;throw new Error(errorResponse.error)}return response2.data}};import*as crypto2 from"node:crypto";function mapRpcDialogResponseToOutcome(response2){return"cancelled"in response2&&response2.cancelled?{status:"cancelled"}:"confirmed"in response2?{status:"answered",value:response2.confirmed}:"value"in response2?{status:"answered",value:response2.value}:{status:"cancelled"}}async function runRpcMode(runtimeHost,options={}){takeOverStdout();let session=runtimeHost.session,facade=createCodingAgentFacade(session),runtimeFacade=createCodingAgentRuntimeFacade(runtimeHost),unsubscribe,unsubscribeBackpressure,output=obj=>{writeRawStdout(serializeJsonLine(obj))},success=(id,command,data)=>data===void 0?{id,type:"response",command,success:!0}:{id,type:"response",command,success:!0,data},error=(id,command,message)=>({id,type:"response",command,success:!1,error:message}),pendingExtensionRequests=new Map,shuttingDown=!1,signalCleanupHandlers=[];function createDialogPromise(opts,defaultValue,request,parseResponse){if(opts?.signal?.aborted)return Promise.resolve(defaultValue);let id=crypto2.randomUUID();return new Promise((resolve22,reject2)=>{let timeoutId,cleanup=()=>{timeoutId&&clearTimeout(timeoutId),opts?.signal?.removeEventListener("abort",onAbort),pendingExtensionRequests.delete(id)},onAbort=()=>{cleanup(),resolve22(defaultValue)};opts?.signal?.addEventListener("abort",onAbort,{once:!0}),opts?.timeout&&(timeoutId=setTimeout(()=>{cleanup(),resolve22(defaultValue)},opts.timeout)),pendingExtensionRequests.set(id,{resolve:response2=>{cleanup(),resolve22(parseResponse(response2))},reject:reject2}),output({type:"extension_ui_request",id,...request})})}let emitInteractionNotify=request=>{output({type:"extension_ui_request",id:crypto2.randomUUID(),method:"notify",message:request.message,notifyType:request.level??"info"})},createInteractionHostV12=()=>({notify:emitInteractionNotify,prompt:(request,context)=>{let opts={signal:context.signal};switch(request.kind){case"notify":return emitInteractionNotify(request),Promise.resolve({status:"delivered"});case"select":return createDialogPromise(opts,{status:"cancelled"},{method:"select",title:request.title,options:[...request.options]},mapRpcDialogResponseToOutcome);case"confirm":return createDialogPromise(opts,{status:"cancelled"},{method:"confirm",title:request.title,message:request.message},mapRpcDialogResponseToOutcome);case"input":return createDialogPromise(opts,{status:"cancelled"},{method:"input",title:request.title,placeholder:request.placeholder},mapRpcDialogResponseToOutcome)}}});options.interactionHostSlot?.setTarget(createInteractionHostV12()),runtimeFacade.setRebindSession(async()=>{await rebindSession()});let rebindSession=async()=>{session=runtimeHost.session,facade=createCodingAgentFacade(session),await session.startSession(),kickMemoryModelPreheat(session),unsubscribe?.(),unsubscribeBackpressure?.(),unsubscribe=facade.subscribe(event=>{output(toJsonEvent(event))}),unsubscribeBackpressure=facade.subscribeRawEventGate(async()=>{await waitForRawStdoutBackpressure()})},registerSignalHandlers2=()=>{let signals=["SIGTERM"];process.platform!=="win32"&&signals.push("SIGHUP");for(let signal of signals){let handler=()=>{killTrackedDetachedChildren(),shutdown2(signal==="SIGHUP"?129:143,signal)};process.on(signal,handler),signalCleanupHandlers.push(()=>process.off(signal,handler))}};await rebindSession(),registerSignalHandlers2();let handleCommand=async command=>{let id=command.id;switch(command.type){case"prompt":{let preflightSucceeded=!1;facade.prompt(command.message,{images:command.images,streamingBehavior:command.streamingBehavior,source:"rpc",preflightResult:disposition=>{preflightSucceeded=!0,output(success(id,"prompt",{disposition}))}}).catch(e=>{preflightSucceeded||output(error(id,"prompt",e.message))});return}case"steer":{let disposition=await facade.steer(command.message,command.images,{source:"rpc"});return success(id,"steer",{disposition})}case"follow_up":{let disposition=await facade.followUp(command.message,command.images,{source:"rpc"});return success(id,"follow_up",{disposition})}case"abort":return await facade.abort(),success(id,"abort");case"clear_queue":return success(id,"clear_queue",facade.clearQueue());case"new_session":{let options2=command.parentSession?{parentSession:command.parentSession}:void 0,result=await runtimeFacade.newSession(options2);return result.cancelled||await rebindSession(),success(id,"new_session",result)}case"get_state":{let suiteId=readSessionSuiteId(facade.getEntries()),state={model:facade.getModel(),thinkingLevel:facade.getThinkingLevel(),isStreaming:facade.isStreaming(),isCompacting:facade.isCompacting(),steeringMode:facade.getSteeringMode(),followUpMode:facade.getFollowUpMode(),sessionFile:facade.getSessionFile(),sessionId:facade.getSessionId(),sessionName:facade.getSessionName(),...suiteId===void 0?{}:{suiteId},messageCount:facade.getState().messages.length,pendingMessageCount:facade.getPendingMessageCount()};return success(id,"get_state",state)}case"set_model":{let model=facade.getAvailableModels().find(m=>m.provider===command.provider&&m.id===command.modelId);return model?(await facade.setModel(model),success(id,"set_model",model)):error(id,"set_model",`Model not found: ${command.provider}/${command.modelId}`)}case"cycle_model":{let result=await facade.cycleModel();return result?success(id,"cycle_model",result):success(id,"cycle_model",null)}case"get_available_models":{let models=facade.getAvailableModels();return success(id,"get_available_models",{models})}case"set_thinking_level":return facade.setThinkingLevel(command.level),success(id,"set_thinking_level");case"cycle_thinking_level":{let level=facade.cycleThinkingLevel();return level?success(id,"cycle_thinking_level",{level}):success(id,"cycle_thinking_level",null)}case"get_available_thinking_levels":{let levels=facade.getAvailableThinkingLevels();return success(id,"get_available_thinking_levels",{levels})}case"set_steering_mode":return facade.setSteeringMode(command.mode),success(id,"set_steering_mode");case"set_follow_up_mode":return facade.setFollowUpMode(command.mode),success(id,"set_follow_up_mode");case"compact":{let result=await facade.compact(command.customInstructions);return success(id,"compact",result)}case"abort_retry":return facade.abortRetry(),success(id,"abort_retry");case"bash":{facade.emitUserBash(command.excludeFromContext??!1);let result=await facade.executeBash(command.command,void 0,{excludeFromContext:command.excludeFromContext,id});return success(id,"bash",result)}case"abort_bash":return facade.abortBash(),success(id,"abort_bash");case"get_session_stats":{let stats=facade.getSessionStats();return success(id,"get_session_stats",stats)}case"export_html":{let path8=await facade.exportToHtml(command.outputPath);return success(id,"export_html",{path:path8})}case"switch_session":{let result=await runtimeFacade.switchSession(command.sessionPath);return result.cancelled||await rebindSession(),success(id,"switch_session",result)}case"fork":{let result=await runtimeFacade.fork(command.entryId);return result.cancelled||await rebindSession(),success(id,"fork",{text:result.selectedText,cancelled:result.cancelled})}case"clone":{let leafId=facade.getLeafId();if(!leafId)return error(id,"clone","Cannot clone session: no current entry selected");let result=await runtimeFacade.fork(leafId,{position:"at"});return result.cancelled||await rebindSession(),success(id,"clone",{cancelled:result.cancelled})}case"get_fork_messages":{let messages=facade.getUserMessagesForForking();return success(id,"get_fork_messages",{messages})}case"get_entries":{let entries=facade.getEntries();if(command.since!==void 0){let sinceIndex=entries.findIndex(e=>e.id===command.since);if(sinceIndex===-1)return error(id,"get_entries",`Entry not found: ${command.since}`);entries=entries.slice(sinceIndex+1)}return success(id,"get_entries",{entries,leafId:facade.getLeafId()})}case"get_tree":return success(id,"get_tree",{tree:facade.getTree(),leafId:facade.getLeafId()});case"get_last_assistant_text":{let text=facade.getLastAssistantText();return success(id,"get_last_assistant_text",{text})}case"set_session_name":{let name=command.name.trim();return name?(facade.setSessionName(name),success(id,"set_session_name")):error(id,"set_session_name","Session name cannot be empty")}case"get_messages":return success(id,"get_messages",{messages:facade.getState().messages});case"get_metrics":{let snapshot2=options.getMetrics?.(command.windowTurns===void 0?void 0:{windowTurns:command.windowTurns});return snapshot2?success(id,"get_metrics",snapshot2):error(id,"get_metrics","Metrics are not available: the observability plugin is not mounted in this session")}case"get_commands":{let commands=[];for(let template of facade.getPromptTemplates())commands.push({name:template.name,description:template.description,source:"prompt",sourceInfo:template.sourceInfo});for(let skill of facade.getSkills().skills)commands.push({name:`skill:${skill.name}`,description:skill.description,source:"skill",sourceInfo:skill.sourceInfo});let capabilityRuntime=session.getCapabilityRuntime();for(let{definition,source}of capabilityRuntime.listCommands())commands.some(command2=>command2.name===definition.name)||commands.push({name:definition.name,description:definition.description,source:"capability",sourceInfo:createSyntheticSourceInfo(`<plugin:${source}:${definition.name}>`,{source})});return success(id,"get_commands",{commands})}default:{let unknownCommand=command;if(options.capabilities?.hasRpcMethod(unknownCommand.type)){let data=await options.capabilities.dispatchRpc(unknownCommand.type,command);return{id,type:"response",command:unknownCommand.type,success:!0,data}}return error(id,unknownCommand.type,`Unknown command: ${unknownCommand.type}`)}}},detachInput=()=>{};async function shutdown2(exitCode=0,signal){shuttingDown&&process.exit(exitCode),shuttingDown=!0;for(let cleanup of signalCleanupHandlers)cleanup();unsubscribe?.(),unsubscribeBackpressure?.(),await runtimeHost.dispose(),detachInput(),process.stdin.pause(),signal!=="SIGTERM"&&await flushRawStdout(),process.exit(exitCode)}let handleInputLine=async line=>{let parsed;try{parsed=JSON.parse(line)}catch(parseError){output(error(void 0,"parse",`Failed to parse command: ${parseError instanceof Error?parseError.message:String(parseError)}`)),await waitForRawStdoutBackpressure();return}if(typeof parsed=="object"&&parsed!==null&&"type"in parsed&&parsed.type==="extension_ui_response"){let response2=parsed,pending=pendingExtensionRequests.get(response2.id);pending&&(pendingExtensionRequests.delete(response2.id),pending.resolve(response2));return}let command=parsed;try{let response2=await handleCommand(command);response2&&(output(response2),await waitForRawStdoutBackpressure())}catch(commandError){output(error(command.id,command.type,commandError instanceof Error?commandError.message:String(commandError))),await waitForRawStdoutBackpressure()}},onInputEnd=()=>{shutdown2()};return process.stdin.on("end",onInputEnd),detachInput=(()=>{let detachJsonl=attachJsonlLineReader(process.stdin,line=>{handleInputLine(line)});return()=>{detachJsonl(),process.stdin.off("end",onInputEnd)}})(),new Promise(()=>{})}var MAX_PLUGIN_ENTRIES_V1=128,MAX_DISPLAY_CHARS_V1=256,MAX_DIAGNOSTIC_CODES_V1=8;function safeDisplay(value){return value.replace(/\u001b\[[0-?]*[ -/]*[@-~]/gu,"").replace(/[\u0000-\u001f\u007f]/gu,"\uFFFD").slice(0,MAX_DISPLAY_CHARS_V1)}function projectSnapshot(snapshot2){let entries=snapshot2.entries.slice(0,MAX_PLUGIN_ENTRIES_V1).map(entry=>Object.freeze({pluginId:entry.pluginId,pluginVersion:entry.pluginVersion,status:entry.status,...entry.installedVersion===void 0?{}:{installedVersion:entry.installedVersion},...entry.lifecycle===void 0?{}:{lifecycle:entry.lifecycle},diagnosticCodes:Object.freeze(entry.diagnosticCodes.slice(0,MAX_DIAGNOSTIC_CODES_V1).map(code=>safeDisplay(code)))}));return Object.freeze({entries:Object.freeze(entries),truncated:snapshot2.truncated||snapshot2.entries.length>MAX_PLUGIN_ENTRIES_V1})}function actionsFor(entry){switch(entry.status){case"available":return["install"];case"update-available":return["update","remove"];case"installed":return["remove"];case"unavailable":return[]}}function actionTargetVersion(entry,action){return action==="remove"?entry.installedVersion??entry.pluginVersion:entry.pluginVersion}function errorCode(result){return result.code??"manager-operation-failed"}var PluginManagerEntryComponent=class{controller;onClose;requestRender;entries=Object.freeze([]);truncated=!1;selectedIndex=0;selectedActionIndex=0;confirmation;busy=!1;status=Object.freeze({status:"error",entryCount:0,truncated:!1});_focused=!1;get focused(){return this._focused}set focused(value){this._focused=value}constructor(options){this.controller=options.controller,this.onClose=options.onClose,this.requestRender=options.requestRender,options.snapshot!==void 0&&this.setSnapshot(options.snapshot)}setSnapshot(snapshot2){let projected=projectSnapshot(snapshot2);this.entries=projected.entries,this.truncated=projected.truncated,this.selectedIndex=Math.min(this.selectedIndex,Math.max(0,this.entries.length-1)),this.selectedActionIndex=Math.min(this.selectedActionIndex,Math.max(0,this.currentActions().length-1)),this.status=Object.freeze({status:"ready",entryCount:this.entries.length,truncated:this.truncated})}currentEntry(){return this.entries[this.selectedIndex]}currentActions(){let entry=this.currentEntry();return entry===void 0?[]:actionsFor(entry)}currentAction(){return this.currentActions()[this.selectedActionIndex]}request(){this.requestRender?.()}render(width){if(!this._focused){let state=this.status.status==="ready"?t("catalog {count}",{count:this.status.entryCount}):t("catalog unavailable"),bounded=this.truncated?t(", bounded"):"";return[truncateToWidth(theme.fg("muted",` ${t("Plugin manager \xB7 {state}{bounded} \xB7 Enter open",{state,bounded})}`),width,"...")]}let lines=[truncateToWidth(theme.bold(` ${t("Plugin manager")}`),width,"...")];if(this.busy)lines.push(truncateToWidth(theme.fg("accent",` ${t("Working\u2026")}`),width,"..."));else if(this.confirmation!==void 0){let entry=this.currentEntry(),action=this.currentAction();if(entry!==void 0&&action!==void 0){let targetVersion=actionTargetVersion(entry,action)??entry.pluginVersion;lines.push(truncateToWidth(theme.fg("error",` ${t("Confirm {action} {plugin}@{version}? Enter confirm \xB7 Esc cancel",{action,plugin:safeDisplay(entry.pluginId),version:safeDisplay(targetVersion)})}`),width,"..."))}}else this.status.status==="error"&&this.status.diagnosticCode!==void 0&&lines.push(truncateToWidth(theme.fg("error",` ${t("Error: {code}",{code:this.status.diagnosticCode})}`),width,"..."));if(this.entries.length===0)lines.push(theme.fg("dim",` ${t("No plugins available")}`));else for(let[index,entry]of this.entries.entries()){let cursor=index===this.selectedIndex?">":" ",status=entry.status,installed=entry.installedVersion===void 0?"":` ${t("installed {version}",{version:safeDisplay(entry.installedVersion)})}`,diagnostics=entry.diagnosticCodes.length===0?"":` [${entry.diagnosticCodes.join(", ")}]`;lines.push(truncateToWidth(`${cursor} ${safeDisplay(entry.pluginId)}@${safeDisplay(entry.pluginVersion)} \xB7 ${status}${installed}${diagnostics}`,width,"..."))}if(this.currentActions().length>0&&!this.busy){let action=this.currentAction();lines.push(truncateToWidth(theme.fg("muted",` ${t("Action: {action} \xB7 Tab switch action \xB7 Enter confirm",{action:action??"install"})}`),width,"..."))}else this.entries.length>0&&!this.busy&&lines.push(truncateToWidth(theme.fg("dim",` ${t("Selected plugin is unavailable")}`),width,"..."));return this.truncated&&lines.push(theme.fg("dim",` ${t("(list bounded)")}`)),lines.push(truncateToWidth(theme.fg("dim",` ${t("\u2191\u2193 navigate \xB7 Esc close")}`),width,"...")),lines}async refresh(){try{let result=await this.controller.getSnapshot();return result.status==="ok"?(this.setSnapshot(result.snapshot),this.request(),this.status):(this.status=Object.freeze({status:"error",entryCount:0,truncated:!1,diagnosticCode:result.code}),this.entries=Object.freeze([]),this.truncated=!1,this.request(),this.status)}catch{return this.status=Object.freeze({status:"error",entryCount:0,truncated:!1,diagnosticCode:"manager-operation-failed"}),this.entries=Object.freeze([]),this.truncated=!1,this.request(),this.status}}async perform(action){let entry=this.currentEntry();if(entry===void 0)return;this.busy=!0,this.confirmation=void 0,this.request();let result;try{let input={pluginId:entry.pluginId,pluginVersion:actionTargetVersion(entry,action),confirmed:!0};result=await this.controller[action](input)}catch{result={status:"failed",code:"manager-operation-failed"}}result.snapshot!==void 0&&this.setSnapshot(result.snapshot);let mutationCode=result.status==="succeeded"?void 0:errorCode(result),refreshed=result.snapshot===void 0?await this.refresh():this.status;mutationCode!==void 0&&(this.status=Object.freeze({...refreshed,status:"error",diagnosticCode:mutationCode})),this.busy=!1,this.selectedActionIndex=Math.min(this.selectedActionIndex,Math.max(0,this.currentActions().length-1)),this.request()}async openPluginManager(){return await this.refresh()}handleInput(data){if(!this._focused)return;let kb=getKeybindings();if(!this.busy){if(this.confirmation!==void 0){if(kb.matches(data,"tui.select.cancel")){this.confirmation=void 0,this.request();return}if(kb.matches(data,"tui.select.confirm")){let action=this.currentAction();action!==void 0&&this.perform(action);return}return}if(kb.matches(data,"tui.select.cancel")){this._focused=!1,this.onClose?.(),this.request();return}if(kb.matches(data,"tui.select.up")){this.selectedIndex=Math.max(0,this.selectedIndex-1),this.selectedActionIndex=0,this.request();return}if(kb.matches(data,"tui.select.down")){this.selectedIndex=Math.min(Math.max(0,this.entries.length-1),this.selectedIndex+1),this.selectedActionIndex=0,this.request();return}if(kb.matches(data,"tui.input.tab")){let actions=this.currentActions();actions.length>0&&(this.selectedActionIndex=(this.selectedActionIndex+1)%actions.length),this.request();return}if(kb.matches(data,"tui.select.confirm")){let entry=this.currentEntry(),action=this.currentAction();entry!==void 0&&action!==void 0&&(this.confirmation={pluginId:entry.pluginId,action},this.request())}}}invalidate(){}getSelectedPluginId(){return this.currentEntry()?.pluginId}getSelectedAction(){return this.currentAction()}getStatus(){return this.status}};var plugin_selection_controller_exports={};__export(plugin_selection_controller_exports,{createPluginSelectionControllerV1:()=>createPluginSelectionControllerV1});var MAX_PROFILES=32,MAX_PLUGINS_PER_PROFILE=128,MAX_DIAGNOSTIC_CODES=8;function diagnosticCodes(resolution,pluginId){if(resolution.status!=="resolved")return Object.freeze([]);let plugin=resolution.resolution.plugins.find(candidate=>candidate.pluginId===pluginId);return Object.freeze((plugin?.diagnostics??[]).slice(0,MAX_DIAGNOSTIC_CODES).map(item=>item.code))}function profileById(profileId){return listBuiltinPluginProfilesV1().find(profile=>profile.id===profileId)}function selectionForProfile(snapshot2,profileId){return snapshot2.selections.find(selection=>selection.profileId===profileId)}function pluginState(pluginId,selection){return selection?.disabledPluginIds.includes(pluginId)===!0?"disabled":selection===void 0||selection.selectedPluginIds.includes(pluginId)?"selected":"available"}function makeSnapshot2(storeStatus,storeSnapshot,host,scope,verifiedPlugins,manifestOverrides){let manifests2=new Set(listBuiltinPluginManifestsV1().map(manifest=>manifest.id)),profiles2=listBuiltinPluginProfilesV1().slice(0,MAX_PROFILES).map(profile=>{let selection=selectionForProfile(storeSnapshot,profile.id),resolution;try{resolution=resolveBuiltinPluginProfileV1({profileId:profile.id,host,verifiedPlugins,manifestOverrides})}catch{resolution={status:"host_facts_required",profileId:profile.id}}let plugins=profile.pluginIds.slice(0,MAX_PLUGINS_PER_PROFILE).map(pluginId=>{let known=manifests2.has(pluginId)||manifestOverrides?.[pluginId]!==void 0,ready=known&&resolution.status==="resolved"&&resolution.resolution.plugins.some(candidate=>candidate.pluginId===pluginId&&candidate.status==="installed-ready");return Object.freeze({pluginId,state:pluginState(pluginId,selection),availability:ready?"ready":"unavailable",diagnosticCodes:known?diagnosticCodes(resolution,pluginId):Object.freeze([])})});return Object.freeze({profileId:profile.id,version:profile.version,plugins:Object.freeze(plugins)})});return Object.freeze({version:1,scope,storeStatus,profiles:Object.freeze(profiles2)})}function resultFromRead(result,host,scope,verifiedPlugins,manifestOverrides){return result.status==="ok"||result.status==="missing"?{status:"ok",snapshot:makeSnapshot2(result.status,result.snapshot,host,scope,verifiedPlugins,manifestOverrides)}:{status:"error",code:result.status==="cancelled"?"store-cancelled":"store-invalid"}}function createPluginSelectionControllerV1(options){let scope=options.scope??"global",getSnapshot=async(input={})=>{try{return resultFromRead(await options.store.read(input),options.host,scope,options.verifiedPlugins,options.manifestOverrides)}catch{return{status:"error",code:"store-error"}}},setState=async input=>{let profile=profileById(input.profileId);if(profile===void 0)return{status:"error",code:"unknown-profile"};if(!profile.pluginIds.includes(input.pluginId))return{status:"error",code:"unknown-plugin"};let current=await getSnapshot({signal:input.signal});if(current.status!=="ok")return current;let currentSelectionResult=await options.store.read({signal:input.signal});if(currentSelectionResult.status!=="ok"&¤tSelectionResult.status!=="missing")return{status:"error",code:currentSelectionResult.status==="cancelled"?"write-cancelled":"store-invalid"};let existing=selectionForProfile(currentSelectionResult.snapshot,profile.id),disabled=new Set(existing?.disabledPluginIds??[]),selected=new Set(existing?.selectedPluginIds??profile.pluginIds);if(input.state==="disabled")selected.delete(input.pluginId),disabled.add(input.pluginId);else{if(current.snapshot.profiles.find(candidate=>candidate.profileId===profile.id)?.plugins.find(candidate=>candidate.pluginId===input.pluginId)?.availability!=="ready")return{status:"error",code:"unavailable-plugin",snapshot:current.snapshot};selected.add(input.pluginId),disabled.delete(input.pluginId)}let selection=createPluginSelectionV1({profileId:profile.id,selectedPluginIds:[...selected],disabledPluginIds:[...disabled]}),mutation;try{mutation=await options.store.set({selection,signal:input.signal})}catch{return{status:"error",code:"write-error",snapshot:current.snapshot}}return mutation.status!=="ok"?{status:"error",code:mutation.status==="cancelled"?"write-cancelled":"write-invalid",snapshot:current.snapshot}:{status:"ok",snapshot:makeSnapshot2("ok",mutation.snapshot,options.host,scope,options.verifiedPlugins,options.manifestOverrides)}};return Object.freeze({getSnapshot,setState,toggle:async input=>{let snapshot2=await getSnapshot({signal:input.signal});if(snapshot2.status!=="ok")return snapshot2;let profile=snapshot2.snapshot.profiles.find(candidate=>candidate.profileId===input.profileId),plugin=profile?.plugins.find(candidate=>candidate.pluginId===input.pluginId);return profile===void 0?{status:"error",code:"unknown-profile"}:plugin===void 0?{status:"error",code:"unknown-plugin"}:plugin.state==="disabled"&&plugin.availability!=="ready"?{status:"error",code:"unavailable-plugin",snapshot:snapshot2.snapshot}:await setState({...input,state:plugin.state==="disabled"?"selected":"disabled"})}})}import{existsSync as existsSync28}from"node:fs";import{join as join53}from"node:path";import{createInterface}from"node:readline";var AuthCommandError=class extends Error{},AUTH_COMMAND_USAGE={check:`${APP_NAME} auth check --provider <provider> [--json] [--credentials] [--no-refresh]`,api_key:`${APP_NAME} auth print-api-key --provider <provider> [--model <model>]`,bearer_token:`${APP_NAME} auth print-bearer-token --provider <provider> [--model <model>] [--min-expiry <duration>]`};function getAuthCommandName(kind){return kind==="check"?"auth check":kind==="api_key"?"auth print-api-key":"auth print-bearer-token"}function getAuthCommandUsage(kind){return AUTH_COMMAND_USAGE[kind]}function isAuthCommandHelp(args){return args[0]==="auth"&&(args[1]===void 0||args[1]==="help"||args.includes("--help")||args.includes("-h"))}function printAuthCommandHelp(){console.log(`${t("Usage:")}
|
|
770
770
|
${APP_NAME} auth print-api-key [--provider <provider>] [--model <model>]
|
|
771
771
|
${APP_NAME} auth print-bearer-token [--provider <provider>] [--model <model>] [--min-expiry <duration>]
|
|
772
772
|
${APP_NAME} auth check [--provider <provider>] [--model <model>] [--json] [--credentials] [--no-refresh]
|