import type { AgentAdapterType, EnvironmentDriver } from "./constants.js"; import type { SandboxEnvironmentProvider } from "./types/environment.js"; import type { JsonSchema } from "./types/plugin.js"; export type EnvironmentSupportStatus = "supported" | "unsupported"; export interface AdapterEnvironmentSupport { adapterType: AgentAdapterType; drivers: Record; sandboxProviders: Record; } export interface EnvironmentProviderCapability { status: EnvironmentSupportStatus; supportsSavedProbe: boolean; supportsUnsavedProbe: boolean; supportsRunExecution: boolean; supportsReusableLeases: boolean; displayName?: string; description?: string; source?: "builtin" | "plugin"; pluginKey?: string; pluginId?: string; configSchema?: JsonSchema; } export interface EnvironmentCapabilities { adapters: AdapterEnvironmentSupport[]; drivers: Record; sandboxProviders: Record; } const REMOTE_MANAGED_ADAPTERS = new Set([ "acpx_local", "claude_local", "codex_local", "cursor", "gemini_local", "opencode_local", "pi_local", ]); export function adapterSupportsRemoteManagedEnvironments(adapterType: string): boolean { return REMOTE_MANAGED_ADAPTERS.has(adapterType as AgentAdapterType); } export function supportedEnvironmentDriversForAdapter(adapterType: string): EnvironmentDriver[] { return adapterSupportsRemoteManagedEnvironments(adapterType) ? ["local", "ssh", "sandbox"] : ["local"]; } export function supportedSandboxProvidersForAdapter( adapterType: string, additionalProviders: readonly string[] = [], ): SandboxEnvironmentProvider[] { return adapterSupportsRemoteManagedEnvironments(adapterType) ? Array.from(new Set(additionalProviders)) as SandboxEnvironmentProvider[] : []; } export function isEnvironmentDriverSupportedForAdapter( adapterType: string, driver: string, ): boolean { return supportedEnvironmentDriversForAdapter(adapterType).includes(driver as EnvironmentDriver); } export function isSandboxProviderSupportedForAdapter( adapterType: string, provider: string | null | undefined, additionalProviders: readonly string[] = [], ): boolean { if (!provider) return false; return supportedSandboxProvidersForAdapter(adapterType, additionalProviders).includes( provider as SandboxEnvironmentProvider, ); } export function getAdapterEnvironmentSupport( adapterType: AgentAdapterType, additionalSandboxProviders: readonly string[] = [], ): AdapterEnvironmentSupport { const supportedDrivers = new Set(supportedEnvironmentDriversForAdapter(adapterType)); const supportedProviders = new Set(supportedSandboxProvidersForAdapter(adapterType, additionalSandboxProviders)); const sandboxProviders: Record = { fake: "unsupported", }; for (const provider of additionalSandboxProviders) { sandboxProviders[provider as SandboxEnvironmentProvider] = supportedProviders.has(provider as SandboxEnvironmentProvider) ? "supported" : "unsupported"; } return { adapterType, drivers: { local: supportedDrivers.has("local") ? "supported" : "unsupported", ssh: supportedDrivers.has("ssh") ? "supported" : "unsupported", sandbox: supportedDrivers.has("sandbox") ? "supported" : "unsupported", plugin: supportedDrivers.has("plugin") ? "supported" : "unsupported", }, sandboxProviders, }; } export function getEnvironmentCapabilities( adapterTypes: readonly AgentAdapterType[], options: { sandboxProviders?: Record>; } = {}, ): EnvironmentCapabilities { const pluginProviderKeys = Object.keys(options.sandboxProviders ?? {}); const sandboxProviders: Record = { fake: { status: "unsupported", supportsSavedProbe: true, supportsUnsavedProbe: true, supportsRunExecution: false, supportsReusableLeases: true, displayName: "Fake", source: "builtin", }, }; for (const [provider, capability] of Object.entries(options.sandboxProviders ?? {})) { sandboxProviders[provider as SandboxEnvironmentProvider] = { status: capability.status ?? "supported", supportsSavedProbe: capability.supportsSavedProbe ?? true, supportsUnsavedProbe: capability.supportsUnsavedProbe ?? true, supportsRunExecution: capability.supportsRunExecution ?? true, supportsReusableLeases: capability.supportsReusableLeases ?? true, displayName: capability.displayName, description: capability.description, source: capability.source ?? "plugin", pluginKey: capability.pluginKey, pluginId: capability.pluginId, configSchema: capability.configSchema, }; } return { adapters: adapterTypes.map((adapterType) => getAdapterEnvironmentSupport(adapterType, pluginProviderKeys)), drivers: { local: "supported", ssh: "supported", sandbox: "supported", plugin: "unsupported", }, sandboxProviders, }; }