perf improvements + /login fix
This commit is contained in:
@@ -377,7 +377,13 @@ const MessagesImpl = ({
|
||||
columns
|
||||
} = useTerminalSize();
|
||||
const toggleShowAllShortcut = useShortcutDisplay('transcript:toggleShowAll', 'Transcript', 'Ctrl+E');
|
||||
const normalizedMessages = useMemo(() => normalizeMessages(messages).filter(isNotEmptyMessage), [messages]);
|
||||
// In the main-screen renderer, pre-compact history already lives in native
|
||||
// terminal scrollback, so normalizing it again just adds O(n) work on every
|
||||
// render. Fullscreen/transcript modes still need the full in-memory history.
|
||||
const normalizationSourceMessages = useMemo(() => verbose || isFullscreenEnvEnabled() ? messages : getMessagesAfterCompactBoundary(messages, {
|
||||
includeSnipped: true
|
||||
}), [messages, verbose]);
|
||||
const normalizedMessages = useMemo(() => normalizeMessages(normalizationSourceMessages).filter(isNotEmptyMessage), [normalizationSourceMessages]);
|
||||
|
||||
// Check if streaming thinking should be visible (streaming or within 30s timeout)
|
||||
const isStreamingThinkingVisible = useMemo(() => {
|
||||
@@ -485,18 +491,7 @@ const MessagesImpl = ({
|
||||
hasTruncatedMessages: hasTruncatedMessages_0,
|
||||
hiddenMessageCount: hiddenMessageCount_0
|
||||
} = useMemo(() => {
|
||||
// In fullscreen mode the alt buffer has no native scrollback, so the
|
||||
// compact-boundary filter just hides history the ScrollBox could
|
||||
// otherwise scroll to. Main-screen mode keeps the filter — pre-compact
|
||||
// rows live above the viewport in native scrollback there, and
|
||||
// re-rendering them triggers full resets.
|
||||
// includeSnipped: UI rendering keeps snipped messages for scrollback
|
||||
// (this PR's core goal — full history in UI, filter only for the model).
|
||||
// Also avoids a UUID mismatch: normalizeMessages derives new UUIDs, so
|
||||
// projectSnippedView's check against original removedUuids would fail.
|
||||
const compactAwareMessages = verbose || isFullscreenEnvEnabled() ? normalizedMessages : getMessagesAfterCompactBoundary(normalizedMessages, {
|
||||
includeSnipped: true
|
||||
});
|
||||
const compactAwareMessages = normalizedMessages;
|
||||
const messagesToShowNotTruncated = reorderMessagesInUI(compactAwareMessages.filter((msg_2): msg_2 is Exclude<NormalizedMessage, ProgressMessageType> => msg_2.type !== 'progress')
|
||||
// CC-724: drop attachment messages that AttachmentMessage renders as
|
||||
// null (hook_success, hook_additional_context, hook_cancelled, etc.)
|
||||
|
||||
88
src/components/OpenRouterLoginFlow.tsx
Normal file
88
src/components/OpenRouterLoginFlow.tsx
Normal file
@@ -0,0 +1,88 @@
|
||||
import * as React from 'react'
|
||||
import { useState } from 'react'
|
||||
import { Box, Text } from '../ink.js'
|
||||
import { saveOpenRouterApiKey } from '../utils/auth.js'
|
||||
import { Spinner } from './Spinner.js'
|
||||
import TextInput from './TextInput.js'
|
||||
|
||||
type OpenRouterLoginFlowProps = {
|
||||
onDone: () => void
|
||||
startingMessage?: string
|
||||
}
|
||||
|
||||
export function OpenRouterLoginFlow({
|
||||
onDone,
|
||||
startingMessage,
|
||||
}: OpenRouterLoginFlowProps): React.ReactNode {
|
||||
const [isBusy, setIsBusy] = useState(false)
|
||||
const [status, setStatus] = useState<string | null>(null)
|
||||
const [inputValue, setInputValue] = useState('')
|
||||
const [cursorOffset, setCursorOffset] = useState(0)
|
||||
|
||||
async function handleSubmit(value: string): Promise<void> {
|
||||
const trimmed = value.trim()
|
||||
if (!trimmed) {
|
||||
return
|
||||
}
|
||||
|
||||
setIsBusy(true)
|
||||
setStatus(null)
|
||||
try {
|
||||
await saveOpenRouterApiKey(trimmed)
|
||||
onDone()
|
||||
} catch (error) {
|
||||
setStatus(error instanceof Error ? error.message : String(error))
|
||||
} finally {
|
||||
setIsBusy(false)
|
||||
}
|
||||
}
|
||||
|
||||
if (isBusy) {
|
||||
return (
|
||||
<Box flexDirection="column" gap={1}>
|
||||
<Box>
|
||||
<Spinner />
|
||||
<Text>Configuring OpenRouter login for Better-Clawd...</Text>
|
||||
</Box>
|
||||
<Text dimColor={true}>
|
||||
OpenRouter support uses your OpenRouter API key with the Responses API
|
||||
endpoint.
|
||||
</Text>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Box flexDirection="column" gap={1}>
|
||||
<Text>
|
||||
{startingMessage ??
|
||||
'Better-Clawd can use OpenRouter with your OpenRouter API key.'}
|
||||
</Text>
|
||||
<Text dimColor={true}>
|
||||
Paste your OpenRouter key to use `https://openrouter.ai/api/v1` and the
|
||||
Responses API compatibility layer.
|
||||
</Text>
|
||||
<Box>
|
||||
<Text>Paste your OpenRouter API key:</Text>
|
||||
<TextInput
|
||||
value={inputValue}
|
||||
onChange={setInputValue}
|
||||
onSubmit={handleSubmit}
|
||||
onExit={() => {
|
||||
setInputValue('')
|
||||
setCursorOffset(0)
|
||||
}}
|
||||
cursorOffset={cursorOffset}
|
||||
onChangeCursorOffset={setCursorOffset}
|
||||
columns={72}
|
||||
mask="*"
|
||||
/>
|
||||
</Box>
|
||||
{status ? <Text color="error">{status}</Text> : null}
|
||||
<Text dimColor={true}>
|
||||
Press <Text bold={true}>Enter</Text> to save, or <Text bold={true}>Esc</Text>{' '}
|
||||
to cancel.
|
||||
</Text>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user