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
54 changes: 49 additions & 5 deletions documents/LocalDevelopmentSetup.md
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,46 @@ Create `.vscode/settings.json` and copy the following JSON:

---

### Running with Automated Script

For convenience, you can use the provided startup scripts that handle environment setup and start both backend and frontend services automatically. This is the quickest way to get up and running locally.

> **Note**: You must complete **Step 1 (Prerequisites)** and **Step 2 (Development Tools Setup)** before using the automated scripts.

#### Windows (Command Prompt or PowerShell):

```cmd
cd src
.\start.cmd
```

#### macOS/Linux/WSL:

```bash
cd src
chmod +x start.sh
./start.sh
```

### What the Scripts Do

The startup scripts automatically handle:
- Environment variable configuration
- Azure authentication
- Azure RBAC role assignments (Cosmos DB, SQL Server, AI Foundry, AI Search)
- Python virtual environment setup
- Backend dependency installation
- Frontend dependency installation
- Starting both backend and frontend servers

> **Note**: The script includes a 30-second wait for the backend to initialize before starting the frontend. If you see connection errors initially, wait a moment and reload the page.

---

## Running Backend and Frontend Manually

If you prefer more control over the setup process, follow the steps below to configure and run each service individually.

## Step 3: Azure Authentication Setup

Before configuring services, authenticate with Azure:
Expand Down Expand Up @@ -385,13 +425,17 @@ az role assignment create \
```

#### Cosmos DB Access

```bash
# Get your principal ID
PRINCIPAL_ID=$(az ad signed-in-user show --query id -o tsv)

# Assign Cosmos DB Built-in Data Contributor role
az role assignment create \
--role "Cosmos DB Built-in Data Contributor" \
--assignee $PRINCIPAL_ID \
--scope "/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.DocumentDB/databaseAccounts/<cosmos-account-name>"
az cosmosdb sql role assignment create \
--resource-group <resource-group-name> \
--account-name <cosmos-db-account-name> \
--role-definition-name "Cosmos DB Built-in Data Contributor" \
--principal-id $PRINCIPAL_ID \
--scope /subscriptions/<subscription-id>/resourceGroups/<resource-group-name>/providers/Microsoft.DocumentDB/databaseAccounts/<cosmos-db-account-name>
```

#### Azure Storage Access
Expand Down
1 change: 1 addition & 0 deletions infra/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,7 @@ module searchServiceUpdate 'br/public:avm/res/search/search-service:0.12.0' = {
params: {
// Required parameters
name: aiSearchName
location: location
enableTelemetry: enableTelemetry
diagnosticSettings: enableMonitoring ? [
{
Expand Down
11 changes: 7 additions & 4 deletions infra/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"_generator": {
"name": "bicep",
"version": "0.41.2.15936",
"templateHash": "9287430903779325833"
"templateHash": "949305639975172329"
}
},
"parameters": {
Expand Down Expand Up @@ -28296,9 +28296,9 @@
},
"dependsOn": [
"aiFoundryAiServices",
"[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').aiServices)]",
"[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').openAI)]",
"[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').cognitiveServices)]",
"[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').openAI)]",
"[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').aiServices)]",
"virtualNetwork"
]
},
Expand Down Expand Up @@ -31613,6 +31613,9 @@
"name": {
"value": "[variables('aiSearchName')]"
},
"location": {
"value": "[parameters('location')]"
},
"enableTelemetry": {
"value": "[parameters('enableTelemetry')]"
},
Expand Down Expand Up @@ -41904,9 +41907,9 @@
}
},
"dependsOn": [
"[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').storageDfs)]",
"[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').storageFile)]",
"[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').storageQueue)]",
"[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').storageDfs)]",
"[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').storageBlob)]",
"userAssignedIdentity",
"virtualNetwork"
Expand Down
4 changes: 4 additions & 0 deletions infra/main_custom.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,7 @@ module searchServiceUpdate 'br/public:avm/res/search/search-service:0.12.0' = {
params: {
// Required parameters
name: aiSearchName
location: location
enableTelemetry: enableTelemetry
Comment thread
Harsh-Microsoft marked this conversation as resolved.
diagnosticSettings: enableMonitoring ? [
{
Expand Down Expand Up @@ -856,6 +857,9 @@ module searchServiceUpdate 'br/public:avm/res/search/search-service:0.12.0' = {
]
: []
}
dependsOn: [
searchService
]
}

// ========== Search Service to AI Services Role Assignment ========== //
Expand Down
2 changes: 1 addition & 1 deletion infra/scripts/agent_scripts/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
aiohttp==3.13.3
aiohttp==3.13.4
azure-identity==1.25.2
azure-ai-projects==2.0.0b3
2 changes: 1 addition & 1 deletion infra/scripts/index_scripts/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ azure-ai-agents==1.2.0b5
azure-ai-inference==1.0.0b9
agent-framework-core==1.0.0rc2
agent-framework-azure-ai==1.0.0rc2
pypdf==6.6.2
pypdf==6.10.0
tiktoken==0.12.0
azure-identity==1.25.2
azure-ai-textanalytics==5.3.0
Expand Down
2 changes: 2 additions & 0 deletions infra/scripts/run_create_agents_scripts.sh
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,8 @@ titleAgentName=""
while IFS='=' read -r key value; do
# Skip empty lines or lines without '='
[ -z "$key" ] && continue
# Strip trailing carriage return if present (Windows line endings)
value="${value%$'\r'}"
case "$key" in
conversationAgentName)
conversationAgentName="$value"
Expand Down
6 changes: 3 additions & 3 deletions src/App/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/App/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
"d3-color": "$d3-color",
"nth-check": "$nth-check",
"flatted": "^3.4.2",
"lodash": "4.18.1",
"node-forge": "^1.4.0",
"react-scripts": {
"picomatch": "^4.0.4"
Expand Down
8 changes: 4 additions & 4 deletions src/api/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ pydantic[email]==2.11.10

# Azure SDK Core
azure-core==1.38.0
requests==2.32.5
types-requests==2.32.4.20260107
aiohttp==3.13.3
requests==2.33.0
types-requests==2.33.0.20260408
aiohttp==3.13.4

# Azure Services
azure-identity==1.25.2
Expand All @@ -35,6 +35,6 @@ opentelemetry-instrumentation==0.60b0
azure-monitor-opentelemetry==1.8.3

# Development tools
pytest==9.0.2
pytest==9.0.3
pytest-cov==7.0.0
pytest-asyncio==1.3.0
41 changes: 35 additions & 6 deletions src/start.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ if exist "%API_ENV_FILE%" (
echo 2. Manually create %API_ENV_FILE% with required environment variables
echo 3. Copy an existing .env file to %API_ENV_FILE%
echo.
echo For more information, see: documents/LocalDebuggingSetup.md
echo For more information, see: documents/LocalDevelopmentSetup.md
exit /b 1
)

Expand All @@ -131,7 +131,7 @@ set APP_ENV_FILE=%ROOT_DIR%\src\App\.env
(
echo REACT_APP_API_BASE_URL=http://127.0.0.1:8000
) > "%APP_ENV_FILE%"
echo Updated src/App/.env with APP_API_BASE_URL
echo Updated src/App/.env with REACT_APP_API_BASE_URL

REM Add or update APP_ENV="dev" in API .env file
echo Checking for existing APP_ENV in src/api/.env...
Expand Down Expand Up @@ -284,6 +284,18 @@ if errorlevel 1 (
)
cd %ROOT_DIR%

REM Close any processes using ports 8000 and 3000
echo Checking for processes using ports 8000 and 3000...
REM Kill any existing processes on ports 8000 and 3000 before starting
for %%P in (8000 3000) do (
for /f "tokens=5" %%A in ('netstat -ano ^| findstr "LISTENING" ^| findstr ":%%P "') do (
if "%%A" neq "0" (
echo Port %%P is already in use by PID %%A. Stopping it...
taskkill /F /PID %%A /T >nul 2>&1
)
)
)

REM Start backend and frontend
echo Starting backend server...
cd %ROOT_DIR%
Expand All @@ -297,10 +309,27 @@ timeout /t 30 /nobreak >nul

echo Starting frontend server...
cd %ROOT_DIR%\src\App
call npm start

echo Both servers have been started.
echo Backend running at http://127.0.0.1:8000
echo Frontend running at http://localhost:3000
REM Show server information before starting
echo.
echo ========================================
echo Both servers are now running:
echo Backend: http://127.0.0.1:8000
echo Frontend: http://localhost:3000
echo ========================================
echo Press Ctrl+C to stop all servers
echo.

REM Start npm with PowerShell wrapper for automatic cleanup on Ctrl+C (single line for reliability)
powershell -NoProfile -ExecutionPolicy Bypass -Command "try { npm start } finally { Write-Host ''; Write-Host 'Stopping all processes...'; Start-Sleep -Milliseconds 500; @(8000, 3000) | ForEach-Object { $port = $_; Get-NetTCPConnection -LocalPort $port -State Listen -ErrorAction SilentlyContinue | ForEach-Object { $pid_ = $_.OwningProcess; if ($pid_ -and $pid_ -ne 0) { taskkill /F /PID $pid_ /T 2>$null } } }; Write-Host 'Cleanup complete.'; Write-Host ''; Write-Host 'All servers stopped.' -ForegroundColor Yellow }"

REM Fallback cleanup in case PowerShell finally block was interrupted
for %%P in (8000 3000) do (
for /f "tokens=5" %%A in ('netstat -ano ^| findstr "LISTENING" ^| findstr ":%%P "') do (
if "%%A" neq "0" (
taskkill /F /PID %%A /T >nul 2>&1
)
)
)

endlocal
58 changes: 52 additions & 6 deletions src/start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ check_local_env() {
echo " 2. Manually create $API_ENV_FILE with required environment variables"
echo " 3. Copy an existing .env file to $API_ENV_FILE"
echo ""
echo "For more information, see: documents/LocalDebuggingSetup.md"
echo "For more information, see: documents/LocalDevelopmentSetup.md"
exit 1
fi
}
Expand Down Expand Up @@ -97,7 +97,12 @@ setup_environment() {
echo "Checking for existing APP_ENV in src/api/.env..."
if grep -q "^APP_ENV=" "$API_ENV_FILE" 2>/dev/null; then
echo "APP_ENV already exists, updating to \"dev\"..."
sed -i 's/^APP_ENV=.*/APP_ENV="dev"/' "$API_ENV_FILE"
# macOS/BSD sed requires -i with extension, use portable approach
if [[ "$OSTYPE" == "darwin"* ]]; then
sed -i '' 's/^APP_ENV=.*/APP_ENV="dev"/' "$API_ENV_FILE"
else
sed -i 's/^APP_ENV=.*/APP_ENV="dev"/' "$API_ENV_FILE"
fi
else
echo "APP_ENV not found, adding APP_ENV=\"dev\"..."
echo 'APP_ENV="dev"' >> "$API_ENV_FILE"
Expand Down Expand Up @@ -286,6 +291,15 @@ setup_environment() {
npm install --force || { echo "Failed to restore frontend npm packages"; exit 1; }
cd "$ROOT_DIR"

# Kill any existing processes on ports 8000 and 3000 before starting
for port in 8000 3000; do
pid=$(lsof -ti :"$port" 2>/dev/null)
if [ -n "$pid" ]; then
echo "Port $port is already in use by PID $pid. Stopping it..."
kill -9 $pid
fi
done

# Start backend and frontend
echo "Starting backend server..."
cd "$ROOT_DIR"
Expand All @@ -305,11 +319,43 @@ setup_environment() {

echo "Starting frontend server..."
cd "$ROOT_DIR/src/App"

# Show server information before starting
echo ""
echo "========================================"
echo "Both servers are now running:"
echo " Backend: http://127.0.0.1:8000"
echo " Frontend: http://localhost:3000"
echo "========================================"
echo "Press Ctrl+C to stop all servers"
echo ""

# Setup cleanup function to kill both backend and frontend on Ctrl+C
cleanup() {
echo ""
echo "Cleaning up processes..."
sleep 0.5

for port in 8000 3000; do
pid=$(lsof -ti :"$port" 2>/dev/null)
if [ -n "$pid" ]; then
echo "Stopping process on port $port (PID $pid)..."
kill -9 $pid 2>/dev/null
fi
done

echo "All servers stopped."
exit 0
}

# Trap Ctrl+C and other termination signals
trap cleanup INT TERM

# Start npm (this will block until Ctrl+C)
npm start

echo "Both servers have been started."
echo "Backend running at http://127.0.0.1:8000"
echo "Frontend running at http://localhost:3000"

# Cleanup after npm exits normally
cleanup
}

# Check if .azure folder exists first
Expand Down
Loading