import { a as CodemationConfigNormalizer, t as CodemationConsumerConfigLoader } from "./CodemationConsumerConfigLoader-By-6tuGc.js";
import { m as ApplicationTokens } from "./CredentialServices-Bios0dM8.js";
import { A as WorkflowDefinitionMapper, C as CodemationHonoApiApp, M as GetWorkflowDetailQuery, d as FrontendRuntime, j as GetWorkflowSummariesQuery, m as AppContainerLifecycle, t as AppContainerFactory } from "./AppContainerFactory-jpYXGZGe.js";
import { r as CodemationPluginPackageMetadata, t as AppConfigFactory } from "./AppConfigFactory-D4LL1aOR.js";
import { readFile, readdir } from "node:fs/promises";
import path from "node:path";
import { pathToFileURL } from "node:url";
import { accessSync } from "node:fs";

//#region src/presentation/http/CodemationServerGatewayFactory.ts
var CodemationServerGateway = class CodemationServerGateway {
	static contextsByConfig = /* @__PURE__ */ new WeakMap();
	constructor(config, consumerRoot, configSource, workflowSources = [], env) {
		this.config = config;
		this.consumerRoot = consumerRoot;
		this.configSource = configSource;
		this.workflowSources = workflowSources;
		this.env = env;
	}
	async dispatch(request) {
		return await (await this.getContext()).httpApi.fetch(request);
	}
	async prepare() {
		await this.getContext();
	}
	async close() {
		const cachedContext = CodemationServerGateway.contextsByConfig.get(this.config);
		if (!cachedContext) return;
		CodemationServerGateway.contextsByConfig.delete(this.config);
		await (await cachedContext).container.resolve(AppContainerLifecycle).stop();
	}
	async loadWorkflowSummaries() {
		const context = await this.getContext();
		return (await context.queryBus.execute(new GetWorkflowSummariesQuery())).map((workflow) => context.workflowDefinitionMapper.toSummary(workflow));
	}
	async loadWorkflowDetail(workflowId) {
		const context = await this.getContext();
		const workflow = await context.queryBus.execute(new GetWorkflowDetailQuery(workflowId));
		if (!workflow) throw new Error(`Unknown workflowId: ${workflowId}`);
		return await context.workflowDefinitionMapper.map(workflow);
	}
	getContext() {
		const cachedContext = CodemationServerGateway.contextsByConfig.get(this.config);
		if (cachedContext) return cachedContext;
		const nextContext = this.createContext();
		CodemationServerGateway.contextsByConfig.set(this.config, nextContext);
		return nextContext;
	}
	async createContext() {
		const repoRoot = this.detectWorkspaceRoot(this.consumerRoot);
		const env = this.env ?? process.env;
		const appConfig = new AppConfigFactory().create({
			repoRoot,
			consumerRoot: this.consumerRoot,
			env,
			config: new CodemationConfigNormalizer().normalize(this.config),
			workflowSources: this.resolveWorkflowSources()
		});
		const container = await new AppContainerFactory().create({
			appConfig,
			sharedWorkflowWebsocketServer: null
		});
		await container.resolve(FrontendRuntime).start();
		return {
			container,
			httpApi: container.resolve(CodemationHonoApiApp),
			queryBus: container.resolve(ApplicationTokens.QueryBus),
			workflowDefinitionMapper: container.resolve(WorkflowDefinitionMapper)
		};
	}
	resolveWorkflowSources() {
		if (this.workflowSources.length > 0) return [...this.workflowSources];
		if (!this.configSource || !this.config.workflows || this.config.workflows.length === 0) return [];
		return [this.configSource];
	}
	detectWorkspaceRoot(startDirectory) {
		let currentDirectory = path.resolve(startDirectory);
		while (true) try {
			accessSync(path.resolve(currentDirectory, "pnpm-workspace.yaml"));
			return currentDirectory;
		} catch {
			const parentDirectory = path.dirname(currentDirectory);
			if (parentDirectory === currentDirectory) return startDirectory;
			currentDirectory = parentDirectory;
		}
	}
};

//#endregion
//#region src/presentation/server/AppConfigLoader.ts
var AppConfigLoader = class {
	constructor(consumerConfigLoader = new CodemationConsumerConfigLoader(), appConfigFactory = new AppConfigFactory()) {
		this.consumerConfigLoader = consumerConfigLoader;
		this.appConfigFactory = appConfigFactory;
	}
	async load(args) {
		const resolution = await this.consumerConfigLoader.load({
			consumerRoot: args.consumerRoot,
			configPathOverride: args.configPathOverride
		});
		return {
			appConfig: this.appConfigFactory.create({
				repoRoot: args.repoRoot,
				consumerRoot: args.consumerRoot,
				env: args.env,
				config: resolution.config,
				workflowSources: resolution.workflowSources
			}),
			bootstrapSource: resolution.bootstrapSource
		};
	}
};

//#endregion
//#region src/presentation/server/CodemationPluginDiscovery.ts
var CodemationPluginDiscovery = class {
	pluginPackageMetadata = new CodemationPluginPackageMetadata();
	async discover(consumerRoot) {
		const nodeModulesRoot = path.resolve(consumerRoot, "node_modules");
		const packageRoots = await this.collectPackageRoots(nodeModulesRoot);
		const discoveredPackages = [];
		for (const packageRoot of packageRoots) {
			const packageJson = await this.readPackageJson(path.resolve(packageRoot, "package.json"));
			const pluginManifest = packageJson.codemation?.plugin;
			if (!packageJson.name || typeof pluginManifest !== "string" || pluginManifest.trim().length === 0) continue;
			discoveredPackages.push({
				packageName: packageJson.name,
				packageRoot,
				pluginEntry: pluginManifest,
				developmentEntry: await this.resolveDevelopmentPluginEntry(packageRoot)
			});
		}
		return discoveredPackages.sort((left, right) => left.packageName.localeCompare(right.packageName));
	}
	async resolvePlugins(consumerRoot) {
		const discoveredPackages = await this.discover(consumerRoot);
		return await this.resolveDiscoveredPackages(discoveredPackages);
	}
	async resolveDiscoveredPackages(discoveredPackages) {
		const resolvedPackages = [];
		for (const discoveredPackage of discoveredPackages) resolvedPackages.push({
			...discoveredPackage,
			plugin: await this.loadPlugin(discoveredPackage)
		});
		return resolvedPackages;
	}
	async collectPackageRoots(nodeModulesRoot) {
		try {
			const entries = await readdir(nodeModulesRoot, { withFileTypes: true });
			const packageRoots = [];
			for (const entry of entries) {
				if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
				if (entry.name.startsWith("@")) {
					const scopedEntries = await readdir(path.resolve(nodeModulesRoot, entry.name), { withFileTypes: true });
					for (const scopedEntry of scopedEntries) if (scopedEntry.isDirectory() || scopedEntry.isSymbolicLink()) packageRoots.push(path.resolve(nodeModulesRoot, entry.name, scopedEntry.name));
					continue;
				}
				packageRoots.push(path.resolve(nodeModulesRoot, entry.name));
			}
			return packageRoots;
		} catch {
			return [];
		}
	}
	async readPackageJson(packageJsonPath) {
		try {
			const rawPackageJson = await readFile(packageJsonPath, "utf8");
			return JSON.parse(rawPackageJson);
		} catch {
			return {};
		}
	}
	async loadPlugin(discoveredPackage) {
		const pluginModulePath = path.resolve(discoveredPackage.packageRoot, this.resolvePluginEntry(discoveredPackage));
		const exportedValue = (await import(
			/* webpackIgnore: true */
			this.resolvePluginModuleSpecifier(pluginModulePath)
)).default;
		const plugin = this.resolvePluginValue(exportedValue);
		if (!plugin) throw new Error(`Plugin package "${discoveredPackage.packageName}" did not default-export a Codemation plugin.`);
		return this.pluginPackageMetadata.attachPackageName(plugin, discoveredPackage.packageName);
	}
	resolvePluginValue(value) {
		if (this.isPluginConfig(value)) return value;
		return null;
	}
	isPluginConfig(value) {
		if (!value || typeof value !== "object" || Array.isArray(value)) return false;
		const pluginValue = value;
		if (pluginValue.register !== void 0 && typeof pluginValue.register !== "function") return false;
		if (pluginValue.credentialTypes !== void 0 && !Array.isArray(pluginValue.credentialTypes)) return false;
		if (pluginValue.mcpServers !== void 0 && !Array.isArray(pluginValue.mcpServers)) return false;
		return pluginValue.register !== void 0 || pluginValue.credentialTypes !== void 0 || pluginValue.mcpServers !== void 0 || pluginValue.sandbox !== void 0 || Object.keys(pluginValue).length === 0;
	}
	resolvePluginEntry(discoveredPackage) {
		return process.env.CODEMATION_PREFER_PLUGIN_SOURCE_ENTRY === "true" && typeof discoveredPackage.developmentEntry === "string" && discoveredPackage.developmentEntry.trim().length > 0 ? discoveredPackage.developmentEntry : discoveredPackage.pluginEntry;
	}
	async resolveDevelopmentPluginEntry(packageRoot) {
		const candidates = [
			path.resolve(packageRoot, "codemation.plugin.ts"),
			path.resolve(packageRoot, "codemation.plugin.js"),
			path.resolve(packageRoot, "src", "codemation.plugin.ts"),
			path.resolve(packageRoot, "src", "codemation.plugin.js")
		];
		for (const candidate of candidates) if (await this.exists(candidate)) return path.relative(packageRoot, candidate);
	}
	async exists(filePath) {
		try {
			await readFile(filePath, "utf8");
			return true;
		} catch {
			return false;
		}
	}
	resolvePluginModuleSpecifier(pluginModulePath) {
		return pathToFileURL(pluginModulePath).href;
	}
};

//#endregion
export { AppConfigLoader as n, CodemationServerGateway as r, CodemationPluginDiscovery as t };
//# sourceMappingURL=server-BlG9qV5S.js.map