fix(tui): submit prompt when resuming session (#38260)

This commit is contained in:
Simon Klee 2026-07-22 10:34:39 +02:00 committed by GitHub
commit ced3d5e02a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 112 additions and 7 deletions

View file

@ -525,6 +525,7 @@ function App(props: { pair?: DialogPairCredentials; started: number }) {
})
const args = useArgs()
const startupPrompt = args.prompt ? { text: args.prompt, files: [], agents: [], pasted: [] } : undefined
onMount(() => {
batch(() => {
if (args.agent) local.agent.set(args.agent)
@ -542,6 +543,7 @@ function App(props: { pair?: DialogPairCredentials; started: number }) {
route.navigate({
type: "session",
sessionID: args.sessionID,
prompt: startupPrompt,
})
}
})
@ -564,12 +566,12 @@ function App(props: { pair?: DialogPairCredentials; started: number }) {
const match = response.data[0]?.id
if (!match) return
if (!args.fork) {
route.navigate({ type: "session", sessionID: match })
route.navigate({ type: "session", sessionID: match, prompt: startupPrompt })
return
}
void client.api.session
.fork({ sessionID: match })
.then((result) => route.navigate({ type: "session", sessionID: result.id }))
.then((result) => route.navigate({ type: "session", sessionID: result.id, prompt: startupPrompt }))
.catch(toast.error)
})
.catch(toast.error)
@ -582,7 +584,7 @@ function App(props: { pair?: DialogPairCredentials; started: number }) {
forked = true
void client.api.session
.fork({ sessionID: args.sessionID })
.then((result) => route.navigate({ type: "session", sessionID: result.id }))
.then((result) => route.navigate({ type: "session", sessionID: result.id, prompt: startupPrompt }))
.catch(toast.error)
})

View file

@ -84,6 +84,7 @@ import { createSessionRows, messageBoundaryIDs, resolvePart, type PartRef, type
import { switchLabel } from "../../util/model"
import { findMessageBoundary, messageNavigationSlack } from "./message-navigation"
import { stringWidth } from "../../util/string-width"
import { useArgs } from "../../context/args"
addDefaultParsers(parsers.parsers)
@ -120,6 +121,7 @@ export function Session() {
const { navigate } = useRoute()
const data = useData()
const local = useLocal()
const args = useArgs()
const paths = useTuiPaths()
const configState = useConfig()
const config = configState.data
@ -216,6 +218,7 @@ export function Session() {
const boundaries = createMemo(() => messageBoundaryIDs(rows, messages()))
const [navigationMessage, setNavigationMessage] = createSignal<string>()
const [navigationSlack, setNavigationSlack] = createSignal(0)
const [synced, setSynced] = createSignal(false)
const clearMessageNavigation = () => {
setNavigationSlack(0)
@ -242,6 +245,7 @@ export function Session() {
createEffect(() => {
if (client.connection.status() !== "connected") return
setSynced(false)
const sessionID = route.sessionID
void (async () => {
await Promise.all([
@ -261,6 +265,7 @@ export function Session() {
}
editor.reconnect(info.location.directory)
if (route.sessionID === sessionID && scroll) scroll.scrollBy(100_000)
setSynced(true)
})().catch((error) => {
if (route.sessionID !== sessionID) return
toast.show({
@ -273,15 +278,25 @@ export function Session() {
})
let seeded = false
let sent = false
let scroll: ScrollBoxRenderable
let prompt: PromptRef | undefined
const [prompt, setPrompt] = createSignal<PromptRef>()
const bind = (r: PromptRef | undefined) => {
prompt = r
setPrompt(r)
promptRef.set(r)
if (seeded || !route.prompt || !r) return
seeded = true
r.set(route.prompt)
}
createEffect(() => {
const current = prompt()
if (sent || !current || !synced() || !local.model.ready) return
if (!local.agent.current() || !local.model.current()) return
if (!args.prompt || route.prompt?.text !== args.prompt || current.current.text !== args.prompt) return
sent = true
current.submit()
})
const dialog = useDialog()
const renderer = useRenderer()
const unavailable = (feature: string) => {
@ -526,7 +541,7 @@ export function Session() {
void client.api.session.revert
.stage({ sessionID: route.sessionID, messageID: message.id })
.catch((error) => toast.show({ message: errorMessage(error), variant: "error", duration: 5000 }))
prompt?.set({
prompt()?.set({
...projectedPromptInput(message),
pasted: [],
})