Skip to content
Merged
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: 48 additions & 3 deletions ui/desktop/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ if (process.platform === 'win32') {
const recentDirs = loadRecentDirs();
const openDir = recentDirs.length > 0 ? recentDirs[0] : null;

const recipeDeeplink = parsedUrl.searchParams.get('config');
const recipeDeeplink = parseRecipeDeeplink(protocolUrl);
const scheduledJobId = parsedUrl.searchParams.get('scheduledJob');

createChat(
Expand Down Expand Up @@ -319,6 +319,8 @@ async function processProtocolUrl(parsedUrl: URL, window: BrowserWindow) {
pendingDeepLink = null;
}

let windowDeeplinkURL: string | null = null;

app.on('open-url', async (_event, url) => {
if (process.platform !== 'win32') {
const parsedUrl = new URL(url);
Expand All @@ -329,7 +331,10 @@ app.on('open-url', async (_event, url) => {
console.log('[Main] Received open-url event:', url);
if (parsedUrl.hostname === 'bot' || parsedUrl.hostname === 'recipe') {
console.log('[Main] Detected bot/recipe URL, creating new chat window');
const recipeDeeplink = parsedUrl.searchParams.get('config');
let recipeDeeplink = parseRecipeDeeplink(url);
if (recipeDeeplink) {
windowDeeplinkURL = url;
}
const scheduledJobId = parsedUrl.searchParams.get('scheduledJob');

// Create a new window directly
Expand Down Expand Up @@ -1037,12 +1042,52 @@ const openDirectoryDialog = async (): Promise<OpenDialogReturnValue> => {
}

addRecentDir(dirToAdd);

let recipeDeeplink: string | undefined = undefined;
if (windowDeeplinkURL) {
recipeDeeplink = parseRecipeDeeplink(windowDeeplinkURL);
}
// Create a new window with the selected directory
await createChat(app, undefined, dirToAdd);
await createChat(
app,
undefined,
dirToAdd,
undefined,
undefined,
undefined,
undefined,
recipeDeeplink
);
}
return result;
};

function parseRecipeDeeplink(url: string): string | undefined {
const parsedUrl = new URL(url);
let recipeDeeplink = parsedUrl.searchParams.get('config');
if (recipeDeeplink && !url.includes(recipeDeeplink)) {
// URLSearchParams decodes + as space, which can break encoded configs
// Parse raw query to preserve "+" characters in values like config
const search = parsedUrl.search || '';
// parse recipe deeplink from search params
const configMatch = search.match(/(?:[?&])config=([^&]*)/);
// get recipe deeplink from config match
let recipeDeeplinkTmp = configMatch ? configMatch[1] : null;
if (recipeDeeplinkTmp) {
try {
recipeDeeplink = decodeURIComponent(recipeDeeplinkTmp);
} catch {
// Leave as-is if decoding fails
return undefined;
}
}
}
if (recipeDeeplink) {
return recipeDeeplink;
}
return undefined;
}

// Global error handler
const handleFatalError = (error: Error) => {
const windows = BrowserWindow.getAllWindows();
Expand Down
Loading