mirror of
https://github.com/sst/opencode.git
synced 2025-12-23 10:11:41 +00:00
Preserve prompt input when creating new session (#4993)
This commit is contained in:
parent
1d6e3d477b
commit
27c99b46cb
6 changed files with 55 additions and 8 deletions
|
|
@ -32,6 +32,7 @@ import { KVProvider, useKV } from "./context/kv"
|
|||
import { Provider } from "@/provider/provider"
|
||||
import { ArgsProvider, useArgs, type Args } from "./context/args"
|
||||
import open from "open"
|
||||
import { PromptRefProvider, usePromptRef } from "./context/prompt"
|
||||
|
||||
async function getTerminalBackgroundColor(): Promise<"dark" | "light"> {
|
||||
// can't set raw mode if not a TTY
|
||||
|
|
@ -119,7 +120,9 @@ export function tui(input: { url: string; args: Args; onExit?: () => Promise<voi
|
|||
<DialogProvider>
|
||||
<CommandProvider>
|
||||
<PromptHistoryProvider>
|
||||
<App />
|
||||
<PromptRefProvider>
|
||||
<App />
|
||||
</PromptRefProvider>
|
||||
</PromptHistoryProvider>
|
||||
</CommandProvider>
|
||||
</DialogProvider>
|
||||
|
|
@ -160,6 +163,7 @@ function App() {
|
|||
const { theme, mode, setMode } = useTheme()
|
||||
const sync = useSync()
|
||||
const exit = useExit()
|
||||
const promptRef = usePromptRef()
|
||||
|
||||
createEffect(() => {
|
||||
console.log(JSON.stringify(route.data))
|
||||
|
|
@ -225,8 +229,12 @@ function App() {
|
|||
keybind: "session_new",
|
||||
category: "Session",
|
||||
onSelect: () => {
|
||||
const current = promptRef.current
|
||||
// Don't require focus - if there's any text, preserve it
|
||||
const currentPrompt = current?.current?.input ? current.current : undefined
|
||||
route.navigate({
|
||||
type: "home",
|
||||
initialPrompt: currentPrompt,
|
||||
})
|
||||
dialog.clear()
|
||||
},
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ export type PromptProps = {
|
|||
|
||||
export type PromptRef = {
|
||||
focused: boolean
|
||||
current: PromptInfo
|
||||
set(prompt: PromptInfo): void
|
||||
reset(): void
|
||||
blur(): void
|
||||
|
|
@ -377,6 +378,9 @@ export function Prompt(props: PromptProps) {
|
|||
get focused() {
|
||||
return input.focused
|
||||
},
|
||||
get current() {
|
||||
return store.prompt
|
||||
},
|
||||
focus() {
|
||||
input.focus()
|
||||
},
|
||||
|
|
|
|||
18
packages/opencode/src/cli/cmd/tui/context/prompt.tsx
Normal file
18
packages/opencode/src/cli/cmd/tui/context/prompt.tsx
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import { createSimpleContext } from "./helper"
|
||||
import type { PromptRef } from "../component/prompt"
|
||||
|
||||
export const { use: usePromptRef, provider: PromptRefProvider } = createSimpleContext({
|
||||
name: "PromptRef",
|
||||
init: () => {
|
||||
let current: PromptRef | undefined
|
||||
|
||||
return {
|
||||
get current() {
|
||||
return current
|
||||
},
|
||||
set(ref: PromptRef | undefined) {
|
||||
current = ref
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
|
@ -1,8 +1,10 @@
|
|||
import { createStore } from "solid-js/store"
|
||||
import { createSimpleContext } from "./helper"
|
||||
import type { PromptInfo } from "../component/prompt/history"
|
||||
|
||||
export type HomeRoute = {
|
||||
type: "home"
|
||||
initialPrompt?: PromptInfo
|
||||
}
|
||||
|
||||
export type SessionRoute = {
|
||||
|
|
|
|||
|
|
@ -1,15 +1,14 @@
|
|||
import { Prompt, type PromptRef } from "@tui/component/prompt"
|
||||
import { createMemo, Match, onMount, Show, Switch, type ParentProps } from "solid-js"
|
||||
import { createMemo, Match, onMount, Show, Switch } from "solid-js"
|
||||
import { useTheme } from "@tui/context/theme"
|
||||
import { useKeybind } from "../context/keybind"
|
||||
import type { KeybindsConfig } from "@opencode-ai/sdk"
|
||||
import { Logo } from "../component/logo"
|
||||
import { Locale } from "@/util/locale"
|
||||
import { useSync } from "../context/sync"
|
||||
import { Toast } from "../ui/toast"
|
||||
import { useArgs } from "../context/args"
|
||||
import { Global } from "@/global"
|
||||
import { useDirectory } from "../context/directory"
|
||||
import { useRoute, useRouteData } from "@tui/context/route"
|
||||
import { usePromptRef } from "../context/prompt"
|
||||
|
||||
// TODO: what is the best way to do this?
|
||||
let once = false
|
||||
|
|
@ -17,6 +16,8 @@ let once = false
|
|||
export function Home() {
|
||||
const sync = useSync()
|
||||
const { theme } = useTheme()
|
||||
const route = useRouteData("home")
|
||||
const promptRef = usePromptRef()
|
||||
const mcp = createMemo(() => Object.keys(sync.data.mcp).length > 0)
|
||||
const mcpError = createMemo(() => {
|
||||
return Object.values(sync.data.mcp).some((x) => x.status === "failed")
|
||||
|
|
@ -45,7 +46,10 @@ export function Home() {
|
|||
const args = useArgs()
|
||||
onMount(() => {
|
||||
if (once) return
|
||||
if (args.prompt) {
|
||||
if (route.initialPrompt) {
|
||||
prompt.set(route.initialPrompt)
|
||||
once = true
|
||||
} else if (args.prompt) {
|
||||
prompt.set({ input: args.prompt, parts: [] })
|
||||
once = true
|
||||
}
|
||||
|
|
@ -57,7 +61,13 @@ export function Home() {
|
|||
<box flexGrow={1} justifyContent="center" alignItems="center" paddingLeft={2} paddingRight={2} gap={1}>
|
||||
<Logo />
|
||||
<box width="100%" maxWidth={75} zIndex={1000} paddingTop={1}>
|
||||
<Prompt ref={(r) => (prompt = r)} hint={Hint} />
|
||||
<Prompt
|
||||
ref={(r) => {
|
||||
prompt = r
|
||||
promptRef.set(r)
|
||||
}}
|
||||
hint={Hint}
|
||||
/>
|
||||
</box>
|
||||
<Toast />
|
||||
</box>
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ import { useKV } from "../../context/kv.tsx"
|
|||
import { Editor } from "../../util/editor"
|
||||
import stripAnsi from "strip-ansi"
|
||||
import { Footer } from "./footer.tsx"
|
||||
import { usePromptRef } from "../../context/prompt"
|
||||
|
||||
addDefaultParsers(parsers.parsers)
|
||||
|
||||
|
|
@ -99,6 +100,7 @@ export function Session() {
|
|||
const sync = useSync()
|
||||
const kv = useKV()
|
||||
const { theme } = useTheme()
|
||||
const promptRef = usePromptRef()
|
||||
const session = createMemo(() => sync.session.get(route.sessionID)!)
|
||||
const messages = createMemo(() => sync.data.message[route.sessionID] ?? [])
|
||||
const permissions = createMemo(() => sync.data.permission[route.sessionID] ?? [])
|
||||
|
|
@ -949,7 +951,10 @@ export function Session() {
|
|||
</scrollbox>
|
||||
<box flexShrink={0}>
|
||||
<Prompt
|
||||
ref={(r) => (prompt = r)}
|
||||
ref={(r) => {
|
||||
prompt = r
|
||||
promptRef.set(r)
|
||||
}}
|
||||
disabled={permissions().length > 0}
|
||||
onSubmit={() => {
|
||||
toBottom()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue