Skip to content
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
5 changes: 5 additions & 0 deletions jetpacker/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,8 @@ export/

# Generated third-party notices
THIRD_PARTY_NOTICES

# Python files
**/__pycache__/
*.pyc

1 change: 1 addition & 0 deletions jetpacker/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ If you wish to run, explore, or modify the code locally:
1. Clone the repository:
```bash
git clone https://github.com/android/ai-samples.git
cd ai-samples/jetpacker
```
2. Open the project in Android Studio.
3. Gradle will automatically sync and resolve dependencies.
Expand Down
31 changes: 20 additions & 11 deletions jetpacker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
</table>

## Overview
JetPacker provides users with powerful tools to manage their upcoming trips, build out rich itineraries, record voice notes, manage travel expenses, generate on-device "Trip Summaries and Tips", generate AI reviews, chat with hotel staff via automatic translation, get real-time museum assistant guidance, and contribute to Android's intelligence system with trip management functions through [AppFunctions](https://d.android.com/ai/appfunctions).
JetPacker provides users with powerful tools to manage their upcoming trips, build out rich itineraries, record voice notes, manage travel expenses, generate on-device "Trip Summaries and Tips", generate AI reviews, chat with hotel staff via automatic translation, and get real-time museum assistant guidance.

## Architecture
This project is built using modern Android architecture components:
Expand All @@ -25,7 +25,6 @@ This project is built using modern Android architecture components:
- **On-Device AI**: ML Kit GenAI (Prompt, Speech Recognition, Translation)
- **Cloud & Hybrid AI**: Firebase AI Logic (Gemini grounded with URL/Maps/Search, and hybrid models with on-device fallback)
- **App Security**: Firebase App Check (with Play Integrity and Debug Provider)
- **Assistant Integration**: Android [AppFunctions](https://d.android.com/ai/appfunctions) (`androidx.appfunctions`)

## Module Overview
JetPacker follows a clean, multi-module Android structure organized by responsibility and domain:
Expand All @@ -44,7 +43,6 @@ JetPacker follows a clean, multi-module Android structure organized by responsib
- **`:feature:home`**: Dashboard screen displaying the user's upcoming trips list.
- **`:feature:create_trip`**: Unified trip form module handling both new trip creation and existing trip editing (`EditTripScreen`).
- **`:feature:detail`**: Detailed view screens for specific itinerary events (Flights, Hotels, Restaurants, Museums, Tours).
- **`:feature:appfunctions`**: Android AppFunctions framework integration (`JetPackerAppFunctionService`) contributing structured functions to Android's intelligence system for trips, expenses, itineraries, and voice notes.
- **`:feature:trip`**: Top-level trip container shell (`TripScreen`) holding bottom navigation and orchestrating trip sub-tabs.
- **`:feature:trip:itinerary`**: Pure itinerary timeline screen displaying daily scheduled events.
- **`:feature:trip:itinerary:enrichment`**: On-device AI summaries and tips (`TripSummaryAndTipsCard`) and dynamic daily theme generators.
Expand Down Expand Up @@ -92,6 +90,25 @@ cd android
./gradlew test
```

### Running the Booking Assistant Server
JetPacker uses a local Python-based Server-Sent Events (SSE) server to simulate the booking agents. To run the booking assistant backend:

```bash
# Navigate to the booking-server directory
cd android/booking-server

# Set your Gemini API Key
export GEMINI_API_KEY="your-api-key-here"

# Run the server using its virtual environment
./.venv/bin/uvicorn booking_server:app --host 0.0.0.0 --port 8000
```

> [!IMPORTANT]
> A valid `GEMINI_API_KEY` (or `GOOGLE_API_KEY`) environment variable is required. If the key is missing at startup, the server will print a clear error banner and exit immediately.

This runs the FastAPI booking server on port 8000. When running the app on the Android Emulator, localhost is remapped to `10.0.2.2:8000` to automatically route requests to this server.

## On-Device AI Features
JetPacker integrates local on-device AI capabilities using ML Kit. These features run entirely on-device and can be toggled or customized in `android/core/flags/src/main/kotlin/com/example/jetpacker/core/flags/FeatureFlags.kt`:
- **ENABLE_TRIP_SUMMARY_AND_TIPS**: Generates an on-device card summary of the current trip using ML Kit GenAI Prompt.
Expand All @@ -105,14 +122,6 @@ JetPacker also integrates online hybrid features using Firebase AI Logic (Gemini
- **ENABLE_REVIEW_GENERATION**: Topic-selected review generator (uses Gemini 2.5 flash-lite on-device with cloud fallback).
- **Hotel Support Chat**: Receives hotel receptionist assistance with real-time ML Kit + Gemini translation.

## AppFunctions Integration
JetPacker uses Android's [**AppFunctions**](https://d.android.com/ai/appfunctions) library (`androidx.appfunctions`) in `:feature:appfunctions` to contribute to Android's intelligence system with structured travel actions and data queries via `JetPackerAppFunctionService`:
- **Trip Management**: `searchTrip` (filter by ID, name, location, and dates) and `createTrip`.
- **Itinerary Events**: `getItinerary` and `addItineraryEvent` (activity, dining, accommodation, etc.).
- **Expense Tracking**: `getExpenses` and `addExpense` (amount, currency, category).
- **Voice Notes**: `getVoiceNotes` and `addVoiceNote` (recorded transcriptions linked to trips).
- **Day Themes**: `getDayThemes` and `setDayTheme` for daily trip customization.


## IDE Setup & Development

Expand Down
3 changes: 3 additions & 0 deletions jetpacker/android/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ dependencies {
implementation(libs.accompanist.permissions)
implementation(project(":feature:trip:voice_notes"))
implementation(project(":feature:trip:expenses"))
implementation(project(":feature:trip:booking_assistant"))
implementation(project(":feature:trip:itinerary:enrichment"))
implementation(libs.androidx.activity.compose)
implementation(libs.androidx.camera.camera2)
Expand Down Expand Up @@ -149,6 +150,8 @@ dependencies {
implementation(libs.firebase.appcheck.playintegrity)
implementation(libs.firebase.appcheck.debug)



debugImplementation(libs.androidx.compose.ui.test.manifest)
debugImplementation(libs.androidx.compose.ui.tooling)

Expand Down
2 changes: 1 addition & 1 deletion jetpacker/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.JetPacker"
android:usesCleartextTraffic="false">
android:usesCleartextTraffic="true">
<activity
android:name=".MainActivity"
android:exported="true"
Expand Down
73 changes: 73 additions & 0 deletions jetpacker/android/booking-server/booking_catalog.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
{
"catalogId": "https://example.com/catalogs/booking_assistant/v1/catalog.json",
"components": [
{
"name": "InteractiveOptionPicker",
"description": "Renders custom options and confirm action",
"properties": {
"type": "object",
"properties": {
"prompt": {
"type": "string",
"description": "Prompt header text."
},
"options": {
"type": "array",
"items": {
"type": "string"
},
"description": "List of custom option button labels."
},
"selectedIdx": {
"type": "integer",
"description": "Index of the currently selected option (0-indexed)."
},
"confirmBtnText": {
"type": "string",
"description": "Label for the confirmation button."
}
},
"required": ["prompt", "options"]
}
},
{
"name": "SeatSelectionPicker",
"description": "Renders seat choices as a clean selection grid",
"properties": {
"type": "object",
"properties": {
"prompt": {
"type": "string",
"description": "Prompt choice text."
},
"seats": {
"type": "array",
"items": {
"type": "string"
},
"description": "List of seat label strings."
},
"selectedSeat": {
"type": "string",
"description": "Selected seat label."
}
},
"required": ["prompt", "seats"]
}
},
{
"name": "BookingStatus",
"description": "Renders final booking success confirmation banner",
"properties": {
"type": "object",
"properties": {
"text": {
"type": "string",
"description": "Banner success message text."
}
},
"required": ["text"]
}
}
]
}
Loading
Loading