import { init_agent_scope, resolveDefaultAgentId } from "../../../agent/agent-scope.js";
import { extractProfileAgentId } from "../../../config/agent-profile.js";
import { init_providers, resolveModel } from "../../../providers/index.js";
import { createWorkflowCatalog } from "../../../agent/workflow/catalog.js";
import { DelegateSubagentRunner } from "../../../agent/workflow/subagent-runner.js";
import { resolveModelRef } from "../../../config/agent-typed-models.js";
import { AgentToolsFactory } from "../../../agent/tools/factory.js";
import { isTerminalWorkflowRunStatus } from "../../../workflows/domain/run.js";
import { WorkflowEngine } from "../../../workflows/engine/workflow-engine.js";
import { WorkflowEventStore } from "../../../workflows/store/event-store.js";
import { WorkflowRunStore } from "../../../workflows/store/run-store.js";
import "../../../workflows/index.js";
import { randomUUID } from "node:crypto";
//#region src/gateway/hono/routes/workflows.ts
init_agent_scope();
init_providers();
const DEFAULT_WORKFLOW_CONCURRENCY = 4;
const DEFAULT_WORKFLOW_TIMEOUT_SEC = 1800;
const DEFAULT_WORKFLOW_MAX_SUBAGENTS = 100;
const activeWorkflowRuns = /* @__PURE__ */ new Map();
function registerWorkflowRoutes(authenticated, deps) {
	const { service } = deps;
	authenticated.get("/api/workflows/definitions", (c) => {
		const catalog = createWorkflowCatalog();
		const definitions = catalog.list().map((entry) => {
			try {
				return toWorkflowDefinition(catalog.load(entry.name));
			} catch {
				return null;
			}
		}).filter((definition) => Boolean(definition));
		return c.json({ definitions });
	});
	authenticated.get("/api/workflows/definitions/:id", (c) => {
		const id = c.req.param("id");
		const catalog = createWorkflowCatalog();
		try {
			const definition = toWorkflowDefinition(catalog.load(id));
			return c.json({ definition });
		} catch (err) {
			return c.json({ error: err instanceof Error ? err.message : "Workflow definition not found" }, 404);
		}
	});
	authenticated.post("/api/workflows/definitions", async (c) => {
		const body = await readJsonBody(c.req.raw);
		const name = body.name?.trim();
		const script = body.script?.trim();
		if (!name) return c.json({ error: "name is required" }, 400);
		if (!script) return c.json({ error: "script is required" }, 400);
		const catalog = createWorkflowCatalog();
		try {
			catalog.save(name, script);
			const definition = toWorkflowDefinition(catalog.load(name));
			return c.json({ definition }, 201);
		} catch (err) {
			return c.json({ error: err instanceof Error ? err.message : "Failed to save workflow" }, 400);
		}
	});
	authenticated.delete("/api/workflows/definitions/:id", (c) => {
		const id = c.req.param("id").trim();
		if (!id) return c.json({ error: "id is required" }, 400);
		const catalog = createWorkflowCatalog();
		try {
			if (!catalog.remove(id)) return c.json({ error: "User workflow not found or cannot delete built-in workflow" }, 404);
			return c.json({ removed: true });
		} catch (err) {
			return c.json({ error: err instanceof Error ? err.message : "Failed to delete workflow" }, 400);
		}
	});
	authenticated.get("/api/workflows/stats", async (c) => {
		const agentId = getAgentId(c.req.query("agentId"), service.currentConfig);
		const runs = await createRunStore(service.currentConfig, agentId).listRunSummaries(500);
		return c.json({ stats: buildWorkflowStats(runs) });
	});
	authenticated.post("/api/workflows/runs", async (c) => {
		const body = await readJsonBody(c.req.raw);
		const definitionId = body.definitionId?.trim();
		if (!definitionId) return c.json({ error: "definitionId is required" }, 400);
		const agentId = getAgentId(body.agentId ?? c.req.query("agentId"), service.currentConfig);
		const runId = await queueWorkflowRun({
			deps,
			agentId,
			sessionKey: body.sessionKey?.trim() || `workflow:${agentId}`,
			definitionId,
			input: body.input,
			goal: body.goal,
			source: body.source ?? { kind: "webui" },
			concurrency: normalizePositiveInteger(body.concurrency),
			maxSubagents: normalizePositiveInteger(body.maxSubagents),
			tokenBudget: body.tokenBudget
		});
		if (!runId) return c.json({ error: "Workflow definition not found" }, 404);
		return c.json({ runId }, 202);
	});
	authenticated.get("/api/workflows/runs", async (c) => {
		const agentId = getAgentId(c.req.query("agentId"), service.currentConfig);
		const rawLimit = c.req.query("limit");
		const limit = rawLimit ? Number.parseInt(rawLimit, 10) : 50;
		const runs = await createRunStore(service.currentConfig, agentId).listRunSummaries(Number.isFinite(limit) ? limit : 50);
		return c.json({ runs });
	});
	authenticated.post("/api/workflows/runs/:runId/cancel", async (c) => {
		const runId = c.req.param("runId");
		const agentId = getAgentId(c.req.query("agentId"), service.currentConfig);
		const runStore = createRunStore(service.currentConfig, agentId);
		const controller = activeWorkflowRuns.get(runId);
		if (controller) {
			controller.abort();
			activeWorkflowRuns.delete(runId);
			return c.json({ cancelled: true });
		}
		const view = await runStore.readRunView(runId);
		if (!view) return c.json({ error: "Workflow run not found" }, 404);
		if (isTerminalWorkflowRunStatus(view.run.status)) return c.json({
			cancelled: true,
			alreadyFinished: true
		});
		await new WorkflowEventStore(service.currentConfig, agentId).append({
			runId,
			type: "run_cancelled",
			payload: { reason: "Cancelled by user" }
		});
		const updated = await runStore.rebuildRunView(runId);
		if (updated) service.emit("workflow.run.updated", {
			runId,
			view: updated
		});
		return c.json({ cancelled: true });
	});
	authenticated.get("/api/workflows/runs/:runId", async (c) => {
		const agentId = getAgentId(c.req.query("agentId"), service.currentConfig);
		const runId = c.req.param("runId");
		const view = await createRunStore(service.currentConfig, agentId).readRunView(runId);
		if (!view) return c.json({ error: "Workflow run not found" }, 404);
		return c.json({ view });
	});
	authenticated.post("/api/workflows/runs/:runId/rebuild", async (c) => {
		const agentId = getAgentId(c.req.query("agentId"), service.currentConfig);
		const runId = c.req.param("runId");
		const view = await createRunStore(service.currentConfig, agentId).rebuildRunView(runId);
		if (!view) return c.json({ error: "Workflow run not found" }, 404);
		service.emit("workflow.run.updated", {
			runId,
			view
		});
		return c.json({ view });
	});
	authenticated.post("/api/workflows/runs/:runId/retry", async (c) => {
		const agentId = getAgentId(c.req.query("agentId"), service.currentConfig);
		const runId = c.req.param("runId");
		const existing = await createRunStore(service.currentConfig, agentId).readRunView(runId);
		if (!existing) return c.json({ error: "Workflow run not found" }, 404);
		const newRunId = await queueWorkflowRun({
			deps,
			agentId,
			sessionKey: `workflow:${agentId}`,
			definitionId: existing.run.definitionId,
			input: existing.run.input,
			goal: existing.run.goal,
			source: { kind: "webui" }
		});
		if (!newRunId) return c.json({ error: "Workflow definition not found" }, 404);
		return c.json({ runId: newRunId }, 202);
	});
}
function createRunStore(config, agentId) {
	return new WorkflowRunStore(config, agentId, new WorkflowEventStore(config, agentId));
}
function getAgentId(rawAgentId, config) {
	const trimmed = rawAgentId?.trim();
	if (trimmed) return trimmed;
	return resolveDefaultAgentId(config);
}
function toWorkflowDefinition(loaded) {
	const nowMs = Date.now();
	const phases = loaded.meta.phases?.map((phase, index) => ({
		id: normalizeId(phase.title) || `phase-${index + 1}`,
		title: phase.title,
		description: phase.detail
	})) ?? [];
	return {
		id: loaded.name,
		name: loaded.name,
		title: toTitle(loaded.name),
		description: loaded.meta.description,
		version: "1.0.0",
		phases,
		runtime: {
			kind: "script",
			source: loaded.script
		},
		defaults: {
			concurrency: DEFAULT_WORKFLOW_CONCURRENCY,
			timeoutSec: DEFAULT_WORKFLOW_TIMEOUT_SEC,
			maxSubagents: loaded.meta.estimatedAgents?.max ?? DEFAULT_WORKFLOW_MAX_SUBAGENTS
		},
		metadata: {
			tags: loaded.meta.tags ?? [],
			builtIn: loaded.source === "builtin",
			source: loaded.source,
			whenToUse: loaded.meta.whenToUse,
			estimatedAgents: loaded.meta.estimatedAgents,
			examplePrompts: loaded.meta.examplePrompts,
			i18n: loaded.meta.i18n,
			createdAtMs: nowMs,
			updatedAtMs: nowMs
		}
	};
}
async function queueWorkflowRun(params) {
	const { deps, agentId, sessionKey, definitionId } = params;
	const { service } = deps;
	const catalog = createWorkflowCatalog();
	let definition;
	try {
		definition = toWorkflowDefinition(catalog.load(definitionId));
	} catch {
		return null;
	}
	const eventStore = new WorkflowEventStore(service.currentConfig, agentId);
	const runStore = new WorkflowRunStore(service.currentConfig, agentId, eventStore);
	const runId = randomUUID();
	const abortController = new AbortController();
	const engine = createWorkflowEngine({
		deps,
		eventStore,
		runStore,
		sessionKey
	});
	activeWorkflowRuns.set(runId, abortController);
	engine.startRun(definition, {
		runId,
		input: params.input,
		goal: params.goal,
		source: params.source,
		signal: abortController.signal,
		concurrency: params.concurrency,
		maxSubagents: params.maxSubagents,
		tokenBudget: params.tokenBudget
	}).catch((err) => {
		service.emit("workflow.run.error", {
			runId,
			error: err instanceof Error ? err.message : String(err)
		});
	}).finally(() => {
		activeWorkflowRuns.delete(runId);
	});
	return runId;
}
function buildWorkflowStats(runs) {
	const activeStatuses = new Set(["queued", "running"]);
	const succeededStatuses = new Set(["succeeded"]);
	const failedStatuses = new Set([
		"failed",
		"timeout",
		"cancelled"
	]);
	let durationTotal = 0;
	let durationCount = 0;
	const definitionCounts = /* @__PURE__ */ new Map();
	for (const run of runs) {
		definitionCounts.set(run.definitionId, (definitionCounts.get(run.definitionId) ?? 0) + 1);
		if (run.metrics.durationMs != null && Number.isFinite(run.metrics.durationMs)) {
			durationTotal += run.metrics.durationMs;
			durationCount += 1;
		}
	}
	const topDefinitions = [...definitionCounts.entries()].sort((left, right) => right[1] - left[1]).slice(0, 5).map(([definitionId, count]) => ({
		definitionId,
		count
	}));
	return {
		totalRuns: runs.length,
		activeRuns: runs.filter((run) => activeStatuses.has(run.status)).length,
		succeededRuns: runs.filter((run) => succeededStatuses.has(run.status)).length,
		failedRuns: runs.filter((run) => failedStatuses.has(run.status)).length,
		averageDurationMs: durationCount > 0 ? Math.round(durationTotal / durationCount) : null,
		topDefinitions
	};
}
function createWorkflowEngine(params) {
	const { service } = params.deps;
	const runner = new DelegateSubagentRunner({
		workspace: service.currentWorkspacePath,
		bus: service.messageBusInstance,
		getDefaultModel: () => resolveModel(service.agentService.getModelForSession(params.sessionKey)),
		getConfig: () => service.currentConfig,
		buildChildTools: (childOptions) => buildWorkflowChildTools(childOptions)
	});
	return new WorkflowEngine({
		cwd: service.currentWorkspacePath,
		eventStore: params.eventStore,
		runStore: params.runStore,
		runner,
		resolveModelId: (modelId) => {
			const agentId = extractProfileAgentId(params.sessionKey, service.currentConfig);
			return resolveModel(resolveModelRef(service.currentConfig, agentId, modelId));
		},
		onEventAppended: (event) => {
			service.emit("workflow.event.appended", {
				runId: event.runId,
				event
			});
		},
		onRunViewUpdated: (view) => {
			service.emit("workflow.run.updated", {
				runId: view.run.id,
				view
			});
		}
	});
}
function buildWorkflowChildTools(childOptions) {
	return new AgentToolsFactory({
		workspace: childOptions.workspace,
		bus: childOptions.bus,
		getCurrentContext: () => null,
		getConfig: childOptions.getConfig,
		getPrimaryModel: () => childOptions.model,
		toolExecutorConfig: childOptions.toolExecutorConfig
	}).createAllTools({
		workspace: childOptions.workspace,
		getPrimaryModel: () => childOptions.model,
		disabledTools: new Set(["extensions"])
	});
}
async function readJsonBody(request) {
	try {
		return await request.json();
	} catch {
		return {};
	}
}
function normalizePositiveInteger(value) {
	if (typeof value !== "number" || !Number.isFinite(value) || value < 1) return;
	return Math.floor(value);
}
function normalizeId(value) {
	return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
}
function toTitle(value) {
	return value.split(/[_-]+/g).filter(Boolean).map((part) => `${part.slice(0, 1).toUpperCase()}${part.slice(1)}`).join(" ");
}
//#endregion
export { registerWorkflowRoutes };

//# sourceMappingURL=workflows.js.map