Skip to content

Commit c326c4d

Browse files
committed
Polish IIFE helpers: tighten persistWithMergeBase and PromptActionBar
Collapse dual try/catch in persistWithMergeBase into one path, destructure PromptActionBar props directly, and compute input lines once before the bordered/plain body branch.
1 parent f3dc1a9 commit c326c4d

2 files changed

Lines changed: 28 additions & 36 deletions

File tree

src/tui/components/chat-input.tsx

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,17 @@ export type ChatInputProps = {
6868

6969
// Action bar above the prompt: revolving verb + interrupt/queue hint on the
7070
// left, profile · model · effort right-aligned. Null when nothing to show.
71-
function PromptActionBar(props: {
71+
function PromptActionBar({
72+
showSteerHint,
73+
value,
74+
steerOnEnter,
75+
queuedCount,
76+
verb,
77+
profile,
78+
model,
79+
effort,
80+
attachmentSummary,
81+
}: {
7282
showSteerHint: boolean;
7383
value: string;
7484
steerOnEnter: boolean;
@@ -79,17 +89,6 @@ function PromptActionBar(props: {
7989
effort?: string;
8090
attachmentSummary?: string;
8191
}): ReactNode {
82-
const {
83-
showSteerHint,
84-
value,
85-
steerOnEnter,
86-
queuedCount,
87-
verb,
88-
profile,
89-
model,
90-
effort,
91-
attachmentSummary,
92-
} = props;
9392
// Enter and Alt+Enter are no-ops on an empty field, so with nothing typed
9493
// the hint advertises the interrupt chord instead.
9594
const hasPromptText = value.trim().length > 0;
@@ -99,6 +98,7 @@ function PromptActionBar(props: {
9998
? "Enter queues for orchestrator"
10099
: "Enter steer · Alt+Enter queue";
101100
const steerText = queuedCount > 0 ? `${queuedCount} queued · ${actionsText}` : actionsText;
101+
// exactOptionalPropertyTypes: omit undefined keys rather than pass them.
102102
const modelText = composePromptActionBarModelLabel({
103103
...(profile !== undefined ? { profile } : {}),
104104
...(model !== undefined ? { model } : {}),
@@ -790,9 +790,10 @@ export function ChatInput({
790790

791791
// When slash/@ pickers are open the input renders plainly so the
792792
// suggestion list sits flush above it without a competing border.
793+
const inputLines = renderInputLines();
793794
const inputBody = showSlash || showAt ? (
794795
<Box flexDirection="column" paddingX={1}>
795-
{renderInputLines()}
796+
{inputLines}
796797
</Box>
797798
) : (
798799
<Box marginX={1} flexDirection="column">
@@ -802,7 +803,7 @@ export function ChatInput({
802803
flexDirection="column"
803804
paddingX={1}
804805
>
805-
{renderInputLines()}
806+
{inputLines}
806807
</Box>
807808
</Box>
808809
);

src/tui/hooks/use-provider-manager.ts

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -163,38 +163,31 @@ function persistGlobalSettings(
163163
// Shared disk-first persist path for catalog and tier writes. Loads a fresh
164164
// merge base, builds settings, optionally mutates in-memory state, then saves.
165165
// Fire-and-forget: callers `void` the promise so UI stays non-blocking.
166+
// onBeforeSave runs only after load+build succeed so a failed re-read never
167+
// leaves UI state ahead of disk.
166168
async function persistWithMergeBase(args: {
167169
globalSettingsPath: string;
168170
initialSettings: Settings | undefined;
169171
buildSettings: (base: Settings | undefined) => Settings;
170172
onMessage: (msg: string) => void;
171173
successMessage: string;
172174
failPrefix: string;
173-
/** Runs only after load+build succeed, before the disk write. */
174175
onBeforeSave?: () => void;
175176
}): Promise<void> {
176-
let base: Settings | undefined;
177177
try {
178-
base = await loadMergeBase(args.globalSettingsPath, args.initialSettings);
179-
} catch (err) {
180-
args.onMessage(`${args.failPrefix}: ${err instanceof Error ? err.message : String(err)}`);
181-
return;
182-
}
183-
let settings: Settings;
184-
try {
185-
settings = args.buildSettings(base);
178+
const base = await loadMergeBase(args.globalSettingsPath, args.initialSettings);
179+
const settings = args.buildSettings(base);
180+
args.onBeforeSave?.();
181+
persistGlobalSettings(
182+
args.globalSettingsPath,
183+
settings,
184+
args.onMessage,
185+
args.successMessage,
186+
args.failPrefix,
187+
);
186188
} catch (err) {
187189
args.onMessage(`${args.failPrefix}: ${err instanceof Error ? err.message : String(err)}`);
188-
return;
189190
}
190-
args.onBeforeSave?.();
191-
persistGlobalSettings(
192-
args.globalSettingsPath,
193-
settings,
194-
args.onMessage,
195-
args.successMessage,
196-
args.failPrefix,
197-
);
198191
}
199192

200193
export function useProviderManager({
@@ -353,9 +346,7 @@ export function useProviderManager({
353346
successMessage: string,
354347
): void => {
355348
// Disk-first merge base: mid-session /plugins writes must survive a later
356-
// provider save. Fail closed if settings cannot be re-read. Catalog state
357-
// only updates after load+build succeed so a failed re-read never leaves
358-
// the UI ahead of disk.
349+
// provider save. Fail closed if settings cannot be re-read.
359350
void persistWithMergeBase({
360351
globalSettingsPath,
361352
initialSettings,

0 commit comments

Comments
 (0)