/** * Entry router for the schema-driven TUI shell. * * `resolveEntry()` reads the persisted config (via `readPersistedConfig`) when * `mode === 'auto'` to decide whether to launch the wizard or the settings * shell. This is NOT a pure function — tests that need isolation must use a * tmpdir, set `WIGOLO_CONFIG_PATH`, and call `resetPersistedConfig()` in * `afterEach` to bust the per-path cache. * * `runEntry()` is the side-effecting twin: calls `resolveEntry()` then * either mounts the new Ink shell (`InkRoot`) with the proper * initial view (SettingsHome or 4-step Wizard) or returns a headless code * path so the caller can fall back to its own plain renderer. * * The legacy `runInkInit` / `runInkConfig` entry points are deleted in this * slice; everything Ink-related now flows through here. */ import React from 'react'; import type { CategoryDef } from './schema/types.js'; import type { SettingsStore } from './state/settings-store.js'; import type { ToastStore } from './state/toast-store.js'; import type { ActivityStore } from './state/activity-store.js'; import type { AgentTarget } from './state/agent-targets.js'; import type { SecretStore } from './state/propagation.js'; export type EntryMode = 'wizard' | 'home' | 'auto'; export interface EntryResolution { /** Concrete mode selected. `auto` is always resolved to one of these. */ mode: 'wizard' | 'home'; /** True if the on-disk config file is missing (or the caller forced wizard). */ firstRun: boolean; /** * True when Ink must NOT be mounted (no TTY / CI / --plain / --non-interactive). * The caller is responsible for emitting an equivalent plain-text experience. */ headless: boolean; } export interface ResolveEntryOpts { mode: EntryMode; configPath: string; /** Defaults to `process.stdout.isTTY`. */ isTTY?: boolean; /** Defaults to `process.env.CI === 'true' || '1' || process.env.GITHUB_ACTIONS === 'true'`. */ ci?: boolean; /** Caller-passed `--non-interactive` / `-y` flag. */ nonInteractive?: boolean; /** Caller-passed `--plain` / `-p` flag. */ plain?: boolean; } export declare function resolveEntry(opts: ResolveEntryOpts): Promise; export interface RunEntryOpts extends ResolveEntryOpts { /** Initial store hydrated with the on-disk config + defaults. */ store: SettingsStore; /** Catalog used for schema-driven rendering. */ catalog: ReadonlyArray; /** Optional product version for the SettingsHome header. */ version?: string; /** Optional product name for the SettingsHome header. */ productName?: string; /** Agents registry used for wizard step 4 (Agents). */ agents?: ReadonlyArray; /** Secret store used by the wizard's save step. */ secretStore?: SecretStore; } export interface RunEntryResult { resolution: EntryResolution; /** True when Ink was mounted and `waitUntilExit()` returned. */ mounted: boolean; } interface MountRootProps { store: SettingsStore; catalog: ReadonlyArray; initialView: 'wizard' | 'home'; version?: string; productName?: string; configPath: string; agents?: ReadonlyArray; secretStore?: SecretStore; /** * Test seam — inject pre-loaded components to bypass the lazy dynamic import. * Production callers never pass these; tests pass stubs to avoid I/O. */ _inkRoot?: React.ComponentType<{ store: SettingsStore; catalog: ReadonlyArray; onExit?: () => void; version?: string; productName?: string; toastStore?: ToastStore; activityStore?: ActivityStore; agents?: ReadonlyArray; }>; _wizardSteps?: React.ComponentType<{ store: SettingsStore; catalog: ReadonlyArray; configPath: string; agents?: ReadonlyArray; secretStore?: SecretStore; onDone: () => void; onSkip: () => void; }>; } /** * Inner wrapper that owns the unmount lifecycle via `useApp().exit()`. We * cannot rely on the router to call `useApp` because tests render it bare * and pass a noop `onExit`; centralising the unmount here keeps the router * agnostic of how it is hosted. */ export declare function MountRoot(props: MountRootProps): React.ReactElement; /** * Mounts the Ink shell with either the 4-step Wizard or SettingsHome. * * Headless callers (no TTY / CI / --plain / --non-interactive) get the * resolution back without any rendering so they can fall through to their * own plain-text flow. First-run headless is not implemented here — headless * callers print a "rerun in a terminal or use --plain" message and exit. */ export declare function runEntry(opts: RunEntryOpts): Promise; export {}; //# sourceMappingURL=entry.d.ts.map