@wolfstar/cli 0.6.1 → 0.7.0-next-20260918190835

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.
Files changed (36) hide show
  1. package/README.md +9 -0
  2. package/dist/{build-B0DNtlI8.js → build-BouwhG0y.js} +2 -2
  3. package/dist/{build-B0DNtlI8.js.map → build-BouwhG0y.js.map} +1 -1
  4. package/dist/{build-D4A4OlYR.js → build-CqVlp9y0.js} +2 -2
  5. package/dist/{build-D4A4OlYR.js.map → build-CqVlp9y0.js.map} +1 -1
  6. package/dist/cli.js +4 -4
  7. package/dist/{codegen-DHQH83M3.js → codegen-Do2h4Hl8.js} +2 -2
  8. package/dist/{codegen-DHQH83M3.js.map → codegen-Do2h4Hl8.js.map} +1 -1
  9. package/dist/{codegen-1kW_OnrL.js → codegen-y8gc147n.js} +2 -2
  10. package/dist/{codegen-1kW_OnrL.js.map → codegen-y8gc147n.js.map} +1 -1
  11. package/dist/{dev-CwJg6pSQ.js → dev-BgpW3Gsr.js} +9 -3
  12. package/dist/dev-BgpW3Gsr.js.map +1 -0
  13. package/dist/{dev-C-QKrdnz.js → dev-Dx9emKiU.js} +42 -8
  14. package/dist/dev-Dx9emKiU.js.map +1 -0
  15. package/dist/index.d.ts +42 -1
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +2 -1
  18. package/dist/{info-BrxKCcUW.js → info-Bvt1Jl88.js} +2 -2
  19. package/dist/{info-BrxKCcUW.js.map → info-Bvt1Jl88.js.map} +1 -1
  20. package/dist/{info-rYRLITnv.js → info-pX-M8R11.js} +2 -2
  21. package/dist/{info-rYRLITnv.js.map → info-pX-M8R11.js.map} +1 -1
  22. package/dist/{locales-DZCKWWcq.js → locales-C4_03V54.js} +2 -2
  23. package/dist/{locales-DZCKWWcq.js.map → locales-C4_03V54.js.map} +1 -1
  24. package/dist/theme-Bosd2Kk2.js +151 -0
  25. package/dist/theme-Bosd2Kk2.js.map +1 -0
  26. package/dist/tsc-D3FXjM6P.js +3 -0
  27. package/dist/{tsc-BTuFXw3O.js → tsc-D56BJ6lA.js} +8 -1
  28. package/dist/tsc-D56BJ6lA.js.map +1 -0
  29. package/dist/{tui-BCGQrMQo.js → tui-O94OH1w8.js} +151 -30
  30. package/dist/tui-O94OH1w8.js.map +1 -0
  31. package/package.json +2 -2
  32. package/dist/dev-C-QKrdnz.js.map +0 -1
  33. package/dist/dev-CwJg6pSQ.js.map +0 -1
  34. package/dist/tsc-BTuFXw3O.js.map +0 -1
  35. package/dist/tsc-Ba29w8eS.js +0 -3
  36. package/dist/tui-BCGQrMQo.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tui-O94OH1w8.js","names":[],"sources":["../src/renderers/ink/theme.tsx","../src/renderers/ink/components/HelpOverlay.tsx","../src/renderers/ink/hooks/useLogVersion.ts","../src/renderers/ink/components/Hints.tsx","../src/renderers/ink/components/LogBrowser.tsx","../src/renderers/ink/hooks/useDevStatus.ts","../src/renderers/ink/hooks/useUptime.ts","../src/renderers/panel-logic.ts","../src/renderers/ink/components/InfoOverlay.tsx","../src/renderers/ink/components/Panel.tsx","../src/renderers/ink/hooks/useLogCounters.ts","../src/renderers/ink/hooks/useBuildClock.ts","../src/lib/open-url.ts","../src/renderers/ink/components/ThemeOverlay.tsx","../src/renderers/ink/DevApp.tsx","../src/renderers/capture-output.ts","../src/renderers/tui.tsx"],"sourcesContent":["import { createContext, useContext, type ReactNode } from 'react';\nimport { THEMES, type ThemeName, type ThemeToken } from '../../lib/theme.js';\n\ninterface ThemeState {\n\t/** Whether the UI may use colour. */\n\tcolor: boolean;\n\ttheme: ThemeName;\n}\n\n/**\n * `stars dev` decides once whether the UI may use colour (`NO_COLOR`, `FORCE_COLOR`, TTY detection) and which theme\n * to paint with; every component reads both from here instead of re-deriving them.\n */\nconst ThemeContext = createContext<ThemeState>({ color: true, theme: 'dark' });\n\nexport function ThemeProvider({ color, theme, children }: ThemeState & { children: ReactNode }) {\n\treturn <ThemeContext value={{ color, theme }}>{children}</ThemeContext>;\n}\n\n/**\n * Returns a theme colour only when colour is enabled, so `<Text color={usePaint()('success')}>` degrades to plain text.\n */\nexport function usePaint(): (token: ThemeToken) => string | undefined {\n\tconst { color, theme } = useContext(ThemeContext);\n\treturn (token) => (color ? THEMES[theme][token] : undefined);\n}\n\nexport function useColorEnabled(): boolean {\n\treturn useContext(ThemeContext).color;\n}\n","import { Box, Text, useInput } from 'ink';\nimport { usePaint } from '../theme.js';\n\nconst KEYS: [string, string][] = [\n\t['r', 'restart the bot now'],\n\t['o', 'open the local URL in a browser'],\n\t['t', 'toggle the public tunnel'],\n\t['i', 'show versions, URLs and session info'],\n\t['T', 'pick a colour theme (dark, light, colour-blind friendly, ANSI)'],\n\t['l', 'open the logs (scroll, filter by source or level)'],\n\t['e', 'jump to the last error, keeping its context'],\n\t['c / Ctrl+L', 'clear the log history'],\n\t['q / Ctrl+C', 'stop the bot and quit'],\n\t['?', 'toggle this help']\n];\n\nexport interface HelpOverlayProps {\n\theight: number;\n\twidth: number;\n\tonClose: () => void;\n}\n\n/** The static keys reference, opened with `?` from the pinned panel. */\nexport function HelpOverlay({ height, width, onClose }: HelpOverlayProps) {\n\tconst paint = usePaint();\n\tuseInput((input, key) => {\n\t\tif (!key.ctrl && (key.escape || ['q', 'h', '?'].includes(input))) onClose();\n\t});\n\n\treturn (\n\t\t<Box flexDirection=\"column\" height={height}>\n\t\t\t<Text bold> keyboard shortcuts</Text>\n\t\t\t<Text dimColor>{'─'.repeat(width)}</Text>\n\t\t\t{KEYS.slice(0, Math.max(0, height - 3)).map(([key, description]) => (\n\t\t\t\t<Text key={key} wrap=\"truncate-end\">\n\t\t\t\t\t{' '}\n\t\t\t\t\t<Text bold color={paint('text')}>\n\t\t\t\t\t\t{key.padEnd(14)}\n\t\t\t\t\t</Text>\n\t\t\t\t\t<Text dimColor>{description}</Text>\n\t\t\t\t</Text>\n\t\t\t))}\n\t\t\t<Box flexGrow={1} />\n\t\t\t<Text dimColor> q close</Text>\n\t\t</Box>\n\t);\n}\n","import { useEffect, useState } from 'react';\nimport type { LogBuffer } from '../../../lib/log-buffer.js';\n\n/** Bumps whenever the buffer changes, so a consumer can re-derive a filtered view without re-filtering on every render. */\nexport function useLogVersion(logs: LogBuffer): number {\n\tconst [version, setVersion] = useState(0);\n\n\tuseEffect(() => {\n\t\tconst bump = () => setVersion((current) => current + 1);\n\t\tlogs.on('entry', bump);\n\t\tlogs.on('clear', bump);\n\t\tbump();\n\t\treturn () => {\n\t\t\tlogs.off('entry', bump);\n\t\t\tlogs.off('clear', bump);\n\t\t};\n\t}, [logs]);\n\n\treturn version;\n}\n","import { Text } from 'ink';\n\nexport interface Hint {\n\tkey: string;\n\tlabel: string;\n\tpriority: number;\n}\n\nexport const PANEL_HINTS: Hint[] = [\n\t{ key: 'r', label: 'restart', priority: 80 },\n\t{ key: 'o', label: 'open', priority: 40 },\n\t{ key: 't', label: 'tunnel', priority: 60 },\n\t{ key: 'i', label: 'info', priority: 50 },\n\t{ key: 'T', label: 'theme', priority: 30 },\n\t{ key: 'l', label: 'logs', priority: 70 },\n\t{ key: '?', label: 'help', priority: 100 },\n\t{ key: 'q', label: 'quit', priority: 90 }\n];\n\n/** Drop the lowest-priority shortcuts first; help and the last error survive narrow panes. */\nexport function Hints({ hints, width }: { hints: readonly Hint[]; width: number }) {\n\tconst shown = [...hints];\n\tconst length = () => shown.reduce((size, hint) => size + hint.key.length + hint.label.length + 4, -2);\n\twhile (shown.length > 1 && length() > width) {\n\t\tconst weakest = shown.reduce((a, b) => (a.priority <= b.priority ? a : b));\n\t\tshown.splice(shown.indexOf(weakest), 1);\n\t}\n\treturn (\n\t\t<Text wrap=\"truncate-end\">\n\t\t\t{' '}\n\t\t\t{shown.map(({ key, label }, i) => (\n\t\t\t\t<Text key={key}>\n\t\t\t\t\t{i > 0 && <Text dimColor> · </Text>}\n\t\t\t\t\t<Text bold>{key}</Text>\n\t\t\t\t\t<Text dimColor>{` ${label}`}</Text>\n\t\t\t\t</Text>\n\t\t\t))}\n\t\t</Text>\n\t);\n}\n","import { Box, Text, useInput } from 'ink';\nimport { useMemo, useState } from 'react';\nimport { stripVTControlCharacters } from 'node:util';\nimport type { DevService } from '../../../lib/dev-service.js';\nimport { isErrorDetail, type LogEntry, type LogLevel } from '../../../lib/log-buffer.js';\nimport { useLogVersion } from '../hooks/useLogVersion.js';\nimport { usePaint } from '../theme.js';\nimport { Hints } from './Hints.js';\n\nexport interface LogBrowserProps {\n\tservice: DevService;\n\theight: number;\n\twidth: number;\n\tlastError?: boolean;\n\tonClose: () => void;\n\tonCopy?: (text: string) => void;\n}\n\nconst group = (entry: LogEntry) => (entry.source === 'app' ? 'runtime' : entry.source === 'build' || entry.source === 'tsc' ? 'build' : 'cli');\n\n/** Filterable history, using Nuxt's keys and selecting the last error without discarding its context. */\nexport function LogBrowser({ service, height, width, lastError = false, onClose, onCopy }: LogBrowserProps) {\n\tconst paint = usePaint();\n\tconst [sources, setSources] = useState({ cli: true, build: true, runtime: true });\n\tconst [level, setLevel] = useState<LogLevel | null>(null);\n\tconst [query, setQuery] = useState('');\n\tconst [searching, setSearching] = useState(false);\n\tconst [selected, setSelected] = useState<number | null>(() =>\n\t\tlastError ? (service.logs.entries().findLast((entry) => entry.level === 'error' && !isErrorDetail(entry))?.id ?? null) : null\n\t);\n\tconst version = useLogVersion(service.logs);\n\tconst entries = useMemo(\n\t\t() =>\n\t\t\tservice.logs\n\t\t\t\t.filter({ level })\n\t\t\t\t.filter((entry) => sources[group(entry)] && stripVTControlCharacters(entry.text).toLowerCase().includes(query.toLowerCase())),\n\t\t[service, sources, level, query, version]\n\t);\n\tconst bodyHeight = Math.max(0, height - 3);\n\tconst index = entries.findIndex((entry) => entry.id === selected);\n\tconst rows = entries.flatMap((entry) =>\n\t\tstripVTControlCharacters(entry.text)\n\t\t\t.split('\\n')\n\t\t\t.map((line, i) => ({\n\t\t\t\tentry,\n\t\t\t\ttext: i === 0 ? `${new Date(entry.time).toLocaleTimeString()} ${entry.source.padEnd(6)} ${line}` : ` ${line}`\n\t\t\t}))\n\t);\n\tconst selectedStart = rows.findIndex((row) => row.entry.id === selected);\n\tconst selectedEnd = rows.findLastIndex((row) => row.entry.id === selected) + 1;\n\tconst end =\n\t\tindex < 0 ? rows.length : Math.min(rows.length, selectedStart + Math.max(bodyHeight, Math.min(selectedEnd - selectedStart, bodyHeight)));\n\tconst visible = rows.slice(Math.max(0, end - bodyHeight), end);\n\tconst move = (delta: number) => {\n\t\tif (!entries.length) return;\n\t\tconst next = index < 0 ? (delta < 0 ? entries.length - 1 : 0) : Math.max(0, Math.min(entries.length - 1, index + delta));\n\t\tsetSelected(entries[next]!.id);\n\t};\n\n\tuseInput((input, key) => {\n\t\tif (key.ctrl) return;\n\t\tif (searching) {\n\t\t\tif (key.escape) {\n\t\t\t\tsetSearching(false);\n\t\t\t\tsetQuery('');\n\t\t\t} else if (key.return) setSearching(false);\n\t\t\telse if (key.backspace || key.delete) setQuery((value) => [...value].slice(0, -1).join(''));\n\t\t\telse if (input && !key.upArrow && !key.downArrow) setQuery((value) => value + input);\n\t\t\tsetSelected(null);\n\t\t\treturn;\n\t\t}\n\t\tif (key.escape || input === 'l' || input === 'q') return onClose();\n\t\tif (input === '/') return setSearching(true);\n\t\tif (input === 'e' || input === 'w' || input === 'a') {\n\t\t\tconst next = input === 'e' ? 'error' : input === 'w' ? 'warn' : null;\n\t\t\tsetLevel((current) => (current === next ? null : next));\n\t\t\treturn setSelected(null);\n\t\t}\n\t\tif (input === 'c' || input === 'b' || input === 'r') {\n\t\t\tconst source = input === 'c' ? 'cli' : input === 'b' ? 'build' : 'runtime';\n\t\t\tsetSources((current) => {\n\t\t\t\tconst next = { ...current, [source]: !current[source] };\n\t\t\t\treturn Object.values(next).some(Boolean) ? next : current;\n\t\t\t});\n\t\t\treturn setSelected(null);\n\t\t}\n\t\tif (input === 'x') {\n\t\t\tservice.clearLogs();\n\t\t\treturn setSelected(null);\n\t\t}\n\t\tif (key.upArrow || input === 'k') return move(-1);\n\t\tif (key.downArrow || input === 'j') return move(1);\n\t\tif (key.pageUp) return move(-Math.max(1, bodyHeight));\n\t\tif (key.pageDown) return move(Math.max(1, bodyHeight));\n\t\tif (key.home || input === 'g') return setSelected(entries[0]?.id ?? null);\n\t\tif (key.end || input === 'G') return setSelected(null);\n\t\tif ((key.return || input === 'y') && index >= 0) onCopy?.(stripVTControlCharacters(entries[index]!.text));\n\t});\n\n\tconst hints = searching\n\t\t? [\n\t\t\t\t['enter', 'apply'],\n\t\t\t\t['esc', 'cancel']\n\t\t\t]\n\t\t: [\n\t\t\t\t['↑/↓', 'select'],\n\t\t\t\t['g/G', 'top/bottom'],\n\t\t\t\t['e', 'errors'],\n\t\t\t\t['w', 'warnings'],\n\t\t\t\t['a', 'all'],\n\t\t\t\t['c/b/r', 'sources'],\n\t\t\t\t['/', 'search'],\n\t\t\t\t['x', 'clear'],\n\t\t\t\t['enter', 'copy'],\n\t\t\t\t['q', 'close']\n\t\t\t];\n\treturn (\n\t\t<Box flexDirection=\"column\" height={height}>\n\t\t\t<Text wrap=\"truncate-end\">\n\t\t\t\t{' '}\n\t\t\t\t<Text bold>logs</Text>\n\t\t\t\t<Text dimColor>{` · ${Object.entries(sources)\n\t\t\t\t\t.filter(([, shown]) => shown)\n\t\t\t\t\t.map(([source]) => source)\n\t\t\t\t\t.join(\n\t\t\t\t\t\t'+'\n\t\t\t\t\t)} · ${level ? `${level}+ only` : 'all levels'}${query || searching ? ` · search ${query}${searching ? '▏' : ''}` : ''}`}</Text>\n\t\t\t</Text>\n\t\t\t<Text dimColor>{'─'.repeat(width)}</Text>\n\t\t\t<Box flexDirection=\"column\" height={bodyHeight} overflow=\"hidden\">\n\t\t\t\t{visible.length === 0 && <Text dimColor> no matching logs</Text>}\n\t\t\t\t{visible.map(({ entry, text }, i) => (\n\t\t\t\t\t<Text key={`${entry.id}-${i}`} wrap=\"truncate-end\">\n\t\t\t\t\t\t<Text color={paint('brand')}>{entry.id === selected ? '▎ ' : ' '}</Text>\n\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\tcolor={paint(\n\t\t\t\t\t\t\t\tentry.level === 'error'\n\t\t\t\t\t\t\t\t\t? 'error'\n\t\t\t\t\t\t\t\t\t: entry.level === 'warn'\n\t\t\t\t\t\t\t\t\t\t? 'warning'\n\t\t\t\t\t\t\t\t\t\t: entry.level === 'success'\n\t\t\t\t\t\t\t\t\t\t\t? 'success'\n\t\t\t\t\t\t\t\t\t\t\t: 'text'\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\tdimColor={isErrorDetail(entry)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{text}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t</Text>\n\t\t\t\t))}\n\t\t\t</Box>\n\t\t\t<Hints\n\t\t\t\twidth={width}\n\t\t\t\thints={hints.map(([key, label], i) => ({ key: key!, label: label!, priority: i === hints.length - 1 ? 100 : hints.length - i }))}\n\t\t\t/>\n\t\t</Box>\n\t);\n}\n","import { useEffect, useState } from 'react';\nimport type { DevService, DevStatus } from '../../../lib/dev-service.js';\n\n/**\n * Mirrors the service's status into React state. The service stays the single source of truth: the UI only\n * subscribes to it, exactly like the plain renderer does.\n */\nexport function useDevStatus(service: DevService): DevStatus {\n\tconst [status, setStatus] = useState<DevStatus>(() => service.status);\n\n\tuseEffect(() => {\n\t\tconst onStatus = (next: DevStatus) => setStatus(next);\n\t\tservice.on('status', onStatus);\n\t\tsetStatus(service.status);\n\t\treturn () => {\n\t\t\tservice.off('status', onStatus);\n\t\t};\n\t}, [service]);\n\n\treturn status;\n}\n","import { useEffect, useState } from 'react';\n\n/**\n * Re-renders once a second while the bot is up, so the uptime in the header keeps counting.\n */\nexport function useUptime(startedAt: number | null): number | null {\n\tconst [now, setNow] = useState(() => Date.now());\n\n\tuseEffect(() => {\n\t\tif (startedAt === null) return;\n\n\t\tsetNow(Date.now());\n\t\tconst timer = setInterval(() => setNow(Date.now()), 1000);\n\t\treturn () => clearInterval(timer);\n\t}, [startedAt]);\n\n\treturn startedAt === null ? null : now - startedAt;\n}\n","import type { DevStatus } from '../lib/dev-service.js';\n\nexport type Badge = 'starting' | 'building' | 'restarting' | 'ready' | 'error';\n\n/**\n * The badge and standing description for the panel's status row, mirroring the states Nuxt CLI v4's own dev panel\n * cycles through (`STARTING`/`BUILDING`/`RESTART`/`READY`/`ERROR`).\n */\nexport function describeBadge(status: DevStatus): { badge: Badge; note: string } {\n\tif (status.build === 'building') return { badge: status.startedAt === null ? 'starting' : 'building', note: status.progress.message };\n\tif (status.process === 'starting') return { badge: 'starting', note: 'starting the bot' };\n\tif (status.process === 'stopping') return { badge: 'restarting', note: 'restarting the bot' };\n\tif (status.build === 'failed') return { badge: 'error', note: 'build failed, waiting for changes' };\n\tif (status.process === 'crashed') return { badge: 'error', note: 'the bot crashed, press r to restart' };\n\tif (status.health === 'down') return { badge: 'error', note: 'health check failed' };\n\tif (status.typecheck === 'failed') return { badge: 'error', note: 'type check failed, press e to view it' };\n\tif (status.process === 'stopped') return { badge: 'error', note: 'the bot stopped, press r to restart' };\n\tif (status.progress.fraction < 1) return { badge: 'starting', note: status.progress.message };\n\tif (status.process === 'running') return { badge: 'ready', note: 'watching for changes' };\n\treturn { badge: 'starting', note: 'waiting for the first build' };\n}\n\n/** Formats a duration the way a dev session reads it: `mm:ss` under an hour, `h:mm:ss` above. */\nexport function formatDuration(milliseconds: number): string {\n\tconst total = Math.max(0, Math.floor(milliseconds / 1000));\n\tconst seconds = total % 60;\n\tconst minutes = Math.floor(total / 60) % 60;\n\tconst hours = Math.floor(total / 3600);\n\tconst pad = (value: number) => value.toString().padStart(2, '0');\n\n\treturn hours > 0 ? `${hours}:${pad(minutes)}:${pad(seconds)}` : `${pad(minutes)}:${pad(seconds)}`;\n}\n","import { Box, Text, useInput } from 'ink';\nimport type { DevService } from '../../../lib/dev-service.js';\nimport { useDevStatus } from '../hooks/useDevStatus.js';\nimport { useUptime } from '../hooks/useUptime.js';\nimport { formatDuration } from '../../panel-logic.js';\n\nexport function InfoOverlay({ service, height, width, onClose }: { service: DevService; height: number; width: number; onClose: () => void }) {\n\tconst status = useDevStatus(service);\n\tconst uptime = useUptime(status.startedAt);\n\tuseInput((input, key) => {\n\t\tif (!key.ctrl && (key.escape || ['q', 'i'].includes(input))) onClose();\n\t});\n\tconst lines = [\n\t\t['Project', service.config.packageJson?.name ?? 'stars project'],\n\t\t['Root', service.config.root],\n\t\t['Node', process.version],\n\t\t['Builder', service.builder.tool],\n\t\t['Local', status.url ?? '—'],\n\t\t['Tunnel', status.tunnelUrl ?? status.tunnel],\n\t\t['Process', `${status.process}${status.pid ? ` (${status.pid})` : ''}`],\n\t\t['Uptime', uptime === null ? '—' : formatDuration(uptime)],\n\t\t['Restarts', String(status.restarts)],\n\t\t['Health', service.config.dev.health ? status.health : 'not configured (READY reports process state)'],\n\t\t['Types', `${status.typecheck}${status.typeErrors ? ` (${status.typeErrors} errors)` : ''}`],\n\t\t['Log file', service.config.dev.logFile ?? 'disabled']\n\t];\n\treturn (\n\t\t<Box flexDirection=\"column\" height={height}>\n\t\t\t<Text bold wrap=\"truncate-end\">\n\t\t\t\t{' '}\n\t\t\t\tsession info\n\t\t\t</Text>\n\t\t\t<Text dimColor>{'─'.repeat(width)}</Text>\n\t\t\t{lines.slice(0, Math.max(0, height - 3)).map(([label, value]) => (\n\t\t\t\t<Text key={label} wrap=\"truncate-end\">\n\t\t\t\t\t{' '}\n\t\t\t\t\t<Text bold>{label!.padEnd(10)}</Text>\n\t\t\t\t\t<Text dimColor>{value}</Text>\n\t\t\t\t</Text>\n\t\t\t))}\n\t\t\t<Box flexGrow={1} />\n\t\t\t<Text dimColor> q close</Text>\n\t\t</Box>\n\t);\n}\n","import { Box, Text } from 'ink';\nimport type { ReactNode } from 'react';\nimport type { ResolvedStarsConfig } from '@wolfstar/http-framework/config';\nimport type { DevStatus } from '../../../lib/dev-service.js';\nimport { readOwnPackageJson } from '../../../lib/version.js';\nimport type { LogCounters } from '../hooks/useLogCounters.js';\nimport { describeBadge } from '../../panel-logic.js';\nimport { usePaint } from '../theme.js';\nimport { Hints, PANEL_HINTS } from './Hints.js';\n\nexport interface PanelProps {\n\tstatus: DevStatus;\n\tconfig: ResolvedStarsConfig;\n\tcounters: LogCounters;\n\tframe: number;\n\telapsedMs: number;\n\twidth: number;\n\theight: number;\n\tconfirmQuit: boolean;\n}\n\n/** Nuxt's wordmark / URLs / progress / status / hints layout, with Stars branding. */\nexport function Panel({ status, config, counters, frame, elapsedMs, width, height, confirmQuit }: PanelProps) {\n\tconst paint = usePaint();\n\tconst state = describeBadge(status);\n\tconst busy = state.badge !== 'ready' && state.badge !== 'error';\n\tconst badge = !busy && counters.errors > 0 ? 'error' : state.badge;\n\tconst note = badge === 'error' && state.badge === 'ready' ? 'an error was logged · press e to view it' : state.note;\n\tconst filled = Math.round(Math.min(1, Math.max(0, status.progress.fraction)) * 20);\n\tconst wordmark = config.dev.banner === false ? [] : (config.dev.banner?.flatMap((line) => line.split('\\n')) ?? [null]);\n\tconst blocks: { name: string; content: ReactNode }[] = [\n\t\t...wordmark.slice(0, 4).map((line, index) => ({\n\t\t\tname: 'wordmark',\n\t\t\tcontent: (\n\t\t\t\t<Box key={index} justifyContent=\"space-between\">\n\t\t\t\t\t<Text wrap=\"truncate-end\">\n\t\t\t\t\t\t{' '}\n\t\t\t\t\t\t{line === null ? (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<Text color={paint('brand')}>\n\t\t\t\t\t\t\t\t\t{[...'·✦★✦'].map((cell, i) => (\n\t\t\t\t\t\t\t\t\t\t<Text key={i} dimColor={busy && i !== frame % 4}>\n\t\t\t\t\t\t\t\t\t\t\t{cell}\n\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t{' '}\n\t\t\t\t\t\t\t\t<Text bold color={paint('brand')}>\n\t\t\t\t\t\t\t\t\tStars\n\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t<Text dimColor>{` ${readOwnPackageJson().version}`}</Text>\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<Text color={paint('brand')}>{line}</Text>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</Text>\n\t\t\t\t\t{index === 0 && width >= 60 && badge === 'ready' && status.progress.readyMs !== null && (\n\t\t\t\t\t\t<Text dimColor>{`ready in ${(status.progress.readyMs / 1000).toFixed(2)}s `}</Text>\n\t\t\t\t\t)}\n\t\t\t\t</Box>\n\t\t\t)\n\t\t})),\n\t\t{ name: 'space', content: <Text> </Text> },\n\t\t...(status.url\n\t\t\t? [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'urls',\n\t\t\t\t\t\tcontent: (\n\t\t\t\t\t\t\t<Text wrap=\"truncate-end\">\n\t\t\t\t\t\t\t\t{' '}\n\t\t\t\t\t\t\t\t<Text dimColor>{'Local '}</Text>\n\t\t\t\t\t\t\t\t<Text color={paint('url')} dimColor={busy}>\n\t\t\t\t\t\t\t\t\t{status.url}\n\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t{busy && <Text color={paint('busy')}>{` ${['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'][frame % 10]}`}</Text>}\n\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t: []),\n\t\t...(status.tunnelUrl\n\t\t\t? [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'urls',\n\t\t\t\t\t\tcontent: (\n\t\t\t\t\t\t\t<Text wrap=\"truncate-end\">\n\t\t\t\t\t\t\t\t{' '}\n\t\t\t\t\t\t\t\t<Text dimColor>{'Tunnel '}</Text>\n\t\t\t\t\t\t\t\t<Text color={paint('tunnel')}>{status.tunnelUrl}</Text>\n\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t: []),\n\t\t{ name: 'space', content: <Text> </Text> },\n\t\t{\n\t\t\tname: 'summary',\n\t\t\tcontent: busy ? (\n\t\t\t\t<Text wrap=\"truncate-end\">\n\t\t\t\t\t{' '}\n\t\t\t\t\t<Text color={paint('brand')}>{'━'.repeat(filled)}</Text>\n\t\t\t\t\t<Text dimColor>\n\t\t\t\t\t\t{'━'.repeat(20 - filled)}\n\t\t\t\t\t\t{` ${Math.round(status.progress.fraction * 100)}% · ${(elapsedMs / 1000).toFixed(1)}s`}\n\t\t\t\t\t</Text>\n\t\t\t\t</Text>\n\t\t\t) : (\n\t\t\t\t<Text wrap=\"truncate-end\">\n\t\t\t\t\t{' '}\n\t\t\t\t\t{counters.warnings > 0 && (\n\t\t\t\t\t\t<Text color={paint('warning')}>{`⚠ ${counters.warnings} ${plural(counters.warnings, 'warning')} `}</Text>\n\t\t\t\t\t)}\n\t\t\t\t\t{counters.errors > 0 && <Text bold color={paint('error')}>{`✖ ${counters.errors} ${plural(counters.errors, 'error')} `}</Text>}\n\t\t\t\t\t{counters.errors === 0 && counters.warnings === 0 && (\n\t\t\t\t\t\t<Text dimColor>\n\t\t\t\t\t\t\t{status.typecheck === 'checking'\n\t\t\t\t\t\t\t\t? 'checking types'\n\t\t\t\t\t\t\t\t: status.tunnel === 'failed'\n\t\t\t\t\t\t\t\t\t? 'tunnel failed · press l to view logs'\n\t\t\t\t\t\t\t\t\t: 'logs folded away · press l to view'}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t)}\n\t\t\t\t</Text>\n\t\t\t)\n\t\t},\n\t\t{ name: 'space', content: <Text> </Text> },\n\t\t{\n\t\t\tname: 'status',\n\t\t\tcontent: (\n\t\t\t\t<Text wrap=\"truncate-end\">\n\t\t\t\t\t{' '}\n\t\t\t\t\t<Text\n\t\t\t\t\t\tbold\n\t\t\t\t\t\tbackgroundColor={paint(confirmQuit || busy ? 'busy' : badge === 'error' ? 'error' : 'success')}\n\t\t\t\t\t\tcolor={paint(badge === 'error' && !confirmQuit ? 'onError' : 'onBright')}\n\t\t\t\t\t>{` ${confirmQuit ? 'QUIT?' : badge === 'restarting' ? 'RESTART' : badge.toUpperCase()} `}</Text>\n\t\t\t\t\t{' '}\n\t\t\t\t\t<Text dimColor>{confirmQuit ? 'press y to confirm, esc to stay' : note}</Text>\n\t\t\t\t</Text>\n\t\t\t)\n\t\t},\n\t\t{\n\t\t\tname: 'hints',\n\t\t\tcontent: confirmQuit ? (\n\t\t\t\t<Text> </Text>\n\t\t\t) : (\n\t\t\t\t<Hints width={width} hints={[...(counters.errors ? [{ key: 'e', label: 'last error', priority: Infinity }] : []), ...PANEL_HINTS]} />\n\t\t\t)\n\t\t}\n\t];\n\tlet shown = blocks;\n\tconst budget = Math.max(2, Math.min(height, 14));\n\tfor (const name of ['space', 'summary', 'urls', 'wordmark']) {\n\t\tif (shown.length <= budget) break;\n\t\tshown = shown.filter((block) => block.name !== name);\n\t}\n\tshown = shown.filter((block, i, all) => block.name !== 'space' || (i > 0 && i < all.length - 1 && all[i - 1]?.name !== 'space'));\n\treturn (\n\t\t<Box flexDirection=\"column\">\n\t\t\t{shown.map((block, index) => (\n\t\t\t\t<Box key={index} flexDirection=\"column\" height={1}>\n\t\t\t\t\t{block.content}\n\t\t\t\t</Box>\n\t\t\t))}\n\t\t</Box>\n\t);\n}\n\nfunction plural(count: number, word: string): string {\n\treturn count === 1 ? word : `${word}s`;\n}\n","import { useEffect, useState } from 'react';\nimport type { DevService, DevStatus } from '../../../lib/dev-service.js';\nimport { isErrorDetail, type LogEntry } from '../../../lib/log-buffer.js';\n\nexport interface LogCounters {\n\twarnings: number;\n\terrors: number;\n}\n\n/**\n * Warnings and errors logged since the last successful build, the way Nuxt CLI v4's own panel counts them: the\n * badge's job is the current state, this line is what happened getting there.\n */\nexport function useLogCounters(service: DevService): LogCounters {\n\tconst count = () =>\n\t\tservice.logs.entries().reduce<LogCounters>(\n\t\t\t(total, entry) => ({\n\t\t\t\twarnings: total.warnings + Number(entry.level === 'warn'),\n\t\t\t\terrors: total.errors + Number(entry.level === 'error' && !isErrorDetail(entry))\n\t\t\t}),\n\t\t\t{ warnings: 0, errors: 0 }\n\t\t);\n\tconst [counters, setCounters] = useState<LogCounters>(count);\n\n\tuseEffect(() => {\n\t\tlet previousBuild: DevStatus['build'] = service.status.build;\n\t\tlet previousStart = service.status.startedAt;\n\n\t\tconst onEntry = (entry: LogEntry) => {\n\t\t\tif (entry.level === 'warn') setCounters((current) => ({ ...current, warnings: current.warnings + 1 }));\n\t\t\telse if (entry.level === 'error' && !isErrorDetail(entry)) setCounters((current) => ({ ...current, errors: current.errors + 1 }));\n\t\t};\n\n\t\tconst onStatus = (status: DevStatus) => {\n\t\t\tif (\n\t\t\t\t(status.build === 'building' && previousBuild !== 'building' && previousBuild !== 'idle') ||\n\t\t\t\t(status.lastRestartReason === 'manual' && status.startedAt !== null && status.startedAt !== previousStart)\n\t\t\t)\n\t\t\t\tsetCounters({ warnings: 0, errors: 0 });\n\t\t\tpreviousBuild = status.build;\n\t\t\tpreviousStart = status.startedAt;\n\t\t};\n\n\t\tservice.logs.on('entry', onEntry);\n\t\tconst onClear = () => setCounters({ warnings: 0, errors: 0 });\n\t\tservice.logs.on('clear', onClear);\n\t\tservice.on('status', onStatus);\n\t\tsetCounters(count());\n\t\treturn () => {\n\t\t\tservice.logs.off('entry', onEntry);\n\t\t\tservice.logs.off('clear', onClear);\n\t\t\tservice.off('status', onStatus);\n\t\t};\n\t}, [service]);\n\n\treturn counters;\n}\n","import { useEffect, useState } from 'react';\n\n/** The clock moves during a long compiler phase; the percentage only moves on real build events. */\nexport function useBuildClock(startedAt: number, active: boolean, reducedMotion: boolean) {\n\tconst [now, setNow] = useState(Date.now);\n\tuseEffect(() => {\n\t\tif (!active) return;\n\t\tsetNow(Date.now());\n\t\tconst timer = setInterval(() => setNow(Date.now()), reducedMotion ? 1000 : 120);\n\t\treturn () => clearInterval(timer);\n\t}, [startedAt, active, reducedMotion]);\n\tconst elapsedMs = Math.max(0, now - startedAt);\n\treturn { elapsedMs, frame: reducedMotion ? 0 : Math.floor(elapsedMs / 120) };\n}\n","import { execFile } from 'node:child_process';\n\n/** Called only on an explicit `o` keypress, with no shell interpolation. */\nexport function openDevUrl(value: string | null): Promise<void> {\n\tif (!value) return Promise.resolve();\n\tconst url = new URL(value);\n\tif (url.protocol !== 'http:' && url.protocol !== 'https:') return Promise.reject(new Error('Only HTTP(S) URLs can be opened.'));\n\tconst [command, args] =\n\t\tprocess.platform === 'win32'\n\t\t\t? (['rundll32', ['url.dll,FileProtocolHandler', url.href]] as const)\n\t\t\t: process.platform === 'darwin'\n\t\t\t\t? (['open', [url.href]] as const)\n\t\t\t\t: (['xdg-open', [url.href]] as const);\n\treturn new Promise((resolve, reject) =>\n\t\texecFile(command, [...args], (error) => (error ? reject(new Error(`Could not open the browser: ${error.message}`)) : resolve()))\n\t);\n}\n","import { Box, Text, useInput } from 'ink';\nimport { useState } from 'react';\nimport { THEME_SETTINGS, THEMES, detectTerminalBackground, type ThemeSetting } from '../../../lib/theme.js';\nimport { useColorEnabled } from '../theme.js';\n\nconst DESCRIPTIONS: Record<ThemeSetting, string> = {\n\tauto: 'match the terminal background',\n\tdark: 'for dark terminals',\n\tlight: 'for light terminals',\n\t'dark-daltonized': 'dark, colour-blind friendly (blue/orange)',\n\t'light-daltonized': 'light, colour-blind friendly (blue/orange)',\n\t'dark-ansi': 'dark, only your terminal palette',\n\t'light-ansi': 'light, only your terminal palette'\n};\n\nexport interface ThemeOverlayProps {\n\t/** The theme setting in effect when the picker opened. */\n\tcurrent: ThemeSetting;\n\theight: number;\n\twidth: number;\n\t/** Called while moving through the list, so the whole UI previews the highlighted theme. */\n\tonPreview: (setting: ThemeSetting) => void;\n\tonSelect: (setting: ThemeSetting) => void;\n\t/** Closes without saving; the caller restores the theme that was in effect. */\n\tonClose: () => void;\n}\n\n/** Like Claude Code's `/theme`: arrows preview live, `Enter` keeps the choice and saves it, `Esc` restores. */\nexport function ThemeOverlay({ current, height, width, onPreview, onSelect, onClose }: ThemeOverlayProps) {\n\tconst color = useColorEnabled();\n\tconst [index, setIndex] = useState(Math.max(0, THEME_SETTINGS.indexOf(current)));\n\n\tconst move = (delta: number) => {\n\t\tconst next = (index + delta + THEME_SETTINGS.length) % THEME_SETTINGS.length;\n\t\tsetIndex(next);\n\t\tonPreview(THEME_SETTINGS[next]!);\n\t};\n\n\tuseInput((input, key) => {\n\t\tif (key.ctrl) return;\n\t\tif (key.escape || input === 'q' || input === 'T') return onClose();\n\t\tif (key.return) return onSelect(THEME_SETTINGS[index]!);\n\t\tif (key.upArrow || input === 'k') return move(-1);\n\t\tif (key.downArrow || input === 'j') return move(1);\n\t});\n\n\treturn (\n\t\t<Box flexDirection=\"column\" height={height}>\n\t\t\t<Text bold> colour theme</Text>\n\t\t\t<Text dimColor>{'─'.repeat(width)}</Text>\n\t\t\t{THEME_SETTINGS.slice(0, Math.max(0, height - 3)).map((setting, i) => {\n\t\t\t\tconst swatch = THEMES[setting === 'auto' ? detectTerminalBackground() : setting];\n\t\t\t\treturn (\n\t\t\t\t\t<Text key={setting} wrap=\"truncate-end\">\n\t\t\t\t\t\t{i === index ? ' ▎ ' : ' '}\n\t\t\t\t\t\t<Text bold={i === index}>{setting.padEnd(18)}</Text>\n\t\t\t\t\t\t{color && (\n\t\t\t\t\t\t\t<Text>\n\t\t\t\t\t\t\t\t<Text color={swatch.success}>● </Text>\n\t\t\t\t\t\t\t\t<Text color={swatch.warning}>● </Text>\n\t\t\t\t\t\t\t\t<Text color={swatch.error}>● </Text>\n\t\t\t\t\t\t\t\t<Text color={swatch.url}>● </Text>\n\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t)}\n\t\t\t\t\t\t<Text dimColor>{` ${DESCRIPTIONS[setting]}${setting === current ? ' (current)' : ''}`}</Text>\n\t\t\t\t\t</Text>\n\t\t\t\t);\n\t\t\t})}\n\t\t\t<Box flexGrow={1} />\n\t\t\t<Text dimColor> ↑/↓ preview · enter save · esc cancel</Text>\n\t\t</Box>\n\t);\n}\n","import { Box, useInput, useWindowSize } from 'ink';\nimport { useState } from 'react';\nimport type { DevService } from '../../lib/dev-service.js';\nimport { HelpOverlay } from './components/HelpOverlay.js';\nimport { LogBrowser } from './components/LogBrowser.js';\nimport { InfoOverlay } from './components/InfoOverlay.js';\nimport { Panel } from './components/Panel.js';\nimport { useDevStatus } from './hooks/useDevStatus.js';\nimport { useLogCounters } from './hooks/useLogCounters.js';\nimport { useBuildClock } from './hooks/useBuildClock.js';\nimport { describeBadge } from '../panel-logic.js';\nimport { openDevUrl } from '../../lib/open-url.js';\nimport { ThemeProvider } from './theme.js';\nimport { ThemeOverlay } from './components/ThemeOverlay.js';\nimport { resolveTheme, type ThemeSetting } from '../../lib/theme.js';\n\nexport interface DevAppProps {\n\tservice: DevService;\n\tcolor: boolean;\n\t/** The theme setting to start with; `auto` follows the terminal background. */\n\ttheme: ThemeSetting;\n\treducedMotion: boolean;\n\t/** Called when the user asks to quit, so the CLI can stop the bot and exit. */\n\tonQuit: () => void;\n\tonViewChange: (overlay: boolean) => void;\n\tonCopy: (text: string) => void;\n\t/** Called when the user keeps a theme in the picker, so the CLI can remember it. */\n\tonThemeSave: (setting: ThemeSetting) => void;\n}\n\ntype View = 'panel' | 'logs' | 'errors' | 'help' | 'info' | 'theme';\n\n/**\n * A bottom-aligned panel in the normal buffer, with logs folded away. Only the browsable overlays use the\n * alternate screen, preserving the terminal's history and the panel when they close.\n */\nexport function DevApp({ service, color, theme, reducedMotion, onQuit, onViewChange, onCopy, onThemeSave }: DevAppProps) {\n\tconst { columns, rows } = useWindowSize();\n\tconst [view, setView] = useState<View>('panel');\n\tconst [confirmQuit, setConfirmQuit] = useState(false);\n\t// `saved` is what Esc restores after previewing other themes in the picker.\n\tconst [saved, setSaved] = useState(theme);\n\tconst [preview, setPreview] = useState(theme);\n\n\tconst status = useDevStatus(service);\n\tconst counters = useLogCounters(service);\n\tconst badge = describeBadge(status).badge;\n\tconst busy = badge !== 'ready' && badge !== 'error';\n\tconst clock = useBuildClock(status.progress.startedAt, busy && view === 'panel', reducedMotion);\n\n\tconst width = Math.max(1, columns);\n\tconst height = Math.max(2, rows - 1);\n\n\tconst changeView = (next: View) => {\n\t\tonViewChange(next !== 'panel');\n\t\tsetView(next);\n\t};\n\n\tuseInput((input, key) => {\n\t\tif (key.ctrl && input === 'c') return onQuit();\n\t\tif (key.ctrl && input === 'l') return service.clearLogs();\n\t\tif (view !== 'panel') return;\n\t\tif (confirmQuit) {\n\t\t\tif (input === 'y') return onQuit();\n\t\t\treturn setConfirmQuit(false);\n\t\t}\n\t\tif (key.ctrl && input === 'r') return void service.restart('manual');\n\t\tif (key.ctrl && input === 'd') return busy ? setConfirmQuit(true) : onQuit();\n\n\t\tswitch (input) {\n\t\t\tcase 'q':\n\t\t\t\treturn busy ? setConfirmQuit(true) : onQuit();\n\t\t\tcase 'r':\n\t\t\t\treturn void service.restart('manual');\n\t\t\tcase 'l':\n\t\t\t\treturn changeView('logs');\n\t\t\tcase 'e':\n\t\t\t\treturn changeView('errors');\n\t\t\tcase 'c':\n\t\t\t\treturn service.clearLogs();\n\t\t\tcase 'o':\n\t\t\t\treturn void openDevUrl(status.url).catch((error: Error) => service.log('stars', 'warn', error.message));\n\t\t\tcase 't':\n\t\t\t\treturn void service.toggleTunnel();\n\t\t\tcase 'i':\n\t\t\t\treturn changeView('info');\n\t\t\tcase 'T':\n\t\t\t\treturn changeView('theme');\n\t\t\tcase 'h':\n\t\t\tcase '?':\n\t\t\t\treturn changeView('help');\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t});\n\n\treturn (\n\t\t<ThemeProvider color={color} theme={resolveTheme(preview)}>\n\t\t\t<Box width={width} height={height} flexDirection=\"column\" justifyContent={view === 'panel' ? 'flex-end' : 'flex-start'}>\n\t\t\t\t{(view === 'logs' || view === 'errors') && (\n\t\t\t\t\t<LogBrowser\n\t\t\t\t\t\tservice={service}\n\t\t\t\t\t\theight={height}\n\t\t\t\t\t\twidth={width}\n\t\t\t\t\t\tlastError={view === 'errors'}\n\t\t\t\t\t\tonCopy={onCopy}\n\t\t\t\t\t\tonClose={() => changeView('panel')}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t\t{view === 'help' && <HelpOverlay height={height} width={width} onClose={() => changeView('panel')} />}\n\t\t\t\t{view === 'info' && <InfoOverlay service={service} height={height} width={width} onClose={() => changeView('panel')} />}\n\t\t\t\t{view === 'theme' && (\n\t\t\t\t\t<ThemeOverlay\n\t\t\t\t\t\tcurrent={saved}\n\t\t\t\t\t\theight={height}\n\t\t\t\t\t\twidth={width}\n\t\t\t\t\t\tonPreview={setPreview}\n\t\t\t\t\t\tonSelect={(setting) => {\n\t\t\t\t\t\t\tsetSaved(setting);\n\t\t\t\t\t\t\tsetPreview(setting);\n\t\t\t\t\t\t\tonThemeSave(setting);\n\t\t\t\t\t\t\tchangeView('panel');\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tonClose={() => {\n\t\t\t\t\t\t\tsetPreview(saved);\n\t\t\t\t\t\t\tchangeView('panel');\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t\t{view === 'panel' && (\n\t\t\t\t\t<Panel\n\t\t\t\t\t\tstatus={status}\n\t\t\t\t\t\tconfig={service.config}\n\t\t\t\t\t\tcounters={counters}\n\t\t\t\t\t\t{...clock}\n\t\t\t\t\t\twidth={width}\n\t\t\t\t\t\theight={height}\n\t\t\t\t\t\tconfirmQuit={confirmQuit}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</Box>\n\t\t</ThemeProvider>\n\t);\n}\n","import { StringDecoder } from 'node:string_decoder';\nimport type { DevService } from '../lib/dev-service.js';\nimport { classifyAppLine, type LogLevel } from '../lib/log-buffer.js';\n\n/** Capture third-party writes before build plugins run. Ink writes through a separate, unpatched sink. */\nexport function captureOutput(service: DevService, stream: NodeJS.WriteStream, fallback: LogLevel): () => void {\n\tconst original = stream.write;\n\tconst decoder = new StringDecoder('utf8');\n\tlet pending = '';\n\tconst emit = (text: string) => {\n\t\tif (text.trim()) service.log('build', classifyAppLine(text, fallback), text);\n\t};\n\tconst write: typeof stream.write = (chunk: unknown, encoding?: unknown, callback?: unknown) => {\n\t\tpending += typeof chunk === 'string' ? chunk : chunk instanceof Uint8Array ? decoder.write(Buffer.from(chunk)) : String(chunk);\n\t\tconst lines = pending.split(/\\r?\\n/);\n\t\tpending = lines.pop() ?? '';\n\t\tfor (const line of lines) emit(line);\n\t\t// A tool without newlines must not grow the capture indefinitely.\n\t\tif (pending.length > 65536) {\n\t\t\temit(pending);\n\t\t\tpending = '';\n\t\t}\n\t\tconst done = typeof encoding === 'function' ? encoding : callback;\n\t\tif (typeof done === 'function') queueMicrotask(() => done());\n\t\treturn true;\n\t};\n\tstream.write = write;\n\treturn () => {\n\t\tif (stream.write === write) stream.write = original;\n\t\temit(pending + decoder.end());\n\t\tpending = '';\n\t};\n}\n","import { render } from 'ink';\nimport type { DevService } from '../lib/dev-service.js';\nimport { DevApp } from './ink/DevApp.js';\nimport type { Renderer } from './plain.js';\nimport { captureOutput } from './capture-output.js';\nimport { isErrorDetail } from '../lib/log-buffer.js';\nimport type { ThemeSetting } from '../lib/theme.js';\n\nexport interface TuiRendererOptions {\n\tstdout?: NodeJS.WriteStream;\n\tstdin?: NodeJS.ReadStream;\n\tcolor?: boolean;\n\t/** Defaults to `auto`. */\n\ttheme?: ThemeSetting;\n\t/** Called when the user keeps a theme in the picker. */\n\tonThemeSave?: (setting: ThemeSetting) => void;\n\t/** Freezes spinners, for `STARS_REDUCED_MOTION=1`. */\n\treducedMotion?: boolean;\n\t/** Caps how often Ink repaints; the default is Ink's own. */\n\tfps?: number;\n}\n\n/**\n * A normal-buffer, bottom-aligned panel and alternate-buffer overlays. External output is captured for the log\n * browser; the renderer alone writes to the terminal. Switching views and teardown restore the original buffer.\n *\n * `start()` resolves when the user quits, which is what `stars dev` waits on before shutting the bot down.\n */\nexport function createTuiRenderer(service: DevService, options: TuiRendererOptions = {}): Renderer {\n\tconst stdout = options.stdout ?? process.stdout;\n\tconst stdin = options.stdin ?? process.stdin;\n\tconst write = stdout.write.bind(stdout);\n\t// Bind methods to the real stream (resize subscriptions included), except write which bypasses capture.\n\tconst sink = new Proxy(stdout, {\n\t\tget(target, property) {\n\t\t\tif (property === 'write') return write;\n\t\t\tconst value = Reflect.get(target, property, target);\n\t\t\treturn typeof value === 'function' ? value.bind(target) : value;\n\t\t}\n\t});\n\tconst restoreOutput =\n\t\tstdout === process.stdout ? [captureOutput(service, process.stdout, 'info'), captureOutput(service, process.stderr, 'warn')] : [];\n\tlet alternate = false;\n\tlet stopped = false;\n\tconst switchView = (overlay: boolean) => {\n\t\tif (overlay === alternate || stopped) return;\n\t\tinstance.clear();\n\t\twrite(overlay ? '\\u001B[?1049h\\u001B[H' : '\\u001B[?1049l');\n\t\talternate = overlay;\n\t};\n\n\tlet quit!: () => void;\n\tconst quitting = new Promise<void>((resolve) => {\n\t\tquit = resolve;\n\t});\n\n\tconst instance = render(\n\t\t<DevApp\n\t\t\tservice={service}\n\t\t\tcolor={options.color ?? false}\n\t\t\ttheme={options.theme ?? 'auto'}\n\t\t\tonThemeSave={options.onThemeSave ?? (() => {})}\n\t\t\treducedMotion={options.reducedMotion ?? false}\n\t\t\tonQuit={quit}\n\t\t\tonViewChange={switchView}\n\t\t\tonCopy={(text) => write(`\\u001B]52;c;${Buffer.from(text.slice(0, 65536)).toString('base64')}\\u0007`)}\n\t\t/>,\n\t\t{\n\t\t\tstdout: sink,\n\t\t\tstdin,\n\t\t\t// `stars dev` owns the shutdown: it stops the bot, then exits with the right code.\n\t\t\texitOnCtrlC: false,\n\t\t\tpatchConsole: false,\n\t\t\t// `createTuiRenderer` only runs once `resolveOutputMode()` already picked 'tui' (never in CI or on a\n\t\t\t// non-TTY stdout), so Ink is told to trust that instead of re-deriving it from `process.env.CI`: on a\n\t\t\t// CI runner that env var is set even for this package's own test process, which would otherwise force\n\t\t\t// Ink's non-interactive mode (no repaint until unmount) despite the fake stdin/stdout looking like a\n\t\t\t// real TTY.\n\t\t\tinteractive: true,\n\t\t\t...(options.fps === undefined ? {} : { maxFps: options.fps })\n\t\t}\n\t);\n\n\treturn {\n\t\tasync start() {\n\t\t\tawait Promise.race([quitting, instance.waitUntilExit()]);\n\t\t},\n\t\tstop() {\n\t\t\tif (stopped) return;\n\t\t\tstopped = true;\n\t\t\tif (alternate) instance.clear();\n\t\t\tinstance.unmount();\n\t\t\tif (alternate) write('\\u001B[?1049l');\n\t\t\twrite('\\u001B[?25h');\n\t\t\tfor (const restore of restoreOutput) restore();\n\t\t\t// A fatal startup must not leave the user with only a folded error and no way to read it.\n\t\t\tif (service.status.progress.readyMs === null) {\n\t\t\t\tconst error = service.logs.entries().findLast((entry) => entry.level === 'error' && !isErrorDetail(entry));\n\t\t\t\tif (error) write(`\\n${error.text}\\n`);\n\t\t\t}\n\t\t\tquit();\n\t\t}\n\t};\n}\n\nexport { formatDuration } from './panel-logic.js';\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wolfstar/cli",
3
- "version": "0.6.1",
3
+ "version": "0.7.0-next-20260918190835",
4
4
  "description": "The stars command line interface for @wolfstar/http-framework projects: typed configuration, dev server, build and project info",
5
5
  "keywords": [
6
6
  "api",
@@ -51,7 +51,7 @@
51
51
  "dependencies": {
52
52
  "@clack/prompts": "^1.8.0",
53
53
  "@sapphire/ts-config": "^5.0.3",
54
- "@wolfstar/http-framework": "^4.0.1",
54
+ "@wolfstar/http-framework": "^4.0.2",
55
55
  "chokidar": "^5.0.0",
56
56
  "citty": "^0.2.2",
57
57
  "colorette": "^2.0.20",
@@ -1 +0,0 @@
1
- {"version":3,"file":"dev-C-QKrdnz.js","names":[],"sources":["../src/lib/typechecker.ts","../src/lib/dev-service.ts","../src/lib/host.ts","../src/lib/log-file.ts","../src/lib/tasks/dev.ts"],"sourcesContent":["import type { ResolvedStarsConfig, StarsTypechecker } from '@wolfstar/http-framework/config';\nimport { spawn, type ChildProcess } from 'node:child_process';\nimport { EventEmitter } from 'node:events';\nimport { resolveTscBinary } from './builders/tsc.js';\nimport { CliError } from './errors.js';\nimport type { LogLevel } from './log-buffer.js';\nimport { createLineSplitter } from './process-supervisor.js';\nimport { resolveBinary } from './project.js';\n\nconst WATCH_START = /Starting (incremental )?compilation/;\nconst WATCH_DONE = /Found (\\d+) errors?\\. Watching for file changes/;\nconst ONE_SHOT_DONE = /Found (\\d+) errors?/;\nconst ERROR_LINE = /error TS\\d+:/;\n\nexport type TypecheckState = 'idle' | 'checking' | 'ok' | 'failed';\n\nexport interface TypecheckerEvents {\n\tlog: [level: LogLevel, text: string];\n\tstate: [state: TypecheckState, errors: number];\n}\n\nexport interface TypecheckCommand {\n\t/** The executable, and whether it is a script `node` has to run. */\n\treadonly command: string;\n\treadonly args: readonly string[];\n\treadonly node: boolean;\n\t/** Whether the checker watches the project itself, or has to be re-run after every build. */\n\treadonly watch: boolean;\n}\n\n/**\n * Runs a type checker next to the bot and reports type errors on their own channel, without ever blocking builds or\n * restarts: `stars dev` keeps running whatever the build tool produced, the way Seedcord's `hmr.typecheck` and\n * Vite's `checker` plugin do.\n *\n * `tsc` and `golar` (which forwards to TypeScript) watch the project themselves; `tsz` has no watch mode, so\n * {@link Typechecker.check} re-runs it after every build instead.\n */\nexport class Typechecker extends EventEmitter<TypecheckerEvents> {\n\t#child: ChildProcess | null = null;\n\t#state: TypecheckState = 'idle';\n\t#errors = 0;\n\t#pending = false;\n\n\tpublic constructor(private readonly config: ResolvedStarsConfig) {\n\t\tsuper();\n\t}\n\n\tpublic get state(): TypecheckState {\n\t\treturn this.#state;\n\t}\n\n\tpublic get errors(): number {\n\t\treturn this.#errors;\n\t}\n\n\t/** Whether the checker re-runs per build instead of watching on its own. */\n\tpublic get oneShot(): boolean {\n\t\treturn this.config.dev.typecheck.enabled && !resolveTypecheckCommand(this.config).watch;\n\t}\n\n\tpublic start(): void {\n\t\tif (!this.config.dev.typecheck.enabled) return;\n\t\tthis.#run();\n\t}\n\n\t/**\n\t * Re-runs a checker that cannot watch. Called after every successful build; a run already in flight is replaced,\n\t * so a fast series of builds only leaves the last check standing.\n\t */\n\tpublic check(): void {\n\t\tif (!this.oneShot) return;\n\t\tif (this.#child) {\n\t\t\tthis.#pending = true;\n\t\t\tthis.#child.kill();\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#run();\n\t}\n\n\tpublic close(): Promise<void> {\n\t\tconst child = this.#child;\n\t\tthis.#child = null;\n\t\tthis.#pending = false;\n\t\tif (!child || child.exitCode !== null) return Promise.resolve();\n\n\t\treturn new Promise((resolve) => {\n\t\t\tchild.once('exit', () => resolve());\n\t\t\tchild.kill();\n\t\t});\n\t}\n\n\t#run(): void {\n\t\tconst { command, args, node, watch } = resolveTypecheckCommand(this.config);\n\t\tconst child = spawn(node ? process.execPath : command, node ? [command, ...args] : [...args], {\n\t\t\tcwd: this.config.root,\n\t\t\tenv: process.env,\n\t\t\tstdio: ['ignore', 'pipe', 'pipe'],\n\t\t\twindowsHide: true\n\t\t});\n\t\tthis.#child = child;\n\t\tthis.#setState('checking', 0);\n\n\t\tlet errors = 0;\n\t\tconst handleLine = (line: string) => {\n\t\t\tif (ERROR_LINE.test(line)) errors++;\n\t\t\tthis.#handleLine(line);\n\t\t};\n\n\t\tconst stdout = createLineSplitter(handleLine);\n\t\tconst stderr = createLineSplitter(handleLine);\n\t\tchild.stdout?.on('data', stdout.push);\n\t\tchild.stderr?.on('data', stderr.push);\n\n\t\tchild.once('exit', (code) => {\n\t\t\tstdout.flush();\n\t\t\tstderr.flush();\n\t\t\tthis.#child = null;\n\n\t\t\tif (!watch && this.#state === 'checking') {\n\t\t\t\t// A one-shot checker only reports through its exit code when it prints no summary line.\n\t\t\t\tthis.#setState(code === 0 && errors === 0 ? 'ok' : 'failed', errors);\n\t\t\t}\n\n\t\t\tif (this.#pending) {\n\t\t\t\tthis.#pending = false;\n\t\t\t\tthis.#run();\n\t\t\t}\n\t\t});\n\t\tchild.once('error', (error: NodeJS.ErrnoException) => {\n\t\t\tthis.#child = null;\n\t\t\tthis.emit('log', 'error', error.code === 'ENOENT' ? `${command} is not installed` : error.message);\n\t\t\tthis.#setState('failed', this.#errors);\n\t\t});\n\t}\n\n\t#handleLine(line: string): void {\n\t\tconst text = line.trim();\n\t\tif (text.length === 0) return;\n\n\t\tif (WATCH_START.test(text)) {\n\t\t\tthis.#setState('checking', 0);\n\t\t\treturn;\n\t\t}\n\n\t\tif (ERROR_LINE.test(text)) {\n\t\t\tthis.emit('log', 'error', text);\n\t\t\treturn;\n\t\t}\n\n\t\tconst done = WATCH_DONE.exec(text) ?? ONE_SHOT_DONE.exec(text);\n\t\tif (done) {\n\t\t\tconst errors = Number(done[1]);\n\t\t\tthis.#setState(errors === 0 ? 'ok' : 'failed', errors);\n\t\t\tthis.emit('log', errors === 0 ? 'success' : 'error', errors === 0 ? 'No type errors' : `${errors} type error${errors === 1 ? '' : 's'}`);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.emit('log', 'info', text);\n\t}\n\n\t#setState(state: TypecheckState, errors: number): void {\n\t\tthis.#state = state;\n\t\tthis.#errors = errors;\n\t\tthis.emit('state', state, errors);\n\t}\n}\n\n/**\n * Builds the command line of the configured type checker, resolved from the project's own `node_modules`.\n *\n * @throws {CliError} when the checker is not installed in the project.\n */\nexport function resolveTypecheckCommand(config: ResolvedStarsConfig): TypecheckCommand {\n\tconst { checker, tsconfig } = config.dev.typecheck;\n\tconst project = tsconfig!;\n\n\tswitch (checker) {\n\t\tcase 'golar': {\n\t\t\t// `golar tsc` forwards everything after it to the TypeScript CLI, watch mode included.\n\t\t\tconst golar = resolveBinary(config.root, 'golar', 'golar');\n\t\t\tif (!golar) throw missing(config, 'golar', 'Install it with `pnpm add -D golar`');\n\n\t\t\treturn { command: golar, args: ['tsc', ...WATCH_ARGS, '-p', project], node: true, watch: true };\n\t\t}\n\n\t\tcase 'tsz': {\n\t\t\t// `tsz` is an early, tsc-compatible checker with no watch mode; `try-tsz` is its comparison harness.\n\t\t\tconst tsz = resolveBinary(config.root, '@mohsen-azimi/tsz-dev', 'tsz');\n\t\t\tif (tsz) return { command: tsz, args: ['--noEmit', '-p', project], node: true, watch: false };\n\n\t\t\tconst tryTsz = resolveBinary(config.root, 'try-tsz', 'try-tsz');\n\t\t\tif (tryTsz) return { command: tryTsz, args: ['-p', project], node: true, watch: false };\n\n\t\t\tthrow missing(config, 'tsz', 'Install it with `pnpm add -D @mohsen-azimi/tsz-dev` (or `try-tsz`)');\n\t\t}\n\n\t\tdefault: {\n\t\t\tconst tsc = resolveTscBinary(config.root);\n\t\t\tif (!tsc) throw missing(config, 'typescript', 'Install it with `pnpm add -D typescript`');\n\n\t\t\treturn { command: tsc, args: [...WATCH_ARGS, '-p', project], node: true, watch: true };\n\t\t}\n\t}\n}\n\nconst WATCH_ARGS = ['--noEmit', '--watch', '--preserveWatchOutput', '--pretty', 'false'] as const;\n\nfunction missing(config: ResolvedStarsConfig, name: string, install: string): CliError {\n\treturn new CliError(`\"${name}\" is not installed in ${config.root}`, {\n\t\tcode: 'DEPENDENCY_MISSING',\n\t\thint: `${install}, pick another \\`dev.typecheck.checker\\`, or set \\`dev.typecheck\\` to false.`\n\t});\n}\n\nexport type { StarsTypechecker };\n","import { EventEmitter } from 'node:events';\nimport type { Builder, BuildOutcome } from './builders/types.js';\nimport { displayPath, type ResolvedStarsConfig } from '@wolfstar/http-framework/config';\nimport { classifyAppLine, LogBuffer, type LogLevel, type LogSource } from './log-buffer.js';\nimport { Locales } from './locales.js';\nimport { ProcessSupervisor, type ProcessExit, type ProcessState } from './process-supervisor.js';\nimport { Tunnel, type TunnelState } from './tunnel.js';\nimport { Typechecker, type TypecheckState } from './typechecker.js';\n\nexport type BuildState = 'idle' | 'building' | 'ok' | 'failed';\nexport type HealthState = 'unknown' | 'ok' | 'down';\nexport type RestartReason = 'initial' | 'build' | 'manual' | 'crash';\n\nexport interface DevStatus {\n\treadonly progress: { readonly fraction: number; readonly message: string; readonly startedAt: number; readonly readyMs: number | null };\n\treadonly process: ProcessState;\n\treadonly build: BuildState;\n\treadonly health: HealthState;\n\treadonly pid: number | null;\n\treadonly startedAt: number | null;\n\treadonly restarts: number;\n\treadonly lastRestartReason: RestartReason | null;\n\treadonly lastBuild: BuildOutcome | null;\n\treadonly lastExit: ProcessExit | null;\n\treadonly url: string | null;\n\treadonly typecheck: TypecheckState;\n\treadonly typeErrors: number;\n\treadonly tunnel: TunnelState;\n\treadonly tunnelUrl: string | null;\n}\n\nexport interface DevServiceEvents {\n\tstatus: [status: DevStatus];\n}\n\nexport interface DevServiceOptions {\n\tbuilder: Builder;\n\tlogs?: LogBuffer;\n\t/** Overrides for tests. */\n\tsupervisor?: ProcessSupervisor;\n\ttypechecker?: Typechecker;\n\ttunnel?: Tunnel;\n\thealthInterval?: number;\n}\n\n/**\n * The headless heart of `stars dev`: builds, (re)starts the bot and exposes state and logs.\n * Renderers (plain or TUI) only subscribe to it, they never own behaviour.\n */\nexport class DevService extends EventEmitter<DevServiceEvents> {\n\tpublic readonly logs: LogBuffer;\n\tpublic readonly builder: Builder;\n\tpublic readonly supervisor: ProcessSupervisor;\n\tpublic readonly typechecker: Typechecker;\n\tpublic readonly tunnel: Tunnel;\n\tpublic readonly locales: Locales;\n\n\t#build: BuildState = 'idle';\n\t#health: HealthState = 'unknown';\n\t#restarts = 0;\n\t#lastRestartReason: RestartReason | null = null;\n\t#lastBuild: BuildOutcome | null = null;\n\t#lastExit: ProcessExit | null = null;\n\t#restartTimer: NodeJS.Timeout | null = null;\n\t#healthTimer: NodeJS.Timeout | null = null;\n\t#pendingReason: RestartReason | null = null;\n\t#stopped = false;\n\t#queue: Promise<void> = Promise.resolve();\n\t#progress = { fraction: 0, message: 'preparing your app', startedAt: Date.now(), readyMs: null as number | null };\n\n\tpublic constructor(\n\t\tpublic readonly config: ResolvedStarsConfig,\n\t\toptions: DevServiceOptions\n\t) {\n\t\tsuper();\n\t\tthis.logs = options.logs ?? new LogBuffer();\n\t\tthis.builder = options.builder;\n\t\tthis.supervisor = options.supervisor ?? createSupervisor(config);\n\t\tthis.typechecker = options.typechecker ?? new Typechecker(config);\n\t\tthis.tunnel = options.tunnel ?? new Tunnel(config);\n\t\tthis.locales = new Locales(config);\n\n\t\tthis.builder.on('start', () => {\n\t\t\tthis.#progress = { fraction: 0, message: 'preparing build', startedAt: Date.now(), readyMs: null };\n\t\t\tthis.#setBuild('building');\n\t\t});\n\t\tthis.builder.on('progress', (fraction, message) => {\n\t\t\tthis.#progress = { ...this.#progress, fraction: Math.max(this.#progress.fraction, Math.min(0.75, fraction)), message };\n\t\t\tthis.#emitStatus();\n\t\t});\n\t\tthis.builder.on('success', (outcome) => this.#onBuildSuccess(outcome));\n\t\tthis.builder.on('failure', (outcome) => this.#onBuildFailure(outcome));\n\t\tthis.builder.on('log', (level, text) => this.log('build', level, text));\n\n\t\tthis.supervisor.on('state', () => {\n\t\t\tif (this.supervisor.state === 'running') {\n\t\t\t\tthis.#settleProgress();\n\t\t\t\tvoid this.#checkHealth();\n\t\t\t}\n\t\t\tthis.#emitStatus();\n\t\t});\n\t\tthis.supervisor.on('stdout', (line) => this.log('app', classifyAppLine(line, 'info'), line));\n\t\tthis.supervisor.on('stderr', (line) => this.log('app', classifyAppLine(line, 'error'), line));\n\t\tthis.supervisor.on('error', (error) => this.log('stars', 'error', `Failed to start the bot: ${error.message}`));\n\t\tthis.supervisor.on('exit', (exit) => this.#onExit(exit));\n\n\t\tthis.typechecker.on('log', (level, text) => this.log('tsc', level, text));\n\t\tthis.typechecker.on('state', () => this.#emitStatus());\n\t\tthis.tunnel.on('log', (level, text) => this.log('tunnel', level, text));\n\t\tthis.tunnel.on('state', () => this.#emitStatus());\n\t\tthis.locales.on('log', (level, text) => this.log('build', level, text));\n\t\tthis.locales.on('change', () => {\n\t\t\tif (this.#build === 'ok') this.#scheduleRestart('build');\n\t\t});\n\n\t\tif (config.dev.url && config.dev.health) {\n\t\t\tconst interval = options.healthInterval ?? 5000;\n\t\t\tthis.#healthTimer = setInterval(() => void this.#checkHealth(), interval);\n\t\t\tthis.#healthTimer.unref();\n\t\t}\n\t}\n\n\tpublic get status(): DevStatus {\n\t\treturn {\n\t\t\tprogress: this.#progress,\n\t\t\tprocess: this.supervisor.state,\n\t\t\tbuild: this.#build,\n\t\t\thealth: this.#health,\n\t\t\tpid: this.supervisor.pid,\n\t\t\tstartedAt: this.supervisor.startedAt,\n\t\t\trestarts: this.#restarts,\n\t\t\tlastRestartReason: this.#lastRestartReason,\n\t\t\tlastBuild: this.#lastBuild,\n\t\t\tlastExit: this.#lastExit,\n\t\t\turl: this.config.dev.url,\n\t\t\ttypecheck: this.typechecker.state,\n\t\t\ttypeErrors: this.typechecker.errors,\n\t\t\ttunnel: this.tunnel.state,\n\t\t\ttunnelUrl: this.tunnel.url\n\t\t};\n\t}\n\n\tpublic log(source: LogSource, level: LogLevel, text: string): void {\n\t\tthis.logs.push({ source, level, text });\n\t}\n\n\t/**\n\t * Starts watching; the bot starts after the first successful build.\n\t */\n\tpublic async start(): Promise<void> {\n\t\tthis.#stopped = false;\n\t\tconst entry = displayPath(this.config.root, this.config.entry);\n\t\tthis.log('stars', 'info', this.config.build.tool === 'none' ? `Watching ${entry}` : `Watching ${entry} with ${this.config.build.tool}`);\n\t\tif (this.config.dev.typecheck.enabled) this.typechecker.start();\n\t\tawait this.locales.watch();\n\t\t// The tunnel comes up next to the build: neither waits for the other, and a failed tunnel never stops the bot.\n\t\tvoid this.tunnel.start();\n\t\tawait this.builder.watch();\n\t}\n\n\t/**\n\t * Restarts the bot immediately (used by the `r` key and by `SIGUSR2`).\n\t */\n\tpublic restart(reason: RestartReason = 'manual'): Promise<void> {\n\t\tthis.#clearRestartTimer();\n\t\treturn this.#enqueue(async () => {\n\t\t\tif (this.#stopped) return;\n\t\t\tif (reason === 'manual' || reason === 'crash') {\n\t\t\t\tthis.#progress = { fraction: 0, message: 'restarting the bot', startedAt: Date.now(), readyMs: null };\n\t\t\t}\n\t\t\tthis.#lastRestartReason = reason;\n\t\t\tif (this.supervisor.running) {\n\t\t\t\tthis.#restarts++;\n\t\t\t\tthis.log('stars', 'info', `Restarting (${describeReason(reason)})`);\n\t\t\t\tawait this.supervisor.stop();\n\t\t\t} else {\n\t\t\t\tthis.log('stars', 'info', `Starting (${describeReason(reason)})`);\n\t\t\t}\n\n\t\t\tif (this.#stopped) return;\n\t\t\tthis.#progress = { ...this.#progress, fraction: 0.75, message: 'starting the bot' };\n\t\t\tthis.#health = 'unknown';\n\t\t\tthis.supervisor.start();\n\t\t\tthis.#emitStatus();\n\t\t});\n\t}\n\n\t/** Opens or closes the public tunnel (used by the `t` key). */\n\tpublic toggleTunnel(): Promise<void> {\n\t\treturn this.tunnel.toggle();\n\t}\n\n\t/**\n\t * Stops the watcher and the bot. Safe to call more than once.\n\t */\n\tpublic async stop(): Promise<void> {\n\t\tthis.#stopped = true;\n\t\tthis.#clearRestartTimer();\n\t\tif (this.#healthTimer) clearInterval(this.#healthTimer);\n\t\tthis.#healthTimer = null;\n\t\tawait this.#enqueue(async () => {\n\t\t\tawait Promise.allSettled([\n\t\t\t\tthis.builder.close(),\n\t\t\t\tthis.supervisor.stop(),\n\t\t\t\tthis.typechecker.close(),\n\t\t\t\tthis.tunnel.close(),\n\t\t\t\tthis.locales.close()\n\t\t\t]);\n\t\t});\n\t}\n\n\tpublic clearLogs(): void {\n\t\tthis.logs.clear();\n\t}\n\n\t#onBuildSuccess(outcome: BuildOutcome): void {\n\t\ttry {\n\t\t\tthis.locales.copy();\n\t\t} catch (error) {\n\t\t\tthis.#onBuildFailure({\n\t\t\t\t...outcome,\n\t\t\t\tok: false,\n\t\t\t\tmessage: `Failed to copy locales: ${error instanceof Error ? error.message : String(error)}`\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tthis.#lastBuild = outcome;\n\t\tthis.#progress = { ...this.#progress, fraction: 0.75, message: 'starting the bot' };\n\t\tthis.#setBuild('ok');\n\t\tif (this.#stopped) return;\n\t\t// A checker without a watch mode (`tsz`) only knows about the change once the build is through.\n\t\tthis.typechecker.check();\n\t\tthis.log('stars', 'success', this.builder.tool === 'none' ? 'Sources changed' : `Build succeeded in ${outcome.durationMs}ms`);\n\t\tthis.#scheduleRestart(this.supervisor.state === 'idle' ? 'initial' : 'build');\n\t}\n\n\t#onBuildFailure(outcome: BuildOutcome): void {\n\t\tthis.#lastBuild = outcome;\n\t\tthis.#setBuild('failed');\n\t\tthis.#clearRestartTimer();\n\t\tthis.log('stars', 'error', `Build failed${outcome.message ? `: ${outcome.message}` : ''}, waiting for changes`);\n\t}\n\n\t#onExit(exit: ProcessExit): void {\n\t\tthis.#lastExit = exit;\n\t\tthis.#health = 'unknown';\n\t\tif (!exit.requested) {\n\t\t\tconst how = exit.signal ? `signal ${exit.signal}` : `code ${exit.code}`;\n\t\t\tthis.log('stars', exit.code === 0 ? 'warn' : 'error', `The bot exited with ${how}, waiting for changes (press r to restart)`);\n\t\t}\n\t\tthis.#emitStatus();\n\t}\n\n\t#scheduleRestart(reason: RestartReason): void {\n\t\tthis.#pendingReason = reason;\n\t\tthis.#clearRestartTimer();\n\t\tthis.#restartTimer = setTimeout(() => {\n\t\t\tthis.#restartTimer = null;\n\t\t\tconst pending = this.#pendingReason ?? reason;\n\t\t\tthis.#pendingReason = null;\n\t\t\tvoid this.restart(pending);\n\t\t}, this.config.dev.debounce);\n\t}\n\n\t#clearRestartTimer(): void {\n\t\tif (this.#restartTimer) clearTimeout(this.#restartTimer);\n\t\tthis.#restartTimer = null;\n\t}\n\n\t#enqueue(task: () => Promise<void>): Promise<void> {\n\t\tthis.#queue = this.#queue.then(task, task);\n\t\treturn this.#queue;\n\t}\n\n\t#setBuild(state: BuildState): void {\n\t\tif (this.#build === state) return;\n\t\tthis.#build = state;\n\t\tthis.#emitStatus();\n\t}\n\n\tasync #checkHealth(): Promise<void> {\n\t\tif (!this.supervisor.running || !this.config.dev.url || !this.config.dev.health) return;\n\t\tconst pid = this.supervisor.pid;\n\n\t\tlet next: HealthState;\n\t\ttry {\n\t\t\tconst response = await fetch(new URL(this.config.dev.health, this.config.dev.url), { signal: AbortSignal.timeout(2000) });\n\t\t\tnext = response.status < 500 ? 'ok' : 'down';\n\t\t} catch {\n\t\t\tnext = 'down';\n\t\t}\n\n\t\tif (this.#stopped || pid !== this.supervisor.pid) return;\n\t\tif (next !== this.#health) {\n\t\t\tthis.#health = next;\n\t\t\tif (next === 'ok') this.#settleProgress();\n\t\t\tthis.#emitStatus();\n\t\t}\n\t}\n\n\t#settleProgress(): void {\n\t\tif (this.config.dev.health && this.#health !== 'ok') return;\n\t\tif (this.#build !== 'ok') return;\n\t\tthis.#progress = {\n\t\t\t...this.#progress,\n\t\t\tfraction: 1,\n\t\t\tmessage: 'watching for changes',\n\t\t\treadyMs: this.#progress.readyMs ?? Date.now() - this.#progress.startedAt\n\t\t};\n\t}\n\n\t#emitStatus(): void {\n\t\tthis.emit('status', this.status);\n\t}\n}\n\nexport function createSupervisor(config: ResolvedStarsConfig): ProcessSupervisor {\n\treturn new ProcessSupervisor({\n\t\tcommand: process.execPath,\n\t\targs: [...config.dev.nodeArgs, config.build.output, ...config.dev.args],\n\t\tcwd: config.root,\n\t\tenv: {\n\t\t\t...process.env,\n\t\t\t...config.dev.env,\n\t\t\tSTARS_DEV: '1',\n\t\t\tNODE_ENV: 'development',\n\t\t\tFORCE_COLOR: process.env.NO_COLOR !== undefined ? undefined : (process.env.FORCE_COLOR ?? (process.stdout.isTTY ? '1' : undefined))\n\t\t},\n\t\tkillTimeout: config.dev.killTimeout\n\t});\n}\n\nexport function describeReason(reason: RestartReason): string {\n\tswitch (reason) {\n\t\tcase 'initial':\n\t\t\treturn 'first build';\n\t\tcase 'build':\n\t\t\treturn 'sources changed';\n\t\tcase 'manual':\n\t\t\treturn 'manual restart';\n\t\tcase 'crash':\n\t\t\treturn 'after crash';\n\t}\n}\n","import { lookup } from 'node:dns/promises';\n\n/**\n * Resolves `localhost` the way Vite's dev server does: Node's default DNS result order (`dns.lookup('localhost')`)\n * can disagree with the OS's own, \"verbatim\" resolution order — a well known source of a dev URL that prints fine\n * but is not the address the bot actually bound to (e.g. an IPv6-first system where the server listens on IPv4\n * only). When the two disagree this returns the OS's own address instead of the literal `localhost` hostname.\n */\nexport async function resolveLocalhost(): Promise<string> {\n\ttry {\n\t\tconst [ordered, verbatim] = await Promise.all([lookup('localhost'), lookup('localhost', { verbatim: true })]);\n\t\treturn ordered.family === verbatim.family && ordered.address === verbatim.address ? 'localhost' : verbatim.address;\n\t} catch {\n\t\treturn 'localhost';\n\t}\n}\n\n/**\n * Replaces a `localhost` hostname in `url` with {@link resolveLocalhost}'s result. Any other hostname (an explicit\n * `dev.url` override, a LAN address, …) is returned untouched.\n */\nexport async function withResolvedLocalhost(url: string): Promise<string> {\n\tconst parsed = new URL(url);\n\tif (parsed.hostname !== 'localhost') return url;\n\n\tconst host = await resolveLocalhost();\n\tif (host === 'localhost') return url;\n\n\tparsed.hostname = host.includes(':') ? `[${host}]` : host;\n\treturn parsed.href;\n}\n","import { createWriteStream, mkdirSync, type WriteStream } from 'node:fs';\nimport { dirname } from 'node:path';\nimport type { LogBuffer, LogEntry } from './log-buffer.js';\n\n/**\n * Mirrors a dev session's logs into a file, so a run can be read back after the terminal UI is gone (the TUI takes\n * over the alternate screen and its scrollback disappears on exit). Seedcord keeps a `logs/` directory for the same\n * reason; this writes a single, truncated-per-run file instead.\n */\nexport class LogFileWriter {\n\t#stream: WriteStream | null = null;\n\n\tpublic constructor(\n\t\tpublic readonly file: string,\n\t\tprivate readonly logs: LogBuffer\n\t) {}\n\n\tpublic open(): void {\n\t\tif (this.#stream) return;\n\n\t\tmkdirSync(dirname(this.file), { recursive: true });\n\t\tthis.#stream = createWriteStream(this.file, { flags: 'w' });\n\t\t// A broken pipe or a read-only directory must never take the dev session down with it.\n\t\tthis.#stream.on('error', () => this.close());\n\n\t\tfor (const entry of this.logs.entries()) this.#write(entry);\n\t\tthis.logs.on('entry', this.#write);\n\t}\n\n\tpublic close(): void {\n\t\tconst stream = this.#stream;\n\t\tthis.#stream = null;\n\t\tif (!stream) return;\n\n\t\tthis.logs.off('entry', this.#write);\n\t\tstream.end();\n\t}\n\n\t#write = (entry: LogEntry): void => {\n\t\tthis.#stream?.write(`${format(entry)}\\n`);\n\t};\n}\n\nfunction format(entry: LogEntry): string {\n\treturn `${new Date(entry.time).toISOString()} ${entry.level.padEnd(7)} ${entry.source.padEnd(6)} ${entry.text}`;\n}\n","import { loadStarsConfig, type ResolvedStarsConfig } from '@wolfstar/http-framework/config';\nimport type { ProjectArgs } from '../args.js';\nimport { resolveCwd } from '../args.js';\nimport { assertSupportedExperiments, createBuilder } from '../builders/index.js';\nimport { DevService } from '../dev-service.js';\nimport { ExitCode } from '../errors.js';\nimport { withResolvedLocalhost } from '../host.js';\nimport { LogFileWriter } from '../log-file.js';\nimport { prefersReducedMotion, resolveOutputMode, shouldUseColor } from '../output-mode.js';\nimport { prepareProject } from './prepare.js';\n\nexport interface DevTaskOptions extends ProjectArgs {\n\ttui?: boolean;\n}\n\nexport async function runDev(options: DevTaskOptions): Promise<void> {\n\t// Dev mode applies to config evaluation, build plugins, and the supervised application — not only the child.\n\tprocess.env.NODE_ENV = 'development';\n\tconst config = await resolveDevConfig(\n\t\tawait loadStarsConfig({ cwd: resolveCwd(options), configFile: options.config, env: { ...process.env, NODE_ENV: 'development' } })\n\t);\n\tassertSupportedExperiments(config);\n\tconst mode = resolveOutputMode({ tui: options.tui });\n\tconst color = shouldUseColor();\n\n\tconst service = new DevService(config, { builder: await createBuilder(config) });\n\tconst logFile = config.dev.logFile ? new LogFileWriter(config.dev.logFile, service.logs) : null;\n\tlogFile?.open();\n\tconst renderer =\n\t\tmode === 'tui'\n\t\t\t? (await import('../../renderers/tui.js')).createTuiRenderer(service, { color, reducedMotion: prefersReducedMotion() })\n\t\t\t: (await import('../../renderers/plain.js')).createPlainRenderer(service, { color });\n\n\tlet exiting: Promise<never> | null = null;\n\tconst shutdown = (code: ExitCode): Promise<never> => {\n\t\texiting ??= (async () => {\n\t\t\trenderer.stop();\n\t\t\tawait service.stop();\n\t\t\tlogFile?.close();\n\t\t\tprocess.exit(code);\n\t\t})();\n\t\treturn exiting;\n\t};\n\n\tprocess.once('SIGINT', () => void shutdown(ExitCode.Interrupted));\n\tprocess.once('SIGTERM', () => void shutdown(ExitCode.Terminated));\n\tprocess.once('SIGHUP', () => void shutdown(ExitCode.Terminated));\n\tif (process.platform !== 'win32') process.on('SIGUSR2', () => void service.restart('manual'));\n\n\tconst finished = renderer.start().then(() => shutdown(ExitCode.Ok));\n\ttry {\n\t\tawait prepareProject(config);\n\t\tawait service.start();\n\t} catch (error) {\n\t\tservice.log('stars', 'error', error instanceof Error ? (error.stack ?? error.message) : String(error));\n\t\tawait shutdown(ExitCode.Error);\n\t}\n\tawait finished;\n}\n\n/**\n * Resolves `dev.url`'s `localhost` to the address that is actually reachable (see {@link withResolvedLocalhost}),\n * the way Vite's dev server does when it starts. Only `stars dev` pays this DNS lookup; `stars info`/`stars build`\n * show or use the unresolved config as-is, since they never talk to the bot.\n */\nasync function resolveDevConfig(config: ResolvedStarsConfig): Promise<ResolvedStarsConfig> {\n\tif (!config.dev.url) return config;\n\n\tconst url = await withResolvedLocalhost(config.dev.url);\n\treturn url === config.dev.url ? config : { ...config, dev: { ...config.dev, url } };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AASA,MAAM,cAAc;AACpB,MAAM,aAAa;AACnB,MAAM,gBAAgB;AACtB,MAAM,aAAa;;;;;;;;;AA0BnB,IAAa,cAAb,cAAiC,aAAgC;CAM5B;CALpC,SAA8B;CAC9B,SAAyB;CACzB,UAAU;CACV,WAAW;CAEX,AAAO,YAAY,AAAiB,QAA6B;EAChE,MAAM;EAD6B;CAEpC;CAEA,IAAW,QAAwB;EAClC,OAAO,KAAK;CACb;CAEA,IAAW,SAAiB;EAC3B,OAAO,KAAK;CACb;;CAGA,IAAW,UAAmB;EAC7B,OAAO,KAAK,OAAO,IAAI,UAAU,WAAW,CAAC,wBAAwB,KAAK,MAAM,CAAC,CAAC;CACnF;CAEA,AAAO,QAAc;EACpB,IAAI,CAAC,KAAK,OAAO,IAAI,UAAU,SAAS;EACxC,KAAK,KAAK;CACX;;;;;CAMA,AAAO,QAAc;EACpB,IAAI,CAAC,KAAK,SAAS;EACnB,IAAI,KAAK,QAAQ;GAChB,KAAK,WAAW;GAChB,KAAK,OAAO,KAAK;GACjB;EACD;EAEA,KAAK,KAAK;CACX;CAEA,AAAO,QAAuB;EAC7B,MAAM,QAAQ,KAAK;EACnB,KAAK,SAAS;EACd,KAAK,WAAW;EAChB,IAAI,CAAC,SAAS,MAAM,aAAa,MAAM,OAAO,QAAQ,QAAQ;EAE9D,OAAO,IAAI,SAAS,YAAY;GAC/B,MAAM,KAAK,cAAc,QAAQ,CAAC;GAClC,MAAM,KAAK;EACZ,CAAC;CACF;CAEA,OAAa;EACZ,MAAM,EAAE,SAAS,MAAM,MAAM,UAAU,wBAAwB,KAAK,MAAM;EAC1E,MAAM,QAAQ,MAAM,OAAO,QAAQ,WAAW,SAAS,OAAO,CAAC,SAAS,GAAG,IAAI,IAAI,CAAC,GAAG,IAAI,GAAG;GAC7F,KAAK,KAAK,OAAO;GACjB,KAAK,QAAQ;GACb,OAAO;IAAC;IAAU;IAAQ;GAAM;GAChC,aAAa;EACd,CAAC;EACD,KAAK,SAAS;EACd,KAAK,UAAU,YAAY,CAAC;EAE5B,IAAI,SAAS;EACb,MAAM,cAAc,SAAiB;GACpC,IAAI,WAAW,KAAK,IAAI,GAAG;GAC3B,KAAK,YAAY,IAAI;EACtB;EAEA,MAAM,SAAS,mBAAmB,UAAU;EAC5C,MAAM,SAAS,mBAAmB,UAAU;EAC5C,MAAM,QAAQ,GAAG,QAAQ,OAAO,IAAI;EACpC,MAAM,QAAQ,GAAG,QAAQ,OAAO,IAAI;EAEpC,MAAM,KAAK,SAAS,SAAS;GAC5B,OAAO,MAAM;GACb,OAAO,MAAM;GACb,KAAK,SAAS;GAEd,IAAI,CAAC,SAAS,KAAK,WAAW,YAE7B,KAAK,UAAU,SAAS,KAAK,WAAW,IAAI,OAAO,UAAU,MAAM;GAGpE,IAAI,KAAK,UAAU;IAClB,KAAK,WAAW;IAChB,KAAK,KAAK;GACX;EACD,CAAC;EACD,MAAM,KAAK,UAAU,UAAiC;GACrD,KAAK,SAAS;GACd,KAAK,KAAK,OAAO,SAAS,MAAM,SAAS,WAAW,GAAG,QAAQ,qBAAqB,MAAM,OAAO;GACjG,KAAK,UAAU,UAAU,KAAK,OAAO;EACtC,CAAC;CACF;CAEA,YAAY,MAAoB;EAC/B,MAAM,OAAO,KAAK,KAAK;EACvB,IAAI,KAAK,WAAW,GAAG;EAEvB,IAAI,YAAY,KAAK,IAAI,GAAG;GAC3B,KAAK,UAAU,YAAY,CAAC;GAC5B;EACD;EAEA,IAAI,WAAW,KAAK,IAAI,GAAG;GAC1B,KAAK,KAAK,OAAO,SAAS,IAAI;GAC9B;EACD;EAEA,MAAM,OAAO,WAAW,KAAK,IAAI,KAAK,cAAc,KAAK,IAAI;EAC7D,IAAI,MAAM;GACT,MAAM,SAAS,OAAO,KAAK,EAAE;GAC7B,KAAK,UAAU,WAAW,IAAI,OAAO,UAAU,MAAM;GACrD,KAAK,KAAK,OAAO,WAAW,IAAI,YAAY,SAAS,WAAW,IAAI,mBAAmB,GAAG,OAAO,aAAa,WAAW,IAAI,KAAK,KAAK;GACvI;EACD;EAEA,KAAK,KAAK,OAAO,QAAQ,IAAI;CAC9B;CAEA,UAAU,OAAuB,QAAsB;EACtD,KAAK,SAAS;EACd,KAAK,UAAU;EACf,KAAK,KAAK,SAAS,OAAO,MAAM;CACjC;AACD;;;;;;AAOA,SAAgB,wBAAwB,QAA+C;CACtF,MAAM,EAAE,SAAS,aAAa,OAAO,IAAI;CACzC,MAAM,UAAU;CAEhB,QAAQ,SAAR;EACC,KAAK,SAAS;GAEb,MAAM,QAAQ,cAAc,OAAO,MAAM,SAAS,OAAO;GACzD,IAAI,CAAC,OAAO,MAAM,QAAQ,QAAQ,SAAS,qCAAqC;GAEhF,OAAO;IAAE,SAAS;IAAO,MAAM;KAAC;KAAO,GAAG;KAAY;KAAM;IAAO;IAAG,MAAM;IAAM,OAAO;GAAK;EAC/F;EAEA,KAAK,OAAO;GAEX,MAAM,MAAM,cAAc,OAAO,MAAM,yBAAyB,KAAK;GACrE,IAAI,KAAK,OAAO;IAAE,SAAS;IAAK,MAAM;KAAC;KAAY;KAAM;IAAO;IAAG,MAAM;IAAM,OAAO;GAAM;GAE5F,MAAM,SAAS,cAAc,OAAO,MAAM,WAAW,SAAS;GAC9D,IAAI,QAAQ,OAAO;IAAE,SAAS;IAAQ,MAAM,CAAC,MAAM,OAAO;IAAG,MAAM;IAAM,OAAO;GAAM;GAEtF,MAAM,QAAQ,QAAQ,OAAO,oEAAoE;EAClG;EAEA,SAAS;GACR,MAAM,MAAM,iBAAiB,OAAO,IAAI;GACxC,IAAI,CAAC,KAAK,MAAM,QAAQ,QAAQ,cAAc,0CAA0C;GAExF,OAAO;IAAE,SAAS;IAAK,MAAM;KAAC,GAAG;KAAY;KAAM;IAAO;IAAG,MAAM;IAAM,OAAO;GAAK;EACtF;CACD;AACD;AAEA,MAAM,aAAa;CAAC;CAAY;CAAW;CAAyB;CAAY;AAAO;AAEvF,SAAS,QAAQ,QAA6B,MAAc,SAA2B;CACtF,OAAO,IAAI,SAAS,IAAI,KAAK,wBAAwB,OAAO,QAAQ;EACnE,MAAM;EACN,MAAM,GAAG,QAAQ;CAClB,CAAC;AACF;;;;;;;;ACrKA,IAAa,aAAb,cAAgC,aAA+B;CAsB7C;CArBjB,AAAgB;CAChB,AAAgB;CAChB,AAAgB;CAChB,AAAgB;CAChB,AAAgB;CAChB,AAAgB;CAEhB,SAAqB;CACrB,UAAuB;CACvB,YAAY;CACZ,qBAA2C;CAC3C,aAAkC;CAClC,YAAgC;CAChC,gBAAuC;CACvC,eAAsC;CACtC,iBAAuC;CACvC,WAAW;CACX,SAAwB,QAAQ,QAAQ;CACxC,YAAY;EAAE,UAAU;EAAG,SAAS;EAAsB,WAAW,KAAK,IAAI;EAAG,SAAS;CAAsB;CAEhH,AAAO,YACN,AAAgB,QAChB,SACC;EACD,MAAM;EAHU;EAIhB,KAAK,OAAO,QAAQ,QAAQ,IAAI,UAAU;EAC1C,KAAK,UAAU,QAAQ;EACvB,KAAK,aAAa,QAAQ,cAAc,iBAAiB,MAAM;EAC/D,KAAK,cAAc,QAAQ,eAAe,IAAI,YAAY,MAAM;EAChE,KAAK,SAAS,QAAQ,UAAU,IAAI,OAAO,MAAM;EACjD,KAAK,UAAU,IAAI,QAAQ,MAAM;EAEjC,KAAK,QAAQ,GAAG,eAAe;GAC9B,KAAK,YAAY;IAAE,UAAU;IAAG,SAAS;IAAmB,WAAW,KAAK,IAAI;IAAG,SAAS;GAAK;GACjG,KAAK,UAAU,UAAU;EAC1B,CAAC;EACD,KAAK,QAAQ,GAAG,aAAa,UAAU,YAAY;GAClD,KAAK,YAAY;IAAE,GAAG,KAAK;IAAW,UAAU,KAAK,IAAI,KAAK,UAAU,UAAU,KAAK,IAAI,KAAM,QAAQ,CAAC;IAAG;GAAQ;GACrH,KAAK,YAAY;EAClB,CAAC;EACD,KAAK,QAAQ,GAAG,YAAY,YAAY,KAAK,gBAAgB,OAAO,CAAC;EACrE,KAAK,QAAQ,GAAG,YAAY,YAAY,KAAK,gBAAgB,OAAO,CAAC;EACrE,KAAK,QAAQ,GAAG,QAAQ,OAAO,SAAS,KAAK,IAAI,SAAS,OAAO,IAAI,CAAC;EAEtE,KAAK,WAAW,GAAG,eAAe;GACjC,IAAI,KAAK,WAAW,UAAU,WAAW;IACxC,KAAK,gBAAgB;IACrB,AAAK,KAAK,aAAa;GACxB;GACA,KAAK,YAAY;EAClB,CAAC;EACD,KAAK,WAAW,GAAG,WAAW,SAAS,KAAK,IAAI,OAAO,gBAAgB,MAAM,MAAM,GAAG,IAAI,CAAC;EAC3F,KAAK,WAAW,GAAG,WAAW,SAAS,KAAK,IAAI,OAAO,gBAAgB,MAAM,OAAO,GAAG,IAAI,CAAC;EAC5F,KAAK,WAAW,GAAG,UAAU,UAAU,KAAK,IAAI,SAAS,SAAS,4BAA4B,MAAM,SAAS,CAAC;EAC9G,KAAK,WAAW,GAAG,SAAS,SAAS,KAAK,QAAQ,IAAI,CAAC;EAEvD,KAAK,YAAY,GAAG,QAAQ,OAAO,SAAS,KAAK,IAAI,OAAO,OAAO,IAAI,CAAC;EACxE,KAAK,YAAY,GAAG,eAAe,KAAK,YAAY,CAAC;EACrD,KAAK,OAAO,GAAG,QAAQ,OAAO,SAAS,KAAK,IAAI,UAAU,OAAO,IAAI,CAAC;EACtE,KAAK,OAAO,GAAG,eAAe,KAAK,YAAY,CAAC;EAChD,KAAK,QAAQ,GAAG,QAAQ,OAAO,SAAS,KAAK,IAAI,SAAS,OAAO,IAAI,CAAC;EACtE,KAAK,QAAQ,GAAG,gBAAgB;GAC/B,IAAI,KAAK,WAAW,MAAM,KAAK,iBAAiB,OAAO;EACxD,CAAC;EAED,IAAI,OAAO,IAAI,OAAO,OAAO,IAAI,QAAQ;GACxC,MAAM,WAAW,QAAQ,kBAAkB;GAC3C,KAAK,eAAe,kBAAkB,KAAK,KAAK,aAAa,GAAG,QAAQ;GACxE,KAAK,aAAa,MAAM;EACzB;CACD;CAEA,IAAW,SAAoB;EAC9B,OAAO;GACN,UAAU,KAAK;GACf,SAAS,KAAK,WAAW;GACzB,OAAO,KAAK;GACZ,QAAQ,KAAK;GACb,KAAK,KAAK,WAAW;GACrB,WAAW,KAAK,WAAW;GAC3B,UAAU,KAAK;GACf,mBAAmB,KAAK;GACxB,WAAW,KAAK;GAChB,UAAU,KAAK;GACf,KAAK,KAAK,OAAO,IAAI;GACrB,WAAW,KAAK,YAAY;GAC5B,YAAY,KAAK,YAAY;GAC7B,QAAQ,KAAK,OAAO;GACpB,WAAW,KAAK,OAAO;EACxB;CACD;CAEA,AAAO,IAAI,QAAmB,OAAiB,MAAoB;EAClE,KAAK,KAAK,KAAK;GAAE;GAAQ;GAAO;EAAK,CAAC;CACvC;;;;CAKA,MAAa,QAAuB;EACnC,KAAK,WAAW;EAChB,MAAM,QAAQ,YAAY,KAAK,OAAO,MAAM,KAAK,OAAO,KAAK;EAC7D,KAAK,IAAI,SAAS,QAAQ,KAAK,OAAO,MAAM,SAAS,SAAS,YAAY,UAAU,YAAY,MAAM,QAAQ,KAAK,OAAO,MAAM,MAAM;EACtI,IAAI,KAAK,OAAO,IAAI,UAAU,SAAS,KAAK,YAAY,MAAM;EAC9D,MAAM,KAAK,QAAQ,MAAM;EAEzB,AAAK,KAAK,OAAO,MAAM;EACvB,MAAM,KAAK,QAAQ,MAAM;CAC1B;;;;CAKA,AAAO,QAAQ,SAAwB,UAAyB;EAC/D,KAAK,mBAAmB;EACxB,OAAO,KAAK,SAAS,YAAY;GAChC,IAAI,KAAK,UAAU;GACnB,IAAI,WAAW,YAAY,WAAW,SACrC,KAAK,YAAY;IAAE,UAAU;IAAG,SAAS;IAAsB,WAAW,KAAK,IAAI;IAAG,SAAS;GAAK;GAErG,KAAK,qBAAqB;GAC1B,IAAI,KAAK,WAAW,SAAS;IAC5B,KAAK;IACL,KAAK,IAAI,SAAS,QAAQ,eAAe,eAAe,MAAM,EAAE,EAAE;IAClE,MAAM,KAAK,WAAW,KAAK;GAC5B,OACC,KAAK,IAAI,SAAS,QAAQ,aAAa,eAAe,MAAM,EAAE,EAAE;GAGjE,IAAI,KAAK,UAAU;GACnB,KAAK,YAAY;IAAE,GAAG,KAAK;IAAW,UAAU;IAAM,SAAS;GAAmB;GAClF,KAAK,UAAU;GACf,KAAK,WAAW,MAAM;GACtB,KAAK,YAAY;EAClB,CAAC;CACF;;CAGA,AAAO,eAA8B;EACpC,OAAO,KAAK,OAAO,OAAO;CAC3B;;;;CAKA,MAAa,OAAsB;EAClC,KAAK,WAAW;EAChB,KAAK,mBAAmB;EACxB,IAAI,KAAK,cAAc,cAAc,KAAK,YAAY;EACtD,KAAK,eAAe;EACpB,MAAM,KAAK,SAAS,YAAY;GAC/B,MAAM,QAAQ,WAAW;IACxB,KAAK,QAAQ,MAAM;IACnB,KAAK,WAAW,KAAK;IACrB,KAAK,YAAY,MAAM;IACvB,KAAK,OAAO,MAAM;IAClB,KAAK,QAAQ,MAAM;GACpB,CAAC;EACF,CAAC;CACF;CAEA,AAAO,YAAkB;EACxB,KAAK,KAAK,MAAM;CACjB;CAEA,gBAAgB,SAA6B;EAC5C,IAAI;GACH,KAAK,QAAQ,KAAK;EACnB,SAAS,OAAO;GACf,KAAK,gBAAgB;IACpB,GAAG;IACH,IAAI;IACJ,SAAS,2BAA2B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;GAC1F,CAAC;GACD;EACD;EACA,KAAK,aAAa;EAClB,KAAK,YAAY;GAAE,GAAG,KAAK;GAAW,UAAU;GAAM,SAAS;EAAmB;EAClF,KAAK,UAAU,IAAI;EACnB,IAAI,KAAK,UAAU;EAEnB,KAAK,YAAY,MAAM;EACvB,KAAK,IAAI,SAAS,WAAW,KAAK,QAAQ,SAAS,SAAS,oBAAoB,sBAAsB,QAAQ,WAAW,GAAG;EAC5H,KAAK,iBAAiB,KAAK,WAAW,UAAU,SAAS,YAAY,OAAO;CAC7E;CAEA,gBAAgB,SAA6B;EAC5C,KAAK,aAAa;EAClB,KAAK,UAAU,QAAQ;EACvB,KAAK,mBAAmB;EACxB,KAAK,IAAI,SAAS,SAAS,eAAe,QAAQ,UAAU,KAAK,QAAQ,YAAY,GAAG,sBAAsB;CAC/G;CAEA,QAAQ,MAAyB;EAChC,KAAK,YAAY;EACjB,KAAK,UAAU;EACf,IAAI,CAAC,KAAK,WAAW;GACpB,MAAM,MAAM,KAAK,SAAS,UAAU,KAAK,WAAW,QAAQ,KAAK;GACjE,KAAK,IAAI,SAAS,KAAK,SAAS,IAAI,SAAS,SAAS,uBAAuB,IAAI,2CAA2C;EAC7H;EACA,KAAK,YAAY;CAClB;CAEA,iBAAiB,QAA6B;EAC7C,KAAK,iBAAiB;EACtB,KAAK,mBAAmB;EACxB,KAAK,gBAAgB,iBAAiB;GACrC,KAAK,gBAAgB;GACrB,MAAM,UAAU,KAAK,kBAAkB;GACvC,KAAK,iBAAiB;GACtB,AAAK,KAAK,QAAQ,OAAO;EAC1B,GAAG,KAAK,OAAO,IAAI,QAAQ;CAC5B;CAEA,qBAA2B;EAC1B,IAAI,KAAK,eAAe,aAAa,KAAK,aAAa;EACvD,KAAK,gBAAgB;CACtB;CAEA,SAAS,MAA0C;EAClD,KAAK,SAAS,KAAK,OAAO,KAAK,MAAM,IAAI;EACzC,OAAO,KAAK;CACb;CAEA,UAAU,OAAyB;EAClC,IAAI,KAAK,WAAW,OAAO;EAC3B,KAAK,SAAS;EACd,KAAK,YAAY;CAClB;CAEA,MAAM,eAA8B;EACnC,IAAI,CAAC,KAAK,WAAW,WAAW,CAAC,KAAK,OAAO,IAAI,OAAO,CAAC,KAAK,OAAO,IAAI,QAAQ;EACjF,MAAM,MAAM,KAAK,WAAW;EAE5B,IAAI;EACJ,IAAI;GAEH,QAAO,MADgB,MAAM,IAAI,IAAI,KAAK,OAAO,IAAI,QAAQ,KAAK,OAAO,IAAI,GAAG,GAAG,EAAE,QAAQ,YAAY,QAAQ,GAAI,EAAE,CAAC,EACzG,CAAC,SAAS,MAAM,OAAO;EACvC,QAAQ;GACP,OAAO;EACR;EAEA,IAAI,KAAK,YAAY,QAAQ,KAAK,WAAW,KAAK;EAClD,IAAI,SAAS,KAAK,SAAS;GAC1B,KAAK,UAAU;GACf,IAAI,SAAS,MAAM,KAAK,gBAAgB;GACxC,KAAK,YAAY;EAClB;CACD;CAEA,kBAAwB;EACvB,IAAI,KAAK,OAAO,IAAI,UAAU,KAAK,YAAY,MAAM;EACrD,IAAI,KAAK,WAAW,MAAM;EAC1B,KAAK,YAAY;GAChB,GAAG,KAAK;GACR,UAAU;GACV,SAAS;GACT,SAAS,KAAK,UAAU,WAAW,KAAK,IAAI,IAAI,KAAK,UAAU;EAChE;CACD;CAEA,cAAoB;EACnB,KAAK,KAAK,UAAU,KAAK,MAAM;CAChC;AACD;AAEA,SAAgB,iBAAiB,QAAgD;CAChF,OAAO,IAAI,kBAAkB;EAC5B,SAAS,QAAQ;EACjB,MAAM;GAAC,GAAG,OAAO,IAAI;GAAU,OAAO,MAAM;GAAQ,GAAG,OAAO,IAAI;EAAI;EACtE,KAAK,OAAO;EACZ,KAAK;GACJ,GAAG,QAAQ;GACX,GAAG,OAAO,IAAI;GACd,WAAW;GACX,UAAU;GACV,aAAa,QAAQ,IAAI,aAAa,SAAY,SAAa,QAAQ,IAAI,gBAAgB,QAAQ,OAAO,QAAQ,MAAM;EACzH;EACA,aAAa,OAAO,IAAI;CACzB,CAAC;AACF;AAEA,SAAgB,eAAe,QAA+B;CAC7D,QAAQ,QAAR;EACC,KAAK,WACJ,OAAO;EACR,KAAK,SACJ,OAAO;EACR,KAAK,UACJ,OAAO;EACR,KAAK,SACJ,OAAO;CACT;AACD;;;;;;;;;;AC/UA,eAAsB,mBAAoC;CACzD,IAAI;EACH,MAAM,CAAC,SAAS,YAAY,MAAM,QAAQ,IAAI,CAAC,OAAO,WAAW,GAAG,OAAO,aAAa,EAAE,UAAU,KAAK,CAAC,CAAC,CAAC;EAC5G,OAAO,QAAQ,WAAW,SAAS,UAAU,QAAQ,YAAY,SAAS,UAAU,cAAc,SAAS;CAC5G,QAAQ;EACP,OAAO;CACR;AACD;;;;;AAMA,eAAsB,sBAAsB,KAA8B;CACzE,MAAM,SAAS,IAAI,IAAI,GAAG;CAC1B,IAAI,OAAO,aAAa,aAAa,OAAO;CAE5C,MAAM,OAAO,MAAM,iBAAiB;CACpC,IAAI,SAAS,aAAa,OAAO;CAEjC,OAAO,WAAW,KAAK,SAAS,GAAG,IAAI,IAAI,KAAK,KAAK;CACrD,OAAO,OAAO;AACf;;;;;;;;;ACrBA,IAAa,gBAAb,MAA2B;CAIT;CACC;CAJlB,UAA8B;CAE9B,AAAO,YACN,AAAgB,MAChB,AAAiB,MAChB;EAFe;EACC;CACf;CAEH,AAAO,OAAa;EACnB,IAAI,KAAK,SAAS;EAElB,UAAU,QAAQ,KAAK,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;EACjD,KAAK,UAAU,kBAAkB,KAAK,MAAM,EAAE,OAAO,IAAI,CAAC;EAE1D,KAAK,QAAQ,GAAG,eAAe,KAAK,MAAM,CAAC;EAE3C,KAAK,MAAM,SAAS,KAAK,KAAK,QAAQ,GAAG,KAAK,OAAO,KAAK;EAC1D,KAAK,KAAK,GAAG,SAAS,KAAK,MAAM;CAClC;CAEA,AAAO,QAAc;EACpB,MAAM,SAAS,KAAK;EACpB,KAAK,UAAU;EACf,IAAI,CAAC,QAAQ;EAEb,KAAK,KAAK,IAAI,SAAS,KAAK,MAAM;EAClC,OAAO,IAAI;CACZ;CAEA,UAAU,UAA0B;EACnC,KAAK,SAAS,MAAM,GAAG,OAAO,KAAK,EAAE,GAAG;CACzC;AACD;AAEA,SAAS,OAAO,OAAyB;CACxC,OAAO,GAAG,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,YAAY,EAAE,GAAG,MAAM,MAAM,OAAO,CAAC,EAAE,GAAG,MAAM,OAAO,OAAO,CAAC,EAAE,GAAG,MAAM;AAC1G;;;;AC9BA,eAAsB,OAAO,SAAwC;CAEpE,QAAQ,IAAI,WAAW;CACvB,MAAM,SAAS,MAAM,iBACpB,MAAM,gBAAgB;EAAE,KAAK,WAAW,OAAO;EAAG,YAAY,QAAQ;EAAQ,KAAK;GAAE,GAAG,QAAQ;GAAK,UAAU;EAAc;CAAE,CAAC,CACjI;CACA,2BAA2B,MAAM;CACjC,MAAM,OAAO,kBAAkB,EAAE,KAAK,QAAQ,IAAI,CAAC;CACnD,MAAM,QAAQ,eAAe;CAE7B,MAAM,UAAU,IAAI,WAAW,QAAQ,EAAE,SAAS,MAAM,cAAc,MAAM,EAAE,CAAC;CAC/E,MAAM,UAAU,OAAO,IAAI,UAAU,IAAI,cAAc,OAAO,IAAI,SAAS,QAAQ,IAAI,IAAI;CAC3F,SAAS,KAAK;CACd,MAAM,WACL,SAAS,SACL,MAAM,OAAO,qBAAyB,CAAE,kBAAkB,SAAS;EAAE;EAAO,eAAe,qBAAqB;CAAE,CAAC,KACnH,MAAM,OAAO,uBAA2B,CAAE,oBAAoB,SAAS,EAAE,MAAM,CAAC;CAErF,IAAI,UAAiC;CACrC,MAAM,YAAY,SAAmC;EACpD,aAAa,YAAY;GACxB,SAAS,KAAK;GACd,MAAM,QAAQ,KAAK;GACnB,SAAS,MAAM;GACf,QAAQ,KAAK,IAAI;EAClB,EAAC,CAAE;EACH,OAAO;CACR;CAEA,QAAQ,KAAK,gBAAgB,KAAK,SAAS,SAAS,WAAW,CAAC;CAChE,QAAQ,KAAK,iBAAiB,KAAK,SAAS,SAAS,UAAU,CAAC;CAChE,QAAQ,KAAK,gBAAgB,KAAK,SAAS,SAAS,UAAU,CAAC;CAC/D,IAAI,QAAQ,aAAa,SAAS,QAAQ,GAAG,iBAAiB,KAAK,QAAQ,QAAQ,QAAQ,CAAC;CAE5F,MAAM,WAAW,SAAS,MAAM,CAAC,CAAC,WAAW,SAAS,SAAS,EAAE,CAAC;CAClE,IAAI;EACH,MAAM,eAAe,MAAM;EAC3B,MAAM,QAAQ,MAAM;CACrB,SAAS,OAAO;EACf,QAAQ,IAAI,SAAS,SAAS,iBAAiB,QAAS,MAAM,SAAS,MAAM,UAAW,OAAO,KAAK,CAAC;EACrG,MAAM,SAAS,SAAS,KAAK;CAC9B;CACA,MAAM;AACP;;;;;;AAOA,eAAe,iBAAiB,QAA2D;CAC1F,IAAI,CAAC,OAAO,IAAI,KAAK,OAAO;CAE5B,MAAM,MAAM,MAAM,sBAAsB,OAAO,IAAI,GAAG;CACtD,OAAO,QAAQ,OAAO,IAAI,MAAM,SAAS;EAAE,GAAG;EAAQ,KAAK;GAAE,GAAG,OAAO;GAAK;EAAI;CAAE;AACnF"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"dev-CwJg6pSQ.js","names":[],"sources":["../src/commands/dev.ts"],"sourcesContent":["import { defineCommand } from 'citty';\nimport { projectArgs } from '../lib/args.js';\n\nexport default defineCommand({\n\tmeta: {\n\t\tname: 'dev',\n\t\tdescription: 'Build, run and restart the bot on changes'\n\t},\n\targs: {\n\t\t...projectArgs,\n\t\ttui: {\n\t\t\ttype: 'boolean',\n\t\t\tdescription: 'Interactive terminal UI; use --no-tui (or STARS_TUI=plain) for plain line output',\n\t\t\tdefault: true\n\t\t}\n\t},\n\tasync run({ args }) {\n\t\tconst { runDev } = await import('../lib/tasks/dev.js');\n\t\tawait runDev({ config: args.config, cwd: args.cwd, tui: args.tui ? undefined : false });\n\t}\n});\n"],"mappings":";;;;AAGA,kBAAe,cAAc;CAC5B,MAAM;EACL,MAAM;EACN,aAAa;CACd;CACA,MAAM;EACL,GAAG;EACH,KAAK;GACJ,MAAM;GACN,aAAa;GACb,SAAS;EACV;CACD;CACA,MAAM,IAAI,EAAE,QAAQ;EACnB,MAAM,EAAE,WAAW,MAAM,OAAO;EAChC,MAAM,OAAO;GAAE,QAAQ,KAAK;GAAQ,KAAK,KAAK;GAAK,KAAK,KAAK,MAAM,SAAY;EAAM,CAAC;CACvF;AACD,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"tsc-BTuFXw3O.js","names":[],"sources":["../src/lib/process-supervisor.ts","../src/lib/builders/tsc.ts"],"sourcesContent":["import { spawn, type ChildProcess } from 'node:child_process';\nimport { EventEmitter } from 'node:events';\n\nexport type ProcessState = 'idle' | 'starting' | 'running' | 'stopping' | 'stopped' | 'crashed';\n\nexport interface ProcessExit {\n\tcode: number | null;\n\tsignal: NodeJS.Signals | null;\n\t/** Whether the exit was requested through {@link ProcessSupervisor.stop}. */\n\trequested: boolean;\n}\n\nexport interface ProcessSupervisorOptions {\n\tcommand: string;\n\targs: readonly string[];\n\tcwd: string;\n\tenv: NodeJS.ProcessEnv;\n\t/** Milliseconds to wait after `SIGTERM` before sending `SIGKILL`. */\n\tkillTimeout: number;\n}\n\nexport interface ProcessSupervisorEvents {\n\tstate: [state: ProcessState];\n\tstdout: [line: string];\n\tstderr: [line: string];\n\texit: [exit: ProcessExit];\n\terror: [error: Error];\n}\n\n/**\n * Owns a single child process: starts it, streams its output line by line and stops it gracefully.\n */\nexport class ProcessSupervisor extends EventEmitter<ProcessSupervisorEvents> {\n\t#child: ChildProcess | null = null;\n\t#state: ProcessState = 'idle';\n\t#startedAt: number | null = null;\n\t#stopping: Promise<void> | null = null;\n\n\tpublic constructor(private readonly options: ProcessSupervisorOptions) {\n\t\tsuper();\n\t}\n\n\tpublic get state(): ProcessState {\n\t\treturn this.#state;\n\t}\n\n\tpublic get pid(): number | null {\n\t\treturn this.#child?.pid ?? null;\n\t}\n\n\tpublic get startedAt(): number | null {\n\t\treturn this.#startedAt;\n\t}\n\n\tpublic get running(): boolean {\n\t\treturn this.#state === 'starting' || this.#state === 'running';\n\t}\n\n\tpublic start(): void {\n\t\tif (this.#child) throw new Error('The process is already running, call stop() or restart() first.');\n\n\t\tconst { command, args, cwd, env } = this.options;\n\t\tthis.#setState('starting');\n\n\t\tconst child = spawn(command, args, { cwd, env, stdio: ['ignore', 'pipe', 'pipe'], windowsHide: true });\n\t\tthis.#child = child;\n\t\tthis.#startedAt = Date.now();\n\n\t\tlet requested = false;\n\t\tconst stdout = createLineSplitter((line) => this.emit('stdout', line));\n\t\tconst stderr = createLineSplitter((line) => this.emit('stderr', line));\n\t\tchild.stdout?.on('data', stdout.push);\n\t\tchild.stderr?.on('data', stderr.push);\n\n\t\tchild.once('spawn', () => {\n\t\t\tif (this.#child === child) this.#setState('running');\n\t\t});\n\n\t\tchild.once('error', (error) => {\n\t\t\tthis.emit('error', error);\n\t\t});\n\n\t\tchild.once('exit', (code, signal) => {\n\t\t\tstdout.flush();\n\t\t\tstderr.flush();\n\t\t\trequested = this.#state === 'stopping';\n\t\t\tthis.#child = null;\n\t\t\tthis.#startedAt = null;\n\t\t\tthis.#setState(requested || code === 0 ? 'stopped' : 'crashed');\n\t\t\tthis.emit('exit', { code, signal, requested });\n\t\t});\n\t}\n\n\t/**\n\t * Sends `SIGTERM`, escalates to `SIGKILL` after `killTimeout` and resolves once the process exited.\n\t */\n\tpublic stop(): Promise<void> {\n\t\tconst child = this.#child;\n\t\tif (!child) return Promise.resolve();\n\t\tif (this.#stopping) return this.#stopping;\n\n\t\tthis.#setState('stopping');\n\t\tthis.#stopping = new Promise<void>((resolve) => {\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tif (child.exitCode === null && child.signalCode === null) child.kill('SIGKILL');\n\t\t\t}, this.options.killTimeout);\n\t\t\ttimer.unref();\n\n\t\t\tchild.once('exit', () => {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\tthis.#stopping = null;\n\t\t\t\tresolve();\n\t\t\t});\n\n\t\t\tif (!child.kill('SIGTERM')) {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\tthis.#stopping = null;\n\t\t\t\tresolve();\n\t\t\t}\n\t\t});\n\n\t\treturn this.#stopping;\n\t}\n\n\tpublic async restart(): Promise<void> {\n\t\tawait this.stop();\n\t\tthis.start();\n\t}\n\n\t#setState(state: ProcessState): void {\n\t\tif (this.#state === state) return;\n\t\tthis.#state = state;\n\t\tthis.emit('state', state);\n\t}\n}\n\n/**\n * Splits a byte stream into complete lines, keeping the trailing partial line until the next chunk.\n */\nexport function createLineSplitter(onLine: (line: string) => void) {\n\tlet remainder = '';\n\treturn {\n\t\tpush(chunk: Buffer | string) {\n\t\t\tremainder += chunk.toString();\n\t\t\tconst lines = remainder.split(/\\r?\\n/);\n\t\t\tremainder = lines.pop() ?? '';\n\t\t\tfor (const line of lines) onLine(line);\n\t\t},\n\t\tflush() {\n\t\t\tif (remainder.length > 0) onLine(remainder);\n\t\t\tremainder = '';\n\t\t}\n\t};\n}\n","import { spawn, type ChildProcess } from 'node:child_process';\nimport { EventEmitter } from 'node:events';\nimport type { ResolvedStarsConfig } from '@wolfstar/http-framework/config';\nimport { CliError } from '../errors.js';\nimport { createLineSplitter } from '../process-supervisor.js';\nimport { resolveBinary } from '../project.js';\nimport type { Builder, BuilderEvents, BuildOutcome } from './types.js';\n\nconst INSTALL_HINT = \"Install it with `pnpm add -D typescript`, or set `build.tool` to 'tsdown' or 'none'.\";\nconst WATCH_START = /Starting (incremental )?compilation/;\nconst WATCH_DONE = /Found (\\d+) errors?\\. Watching for file changes/;\nconst ERROR_LINE = /error TS\\d+:/;\n\n/**\n * Builds through the project's `tsc -b`, parsing its output to report progress.\n */\nexport class TscBuilder extends EventEmitter<BuilderEvents> implements Builder {\n\tpublic readonly tool = 'tsc' as const;\n\t#child: ChildProcess | null = null;\n\t#startedAt = 0;\n\t#firstError: string | null = null;\n\n\tpublic constructor(private readonly config: ResolvedStarsConfig) {\n\t\tsuper();\n\t}\n\n\tpublic build(): Promise<BuildOutcome> {\n\t\tconst child = this.#spawn([]);\n\t\tthis.#begin();\n\n\t\treturn new Promise((resolve) => {\n\t\t\tchild.once('exit', (code) => {\n\t\t\t\tthis.#child = null;\n\t\t\t\tresolve(this.#finish(code === 0 ? null : (this.#firstError ?? `tsc exited with code ${code}`)));\n\t\t\t});\n\t\t});\n\t}\n\n\tpublic watch(): Promise<void> {\n\t\tthis.#spawn(['--watch', '--preserveWatchOutput']);\n\t\tthis.#begin();\n\t\treturn Promise.resolve();\n\t}\n\n\tpublic close(): Promise<void> {\n\t\tconst child = this.#child;\n\t\tthis.#child = null;\n\t\tif (!child || child.exitCode !== null) return Promise.resolve();\n\n\t\treturn new Promise((resolve) => {\n\t\t\tchild.once('exit', () => resolve());\n\t\t\tchild.kill();\n\t\t});\n\t}\n\n\t#spawn(extraArgs: string[]): ChildProcess {\n\t\tconst tsc = resolveTscBinary(this.config.root);\n\t\tif (!tsc) throw new CliError(`\"typescript\" is not installed in ${this.config.root}`, { code: 'DEPENDENCY_MISSING', hint: INSTALL_HINT });\n\n\t\tconst child = spawn(process.execPath, [tsc, '-b', this.config.build.tsconfig!, '--pretty', 'false', ...extraArgs], {\n\t\t\tcwd: this.config.root,\n\t\t\tenv: process.env,\n\t\t\tstdio: ['ignore', 'pipe', 'pipe'],\n\t\t\twindowsHide: true\n\t\t});\n\t\tthis.#child = child;\n\n\t\tconst handleLine = (line: string) => this.#handleLine(line);\n\t\tconst stdout = createLineSplitter(handleLine);\n\t\tconst stderr = createLineSplitter(handleLine);\n\t\tchild.stdout?.on('data', stdout.push);\n\t\tchild.stderr?.on('data', stderr.push);\n\t\tchild.once('exit', () => {\n\t\t\tstdout.flush();\n\t\t\tstderr.flush();\n\t\t});\n\t\tchild.once('error', (error) => this.emit('log', 'error', error.message));\n\n\t\treturn child;\n\t}\n\n\t#handleLine(line: string): void {\n\t\tconst text = line.trim();\n\t\tif (text.length === 0) return;\n\n\t\tif (WATCH_START.test(text)) {\n\t\t\tif (this.#startedAt === 0) this.#begin();\n\t\t\treturn;\n\t\t}\n\n\t\tif (ERROR_LINE.test(text)) {\n\t\t\tthis.#firstError ??= text;\n\t\t\tthis.emit('log', 'error', text);\n\t\t\treturn;\n\t\t}\n\n\t\tconst done = WATCH_DONE.exec(text);\n\t\tif (done) {\n\t\t\tconst errors = Number(done[1]);\n\t\t\tthis.emit('log', errors === 0 ? 'success' : 'error', text);\n\t\t\tthis.#finish(errors === 0 ? null : (this.#firstError ?? text));\n\t\t\treturn;\n\t\t}\n\n\t\tthis.emit('log', 'info', text);\n\t}\n\n\t#begin(): void {\n\t\tthis.#firstError = null;\n\t\tthis.#startedAt = performance.now();\n\t\tthis.emit('start');\n\t}\n\n\t#finish(message: string | null): BuildOutcome {\n\t\tconst outcome: BuildOutcome = { ok: message === null, durationMs: Math.round(performance.now() - this.#startedAt), message };\n\t\tthis.#startedAt = 0;\n\t\tthis.emit(outcome.ok ? 'success' : 'failure', outcome);\n\t\treturn outcome;\n\t}\n}\n\n/**\n * Locates the `tsc` script of the project's TypeScript through its `package.json#bin`, which works for both the\n * classic `lib/tsc.js` layout (TypeScript ≤ 6) and the native `bin/tsc` launcher (TypeScript 7, whose `exports` map\n * hides `lib/`).\n */\nexport function resolveTscBinary(root: string): string | null {\n\treturn resolveBinary(root, 'typescript', 'tsc');\n}\n"],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- import { n as resolveTscBinary, t as TscBuilder } from "./tsc-BTuFXw3O.js";
2
-
3
- export { TscBuilder };
@@ -1 +0,0 @@
1
- {"version":3,"file":"tui-BCGQrMQo.js","names":[],"sources":["../src/renderers/ink/theme.tsx","../src/renderers/ink/components/HelpOverlay.tsx","../src/renderers/ink/hooks/useLogVersion.ts","../src/renderers/ink/components/Hints.tsx","../src/renderers/ink/components/LogBrowser.tsx","../src/renderers/ink/hooks/useDevStatus.ts","../src/renderers/ink/hooks/useUptime.ts","../src/renderers/panel-logic.ts","../src/renderers/ink/components/InfoOverlay.tsx","../src/renderers/ink/components/Panel.tsx","../src/renderers/ink/hooks/useLogCounters.ts","../src/renderers/ink/hooks/useBuildClock.ts","../src/lib/open-url.ts","../src/renderers/ink/DevApp.tsx","../src/renderers/capture-output.ts","../src/renderers/tui.tsx"],"sourcesContent":["import { createContext, useContext, type ReactNode } from 'react';\n\n/**\n * Whether the UI may use colour. `stars dev` decides this once (`NO_COLOR`, `FORCE_COLOR`, TTY detection) and every\n * component reads it from here instead of re-deriving it.\n */\nconst ColorContext = createContext(true);\n\nexport function ColorProvider({ color, children }: { color: boolean; children: ReactNode }) {\n\treturn <ColorContext value={color}>{children}</ColorContext>;\n}\n\n/**\n * Returns a colour name only when colour is enabled, so `<Text color={useColor()('green')}>` degrades to plain text.\n */\nexport function useColor(): (name: string) => string | undefined {\n\tconst enabled = useContext(ColorContext);\n\treturn (name) => (enabled ? name : undefined);\n}\n","import { Box, Text, useInput } from 'ink';\nimport { useColor } from '../theme.js';\n\nconst KEYS: [string, string][] = [\n\t['r', 'restart the bot now'],\n\t['o', 'open the local URL in a browser'],\n\t['t', 'toggle the public tunnel'],\n\t['i', 'show versions, URLs and session info'],\n\t['l', 'open the logs (scroll, filter by source or level)'],\n\t['e', 'jump to the last error, keeping its context'],\n\t['c / Ctrl+L', 'clear the log history'],\n\t['q / Ctrl+C', 'stop the bot and quit'],\n\t['?', 'toggle this help']\n];\n\nexport interface HelpOverlayProps {\n\theight: number;\n\twidth: number;\n\tonClose: () => void;\n}\n\n/** The static keys reference, opened with `?` from the pinned panel. */\nexport function HelpOverlay({ height, width, onClose }: HelpOverlayProps) {\n\tconst paint = useColor();\n\tuseInput((input, key) => {\n\t\tif (!key.ctrl && (key.escape || ['q', 'h', '?'].includes(input))) onClose();\n\t});\n\n\treturn (\n\t\t<Box flexDirection=\"column\" height={height}>\n\t\t\t<Text bold> keyboard shortcuts</Text>\n\t\t\t<Text dimColor>{'─'.repeat(width)}</Text>\n\t\t\t{KEYS.slice(0, Math.max(0, height - 3)).map(([key, description]) => (\n\t\t\t\t<Text key={key} wrap=\"truncate-end\">\n\t\t\t\t\t{' '}\n\t\t\t\t\t<Text bold color={paint('white')}>\n\t\t\t\t\t\t{key.padEnd(14)}\n\t\t\t\t\t</Text>\n\t\t\t\t\t<Text dimColor>{description}</Text>\n\t\t\t\t</Text>\n\t\t\t))}\n\t\t\t<Box flexGrow={1} />\n\t\t\t<Text dimColor> q close</Text>\n\t\t</Box>\n\t);\n}\n","import { useEffect, useState } from 'react';\nimport type { LogBuffer } from '../../../lib/log-buffer.js';\n\n/** Bumps whenever the buffer changes, so a consumer can re-derive a filtered view without re-filtering on every render. */\nexport function useLogVersion(logs: LogBuffer): number {\n\tconst [version, setVersion] = useState(0);\n\n\tuseEffect(() => {\n\t\tconst bump = () => setVersion((current) => current + 1);\n\t\tlogs.on('entry', bump);\n\t\tlogs.on('clear', bump);\n\t\tbump();\n\t\treturn () => {\n\t\t\tlogs.off('entry', bump);\n\t\t\tlogs.off('clear', bump);\n\t\t};\n\t}, [logs]);\n\n\treturn version;\n}\n","import { Text } from 'ink';\n\nexport interface Hint {\n\tkey: string;\n\tlabel: string;\n\tpriority: number;\n}\n\nexport const PANEL_HINTS: Hint[] = [\n\t{ key: 'r', label: 'restart', priority: 80 },\n\t{ key: 'o', label: 'open', priority: 40 },\n\t{ key: 't', label: 'tunnel', priority: 60 },\n\t{ key: 'i', label: 'info', priority: 50 },\n\t{ key: 'l', label: 'logs', priority: 70 },\n\t{ key: '?', label: 'help', priority: 100 },\n\t{ key: 'q', label: 'quit', priority: 90 }\n];\n\n/** Drop the lowest-priority shortcuts first; help and the last error survive narrow panes. */\nexport function Hints({ hints, width }: { hints: readonly Hint[]; width: number }) {\n\tconst shown = [...hints];\n\tconst length = () => shown.reduce((size, hint) => size + hint.key.length + hint.label.length + 4, -2);\n\twhile (shown.length > 1 && length() > width) {\n\t\tconst weakest = shown.reduce((a, b) => (a.priority <= b.priority ? a : b));\n\t\tshown.splice(shown.indexOf(weakest), 1);\n\t}\n\treturn (\n\t\t<Text wrap=\"truncate-end\">\n\t\t\t{' '}\n\t\t\t{shown.map(({ key, label }, i) => (\n\t\t\t\t<Text key={key}>\n\t\t\t\t\t{i > 0 && <Text dimColor> · </Text>}\n\t\t\t\t\t<Text bold>{key}</Text>\n\t\t\t\t\t<Text dimColor>{` ${label}`}</Text>\n\t\t\t\t</Text>\n\t\t\t))}\n\t\t</Text>\n\t);\n}\n","import { Box, Text, useInput } from 'ink';\nimport { useMemo, useState } from 'react';\nimport { stripVTControlCharacters } from 'node:util';\nimport type { DevService } from '../../../lib/dev-service.js';\nimport { isErrorDetail, type LogEntry, type LogLevel } from '../../../lib/log-buffer.js';\nimport { useLogVersion } from '../hooks/useLogVersion.js';\nimport { useColor } from '../theme.js';\nimport { Hints } from './Hints.js';\n\nexport interface LogBrowserProps {\n\tservice: DevService;\n\theight: number;\n\twidth: number;\n\tlastError?: boolean;\n\tonClose: () => void;\n\tonCopy?: (text: string) => void;\n}\n\nconst group = (entry: LogEntry) => (entry.source === 'app' ? 'runtime' : entry.source === 'build' || entry.source === 'tsc' ? 'build' : 'cli');\n\n/** Filterable history, using Nuxt's keys and selecting the last error without discarding its context. */\nexport function LogBrowser({ service, height, width, lastError = false, onClose, onCopy }: LogBrowserProps) {\n\tconst paint = useColor();\n\tconst [sources, setSources] = useState({ cli: true, build: true, runtime: true });\n\tconst [level, setLevel] = useState<LogLevel | null>(null);\n\tconst [query, setQuery] = useState('');\n\tconst [searching, setSearching] = useState(false);\n\tconst [selected, setSelected] = useState<number | null>(() =>\n\t\tlastError ? (service.logs.entries().findLast((entry) => entry.level === 'error' && !isErrorDetail(entry))?.id ?? null) : null\n\t);\n\tconst version = useLogVersion(service.logs);\n\tconst entries = useMemo(\n\t\t() =>\n\t\t\tservice.logs\n\t\t\t\t.filter({ level })\n\t\t\t\t.filter((entry) => sources[group(entry)] && stripVTControlCharacters(entry.text).toLowerCase().includes(query.toLowerCase())),\n\t\t[service, sources, level, query, version]\n\t);\n\tconst bodyHeight = Math.max(0, height - 3);\n\tconst index = entries.findIndex((entry) => entry.id === selected);\n\tconst rows = entries.flatMap((entry) =>\n\t\tstripVTControlCharacters(entry.text)\n\t\t\t.split('\\n')\n\t\t\t.map((line, i) => ({\n\t\t\t\tentry,\n\t\t\t\ttext: i === 0 ? `${new Date(entry.time).toLocaleTimeString()} ${entry.source.padEnd(6)} ${line}` : ` ${line}`\n\t\t\t}))\n\t);\n\tconst selectedStart = rows.findIndex((row) => row.entry.id === selected);\n\tconst selectedEnd = rows.findLastIndex((row) => row.entry.id === selected) + 1;\n\tconst end =\n\t\tindex < 0 ? rows.length : Math.min(rows.length, selectedStart + Math.max(bodyHeight, Math.min(selectedEnd - selectedStart, bodyHeight)));\n\tconst visible = rows.slice(Math.max(0, end - bodyHeight), end);\n\tconst move = (delta: number) => {\n\t\tif (!entries.length) return;\n\t\tconst next = index < 0 ? (delta < 0 ? entries.length - 1 : 0) : Math.max(0, Math.min(entries.length - 1, index + delta));\n\t\tsetSelected(entries[next]!.id);\n\t};\n\n\tuseInput((input, key) => {\n\t\tif (key.ctrl) return;\n\t\tif (searching) {\n\t\t\tif (key.escape) {\n\t\t\t\tsetSearching(false);\n\t\t\t\tsetQuery('');\n\t\t\t} else if (key.return) setSearching(false);\n\t\t\telse if (key.backspace || key.delete) setQuery((value) => [...value].slice(0, -1).join(''));\n\t\t\telse if (input && !key.upArrow && !key.downArrow) setQuery((value) => value + input);\n\t\t\tsetSelected(null);\n\t\t\treturn;\n\t\t}\n\t\tif (key.escape || input === 'l' || input === 'q') return onClose();\n\t\tif (input === '/') return setSearching(true);\n\t\tif (input === 'e' || input === 'w' || input === 'a') {\n\t\t\tconst next = input === 'e' ? 'error' : input === 'w' ? 'warn' : null;\n\t\t\tsetLevel((current) => (current === next ? null : next));\n\t\t\treturn setSelected(null);\n\t\t}\n\t\tif (input === 'c' || input === 'b' || input === 'r') {\n\t\t\tconst source = input === 'c' ? 'cli' : input === 'b' ? 'build' : 'runtime';\n\t\t\tsetSources((current) => {\n\t\t\t\tconst next = { ...current, [source]: !current[source] };\n\t\t\t\treturn Object.values(next).some(Boolean) ? next : current;\n\t\t\t});\n\t\t\treturn setSelected(null);\n\t\t}\n\t\tif (input === 'x') {\n\t\t\tservice.clearLogs();\n\t\t\treturn setSelected(null);\n\t\t}\n\t\tif (key.upArrow || input === 'k') return move(-1);\n\t\tif (key.downArrow || input === 'j') return move(1);\n\t\tif (key.pageUp) return move(-Math.max(1, bodyHeight));\n\t\tif (key.pageDown) return move(Math.max(1, bodyHeight));\n\t\tif (key.home || input === 'g') return setSelected(entries[0]?.id ?? null);\n\t\tif (key.end || input === 'G') return setSelected(null);\n\t\tif ((key.return || input === 'y') && index >= 0) onCopy?.(stripVTControlCharacters(entries[index]!.text));\n\t});\n\n\tconst hints = searching\n\t\t? [\n\t\t\t\t['enter', 'apply'],\n\t\t\t\t['esc', 'cancel']\n\t\t\t]\n\t\t: [\n\t\t\t\t['↑/↓', 'select'],\n\t\t\t\t['g/G', 'top/bottom'],\n\t\t\t\t['e', 'errors'],\n\t\t\t\t['w', 'warnings'],\n\t\t\t\t['a', 'all'],\n\t\t\t\t['c/b/r', 'sources'],\n\t\t\t\t['/', 'search'],\n\t\t\t\t['x', 'clear'],\n\t\t\t\t['enter', 'copy'],\n\t\t\t\t['q', 'close']\n\t\t\t];\n\treturn (\n\t\t<Box flexDirection=\"column\" height={height}>\n\t\t\t<Text wrap=\"truncate-end\">\n\t\t\t\t{' '}\n\t\t\t\t<Text bold>logs</Text>\n\t\t\t\t<Text dimColor>{` · ${Object.entries(sources)\n\t\t\t\t\t.filter(([, shown]) => shown)\n\t\t\t\t\t.map(([source]) => source)\n\t\t\t\t\t.join(\n\t\t\t\t\t\t'+'\n\t\t\t\t\t)} · ${level ? `${level}+ only` : 'all levels'}${query || searching ? ` · search ${query}${searching ? '▏' : ''}` : ''}`}</Text>\n\t\t\t</Text>\n\t\t\t<Text dimColor>{'─'.repeat(width)}</Text>\n\t\t\t<Box flexDirection=\"column\" height={bodyHeight} overflow=\"hidden\">\n\t\t\t\t{visible.length === 0 && <Text dimColor> no matching logs</Text>}\n\t\t\t\t{visible.map(({ entry, text }, i) => (\n\t\t\t\t\t<Text key={`${entry.id}-${i}`} wrap=\"truncate-end\">\n\t\t\t\t\t\t<Text color={paint('green')}>{entry.id === selected ? '▎ ' : ' '}</Text>\n\t\t\t\t\t\t<Text\n\t\t\t\t\t\t\tcolor={paint(\n\t\t\t\t\t\t\t\tentry.level === 'error' ? 'red' : entry.level === 'warn' ? 'yellow' : entry.level === 'success' ? 'green' : 'white'\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\tdimColor={isErrorDetail(entry)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{text}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t</Text>\n\t\t\t\t))}\n\t\t\t</Box>\n\t\t\t<Hints\n\t\t\t\twidth={width}\n\t\t\t\thints={hints.map(([key, label], i) => ({ key: key!, label: label!, priority: i === hints.length - 1 ? 100 : hints.length - i }))}\n\t\t\t/>\n\t\t</Box>\n\t);\n}\n","import { useEffect, useState } from 'react';\nimport type { DevService, DevStatus } from '../../../lib/dev-service.js';\n\n/**\n * Mirrors the service's status into React state. The service stays the single source of truth: the UI only\n * subscribes to it, exactly like the plain renderer does.\n */\nexport function useDevStatus(service: DevService): DevStatus {\n\tconst [status, setStatus] = useState<DevStatus>(() => service.status);\n\n\tuseEffect(() => {\n\t\tconst onStatus = (next: DevStatus) => setStatus(next);\n\t\tservice.on('status', onStatus);\n\t\tsetStatus(service.status);\n\t\treturn () => {\n\t\t\tservice.off('status', onStatus);\n\t\t};\n\t}, [service]);\n\n\treturn status;\n}\n","import { useEffect, useState } from 'react';\n\n/**\n * Re-renders once a second while the bot is up, so the uptime in the header keeps counting.\n */\nexport function useUptime(startedAt: number | null): number | null {\n\tconst [now, setNow] = useState(() => Date.now());\n\n\tuseEffect(() => {\n\t\tif (startedAt === null) return;\n\n\t\tsetNow(Date.now());\n\t\tconst timer = setInterval(() => setNow(Date.now()), 1000);\n\t\treturn () => clearInterval(timer);\n\t}, [startedAt]);\n\n\treturn startedAt === null ? null : now - startedAt;\n}\n","import type { DevStatus } from '../lib/dev-service.js';\n\nexport type Badge = 'starting' | 'building' | 'restarting' | 'ready' | 'error';\n\n/**\n * The badge and standing description for the panel's status row, mirroring the states Nuxt CLI v4's own dev panel\n * cycles through (`STARTING`/`BUILDING`/`RESTART`/`READY`/`ERROR`).\n */\nexport function describeBadge(status: DevStatus): { badge: Badge; note: string } {\n\tif (status.build === 'building') return { badge: status.startedAt === null ? 'starting' : 'building', note: status.progress.message };\n\tif (status.process === 'starting') return { badge: 'starting', note: 'starting the bot' };\n\tif (status.process === 'stopping') return { badge: 'restarting', note: 'restarting the bot' };\n\tif (status.build === 'failed') return { badge: 'error', note: 'build failed, waiting for changes' };\n\tif (status.process === 'crashed') return { badge: 'error', note: 'the bot crashed, press r to restart' };\n\tif (status.health === 'down') return { badge: 'error', note: 'health check failed' };\n\tif (status.typecheck === 'failed') return { badge: 'error', note: 'type check failed, press e to view it' };\n\tif (status.process === 'stopped') return { badge: 'error', note: 'the bot stopped, press r to restart' };\n\tif (status.progress.fraction < 1) return { badge: 'starting', note: status.progress.message };\n\tif (status.process === 'running') return { badge: 'ready', note: 'watching for changes' };\n\treturn { badge: 'starting', note: 'waiting for the first build' };\n}\n\n/** Formats a duration the way a dev session reads it: `mm:ss` under an hour, `h:mm:ss` above. */\nexport function formatDuration(milliseconds: number): string {\n\tconst total = Math.max(0, Math.floor(milliseconds / 1000));\n\tconst seconds = total % 60;\n\tconst minutes = Math.floor(total / 60) % 60;\n\tconst hours = Math.floor(total / 3600);\n\tconst pad = (value: number) => value.toString().padStart(2, '0');\n\n\treturn hours > 0 ? `${hours}:${pad(minutes)}:${pad(seconds)}` : `${pad(minutes)}:${pad(seconds)}`;\n}\n","import { Box, Text, useInput } from 'ink';\nimport type { DevService } from '../../../lib/dev-service.js';\nimport { useDevStatus } from '../hooks/useDevStatus.js';\nimport { useUptime } from '../hooks/useUptime.js';\nimport { formatDuration } from '../../panel-logic.js';\n\nexport function InfoOverlay({ service, height, width, onClose }: { service: DevService; height: number; width: number; onClose: () => void }) {\n\tconst status = useDevStatus(service);\n\tconst uptime = useUptime(status.startedAt);\n\tuseInput((input, key) => {\n\t\tif (!key.ctrl && (key.escape || ['q', 'i'].includes(input))) onClose();\n\t});\n\tconst lines = [\n\t\t['Project', service.config.packageJson?.name ?? 'stars project'],\n\t\t['Root', service.config.root],\n\t\t['Node', process.version],\n\t\t['Builder', service.builder.tool],\n\t\t['Local', status.url ?? '—'],\n\t\t['Tunnel', status.tunnelUrl ?? status.tunnel],\n\t\t['Process', `${status.process}${status.pid ? ` (${status.pid})` : ''}`],\n\t\t['Uptime', uptime === null ? '—' : formatDuration(uptime)],\n\t\t['Restarts', String(status.restarts)],\n\t\t['Health', service.config.dev.health ? status.health : 'not configured (READY reports process state)'],\n\t\t['Types', `${status.typecheck}${status.typeErrors ? ` (${status.typeErrors} errors)` : ''}`],\n\t\t['Log file', service.config.dev.logFile ?? 'disabled']\n\t];\n\treturn (\n\t\t<Box flexDirection=\"column\" height={height}>\n\t\t\t<Text bold wrap=\"truncate-end\">\n\t\t\t\t{' '}\n\t\t\t\tsession info\n\t\t\t</Text>\n\t\t\t<Text dimColor>{'─'.repeat(width)}</Text>\n\t\t\t{lines.slice(0, Math.max(0, height - 3)).map(([label, value]) => (\n\t\t\t\t<Text key={label} wrap=\"truncate-end\">\n\t\t\t\t\t{' '}\n\t\t\t\t\t<Text bold>{label!.padEnd(10)}</Text>\n\t\t\t\t\t<Text dimColor>{value}</Text>\n\t\t\t\t</Text>\n\t\t\t))}\n\t\t\t<Box flexGrow={1} />\n\t\t\t<Text dimColor> q close</Text>\n\t\t</Box>\n\t);\n}\n","import { Box, Text } from 'ink';\nimport type { ReactNode } from 'react';\nimport type { ResolvedStarsConfig } from '@wolfstar/http-framework/config';\nimport type { DevStatus } from '../../../lib/dev-service.js';\nimport { readOwnPackageJson } from '../../../lib/version.js';\nimport type { LogCounters } from '../hooks/useLogCounters.js';\nimport { describeBadge } from '../../panel-logic.js';\nimport { useColor } from '../theme.js';\nimport { Hints, PANEL_HINTS } from './Hints.js';\n\nexport interface PanelProps {\n\tstatus: DevStatus;\n\tconfig: ResolvedStarsConfig;\n\tcounters: LogCounters;\n\tframe: number;\n\telapsedMs: number;\n\twidth: number;\n\theight: number;\n\tconfirmQuit: boolean;\n}\n\n/** Nuxt's wordmark / URLs / progress / status / hints layout, with Stars branding. */\nexport function Panel({ status, config, counters, frame, elapsedMs, width, height, confirmQuit }: PanelProps) {\n\tconst paint = useColor();\n\tconst state = describeBadge(status);\n\tconst busy = state.badge !== 'ready' && state.badge !== 'error';\n\tconst badge = !busy && counters.errors > 0 ? 'error' : state.badge;\n\tconst note = badge === 'error' && state.badge === 'ready' ? 'an error was logged · press e to view it' : state.note;\n\tconst filled = Math.round(Math.min(1, Math.max(0, status.progress.fraction)) * 20);\n\tconst wordmark = config.dev.banner === false ? [] : (config.dev.banner?.flatMap((line) => line.split('\\n')) ?? [null]);\n\tconst blocks: { name: string; content: ReactNode }[] = [\n\t\t...wordmark.slice(0, 4).map((line, index) => ({\n\t\t\tname: 'wordmark',\n\t\t\tcontent: (\n\t\t\t\t<Box key={index} justifyContent=\"space-between\">\n\t\t\t\t\t<Text wrap=\"truncate-end\">\n\t\t\t\t\t\t{' '}\n\t\t\t\t\t\t{line === null ? (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<Text color={paint('green')}>\n\t\t\t\t\t\t\t\t\t{[...'·✦★✦'].map((cell, i) => (\n\t\t\t\t\t\t\t\t\t\t<Text key={i} dimColor={busy && i !== frame % 4}>\n\t\t\t\t\t\t\t\t\t\t\t{cell}\n\t\t\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t{' '}\n\t\t\t\t\t\t\t\t<Text bold color={paint('green')}>\n\t\t\t\t\t\t\t\t\tStars\n\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t<Text dimColor>{` ${readOwnPackageJson().version}`}</Text>\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<Text color={paint('green')}>{line}</Text>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</Text>\n\t\t\t\t\t{index === 0 && width >= 60 && badge === 'ready' && status.progress.readyMs !== null && (\n\t\t\t\t\t\t<Text dimColor>{`ready in ${(status.progress.readyMs / 1000).toFixed(2)}s `}</Text>\n\t\t\t\t\t)}\n\t\t\t\t</Box>\n\t\t\t)\n\t\t})),\n\t\t{ name: 'space', content: <Text> </Text> },\n\t\t...(status.url\n\t\t\t? [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'urls',\n\t\t\t\t\t\tcontent: (\n\t\t\t\t\t\t\t<Text wrap=\"truncate-end\">\n\t\t\t\t\t\t\t\t{' '}\n\t\t\t\t\t\t\t\t<Text dimColor>{'Local '}</Text>\n\t\t\t\t\t\t\t\t<Text color={paint('cyan')} dimColor={busy}>\n\t\t\t\t\t\t\t\t\t{status.url}\n\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t\t{busy && <Text color={paint('yellow')}>{` ${['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'][frame % 10]}`}</Text>}\n\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t: []),\n\t\t...(status.tunnelUrl\n\t\t\t? [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'urls',\n\t\t\t\t\t\tcontent: (\n\t\t\t\t\t\t\t<Text wrap=\"truncate-end\">\n\t\t\t\t\t\t\t\t{' '}\n\t\t\t\t\t\t\t\t<Text dimColor>{'Tunnel '}</Text>\n\t\t\t\t\t\t\t\t<Text color={paint('magenta')}>{status.tunnelUrl}</Text>\n\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t: []),\n\t\t{ name: 'space', content: <Text> </Text> },\n\t\t{\n\t\t\tname: 'summary',\n\t\t\tcontent: busy ? (\n\t\t\t\t<Text wrap=\"truncate-end\">\n\t\t\t\t\t{' '}\n\t\t\t\t\t<Text color={paint('green')}>{'━'.repeat(filled)}</Text>\n\t\t\t\t\t<Text dimColor>\n\t\t\t\t\t\t{'━'.repeat(20 - filled)}\n\t\t\t\t\t\t{` ${Math.round(status.progress.fraction * 100)}% · ${(elapsedMs / 1000).toFixed(1)}s`}\n\t\t\t\t\t</Text>\n\t\t\t\t</Text>\n\t\t\t) : (\n\t\t\t\t<Text wrap=\"truncate-end\">\n\t\t\t\t\t{' '}\n\t\t\t\t\t{counters.warnings > 0 && (\n\t\t\t\t\t\t<Text color={paint('yellow')}>{`⚠ ${counters.warnings} ${plural(counters.warnings, 'warning')} `}</Text>\n\t\t\t\t\t)}\n\t\t\t\t\t{counters.errors > 0 && <Text bold color={paint('red')}>{`✖ ${counters.errors} ${plural(counters.errors, 'error')} `}</Text>}\n\t\t\t\t\t{counters.errors === 0 && counters.warnings === 0 && (\n\t\t\t\t\t\t<Text dimColor>\n\t\t\t\t\t\t\t{status.typecheck === 'checking'\n\t\t\t\t\t\t\t\t? 'checking types'\n\t\t\t\t\t\t\t\t: status.tunnel === 'failed'\n\t\t\t\t\t\t\t\t\t? 'tunnel failed · press l to view logs'\n\t\t\t\t\t\t\t\t\t: 'logs folded away · press l to view'}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t)}\n\t\t\t\t</Text>\n\t\t\t)\n\t\t},\n\t\t{ name: 'space', content: <Text> </Text> },\n\t\t{\n\t\t\tname: 'status',\n\t\t\tcontent: (\n\t\t\t\t<Text wrap=\"truncate-end\">\n\t\t\t\t\t{' '}\n\t\t\t\t\t<Text\n\t\t\t\t\t\tbold\n\t\t\t\t\t\tbackgroundColor={paint(confirmQuit || busy ? 'yellow' : badge === 'error' ? 'red' : 'green')}\n\t\t\t\t\t\tcolor={paint(badge === 'error' && !confirmQuit ? 'white' : 'black')}\n\t\t\t\t\t>{` ${confirmQuit ? 'QUIT?' : badge === 'restarting' ? 'RESTART' : badge.toUpperCase()} `}</Text>\n\t\t\t\t\t{' '}\n\t\t\t\t\t<Text dimColor>{confirmQuit ? 'press y to confirm, esc to stay' : note}</Text>\n\t\t\t\t</Text>\n\t\t\t)\n\t\t},\n\t\t{\n\t\t\tname: 'hints',\n\t\t\tcontent: confirmQuit ? (\n\t\t\t\t<Text> </Text>\n\t\t\t) : (\n\t\t\t\t<Hints width={width} hints={[...(counters.errors ? [{ key: 'e', label: 'last error', priority: Infinity }] : []), ...PANEL_HINTS]} />\n\t\t\t)\n\t\t}\n\t];\n\tlet shown = blocks;\n\tconst budget = Math.max(2, Math.min(height, 14));\n\tfor (const name of ['space', 'summary', 'urls', 'wordmark']) {\n\t\tif (shown.length <= budget) break;\n\t\tshown = shown.filter((block) => block.name !== name);\n\t}\n\tshown = shown.filter((block, i, all) => block.name !== 'space' || (i > 0 && i < all.length - 1 && all[i - 1]?.name !== 'space'));\n\treturn (\n\t\t<Box flexDirection=\"column\">\n\t\t\t{shown.map((block, index) => (\n\t\t\t\t<Box key={index} flexDirection=\"column\" height={1}>\n\t\t\t\t\t{block.content}\n\t\t\t\t</Box>\n\t\t\t))}\n\t\t</Box>\n\t);\n}\n\nfunction plural(count: number, word: string): string {\n\treturn count === 1 ? word : `${word}s`;\n}\n","import { useEffect, useState } from 'react';\nimport type { DevService, DevStatus } from '../../../lib/dev-service.js';\nimport { isErrorDetail, type LogEntry } from '../../../lib/log-buffer.js';\n\nexport interface LogCounters {\n\twarnings: number;\n\terrors: number;\n}\n\n/**\n * Warnings and errors logged since the last successful build, the way Nuxt CLI v4's own panel counts them: the\n * badge's job is the current state, this line is what happened getting there.\n */\nexport function useLogCounters(service: DevService): LogCounters {\n\tconst count = () =>\n\t\tservice.logs.entries().reduce<LogCounters>(\n\t\t\t(total, entry) => ({\n\t\t\t\twarnings: total.warnings + Number(entry.level === 'warn'),\n\t\t\t\terrors: total.errors + Number(entry.level === 'error' && !isErrorDetail(entry))\n\t\t\t}),\n\t\t\t{ warnings: 0, errors: 0 }\n\t\t);\n\tconst [counters, setCounters] = useState<LogCounters>(count);\n\n\tuseEffect(() => {\n\t\tlet previousBuild: DevStatus['build'] = service.status.build;\n\t\tlet previousStart = service.status.startedAt;\n\n\t\tconst onEntry = (entry: LogEntry) => {\n\t\t\tif (entry.level === 'warn') setCounters((current) => ({ ...current, warnings: current.warnings + 1 }));\n\t\t\telse if (entry.level === 'error' && !isErrorDetail(entry)) setCounters((current) => ({ ...current, errors: current.errors + 1 }));\n\t\t};\n\n\t\tconst onStatus = (status: DevStatus) => {\n\t\t\tif (\n\t\t\t\t(status.build === 'building' && previousBuild !== 'building' && previousBuild !== 'idle') ||\n\t\t\t\t(status.lastRestartReason === 'manual' && status.startedAt !== null && status.startedAt !== previousStart)\n\t\t\t)\n\t\t\t\tsetCounters({ warnings: 0, errors: 0 });\n\t\t\tpreviousBuild = status.build;\n\t\t\tpreviousStart = status.startedAt;\n\t\t};\n\n\t\tservice.logs.on('entry', onEntry);\n\t\tconst onClear = () => setCounters({ warnings: 0, errors: 0 });\n\t\tservice.logs.on('clear', onClear);\n\t\tservice.on('status', onStatus);\n\t\tsetCounters(count());\n\t\treturn () => {\n\t\t\tservice.logs.off('entry', onEntry);\n\t\t\tservice.logs.off('clear', onClear);\n\t\t\tservice.off('status', onStatus);\n\t\t};\n\t}, [service]);\n\n\treturn counters;\n}\n","import { useEffect, useState } from 'react';\n\n/** The clock moves during a long compiler phase; the percentage only moves on real build events. */\nexport function useBuildClock(startedAt: number, active: boolean, reducedMotion: boolean) {\n\tconst [now, setNow] = useState(Date.now);\n\tuseEffect(() => {\n\t\tif (!active) return;\n\t\tsetNow(Date.now());\n\t\tconst timer = setInterval(() => setNow(Date.now()), reducedMotion ? 1000 : 120);\n\t\treturn () => clearInterval(timer);\n\t}, [startedAt, active, reducedMotion]);\n\tconst elapsedMs = Math.max(0, now - startedAt);\n\treturn { elapsedMs, frame: reducedMotion ? 0 : Math.floor(elapsedMs / 120) };\n}\n","import { execFile } from 'node:child_process';\n\n/** Called only on an explicit `o` keypress, with no shell interpolation. */\nexport function openDevUrl(value: string | null): Promise<void> {\n\tif (!value) return Promise.resolve();\n\tconst url = new URL(value);\n\tif (url.protocol !== 'http:' && url.protocol !== 'https:') return Promise.reject(new Error('Only HTTP(S) URLs can be opened.'));\n\tconst [command, args] =\n\t\tprocess.platform === 'win32'\n\t\t\t? (['rundll32', ['url.dll,FileProtocolHandler', url.href]] as const)\n\t\t\t: process.platform === 'darwin'\n\t\t\t\t? (['open', [url.href]] as const)\n\t\t\t\t: (['xdg-open', [url.href]] as const);\n\treturn new Promise((resolve, reject) =>\n\t\texecFile(command, [...args], (error) => (error ? reject(new Error(`Could not open the browser: ${error.message}`)) : resolve()))\n\t);\n}\n","import { Box, useInput, useWindowSize } from 'ink';\nimport { useState } from 'react';\nimport type { DevService } from '../../lib/dev-service.js';\nimport { HelpOverlay } from './components/HelpOverlay.js';\nimport { LogBrowser } from './components/LogBrowser.js';\nimport { InfoOverlay } from './components/InfoOverlay.js';\nimport { Panel } from './components/Panel.js';\nimport { useDevStatus } from './hooks/useDevStatus.js';\nimport { useLogCounters } from './hooks/useLogCounters.js';\nimport { useBuildClock } from './hooks/useBuildClock.js';\nimport { describeBadge } from '../panel-logic.js';\nimport { openDevUrl } from '../../lib/open-url.js';\nimport { ColorProvider } from './theme.js';\n\nexport interface DevAppProps {\n\tservice: DevService;\n\tcolor: boolean;\n\treducedMotion: boolean;\n\t/** Called when the user asks to quit, so the CLI can stop the bot and exit. */\n\tonQuit: () => void;\n\tonViewChange: (overlay: boolean) => void;\n\tonCopy: (text: string) => void;\n}\n\ntype View = 'panel' | 'logs' | 'errors' | 'help' | 'info';\n\n/**\n * A bottom-aligned panel in the normal buffer, with logs folded away. Only the browsable overlays use the\n * alternate screen, preserving the terminal's history and the panel when they close.\n */\nexport function DevApp({ service, color, reducedMotion, onQuit, onViewChange, onCopy }: DevAppProps) {\n\tconst { columns, rows } = useWindowSize();\n\tconst [view, setView] = useState<View>('panel');\n\tconst [confirmQuit, setConfirmQuit] = useState(false);\n\n\tconst status = useDevStatus(service);\n\tconst counters = useLogCounters(service);\n\tconst badge = describeBadge(status).badge;\n\tconst busy = badge !== 'ready' && badge !== 'error';\n\tconst clock = useBuildClock(status.progress.startedAt, busy && view === 'panel', reducedMotion);\n\n\tconst width = Math.max(1, columns);\n\tconst height = Math.max(2, rows - 1);\n\n\tconst changeView = (next: View) => {\n\t\tonViewChange(next !== 'panel');\n\t\tsetView(next);\n\t};\n\n\tuseInput((input, key) => {\n\t\tif (key.ctrl && input === 'c') return onQuit();\n\t\tif (key.ctrl && input === 'l') return service.clearLogs();\n\t\tif (view !== 'panel') return;\n\t\tif (confirmQuit) {\n\t\t\tif (input === 'y') return onQuit();\n\t\t\treturn setConfirmQuit(false);\n\t\t}\n\t\tif (key.ctrl && input === 'r') return void service.restart('manual');\n\t\tif (key.ctrl && input === 'd') return busy ? setConfirmQuit(true) : onQuit();\n\n\t\tswitch (input) {\n\t\t\tcase 'q':\n\t\t\t\treturn busy ? setConfirmQuit(true) : onQuit();\n\t\t\tcase 'r':\n\t\t\t\treturn void service.restart('manual');\n\t\t\tcase 'l':\n\t\t\t\treturn changeView('logs');\n\t\t\tcase 'e':\n\t\t\t\treturn changeView('errors');\n\t\t\tcase 'c':\n\t\t\t\treturn service.clearLogs();\n\t\t\tcase 'o':\n\t\t\t\treturn void openDevUrl(status.url).catch((error: Error) => service.log('stars', 'warn', error.message));\n\t\t\tcase 't':\n\t\t\t\treturn void service.toggleTunnel();\n\t\t\tcase 'i':\n\t\t\t\treturn changeView('info');\n\t\t\tcase 'h':\n\t\t\tcase '?':\n\t\t\t\treturn changeView('help');\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t});\n\n\treturn (\n\t\t<ColorProvider color={color}>\n\t\t\t<Box width={width} height={height} flexDirection=\"column\" justifyContent={view === 'panel' ? 'flex-end' : 'flex-start'}>\n\t\t\t\t{(view === 'logs' || view === 'errors') && (\n\t\t\t\t\t<LogBrowser\n\t\t\t\t\t\tservice={service}\n\t\t\t\t\t\theight={height}\n\t\t\t\t\t\twidth={width}\n\t\t\t\t\t\tlastError={view === 'errors'}\n\t\t\t\t\t\tonCopy={onCopy}\n\t\t\t\t\t\tonClose={() => changeView('panel')}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t\t{view === 'help' && <HelpOverlay height={height} width={width} onClose={() => changeView('panel')} />}\n\t\t\t\t{view === 'info' && <InfoOverlay service={service} height={height} width={width} onClose={() => changeView('panel')} />}\n\t\t\t\t{view === 'panel' && (\n\t\t\t\t\t<Panel\n\t\t\t\t\t\tstatus={status}\n\t\t\t\t\t\tconfig={service.config}\n\t\t\t\t\t\tcounters={counters}\n\t\t\t\t\t\t{...clock}\n\t\t\t\t\t\twidth={width}\n\t\t\t\t\t\theight={height}\n\t\t\t\t\t\tconfirmQuit={confirmQuit}\n\t\t\t\t\t/>\n\t\t\t\t)}\n\t\t\t</Box>\n\t\t</ColorProvider>\n\t);\n}\n","import { StringDecoder } from 'node:string_decoder';\nimport type { DevService } from '../lib/dev-service.js';\nimport { classifyAppLine, type LogLevel } from '../lib/log-buffer.js';\n\n/** Capture third-party writes before build plugins run. Ink writes through a separate, unpatched sink. */\nexport function captureOutput(service: DevService, stream: NodeJS.WriteStream, fallback: LogLevel): () => void {\n\tconst original = stream.write;\n\tconst decoder = new StringDecoder('utf8');\n\tlet pending = '';\n\tconst emit = (text: string) => {\n\t\tif (text.trim()) service.log('build', classifyAppLine(text, fallback), text);\n\t};\n\tconst write: typeof stream.write = (chunk: unknown, encoding?: unknown, callback?: unknown) => {\n\t\tpending += typeof chunk === 'string' ? chunk : chunk instanceof Uint8Array ? decoder.write(Buffer.from(chunk)) : String(chunk);\n\t\tconst lines = pending.split(/\\r?\\n/);\n\t\tpending = lines.pop() ?? '';\n\t\tfor (const line of lines) emit(line);\n\t\t// A tool without newlines must not grow the capture indefinitely.\n\t\tif (pending.length > 65536) {\n\t\t\temit(pending);\n\t\t\tpending = '';\n\t\t}\n\t\tconst done = typeof encoding === 'function' ? encoding : callback;\n\t\tif (typeof done === 'function') queueMicrotask(() => done());\n\t\treturn true;\n\t};\n\tstream.write = write;\n\treturn () => {\n\t\tif (stream.write === write) stream.write = original;\n\t\temit(pending + decoder.end());\n\t\tpending = '';\n\t};\n}\n","import { render } from 'ink';\nimport type { DevService } from '../lib/dev-service.js';\nimport { DevApp } from './ink/DevApp.js';\nimport type { Renderer } from './plain.js';\nimport { captureOutput } from './capture-output.js';\nimport { isErrorDetail } from '../lib/log-buffer.js';\n\nexport interface TuiRendererOptions {\n\tstdout?: NodeJS.WriteStream;\n\tstdin?: NodeJS.ReadStream;\n\tcolor?: boolean;\n\t/** Freezes spinners, for `STARS_REDUCED_MOTION=1`. */\n\treducedMotion?: boolean;\n\t/** Caps how often Ink repaints; the default is Ink's own. */\n\tfps?: number;\n}\n\n/**\n * A normal-buffer, bottom-aligned panel and alternate-buffer overlays. External output is captured for the log\n * browser; the renderer alone writes to the terminal. Switching views and teardown restore the original buffer.\n *\n * `start()` resolves when the user quits, which is what `stars dev` waits on before shutting the bot down.\n */\nexport function createTuiRenderer(service: DevService, options: TuiRendererOptions = {}): Renderer {\n\tconst stdout = options.stdout ?? process.stdout;\n\tconst stdin = options.stdin ?? process.stdin;\n\tconst write = stdout.write.bind(stdout);\n\t// Bind methods to the real stream (resize subscriptions included), except write which bypasses capture.\n\tconst sink = new Proxy(stdout, {\n\t\tget(target, property) {\n\t\t\tif (property === 'write') return write;\n\t\t\tconst value = Reflect.get(target, property, target);\n\t\t\treturn typeof value === 'function' ? value.bind(target) : value;\n\t\t}\n\t});\n\tconst restoreOutput =\n\t\tstdout === process.stdout ? [captureOutput(service, process.stdout, 'info'), captureOutput(service, process.stderr, 'warn')] : [];\n\tlet alternate = false;\n\tlet stopped = false;\n\tconst switchView = (overlay: boolean) => {\n\t\tif (overlay === alternate || stopped) return;\n\t\tinstance.clear();\n\t\twrite(overlay ? '\\u001B[?1049h\\u001B[H' : '\\u001B[?1049l');\n\t\talternate = overlay;\n\t};\n\n\tlet quit!: () => void;\n\tconst quitting = new Promise<void>((resolve) => {\n\t\tquit = resolve;\n\t});\n\n\tconst instance = render(\n\t\t<DevApp\n\t\t\tservice={service}\n\t\t\tcolor={options.color ?? false}\n\t\t\treducedMotion={options.reducedMotion ?? false}\n\t\t\tonQuit={quit}\n\t\t\tonViewChange={switchView}\n\t\t\tonCopy={(text) => write(`\\u001B]52;c;${Buffer.from(text.slice(0, 65536)).toString('base64')}\\u0007`)}\n\t\t/>,\n\t\t{\n\t\t\tstdout: sink,\n\t\t\tstdin,\n\t\t\t// `stars dev` owns the shutdown: it stops the bot, then exits with the right code.\n\t\t\texitOnCtrlC: false,\n\t\t\tpatchConsole: false,\n\t\t\t// `createTuiRenderer` only runs once `resolveOutputMode()` already picked 'tui' (never in CI or on a\n\t\t\t// non-TTY stdout), so Ink is told to trust that instead of re-deriving it from `process.env.CI`: on a\n\t\t\t// CI runner that env var is set even for this package's own test process, which would otherwise force\n\t\t\t// Ink's non-interactive mode (no repaint until unmount) despite the fake stdin/stdout looking like a\n\t\t\t// real TTY.\n\t\t\tinteractive: true,\n\t\t\t...(options.fps === undefined ? {} : { maxFps: options.fps })\n\t\t}\n\t);\n\n\treturn {\n\t\tasync start() {\n\t\t\tawait Promise.race([quitting, instance.waitUntilExit()]);\n\t\t},\n\t\tstop() {\n\t\t\tif (stopped) return;\n\t\t\tstopped = true;\n\t\t\tif (alternate) instance.clear();\n\t\t\tinstance.unmount();\n\t\t\tif (alternate) write('\\u001B[?1049l');\n\t\t\twrite('\\u001B[?25h');\n\t\t\tfor (const restore of restoreOutput) restore();\n\t\t\t// A fatal startup must not leave the user with only a folded error and no way to read it.\n\t\t\tif (service.status.progress.readyMs === null) {\n\t\t\t\tconst error = service.logs.entries().findLast((entry) => entry.level === 'error' && !isErrorDetail(entry));\n\t\t\t\tif (error) write(`\\n${error.text}\\n`);\n\t\t\t}\n\t\t\tquit();\n\t\t}\n\t};\n}\n\nexport { formatDuration } from './panel-logic.js';\n"],"mappings":"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"}