Compare commits

...

4 Commits

Author SHA1 Message Date
Shoubhit Dash
d8c3d8d884 highlight clickable inline tools 2026-03-05 19:07:49 +05:30
Shoubhit Dash
66ba6c4d34 Merge branch 'dev' into fix/subagent-navigation-inline-click 2026-03-05 19:05:30 +05:30
Shoubhit Dash
c4c3a020f9 refactor(tui): use renderer.hasSelection guards 2026-03-04 17:39:44 +05:30
Shoubhit Dash
002b81cd67 fix(tui): keep inline task navigation and fix nested child jump 2026-03-04 17:06:10 +05:30

View File

@@ -128,6 +128,11 @@ export function Session() {
.filter((x) => x.parentID === parentID || x.id === parentID)
.toSorted((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0))
})
const subagents = createMemo(() => {
return sync.data.session
.filter((x) => x.parentID === route.sessionID)
.toSorted((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0))
})
const messages = createMemo(() => sync.data.message[route.sessionID] ?? [])
const permissions = createMemo(() => {
if (session()?.parentID) return []
@@ -316,20 +321,14 @@ export function Session() {
const local = useLocal()
function moveFirstChild() {
if (children().length === 1) return
const next = children().find((x) => !!x.parentID)
if (next) {
navigate({
type: "session",
sessionID: next.id,
})
}
const next = subagents()[0]
if (!next) return
navigate({ type: "session", sessionID: next.id })
}
function moveChild(direction: number) {
if (children().length === 1) return
const sessions = children().filter((x) => !!x.parentID)
if (sessions.length === 0) return
let next = sessions.findIndex((x) => x.id === session()?.id) + direction
if (next >= sessions.length) next = 0
@@ -1124,7 +1123,7 @@ export function Session() {
<UserMessage
index={index()}
onMouseUp={() => {
if (renderer.getSelection()?.getSelectedText()) return
if (renderer.hasSelection) return
dialog.replace(() => (
<DialogMessage
messageID={message.id}
@@ -1623,6 +1622,7 @@ function InlineTool(props: {
complete: any
pending: string
spinner?: boolean
onClick?: () => void
children: JSX.Element
part: ToolPart
}) {
@@ -1630,6 +1630,8 @@ function InlineTool(props: {
const { theme } = useTheme()
const ctx = use()
const sync = useSync()
const renderer = useRenderer()
const [hover, setHover] = createSignal(false)
const permission = createMemo(() => {
const callID = sync.data.permission[ctx.sessionID]?.at(0)?.tool?.callID
@@ -1678,13 +1680,23 @@ function InlineTool(props: {
return
}
}}
onMouseOver={() => props.onClick && setHover(true)}
onMouseOut={() => setHover(false)}
onMouseUp={() => {
if (renderer.hasSelection) return
props.onClick?.()
}}
>
<Switch>
<Match when={props.spinner}>
<Spinner color={fg()} children={props.children} />
<Spinner color={hover() ? theme.text : fg()} children={props.children} />
</Match>
<Match when={true}>
<text paddingLeft={3} fg={fg()} attributes={denied() ? TextAttributes.STRIKETHROUGH : undefined}>
<text
paddingLeft={3}
fg={hover() ? theme.text : fg()}
attributes={denied() ? TextAttributes.STRIKETHROUGH : undefined}
>
<Show fallback={<>~ {props.pending}</>} when={props.complete}>
<span style={{ fg: props.iconColor }}>{props.icon}</span> {props.children}
</Show>
@@ -1723,7 +1735,7 @@ function BlockTool(props: {
onMouseOver={() => props.onClick && setHover(true)}
onMouseOut={() => setHover(false)}
onMouseUp={() => {
if (renderer.getSelection()?.getSelectedText()) return
if (renderer.hasSelection) return
props.onClick?.()
}}
>
@@ -1943,10 +1955,7 @@ function WebSearch(props: ToolProps<any>) {
}
function Task(props: ToolProps<typeof TaskTool>) {
const { theme } = useTheme()
const keybind = useKeybind()
const { navigate } = useRoute()
const local = useLocal()
const sync = useSync()
onMount(() => {
@@ -1999,6 +2008,15 @@ function Task(props: ToolProps<typeof TaskTool>) {
complete={props.input.description}
pending="Delegating..."
part={props.part}
onClick={
props.metadata.sessionId
? () => {
const id = props.metadata.sessionId
if (!id) return
navigate({ type: "session", sessionID: id })
}
: undefined
}
>
{content()}
</InlineTool>