# Project export: ruteX

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: Cal Hacks 11.0
- Tagline: Let's redefine your navigation experience
- Devpost: https://devpost.com/software/rutex
- GitHub: https://github.com/asadCoder/rutexbackend
- Demo: https://github.com/VikramChandraNarra/rutex
- Team: 1 GitHub contributor(s) — Asad (4 commits)

## Devpost submission (written by the team)

No Devpost description available.

## README (from the GitHub repository)

No README available.

## Detected evidence (automated analysis)

Indexed codebase: 4 recognized source files, 17 KB.
- Python (language) — detected in the code
- Flask (technology) — claimed on Devpost, not found in the code
- Google Gemini (technology) — claimed on Devpost, not found in the code
- Node.js (technology) — claimed on Devpost, not found in the code
- React (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (4 of 4)

```
brain_gemini_agent.py
health_agent.py
route_verifyer_agent.py
starter_agent.py
```

### Dependencies

No dependency index available.

### Recent commits (newest first)

- Updated starter agent
- Added more agents
- Added routes verifier using google directions api
- Added driver agent and brain gemini agent

## Key source files (fetched from GitHub, selected and truncated for size)

### health_agent.py

```python
"""
This agent can ask a question to the AI model agent and display the answer.
"""
from uagents import Agent, Context, Model

AGENT_MAILBOX_KEY = "bda4ea99-565a-4e71-80ef-508573ada912"
GOOGLE_FIT_AGENT_ADDRESS = "agent1qtlrw0pv7mgaz324j6euxka66knmxnch8grzfsuj6gd68zp5fvhr2m98ez0"
STARTER_AGENT_ADDRESS = "agent1qdw67s95esk0zwn8qxf0ln22e8zah9rqfrqqa4qyda7mjtpf3hsw640wuwr"



HealthAgent = Agent(
    name="HealthAgent",
    port=8007,
    seed="HealthAgent secret phrase",
    # endpoint=["http://127.0.0.1:8007/submit"],
    mailbox=f"{AGENT_MAILBOX_KEY}@https://agentverse.ai",
)


class Message(Model):
    message: str

class Request(Model):
    text: str


class Error(Model):
    text: str


    
class JSONResponse(Model):
    response: dict  


@HealthAgent.on_message(model=Request)
async def handle_data(ctx: Context, sender: str,  msg: Request):
    """Log response from AI Model Agent """
    ctx.logger.info(f"Got response from {sender}: {msg.text}")

    #Noete: this agent does not block this agent (yet?), the child nodes sends the stats to the starter_agent
    if msg.text == 'getStepsNeeded':
        ctx.logger.info("Getting needed steps")
        await ctx.send(GOOGLE_FIT_AGENT_ADDRESS, Request(text="getNeededSteps"))


    
		

@HealthAgent.on_message(model=Error)
async def handle_error(ctx: Context, sender: str, error: Error):
    """log error from AI Model Agent"""
    ctx.logger.info(f"Got error from AI model agent: {error}")

	    
@HealthAgent.on_interval(60)
async def interval_task(ctx: Context):
    print("I, health, am alive", HealthAgent.address)


if __name__ == "__main__":
    HealthAgent.run()
    
```

### starter_agent.py

```python
"""
This agent can ask a question to the AI model agent and display the answer.
"""
from uagents import Agent, Context, Model
import asyncio
import json


StarterAgent = Agent(
    name="StarterAgent",
    port=8000,
    seed="SenderAgent secret phrase",
    endpoint=["http://127.0.0.1:8000/submit"],
    mailbox="01feeae0-5cad-4706-a067-4070825e206d"
)


AI_MODEL_AGENT_ADDRESS = "agent1qd8ymq4najh5wycvhvhcw3l5lmkgkvkrqevrs6wpp5ll0khfdq6v2cq6859"
ROUTE_VERIFYER_AGENT_ADDRESS = "agent1qtg6p77ujvm02mrd9lrp4naxppm0aq24vhspg96z3yfwgv5nhe5cvmy6grd"
HEALTH_AGENT_ADDRESS = "agent1q0enqfa6fueh6fz6xt56hm5s5gjrt4exyxvda97dnxxun0wuv4ks52xezvv"

# Global variables to hold the response and event
response_event = asyncio.Event()
responseFromAgent = None

route = None

class Request(Model):
    text: str


class Error(Model):
    text: str


class Data(Model):
    value: float
    unit: str
    timestamp: str
    confidence: float
    source: str
    notes: str
    
class JSONResponse(Model):
    response: dict  

@StarterAgent.on_message(model=Request)
async def handle_data(ctx: Context, sender: str, request: Request):
    global responseFromAgent
    """Log response from AI Model Agent """
    ctx.logger.info(f"Got response from agent: {request}")
    # responseFromAgent = json.loads(request.text)
    responseFromAgent = request.text
	# Set the event to indicate the response has been received
    response_event.set()

@StarterAgent.on_message(model=Error)
async def handle_error(ctx: Context, sender: str, error: Error):
    """log error from AI Model Agent"""
    ctx.logger.info(f"Got error from AI model agent: {error}")


@StarterAgent.on_rest_post("/post/route", Request, JSONResponse)
async def handle_post(ctx: Context, req: Request) -> JSONResponse:
    global response_from_ai_model, response_event, route

    # Handle CORS for OPTIONS request
    if req.text is None:  # Assuming OPTIONS requests won't have body
        ctx.response_headers["Access-Control-Allow-Origin"] = "*"  # Allow the specific origin
        # return {"status": 204}  # No Content response
    
    # Access request data properly
    userInput = req.text
    ctx.logger.info(f"Received text: {userInput}")
    
	# Reset the event before sending the request
    response_event.clear()
    
    # Generate the route and create a response
    await ctx.send(AI_MODEL_AGENT_ADDRESS, Request(text=userInput))
    
    await response_event.wait()
    ctx.logger.info(f"Returned from gemini: {responseFromAgent}")

    # verify the route using verifyer agent
    response_event.clear()
    await ctx.send(ROUTE_VERIFYER_AGENT_ADDRESS, Request(text=responseFromAgent))

    await response_event.wait()
    ctx.logger.info(f"Returned from verifier: {responseFromAgent}")
    route = json.loads(responseFromAgent)

    # get health stats...currently we are only getting steps goal for the user
    response_event.clear()
    await ctx.send(HEALTH_AGENT_ADDRESS, Request(text="getStepsNeeded"))

    await response_event.wait()
    ctx.logger.info(f"Returned from health agent: {responseFromAgent}")

    route["route1Info"]["stepsNeeded"] = responseFromAgent

    return JSONResponse(response=route)

	    
@StarterAgent.on_interval(60)
async def interval_task(ctx: Context):
    print("I, starter, am alive", StarterAgent.address)

if __name__ == "__main__":
    StarterAgent.run()
    
```

### brain_gemini_agent.py

```python
"""
This agent can respond to plain text questions with data from an AI model and convert it into a machine readable format.
"""
from uagents import Agent, Context, Model
import requests
import json
import google.generativeai as genai

 
BrainGemini = Agent(
   name="BrainGemini",
   port=8001,
   seed="ReceiverAgent secret phrase",
   endpoint=["http://127.0.0.1:8001/submit"],
)

api_key = "AIzaSyAMOD8ikp9oSEK57ckFk2XFDPtULPm_jPw"

genai.configure(api_key=api_key)


# Define the generation config
generation_config = {
    "temperature": 1,
    "top_p": 0.95,
    "top_k": 64,
    "max_output_tokens": 8192,
    "response_mime_type": "application/json",
}

# Initialize the Generative Model
model = genai.GenerativeModel(
    model_name="gemini-1.5-flash",
    # generation_config=generation_config,
    generation_config={"response_mime_type": "application/json"},
    system_instruction="You are a helpful assistant for providing multimodal routes. I would like you to return the route in proper JSON format with double quotes for keys and string values, and where each subroute is a jSON object. \n{\nroute1Info : \n{\ntotalTime: int,\ndistance: \"total distance in km\"\ndescription: \"One liner describing route\",\nexpression:  \"Describes the sequential order of the modes of transport taken and the number if transit (e.g walking | transit | driving | bicycling),\nefficiency: \"time saved\",\neffectiveness: \"CO2 emissions approx only for driving; otherwise leave as null\",\nhealth: \"total calories burned; otherwise leave as null\"\n},\nroute1: [\n    {\n        start: \"Starting location full address, as it is on google maps\",\n        end: \"Destination location full address, as it is on google maps\",\n        timeTaken: \"Duration of this segment (e.g., '10 mins', '25 mins')\",\n        modeOfTransport: \"The mode of transport for this segment (options: 'driving', 'walking', 'bicycling', 'transit')\",\n        nameOfTransport: \"For public transit, provide the name or number of the transport (e.g., 'Bus 22', 'Line 1 Subway'); otherwise leave as an empty string\",\n        calories: \"Estimated calories burned for this segment (if applicable, e.g., for walking or cycling); otherwise leave as null\",\n        gasUsed: \"Estimated gas used in liters (if applicable, e.g., for driving); otherwise leave as null\",\n        totalCost: \"Cost incurred for this segment (e.g., ticket prices, tolls, fuel cost); leave as null if not applicable\"\n    }\n]}\n\nDon't turn the keys into strings, don't include any other text. \n",
)



class Request(Model):
    text: str


class Error(Model):
    text: str

class JSONResponse(Model):
    response: dict  


def get_base_route(context: str, prompt: str, max_tokens: int = 1024):
    """Send a prompt and context to the AI model and return the content of the completion"""
    response = model.generate_content(prompt)
    route_data = json.loads(response.text)
    # print(json.dumps(route_data))

    return Request(text=str(json.dumps(route_data)))
    

@BrainGemini.on_message(model=Request)
async def handle_request(ctx: Context, sender: str, request: Request):
    """Message handler for data requests sent to this agent"""
    ctx.logger.info(f"Got request from {sender}: {request.text}")
    response = get_base_route(ctx, request.text)
    await ctx.send(sender, response)
    
@BrainGemini.on_interval(60)
async def interval_task(ctx: Context):
    try:
        print("I, brain, am alive", BrainGemini.address)
    except AttributeError:
        print("BrainGemini does not have an 'address' attribute.")

		
if __name__ == "__main__":
    BrainGemini.run()
    
```

### route_verifyer_agent.py

```python
### The aim of this Route Verifier Agent is to verify all aspects
### of the route including distance, cost, duration etc using various apis acting as agents.
### Currently, we are only verifying the duration and distance using google directions api.


from uagents import Agent, Bureau, Context, Model
import requests
import json
import googlemaps
from datetime import datetime



gmaps = googlemaps.Client(key='AIzaSyDmFTRzH4UebgjP7ifLPTpo8WAmC0qXux8')
STARTER_AGENT_ADDRESS = "agent1qdw67s95esk0zwn8qxf0ln22e8zah9rqfrqqa4qyda7mjtpf3hsw640wuwr"


 
RouteVeriferAgent = Agent(
   name="RouteVeriferAgent",
   port=8004,
   seed="RouteVeriferAgent secret phrase",
   endpoint=["http://127.0.0.1:8004/submit"],
)

GoogleDirAgent = Agent(
   name="GoogleDirAgent",
   port=8005,
   seed="GoogleDirAgent recovery phrase",
   endpoint=["http://127.0.0.1:8005/submit"],
)

GoogleDirAgent_address = GoogleDirAgent.address


class Request(Model):
    text: str


class Error(Model):
    text: str


class Data(Model):
    value: float
    unit: str
    timestamp: str
    confidence: float
    source: str
    notes: str

class JSONResponse(Model):
    response: dict  


def get_completion(context: str, prompt: str, max_tokens: int = 1024):
    """Send a prompt and context to the AI model and return the content of the completion"""
        

@RouteVeriferAgent.on_message(model=Request)
async def handle_request(ctx: Context, sender: str, request: Request):
    """Message handler for data requests sent to this agent"""
    ctx.logger.info(f"Got request from {sender}: {request.text}")

    #first verify times from google
    await ctx.send(GoogleDirAgent_address, request)


    
    
@RouteVeriferAgent.on_interval(60)
async def interval_task(ctx: Context):
    try:
        print("I, RouteVeriferAgent, am alive", RouteVeriferAgent.address)
        print("I, GoogleDirAgent, am alive", GoogleDirAgent.address)
    except AttributeError:
        print("RouteVeriferAgent does not have an 'address' attribute.")


@GoogleDirAgent.on_message(model=Request)
async def google_dir_message_handler(ctx: Context, sender: str, msg: Request):
    ctx.logger.info(f"Received message from {sender}: {msg.text}")

    ctx.logger.info(f"Before updating: {msg.text}")
    updated_path = update_route_with_directions(json.loads(msg.text))
    ctx.logger.info(f"After updating: {updated_path}")
    await ctx.send(STARTER_AGENT_ADDRESS, Request(text=str(updated_path)))



def update_route_with_directions(route_plan):
    route_info = route_plan.get('route1Info', {})
    route_steps = route_plan.get('route1', [])

    total_distance = 0  # in meters
    total_duration = 0  # in seconds

    updated_steps = []

    for step in route_steps:
        origin = step.get('start')
        destination = step.get('end')
        mode = step.get('modeOfTransport', 'driving')

        if not origin or not destination:
            continue  # Skip if start or end is missing

        now = datetime.now()
        directions_result = gmaps.directions(origin, destination, mode, departure_time=now)
        
        if not directions_result:
            continue  # Skip if API call failed

        # Extract the first route and first leg
        first_route = directions_result[0]  # Get the first route
        first_leg = first_route['legs'][0]  # Get the first leg of that route

        # Extract distance and duration from the leg
        leg_distance = first_leg['distance']['value']  # in meters
        leg_duration = first_leg['duration']['value']  # in seconds

        total_distance += leg_distance
        total_duration += leg_duration

        # Update step with accurate data
        step["timeTaken"] = f"{int(leg_duration / 60)} mins"
        step["distance"] = f"{leg_distance / 1000:.2f} km"

        # Add any additional calculations (e.g., calories, gas used)
        if step["modeOfTransport"] == "walking":
            # Estimate calories burned (approx 50 kcal per km)
            calories = int((leg_distance / 1000) * 50)
            step["calories"] = calories
        elif step["modeOfTransport"] == "bicycling":
            # Estimate calories burned (approx 30 kcal per km)
            calories = int((leg_distance / 1000) * 30)
            step["calories"] = calories
        else:
            step["calories"] = None

        if step["modeOfTransport"] == "driving":
            # Estimate gas used (approx 8 liters per 100 km)
            gas_used = (leg_distance / 1000) * 8 / 100  # liters
            step["gasUsed"] = f"{gas_used:.2f} liters"
        else:
            step["gasUsed"] = None

        # Assume totalCost is not applicable unless specified
        step["totalCost"] = None

        # Update nameOfTransport if mode is transit
        if step["modeOfTransport"] == "transit":
            # Extract transit details
            transit_details = first_leg.get("transit_details", {})
            line = transit_details.get("line", {})
            vehicle = line.get("vehicle", {})
            step["nameOfTransport"] = line.get("short_name") or line.get("name") or vehicle.get("name", "")
        else:
            step["nameOfTransport"] = ""

        updated_steps.append(step)

    # Update route_info with total distance and time
    route_info["totalTime"] = int(total_duration / 60)  # in minutes
    route_info["distance"] = f"{total_distance / 1000:.2f} km"

    # Recalculate efficiency, effectiveness, and health if needed
    # For simplicity, we'll leave these as is unless specific calculations are required

    # Update the route plan
    route_plan["route1Info"] = route_info
    route_plan["route1"] = updated_steps

    return json.dumps(route_plan)


# def update_route_with_directions(route_plan):
    endpoint = 'https://maps.googleapis.com/maps/api/directions/json'

    route_info = route_plan.get('route1Info', {})
    route_steps = route_plan.get('route1', [])

    total_distance = 0  # in meters
    total_duration = 0  # in seconds

    updated
[truncated — 2931 more characters]
```