feat: inline permission prompt and improve TUI layout
- Render permission modal inline below log panel instead of floating CenteredModal overlay - Hide input area when permission prompt is active - Add dev:debug and dev:debug-brk scripts for Bun inspector debugging - Add background color to header to prevent content bleeding through - Add margin spacing between header and log panel - Change permission modal border to top-only for cleaner inline appearance
This commit is contained in:
@@ -16,6 +16,7 @@ import {
|
||||
advanceStep,
|
||||
getExecutionState,
|
||||
} from "@services/chat-tui-service";
|
||||
import { DISABLE_MOUSE_TRACKING } from "@constants/terminal";
|
||||
import versionData from "@/version.json";
|
||||
import { ExitProvider, useExit } from "@tui-solid/context/exit";
|
||||
import { RouteProvider, useRoute } from "@tui-solid/context/route";
|
||||
@@ -179,7 +180,11 @@ function AppContent(props: AppProps) {
|
||||
const toggled = togglePauseResume();
|
||||
if (toggled) {
|
||||
const state = getExecutionState();
|
||||
toast.info(state.state === "paused" ? "⏸ Execution paused" : "▶ Execution resumed");
|
||||
toast.info(
|
||||
state.state === "paused"
|
||||
? "⏸ Execution paused"
|
||||
: "▶ Execution resumed",
|
||||
);
|
||||
evt.preventDefault();
|
||||
return;
|
||||
}
|
||||
@@ -191,7 +196,9 @@ function AppContent(props: AppProps) {
|
||||
if (state.state !== "idle") {
|
||||
abortCurrentOperation(true).then((aborted) => {
|
||||
if (aborted) {
|
||||
toast.info(`Aborted with rollback of ${state.rollbackCount} action(s)`);
|
||||
toast.info(
|
||||
`Aborted with rollback of ${state.rollbackCount} action(s)`,
|
||||
);
|
||||
}
|
||||
});
|
||||
evt.preventDefault();
|
||||
@@ -205,7 +212,9 @@ function AppContent(props: AppProps) {
|
||||
if (state.state !== "idle") {
|
||||
const isStepMode = state.state === "stepping";
|
||||
setStepMode(!isStepMode);
|
||||
toast.info(isStepMode ? "🏃 Step mode disabled" : "🚶 Step mode enabled");
|
||||
toast.info(
|
||||
isStepMode ? "🏃 Step mode disabled" : "🚶 Step mode enabled",
|
||||
);
|
||||
evt.preventDefault();
|
||||
return;
|
||||
}
|
||||
@@ -511,11 +520,16 @@ export interface TuiRenderOptions extends TuiInput {
|
||||
|
||||
export function tui(options: TuiRenderOptions): Promise<TuiOutput> {
|
||||
return new Promise<TuiOutput>((resolve) => {
|
||||
render(() => <App {...options} onExit={resolve} />, {
|
||||
const handleExit = (output: TuiOutput): void => {
|
||||
process.stdout.write(DISABLE_MOUSE_TRACKING);
|
||||
resolve(output);
|
||||
};
|
||||
|
||||
render(() => <App {...options} onExit={handleExit} />, {
|
||||
targetFps: 60,
|
||||
exitOnCtrlC: false,
|
||||
useKittyKeyboard: {},
|
||||
useMouse: false,
|
||||
useMouse: true,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -139,8 +139,10 @@ export function Header(props: HeaderProps) {
|
||||
justifyContent="space-between"
|
||||
paddingLeft={1}
|
||||
paddingRight={1}
|
||||
marginBottom={1}
|
||||
borderColor={theme.colors.border}
|
||||
border={["bottom"]}
|
||||
backgroundColor={theme.colors.background}
|
||||
>
|
||||
<box flexDirection="row" gap={1}>
|
||||
<Show when={showBanner()}>
|
||||
|
||||
@@ -100,12 +100,15 @@ export function PermissionModal(props: PermissionModalProps) {
|
||||
<box
|
||||
flexDirection="column"
|
||||
borderColor={theme.colors.borderWarning}
|
||||
border={["top", "bottom", "left", "right"]}
|
||||
border={["top"]}
|
||||
backgroundColor={theme.colors.background}
|
||||
paddingLeft={2}
|
||||
paddingRight={2}
|
||||
paddingTop={1}
|
||||
paddingBottom={1}
|
||||
width="100%"
|
||||
height="auto"
|
||||
flexShrink={0}
|
||||
>
|
||||
<box marginBottom={1}>
|
||||
<text fg={theme.colors.warning} attributes={TextAttributes.BOLD}>
|
||||
|
||||
@@ -287,8 +287,20 @@ export function Session(props: SessionProps) {
|
||||
</Show>
|
||||
</box>
|
||||
|
||||
<Show
|
||||
when={app.mode() === "permission_prompt" && app.permissionRequest()}
|
||||
>
|
||||
<PermissionModal
|
||||
request={app.permissionRequest()!}
|
||||
onRespond={props.onPermissionResponse}
|
||||
isActive={app.mode() === "permission_prompt"}
|
||||
/>
|
||||
</Show>
|
||||
|
||||
<StatusBar />
|
||||
<InputArea onSubmit={props.onSubmit} />
|
||||
<Show when={app.mode() !== "permission_prompt"}>
|
||||
<InputArea onSubmit={props.onSubmit} />
|
||||
</Show>
|
||||
|
||||
<Switch>
|
||||
<Match when={app.mode() === "command_menu"}>
|
||||
@@ -393,18 +405,6 @@ export function Session(props: SessionProps) {
|
||||
</CenteredModal>
|
||||
</Match>
|
||||
|
||||
<Match
|
||||
when={app.mode() === "permission_prompt" && app.permissionRequest()}
|
||||
>
|
||||
<CenteredModal>
|
||||
<PermissionModal
|
||||
request={app.permissionRequest()!}
|
||||
onRespond={props.onPermissionResponse}
|
||||
isActive={app.mode() === "permission_prompt"}
|
||||
/>
|
||||
</CenteredModal>
|
||||
</Match>
|
||||
|
||||
<Match when={app.mode() === "learning_prompt" && app.learningPrompt()}>
|
||||
<CenteredModal>
|
||||
<LearningModal
|
||||
|
||||
Reference in New Issue
Block a user