@agimon-ai/doompi-workflow 0.0.1-alpha.97 → 0.0.1-alpha.99
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/README.md +7 -0
- package/dist/apiContracts.cjs +3 -0
- package/dist/apiContracts.cjs.map +1 -1
- package/dist/apiContracts.d.mts.map +1 -1
- package/dist/apiContracts.mjs +3 -0
- package/dist/apiContracts.mjs.map +1 -1
- package/dist/extensions/pi.cjs +102 -644
- package/dist/extensions/pi.cjs.map +1 -1
- package/dist/extensions/pi.d.mts.map +1 -1
- package/dist/extensions/pi.mjs +49 -591
- package/dist/extensions/pi.mjs.map +1 -1
- package/dist/extensions/server.cjs +1718 -608
- package/dist/extensions/server.cjs.map +1 -1
- package/dist/extensions/server.d.mts.map +1 -1
- package/dist/extensions/server.mjs +1720 -610
- package/dist/extensions/server.mjs.map +1 -1
- package/dist/extensions/web.mjs +644 -218
- package/dist/extensions/web.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.mts +10 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{workflowLaunchCommand-Bhr-PvdD.mjs → workflowLaunchCommand-BLrxmzdd.mjs} +14 -7
- package/dist/workflowLaunchCommand-BLrxmzdd.mjs.map +1 -0
- package/dist/{workflowLaunchCommand-7y8xg5YF.cjs → workflowLaunchCommand-DJyDB96d.cjs} +14 -7
- package/dist/workflowLaunchCommand-DJyDB96d.cjs.map +1 -0
- package/dist/workflowTerminal-Bb4bLtLu.cjs +962 -0
- package/dist/workflowTerminal-Bb4bLtLu.cjs.map +1 -0
- package/dist/workflowTerminal-QzufjHCa.mjs +730 -0
- package/dist/workflowTerminal-QzufjHCa.mjs.map +1 -0
- package/package.json +9 -9
- package/src/prompts/doompi-author-workflow/SKILL.md +26 -0
- package/src/prompts/doompi-use-workflow/SKILL.md +1 -1
- package/src/types/webWorkflowTerminal.ts +16 -0
- package/src/types/webWorkflows.ts +20 -0
- package/dist/workflowLaunchCommand-7y8xg5YF.cjs.map +0 -1
- package/dist/workflowLaunchCommand-Bhr-PvdD.mjs.map +0 -1
- package/dist/workflowTerminal-Bj4KKpoA.mjs +0 -148
- package/dist/workflowTerminal-Bj4KKpoA.mjs.map +0 -1
- package/dist/workflowTerminal-WM_cpxIO.cjs +0 -200
- package/dist/workflowTerminal-WM_cpxIO.cjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.cjs","names":["readWorkflowCatalog","summarizeWorkflow","statSync","resolve","os","path","fs","createEmbeddedWorkflowFeature","defineMinorMode","serverMinorModes","registerRunProvider","skill","z","resolve","parseWorkflowLaunchCommand","resolveWorkflowEntry","validateWorkflowLaunch","defineApiRoutes","apiResponse","WorkflowRegistryService","WorkflowTerminalFacade","createWorkflowTerminalService","Hono","routes","streamSSE","randomUUID","path","fs","Readable","defineRoot","runtime","defineRoutedContribution","legacy","defineChannel","defineChannel","defineRoutedContribution","defineRoutedContribution","defineRoutedContribution","defineRoutedContribution","defineRoutedContribution","defineRoutedContribution","defineRoutedContribution","defineRoutedContribution","defineRoutedContribution","defineRoutedContribution","defineServerPlugin","apiRoute","channelWorkflowCatalog","channelWorkflows","rootSession","composeRootHooks","apiRoute2","commandWorkflowLaunch","hookSessionShutdown","hookToolExecutionEnd","resourceDoompiAuthorWorkflow","resourceDoompiUseWorkflow","resourceWorkflowRecovery","toolLaunchWorkflow","toolListWorkflows","toolWorkflowRun"],"sources":["../../src/services/webWorkflowCatalog/index.ts","../../src/services/workflowCatalogDeps/index.ts","../../src/services/workflowRuns/index.ts","../../src/services/workflowWatcher/index.ts","../../src/types/webWorkflows.ts","../../src/services/serverRuntime/index.ts","../../src/types/apiRoutes.ts","../../src/types/webWorkflowTerminal.ts","../../src/services/workflowHubApi/index.ts","../../src/extensions/workspaces/sessions/(backend)/_lib/index.server.ts","../../src/extensions/workspaces/sessions/(backend)/root.server.ts","../../src/services/workflowCatalogChannel/index.ts","../../src/services/workflowsHubChannel/index.ts","../../src/extensions/(backend)/_lib/index.server.ts","../../src/extensions/(backend)/api/workflow/route.server.ts","../../src/extensions/(backend)/channel/workflow-catalog.server.ts","../../src/extensions/(backend)/channel/workflows.server.ts","../../src/extensions/workspaces/sessions/(backend)/api/workflow/route.server.ts","../../src/extensions/workspaces/sessions/(backend)/command/workflow-launch.server.ts","../../src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.ts","../../src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.server.ts","../../src/extensions/workspaces/sessions/(backend)/resource/doompi-author-workflow.server.ts","../../src/extensions/workspaces/sessions/(backend)/resource/doompi-use-workflow.server.ts","../../src/extensions/workspaces/sessions/(backend)/resource/workflow-recovery.server.ts","../../src/extensions/workspaces/sessions/(backend)/tool/launch-workflow.server.ts","../../src/extensions/workspaces/sessions/(backend)/tool/list-workflows.server.ts","../../src/extensions/workspaces/sessions/(backend)/tool/workflow-run.server.ts","../../generated/server.ts"],"sourcesContent":["import type {\n WorkflowCatalogArtifactView,\n WorkflowCatalogEntryView,\n WorkflowCatalogInputView,\n WorkflowCatalogJobView,\n} from '../../types/webWorkflows';\n/**\n * The cockpit's view of the workflows a session can launch.\n *\n * The engine already reads a repository's workflow files and parses one of\n * them into triggers, inputs, jobs, artifacts and compatible runners, so this\n * module only shapes that answer for the wire and remembers what it read.\n *\n * WHY A CACHE:\n * A session reads the catalog for its initial projection and when its lifecycle\n * publishes a workflow update. Entries are kept per path and reused while the\n * file's size and modification time are unchanged, which is the same test a\n * build tool makes and costs one stat per file.\n */\n\n/** What the engine reports for one workflow file before it is parsed. */\nexport interface CatalogListEntry {\n path: string;\n relativePath: string;\n name: string;\n description: string;\n tags: string[];\n}\n\n/** One file's parsed detail, or the reason it could not be read. */\nexport interface CatalogDetail {\n triggers: string[];\n inputs: WorkflowCatalogInputView[];\n jobs: WorkflowCatalogJobView[];\n artifacts: WorkflowCatalogArtifactView[];\n runners?: string[];\n error?: string;\n}\n\n/** What a file looked like when it was last parsed. */\nexport interface CatalogFileStamp {\n size: number;\n modifiedAt: number;\n}\n\nexport interface WorkflowCatalogReaderDeps {\n /** Every workflow file under a directory. */\n list(directory: string): Promise<CatalogListEntry[]>;\n /** One file's parsed detail; never throws, so a bad file cannot empty a board. */\n summarize(path: string): CatalogDetail;\n /** Size and modification time, or undefined when the file is gone. */\n stamp(path: string): CatalogFileStamp | undefined;\n}\n\ninterface CachedEntry {\n stamp: CatalogFileStamp;\n detail: CatalogDetail;\n}\n\n/** Reads one directory's catalog, reusing what it parsed last time. */\nexport interface WorkflowCatalogReader {\n read(directory: string): Promise<WorkflowCatalogEntryView[]>;\n /** Drops what was parsed for files no longer listed, so a cache cannot grow forever. */\n forget(keep: ReadonlySet<string>): void;\n}\n\nfunction unchanged(left: CatalogFileStamp | undefined, right: CatalogFileStamp | undefined): boolean {\n return left !== undefined && right !== undefined && left.size === right.size && left.modifiedAt === right.modifiedAt;\n}\n\nexport function createWorkflowCatalogReader(deps: WorkflowCatalogReaderDeps): WorkflowCatalogReader {\n const cache = new Map<string, CachedEntry>();\n\n const detailFor = (path: string): CatalogDetail => {\n const stamp = deps.stamp(path);\n const cached = cache.get(path);\n if (cached && unchanged(cached.stamp, stamp)) return cached.detail;\n const detail = deps.summarize(path);\n // A file that vanished between listing and stat is parsed anyway, which\n // answers with its own error; it just cannot be cached against a stamp.\n if (stamp !== undefined) cache.set(path, { stamp, detail });\n return detail;\n };\n\n return {\n async read(directory) {\n const listed = await deps.list(directory);\n return listed.map((entry) => {\n const detail = detailFor(entry.path);\n return {\n path: entry.path,\n relativePath: entry.relativePath,\n name: entry.name === '' ? entry.relativePath : entry.name,\n description: entry.description,\n tags: entry.tags,\n triggers: detail.triggers,\n inputs: detail.inputs,\n jobs: detail.jobs,\n artifacts: detail.artifacts,\n ...(detail.runners === undefined ? {} : { runners: detail.runners }),\n ...(detail.error === undefined ? {} : { error: detail.error }),\n };\n });\n },\n forget(keep) {\n for (const path of cache.keys()) {\n if (!keep.has(path)) cache.delete(path);\n }\n },\n };\n}\n\n/** The launchable rows first, then the ones that would not parse, name ordered. */\nexport function presentWorkflowCatalog(entries: readonly WorkflowCatalogEntryView[]): WorkflowCatalogEntryView[] {\n return [...entries].sort((left, right) => {\n if ((left.error === undefined) !== (right.error === undefined)) return left.error === undefined ? -1 : 1;\n return left.name.localeCompare(right.name);\n });\n}\n","import { statSync } from 'node:fs';\n\nimport { readWorkflowCatalog, summarizeWorkflow } from '@agimon-ai/workflow-mcp';\n\nimport type { WorkflowCatalogReaderDeps } from '../webWorkflowCatalog';\n\n/** Connect the pure catalog projection service to the workflow engine and filesystem. */\nexport function defaultCatalogDeps(): WorkflowCatalogReaderDeps {\n return {\n list: (directory) => readWorkflowCatalog(directory),\n summarize: (workflowPath) => summarizeWorkflow(workflowPath),\n stamp: (workflowPath) => {\n try {\n const stats = statSync(workflowPath);\n return { size: stats.size, modifiedAt: stats.mtimeMs };\n } catch {\n return undefined;\n }\n },\n };\n}\n","import { resolve } from 'node:path';\n\nimport type {\n WorkflowJobPhase,\n WorkflowJobView,\n WorkflowOutcome,\n WorkflowPosition,\n WorkflowProgressState,\n WorkflowRunView,\n WorkflowStage,\n WorkflowStepView,\n} from '../../types/webWorkflows';\n\n/**\n * MIRRORS @agimon-ai/workflow-mcp's on-disk registry\n * (src/services/WorkflowRegistryService.ts and WorkflowProgressService.ts in\n * that package). The engine keeps one directory per run under\n * `<home>/workspaces/<workspace>/<stage>/<runKey>/` holding a `run.json`\n * record and an append-only `progress.ndjson` job/step log; the hub only ever\n * reads them. The derivation is duplicated rather than imported because\n * doompi-web must not depend on the engine at runtime; the unit suite pins\n * this mirror against the package's published types.\n */\nconst DEFAULT_WORKFLOW_HOME_DIR_NAME = '.workflow-mcp';\nexport const WORKFLOW_HOME_ENV = 'WORKFLOW_MCP_HOME';\nexport const WORKSPACES_DIR_NAME = 'workspaces';\nexport const RUN_RECORD_FILE_NAME = 'run.json';\nexport const PROGRESS_FILE_NAME = 'progress.ndjson';\nexport const WORKFLOW_STAGES: readonly WorkflowStage[] = ['running', 'completed', 'error'];\n\n/**\n * Errored runs stay a day, which is how long recovery has to act on them.\n *\n * Finished runs have no retention of their own: a session keeps every run it\n * launched, grouped by outcome, for as long as the session lives. A run leaves\n * the view when the engine prunes its registry directory, not on a timer here,\n * because \"what did this session run today\" is a question asked long after the\n * run settled.\n */\nexport const WORKFLOW_ERROR_RETENTION_MS = 24 * 60 * 60 * 1000;\n/**\n * Upper bound per outcome group rather than over the whole list.\n *\n * One cap across every run let a long stream of green runs push a failure out\n * of the list, which is the one thing that must never fall off the end.\n */\nexport const MAX_PRESENTED_WORKFLOW_RUNS_PER_GROUP = 24;\n\n/** The env key doompi-workflow stamps on runs it launches; ties a run to a Pi session. */\nexport const PI_SESSION_ENV = 'PI_SESSION_ID';\n\nconst PROGRESS_STATES: ReadonlySet<string> = new Set([\n 'running',\n 'completed',\n 'skipped',\n 'failed',\n 'pause_requested',\n 'paused',\n 'resumed',\n]);\nconst OUTCOMES: ReadonlySet<string> = new Set(['success', 'skipped', 'failed', 'interrupted']);\nconst EXECUTION_STATES: ReadonlySet<string> = new Set(['running', 'pause_requested', 'paused', 'resume_requested']);\nconst STEP_TERMINAL_STATES: ReadonlySet<WorkflowProgressState> = new Set(['completed', 'skipped', 'failed']);\n/** The engine records its pre:/post: blocks under these reserved pseudo-job names. */\nconst PHASE_JOB_PRE = 'pre';\nconst PHASE_JOB_POST = 'post';\n\n// oxlint-disable-next-line no-control-regex -- stripping terminal color codes from errorMessage is the point\nconst ANSI_ESCAPE_PATTERN = /\\u001b\\[[0-9;]*[A-Za-z]/g;\n\nexport interface WorkflowHomeInput {\n /** process.env.WORKFLOW_MCP_HOME, supplied by the caller. */\n envValue: string | undefined;\n /** os.homedir(), supplied by the caller. */\n homeDir: string;\n}\n\n/** Where workflow-mcp keeps its registry, mirroring the engine's own resolution. */\nexport function resolveWorkflowHome(input: WorkflowHomeInput): string {\n return resolve(\n input.envValue !== undefined && input.envValue !== ''\n ? input.envValue\n : resolve(input.homeDir, DEFAULT_WORKFLOW_HOME_DIR_NAME),\n );\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction asOptionalString(value: unknown): string | undefined {\n return typeof value === 'string' && value !== '' ? value : undefined;\n}\n\nfunction asOptionalNumber(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\nfunction stripAnsi(text: string): string {\n return text.replace(ANSI_ESCAPE_PATTERN, '').trim();\n}\n\n/**\n * One run record plus the facts the hub needs for session scoping but the\n * page never sees.\n */\nexport interface ParsedWorkflowRun {\n /** The wire view, before the progress log is folded in (jobs empty). */\n view: WorkflowRunView;\n /** env.PI_SESSION_ID from the record, when the launcher stamped one. */\n piSessionId?: string;\n}\n\n/**\n * Validates one run.json into the wire shape plus scoping facts.\n *\n * Returns undefined for anything unreadable or a foreign format. The record\n * is trusted for its own stage: the registry rewrites it when a run moves\n * between stage directories.\n */\nexport function parseWorkflowRunRecord(raw: string): ParsedWorkflowRun | undefined {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return undefined;\n }\n if (!isRecord(parsed)) return undefined;\n const runKey = asOptionalString(parsed.runKey);\n const workspace = asOptionalString(parsed.workspace);\n const workflowPath = asOptionalString(parsed.workflowPath);\n const startedAt = asOptionalString(parsed.startedAt);\n const stage = asOptionalString(parsed.stage);\n if (!runKey || !workspace || !workflowPath || !startedAt) return undefined;\n if (stage === undefined || !WORKFLOW_STAGES.includes(stage as WorkflowStage)) return undefined;\n\n const outcome = asOptionalString(parsed.outcome);\n const executionState = asOptionalString(parsed.executionState);\n const rawError = asOptionalString(parsed.errorMessage);\n const env = isRecord(parsed.env) ? parsed.env : undefined;\n const view: WorkflowRunView = {\n runKey,\n workspace,\n displayName: asOptionalString(parsed.displayName) ?? runKey,\n ...(asOptionalString(parsed.workflowName) === undefined\n ? {}\n : { workflowName: asOptionalString(parsed.workflowName) }),\n workflowPath,\n stage: stage as WorkflowStage,\n ...(outcome !== undefined && OUTCOMES.has(outcome) ? { outcome: outcome as WorkflowOutcome } : {}),\n ...(executionState !== undefined && EXECUTION_STATES.has(executionState)\n ? { executionState: executionState as WorkflowRunView['executionState'] }\n : {}),\n ...(asOptionalString(parsed.prompt) === undefined ? {} : { prompt: asOptionalString(parsed.prompt) }),\n startedAt,\n ...(asOptionalString(parsed.finishedAt) === undefined ? {} : { finishedAt: asOptionalString(parsed.finishedAt) }),\n ...(rawError === undefined ? {} : { errorMessage: stripAnsi(rawError) }),\n ...(asOptionalString(parsed.failedJob) === undefined ? {} : { failedJob: asOptionalString(parsed.failedJob) }),\n ...(parsed.stale === true ? { stale: true } : {}),\n ...(asOptionalString(parsed.staleReason) === undefined\n ? {}\n : { staleReason: asOptionalString(parsed.staleReason) }),\n ...(asOptionalString(parsed.worktreeBranch) === undefined\n ? {}\n : { worktreeBranch: asOptionalString(parsed.worktreeBranch) }),\n jobs: [],\n };\n const piSessionId = env === undefined ? undefined : asOptionalString(env[PI_SESSION_ENV]);\n return { view, ...(piSessionId === undefined ? {} : { piSessionId }) };\n}\n\ninterface WorkflowProgressEvent {\n type: 'job' | 'step';\n status: WorkflowProgressState;\n job: string;\n step?: string;\n index?: number;\n total?: number;\n reason?: string;\n at: string;\n}\n\n/**\n * Parses the append-only progress log. Malformed lines are skipped rather\n * than failing the file: a reader routinely catches a torn final line\n * mid-append.\n */\nexport function parseWorkflowProgress(raw: string): WorkflowProgressEvent[] {\n const events: WorkflowProgressEvent[] = [];\n for (const line of raw.split('\\n')) {\n const trimmed = line.trim();\n if (trimmed === '') continue;\n let parsed: unknown;\n try {\n parsed = JSON.parse(trimmed);\n } catch {\n continue;\n }\n if (!isRecord(parsed)) continue;\n const type = parsed.type;\n const status = asOptionalString(parsed.status);\n const job = asOptionalString(parsed.job);\n const at = asOptionalString(parsed.at);\n if ((type !== 'job' && type !== 'step') || !job || !at) continue;\n if (status === undefined || !PROGRESS_STATES.has(status)) continue;\n const step = asOptionalString(parsed.step);\n const index = asOptionalNumber(parsed.index);\n const total = asOptionalNumber(parsed.total);\n const reason = asOptionalString(parsed.reason);\n events.push({\n type,\n status: status as WorkflowProgressState,\n job,\n ...(step === undefined ? {} : { step }),\n ...(index === undefined ? {} : { index }),\n ...(total === undefined ? {} : { total }),\n ...(reason === undefined ? {} : { reason }),\n at,\n });\n }\n return events;\n}\n\nfunction jobPhase(name: string): WorkflowJobPhase {\n if (name === PHASE_JOB_PRE) return PHASE_JOB_PRE;\n if (name === PHASE_JOB_POST) return PHASE_JOB_POST;\n return 'job';\n}\n\n/**\n * Folds the event log into the current job tree; later events win, so a job\n * that started and later failed reads as failed. Jobs and steps keep the\n * order of their first appearance.\n */\nexport function foldWorkflowProgress(events: readonly WorkflowProgressEvent[]): WorkflowJobView[] {\n const jobs: WorkflowJobView[] = [];\n const jobByName = new Map<string, WorkflowJobView>();\n for (const event of events) {\n let job = jobByName.get(event.job);\n if (job === undefined) {\n job = { name: event.job, phase: jobPhase(event.job), status: event.status, steps: [] };\n jobByName.set(event.job, job);\n jobs.push(job);\n }\n if (event.type === 'job') {\n job.status = event.status;\n if (event.reason !== undefined) job.reason = event.reason;\n if (event.index !== undefined) job.index = event.index;\n if (event.total !== undefined) job.total = event.total;\n if (event.status === 'running' && job.startedAt === undefined) job.startedAt = event.at;\n if (STEP_TERMINAL_STATES.has(event.status)) job.endedAt = event.at;\n continue;\n }\n if (event.step === undefined) continue;\n let step: WorkflowStepView | undefined = job.steps.find((candidate) => candidate.name === event.step);\n if (step === undefined) {\n step = { name: event.step, status: event.status };\n job.steps.push(step);\n }\n step.status = event.status;\n if (event.reason !== undefined) step.reason = event.reason;\n if (event.status === 'running' && step.startedAt === undefined) step.startedAt = event.at;\n if (STEP_TERMINAL_STATES.has(event.status)) step.endedAt = event.at;\n }\n return jobs;\n}\n\nconst ACTIVE_PROGRESS_STATES: ReadonlySet<WorkflowProgressState> = new Set([\n 'running',\n 'pause_requested',\n 'paused',\n 'resumed',\n]);\n\n/** The job and step a run is on right now, for the NOW breadcrumb. */\nexport function workflowPosition(jobs: readonly WorkflowJobView[]): WorkflowPosition | undefined {\n for (let jobIndex = jobs.length - 1; jobIndex >= 0; jobIndex -= 1) {\n const job = jobs[jobIndex]!;\n if (!ACTIVE_PROGRESS_STATES.has(job.status)) continue;\n for (let stepIndex = job.steps.length - 1; stepIndex >= 0; stepIndex -= 1) {\n const step = job.steps[stepIndex]!;\n if (ACTIVE_PROGRESS_STATES.has(step.status)) {\n return {\n job: job.name,\n step: step.name,\n ...(job.index === undefined ? {} : { index: job.index }),\n ...(job.total === undefined ? {} : { total: job.total }),\n };\n }\n }\n return {\n job: job.name,\n ...(job.index === undefined ? {} : { index: job.index }),\n ...(job.total === undefined ? {} : { total: job.total }),\n };\n }\n return undefined;\n}\n\n/** The finished view: record fields plus the folded job tree and position. */\nexport function completeWorkflowRunView(view: WorkflowRunView, jobs: WorkflowJobView[]): WorkflowRunView {\n const position = view.stage === 'running' ? workflowPosition(jobs) : undefined;\n return { ...view, jobs, ...(position === undefined ? {} : { position }) };\n}\n\n/**\n * Whether a run belongs on a session's workflow tab: launched by that Pi\n * session, which is the same env test doompi-workflow's isSessionRun applies.\n *\n * The registry is one directory under $HOME shared by every repository and\n * every Pi session on the machine, so repository proximity is not ownership.\n * Scoping on it as well let two sessions open in one repo read each other's\n * history, and kept a dead session's runs on the board of every session that\n * replaced it. Fails closed on an unstamped record, which is what a launch\n * from the CLI rather than from a session leaves behind.\n */\nexport function runBelongsToSession(run: ParsedWorkflowRun, sessionId: string): boolean {\n return run.piSessionId !== undefined && run.piSessionId === sessionId;\n}\n\nfunction parseTime(value: string | undefined): number {\n if (value === undefined) return 0;\n const time = Date.parse(value);\n return Number.isFinite(time) ? time : 0;\n}\n\nconst STAGE_ORDER: Readonly<Record<WorkflowStage, number>> = { running: 0, error: 1, completed: 2 };\n\n/**\n * Whether a run still belongs in the view.\n *\n * Only errored runs age out here, and slowly: everything else a session\n * started stays until the engine forgets the run itself.\n */\nfunction withinRetention(run: WorkflowRunView, now: number): boolean {\n if (run.stage !== 'error') return true;\n const settledAt = parseTime(run.finishedAt) || parseTime(run.startedAt);\n return now - settledAt < WORKFLOW_ERROR_RETENTION_MS;\n}\n\n/**\n * When a run last moved, which is what orders it within its group.\n *\n * A running run has only its start; a settled one is ordered by when it\n * settled, because a list kept for the whole session is read as a history and\n * two runs started together can finish an hour apart.\n */\nfunction lastMovedAt(run: WorkflowRunView): number {\n return run.stage === 'running' ? parseTime(run.startedAt) : parseTime(run.finishedAt) || parseTime(run.startedAt);\n}\n\n/**\n * Running runs first, then errored (recovery acts on them), then finished;\n * newest first within a group, and each group capped on its own.\n */\nexport function presentWorkflowRuns(runs: readonly WorkflowRunView[], now: number): WorkflowRunView[] {\n const groups = new Map<WorkflowStage, WorkflowRunView[]>();\n for (const run of runs) {\n if (!withinRetention(run, now)) continue;\n const group = groups.get(run.stage);\n if (group) group.push(run);\n else groups.set(run.stage, [run]);\n }\n return [...groups.entries()]\n .sort(([left], [right]) => STAGE_ORDER[left] - STAGE_ORDER[right])\n .flatMap(([, group]) =>\n group\n .sort((left, right) => lastMovedAt(right) - lastMovedAt(left))\n .slice(0, MAX_PRESENTED_WORKFLOW_RUNS_PER_GROUP),\n );\n}\n","import fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport {\n completeWorkflowRunView,\n foldWorkflowProgress,\n type ParsedWorkflowRun,\n parseWorkflowProgress,\n parseWorkflowRunRecord,\n PROGRESS_FILE_NAME,\n resolveWorkflowHome,\n RUN_RECORD_FILE_NAME,\n WORKFLOW_HOME_ENV,\n WORKFLOW_STAGES,\n WORKSPACES_DIR_NAME,\n} from '../workflowRuns';\n\nexport interface ReadWorkflowRunsOptions {\n /** Registry home override, primarily for tests. */\n homeDir?: string;\n /** Admitted session environment used to resolve the registry home. */\n environment?: Readonly<Record<string, string | undefined>>;\n}\n\n/**\n * Read the durable workflow registry once.\n *\n * The registry is an initial snapshot only. Live delivery belongs to the\n * session lifecycle and is routed through the host-owned direct event bus.\n */\nexport function readWorkflowRuns(options: ReadWorkflowRunsOptions = {}): ParsedWorkflowRun[] {\n const environment = options.environment;\n const homeDir =\n options.homeDir ??\n resolveWorkflowHome({\n envValue: environment?.[WORKFLOW_HOME_ENV],\n homeDir: os.homedir(),\n });\n const workspacesDir = path.join(homeDir, WORKSPACES_DIR_NAME);\n const recordCache = new Map<string, { size: number; mtimeMs: number; value: ParsedWorkflowRun | undefined }>();\n const progressCache = new Map<\n string,\n { size: number; mtimeMs: number; value: ReturnType<typeof foldWorkflowProgress> }\n >();\n\n const cachedParse = <T>(\n cache: Map<string, { size: number; mtimeMs: number; value: T }>,\n filePath: string,\n parse: (raw: string) => T,\n empty: T,\n ): T => {\n let stat: fs.Stats;\n try {\n stat = fs.statSync(filePath);\n } catch {\n cache.delete(filePath);\n return empty;\n }\n const cached = cache.get(filePath);\n if (cached && cached.size === stat.size && cached.mtimeMs === stat.mtimeMs) return cached.value;\n let raw: string;\n try {\n raw = fs.readFileSync(filePath, 'utf8');\n } catch {\n cache.delete(filePath);\n return empty;\n }\n const value = parse(raw);\n cache.set(filePath, { size: stat.size, mtimeMs: stat.mtimeMs, value });\n return value;\n };\n\n const listDir = (directory: string): string[] => {\n try {\n return fs.readdirSync(directory).sort();\n } catch {\n return [];\n }\n };\n\n const runs: ParsedWorkflowRun[] = [];\n for (const workspace of listDir(workspacesDir)) {\n for (const stage of WORKFLOW_STAGES) {\n const stageDir = path.join(workspacesDir, workspace, stage);\n for (const runKey of listDir(stageDir)) {\n const runDir = path.join(stageDir, runKey);\n const recordPath = path.join(runDir, RUN_RECORD_FILE_NAME);\n const progressPath = path.join(runDir, PROGRESS_FILE_NAME);\n const parsed = cachedParse(recordCache, recordPath, parseWorkflowRunRecord, undefined);\n if (parsed === undefined) continue;\n const jobs = cachedParse(\n progressCache,\n progressPath,\n (raw) => foldWorkflowProgress(parseWorkflowProgress(raw)),\n [],\n );\n runs.push({ ...parsed, view: completeWorkflowRunView(parsed.view, jobs) });\n }\n }\n }\n return runs;\n}\n","/**\n * Workflow run view types shared by this package's hub channel and its web\n * plugin. The shapes mirror what the embedded workflow-mcp engine records;\n * the cockpit renders them as 'workflow_runs' channel payloads.\n */\n\n/** workflow-mcp's own stage vocabulary; the registry bucket a run record sits in. */\nexport type WorkflowStage = 'running' | 'completed' | 'error';\n\n/** workflow-mcp's terminal outcome for a finished run. */\nexport type WorkflowOutcome = 'success' | 'skipped' | 'failed' | 'interrupted';\n\n/** Job and step states as workflow-mcp records them in the progress log. */\nexport type WorkflowProgressState =\n | 'running'\n | 'completed'\n | 'skipped'\n | 'failed'\n | 'pause_requested'\n | 'paused'\n | 'resumed';\n\nexport interface WorkflowStepView {\n name: string;\n status: WorkflowProgressState;\n /** Why the step is in its state, when the engine recorded one (e.g. a skip condition). */\n reason?: string;\n /** ISO 8601 of the step's first running event. */\n startedAt?: string;\n /** ISO 8601 of the step's terminal event. */\n endedAt?: string;\n}\n\n/** 'pre' and 'post' are the engine's pseudo-jobs for its pre:/post: blocks. */\nexport type WorkflowJobPhase = 'pre' | 'job' | 'post';\n\nexport interface WorkflowJobView {\n name: string;\n phase: WorkflowJobPhase;\n status: WorkflowProgressState;\n reason?: string;\n /** Position among the run's jobs, when the engine recorded one. */\n index?: number;\n total?: number;\n startedAt?: string;\n endedAt?: string;\n steps: WorkflowStepView[];\n}\n\n/** The job and step a run is on right now; drives the NOW breadcrumb. */\nexport interface WorkflowPosition {\n job: string;\n step?: string;\n index?: number;\n total?: number;\n}\n\n/**\n * One workflow run of a session, read from workflow-mcp's registry: the\n * run.json record plus the folded progress.ndjson job tree.\n */\nexport interface WorkflowRunView {\n /** Registry identity within its workspace; unique per workspace+stage. */\n runKey: string;\n workspace: string;\n displayName: string;\n workflowName?: string;\n workflowPath: string;\n stage: WorkflowStage;\n outcome?: WorkflowOutcome;\n /** Present while the engine is pausing or paused; absent for plain running. */\n executionState?: 'running' | 'pause_requested' | 'paused' | 'resume_requested';\n /** The prompt the run was launched with, when one was recorded. */\n prompt?: string;\n /** ISO 8601, from the run record. */\n startedAt: string;\n finishedAt?: string;\n /** Failure cause with ANSI escapes stripped, present when the run errored. */\n errorMessage?: string;\n /** The job the engine blamed for the failure, when it recorded one. */\n failedJob?: string;\n /** True when reconciliation decided the recorded pid is no longer alive. */\n stale?: boolean;\n staleReason?: string;\n worktreeBranch?: string;\n position?: WorkflowPosition;\n jobs: WorkflowJobView[];\n}\n\n/** What the workflow runs channel publishes for one session. */\nexport interface WorkflowRunsPayload {\n runs: WorkflowRunView[];\n}\n\nexport const WORKFLOW_RUNS_TYPE = 'workflow_runs';\n\n/**\n * One workflow the session's directory can launch, as the catalog drawer\n * lists it: the engine's own catalog entry plus the parsed detail the drawer\n * unfolds and the launch dialog turns into fields.\n */\nexport interface WorkflowCatalogEntryView {\n /** Absolute path, the row's stable identity. */\n path: string;\n relativePath: string;\n name: string;\n description: string;\n tags: string[];\n /** The trigger names the file declares, such as workflow_dispatch. */\n triggers: string[];\n inputs: WorkflowCatalogInputView[];\n jobs: WorkflowCatalogJobView[];\n artifacts: WorkflowCatalogArtifactView[];\n /** Absent when the workflow names no runner map, which means any runner will do. */\n runners?: string[];\n /** Set when the file could not be parsed; the row shows this instead of guessing. */\n error?: string;\n}\n\nexport interface WorkflowCatalogInputView {\n name: string;\n description?: string;\n required?: boolean;\n default?: string;\n type?: string;\n options?: string[];\n}\n\nexport interface WorkflowCatalogJobView {\n name: string;\n steps: string[];\n}\n\nexport interface WorkflowCatalogArtifactView {\n path: string;\n kind: 'file' | 'directory';\n description: string;\n producedBy: string[];\n}\n\n/** What the catalog channel publishes for one session. */\nexport interface WorkflowCatalogPayload {\n /** The directory the catalog was read from, which is the session's own. */\n cwd: string;\n workflows: WorkflowCatalogEntryView[];\n /** Present when the directory could not be read at all. */\n warning?: string;\n}\n\nexport const WORKFLOW_CATALOG_TYPE = 'workflow_catalog';\n","import { resolve } from 'node:path';\n\nimport {\n type DoomHeadlessExecutionContext,\n type DoomHeadlessContent,\n type DoomHeadlessToolResult,\n} from '@agimon-ai/doompi-core/headless';\nimport { serverMinorModes } from '@agimon-ai/doompi-minor-mode';\nimport { defineMinorMode, type MinorModeOwner, type MinorModeState } from '@agimon-ai/doompi-minor-mode';\nimport { createEmbeddedWorkflowFeature } from '@agimon-ai/workflow-mcp';\nimport { z } from 'zod';\n\nimport { registerRunProvider, type RunProviderHandle } from '../../services/backgroundWork';\nimport { createWorkflowCatalogReader, presentWorkflowCatalog } from '../../services/webWorkflowCatalog';\nimport { defaultCatalogDeps } from '../../services/workflowCatalogDeps';\nimport {\n parseWorkflowLaunchCommand,\n resolveWorkflowEntry,\n validateWorkflowLaunch,\n} from '../../services/workflowLaunchCommand';\nimport { readWorkflowSkill as skill } from '../../services/workflowResource';\nimport { PI_SESSION_ENV, presentWorkflowRuns, runBelongsToSession } from '../../services/workflowRuns';\nimport { readWorkflowRuns } from '../../services/workflowWatcher';\nimport { WORKFLOW_CATALOG_TYPE, WORKFLOW_RUNS_TYPE } from '../../types/webWorkflows';\n\nconst SOURCE = '@agimon-ai/doompi-workflow';\nconst WORKFLOW_MODE_ID = 'workflow';\nconst LIST_TOOL = 'list_workflows';\nconst LAUNCH_TOOL = 'launch_workflow';\nconst RUN_TOOL = 'workflow_run';\n\nfunction callResult(value: unknown): DoomHeadlessToolResult {\n const content: DoomHeadlessContent[] = [];\n if (typeof value === 'object' && value !== null && 'content' in value && Array.isArray(value.content)) {\n for (const item of value.content) {\n if (typeof item !== 'object' || item === null || !('type' in item)) continue;\n const record = item as Record<string, unknown>;\n if (record.type === 'text' && typeof record.text === 'string') content.push({ type: 'text', text: record.text });\n else if (record.type === 'image' && typeof record.data === 'string' && typeof record.mimeType === 'string') {\n content.push({ type: 'image', data: record.data, mimeType: record.mimeType });\n }\n }\n }\n if (content.length === 0) content.push({ type: 'text', text: JSON.stringify(value, null, 2) });\n return {\n content,\n details: value,\n ...(typeof value === 'object' && value !== null && 'isError' in value && value.isError === true\n ? { isError: true }\n : {}),\n };\n}\n\nimport { type DoomHeadlessHostService } from '@agimon-ai/doompi-core/headless';\nimport { type DoomServerHostService, type DoomServerSessionPlugin } from '@agimon-ai/doompi-core/serverFacet';\nexport function createWorkflowServerRuntime(\n host: DoomHeadlessHostService,\n serverHost: DoomServerHostService,\n): DoomServerSessionPlugin {\n if (serverHost.context.directEvents === undefined)\n throw new Error('Workflow headless facet requires the session direct event bus.');\n const directEvents = serverHost.context.directEvents;\n let runProvider: RunProviderHandle | undefined;\n const catalogReader = createWorkflowCatalogReader(defaultCatalogDeps());\n const publishLifecycle = async (executionContext: typeof host.context): Promise<boolean> => {\n const records = readWorkflowRuns({ environment: executionContext.environment }).filter((run) =>\n runBelongsToSession(run, executionContext.sessionId),\n );\n const activeItems = records\n .filter((run) => run.view.stage === 'running' && run.view.stale !== true)\n .map((run) => ({ id: `${run.view.workspace}/${run.view.runKey}`, sessionId: executionContext.sessionId }));\n runProvider?.update(activeItems);\n const runs = presentWorkflowRuns(\n records.map((run) => run.view),\n Date.now(),\n );\n directEvents.publish(WORKFLOW_RUNS_TYPE, executionContext.sessionId, { runs });\n try {\n directEvents.publish(WORKFLOW_CATALOG_TYPE, executionContext.sessionId, {\n cwd: executionContext.cwd,\n workflows: presentWorkflowCatalog(await catalogReader.read(executionContext.cwd)),\n });\n } catch (error) {\n const warning = error instanceof Error ? error.message : String(error);\n directEvents.publish(WORKFLOW_CATALOG_TYPE, executionContext.sessionId, {\n cwd: executionContext.cwd,\n workflows: [],\n warning,\n });\n }\n return activeItems.length > 0;\n };\n const feature = createEmbeddedWorkflowFeature();\n const launch = (parameters: Parameters<typeof feature.runTool.execute>[0]) =>\n feature.runTool.execute({\n ...parameters,\n env: { ...parameters.env, [PI_SESSION_ENV]: host.context.sessionId },\n });\n let control: ReturnType<typeof feature.createRunControl> | undefined;\n let controlDisposers: (() => void)[] = [];\n const disposeControl = (): void => {\n for (const dispose of controlDisposers.splice(0)) dispose();\n control?.dispose();\n control = undefined;\n };\n let modeOwner: MinorModeOwner | undefined;\n const modeSelected = (): boolean => (host.context.selection.state?.['minor-mode'] ?? []).includes(WORKFLOW_MODE_ID);\n const modeState = (): MinorModeState => {\n const active = modeSelected();\n return {\n activation: active ? 'active' : 'inactive',\n condition: 'ready',\n ...(active ? { detail: 'workflow tools available' } : {}),\n actions: [\n { id: 'activate', enabled: !active, ...(!active ? {} : { disabledReason: 'Workflow mode is active.' }) },\n { id: 'deactivate', enabled: active, ...(active ? {} : { disabledReason: 'Workflow mode is inactive.' }) },\n ],\n };\n };\n const selectMode = async (enabled: boolean): Promise<void> => {\n const modes = (host.context.selection.state?.['minor-mode'] ?? []).filter((mode) => mode !== WORKFLOW_MODE_ID);\n await host.changeSelection({\n axis: 'state',\n key: 'minor-mode',\n values: enabled ? [...modes, WORKFLOW_MODE_ID] : modes,\n });\n modeOwner?.publish();\n };\n modeOwner = defineMinorMode({\n descriptor: {\n source: SOURCE,\n id: WORKFLOW_MODE_ID,\n label: 'Workflow',\n description: 'Workflow discovery, launch, inspection, control, and recovery tools.',\n order: 20,\n actions: [\n {\n id: 'activate',\n label: 'Activate',\n description: 'Enable workflow tools for this session.',\n contexts: ['headless'],\n parameters: [],\n },\n {\n id: 'deactivate',\n label: 'Deactivate',\n description: 'Disable workflow tools without stopping active runs.',\n contexts: ['headless'],\n parameters: [],\n },\n ],\n },\n state: modeState,\n async handleAction(_runtime, actionId, _argumentsValue, execution) {\n execution.signal.throwIfAborted();\n if (actionId === 'activate') {\n await selectMode(true);\n return { message: 'Workflow mode activated.' };\n }\n if (actionId === 'deactivate') {\n await selectMode(false);\n return { message: 'Workflow mode deactivated.' };\n }\n throw new Error(`Unknown workflow mode action: ${actionId}`);\n },\n }).createOwner(undefined);\n return {\n services: [\n serverMinorModes([modeOwner]),\n (context) => {\n const provider = registerRunProvider(context);\n runProvider = provider;\n return () => {\n provider.dispose();\n if (runProvider === provider) runProvider = undefined;\n };\n },\n ],\n hooks: [\n {\n event: 'tool_execution_end',\n handle: async (_event, executionContext) => {\n await publishLifecycle(executionContext);\n },\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n event: 'session_shutdown',\n handle: disposeControl,\n },\n ],\n resources: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'doompi-author-workflow',\n kind: 'skill',\n read: () => skill('doompi-author-workflow'),\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'doompi-use-workflow',\n kind: 'skill',\n read: () => skill('doompi-use-workflow'),\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'workflow-recovery',\n kind: 'skill',\n read: () => skill('workflow-recovery'),\n },\n ],\n activities: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: SOURCE,\n async start(executionContext) {\n const reportFailure = (error: unknown): void => {\n process.emitWarning(`Could not publish headless workflow state: ${String(error)}`);\n };\n const stopFor =\n (ownedControl: NonNullable<typeof control>): (() => void) =>\n () => {\n void publishLifecycle(executionContext)\n .then((active) => {\n if (!active && !modeSelected() && control === ownedControl) disposeControl();\n })\n .catch(reportFailure);\n };\n if (control !== undefined) {\n const ownedControl = control;\n await publishLifecycle(executionContext);\n return stopFor(ownedControl);\n }\n control = feature.createRunControl({});\n const ownedControl = control;\n const refresh = (): void => {\n void publishLifecycle(executionContext)\n .then((active) => {\n if (!active && !modeSelected() && control === ownedControl) disposeControl();\n })\n .catch(reportFailure);\n };\n controlDisposers = [\n ownedControl.on('runStarted', refresh),\n ownedControl.on('runUpdated', refresh),\n ownedControl.on('runFinished', refresh),\n ];\n try {\n await ownedControl.start();\n await publishLifecycle(executionContext);\n return stopFor(ownedControl);\n } catch (error) {\n if (control === ownedControl) disposeControl();\n throw error;\n }\n },\n },\n ],\n tools: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: LIST_TOOL,\n label: 'List Workflows',\n description: 'List workflow definitions in this repository, not existing runs.',\n promptGuidelines: ['Use list_workflows to discover definitions, not to find an existing run.'],\n parameters: z.toJSONSchema(feature.listWorkflowsTool.getInputSchema()),\n executionMode: 'serial',\n async execute(_toolCallId, parameters, signal, _onUpdate, context) {\n signal?.throwIfAborted();\n const input = parameters as Parameters<typeof feature.listWorkflowsTool.execute>[0];\n return callResult(\n await feature.listWorkflowsTool.execute({\n ...input,\n directory:\n input?.directory === undefined\n ? context.cwd\n : typeof input.directory === 'string'\n ? resolve(context.cwd, input.directory)\n : input.directory,\n }),\n );\n },\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: LAUNCH_TOOL,\n label: 'Launch Workflow',\n description: 'Start a workflow run. A successful launch is not a completed workflow.',\n promptGuidelines: [\n 'Launch returns when a run starts, not when it finishes. Use the exact run key and separate workspace from its launch result for workflow_run status, not Agiflow project or job identifiers.',\n 'Do not relaunch a healthy running workflow merely because it has not completed.',\n ],\n parameters: z.toJSONSchema(feature.runTool.getInputSchema()),\n executionMode: 'serial',\n async execute(_toolCallId, parameters, signal, _onUpdate, context) {\n signal?.throwIfAborted();\n const input = parameters as Parameters<typeof feature.runTool.execute>[0];\n return callResult(\n await launch({\n ...input,\n ...(typeof input.workflowPath === 'string'\n ? { workflowPath: resolve(context.cwd, input.workflowPath) }\n : {}),\n }),\n );\n },\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: RUN_TOOL,\n label: 'Workflow Run',\n description:\n 'Inspect a session-owned workflow by exact run key and separate workspace, or request cooperative control.',\n promptGuidelines: [\n 'Use workflow_run status for the recorded stage, outcome, position, jobs, and steps. A successful status lookup is not evidence that the workflow completed.',\n 'For a healthy running workflow, summarize the recorded progress. Do not automatically search CLI commands or filesystem logs, relaunch, or diagnose failure merely because it remains running.',\n 'Investigate further when the run reports failure or staleness, or when the user requests diagnostics. Only status, pause, resume, and stop are supported here; stop only on user request.',\n 'Use exact registry runKey and separate workspace from the launch or status result. Agiflow project and job identifiers are not workflow run keys.',\n ],\n parameters: {\n type: 'object',\n properties: {\n action: { type: 'string', enum: ['status', 'pause', 'resume', 'stop'] },\n runKey: {\n type: 'string',\n minLength: 1,\n description:\n 'Exact registry run key from the launch result, without the workspace prefix. Not an Agiflow job ID.',\n },\n workspace: {\n type: 'string',\n description: 'Workspace from the launch result, passed separately from runKey.',\n },\n reason: { type: 'string' },\n expectedRunId: { type: 'string' },\n },\n required: ['action', 'runKey'],\n additionalProperties: false,\n },\n executionMode: 'serial',\n async execute(_toolCallId, parameters, signal) {\n signal?.throwIfAborted();\n const input = parameters as unknown as {\n action: 'status' | 'pause' | 'resume' | 'stop';\n runKey: string;\n workspace?: string;\n reason?: string;\n expectedRunId?: string;\n };\n const runs = readWorkflowRuns({ environment: host.context.environment }).filter(\n (run) =>\n runBelongsToSession(run, host.context.sessionId) &&\n run.view.runKey === input.runKey &&\n (input.workspace === undefined || run.view.workspace === input.workspace),\n );\n if (runs.length !== 1)\n return {\n ...callResult({\n error:\n runs.length === 0\n ? 'No matching workflow run was found in this session. This is a lookup failure, not evidence that the workflow failed. Use the exact runKey and separate workspace from its launch result, not Agiflow job identifiers.'\n : 'Specify the workspace for this run key.',\n }),\n isError: true,\n };\n const run = runs[0]!.view;\n if (input.action === 'status') return callResult(run);\n if (!control) return callResult({ error: 'Workflow activity is not active.' });\n if (typeof input.expectedRunId !== 'string' || input.expectedRunId.length === 0) {\n return callResult({ error: 'expectedRunId is required for workflow control.' });\n }\n const request =\n input.action === 'pause'\n ? await control.pause(input.runKey, input.expectedRunId, input.workspace, input.reason)\n : input.action === 'resume'\n ? await control.resume(input.runKey, input.expectedRunId, input.workspace)\n : await control.stop(input.runKey, input.expectedRunId, input.workspace, input.reason);\n return callResult(request);\n },\n },\n ],\n commands: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'workflow-launch',\n description: 'Launch a workflow from a slash command.',\n async execute(args: string, execution: DoomHeadlessExecutionContext) {\n const parsed = parseWorkflowLaunchCommand(args);\n if ('error' in parsed) {\n await execution.client.notify({ body: parsed.error, level: 'error' });\n return;\n }\n try {\n const entry = resolveWorkflowEntry(await catalogReader.read(execution.cwd), parsed.workflow);\n if (!entry || entry.error) {\n await execution.client.notify({\n body: entry?.error ?? `Workflow not found: ${parsed.workflow}`,\n level: 'error',\n });\n return;\n }\n const problems = validateWorkflowLaunch(entry, parsed);\n if (problems.length > 0) {\n await execution.client.notify({ body: problems.join('\\n'), level: 'error' });\n return;\n }\n const result = callResult(\n await launch({\n workflowPath: entry.path,\n ...(parsed.runner === undefined ? {} : { runner: parsed.runner }),\n ...(Object.keys(parsed.inputs).length === 0 ? {} : { inputs: parsed.inputs }),\n ...(parsed.prompt === undefined ? {} : { prompt: parsed.prompt }),\n }),\n );\n const rendered = result.content.find((item) => item.type === 'text');\n await execution.client.notify({\n body: rendered?.type === 'text' ? rendered.text : 'Workflow launch requested.',\n level: result.isError ? 'error' : 'info',\n });\n } catch (error) {\n await execution.client.notify({ body: String(error), level: 'error' });\n }\n },\n },\n ],\n onDispose() {\n disposeControl();\n runProvider?.dispose();\n runProvider = undefined;\n },\n };\n}\n","import { apiResponse, defineApiRoutes } from '@agimon-ai/doompi-core/web';\n\nimport type {\n WorkflowArtifactContentResponse,\n WorkflowArtifactsResponse,\n WorkflowControlResponse,\n WorkflowDeleteResponse,\n} from './webWorkflowTerminal';\n\n/**\n * This package's routes, as data.\n *\n * No scope and no base path. The build reads both off\n * `src/extensions/(backend)/api/workflow/`, so the mount is stated once, by the\n * folder that creates it. The same API answers at all three scopes, because a\n * global contribution cascades into workspace and session; the folder under\n * `workspaces/sessions/` only re-mounts it for a session's own server.\n *\n * This is the one file the routes, the Hono app and the browser all read, so a\n * path cannot move on one side alone. The page used to build the hub's own\n * absolute URL and then rewrite its plugin prefix with String.replace to reach\n * a session, which is exactly the kind of copy that can move by one character\n * without anything noticing.\n *\n * `:workspace` and `:runKey` are Hono's own parameter syntax, because the app\n * registers `path` verbatim.\n */\n\n/** One run, which every route below addresses. */\nconst RUN = '/runs/:workspace/:runKey';\n\n/**\n * The artifact route's parameter, as Hono spells a multi-segment match.\n *\n * An artifact is named by its path inside the run directory, so `reports/a.md`\n * is one parameter across two segments. The client's `params` substitution\n * fills a single segment and percent-encodes the slash with it, so the page\n * substitutes this one itself; see the page's `_lib/terminalApi.ts`.\n */\nexport const ARTIFACT_NAME_PARAM = ':name{.+}';\n\n/** Query parameters the artifact route reads, spelled once for both halves. */\nexport const ARTIFACT_RAW_PARAM = 'raw';\nexport const ARTIFACT_DOWNLOAD_PARAM = 'download';\n\nexport default defineApiRoutes({\n /**\n * The terminal, as server-sent events.\n *\n * `stream: true` gets a URL and no call method: the consumer is the browser's\n * own `EventSource`, and a relayed call would buffer a stream that never ends.\n */\n screen: {\n method: 'GET',\n path: `${RUN}/screen/stream`,\n stream: true,\n },\n control: {\n method: 'POST',\n path: `${RUN}/control`,\n response: apiResponse<WorkflowControlResponse>(),\n },\n keys: {\n method: 'POST',\n path: `${RUN}/keys`,\n },\n resize: {\n method: 'POST',\n path: `${RUN}/resize`,\n response: apiResponse<{ resized: boolean }>(),\n },\n remove: {\n method: 'DELETE',\n path: RUN,\n response: apiResponse<WorkflowDeleteResponse>(),\n },\n artifacts: {\n method: 'GET',\n path: `${RUN}/artifacts`,\n response: apiResponse<WorkflowArtifactsResponse>(),\n },\n /** One artifact: its metadata and text, or its raw bytes under `raw=1`. */\n artifact: {\n method: 'GET',\n path: `${RUN}/artifacts/${ARTIFACT_NAME_PARAM}`,\n query: [ARTIFACT_RAW_PARAM, ARTIFACT_DOWNLOAD_PARAM],\n response: apiResponse<WorkflowArtifactContentResponse>(),\n },\n});\n","/**\n * The wire contract between this package's hub API and its cockpit client:\n * one run's terminal, and the files its run directory holds.\n *\n * Both halves of the cockpit import these names, so the route strings and the\n * event names live here rather than being spelled twice.\n */\n\n/**\n * Segment this package's API is mounted under, below /api/plugins/.\n *\n * The same word names `src/extensions/(backend)/api/workflow/`, which is where\n * the build reads the mount for the browser's client, so the two cannot drift.\n * The routes themselves are declared in `apiRoutes.ts`.\n */\nexport const WORKFLOW_API_BASE_PATH = 'workflow';\n\n/** The SSE event name the screen stream writes. */\nexport const WORKFLOW_SCREEN_EVENT = 'screen';\n\n/** What a surface may do with one run's terminal, and why anything is missing. */\nexport interface WorkflowTerminalCapabilitiesView {\n readable: boolean;\n writable: boolean;\n resizable: boolean;\n reason?: string;\n}\n\n/** One frame of a run's terminal, as the stream pushes it. */\nexport interface WorkflowScreenEvent {\n /** The visible screen, newest line last, carrying the colour the run printed. */\n lines: string[];\n capabilities: WorkflowTerminalCapabilitiesView;\n /** True once the run has settled, after which the stream ends. */\n ended?: boolean;\n}\n\n/** Answer to taking or releasing the keyboard for one run. */\nexport interface WorkflowControlResponse {\n /** True when this caller now holds the keyboard. */\n held: boolean;\n /** The token later writes must carry; absent when control was refused or released. */\n token?: string;\n /** Why control was refused, worded for a reader. */\n reason?: string;\n}\n\n/** Answer after a settled run and its directory have been permanently removed. */\nexport interface WorkflowDeleteResponse {\n deleted: true;\n}\n\n/** How a declared run-directory entry compares with what is on disk. */\nexport type WorkflowArtifactState = 'written' | 'empty' | 'pending' | 'unreadable';\n\n/** One file or directory in a run's own folder. */\nexport interface WorkflowArtifactView {\n /** Path relative to the run directory, which is also the read route's parameter. */\n path: string;\n kind: 'file' | 'directory';\n /** What the workflow says this file is for; empty for a file it never declared. */\n description: string;\n /** The jobs the workflow says write it. */\n producedBy: string[];\n /** True when the workflow's run-directory block names this entry. */\n declared: boolean;\n state: WorkflowArtifactState;\n /** Bytes on disk, absent until the file exists. */\n size?: number;\n /** ISO 8601 of the last write, absent until the file exists. */\n modifiedAt?: string;\n}\n\nexport interface WorkflowArtifactsResponse {\n /** Absolute path of the run's own directory, which the reader may want to open. */\n runDir: string;\n /** What the workflow says the directory is for. */\n description: string;\n artifacts: WorkflowArtifactView[];\n}\n\n/** One artifact's metadata and optional text, as the viewer tab reads it. */\nexport interface WorkflowArtifactContentResponse {\n path: string;\n size: number;\n modifiedAt: string;\n /** Media type inferred from the file extension by the trusted hub. Absent on older hubs. */\n mimeType?: string;\n /** Present for text formats; binary files are streamed from the raw route instead. */\n text?: string;\n /** True when textual content was longer than the reader's byte budget. */\n truncated: boolean;\n}\n","import { randomUUID } from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { Readable } from 'node:stream';\n\nimport type { DoomApi, DoomApiContext, DoomApiHandler } from '@agimon-ai/doompi-core/packageApi';\nimport {\n WorkflowRegistryService,\n WorkflowTerminalService as WorkflowTerminalFacade,\n type WorkflowRunRecord,\n type WorkflowStage,\n} from '@agimon-ai/workflow-mcp';\nimport { type Context, Hono } from 'hono';\nimport { streamSSE } from 'hono/streaming';\n\nimport { createWorkflowTerminalService } from '../../services/workflowTerminal';\nimport routes, { ARTIFACT_DOWNLOAD_PARAM, ARTIFACT_RAW_PARAM } from '../../types/apiRoutes';\nimport {\n WORKFLOW_API_BASE_PATH,\n WORKFLOW_SCREEN_EVENT,\n type WorkflowArtifactContentResponse,\n type WorkflowArtifactsResponse,\n type WorkflowArtifactView,\n type WorkflowControlResponse,\n type WorkflowDeleteResponse,\n type WorkflowScreenEvent,\n} from '../../types/webWorkflowTerminal';\n\n/** Stages a run can be recorded under, newest first: a live run is the common case. */\nconst STAGES: readonly WorkflowStage[] = ['running', 'error', 'completed'];\n/** Lines of screen the stream sends, which is a terminal's visible height plus room. */\nconst SCREEN_LINES = 48;\n/** How often the stream re-reads; the service coalesces, so this is an upper bound. */\nconst STREAM_TICK_MS = 500;\n/** How often a settled run is re-checked before the stream closes itself. */\nconst SETTLED_POLL_TICKS = 4;\n/** Bytes of one textual artifact returned as JSON; binary previews use a stream. */\nconst MAX_ARTIFACT_BYTES = 512 * 1024;\n/** Path segments a client supplies are names, never paths. */\nconst SAFE_SEGMENT = /^[\\w.@-]+$/;\nconst ARTIFACT_MIME_TYPES: Readonly<Record<string, string>> = {\n '.aac': 'audio/aac',\n '.bmp': 'image/bmp',\n '.css': 'text/css',\n '.csv': 'text/csv',\n '.gif': 'image/gif',\n '.htm': 'text/html',\n '.html': 'text/html',\n '.ico': 'image/x-icon',\n '.jpeg': 'image/jpeg',\n '.jpg': 'image/jpeg',\n '.js': 'text/javascript',\n '.json': 'application/json',\n '.jsx': 'text/jsx',\n '.m4a': 'audio/mp4',\n '.markdown': 'text/markdown',\n '.md': 'text/markdown',\n '.mov': 'video/quicktime',\n '.mp3': 'audio/mpeg',\n '.mp4': 'video/mp4',\n '.oga': 'audio/ogg',\n '.ogg': 'audio/ogg',\n '.ogv': 'video/ogg',\n '.pdf': 'application/pdf',\n '.png': 'image/png',\n '.sh': 'text/x-shellscript',\n '.svg': 'image/svg+xml',\n '.toml': 'text/toml',\n '.ts': 'text/typescript',\n '.tsv': 'text/tab-separated-values',\n '.tsx': 'text/tsx',\n '.txt': 'text/plain',\n '.wav': 'audio/wav',\n '.webm': 'video/webm',\n '.webp': 'image/webp',\n '.xml': 'application/xml',\n '.yaml': 'text/yaml',\n '.yml': 'text/yaml',\n};\n\n/**\n * One request's JSON body as a plain record.\n *\n * A body that is absent, malformed, or not an object reads as empty rather\n * than failing the route: every field is checked by the route anyway, and a\n * 400 naming the missing field beats a parse error naming nothing.\n */\nasync function jsonBody(context: Context): Promise<Record<string, unknown>> {\n const parsed: unknown = await context.req.json().catch(() => undefined);\n return parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : {};\n}\n\n/** Rejects anything that could climb out of the registry before a path is built. */\nfunction isSafeSegment(value: string): boolean {\n return value !== '' && value !== '../adapters' && value !== '..' && SAFE_SEGMENT.test(value);\n}\n\n/** One run's identity for caches and leases, stable across stage moves. */\nfunction runIdentityOf(workspace: string, runKey: string): string {\n return `${workspace}/${runKey}`;\n}\n\nexport interface WorkflowHubApiOptions {\n registry?: WorkflowRegistryService;\n terminal?: WorkflowTerminalFacade;\n now?: () => number;\n}\n\n/**\n * This package's HTTP surface: one workflow run's terminal, and the files its\n * run directory holds.\n *\n * Mounted in the hub rather than in a session's server, because a run's\n * terminal belongs to its multiplexer rather than to the session that launched\n * it: any process can read a tmux pane, and the session's own server cannot\n * reach anything more. The routes therefore name a run, never a session.\n */\nexport function createWorkflowHubApi(options: WorkflowHubApiOptions = {}): Hono {\n const registry = options.registry ?? new WorkflowRegistryService();\n const facade = options.terminal ?? new WorkflowTerminalFacade();\n const terminal = createWorkflowTerminalService<WorkflowRunRecord>({\n terminal: facade,\n now: options.now ?? (() => Date.now()),\n });\n const app = new Hono();\n\n /** The record behind a request, whichever stage it now sits in. */\n const runOf = async (workspace: string, runKey: string): Promise<WorkflowRunRecord | undefined> => {\n if (!isSafeSegment(workspace) || !isSafeSegment(runKey)) return undefined;\n for (const stage of STAGES) {\n try {\n return await registry.readRunByKey(workspace, stage, runKey);\n } catch {\n // Not in this stage. A run moves between them as it settles, so a miss\n // here is ordinary; only a miss in every stage means no such run.\n }\n }\n return undefined;\n };\n\n const missing = (workspace: string, runKey: string): { error: string } => ({\n error: `No workflow run '${runKey}' in workspace '${workspace}'.`,\n });\n\n app.get(routes.screen.path, async (context) => {\n const workspace = context.req.param('workspace');\n const runKey = context.req.param('runKey');\n const record = await runOf(workspace, runKey);\n if (record === undefined) return context.json(missing(workspace, runKey), 404);\n const identity = runIdentityOf(workspace, runKey);\n\n return streamSSE(context, async (stream) => {\n let settledTicks = 0;\n let running = true;\n stream.onAbort(() => {\n running = false;\n });\n while (running) {\n const current = (await runOf(workspace, runKey)) ?? record;\n const capabilities = terminal.capabilities(current);\n const lines = capabilities.readable ? await terminal.screen(identity, current, SCREEN_LINES) : [];\n // A settled run is read a few more times before the stream closes: the\n // last thing a failing step printed is what the reader came for, and it\n // lands after the record has already moved to its final stage.\n const settled = current.stage !== 'running';\n if (settled) settledTicks += 1;\n const ended = settled && settledTicks >= SETTLED_POLL_TICKS;\n const event: WorkflowScreenEvent = { lines, capabilities, ...(ended ? { ended: true } : {}) };\n await stream.writeSSE({ event: WORKFLOW_SCREEN_EVENT, data: JSON.stringify(event) });\n if (ended) break;\n await stream.sleep(STREAM_TICK_MS);\n }\n terminal.forget(new Set());\n });\n });\n\n app.post(routes.control.path, async (context) => {\n const workspace = context.req.param('workspace');\n const runKey = context.req.param('runKey');\n const record = await runOf(workspace, runKey);\n if (record === undefined) return context.json(missing(workspace, runKey), 404);\n const identity = runIdentityOf(workspace, runKey);\n const body = await jsonBody(context);\n const capabilities = terminal.capabilities(record);\n\n if (body.release === true) {\n if (typeof body.token === 'string') terminal.releaseControl(identity, body.token);\n const released: WorkflowControlResponse = { held: false };\n return context.json(released);\n }\n if (!capabilities.writable) {\n const refused: WorkflowControlResponse = { held: false, reason: capabilities.reason };\n return context.json(refused, 409);\n }\n const token = typeof body.token === 'string' && body.token !== '' ? body.token : randomUUID();\n if (!terminal.takeControl(identity, token)) {\n const taken: WorkflowControlResponse = { held: false, reason: 'Another reader holds the keyboard.' };\n return context.json(taken, 409);\n }\n const held: WorkflowControlResponse = { held: true, token };\n return context.json(held);\n });\n\n app.post(routes.keys.path, async (context) => {\n const workspace = context.req.param('workspace');\n const runKey = context.req.param('runKey');\n const record = await runOf(workspace, runKey);\n if (record === undefined) return context.json(missing(workspace, runKey), 404);\n const body = await jsonBody(context);\n if (typeof body.token !== 'string' || typeof body.data !== 'string') {\n return context.json({ error: 'A keystroke needs a control token and its data.' }, 400);\n }\n try {\n await terminal.write(runIdentityOf(workspace, runKey), record, body.token, body.data);\n } catch (error) {\n return context.json({ error: error instanceof Error ? error.message : String(error) }, 409);\n }\n return context.body(null, 204);\n });\n\n app.post(routes.resize.path, async (context) => {\n const workspace = context.req.param('workspace');\n const runKey = context.req.param('runKey');\n const record = await runOf(workspace, runKey);\n if (record === undefined) return context.json(missing(workspace, runKey), 404);\n const body = await jsonBody(context);\n const { token, columns, rows } = body;\n if (typeof token !== 'string' || typeof columns !== 'number' || typeof rows !== 'number') {\n return context.json({ error: 'A resize needs a control token, columns and rows.' }, 400);\n }\n try {\n const resized = await terminal.resize(runIdentityOf(workspace, runKey), record, token, columns, rows);\n return context.json({ resized });\n } catch (error) {\n return context.json({ error: error instanceof Error ? error.message : String(error) }, 409);\n }\n });\n\n app.delete(routes.remove.path, async (context) => {\n const workspace = context.req.param('workspace');\n const runKey = context.req.param('runKey');\n const record = await runOf(workspace, runKey);\n if (record === undefined) return context.json(missing(workspace, runKey), 404);\n if (record.stage === 'running') {\n return context.json({ error: 'A running workflow must be stopped before it can be deleted.' }, 409);\n }\n try {\n fs.rmSync(registry.runDirectoryFor(record), { recursive: true, force: true });\n } catch (error) {\n return context.json({ error: error instanceof Error ? error.message : String(error) }, 409);\n }\n const response: WorkflowDeleteResponse = { deleted: true };\n return context.json(response);\n });\n\n app.get(routes.artifacts.path, async (context) => {\n const workspace = context.req.param('workspace');\n const runKey = context.req.param('runKey');\n const record = await runOf(workspace, runKey);\n if (record === undefined) return context.json(missing(workspace, runKey), 404);\n const runDir = registry.runDirectoryFor(record);\n const body: WorkflowArtifactsResponse = {\n runDir,\n description: record.runDirectory?.description ?? '',\n artifacts: readArtifacts(runDir, record),\n };\n return context.json(body);\n });\n\n app.get(routes.artifact.path, async (context) => {\n const workspace = context.req.param('workspace');\n const runKey = context.req.param('runKey');\n const record = await runOf(workspace, runKey);\n if (record === undefined) return context.json(missing(workspace, runKey), 404);\n const runDir = registry.runDirectoryFor(record);\n const requested = context.req.param('name');\n const resolved = resolveInside(runDir, requested);\n if (resolved === undefined) return context.json({ error: `'${requested}' is not inside this run.` }, 400);\n if (context.req.query(ARTIFACT_RAW_PARAM) === '1') {\n const response = streamArtifact(\n resolved,\n requested,\n context.req.header('range'),\n context.req.query(ARTIFACT_DOWNLOAD_PARAM) === '1',\n );\n return response ?? context.json({ error: `'${requested}' has not been written.` }, 404);\n }\n const body = readArtifact(resolved, requested);\n if (body === undefined) return context.json({ error: `'${requested}' has not been written.` }, 404);\n return context.json(body);\n });\n\n return app;\n}\n\n/**\n * A path inside the run directory, or undefined when it points anywhere else.\n *\n * The client supplies this one verbatim, unlike the run key, so it is resolved\n * and then checked rather than trusted: without the check the route would read\n * any file the hub can reach.\n */\nfunction resolveInside(runDir: string, requested: string): string | undefined {\n const resolved = path.resolve(runDir, requested);\n const root = path.resolve(runDir);\n if (resolved !== root && !resolved.startsWith(`${root}${path.sep}`)) return undefined;\n return resolved;\n}\n\n/** Size and modification time of one path, or undefined when it is not there. */\nfunction statOf(target: string): fs.Stats | undefined {\n try {\n return fs.statSync(target);\n } catch {\n return undefined; // Not written yet, which is an ordinary state for an artifact.\n }\n}\n\nfunction stateOf(stats: fs.Stats | undefined): WorkflowArtifactView['state'] {\n if (stats === undefined) return 'pending';\n if (stats.isDirectory()) return 'written';\n return stats.size === 0 ? 'empty' : 'written';\n}\n\nfunction viewOf(\n runDir: string,\n entry: Omit<WorkflowArtifactView, 'state' | 'size' | 'modifiedAt'>,\n): WorkflowArtifactView {\n const stats = statOf(path.join(runDir, entry.path));\n return {\n ...entry,\n state: stateOf(stats),\n ...(stats === undefined ? {} : { size: stats.size, modifiedAt: stats.mtime.toISOString() }),\n };\n}\n\n/**\n * What the run directory holds: the workflow's own declaration first, then the\n * files nobody declared.\n *\n * The declaration is the point of the folder, so it leads and keeps its order\n * even for entries no job has written yet. The rest follows rather than being\n * hidden: the engine's own context.md and progress log are often exactly what a\n * reader is looking for.\n */\nfunction readArtifacts(runDir: string, record: WorkflowRunRecord): WorkflowArtifactView[] {\n const declared = (record.runDirectory?.entries ?? []).map((entry) =>\n viewOf(runDir, {\n path: entry.path,\n kind: entry.kind,\n description: entry.description,\n producedBy: entry['produced-by'] ?? [],\n declared: true,\n }),\n );\n const claimed = new Set(declared.map((entry) => entry.path));\n let names: fs.Dirent[];\n try {\n names = fs.readdirSync(runDir, { withFileTypes: true });\n } catch {\n return declared; // The directory is gone; the declaration is still worth showing.\n }\n const found = names\n .filter((entry) => !claimed.has(entry.name))\n .map((entry) =>\n viewOf(runDir, {\n path: entry.name,\n kind: entry.isDirectory() ? 'directory' : 'file',\n description: '',\n producedBy: [],\n declared: false,\n }),\n )\n .sort((left, right) => left.path.localeCompare(right.path));\n return [...declared, ...found];\n}\n\n/** Browser content type inferred from a filename without trusting client input. */\nfunction artifactMimeType(requested: string): string {\n return ARTIFACT_MIME_TYPES[path.extname(requested).toLowerCase()] ?? 'application/octet-stream';\n}\n\nfunction isTextArtifact(mimeType: string): boolean {\n return mimeType.startsWith('text/') || mimeType === 'application/json' || mimeType === 'application/xml';\n}\n\n/** One artifact's metadata and bounded text, or undefined when it is not readable. */\nfunction readArtifact(resolved: string, requested: string): WorkflowArtifactContentResponse | undefined {\n const stats = statOf(resolved);\n if (stats === undefined || stats.isDirectory()) return undefined;\n const mimeType = artifactMimeType(requested);\n let text: string | undefined;\n if (isTextArtifact(mimeType)) {\n try {\n const handle = fs.openSync(resolved, 'r');\n try {\n const buffer = Buffer.alloc(Math.min(stats.size, MAX_ARTIFACT_BYTES));\n fs.readSync(handle, buffer, 0, buffer.length, 0);\n text = buffer.toString('utf8');\n } finally {\n fs.closeSync(handle);\n }\n } catch {\n return undefined;\n }\n }\n return {\n path: requested,\n size: stats.size,\n modifiedAt: stats.mtime.toISOString(),\n mimeType,\n ...(text === undefined ? {} : { text }),\n truncated: text !== undefined && stats.size > MAX_ARTIFACT_BYTES,\n };\n}\n\n/** Streams media with byte-range support so browser audio, video, and PDF controls can seek. */\nfunction streamArtifact(\n resolved: string,\n requested: string,\n rangeHeader: string | undefined,\n download: boolean,\n): Response | undefined {\n const stats = statOf(resolved);\n if (stats === undefined || stats.isDirectory()) return undefined;\n const mimeType = artifactMimeType(requested);\n let start = 0;\n let end = Math.max(0, stats.size - 1);\n let partial = false;\n const match = rangeHeader?.match(/^bytes=(\\d*)-(\\d*)$/);\n if (match !== null && match !== undefined && stats.size > 0) {\n const requestedStart = match[1] === '' ? undefined : Number(match[1]);\n const requestedEnd = match[2] === '' ? undefined : Number(match[2]);\n if (requestedStart === undefined && requestedEnd !== undefined) {\n start = Math.max(0, stats.size - requestedEnd);\n } else if (requestedStart !== undefined) {\n start = requestedStart;\n end = requestedEnd === undefined ? end : Math.min(requestedEnd, end);\n }\n if (start >= stats.size || start > end) {\n return new Response(null, { status: 416, headers: { 'content-range': `bytes */${String(stats.size)}` } });\n }\n partial = true;\n }\n const filename = path.basename(requested).replace(/[\"\\\\\\r\\n]/g, '_');\n const forceDownload = download || mimeType === 'text/html';\n const headers = new Headers({\n 'accept-ranges': 'bytes',\n 'content-disposition': `${forceDownload ? 'attachment' : 'inline'}; filename=\"${filename}\"`,\n 'content-length': String(stats.size === 0 ? 0 : end - start + 1),\n 'content-type': mimeType,\n 'x-content-type-options': 'nosniff',\n });\n if (partial) headers.set('content-range', `bytes ${String(start)}-${String(end)}/${String(stats.size)}`);\n if (stats.size === 0) return new Response(null, { status: 200, headers });\n const body = Readable.toWeb(fs.createReadStream(resolved, { start, end }));\n return new Response(body, { status: partial ? 206 : 200, headers });\n}\n\n/** The named export a host imports from this package's built hub entry. */\nexport const api: DoomApi = {\n basePath: WORKFLOW_API_BASE_PATH,\n start(_context: DoomApiContext): DoomApiHandler {\n // Hub-scoped: the host hands no session, and these routes want none. A run\n // is addressed by its registry identity, which is machine-wide.\n const app = createWorkflowHubApi();\n return {\n fetch: (request) => app.fetch(request),\n // Nothing outlives a request: a stream's loop ends when its own socket\n // aborts, and the caches it touched are per run rather than per client.\n close: () => undefined,\n };\n },\n};\n","import type { DoomServerPluginDefinition } from '@agimon-ai/doompi-core/serverFacet';\n\nimport { createWorkflowServerRuntime } from '../../../../../services/serverRuntime';\nimport { api } from '../../../../../services/workflowHubApi';\n\nexport default (({ agent, host }) => ({\n api: [api],\n ...(agent ? createWorkflowServerRuntime(agent, host) : {}),\n})) satisfies NonNullable<DoomServerPluginDefinition['session']>;\n","import { defineRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport runtime from './_lib/index.server';\n\nexport default defineRoot((context: Parameters<typeof runtime>[0]) => {\n const value = runtime(context);\n return {\n value,\n services: value.services,\n activities: value.activities,\n onStart: value.onStart,\n onStop: value.onStop,\n onDispose: value.onDispose,\n };\n});\n","import type { DoomHubChannelSource, DoomHubSessionScope, DoomHubChannel } from '@agimon-ai/doompi-core/hubChannel';\n\nimport {\n createWorkflowCatalogReader,\n presentWorkflowCatalog,\n type WorkflowCatalogReaderDeps,\n} from '../../services/webWorkflowCatalog';\nimport { defaultCatalogDeps } from '../../services/workflowCatalogDeps';\nimport { WORKFLOW_CATALOG_TYPE, type WorkflowCatalogPayload } from '../../types/webWorkflows';\n\nexport interface WorkflowCatalogChannelOptions {\n deps?: WorkflowCatalogReaderDeps;\n}\n\n/**\n * The workflow catalog channel. Durable state seeds a session once, then\n * session lifecycle events deliver updates over the direct event bus.\n */\nexport function createWorkflowCatalogChannel(options: WorkflowCatalogChannelOptions = {}): DoomHubChannel {\n const reader = createWorkflowCatalogReader(options.deps ?? defaultCatalogDeps());\n return {\n frameType: WORKFLOW_CATALOG_TYPE,\n start(host) {\n const scopes = new Map<string, DoomHubSessionScope>();\n const latest = new Map<string, WorkflowCatalogPayload>();\n const subscriptions = new Map<string, () => void>();\n const publish = (scope: DoomHubSessionScope, payload: WorkflowCatalogPayload): void => {\n latest.set(scope.sessionId, payload);\n host.publish(scope.sessionId, payload);\n };\n const readInitial = async (scope: DoomHubSessionScope): Promise<void> => {\n let payload: WorkflowCatalogPayload;\n try {\n payload = {\n cwd: scope.cwd,\n workflows: presentWorkflowCatalog(await reader.read(scope.cwd)),\n };\n } catch (error) {\n const warning = error instanceof Error ? error.message : String(error);\n payload = { cwd: scope.cwd, workflows: [], warning };\n host.onNotice(`workflow catalog for ${scope.cwd} is unavailable (${warning})`);\n }\n if (scopes.get(scope.sessionId) === scope) publish(scope, payload);\n };\n const source: DoomHubChannelSource = {\n payloadFor(scope) {\n return scopes.has(scope.sessionId) ? latest.get(scope.sessionId) : undefined;\n },\n sessionAdded(scope) {\n scopes.set(scope.sessionId, scope);\n subscriptions.get(scope.sessionId)?.();\n const unsubscribe = host.directEvents.subscribe(\n WORKFLOW_CATALOG_TYPE,\n scope.sessionId,\n (value) => {\n if (isWorkflowCatalogPayload(value)) publish(scope, value);\n },\n { replayLatest: true },\n );\n subscriptions.set(scope.sessionId, unsubscribe);\n void readInitial(scope);\n },\n sessionRemoved(sessionId) {\n subscriptions.get(sessionId)?.();\n subscriptions.delete(sessionId);\n scopes.delete(sessionId);\n latest.delete(sessionId);\n },\n close() {\n for (const unsubscribe of subscriptions.values()) unsubscribe();\n subscriptions.clear();\n scopes.clear();\n latest.clear();\n },\n };\n return source;\n },\n };\n}\n\nfunction isWorkflowCatalogPayload(value: unknown): value is WorkflowCatalogPayload {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as { cwd?: unknown }).cwd === 'string' &&\n Array.isArray((value as { workflows?: unknown }).workflows)\n );\n}\n","import type { DoomHubChannelSource, DoomHubSessionScope, DoomHubChannel } from '@agimon-ai/doompi-core/hubChannel';\n\nimport { presentWorkflowRuns, runBelongsToSession, type ParsedWorkflowRun } from '../../services/workflowRuns';\nimport { readWorkflowRuns, type ReadWorkflowRunsOptions } from '../../services/workflowWatcher';\nimport { WORKFLOW_RUNS_TYPE, type WorkflowRunView, type WorkflowRunsPayload } from '../../types/webWorkflows';\n\nexport interface WorkflowsChannelOptions {\n /** Injectable durable initial snapshot reader for tests. */\n read?: (options: ReadWorkflowRunsOptions) => ParsedWorkflowRun[];\n}\n\nfunction isWorkflowRunsPayload(value: unknown): value is WorkflowRunsPayload {\n return typeof value === 'object' && value !== null && Array.isArray((value as { runs?: unknown }).runs);\n}\n\n/**\n * The workflow runs data channel. Durable registry state seeds each session\n * once; subsequent updates arrive through the host-owned direct event bus.\n */\nexport function createWorkflowsChannel(options: WorkflowsChannelOptions = {}): DoomHubChannel {\n const read = options.read ?? readWorkflowRuns;\n return {\n frameType: WORKFLOW_RUNS_TYPE,\n start(host) {\n const scopes = new Map<string, DoomHubSessionScope>();\n const latest = new Map<string, WorkflowRunsPayload>();\n const subscriptions = new Map<string, () => void>();\n const runsFor = (scope: DoomHubSessionScope, parsed: readonly ParsedWorkflowRun[]): WorkflowRunView[] =>\n presentWorkflowRuns(\n parsed.filter((run) => runBelongsToSession(run, scope.sessionId)).map((run) => run.view),\n Date.now(),\n );\n const publish = (scope: DoomHubSessionScope, payload: WorkflowRunsPayload): void => {\n latest.set(scope.sessionId, payload);\n host.publish(scope.sessionId, payload);\n };\n const source: DoomHubChannelSource = {\n payloadFor(scope) {\n return scopes.has(scope.sessionId) ? latest.get(scope.sessionId) : undefined;\n },\n sessionAdded(scope) {\n scopes.set(scope.sessionId, scope);\n subscriptions.get(scope.sessionId)?.();\n const unsubscribe = host.directEvents.subscribe(\n WORKFLOW_RUNS_TYPE,\n scope.sessionId,\n (value) => {\n if (isWorkflowRunsPayload(value)) publish(scope, value);\n },\n { replayLatest: true },\n );\n subscriptions.set(scope.sessionId, unsubscribe);\n const payload = { runs: runsFor(scope, read({ environment: scope.environment })) };\n publish(scope, payload);\n },\n sessionRemoved(sessionId) {\n subscriptions.get(sessionId)?.();\n subscriptions.delete(sessionId);\n scopes.delete(sessionId);\n latest.delete(sessionId);\n },\n close() {\n for (const unsubscribe of subscriptions.values()) unsubscribe();\n subscriptions.clear();\n scopes.clear();\n latest.clear();\n },\n };\n return source;\n },\n };\n}\n","import type { DoomServerPluginDefinition } from '@agimon-ai/doompi-core/serverFacet';\n\nimport { createWorkflowCatalogChannel } from '../../../services/workflowCatalogChannel';\nimport { api } from '../../../services/workflowHubApi';\nimport { createWorkflowsChannel } from '../../../services/workflowsHubChannel';\n\nexport default (({ host }) =>\n host.scope === 'session'\n ? {}\n : { channels: [createWorkflowsChannel, createWorkflowCatalogChannel], api: [api] }) satisfies NonNullable<\n DoomServerPluginDefinition['global']\n>;\n","import { defineRoutedContribution } from '@agimon-ai/doompi-core/extensionFile';\n\nimport legacy from '../../_lib/index.server';\n\nexport default defineRoutedContribution((context: Parameters<typeof legacy>[0]) => legacy(context).api?.[0], {\n cardinality: 'optional',\n});\n","import { defineChannel } from '@agimon-ai/doompi-core/extensionFile';\n\nimport { createWorkflowCatalogChannel } from '../../../services/workflowCatalogChannel';\n\nexport default defineChannel(createWorkflowCatalogChannel);\n","import { defineChannel } from '@agimon-ai/doompi-core/extensionFile';\n\nimport { createWorkflowsChannel } from '../../../services/workflowsHubChannel';\n\nexport default defineChannel(createWorkflowsChannel);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport runtime from '../../_lib/index.server';\n\nexport default defineRoutedContribution(\n (context: WithRoot<unknown, ReturnType<typeof runtime>>) => context.root.api?.[0],\n { cardinality: 'optional' },\n);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport runtime from '../_lib/index.server';\n\nexport default defineRoutedContribution(\n (context: WithRoot<unknown, ReturnType<typeof runtime>>) => context.root.commands?.[0],\n { cardinality: 'optional' },\n);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport runtime from '../_lib/index.server';\n\nexport default defineRoutedContribution(\n (context: WithRoot<unknown, ReturnType<typeof runtime>>) => context.root.hooks?.[1],\n { cardinality: 'optional' },\n);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport runtime from '../_lib/index.server';\n\nexport default defineRoutedContribution(\n (context: WithRoot<unknown, ReturnType<typeof runtime>>) => context.root.hooks?.[0],\n { cardinality: 'optional' },\n);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport runtime from '../_lib/index.server';\n\nexport default defineRoutedContribution(\n (context: WithRoot<unknown, ReturnType<typeof runtime>>) => context.root.resources?.[0],\n { cardinality: 'optional' },\n);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport runtime from '../_lib/index.server';\n\nexport default defineRoutedContribution(\n (context: WithRoot<unknown, ReturnType<typeof runtime>>) => context.root.resources?.[1],\n { cardinality: 'optional' },\n);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport runtime from '../_lib/index.server';\n\nexport default defineRoutedContribution(\n (context: WithRoot<unknown, ReturnType<typeof runtime>>) => context.root.resources?.[2],\n { cardinality: 'optional' },\n);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport runtime from '../_lib/index.server';\n\nexport default defineRoutedContribution(\n (context: WithRoot<unknown, ReturnType<typeof runtime>>) => context.root.tools?.[1],\n { cardinality: 'optional' },\n);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport runtime from '../_lib/index.server';\n\nexport default defineRoutedContribution(\n (context: WithRoot<unknown, ReturnType<typeof runtime>>) => context.root.tools?.[0],\n { cardinality: 'optional' },\n);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport runtime from '../_lib/index.server';\n\nexport default defineRoutedContribution(\n (context: WithRoot<unknown, ReturnType<typeof runtime>>) => context.root.tools?.[2],\n { cardinality: 'optional' },\n);\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { defineServerPlugin, type DoomServerSessionPlugin } from '@agimon-ai/doompi-core/serverFacet';\nimport { composeRootHooks } from '@agimon-ai/doompi-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.server';\nimport apiRoute from '../src/extensions/(backend)/api/workflow/route.server';\nimport channelWorkflowCatalog from '../src/extensions/(backend)/channel/workflow-catalog.server';\nimport channelWorkflows from '../src/extensions/(backend)/channel/workflows.server';\nimport apiRoute2 from '../src/extensions/workspaces/sessions/(backend)/api/workflow/route.server';\nimport commandWorkflowLaunch from '../src/extensions/workspaces/sessions/(backend)/command/workflow-launch.server';\nimport hookSessionShutdown from '../src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server';\nimport hookToolExecutionEnd from '../src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.server';\nimport resourceDoompiAuthorWorkflow from '../src/extensions/workspaces/sessions/(backend)/resource/doompi-author-workflow.server';\nimport resourceDoompiUseWorkflow from '../src/extensions/workspaces/sessions/(backend)/resource/doompi-use-workflow.server';\nimport resourceWorkflowRecovery from '../src/extensions/workspaces/sessions/(backend)/resource/workflow-recovery.server';\nimport toolLaunchWorkflow from '../src/extensions/workspaces/sessions/(backend)/tool/launch-workflow.server';\nimport toolListWorkflows from '../src/extensions/workspaces/sessions/(backend)/tool/list-workflows.server';\nimport toolWorkflowRun from '../src/extensions/workspaces/sessions/(backend)/tool/workflow-run.server';\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\n/* v8 ignore next -- generated normalization branch */\nconst defined = <T>(values: readonly (T | undefined)[]): T[] =>\n values.filter((value): value is T => value !== undefined);\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const facet = defineServerPlugin({\n name: '@agimon-ai/doompi-workflow',\n global: (context) => ({\n get api(): DoomServerSessionPlugin['api'] { return defined([at(apiRoute, context)]); },\n get channels(): DoomServerSessionPlugin['channels'] { return [() => via({ frameType: 'workflow_catalog' }, channelWorkflowCatalog()), () => via({ frameType: 'workflows' }, channelWorkflows())]; },\n }),\n workspace: (context) => ({\n get api(): DoomServerSessionPlugin['api'] { return defined([at(apiRoute, context)]); },\n get channels(): DoomServerSessionPlugin['channels'] { return [() => via({ frameType: 'workflow_catalog' }, channelWorkflowCatalog()), () => via({ frameType: 'workflows' }, channelWorkflows())]; },\n }),\n session: async (context) => {\n const scopeSession = await rootSession(context);\n const contextSession = { ...context, root: scopeSession.value };\n return {\n ...composeRootHooks(scopeSession),\n get api(): DoomServerSessionPlugin['api'] { return defined([at(apiRoute, context), at(apiRoute2, contextSession)]); },\n get channels(): DoomServerSessionPlugin['channels'] { return [() => via({ frameType: 'workflow_catalog' }, channelWorkflowCatalog()), () => via({ frameType: 'workflows' }, channelWorkflows())]; },\n get commands(): DoomServerSessionPlugin['commands'] { return defined([via({ name: 'workflow-launch' }, at(commandWorkflowLaunch, contextSession))]); },\n get hooks(): DoomServerSessionPlugin['hooks'] { return defined([via({ event: 'session_shutdown' }, at(hookSessionShutdown, contextSession)), via({ event: 'tool_execution_end' }, at(hookToolExecutionEnd, contextSession))]); },\n get resources(): DoomServerSessionPlugin['resources'] { return defined([at(resourceDoompiAuthorWorkflow, contextSession), at(resourceDoompiUseWorkflow, contextSession), at(resourceWorkflowRecovery, contextSession)]); },\n get tools(): DoomServerSessionPlugin['tools'] { return defined([via({ name: 'launch_workflow' }, at(toolLaunchWorkflow, contextSession)), via({ name: 'list_workflows' }, at(toolListWorkflows, contextSession)), via({ name: 'workflow_run' }, at(toolWorkflowRun, contextSession))]); },\n services: [...(scopeSession.services ?? [])],\n get activities(): DoomServerSessionPlugin['activities'] { return [...(scopeSession.activities ?? [])]; },\n };\n },\n});\n\nexport default facet;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"server.cjs","names":["resolve","delay","textResult","fs","plain","WORKFLOW_LAUNCH_ID_ENV","path","createWorkflowLaunchExecutor","z","WORKFLOW_DECISION_STEERING_ENV","WORKFLOW_DECISION_STEERING_HOST","WORKFLOW_STEP_SESSION_PROVENANCE","WORKFLOW_DECISION_FILE_ENV","readStepDecision","gateStepDecision","NativeTerminalService","terminalSocketPath","serveNativeTerminal","fs","readWorkflowCatalog","summarizeWorkflow","diagnoseWorkflow","statSync","fs","connectNativeTerminal","path","defineApiRoutes","apiResponse","WorkflowRegistryService","WorkflowTerminalFacade","createWorkflowTerminalService","Hono","routes","streamSSE","randomUUID","path","fs","Readable","os","path","fs","createDoomTelemetry","createEmbeddedWorkflowFeature","randomUUID","resolve","relative","isAbsolute","validateWorkflowLaunch","routes","isWorkflowDispatcherProcess","resolveDispatcherParentSession","resolveRootSessionId","defineMinorMode","serverMinorModes","registerRunProvider","skill","z","parseWorkflowLaunchCommand","resolveWorkflowEntry","defineRoot","runtime","defineRoutedContribution","legacy","defineChannel","defineChannel","defineRoutedContribution","defineRoutedContribution","defineRoutedContribution","defineRoutedContribution","defineRoutedContribution","defineRoutedContribution","defineRoutedContribution","defineRoutedContribution","defineRoutedContribution","defineRoutedContribution","defineRoutedContribution","defineServerPlugin","apiRoute","channelWorkflowCatalog","channelWorkflows","rootSession","composeRootHooks","apiRoute2","commandWorkflowLaunch","hookSessionShutdown","hookToolExecutionEnd","resourceDoompiAuthorWorkflow","resourceDoompiUseWorkflow","resourceWorkflowRecovery","toolRestrictionDispatcher","toolLaunchWorkflow","toolListWorkflows","toolWorkflowRun"],"sources":["../../src/services/workflowRuns/index.ts","../../src/services/serverLaunch/index.ts","../../src/schemas/runConfig.ts","../../src/types/webWorkflows.ts","../../src/services/stepExecutor/index.ts","../../src/services/webWorkflowCatalog/index.ts","../../src/services/workflowCatalogDeps/index.ts","../../src/services/stepPaneTerminal/index.ts","../../src/types/apiRoutes.ts","../../src/types/webWorkflowTerminal.ts","../../src/services/workflowHubApi/index.ts","../../src/services/workflowWatcher/index.ts","../../src/services/serverRuntime/index.ts","../../src/extensions/workspaces/sessions/(backend)/_lib/index.server.ts","../../src/extensions/workspaces/sessions/(backend)/root.server.ts","../../src/services/workflowCatalogChannel/index.ts","../../src/services/workflowsHubChannel/index.ts","../../src/extensions/(backend)/_lib/index.server.ts","../../src/extensions/(backend)/api/workflow/route.server.ts","../../src/extensions/(backend)/channel/workflow-catalog.server.ts","../../src/extensions/(backend)/channel/workflows.server.ts","../../src/extensions/workspaces/sessions/(backend)/api/workflow/route.server.ts","../../src/extensions/workspaces/sessions/(backend)/command/workflow-launch.server.ts","../../src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.ts","../../src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.server.ts","../../src/extensions/workspaces/sessions/(backend)/resource/doompi-author-workflow.server.ts","../../src/extensions/workspaces/sessions/(backend)/resource/doompi-use-workflow.server.ts","../../src/extensions/workspaces/sessions/(backend)/resource/workflow-recovery.server.ts","../../src/extensions/workspaces/sessions/(backend)/tool-restriction/dispatcher.server.ts","../../src/extensions/workspaces/sessions/(backend)/tool/launch-workflow.server.ts","../../src/extensions/workspaces/sessions/(backend)/tool/list-workflows.server.ts","../../src/extensions/workspaces/sessions/(backend)/tool/workflow-run.server.ts","../../generated/server.ts"],"sourcesContent":["import { resolve } from 'node:path';\n\nimport type {\n WorkflowJobPhase,\n WorkflowJobView,\n WorkflowOutcome,\n WorkflowPosition,\n WorkflowProgressState,\n WorkflowRunView,\n WorkflowStage,\n WorkflowStepRefView,\n WorkflowStepView,\n} from '../../types/webWorkflows';\n\n/**\n * MIRRORS @agimon-ai/workflow-mcp's on-disk registry\n * (src/services/WorkflowRegistryService.ts and WorkflowProgressService.ts in\n * that package). The engine keeps one directory per run under\n * `<home>/workspaces/<workspace>/<stage>/<runKey>/` holding a `run.json`\n * record and an append-only `progress.ndjson` job/step log; the hub only ever\n * reads them. The derivation is duplicated rather than imported because\n * doompi-web must not depend on the engine at runtime; the unit suite pins\n * this mirror against the package's published types.\n */\nconst DEFAULT_WORKFLOW_HOME_DIR_NAME = '.workflow-mcp';\nexport const WORKFLOW_HOME_ENV = 'WORKFLOW_MCP_HOME';\nexport const WORKSPACES_DIR_NAME = 'workspaces';\nexport const RUN_RECORD_FILE_NAME = 'run.json';\nexport const PROGRESS_FILE_NAME = 'progress.ndjson';\nexport const WORKFLOW_STAGES: readonly WorkflowStage[] = ['running', 'completed', 'error'];\n\n/**\n * Errored runs stay a day, which is how long recovery has to act on them.\n *\n * Finished runs have no retention of their own: a session keeps every run it\n * launched, grouped by outcome, for as long as the session lives. A run leaves\n * the view when the engine prunes its registry directory, not on a timer here,\n * because \"what did this session run today\" is a question asked long after the\n * run settled.\n */\nexport const WORKFLOW_ERROR_RETENTION_MS = 24 * 60 * 60 * 1000;\n/**\n * Upper bound per outcome group rather than over the whole list.\n *\n * One cap across every run let a long stream of green runs push a failure out\n * of the list, which is the one thing that must never fall off the end.\n */\nexport const MAX_PRESENTED_WORKFLOW_RUNS_PER_GROUP = 24;\n\n/** The env key doompi-workflow stamps on runs it launches; ties a run to a Pi session. */\nexport const PI_SESSION_ENV = 'PI_SESSION_ID';\n\nconst PROGRESS_STATES: ReadonlySet<string> = new Set([\n 'running',\n 'completed',\n 'skipped',\n 'failed',\n 'pause_requested',\n 'paused',\n 'resumed',\n]);\nconst OUTCOMES: ReadonlySet<string> = new Set(['success', 'skipped', 'failed', 'interrupted']);\nconst EXECUTION_STATES: ReadonlySet<string> = new Set(['running', 'pause_requested', 'paused', 'resume_requested']);\nconst STEP_TERMINAL_STATES: ReadonlySet<WorkflowProgressState> = new Set(['completed', 'skipped', 'failed']);\n/** The engine records its pre:/post: blocks under these reserved pseudo-job names. */\nconst PHASE_JOB_PRE = 'pre';\nconst PHASE_JOB_POST = 'post';\n\n// oxlint-disable-next-line no-control-regex -- stripping terminal color codes from errorMessage is the point\nconst ANSI_ESCAPE_PATTERN = /\\u001b\\[[0-9;]*[A-Za-z]/g;\n\nexport interface WorkflowHomeInput {\n /** process.env.WORKFLOW_MCP_HOME, supplied by the caller. */\n envValue: string | undefined;\n /** os.homedir(), supplied by the caller. */\n homeDir: string;\n}\n\n/** Where workflow-mcp keeps its registry, mirroring the engine's own resolution. */\nexport function resolveWorkflowHome(input: WorkflowHomeInput): string {\n return resolve(\n input.envValue !== undefined && input.envValue !== ''\n ? input.envValue\n : resolve(input.homeDir, DEFAULT_WORKFLOW_HOME_DIR_NAME),\n );\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction asOptionalString(value: unknown): string | undefined {\n return typeof value === 'string' && value !== '' ? value : undefined;\n}\n\nfunction asOptionalNumber(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\n/** Text without its terminal escape codes, as a log file or a reader wants it. */\nexport function withoutAnsi(text: string): string {\n return text.replace(ANSI_ESCAPE_PATTERN, '');\n}\n\nfunction stripAnsi(text: string): string {\n return withoutAnsi(text).trim();\n}\n\n/**\n * One run record plus the facts the hub needs for session scoping but the\n * page never sees.\n */\nexport interface ParsedWorkflowRun {\n /** The wire view, before the progress log is folded in (jobs empty). */\n view: WorkflowRunView;\n /** env.PI_SESSION_ID from the record, when the launcher stamped one. */\n piSessionId?: string;\n}\n\n/**\n * Validates one run.json into the wire shape plus scoping facts.\n *\n * Returns undefined for anything unreadable or a foreign format. The record\n * is trusted for its own stage: the registry rewrites it when a run moves\n * between stage directories.\n */\nexport function parseWorkflowRunRecord(raw: string): ParsedWorkflowRun | undefined {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return undefined;\n }\n if (!isRecord(parsed)) return undefined;\n const runKey = asOptionalString(parsed.runKey);\n const workspace = asOptionalString(parsed.workspace);\n const workflowPath = asOptionalString(parsed.workflowPath);\n const startedAt = asOptionalString(parsed.startedAt);\n const stage = asOptionalString(parsed.stage);\n if (!runKey || !workspace || !workflowPath || !startedAt) return undefined;\n if (stage === undefined || !WORKFLOW_STAGES.includes(stage as WorkflowStage)) return undefined;\n\n const outcome = asOptionalString(parsed.outcome);\n const executionState = asOptionalString(parsed.executionState);\n const rawError = asOptionalString(parsed.errorMessage);\n const env = isRecord(parsed.env) ? parsed.env : undefined;\n const view: WorkflowRunView = {\n runKey,\n workspace,\n displayName: asOptionalString(parsed.displayName) ?? runKey,\n ...(asOptionalString(parsed.workflowName) === undefined\n ? {}\n : { workflowName: asOptionalString(parsed.workflowName) }),\n workflowPath,\n stage: stage as WorkflowStage,\n ...(outcome !== undefined && OUTCOMES.has(outcome) ? { outcome: outcome as WorkflowOutcome } : {}),\n ...(executionState !== undefined && EXECUTION_STATES.has(executionState)\n ? { executionState: executionState as WorkflowRunView['executionState'] }\n : {}),\n ...(asOptionalString(parsed.prompt) === undefined ? {} : { prompt: asOptionalString(parsed.prompt) }),\n startedAt,\n ...(asOptionalString(parsed.finishedAt) === undefined ? {} : { finishedAt: asOptionalString(parsed.finishedAt) }),\n ...(rawError === undefined ? {} : { errorMessage: stripAnsi(rawError) }),\n ...(asOptionalString(parsed.failedJob) === undefined ? {} : { failedJob: asOptionalString(parsed.failedJob) }),\n ...(parsed.stale === true ? { stale: true } : {}),\n ...(asOptionalString(parsed.staleReason) === undefined\n ? {}\n : { staleReason: asOptionalString(parsed.staleReason) }),\n ...(asOptionalString(parsed.worktreeBranch) === undefined\n ? {}\n : { worktreeBranch: asOptionalString(parsed.worktreeBranch) }),\n jobs: [],\n };\n const piSessionId = env === undefined ? undefined : asOptionalString(env[PI_SESSION_ENV]);\n return { view, ...(piSessionId === undefined ? {} : { piSessionId }) };\n}\n\ninterface WorkflowProgressEvent {\n type: 'job' | 'step';\n status: WorkflowProgressState;\n job: string;\n step?: string;\n index?: number;\n total?: number;\n reason?: string;\n ref?: WorkflowStepRefView;\n group?: string;\n at: string;\n}\n\nfunction parseStepRef(value: unknown): WorkflowStepRefView | undefined {\n if (!isRecord(value)) return undefined;\n const kind = asOptionalString(value.kind);\n const id = asOptionalString(value.id);\n if (!kind || !id) return undefined;\n const label = asOptionalString(value.label);\n return { kind, id, ...(label === undefined ? {} : { label }) };\n}\n\n/**\n * Parses the append-only progress log. Malformed lines are skipped rather\n * than failing the file: a reader routinely catches a torn final line\n * mid-append.\n */\nexport function parseWorkflowProgress(raw: string): WorkflowProgressEvent[] {\n const events: WorkflowProgressEvent[] = [];\n for (const line of raw.split('\\n')) {\n const trimmed = line.trim();\n if (trimmed === '') continue;\n let parsed: unknown;\n try {\n parsed = JSON.parse(trimmed);\n } catch {\n continue;\n }\n if (!isRecord(parsed)) continue;\n const type = parsed.type;\n const status = asOptionalString(parsed.status);\n const job = asOptionalString(parsed.job);\n const at = asOptionalString(parsed.at);\n if ((type !== 'job' && type !== 'step') || !job || !at) continue;\n if (status === undefined || !PROGRESS_STATES.has(status)) continue;\n const step = asOptionalString(parsed.step);\n const index = asOptionalNumber(parsed.index);\n const total = asOptionalNumber(parsed.total);\n const reason = asOptionalString(parsed.reason);\n const ref = parseStepRef(parsed.ref);\n const group = asOptionalString(parsed.group);\n events.push({\n type,\n status: status as WorkflowProgressState,\n job,\n ...(step === undefined ? {} : { step }),\n ...(index === undefined ? {} : { index }),\n ...(total === undefined ? {} : { total }),\n ...(reason === undefined ? {} : { reason }),\n ...(ref === undefined ? {} : { ref }),\n ...(group === undefined ? {} : { group }),\n at,\n });\n }\n return events;\n}\n\nfunction jobPhase(name: string): WorkflowJobPhase {\n if (name === PHASE_JOB_PRE) return PHASE_JOB_PRE;\n if (name === PHASE_JOB_POST) return PHASE_JOB_POST;\n return 'job';\n}\n\n/**\n * Folds the event log into the current job tree; later events win, so a job\n * that started and later failed reads as failed. Jobs and steps keep the\n * order of their first appearance.\n */\nexport function foldWorkflowProgress(events: readonly WorkflowProgressEvent[]): WorkflowJobView[] {\n const jobs: WorkflowJobView[] = [];\n const jobByName = new Map<string, WorkflowJobView>();\n for (const event of events) {\n let job = jobByName.get(event.job);\n if (job === undefined) {\n job = { name: event.job, phase: jobPhase(event.job), status: event.status, steps: [] };\n jobByName.set(event.job, job);\n jobs.push(job);\n }\n if (event.type === 'job') {\n job.status = event.status;\n if (event.reason !== undefined) job.reason = event.reason;\n if (event.index !== undefined) job.index = event.index;\n if (event.total !== undefined) job.total = event.total;\n if (event.status === 'running' && job.startedAt === undefined) job.startedAt = event.at;\n if (STEP_TERMINAL_STATES.has(event.status)) job.endedAt = event.at;\n continue;\n }\n if (event.step === undefined) continue;\n let step: WorkflowStepView | undefined = job.steps.find((candidate) => candidate.name === event.step);\n if (step === undefined) {\n step = { name: event.step, status: event.status };\n job.steps.push(step);\n } else if (event.status === 'running' && step.status !== 'running') {\n // Started again, as a fix loop does: nothing of the previous attempt, its\n // session or pane included, belongs to this one. Guidance for the old\n // session would wake an agent working beside the new attempt.\n delete step.ref;\n delete step.reason;\n delete step.endedAt;\n delete step.startedAt;\n }\n step.status = event.status;\n if (event.reason !== undefined) step.reason = event.reason;\n if (event.ref !== undefined) step.ref = event.ref;\n if (event.group !== undefined) step.group = event.group;\n if (event.status === 'running' && step.startedAt === undefined) step.startedAt = event.at;\n if (STEP_TERMINAL_STATES.has(event.status)) step.endedAt = event.at;\n }\n return jobs;\n}\n\nconst ACTIVE_PROGRESS_STATES: ReadonlySet<WorkflowProgressState> = new Set([\n 'running',\n 'pause_requested',\n 'paused',\n 'resumed',\n]);\n\n/** The job and step a run is on right now, for the NOW breadcrumb. */\nexport function workflowPosition(jobs: readonly WorkflowJobView[]): WorkflowPosition | undefined {\n for (let jobIndex = jobs.length - 1; jobIndex >= 0; jobIndex -= 1) {\n const job = jobs[jobIndex]!;\n if (!ACTIVE_PROGRESS_STATES.has(job.status)) continue;\n for (let stepIndex = job.steps.length - 1; stepIndex >= 0; stepIndex -= 1) {\n const step = job.steps[stepIndex]!;\n if (ACTIVE_PROGRESS_STATES.has(step.status)) {\n return {\n job: job.name,\n step: step.name,\n ...(job.index === undefined ? {} : { index: job.index }),\n ...(job.total === undefined ? {} : { total: job.total }),\n };\n }\n }\n return {\n job: job.name,\n ...(job.index === undefined ? {} : { index: job.index }),\n ...(job.total === undefined ? {} : { total: job.total }),\n };\n }\n return undefined;\n}\n\n/** The finished view: record fields plus the folded job tree and position. */\nexport function completeWorkflowRunView(view: WorkflowRunView, jobs: WorkflowJobView[]): WorkflowRunView {\n const position = view.stage === 'running' ? workflowPosition(jobs) : undefined;\n return { ...view, jobs, ...(position === undefined ? {} : { position }) };\n}\n\n/**\n * Whether a run belongs on a session's workflow tab: launched by that Pi\n * session, which is the same env test doompi-workflow's isSessionRun applies.\n *\n * The registry is one directory under $HOME shared by every repository and\n * every Pi session on the machine, so repository proximity is not ownership.\n * Scoping on it as well let two sessions open in one repo read each other's\n * history, and kept a dead session's runs on the board of every session that\n * replaced it. Fails closed on an unstamped record, which is what a launch\n * from the CLI rather than from a session leaves behind.\n */\nexport function runBelongsToSession(run: ParsedWorkflowRun, sessionId: string): boolean {\n return run.piSessionId !== undefined && run.piSessionId === sessionId;\n}\n\nfunction parseTime(value: string | undefined): number {\n if (value === undefined) return 0;\n const time = Date.parse(value);\n return Number.isFinite(time) ? time : 0;\n}\n\nconst STAGE_ORDER: Readonly<Record<WorkflowStage, number>> = { running: 0, error: 1, completed: 2 };\n\n/**\n * Whether a run still belongs in the view.\n *\n * Only errored runs age out here, and slowly: everything else a session\n * started stays until the engine forgets the run itself.\n */\nfunction withinRetention(run: WorkflowRunView, now: number): boolean {\n if (run.stage !== 'error') return true;\n const settledAt = parseTime(run.finishedAt) || parseTime(run.startedAt);\n return now - settledAt < WORKFLOW_ERROR_RETENTION_MS;\n}\n\n/**\n * When a run last moved, which is what orders it within its group.\n *\n * A running run has only its start; a settled one is ordered by when it\n * settled, because a list kept for the whole session is read as a history and\n * two runs started together can finish an hour apart.\n */\nfunction lastMovedAt(run: WorkflowRunView): number {\n return run.stage === 'running' ? parseTime(run.startedAt) : parseTime(run.finishedAt) || parseTime(run.startedAt);\n}\n\n/**\n * Running runs first, then errored (recovery acts on them), then finished;\n * newest first within a group, and each group capped on its own.\n */\nexport function presentWorkflowRuns(runs: readonly WorkflowRunView[], now: number): WorkflowRunView[] {\n const groups = new Map<WorkflowStage, WorkflowRunView[]>();\n for (const run of runs) {\n if (!withinRetention(run, now)) continue;\n const group = groups.get(run.stage);\n if (group) group.push(run);\n else groups.set(run.stage, [run]);\n }\n return [...groups.entries()]\n .sort(([left], [right]) => STAGE_ORDER[left] - STAGE_ORDER[right])\n .flatMap(([, group]) =>\n group\n .sort((left, right) => lastMovedAt(right) - lastMovedAt(left))\n .slice(0, MAX_PRESENTED_WORKFLOW_RUNS_PER_GROUP),\n );\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\n\nimport type { Logger, WorkflowRunRecord, WorkflowRunRegistration } from '@agimon-ai/workflow-mcp';\nimport type { CallToolResult } from '@modelcontextprotocol/server';\n\nimport { WORKFLOW_LAUNCH_ID_ENV } from '../../constants/workflow';\nimport type { StepTelemetry } from '../stepExecutor/type';\nimport {\n createWorkflowLaunchExecutor,\n type WorkflowLaunchContext,\n type WorkflowLaunchInput,\n} from '../workflowExecution';\nimport { withoutAnsi as plain } from '../workflowRuns';\nimport type { ServerLaunchDependencies, ServerLauncher } from './type';\n\n/** Beside the run's own files, so the run's artifacts list and its deletion both include it. */\nexport const RUN_LOG_FILENAME = 'engine.log';\n/** Exit codes a run ends with when nothing went wrong: finished, or skipped by its triggers. */\nconst SUCCESS_EXIT_CODES = new Set([0, 2]);\n/** Lines kept before a run has a directory to write them to. */\nconst PENDING_LINE_LIMIT = 500;\n/** How much of a failed run's output its telemetry keeps. */\nconst FAILURE_TAIL_LINES = 20;\n/** How long closing a session waits for its in-process runs to stop. */\nconst STOP_TIMEOUT_MS = 10_000;\nconst SESSION_CLOSED_REASON = 'The session that runs this workflow closed.';\nconst RUNNING_STAGE = 'running';\n\nconst LAUNCH_REQUESTED_EVENT = 'doom_workflow.launch_requested';\nconst RUN_STARTED_EVENT = 'doom_workflow.run_started';\nconst RUN_FINISHED_EVENT = 'doom_workflow.run_finished';\nconst RUN_FAILED_EVENT = 'doom_workflow.run_failed';\nconst ENGINE_ERROR_EVENT = 'doom_workflow.engine_error';\nconst ENGINE_WARNING_EVENT = 'doom_workflow.engine_warning';\nconst RUN_LOG_FAILED_EVENT = 'doom_workflow.run_log_failed';\nconst RUN_STOP_FAILED_EVENT = 'doom_workflow.run_stop_failed';\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((settle) => {\n const timer = setTimeout(settle, ms);\n timer.unref?.();\n });\n}\n\nfunction textResult(text: string, isError = false): CallToolResult {\n return { content: [{ type: 'text', text }], ...(isError ? { isError: true } : {}) };\n}\n\n/** An engine log for one run: its lines as they are written, then in the run directory. */\ninterface RunLog {\n readonly logger: Logger;\n /** Writes what was held so far into `file`, and every later line after it. */\n attach(file: string): void;\n /** Settles once every line written so far has reached the file. */\n flushed(): Promise<void>;\n}\n\n/**\n * The engine's log for one run, where a reader can find it.\n *\n * The engine writes why a step failed as a log line. Without a logger, those\n * lines exist only in the output the run returns at its end, so a run that is\n * still going, or one read later, has nothing to say about its failures. Here\n * every line goes to the run directory's `engine.log`, and errors and warnings\n * also go to telemetry, with the line as the exception so the text survives.\n */\nfunction createRunLog(telemetry: StepTelemetry | undefined): RunLog {\n const pending: string[] = [];\n let file: string | undefined;\n let writing = Promise.resolve();\n const reportLogFailure = (error: unknown): Promise<void> =>\n telemetry?.recordWarning(RUN_LOG_FAILED_EVENT, error) ?? Promise.resolve();\n const append = (line: string): void => {\n if (file === undefined) {\n pending.push(line);\n if (pending.length > PENDING_LINE_LIMIT) pending.shift();\n return;\n }\n const target = file;\n writing = writing.then(() => fs.promises.appendFile(target, `${line}\\n`, 'utf8')).catch(reportLogFailure);\n };\n return {\n logger: {\n info: (message) => append(plain(message)),\n warn: (message) => {\n const line = plain(message);\n append(line);\n void telemetry?.recordWarning(ENGINE_WARNING_EVENT, new Error(line.trim()));\n },\n error: (message) => {\n const line = plain(message);\n append(line);\n void telemetry?.recordError(ENGINE_ERROR_EVENT, new Error(line.trim()), {}, { includeException: true });\n },\n },\n attach(target) {\n file = target;\n const held = pending.splice(0);\n if (held.length === 0) return;\n writing = writing\n .then(() => fs.promises.appendFile(target, held.map((line) => `${line}\\n`).join(''), 'utf8'))\n .catch(reportLogFailure);\n },\n flushed: () => writing,\n };\n}\n\n/** A run this launcher started and has not seen end. */\ninterface ActiveRun {\n registration?: WorkflowRunRegistration;\n settled: Promise<void>;\n}\n\n/**\n * Runs workflows inside the DoomPi server for one session.\n *\n * It is the same launch the Pi extension runs, through the same executor:\n * the same Agiflow checks, capacity limit and runner check, and the same\n * answer once the run registers. What the server adds is where the run\n * happens, in this process with the host's step executor, and what it keeps:\n * each run's engine log, telemetry for its start and end, a notice when a run\n * fails after its launch already answered, and a stop for every run still\n * going when the session closes.\n */\nexport function createServerLauncher(dependencies: ServerLaunchDependencies): ServerLauncher {\n const { feature, telemetry } = dependencies;\n const active = new Map<string, ActiveRun>();\n\n const runInProcess = async (input: WorkflowLaunchInput): Promise<CallToolResult> => {\n const launchId = input.env?.[WORKFLOW_LAUNCH_ID_ENV];\n if (launchId === undefined) throw new Error('An in-process launch needs its launch id.');\n const log = createRunLog(telemetry);\n const run: ActiveRun = { settled: Promise.resolve() };\n active.set(launchId, run);\n const runner = input.runner ?? input.cliAgent;\n const execution = (async (): Promise<CallToolResult> => {\n try {\n const result = await feature.createRunService({ logger: log.logger }).run({\n ...input,\n ...(runner === undefined ? {} : { runner }),\n // In this process the host's step executor reaches the run; a terminal launcher would not.\n skipLaunch: true,\n onRegistered: (registration) => {\n run.registration = registration;\n log.attach(path.join(registration.runDir, RUN_LOG_FILENAME));\n void telemetry?.recordEvent(RUN_STARTED_EVENT, { outcome: 'started' });\n dependencies.onRunsChanged?.();\n },\n });\n if (SUCCESS_EXIT_CODES.has(result.exitCode)) {\n void telemetry?.recordEvent(RUN_FINISHED_EVENT, { outcome: 'success', exit_code: result.exitCode });\n return textResult(plain(result.output) || 'Workflow completed.');\n }\n const tail = plain(result.output).trim().split('\\n').slice(-FAILURE_TAIL_LINES).join('\\n');\n void telemetry?.recordError(\n RUN_FAILED_EVENT,\n new Error(tail || `The workflow exited with code ${String(result.exitCode)}.`),\n { exit_code: result.exitCode },\n { includeException: true },\n );\n // The engine's output is colored for a terminal; a notice or a tool result is not one.\n return textResult(`Workflow failed (exit code ${String(result.exitCode)}):\\n\\n${plain(result.output)}`, true);\n } catch (error) {\n void telemetry?.recordError(RUN_FAILED_EVENT, error, { outcome: 'error' }, { includeException: true });\n throw error;\n } finally {\n await log.flushed();\n active.delete(launchId);\n dependencies.onRunsChanged?.();\n }\n })();\n run.settled = execution.then(\n () => undefined,\n () => undefined,\n );\n return execution;\n };\n\n const executor = createWorkflowLaunchExecutor<WorkflowLaunchContext>({\n environment: dependencies.environment,\n activeRunCount: async () => active.size,\n ...(dependencies.rejectRunner === undefined ? {} : { rejectRunner: dependencies.rejectRunner }),\n runTool: { execute: runInProcess },\n // Every run is tracked in `active` by runInProcess itself.\n trackPendingRun: (pending) => pending,\n findLaunchedRun: async ({ launchId }): Promise<WorkflowRunRecord | undefined> => {\n const registration = active.get(launchId)?.registration;\n if (registration === undefined) return undefined;\n return feature.registry.readRunByKey(registration.workspace, RUNNING_STAGE, registration.runKey);\n },\n onLateFailure: (error) => {\n const detail = error instanceof Error ? error.message : String(error);\n void dependencies.notify(`Workflow launch failed after it was reported started.\\n${detail}`, 'warning');\n },\n onLaunch: () => {\n void telemetry?.recordEvent(LAUNCH_REQUESTED_EVENT, { outcome: 'requested' });\n dependencies.onRunsChanged?.();\n },\n ...(dependencies.launchAckPollMs === undefined ? {} : { launchAckPollMs: dependencies.launchAckPollMs }),\n ...(dependencies.launchAckTimeoutMs === undefined ? {} : { launchAckTimeoutMs: dependencies.launchAckTimeoutMs }),\n });\n const context: WorkflowLaunchContext = { sessionManager: { getSessionId: () => dependencies.sessionId } };\n\n return {\n launch: (input) => executor.execute(input, context),\n activeRunCount: () => active.size,\n async dispose() {\n const runs = [...active.values()];\n if (runs.length === 0) return;\n // The same stop the web panel and the workflow tool request; the engine reads it between steps.\n await Promise.all(\n runs.map(async ({ registration }) => {\n if (registration === undefined) return;\n try {\n await feature.registry.requestStop(\n registration.workspace,\n registration.runKey,\n SESSION_CLOSED_REASON,\n registration.runId,\n );\n } catch (error) {\n await telemetry?.recordWarning(RUN_STOP_FAILED_EVENT, error);\n }\n }),\n );\n await Promise.race([\n Promise.all(runs.map((run) => run.settled)),\n delay(dependencies.stopTimeoutMs ?? STOP_TIMEOUT_MS),\n ]);\n },\n };\n}\n","import { z } from 'zod';\n\n/** A YAML list, or one comma-separated string, as `--domains a,b` accepts. */\nconst nameList = z\n .union([z.string(), z.array(z.string())])\n .transform((value) =>\n (Array.isArray(value) ? value : value.split(',')).map((name) => name.trim()).filter((name) => name.length > 0),\n );\n\nconst singleName = z.string().trim().min(1);\n\n/**\n * The DoomPi keys of a workflow step's `runConfig`.\n *\n * The engine treats `runConfig` as an opaque map, so this is where a typo such\n * as `majormode` is caught instead of silently running on workspace defaults.\n */\nexport const doompiRunConfigSchema = z\n .object({\n majorMode: singleName.optional().describe('Major mode the step session runs in.'),\n minorModes: nameList.optional().describe('Minor modes activated in the step session.'),\n profile: singleName.optional().describe('Profile the step session runs as.'),\n domains: nameList.optional().describe('Domains selected for the step session. An empty list selects none.'),\n model: singleName.optional().describe('Model selector, provider/id.'),\n thinking: singleName.optional().describe('Thinking level for the model.'),\n })\n .strict();\n\n/**\n * The same keys for a templated step, whose `runConfig` is also the data its\n * command template reads: keys DoomPi does not use are left to the template.\n */\nexport const doompiTemplateRunConfigSchema = doompiRunConfigSchema.strip();\n\nexport type DoompiRunConfig = z.infer<typeof doompiRunConfigSchema>;\n\n/** The runConfig keys DoomPi reads itself, the host keys `workflow-mcp doctor` checks steps against. */\nexport const DOOMPI_RUN_CONFIG_KEYS: readonly string[] = doompiRunConfigSchema.keyof().options;\n","/**\n * Workflow run view types shared by this package's hub channel and its web\n * plugin. The shapes mirror what the embedded workflow-mcp engine records;\n * the cockpit renders them as 'workflow_runs' channel payloads.\n */\n\n/** workflow-mcp's own stage vocabulary; the registry bucket a run record sits in. */\nexport type WorkflowStage = 'running' | 'completed' | 'error';\n\n/** workflow-mcp's terminal outcome for a finished run. */\nexport type WorkflowOutcome = 'success' | 'skipped' | 'failed' | 'interrupted';\n\n/** Job and step states as workflow-mcp records them in the progress log. */\nexport type WorkflowProgressState =\n | 'running'\n | 'completed'\n | 'skipped'\n | 'failed'\n | 'pause_requested'\n | 'paused'\n | 'resumed';\n\n/** A customRun step ran as this child session. */\nexport const STEP_SESSION_REF_KIND = 'session';\n/** A command step ran in this terminal pane. */\nexport const STEP_PANE_REF_KIND = 'pane';\n\n/** Where a host executor ran a step: `session` for a customRun agent, `pane` for a command. */\nexport interface WorkflowStepRefView {\n kind: string;\n id: string;\n label?: string;\n}\n\nexport interface WorkflowStepView {\n name: string;\n status: WorkflowProgressState;\n /** Kept after the step ends, so a finished agent step still opens its conversation. */\n ref?: WorkflowStepRefView;\n /** Why the step is in its state, when the engine recorded one (e.g. a skip condition). */\n reason?: string;\n /** The parallel group the step ran in, beside the group's other steps. */\n group?: string;\n /** ISO 8601 of the step's first running event. */\n startedAt?: string;\n /** ISO 8601 of the step's terminal event. */\n endedAt?: string;\n}\n\n/** 'pre' and 'post' are the engine's pseudo-jobs for its pre:/post: blocks. */\nexport type WorkflowJobPhase = 'pre' | 'job' | 'post';\n\nexport interface WorkflowJobView {\n name: string;\n phase: WorkflowJobPhase;\n status: WorkflowProgressState;\n reason?: string;\n /** Position among the run's jobs, when the engine recorded one. */\n index?: number;\n total?: number;\n startedAt?: string;\n endedAt?: string;\n steps: WorkflowStepView[];\n}\n\n/** The job and step a run is on right now; drives the NOW breadcrumb. */\nexport interface WorkflowPosition {\n job: string;\n step?: string;\n index?: number;\n total?: number;\n}\n\n/**\n * One workflow run of a session, read from workflow-mcp's registry: the\n * run.json record plus the folded progress.ndjson job tree.\n */\nexport interface WorkflowRunView {\n /** Registry identity within its workspace; unique per workspace+stage. */\n runKey: string;\n workspace: string;\n displayName: string;\n workflowName?: string;\n workflowPath: string;\n stage: WorkflowStage;\n outcome?: WorkflowOutcome;\n /** Present while the engine is pausing or paused; absent for plain running. */\n executionState?: 'running' | 'pause_requested' | 'paused' | 'resume_requested';\n /** The prompt the run was launched with, when one was recorded. */\n prompt?: string;\n /** ISO 8601, from the run record. */\n startedAt: string;\n finishedAt?: string;\n /** Failure cause with ANSI escapes stripped, present when the run errored. */\n errorMessage?: string;\n /** The job the engine blamed for the failure, when it recorded one. */\n failedJob?: string;\n /** True when reconciliation decided the recorded pid is no longer alive. */\n stale?: boolean;\n staleReason?: string;\n worktreeBranch?: string;\n position?: WorkflowPosition;\n jobs: WorkflowJobView[];\n}\n\n/** What the workflow runs channel publishes for one session. */\nexport interface WorkflowRunsPayload {\n runs: WorkflowRunView[];\n}\n\nexport const WORKFLOW_RUNS_TYPE = 'workflow_runs';\n\n/**\n * One workflow the session's directory can launch, as the catalog drawer\n * lists it: the engine's own catalog entry plus the parsed detail the drawer\n * unfolds and the launch dialog turns into fields.\n */\nexport interface WorkflowCatalogEntryView {\n /** Absolute path, the row's stable identity. */\n path: string;\n relativePath: string;\n name: string;\n description: string;\n tags: string[];\n /** The trigger names the file declares, such as workflow_dispatch. */\n triggers: string[];\n inputs: WorkflowCatalogInputView[];\n jobs: WorkflowCatalogJobView[];\n artifacts: WorkflowCatalogArtifactView[];\n /** Absent when the workflow names no runner map, which means any runner will do. */\n runners?: string[];\n /** Commands every templated step offers; absent when no step is templated. */\n commands?: string[];\n /** Declared model choices; `default` is used when a launch names none. */\n choices?: string[];\n /** Set when the file could not be parsed; the row shows this instead of guessing. */\n error?: string;\n}\n\nexport interface WorkflowCatalogInputView {\n name: string;\n description?: string;\n required?: boolean;\n default?: string;\n type?: string;\n options?: string[];\n}\n\nexport interface WorkflowCatalogJobView {\n name: string;\n steps: string[];\n}\n\nexport interface WorkflowCatalogArtifactView {\n path: string;\n kind: 'file' | 'directory';\n description: string;\n producedBy: string[];\n}\n\n/** What the catalog channel publishes for one session. */\nexport interface WorkflowCatalogPayload {\n /** The directory the catalog was read from, which is the session's own. */\n cwd: string;\n workflows: WorkflowCatalogEntryView[];\n /** Present when the directory could not be read at all. */\n warning?: string;\n}\n\nexport const WORKFLOW_CATALOG_TYPE = 'workflow_catalog';\n","import fs from 'node:fs';\n\nimport { type DoomHubSessionSelection, WORKFLOW_STEP_SESSION_PROVENANCE } from '@agimon-ai/doompi-core/hubChannel';\nimport {\n gateStepDecision,\n NativeTerminalService,\n readStepDecision,\n serveNativeTerminal,\n type StepExecution,\n type StepExecutionOutcome,\n type StepExecutor,\n terminalSocketPath,\n WORKFLOW_DECISION_FILE_ENV,\n WORKFLOW_DECISION_STEERING_ENV,\n WORKFLOW_DECISION_STEERING_HOST,\n} from '@agimon-ai/workflow-mcp';\n\nimport {\n DOOMPI_RUN_CONFIG_KEYS,\n type DoompiRunConfig,\n doompiRunConfigSchema,\n doompiTemplateRunConfigSchema,\n} from '../../schemas/runConfig';\nimport { STEP_PANE_REF_KIND, STEP_SESSION_REF_KIND } from '../../types/webWorkflows';\nimport type { StepExecutorDependencies, StepPaneLauncher, StepTelemetry } from './type';\n\nconst STEP_DISPLAY_ENV = 'WORKFLOW_STEP_DISPLAY';\nconst WORKFLOW_NAME_ENV = 'WORKFLOW_NAME';\n/** The engine's completion signal for terminal agents; a session this host steers never uses it. */\nconst WORKFLOW_STATUS_FILE_ENV = 'WORKFLOW_STATUS_FILE';\n/** How long a busy step session is left to finish a turn it was given elsewhere, such as web guidance. */\nconst BUSY_RETRY_MS = 2_000;\n/** How long ending a step's session may take before the step stops waiting for it. */\nconst RELEASE_TIMEOUT_MS = 10_000;\n/** What the runtime says when a turn is already running; the reminder then waits for it. */\nconst BUSY_SESSION_PATTERN = /\\bbusy\\b|LaneBusy/i;\n\nconst STEP_SESSION_STARTED_EVENT = 'doom_workflow.step_session_started';\nconst STEP_SESSION_FAILED_EVENT = 'doom_workflow.step_session_failed';\nconst STEP_REMINDER_EVENT = 'doom_workflow.step_reminder';\nconst STEP_SESSION_RELEASE_FAILED_EVENT = 'doom_workflow.step_session_release_failed';\nconst STEP_PANE_FAILED_EVENT = 'doom_workflow.step_pane_failed';\n\n/** The command template a templated step runs through: its name, and the values it reads. */\nexport interface RunConfigTemplate {\n readonly name: string;\n readonly reads?: readonly string[];\n}\n\nconst DOOMPI_KEYS: ReadonlySet<string> = new Set(DOOMPI_RUN_CONFIG_KEYS);\n\n/**\n * A step's `runConfig`, validated against the keys DoomPi understands.\n *\n * A templated step's may also carry keys its command template reads. A key\n * that is neither, such as `majormode`, fails the step rather than running it\n * on workspace defaults. An engine that does not say what its template reads\n * leaves such keys unchecked.\n */\nexport function readDoompiRunConfig(runConfig: unknown, template?: RunConfigTemplate): DoompiRunConfig {\n const parsed = (template === undefined ? doompiRunConfigSchema : doompiTemplateRunConfigSchema).safeParse(\n runConfig ?? {},\n );\n if (!parsed.success) {\n const problems = parsed.error.issues.map((issue) => `${issue.path.join('.') || 'runConfig'}: ${issue.message}`);\n throw new Error(`Invalid runConfig: ${problems.join('; ')}`);\n }\n if (template?.reads !== undefined && typeof runConfig === 'object' && runConfig !== null) {\n const reads = new Set(template.reads);\n const unknown = Object.keys(runConfig).filter((key) => !DOOMPI_KEYS.has(key) && !reads.has(key));\n if (unknown.length > 0) {\n throw new Error(\n `Invalid runConfig: ${unknown.join(', ')} is neither a DoomPi setting nor read by the \"${template.name}\" command.`,\n );\n }\n }\n return parsed.data;\n}\n\n/** The selection a step session is pinned to; unset keys keep the workspace defaults. */\nexport function sessionSelection(config: DoompiRunConfig): DoomHubSessionSelection {\n return {\n ...(config.majorMode === undefined ? {} : { majorMode: config.majorMode }),\n ...(config.minorModes === undefined ? {} : { minorModes: config.minorModes }),\n ...(config.profile === undefined ? {} : { profile: config.profile }),\n ...(config.domains === undefined ? {} : { domains: config.domains }),\n };\n}\n\n/**\n * What a step adds to the host environment.\n *\n * The step environment is the whole process environment plus the run's own\n * keys. Handing all of it to the session would pin a copy of the host's\n * variables into it; the difference is the part the agent actually needs, such\n * as WORKFLOW_RUN_DIR for the artifacts its prompt names.\n */\nexport function stepEnvironment(\n env: Readonly<Record<string, string>>,\n host: Readonly<Record<string, string | undefined>>,\n): Record<string, string> {\n return Object.fromEntries(Object.entries(env).filter(([key, value]) => host[key] !== value));\n}\n\nfunction stepSessionName(env: Readonly<Record<string, string>>, stepName: string): string {\n const display = env[STEP_DISPLAY_ENV] ?? stepName;\n const workflow = env[WORKFLOW_NAME_ENV];\n return workflow ? `${workflow}: ${display}` : display;\n}\n\nfunction asError(error: unknown): Error {\n return error instanceof Error ? error : new Error(String(error));\n}\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((settle) => {\n const timer = setTimeout(settle, ms);\n timer.unref?.();\n });\n}\n\n/** A promise settled by `settle`, so a stop can end a wait that nothing else would. */\nfunction signal(): { promise: Promise<void>; settle: () => void } {\n let settle: () => void = () => undefined;\n const promise = new Promise<void>((resolve) => {\n settle = resolve;\n });\n return { promise, settle };\n}\n\n/**\n * An execution that already failed, with why.\n *\n * Returned instead of throwing: the engine reports a thrown start as a spawn\n * error about shells and permissions, while a failed completion keeps this\n * message as the step's reason.\n */\nfunction failedExecution(error: unknown): StepExecution {\n return { completion: Promise.resolve({ error: asError(error) }), stop: async () => undefined };\n}\n\n/** What one step session runs: its settings, what it is asked, and the step it reports on. */\ninterface StepSessionRequest {\n readonly cwd: string;\n readonly env: Readonly<Record<string, string>>;\n readonly stepName: string;\n readonly runConfig: unknown;\n readonly prompt: string;\n readonly systemPrompt?: string;\n /** A templated step's command: its runConfig also feeds that command's template. */\n readonly template?: RunConfigTemplate;\n}\n\n/**\n * Runs workflow steps inside DoomPi instead of a shell.\n *\n * A customRun step becomes a child session of the launching session, with the\n * step's major mode, minor modes, profile, domains and model, so its messages\n * stream like any other conversation. Command steps go to their own terminal\n * pane when a launcher is available and fall back to the engine's spawn when\n * it is not.\n */\nexport function createStepExecutor(dependencies: StepExecutorDependencies): StepExecutor {\n const { sessionService, launchPane, telemetry } = dependencies;\n const prompt = sessionService.prompt?.bind(sessionService);\n\n /**\n * Run a step as a child session of the launching session, with the step's\n * major mode, minor modes, profile, domains and model.\n *\n * The session keeps going until the step has what the workflow needs: each\n * time the agent settles, the engine's decision gate is asked, and while\n * the step still lacks a decision (or its declared artifacts) the session is\n * prompted with the gate's reminder. The gate counts reminders against its\n * cap, so a stuck agent ends and the engine fails the step.\n */\n async function runSession(request: StepSessionRequest): Promise<StepExecution> {\n if (prompt === undefined) return failedExecution('This host cannot prompt sessions, so this step cannot run here.');\n const attributes = { 'workflow.step.name': request.stepName, templated: request.template !== undefined };\n let scope: Awaited<ReturnType<typeof sessionService.create>>;\n let name: string;\n try {\n const config = readDoompiRunConfig(request.runConfig, request.template);\n name = stepSessionName(request.env, request.stepName);\n const environment = stepEnvironment(request.env, dependencies.hostEnvironment);\n // This host ends the step when the agent settles and steers it itself, so\n // hooks inside the session must neither end the step nor nudge the agent.\n delete environment[WORKFLOW_STATUS_FILE_ENV];\n environment[WORKFLOW_DECISION_STEERING_ENV] = WORKFLOW_DECISION_STEERING_HOST;\n scope = await sessionService.create({\n cwd: request.cwd,\n name,\n parentSessionId: dependencies.parentSessionId,\n // Keeps the session out of the rail: its conversation is read in the workflow's view.\n sessionProvenance: WORKFLOW_STEP_SESSION_PROVENANCE,\n selection: sessionSelection(config),\n ...(config.model === undefined ? {} : { model: config.model }),\n ...(config.thinking === undefined ? {} : { thinking: config.thinking }),\n ...(request.systemPrompt === undefined ? {} : { appendSystemPrompt: request.systemPrompt }),\n environment,\n });\n } catch (error) {\n void telemetry?.recordError(STEP_SESSION_FAILED_EVENT, error, attributes, { includeException: true });\n return failedExecution(error);\n }\n void telemetry?.recordEvent(STEP_SESSION_STARTED_EVENT, { ...attributes, outcome: 'started' });\n const sessionId = scope.sessionId;\n const stopped = signal();\n let stopRequested = false;\n const decided = (): boolean => {\n const path = request.env[WORKFLOW_DECISION_FILE_ENV];\n return path !== undefined && readStepDecision(path) !== undefined;\n };\n\n /**\n * Give the agent the gate's reminder. A session busy with a turn it was\n * given elsewhere, like web guidance, is left to finish it, then reminded\n * unless it decided meanwhile. Undefined means the step needs no more turns.\n */\n const remind = async (message: string): Promise<{ settled: Promise<void> } | undefined> => {\n for (;;) {\n try {\n return await prompt(sessionId, message);\n } catch (error) {\n if (!BUSY_SESSION_PATTERN.test(asError(error).message)) throw error;\n void telemetry?.recordEvent(STEP_REMINDER_EVENT, { ...attributes, outcome: 'busy' });\n await Promise.race([delay(dependencies.busyRetryMs ?? BUSY_RETRY_MS), stopped.promise]);\n if (stopRequested || decided()) return undefined;\n }\n }\n };\n\n /**\n * End the session once the step is over. Released, it stays readable in the\n * workflow's view without holding a model, tools and extensions in the host.\n * A host that cannot release it is asked to abort a stopped turn instead.\n */\n const endSession = async (): Promise<void> => {\n const ending = sessionService.release\n ? sessionService.release(sessionId)\n : stopRequested\n ? (sessionService.abort?.(sessionId) ?? Promise.resolve())\n : Promise.resolve();\n const timeout = delay(dependencies.releaseTimeoutMs ?? RELEASE_TIMEOUT_MS).then(() => {\n throw new Error(\n `The step session did not end within ${String(dependencies.releaseTimeoutMs ?? RELEASE_TIMEOUT_MS)}ms.`,\n );\n });\n try {\n await Promise.race([ending, timeout]);\n } catch (error) {\n // The step's outcome is already decided; a session left running is reported, not fatal.\n void telemetry?.recordWarning(STEP_SESSION_RELEASE_FAILED_EVENT, error, attributes);\n }\n };\n\n const completion = async (): Promise<StepExecutionOutcome> => {\n let receipt: { settled: Promise<void> } | undefined = await prompt(sessionId, request.prompt);\n while (receipt !== undefined) {\n // A stop ends the wait even when the turn itself never settles.\n await Promise.race([receipt.settled, stopped.promise]);\n if (stopRequested) return { exitCode: 0 };\n const gate = await gateStepDecision(request.env);\n if (gate.action === 'allow') return { exitCode: 0 };\n void telemetry?.recordEvent(STEP_REMINDER_EVENT, { ...attributes, outcome: 'sent' });\n receipt = await remind(gate.message);\n }\n return { exitCode: 0 };\n };\n return {\n ref: { kind: STEP_SESSION_REF_KIND, id: sessionId, label: name },\n completion: completion()\n .catch((error: unknown): StepExecutionOutcome => ({ error: asError(error) }))\n .then(async (outcome) => {\n await endSession();\n return outcome;\n }),\n stop: async () => {\n stopRequested = true;\n stopped.settle();\n },\n };\n }\n\n return {\n async custom(request) {\n return runSession({\n cwd: request.cwd,\n env: request.env,\n stepName: request.stepName,\n runConfig: request.runConfig,\n prompt: request.customRun.prompt,\n ...(request.customRun.systemPrompt === undefined ? {} : { systemPrompt: request.customRun.systemPrompt }),\n });\n },\n async command(request) {\n // A templated command that allows it runs in-process from its values;\n // its rendered shell command is only the fallback for other hosts.\n const template = request.template;\n if (template?.inProcess && prompt !== undefined) {\n return runSession({\n cwd: request.cwd,\n env: request.env,\n stepName: request.stepName,\n runConfig: request.runConfig,\n template: { name: template.name, ...(template.reads === undefined ? {} : { reads: template.reads }) },\n prompt: template.prompt,\n ...(template.systemPrompt === undefined ? {} : { systemPrompt: template.systemPrompt }),\n });\n }\n if (launchPane === undefined) return undefined;\n let pane: Awaited<ReturnType<StepPaneLauncher>>;\n try {\n pane = await launchPane({\n id: dependencies.createId(),\n command: request.command,\n cwd: request.cwd,\n env: request.env,\n });\n } catch (error) {\n void telemetry?.recordError(\n STEP_PANE_FAILED_EVENT,\n error,\n { 'workflow.step.name': request.stepName },\n {\n includeException: true,\n },\n );\n return failedExecution(error);\n }\n if (pane === undefined) return undefined;\n return {\n ref: { kind: STEP_PANE_REF_KIND, id: pane.target, label: request.stepName },\n completion: pane.completion.then(\n (result): StepExecutionOutcome => result,\n (error: unknown): StepExecutionOutcome => ({ error: asError(error) }),\n ),\n stop: async () => {\n await pane.stop();\n },\n };\n },\n };\n}\n\n/** The shell a command step runs in, the same one the engine spawns it with. */\nconst STEP_SHELL = '/bin/zsh';\n/** Namespace for step pane sockets, apart from whole-run terminal sockets. */\nconst STEP_PANE_SOCKET_SCOPE = 'doompi-workflow-steps';\nconst PANE_LOG_SUFFIX = '.log';\nconst PANE_CAPTURE_COLUMNS = 120;\nconst PANE_CAPTURE_ROWS = 40;\n\n/** Where a finished step pane's last screen is kept: beside the socket that served it. */\nexport function stepPaneLogPath(socketPath: string): string {\n return `${socketPath}${PANE_LOG_SUFFIX}`;\n}\n\n/** The pane's current screen, or undefined once there is no pane left to read. */\nasync function lastScreen(service: NativeTerminalService, key: string): Promise<string | undefined> {\n try {\n const viewer = await service.attach(key, PANE_CAPTURE_COLUMNS, PANE_CAPTURE_ROWS);\n const lines = await viewer.snapshot();\n viewer.detach();\n return `${lines.join('\\n')}\\n`;\n } catch {\n // Nothing is left to read; the step's outcome does not depend on its last screen.\n return undefined;\n }\n}\n\n/**\n * Opens each command step in its own RMUX pane, through workflow-mcp's terminal host.\n *\n * The pane gets the step's whole environment, which is what lets an agent's\n * Stop hook end an interactive step through WORKFLOW_STATUS_FILE. A unix\n * socket serves the pane to the run terminal in any scope; the socket path is\n * the pane's target. When the step ends or is stopped, its last screen is kept\n * beside the socket and the pane is released, whatever fails on the way.\n */\nexport function createNativeStepPaneLauncher(\n service = new NativeTerminalService(),\n telemetry?: StepTelemetry,\n): StepPaneLauncher {\n const report = (stage: string) => (error: unknown) =>\n telemetry?.recordWarning(STEP_PANE_FAILED_EVENT, error, { stage }) ?? Promise.resolve();\n return async (request) => {\n if (!(await service.available())) return undefined;\n await service.spawn({\n command: STEP_SHELL,\n args: ['-c', request.command],\n cwd: request.cwd,\n env: { ...request.env },\n runKey: request.id,\n });\n const target = terminalSocketPath(STEP_PANE_SOCKET_SCOPE, request.id);\n let server: Awaited<ReturnType<typeof serveNativeTerminal>>;\n try {\n server = await serveNativeTerminal({ service, runKey: request.id, socketPath: target });\n } catch (error) {\n // A pane nobody can reach must not keep running its command untracked.\n await service.kill(request.id).catch(report('kill'));\n throw error;\n }\n let finishing: Promise<string | undefined> | undefined;\n const finish = (): Promise<string | undefined> =>\n (finishing ??= (async () => {\n let screen: string | undefined;\n try {\n screen = await lastScreen(service, request.id);\n if (screen !== undefined) await fs.promises.writeFile(stepPaneLogPath(target), screen, 'utf8');\n } catch (error) {\n // Keeping the last screen is a courtesy; the step's outcome is its exit code.\n await report('keep-screen')(error);\n } finally {\n await server.close().catch(report('close-socket'));\n await service.kill(request.id).catch(report('kill'));\n }\n return screen;\n })());\n return {\n target,\n // The last screen is the step's output tail, the reason a failing restart-from check reports.\n completion: service.ended(request.id).then(async (exitCode) => {\n const screen = (await finish())?.trimEnd();\n return screen ? { exitCode, outputTail: screen } : { exitCode };\n }),\n stop: async () => {\n await finish();\n return true;\n },\n };\n };\n}\n","import type {\n WorkflowCatalogArtifactView,\n WorkflowCatalogEntryView,\n WorkflowCatalogInputView,\n WorkflowCatalogJobView,\n} from '../../types/webWorkflows';\n/**\n * The cockpit's view of the workflows a session can launch.\n *\n * The engine already reads a repository's workflow files and parses one of\n * them into triggers, inputs, jobs, artifacts and compatible runners, so this\n * module only shapes that answer for the wire and remembers what it read.\n *\n * WHY A CACHE:\n * A session reads the catalog for its initial projection and when its lifecycle\n * publishes a workflow update. Entries are kept per path and reused while the\n * file's size and modification time are unchanged, which is the same test a\n * build tool makes and costs one stat per file.\n */\n\n/** What the engine reports for one workflow file before it is parsed. */\nexport interface CatalogListEntry {\n path: string;\n relativePath: string;\n name: string;\n description: string;\n tags: string[];\n}\n\n/** One file's parsed detail, or the reason it could not be read. */\nexport interface CatalogDetail {\n triggers: string[];\n inputs: WorkflowCatalogInputView[];\n jobs: WorkflowCatalogJobView[];\n artifacts: WorkflowCatalogArtifactView[];\n runners?: string[];\n commands?: string[];\n choices?: string[];\n error?: string;\n}\n\n/** What a file looked like when it was last parsed. */\nexport interface CatalogFileStamp {\n size: number;\n modifiedAt: number;\n}\n\nexport interface WorkflowCatalogReaderDeps {\n /** Every workflow file under a directory. */\n list(directory: string): Promise<CatalogListEntry[]>;\n /** One file's parsed detail; never throws, so a bad file cannot empty a board. */\n summarize(path: string): CatalogDetail;\n /** Size and modification time, or undefined when the file is gone. */\n stamp(path: string): CatalogFileStamp | undefined;\n}\n\ninterface CachedEntry {\n stamp: CatalogFileStamp;\n detail: CatalogDetail;\n}\n\n/** Reads one directory's catalog, reusing what it parsed last time. */\nexport interface WorkflowCatalogReader {\n read(directory: string): Promise<WorkflowCatalogEntryView[]>;\n /** Drops what was parsed for files no longer listed, so a cache cannot grow forever. */\n forget(keep: ReadonlySet<string>): void;\n}\n\nfunction unchanged(left: CatalogFileStamp | undefined, right: CatalogFileStamp | undefined): boolean {\n return left !== undefined && right !== undefined && left.size === right.size && left.modifiedAt === right.modifiedAt;\n}\n\nexport function createWorkflowCatalogReader(deps: WorkflowCatalogReaderDeps): WorkflowCatalogReader {\n const cache = new Map<string, CachedEntry>();\n\n const detailFor = (path: string): CatalogDetail => {\n const stamp = deps.stamp(path);\n const cached = cache.get(path);\n if (cached && unchanged(cached.stamp, stamp)) return cached.detail;\n const detail = deps.summarize(path);\n // A file that vanished between listing and stat is parsed anyway, which\n // answers with its own error; it just cannot be cached against a stamp.\n if (stamp !== undefined) cache.set(path, { stamp, detail });\n return detail;\n };\n\n return {\n async read(directory) {\n const listed = await deps.list(directory);\n return listed.map((entry) => {\n const detail = detailFor(entry.path);\n return {\n path: entry.path,\n relativePath: entry.relativePath,\n name: entry.name === '' ? entry.relativePath : entry.name,\n description: entry.description,\n tags: entry.tags,\n triggers: detail.triggers,\n inputs: detail.inputs,\n jobs: detail.jobs,\n artifacts: detail.artifacts,\n ...(detail.runners === undefined ? {} : { runners: detail.runners }),\n ...(detail.commands === undefined ? {} : { commands: detail.commands }),\n ...(detail.choices === undefined ? {} : { choices: detail.choices }),\n ...(detail.error === undefined ? {} : { error: detail.error }),\n };\n });\n },\n forget(keep) {\n for (const path of cache.keys()) {\n if (!keep.has(path)) cache.delete(path);\n }\n },\n };\n}\n\n/** The launchable rows first, then the ones that would not parse, name ordered. */\nexport function presentWorkflowCatalog(entries: readonly WorkflowCatalogEntryView[]): WorkflowCatalogEntryView[] {\n return [...entries].sort((left, right) => {\n if ((left.error === undefined) !== (right.error === undefined)) return left.error === undefined ? -1 : 1;\n return left.name.localeCompare(right.name);\n });\n}\n","import { statSync } from 'node:fs';\n\nimport { diagnoseWorkflow, readWorkflowCatalog, summarizeWorkflow } from '@agimon-ai/workflow-mcp';\n\nimport { DOOMPI_RUN_CONFIG_KEYS } from '../../schemas/runConfig';\nimport type { WorkflowCatalogReaderDeps } from '../webWorkflowCatalog';\n\n/**\n * Connect the pure catalog projection service to the workflow engine and filesystem.\n *\n * A workflow that parses can still be one DoomPi would fail mid-run, such as\n * a step whose runConfig misspells `majorMode`. The engine's doctor, told the\n * keys DoomPi reads, finds those; its errors mark the workflow as one that\n * cannot launch, in the catalog and at every launch, rather than at the step.\n */\nexport function defaultCatalogDeps(): WorkflowCatalogReaderDeps {\n return {\n list: (directory) => readWorkflowCatalog(directory),\n summarize: (workflowPath) => {\n const detail = summarizeWorkflow(workflowPath);\n if (detail.error !== undefined) return detail;\n const errors = diagnoseWorkflow(workflowPath, { runConfigKeys: DOOMPI_RUN_CONFIG_KEYS }).diagnostics.filter(\n (diagnostic) => diagnostic.level === 'error',\n );\n if (errors.length === 0) return detail;\n return {\n ...detail,\n error: errors\n .map((diagnostic) =>\n diagnostic.location === undefined ? diagnostic.message : `${diagnostic.location}: ${diagnostic.message}`,\n )\n .join('\\n'),\n };\n },\n stamp: (workflowPath) => {\n try {\n const stats = statSync(workflowPath);\n return { size: stats.size, modifiedAt: stats.mtimeMs };\n } catch {\n return undefined;\n }\n },\n };\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { connectNativeTerminal, type WorkflowRegistryService, type WorkflowRunRecord } from '@agimon-ai/workflow-mcp';\n\nimport { STEP_PANE_REF_KIND, STEP_SESSION_REF_KIND } from '../../types/webWorkflows';\nimport type { WorkflowTerminalCapabilitiesView } from '../../types/webWorkflowTerminal';\nimport { stepPaneLogPath } from '../stepExecutor';\nimport { parseWorkflowProgress } from '../workflowRuns';\nimport type { TerminalPort } from '../workflowTerminal';\nimport type { RunStepRefs, RunTerminalTarget, StepPaneTerminalDependencies, StepRef } from './type';\n\nconst PROGRESS_FILENAME = 'progress.ndjson';\nconst NATIVE_LAUNCHER = 'native';\n/** Runs whose folded refs are kept between reads; a screen stream reads its run twice a second. */\nconst REFS_CACHE_LIMIT = 256;\nconst PANE_CAPABILITIES: WorkflowTerminalCapabilitiesView = { readable: true, writable: true, resizable: false };\nconst PANE_LOG_CAPABILITIES: WorkflowTerminalCapabilitiesView = {\n readable: true,\n writable: false,\n resizable: false,\n reason: 'That step has finished; this is the output it left.',\n};\nconst SESSION_STEP_REASON =\n 'This step runs as an agent session; its conversation appears here as soon as the session starts.';\nconst PANE_GONE_LINE = 'The step pane has closed.';\n\n/** The step events this fold reads, as the shared progress parser returns them. */\ninterface StepProgressEvent {\n readonly type: string;\n readonly status: string;\n readonly job: string;\n readonly step?: string;\n readonly ref?: StepRef;\n}\n\n/**\n * The steps a run is on and its latest pane, folded from its progress log.\n *\n * Later events win, as in the engine's own summary. Steps of a parallel group\n * run at once, so every running step is kept, and the current one is the\n * latest-started step still running. A step that starts again is a new\n * attempt: its previous session or pane is not this attempt's, so the ref is\n * dropped until the new one is recorded. The latest pane is kept after it\n * finishes so a run between steps, or one that has ended, can still show what\n * its last command printed.\n */\nexport function stepRefsFrom(events: readonly StepProgressEvent[]): RunStepRefs {\n // Insertion order is start order: a step that starts again moves to the end.\n const steps = new Map<string, { running: boolean; ref?: StepRef }>();\n const known = new Map<string, StepRef>();\n let lastPane: StepRef | undefined;\n for (const event of events) {\n if (event.type !== 'step' || event.step === undefined) continue;\n const key = `${event.job}\\u0000${event.step}`;\n const previous = steps.get(key);\n const running = event.status === 'running';\n const restarted = running && previous?.running !== true;\n if (restarted) steps.delete(key);\n const ref = event.ref ?? (restarted ? undefined : previous?.ref);\n steps.set(key, { running, ...(ref === undefined ? {} : { ref }) });\n if (event.ref !== undefined) known.set(event.ref.id, event.ref);\n if (event.ref?.kind === STEP_PANE_REF_KIND) lastPane = event.ref;\n }\n const running = [...steps.values()]\n .filter((step) => step.running && step.ref !== undefined)\n .map((step) => step.ref as StepRef);\n const current = running.at(-1);\n return {\n ...(current === undefined ? {} : { current }),\n ...(running.length === 0 ? {} : { running }),\n ...(lastPane === undefined ? {} : { lastPane }),\n ...(known.size === 0 ? {} : { known: [...known.values()] }),\n };\n}\n\n/**\n * Reads a run's refs, folding its progress log again only when the log changed.\n *\n * Every screen, keystroke and capability check asks for them, and the log grows\n * with every fix loop, so an unchanged file (same size and modification time)\n * answers from the last fold.\n */\nfunction createStepRefsReader(): (file: string) => RunStepRefs {\n const cache = new Map<string, { size: number; mtimeMs: number; refs: RunStepRefs }>();\n return (file) => {\n let stats: fs.Stats;\n try {\n stats = fs.statSync(file);\n } catch {\n // No log yet: a run records progress only once its first step starts.\n return {};\n }\n const cached = cache.get(file);\n if (cached !== undefined && cached.size === stats.size && cached.mtimeMs === stats.mtimeMs) return cached.refs;\n let raw: string;\n try {\n raw = fs.readFileSync(file, 'utf8');\n } catch {\n // Removed between the stat and the read, as a deleted run is; nothing is left to follow.\n return {};\n }\n const refs = stepRefsFrom(parseWorkflowProgress(raw));\n cache.delete(file);\n cache.set(file, { size: stats.size, mtimeMs: stats.mtimeMs, refs });\n if (cache.size > REFS_CACHE_LIMIT) cache.delete(cache.keys().next().value as string);\n return refs;\n };\n}\n\n/**\n * Real dependencies: the registry's run directory, and the step executor's pane sockets.\n *\n * A pane is reached through the socket its step was served on, so any scope\n * of the server can read it, and a finished one through the screen kept\n * beside that socket.\n */\nexport function createStepPaneTerminalDependencies(registry: WorkflowRegistryService): StepPaneTerminalDependencies {\n const native = connectNativeTerminal();\n const readRefs = createStepRefsReader();\n return {\n stepRefs: (record) => readRefs(path.join(registry.runDirectoryFor(record), PROGRESS_FILENAME)),\n paneClient: () => ({\n capture: (target) =>\n native.snapshot(target, {}).then(\n (lines) => lines.join('\\n'),\n // A pane that already closed has no screen; its kept log answers instead.\n () => undefined,\n ),\n input: (target, text) =>\n native.write(target, text).then(\n () => true,\n () => false,\n ),\n }),\n paneLog: (_record, pane) =>\n fs.promises.readFile(stepPaneLogPath(pane.id), 'utf8').catch(\n // Kept screens live in the temp directory, which the system may already have cleared.\n () => undefined,\n ),\n };\n}\n\n/** Removes the screens a run's finished panes left behind, once the run itself is deleted. */\nexport async function removeStepPaneLogs(refs: RunStepRefs): Promise<void> {\n const panes = (refs.known ?? []).filter((ref) => ref.kind === STEP_PANE_REF_KIND);\n await Promise.all(panes.map((pane) => fs.promises.rm(stepPaneLogPath(pane.id), { force: true })));\n}\n\nfunction lastLines(text: string, count: number | undefined): string[] {\n const lines = text.replace(/\\n+$/, '').split('\\n');\n return count === undefined ? lines : lines.slice(-count);\n}\n\n/** The ref a request reads, and whether its step is still running. */\ninterface ResolvedStep {\n readonly ref: StepRef;\n readonly running: boolean;\n}\n\n/**\n * A run terminal that follows the step a host executor placed.\n *\n * A run executing in the server has no launcher pane of its own; each command\n * step gets one instead. A request naming a step reads that step's pane, which\n * is how each step of a parallel group gets its own screen and keyboard.\n * Without one it follows the current step. While a customRun step runs, there\n * is no terminal to show, so it says where the agent's messages are. Between\n * steps and after the run, an in-process run shows what its latest command\n * printed. A run delegated to a terminal launcher keeps the engine's facade.\n */\nexport function createStepPaneTerminal(\n facade: TerminalPort<WorkflowRunRecord>,\n dependencies: StepPaneTerminalDependencies,\n): TerminalPort<RunTerminalTarget> {\n // A server run records the server itself as its native launcher and has no terminal socket.\n const inProcess = (record: WorkflowRunRecord): boolean =>\n record.launcher?.type === NATIVE_LAUNCHER && record.terminalSocket === undefined;\n const resolveStep = (target: RunTerminalTarget): ResolvedStep | undefined => {\n const refs = dependencies.stepRefs(target.record);\n const isRunning = (ref: StepRef): boolean => refs.running?.some((candidate) => candidate.id === ref.id) === true;\n if (target.step !== undefined) {\n const named = refs.known?.find((ref) => ref.id === target.step);\n if (named !== undefined) return { ref: named, running: isRunning(named) };\n }\n if (refs.current !== undefined) return { ref: refs.current, running: true };\n if (refs.lastPane !== undefined && inProcess(target.record)) return { ref: refs.lastPane, running: false };\n return undefined;\n };\n const readLog = async (record: WorkflowRunRecord, pane: StepRef, lines: number | undefined): Promise<string[]> => {\n const log = await dependencies.paneLog(record, pane);\n return log === undefined ? [PANE_GONE_LINE] : lastLines(log, lines);\n };\n\n return {\n capabilities(target) {\n const step = resolveStep(target);\n if (step === undefined) return facade.capabilities(target.record);\n if (step.ref.kind === STEP_SESSION_REF_KIND) {\n return { readable: false, writable: false, resizable: false, reason: SESSION_STEP_REASON };\n }\n return step.running ? PANE_CAPABILITIES : PANE_LOG_CAPABILITIES;\n },\n async screen(target, options) {\n const step = resolveStep(target);\n if (step === undefined) return facade.screen(target.record, options);\n if (step.ref.kind === STEP_SESSION_REF_KIND) return [SESSION_STEP_REASON];\n if (step.running) {\n const screen = await dependencies.paneClient(target.record).capture(step.ref.id);\n if (screen !== undefined) return lastLines(screen, options.lines);\n // The pane closed between the progress read and the capture; its log has the same text.\n }\n return readLog(target.record, step.ref, options.lines);\n },\n async write(target, data) {\n const step = resolveStep(target);\n if (step === undefined) return facade.write(target.record, data);\n if (step.ref.kind !== STEP_PANE_REF_KIND || !step.running) throw new Error(PANE_GONE_LINE);\n if (!(await dependencies.paneClient(target.record).input(step.ref.id, data))) throw new Error(PANE_GONE_LINE);\n },\n async resize(target, columns, rows) {\n if (resolveStep(target) !== undefined) return false;\n return facade.resize(target.record, columns, rows);\n },\n };\n}\n","import { apiResponse, defineApiRoutes } from '@agimon-ai/doompi-core/web';\n\nimport type {\n WorkflowArtifactContentResponse,\n WorkflowArtifactsResponse,\n WorkflowControlResponse,\n WorkflowDeleteResponse,\n WorkflowLaunchResponse,\n WorkflowSteerResponse,\n WorkflowStopResponse,\n} from './webWorkflowTerminal';\n\n/**\n * This package's routes, as data.\n *\n * No scope and no base path. The build reads both off\n * `src/extensions/(backend)/api/workflow/`, so the mount is stated once, by the\n * folder that creates it. The same API answers at all three scopes, because a\n * global contribution cascades into workspace and session; the folder under\n * `workspaces/sessions/` only re-mounts it for a session's own server.\n *\n * This is the one file the routes, the Hono app and the browser all read, so a\n * path cannot move on one side alone. The page used to build the hub's own\n * absolute URL and then rewrite its plugin prefix with String.replace to reach\n * a session, which is exactly the kind of copy that can move by one character\n * without anything noticing.\n *\n * `:workspace` and `:runKey` are Hono's own parameter syntax, because the app\n * registers `path` verbatim.\n */\n\n/** One run, which every route below addresses. */\nconst RUN = '/runs/:workspace/:runKey';\n\n/**\n * The artifact route's parameter, as Hono spells a multi-segment match.\n *\n * An artifact is named by its path inside the run directory, so `reports/a.md`\n * is one parameter across two segments. The client's `params` substitution\n * fills a single segment and percent-encodes the slash with it, so the page\n * substitutes this one itself; see the page's `_lib/terminalApi.ts`.\n */\nexport const ARTIFACT_NAME_PARAM = ':name{.+}';\n\n/**\n * The step whose pane a terminal route reads: a step ref's id. Absent, the\n * route follows the run's current step, which is one of a parallel group's.\n */\nexport const STEP_TARGET_PARAM = 'step';\n\n/** Query parameters the artifact route reads, spelled once for both halves. */\nexport const ARTIFACT_RAW_PARAM = 'raw';\nexport const ARTIFACT_DOWNLOAD_PARAM = 'download';\n\nexport default defineApiRoutes({\n /**\n * The terminal, as server-sent events.\n *\n * `stream: true` gets a URL and no call method: the consumer is the browser's\n * own `EventSource`, and a relayed call would buffer a stream that never ends.\n */\n screen: {\n method: 'GET',\n path: `${RUN}/screen/stream`,\n query: [STEP_TARGET_PARAM],\n stream: true,\n },\n control: {\n method: 'POST',\n path: `${RUN}/control`,\n response: apiResponse<WorkflowControlResponse>(),\n },\n keys: {\n method: 'POST',\n path: `${RUN}/keys`,\n },\n resize: {\n method: 'POST',\n path: `${RUN}/resize`,\n response: apiResponse<{ resized: boolean }>(),\n },\n remove: {\n method: 'DELETE',\n path: RUN,\n response: apiResponse<WorkflowDeleteResponse>(),\n },\n stop: {\n method: 'POST',\n path: `${RUN}/stop`,\n response: apiResponse<WorkflowStopResponse>(),\n },\n /** Guidance for the agent session the running step is in, like steering a Team sub-agent. */\n steer: {\n method: 'POST',\n path: `${RUN}/steer`,\n response: apiResponse<WorkflowSteerResponse>(),\n },\n /**\n * Launch a workflow into the mounting session's own runtime, which then owns\n * the run. A dispatcher session reaches its root's session mount through this.\n */\n launch: {\n method: 'POST',\n path: '/launch',\n response: apiResponse<WorkflowLaunchResponse>(),\n },\n artifacts: {\n method: 'GET',\n path: `${RUN}/artifacts`,\n response: apiResponse<WorkflowArtifactsResponse>(),\n },\n /** One artifact: its metadata and text, or its raw bytes under `raw=1`. */\n artifact: {\n method: 'GET',\n path: `${RUN}/artifacts/${ARTIFACT_NAME_PARAM}`,\n query: [ARTIFACT_RAW_PARAM, ARTIFACT_DOWNLOAD_PARAM],\n response: apiResponse<WorkflowArtifactContentResponse>(),\n },\n});\n","/**\n * The wire contract between this package's hub API and its cockpit client:\n * one run's terminal, and the files its run directory holds.\n *\n * Both halves of the cockpit import these names, so the route strings and the\n * event names live here rather than being spelled twice.\n */\n\n/**\n * Segment this package's API is mounted under, below /api/plugins/.\n *\n * The same word names `src/extensions/(backend)/api/workflow/`, which is where\n * the build reads the mount for the browser's client, so the two cannot drift.\n * The routes themselves are declared in `apiRoutes.ts`.\n */\nexport const WORKFLOW_API_BASE_PATH = 'workflow';\n\n/** The SSE event name the screen stream writes. */\nexport const WORKFLOW_SCREEN_EVENT = 'screen';\n\n/** What a surface may do with one run's terminal, and why anything is missing. */\nexport interface WorkflowTerminalCapabilitiesView {\n readable: boolean;\n writable: boolean;\n resizable: boolean;\n reason?: string;\n}\n\n/** One frame of a run's terminal, as the stream pushes it. */\nexport interface WorkflowScreenEvent {\n /** The visible screen, newest line last, carrying the colour the run printed. */\n lines: string[];\n capabilities: WorkflowTerminalCapabilitiesView;\n /** True once the run has settled, after which the stream ends. */\n ended?: boolean;\n}\n\n/** Answer to taking or releasing the keyboard for one run. */\nexport interface WorkflowControlResponse {\n /** True when this caller now holds the keyboard. */\n held: boolean;\n /** The token later writes must carry; absent when control was refused or released. */\n token?: string;\n /** Why control was refused, worded for a reader. */\n reason?: string;\n}\n\n/** Answer after a settled run and its directory have been permanently removed. */\nexport interface WorkflowDeleteResponse {\n deleted: true;\n}\n\n/** Answer once a stop request is recorded; the engine ends the run at its next check. */\nexport interface WorkflowStopResponse {\n requested: true;\n}\n\n/** Answer once guidance reached the running step's agent session. */\nexport interface WorkflowSteerResponse {\n delivered: true;\n}\n\n/** What launching a workflow into a session answered, as the launch tool reports it. */\nexport interface WorkflowLaunchResponse {\n text: string;\n isError?: boolean;\n}\n\n/** How a declared run-directory entry compares with what is on disk. */\nexport type WorkflowArtifactState = 'written' | 'empty' | 'pending' | 'unreadable';\n\n/** One file or directory in a run's own folder. */\nexport interface WorkflowArtifactView {\n /** Path relative to the run directory, which is also the read route's parameter. */\n path: string;\n kind: 'file' | 'directory';\n /** What the workflow says this file is for; empty for a file it never declared. */\n description: string;\n /** The jobs the workflow says write it. */\n producedBy: string[];\n /** True when the workflow's run-directory block names this entry. */\n declared: boolean;\n state: WorkflowArtifactState;\n /** Bytes on disk, absent until the file exists. */\n size?: number;\n /** ISO 8601 of the last write, absent until the file exists. */\n modifiedAt?: string;\n}\n\nexport interface WorkflowArtifactsResponse {\n /** Absolute path of the run's own directory, which the reader may want to open. */\n runDir: string;\n /** What the workflow says the directory is for. */\n description: string;\n artifacts: WorkflowArtifactView[];\n}\n\n/** One artifact's metadata and optional text, as the viewer tab reads it. */\nexport interface WorkflowArtifactContentResponse {\n path: string;\n size: number;\n modifiedAt: string;\n /** Media type inferred from the file extension by the trusted hub. Absent on older hubs. */\n mimeType?: string;\n /** Present for text formats; binary files are streamed from the raw route instead. */\n text?: string;\n /** True when textual content was longer than the reader's byte budget. */\n truncated: boolean;\n}\n","import { randomUUID } from 'node:crypto';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { Readable } from 'node:stream';\n\nimport type { DoomApi, DoomApiContext, DoomApiHandler } from '@agimon-ai/doompi-core/packageApi';\nimport {\n WorkflowRegistryService,\n WorkflowTerminalService as WorkflowTerminalFacade,\n type WorkflowRunRecord,\n type WorkflowStage,\n} from '@agimon-ai/workflow-mcp';\nimport { type Context, Hono } from 'hono';\nimport { streamSSE } from 'hono/streaming';\n\nimport {\n createStepPaneTerminal,\n createStepPaneTerminalDependencies,\n removeStepPaneLogs,\n} from '../../services/stepPaneTerminal';\nimport type { RunTerminalTarget } from '../../services/stepPaneTerminal/type';\nimport { createWorkflowTerminalService } from '../../services/workflowTerminal';\nimport routes, { ARTIFACT_DOWNLOAD_PARAM, ARTIFACT_RAW_PARAM, STEP_TARGET_PARAM } from '../../types/apiRoutes';\nimport { STEP_SESSION_REF_KIND } from '../../types/webWorkflows';\nimport {\n WORKFLOW_API_BASE_PATH,\n WORKFLOW_SCREEN_EVENT,\n type WorkflowArtifactContentResponse,\n type WorkflowArtifactsResponse,\n type WorkflowArtifactView,\n type WorkflowControlResponse,\n type WorkflowDeleteResponse,\n type WorkflowLaunchResponse,\n type WorkflowScreenEvent,\n type WorkflowSteerResponse,\n type WorkflowStopResponse,\n} from '../../types/webWorkflowTerminal';\n\n/** Stages a run can be recorded under, newest first: a live run is the common case. */\nconst STAGES: readonly WorkflowStage[] = ['running', 'error', 'completed'];\n/** Lines of screen the stream sends, which is a terminal's visible height plus room. */\nconst SCREEN_LINES = 48;\n/** How often the stream re-reads; the service coalesces, so this is an upper bound. */\nconst STREAM_TICK_MS = 500;\n/** How often a settled run is re-checked before the stream closes itself. */\nconst SETTLED_POLL_TICKS = 4;\n/** Bytes of one textual artifact returned as JSON; binary previews use a stream. */\nconst MAX_ARTIFACT_BYTES = 512 * 1024;\n/** Recorded with a stop the web panel asks for, so the run log says where it came from. */\nconst WEB_STOP_REASON = 'Stopped from the web workflow panel.';\n/** Path segments a client supplies are names, never paths. */\nconst SAFE_SEGMENT = /^[\\w.@-]+$/;\nconst ARTIFACT_MIME_TYPES: Readonly<Record<string, string>> = {\n '.aac': 'audio/aac',\n '.bmp': 'image/bmp',\n '.css': 'text/css',\n '.csv': 'text/csv',\n '.gif': 'image/gif',\n '.htm': 'text/html',\n '.html': 'text/html',\n '.ico': 'image/x-icon',\n '.jpeg': 'image/jpeg',\n '.jpg': 'image/jpeg',\n '.js': 'text/javascript',\n '.json': 'application/json',\n '.jsx': 'text/jsx',\n // A run's engine log, which a reader opens to see why a step failed.\n '.log': 'text/plain',\n '.m4a': 'audio/mp4',\n '.markdown': 'text/markdown',\n '.md': 'text/markdown',\n '.mov': 'video/quicktime',\n '.mp3': 'audio/mpeg',\n '.mp4': 'video/mp4',\n '.oga': 'audio/ogg',\n '.ogg': 'audio/ogg',\n '.ogv': 'video/ogg',\n '.pdf': 'application/pdf',\n '.png': 'image/png',\n '.sh': 'text/x-shellscript',\n '.svg': 'image/svg+xml',\n '.toml': 'text/toml',\n '.ts': 'text/typescript',\n '.tsv': 'text/tab-separated-values',\n '.tsx': 'text/tsx',\n '.txt': 'text/plain',\n '.wav': 'audio/wav',\n '.webm': 'video/webm',\n '.webp': 'image/webp',\n '.xml': 'application/xml',\n '.yaml': 'text/yaml',\n '.yml': 'text/yaml',\n};\n\n/**\n * One request's JSON body as a plain record.\n *\n * A body that is absent, malformed, or not an object reads as empty rather\n * than failing the route: every field is checked by the route anyway, and a\n * 400 naming the missing field beats a parse error naming nothing.\n */\nasync function jsonBody(context: Context): Promise<Record<string, unknown>> {\n const parsed: unknown = await context.req.json().catch(() => undefined);\n return parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : {};\n}\n\n/** Rejects anything that could climb out of the registry before a path is built. */\nfunction isSafeSegment(value: string): boolean {\n return value !== '' && value !== '../adapters' && value !== '..' && SAFE_SEGMENT.test(value);\n}\n\n/**\n * One terminal's identity for caches and leases, stable across stage moves: a\n * run's, or one step's pane in it, which keeps its own screen and keyboard.\n */\nfunction runIdentityOf(workspace: string, runKey: string, step?: string): string {\n return step === undefined ? `${workspace}/${runKey}` : `${workspace}/${runKey}#${step}`;\n}\n\n/** The step a terminal request names, from its query or body; absent follows the current step. */\nfunction stepOf(value: unknown): string | undefined {\n return typeof value === 'string' && value !== '' ? value : undefined;\n}\n\nexport interface WorkflowHubApiOptions {\n registry?: WorkflowRegistryService;\n terminal?: WorkflowTerminalFacade;\n now?: () => number;\n /**\n * Guides a live session that the mounting session started. Present only on a\n * session mount, whose session service refuses sessions it did not start.\n */\n steer?: (sessionId: string, message: string) => Promise<void>;\n /**\n * Runs a workflow in the mounting session, which then owns it. Present only on\n * the mount of a session with a workflow runtime.\n */\n launch?: (parameters: Record<string, unknown>) => Promise<WorkflowLaunchResponse>;\n}\n\n/**\n * This package's HTTP surface: one workflow run's terminal, and the files its\n * run directory holds.\n *\n * Mounted in the hub rather than in a session's server, because a run's\n * terminal belongs to its multiplexer rather than to the session that launched\n * it: any process can read a tmux pane, and the session's own server cannot\n * reach anything more. The routes therefore name a run, never a session.\n */\nexport function createWorkflowHubApi(options: WorkflowHubApiOptions = {}): Hono {\n const registry = options.registry ?? new WorkflowRegistryService();\n const facade = options.terminal ?? new WorkflowTerminalFacade();\n const stepPanes = createStepPaneTerminalDependencies(registry);\n const terminal = createWorkflowTerminalService<RunTerminalTarget>({\n // A run executing in the server has a pane per command step instead of one for the whole run.\n terminal: createStepPaneTerminal(facade, stepPanes),\n now: options.now ?? (() => Date.now()),\n });\n const app = new Hono();\n\n /** The record behind a request, whichever stage it now sits in. */\n const runOf = async (workspace: string, runKey: string): Promise<WorkflowRunRecord | undefined> => {\n if (!isSafeSegment(workspace) || !isSafeSegment(runKey)) return undefined;\n for (const stage of STAGES) {\n try {\n return await registry.readRunByKey(workspace, stage, runKey);\n } catch {\n // Not in this stage. A run moves between them as it settles, so a miss\n // here is ordinary; only a miss in every stage means no such run.\n }\n }\n return undefined;\n };\n\n const missing = (workspace: string, runKey: string): { error: string } => ({\n error: `No workflow run '${runKey}' in workspace '${workspace}'.`,\n });\n\n app.get(routes.screen.path, async (context) => {\n const workspace = context.req.param('workspace');\n const runKey = context.req.param('runKey');\n const record = await runOf(workspace, runKey);\n if (record === undefined) return context.json(missing(workspace, runKey), 404);\n const step = stepOf(context.req.query(STEP_TARGET_PARAM));\n const identity = runIdentityOf(workspace, runKey, step);\n\n return streamSSE(context, async (stream) => {\n let settledTicks = 0;\n let running = true;\n let latest = record;\n stream.onAbort(() => {\n running = false;\n });\n while (running) {\n const current = (await runOf(workspace, runKey)) ?? record;\n latest = current;\n const target: RunTerminalTarget = { record: current, ...(step === undefined ? {} : { step }) };\n const capabilities = terminal.capabilities(target);\n const lines = capabilities.readable ? await terminal.screen(identity, target, SCREEN_LINES) : [];\n // A settled run is read a few more times before the stream closes: the\n // last thing a failing step printed is what the reader came for, and it\n // lands after the record has already moved to its final stage.\n const settled = current.stage !== 'running';\n if (settled) settledTicks += 1;\n const ended = settled && settledTicks >= SETTLED_POLL_TICKS;\n const event: WorkflowScreenEvent = { lines, capabilities, ...(ended ? { ended: true } : {}) };\n await stream.writeSSE({ event: WORKFLOW_SCREEN_EVENT, data: JSON.stringify(event) });\n if (ended) break;\n await stream.sleep(STREAM_TICK_MS);\n }\n // Only a settled run is forgotten, and only this one. A reader closing its\n // stream, which happens whenever a panel unmounts, must not drop the\n // keyboard lease someone just took on another panel, or on another run.\n if (latest.stage !== 'running') terminal.forgetRun(identity);\n });\n });\n\n app.post(routes.control.path, async (context) => {\n const workspace = context.req.param('workspace');\n const runKey = context.req.param('runKey');\n const record = await runOf(workspace, runKey);\n if (record === undefined) return context.json(missing(workspace, runKey), 404);\n const body = await jsonBody(context);\n const step = stepOf(body.step);\n const identity = runIdentityOf(workspace, runKey, step);\n const capabilities = terminal.capabilities({ record, ...(step === undefined ? {} : { step }) });\n\n if (body.release === true) {\n if (typeof body.token === 'string') terminal.releaseControl(identity, body.token);\n const released: WorkflowControlResponse = { held: false };\n return context.json(released);\n }\n if (!capabilities.writable) {\n const refused: WorkflowControlResponse = { held: false, reason: capabilities.reason };\n return context.json(refused, 409);\n }\n const token = typeof body.token === 'string' && body.token !== '' ? body.token : randomUUID();\n if (!terminal.takeControl(identity, token)) {\n const taken: WorkflowControlResponse = { held: false, reason: 'Another reader holds the keyboard.' };\n return context.json(taken, 409);\n }\n const held: WorkflowControlResponse = { held: true, token };\n return context.json(held);\n });\n\n app.post(routes.keys.path, async (context) => {\n const workspace = context.req.param('workspace');\n const runKey = context.req.param('runKey');\n const record = await runOf(workspace, runKey);\n if (record === undefined) return context.json(missing(workspace, runKey), 404);\n const body = await jsonBody(context);\n if (typeof body.token !== 'string' || typeof body.data !== 'string') {\n return context.json({ error: 'A keystroke needs a control token and its data.' }, 400);\n }\n const step = stepOf(body.step);\n try {\n await terminal.write(\n runIdentityOf(workspace, runKey, step),\n { record, ...(step === undefined ? {} : { step }) },\n body.token,\n body.data,\n );\n } catch (error) {\n return context.json({ error: error instanceof Error ? error.message : String(error) }, 409);\n }\n return context.body(null, 204);\n });\n\n app.post(routes.resize.path, async (context) => {\n const workspace = context.req.param('workspace');\n const runKey = context.req.param('runKey');\n const record = await runOf(workspace, runKey);\n if (record === undefined) return context.json(missing(workspace, runKey), 404);\n const body = await jsonBody(context);\n const { token, columns, rows } = body;\n if (typeof token !== 'string' || typeof columns !== 'number' || typeof rows !== 'number') {\n return context.json({ error: 'A resize needs a control token, columns and rows.' }, 400);\n }\n const step = stepOf(body.step);\n try {\n const resized = await terminal.resize(\n runIdentityOf(workspace, runKey, step),\n { record, ...(step === undefined ? {} : { step }) },\n token,\n columns,\n rows,\n );\n return context.json({ resized });\n } catch (error) {\n return context.json({ error: error instanceof Error ? error.message : String(error) }, 409);\n }\n });\n\n app.post(routes.stop.path, async (context) => {\n const workspace = context.req.param('workspace');\n const runKey = context.req.param('runKey');\n const record = await runOf(workspace, runKey);\n if (record === undefined) return context.json(missing(workspace, runKey), 404);\n if (record.stage !== 'running' || record.runId === undefined) {\n return context.json({ error: 'Only a running workflow can be stopped.' }, 409);\n }\n try {\n // The same request the workflow tool's stop writes; the engine that owns the\n // run reads it wherever that engine lives, in this server or in a terminal.\n await registry.requestStop(workspace, runKey, WEB_STOP_REASON, record.runId);\n } catch (error) {\n return context.json({ error: error instanceof Error ? error.message : String(error) }, 409);\n }\n const response: WorkflowStopResponse = { requested: true };\n return context.json(response);\n });\n\n app.post(routes.steer.path, async (context) => {\n const workspace = context.req.param('workspace');\n const runKey = context.req.param('runKey');\n const record = await runOf(workspace, runKey);\n if (record === undefined) return context.json(missing(workspace, runKey), 404);\n const body = await jsonBody(context);\n const message = typeof body.message === 'string' ? body.message.trim() : '';\n if (message === '') return context.json({ error: 'Guidance needs a message.' }, 400);\n if (record.stage !== 'running') return context.json({ error: 'Only a running workflow can be steered.' }, 409);\n // Only a step running now, and only an agent session. A browser names the\n // run, and inside a parallel group the step's own session; any other\n // session is out of reach.\n const refs = stepPanes.stepRefs(record);\n const step = typeof body.step === 'string' ? body.step : undefined;\n const current = step === undefined ? refs.current : (refs.running ?? []).find((candidate) => candidate.id === step);\n if (current?.kind !== STEP_SESSION_REF_KIND) {\n return context.json({ error: 'The running step is not an agent session.' }, 409);\n }\n if (options.steer === undefined) {\n return context.json({ error: 'Steering is available from the session that launched this run.' }, 409);\n }\n try {\n await options.steer(current.id, message);\n } catch (error) {\n return context.json({ error: error instanceof Error ? error.message : String(error) }, 409);\n }\n const response: WorkflowSteerResponse = { delivered: true };\n return context.json(response);\n });\n\n app.post(routes.launch.path, async (context) => {\n if (options.launch === undefined) {\n return context.json({ error: 'Launching needs the mount of a session with a workflow runtime.' }, 409);\n }\n const response: WorkflowLaunchResponse = await options.launch(await jsonBody(context));\n return context.json(response);\n });\n\n app.delete(routes.remove.path, async (context) => {\n const workspace = context.req.param('workspace');\n const runKey = context.req.param('runKey');\n const record = await runOf(workspace, runKey);\n if (record === undefined) return context.json(missing(workspace, runKey), 404);\n if (record.stage === 'running') {\n return context.json({ error: 'A running workflow must be stopped before it can be deleted.' }, 409);\n }\n // Read before the run directory goes: its progress log is what names the panes.\n const refs = stepPanes.stepRefs(record);\n try {\n fs.rmSync(registry.runDirectoryFor(record), { recursive: true, force: true });\n await removeStepPaneLogs(refs);\n } catch (error) {\n return context.json({ error: error instanceof Error ? error.message : String(error) }, 409);\n }\n const response: WorkflowDeleteResponse = { deleted: true };\n return context.json(response);\n });\n\n app.get(routes.artifacts.path, async (context) => {\n const workspace = context.req.param('workspace');\n const runKey = context.req.param('runKey');\n const record = await runOf(workspace, runKey);\n if (record === undefined) return context.json(missing(workspace, runKey), 404);\n const runDir = registry.runDirectoryFor(record);\n const body: WorkflowArtifactsResponse = {\n runDir,\n description: record.runDirectory?.description ?? '',\n artifacts: readArtifacts(runDir, record),\n };\n return context.json(body);\n });\n\n app.get(routes.artifact.path, async (context) => {\n const workspace = context.req.param('workspace');\n const runKey = context.req.param('runKey');\n const record = await runOf(workspace, runKey);\n if (record === undefined) return context.json(missing(workspace, runKey), 404);\n const runDir = registry.runDirectoryFor(record);\n const requested = context.req.param('name');\n const resolved = resolveInside(runDir, requested);\n if (resolved === undefined) return context.json({ error: `'${requested}' is not inside this run.` }, 400);\n if (context.req.query(ARTIFACT_RAW_PARAM) === '1') {\n const response = streamArtifact(\n resolved,\n requested,\n context.req.header('range'),\n context.req.query(ARTIFACT_DOWNLOAD_PARAM) === '1',\n );\n return response ?? context.json({ error: `'${requested}' has not been written.` }, 404);\n }\n const body = readArtifact(resolved, requested);\n if (body === undefined) return context.json({ error: `'${requested}' has not been written.` }, 404);\n return context.json(body);\n });\n\n return app;\n}\n\n/**\n * A path inside the run directory, or undefined when it points anywhere else.\n *\n * The client supplies this one verbatim, unlike the run key, so it is resolved\n * and then checked rather than trusted: without the check the route would read\n * any file the hub can reach.\n */\nfunction resolveInside(runDir: string, requested: string): string | undefined {\n const resolved = path.resolve(runDir, requested);\n const root = path.resolve(runDir);\n if (resolved !== root && !resolved.startsWith(`${root}${path.sep}`)) return undefined;\n return resolved;\n}\n\n/** Size and modification time of one path, or undefined when it is not there. */\nfunction statOf(target: string): fs.Stats | undefined {\n try {\n return fs.statSync(target);\n } catch {\n return undefined; // Not written yet, which is an ordinary state for an artifact.\n }\n}\n\nfunction stateOf(stats: fs.Stats | undefined): WorkflowArtifactView['state'] {\n if (stats === undefined) return 'pending';\n if (stats.isDirectory()) return 'written';\n return stats.size === 0 ? 'empty' : 'written';\n}\n\nfunction viewOf(\n runDir: string,\n entry: Omit<WorkflowArtifactView, 'state' | 'size' | 'modifiedAt'>,\n): WorkflowArtifactView {\n const stats = statOf(path.join(runDir, entry.path));\n return {\n ...entry,\n state: stateOf(stats),\n ...(stats === undefined ? {} : { size: stats.size, modifiedAt: stats.mtime.toISOString() }),\n };\n}\n\n/**\n * What the run directory holds: the workflow's own declaration first, then the\n * files nobody declared.\n *\n * The declaration is the point of the folder, so it leads and keeps its order\n * even for entries no job has written yet. The rest follows rather than being\n * hidden: the engine's own context.md and progress log are often exactly what a\n * reader is looking for.\n */\nfunction readArtifacts(runDir: string, record: WorkflowRunRecord): WorkflowArtifactView[] {\n const declared = (record.runDirectory?.entries ?? []).map((entry) =>\n viewOf(runDir, {\n path: entry.path,\n kind: entry.kind,\n description: entry.description,\n producedBy: entry['produced-by'] ?? [],\n declared: true,\n }),\n );\n const claimed = new Set(declared.map((entry) => entry.path));\n let names: fs.Dirent[];\n try {\n names = fs.readdirSync(runDir, { withFileTypes: true });\n } catch {\n return declared; // The directory is gone; the declaration is still worth showing.\n }\n const found = names\n .filter((entry) => !claimed.has(entry.name))\n .map((entry) =>\n viewOf(runDir, {\n path: entry.name,\n kind: entry.isDirectory() ? 'directory' : 'file',\n description: '',\n producedBy: [],\n declared: false,\n }),\n )\n .sort((left, right) => left.path.localeCompare(right.path));\n return [...declared, ...found];\n}\n\n/** Browser content type inferred from a filename without trusting client input. */\nfunction artifactMimeType(requested: string): string {\n return ARTIFACT_MIME_TYPES[path.extname(requested).toLowerCase()] ?? 'application/octet-stream';\n}\n\nfunction isTextArtifact(mimeType: string): boolean {\n return mimeType.startsWith('text/') || mimeType === 'application/json' || mimeType === 'application/xml';\n}\n\n/** One artifact's metadata and bounded text, or undefined when it is not readable. */\nfunction readArtifact(resolved: string, requested: string): WorkflowArtifactContentResponse | undefined {\n const stats = statOf(resolved);\n if (stats === undefined || stats.isDirectory()) return undefined;\n const mimeType = artifactMimeType(requested);\n let text: string | undefined;\n if (isTextArtifact(mimeType)) {\n try {\n const handle = fs.openSync(resolved, 'r');\n try {\n const buffer = Buffer.alloc(Math.min(stats.size, MAX_ARTIFACT_BYTES));\n fs.readSync(handle, buffer, 0, buffer.length, 0);\n text = buffer.toString('utf8');\n } finally {\n fs.closeSync(handle);\n }\n } catch {\n return undefined;\n }\n }\n return {\n path: requested,\n size: stats.size,\n modifiedAt: stats.mtime.toISOString(),\n mimeType,\n ...(text === undefined ? {} : { text }),\n truncated: text !== undefined && stats.size > MAX_ARTIFACT_BYTES,\n };\n}\n\n/** Streams media with byte-range support so browser audio, video, and PDF controls can seek. */\nfunction streamArtifact(\n resolved: string,\n requested: string,\n rangeHeader: string | undefined,\n download: boolean,\n): Response | undefined {\n const stats = statOf(resolved);\n if (stats === undefined || stats.isDirectory()) return undefined;\n const mimeType = artifactMimeType(requested);\n let start = 0;\n let end = Math.max(0, stats.size - 1);\n let partial = false;\n const match = rangeHeader?.match(/^bytes=(\\d*)-(\\d*)$/);\n if (match !== null && match !== undefined && stats.size > 0) {\n const requestedStart = match[1] === '' ? undefined : Number(match[1]);\n const requestedEnd = match[2] === '' ? undefined : Number(match[2]);\n if (requestedStart === undefined && requestedEnd !== undefined) {\n start = Math.max(0, stats.size - requestedEnd);\n } else if (requestedStart !== undefined) {\n start = requestedStart;\n end = requestedEnd === undefined ? end : Math.min(requestedEnd, end);\n }\n if (start >= stats.size || start > end) {\n return new Response(null, { status: 416, headers: { 'content-range': `bytes */${String(stats.size)}` } });\n }\n partial = true;\n }\n const filename = path.basename(requested).replace(/[\"\\\\\\r\\n]/g, '_');\n const forceDownload = download || mimeType === 'text/html';\n const headers = new Headers({\n 'accept-ranges': 'bytes',\n 'content-disposition': `${forceDownload ? 'attachment' : 'inline'}; filename=\"${filename}\"`,\n 'content-length': String(stats.size === 0 ? 0 : end - start + 1),\n 'content-type': mimeType,\n 'x-content-type-options': 'nosniff',\n });\n if (partial) headers.set('content-range', `bytes ${String(start)}-${String(end)}/${String(stats.size)}`);\n if (stats.size === 0) return new Response(null, { status: 200, headers });\n const body = Readable.toWeb(fs.createReadStream(resolved, { start, end }));\n return new Response(body, { status: partial ? 206 : 200, headers });\n}\n\n/**\n * This package's API, mounted by a session with its runtime's `launch` and by\n * the hub without one.\n */\nexport function createWorkflowApi(launch?: WorkflowHubApiOptions['launch']): DoomApi {\n return {\n basePath: WORKFLOW_API_BASE_PATH,\n start(context: DoomApiContext): DoomApiHandler {\n // A run is addressed by its registry identity, which is machine-wide. Only\n // steering and launching need a session: the one mounting this API, which\n // may guide only the step sessions it started.\n const steer = context.sessionService?.steer?.bind(context.sessionService);\n const app = createWorkflowHubApi({\n ...(steer === undefined ? {} : { steer: (sessionId, message) => steer(sessionId, message) }),\n ...(launch === undefined ? {} : { launch }),\n });\n return {\n fetch: (request) => app.fetch(request),\n // Nothing outlives a request: a stream's loop ends when its own socket\n // aborts, and the caches it touched are per run rather than per client.\n close: () => undefined,\n };\n },\n };\n}\n\n/** The named export a host imports from this package's built hub entry. */\nexport const api: DoomApi = createWorkflowApi();\n","import fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport {\n completeWorkflowRunView,\n foldWorkflowProgress,\n type ParsedWorkflowRun,\n parseWorkflowProgress,\n parseWorkflowRunRecord,\n PROGRESS_FILE_NAME,\n resolveWorkflowHome,\n RUN_RECORD_FILE_NAME,\n WORKFLOW_HOME_ENV,\n WORKFLOW_STAGES,\n WORKSPACES_DIR_NAME,\n} from '../workflowRuns';\n\nexport interface ReadWorkflowRunsOptions {\n /** Registry home override, primarily for tests. */\n homeDir?: string;\n /** Admitted session environment used to resolve the registry home. */\n environment?: Readonly<Record<string, string | undefined>>;\n}\n\n/**\n * Read the durable workflow registry once.\n *\n * The registry is an initial snapshot only. Live delivery belongs to the\n * session lifecycle and is routed through the host-owned direct event bus.\n */\nexport function readWorkflowRuns(options: ReadWorkflowRunsOptions = {}): ParsedWorkflowRun[] {\n const environment = options.environment;\n const homeDir =\n options.homeDir ??\n resolveWorkflowHome({\n envValue: environment?.[WORKFLOW_HOME_ENV],\n homeDir: os.homedir(),\n });\n const workspacesDir = path.join(homeDir, WORKSPACES_DIR_NAME);\n const recordCache = new Map<string, { size: number; mtimeMs: number; value: ParsedWorkflowRun | undefined }>();\n const progressCache = new Map<\n string,\n { size: number; mtimeMs: number; value: ReturnType<typeof foldWorkflowProgress> }\n >();\n\n const cachedParse = <T>(\n cache: Map<string, { size: number; mtimeMs: number; value: T }>,\n filePath: string,\n parse: (raw: string) => T,\n empty: T,\n ): T => {\n let stat: fs.Stats;\n try {\n stat = fs.statSync(filePath);\n } catch {\n cache.delete(filePath);\n return empty;\n }\n const cached = cache.get(filePath);\n if (cached && cached.size === stat.size && cached.mtimeMs === stat.mtimeMs) return cached.value;\n let raw: string;\n try {\n raw = fs.readFileSync(filePath, 'utf8');\n } catch {\n cache.delete(filePath);\n return empty;\n }\n const value = parse(raw);\n cache.set(filePath, { size: stat.size, mtimeMs: stat.mtimeMs, value });\n return value;\n };\n\n const listDir = (directory: string): string[] => {\n try {\n return fs.readdirSync(directory).sort();\n } catch {\n return [];\n }\n };\n\n const runs: ParsedWorkflowRun[] = [];\n for (const workspace of listDir(workspacesDir)) {\n for (const stage of WORKFLOW_STAGES) {\n const stageDir = path.join(workspacesDir, workspace, stage);\n for (const runKey of listDir(stageDir)) {\n const runDir = path.join(stageDir, runKey);\n const recordPath = path.join(runDir, RUN_RECORD_FILE_NAME);\n const progressPath = path.join(runDir, PROGRESS_FILE_NAME);\n const parsed = cachedParse(recordCache, recordPath, parseWorkflowRunRecord, undefined);\n if (parsed === undefined) continue;\n const jobs = cachedParse(\n progressCache,\n progressPath,\n (raw) => foldWorkflowProgress(parseWorkflowProgress(raw)),\n [],\n );\n runs.push({ ...parsed, view: completeWorkflowRunView(parsed.view, jobs) });\n }\n }\n }\n return runs;\n}\n","import { randomUUID } from 'node:crypto';\nimport { isAbsolute, relative, resolve } from 'node:path';\n\nimport { resolveRootSessionId } from '@agimon-ai/doompi-core/childProcess';\nimport {\n type DoomHeadlessExecutionContext,\n type DoomHeadlessContent,\n type DoomHeadlessToolResult,\n} from '@agimon-ai/doompi-core/headless';\nimport { serverMinorModes } from '@agimon-ai/doompi-minor-mode';\nimport { defineMinorMode, type MinorModeOwner, type MinorModeState } from '@agimon-ai/doompi-minor-mode';\nimport { createDoomTelemetry } from '@agimon-ai/doompi-telemetry';\nimport { createEmbeddedWorkflowFeature } from '@agimon-ai/workflow-mcp';\nimport type { CallToolResult } from '@modelcontextprotocol/server';\nimport { z } from 'zod';\n\nimport { registerRunProvider, type RunProviderHandle } from '../../services/backgroundWork';\nimport { createServerLauncher } from '../../services/serverLaunch';\nimport { createNativeStepPaneLauncher, createStepExecutor } from '../../services/stepExecutor';\nimport { createWorkflowCatalogReader, presentWorkflowCatalog } from '../../services/webWorkflowCatalog';\nimport { defaultCatalogDeps } from '../../services/workflowCatalogDeps';\nimport type { WorkflowLaunchInput } from '../../services/workflowExecution';\nimport { isWorkflowDispatcherProcess, resolveDispatcherParentSession } from '../../services/workflowFence';\nimport { createWorkflowApi } from '../../services/workflowHubApi';\nimport {\n parseWorkflowLaunchCommand,\n resolveWorkflowEntry,\n validateWorkflowLaunch,\n} from '../../services/workflowLaunchCommand';\nimport { readWorkflowSkill as skill } from '../../services/workflowResource';\nimport { presentWorkflowRuns, runBelongsToSession } from '../../services/workflowRuns';\nimport { readWorkflowRuns } from '../../services/workflowWatcher';\nimport routes from '../../types/apiRoutes';\nimport { WORKFLOW_CATALOG_TYPE, WORKFLOW_RUNS_TYPE } from '../../types/webWorkflows';\nimport { WORKFLOW_API_BASE_PATH, type WorkflowLaunchResponse } from '../../types/webWorkflowTerminal';\n\nconst SOURCE = '@agimon-ai/doompi-workflow';\nconst WORKFLOW_MODE_ID = 'workflow';\nconst LIST_TOOL = 'list_workflows';\nconst LAUNCH_TOOL = 'launch_workflow';\nconst RUN_TOOL = 'workflow_run';\n/** Origin of a request dispatched in process to another mount; nothing resolves it. */\nconst IN_PROCESS_ORIGIN = 'http://doompi.local';\n/** A burst of job and step events is published once, this long after the first. */\nconst RUNS_PUBLISH_DEBOUNCE_MS = 100;\n/** A notification body's limit; a longer failure is cut to it. */\nconst NOTICE_BODY_LIMIT = 4_000;\n\ntype LaunchResult = { content: { type: 'text'; text: string }[]; isError?: boolean };\n/** Where a launch comes from: the directory it names paths against, and the repository they must stay in. */\ntype LaunchLocation = { readonly cwd: string; readonly repoRoot: string };\n\n/**\n * A launch refused because the workflow needs fixing. The doctor's findings\n * name only a job and a step, so the notice names the workflow and says\n * nothing ran; in a conversation it otherwise reads as part of whatever run\n * was reported just before it.\n */\nfunction needsFixingNotice(workflow: string, error: string): string {\n return `Workflow \"${workflow}\" was not launched: it needs fixing.\\n${error}`;\n}\n\nfunction textResult(text: string, isError = false): LaunchResult {\n return { content: [{ type: 'text', text }], ...(isError ? { isError: true } : {}) };\n}\n\nfunction isLaunchResponse(value: unknown): value is WorkflowLaunchResponse {\n return typeof value === 'object' && value !== null && 'text' in value && typeof value.text === 'string';\n}\n\nfunction errorOf(value: unknown): string | undefined {\n return typeof value === 'object' && value !== null && 'error' in value && typeof value.error === 'string'\n ? value.error\n : undefined;\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/** The text of a launch's tool result, as the launch tool and the API report it. */\nfunction launchResultOf(result: CallToolResult): LaunchResult {\n const text = result.content\n .map((item) => (item.type === 'text' ? item.text : ''))\n .filter((line) => line !== '')\n .join('\\n');\n return textResult(text || 'Workflow launch requested.', result.isError === true);\n}\n\nfunction callResult(value: unknown): DoomHeadlessToolResult {\n const content: DoomHeadlessContent[] = [];\n if (typeof value === 'object' && value !== null && 'content' in value && Array.isArray(value.content)) {\n for (const item of value.content) {\n if (typeof item !== 'object' || item === null || !('type' in item)) continue;\n const record = item as Record<string, unknown>;\n if (record.type === 'text' && typeof record.text === 'string') content.push({ type: 'text', text: record.text });\n else if (record.type === 'image' && typeof record.data === 'string' && typeof record.mimeType === 'string') {\n content.push({ type: 'image', data: record.data, mimeType: record.mimeType });\n }\n }\n }\n if (content.length === 0) content.push({ type: 'text', text: JSON.stringify(value, null, 2) });\n return {\n content,\n details: value,\n ...(typeof value === 'object' && value !== null && 'isError' in value && value.isError === true\n ? { isError: true }\n : {}),\n };\n}\n\nimport { type DoomHeadlessHostService } from '@agimon-ai/doompi-core/headless';\nimport { type DoomServerHostService, type DoomServerSessionPlugin } from '@agimon-ai/doompi-core/serverFacet';\nexport function createWorkflowServerRuntime(\n host: DoomHeadlessHostService,\n serverHost: DoomServerHostService,\n): DoomServerSessionPlugin {\n if (serverHost.context.directEvents === undefined)\n throw new Error('Workflow headless facet requires the session direct event bus.');\n const directEvents = serverHost.context.directEvents;\n let runProvider: RunProviderHandle | undefined;\n const catalogDeps = defaultCatalogDeps();\n const catalogReader = createWorkflowCatalogReader(catalogDeps);\n const telemetry = createDoomTelemetry({\n serviceName: 'doom-workflow',\n packageName: SOURCE,\n cwd: host.context.cwd,\n env: host.context.environment,\n enableLogs: true,\n enableTraces: true,\n });\n /** This session's runs, published to its panel and counted as its background work. */\n const publishRuns = (executionContext: typeof host.context): boolean => {\n const records = readWorkflowRuns({ environment: executionContext.environment }).filter((run) =>\n runBelongsToSession(run, executionContext.sessionId),\n );\n const activeItems = records\n .filter((run) => run.view.stage === 'running' && run.view.stale !== true)\n .map((run) => ({ id: `${run.view.workspace}/${run.view.runKey}`, sessionId: executionContext.sessionId }));\n runProvider?.update(activeItems);\n const runs = presentWorkflowRuns(\n records.map((run) => run.view),\n Date.now(),\n );\n directEvents.publish(WORKFLOW_RUNS_TYPE, executionContext.sessionId, { runs });\n return activeItems.length > 0;\n };\n /** The workflows this session can launch. Runs moving on do not change them, so their events skip this. */\n const publishCatalog = async (executionContext: typeof host.context): Promise<void> => {\n try {\n directEvents.publish(WORKFLOW_CATALOG_TYPE, executionContext.sessionId, {\n cwd: executionContext.cwd,\n workflows: presentWorkflowCatalog(await catalogReader.read(executionContext.cwd)),\n });\n } catch (error) {\n const warning = error instanceof Error ? error.message : String(error);\n directEvents.publish(WORKFLOW_CATALOG_TYPE, executionContext.sessionId, {\n cwd: executionContext.cwd,\n workflows: [],\n warning,\n });\n }\n };\n const publishLifecycle = async (executionContext: typeof host.context): Promise<boolean> => {\n const active = publishRuns(executionContext);\n await publishCatalog(executionContext);\n return active;\n };\n let runsTimer: ReturnType<typeof setTimeout> | undefined;\n /** Publishes the runs once for a burst of job and step events, which a fix loop can produce by the dozen. */\n const publishRunsSoon = (executionContext: typeof host.context, after?: (active: boolean) => void): void => {\n if (runsTimer !== undefined) return;\n runsTimer = setTimeout(() => {\n runsTimer = undefined;\n try {\n after?.(publishRuns(executionContext));\n } catch (error) {\n void telemetry.recordWarning('doom_workflow.publish_failed', error);\n }\n }, RUNS_PUBLISH_DEBOUNCE_MS);\n runsTimer.unref?.();\n };\n // Steps run in this process: customRun as child sessions of this one, commands in their own panes.\n const sessionService = serverHost.context.sessionService;\n const feature = createEmbeddedWorkflowFeature(\n sessionService === undefined\n ? {}\n : {\n stepExecutor: createStepExecutor({\n sessionService,\n parentSessionId: host.context.sessionId,\n hostEnvironment: process.env,\n launchPane: createNativeStepPaneLauncher(undefined, telemetry),\n createId: () => `workflow-${randomUUID()}`,\n telemetry,\n }),\n },\n );\n type LaunchParameters = Parameters<typeof feature.runTool.execute>[0];\n const launcher = createServerLauncher({\n feature,\n sessionId: host.context.sessionId,\n environment: host.context.environment,\n telemetry,\n notify: (body, level) => host.context.client.notify({ body: body.slice(0, NOTICE_BODY_LIMIT), level }),\n onRunsChanged: () => publishRunsSoon(host.context),\n });\n /**\n * Why this session cannot run a launch, or undefined when it can.\n *\n * The checks the slash command makes through the catalog, made for every\n * launch whatever asked for it: the launch tool, another session, or the\n * browser. The workflow must be a file in the repository the launch comes\n * from, a worktree's own when it runs in one, and its runner, command,\n * choice, inputs and prompt must be ones it declares.\n */\n const refuseLaunch = (input: WorkflowLaunchInput, where: LaunchLocation): string | undefined => {\n if (typeof input.workflowPath !== 'string' || input.workflowPath === '') return 'A launch needs a workflowPath.';\n const workflowPath = resolve(where.cwd, input.workflowPath);\n const inside = relative(where.repoRoot, workflowPath);\n if (inside.startsWith('..') || isAbsolute(inside)) {\n return `Workflow ${input.workflowPath} is outside this session's repository, so it cannot be launched here.`;\n }\n const detail = catalogDeps.summarize(workflowPath);\n if (detail.error !== undefined) return needsFixingNotice(inside, detail.error);\n const problems = validateWorkflowLaunch(detail, {\n inputs: input.inputs ?? {},\n ...(input.prompt === undefined ? {} : { prompt: input.prompt }),\n ...((input.runner ?? input.cliAgent) === undefined ? {} : { runner: input.runner ?? input.cliAgent }),\n ...(input.command === undefined ? {} : { command: input.command }),\n ...(input.choice === undefined ? {} : { choice: input.choice }),\n });\n return problems.length === 0 ? undefined : problems.join('\\n');\n };\n /**\n * Run a workflow in this process and answer once it has registered.\n *\n * The launch goes through the same executor the Pi extension uses; see\n * `createServerLauncher` for what the server adds around it.\n */\n const launchHere = async (\n parameters: LaunchParameters,\n where: LaunchLocation = host.context,\n ): Promise<LaunchResult> => {\n let input: WorkflowLaunchInput;\n try {\n input = feature.runTool.getInputSchema().parse(parameters);\n } catch (error) {\n return textResult(`Error: ${errorMessage(error)}`, true);\n }\n const refusal = refuseLaunch(input, where);\n if (refusal !== undefined) return textResult(`Error: ${refusal}`, true);\n try {\n return launchResultOf(await launcher.launch({ ...input, workflowPath: resolve(where.cwd, input.workflowPath) }));\n } catch (error) {\n return textResult(`Error: ${errorMessage(error)}`, true);\n }\n };\n /**\n * Hand a launch to the session that owns this session's runs, through that\n * session's own mount of this package's API. The owner runs it, so the run\n * and its step sessions outlive this session, as a dispatcher's launches must.\n */\n const launchIn = async (owner: string, parameters: LaunchParameters): Promise<LaunchResult> => {\n if (serverHost.context.requestApi === undefined) {\n return textResult(`Error: this host cannot reach session ${owner} to launch the workflow there.`, true);\n }\n const response = await serverHost.context.requestApi(\n { scope: 'session', sessionId: owner },\n WORKFLOW_API_BASE_PATH,\n new Request(`${IN_PROCESS_ORIGIN}${routes.launch.path}`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(parameters),\n }),\n );\n const body: unknown = await response.json().catch((error: unknown) => ({ error: String(error) }));\n if (response.ok && isLaunchResponse(body)) return textResult(body.text, body.isError === true);\n const reason = errorOf(body) ?? `HTTP ${String(response.status)}`;\n return textResult(`Error: session ${owner} did not launch the workflow (${reason}).`, true);\n };\n /**\n * A workflow dispatcher launches for its root session, the way a CLI\n * dispatcher child does: the same markers name it, and the root runs what\n * it launches. Any other session runs its own launches.\n */\n const dispatcher = isWorkflowDispatcherProcess(host.context.environment);\n const launchOwner = (): string | undefined => {\n if (!dispatcher) return undefined;\n const parent = resolveDispatcherParentSession(host.context.environment);\n if (parent === undefined) return undefined;\n const owner = resolveRootSessionId(parent, host.context.environment);\n return owner === host.context.sessionId ? undefined : owner;\n };\n const launch = async (parameters: LaunchParameters, where?: LaunchLocation): Promise<LaunchResult> => {\n const owner = launchOwner();\n return owner === undefined ? launchHere(parameters, where) : launchIn(owner, parameters);\n };\n /** A launch another session handed this one: this session runs and owns it. */\n const launchFromApi = async (parameters: Record<string, unknown>): Promise<WorkflowLaunchResponse> => {\n const result = await launchHere(parameters as LaunchParameters);\n // No tool call ends here to refresh the panel, so publish the new run now.\n publishRunsSoon(host.context);\n return {\n text: result.content.map((item) => item.text).join('\\n'),\n ...(result.isError === true ? { isError: true } : {}),\n };\n };\n let control: ReturnType<typeof feature.createRunControl> | undefined;\n let controlDisposers: (() => void)[] = [];\n const disposeControl = (): void => {\n for (const dispose of controlDisposers.splice(0)) dispose();\n control?.dispose();\n control = undefined;\n };\n let modeOwner: MinorModeOwner | undefined;\n const modeSelected = (): boolean => (host.context.selection.state?.['minor-mode'] ?? []).includes(WORKFLOW_MODE_ID);\n const modeState = (): MinorModeState => {\n const active = modeSelected();\n return {\n activation: active ? 'active' : 'inactive',\n condition: 'ready',\n ...(active ? { detail: 'workflow tools available' } : {}),\n actions: [\n { id: 'activate', enabled: !active, ...(!active ? {} : { disabledReason: 'Workflow mode is active.' }) },\n { id: 'deactivate', enabled: active, ...(active ? {} : { disabledReason: 'Workflow mode is inactive.' }) },\n ],\n };\n };\n const selectMode = async (enabled: boolean): Promise<void> => {\n const modes = (host.context.selection.state?.['minor-mode'] ?? []).filter((mode) => mode !== WORKFLOW_MODE_ID);\n await host.changeSelection({\n axis: 'state',\n key: 'minor-mode',\n values: enabled ? [...modes, WORKFLOW_MODE_ID] : modes,\n });\n modeOwner?.publish();\n };\n modeOwner = defineMinorMode({\n descriptor: {\n source: SOURCE,\n id: WORKFLOW_MODE_ID,\n label: 'Workflow',\n description: 'Workflow discovery, launch, inspection, control, and recovery tools.',\n order: 20,\n actions: [\n {\n id: 'activate',\n label: 'Activate',\n description: 'Enable workflow tools for this session.',\n contexts: ['headless'],\n parameters: [],\n },\n {\n id: 'deactivate',\n label: 'Deactivate',\n description: 'Disable workflow tools without stopping active runs.',\n contexts: ['headless'],\n parameters: [],\n },\n ],\n },\n state: modeState,\n async handleAction(_runtime, actionId, _argumentsValue, execution) {\n execution.signal.throwIfAborted();\n if (actionId === 'activate') {\n await selectMode(true);\n return { message: 'Workflow mode activated.' };\n }\n if (actionId === 'deactivate') {\n await selectMode(false);\n return { message: 'Workflow mode deactivated.' };\n }\n throw new Error(`Unknown workflow mode action: ${actionId}`);\n },\n }).createOwner(undefined);\n return {\n api: [createWorkflowApi(launchFromApi)],\n services: [\n serverMinorModes([modeOwner]),\n (context) => {\n const provider = registerRunProvider(context);\n runProvider = provider;\n return () => {\n provider.dispose();\n if (runProvider === provider) runProvider = undefined;\n };\n },\n ],\n hooks: [\n {\n event: 'tool_execution_end',\n handle: async (_event, executionContext) => {\n await publishLifecycle(executionContext);\n },\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n event: 'session_shutdown',\n handle: disposeControl,\n },\n ],\n resources: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'doompi-author-workflow',\n kind: 'skill',\n read: () => skill('doompi-author-workflow'),\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'doompi-use-workflow',\n kind: 'skill',\n read: () => skill('doompi-use-workflow'),\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'workflow-recovery',\n kind: 'skill',\n read: () => skill('workflow-recovery'),\n },\n ],\n activities: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: SOURCE,\n async start(executionContext) {\n const reportFailure = (error: unknown): void => {\n process.emitWarning(`Could not publish headless workflow state: ${String(error)}`);\n };\n const stopFor =\n (ownedControl: NonNullable<typeof control>): (() => void) =>\n () => {\n void publishLifecycle(executionContext)\n .then((active) => {\n if (!active && !modeSelected() && control === ownedControl) disposeControl();\n })\n .catch(reportFailure);\n };\n if (control !== undefined) {\n const ownedControl = control;\n await publishLifecycle(executionContext);\n return stopFor(ownedControl);\n }\n control = feature.createRunControl({});\n const ownedControl = control;\n const refresh = (): void => {\n publishRunsSoon(executionContext, (active) => {\n if (!active && !modeSelected() && control === ownedControl) disposeControl();\n });\n };\n // Job and step transitions live only in the progress log. A step's execution\n // ref, which tells the web view to show an agent session instead of a\n // terminal, lands there after the step started, with no run record change.\n controlDisposers = [\n ownedControl.on('runStarted', refresh),\n ownedControl.on('runUpdated', refresh),\n ownedControl.on('runFinished', refresh),\n ownedControl.on('job', refresh),\n ownedControl.on('step', refresh),\n ];\n try {\n await ownedControl.start();\n await publishLifecycle(executionContext);\n return stopFor(ownedControl);\n } catch (error) {\n if (control === ownedControl) disposeControl();\n throw error;\n }\n },\n },\n ],\n tools: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: LIST_TOOL,\n label: 'List Workflows',\n description: 'List workflow definitions in this repository, not existing runs.',\n promptGuidelines: ['Use list_workflows to discover definitions, not to find an existing run.'],\n parameters: z.toJSONSchema(feature.listWorkflowsTool.getInputSchema()),\n executionMode: 'serial',\n async execute(_toolCallId, parameters, signal, _onUpdate, context) {\n signal?.throwIfAborted();\n const input = parameters as Parameters<typeof feature.listWorkflowsTool.execute>[0];\n return callResult(\n await feature.listWorkflowsTool.execute({\n ...input,\n directory:\n input?.directory === undefined\n ? context.cwd\n : typeof input.directory === 'string'\n ? resolve(context.cwd, input.directory)\n : input.directory,\n }),\n );\n },\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: LAUNCH_TOOL,\n label: 'Launch Workflow',\n description: 'Start a workflow run. A successful launch is not a completed workflow.',\n promptGuidelines: [\n 'Launch returns when a run starts, not when it finishes. Use the exact run key and separate workspace from its launch result for workflow_run status, not Agiflow project or job identifiers.',\n 'Do not relaunch a healthy running workflow merely because it has not completed.',\n ],\n parameters: z.toJSONSchema(feature.runTool.getInputSchema()),\n executionMode: 'serial',\n async execute(_toolCallId, parameters, signal, _onUpdate, context) {\n signal?.throwIfAborted();\n const input = parameters as Parameters<typeof feature.runTool.execute>[0];\n return callResult(\n await launch(\n {\n ...input,\n ...(typeof input.workflowPath === 'string'\n ? { workflowPath: resolve(context.cwd, input.workflowPath) }\n : {}),\n },\n context,\n ),\n );\n },\n },\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: RUN_TOOL,\n label: 'Workflow Run',\n description:\n 'Inspect a session-owned workflow by exact run key and separate workspace, or request cooperative control.',\n promptGuidelines: [\n 'Use workflow_run status for the recorded stage, outcome, position, jobs, and steps. A successful status lookup is not evidence that the workflow completed.',\n 'For a healthy running workflow, summarize the recorded progress. Do not automatically search CLI commands or filesystem logs, relaunch, or diagnose failure merely because it remains running.',\n 'Investigate further when the run reports failure or staleness, or when the user requests diagnostics. Only status, pause, resume, and stop are supported here; stop only on user request.',\n 'Use exact registry runKey and separate workspace from the launch or status result. Agiflow project and job identifiers are not workflow run keys.',\n ],\n parameters: {\n type: 'object',\n properties: {\n action: { type: 'string', enum: ['status', 'pause', 'resume', 'stop'] },\n runKey: {\n type: 'string',\n minLength: 1,\n description:\n 'Exact registry run key from the launch result, without the workspace prefix. Not an Agiflow job ID.',\n },\n workspace: {\n type: 'string',\n description: 'Workspace from the launch result, passed separately from runKey.',\n },\n reason: { type: 'string' },\n expectedRunId: { type: 'string' },\n },\n required: ['action', 'runKey'],\n additionalProperties: false,\n },\n executionMode: 'serial',\n async execute(_toolCallId, parameters, signal) {\n signal?.throwIfAborted();\n const input = parameters as unknown as {\n action: 'status' | 'pause' | 'resume' | 'stop';\n runKey: string;\n workspace?: string;\n reason?: string;\n expectedRunId?: string;\n };\n const runs = readWorkflowRuns({ environment: host.context.environment }).filter(\n (run) =>\n runBelongsToSession(run, host.context.sessionId) &&\n run.view.runKey === input.runKey &&\n (input.workspace === undefined || run.view.workspace === input.workspace),\n );\n if (runs.length !== 1)\n return {\n ...callResult({\n error:\n runs.length === 0\n ? 'No matching workflow run was found in this session. This is a lookup failure, not evidence that the workflow failed. Use the exact runKey and separate workspace from its launch result, not Agiflow job identifiers.'\n : 'Specify the workspace for this run key.',\n }),\n isError: true,\n };\n const run = runs[0]!.view;\n if (input.action === 'status') return callResult(run);\n if (!control) return callResult({ error: 'Workflow activity is not active.' });\n if (typeof input.expectedRunId !== 'string' || input.expectedRunId.length === 0) {\n return callResult({ error: 'expectedRunId is required for workflow control.' });\n }\n const request =\n input.action === 'pause'\n ? await control.pause(input.runKey, input.expectedRunId, input.workspace, input.reason)\n : input.action === 'resume'\n ? await control.resume(input.runKey, input.expectedRunId, input.workspace)\n : await control.stop(input.runKey, input.expectedRunId, input.workspace, input.reason);\n return callResult(request);\n },\n },\n ],\n commands: [\n {\n when: { state: { 'minor-mode': WORKFLOW_MODE_ID }, attribution: { kind: 'minor', mode: WORKFLOW_MODE_ID } },\n name: 'workflow-launch',\n description: 'Launch a workflow from a slash command.',\n async execute(args: string, execution: DoomHeadlessExecutionContext) {\n const parsed = parseWorkflowLaunchCommand(args);\n if ('error' in parsed) {\n await execution.client.notify({ body: parsed.error, level: 'error' });\n return;\n }\n try {\n const entry = resolveWorkflowEntry(await catalogReader.read(execution.cwd), parsed.workflow);\n if (!entry || entry.error) {\n await execution.client.notify({\n body: entry?.error\n ? needsFixingNotice(entry.name, entry.error)\n : `Workflow not found: ${parsed.workflow}`,\n level: 'error',\n });\n return;\n }\n const problems = validateWorkflowLaunch(entry, parsed);\n if (problems.length > 0) {\n await execution.client.notify({ body: problems.join('\\n'), level: 'error' });\n return;\n }\n const result = callResult(\n await launch(\n {\n workflowPath: entry.path,\n ...(parsed.runner === undefined ? {} : { runner: parsed.runner }),\n ...(parsed.command === undefined ? {} : { command: parsed.command }),\n ...(parsed.choice === undefined ? {} : { choice: parsed.choice }),\n ...(Object.keys(parsed.inputs).length === 0 ? {} : { inputs: parsed.inputs }),\n ...(parsed.prompt === undefined ? {} : { prompt: parsed.prompt }),\n },\n execution,\n ),\n );\n const rendered = result.content.find((item) => item.type === 'text');\n await execution.client.notify({\n body: rendered?.type === 'text' ? rendered.text : 'Workflow launch requested.',\n level: result.isError ? 'error' : 'info',\n });\n } catch (error) {\n await execution.client.notify({ body: String(error), level: 'error' });\n }\n },\n },\n ],\n // A dispatcher launches for its root and never works a run itself, as a CLI dispatcher child.\n ...(dispatcher ? { toolRestrictions: [{ excludedTools: [RUN_TOOL] }] } : {}),\n async onDispose() {\n disposeControl();\n if (runsTimer !== undefined) clearTimeout(runsTimer);\n // Runs this session is running stop with it, rather than going on under a parent that is gone.\n await launcher.dispose();\n runProvider?.dispose();\n runProvider = undefined;\n await telemetry.shutdown();\n },\n };\n}\n","import type { DoomServerPluginDefinition } from '@agimon-ai/doompi-core/serverFacet';\n\nimport { createWorkflowServerRuntime } from '../../../../../services/serverRuntime';\nimport { api } from '../../../../../services/workflowHubApi';\n\n// A session with an agent mounts the API with its runtime, which can launch into this session.\nexport default (({ agent, host }) =>\n agent ? createWorkflowServerRuntime(agent, host) : { api: [api] }) satisfies NonNullable<\n DoomServerPluginDefinition['session']\n>;\n","import { defineRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport runtime from './_lib/index.server';\n\nexport default defineRoot((context: Parameters<typeof runtime>[0]) => {\n const value = runtime(context);\n return {\n value,\n services: value.services,\n activities: value.activities,\n onStart: value.onStart,\n onStop: value.onStop,\n onDispose: value.onDispose,\n };\n});\n","import type { DoomHubChannelSource, DoomHubSessionScope, DoomHubChannel } from '@agimon-ai/doompi-core/hubChannel';\n\nimport {\n createWorkflowCatalogReader,\n presentWorkflowCatalog,\n type WorkflowCatalogReaderDeps,\n} from '../../services/webWorkflowCatalog';\nimport { defaultCatalogDeps } from '../../services/workflowCatalogDeps';\nimport { WORKFLOW_CATALOG_TYPE, type WorkflowCatalogPayload } from '../../types/webWorkflows';\n\nexport interface WorkflowCatalogChannelOptions {\n deps?: WorkflowCatalogReaderDeps;\n}\n\n/**\n * The workflow catalog channel. Durable state seeds a session once, then\n * session lifecycle events deliver updates over the direct event bus.\n */\nexport function createWorkflowCatalogChannel(options: WorkflowCatalogChannelOptions = {}): DoomHubChannel {\n const reader = createWorkflowCatalogReader(options.deps ?? defaultCatalogDeps());\n return {\n frameType: WORKFLOW_CATALOG_TYPE,\n start(host) {\n const scopes = new Map<string, DoomHubSessionScope>();\n const latest = new Map<string, WorkflowCatalogPayload>();\n const subscriptions = new Map<string, () => void>();\n const publish = (scope: DoomHubSessionScope, payload: WorkflowCatalogPayload): void => {\n latest.set(scope.sessionId, payload);\n host.publish(scope.sessionId, payload);\n };\n const readInitial = async (scope: DoomHubSessionScope): Promise<void> => {\n let payload: WorkflowCatalogPayload;\n try {\n payload = {\n cwd: scope.cwd,\n workflows: presentWorkflowCatalog(await reader.read(scope.cwd)),\n };\n } catch (error) {\n const warning = error instanceof Error ? error.message : String(error);\n payload = { cwd: scope.cwd, workflows: [], warning };\n host.onNotice(`workflow catalog for ${scope.cwd} is unavailable (${warning})`);\n }\n if (scopes.get(scope.sessionId) === scope) publish(scope, payload);\n };\n const source: DoomHubChannelSource = {\n payloadFor(scope) {\n return scopes.has(scope.sessionId) ? latest.get(scope.sessionId) : undefined;\n },\n sessionAdded(scope) {\n scopes.set(scope.sessionId, scope);\n subscriptions.get(scope.sessionId)?.();\n const unsubscribe = host.directEvents.subscribe(\n WORKFLOW_CATALOG_TYPE,\n scope.sessionId,\n (value) => {\n if (isWorkflowCatalogPayload(value)) publish(scope, value);\n },\n { replayLatest: true },\n );\n subscriptions.set(scope.sessionId, unsubscribe);\n void readInitial(scope);\n },\n sessionRemoved(sessionId) {\n subscriptions.get(sessionId)?.();\n subscriptions.delete(sessionId);\n scopes.delete(sessionId);\n latest.delete(sessionId);\n },\n close() {\n for (const unsubscribe of subscriptions.values()) unsubscribe();\n subscriptions.clear();\n scopes.clear();\n latest.clear();\n },\n };\n return source;\n },\n };\n}\n\nfunction isWorkflowCatalogPayload(value: unknown): value is WorkflowCatalogPayload {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as { cwd?: unknown }).cwd === 'string' &&\n Array.isArray((value as { workflows?: unknown }).workflows)\n );\n}\n","import type { DoomHubChannelSource, DoomHubSessionScope, DoomHubChannel } from '@agimon-ai/doompi-core/hubChannel';\n\nimport { presentWorkflowRuns, runBelongsToSession, type ParsedWorkflowRun } from '../../services/workflowRuns';\nimport { readWorkflowRuns, type ReadWorkflowRunsOptions } from '../../services/workflowWatcher';\nimport { WORKFLOW_RUNS_TYPE, type WorkflowRunView, type WorkflowRunsPayload } from '../../types/webWorkflows';\n\nexport interface WorkflowsChannelOptions {\n /** Injectable durable initial snapshot reader for tests. */\n read?: (options: ReadWorkflowRunsOptions) => ParsedWorkflowRun[];\n}\n\nfunction isWorkflowRunsPayload(value: unknown): value is WorkflowRunsPayload {\n return typeof value === 'object' && value !== null && Array.isArray((value as { runs?: unknown }).runs);\n}\n\n/**\n * The workflow runs data channel. Durable registry state seeds each session\n * once; subsequent updates arrive through the host-owned direct event bus.\n */\nexport function createWorkflowsChannel(options: WorkflowsChannelOptions = {}): DoomHubChannel {\n const read = options.read ?? readWorkflowRuns;\n return {\n frameType: WORKFLOW_RUNS_TYPE,\n start(host) {\n const scopes = new Map<string, DoomHubSessionScope>();\n const latest = new Map<string, WorkflowRunsPayload>();\n const subscriptions = new Map<string, () => void>();\n const runsFor = (scope: DoomHubSessionScope, parsed: readonly ParsedWorkflowRun[]): WorkflowRunView[] =>\n presentWorkflowRuns(\n parsed.filter((run) => runBelongsToSession(run, scope.sessionId)).map((run) => run.view),\n Date.now(),\n );\n const publish = (scope: DoomHubSessionScope, payload: WorkflowRunsPayload): void => {\n latest.set(scope.sessionId, payload);\n host.publish(scope.sessionId, payload);\n };\n const source: DoomHubChannelSource = {\n payloadFor(scope) {\n return scopes.has(scope.sessionId) ? latest.get(scope.sessionId) : undefined;\n },\n sessionAdded(scope) {\n scopes.set(scope.sessionId, scope);\n subscriptions.get(scope.sessionId)?.();\n const unsubscribe = host.directEvents.subscribe(\n WORKFLOW_RUNS_TYPE,\n scope.sessionId,\n (value) => {\n if (isWorkflowRunsPayload(value)) publish(scope, value);\n },\n { replayLatest: true },\n );\n subscriptions.set(scope.sessionId, unsubscribe);\n const payload = { runs: runsFor(scope, read({ environment: scope.environment })) };\n publish(scope, payload);\n },\n sessionRemoved(sessionId) {\n subscriptions.get(sessionId)?.();\n subscriptions.delete(sessionId);\n scopes.delete(sessionId);\n latest.delete(sessionId);\n },\n close() {\n for (const unsubscribe of subscriptions.values()) unsubscribe();\n subscriptions.clear();\n scopes.clear();\n latest.clear();\n },\n };\n return source;\n },\n };\n}\n","import type { DoomServerPluginDefinition } from '@agimon-ai/doompi-core/serverFacet';\n\nimport { createWorkflowCatalogChannel } from '../../../services/workflowCatalogChannel';\nimport { api } from '../../../services/workflowHubApi';\nimport { createWorkflowsChannel } from '../../../services/workflowsHubChannel';\n\nexport default (({ host }) =>\n host.scope === 'session'\n ? {}\n : { channels: [createWorkflowsChannel, createWorkflowCatalogChannel], api: [api] }) satisfies NonNullable<\n DoomServerPluginDefinition['global']\n>;\n","import { defineRoutedContribution } from '@agimon-ai/doompi-core/extensionFile';\n\nimport legacy from '../../_lib/index.server';\n\nexport default defineRoutedContribution((context: Parameters<typeof legacy>[0]) => legacy(context).api?.[0], {\n cardinality: 'optional',\n});\n","import { defineChannel } from '@agimon-ai/doompi-core/extensionFile';\n\nimport { createWorkflowCatalogChannel } from '../../../services/workflowCatalogChannel';\n\nexport default defineChannel(createWorkflowCatalogChannel);\n","import { defineChannel } from '@agimon-ai/doompi-core/extensionFile';\n\nimport { createWorkflowsChannel } from '../../../services/workflowsHubChannel';\n\nexport default defineChannel(createWorkflowsChannel);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport runtime from '../../_lib/index.server';\n\nexport default defineRoutedContribution(\n (context: WithRoot<unknown, ReturnType<typeof runtime>>) => context.root.api?.[0],\n { cardinality: 'optional' },\n);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport runtime from '../_lib/index.server';\n\nexport default defineRoutedContribution(\n (context: WithRoot<unknown, ReturnType<typeof runtime>>) => context.root.commands?.[0],\n { cardinality: 'optional' },\n);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport runtime from '../_lib/index.server';\n\nexport default defineRoutedContribution(\n (context: WithRoot<unknown, ReturnType<typeof runtime>>) => context.root.hooks?.[1],\n { cardinality: 'optional' },\n);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport runtime from '../_lib/index.server';\n\nexport default defineRoutedContribution(\n (context: WithRoot<unknown, ReturnType<typeof runtime>>) => context.root.hooks?.[0],\n { cardinality: 'optional' },\n);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport runtime from '../_lib/index.server';\n\nexport default defineRoutedContribution(\n (context: WithRoot<unknown, ReturnType<typeof runtime>>) => context.root.resources?.[0],\n { cardinality: 'optional' },\n);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport runtime from '../_lib/index.server';\n\nexport default defineRoutedContribution(\n (context: WithRoot<unknown, ReturnType<typeof runtime>>) => context.root.resources?.[1],\n { cardinality: 'optional' },\n);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport runtime from '../_lib/index.server';\n\nexport default defineRoutedContribution(\n (context: WithRoot<unknown, ReturnType<typeof runtime>>) => context.root.resources?.[2],\n { cardinality: 'optional' },\n);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport runtime from '../_lib/index.server';\n\nexport default defineRoutedContribution(\n (context: WithRoot<unknown, ReturnType<typeof runtime>>) => context.root.toolRestrictions?.[0],\n { cardinality: 'optional' },\n);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport runtime from '../_lib/index.server';\n\nexport default defineRoutedContribution(\n (context: WithRoot<unknown, ReturnType<typeof runtime>>) => context.root.tools?.[1],\n { cardinality: 'optional' },\n);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport runtime from '../_lib/index.server';\n\nexport default defineRoutedContribution(\n (context: WithRoot<unknown, ReturnType<typeof runtime>>) => context.root.tools?.[0],\n { cardinality: 'optional' },\n);\n","import { defineRoutedContribution, type WithRoot } from '@agimon-ai/doompi-core/extensionFile';\n\nimport runtime from '../_lib/index.server';\n\nexport default defineRoutedContribution(\n (context: WithRoot<unknown, ReturnType<typeof runtime>>) => context.root.tools?.[2],\n { cardinality: 'optional' },\n);\n","// Generated by @agimon-ai/doompi-build. Do not edit by hand.\nimport { defineServerPlugin, type DoomServerSessionPlugin } from '@agimon-ai/doompi-core/serverFacet';\nimport { composeRootHooks } from '@agimon-ai/doompi-core/extensionFile';\n\nimport rootSession from '../src/extensions/workspaces/sessions/(backend)/root.server';\nimport apiRoute from '../src/extensions/(backend)/api/workflow/route.server';\nimport channelWorkflowCatalog from '../src/extensions/(backend)/channel/workflow-catalog.server';\nimport channelWorkflows from '../src/extensions/(backend)/channel/workflows.server';\nimport apiRoute2 from '../src/extensions/workspaces/sessions/(backend)/api/workflow/route.server';\nimport commandWorkflowLaunch from '../src/extensions/workspaces/sessions/(backend)/command/workflow-launch.server';\nimport hookSessionShutdown from '../src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server';\nimport hookToolExecutionEnd from '../src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.server';\nimport resourceDoompiAuthorWorkflow from '../src/extensions/workspaces/sessions/(backend)/resource/doompi-author-workflow.server';\nimport resourceDoompiUseWorkflow from '../src/extensions/workspaces/sessions/(backend)/resource/doompi-use-workflow.server';\nimport resourceWorkflowRecovery from '../src/extensions/workspaces/sessions/(backend)/resource/workflow-recovery.server';\nimport toolRestrictionDispatcher from '../src/extensions/workspaces/sessions/(backend)/tool-restriction/dispatcher.server';\nimport toolLaunchWorkflow from '../src/extensions/workspaces/sessions/(backend)/tool/launch-workflow.server';\nimport toolListWorkflows from '../src/extensions/workspaces/sessions/(backend)/tool/list-workflows.server';\nimport toolWorkflowRun from '../src/extensions/workspaces/sessions/(backend)/tool/workflow-run.server';\n\ntype Factory<T, C> = (context: C) => T;\nconst at = <T, C>(value: T | Factory<T, C>, context: C): T =>\n typeof value === 'function' ? (value as Factory<T, C>)(context) : value;\n/* v8 ignore next -- generated normalization branch */\nconst defined = <T>(values: readonly (T | undefined)[]): T[] =>\n values.filter((value): value is T => value !== undefined);\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const facet = defineServerPlugin({\n name: '@agimon-ai/doompi-workflow',\n global: (context) => ({\n get api(): DoomServerSessionPlugin['api'] { return defined([at(apiRoute, context)]); },\n get channels(): DoomServerSessionPlugin['channels'] { return [() => via({ frameType: 'workflow_catalog' }, channelWorkflowCatalog()), () => via({ frameType: 'workflows' }, channelWorkflows())]; },\n }),\n workspace: (context) => ({\n get api(): DoomServerSessionPlugin['api'] { return defined([at(apiRoute, context)]); },\n get channels(): DoomServerSessionPlugin['channels'] { return [() => via({ frameType: 'workflow_catalog' }, channelWorkflowCatalog()), () => via({ frameType: 'workflows' }, channelWorkflows())]; },\n }),\n session: async (context) => {\n const scopeSession = await rootSession(context);\n const contextSession = { ...context, root: scopeSession.value };\n return {\n ...composeRootHooks(scopeSession),\n get api(): DoomServerSessionPlugin['api'] { return defined([at(apiRoute, context), at(apiRoute2, contextSession)]); },\n get channels(): DoomServerSessionPlugin['channels'] { return [() => via({ frameType: 'workflow_catalog' }, channelWorkflowCatalog()), () => via({ frameType: 'workflows' }, channelWorkflows())]; },\n get commands(): DoomServerSessionPlugin['commands'] { return defined([via({ name: 'workflow-launch' }, at(commandWorkflowLaunch, contextSession))]); },\n get hooks(): DoomServerSessionPlugin['hooks'] { return defined([via({ event: 'session_shutdown' }, at(hookSessionShutdown, contextSession)), via({ event: 'tool_execution_end' }, at(hookToolExecutionEnd, contextSession))]); },\n get resources(): DoomServerSessionPlugin['resources'] { return defined([at(resourceDoompiAuthorWorkflow, contextSession), at(resourceDoompiUseWorkflow, contextSession), at(resourceWorkflowRecovery, contextSession)]); },\n get toolRestrictions(): DoomServerSessionPlugin['toolRestrictions'] { return defined([at(toolRestrictionDispatcher, contextSession)]); },\n get tools(): DoomServerSessionPlugin['tools'] { return defined([via({ name: 'launch_workflow' }, at(toolLaunchWorkflow, contextSession)), via({ name: 'list_workflows' }, at(toolListWorkflows, contextSession)), via({ name: 'workflow_run' }, at(toolWorkflowRun, contextSession))]); },\n services: [...(scopeSession.services ?? [])],\n get activities(): DoomServerSessionPlugin['activities'] { return [...(scopeSession.activities ?? [])]; },\n };\n },\n});\n\nexport default facet;\n"],"mappings":"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"}
|