Merge branch 'dev' into feat/canceled-prompts-in-history
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { BoxRenderable, TextareaRenderable, MouseEvent, PasteEvent, t, dim, fg } from "@opentui/core"
|
||||
import { createEffect, createMemo, type JSX, onMount, createSignal, onCleanup, Show, Switch, Match } from "solid-js"
|
||||
import { createEffect, createMemo, type JSX, onMount, createSignal, onCleanup, on, Show, Switch, Match } from "solid-js"
|
||||
import "opentui-spinner/solid"
|
||||
import { useLocal } from "@tui/context/local"
|
||||
import { useTheme } from "@tui/context/theme"
|
||||
@@ -54,6 +54,7 @@ export type PromptRef = {
|
||||
}
|
||||
|
||||
const PLACEHOLDERS = ["Fix a TODO in the codebase", "What is the tech stack of this project?", "Fix broken tests"]
|
||||
const SHELL_PLACEHOLDERS = ["ls -la", "git status", "pwd"]
|
||||
|
||||
export function Prompt(props: PromptProps) {
|
||||
let input: TextareaRenderable
|
||||
@@ -134,6 +135,16 @@ export function Prompt(props: PromptProps) {
|
||||
interrupt: 0,
|
||||
})
|
||||
|
||||
createEffect(
|
||||
on(
|
||||
() => props.sessionID,
|
||||
() => {
|
||||
setStore("placeholder", Math.floor(Math.random() * PLACEHOLDERS.length))
|
||||
},
|
||||
{ defer: true },
|
||||
),
|
||||
)
|
||||
|
||||
// Initialize agent/model/variant from last user message when session changes
|
||||
let syncedSessionID: string | undefined
|
||||
createEffect(() => {
|
||||
@@ -736,6 +747,15 @@ export function Prompt(props: PromptProps) {
|
||||
return !!current
|
||||
})
|
||||
|
||||
const placeholderText = createMemo(() => {
|
||||
if (props.sessionID) return undefined
|
||||
if (store.mode === "shell") {
|
||||
const example = SHELL_PLACEHOLDERS[store.placeholder % SHELL_PLACEHOLDERS.length]
|
||||
return `Run a command... "${example}"`
|
||||
}
|
||||
return `Ask anything... "${PLACEHOLDERS[store.placeholder % PLACEHOLDERS.length]}"`
|
||||
})
|
||||
|
||||
const spinnerDef = createMemo(() => {
|
||||
const color = local.agent.color(local.agent.current().name)
|
||||
return {
|
||||
@@ -797,7 +817,7 @@ export function Prompt(props: PromptProps) {
|
||||
flexGrow={1}
|
||||
>
|
||||
<textarea
|
||||
placeholder={props.sessionID ? undefined : `Ask anything... "${PLACEHOLDERS[store.placeholder]}"`}
|
||||
placeholder={placeholderText()}
|
||||
textColor={keybind.leader ? theme.textMuted : theme.text}
|
||||
focusedTextColor={keybind.leader ? theme.textMuted : theme.text}
|
||||
minHeight={1}
|
||||
@@ -856,6 +876,7 @@ export function Prompt(props: PromptProps) {
|
||||
}
|
||||
}
|
||||
if (e.name === "!" && input.visualCursor.offset === 0) {
|
||||
setStore("placeholder", Math.floor(Math.random() * SHELL_PLACEHOLDERS.length))
|
||||
setStore("mode", "shell")
|
||||
e.preventDefault()
|
||||
return
|
||||
|
||||
@@ -93,10 +93,14 @@ export function Home() {
|
||||
|
||||
return (
|
||||
<>
|
||||
<box flexGrow={1} justifyContent="center" alignItems="center" paddingLeft={2} paddingRight={2} gap={1}>
|
||||
<box height={3} />
|
||||
<Logo />
|
||||
<box width="100%" maxWidth={75} zIndex={1000} paddingTop={1}>
|
||||
<box flexGrow={1} alignItems="center" paddingLeft={2} paddingRight={2}>
|
||||
<box flexGrow={1} minHeight={0} />
|
||||
<box height={4} minHeight={0} flexShrink={1} />
|
||||
<box flexShrink={0}>
|
||||
<Logo />
|
||||
</box>
|
||||
<box height={1} minHeight={0} flexShrink={1} />
|
||||
<box width="100%" maxWidth={75} zIndex={1000} paddingTop={1} flexShrink={0}>
|
||||
<Prompt
|
||||
ref={(r) => {
|
||||
prompt = r
|
||||
@@ -105,11 +109,12 @@ export function Home() {
|
||||
hint={Hint}
|
||||
/>
|
||||
</box>
|
||||
<box height={3} width="100%" maxWidth={75} alignItems="center" paddingTop={2}>
|
||||
<box height={4} minHeight={0} width="100%" maxWidth={75} alignItems="center" paddingTop={3} flexShrink={1}>
|
||||
<Show when={showTips()}>
|
||||
<Tips />
|
||||
</Show>
|
||||
</box>
|
||||
<box flexGrow={1} minHeight={0} />
|
||||
<Toast />
|
||||
</box>
|
||||
<box paddingTop={1} paddingBottom={1} paddingLeft={2} paddingRight={2} flexDirection="row" flexShrink={0} gap={2}>
|
||||
|
||||
@@ -141,7 +141,7 @@ export function Session() {
|
||||
})
|
||||
|
||||
const dimensions = useTerminalDimensions()
|
||||
const [sidebar, setSidebar] = kv.signal<"auto" | "hide">("sidebar", "hide")
|
||||
const [sidebar, setSidebar] = kv.signal<"auto" | "hide">("sidebar", "auto")
|
||||
const [sidebarOpen, setSidebarOpen] = createSignal(false)
|
||||
const [conceal, setConceal] = createSignal(true)
|
||||
const [showThinking, setShowThinking] = kv.signal("thinking_visibility", true)
|
||||
@@ -314,26 +314,31 @@ export function Session() {
|
||||
const command = useCommandDialog()
|
||||
command.register(() => [
|
||||
{
|
||||
title: "Share session",
|
||||
title: session()?.share?.url ? "Copy share link" : "Share session",
|
||||
value: "session.share",
|
||||
suggested: route.type === "session",
|
||||
keybind: "session_share",
|
||||
category: "Session",
|
||||
enabled: sync.data.config.share !== "disabled" && !session()?.share?.url,
|
||||
enabled: sync.data.config.share !== "disabled",
|
||||
slash: {
|
||||
name: "share",
|
||||
},
|
||||
onSelect: async (dialog) => {
|
||||
const copy = (url: string) =>
|
||||
Clipboard.copy(url)
|
||||
.then(() => toast.show({ message: "Share URL copied to clipboard!", variant: "success" }))
|
||||
.catch(() => toast.show({ message: "Failed to copy URL to clipboard", variant: "error" }))
|
||||
const url = session()?.share?.url
|
||||
if (url) {
|
||||
await copy(url)
|
||||
dialog.clear()
|
||||
return
|
||||
}
|
||||
await sdk.client.session
|
||||
.share({
|
||||
sessionID: route.sessionID,
|
||||
})
|
||||
.then((res) =>
|
||||
Clipboard.copy(res.data!.share!.url).catch(() =>
|
||||
toast.show({ message: "Failed to copy URL to clipboard", variant: "error" }),
|
||||
),
|
||||
)
|
||||
.then(() => toast.show({ message: "Share URL copied to clipboard!", variant: "success" }))
|
||||
.then((res) => copy(res.data!.share!.url))
|
||||
.catch(() => toast.show({ message: "Failed to share session", variant: "error" }))
|
||||
dialog.clear()
|
||||
},
|
||||
|
||||
@@ -57,7 +57,7 @@ function init() {
|
||||
})
|
||||
|
||||
useKeyboard((evt) => {
|
||||
if (evt.name === "escape" && store.stack.length > 0) {
|
||||
if ((evt.name === "escape" || (evt.ctrl && evt.name === "c")) && store.stack.length > 0) {
|
||||
const current = store.stack.at(-1)!
|
||||
current.onClose?.()
|
||||
setStore("stack", store.stack.slice(0, -1))
|
||||
|
||||
Reference in New Issue
Block a user