From 30b9af6a5e4b5f07214e3cc3dc54ff066e3a6277 Mon Sep 17 00:00:00 2001 From: Zane Staggs Date: Mon, 9 Feb 2026 10:24:21 -0800 Subject: [PATCH 1/2] strip empty extensions array when deeplink also --- ui/desktop/src/App.tsx | 20 +++----------- .../src/components/recipes/RecipesView.tsx | 9 ++++--- ui/desktop/src/main.ts | 27 ++++--------------- ui/desktop/src/preload.ts | 6 ++--- ui/desktop/src/recipe/index.ts | 13 +++++++++ ui/desktop/src/sessions.ts | 13 ++++----- 6 files changed, 34 insertions(+), 54 deletions(-) diff --git a/ui/desktop/src/App.tsx b/ui/desktop/src/App.tsx index 576869a01a18..3f07cea48aa8 100644 --- a/ui/desktop/src/App.tsx +++ b/ui/desktop/src/App.tsx @@ -83,23 +83,17 @@ const PairRouteWrapper = ({ const [isCreatingSession, setIsCreatingSession] = useState(false); const resumeSessionId = searchParams.get('resumeSessionId') ?? undefined; - const recipeId = searchParams.get('recipeId') ?? undefined; const recipeDeeplinkFromConfig = window.appConfig?.get('recipeDeeplink') as string | undefined; const initialMessage = routeState.initialMessage; - // Create session if we have an initialMessage, recipeId, or recipeDeeplink but no sessionId + // Create session if we have an initialMessage or recipeDeeplink but no sessionId useEffect(() => { - if ( - (initialMessage || recipeId || recipeDeeplinkFromConfig) && - !resumeSessionId && - !isCreatingSession - ) { + if ((initialMessage || recipeDeeplinkFromConfig) && !resumeSessionId && !isCreatingSession) { setIsCreatingSession(true); (async () => { try { const newSession = await createSession(getInitialWorkingDir(), { - recipeId, recipeDeeplink: recipeDeeplinkFromConfig, allExtensions: extensionsList, }); @@ -115,7 +109,6 @@ const PairRouteWrapper = ({ setSearchParams((prev) => { prev.set('resumeSessionId', newSession.id); - prev.delete('recipeId'); return prev; }); } catch (error) { @@ -133,14 +126,7 @@ const PairRouteWrapper = ({ // Note: isCreatingSession is intentionally NOT in the dependency array // It's only used as a guard to prevent concurrent session creation // eslint-disable-next-line react-hooks/exhaustive-deps - }, [ - initialMessage, - recipeId, - recipeDeeplinkFromConfig, - resumeSessionId, - setSearchParams, - extensionsList, - ]); + }, [initialMessage, recipeDeeplinkFromConfig, resumeSessionId, setSearchParams, extensionsList]); // Add resumed session to active sessions if not already there useEffect(() => { diff --git a/ui/desktop/src/components/recipes/RecipesView.tsx b/ui/desktop/src/components/recipes/RecipesView.tsx index 5390c5984e5f..b7c2a8138024 100644 --- a/ui/desktop/src/components/recipes/RecipesView.tsx +++ b/ui/desktop/src/components/recipes/RecipesView.tsx @@ -32,7 +32,7 @@ import { } from '../../api'; import ImportRecipeForm, { ImportRecipeButton } from './ImportRecipeForm'; import CreateEditRecipeModal from './CreateEditRecipeModal'; -import { generateDeepLink, Recipe, stripEmptyExtensions } from '../../recipe'; +import { generateDeepLink, encodeRecipe, Recipe, stripEmptyExtensions } from '../../recipe'; import { useNavigation } from '../../hooks/useNavigation'; import { CronPicker } from '../schedule/CronPicker'; import { Dialog, DialogContent, DialogHeader, DialogTitle } from '../ui/dialog'; @@ -165,15 +165,16 @@ export default function RecipesView() { } }; - const handleStartRecipeChatInNewWindow = (recipeId: string) => { + const handleStartRecipeChatInNewWindow = async (recipe: Recipe) => { try { + const encodedRecipe = await encodeRecipe(stripEmptyExtensions(recipe) as Recipe); window.electron.createChatWindow( undefined, getInitialWorkingDir(), undefined, undefined, 'pair', - recipeId + encodedRecipe ); trackRecipeStarted(true, undefined, true); } catch (error) { @@ -521,7 +522,7 @@ export default function RecipesView() {