|
|
@@ -1096,181 +1096,181 @@ export function Session() {
|
|
|
tui: tuiConfig,
|
|
|
}}
|
|
|
>
|
|
|
- <box flexDirection="row" flexGrow={1} minHeight={0}>
|
|
|
- <box flexGrow={1} minHeight={0} paddingBottom={1} paddingLeft={2} paddingRight={2} gap={1}>
|
|
|
- <Show when={session()}>
|
|
|
- <scrollbox
|
|
|
- ref={(r) => (scroll = r)}
|
|
|
- viewportOptions={{
|
|
|
- paddingRight: showScrollbar() ? 1 : 0,
|
|
|
- }}
|
|
|
- verticalScrollbarOptions={{
|
|
|
- paddingLeft: 1,
|
|
|
- visible: showScrollbar(),
|
|
|
- trackOptions: {
|
|
|
- backgroundColor: theme.backgroundElement,
|
|
|
- foregroundColor: theme.border,
|
|
|
- },
|
|
|
- }}
|
|
|
- stickyScroll={true}
|
|
|
- stickyStart="bottom"
|
|
|
- flexGrow={1}
|
|
|
- scrollAcceleration={scrollAcceleration()}
|
|
|
- >
|
|
|
- <box height={1} />
|
|
|
- <For each={messages()}>
|
|
|
- {(message, index) => (
|
|
|
- <Switch>
|
|
|
- <Match when={message.id === revert()?.messageID}>
|
|
|
- {(function () {
|
|
|
- const command = useCommandPalette()
|
|
|
- const redoShortcut = useCommandShortcut("session.redo")
|
|
|
- const [hover, setHover] = createSignal(false)
|
|
|
- const dialog = useDialog()
|
|
|
-
|
|
|
- const handleUnrevert = async () => {
|
|
|
- const confirmed = await DialogConfirm.show(
|
|
|
- dialog,
|
|
|
- "Confirm Redo",
|
|
|
- "Are you sure you want to restore the reverted messages?",
|
|
|
- )
|
|
|
- if (confirmed) {
|
|
|
- command.run("session.redo")
|
|
|
+ <box flexDirection="row" flexGrow={1} minHeight={0}>
|
|
|
+ <box flexGrow={1} minHeight={0} paddingBottom={1} paddingLeft={2} paddingRight={2} gap={1}>
|
|
|
+ <Show when={session()}>
|
|
|
+ <scrollbox
|
|
|
+ ref={(r) => (scroll = r)}
|
|
|
+ viewportOptions={{
|
|
|
+ paddingRight: showScrollbar() ? 1 : 0,
|
|
|
+ }}
|
|
|
+ verticalScrollbarOptions={{
|
|
|
+ paddingLeft: 1,
|
|
|
+ visible: showScrollbar(),
|
|
|
+ trackOptions: {
|
|
|
+ backgroundColor: theme.backgroundElement,
|
|
|
+ foregroundColor: theme.border,
|
|
|
+ },
|
|
|
+ }}
|
|
|
+ stickyScroll={true}
|
|
|
+ stickyStart="bottom"
|
|
|
+ flexGrow={1}
|
|
|
+ scrollAcceleration={scrollAcceleration()}
|
|
|
+ >
|
|
|
+ <box height={1} />
|
|
|
+ <For each={messages()}>
|
|
|
+ {(message, index) => (
|
|
|
+ <Switch>
|
|
|
+ <Match when={message.id === revert()?.messageID}>
|
|
|
+ {(function () {
|
|
|
+ const command = useCommandPalette()
|
|
|
+ const redoShortcut = useCommandShortcut("session.redo")
|
|
|
+ const [hover, setHover] = createSignal(false)
|
|
|
+ const dialog = useDialog()
|
|
|
+
|
|
|
+ const handleUnrevert = async () => {
|
|
|
+ const confirmed = await DialogConfirm.show(
|
|
|
+ dialog,
|
|
|
+ "Confirm Redo",
|
|
|
+ "Are you sure you want to restore the reverted messages?",
|
|
|
+ )
|
|
|
+ if (confirmed) {
|
|
|
+ command.run("session.redo")
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- return (
|
|
|
- <box
|
|
|
- onMouseOver={() => setHover(true)}
|
|
|
- onMouseOut={() => setHover(false)}
|
|
|
- onMouseUp={handleUnrevert}
|
|
|
- marginTop={1}
|
|
|
- flexShrink={0}
|
|
|
- border={["left"]}
|
|
|
- customBorderChars={SplitBorder.customBorderChars}
|
|
|
- borderColor={theme.backgroundPanel}
|
|
|
- >
|
|
|
+
|
|
|
+ return (
|
|
|
<box
|
|
|
- paddingTop={1}
|
|
|
- paddingBottom={1}
|
|
|
- paddingLeft={2}
|
|
|
- backgroundColor={hover() ? theme.backgroundElement : theme.backgroundPanel}
|
|
|
+ onMouseOver={() => setHover(true)}
|
|
|
+ onMouseOut={() => setHover(false)}
|
|
|
+ onMouseUp={handleUnrevert}
|
|
|
+ marginTop={1}
|
|
|
+ flexShrink={0}
|
|
|
+ border={["left"]}
|
|
|
+ customBorderChars={SplitBorder.customBorderChars}
|
|
|
+ borderColor={theme.backgroundPanel}
|
|
|
>
|
|
|
- <text fg={theme.textMuted}>{revert()!.reverted.length} message reverted</text>
|
|
|
- <text fg={theme.textMuted}>
|
|
|
- <span style={{ fg: theme.text }}>{redoShortcut()}</span> or /redo to restore
|
|
|
- </text>
|
|
|
- <Show when={revert()!.diffFiles?.length}>
|
|
|
- <box marginTop={1}>
|
|
|
- <For each={revert()!.diffFiles}>
|
|
|
- {(file) => (
|
|
|
- <text fg={theme.text}>
|
|
|
- {file.filename}
|
|
|
- <Show when={file.additions > 0}>
|
|
|
- <span style={{ fg: theme.diffAdded }}> +{file.additions}</span>
|
|
|
- </Show>
|
|
|
- <Show when={file.deletions > 0}>
|
|
|
- <span style={{ fg: theme.diffRemoved }}> -{file.deletions}</span>
|
|
|
- </Show>
|
|
|
- </text>
|
|
|
- )}
|
|
|
- </For>
|
|
|
- </box>
|
|
|
- </Show>
|
|
|
+ <box
|
|
|
+ paddingTop={1}
|
|
|
+ paddingBottom={1}
|
|
|
+ paddingLeft={2}
|
|
|
+ backgroundColor={hover() ? theme.backgroundElement : theme.backgroundPanel}
|
|
|
+ >
|
|
|
+ <text fg={theme.textMuted}>{revert()!.reverted.length} message reverted</text>
|
|
|
+ <text fg={theme.textMuted}>
|
|
|
+ <span style={{ fg: theme.text }}>{redoShortcut()}</span> or /redo to restore
|
|
|
+ </text>
|
|
|
+ <Show when={revert()!.diffFiles?.length}>
|
|
|
+ <box marginTop={1}>
|
|
|
+ <For each={revert()!.diffFiles}>
|
|
|
+ {(file) => (
|
|
|
+ <text fg={theme.text}>
|
|
|
+ {file.filename}
|
|
|
+ <Show when={file.additions > 0}>
|
|
|
+ <span style={{ fg: theme.diffAdded }}> +{file.additions}</span>
|
|
|
+ </Show>
|
|
|
+ <Show when={file.deletions > 0}>
|
|
|
+ <span style={{ fg: theme.diffRemoved }}> -{file.deletions}</span>
|
|
|
+ </Show>
|
|
|
+ </text>
|
|
|
+ )}
|
|
|
+ </For>
|
|
|
+ </box>
|
|
|
+ </Show>
|
|
|
+ </box>
|
|
|
</box>
|
|
|
- </box>
|
|
|
- )
|
|
|
- })()}
|
|
|
- </Match>
|
|
|
- <Match when={revert()?.messageID && message.id >= revert()!.messageID}>
|
|
|
- <></>
|
|
|
- </Match>
|
|
|
- <Match when={message.role === "user"}>
|
|
|
- <UserMessage
|
|
|
- index={index()}
|
|
|
- onMouseUp={() => {
|
|
|
- if (renderer.getSelection()?.getSelectedText()) return
|
|
|
- dialog.replace(() => (
|
|
|
- <DialogMessage
|
|
|
- messageID={message.id}
|
|
|
- sessionID={route.sessionID}
|
|
|
- setPrompt={(promptInfo) => prompt?.set(promptInfo)}
|
|
|
- />
|
|
|
- ))
|
|
|
- }}
|
|
|
- message={message as UserMessage}
|
|
|
- parts={sync.data.part[message.id] ?? []}
|
|
|
- pending={pending()}
|
|
|
- />
|
|
|
- </Match>
|
|
|
- <Match when={message.role === "assistant"}>
|
|
|
- <AssistantMessage
|
|
|
- last={lastAssistant()?.id === message.id}
|
|
|
- message={message as AssistantMessage}
|
|
|
- parts={sync.data.part[message.id] ?? []}
|
|
|
- />
|
|
|
- </Match>
|
|
|
- </Switch>
|
|
|
- )}
|
|
|
- </For>
|
|
|
- </scrollbox>
|
|
|
- <box flexShrink={0}>
|
|
|
- <Show when={permissions().length > 0}>
|
|
|
- <PermissionPrompt request={permissions()[0]} />
|
|
|
- </Show>
|
|
|
- <Show when={permissions().length === 0 && questions().length > 0}>
|
|
|
- <QuestionPrompt request={questions()[0]} />
|
|
|
- </Show>
|
|
|
- <Show when={session()?.parentID}>
|
|
|
- <SubagentFooter />
|
|
|
- </Show>
|
|
|
- <Show when={visible()}>
|
|
|
- <TuiPluginRuntime.Slot
|
|
|
- name="session_prompt"
|
|
|
- mode="replace"
|
|
|
- session_id={route.sessionID}
|
|
|
- visible={visible()}
|
|
|
- disabled={disabled()}
|
|
|
- on_submit={toBottom}
|
|
|
- ref={bind}
|
|
|
- >
|
|
|
- <Prompt
|
|
|
+ )
|
|
|
+ })()}
|
|
|
+ </Match>
|
|
|
+ <Match when={revert()?.messageID && message.id >= revert()!.messageID}>
|
|
|
+ <></>
|
|
|
+ </Match>
|
|
|
+ <Match when={message.role === "user"}>
|
|
|
+ <UserMessage
|
|
|
+ index={index()}
|
|
|
+ onMouseUp={() => {
|
|
|
+ if (renderer.getSelection()?.getSelectedText()) return
|
|
|
+ dialog.replace(() => (
|
|
|
+ <DialogMessage
|
|
|
+ messageID={message.id}
|
|
|
+ sessionID={route.sessionID}
|
|
|
+ setPrompt={(promptInfo) => prompt?.set(promptInfo)}
|
|
|
+ />
|
|
|
+ ))
|
|
|
+ }}
|
|
|
+ message={message as UserMessage}
|
|
|
+ parts={sync.data.part[message.id] ?? []}
|
|
|
+ pending={pending()}
|
|
|
+ />
|
|
|
+ </Match>
|
|
|
+ <Match when={message.role === "assistant"}>
|
|
|
+ <AssistantMessage
|
|
|
+ last={lastAssistant()?.id === message.id}
|
|
|
+ message={message as AssistantMessage}
|
|
|
+ parts={sync.data.part[message.id] ?? []}
|
|
|
+ />
|
|
|
+ </Match>
|
|
|
+ </Switch>
|
|
|
+ )}
|
|
|
+ </For>
|
|
|
+ </scrollbox>
|
|
|
+ <box flexShrink={0}>
|
|
|
+ <Show when={permissions().length > 0}>
|
|
|
+ <PermissionPrompt request={permissions()[0]} />
|
|
|
+ </Show>
|
|
|
+ <Show when={permissions().length === 0 && questions().length > 0}>
|
|
|
+ <QuestionPrompt request={questions()[0]} />
|
|
|
+ </Show>
|
|
|
+ <Show when={session()?.parentID}>
|
|
|
+ <SubagentFooter />
|
|
|
+ </Show>
|
|
|
+ <Show when={visible()}>
|
|
|
+ <TuiPluginRuntime.Slot
|
|
|
+ name="session_prompt"
|
|
|
+ mode="replace"
|
|
|
+ session_id={route.sessionID}
|
|
|
visible={visible()}
|
|
|
- ref={bind}
|
|
|
disabled={disabled()}
|
|
|
- onSubmit={() => {
|
|
|
- toBottom()
|
|
|
- }}
|
|
|
- sessionID={route.sessionID}
|
|
|
- right={<TuiPluginRuntime.Slot name="session_prompt_right" session_id={route.sessionID} />}
|
|
|
- />
|
|
|
- </TuiPluginRuntime.Slot>
|
|
|
- </Show>
|
|
|
- </box>
|
|
|
+ on_submit={toBottom}
|
|
|
+ ref={bind}
|
|
|
+ >
|
|
|
+ <Prompt
|
|
|
+ visible={visible()}
|
|
|
+ ref={bind}
|
|
|
+ disabled={disabled()}
|
|
|
+ onSubmit={() => {
|
|
|
+ toBottom()
|
|
|
+ }}
|
|
|
+ sessionID={route.sessionID}
|
|
|
+ right={<TuiPluginRuntime.Slot name="session_prompt_right" session_id={route.sessionID} />}
|
|
|
+ />
|
|
|
+ </TuiPluginRuntime.Slot>
|
|
|
+ </Show>
|
|
|
+ </box>
|
|
|
+ </Show>
|
|
|
+ <Toast />
|
|
|
+ </box>
|
|
|
+ <Show when={sidebarVisible()}>
|
|
|
+ <Switch>
|
|
|
+ <Match when={wide()}>
|
|
|
+ <Sidebar sessionID={route.sessionID} />
|
|
|
+ </Match>
|
|
|
+ <Match when={!wide()}>
|
|
|
+ <box
|
|
|
+ position="absolute"
|
|
|
+ top={0}
|
|
|
+ left={0}
|
|
|
+ right={0}
|
|
|
+ bottom={0}
|
|
|
+ alignItems="flex-end"
|
|
|
+ backgroundColor={RGBA.fromInts(0, 0, 0, 70)}
|
|
|
+ >
|
|
|
+ <Sidebar sessionID={route.sessionID} />
|
|
|
+ </box>
|
|
|
+ </Match>
|
|
|
+ </Switch>
|
|
|
</Show>
|
|
|
- <Toast />
|
|
|
</box>
|
|
|
- <Show when={sidebarVisible()}>
|
|
|
- <Switch>
|
|
|
- <Match when={wide()}>
|
|
|
- <Sidebar sessionID={route.sessionID} />
|
|
|
- </Match>
|
|
|
- <Match when={!wide()}>
|
|
|
- <box
|
|
|
- position="absolute"
|
|
|
- top={0}
|
|
|
- left={0}
|
|
|
- right={0}
|
|
|
- bottom={0}
|
|
|
- alignItems="flex-end"
|
|
|
- backgroundColor={RGBA.fromInts(0, 0, 0, 70)}
|
|
|
- >
|
|
|
- <Sidebar sessionID={route.sessionID} />
|
|
|
- </box>
|
|
|
- </Match>
|
|
|
- </Switch>
|
|
|
- </Show>
|
|
|
- </box>
|
|
|
</context.Provider>
|
|
|
</PathFormatterProvider>
|
|
|
)
|