Skip to content

Commit 69e9009

Browse files
committed
add forceReload event on any tool result. (#673)
* add forceReload event on any tool result. * rename forceReload event * chore: rename forceReload * fix: compression stop, only stop the chat when it's compressed and more than 40 messages from the last user message. * fix: combine comppression and chat suggestion use similar logic. * enable send if the user dimisses the request to start a new chat * fix: open chat suggestion box when restoring a large chat.
1 parent 15e65d0 commit 69e9009

File tree

11 files changed

+45
-47
lines changed

11 files changed

+45
-47
lines changed

refact-agent/gui/src/app/middleware.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
setIsWaitingForResponse,
1414
upsertToolCall,
1515
sendCurrentChatToLspAfterToolCallUpdate,
16+
chatResponse,
1617
} from "../features/Chat/Thread";
1718
import { statisticsApi } from "../services/refact/statistics";
1819
import { integrationsApi } from "../services/refact/integrations";
@@ -38,8 +39,12 @@ import {
3839
updateConfirmationAfterIdeToolUse,
3940
} from "../features/ToolConfirmation/confirmationSlice";
4041
import { setInitialAgentUsage } from "../features/AgentUsage/agentUsageSlice";
41-
import { ideToolCallResponse } from "../hooks/useEventBusForIDE";
42+
import {
43+
ideToolCallResponse,
44+
ideForceReloadProjectTreeFiles,
45+
} from "../hooks/useEventBusForIDE";
4246
import { upsertToolCallIntoHistory } from "../features/History/historySlice";
47+
import { isToolResponse } from "../events";
4348

4449
const AUTH_ERROR_MESSAGE =
4550
"There is an issue with your API key. Check out your API Key or re-login";
@@ -536,3 +541,16 @@ startListening({
536541
}
537542
},
538543
});
544+
545+
// JB file refresh
546+
// TBD: this could include diff messages to
547+
startListening({
548+
actionCreator: chatResponse,
549+
effect: (action, listenerApi) => {
550+
const state = listenerApi.getState();
551+
if (state.config.host !== "jetbrains") return;
552+
if (!isToolResponse(action.payload)) return;
553+
if (!window.postIntellijMessage) return;
554+
window.postIntellijMessage(ideForceReloadProjectTreeFiles());
555+
},
556+
});

refact-agent/gui/src/components/Chat/Chat.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import {
1010
useGetCapsQuery,
1111
useCapsForToolUse,
1212
useAgentUsage,
13-
useLastSentCompressionStop,
1413
} from "../../hooks";
1514
import { type Config } from "../../features/Config/configSlice";
1615
import {
@@ -54,7 +53,6 @@ export const Chat: React.FC<ChatProps> = ({
5453
const { submit, abort, retryFromIndex } = useSendChatRequest();
5554

5655
const chatToolUse = useAppSelector(getSelectedToolUse);
57-
const compressionStop = useLastSentCompressionStop();
5856
const threadNewChatSuggested = useAppSelector(selectThreadNewChatSuggested);
5957
const messages = useAppSelector(selectMessages);
6058
const capsForToolUse = useCapsForToolUse();
@@ -106,9 +104,8 @@ export const Chat: React.FC<ChatProps> = ({
106104
<AgentUsage />
107105
<SuggestNewChat
108106
shouldBeVisible={
109-
compressionStop.stopped ||
110-
(threadNewChatSuggested.wasSuggested &&
111-
!threadNewChatSuggested.wasRejectedByUser)
107+
threadNewChatSuggested.wasSuggested &&
108+
!threadNewChatSuggested.wasRejectedByUser
112109
}
113110
/>
114111
{!isStreaming && preventSend && unCalledTools && (

refact-agent/gui/src/components/ChatForm/SuggestNewChat/SuggestNewChat.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
import { popBackTo, push } from "../../../features/Pages/pagesSlice";
1414
import { telemetryApi } from "../../../services/refact";
1515
import {
16+
enableSend,
1617
newChatAction,
1718
selectChatId,
1819
setIsNewChatSuggestionRejected,
@@ -64,6 +65,7 @@ export const SuggestNewChat = ({
6465

6566
const handleClose = () => {
6667
dispatch(setIsNewChatSuggestionRejected({ chatId, value: true }));
68+
dispatch(enableSend({ id: chatId }));
6769

6870
void sendTelemetryEvent({
6971
scope: `dismissedNewChatSuggestionWarning`,

refact-agent/gui/src/components/UsageCounter/useUsageCounter.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import {
33
selectIsStreaming,
44
selectIsWaiting,
55
selectMessages,
6-
// selectLastSentCompression,
76
} from "../../features/Chat";
87
import { useAppSelector, useLastSentCompressionStop } from "../../hooks";
98
import {
@@ -33,19 +32,17 @@ export function useUsageCounter() {
3332
}, [currentThreadUsage]);
3433

3534
const isOverflown = useMemo(() => {
36-
if (!compressionStop.stopped) return false;
3735
if (compressionStop.strength === "low") return true;
3836
if (compressionStop.strength === "medium") return true;
3937
if (compressionStop.strength === "high") return true;
4038
return false;
41-
}, [compressionStop.stopped, compressionStop.strength]);
39+
}, [compressionStop.strength]);
4240

4341
const isWarning = useMemo(() => {
44-
if (!compressionStop.stopped) return false;
4542
if (compressionStop.strength === "medium") return true;
4643
if (compressionStop.strength === "high") return true;
4744
return false;
48-
}, [compressionStop.stopped, compressionStop.strength]);
45+
}, [compressionStop.strength]);
4946

5047
const shouldShow = useMemo(() => {
5148
return messages.length > 0 && !isStreaming && !isWaiting;

refact-agent/gui/src/features/Chat/Thread/reducer.ts

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ import {
3939
setIsNewChatSuggestionRejected,
4040
upsertToolCall,
4141
setIncreaseMaxTokens,
42-
setThreadPaused,
4342
} from "./actions";
4443
import { formatChatResponse } from "./utils";
4544
import {
@@ -79,7 +78,6 @@ const createChatThread = (
7978
boost_reasoning: false,
8079
automatic_patch: false,
8180
increase_max_tokens: false,
82-
paused: false,
8381
};
8482
return chat;
8583
};
@@ -209,7 +207,7 @@ export const chatReducer = createReducer(initialState, (builder) => {
209207
action.payload.compression_strength !== "absent"
210208
) {
211209
state.thread.new_chat_suggested = {
212-
...state.thread.new_chat_suggested,
210+
wasRejectedByUser: false,
213211
wasSuggested: true,
214212
};
215213
}
@@ -243,15 +241,14 @@ export const chatReducer = createReducer(initialState, (builder) => {
243241

244242
builder.addCase(setIsNewChatSuggested, (state, action) => {
245243
if (state.thread.id !== action.payload.chatId) return state;
246-
state.thread.paused = true;
247244
state.thread.new_chat_suggested = {
248245
wasSuggested: action.payload.value,
249246
};
250247
});
251248

252249
builder.addCase(setIsNewChatSuggestionRejected, (state, action) => {
253250
if (state.thread.id !== action.payload.chatId) return state;
254-
state.thread.paused = false;
251+
state.prevent_send = false;
255252
state.thread.new_chat_suggested = {
256253
...state.thread.new_chat_suggested,
257254
wasRejectedByUser: action.payload.value,
@@ -279,7 +276,6 @@ export const chatReducer = createReducer(initialState, (builder) => {
279276
state.streaming = true;
280277
state.thread.read = false;
281278
state.prevent_send = false;
282-
state.thread.paused = false;
283279
});
284280

285281
builder.addCase(removeChatFromCache, (state, action) => {
@@ -337,7 +333,7 @@ export const chatReducer = createReducer(initialState, (builder) => {
337333
lastUserMessage.compression_strength !== "absent"
338334
) {
339335
state.thread.new_chat_suggested = {
340-
...state.thread.new_chat_suggested,
336+
wasRejectedByUser: false,
341337
wasSuggested: true,
342338
};
343339
}
@@ -427,10 +423,6 @@ export const chatReducer = createReducer(initialState, (builder) => {
427423
state.thread.increase_max_tokens = action.payload;
428424
});
429425

430-
builder.addCase(setThreadPaused, (state, action) => {
431-
state.thread.paused = action.payload;
432-
});
433-
434426
builder.addMatcher(
435427
capsApi.endpoints.getCaps.matchFulfilled,
436428
(state, action) => {

refact-agent/gui/src/features/Chat/Thread/selectors.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,3 @@ export const selectLastSentCompression = createSelector(
9494
return lastCompression;
9595
},
9696
);
97-
98-
export const selectThreadPaused = createSelector(
99-
selectThread,
100-
(thread) => thread.paused ?? false,
101-
);

refact-agent/gui/src/features/Chat/Thread/types.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ export type ChatThread = {
2929
currentMaximumContextTokens?: number;
3030
currentMessageContextTokens?: number;
3131
increase_max_tokens?: boolean;
32-
paused?: boolean;
3332
};
3433

3534
export type SuggestedChat = {

refact-agent/gui/src/hooks/useCompressionStop.ts

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ import { useEffect, useCallback, useMemo } from "react";
22
import { useAppSelector } from "./useAppSelector";
33
import { useAppDispatch } from "./useAppDispatch";
44
import {
5+
selectChatId,
56
selectLastSentCompression,
67
selectMessages,
7-
selectThreadPaused,
8-
setThreadPaused,
8+
setIsNewChatSuggested,
9+
setIsNewChatSuggestionRejected,
10+
setPreventSend,
911
} from "../features/Chat";
1012
import { takeFromEndWhile } from "../utils";
1113
import { isUserMessage } from "../events";
@@ -14,12 +16,7 @@ export function useLastSentCompressionStop() {
1416
const dispatch = useAppDispatch();
1517
const lastSentCompression = useAppSelector(selectLastSentCompression);
1618
const messages = useAppSelector(selectMessages);
17-
const stopped = useAppSelector(selectThreadPaused);
18-
useEffect(() => {
19-
if (lastSentCompression && lastSentCompression !== "absent" && !stopped) {
20-
dispatch(setThreadPaused(true));
21-
}
22-
}, [dispatch, lastSentCompression, stopped]);
19+
const chatId = useAppSelector(selectChatId);
2320

2421
const messagesFromLastUserMessage = useMemo(() => {
2522
return takeFromEndWhile(messages, (message) => !isUserMessage(message))
@@ -30,16 +27,16 @@ export function useLastSentCompressionStop() {
3027
if (
3128
lastSentCompression &&
3229
lastSentCompression !== "absent" &&
33-
messagesFromLastUserMessage >= 40 &&
34-
!stopped
30+
messagesFromLastUserMessage >= 40
3531
) {
36-
dispatch(setThreadPaused(true));
32+
dispatch(setPreventSend({ id: chatId }));
33+
dispatch(setIsNewChatSuggested({ chatId, value: true }));
3734
}
38-
}, [dispatch, lastSentCompression, messagesFromLastUserMessage, stopped]);
35+
}, [chatId, dispatch, lastSentCompression, messagesFromLastUserMessage]);
3936

4037
const resume = useCallback(() => {
41-
dispatch(setThreadPaused(false));
42-
}, [dispatch]);
38+
dispatch(setIsNewChatSuggestionRejected({ chatId, value: true }));
39+
}, [chatId, dispatch]);
4340

44-
return { stopped, resume, strength: lastSentCompression };
41+
return { resume, strength: lastSentCompression };
4542
}

refact-agent/gui/src/hooks/useDiffFileReload.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { isDiffMessage } from "../services/refact";
99
* Hook to handle file reloading for diff messages in JetBrains IDE
1010
* Ensures each file is only reloaded once per message
1111
*/
12+
// Note this won't work if the chat is in the cache.
1213
export function useDiffFileReload() {
1314
const messages = useAppSelector(selectMessages);
1415
const configIdeHost = useAppSelector(selectConfig).host;

refact-agent/gui/src/hooks/useEventBusForIDE.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ export const ideToolCallResponse = createAction<{
6363
accepted: boolean | "indeterminate";
6464
}>("ide/toolEditResponse");
6565

66+
export const ideForceReloadProjectTreeFiles = createAction(
67+
"ide/forceReloadProjectTreeFiles",
68+
);
69+
6670
export const useEventsBusForIDE = () => {
6771
const [sendTelemetryEvent] =
6872
telemetryApi.useLazySendTelemetryChatEventQuery();

refact-agent/gui/src/hooks/useSendChatRequest.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ import {
5656

5757
import { v4 as uuidv4 } from "uuid";
5858
import { upsertToolCallIntoHistory } from "../features/History/historySlice";
59-
import { useLastSentCompressionStop } from "./useCompressionStop";
6059

6160
type SubmitHandlerParams =
6261
| {
@@ -356,7 +355,6 @@ export function useAutoSend() {
356355
const sendImmediately = useAppSelector(selectSendImmediately);
357356
const wasInteracted = useAppSelector(getToolsInteractionStatus); // shows if tool confirmation popup was interacted by user
358357
const areToolsConfirmed = useAppSelector(getToolsConfirmationStatus);
359-
const compressionStop = useLastSentCompressionStop();
360358
const { sendMessages, abort, messagesWithSystemPrompt } =
361359
useSendChatRequest();
362360
// TODO: make a selector for this, or show tool formation
@@ -381,7 +379,6 @@ export function useAutoSend() {
381379
const lastMessage = currentMessages.slice(-1)[0];
382380

383381
if (
384-
!compressionStop.stopped &&
385382
isAssistantMessage(lastMessage) &&
386383
lastMessage.tool_calls &&
387384
lastMessage.tool_calls.length > 0
@@ -418,6 +415,5 @@ export function useAutoSend() {
418415
isIntegration,
419416
thread.mode,
420417
thread,
421-
compressionStop.stopped,
422418
]);
423419
}

0 commit comments

Comments
 (0)