Skip to content

feat: Add Windows compatibility and cross-platform development support #69

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
22 changes: 18 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,31 +36,45 @@ Follow these steps to get the application running locally for development and te

**2. Install Dependencies:**

**Backend:**
**For Linux/Mac:**

**Backend:**
```bash
cd backend
pip install .
```

**Frontend:**

```bash
cd frontend
npm install
```


**3. Run Development Servers:**

**Backend & Frontend:**
**For Linux/Mac:**

```bash
make dev
```
This will run the backend and frontend development servers. Open your browser and navigate to the frontend development server URL (e.g., `http://localhost:5173/app`).

**For Windows:**

```batch
start-app.bat
```

This will run the backend and frontend development servers. Open your browser and navigate to the frontend development server URL (e.g., `http://localhost:5173/app`).

_Alternatively, you can run the backend and frontend development servers separately. For the backend, open a terminal in the `backend/` directory and run `langgraph dev`. The backend API will be available at `http://127.0.0.1:2024`. It will also open a browser window to the LangGraph UI. For the frontend, open a terminal in the `frontend/` directory and run `npm run dev`. The frontend will be available at `http://localhost:5173`._

**Windows Users:** If you don't have `make` installed, use the provided batch files:
- `start-app.bat` - Automatically installs dependencies (if needed) and starts both servers


**Note:** The `start-app.bat` will automatically install dependencies on first run and skip installation on subsequent runs if everything is already set up.

## How the Backend Agent Works (High-Level)

The core of the backend is a LangGraph agent defined in `backend/src/agent/graph.py`. It follows these steps:
Expand Down
98 changes: 58 additions & 40 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,49 +27,67 @@ export default function App() {
assistantId: "agent",
messagesKey: "messages",
onFinish: (event: any) => {
console.log(event);
console.log('Finish event:', event);
},
onUpdateEvent: (event: any) => {
console.log('Received event:', event);
let processedEvent: ProcessedEvent | null = null;
if (event.generate_query) {
processedEvent = {
title: "Generating Search Queries",
data: event.generate_query.query_list.join(", "),
};
} else if (event.web_research) {
const sources = event.web_research.sources_gathered || [];
const numSources = sources.length;
const uniqueLabels = [
...new Set(sources.map((s: any) => s.label).filter(Boolean)),
];
const exampleLabels = uniqueLabels.slice(0, 3).join(", ");
processedEvent = {
title: "Web Research",
data: `Gathered ${numSources} sources. Related to: ${
exampleLabels || "N/A"
}.`,
};
} else if (event.reflection) {
processedEvent = {
title: "Reflection",
data: event.reflection.is_sufficient
? "Search successful, generating final answer."
: `Need more information, searching for ${event.reflection.follow_up_queries.join(
", "
)}`,
};
} else if (event.finalize_answer) {
processedEvent = {
title: "Finalizing Answer",
data: "Composing and presenting the final answer.",
};
hasFinalizeEventOccurredRef.current = true;
}
if (processedEvent) {
setProcessedEventsTimeline((prevEvents) => [
...prevEvents,
processedEvent!,
]);

try {
if (event?.messages?.[0]?.content) {
// Handle message content
const content = event.messages[0].content;
processedEvent = {
title: "Response",
data: Array.isArray(content) ? content.join("\n") : String(content),
};
} else if (event?.generate_query?.query_list) {
const queryList = event.generate_query.query_list;
processedEvent = {
title: "Generating Search Queries",
data: Array.isArray(queryList) ? queryList.join(", ") : String(queryList),
};
} else if (event?.web_research) {
const sources = event.web_research.sources_gathered || [];
const numSources = sources.length;
const uniqueLabels = [
...new Set(sources.map((s: any) => s?.label).filter(Boolean)),
];
const exampleLabels = uniqueLabels.slice(0, 3).join(", ");
processedEvent = {
title: "Web Research",
data: `Gathered ${numSources} sources. Related to: ${
exampleLabels || "N/A"
}.`,
};
} else if (event?.reflection) {
const followUpQueries = event.reflection.follow_up_queries;
processedEvent = {
title: "Reflection",
data: event.reflection.is_sufficient
? "Search successful, generating final answer."
: `Need more information, searching for ${
Array.isArray(followUpQueries)
? followUpQueries.join(", ")
: followUpQueries || "additional information"
}`,
};
} else if (event?.finalize_answer) {
processedEvent = {
title: "Finalizing Answer",
data: "Composing and presenting the final answer.",
};
hasFinalizeEventOccurredRef.current = true;
}

if (processedEvent) {
setProcessedEventsTimeline((prevEvents) => [
...prevEvents,
processedEvent!,
]);
}
} catch (error) {
console.error('Error processing event:', error, event);
}
},
});
Expand Down
31 changes: 30 additions & 1 deletion frontend/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,42 @@ import { defineConfig } from "vite";
import react from "@vitejs/plugin-react-swc";
import tailwindcss from "@tailwindcss/vite";

// Cross-platform fix for path resolution
// The usual `new URL(".", import.meta.url).pathname` breaks on Windows
// (e.g., "C:\path" turns into "/C:/path" and causes issues)
// This approach works reliably on all platforms

function resolveSrcPath(): string {
try {
// Modern ESM approach (preferred for Linux/Mac)
const esmPath = new URL(".", import.meta.url).pathname;
// On Windows, pathname might have issues, so we validate it
const resolvedPath = path.resolve(esmPath, "./src");

// Quick validation - if the path looks wrong (common on Windows), use fallback
if (process.platform === "win32" && esmPath.startsWith("/C:")) {
throw new Error("Windows path issue detected");
}

return resolvedPath;
} catch {
// Fallback for Windows or any environment where ESM URL handling fails
return path.resolve(__dirname, "./src");
}
}

const srcPath = resolveSrcPath();

// Debug log for development (can be removed in production)
console.log(`[Vite Config] Resolved src path: ${srcPath}`);

// https://vitejs.dev/config/
export default defineConfig({
plugins: [react(), tailwindcss()],
base: "/app/",
resolve: {
alias: {
"@": path.resolve(new URL(".", import.meta.url).pathname, "./src"),
"@": srcPath,
},
},
server: {
Expand Down
97 changes: 97 additions & 0 deletions start-app.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
@echo off
title Gemini Fullstack LangGraph - Setup & Start

echo ========================================
echo Gemini Fullstack LangGraph Quickstart
echo ========================================
echo.

REM Check if this is first time setup
set FIRST_TIME=0

REM Check if backend dependencies are installed
echo Checking backend dependencies...
cd backend
pip show langgraph >nul 2>&1
if %errorlevel% neq 0 (
echo Backend dependencies not found. Installing...
set FIRST_TIME=1
pip install .
if %errorlevel% neq 0 (
echo Error: Failed to install backend dependencies
pause
exit /b 1
)
echo ✓ Backend dependencies installed successfully
) else (
echo ✓ Backend dependencies already installed
)
cd ..

REM Check if frontend dependencies are installed
echo Checking frontend dependencies...
if not exist "frontend\node_modules" (
echo Frontend dependencies not found. Installing...
set FIRST_TIME=1
cd frontend
npm install
if %errorlevel% neq 0 (
echo Error: Failed to install frontend dependencies
pause
exit /b 1
)
echo ✓ Frontend dependencies installed successfully
cd ..
) else (
echo ✓ Frontend dependencies already installed
)

REM Check for .env file
echo.
echo Checking API key configuration...
if not exist "backend\.env" (
echo ⚠️ WARNING: No .env file found in backend directory
echo.
echo Please create backend\.env with your Gemini API key:
echo GEMINI_API_KEY="your_actual_api_key_here"
echo.
echo Get your API key from: https://aistudio.google.com/app/apikey
echo.
) else (
echo ✓ .env file found
)

echo.
if %FIRST_TIME%==1 (
echo ✓ Setup completed successfully!
echo.
)

echo ========================================
echo Starting Development Servers
echo ========================================
echo.
echo Frontend: http://localhost:5173/app/
echo Backend: http://127.0.0.1:2024
echo.
echo Press Ctrl+C in any window to stop both servers
echo.

REM Start backend server in a new window
start "Backend Server - LangGraph" cmd /k "cd /d %~dp0backend && echo Starting backend server... && langgraph dev"

REM Wait a moment for backend to start
timeout /t 3 /nobreak >nul

REM Start frontend server in a new window
start "Frontend Server - React/Vite" cmd /k "cd /d %~dp0frontend && echo Starting frontend server... && npm run dev"

echo.
echo Both servers are starting in separate windows...
echo.
echo To stop the servers:
echo 1. Close both command prompt windows, or
echo 2. Press Ctrl+C in each window
echo.
echo Press any key to close this window...
pause >nul