Skip to content

Commit 5b45f79

Browse files
committed
🤖 refactor: unify auto-compaction state, improve slider interaction
1 parent 0437bd4 commit 5b45f79

File tree

7 files changed

+60
-71
lines changed

7 files changed

+60
-71
lines changed

src/browser/components/AIView.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ const AIViewInner: React.FC<AIViewProps> = ({
9191
const pendingSendOptions = useSendMessageOptions(workspaceId);
9292
const pendingModel = pendingSendOptions.model;
9393

94-
const { enabled: autoCompactionEnabled, threshold: autoCompactionThreshold } =
94+
const { threshold: autoCompactionThreshold } =
9595
useAutoCompactionSettings(workspaceId, pendingModel);
9696
const handledModelErrorsRef = useRef<Set<string>>(new Set());
9797

@@ -138,7 +138,6 @@ const AIViewInner: React.FC<AIViewProps> = ({
138138
workspaceUsage,
139139
pendingModel,
140140
use1M,
141-
autoCompactionEnabled,
142141
autoCompactionThreshold / 100
143142
);
144143

src/browser/components/RightSidebar.tsx

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -138,10 +138,8 @@ const RightSidebarComponent: React.FC<RightSidebarProps> = ({
138138
const lastUsage = usage?.liveUsage ?? usage?.usageHistory[usage.usageHistory.length - 1];
139139
const model = lastUsage?.model ?? null;
140140

141-
// Auto-compaction settings: enabled per-workspace, threshold per-model
141+
// Auto-compaction settings: threshold per-model
142142
const {
143-
enabled: autoCompactEnabled,
144-
setEnabled: setAutoCompactEnabled,
145143
threshold: autoCompactThreshold,
146144
setThreshold: setAutoCompactThreshold,
147145
} = useAutoCompactionSettings(workspaceId, model);
@@ -194,12 +192,10 @@ const RightSidebarComponent: React.FC<RightSidebarProps> = ({
194192
const showMeter = showCollapsed || selectedTab === "review";
195193
const autoCompactionProps = React.useMemo(
196194
() => ({
197-
enabled: autoCompactEnabled,
198195
threshold: autoCompactThreshold,
199-
setEnabled: setAutoCompactEnabled,
200196
setThreshold: setAutoCompactThreshold,
201197
}),
202-
[autoCompactEnabled, autoCompactThreshold, setAutoCompactEnabled, setAutoCompactThreshold]
198+
[autoCompactThreshold, setAutoCompactThreshold]
203199
);
204200
const verticalMeter = showMeter ? (
205201
<VerticalTokenMeter data={verticalMeterData} autoCompaction={autoCompactionProps} />

src/browser/components/RightSidebar/CostsTab.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,8 @@ const CostsTabComponent: React.FC<CostsTabProps> = ({ workspaceId }) => {
6868
const contextUsage = usage.liveUsage ?? usage.usageHistory[usage.usageHistory.length - 1];
6969
const currentModel = contextUsage?.model ?? null;
7070

71-
// Auto-compaction settings: enabled per-workspace, threshold per-model
71+
// Auto-compaction settings: threshold per-model (100 = disabled)
7272
const {
73-
enabled: autoCompactEnabled,
74-
setEnabled: setAutoCompactEnabled,
7573
threshold: autoCompactThreshold,
7674
setThreshold: setAutoCompactThreshold,
7775
} = useAutoCompactionSettings(workspaceId, currentModel);
@@ -193,6 +191,7 @@ const CostsTabComponent: React.FC<CostsTabProps> = ({ workspaceId }) => {
193191
<div className="bg-border-light relative flex h-1.5 w-full overflow-visible rounded-[3px]">
194192
{cachedPercentage > 0 && (
195193
<div
194+
key="cached"
196195
className="h-full transition-[width] duration-300"
197196
style={{
198197
width: `${cachedPercentage}%`,
@@ -202,6 +201,7 @@ const CostsTabComponent: React.FC<CostsTabProps> = ({ workspaceId }) => {
202201
)}
203202
{cacheCreatePercentage > 0 && (
204203
<div
204+
key="cacheCreate"
205205
className="h-full transition-[width] duration-300"
206206
style={{
207207
width: `${cacheCreatePercentage}%`,
@@ -210,13 +210,15 @@ const CostsTabComponent: React.FC<CostsTabProps> = ({ workspaceId }) => {
210210
/>
211211
)}
212212
<div
213+
key="input"
213214
className="h-full transition-[width] duration-300"
214215
style={{
215216
width: `${inputPercentage}%`,
216217
background: TOKEN_COMPONENT_COLORS.input,
217218
}}
218219
/>
219220
<div
221+
key="output"
220222
className="h-full transition-[width] duration-300"
221223
style={{
222224
width: `${outputPercentage}%`,
@@ -225,6 +227,7 @@ const CostsTabComponent: React.FC<CostsTabProps> = ({ workspaceId }) => {
225227
/>
226228
{reasoningPercentage > 0 && (
227229
<div
230+
key="reasoning"
228231
className="h-full transition-[width] duration-300"
229232
style={{
230233
width: `${reasoningPercentage}%`,
@@ -235,10 +238,9 @@ const CostsTabComponent: React.FC<CostsTabProps> = ({ workspaceId }) => {
235238
{/* Threshold slider overlay - inside bar for proper positioning */}
236239
{maxTokens && (
237240
<HorizontalThresholdSlider
241+
key="slider"
238242
config={{
239-
enabled: autoCompactEnabled,
240243
threshold: autoCompactThreshold,
241-
setEnabled: setAutoCompactEnabled,
242244
setThreshold: setAutoCompactThreshold,
243245
}}
244246
/>

src/browser/components/RightSidebar/ThresholdSlider.tsx

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@ import {
77
// ----- Types -----
88

99
export interface AutoCompactionConfig {
10-
enabled: boolean;
1110
threshold: number;
12-
setEnabled: (enabled: boolean) => void;
1311
setThreshold: (threshold: number) => void;
1412
}
1513

@@ -38,7 +36,10 @@ export const HorizontalThresholdSlider: React.FC<HorizontalThresholdSliderProps>
3836
const [dragValue, setDragValue] = useState<number | null>(null);
3937

4038
// Current display position
41-
const position = dragValue ?? (config.enabled ? config.threshold : DISABLE_THRESHOLD);
39+
const position = dragValue ?? config.threshold;
40+
41+
// Derive enabled state from threshold
42+
const isEnabled = config.threshold < DISABLE_THRESHOLD;
4243

4344
const calculatePercentage = useCallback(
4445
(clientX: number): number => {
@@ -47,6 +48,7 @@ export const HorizontalThresholdSlider: React.FC<HorizontalThresholdSliderProps>
4748

4849
const rect = container.getBoundingClientRect();
4950
const raw = ((clientX - rect.left) / rect.width) * 100;
51+
// Allow dragging up to 100 (disabled state)
5052
const clamped = Math.max(AUTO_COMPACTION_THRESHOLD_MIN, Math.min(100, raw));
5153
return Math.round(clamped / 5) * 5;
5254
},
@@ -56,9 +58,10 @@ export const HorizontalThresholdSlider: React.FC<HorizontalThresholdSliderProps>
5658
const applyThreshold = useCallback(
5759
(percentage: number) => {
5860
if (percentage >= DISABLE_THRESHOLD) {
59-
config.setEnabled(false);
61+
// Set to 100 to disable
62+
config.setThreshold(100);
6063
} else {
61-
if (!config.enabled) config.setEnabled(true);
64+
// Clamp to max allowed active threshold (e.g. 90%)
6265
config.setThreshold(Math.min(percentage, AUTO_COMPACTION_THRESHOLD_MAX));
6366
}
6467
},
@@ -99,11 +102,11 @@ export const HorizontalThresholdSlider: React.FC<HorizontalThresholdSliderProps>
99102
? dragValue !== null && dragValue >= DISABLE_THRESHOLD
100103
? "Release to disable auto-compact"
101104
: `Auto-compact at ${dragValue}%`
102-
: config.enabled
105+
: isEnabled
103106
? `Auto-compact at ${config.threshold}% · Drag to adjust`
104107
: "Auto-compact disabled · Drag left to enable";
105108

106-
const lineColor = config.enabled
109+
const lineColor = isEnabled
107110
? "var(--color-plan-mode)"
108111
: "var(--color-muted)";
109112
const opacity = isDragging ? 1 : 0.8;
@@ -124,6 +127,7 @@ export const HorizontalThresholdSlider: React.FC<HorizontalThresholdSliderProps>
124127
right: 0,
125128
pointerEvents: "auto", // Re-enable pointer events for the hit area
126129
zIndex: 20,
130+
backgroundColor: "rgba(0,0,0,0)", // Ensure hit area captures events even if transparent
127131
}}
128132
onMouseDown={handleMouseDown}
129133
title={title}
Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,29 @@
11
import { usePersistedState } from "@/browser/hooks/usePersistedState";
22
import {
3-
getAutoCompactionEnabledKey,
43
getAutoCompactionThresholdKey,
54
} from "@/common/constants/storage";
65
import { DEFAULT_AUTO_COMPACTION_THRESHOLD_PERCENT } from "@/common/constants/ui";
76

87
export interface AutoCompactionSettings {
9-
/** Whether auto-compaction is enabled for this workspace */
10-
enabled: boolean;
11-
/** Update enabled state */
12-
setEnabled: (value: boolean) => void;
13-
/** Current threshold percentage (50-90) */
8+
/** Current threshold percentage (50-100). 100 means disabled. */
149
threshold: number;
15-
/** Update threshold percentage (will be clamped to 50-90 range by UI) */
10+
/** Update threshold percentage */
1611
setThreshold: (value: number) => void;
1712
}
1813

1914
/**
2015
* Custom hook for auto-compaction settings.
21-
* - Enabled state is per-workspace
2216
* - Threshold is per-model (different models have different context windows)
17+
* - Threshold >= 100% means disabled for that model
2318
*
24-
* @param workspaceId - Workspace identifier for enabled state
19+
* @param workspaceId - Workspace identifier (unused now, kept for API compatibility if needed)
2520
* @param model - Model identifier for threshold (e.g., "claude-sonnet-4-5")
2621
* @returns Settings object with getters and setters
2722
*/
2823
export function useAutoCompactionSettings(
2924
workspaceId: string,
3025
model: string | null
3126
): AutoCompactionSettings {
32-
const [enabled, setEnabled] = usePersistedState<boolean>(
33-
getAutoCompactionEnabledKey(workspaceId),
34-
true,
35-
{ listener: true }
36-
);
37-
3827
// Use model for threshold key, fall back to "default" if no model
3928
const thresholdKey = getAutoCompactionThresholdKey(model ?? "default");
4029
const [threshold, setThreshold] = usePersistedState<number>(
@@ -43,5 +32,5 @@ export function useAutoCompactionSettings(
4332
{ listener: true }
4433
);
4534

46-
return { enabled, setEnabled, threshold, setThreshold };
35+
return { threshold, setThreshold };
4736
}

0 commit comments

Comments
 (0)