chore: formatting etc

This commit is contained in:
Brooklyn Nicholson 2026-04-03 20:14:57 -05:00
parent 56a69e519b
commit 5a5d90c85a
14 changed files with 698 additions and 237 deletions

View file

@ -1,23 +1,21 @@
import { Box, Text } from 'ink'
import { COMMANDS } from '../constants.js'
import type { Theme } from '../theme.js'
export function CommandPalette({ filter, t }: { filter: string; t: Theme }) {
const matches = COMMANDS.filter(([cmd]) => cmd.startsWith(filter))
export function CommandPalette({ matches, t }: { matches: [string, string][]; t: Theme }) {
if (!matches.length) {
return null
}
return (
<Box flexDirection="column">
{matches.map(([cmd, desc]) => (
<Text key={cmd}>
<Box flexDirection="column" marginBottom={1}>
{matches.map(([cmd, desc], i) => (
<Text key={`${i}-${cmd}`}>
<Text bold color={t.color.amber}>
{cmd}
</Text>
<Text color={t.color.dim}> {desc}</Text>
{desc ? <Text color={t.color.dim}> {desc}</Text> : null}
</Text>
))}
</Box>

View file

@ -147,37 +147,47 @@ export function Md({ compact, t, text }: { compact?: boolean; t: Theme; text: st
if (line.match(/^>\s?/)) {
const quoteLines: string[] = []
while (i < lines.length && lines[i]!.match(/^>\s?/)) {
quoteLines.push(lines[i]!.replace(/^>\s?/, ''))
i++
}
nodes.push(
<Box flexDirection="column" key={key}>
{quoteLines.map((ql, qi) => (
<Text color={t.color.dim} key={qi}>
{' │ '}<MdInline t={t} text={ql} />
{' │ '}
<MdInline t={t} text={ql} />
</Text>
))}
</Box>
)
continue
}
if (line.includes('|') && line.trim().startsWith('|')) {
const tableRows: string[][] = []
while (i < lines.length && lines[i]!.trim().startsWith('|')) {
const row = lines[i]!.trim()
if (!/^[|\s:-]+$/.test(row)) {
tableRows.push(
row.split('|').filter(Boolean).map(c => c.trim())
row
.split('|')
.filter(Boolean)
.map(c => c.trim())
)
}
i++
}
if (tableRows.length) {
const widths = tableRows[0]!.map((_, ci) =>
Math.max(...tableRows.map(r => (r[ci] ?? '').length))
)
const widths = tableRows[0]!.map((_, ci) => Math.max(...tableRows.map(r => (r[ci] ?? '').length)))
nodes.push(
<Box flexDirection="column" key={key} paddingLeft={2}>
{tableRows.map((row, ri) => (
@ -188,6 +198,7 @@ export function Md({ compact, t, text }: { compact?: boolean; t: Theme; text: st
</Box>
)
}
continue
}

View file

@ -5,7 +5,11 @@ import { useState } from 'react'
import type { Theme } from '../theme.js'
export function MaskedPrompt({
icon, label, onSubmit, sub, t
icon,
label,
onSubmit,
sub,
t
}: {
icon: string
label: string
@ -17,8 +21,10 @@ export function MaskedPrompt({
return (
<Box flexDirection="column">
<Text bold color={t.color.warn}>{icon} {label}</Text>
{sub && <Text color={t.color.dim}> {sub}</Text>}
<Text bold color={t.color.warn}>
{icon} {label}
</Text>
{sub && <Text color={t.color.dim}> {sub}</Text>}
<Box>
<Text color={t.color.label}>{'> '}</Text>

View file

@ -14,8 +14,15 @@ interface SessionItem {
function age(ts: number): string {
const d = (Date.now() / 1000 - ts) / 86400
if (d < 1) return 'today'
if (d < 2) return 'yesterday'
if (d < 1) {
return 'today'
}
if (d < 2) {
return 'yesterday'
}
return `${Math.floor(d)}d ago`
}
@ -46,16 +53,32 @@ export function SessionPicker({
}, [gw])
useInput((ch, key) => {
if (key.escape) return onCancel()
if (key.upArrow && sel > 0) setSel(s => s - 1)
if (key.downArrow && sel < items.length - 1) setSel(s => s + 1)
if (key.return && items[sel]) onSelect(items[sel]!.id)
if (key.escape) {
return onCancel()
}
if (key.upArrow && sel > 0) {
setSel(s => s - 1)
}
if (key.downArrow && sel < items.length - 1) {
setSel(s => s + 1)
}
if (key.return && items[sel]) {
onSelect(items[sel]!.id)
}
const n = parseInt(ch)
if (n >= 1 && n <= Math.min(9, items.length)) onSelect(items[n - 1]!.id)
if (n >= 1 && n <= Math.min(9, items.length)) {
onSelect(items[n - 1]!.id)
}
})
if (loading) return <Text color={t.color.dim}>loading sessions</Text>
if (loading) {
return <Text color={t.color.dim}>loading sessions</Text>
}
if (!items.length) {
return (
@ -71,10 +94,13 @@ export function SessionPicker({
return (
<Box flexDirection="column">
<Text bold color={t.color.amber}>Resume Session</Text>
{off > 0 && <Text color={t.color.dim}> {off} more</Text>}
<Text bold color={t.color.amber}>
Resume Session
</Text>
{off > 0 && <Text color={t.color.dim}> {off} more</Text>}
{visible.map((s, vi) => {
const i = off + vi
return (
<Text key={s.id}>
<Text color={sel === i ? t.color.label : t.color.dim}>{sel === i ? '▸ ' : ' '}</Text>
@ -82,12 +108,13 @@ export function SessionPicker({
{i + 1}. {s.title || s.preview || s.id.slice(0, 8)}
</Text>
<Text color={t.color.dim}>
{' '}({s.message_count} msgs, {age(s.started_at)})
{' '}
({s.message_count} msgs, {age(s.started_at)})
</Text>
</Text>
)
})}
{off + VISIBLE < items.length && <Text color={t.color.dim}> {items.length - off - VISIBLE} more</Text>}
{off + VISIBLE < items.length && <Text color={t.color.dim}> {items.length - off - VISIBLE} more</Text>}
<Text color={t.color.dim}>/ select · Enter resume · 1-9 quick · Esc cancel</Text>
</Box>
)

View file

@ -6,7 +6,17 @@ import { pick } from '../lib/text.js'
import type { Theme } from '../theme.js'
import type { ActiveTool } from '../types.js'
export function Thinking({ reasoning, t, thinking, tools }: { reasoning: string; t: Theme; thinking?: string; tools: ActiveTool[] }) {
export function Thinking({
reasoning,
t,
thinking,
tools
}: {
reasoning: string
t: Theme
thinking?: string
tools: ActiveTool[]
}) {
const [frame, setFrame] = useState(0)
const [verb] = useState(() => pick(VERBS))
const [face] = useState(() => pick(FACES))