Skip to content

Commit 685acbc

Browse files
committed
fix: fix various jetbrains issues and startup activity logic
1 parent 351888e commit 685acbc

File tree

5 files changed

+118
-92
lines changed

5 files changed

+118
-92
lines changed

core/llm/llms/Ollama.ts

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -641,21 +641,29 @@ class Ollama extends BaseLLM implements ModelInstaller {
641641
if (this.apiKey) {
642642
headers.Authorization = `Bearer ${this.apiKey}`;
643643
}
644-
const response = await this.fetch(
645-
// localhost was causing fetch failed in pkg binary only for this Ollama endpoint
646-
this.getEndpoint("api/tags"),
647-
{
644+
645+
try {
646+
const response = await this.fetch(this.getEndpoint("api/tags"), {
648647
method: "GET",
649648
headers: headers,
650-
},
651-
);
652-
const data = await response.json();
653-
if (response.ok) {
654-
return data.models.map((model: any) => model.name);
655-
} else {
656-
throw new Error(
657-
"Failed to list Ollama models. Make sure Ollama is running.",
658-
);
649+
});
650+
const data = await response.json();
651+
if (response.ok) {
652+
return data.models.map((model: any) => model.name);
653+
} else {
654+
console.warn(
655+
`Ollama /api/tags returned status ${response.status}:`,
656+
data,
657+
);
658+
throw new Error(
659+
"Failed to list Ollama models. Make sure Ollama is running.",
660+
);
661+
}
662+
} catch (error) {
663+
console.warn("Failed to list Ollama models:", error);
664+
// If Ollama is not running or returns an error, return an empty list
665+
// This allows the application to continue without blocking on Ollama
666+
return [];
659667
}
660668
}
661669

extensions/intellij/src/main/kotlin/com/github/continuedev/continueintellijextension/activities/ContinuePluginStartupActivity.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,6 @@ class ContinuePluginStartupActivity : StartupActivity, DumbAware {
146146
val diffManager = DiffManager(project)
147147

148148
continuePluginService.diffManager = diffManager
149-
150-
val coreMessengerManager = CoreMessengerManager(project, ideProtocolClient, coroutineScope)
151-
continuePluginService.coreMessengerManager = coreMessengerManager
152149
continuePluginService.ideProtocolClient = ideProtocolClient
153150

154151
// Listen to changes to settings so the core can reload remote configuration
@@ -306,6 +303,9 @@ class ContinuePluginStartupActivity : StartupActivity, DumbAware {
306303
listener,
307304
project.service<ContinuePluginDisposable>()
308305
)
306+
307+
val coreMessengerManager = CoreMessengerManager(project, ideProtocolClient, coroutineScope)
308+
continuePluginService.coreMessengerManager = coreMessengerManager
309309
}
310310
}
311311
}

gui/src/components/OSRContextMenu.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { useContext, useEffect, useRef, useState } from "react";
2-
import useIsOSREnabled from "../hooks/useIsOSREnabled";
32
import { IdeMessengerContext } from "../context/IdeMessenger";
3+
import useIsOSREnabled from "../hooks/useIsOSREnabled";
44
import { getPlatform } from "../util";
55

66
interface Position {
@@ -140,7 +140,7 @@ const OSRContextMenu = () => {
140140
}
141141

142142
setPosition(null);
143-
if (isOSREnabled && platform.current !== "mac") {
143+
if (isOSREnabled) {
144144
document.addEventListener("mousedown", clickHandler);
145145
document.addEventListener("mouseleave", leaveWindowHandler);
146146
document.addEventListener("contextmenu", contextMenuHandler);
@@ -153,7 +153,7 @@ const OSRContextMenu = () => {
153153
};
154154
}, [isOSREnabled]);
155155

156-
if (platform.current === "mac" || !isOSREnabled || !position) {
156+
if (!isOSREnabled || !position) {
157157
return null;
158158
}
159159
return (

gui/src/context/IdeMessenger.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ export class IdeMessenger implements IIdeMessenger {
8383
if (typeof vscode === "undefined") {
8484
if (isJetBrains()) {
8585
if (window.postIntellijMessage === undefined) {
86-
console.log(
86+
console.debug(
8787
"Unable to send message: postIntellijMessage is undefined. ",
8888
messageType,
8989
data,

gui/src/hooks/ParallelListeners.tsx

Lines changed: 90 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ import { setLocalStorage } from "../util/localStorage";
3535
import { migrateLocalStorage } from "../util/migrateLocalStorage";
3636
import { useWebviewListener } from "./useWebviewListener";
3737

38+
const INITIAL_CONFIG_POLLING_INTERVAL = 2_000;
39+
const INITIAL_CONFIG_POLLING_MAX_ATTEMPTS = 100;
40+
3841
function ParallelListeners() {
3942
const dispatch = useAppDispatch();
4043
const ideMessenger = useContext(IdeMessengerContext);
@@ -43,25 +46,71 @@ function ParallelListeners() {
4346
const selectedProfileId = useAppSelector(
4447
(store) => store.profiles.selectedProfileId,
4548
);
46-
const hasDoneInitialConfigLoad = useRef(false);
49+
50+
const hasReceivedOrRetrievedConfig = useRef(false);
4751

4852
// Load symbols for chat on any session change
4953
const sessionId = useAppSelector((state) => state.session.id);
5054
const lastSessionId = useAppSelector((store) => store.session.lastSessionId);
5155
const [initialSessionId] = useState(sessionId || lastSessionId);
5256

57+
// Once we know core is up
58+
const onInitialConfigLoad = useCallback(async () => {
59+
debugger;
60+
dispatch(setConfigLoading(false));
61+
void dispatch(refreshSessionMetadata({}));
62+
63+
const jetbrains = isJetBrains();
64+
if (jetbrains) {
65+
// Save theme colors to local storage for immediate loading in JetBrains
66+
void ideMessenger
67+
.request("jetbrains/getColors", undefined)
68+
.then((result) => {
69+
if (result.status === "success") {
70+
setDocumentStylesFromTheme(result.content);
71+
}
72+
});
73+
74+
// Tell JetBrains the webview is ready
75+
void ideMessenger
76+
.request("jetbrains/onLoad", undefined)
77+
.then((result) => {
78+
if (result.status === "success") {
79+
const msg = result.content;
80+
(window as any).windowId = msg.windowId;
81+
(window as any).serverUrl = msg.serverUrl;
82+
(window as any).workspacePaths = msg.workspacePaths;
83+
(window as any).vscMachineId = msg.vscMachineId;
84+
(window as any).vscMediaUrl = msg.vscMediaUrl;
85+
}
86+
});
87+
}
88+
89+
ideMessenger.post("docs/initStatuses", undefined);
90+
void dispatch(updateFileSymbolsFromHistory());
91+
92+
if (initialSessionId) {
93+
await dispatch(
94+
loadSession({
95+
sessionId: initialSessionId,
96+
saveCurrentSession: false,
97+
}),
98+
);
99+
}
100+
}, [initialSessionId, ideMessenger]);
101+
53102
const handleConfigUpdate = useCallback(
54-
async (isInitial: boolean, result: FromCoreProtocol["configUpdate"][0]) => {
103+
async (result: FromCoreProtocol["configUpdate"][0]) => {
55104
const {
56105
result: configResult,
57106
profileId,
58107
organizations,
59108
selectedOrgId,
60109
} = result;
61-
if (isInitial && hasDoneInitialConfigLoad.current) {
62-
return;
110+
if (hasReceivedOrRetrievedConfig.current === false) {
111+
await onInitialConfigLoad();
63112
}
64-
hasDoneInitialConfigLoad.current = true;
113+
hasReceivedOrRetrievedConfig.current = true;
65114
dispatch(setOrganizations(organizations));
66115
dispatch(setSelectedOrgId(selectedOrgId));
67116
dispatch(setSelectedProfile(profileId));
@@ -92,56 +141,65 @@ function ParallelListeners() {
92141
setHasReasoningEnabled(supportsReasoning && !isReasoningDisabled),
93142
);
94143
},
95-
[dispatch, hasDoneInitialConfigLoad],
144+
[dispatch, hasReceivedOrRetrievedConfig, onInitialConfigLoad],
96145
);
97146

98-
// Load config from the IDE
147+
// Startup activity
99148
useEffect(() => {
100-
async function initialLoadConfig() {
101-
dispatch(setIsSessionMetadataLoading(true));
102-
dispatch(setConfigLoading(true));
149+
void dispatch(cancelStream());
150+
dispatch(setIsSessionMetadataLoading(true));
151+
dispatch(setConfigLoading(true));
152+
153+
// Local storage migration/jetbrains styles loading
154+
const jetbrains = isJetBrains();
155+
setDocumentStylesFromLocalStorage(jetbrains);
156+
157+
migrateLocalStorage(dispatch);
158+
159+
// Poll config just to be safe
160+
async function pollInitialConfigLoad() {
103161
const result = await ideMessenger.request(
104162
"config/getSerializedProfileInfo",
105163
undefined,
106164
);
107165
if (result.status === "success") {
108-
await handleConfigUpdate(true, result.content);
109-
}
110-
dispatch(setConfigLoading(false));
111-
if (initialSessionId) {
112-
await dispatch(
113-
loadSession({
114-
sessionId: initialSessionId,
115-
saveCurrentSession: false,
116-
}),
117-
);
166+
console.log("succeeded", result.content);
167+
if (hasReceivedOrRetrievedConfig.current === false) {
168+
await handleConfigUpdate(result.content);
169+
}
170+
} else {
171+
console.log("Failed");
172+
console.error(result.error);
118173
}
119174
}
120-
void initialLoadConfig();
175+
void pollInitialConfigLoad();
176+
let pollAttempts = 0;
121177
const interval = setInterval(() => {
122-
if (hasDoneInitialConfigLoad.current) {
123-
// Init to run on initial config load
124-
ideMessenger.post("docs/initStatuses", undefined);
125-
void dispatch(updateFileSymbolsFromHistory());
126-
void dispatch(refreshSessionMetadata({}));
127-
128-
// This triggers sending pending status to the GUI for relevant docs indexes
178+
if (hasReceivedOrRetrievedConfig.current) {
129179
clearInterval(interval);
180+
} else if (pollAttempts >= INITIAL_CONFIG_POLLING_MAX_ATTEMPTS) {
181+
clearInterval(interval);
182+
console.warn(
183+
`Config polling stopped after ${INITIAL_CONFIG_POLLING_MAX_ATTEMPTS} attempts`,
184+
);
130185
} else {
131-
void initialLoadConfig();
186+
console.log("Config load attempt #" + pollAttempts);
187+
pollAttempts++;
188+
void pollInitialConfigLoad();
132189
}
133-
}, 2_000);
190+
}, INITIAL_CONFIG_POLLING_INTERVAL);
134191

135192
return () => clearInterval(interval);
136-
}, [hasDoneInitialConfigLoad, ideMessenger, initialSessionId]);
193+
}, [hasReceivedOrRetrievedConfig, ideMessenger, handleConfigUpdate]);
137194

195+
// Handle config update events from core
138196
useWebviewListener(
139197
"configUpdate",
140198
async (update) => {
141199
if (!update) {
142200
return;
143201
}
144-
await handleConfigUpdate(false, update);
202+
await handleConfigUpdate(update);
145203
},
146204
[handleConfigUpdate],
147205
);
@@ -152,42 +210,6 @@ function ParallelListeners() {
152210
}
153211
}, [sessionId]);
154212

155-
// ON LOAD
156-
useEffect(() => {
157-
// Override persisted state
158-
void dispatch(cancelStream());
159-
160-
const jetbrains = isJetBrains();
161-
setDocumentStylesFromLocalStorage(jetbrains);
162-
163-
if (jetbrains) {
164-
// Save theme colors to local storage for immediate loading in JetBrains
165-
void ideMessenger
166-
.request("jetbrains/getColors", undefined)
167-
.then((result) => {
168-
if (result.status === "success") {
169-
setDocumentStylesFromTheme(result.content);
170-
}
171-
});
172-
173-
// Tell JetBrains the webview is ready
174-
void ideMessenger
175-
.request("jetbrains/onLoad", undefined)
176-
.then((result) => {
177-
if (result.status === "error") {
178-
return;
179-
}
180-
181-
const msg = result.content;
182-
(window as any).windowId = msg.windowId;
183-
(window as any).serverUrl = msg.serverUrl;
184-
(window as any).workspacePaths = msg.workspacePaths;
185-
(window as any).vscMachineId = msg.vscMachineId;
186-
(window as any).vscMediaUrl = msg.vscMediaUrl;
187-
});
188-
}
189-
}, []);
190-
191213
useWebviewListener(
192214
"jetbrains/setColors",
193215
async (data) => {
@@ -253,10 +275,6 @@ function ParallelListeners() {
253275
}
254276
}, [isInEdit, history]);
255277

256-
useEffect(() => {
257-
migrateLocalStorage(dispatch);
258-
}, []);
259-
260278
return <></>;
261279
}
262280

0 commit comments

Comments
 (0)