@sushanglewis/lincoln 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +193 -0
- package/dist/main.js +1009 -0
- package/dist/main.js.map +1 -0
- package/package.json +48 -0
package/dist/main.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli.tsx","../src/config/args.ts","../src/config/resolveConfig.ts","../src/config/loadConfig.ts","../src/utils/sessionId.ts","../src/components/RecordingApp.tsx","../src/components/StatusPanel.tsx","../src/utils/formatDuration.ts","../src/components/LogView.tsx","../src/components/HintBar.tsx","../src/components/DevicesMenu.tsx","../src/components/SelectMenu.tsx","../src/components/ModelMenu.tsx","../src/hooks/useKeyHandler.ts","../src/recording/useRecorder.ts","../src/recording/spawnRecorder.ts","../src/devices/listDevices.ts","../src/devices/parseDevices.ts","../src/models/models.ts","../src/models/runWarmup.ts","../src/models/warmupProgress.ts","../src/main.tsx"],"sourcesContent":["#!/usr/bin/env node\nimport { Box, Text } from 'ink'\nimport React from 'react'\n\nimport { parseArgs, type ParsedArgs } from './config/args'\nimport { resolveConfig, type ResolvedConfig } from './config/resolveConfig'\nimport { RecordingApp } from './components/RecordingApp'\n\nexport interface AppProps {\n args: ParsedArgs\n config: ResolvedConfig\n}\n\nexport function App({ args, config }: AppProps) {\n if (args.help) {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text bold>lincoln</Text>\n <Text>Cross-tool TUI for Lincoln interview recording.</Text>\n <Text />\n <Text bold>Usage:</Text>\n <Text> lincoln [options]</Text>\n <Text />\n <Text bold>Options:</Text>\n <Text> --topic Interview topic</Text>\n <Text> --design-id Design ID for the session</Text>\n <Text> --branch Current branch name</Text>\n <Text> --session-id Explicit session ID</Text>\n <Text> --no-tui Run without the terminal UI</Text>\n <Text> --help, -h Show this help message</Text>\n <Text />\n <Text dimColor>Configuration files: ~/.lincolnrc, ./.lincolnrc</Text>\n </Box>\n )\n }\n\n return (\n <RecordingApp\n workspaceRoot={config.workspaceRoot}\n sessionId={config.sessionId}\n topic={config.topic}\n designId={config.designId}\n branch={config.branch}\n audioMeterStyle={config.audioMeterStyle}\n />\n )\n}\n\nexport async function main(argv: string[] = process.argv.slice(2)): Promise<void> {\n const args = parseArgs(argv)\n const config = resolveConfig(args)\n\n if (args.noTui) {\n console.log(JSON.stringify(config, null, 2))\n return\n }\n\n const { render } = await import('ink')\n render(<App args={args} config={config} />)\n}\n","import { parseArgs as nodeParseArgs } from 'node:util'\n\nexport interface ParsedArgs {\n topic?: string\n designId?: string\n branch?: string\n sessionId?: string\n noTui: boolean\n help: boolean\n}\n\nexport function parseArgs(argv: string[]): ParsedArgs {\n const { values } = nodeParseArgs({\n args: argv,\n options: {\n topic: { type: 'string' },\n 'design-id': { type: 'string' },\n branch: { type: 'string' },\n 'session-id': { type: 'string' },\n 'no-tui': { type: 'boolean', default: false },\n help: { type: 'boolean', short: 'h', default: false },\n },\n strict: false,\n allowPositionals: true,\n })\n\n return {\n topic: values.topic as string | undefined,\n designId: values['design-id'] as string | undefined,\n branch: values.branch as string | undefined,\n sessionId: values['session-id'] as string | undefined,\n noTui: values['no-tui'] as boolean,\n help: values.help as boolean,\n }\n}\n","import { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nimport { LincolnConfig, loadConfigOptional } from './loadConfig'\nimport { generateSessionId } from '../utils/sessionId'\n\nexport interface ParsedArgs {\n topic?: string\n designId?: string\n branch?: string\n sessionId?: string\n noTui?: boolean\n help?: boolean\n}\n\nexport interface ResolvedConfig extends Required<Pick<LincolnConfig, 'autoProcess' | 'showAudioMeter' | 'audioMeterStyle'>> {\n workspaceRoot: string\n sessionId: string\n topic: string\n designId: string\n branch: string\n noTui: boolean\n}\n\ninterface ResolveOptions {\n cwd?: string\n home?: string\n now?: Date\n}\n\nfunction pickFirst(...values: Array<string | undefined>): string {\n for (const value of values) {\n if (value !== undefined && value !== '') {\n return value\n }\n }\n return ''\n}\n\nfunction uniqueSessionId(workspaceRoot: string, now: Date, descriptor?: string): string {\n const baseSessionId = generateSessionId({ now, descriptor })\n const recordingPath = join(workspaceRoot, 'recordings', `${baseSessionId}.m4a`)\n if (!existsSync(recordingPath)) {\n return baseSessionId\n }\n\n for (let counter = 1; counter <= 999; counter += 1) {\n const candidate = `${baseSessionId}-${String(counter).padStart(3, '0')}`\n const candidatePath = join(workspaceRoot, 'recordings', `${candidate}.m4a`)\n if (!existsSync(candidatePath)) {\n return candidate\n }\n }\n\n return baseSessionId\n}\n\nexport function resolveConfig(args: ParsedArgs, options: ResolveOptions = {}): ResolvedConfig {\n const cwd = options.cwd ?? process.cwd()\n const home = options.home ?? homedir()\n const now = options.now ?? new Date()\n\n const globalConfig = loadConfigOptional(join(home, '.lincolnrc'))\n const localConfig = loadConfigOptional(join(cwd, '.lincolnrc'))\n\n const topic = pickFirst(args.topic, localConfig.defaultTopic, globalConfig.defaultTopic)\n const designId = pickFirst(args.designId, localConfig.defaultDesignId, globalConfig.defaultDesignId)\n const branch = pickFirst(args.branch, localConfig.defaultBranch, globalConfig.defaultBranch)\n\n const descriptor = designId || topic || undefined\n const sessionId = args.sessionId || uniqueSessionId(cwd, now, descriptor)\n\n return {\n workspaceRoot: cwd,\n sessionId,\n topic,\n designId,\n branch,\n noTui: args.noTui ?? false,\n autoProcess: localConfig.autoProcess ?? globalConfig.autoProcess ?? false,\n showAudioMeter: localConfig.showAudioMeter ?? globalConfig.showAudioMeter ?? true,\n audioMeterStyle: localConfig.audioMeterStyle ?? globalConfig.audioMeterStyle ?? 'bar',\n }\n}\n","import { readFileSync } from 'node:fs'\nimport { PathLike } from 'node:fs'\n\nimport yaml from 'js-yaml'\n\nexport interface LincolnConfig {\n defaultTopic?: string\n defaultDesignId?: string\n defaultBranch?: string\n autoProcess?: boolean\n showAudioMeter?: boolean\n audioMeterStyle?: 'bar' | 'dot' | 'wave'\n}\n\nfunction parseConfig(content: string, path: PathLike): LincolnConfig {\n const trimmed = content.trim()\n if (!trimmed) {\n return {}\n }\n\n const isJson = trimmed.startsWith('{') || trimmed.startsWith('[')\n const raw = isJson ? JSON.parse(trimmed) : yaml.load(trimmed)\n\n if (raw === null || typeof raw !== 'object') {\n return {}\n }\n\n const data = raw as Record<string, unknown>\n\n return {\n defaultTopic: asString(data.default_topic),\n defaultDesignId: asString(data.default_design_id),\n defaultBranch: asString(data.default_branch),\n autoProcess: asBoolean(data.auto_process),\n showAudioMeter: asBoolean(data.show_audio_meter),\n audioMeterStyle: asMeterStyle(data.audio_meter_style),\n }\n}\n\nfunction asString(value: unknown): string | undefined {\n return typeof value === 'string' ? value : undefined\n}\n\nfunction asBoolean(value: unknown): boolean | undefined {\n return typeof value === 'boolean' ? value : undefined\n}\n\nfunction asMeterStyle(value: unknown): LincolnConfig['audioMeterStyle'] {\n if (value === 'bar' || value === 'dot' || value === 'wave') {\n return value\n }\n return undefined\n}\n\nexport function loadConfig(path: PathLike): LincolnConfig {\n let content: string\n try {\n content = readFileSync(path, 'utf-8')\n } catch (error) {\n throw new Error(`Config file not found: ${String(path)}`)\n }\n\n try {\n return parseConfig(content, path)\n } catch (error) {\n const cause = error instanceof Error ? error.message : String(error)\n throw new Error(`Failed to parse config ${String(path)}: ${cause}`)\n }\n}\n\nexport function loadConfigOptional(path: PathLike): LincolnConfig {\n try {\n return loadConfig(path)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n if (message.includes('Config file not found')) {\n return {}\n }\n throw error\n }\n}\n","export interface GenerateSessionIdOptions {\n now?: Date\n descriptor?: string\n}\n\nexport function generateSessionId(options: GenerateSessionIdOptions = {}): string {\n const now = options.now ?? new Date()\n const date = now.toISOString().slice(0, 10)\n const slug = normalizeDescriptor(options.descriptor)\n return `${date}-${slug}`\n}\n\nfunction normalizeDescriptor(descriptor: string | undefined): string {\n if (!descriptor) {\n return 'recording'\n }\n\n const normalized = descriptor\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9一-龥]+/g, '-')\n .replace(/^-+|-+$/g, '')\n\n return normalized.slice(0, 80) || 'recording'\n}\n","import { Box, useApp } from 'ink'\nimport React, { useCallback, useEffect, useMemo, useState } from 'react'\n\nimport { StatusPanel } from './StatusPanel'\nimport { LogView, type LogEntry } from './LogView'\nimport { HintBar } from './HintBar'\nimport { DevicesMenu } from './DevicesMenu'\nimport { ModelMenu } from './ModelMenu'\nimport { useKeyHandler } from '../hooks/useKeyHandler'\nimport { useRecorder } from '../recording/useRecorder'\nimport { listDevices } from '../devices/listDevices'\nimport { defaultModelCacheDir, listModelStatuses, type ModelStatus } from '../models/models'\nimport { runWarmup } from '../models/runWarmup'\nimport type { WarmupProgress } from '../models/warmupProgress'\nimport type { DeviceList } from '../devices/parseDevices'\n\ntype AppMode = 'main' | 'devices' | 'model'\n\nexport interface RecordingAppProps {\n workspaceRoot: string\n sessionId: string\n topic: string\n designId: string\n branch: string\n audioMeterStyle?: 'bar' | 'dot' | 'wave'\n lincolnRecordPath?: string\n listDevicesFn?: () => Promise<DeviceList>\n listModelStatusesFn?: () => Promise<ModelStatus[]>\n runWarmupFn?: (model: string, onProgress: (p: WarmupProgress) => void) => Promise<string>\n}\n\nfunction createLogId() {\n return `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`\n}\n\nexport function RecordingApp({\n workspaceRoot,\n sessionId,\n topic,\n designId,\n branch,\n audioMeterStyle = 'bar',\n lincolnRecordPath,\n listDevicesFn,\n listModelStatusesFn,\n runWarmupFn,\n}: RecordingAppProps) {\n const { exit } = useApp()\n const [logs, setLogs] = useState<LogEntry[]>([])\n const [mode, setMode] = useState<AppMode>('main')\n const [mic, setMic] = useState<string | null>(null)\n const [model, setModel] = useState<string | null>(null)\n\n const addLog = useCallback((message: string, type: LogEntry['type'] = 'info') => {\n setLogs(prev => [...prev, { id: createLogId(), message, type }])\n }, [])\n\n const { state, start, stop, cancel } = useRecorder({\n workspaceRoot,\n sessionId,\n lincolnRecordPath,\n mic,\n model,\n startOnMount: false,\n })\n\n useEffect(() => {\n switch (state.status) {\n case 'recording':\n addLog('Recording started.', 'info')\n break\n case 'stopped':\n addLog(`Saved to ${workspaceRoot}/${sessionId}/audio.wav`, 'success')\n addLog(`Run: claude process-interview ${sessionId}`, 'command')\n break\n case 'cancelled':\n addLog('Recording cancelled. No files were saved.', 'error')\n break\n case 'error':\n addLog(`Recording error: ${state.errorMessage ?? 'unknown error'}`, 'error')\n break\n }\n }, [state.status, state.errorMessage, addLog, workspaceRoot, sessionId])\n\n const handleQuit = useCallback(() => {\n exit()\n }, [exit])\n\n const handleRecord = useCallback(() => {\n if (state.status === 'idle') {\n start()\n }\n }, [state.status, start])\n\n const handleStop = useCallback(() => {\n if (state.status === 'recording') {\n stop().catch(() => {})\n }\n }, [state.status, stop])\n\n const handleCancel = useCallback(() => {\n if (state.status === 'recording') {\n cancel().catch(() => {})\n }\n }, [state.status, cancel])\n\n const handleDevices = useCallback(() => {\n if (state.status === 'idle') {\n setMode('devices')\n }\n }, [state.status])\n\n const handleModel = useCallback(() => {\n if (state.status === 'idle') {\n setMode('model')\n }\n }, [state.status])\n\n const handleDeviceSelect = useCallback(\n (device: string) => {\n setMic(device)\n addLog(`Input device: ${device}`, 'success')\n setMode('main')\n },\n [addLog],\n )\n\n const handleModelSelect = useCallback(\n (name: string) => {\n setModel(name)\n addLog(`Model: ${name}`, 'success')\n setMode('main')\n },\n [addLog],\n )\n\n const handleMenuClose = useCallback(() => {\n setMode('main')\n }, [])\n\n const isTerminal = state.status === 'stopped' || state.status === 'cancelled' || state.status === 'error'\n\n useKeyHandler({\n enabled: mode === 'main',\n onRecord: handleRecord,\n onStop: handleStop,\n onCancel: handleCancel,\n onQuit: handleQuit,\n onDevices: handleDevices,\n onModel: handleModel,\n onAnyKey: isTerminal ? handleQuit : undefined,\n })\n\n const hintMode = useMemo(() => {\n if (mode !== 'main') return 'menu'\n if (state.status === 'idle') return 'idle'\n if (state.status === 'recording') return 'recording'\n if (state.status === 'stopped') return 'stopped'\n if (state.status === 'cancelled') return 'cancelled'\n return 'error'\n }, [mode, state.status])\n\n const devicesLoader = useCallback(\n () => (listDevicesFn ?? (() => listDevices(lincolnRecordPath)))(),\n [listDevicesFn, lincolnRecordPath],\n )\n\n const modelsLoader = useCallback(\n () => (listModelStatusesFn ?? (() => Promise.resolve(listModelStatuses(defaultModelCacheDir()))))(),\n [listModelStatusesFn],\n )\n\n const warmupRunner = useCallback(\n (name: string, onProgress: (p: WarmupProgress) => void) =>\n runWarmupFn\n ? runWarmupFn(name, onProgress)\n : runWarmup({ model: name, lincolnRecordPath, onProgress }),\n [runWarmupFn, lincolnRecordPath],\n )\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"gray\" height={24}>\n <StatusPanel\n sessionId={sessionId}\n topic={topic}\n designId={designId}\n branch={branch}\n status={state.status}\n duration={state.duration}\n />\n {mode === 'devices' && (\n <DevicesMenu\n listDevicesFn={devicesLoader}\n onSelect={handleDeviceSelect}\n onClose={handleMenuClose}\n />\n )}\n {mode === 'model' && (\n <ModelMenu\n listModelStatusesFn={modelsLoader}\n runWarmupFn={warmupRunner}\n onSelect={handleModelSelect}\n onClose={handleMenuClose}\n />\n )}\n <LogView logs={logs} />\n <Box flexGrow={1} />\n <HintBar mode={hintMode} />\n </Box>\n )\n}\n","import { Box, Text } from 'ink'\nimport React from 'react'\n\nimport { formatDuration } from '../utils/formatDuration'\n\nexport interface StatusPanelProps {\n sessionId: string\n topic?: string\n designId?: string\n branch?: string\n status: 'idle' | 'recording' | 'stopped' | 'cancelled' | 'error'\n duration: number\n amplitude?: number\n}\n\nexport function StatusPanel({\n sessionId,\n topic,\n designId,\n branch,\n status,\n duration,\n}: StatusPanelProps) {\n const statusLabel = {\n idle: 'Ready',\n recording: `Recording ${formatDuration(duration)}`,\n stopped: 'Stopped',\n cancelled: 'Cancelled',\n error: 'Error',\n }[status]\n\n const statusColor = status === 'recording' ? 'red' : status === 'error' ? 'red' : status === 'cancelled' ? 'yellow' : 'green'\n\n return (\n <Box flexDirection=\"column\" paddingX={1} paddingTop={1}>\n <Box flexDirection=\"row\" justifyContent=\"space-between\" alignItems=\"center\">\n <Text bold color=\"white\">Lincoln Recorder</Text>\n <Box flexDirection=\"row\" gap={1}>\n <Text color={statusColor}>{status === 'recording' ? '●' : '○'}</Text>\n <Text>{statusLabel}</Text>\n </Box>\n </Box>\n\n <Box flexDirection=\"column\" paddingY={1}>\n <Text dimColor>Session: {sessionId}</Text>\n {topic ? <Text dimColor>Topic: {topic}</Text> : null}\n {designId ? <Text dimColor>Design: {designId}</Text> : null}\n {branch ? <Text dimColor>Branch: {branch}</Text> : null}\n </Box>\n </Box>\n )\n}\n","export function formatDuration(totalSeconds: number): string {\n const safeSeconds = Math.max(0, Math.floor(totalSeconds))\n const minutes = Math.floor(safeSeconds / 60)\n const seconds = safeSeconds % 60\n return `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`\n}\n","import { Box, Text } from 'ink'\nimport React from 'react'\n\nexport interface LogEntry {\n id: string\n message: string\n type?: 'info' | 'success' | 'error' | 'command'\n}\n\nexport interface LogViewProps {\n logs: LogEntry[]\n}\n\nconst TYPE_COLORS: Record<string, string | undefined> = {\n info: undefined,\n success: 'green',\n error: 'red',\n command: 'cyan',\n}\n\nexport function LogView({ logs }: LogViewProps) {\n const visible = logs.slice(-8)\n\n return (\n <Box flexDirection=\"column\" paddingX={1} flexGrow={1}>\n <Text underline dimColor>Log</Text>\n {visible.length === 0 ? (\n <Text dimColor>No events yet.</Text>\n ) : (\n visible.map(log => (\n <Text key={log.id} color={TYPE_COLORS[log.type ?? 'info']}>{log.message}</Text>\n ))\n )}\n </Box>\n )\n}\n","import { Box, Text } from 'ink'\nimport React from 'react'\n\nexport type HintKey = 'idle' | 'recording' | 'stopped' | 'cancelled' | 'error' | 'menu'\n\nexport interface HintBarProps {\n mode: HintKey\n}\n\nconst HINTS: Record<HintKey, string> = {\n idle: '[r] record [d] devices [m] model [q] quit',\n recording: '[s] stop [c] cancel',\n stopped: '[any key] exit',\n cancelled: '[q] exit',\n error: '[q] exit',\n menu: '[↑↓] select [enter] confirm [esc] back',\n}\n\nexport function HintBar({ mode }: HintBarProps) {\n return (\n <Box paddingX={1} paddingY={1}>\n <Text dimColor>{HINTS[mode]}</Text>\n </Box>\n )\n}\n","import { Box, Text, useInput } from 'ink'\nimport React, { useEffect, useState } from 'react'\n\nimport { SelectMenu } from './SelectMenu'\nimport type { DeviceList } from '../devices/parseDevices'\n\nexport interface DevicesMenuProps {\n listDevicesFn: () => Promise<DeviceList>\n onSelect: (device: string) => void\n onClose: () => void\n}\n\ntype LoadState =\n | { status: 'loading' }\n | { status: 'loaded'; list: DeviceList }\n | { status: 'error'; message: string }\n\nexport function DevicesMenu({ listDevicesFn, onSelect, onClose }: DevicesMenuProps) {\n const [loadState, setLoadState] = useState<LoadState>({ status: 'loading' })\n\n useEffect(() => {\n let cancelled = false\n listDevicesFn()\n .then(list => {\n if (!cancelled) setLoadState({ status: 'loaded', list })\n })\n .catch(error => {\n if (!cancelled) {\n setLoadState({\n status: 'error',\n message: error instanceof Error ? error.message : String(error),\n })\n }\n })\n return () => {\n cancelled = true\n }\n }, [listDevicesFn])\n\n useInput(\n (_input, key) => {\n if (key.escape) onClose()\n },\n { isActive: loadState.status !== 'loaded' },\n )\n\n if (loadState.status === 'loading') {\n return (\n <Box paddingX={1}>\n <Text dimColor>Loading devices…</Text>\n </Box>\n )\n }\n\n if (loadState.status === 'error') {\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Text color=\"red\">Failed to list devices: {loadState.message}</Text>\n <Text dimColor>[esc] back</Text>\n </Box>\n )\n }\n\n const { list } = loadState\n const items = list.devices.map(name => ({\n key: name,\n label: name === list.defaultDevice ? `${name} (default)` : name,\n }))\n\n return (\n <SelectMenu\n title=\"Devices\"\n items={items}\n onSelect={onSelect}\n onClose={onClose}\n footer=\"[↑↓] select [enter] confirm [esc] back\"\n />\n )\n}\n","import { Box, Text, useInput } from 'ink'\nimport React, { useState } from 'react'\n\nexport interface SelectMenuItem {\n key: string\n label: string\n}\n\nexport interface SelectMenuProps {\n title: string\n items: SelectMenuItem[]\n onSelect: (key: string) => void\n onClose: () => void\n footer?: string\n}\n\nexport function SelectMenu({ title, items, onSelect, onClose, footer }: SelectMenuProps) {\n const [index, setIndex] = useState(0)\n\n useInput((_input, key) => {\n if (key.escape) {\n onClose()\n return\n }\n if (key.upArrow) {\n setIndex(i => (i > 0 ? i - 1 : items.length - 1))\n return\n }\n if (key.downArrow) {\n setIndex(i => (i < items.length - 1 ? i + 1 : 0))\n return\n }\n if (key.return && items.length > 0) {\n onSelect(items[Math.min(index, items.length - 1)].key)\n }\n })\n\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Text bold>{title}</Text>\n {items.length === 0 ? (\n <Text dimColor>(none)</Text>\n ) : (\n items.map((item, i) => (\n <Text key={item.key} color={i === index ? 'cyan' : undefined}>\n {i === index ? '›' : ' '} {item.label}\n </Text>\n ))\n )}\n {footer ? <Text dimColor>{footer}</Text> : null}\n </Box>\n )\n}\n","import { Box, Text, useInput } from 'ink'\nimport React, { useEffect, useState } from 'react'\n\nimport { SelectMenu } from './SelectMenu'\nimport type { ModelStatus } from '../models/models'\nimport type { WarmupProgress } from '../models/warmupProgress'\n\nexport interface ModelMenuProps {\n listModelStatusesFn: () => Promise<ModelStatus[]>\n runWarmupFn: (model: string, onProgress: (p: WarmupProgress) => void) => Promise<string>\n onSelect: (model: string) => void\n onClose: () => void\n}\n\ntype MenuState =\n | { status: 'loading' }\n | { status: 'loaded'; models: ModelStatus[] }\n | { status: 'downloading'; model: string; percent: number | null; downloaded: number }\n | { status: 'error'; message: string }\n\nexport function ModelMenu({ listModelStatusesFn, runWarmupFn, onSelect, onClose }: ModelMenuProps) {\n const [menuState, setMenuState] = useState<MenuState>({ status: 'loading' })\n\n useEffect(() => {\n let cancelled = false\n listModelStatusesFn()\n .then(models => {\n if (!cancelled) setMenuState({ status: 'loaded', models })\n })\n .catch(error => {\n if (!cancelled) {\n setMenuState({\n status: 'error',\n message: error instanceof Error ? error.message : String(error),\n })\n }\n })\n return () => {\n cancelled = true\n }\n }, [listModelStatusesFn])\n\n useInput(\n (_input, key) => {\n if (key.escape) onClose()\n },\n { isActive: menuState.status === 'error' },\n )\n\n const handleSelect = (name: string) => {\n if (menuState.status !== 'loaded') return\n const target = menuState.models.find(m => m.name === name)\n if (!target) return\n\n if (target.cached) {\n onSelect(name)\n return\n }\n\n setMenuState({ status: 'downloading', model: name, percent: null, downloaded: 0 })\n runWarmupFn(name, progress => {\n setMenuState({\n status: 'downloading',\n model: name,\n percent: progress.percent,\n downloaded: progress.downloaded,\n })\n })\n .then(() => onSelect(name))\n .catch(error => {\n setMenuState({\n status: 'error',\n message: error instanceof Error ? error.message : String(error),\n })\n })\n }\n\n if (menuState.status === 'loading') {\n return (\n <Box paddingX={1}>\n <Text dimColor>Loading models…</Text>\n </Box>\n )\n }\n\n if (menuState.status === 'error') {\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Text color=\"red\">{menuState.message}</Text>\n <Text dimColor>[esc] back</Text>\n </Box>\n )\n }\n\n if (menuState.status === 'downloading') {\n const progressText =\n menuState.percent !== null\n ? `${menuState.percent.toFixed(1)}%`\n : `${menuState.downloaded} bytes`\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Text>Downloading model '{menuState.model}'… {progressText}</Text>\n <Text dimColor>please wait</Text>\n </Box>\n )\n }\n\n const items = menuState.models.map(m => ({\n key: m.name,\n label: m.cached ? `✓ ${m.name}` : `· ${m.name} (not downloaded)`,\n }))\n\n return (\n <SelectMenu\n title=\"Model\"\n items={items}\n onSelect={handleSelect}\n onClose={onClose}\n footer=\"[↑↓] select [enter] confirm [esc] back\"\n />\n )\n}\n","import { useInput } from 'ink'\n\nexport interface KeyHandlerOptions {\n enabled?: boolean\n onRecord?: () => void\n onStop?: () => void\n onCancel?: () => void\n onQuit?: () => void\n onDevices?: () => void\n onModel?: () => void\n onAnyKey?: () => void\n}\n\nexport function useKeyHandler({\n enabled = true,\n onRecord,\n onStop,\n onCancel,\n onQuit,\n onDevices,\n onModel,\n onAnyKey,\n}: KeyHandlerOptions) {\n useInput(\n (input, key) => {\n if (key.escape || input === 'q' || input === 'Q') {\n onQuit?.()\n return\n }\n\n if (key.ctrl && input === 'c') {\n onQuit?.()\n return\n }\n\n switch (input) {\n case 'r':\n case 'R':\n onRecord?.()\n return\n case 's':\n case 'S':\n onStop?.()\n return\n case 'c':\n case 'C':\n onCancel?.()\n return\n case 'd':\n case 'D':\n onDevices?.()\n return\n case 'm':\n case 'M':\n onModel?.()\n return\n }\n\n onAnyKey?.()\n },\n { isActive: enabled },\n )\n}\n","import { useCallback, useEffect, useRef, useState } from 'react'\n\nimport { spawnRecorder, type RecorderProcess, type SpawnRecorderOptions } from './spawnRecorder'\n\nexport interface UseRecorderOptions extends SpawnRecorderOptions {\n startOnMount?: boolean\n}\n\nexport interface RecorderState {\n status: 'idle' | 'recording' | 'stopped' | 'cancelled' | 'error'\n duration: number\n amplitude: number\n errorMessage: string | null\n}\n\nexport interface RecorderController {\n state: RecorderState\n start: () => void\n stop: () => Promise<void>\n cancel: () => Promise<void>\n}\n\nfunction mockAmplitude(duration: number): number {\n return 0.5 + 0.4 * Math.sin(duration * 0.8)\n}\n\nexport function useRecorder(options: UseRecorderOptions): RecorderController {\n const {\n startOnMount = false,\n workspaceRoot,\n sessionId,\n lincolnRecordPath,\n mic,\n model,\n } = options\n const [state, setState] = useState<RecorderState>({\n status: 'idle',\n duration: 0,\n amplitude: 0,\n errorMessage: null,\n })\n\n const recorderRef = useRef<RecorderProcess | null>(null)\n const intervalRef = useRef<NodeJS.Timeout | null>(null)\n const durationRef = useRef(0)\n const terminatingRef = useRef(false)\n\n const clearRecordingInterval = useCallback(() => {\n if (intervalRef.current) {\n clearInterval(intervalRef.current)\n intervalRef.current = null\n }\n }, [])\n\n const start = useCallback(() => {\n if (recorderRef.current) {\n return\n }\n\n terminatingRef.current = false\n setState({ status: 'recording', duration: 0, amplitude: 0.3, errorMessage: null })\n durationRef.current = 0\n\n try {\n const recorder = spawnRecorder({\n workspaceRoot,\n sessionId,\n lincolnRecordPath,\n mic,\n model,\n })\n recorderRef.current = recorder\n\n recorder.on('ready', () => {\n // Recording is active\n })\n\n recorder.on('error', error => {\n setState(s => ({ ...s, status: 'error', errorMessage: error.message }))\n clearRecordingInterval()\n })\n\n recorder.on('exit', (code, signal) => {\n recorderRef.current = null\n clearRecordingInterval()\n\n if (terminatingRef.current) {\n return\n }\n\n const reason = code !== null && code !== undefined\n ? `lincoln-record exited unexpectedly with code ${code}`\n : `lincoln-record exited unexpectedly with signal ${signal}`\n setState(s => ({ ...s, status: 'error', errorMessage: reason }))\n })\n\n intervalRef.current = setInterval(() => {\n durationRef.current += 1\n setState(s => ({\n ...s,\n duration: durationRef.current,\n amplitude: mockAmplitude(durationRef.current),\n }))\n }, 1000)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n setState(s => ({ ...s, status: 'error', errorMessage: message }))\n }\n }, [workspaceRoot, sessionId, lincolnRecordPath, mic, model, clearRecordingInterval])\n\n const stop = useCallback(async () => {\n const recorder = recorderRef.current\n if (!recorder) return\n\n terminatingRef.current = true\n clearRecordingInterval()\n setState(s => ({ ...s, status: 'stopped' }))\n await recorder.stop()\n }, [clearRecordingInterval])\n\n const cancel = useCallback(async () => {\n const recorder = recorderRef.current\n if (!recorder) return\n\n terminatingRef.current = true\n clearRecordingInterval()\n setState(s => ({ ...s, status: 'cancelled' }))\n await recorder.cancel()\n }, [clearRecordingInterval])\n\n useEffect(() => {\n if (startOnMount) {\n start()\n }\n\n return () => {\n clearRecordingInterval()\n if (recorderRef.current) {\n recorderRef.current.cancel().catch(() => {})\n recorderRef.current = null\n }\n }\n }, [startOnMount, start, clearRecordingInterval])\n\n return { state, start, stop, cancel }\n}\n","import { spawn, type ChildProcessByStdio } from 'node:child_process'\nimport { type Readable, type Writable } from 'node:stream'\nimport { EventEmitter } from 'node:events'\n\nexport interface SpawnRecorderOptions {\n workspaceRoot: string\n sessionId: string\n lincolnRecordPath?: string\n mic?: string | null\n model?: string | null\n}\n\nexport interface RecorderProcess {\n on(event: 'ready', listener: () => void): this\n on(event: 'error', listener: (error: Error) => void): this\n on(event: 'exit', listener: (code: number | null, signal: NodeJS.Signals | null) => void): this\n stop(): Promise<void>\n cancel(): Promise<void>\n}\n\nclass RecorderProcessImpl extends EventEmitter implements RecorderProcess {\n private child: ChildProcessByStdio<Writable, Readable, Readable>\n private stopped = false\n private exitPromise: Promise<void>\n private resolveExit: () => void = () => {}\n private exitSettled = false\n\n constructor(child: ChildProcessByStdio<Writable, Readable, Readable>) {\n super()\n this.child = child\n this.exitPromise = new Promise((resolve) => {\n this.resolveExit = resolve\n })\n\n this.child.on('error', (error) => {\n this.emit('error', error)\n this.settleExit()\n })\n\n this.child.on('exit', (code, signal) => {\n this.emit('exit', code, signal)\n this.settleExit()\n })\n\n this.child.stdout.on('data', (data: Buffer) => {\n process.stdout.write(data)\n })\n\n this.child.stderr.on('data', (data: Buffer) => {\n process.stderr.write(data)\n })\n\n // lincoln-record begins capturing immediately; treat it as ready.\n process.nextTick(() => this.emit('ready'))\n }\n\n private settleExit(): void {\n if (!this.exitSettled) {\n this.exitSettled = true\n this.resolveExit()\n }\n }\n\n stop(): Promise<void> {\n return this._terminate('SIGINT')\n }\n\n cancel(): Promise<void> {\n return this._terminate('SIGKILL')\n }\n\n private _terminate(signal: NodeJS.Signals): Promise<void> {\n if (this.stopped) {\n return this.exitPromise\n }\n this.stopped = true\n\n if (this.child.killed) {\n return this.exitPromise\n }\n\n this.child.kill(signal)\n\n const timeout = setTimeout(() => {\n if (!this.child.killed) {\n this.child.kill('SIGKILL')\n }\n }, 5000)\n\n this.exitPromise.finally(() => clearTimeout(timeout))\n\n return this.exitPromise\n }\n}\n\nexport function spawnRecorder(options: SpawnRecorderOptions): RecorderProcess {\n const {\n workspaceRoot,\n sessionId,\n lincolnRecordPath = 'lincoln-record',\n mic,\n model,\n } = options\n\n const args: string[] = [\n 'record',\n '--session-id',\n sessionId,\n '--output',\n workspaceRoot,\n ]\n\n if (mic) {\n args.push('--mic', mic)\n }\n\n if (model) {\n args.push('--model', model)\n }\n\n const child = spawn(lincolnRecordPath, args, {\n cwd: workspaceRoot,\n stdio: ['pipe', 'pipe', 'pipe'],\n })\n\n return new RecorderProcessImpl(child)\n}\n","import { execFile } from 'node:child_process'\nimport { promisify } from 'node:util'\n\nimport { parseDevicesOutput, type DeviceList } from './parseDevices'\n\nconst execFileAsync = promisify(execFile)\n\nexport async function listDevices(lincolnRecordPath = 'lincoln-record'): Promise<DeviceList> {\n const { stdout } = await execFileAsync(lincolnRecordPath, ['devices'])\n return parseDevicesOutput(stdout)\n}\n","export interface DeviceList {\n defaultDevice: string | null\n devices: string[]\n}\n\nconst DEFAULT_PREFIX = 'Default input: '\n\nexport function parseDevicesOutput(output: string): DeviceList {\n let defaultDevice: string | null = null\n const devices: string[] = []\n\n for (const rawLine of output.split('\\n')) {\n const line = rawLine.trim()\n if (!line) continue\n\n if (line.startsWith(DEFAULT_PREFIX)) {\n defaultDevice = line.slice(DEFAULT_PREFIX.length).trim() || null\n continue\n }\n\n devices.push(line)\n }\n\n return { defaultDevice, devices }\n}\n","import { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nexport const KNOWN_MODELS = [\n 'tiny',\n 'base',\n 'small',\n 'medium',\n 'large-v1',\n 'large-v2',\n 'large-v3',\n 'large-v3-turbo',\n]\n\nexport interface ModelStatus {\n name: string\n cached: boolean\n}\n\nexport function defaultModelCacheDir(): string {\n return join(homedir(), '.cache', 'lincoln', 'models')\n}\n\nexport function modelCachePath(name: string, cacheDir: string): string {\n return join(cacheDir, 'whisper', `ggml-${name}.bin`)\n}\n\nexport function listModelStatuses(cacheDir: string): ModelStatus[] {\n return KNOWN_MODELS.map(name => ({\n name,\n cached: existsSync(modelCachePath(name, cacheDir)),\n }))\n}\n","import { spawn } from 'node:child_process'\n\nimport { parseWarmupProgress, type WarmupProgress } from './warmupProgress'\n\nexport interface RunWarmupOptions {\n model: string\n lincolnRecordPath?: string\n onProgress?: (progress: WarmupProgress) => void\n}\n\nconst READY_LINE = /Model ready at (.+)/\n\nexport function runWarmup(options: RunWarmupOptions): Promise<string> {\n const { model, lincolnRecordPath = 'lincoln-record', onProgress } = options\n\n return new Promise((resolve, reject) => {\n const child = spawn(lincolnRecordPath, ['warmup', '--model', model], {\n stdio: ['ignore', 'pipe', 'pipe'],\n })\n\n let readyPath: string | null = null\n\n child.stdout.on('data', (data: Buffer) => {\n const match = READY_LINE.exec(data.toString())\n if (match) {\n readyPath = match[1].trim()\n }\n })\n\n child.stderr.on('data', (data: Buffer) => {\n const progress = parseWarmupProgress(data.toString())\n if (progress) {\n onProgress?.(progress)\n }\n })\n\n child.on('error', reject)\n child.on('exit', code => {\n if (code === 0) {\n resolve(readyPath ?? model)\n } else {\n reject(new Error(`lincoln-record warmup exited with code ${code}`))\n }\n })\n })\n}\n","export interface WarmupProgress {\n downloaded: number\n total: number | null\n percent: number | null\n}\n\nconst PROGRESS_WITH_TOTAL = /downloaded (\\d+) \\/ (\\d+) bytes \\(([\\d.]+)%\\)/\nconst PROGRESS_WITHOUT_TOTAL = /downloaded (\\d+) bytes/\n\nexport function parseWarmupProgress(chunk: string): WarmupProgress | null {\n const withTotal = PROGRESS_WITH_TOTAL.exec(chunk)\n if (withTotal) {\n return {\n downloaded: Number(withTotal[1]),\n total: Number(withTotal[2]),\n percent: Number(withTotal[3]),\n }\n }\n\n const withoutTotal = PROGRESS_WITHOUT_TOTAL.exec(chunk)\n if (withoutTotal) {\n return {\n downloaded: Number(withoutTotal[1]),\n total: null,\n percent: null,\n }\n }\n\n return null\n}\n","#!/usr/bin/env node\nimport { main } from './cli'\n\nmain()\n"],"mappings":"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","names":["Box","Text","Box","useCallback","useEffect","useState","Box","Text","jsx","jsxs","Box","Text","jsx","Box","Text","useInput","useState","Box","Text","jsx","jsxs","jsx","jsxs","useState","list","useInput","Box","Text","Box","Text","useInput","useEffect","useState","jsx","jsxs","useState","useEffect","useInput","Box","Text","useInput","useEffect","useState","useState","useEffect","existsSync","homedir","join","spawn","spawn","jsx","jsxs","useState","useCallback","useEffect","Box","jsx","jsxs","Box","Text"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sushanglewis/lincoln",
|
|
3
|
+
"version": "1.5.0",
|
|
4
|
+
"description": "Cross-tool terminal UI for recording Lincoln interviews",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"bin": {
|
|
10
|
+
"lincoln": "./dist/main.js"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsup",
|
|
17
|
+
"dev": "tsup --watch",
|
|
18
|
+
"test": "vitest run",
|
|
19
|
+
"test:watch": "vitest",
|
|
20
|
+
"typecheck": "tsc --noEmit",
|
|
21
|
+
"typecheck:tests": "tsc -p tsconfig.tests.json",
|
|
22
|
+
"lint": "echo 'lint not configured'"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"ink": "^5.2.0",
|
|
26
|
+
"js-yaml": "^4.1.0",
|
|
27
|
+
"react": "^18.3.1"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@types/js-yaml": "^4.0.9",
|
|
31
|
+
"@types/node": "^22.15.0",
|
|
32
|
+
"@types/react": "^18.3.12",
|
|
33
|
+
"ink-testing-library": "^4.0.0",
|
|
34
|
+
"tsup": "^8.5.0",
|
|
35
|
+
"typescript": "^5.8.3",
|
|
36
|
+
"vitest": "^4.1.9"
|
|
37
|
+
},
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=20.0.0"
|
|
40
|
+
},
|
|
41
|
+
"keywords": [
|
|
42
|
+
"lincoln",
|
|
43
|
+
"interview",
|
|
44
|
+
"recording",
|
|
45
|
+
"tui"
|
|
46
|
+
],
|
|
47
|
+
"license": "MIT"
|
|
48
|
+
}
|