uilint 0.2.154 → 0.2.155
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.
|
@@ -397,6 +397,10 @@ function HelpBar({ verbose, activeFilter = "all" }) {
|
|
|
397
397
|
/* @__PURE__ */ jsx7(Text7, { bold: true, color: "cyan", children: "r" }),
|
|
398
398
|
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: " rebuild index" })
|
|
399
399
|
] }),
|
|
400
|
+
/* @__PURE__ */ jsxs7(Box7, { children: [
|
|
401
|
+
/* @__PURE__ */ jsx7(Text7, { bold: true, color: "cyan", children: "x" }),
|
|
402
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: " clear cache" })
|
|
403
|
+
] }),
|
|
400
404
|
/* @__PURE__ */ jsxs7(Box7, { children: [
|
|
401
405
|
/* @__PURE__ */ jsx7(Text7, { bold: true, color: "cyan", children: "\u2191\u2193" }),
|
|
402
406
|
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: " scroll" })
|
|
@@ -412,7 +416,8 @@ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
|
412
416
|
import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
413
417
|
function ServeDashboard({
|
|
414
418
|
onQuit,
|
|
415
|
-
onRebuildIndex
|
|
419
|
+
onRebuildIndex,
|
|
420
|
+
onClearCache
|
|
416
421
|
}) {
|
|
417
422
|
const { exit } = useApp();
|
|
418
423
|
const store = getDashboardStore();
|
|
@@ -479,6 +484,8 @@ function ServeDashboard({
|
|
|
479
484
|
setScrollOffset(0);
|
|
480
485
|
} else if (input === "r") {
|
|
481
486
|
onRebuildIndex?.();
|
|
487
|
+
} else if (input === "x") {
|
|
488
|
+
onClearCache?.();
|
|
482
489
|
} else if (key.downArrow || input === "j") {
|
|
483
490
|
setScrollOffset((prev) => {
|
|
484
491
|
const maxOffset = Math.max(0, state.activities.length - 15);
|
|
@@ -488,7 +495,7 @@ function ServeDashboard({
|
|
|
488
495
|
setScrollOffset((prev) => Math.max(0, prev - 1));
|
|
489
496
|
}
|
|
490
497
|
},
|
|
491
|
-
[exit, onQuit, onRebuildIndex, store, state.activities.length]
|
|
498
|
+
[exit, onQuit, onRebuildIndex, onClearCache, store, state.activities.length]
|
|
492
499
|
)
|
|
493
500
|
);
|
|
494
501
|
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", width: "100%", children: [
|
|
@@ -559,7 +566,8 @@ function renderDashboard(options = {}) {
|
|
|
559
566
|
ServeDashboard,
|
|
560
567
|
{
|
|
561
568
|
onQuit: options.onQuit,
|
|
562
|
-
onRebuildIndex: options.onRebuildIndex
|
|
569
|
+
onRebuildIndex: options.onRebuildIndex,
|
|
570
|
+
onClearCache: options.onClearCache
|
|
563
571
|
}
|
|
564
572
|
)
|
|
565
573
|
);
|
|
@@ -574,4 +582,4 @@ function renderDashboard(options = {}) {
|
|
|
574
582
|
export {
|
|
575
583
|
renderDashboard
|
|
576
584
|
};
|
|
577
|
-
//# sourceMappingURL=render-
|
|
585
|
+
//# sourceMappingURL=render-XJWB6MVI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/serve/dashboard/render.tsx","../src/commands/serve/dashboard/ServeDashboard.tsx","../src/commands/serve/dashboard/components/ServerHeader.tsx","../src/commands/serve/dashboard/components/WorkspaceInfo.tsx","../src/commands/serve/dashboard/components/StatsBar.tsx","../src/commands/serve/dashboard/components/BackgroundTasks.tsx","../src/commands/serve/dashboard/components/PluginStatusPanel.tsx","../src/commands/serve/dashboard/components/ActivityLog.tsx","../src/commands/serve/dashboard/components/HelpBar.tsx","../src/commands/serve/dashboard/components/OllamaStatus.tsx"],"sourcesContent":["/**\n * Render the dashboard using Ink\n */\n\nimport React from \"react\";\nimport { render } from \"ink\";\nimport { ServeDashboard } from \"./ServeDashboard.js\";\nimport { getDashboardStore } from \"./store.js\";\n\nexport interface RenderOptions {\n onQuit?: () => void;\n onRebuildIndex?: () => void;\n onClearCache?: () => void;\n}\n\n/**\n * Intercept console.log/error/warn so stray output from ESLint rules,\n * child processes, etc. is routed to the dashboard activity log instead\n * of corrupting the Ink terminal UI. Returns a restore function.\n */\nfunction interceptConsole(): () => void {\n const origLog = console.log;\n const origError = console.error;\n const origWarn = console.warn;\n\n const route = (type: \"info\" | \"error\" | \"warning\", args: unknown[]) => {\n const message = args.map(String).join(\" \");\n if (!message.trim()) return;\n getDashboardStore().addActivity({\n type,\n message,\n isError: type === \"error\",\n isWarning: type === \"warning\",\n });\n };\n\n console.log = (...args: unknown[]) => route(\"info\", args);\n console.error = (...args: unknown[]) => route(\"error\", args);\n console.warn = (...args: unknown[]) => route(\"warning\", args);\n\n return () => {\n console.log = origLog;\n console.error = origError;\n console.warn = origWarn;\n };\n}\n\n/**\n * Render the dashboard and return cleanup function\n */\nexport function renderDashboard(options: RenderOptions = {}): {\n unmount: () => void;\n waitUntilExit: () => Promise<void>;\n} {\n // Clear the terminal so prior output doesn't mix with the Ink dashboard\n process.stdout.write(\"\\x1B[2J\\x1B[H\");\n\n // Intercept console methods so stray output goes to the activity log\n const restoreConsole = interceptConsole();\n\n const { unmount: inkUnmount, waitUntilExit: inkWaitUntilExit } = render(\n <ServeDashboard\n onQuit={options.onQuit}\n onRebuildIndex={options.onRebuildIndex}\n onClearCache={options.onClearCache}\n />\n );\n\n return {\n unmount: () => {\n restoreConsole();\n inkUnmount();\n },\n waitUntilExit: () => inkWaitUntilExit().finally(restoreConsole),\n };\n}\n","/**\n * ServeDashboard - main Ink component for the WebSocket server CLI dashboard\n */\n\nimport React, { useState, useEffect, useCallback } from \"react\";\nimport { Box, useInput, useApp } from \"ink\";\nimport {\n ServerHeader,\n WorkspaceInfo,\n StatsBar,\n PluginStatusPanel,\n ActivityLog,\n HelpBar,\n} from \"./components/index.js\";\nimport type { DashboardState } from \"./types.js\";\nimport { getDashboardStore } from \"./store.js\";\n\nexport interface ServeDashboardProps {\n /** Callback when user requests to quit */\n onQuit?: () => void;\n /** Callback when user requests to rebuild index */\n onRebuildIndex?: () => void;\n /** Callback when user requests to clear all caches */\n onClearCache?: () => void;\n}\n\nexport function ServeDashboard({\n onQuit,\n onRebuildIndex,\n onClearCache,\n}: ServeDashboardProps): React.ReactElement {\n const { exit } = useApp();\n const store = getDashboardStore();\n\n // Subscribe to store updates\n const [state, setState] = useState<DashboardState>(store.getState());\n const [scrollOffset, setScrollOffset] = useState(0);\n\n useEffect(() => {\n const unsubscribe = store.subscribe(() => {\n setState(store.getState());\n });\n return unsubscribe;\n }, [store]);\n\n // Clamp scrollOffset when activities change\n useEffect(() => {\n setScrollOffset((prev) => {\n const maxOffset = Math.max(0, state.activities.length - 15);\n return Math.min(prev, maxOffset);\n });\n }, [state.activities.length]);\n\n // Check Ollama status periodically\n useEffect(() => {\n const checkOllamaStatus = async () => {\n try {\n const response = await fetch(\"http://localhost:11434/api/tags\", {\n method: \"GET\",\n signal: AbortSignal.timeout(5000),\n });\n\n if (response.ok) {\n const data = (await response.json()) as { models?: Array<{ name?: string }> };\n const models = data.models || [];\n // Get the first model name as the \"active\" model indicator\n const modelName = models.length > 0 ? models[0].name : undefined;\n store.setOllamaStatus({\n status: \"connected\",\n model: modelName,\n lastChecked: new Date(),\n });\n } else {\n store.setOllamaStatus({\n status: \"error\",\n lastChecked: new Date(),\n });\n }\n } catch {\n store.setOllamaStatus({\n status: \"offline\",\n lastChecked: new Date(),\n });\n }\n };\n\n // Initial check\n checkOllamaStatus();\n\n // Check every 30 seconds\n const interval = setInterval(checkOllamaStatus, 30000);\n return () => clearInterval(interval);\n }, [store]);\n\n // Handle keyboard input\n useInput(\n useCallback(\n (input, key) => {\n if (input === \"q\" || (key.ctrl && input === \"c\")) {\n onQuit?.();\n exit();\n } else if (input === \"c\") {\n store.clearActivities();\n setScrollOffset(0);\n } else if (input === \"v\") {\n store.toggleVerbose();\n } else if (input === \"f\") {\n store.cycleFilter();\n setScrollOffset(0);\n } else if (input === \"r\") {\n onRebuildIndex?.();\n } else if (input === \"x\") {\n onClearCache?.();\n } else if (key.downArrow || input === \"j\") {\n setScrollOffset((prev) => {\n const maxOffset = Math.max(0, state.activities.length - 15);\n return Math.min(maxOffset, prev + 1);\n });\n } else if (key.upArrow || input === \"k\") {\n setScrollOffset((prev) => Math.max(0, prev - 1));\n }\n },\n [exit, onQuit, onRebuildIndex, onClearCache, store, state.activities.length]\n )\n );\n\n return (\n <Box flexDirection=\"column\" width=\"100%\">\n <ServerHeader port={state.port} isRunning={state.isRunning} />\n\n <WorkspaceInfo\n workspaceRoot={state.workspace?.workspaceRoot ?? null}\n appRoot={state.workspace?.appRoot ?? null}\n />\n\n <StatsBar\n connectedClients={state.stats.connectedClients}\n subscriptions={state.stats.subscriptions}\n cacheEntries={state.stats.cacheEntries}\n startTime={state.stats.startTime}\n ollamaStatus={state.ollamaStatus.status}\n ollamaModel={state.ollamaStatus.model}\n />\n\n <PluginStatusPanel plugins={state.pluginStates} />\n\n <ActivityLog\n activities={state.activities}\n maxVisible={15}\n verbose={state.verbose}\n scrollOffset={scrollOffset}\n activeFilter={state.activeFilter}\n />\n\n <HelpBar verbose={state.verbose} activeFilter={state.activeFilter} />\n </Box>\n );\n}\n","/**\n * ServerHeader component - displays server status and URL\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\n\nexport interface ServerHeaderProps {\n port: number;\n isRunning: boolean;\n}\n\nexport function ServerHeader({\n port,\n isRunning,\n}: ServerHeaderProps): React.ReactElement {\n const url = `ws://localhost:${port}`;\n const statusColor = isRunning ? \"green\" : \"red\";\n const statusIcon = isRunning ? \"\\u25CF\" : \"\\u25CB\"; // Filled/hollow circle\n\n return (\n <Box\n borderStyle=\"single\"\n borderColor=\"cyan\"\n paddingX={1}\n justifyContent=\"space-between\"\n >\n <Text bold color=\"cyan\">\n UILint Server\n </Text>\n <Box>\n <Text dimColor>{url}</Text>\n <Text> </Text>\n <Text color={statusColor}>{statusIcon}</Text>\n </Box>\n </Box>\n );\n}\n","/**\n * WorkspaceInfo component - displays workspace and app root paths\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\n\nexport interface WorkspaceInfoProps {\n workspaceRoot: string | null;\n appRoot: string | null;\n}\n\nfunction truncatePath(path: string, maxLen: number = 60): string {\n if (path.length <= maxLen) return path;\n return \"...\" + path.slice(-(maxLen - 3));\n}\n\nexport function WorkspaceInfo({\n workspaceRoot,\n appRoot,\n}: WorkspaceInfoProps): React.ReactElement {\n if (!workspaceRoot && !appRoot) {\n return (\n <Box paddingX={1}>\n <Text dimColor>Initializing...</Text>\n </Box>\n );\n }\n\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Box>\n <Text dimColor>Workspace: </Text>\n <Text>{truncatePath(workspaceRoot || \"\")}</Text>\n </Box>\n {appRoot && appRoot !== workspaceRoot && (\n <Box>\n <Text dimColor>App Root: </Text>\n <Text>{truncatePath(appRoot)}</Text>\n </Box>\n )}\n </Box>\n );\n}\n","/**\n * StatsBar component - displays server statistics\n */\n\nimport React, { useState, useEffect } from \"react\";\nimport { Box, Text } from \"ink\";\nimport type { OllamaStatusState } from \"../types.js\";\n\nexport interface StatsBarProps {\n connectedClients: number;\n subscriptions: number;\n cacheEntries: number;\n startTime: Date;\n ollamaStatus?: OllamaStatusState;\n ollamaModel?: string;\n}\n\nfunction formatUptime(startTime: Date): string {\n const diff = Date.now() - startTime.getTime();\n const seconds = Math.floor(diff / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n\n if (hours > 0) {\n return `${hours}h ${minutes % 60}m`;\n }\n if (minutes > 0) {\n return `${minutes}m ${seconds % 60}s`;\n }\n return `${seconds}s`;\n}\n\nconst ollamaStatusConfig: Record<\n OllamaStatusState,\n { icon: string; color: string }\n> = {\n checking: { icon: \"\\u25CB\", color: \"gray\" },\n connected: { icon: \"\\u25CF\", color: \"green\" },\n offline: { icon: \"\\u25CF\", color: \"red\" },\n error: { icon: \"\\u25CF\", color: \"yellow\" },\n};\n\nexport function StatsBar({\n connectedClients,\n subscriptions,\n cacheEntries,\n startTime,\n ollamaStatus,\n ollamaModel,\n}: StatsBarProps): React.ReactElement {\n const [, setTick] = useState(0);\n\n // Update uptime display every second\n useEffect(() => {\n const timer = setInterval(() => {\n setTick((t) => t + 1);\n }, 1000);\n return () => clearInterval(timer);\n }, []);\n\n const ollamaConfig = ollamaStatus\n ? ollamaStatusConfig[ollamaStatus]\n : ollamaStatusConfig.checking;\n\n return (\n <Box\n borderStyle=\"single\"\n borderColor=\"gray\"\n paddingX={1}\n justifyContent=\"space-between\"\n >\n <Box gap={2}>\n <Box>\n <Text dimColor>Clients: </Text>\n <Text bold color={connectedClients > 0 ? \"green\" : \"gray\"}>\n {connectedClients}\n </Text>\n </Box>\n <Box>\n <Text dimColor>Subs: </Text>\n <Text>{subscriptions}</Text>\n </Box>\n <Box>\n <Text dimColor>Ollama: </Text>\n <Text color={ollamaConfig.color}>{ollamaConfig.icon}</Text>\n {ollamaModel && ollamaStatus === \"connected\" && (\n <Text dimColor> {ollamaModel}</Text>\n )}\n </Box>\n </Box>\n <Box gap={2}>\n <Box>\n <Text dimColor>Cache: </Text>\n <Text>{cacheEntries}</Text>\n </Box>\n <Box>\n <Text dimColor>Uptime: </Text>\n <Text>{formatUptime(startTime)}</Text>\n </Box>\n </Box>\n </Box>\n );\n}\n","/**\n * BackgroundTasks component - displays background task progress\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\nimport type { BackgroundTask } from \"../types.js\";\n\nexport interface BackgroundTasksProps {\n tasks: Map<string, BackgroundTask>;\n}\n\nfunction ProgressBar({\n progress,\n width = 20,\n}: {\n progress: number;\n width?: number;\n}): React.ReactElement {\n const filled = Math.round((progress / 100) * width);\n const empty = width - filled;\n\n return (\n <Text>\n <Text color=\"cyan\">{\"\\u2588\".repeat(filled)}</Text>\n <Text dimColor>{\"\\u2591\".repeat(empty)}</Text>\n </Text>\n );\n}\n\nfunction TaskRow({ task }: { task: BackgroundTask }): React.ReactElement {\n const statusIcon = {\n idle: \"\\u25CB\", // hollow circle\n running: \"\\u25CF\", // filled circle\n complete: \"\\u2713\", // checkmark\n error: \"\\u2717\", // x mark\n }[task.status];\n\n const statusColor = {\n idle: \"gray\",\n running: \"cyan\",\n complete: \"green\",\n error: \"red\",\n }[task.status] as \"gray\" | \"cyan\" | \"green\" | \"red\";\n\n return (\n <Box>\n <Text color={statusColor}>{statusIcon} </Text>\n <Text>{task.name}: </Text>\n {task.status === \"running\" && task.progress !== undefined ? (\n <Box gap={1}>\n <ProgressBar progress={task.progress} width={15} />\n <Text dimColor>\n {task.progress.toFixed(0)}%\n {task.current !== undefined && task.total !== undefined\n ? ` (${task.current}/${task.total})`\n : \"\"}\n </Text>\n </Box>\n ) : task.status === \"complete\" ? (\n <Text color=\"green\">Complete</Text>\n ) : task.status === \"error\" ? (\n <Text color=\"red\">{task.error || \"Failed\"}</Text>\n ) : (\n <Text dimColor>{task.message || \"Idle\"}</Text>\n )}\n </Box>\n );\n}\n\nexport function BackgroundTasks({\n tasks,\n}: BackgroundTasksProps): React.ReactElement | null {\n const taskArray = Array.from(tasks.values());\n\n if (taskArray.length === 0) {\n return null;\n }\n\n return (\n <Box\n flexDirection=\"column\"\n borderStyle=\"single\"\n borderColor=\"gray\"\n paddingX={1}\n >\n <Text bold dimColor>\n Background Tasks\n </Text>\n {taskArray.map((task) => (\n <TaskRow key={task.id} task={task} />\n ))}\n </Box>\n );\n}\n","/**\n * PluginStatusPanel - persistent at-a-glance view of Ollama plugin states.\n *\n * Shows each plugin's lifecycle status, model, and progress in the CLI dashboard.\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\nimport type { PluginState, PluginLifecycle } from \"../types.js\";\n\nexport interface PluginStatusPanelProps {\n plugins: Map<string, PluginState>;\n}\n\nconst statusDisplay: Record<\n PluginLifecycle,\n { icon: string; color: string; label: string }\n> = {\n idle: { icon: \"\\u25CB\", color: \"gray\", label: \"Idle\" },\n \"waiting-for-ollama\": { icon: \"\\u25CC\", color: \"yellow\", label: \"Queued\" },\n \"using-ollama\": { icon: \"\\u25CF\", color: \"cyan\", label: \"Using Ollama\" },\n processing: { icon: \"\\u25CF\", color: \"blue\", label: \"Processing\" },\n complete: { icon: \"\\u2713\", color: \"green\", label: \"Complete\" },\n error: { icon: \"\\u2717\", color: \"red\", label: \"Error\" },\n};\n\nfunction ProgressBar({\n progress,\n width = 12,\n}: {\n progress: number;\n width?: number;\n}): React.ReactElement {\n const filled = Math.round((progress / 100) * width);\n const empty = width - filled;\n return (\n <Text>\n <Text color=\"cyan\">{\"\\u2588\".repeat(filled)}</Text>\n <Text dimColor>{\"\\u2591\".repeat(empty)}</Text>\n </Text>\n );\n}\n\nfunction truncate(str: string, maxLen: number): string {\n if (str.length <= maxLen) return str;\n return str.slice(0, maxLen - 1) + \"\\u2026\";\n}\n\nfunction PluginRow({\n plugin,\n}: {\n plugin: PluginState;\n}): React.ReactElement {\n const display = statusDisplay[plugin.status];\n\n return (\n <Box>\n {/* Status icon */}\n <Text color={display.color}>{display.icon} </Text>\n\n {/* Plugin name — fixed width */}\n <Box width={13}>\n <Text bold={plugin.status !== \"idle\"}>{plugin.name}</Text>\n </Box>\n\n {/* Status label */}\n <Box width={16}>\n <Text color={display.color}>{display.label}</Text>\n </Box>\n\n {/* Model */}\n <Text dimColor>({plugin.model})</Text>\n\n {/* Progress bar for active states */}\n {(plugin.status === \"waiting-for-ollama\" ||\n plugin.status === \"using-ollama\" ||\n plugin.status === \"processing\") &&\n plugin.progress !== undefined && (\n <Box marginLeft={1} gap={1}>\n <ProgressBar progress={plugin.progress} />\n <Text dimColor>\n {plugin.progress.toFixed(0)}%\n {plugin.current !== undefined && plugin.total !== undefined\n ? ` (${plugin.current}/${plugin.total})`\n : \"\"}\n </Text>\n </Box>\n )}\n\n {/* Message */}\n {plugin.message && plugin.status !== \"idle\" && (\n <Text dimColor>{\" \"}{truncate(plugin.message, 40)}</Text>\n )}\n\n {/* Error */}\n {plugin.status === \"error\" && plugin.error && (\n <Text color=\"red\">{\" \"}{truncate(plugin.error, 40)}</Text>\n )}\n </Box>\n );\n}\n\nexport function PluginStatusPanel({\n plugins,\n}: PluginStatusPanelProps): React.ReactElement | null {\n const pluginArray = Array.from(plugins.values());\n\n if (pluginArray.length === 0) {\n return null;\n }\n\n return (\n <Box\n flexDirection=\"column\"\n borderStyle=\"single\"\n borderColor=\"gray\"\n paddingX={1}\n >\n <Text bold dimColor>\n Plugins\n </Text>\n {pluginArray.map((plugin) => (\n <PluginRow key={plugin.id} plugin={plugin} />\n ))}\n </Box>\n );\n}\n","/**\n * ActivityLog component - displays recent server activity\n *\n * Supports filtering by category (errors, vision, semantic, lint)\n * and auto-expanding error details.\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\nimport type { ActivityEntry, ActivityType, ActivityCategory } from \"../types.js\";\n\nexport interface ActivityLogProps {\n activities: ActivityEntry[];\n maxVisible?: number;\n verbose?: boolean;\n scrollOffset?: number;\n activeFilter?: ActivityCategory;\n}\n\nconst filterLabels: Record<ActivityCategory, string> = {\n all: \"All\",\n errors: \"Errors\",\n vision: \"Vision\",\n semantic: \"Semantic\",\n lint: \"Lint\",\n system: \"System\",\n};\n\nfunction formatTime(date: Date): string {\n return date.toLocaleTimeString(\"en-US\", {\n hour12: false,\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n });\n}\n\n/** Strip ANSI escape sequences from a string */\nfunction stripAnsi(str: string): string {\n // eslint-disable-next-line no-control-regex\n return str.replace(/\\x1B\\[[0-9;]*[a-zA-Z]/g, \"\").replace(/\\r/g, \"\");\n}\n\n/** Truncate a string to maxLen, appending \"…\" if truncated */\nfunction truncate(str: string, maxLen: number): string {\n const clean = stripAnsi(str).replace(/\\n/g, \" \");\n if (clean.length <= maxLen) return clean;\n return clean.slice(0, maxLen - 1) + \"…\";\n}\n\ntype InkColor =\n | \"black\" | \"red\" | \"green\" | \"yellow\" | \"blue\"\n | \"magenta\" | \"cyan\" | \"white\" | \"gray\" | \"grey\";\n\nfunction getTypeDisplay(type: ActivityType): { label: string; color: InkColor } {\n const displays: Record<ActivityType, { label: string; color: InkColor }> = {\n \"lint:file\": { label: \"lint\", color: \"blue\" },\n \"lint:element\": { label: \"lint\", color: \"blue\" },\n \"lint:done\": { label: \"lint\", color: \"green\" },\n subscribe: { label: \"sub\", color: \"cyan\" },\n \"cache:invalidate\": { label: \"cache\", color: \"yellow\" },\n \"vision:analyze\": { label: \"vision\", color: \"magenta\" },\n \"vision:done\": { label: \"vision\", color: \"green\" },\n \"vision:check\": { label: \"vision\", color: \"magenta\" },\n \"semantic:analyze\": { label: \"semant\", color: \"blue\" },\n \"semantic:done\": { label: \"semant\", color: \"green\" },\n \"semantic:error\": { label: \"semant\", color: \"red\" },\n \"semantic:skip\": { label: \"semant\", color: \"yellow\" },\n \"config:set\": { label: \"config\", color: \"yellow\" },\n \"rule:config:set\": { label: \"rule\", color: \"yellow\" },\n \"screenshot:save\": { label: \"screen\", color: \"cyan\" },\n \"screenshot:saved\": { label: \"screen\", color: \"green\" },\n \"coverage:request\": { label: \"cov\", color: \"blue\" },\n \"coverage:result\": { label: \"cov\", color: \"green\" },\n \"file:changed\": { label: \"change\", color: \"yellow\" },\n \"client:connect\": { label: \"client\", color: \"green\" },\n \"client:disconnect\": { label: \"client\", color: \"red\" },\n error: { label: \"error\", color: \"red\" },\n warning: { label: \"warn\", color: \"yellow\" },\n info: { label: \"info\", color: \"gray\" },\n };\n\n return displays[type] || { label: type, color: \"gray\" };\n}\n\n// Max width for message/detail lines (leaves room for time + type label + padding)\nconst MAX_MSG_WIDTH = 120;\nconst MAX_DETAIL_WIDTH = 100;\n\nfunction ActivityRow({\n entry,\n verbose,\n}: {\n entry: ActivityEntry;\n verbose?: boolean;\n}): React.ReactElement {\n const { label, color } = getTypeDisplay(entry.type);\n\n // Always show detail for errors, otherwise respect verbose mode\n const showDetail = (verbose || entry.isError) && entry.detail;\n\n return (\n <Box flexDirection=\"column\">\n <Box>\n <Text dimColor>{formatTime(entry.timestamp)} </Text>\n <Text color={color} bold>\n {label.padEnd(7)}\n </Text>\n <Text color={entry.isError ? \"red\" : entry.isWarning ? \"yellow\" : undefined}>\n {truncate(entry.message, MAX_MSG_WIDTH)}\n </Text>\n </Box>\n {showDetail && (\n <Box paddingLeft={16}>\n <Text dimColor>{truncate(entry.detail!, MAX_DETAIL_WIDTH)}</Text>\n </Box>\n )}\n </Box>\n );\n}\n\nexport function ActivityLog({\n activities,\n maxVisible = 15,\n verbose = false,\n scrollOffset = 0,\n activeFilter = \"all\",\n}: ActivityLogProps): React.ReactElement {\n // Apply category filter\n const filtered =\n activeFilter !== \"all\"\n ? activities.filter((a) => a.category === activeFilter)\n : activities;\n\n const total = filtered.length;\n const start = Math.min(scrollOffset, Math.max(0, total - 1));\n const end = Math.min(start + maxVisible, total);\n const visibleActivities = filtered.slice(start, end);\n\n const isScrolled = start > 0;\n const hasMoreBelow = end < total;\n\n return (\n <Box\n flexDirection=\"column\"\n borderStyle=\"single\"\n borderColor=\"gray\"\n paddingX={1}\n flexGrow={1}\n >\n <Box justifyContent=\"space-between\">\n <Box gap={1}>\n <Text bold dimColor>\n Activity\n </Text>\n {activeFilter !== \"all\" && (\n <Text color=\"yellow\">[{filterLabels[activeFilter]}]</Text>\n )}\n </Box>\n <Box gap={1}>\n {isScrolled && (\n <Text color=\"cyan\">{\"\\u2191\"}</Text>\n )}\n {total > maxVisible && (\n <Text dimColor>\n {start + 1}-{end} of {total}\n </Text>\n )}\n {hasMoreBelow && (\n <Text color=\"cyan\">{\"\\u2193\"}</Text>\n )}\n </Box>\n </Box>\n {visibleActivities.length === 0 ? (\n <Text dimColor>\n {activeFilter !== \"all\"\n ? `No ${filterLabels[activeFilter].toLowerCase()} activity yet...`\n : \"No activity yet...\"}\n </Text>\n ) : (\n visibleActivities.map((entry) => (\n <ActivityRow key={entry.id} entry={entry} verbose={verbose} />\n ))\n )}\n </Box>\n );\n}\n","/**\n * HelpBar component - displays keyboard shortcuts\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\nimport type { ActivityCategory } from \"../types.js\";\n\nexport interface HelpBarProps {\n verbose: boolean;\n activeFilter?: ActivityCategory;\n}\n\nconst filterLabels: Record<ActivityCategory, string> = {\n all: \"all\",\n errors: \"errors\",\n vision: \"vision\",\n semantic: \"semantic\",\n lint: \"lint\",\n system: \"system\",\n};\n\nexport function HelpBar({ verbose, activeFilter = \"all\" }: HelpBarProps): React.ReactElement {\n return (\n <Box borderStyle=\"single\" borderColor=\"gray\" paddingX={1} gap={2}>\n <Box>\n <Text bold color=\"cyan\">\n q\n </Text>\n <Text dimColor> quit</Text>\n </Box>\n <Box>\n <Text bold color=\"cyan\">\n c\n </Text>\n <Text dimColor> clear log</Text>\n </Box>\n <Box>\n <Text bold color=\"cyan\">\n v\n </Text>\n <Text dimColor> verbose {verbose ? \"(on)\" : \"(off)\"}</Text>\n </Box>\n <Box>\n <Text bold color=\"cyan\">\n f\n </Text>\n <Text dimColor> filter ({filterLabels[activeFilter]})</Text>\n </Box>\n <Box>\n <Text bold color=\"cyan\">\n r\n </Text>\n <Text dimColor> rebuild index</Text>\n </Box>\n <Box>\n <Text bold color=\"cyan\">\n x\n </Text>\n <Text dimColor> clear cache</Text>\n </Box>\n <Box>\n <Text bold color=\"cyan\">\n {\"\\u2191\\u2193\"}\n </Text>\n <Text dimColor> scroll</Text>\n </Box>\n </Box>\n );\n}\n","/**\n * OllamaStatus component - displays Ollama connection status\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\nimport type { OllamaStatusState } from \"../types.js\";\n\nexport interface OllamaStatusProps {\n status: OllamaStatusState;\n model?: string;\n}\n\nconst statusConfig: Record<\n OllamaStatusState,\n { icon: string; color: string; label: string }\n> = {\n checking: { icon: \"\\u25CB\", color: \"gray\", label: \"checking\" },\n connected: { icon: \"\\u25CF\", color: \"green\", label: \"connected\" },\n offline: { icon: \"\\u25CF\", color: \"red\", label: \"offline\" },\n error: { icon: \"\\u25CF\", color: \"red\", label: \"error\" },\n};\n\nexport function OllamaStatus({\n status,\n model,\n}: OllamaStatusProps): React.ReactElement {\n const config = statusConfig[status];\n\n return (\n <Box gap={1}>\n <Text dimColor>Ollama:</Text>\n <Text color={config.color}>{config.icon}</Text>\n <Text color={config.color}>{config.label}</Text>\n {model && status === \"connected\" && (\n <Text dimColor>({model})</Text>\n )}\n </Box>\n );\n}\n"],"mappings":"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","names":["useState","useEffect","Box","Box","Text","jsx","jsxs","Box","Text","jsx","jsxs","Box","Text","jsx","jsxs","Box","Text","jsx","jsxs","Box","Text","jsx","jsxs","truncate","Box","Text","jsx","jsxs","filterLabels","Box","Text","jsx","jsxs","jsx","jsxs","useState","useEffect","Box","jsx"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uilint",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.155",
|
|
4
4
|
"description": "CLI for UILint - AI-powered UI consistency checking",
|
|
5
5
|
"author": "Peter Suggate",
|
|
6
6
|
"repository": {
|
|
@@ -49,15 +49,15 @@
|
|
|
49
49
|
"react": "^19.2.3",
|
|
50
50
|
"typescript": "^5.9.3",
|
|
51
51
|
"ws": "^8.19.0",
|
|
52
|
-
"uilint-core": "0.2.
|
|
53
|
-
"uilint-eslint": "0.2.
|
|
54
|
-
"uilint-duplicates": "0.2.
|
|
52
|
+
"uilint-core": "0.2.155",
|
|
53
|
+
"uilint-eslint": "0.2.155",
|
|
54
|
+
"uilint-duplicates": "0.2.155"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
|
-
"uilint-
|
|
58
|
-
"uilint-
|
|
59
|
-
"uilint-
|
|
60
|
-
"uilint-
|
|
57
|
+
"uilint-vision": "0.2.155",
|
|
58
|
+
"uilint-semantic": "0.2.152",
|
|
59
|
+
"uilint-duplicates": "0.2.155",
|
|
60
|
+
"uilint-coverage": "0.2.153"
|
|
61
61
|
},
|
|
62
62
|
"peerDependenciesMeta": {
|
|
63
63
|
"uilint-vision": {
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
"ink-testing-library": "^4.0.0",
|
|
88
88
|
"tsup": "^8.5.1",
|
|
89
89
|
"vitest": "^4.0.17",
|
|
90
|
-
"uilint-react": "0.2.
|
|
90
|
+
"uilint-react": "0.2.155"
|
|
91
91
|
},
|
|
92
92
|
"keywords": [
|
|
93
93
|
"cli",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/serve/dashboard/render.tsx","../src/commands/serve/dashboard/ServeDashboard.tsx","../src/commands/serve/dashboard/components/ServerHeader.tsx","../src/commands/serve/dashboard/components/WorkspaceInfo.tsx","../src/commands/serve/dashboard/components/StatsBar.tsx","../src/commands/serve/dashboard/components/BackgroundTasks.tsx","../src/commands/serve/dashboard/components/PluginStatusPanel.tsx","../src/commands/serve/dashboard/components/ActivityLog.tsx","../src/commands/serve/dashboard/components/HelpBar.tsx","../src/commands/serve/dashboard/components/OllamaStatus.tsx"],"sourcesContent":["/**\n * Render the dashboard using Ink\n */\n\nimport React from \"react\";\nimport { render } from \"ink\";\nimport { ServeDashboard } from \"./ServeDashboard.js\";\nimport { getDashboardStore } from \"./store.js\";\n\nexport interface RenderOptions {\n onQuit?: () => void;\n onRebuildIndex?: () => void;\n}\n\n/**\n * Intercept console.log/error/warn so stray output from ESLint rules,\n * child processes, etc. is routed to the dashboard activity log instead\n * of corrupting the Ink terminal UI. Returns a restore function.\n */\nfunction interceptConsole(): () => void {\n const origLog = console.log;\n const origError = console.error;\n const origWarn = console.warn;\n\n const route = (type: \"info\" | \"error\" | \"warning\", args: unknown[]) => {\n const message = args.map(String).join(\" \");\n if (!message.trim()) return;\n getDashboardStore().addActivity({\n type,\n message,\n isError: type === \"error\",\n isWarning: type === \"warning\",\n });\n };\n\n console.log = (...args: unknown[]) => route(\"info\", args);\n console.error = (...args: unknown[]) => route(\"error\", args);\n console.warn = (...args: unknown[]) => route(\"warning\", args);\n\n return () => {\n console.log = origLog;\n console.error = origError;\n console.warn = origWarn;\n };\n}\n\n/**\n * Render the dashboard and return cleanup function\n */\nexport function renderDashboard(options: RenderOptions = {}): {\n unmount: () => void;\n waitUntilExit: () => Promise<void>;\n} {\n // Clear the terminal so prior output doesn't mix with the Ink dashboard\n process.stdout.write(\"\\x1B[2J\\x1B[H\");\n\n // Intercept console methods so stray output goes to the activity log\n const restoreConsole = interceptConsole();\n\n const { unmount: inkUnmount, waitUntilExit: inkWaitUntilExit } = render(\n <ServeDashboard\n onQuit={options.onQuit}\n onRebuildIndex={options.onRebuildIndex}\n />\n );\n\n return {\n unmount: () => {\n restoreConsole();\n inkUnmount();\n },\n waitUntilExit: () => inkWaitUntilExit().finally(restoreConsole),\n };\n}\n","/**\n * ServeDashboard - main Ink component for the WebSocket server CLI dashboard\n */\n\nimport React, { useState, useEffect, useCallback } from \"react\";\nimport { Box, useInput, useApp } from \"ink\";\nimport {\n ServerHeader,\n WorkspaceInfo,\n StatsBar,\n PluginStatusPanel,\n ActivityLog,\n HelpBar,\n} from \"./components/index.js\";\nimport type { DashboardState } from \"./types.js\";\nimport { getDashboardStore } from \"./store.js\";\n\nexport interface ServeDashboardProps {\n /** Callback when user requests to quit */\n onQuit?: () => void;\n /** Callback when user requests to rebuild index */\n onRebuildIndex?: () => void;\n}\n\nexport function ServeDashboard({\n onQuit,\n onRebuildIndex,\n}: ServeDashboardProps): React.ReactElement {\n const { exit } = useApp();\n const store = getDashboardStore();\n\n // Subscribe to store updates\n const [state, setState] = useState<DashboardState>(store.getState());\n const [scrollOffset, setScrollOffset] = useState(0);\n\n useEffect(() => {\n const unsubscribe = store.subscribe(() => {\n setState(store.getState());\n });\n return unsubscribe;\n }, [store]);\n\n // Clamp scrollOffset when activities change\n useEffect(() => {\n setScrollOffset((prev) => {\n const maxOffset = Math.max(0, state.activities.length - 15);\n return Math.min(prev, maxOffset);\n });\n }, [state.activities.length]);\n\n // Check Ollama status periodically\n useEffect(() => {\n const checkOllamaStatus = async () => {\n try {\n const response = await fetch(\"http://localhost:11434/api/tags\", {\n method: \"GET\",\n signal: AbortSignal.timeout(5000),\n });\n\n if (response.ok) {\n const data = (await response.json()) as { models?: Array<{ name?: string }> };\n const models = data.models || [];\n // Get the first model name as the \"active\" model indicator\n const modelName = models.length > 0 ? models[0].name : undefined;\n store.setOllamaStatus({\n status: \"connected\",\n model: modelName,\n lastChecked: new Date(),\n });\n } else {\n store.setOllamaStatus({\n status: \"error\",\n lastChecked: new Date(),\n });\n }\n } catch {\n store.setOllamaStatus({\n status: \"offline\",\n lastChecked: new Date(),\n });\n }\n };\n\n // Initial check\n checkOllamaStatus();\n\n // Check every 30 seconds\n const interval = setInterval(checkOllamaStatus, 30000);\n return () => clearInterval(interval);\n }, [store]);\n\n // Handle keyboard input\n useInput(\n useCallback(\n (input, key) => {\n if (input === \"q\" || (key.ctrl && input === \"c\")) {\n onQuit?.();\n exit();\n } else if (input === \"c\") {\n store.clearActivities();\n setScrollOffset(0);\n } else if (input === \"v\") {\n store.toggleVerbose();\n } else if (input === \"f\") {\n store.cycleFilter();\n setScrollOffset(0);\n } else if (input === \"r\") {\n onRebuildIndex?.();\n } else if (key.downArrow || input === \"j\") {\n setScrollOffset((prev) => {\n const maxOffset = Math.max(0, state.activities.length - 15);\n return Math.min(maxOffset, prev + 1);\n });\n } else if (key.upArrow || input === \"k\") {\n setScrollOffset((prev) => Math.max(0, prev - 1));\n }\n },\n [exit, onQuit, onRebuildIndex, store, state.activities.length]\n )\n );\n\n return (\n <Box flexDirection=\"column\" width=\"100%\">\n <ServerHeader port={state.port} isRunning={state.isRunning} />\n\n <WorkspaceInfo\n workspaceRoot={state.workspace?.workspaceRoot ?? null}\n appRoot={state.workspace?.appRoot ?? null}\n />\n\n <StatsBar\n connectedClients={state.stats.connectedClients}\n subscriptions={state.stats.subscriptions}\n cacheEntries={state.stats.cacheEntries}\n startTime={state.stats.startTime}\n ollamaStatus={state.ollamaStatus.status}\n ollamaModel={state.ollamaStatus.model}\n />\n\n <PluginStatusPanel plugins={state.pluginStates} />\n\n <ActivityLog\n activities={state.activities}\n maxVisible={15}\n verbose={state.verbose}\n scrollOffset={scrollOffset}\n activeFilter={state.activeFilter}\n />\n\n <HelpBar verbose={state.verbose} activeFilter={state.activeFilter} />\n </Box>\n );\n}\n","/**\n * ServerHeader component - displays server status and URL\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\n\nexport interface ServerHeaderProps {\n port: number;\n isRunning: boolean;\n}\n\nexport function ServerHeader({\n port,\n isRunning,\n}: ServerHeaderProps): React.ReactElement {\n const url = `ws://localhost:${port}`;\n const statusColor = isRunning ? \"green\" : \"red\";\n const statusIcon = isRunning ? \"\\u25CF\" : \"\\u25CB\"; // Filled/hollow circle\n\n return (\n <Box\n borderStyle=\"single\"\n borderColor=\"cyan\"\n paddingX={1}\n justifyContent=\"space-between\"\n >\n <Text bold color=\"cyan\">\n UILint Server\n </Text>\n <Box>\n <Text dimColor>{url}</Text>\n <Text> </Text>\n <Text color={statusColor}>{statusIcon}</Text>\n </Box>\n </Box>\n );\n}\n","/**\n * WorkspaceInfo component - displays workspace and app root paths\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\n\nexport interface WorkspaceInfoProps {\n workspaceRoot: string | null;\n appRoot: string | null;\n}\n\nfunction truncatePath(path: string, maxLen: number = 60): string {\n if (path.length <= maxLen) return path;\n return \"...\" + path.slice(-(maxLen - 3));\n}\n\nexport function WorkspaceInfo({\n workspaceRoot,\n appRoot,\n}: WorkspaceInfoProps): React.ReactElement {\n if (!workspaceRoot && !appRoot) {\n return (\n <Box paddingX={1}>\n <Text dimColor>Initializing...</Text>\n </Box>\n );\n }\n\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Box>\n <Text dimColor>Workspace: </Text>\n <Text>{truncatePath(workspaceRoot || \"\")}</Text>\n </Box>\n {appRoot && appRoot !== workspaceRoot && (\n <Box>\n <Text dimColor>App Root: </Text>\n <Text>{truncatePath(appRoot)}</Text>\n </Box>\n )}\n </Box>\n );\n}\n","/**\n * StatsBar component - displays server statistics\n */\n\nimport React, { useState, useEffect } from \"react\";\nimport { Box, Text } from \"ink\";\nimport type { OllamaStatusState } from \"../types.js\";\n\nexport interface StatsBarProps {\n connectedClients: number;\n subscriptions: number;\n cacheEntries: number;\n startTime: Date;\n ollamaStatus?: OllamaStatusState;\n ollamaModel?: string;\n}\n\nfunction formatUptime(startTime: Date): string {\n const diff = Date.now() - startTime.getTime();\n const seconds = Math.floor(diff / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n\n if (hours > 0) {\n return `${hours}h ${minutes % 60}m`;\n }\n if (minutes > 0) {\n return `${minutes}m ${seconds % 60}s`;\n }\n return `${seconds}s`;\n}\n\nconst ollamaStatusConfig: Record<\n OllamaStatusState,\n { icon: string; color: string }\n> = {\n checking: { icon: \"\\u25CB\", color: \"gray\" },\n connected: { icon: \"\\u25CF\", color: \"green\" },\n offline: { icon: \"\\u25CF\", color: \"red\" },\n error: { icon: \"\\u25CF\", color: \"yellow\" },\n};\n\nexport function StatsBar({\n connectedClients,\n subscriptions,\n cacheEntries,\n startTime,\n ollamaStatus,\n ollamaModel,\n}: StatsBarProps): React.ReactElement {\n const [, setTick] = useState(0);\n\n // Update uptime display every second\n useEffect(() => {\n const timer = setInterval(() => {\n setTick((t) => t + 1);\n }, 1000);\n return () => clearInterval(timer);\n }, []);\n\n const ollamaConfig = ollamaStatus\n ? ollamaStatusConfig[ollamaStatus]\n : ollamaStatusConfig.checking;\n\n return (\n <Box\n borderStyle=\"single\"\n borderColor=\"gray\"\n paddingX={1}\n justifyContent=\"space-between\"\n >\n <Box gap={2}>\n <Box>\n <Text dimColor>Clients: </Text>\n <Text bold color={connectedClients > 0 ? \"green\" : \"gray\"}>\n {connectedClients}\n </Text>\n </Box>\n <Box>\n <Text dimColor>Subs: </Text>\n <Text>{subscriptions}</Text>\n </Box>\n <Box>\n <Text dimColor>Ollama: </Text>\n <Text color={ollamaConfig.color}>{ollamaConfig.icon}</Text>\n {ollamaModel && ollamaStatus === \"connected\" && (\n <Text dimColor> {ollamaModel}</Text>\n )}\n </Box>\n </Box>\n <Box gap={2}>\n <Box>\n <Text dimColor>Cache: </Text>\n <Text>{cacheEntries}</Text>\n </Box>\n <Box>\n <Text dimColor>Uptime: </Text>\n <Text>{formatUptime(startTime)}</Text>\n </Box>\n </Box>\n </Box>\n );\n}\n","/**\n * BackgroundTasks component - displays background task progress\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\nimport type { BackgroundTask } from \"../types.js\";\n\nexport interface BackgroundTasksProps {\n tasks: Map<string, BackgroundTask>;\n}\n\nfunction ProgressBar({\n progress,\n width = 20,\n}: {\n progress: number;\n width?: number;\n}): React.ReactElement {\n const filled = Math.round((progress / 100) * width);\n const empty = width - filled;\n\n return (\n <Text>\n <Text color=\"cyan\">{\"\\u2588\".repeat(filled)}</Text>\n <Text dimColor>{\"\\u2591\".repeat(empty)}</Text>\n </Text>\n );\n}\n\nfunction TaskRow({ task }: { task: BackgroundTask }): React.ReactElement {\n const statusIcon = {\n idle: \"\\u25CB\", // hollow circle\n running: \"\\u25CF\", // filled circle\n complete: \"\\u2713\", // checkmark\n error: \"\\u2717\", // x mark\n }[task.status];\n\n const statusColor = {\n idle: \"gray\",\n running: \"cyan\",\n complete: \"green\",\n error: \"red\",\n }[task.status] as \"gray\" | \"cyan\" | \"green\" | \"red\";\n\n return (\n <Box>\n <Text color={statusColor}>{statusIcon} </Text>\n <Text>{task.name}: </Text>\n {task.status === \"running\" && task.progress !== undefined ? (\n <Box gap={1}>\n <ProgressBar progress={task.progress} width={15} />\n <Text dimColor>\n {task.progress.toFixed(0)}%\n {task.current !== undefined && task.total !== undefined\n ? ` (${task.current}/${task.total})`\n : \"\"}\n </Text>\n </Box>\n ) : task.status === \"complete\" ? (\n <Text color=\"green\">Complete</Text>\n ) : task.status === \"error\" ? (\n <Text color=\"red\">{task.error || \"Failed\"}</Text>\n ) : (\n <Text dimColor>{task.message || \"Idle\"}</Text>\n )}\n </Box>\n );\n}\n\nexport function BackgroundTasks({\n tasks,\n}: BackgroundTasksProps): React.ReactElement | null {\n const taskArray = Array.from(tasks.values());\n\n if (taskArray.length === 0) {\n return null;\n }\n\n return (\n <Box\n flexDirection=\"column\"\n borderStyle=\"single\"\n borderColor=\"gray\"\n paddingX={1}\n >\n <Text bold dimColor>\n Background Tasks\n </Text>\n {taskArray.map((task) => (\n <TaskRow key={task.id} task={task} />\n ))}\n </Box>\n );\n}\n","/**\n * PluginStatusPanel - persistent at-a-glance view of Ollama plugin states.\n *\n * Shows each plugin's lifecycle status, model, and progress in the CLI dashboard.\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\nimport type { PluginState, PluginLifecycle } from \"../types.js\";\n\nexport interface PluginStatusPanelProps {\n plugins: Map<string, PluginState>;\n}\n\nconst statusDisplay: Record<\n PluginLifecycle,\n { icon: string; color: string; label: string }\n> = {\n idle: { icon: \"\\u25CB\", color: \"gray\", label: \"Idle\" },\n \"waiting-for-ollama\": { icon: \"\\u25CC\", color: \"yellow\", label: \"Queued\" },\n \"using-ollama\": { icon: \"\\u25CF\", color: \"cyan\", label: \"Using Ollama\" },\n processing: { icon: \"\\u25CF\", color: \"blue\", label: \"Processing\" },\n complete: { icon: \"\\u2713\", color: \"green\", label: \"Complete\" },\n error: { icon: \"\\u2717\", color: \"red\", label: \"Error\" },\n};\n\nfunction ProgressBar({\n progress,\n width = 12,\n}: {\n progress: number;\n width?: number;\n}): React.ReactElement {\n const filled = Math.round((progress / 100) * width);\n const empty = width - filled;\n return (\n <Text>\n <Text color=\"cyan\">{\"\\u2588\".repeat(filled)}</Text>\n <Text dimColor>{\"\\u2591\".repeat(empty)}</Text>\n </Text>\n );\n}\n\nfunction truncate(str: string, maxLen: number): string {\n if (str.length <= maxLen) return str;\n return str.slice(0, maxLen - 1) + \"\\u2026\";\n}\n\nfunction PluginRow({\n plugin,\n}: {\n plugin: PluginState;\n}): React.ReactElement {\n const display = statusDisplay[plugin.status];\n\n return (\n <Box>\n {/* Status icon */}\n <Text color={display.color}>{display.icon} </Text>\n\n {/* Plugin name — fixed width */}\n <Box width={13}>\n <Text bold={plugin.status !== \"idle\"}>{plugin.name}</Text>\n </Box>\n\n {/* Status label */}\n <Box width={16}>\n <Text color={display.color}>{display.label}</Text>\n </Box>\n\n {/* Model */}\n <Text dimColor>({plugin.model})</Text>\n\n {/* Progress bar for active states */}\n {(plugin.status === \"waiting-for-ollama\" ||\n plugin.status === \"using-ollama\" ||\n plugin.status === \"processing\") &&\n plugin.progress !== undefined && (\n <Box marginLeft={1} gap={1}>\n <ProgressBar progress={plugin.progress} />\n <Text dimColor>\n {plugin.progress.toFixed(0)}%\n {plugin.current !== undefined && plugin.total !== undefined\n ? ` (${plugin.current}/${plugin.total})`\n : \"\"}\n </Text>\n </Box>\n )}\n\n {/* Message */}\n {plugin.message && plugin.status !== \"idle\" && (\n <Text dimColor>{\" \"}{truncate(plugin.message, 40)}</Text>\n )}\n\n {/* Error */}\n {plugin.status === \"error\" && plugin.error && (\n <Text color=\"red\">{\" \"}{truncate(plugin.error, 40)}</Text>\n )}\n </Box>\n );\n}\n\nexport function PluginStatusPanel({\n plugins,\n}: PluginStatusPanelProps): React.ReactElement | null {\n const pluginArray = Array.from(plugins.values());\n\n if (pluginArray.length === 0) {\n return null;\n }\n\n return (\n <Box\n flexDirection=\"column\"\n borderStyle=\"single\"\n borderColor=\"gray\"\n paddingX={1}\n >\n <Text bold dimColor>\n Plugins\n </Text>\n {pluginArray.map((plugin) => (\n <PluginRow key={plugin.id} plugin={plugin} />\n ))}\n </Box>\n );\n}\n","/**\n * ActivityLog component - displays recent server activity\n *\n * Supports filtering by category (errors, vision, semantic, lint)\n * and auto-expanding error details.\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\nimport type { ActivityEntry, ActivityType, ActivityCategory } from \"../types.js\";\n\nexport interface ActivityLogProps {\n activities: ActivityEntry[];\n maxVisible?: number;\n verbose?: boolean;\n scrollOffset?: number;\n activeFilter?: ActivityCategory;\n}\n\nconst filterLabels: Record<ActivityCategory, string> = {\n all: \"All\",\n errors: \"Errors\",\n vision: \"Vision\",\n semantic: \"Semantic\",\n lint: \"Lint\",\n system: \"System\",\n};\n\nfunction formatTime(date: Date): string {\n return date.toLocaleTimeString(\"en-US\", {\n hour12: false,\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n });\n}\n\n/** Strip ANSI escape sequences from a string */\nfunction stripAnsi(str: string): string {\n // eslint-disable-next-line no-control-regex\n return str.replace(/\\x1B\\[[0-9;]*[a-zA-Z]/g, \"\").replace(/\\r/g, \"\");\n}\n\n/** Truncate a string to maxLen, appending \"…\" if truncated */\nfunction truncate(str: string, maxLen: number): string {\n const clean = stripAnsi(str).replace(/\\n/g, \" \");\n if (clean.length <= maxLen) return clean;\n return clean.slice(0, maxLen - 1) + \"…\";\n}\n\ntype InkColor =\n | \"black\" | \"red\" | \"green\" | \"yellow\" | \"blue\"\n | \"magenta\" | \"cyan\" | \"white\" | \"gray\" | \"grey\";\n\nfunction getTypeDisplay(type: ActivityType): { label: string; color: InkColor } {\n const displays: Record<ActivityType, { label: string; color: InkColor }> = {\n \"lint:file\": { label: \"lint\", color: \"blue\" },\n \"lint:element\": { label: \"lint\", color: \"blue\" },\n \"lint:done\": { label: \"lint\", color: \"green\" },\n subscribe: { label: \"sub\", color: \"cyan\" },\n \"cache:invalidate\": { label: \"cache\", color: \"yellow\" },\n \"vision:analyze\": { label: \"vision\", color: \"magenta\" },\n \"vision:done\": { label: \"vision\", color: \"green\" },\n \"vision:check\": { label: \"vision\", color: \"magenta\" },\n \"semantic:analyze\": { label: \"semant\", color: \"blue\" },\n \"semantic:done\": { label: \"semant\", color: \"green\" },\n \"semantic:error\": { label: \"semant\", color: \"red\" },\n \"semantic:skip\": { label: \"semant\", color: \"yellow\" },\n \"config:set\": { label: \"config\", color: \"yellow\" },\n \"rule:config:set\": { label: \"rule\", color: \"yellow\" },\n \"screenshot:save\": { label: \"screen\", color: \"cyan\" },\n \"screenshot:saved\": { label: \"screen\", color: \"green\" },\n \"coverage:request\": { label: \"cov\", color: \"blue\" },\n \"coverage:result\": { label: \"cov\", color: \"green\" },\n \"file:changed\": { label: \"change\", color: \"yellow\" },\n \"client:connect\": { label: \"client\", color: \"green\" },\n \"client:disconnect\": { label: \"client\", color: \"red\" },\n error: { label: \"error\", color: \"red\" },\n warning: { label: \"warn\", color: \"yellow\" },\n info: { label: \"info\", color: \"gray\" },\n };\n\n return displays[type] || { label: type, color: \"gray\" };\n}\n\n// Max width for message/detail lines (leaves room for time + type label + padding)\nconst MAX_MSG_WIDTH = 120;\nconst MAX_DETAIL_WIDTH = 100;\n\nfunction ActivityRow({\n entry,\n verbose,\n}: {\n entry: ActivityEntry;\n verbose?: boolean;\n}): React.ReactElement {\n const { label, color } = getTypeDisplay(entry.type);\n\n // Always show detail for errors, otherwise respect verbose mode\n const showDetail = (verbose || entry.isError) && entry.detail;\n\n return (\n <Box flexDirection=\"column\">\n <Box>\n <Text dimColor>{formatTime(entry.timestamp)} </Text>\n <Text color={color} bold>\n {label.padEnd(7)}\n </Text>\n <Text color={entry.isError ? \"red\" : entry.isWarning ? \"yellow\" : undefined}>\n {truncate(entry.message, MAX_MSG_WIDTH)}\n </Text>\n </Box>\n {showDetail && (\n <Box paddingLeft={16}>\n <Text dimColor>{truncate(entry.detail!, MAX_DETAIL_WIDTH)}</Text>\n </Box>\n )}\n </Box>\n );\n}\n\nexport function ActivityLog({\n activities,\n maxVisible = 15,\n verbose = false,\n scrollOffset = 0,\n activeFilter = \"all\",\n}: ActivityLogProps): React.ReactElement {\n // Apply category filter\n const filtered =\n activeFilter !== \"all\"\n ? activities.filter((a) => a.category === activeFilter)\n : activities;\n\n const total = filtered.length;\n const start = Math.min(scrollOffset, Math.max(0, total - 1));\n const end = Math.min(start + maxVisible, total);\n const visibleActivities = filtered.slice(start, end);\n\n const isScrolled = start > 0;\n const hasMoreBelow = end < total;\n\n return (\n <Box\n flexDirection=\"column\"\n borderStyle=\"single\"\n borderColor=\"gray\"\n paddingX={1}\n flexGrow={1}\n >\n <Box justifyContent=\"space-between\">\n <Box gap={1}>\n <Text bold dimColor>\n Activity\n </Text>\n {activeFilter !== \"all\" && (\n <Text color=\"yellow\">[{filterLabels[activeFilter]}]</Text>\n )}\n </Box>\n <Box gap={1}>\n {isScrolled && (\n <Text color=\"cyan\">{\"\\u2191\"}</Text>\n )}\n {total > maxVisible && (\n <Text dimColor>\n {start + 1}-{end} of {total}\n </Text>\n )}\n {hasMoreBelow && (\n <Text color=\"cyan\">{\"\\u2193\"}</Text>\n )}\n </Box>\n </Box>\n {visibleActivities.length === 0 ? (\n <Text dimColor>\n {activeFilter !== \"all\"\n ? `No ${filterLabels[activeFilter].toLowerCase()} activity yet...`\n : \"No activity yet...\"}\n </Text>\n ) : (\n visibleActivities.map((entry) => (\n <ActivityRow key={entry.id} entry={entry} verbose={verbose} />\n ))\n )}\n </Box>\n );\n}\n","/**\n * HelpBar component - displays keyboard shortcuts\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\nimport type { ActivityCategory } from \"../types.js\";\n\nexport interface HelpBarProps {\n verbose: boolean;\n activeFilter?: ActivityCategory;\n}\n\nconst filterLabels: Record<ActivityCategory, string> = {\n all: \"all\",\n errors: \"errors\",\n vision: \"vision\",\n semantic: \"semantic\",\n lint: \"lint\",\n system: \"system\",\n};\n\nexport function HelpBar({ verbose, activeFilter = \"all\" }: HelpBarProps): React.ReactElement {\n return (\n <Box borderStyle=\"single\" borderColor=\"gray\" paddingX={1} gap={2}>\n <Box>\n <Text bold color=\"cyan\">\n q\n </Text>\n <Text dimColor> quit</Text>\n </Box>\n <Box>\n <Text bold color=\"cyan\">\n c\n </Text>\n <Text dimColor> clear log</Text>\n </Box>\n <Box>\n <Text bold color=\"cyan\">\n v\n </Text>\n <Text dimColor> verbose {verbose ? \"(on)\" : \"(off)\"}</Text>\n </Box>\n <Box>\n <Text bold color=\"cyan\">\n f\n </Text>\n <Text dimColor> filter ({filterLabels[activeFilter]})</Text>\n </Box>\n <Box>\n <Text bold color=\"cyan\">\n r\n </Text>\n <Text dimColor> rebuild index</Text>\n </Box>\n <Box>\n <Text bold color=\"cyan\">\n {\"\\u2191\\u2193\"}\n </Text>\n <Text dimColor> scroll</Text>\n </Box>\n </Box>\n );\n}\n","/**\n * OllamaStatus component - displays Ollama connection status\n */\n\nimport React from \"react\";\nimport { Box, Text } from \"ink\";\nimport type { OllamaStatusState } from \"../types.js\";\n\nexport interface OllamaStatusProps {\n status: OllamaStatusState;\n model?: string;\n}\n\nconst statusConfig: Record<\n OllamaStatusState,\n { icon: string; color: string; label: string }\n> = {\n checking: { icon: \"\\u25CB\", color: \"gray\", label: \"checking\" },\n connected: { icon: \"\\u25CF\", color: \"green\", label: \"connected\" },\n offline: { icon: \"\\u25CF\", color: \"red\", label: \"offline\" },\n error: { icon: \"\\u25CF\", color: \"red\", label: \"error\" },\n};\n\nexport function OllamaStatus({\n status,\n model,\n}: OllamaStatusProps): React.ReactElement {\n const config = statusConfig[status];\n\n return (\n <Box gap={1}>\n <Text dimColor>Ollama:</Text>\n <Text color={config.color}>{config.icon}</Text>\n <Text color={config.color}>{config.label}</Text>\n {model && status === \"connected\" && (\n <Text dimColor>({model})</Text>\n )}\n </Box>\n );\n}\n"],"mappings":"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","names":["useState","useEffect","Box","Box","Text","jsx","jsxs","Box","Text","jsx","jsxs","Box","Text","jsx","jsxs","Box","Text","jsx","jsxs","Box","Text","jsx","jsxs","truncate","Box","Text","jsx","jsxs","filterLabels","Box","Text","jsx","jsxs","jsx","jsxs","useState","useEffect","Box","jsx"]}
|