run: add shell mode to prompt (#28315)

Press `!` on an empty prompt to enter shell mode and run a command
through session.shell instead of sending a message
This commit is contained in:
Simon Klee
2026-05-20 09:09:12 +02:00
committed by GitHub
parent 11f7e5a1b0
commit 539b118690
12 changed files with 665 additions and 47 deletions

View File

@@ -60,8 +60,8 @@ function footer() {
api,
events,
commits,
submit(text: string) {
const next = { text, parts: [] as RunPrompt["parts"] }
submit(text: string, mode?: RunPrompt["mode"]) {
const next = mode ? { text, parts: [] as RunPrompt["parts"], mode } : { text, parts: [] as RunPrompt["parts"] }
for (const fn of [...prompts]) {
fn(next)
}
@@ -137,6 +137,64 @@ describe("run runtime queue", () => {
])
})
test("shell mode submits /exit as a shell command", async () => {
const ui = footer()
const seen: RunPrompt[] = []
const task = runPromptQueue({
footer: ui.api,
run: async (input) => {
seen.push(input)
ui.api.close()
},
})
ui.submit("/exit", "shell")
await task
expect(seen).toEqual([{ text: "/exit", parts: [], mode: "shell" }])
expect(ui.commits).toEqual([])
})
test("shell mode submits /new instead of creating a session", async () => {
const ui = footer()
const seen: RunPrompt[] = []
let created = 0
const task = runPromptQueue({
footer: ui.api,
onNewSession: async () => {
created += 1
},
run: async (input) => {
seen.push(input)
ui.api.close()
},
})
ui.submit("/new", "shell")
await task
expect(created).toBe(0)
expect(seen).toEqual([{ text: "/new", parts: [], mode: "shell" }])
expect(ui.commits).toEqual([])
})
test("shell mode does not append a synthetic user row", async () => {
const ui = footer()
const task = runPromptQueue({
footer: ui.api,
run: async () => {
expect(ui.commits).toEqual([])
ui.api.close()
},
})
ui.submit("ls", "shell")
await task
})
test("preserves whitespace for initial input", async () => {
const ui = footer()
const seen: string[] = []