mirror of
https://github.com/temporal-community/temporal-ai-agent.git
synced 2026-03-17 06:58:09 +01:00
Real events for FindEvents and real API for finding flights. TODO invoice creation
This commit is contained in:
@@ -78,7 +78,7 @@ async def send_prompt(prompt: str):
|
|||||||
example_conversation_history="\n ".join(
|
example_conversation_history="\n ".join(
|
||||||
[
|
[
|
||||||
"user: I'd like to travel to an event",
|
"user: I'd like to travel to an event",
|
||||||
"agent: Sure! Let's start by finding an event you'd like to attend. Could you tell me which region and month you're interested in?",
|
"agent: Sure! Let's start by finding an event you'd like to attend. Could you tell me which city and month you're interested in?",
|
||||||
"user: In Sao Paulo, Brazil, in February",
|
"user: In Sao Paulo, Brazil, in February",
|
||||||
"agent: Great! Let's find an events in Sao Paulo, Brazil in February.",
|
"agent: Great! Let's find an events in Sao Paulo, Brazil in February.",
|
||||||
"user_confirmed_tool_run: <user clicks confirm on FindEvents tool>",
|
"user_confirmed_tool_run: <user clicks confirm on FindEvents tool>",
|
||||||
|
|||||||
@@ -61,11 +61,8 @@ export default function App() {
|
|||||||
|
|
||||||
const handleStartNewChat = async () => {
|
const handleStartNewChat = async () => {
|
||||||
try {
|
try {
|
||||||
await fetch("http://127.0.0.1:8000/end-chat", { method: "POST" });
|
|
||||||
// sleep for a bit to allow the server to process the end-chat request
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, 1000)); // todo make less dodgy
|
|
||||||
await fetch(
|
await fetch(
|
||||||
`http://127.0.0.1:8000/send-prompt?prompt=${encodeURIComponent("I'd like to travel to an event.")}`,
|
`http://127.0.0.1:8000/send-prompt?prompt=${encodeURIComponent("I'd like to travel for an event.")}`,
|
||||||
{ method: "POST" }
|
{ method: "POST" }
|
||||||
);
|
);
|
||||||
setConversation([]); // clear local state
|
setConversation([]); // clear local state
|
||||||
|
|||||||
8
scripts/find_events_test.py
Normal file
8
scripts/find_events_test.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
from tools.find_events import find_events
|
||||||
|
import json
|
||||||
|
|
||||||
|
# Example usage
|
||||||
|
if __name__ == "__main__":
|
||||||
|
search_args = {"city": "Sydney", "month": "July"}
|
||||||
|
results = find_events(search_args)
|
||||||
|
print(json.dumps(results, indent=2))
|
||||||
7
scripts/flight_api_test.py
Normal file
7
scripts/flight_api_test.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
from tools.search_flights import search_flights
|
||||||
|
import json
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# Suppose user typed "new" for New York, "lon" for London
|
||||||
|
flights = search_flights("London", "JFK", "2025-01-15", "2025-01-23")
|
||||||
|
print(json.dumps(flights, indent=2))
|
||||||
252
tools/data/find_events_data.json
Normal file
252
tools/data/find_events_data.json
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
{
|
||||||
|
"Melbourne": [
|
||||||
|
{
|
||||||
|
"eventName": "Australian Open",
|
||||||
|
"dateFrom": "2025-01-13",
|
||||||
|
"dateTo": "2025-01-26",
|
||||||
|
"description": "A two-week Grand Slam tennis tournament featuring the world's top players, accompanied by various entertainment options including live music and family-friendly activities."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "Melbourne International Comedy Festival",
|
||||||
|
"dateFrom": "2025-03-26",
|
||||||
|
"dateTo": "2025-04-20",
|
||||||
|
"description": "One of the world's largest comedy festivals, showcasing stand-up, cabaret, theatre, and street performances across numerous city venues."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "Melbourne International Film Festival (MIFF)",
|
||||||
|
"dateFrom": "2025-08-07",
|
||||||
|
"dateTo": "2025-08-23",
|
||||||
|
"description": "Established in 1952, MIFF presents a diverse selection of Australian and international films, including features, documentaries, and shorts."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "Melbourne Fringe Festival",
|
||||||
|
"dateFrom": "2025-09-17",
|
||||||
|
"dateTo": "2025-10-04",
|
||||||
|
"description": "An open-access arts festival featuring a wide array of art forms such as theatre, comedy, music, and digital art across various venues."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "Moomba Festival",
|
||||||
|
"dateFrom": "2025-03-07",
|
||||||
|
"dateTo": "2025-03-10",
|
||||||
|
"description": "Australia's largest free community festival, celebrated over four days during the Labour Day long weekend, including a parade, live music, fireworks, and the famous Birdman Rally along the Yarra River."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "White Night Melbourne",
|
||||||
|
"dateFrom": "2025-08-22",
|
||||||
|
"dateTo": "2025-08-24",
|
||||||
|
"description": "A dusk-to-dawn arts and cultural festival transforming the city with light installations, projections, music, and performances."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "Melbourne Food and Wine Festival",
|
||||||
|
"dateFrom": "2025-03-19",
|
||||||
|
"dateTo": "2025-03-29",
|
||||||
|
"description": "A celebration of Victoria's culinary scene, featuring food and wine events, masterclasses, and dining experiences."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Sydney": [
|
||||||
|
{
|
||||||
|
"eventName": "Sydney Gay and Lesbian Mardi Gras",
|
||||||
|
"dateFrom": "2025-02-14",
|
||||||
|
"dateTo": "2025-03-01",
|
||||||
|
"description": "One of the largest LGBTQ+ festivals globally, featuring a vibrant parade, parties, and cultural events celebrating diversity and inclusion."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "Vivid Sydney",
|
||||||
|
"dateFrom": "2025-05-22",
|
||||||
|
"dateTo": "2025-06-13",
|
||||||
|
"description": "An annual festival of light, music, and ideas, transforming the city with mesmerizing light installations and projections."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "Sydney Festival",
|
||||||
|
"dateFrom": "2025-01-08",
|
||||||
|
"dateTo": "2025-01-26",
|
||||||
|
"description": "A major arts festival presenting a diverse program of theatre, dance, music, and visual arts across the city."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "Sculpture by the Sea, Bondi",
|
||||||
|
"dateFrom": "2025-10-23",
|
||||||
|
"dateTo": "2025-11-09",
|
||||||
|
"description": "An outdoor sculpture exhibition along the Bondi to Tamarama coastal walk, showcasing works by Australian and international artists."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "Sydney Writers' Festival",
|
||||||
|
"dateFrom": "2025-04-27",
|
||||||
|
"dateTo": "2025-05-03",
|
||||||
|
"description": "An annual literary festival featuring talks, panel discussions, and workshops with acclaimed authors and thinkers."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "Sydney Film Festival",
|
||||||
|
"dateFrom": "2025-06-04",
|
||||||
|
"dateTo": "2025-06-15",
|
||||||
|
"description": "One of the longest-running film festivals in the world, showcasing a diverse selection of local and international films."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Auckland": [
|
||||||
|
{
|
||||||
|
"eventName": "Pasifika Festival",
|
||||||
|
"dateFrom": "2025-03-08",
|
||||||
|
"dateTo": "2025-03-09",
|
||||||
|
"description": "The largest Pacific Islands-themed festival globally, celebrating the diverse cultures of the Pacific with traditional cuisine, performances, and arts."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "Auckland Arts Festival",
|
||||||
|
"dateFrom": "2025-03-11",
|
||||||
|
"dateTo": "2025-03-29",
|
||||||
|
"description": "A biennial multi-arts festival showcasing local and international artists in theatre, dance, music, and visual arts."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "Auckland Writers Festival",
|
||||||
|
"dateFrom": "2025-05-13",
|
||||||
|
"dateTo": "2025-05-18",
|
||||||
|
"description": "An annual event bringing together international and local writers for discussions, readings, and workshops."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "Auckland Diwali Festival",
|
||||||
|
"dateFrom": "2025-10-26",
|
||||||
|
"dateTo": "2025-10-27",
|
||||||
|
"description": "A vibrant celebration of Indian culture and the Hindu festival of Diwali, featuring performances, food stalls, and traditional activities."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Brisbane": [
|
||||||
|
{
|
||||||
|
"eventName": "Brisbane Festival",
|
||||||
|
"dateFrom": "2025-09-05",
|
||||||
|
"dateTo": "2025-09-26",
|
||||||
|
"description": "A major international arts festival featuring theatre, music, dance, and visual arts, culminating in the Riverfire fireworks display."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "NRL Magic Round",
|
||||||
|
"dateFrom": "2025-05-02",
|
||||||
|
"dateTo": "2025-05-04",
|
||||||
|
"description": "A rugby league extravaganza where all NRL matches for the round are played at Suncorp Stadium, attracting fans nationwide."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "Brisbane International Film Festival",
|
||||||
|
"dateFrom": "2025-10-01",
|
||||||
|
"dateTo": "2025-10-11",
|
||||||
|
"description": "Showcasing a curated selection of films from around the world, including premieres and special events."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "Brisbane Comedy Festival",
|
||||||
|
"dateFrom": "2025-02-22",
|
||||||
|
"dateTo": "2025-03-24",
|
||||||
|
"description": "A month-long comedy festival featuring local and international comedians in stand-up, sketch, and improv performances."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "Brisbane Writers Festival",
|
||||||
|
"dateFrom": "2025-09-05",
|
||||||
|
"dateTo": "2025-09-08",
|
||||||
|
"description": "An annual literary festival celebrating books, writing, and ideas with author talks, panel discussions, and workshops."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "Brisbane Asia Pacific Film Festival",
|
||||||
|
"dateFrom": "2025-11-29",
|
||||||
|
"dateTo": "2025-12-08",
|
||||||
|
"description": "Showcasing the best cinema from the Asia Pacific region, including features, documentaries, and short films."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Perth": [
|
||||||
|
{
|
||||||
|
"eventName": "Perth Festival",
|
||||||
|
"dateFrom": "2025-02-07",
|
||||||
|
"dateTo": "2025-03-01",
|
||||||
|
"description": "Australia's longest-running cultural festival, offering a diverse program of music, theatre, dance, literature, and visual arts."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "Fringe World Festival",
|
||||||
|
"dateFrom": "2025-01-16",
|
||||||
|
"dateTo": "2025-02-15",
|
||||||
|
"description": "One of the largest fringe festivals globally, featuring a vast array of performances including comedy, cabaret, theatre, and street arts."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "Sculpture by the Sea",
|
||||||
|
"dateFrom": "2025-03-06",
|
||||||
|
"dateTo": "2025-03-23",
|
||||||
|
"description": "An annual outdoor sculpture exhibition along Cottesloe Beach, showcasing works from Australian and international artists."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "Revelation Perth International Film Festival",
|
||||||
|
"dateFrom": "2025-07-03",
|
||||||
|
"dateTo": "2025-07-13",
|
||||||
|
"description": "A showcase of independent cinema, featuring a diverse selection of films, documentaries, and short films."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "Perth Comedy Festival",
|
||||||
|
"dateFrom": "2025-04-22",
|
||||||
|
"dateTo": "2025-05-19",
|
||||||
|
"description": "A month-long comedy festival featuring local and international comedians in stand-up, sketch, and improv performances."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Adelaide": [
|
||||||
|
{
|
||||||
|
"eventName": "Adelaide Festival",
|
||||||
|
"dateFrom": "2025-02-28",
|
||||||
|
"dateTo": "2025-03-15",
|
||||||
|
"description": "A premier arts festival offering a rich program of theatre, music, dance, and visual arts from renowned international and local artists."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "Adelaide Fringe",
|
||||||
|
"dateFrom": "2025-02-14",
|
||||||
|
"dateTo": "2025-03-15",
|
||||||
|
"description": "The largest open-access arts festival in the Southern Hemisphere, featuring thousands of performances across various genres and venues."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "SALA Festival",
|
||||||
|
"dateFrom": "2025-08-01",
|
||||||
|
"dateTo": "2025-08-31",
|
||||||
|
"description": "South Australia's largest visual arts festival, showcasing the work of local artists in exhibitions, workshops, and events."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "OzAsia Festival",
|
||||||
|
"dateFrom": "2025-09-25",
|
||||||
|
"dateTo": "2025-10-11",
|
||||||
|
"description": "A celebration of Asian arts and culture, featuring performances, exhibitions, and events from across the region."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "Adelaide Film Festival",
|
||||||
|
"dateFrom": "2025-10-16",
|
||||||
|
"dateTo": "2025-10-26",
|
||||||
|
"description": "Showcasing a diverse selection of Australian and international films, including features, documentaries, and shorts."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "Adelaide Writers' Week",
|
||||||
|
"dateFrom": "2025-03-01",
|
||||||
|
"dateTo": "2025-03-06",
|
||||||
|
"description": "An annual literary festival featuring talks, panel discussions, and readings by acclaimed authors and thinkers."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Wellington": [
|
||||||
|
{
|
||||||
|
"eventName": "New Zealand Festival of the Arts",
|
||||||
|
"dateFrom": "2025-02-21",
|
||||||
|
"dateTo": "2025-03-15",
|
||||||
|
"description": "The nation's largest celebration of contemporary arts and culture, featuring a diverse range of performances and exhibitions across various venues in Wellington.",
|
||||||
|
"url": "https://www.festival.nz/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "Wellington Jazz Festival",
|
||||||
|
"dateFrom": "2025-06-05",
|
||||||
|
"dateTo": "2025-06-09",
|
||||||
|
"description": "A five-day festival showcasing local and international jazz musicians in concerts, workshops, and community events.",
|
||||||
|
"url": "https://www.jazzfestival.co.nz/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "Wellington on a Plate",
|
||||||
|
"dateFrom": "2025-08-01",
|
||||||
|
"dateTo": "2025-08-16",
|
||||||
|
"description": "A culinary festival celebrating the city's food and beverage industry with special menus, events, and culinary experiences."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "CubaDupa",
|
||||||
|
"dateFrom": "2025-03-28",
|
||||||
|
"dateTo": "2025-03-29",
|
||||||
|
"description": "A vibrant street festival in Wellington's Cuba Street, featuring music, dance, street performers, and food stalls."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eventName": "Wellington Pasifika Festival",
|
||||||
|
"dateFrom": "2025-01-18",
|
||||||
|
"dateTo": "2025-01-19",
|
||||||
|
"description": "A celebration of Pacific Island culture with traditional performances, food stalls, and arts and crafts."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,17 +1,64 @@
|
|||||||
def find_events(args: dict) -> dict:
|
from datetime import datetime
|
||||||
# Example: continent="Oceania", month="April"
|
from pathlib import Path
|
||||||
region = args.get("region")
|
import json
|
||||||
month = args.get("month")
|
|
||||||
print(f"[FindEvents] Searching events in {region} for {month} ...")
|
|
||||||
|
|
||||||
# Stub result
|
|
||||||
|
def find_events(args: dict) -> dict:
|
||||||
|
search_city = args.get("city", "").lower()
|
||||||
|
search_month = args.get("month", "").capitalize()
|
||||||
|
|
||||||
|
file_path = Path(__file__).resolve().parent / "data" / "find_events_data.json"
|
||||||
|
if not file_path.exists():
|
||||||
|
return {"error": "Data file not found."}
|
||||||
|
|
||||||
|
try:
|
||||||
|
month_number = datetime.strptime(search_month, "%B").month
|
||||||
|
except ValueError:
|
||||||
|
return {"error": "Invalid month provided."}
|
||||||
|
|
||||||
|
# Helper to wrap months into [1..12]
|
||||||
|
def get_adjacent_months(m):
|
||||||
|
prev_m = 12 if m == 1 else (m - 1)
|
||||||
|
next_m = 1 if m == 12 else (m + 1)
|
||||||
|
return [prev_m, m, next_m]
|
||||||
|
|
||||||
|
valid_months = get_adjacent_months(month_number)
|
||||||
|
|
||||||
|
matching_events = []
|
||||||
|
for city_name, events in json.load(open(file_path)).items():
|
||||||
|
if search_city and search_city not in city_name.lower():
|
||||||
|
continue
|
||||||
|
|
||||||
|
for event in events:
|
||||||
|
date_from = datetime.strptime(event["dateFrom"], "%Y-%m-%d")
|
||||||
|
date_to = datetime.strptime(event["dateTo"], "%Y-%m-%d")
|
||||||
|
|
||||||
|
# If the event's start or end month is in our valid months
|
||||||
|
if date_from.month in valid_months or date_to.month in valid_months:
|
||||||
|
# Add metadata explaining how it matches
|
||||||
|
if date_from.month == month_number or date_to.month == month_number:
|
||||||
|
month_context = "requested month"
|
||||||
|
elif (
|
||||||
|
date_from.month == valid_months[0]
|
||||||
|
or date_to.month == valid_months[0]
|
||||||
|
):
|
||||||
|
month_context = "previous month"
|
||||||
|
else:
|
||||||
|
month_context = "next month"
|
||||||
|
|
||||||
|
matching_events.append(
|
||||||
|
{
|
||||||
|
"city": city_name,
|
||||||
|
"eventName": event["eventName"],
|
||||||
|
"dateFrom": event["dateFrom"],
|
||||||
|
"dateTo": event["dateTo"],
|
||||||
|
"description": event["description"],
|
||||||
|
"monthContext": month_context,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add top-level metadata if you wish
|
||||||
return {
|
return {
|
||||||
"events": [
|
"note": f"Returning events from {search_month} plus one month either side (i.e., {', '.join(datetime(2025, m, 1).strftime('%B') for m in valid_months)}).",
|
||||||
{
|
"events": matching_events,
|
||||||
"city": "Melbourne",
|
|
||||||
"eventName": "Melbourne International Comedy Festival",
|
|
||||||
"dateFrom": "2025-03-26",
|
|
||||||
"dateTo": "2025-04-20",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,175 @@
|
|||||||
|
import os
|
||||||
|
import json
|
||||||
|
import http.client
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
import urllib.parse
|
||||||
|
|
||||||
|
|
||||||
|
def search_airport(query: str) -> list:
|
||||||
|
"""
|
||||||
|
Returns a list of matching airports/cities from sky-scrapper's searchAirport endpoint.
|
||||||
|
"""
|
||||||
|
load_dotenv()
|
||||||
|
api_key = os.getenv("RAPIDAPI_KEY", "YOUR_DEFAULT_KEY")
|
||||||
|
api_host = os.getenv("RAPIDAPI_HOST", "sky-scrapper.p.rapidapi.com")
|
||||||
|
|
||||||
|
conn = http.client.HTTPSConnection(api_host)
|
||||||
|
headers = {
|
||||||
|
"x-rapidapi-key": api_key,
|
||||||
|
"x-rapidapi-host": api_host,
|
||||||
|
}
|
||||||
|
|
||||||
|
# Sanitize the query to ensure it is URL-safe
|
||||||
|
print(f"Searching for: {query}")
|
||||||
|
encoded_query = urllib.parse.quote(query)
|
||||||
|
path = f"/api/v1/flights/searchAirport?query={encoded_query}&locale=en-US"
|
||||||
|
|
||||||
|
conn.request("GET", path, headers=headers)
|
||||||
|
res = conn.getresponse()
|
||||||
|
if res.status != 200:
|
||||||
|
print(f"Error: API responded with status code {res.status}")
|
||||||
|
print(f"Response: {res.read().decode('utf-8')}")
|
||||||
|
return []
|
||||||
|
|
||||||
|
data = res.read()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
try:
|
||||||
|
return json.loads(data).get("data", [])
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
def search_flights(args: dict) -> dict:
|
def search_flights(args: dict) -> dict:
|
||||||
|
"""
|
||||||
|
1) Looks up airport/city codes via search_airport.
|
||||||
|
2) Finds the first matching skyId/entityId for both origin & destination.
|
||||||
|
3) Calls the flight search endpoint with those codes.
|
||||||
|
"""
|
||||||
|
date_depart = args.get("dateDepart")
|
||||||
|
date_return = args.get("dateReturn")
|
||||||
|
origin_query = args.get("origin")
|
||||||
|
dest_query = args.get("destination")
|
||||||
|
|
||||||
|
# Step 1: Resolve skyIds
|
||||||
|
origin_candidates = search_airport(origin_query)
|
||||||
|
destination_candidates = search_airport(dest_query)
|
||||||
|
|
||||||
|
if not origin_candidates or not destination_candidates:
|
||||||
|
return {"error": "No matches found for origin/destination"}
|
||||||
|
|
||||||
|
origin_params = origin_candidates[0]["navigation"]["relevantFlightParams"]
|
||||||
|
dest_params = destination_candidates[0]["navigation"]["relevantFlightParams"]
|
||||||
|
|
||||||
|
origin_sky_id = origin_params["skyId"] # e.g. "LOND"
|
||||||
|
origin_entity_id = origin_params["entityId"] # e.g. "27544008"
|
||||||
|
dest_sky_id = dest_params["skyId"] # e.g. "NYCA"
|
||||||
|
dest_entity_id = dest_params["entityId"] # e.g. "27537542"
|
||||||
|
|
||||||
|
# Step 2: Call flight search with resolved codes
|
||||||
|
load_dotenv()
|
||||||
|
api_key = os.getenv("RAPIDAPI_KEY", "YOUR_DEFAULT_KEY")
|
||||||
|
api_host = os.getenv("RAPIDAPI_HOST", "sky-scrapper.p.rapidapi.com")
|
||||||
|
|
||||||
|
conn = http.client.HTTPSConnection(api_host)
|
||||||
|
headers = {
|
||||||
|
"x-rapidapi-key": api_key,
|
||||||
|
"x-rapidapi-host": api_host,
|
||||||
|
}
|
||||||
|
|
||||||
|
path = (
|
||||||
|
"/api/v2/flights/searchFlights?"
|
||||||
|
f"originSkyId={origin_sky_id}"
|
||||||
|
f"&destinationSkyId={dest_sky_id}"
|
||||||
|
f"&originEntityId={origin_entity_id}"
|
||||||
|
f"&destinationEntityId={dest_entity_id}"
|
||||||
|
f"&date={date_depart}"
|
||||||
|
f"&returnDate={date_return}"
|
||||||
|
f"&cabinClass=economy&adults=1&sortBy=best¤cy=USD"
|
||||||
|
f"&market=en-US&countryCode=US"
|
||||||
|
)
|
||||||
|
|
||||||
|
conn.request("GET", path, headers=headers)
|
||||||
|
res = conn.getresponse()
|
||||||
|
data = res.read()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
try:
|
||||||
|
json_data = json.loads(data)
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
return {"error": "Invalid JSON response"}
|
||||||
|
|
||||||
|
itineraries = json_data.get("data", {}).get("itineraries", [])
|
||||||
|
if not itineraries:
|
||||||
|
return json_data # Return raw response for debugging if itineraries are empty
|
||||||
|
|
||||||
|
formatted_results = []
|
||||||
|
seen_carriers = set()
|
||||||
|
|
||||||
|
for itinerary in itineraries:
|
||||||
|
legs = itinerary.get("legs", [])
|
||||||
|
if len(legs) >= 2:
|
||||||
|
# Extract outbound and return flight details
|
||||||
|
outbound_leg = legs[0]
|
||||||
|
return_leg = legs[1]
|
||||||
|
|
||||||
|
# Get the first segment for flight details
|
||||||
|
outbound_flight = outbound_leg.get("segments", [{}])[0]
|
||||||
|
return_flight = return_leg.get("segments", [{}])[0]
|
||||||
|
|
||||||
|
# Extract flight details
|
||||||
|
outbound_carrier = outbound_flight.get("operatingCarrier", {}).get(
|
||||||
|
"name", "N/A"
|
||||||
|
)
|
||||||
|
outbound_carrier_code = outbound_flight.get("operatingCarrier", {}).get(
|
||||||
|
"alternateId", ""
|
||||||
|
)
|
||||||
|
outbound_flight_number = outbound_flight.get("flightNumber", "N/A")
|
||||||
|
outbound_flight_code = (
|
||||||
|
f"{outbound_carrier_code}{outbound_flight_number}"
|
||||||
|
if outbound_carrier_code
|
||||||
|
else outbound_flight_number
|
||||||
|
)
|
||||||
|
|
||||||
|
return_carrier = return_flight.get("operatingCarrier", {}).get(
|
||||||
|
"name", "N/A"
|
||||||
|
)
|
||||||
|
return_carrier_code = return_flight.get("operatingCarrier", {}).get(
|
||||||
|
"alternateId", ""
|
||||||
|
)
|
||||||
|
return_flight_number = return_flight.get("flightNumber", "N/A")
|
||||||
|
return_flight_code = (
|
||||||
|
f"{return_carrier_code}{return_flight_number}"
|
||||||
|
if return_carrier_code
|
||||||
|
else return_flight_number
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check if carrier is unique
|
||||||
|
if outbound_carrier not in seen_carriers:
|
||||||
|
seen_carriers.add(outbound_carrier) # Add to seen carriers
|
||||||
|
formatted_results.append(
|
||||||
|
{
|
||||||
|
"outbound_flight_code": outbound_flight_code,
|
||||||
|
"operating_carrier": outbound_carrier,
|
||||||
|
"return_flight_code": return_flight_code,
|
||||||
|
"return_operating_carrier": return_carrier,
|
||||||
|
"price": itinerary.get("price", {}).get("raw", 0.0),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Stop after finding 3 unique carriers
|
||||||
|
if len(formatted_results) >= 3:
|
||||||
|
break
|
||||||
|
|
||||||
|
return {
|
||||||
|
"origin": origin_query,
|
||||||
|
"destination": dest_query,
|
||||||
|
"currency": "USD",
|
||||||
|
"results": formatted_results,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def search_flights_example(args: dict) -> dict:
|
||||||
"""
|
"""
|
||||||
Example function for searching flights.
|
Example function for searching flights.
|
||||||
Currently just prints/returns the passed args,
|
Currently just prints/returns the passed args,
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ from models.tool_definitions import ToolDefinition, ToolArgument
|
|||||||
|
|
||||||
find_events_tool = ToolDefinition(
|
find_events_tool = ToolDefinition(
|
||||||
name="FindEvents",
|
name="FindEvents",
|
||||||
description="Find upcoming events to travel to given a location or region (e.g., 'Oceania') and a date or month",
|
description="Find upcoming events to travel to given a location or city (e.g., 'Oceania') and a date or month",
|
||||||
arguments=[
|
arguments=[
|
||||||
ToolArgument(
|
ToolArgument(
|
||||||
name="region",
|
name="city",
|
||||||
type="string",
|
type="string",
|
||||||
description="Which region to search for events",
|
description="Which city to search for events",
|
||||||
),
|
),
|
||||||
ToolArgument(
|
ToolArgument(
|
||||||
name="month",
|
name="month",
|
||||||
@@ -25,12 +25,12 @@ search_flights_tool = ToolDefinition(
|
|||||||
ToolArgument(
|
ToolArgument(
|
||||||
name="origin",
|
name="origin",
|
||||||
type="string",
|
type="string",
|
||||||
description="Airport or city (infer airport code from city)",
|
description="Airport or city (infer airport code from city and store)",
|
||||||
),
|
),
|
||||||
ToolArgument(
|
ToolArgument(
|
||||||
name="destination",
|
name="destination",
|
||||||
type="string",
|
type="string",
|
||||||
description="Airport or city code for arrival (infer airport code from city)",
|
description="Airport or city code for arrival (infer airport code from city and store)",
|
||||||
),
|
),
|
||||||
ToolArgument(
|
ToolArgument(
|
||||||
name="dateDepart",
|
name="dateDepart",
|
||||||
|
|||||||
Reference in New Issue
Block a user