Luigit
repositories / pi-ext

pi-ext

bugabingas pi extensions

owned by admin

extensions/ultra/implementation.ts

Raw
// ultra runtime: loaded only when the human invokes or completes /ultra.

import { dirname, resolve } from "node:path";
import {
	createAgentSession,
	DefaultPackageManager,
	DefaultResourceLoader,
	type ExtensionAPI,
	type ExtensionCommandContext,
	type ExtensionContext,
	getAgentDir,
	parseArgs,
	SessionManager,
	SettingsManager,
} from "@earendil-works/pi-coding-agent";
import { Type } from "typebox";
import { createActionSummarizer } from "./action-summarizer.ts";
import { renderUltraCall } from "./call.ts";
import { formatUsage } from "./display.ts";
import {
	BUILTIN_TOOL_NAMES,
	extensionLabel,
	loadSubagentFlagCatalog,
	makeResolveModel,
	makeSessionFactory,
	makeSubagentSessionManager,
	type SessionFactoryDeps,
	type SubagentFlagEntry,
	subagentFlagPrompt,
} from "./drivers.ts";
import type { DynamicExtensionResolver } from "./dynamic-types.ts";
import { runWorkflow, type WorkflowResult } from "./engine.ts";
import {
	createSessionWorkflowJournal,
	type SessionWorkflowJournal,
} from "./journal.ts";
import { initialReducerState } from "./progress.ts";
import {
	type BaseStepOptions,
	makeStepRunner,
	type RunnerContext,
	resolveModelTier,
	type StepDrivers,
	type StepRunner,
} from "./runner.ts";
import {
	effectiveModelTiers,
	loadUltraSettings,
	type UltraSettings,
} from "./settings.ts";
import {
	DYNAMIC_EXTENSION_TOOL_NAMES,
	discoverWorkflowCatalog,
	missingWorkflowTools,
	type WorkflowCatalog,
	type WorkflowSpec,
	WorkflowSpecSchema,
	workflowUsesDynamicExtensions,
} from "./spec.ts";
import { span } from "./src/debug.ts";
import { renderUltraResult, UltraOverlayComponent } from "./ui.ts";
import {
	type AutocompleteItem,
	completeUltraCommand,
	formatWorkflowToolResult,
	makeToolProgressSink,
	parseCommandLine,
	parseUltraCommand,
	resolveWorkflowInput,
} from "./wire.ts";

export interface UltraRuntime {
	activateWorkflowTool(): void;
	subagentFlagSection(ctx: ExtensionContext): Promise<string | undefined>;
	getArgumentCompletions(
		prefix: string,
		projectTrusted: boolean,
	): AutocompleteItem[] | null;
	handleCommand(
		argString: string,
		ctx: ExtensionCommandContext,
	): Promise<
		| "completed"
		| "incomplete"
		| "aborted"
		| "disabled"
		| "invalid"
		| "failed"
		| "skipped"
	>;
}

/** Pi's initial built-in selection when no `tools` allowlist or `defaultTools` setting applies. */
const PI_DEFAULT_ACTIVE_TOOLS: ReadonlySet<string> = new Set([
	"read",
	"bash",
	"edit",
	"write",
]);

interface SubagentExtensionSelection {
	all: boolean;
	paths: string[];
	pathKeys: Set<string>;
}

function pathKey(path: string): string {
	const absolute = resolve(path).replaceAll("\\", "/");
	return process.platform === "win32" ? absolute.toLowerCase() : absolute;
}

function notifyWorkflowCompletion(
	ctx: ExtensionContext,
	result: WorkflowResult,
): void {
	if (!ctx.hasUI) return;
	const dropped = result.phases.reduce(
		(count, phase) => count + phase.dropped,
		0,
	);
	const status = result.aborted
		? "aborted"
		: dropped > 0
			? "incomplete"
			: "complete";
	const usage = formatUsage(result.tokenUsage).summary;
	ctx.ui.notify(
		`ultra: "${result.workflow}" ${status} · ${result.phases.length} phases · ${usage}.`,
		status === "complete" ? "info" : "warning",
	);
}

export async function resolveSubagentExtensions(
	setting: UltraSettings["subagentExtensions"],
	options: {
		cwd: string;
		agentDir: string;
		projectTrusted: boolean;
	},
): Promise<SubagentExtensionSelection> {
	if (setting === "all") return { all: true, paths: [], pathKeys: new Set() };
	if (setting === "none") return { all: false, paths: [], pathKeys: new Set() };
	const settingsManager = SettingsManager.create(
		options.cwd,
		options.agentDir,
		{
			projectTrusted: options.projectTrusted,
		},
	);
	const packages = new DefaultPackageManager({
		cwd: options.cwd,
		agentDir: options.agentDir,
		settingsManager,
	});
	const paths = new Set<string>();
	for (const source of setting) {
		const resolved = await packages.resolveExtensionSources([source], {
			temporary: true,
		});
		const enabled = resolved.extensions.filter(
			(extension) => extension.enabled,
		);
		if (!enabled.length) {
			if (/^[a-z0-9][a-z0-9-]*$/u.test(source))
				throw new Error(
					`ultra: subagentExtensions no longer accepts bare extension nickname "${source}"; replace it with a Pi extension source path or package source.`,
				);
			throw new Error(
				`ultra: no enabled extensions resolved from ${JSON.stringify(source)}`,
			);
		}
		for (const extension of enabled) paths.add(extension.path);
	}
	return {
		all: false,
		paths: [...paths],
		pathKeys: new Set([...paths].map(pathKey)),
	};
}

export function createUltraRuntime(pi: ExtensionAPI): UltraRuntime {
	const settings = (ctx: ExtensionContext): UltraSettings => {
		const cfg = loadUltraSettings(pi, ctx);
		return {
			...cfg,
			modelTiers: effectiveModelTiers(cfg, ctx.model?.provider),
		};
	};

	// Workflow files are tiny and human-authored during live sessions. Rescan at
	// each use so a newly saved workflow immediately works without `/reload`.
	// Project workflows are repo-controlled: an untrusted project never
	// contributes runnable workflows (see `discoverWorkflowCatalog`).
	const discover = (cwd: string, projectTrusted: boolean): WorkflowCatalog =>
		discoverWorkflowCatalog(cwd, projectTrusted);

	const activateWorkflowTool = () => {
		const active = pi.getActiveTools();
		if (!active.includes("run_workflow")) {
			pi.setActiveTools([...active, "run_workflow"]);
		}
	};

	const deactivateWorkflowTool = () => {
		const active = pi.getActiveTools();
		if (active.includes("run_workflow")) {
			pi.setActiveTools(active.filter((name) => name !== "run_workflow"));
		}
	};

	const availableSubagentTools = (
		extensions: SubagentExtensionSelection,
	): string[] =>
		pi
			.getAllTools()
			.filter(
				(tool) =>
					tool.name !== "run_workflow" &&
					(extensions.all ||
						BUILTIN_TOOL_NAMES.has(tool.name) ||
						extensions.pathKeys.has(pathKey(tool.sourceInfo.path))),
			)
			.map((tool) => tool.name);

	// One extension load per cwd and selection; children load the same set per step.
	const flagCatalogs = new Map<
		string,
		ReturnType<typeof loadSubagentFlagCatalog>
	>();
	const subagentFlagCatalog = async (ctx: ExtensionContext) => {
		const extensions = await resolveSubagentExtensions(
			settings(ctx).subagentExtensions,
			{
				cwd: ctx.cwd,
				agentDir: getAgentDir(),
				projectTrusted: ctx.isProjectTrusted(),
			},
		);
		const key = JSON.stringify([ctx.cwd, extensions.all, extensions.paths]);
		let catalog = flagCatalogs.get(key);
		if (!catalog) {
			catalog = loadSubagentFlagCatalog({
				DefaultResourceLoader:
					DefaultResourceLoader as unknown as SessionFactoryDeps["DefaultResourceLoader"],
				getAgentDir,
				cwd: ctx.cwd,
				loadExtensions: extensions.all,
				extensionPaths: extensions.paths,
			});
			flagCatalogs.set(key, catalog);
			// A failed load is retried on the next turn instead of being cached.
			catalog.catch(() => flagCatalogs.delete(key));
		}
		return catalog;
	};

	// Children inherit this Pi's CLI flags, so a tool an extension switched off
	// here at startup is switched off in every child too. Refuse before creating
	// any child unless the step sets its own flags (then the child-startup check
	// in drivers.ts is the authority). Pi activates its default builtins and
	// every extension tool at startup; the remaining builtins (grep, find, ls,
	// powershell) are inactive by default and say nothing about extensions, and
	// children activate them explicitly.
	const inactiveToolsError = async (
		ctx: ExtensionContext,
		spec: WorkflowSpec,
	): Promise<string | undefined> => {
		const all = new Set(pi.getAllTools().map((tool) => tool.name));
		const active = new Set(pi.getActiveTools());
		const activeByDefault = (name: string) =>
			!BUILTIN_TOOL_NAMES.has(name) || PI_DEFAULT_ACTIVE_TOOLS.has(name);
		const inactive = [
			...new Set(
				spec.phases
					.filter((phase) => phase.step.flags === undefined)
					.flatMap((phase) => phase.step.tools ?? [])
					.filter(
						(name) =>
							name !== "run_workflow" &&
							all.has(name) &&
							!active.has(name) &&
							activeByDefault(name),
					),
			),
		];
		if (inactive.length === 0) return undefined;
		const catalog = await Promise.resolve()
			.then(() => subagentFlagCatalog(ctx))
			.catch((): SubagentFlagEntry[] => []);
		const candidates = catalog
			.filter((entry) => entry.flags.length > 0)
			.map(
				(entry) =>
					`${entry.extension} (${entry.flags
						.map(
							(flag) =>
								`--${flag.name}${flag.description ? `: ${flag.description}` : ""}`,
						)
						.join(", ")})`,
			);
		const shellInactive = inactive.some(
			(name) => name === "bash" || name === "powershell",
		);
		return [
			`ultra: step tools are inactive in this Pi and children inherit its flags: ${inactive.join(", ")}.`,
			...(candidates.length
				? [
						`Possibly deactivated by an extension with startup flags: ${candidates.join("; ")}.`,
					]
				: []),
			"Use an active alternative or set step.flags.",
			...(shellInactive && active.has("nu")
				? ["The nu tool is active; prefer it."]
				: []),
		].join(" ");
	};

	const workflowError = async (
		ctx: ExtensionContext,
		spec: WorkflowSpec,
		extensions: SubagentExtensionSelection,
		cfg: UltraSettings,
	): Promise<string | undefined> => {
		const cwd = ctx.cwd;
		try {
			for (const phase of spec.phases)
				resolveModelTier(phase.step, cfg.modelTiers);
		} catch (error) {
			return error instanceof Error ? error.message : String(error);
		}
		const available = [
			...availableSubagentTools(extensions),
			...DYNAMIC_EXTENSION_TOOL_NAMES,
		];
		const missing = missingWorkflowTools(spec, available);
		if (missing.length === 0) return inactiveToolsError(ctx, spec);
		const owners = pi
			.getAllTools()
			.filter((tool) => missing.includes(tool.name));
		const selectedEntriesForOwner = (ownerPath: string): string[] =>
			extensions.paths.filter(
				(path) =>
					pathKey(path) !== pathKey(ownerPath) &&
					pathKey(dirname(path)) === pathKey(dirname(ownerPath)),
			);
		const inspectionPaths = new Set<string>();
		const details = [
			`ultra: workflow "${spec.name}" requires unavailable tools: ${missing.join(", ")}`,
			...missing.map((name) => {
				const owner = owners.find((tool) => tool.name === name);
				if (!owner)
					return `${name}: no registered owning extension; check step.tools and installed extensions.`;
				const ownerPath = owner.sourceInfo.path;
				const selectedEntries = selectedEntriesForOwner(ownerPath);
				if (selectedEntries.length) {
					for (const path of selectedEntries) inspectionPaths.add(path);
					return `${name}: loaded owning extension "${extensionLabel(ownerPath)}" at ${JSON.stringify(ownerPath)} does not match selected extension entries ${selectedEntries.map((path) => JSON.stringify(path)).join(", ")}; runtime may be stale or explicit selection differs. Reload/restart Pi and verify the selected entry; do not blindly add the obsolete loaded path.`;
				}
				inspectionPaths.add(ownerPath);
				const label = extensionLabel(ownerPath);
				return `${name}: owning extension "${label}" is excluded by ultra.subagentExtensions; include ${JSON.stringify(ownerPath)} in that setting before using its step.flags.`;
			}),
		];
		if (inspectionPaths.size > 0) {
			try {
				const catalog = await loadSubagentFlagCatalog({
					DefaultResourceLoader:
						DefaultResourceLoader as unknown as SessionFactoryDeps["DefaultResourceLoader"],
					getAgentDir,
					cwd,
					extensionPaths: [...inspectionPaths],
				});
				if (catalog.length) details.push(subagentFlagPrompt(catalog));
			} catch (error) {
				details.push(
					`Could not inspect startup flags: ${error instanceof Error ? error.message : String(error)}`,
				);
			}
		}
		return details.join("\n");
	};

	const createJournal = (
		ctx: ExtensionContext,
		spec: WorkflowSpec,
		cfg: UltraSettings,
		args?: Record<string, unknown>,
	) =>
		createSessionWorkflowJournal({
			cwd: ctx.cwd,
			spec,
			args,
			modelRouting: spec.phases.map(({ step }) => {
				const resolved = resolveModelTier(step, cfg.modelTiers);
				return {
					model:
						resolved.model ??
						(ctx.model ? `${ctx.model.provider}/${ctx.model.id}` : undefined),
					thinkingLevel: resolved.thinkingLevel,
				};
			}),
			entries: ctx.sessionManager.getBranch(),
			appendEntry: (customType, data) => pi.appendEntry(customType, data),
		});

	// Assemble a real `StepRunner` from the injected SDK drivers + this ctx.
	const buildStepRunner = (
		ctx: ExtensionContext,
		spec: WorkflowSpec,
		cfg: UltraSettings,
		journal: SessionWorkflowJournal,
		extensions: SubagentExtensionSelection,
		dynamicExtensions?: DynamicExtensionResolver,
	): StepRunner => {
		// The injected-dep types are deliberately broader than the SDK's specific
		// signatures (so the factories unit-test with simple fakes); the real SDK
		// values are adapted to them here at the boundary. Runtime correctness of
		// these calls is the Task-10 live gate.
		const drivers: StepDrivers = {
			sessionFactory: makeSessionFactory({
				createAgentSession:
					createAgentSession as unknown as SessionFactoryDeps["createAgentSession"],
				DefaultResourceLoader:
					DefaultResourceLoader as unknown as SessionFactoryDeps["DefaultResourceLoader"],
				getAgentDir,
				cwd: ctx.cwd,
				loadExtensions: extensions.all,
				extensionPaths: extensions.paths,
				loadSkills: cfg.subagentSkills === "all",
				// Children inherit the parent's CLI extension flags, parsed exactly as Pi parses them.
				inheritedFlags: parseArgs(process.argv.slice(2)).unknownFlags,
			}),
			resolveModel: makeResolveModel({
				modelRegistry: ctx.modelRegistry,
				defaultModel: ctx.model,
			}),
		};
		const manageSubagentSession = makeSubagentSessionManager({
			SessionManager,
			cwd: ctx.cwd,
			parentSession: ctx.sessionManager.getSessionFile(),
			sessionDir: ctx.sessionManager.getSessionDir(),
			retention: cfg.subagentSessionRetention,
		});
		const ctxLike: RunnerContext = {
			newSessionManager(sessionKey, agentId) {
				const retained = journal.getSession(sessionKey);
				const child = manageSubagentSession({
					name: `ultra ${spec.name} ${journal.id.slice(0, 8)} ${agentId}`,
					retained,
				});
				if (
					child.ref &&
					(!retained ||
						child.ref.id !== retained.id ||
						child.ref.path !== retained.path)
				)
					journal.setSession(sessionKey, child.ref);
				return child;
			},
		};
		const baseOpts: BaseStepOptions = {
			maxRetries: cfg.maxRetries,
			schemas: spec.schemas,
			modelTiers: cfg.modelTiers,
			actionSummarizer: createActionSummarizer(ctx, cfg.actionSummarizerModel),
			dynamicExtensionResolver: dynamicExtensions,
		};
		return makeStepRunner(drivers, ctxLike, baseOpts);
	};

	const dynamicResolver = async (
		ctx: ExtensionContext,
		spec: WorkflowSpec,
		journal: SessionWorkflowJournal,
	): Promise<DynamicExtensionResolver | undefined> => {
		if (!workflowUsesDynamicExtensions(spec)) return undefined;
		const { createDynamicExtensionCoordinator } = await import(
			"./dynamic-catalog.ts"
		);
		return createDynamicExtensionCoordinator({
			agentDir: getAgentDir(),
			parentSessionId: ctx.sessionManager.getSessionId(),
			workflowRunId: journal.id,
		});
	};

	const prepareRun = async (
		ctx: ExtensionContext,
		spec: WorkflowSpec,
		cfg: UltraSettings,
		args: Record<string, unknown> | undefined,
		extensions: SubagentExtensionSelection,
	): Promise<{
		journal: SessionWorkflowJournal;
		dynamicExtensions?: DynamicExtensionResolver | undefined;
		stepRunner: StepRunner;
	}> => {
		const journal = createJournal(ctx, spec, cfg, args);
		const dynamicExtensions = await dynamicResolver(ctx, spec, journal);
		return {
			journal,
			dynamicExtensions,
			stepRunner: buildStepRunner(
				ctx,
				spec,
				cfg,
				journal,
				extensions,
				dynamicExtensions,
			),
		};
	};

	// ── `run_workflow` tool (model-callable, mid-turn, read-only onUpdate surface) ──
	pi.registerTool({
		name: "run_workflow",
		label: "run_workflow",
		exposure: "model-only",
		annotations: { readOnlyHint: false },
		description:
			"run saved or inline multi-agent workflows. An inline spec takes precedence when both spec and name are supplied; args provide workflow inputs. " +
			"return selected output, failures, usage, and fullOutputPath for complete evidence; results above 50KB or 2000 lines return a bounded file reference.",
		promptSnippet: "run saved or inline multi-agent workflows.",
		promptGuidelines: [
			"Use run_workflow when decomposition into independent or sequential child-agent steps reduces context or verification risk.",
			"Use dynamic extensions when a workflow needs a reusable, task-specific capability; read the ultra-authoring skill for how to build and load them.",
		],
		parameters: Type.Object({
			name: Type.Optional(
				Type.String({
					description: "Saved workflow name (project/global/bundled).",
				}),
			),
			spec: Type.Optional(WorkflowSpecSchema),
			args: Type.Optional(
				Type.Record(Type.String(), Type.Unknown(), {
					description: "Workflow inputs, available as {args.NAME}.",
				}),
			),
		}),
		renderCall: renderUltraCall,
		renderResult: renderUltraResult,
		async execute(_toolCallId, params, signal, onUpdate, ctx) {
			const finish = span?.("workflow.execute");
			try {
				const cfg = settings(ctx);
				if (!cfg.enabled) {
					finish?.("finish", { outcome: "disabled" });
					return {
						content: [
							{
								type: "text",
								text: "ultra is disabled (ultra.enabled = false).",
							},
						],
						details: initialReducerState(),
					};
				}
				const catalog = discover(ctx.cwd, ctx.isProjectTrusted());
				const { spec, args } = resolveWorkflowInput(
					params,
					catalog.available,
					undefined,
					cfg.fanoutToolAllowlist,
					catalog.refused,
				);
				const extensions = await resolveSubagentExtensions(
					cfg.subagentExtensions,
					{
						cwd: ctx.cwd,
						agentDir: getAgentDir(),
						projectTrusted: ctx.isProjectTrusted(),
					},
				);
				const error = await workflowError(ctx, spec, extensions, cfg);
				if (error) throw new Error(error);
				const prepared = await prepareRun(ctx, spec, cfg, args, extensions);
				// onProgress folds into the reducer + pushes through `onUpdate`; headless
				// (no `onUpdate`) degrades to a no-op sink that still tracks final state.
				const progress = makeToolProgressSink(onUpdate ?? (() => {}), {
					workflowName: spec.name,
					workflowDescription: spec.description,
				});
				const result = await runWorkflow(spec, args, {
					stepRunner: prepared.stepRunner,
					concurrency: cfg.concurrency,
					journal: prepared.journal,
					dynamicExtensions: prepared.dynamicExtensions,
					signal, // the SDK execute() signal: stops the pool + fans session.abort()
					onProgress: progress.sink,
				});
				const output = await formatWorkflowToolResult(result);
				notifyWorkflowCompletion(ctx, result);
				finish?.("finish", {
					outcome: result.aborted
						? "aborted"
						: result.phases.some((phase) => phase.dropped > 0)
							? "incomplete"
							: "completed",
				});
				return {
					content: [{ type: "text", text: output.text }],
					details: {
						...progress.finish({
							...result,
							fullOutputPath: output.fullOutputPath,
						}),
						fullOutputPath: output.fullOutputPath,
					},
					terminate: false, // the agent keeps reasoning over the results
				};
			} catch (error) {
				finish?.("error", { outcome: "failed" });
				throw error;
			}
		},
	});

	deactivateWorkflowTool();

	const sendExecPrompt = (request: string) => {
		activateWorkflowTool();
		pi.sendUserMessage(`# ultra exec\n\n# user request\n\n${request}`);
	};

	// ── `/ultra [exec | run]` command ──
	return {
		activateWorkflowTool,
		/** Undefined when no sub-agent extension owns both tools and flags, or loading failed. */
		subagentFlagSection: async (ctx: ExtensionContext) => {
			const catalog = await subagentFlagCatalog(ctx).catch(() => []);
			return catalog.length ? subagentFlagPrompt(catalog) : undefined;
		},
		getArgumentCompletions: (prefix: string, projectTrusted: boolean) =>
			completeUltraCommand(
				discover(process.cwd(), projectTrusted).available,
				prefix,
			),
		handleCommand: async (argString: string, ctx: ExtensionCommandContext) => {
			const cfg = settings(ctx);
			if (!cfg.enabled) {
				if (ctx.hasUI)
					ctx.ui.notify(
						"ultra is disabled (ultra.enabled = false).",
						"warning",
					);
				return "disabled";
			}
			// The command surface is the focus-grabbing overlay — interactive only.
			// Headless / non-UI callers use the `run_workflow` tool instead.
			if (!ctx.hasUI) {
				return "skipped";
			}
			const command = parseUltraCommand(argString);
			if (command.subcommand === "activate") {
				activateWorkflowTool();
				ctx.ui.notify("ultra: run_workflow tool enabled.", "info");
				return "completed";
			}
			if (command.subcommand === "exec") {
				sendExecPrompt(command.instructions);
				return "completed";
			}
			if (command.subcommand === "invalid") {
				ctx.ui.notify(
					"Usage: /ultra | /ultra exec <instructions> | /ultra run <workflow> [args]",
					"warning",
				);
				return "invalid";
			}

			const catalog = discover(ctx.cwd, ctx.isProjectTrusted());
			const parsed = parseCommandLine(command.invocation);
			let resolved: {
				spec: WorkflowSpec;
				args?: Record<string, unknown> | undefined;
			};
			try {
				resolved = resolveWorkflowInput(
					{ name: parsed.name, args: parsed.args },
					catalog.available,
					parsed.rest,
					cfg.fanoutToolAllowlist,
					catalog.refused,
				);
			} catch (err) {
				ctx.ui.notify(
					err instanceof Error ? err.message : String(err),
					"error",
				);
				return "invalid";
			}
			const { spec, args: runArgs } = resolved;
			let extensions: SubagentExtensionSelection;
			try {
				extensions = await resolveSubagentExtensions(cfg.subagentExtensions, {
					cwd: ctx.cwd,
					agentDir: getAgentDir(),
					projectTrusted: ctx.isProjectTrusted(),
				});
			} catch (error) {
				ctx.ui.notify(
					error instanceof Error ? error.message : String(error),
					"error",
				);
				return "failed";
			}
			const error = await workflowError(ctx, spec, extensions, cfg);
			if (error) {
				ctx.ui.notify(error, "error");
				return "invalid";
			}
			const prepared = await prepareRun(ctx, spec, cfg, runArgs, extensions);

			// The command owns its AbortController (idle ⇒ ctx.signal is undefined).
			// Global Esc / per-agent abort fire it; the engine fans session.abort().
			const controller = new AbortController();
			const outcome = await ctx.ui.custom<
				| { status: "completed"; result: WorkflowResult }
				| { status: "aborted"; result?: WorkflowResult }
				| { status: "failed"; message: string }
				| null
			>(
				(tui, theme, keybindings, done) => {
					const overlay = new UltraOverlayComponent({
						host: tui,
						theme,
						onRunAbort: () => controller.abort(),
						workflowName: spec.name,
						workflowDescription: spec.description,
						toolUi: tui,
						toolsExpanded: () => ctx.ui.getToolsExpanded(),
						hideToolPreviews: cfg.actionSummarizerModel !== null,
						isToolsExpandKey: (data) =>
							keybindings.matches(data, "app.tools.expand"),
						onToolsExpand: () =>
							ctx.ui.setToolsExpanded(!ctx.ui.getToolsExpanded()),
						cwd: ctx.cwd,
					});
					// P3: return the Component SYNCHRONOUSLY; run the engine DETACHED, or
					// the overlay never renders. `done` resolves the custom() promise.
					void (async () => {
						try {
							const r = await runWorkflow(spec, runArgs, {
								stepRunner: prepared.stepRunner,
								concurrency: cfg.concurrency,
								journal: prepared.journal,
								dynamicExtensions: prepared.dynamicExtensions,
								signal: controller.signal,
								onProgress: (e) => overlay.handleProgress(e),
							});
							done(
								controller.signal.aborted
									? { status: "aborted", result: r }
									: { status: "completed", result: r },
							);
						} catch (error) {
							done(
								controller.signal.aborted
									? { status: "aborted" }
									: {
											status: "failed",
											message:
												error instanceof Error ? error.message : String(error),
										},
							);
						}
					})();
					return overlay;
				},
				{
					overlay: true,
					overlayOptions: {
						anchor: "bottom-left",
						width: "100%",
						maxHeight: "100%",
					},
				},
			);

			if (!outcome) {
				ctx.ui.notify(`ultra: "${spec.name}" aborted.`, "warning");
				return "aborted";
			}
			if (outcome.status === "failed") {
				ctx.ui.notify(outcome.message, "error");
				return "failed";
			}
			const result = outcome.result;
			if (!result) {
				ctx.ui.notify(`ultra: "${spec.name}" aborted.`, "warning");
				return "aborted";
			}
			const output = await formatWorkflowToolResult(result);
			pi.sendMessage({
				customType: "ultra-result",
				content: output.text,
				display: true,
				details: { ...result, fullOutputPath: output.fullOutputPath },
			});
			notifyWorkflowCompletion(ctx, result);
			return result.aborted
				? "aborted"
				: result.phases.some((phase) => phase.dropped > 0)
					? "incomplete"
					: "completed";
		},
	};
}