{"version":3,"file":"workflowInspector.mjs","names":[],"sources":["../../../../src/tui/workflow/workflowInspector.ts"],"sourcesContent":["/**\n * Workflow Space: the `SPC w l` overlay.\n *\n * A doom overlay rather than a hand-rolled frame: the roster owns the left\n * third, the run under the cursor owns the right two thirds, and the chrome is\n * the same frame, breadcrumb and key legend every other doom surface draws.\n *\n * Rendering is pure -- `renderBody(width, height)` reads the last polled\n * snapshot and returns lines with no side effects -- so the surface can be\n * asserted as text without a live terminal.\n */\n\nimport { currentWorkflowPosition, type WorkflowProgressJob } from '@agimon-ai/workflow-mcp';\nimport type { Theme } from '@earendil-works/pi-coding-agent';\nimport { matchesKey, truncateToWidth, visibleWidth } from '@earendil-works/pi-tui';\n\nimport {\n  DOOM_FULLSCREEN_UI_OPTIONS,\n  DOOM_OVERLAY_ACCENT,\n  DoomOverlay,\n  type DoomOverlayChrome,\n  type DoomOverlayTui,\n} from './doomOverlay';\nimport { fitTerminalLine } from './overlayText';\nimport { humanizeDuration } from './workflowStatusRow';\n\nexport const WORKFLOW_INSPECTOR_OVERLAY_OPTIONS = DOOM_FULLSCREEN_UI_OPTIONS.overlayOptions;\n\nexport interface WorkflowInspectorSelection {\n  runId?: string;\n  runKey: string;\n  startedAt: string;\n  workspace: string;\n}\n\nexport interface WorkflowInspectorItem extends WorkflowInspectorSelection {\n  displayName: string;\n  executionState?: string;\n  jobs: WorkflowProgressJob[];\n  key: string;\n  output: string[];\n}\n\nexport interface WorkflowInspectorSource {\n  list(): Promise<WorkflowInspectorItem[]>;\n  output(item: WorkflowInspectorItem): Promise<string[]>;\n}\n\nexport interface WorkflowInspectorOptions {\n  initialKey?: string;\n  refreshMs?: number;\n}\n\nconst TITLE = 'WORKFLOW SPACE';\nconst BREADCRUMB = 'SPC › w / workflows › l / manage';\nconst ROSTER_HEADING = 'RUNNING · this session';\nconst EMPTY_ROSTER = 'No active workflows';\nconst PROGRESS_HEADING = 'PROGRESS';\nconst OUTPUT_HEADING = 'OUTPUT · newest last';\nconst NO_SELECTION = 'Select a workflow to inspect its jobs and output.';\nconst RUNNING_STATE = 'running';\nconst PAUSED_STATE = 'paused';\n/** Mirrors DoomPi's list-navigation legend without adding a runtime doompi-ui dependency. */\nconst LIST_NAVIGATION_KEYS = '↑↓';\nconst FOOTER = `${LIST_NAVIGATION_KEYS} select · PgUp/PgDn page · enter open · esc close`;\nconst FOOTER_HINTS: readonly (readonly [string, string])[] = [\n  [LIST_NAVIGATION_KEYS, 'select'],\n  ['PgUp/PgDn', 'page'],\n  ['enter', 'open'],\n  ['esc', 'close'],\n];\n\nconst DEFAULT_REFRESH_MS = 750;\nconst SELECTION_MARKER = '›';\nconst ELLIPSIS = '…';\n/** pi-tui brackets a truncation ellipsis with this; see `fit`. */\nconst HARD_RESET = '\\x1b[0m';\n/** A third for the roster, two thirds for the run being read. */\nconst LIST_PANE_RATIO = 1 / 3;\n/** One blank column each side of the divider so neither pane touches it. */\nconst PANE_GUTTER = 1;\nconst MIN_PANE_WIDTH = 18;\n/** Below this the roster cannot hold a readable name, so the detail takes the body. */\nconst MIN_TWO_PANE_WIDTH = 48;\n/** Each run occupies a name row and a state row beneath it. */\nconst ROWS_PER_ITEM = 2;\n/** Hanging indent for the state row: clears the marker and the glyph. */\nconst META_INDENT = 4;\n/** Rows the roster heading and its spacer take. */\nconst ROSTER_CHROME_ROWS = 2;\n/** The output tail keeps at least this many rows, or it is not worth a divider. */\nconst MIN_OUTPUT_ROWS = 2;\n\n/** Neither palette name is exported, so take both from the theme's methods. */\ntype ThemeBg = Parameters<Theme['bg']>[0];\ntype ThemeColor = Parameters<Theme['fg']>[0];\n\n/**\n * Truncates and pads to an exact column count.\n *\n * `truncateToWidth` wraps its ellipsis in a hard `\\x1b[0m`, which would strip a\n * row's background for everything after a clipped name. The theme closes its own\n * colours with `\\x1b[39m` and `\\x1b[49m`, so the injected resets are dropped.\n */\nfunction fit(text: string, width: number): string {\n  const clipped = truncateToWidth(text, Math.max(0, width), ELLIPSIS).replaceAll(HARD_RESET, '');\n  return clipped + ' '.repeat(Math.max(0, width - visibleWidth(clipped)));\n}\n\nfunction rightAligned(left: string, right: string, width: number): string {\n  const rightWidth = visibleWidth(right);\n  const leftWidth = Math.max(0, width - rightWidth - 1);\n  return fit(left, leftWidth) + ' '.repeat(Math.max(1, width - leftWidth - rightWidth)) + fit(right, rightWidth);\n}\n\nfunction jobGlyph(status: string): string {\n  return status === 'completed' ? '✓' : status === 'failed' ? '✗' : '●';\n}\n\nfunction jobColour(status: string): ThemeColor {\n  return status === 'completed' ? 'success' : status === 'failed' ? 'error' : 'accent';\n}\n\nfunction progressLines(item: WorkflowInspectorItem, width: number, theme: Theme): string[] {\n  const lines: string[] = [];\n  for (const job of item.jobs) {\n    const position = job.total ? ` · ${(job.index ?? 0) + 1}/${job.total}` : '';\n    lines.push(\n      truncateToWidth(\n        theme.fg(jobColour(job.status), `${jobGlyph(job.status)} ${job.name}`) + theme.fg('dim', position),\n        width,\n        ELLIPSIS,\n      ),\n    );\n    // Only the running job's steps: every finished job's steps would push the\n    // live one off the pane, which is the one thing worth watching.\n    if (job.status !== RUNNING_STATE) continue;\n    for (const step of job.steps) {\n      const stepColour: ThemeColor =\n        step.status === 'failed' ? 'error' : step.status === RUNNING_STATE ? 'muted' : 'dim';\n      lines.push(truncateToWidth(theme.fg(stepColour, `   ${jobGlyph(step.status)} ${step.name}`), width, ELLIPSIS));\n    }\n  }\n  return lines;\n}\n\nfunction detailLines(item: WorkflowInspectorItem | undefined, width: number, height: number, theme: Theme): string[] {\n  if (!item) return [theme.fg('dim', NO_SELECTION)];\n\n  const position = currentWorkflowPosition(item.jobs);\n  const elapsed = humanizeDuration(Math.max(0, Date.now() - Date.parse(item.startedAt)));\n  const executionState = item.executionState ?? RUNNING_STATE;\n  const stateColour: ThemeColor = executionState === PAUSED_STATE ? 'warning' : 'dim';\n  const lines = [\n    rightAligned(\n      `${theme.fg('accent', '●')} ${theme.bold(item.displayName)}`,\n      theme.fg(stateColour, executionState),\n      width,\n    ),\n    truncateToWidth(theme.fg('dim', `${item.runKey} · ${item.workspace} · ${elapsed}`), width, ELLIPSIS),\n    position\n      ? truncateToWidth(\n          `${theme.fg('accent', position.job)}${position.step ? theme.fg('muted', ` · ${position.step}`) : ''}`,\n          width,\n          ELLIPSIS,\n        )\n      : theme.fg('dim', 'starting'),\n    '',\n    theme.fg('dim', PROGRESS_HEADING),\n  ];\n\n  // The output tail claims its rows first: progress is a list that can be paged\n  // to by opening the run, while the tail is the only live signal on screen.\n  const reservedOutput = item.output.length > 0 ? MIN_OUTPUT_ROWS + 1 : 0;\n  const progressRoom = Math.max(0, height - lines.length - reservedOutput);\n  lines.push(...progressLines(item, width, theme).slice(0, progressRoom));\n\n  if (item.output.length > 0 && height - lines.length >= MIN_OUTPUT_ROWS) {\n    lines.push('', theme.fg('dim', OUTPUT_HEADING));\n    const outputRoom = Math.max(0, height - lines.length);\n    // Captured output carries the run's own colour, so it is fitted by the\n    // escape-preserving path: `fit` below drops hard resets, and a capture that\n    // lost its reset bleeds its colour through the divider and down the pane.\n    lines.push(...item.output.slice(-outputRoom).map((line) => fitTerminalLine(line, width)));\n  }\n\n  return lines.slice(0, height);\n}\n\nexport class WorkflowInspectorComponent extends DoomOverlay {\n  private bodyHeight = 8;\n  private completed = false;\n  private error: string | undefined;\n  private items: WorkflowInspectorItem[] = [];\n  private refreshActive = false;\n  private selected = 0;\n  private selectedKey: string | undefined;\n  private readonly timer: ReturnType<typeof setInterval>;\n\n  constructor(\n    tui: DoomOverlayTui,\n    theme: Theme,\n    private readonly source: WorkflowInspectorSource,\n    private readonly done: (selection: WorkflowInspectorSelection | undefined) => void,\n    options: WorkflowInspectorOptions = {},\n  ) {\n    super(tui, theme);\n    this.selectedKey = options.initialKey;\n    void this.refresh();\n    this.timer = setInterval(() => void this.refresh(), options.refreshMs ?? DEFAULT_REFRESH_MS);\n    this.timer.unref?.();\n  }\n\n  private async refresh(): Promise<void> {\n    if (this.refreshActive || this.completed) return;\n    this.refreshActive = true;\n    try {\n      const previousKey = this.items[this.selected]?.key ?? this.selectedKey;\n      const items = await this.source.list();\n      if (this.completed) return;\n      const preserved = previousKey ? items.findIndex((item) => item.key === previousKey) : -1;\n      this.items = items;\n      this.selected = preserved >= 0 ? preserved : Math.min(this.selected, Math.max(0, items.length - 1));\n      this.selectedKey = items[this.selected]?.key;\n      const selected = items[this.selected];\n      if (selected) selected.output = await this.source.output(selected);\n      this.error = undefined;\n      if (!this.completed) this.tui.requestRender();\n    } catch (cause) {\n      this.error = cause instanceof Error ? cause.message : String(cause);\n      if (!this.completed) this.tui.requestRender();\n    } finally {\n      this.refreshActive = false;\n    }\n  }\n\n  private move(delta: number): void {\n    if (this.items.length === 0) return;\n    this.selected = Math.max(0, Math.min(this.items.length - 1, this.selected + delta));\n    this.selectedKey = this.items[this.selected]?.key;\n    void this.refreshSelectedOutput();\n    this.tui.requestRender();\n  }\n\n  private async refreshSelectedOutput(): Promise<void> {\n    const selected = this.items[this.selected];\n    if (!selected || this.completed) return;\n    try {\n      selected.output = await this.source.output(selected);\n      this.error = undefined;\n    } catch (cause) {\n      this.error = cause instanceof Error ? cause.message : String(cause);\n    }\n    if (!this.completed && selected.key === this.selectedKey) this.tui.requestRender();\n  }\n\n  private finish(selection: WorkflowInspectorSelection | undefined): void {\n    if (this.completed) return;\n    this.completed = true;\n    clearInterval(this.timer);\n    this.done(selection);\n  }\n\n  close(): void {\n    this.finish(undefined);\n  }\n\n  handleInput(data: string): void {\n    if (matchesKey(data, 'escape') || matchesKey(data, 'ctrl+c')) {\n      this.finish(undefined);\n      return;\n    }\n    if (matchesKey(data, 'up') || data === 'k') {\n      this.move(-1);\n      return;\n    }\n    if (matchesKey(data, 'down') || data === 'j') {\n      this.move(1);\n      return;\n    }\n    if (matchesKey(data, 'pageUp')) {\n      this.move(-this.rosterCapacity());\n      return;\n    }\n    if (matchesKey(data, 'pageDown')) {\n      this.move(this.rosterCapacity());\n      return;\n    }\n    if (matchesKey(data, 'enter')) {\n      const selected = this.items[this.selected];\n      if (selected) {\n        this.finish({\n          ...(selected.runId ? { runId: selected.runId } : {}),\n          runKey: selected.runKey,\n          startedAt: selected.startedAt,\n          workspace: selected.workspace,\n        });\n      }\n    }\n  }\n\n  /** Runs the roster can draw, which is also what a page key moves by. */\n  private rosterCapacity(): number {\n    return Math.max(1, Math.floor((this.bodyHeight - ROSTER_CHROME_ROWS) / ROWS_PER_ITEM));\n  }\n\n  private current(): WorkflowInspectorItem | undefined {\n    if (this.items.length === 0) return undefined;\n    return this.items[Math.min(this.selected, this.items.length - 1)];\n  }\n\n  protected getChrome(): DoomOverlayChrome {\n    const selected = this.current();\n    const summary = selected\n      ? `${selected.displayName} · ${selected.executionState ?? RUNNING_STATE}`\n      : 'no active workflows';\n    return {\n      title: TITLE,\n      accent: DOOM_OVERLAY_ACCENT,\n      breadcrumb: BREADCRUMB,\n      headerRight: `${this.items.length} running · ${summary}`,\n      footer: FOOTER,\n      footerHints: FOOTER_HINTS,\n      footerRight:\n        this.items.length > 0 ? `${Math.min(this.selected, this.items.length - 1) + 1}/${this.items.length}` : 'empty',\n    };\n  }\n\n  protected renderBody(width: number, height: number): string[] {\n    this.bodyHeight = height;\n    const detailFor = (paneWidth: number): string[] =>\n      this.error\n        ? [this.theme.fg('warning', `Unable to refresh workflows: ${this.error}`)]\n        : detailLines(this.current(), paneWidth, height, this.theme);\n\n    // Too narrow for two useful columns: the detail takes the whole body rather\n    // than shredding both panes into stubs.\n    if (width < MIN_TWO_PANE_WIDTH) return detailFor(width).slice(0, height);\n\n    const leftWidth = Math.max(MIN_PANE_WIDTH, Math.floor((width - 1) * LIST_PANE_RATIO));\n    const rightWidth = Math.max(1, width - leftWidth - 1);\n    const leftContent = Math.max(1, leftWidth - PANE_GUTTER);\n    const rightContent = Math.max(1, rightWidth - PANE_GUTTER);\n\n    const left = this.rosterLines(leftContent);\n    const right = detailFor(rightContent);\n    const divider = this.theme.fg('borderMuted', '│');\n    return Array.from({ length: height }, (_, index) => {\n      // The roster keeps `fit`, whose reset stripping protects its row\n      // backgrounds; the detail pane has none and may carry captured colour.\n      const row = `${fit(left[index] ?? '', leftContent)} ${divider} ${fitTerminalLine(\n        right[index] ?? '',\n        rightContent,\n      )}`;\n      return truncateToWidth(row, width, ELLIPSIS);\n    });\n  }\n\n  private rosterLines(width: number): string[] {\n    const lines = [this.theme.bold(ROSTER_HEADING), ''];\n    if (this.items.length === 0) {\n      lines.push(this.theme.fg('dim', EMPTY_ROSTER));\n      return lines;\n    }\n\n    // Two rows per run: at a third of the width a single row left the name with\n    // a handful of columns once the stage took its share.\n    const budget = this.rosterCapacity();\n    const active = Math.min(this.selected, this.items.length - 1);\n    const start = Math.max(0, Math.min(active - budget + 1, Math.max(0, this.items.length - budget)));\n    for (const [offset, item] of this.items.slice(start, start + budget).entries()) {\n      const current = start + offset === active;\n      const paused = item.executionState === PAUSED_STATE;\n      const marker = current ? this.theme.fg('accent', SELECTION_MARKER) : ' ';\n      const glyph = this.theme.fg(paused ? 'warning' : 'accent', '●');\n      const name = current ? this.theme.bold(item.displayName) : item.displayName;\n      const stage = paused ? PAUSED_STATE : (currentWorkflowPosition(item.jobs)?.job ?? 'starting');\n      const heading = `${marker} ${glyph} ${name}`;\n      const meta = `${' '.repeat(META_INDENT)}${this.theme.fg(paused ? 'warning' : 'dim', stage)}`;\n      const background: ThemeBg = current ? 'selectedBg' : 'userMessageBg';\n      for (const row of [heading, meta]) lines.push(this.theme.bg(background, fit(row, width)));\n    }\n    return lines;\n  }\n\n  /** Overridden: a repaint request is also the cue to re-read the registry. */\n  invalidate(): void {\n    void this.refresh();\n  }\n\n  dispose(): void {\n    if (this.completed) return;\n    this.completed = true;\n    clearInterval(this.timer);\n  }\n}\n"],"mappings":"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"}