Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions packages/desktop/src/main/ipc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import {
IPC,
ChatRequest,
SimpleCompletionRequest,

Check failure on line 9 in packages/desktop/src/main/ipc.ts

View workflow job for this annotation

GitHub Actions / Type Check

Module '"../shared/types"' has no exported member 'SimpleCompletionRequest'.
AppSettings,
McpServerConfig,
Message,
Expand Down Expand Up @@ -675,6 +676,56 @@
autoUpdater.checkForUpdates();
});

// ─── Chat Complete (headless, no streaming events) ────────────────────────
ipcMain.handle(IPC.CHAT_COMPLETE, async (_e, request: SimpleCompletionRequest) => {

Check failure on line 680 in packages/desktop/src/main/ipc.ts

View workflow job for this annotation

GitHub Actions / Type Check

Property 'CHAT_COMPLETE' does not exist on type '{ readonly SETTINGS_GET: "settings:get"; readonly SETTINGS_SET: "settings:set"; readonly CHAT_SEND: "chat:send"; readonly CHAT_STREAM_CHUNK: "chat:stream:chunk"; readonly CHAT_STREAM_THINKING: "chat:stream:thinking"; ... 24 more ...; readonly LOG_OPEN: "log:open"; }'.
const settings = getSettings();
const provider = settings.providers.find((p) => p.id === request.providerId);
if (!provider) throw new Error(`Provider "${request.providerId}" not found.`);

const messages: Message[] = request.messages.map((m) => ({

Check failure on line 685 in packages/desktop/src/main/ipc.ts

View workflow job for this annotation

GitHub Actions / Type Check

Parameter 'm' implicitly has an 'any' type.
id: uuidv4(),
role: m.role,
content: m.content,
timestamp: Date.now(),
}));

// Providers require the conversation to end with a user message.
// Append a closing instruction if the last message is from the assistant.
if (messages.length > 0 && messages[messages.length - 1].role !== 'user') {
messages.push({
id: uuidv4(),
role: 'user',
content: 'Please provide your analysis per your system prompt.',
timestamp: Date.now(),
});
}

const emptyParams = { temperature: 0.7, maxTokens: 2048, topP: 1 };

const getStream = () => {
switch (provider.type) {
case 'anthropic':
return streamAnthropic(provider, messages, request.model, emptyParams, request.systemPrompt, []);
case 'openai':
return streamOpenAI(provider, messages, request.model, emptyParams, request.systemPrompt, []);
case 'lmstudio':
return streamLmStudio(provider, messages, request.model, emptyParams, request.systemPrompt, []);
case 'ollama':
return streamOllama(provider, messages, request.model, emptyParams, request.systemPrompt, []);
case 'gemini':
return streamGemini(provider, messages, request.model, emptyParams, request.systemPrompt, []);
default:
throw new Error(`Provider type "${provider.type}" is not supported for background calls.`);
}
};

let fullText = '';
for await (const event of getStream()) {
if (event.type === 'delta') fullText += event.text;
}
return { text: fullText };
});

// ─── Abort ───────────────────────────────────────────────────────────────
ipcMain.on(IPC.CHAT_ABORT, (_e, conversationId: string) => {
abortControllers.get(conversationId)?.abort();
Expand Down
3 changes: 3 additions & 0 deletions packages/desktop/src/preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
send: (request: ChatRequest): Promise<{ messageId: string }> =>
ipcRenderer.invoke(IPC.CHAT_SEND, request),

complete: (request: import('./shared/types').SimpleCompletionRequest): Promise<{ text: string }> =>

Check failure on line 28 in packages/desktop/src/preload.ts

View workflow job for this annotation

GitHub Actions / Type Check

Namespace '"/home/runner/work/Client/Client/packages/desktop/src/shared/types"' has no exported member 'SimpleCompletionRequest'.
ipcRenderer.invoke(IPC.CHAT_COMPLETE, request),

Check failure on line 29 in packages/desktop/src/preload.ts

View workflow job for this annotation

GitHub Actions / Type Check

Property 'CHAT_COMPLETE' does not exist on type '{ readonly SETTINGS_GET: "settings:get"; readonly SETTINGS_SET: "settings:set"; readonly CHAT_SEND: "chat:send"; readonly CHAT_STREAM_CHUNK: "chat:stream:chunk"; readonly CHAT_STREAM_THINKING: "chat:stream:thinking"; ... 24 more ...; readonly LOG_OPEN: "log:open"; }'.

abort: (conversationId: string): void =>
ipcRenderer.send(IPC.CHAT_ABORT, conversationId),

Expand Down
2 changes: 2 additions & 0 deletions packages/desktop/src/renderer/env.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type {
AppSettings,
ChatRequest,
SimpleCompletionRequest,
FolderEntry,
McpServerConfig,
McpTool,
Expand All @@ -22,6 +23,7 @@ declare global {
api: {
chat: {
send: (request: ChatRequest) => Promise<{ messageId: string }>;
complete: (request: SimpleCompletionRequest) => Promise<{ text: string }>;
abort: (conversationId: string) => void;
onChunk: (cb: (data: StreamChunk) => void) => UnsubFn;
onEnd: (cb: (data: StreamEnd) => void) => UnsubFn;
Expand Down
Loading