Function bodies 217 total
F1Agent.__init__ method · python · L44-L76 (33 LOC)packages/pitlane-agent/src/pitlane_agent/agent.py
def __init__(
self,
workspace_id: str | None = None,
workspace_dir: Path | None = None,
enable_tracing: bool | None = None,
inject_temporal_context: bool = True,
):
"""Initialize the F1 agent.
Args:
workspace_id: Workspace identifier. Auto-generated if None.
workspace_dir: Explicit workspace path. Derived from workspace_id if None.
enable_tracing: Enable OpenTelemetry tracing. If None, uses PITLANE_TRACING_ENABLED env var.
inject_temporal_context: Enable temporal context in system prompt. Default True.
"""
self.workspace_id = workspace_id or generate_workspace_id()
self.workspace_dir = workspace_dir or get_workspace_path(self.workspace_id)
self.inject_temporal_context = inject_temporal_context
self._agent_session_id: str | None = None # Captured from Claude SDK
# Verify workspace exists or create it
if not self.workspF1Agent.chat method · python · L101-L180 (80 LOC)packages/pitlane-agent/src/pitlane_agent/agent.py
async def chat(self, message: str, resume_session_id: str | None = None) -> AsyncIterator[str]:
"""Process a chat message and yield response text chunks.
Args:
message: The user's question or message.
resume_session_id: Optional SDK session ID to resume a previous conversation.
Yields:
Text chunks from the assistant's response.
"""
import os
# Set workspace ID as environment variable so skills can access it
os.environ["PITLANE_WORKSPACE_ID"] = self.workspace_id
# Configure hooks for tracing
hooks = None
if tracing.is_tracing_enabled():
hooks = {
"PreToolUse": [HookMatcher(matcher=None, hooks=[tracing.pre_tool_use_hook])],
"PostToolUse": [HookMatcher(matcher=None, hooks=[tracing.post_tool_use_hook])],
}
# Create a wrapper for can_use_tool that has access to workspace context
workspace_dir = stF1Agent.chat_full method · python · L182-L195 (14 LOC)packages/pitlane-agent/src/pitlane_agent/agent.py
async def chat_full(self, message: str, resume_session_id: str | None = None) -> str:
"""Process a chat message and return the full response.
Args:
message: The user's question or message.
resume_session_id: Optional SDK session ID to resume a previous conversation.
Returns:
The complete response text.
"""
parts = []
async for chunk in self.chat(message, resume_session_id=resume_session_id):
parts.append(chunk)
return "\n".join(parts) if parts else ""validate_mutually_exclusive function · python · L31-L45 (15 LOC)packages/pitlane-agent/src/pitlane_agent/cli_analyze.py
def validate_mutually_exclusive(ctx, param, value):
"""Validate that --drivers and --top-n are mutually exclusive."""
# Get the other parameter's value from context
if param.name == "drivers":
other_value = ctx.params.get("top_n")
elif param.name == "top_n":
other_value = ctx.params.get("drivers")
else:
return value
# Check if both are provided
if value and other_value:
raise click.BadParameter("Cannot specify both --drivers and --top-n options", ctx=ctx, param=param)
return valuelap_times function · python · L67-L100 (34 LOC)packages/pitlane-agent/src/pitlane_agent/cli_analyze.py
def lap_times(
workspace_id: str,
year: int,
gp: str | None,
session: str | None,
test_number: int | None,
session_number: int | None,
drivers: tuple[str, ...],
):
"""Generate lap times chart for specified drivers."""
validate_session_or_test(gp, session, test_number, session_number)
if not workspace_exists(workspace_id):
click.echo(json.dumps({"error": f"Workspace does not exist for workspace ID: {workspace_id}"}), err=True)
sys.exit(1)
workspace_path = get_workspace_path(workspace_id)
try:
result = generate_lap_times_chart(
year=year,
gp=gp,
session_type=session,
drivers=list(drivers),
workspace_dir=workspace_path,
test_number=test_number,
session_number=session_number,
)
result["workspace_id"] = workspace_id
click.echo(json.dumps(result, indent=2))
except Exception as e:
click.echo(json.dumlap_times_distribution function · python · L116-L150 (35 LOC)packages/pitlane-agent/src/pitlane_agent/cli_analyze.py
def lap_times_distribution(
workspace_id: str,
year: int,
gp: str | None,
session: str | None,
test_number: int | None,
session_number: int | None,
drivers: tuple[str, ...],
):
"""Generate lap times distribution chart showing statistical spread."""
validate_session_or_test(gp, session, test_number, session_number)
if not workspace_exists(workspace_id):
click.echo(json.dumps({"error": f"Workspace does not exist for workspace ID: {workspace_id}"}), err=True)
sys.exit(1)
workspace_path = get_workspace_path(workspace_id)
try:
drivers_list = list(drivers) if drivers else None
result = generate_lap_times_distribution_chart(
year=year,
gp=gp,
session_type=session,
drivers=drivers_list,
workspace_dir=workspace_path,
test_number=test_number,
session_number=session_number,
)
result["workspace_id"] = workspace_id
tyre_strategy function · python · L165-L199 (35 LOC)packages/pitlane-agent/src/pitlane_agent/cli_analyze.py
def tyre_strategy(
workspace_id: str,
year: int,
gp: str | None,
session: str | None,
test_number: int | None,
session_number: int | None,
):
"""Generate tyre strategy visualization for a race."""
# Default session to "R" when only --gp is provided (backwards compat)
if gp is not None and session is None and test_number is None:
session = "R"
validate_session_or_test(gp, session, test_number, session_number)
if not workspace_exists(workspace_id):
click.echo(json.dumps({"error": f"Workspace does not exist for workspace ID: {workspace_id}"}), err=True)
sys.exit(1)
workspace_path = get_workspace_path(workspace_id)
try:
result = generate_tyre_strategy_chart(
year=year,
gp=gp,
session_type=session,
workspace_dir=workspace_path,
test_number=test_number,
session_number=session_number,
)
result["workspace_id"] = workspaceRepobility's GitHub App fixes findings like these · https://github.com/apps/repobility-bot
speed_trace function · python · L221-L263 (43 LOC)packages/pitlane-agent/src/pitlane_agent/cli_analyze.py
def speed_trace(
workspace_id: str,
year: int,
gp: str | None,
session: str | None,
test_number: int | None,
session_number: int | None,
drivers: tuple[str, ...],
annotate_corners: bool,
):
"""Generate speed trace comparison for fastest laps of specified drivers."""
validate_session_or_test(gp, session, test_number, session_number)
if not workspace_exists(workspace_id):
click.echo(json.dumps({"error": f"Workspace does not exist for workspace ID: {workspace_id}"}), err=True)
sys.exit(1)
if len(drivers) < 2:
click.echo(json.dumps({"error": "Speed trace requires at least 2 drivers for comparison"}), err=True)
sys.exit(1)
if len(drivers) > 5:
click.echo(json.dumps({"error": "Speed trace supports maximum 5 drivers for readability"}), err=True)
sys.exit(1)
workspace_path = get_workspace_path(workspace_id)
try:
result = generate_speed_trace_chart(
year=year,
telemetry function · python · L285-L327 (43 LOC)packages/pitlane-agent/src/pitlane_agent/cli_analyze.py
def telemetry(
workspace_id: str,
year: int,
gp: str | None,
session: str | None,
test_number: int | None,
session_number: int | None,
drivers: tuple[str, ...],
annotate_corners: bool,
):
"""Generate interactive telemetry chart (speed, RPM, gear, throttle, brake) for fastest laps."""
validate_session_or_test(gp, session, test_number, session_number)
if not workspace_exists(workspace_id):
click.echo(json.dumps({"error": f"Workspace does not exist for workspace ID: {workspace_id}"}), err=True)
sys.exit(1)
if len(drivers) < 2:
click.echo(json.dumps({"error": "Telemetry requires at least 2 drivers for comparison"}), err=True)
sys.exit(1)
if len(drivers) > 5:
click.echo(json.dumps({"error": "Telemetry supports maximum 5 drivers for readability"}), err=True)
sys.exit(1)
workspace_path = get_workspace_path(workspace_id)
try:
result = generate_telemetry_chart(
yeaposition_changes function · python · L351-L387 (37 LOC)packages/pitlane-agent/src/pitlane_agent/cli_analyze.py
def position_changes(
workspace_id: str,
year: int,
gp: str | None,
session: str | None,
test_number: int | None,
session_number: int | None,
drivers: tuple[str, ...],
top_n: int | None,
):
"""Generate position changes chart showing driver positions throughout the race."""
validate_session_or_test(gp, session, test_number, session_number)
if not workspace_exists(workspace_id):
click.echo(json.dumps({"error": f"Workspace does not exist for workspace ID: {workspace_id}"}), err=True)
sys.exit(1)
workspace_path = get_workspace_path(workspace_id)
try:
drivers_list = list(drivers) if drivers else None
result = generate_position_changes_chart(
year=year,
gp=gp,
session_type=session,
drivers=drivers_list,
top_n=top_n,
workspace_dir=workspace_path,
test_number=test_number,
session_number=session_number,
)
track_map function · python · L397-L428 (32 LOC)packages/pitlane-agent/src/pitlane_agent/cli_analyze.py
def track_map(
workspace_id: str,
year: int,
gp: str | None,
session: str | None,
test_number: int | None,
session_number: int | None,
):
"""Generate track map with numbered corner labels."""
validate_session_or_test(gp, session, test_number, session_number)
if not workspace_exists(workspace_id):
click.echo(json.dumps({"error": f"Workspace does not exist for workspace ID: {workspace_id}"}), err=True)
sys.exit(1)
workspace_path = get_workspace_path(workspace_id)
try:
result = generate_track_map_chart(
year=year,
gp=gp,
session_type=session,
workspace_dir=workspace_path,
test_number=test_number,
session_number=session_number,
)
result["workspace_id"] = workspace_id
click.echo(json.dumps(result, indent=2))
except Exception as e:
click.echo(json.dumps({"error": str(e)}), err=True)
sys.exit(1)gear_shifts_map function · python · L444-L477 (34 LOC)packages/pitlane-agent/src/pitlane_agent/cli_analyze.py
def gear_shifts_map(
workspace_id: str,
year: int,
gp: str | None,
session: str | None,
test_number: int | None,
session_number: int | None,
drivers: tuple[str, ...],
):
"""Generate gear shift visualization on track map."""
validate_session_or_test(gp, session, test_number, session_number)
if not workspace_exists(workspace_id):
click.echo(json.dumps({"error": f"Workspace does not exist for workspace ID: {workspace_id}"}), err=True)
sys.exit(1)
workspace_path = get_workspace_path(workspace_id)
try:
result = generate_gear_shifts_map_chart(
year=year,
gp=gp,
session_type=session,
drivers=list(drivers),
workspace_dir=workspace_path,
test_number=test_number,
session_number=session_number,
)
result["workspace_id"] = workspace_id
click.echo(json.dumps(result, indent=2))
except Exception as e:
click.echampionship_possibilities function · python · L495-L523 (29 LOC)packages/pitlane-agent/src/pitlane_agent/cli_analyze.py
def championship_possibilities(workspace_id: str, year: int, championship: str, after_round: int | None):
"""Calculate who can still mathematically win the championship."""
# Verify workspace exists
if not workspace_exists(workspace_id):
click.echo(
json.dumps({"error": f"Workspace does not exist for workspace ID: {workspace_id}"}),
err=True,
)
sys.exit(1)
workspace_path = get_workspace_path(workspace_id)
try:
# Generate chart
result = generate_championship_possibilities_chart(
year=year,
championship=championship,
workspace_dir=workspace_path,
after_round=after_round,
)
# Add session info to result
result["workspace_id"] = workspace_id
click.echo(json.dumps(result, indent=2))
except Exception as e:
click.echo(json.dumps({"error": str(e)}), err=True)
sys.exit(1)multi_lap function · python · L553-L623 (71 LOC)packages/pitlane-agent/src/pitlane_agent/cli_analyze.py
def multi_lap(
workspace_id: str,
year: int,
gp: str | None,
session_type: str | None,
test_number: int | None,
session_number: int | None,
driver: str,
laps: tuple[str, ...],
annotate_corners: bool,
):
"""Compare multiple laps for a single driver within a session.
Each --lap value is either 'best' (fastest lap) or an integer lap number.
Useful for comparing a driver's Q1/Q3 attempts, or stint pace across a race.
Example (GP session):
pitlane analyze multi-lap --year 2024 --gp Monaco --session Q
--driver VER --lap best --lap 3
Example (testing session):
pitlane analyze multi-lap --year 2024 --test 1 --day 2
--driver VER --lap best --lap 3
"""
validate_session_or_test(gp, session_type, test_number, session_number)
if not workspace_exists(workspace_id):
click.echo(json.dumps({"error": f"Workspace does not exist for workspace ID: {workspace_id}"}), err=True)
sys.exit(1)
year_compare function · python · L657-L711 (55 LOC)packages/pitlane-agent/src/pitlane_agent/cli_analyze.py
def year_compare(
workspace_id: str,
gp: str | None,
session_type: str | None,
test_number: int | None,
session_number: int | None,
driver: str,
years: tuple[int, ...],
annotate_corners: bool,
):
"""Compare a driver's best lap at the same track across multiple seasons.
Useful for analysing the impact of regulation changes on lap time, braking,
speed profiles, and driving technique across eras.
Example (GP session):
pitlane analyze year-compare --gp Monza --session Q
--driver VER --years 2022 --years 2024
Example (testing session):
pitlane analyze year-compare --test 1 --day 2
--driver VER --years 2022 --years 2024
"""
validate_session_or_test(gp, session_type, test_number, session_number)
if not workspace_exists(workspace_id):
click.echo(json.dumps({"error": f"Workspace does not exist for workspace ID: {workspace_id}"}), err=True)
sys.exit(1)
if len(years) < 2:
cIf a scraper extracted this row, it came from Repobility (https://repobility.com)
driver_laps function · python · L728-L769 (42 LOC)packages/pitlane-agent/src/pitlane_agent/cli_analyze.py
def driver_laps(
workspace_id: str,
year: int,
gp: str | None,
session_type: str | None,
test_number: int | None,
session_number: int | None,
driver: str,
):
"""Fetch per-lap data for a single driver — no chart generated.
Returns structured JSON with lap times, tyre compounds, stint numbers, pit
events, position, and whether each lap is race-representative (is_accurate).
Use this before multi-lap to identify which lap numbers are worth comparing.
Example (GP session):
pitlane analyze driver-laps --year 2024 --gp Monaco --session R --driver VER
Example (testing session):
pitlane analyze driver-laps --year 2024 --test 1 --day 2 --driver VER
"""
validate_session_or_test(gp, session_type, test_number, session_number)
if not workspace_exists(workspace_id):
click.echo(json.dumps({"error": f"Workspace does not exist for workspace ID: {workspace_id}"}), err=True)
sys.exit(1)
try:
resultseason_summary function · python · L782-L812 (31 LOC)packages/pitlane-agent/src/pitlane_agent/cli_analyze.py
def season_summary(workspace_id: str, year: int, summary_type: str):
"""Generate season summary visualization with per-round championship points.
Loads results for each completed race (and sprint) via FastF1 and produces
an interactive two-panel Plotly heatmap saved as an HTML file.
Example:
pitlane analyze season-summary --workspace-id $PITLANE_WORKSPACE_ID --year 2024
pitlane analyze season-summary --workspace-id $PITLANE_WORKSPACE_ID --year 2024 --type constructors
"""
if not workspace_exists(workspace_id):
click.echo(
json.dumps({"error": f"Workspace does not exist for workspace ID: {workspace_id}"}),
err=True,
)
sys.exit(1)
workspace_path = get_workspace_path(workspace_id)
try:
result = generate_season_summary_chart(
year=year,
summary_type=summary_type,
workspace_dir=workspace_path,
)
result["workspace_id"] = workspace_id
_validate_standings_request function · python · L28-L58 (31 LOC)packages/pitlane-agent/src/pitlane_agent/cli_fetch.py
def _validate_standings_request(workspace_id: str, year: int) -> Path:
"""Validate workspace and year for standings fetch commands.
Args:
workspace_id: Workspace ID
year: Championship year
Returns:
Path to workspace directory
Raises:
SystemExit: If validation fails
"""
# Verify workspace exists
if not workspace_exists(workspace_id):
click.echo(
json.dumps({"error": f"Workspace does not exist for workspace ID: {workspace_id}"}),
err=True,
)
sys.exit(1)
# Validate year
current_year = datetime.now().year
if year < MIN_F1_YEAR or year > current_year + 2:
click.echo(
json.dumps({"error": f"Year must be between {MIN_F1_YEAR} and {current_year + 2}"}),
err=True,
)
sys.exit(1)
return get_workspace_path(workspace_id)session_info function · python · L81-L136 (56 LOC)packages/pitlane-agent/src/pitlane_agent/cli_fetch.py
def session_info(
workspace_id: str,
year: int,
gp: str | None,
session: str | None,
test_number: int | None,
session_number: int | None,
):
"""Fetch session information and store in workspace."""
validate_session_or_test(gp, session, test_number, session_number)
# Verify workspace exists
if not workspace_exists(workspace_id):
click.echo(
json.dumps({"error": f"Workspace does not exist for workspace ID: {workspace_id}"}),
err=True,
)
sys.exit(1)
workspace_path = get_workspace_path(workspace_id)
try:
# Fetch session info
info = get_session_info(
year,
gp=gp,
session_type=session,
test_number=test_number,
session_number=session_number,
)
# Write to workspace
output_file = build_data_path(
workspace_path,
"session_info",
year=year,
gp=gp,
driver_info function · python · L165-L217 (53 LOC)packages/pitlane-agent/src/pitlane_agent/cli_fetch.py
def driver_info(
workspace_id: str,
driver_code: str | None,
season: int | None,
limit: int,
offset: int,
):
"""Fetch driver information and store in workspace."""
# Verify workspace exists
if not workspace_exists(workspace_id):
click.echo(
json.dumps({"error": f"Workspace does not exist for workspace ID: {workspace_id}"}),
err=True,
)
sys.exit(1)
# Validate season if provided
if season is not None:
current_year = datetime.now().year
if season < 1950 or season > current_year + 2:
click.echo(
json.dumps({"error": f"Season must be between 1950 and {current_year + 2}"}),
err=True,
)
sys.exit(1)
workspace_path = get_workspace_path(workspace_id)
try:
# Fetch driver info
info = get_driver_info(
driver_code=driver_code,
season=season,
limit=limit,
ofevent_schedule function · python · L246-L297 (52 LOC)packages/pitlane-agent/src/pitlane_agent/cli_fetch.py
def event_schedule(
workspace_id: str,
year: int,
round_number: int | None,
country: str | None,
include_testing: bool,
):
"""Fetch event schedule and store in workspace."""
# Verify workspace exists
if not workspace_exists(workspace_id):
click.echo(
json.dumps({"error": f"Workspace does not exist for workspace ID: {workspace_id}"}),
err=True,
)
sys.exit(1)
# Validate year input
current_year = datetime.now().year
if year < 1950 or year > current_year + 2:
click.echo(
json.dumps({"error": f"Year must be between 1950 and {current_year + 2}"}),
err=True,
)
sys.exit(1)
workspace_path = get_workspace_path(workspace_id)
try:
# Fetch schedule
schedule = get_event_schedule(
year,
round_number=round_number,
country=country,
include_testing=include_testing,
)
# Write driver_standings function · python · L310-L336 (27 LOC)packages/pitlane-agent/src/pitlane_agent/cli_fetch.py
def driver_standings(workspace_id: str, year: int, round_number: int | None):
"""Fetch driver championship standings and store in workspace."""
# Validate request
workspace_path = _validate_standings_request(workspace_id, year)
try:
# Fetch standings
standings = get_driver_standings(year, round_number)
# Write to workspace
output_file = build_data_path(workspace_path, "driver_standings", year=year, round_number=round_number)
with open(output_file, "w") as f:
json.dump(standings, f, indent=2)
# Return result
result = {
"data_file": str(output_file),
"year": year,
"round": standings["round"],
"total_standings": standings["total_standings"],
}
click.echo(json.dumps(result, indent=2))
except Exception as e:
click.echo(json.dumps({"error": str(e)}), err=True)
sys.exit(1)constructor_standings function · python · L349-L375 (27 LOC)packages/pitlane-agent/src/pitlane_agent/cli_fetch.py
def constructor_standings(workspace_id: str, year: int, round_number: int | None):
"""Fetch constructor championship standings and store in workspace."""
# Validate request
workspace_path = _validate_standings_request(workspace_id, year)
try:
# Fetch standings
standings = get_constructor_standings(year, round_number)
# Write to workspace
output_file = build_data_path(workspace_path, "constructor_standings", year=year, round_number=round_number)
with open(output_file, "w") as f:
json.dump(standings, f, indent=2)
# Return result
result = {
"data_file": str(output_file),
"year": year,
"round": standings["round"],
"total_standings": standings["total_standings"],
}
click.echo(json.dumps(result, indent=2))
except Exception as e:
click.echo(json.dumps({"error": str(e)}), err=True)
sys.exit(1)Want fix-PRs on findings? Install Repobility's GitHub App · github.com/apps/repobility-bot
race_control function · python · L434-L506 (73 LOC)packages/pitlane-agent/src/pitlane_agent/cli_fetch.py
def race_control(
workspace_id: str,
year: int,
gp: str | None,
session: str | None,
test_number: int | None,
session_number: int | None,
detail: str,
category: str | None,
flag_type: str | None,
driver: str | None,
lap_start: int | None,
lap_end: int | None,
sector: int | None,
):
"""Fetch race control messages and store in workspace."""
validate_session_or_test(gp, session, test_number, session_number)
# Verify workspace exists
if not workspace_exists(workspace_id):
click.echo(
json.dumps({"error": f"Workspace does not exist for workspace ID: {workspace_id}"}),
err=True,
)
sys.exit(1)
workspace_path = get_workspace_path(workspace_id)
try:
# Fetch race control messages
messages = get_race_control_messages(
year=year,
gp=gp,
session_type=session,
detail=detail,
category=category,
season_summary function · python · L512-L534 (23 LOC)packages/pitlane-agent/src/pitlane_agent/cli_fetch.py
def season_summary(workspace_id: str, year: int):
"""Fetch season summary with races ranked by wildness score."""
workspace_path = _validate_standings_request(workspace_id, year)
try:
summary = get_season_summary(year)
# Write to workspace
output_file = build_data_path(workspace_path, "season_summary", year=year)
with open(output_file, "w") as f:
json.dump(summary, f, indent=2)
# Return result
result = {
"data_file": str(output_file),
"year": year,
"total_races": summary["total_races"],
}
click.echo(json.dumps(result, indent=2))
except Exception as e:
click.echo(json.dumps({"error": str(e)}), err=True)
sys.exit(1)pitlane function · python · L32-L37 (6 LOC)packages/pitlane-agent/src/pitlane_agent/cli.py
def pitlane():
"""PitLane AI - F1 data analysis tools powered by FastF1 and Claude."""
# Suppress logging from underlying libraries
logging.getLogger("fastf1").setLevel(logging.WARNING)
# Suppress deprecation warnings from FastF1
warnings.filterwarnings("ignore", category=FutureWarning, module="fastf1")create function · python · L49-L59 (11 LOC)packages/pitlane-agent/src/pitlane_agent/cli.py
def create(workspace_id: str | None, description: str | None):
"""Create a new workspace."""
try:
result = create_workspace(workspace_id=workspace_id, description=description)
click.echo(json.dumps(result, indent=2))
except ValueError as e:
click.echo(json.dumps({"error": str(e)}), err=True)
sys.exit(1)
except Exception as e:
click.echo(json.dumps({"error": str(e)}), err=True)
sys.exit(1)list function · python · L64-L75 (12 LOC)packages/pitlane-agent/src/pitlane_agent/cli.py
def list(show_all: bool):
"""List workspaces."""
try:
workspaces = list_workspaces(show_all=show_all)
result = {
"total": len(workspaces),
"workspaces": workspaces,
}
click.echo(json.dumps(result, indent=2))
except Exception as e:
click.echo(json.dumps({"error": str(e)}), err=True)
sys.exit(1)info function · python · L80-L90 (11 LOC)packages/pitlane-agent/src/pitlane_agent/cli.py
def info(workspace_id: str):
"""Show workspace information."""
try:
info_data = get_workspace_info(workspace_id)
click.echo(json.dumps(info_data, indent=2))
except ValueError as e:
click.echo(json.dumps({"error": str(e)}), err=True)
sys.exit(1)
except Exception as e:
click.echo(json.dumps({"error": str(e)}), err=True)
sys.exit(1)clean function · python · L102-L124 (23 LOC)packages/pitlane-agent/src/pitlane_agent/cli.py
def clean(older_than: int | None, all_workspaces: bool, yes: bool):
"""Clean old workspaces."""
if not all_workspaces and older_than is None:
click.echo(
json.dumps({"error": "Must specify either --older-than or --all"}),
err=True,
)
sys.exit(1)
# Confirmation prompt
if not yes:
message = "Remove ALL workspaces?" if all_workspaces else f"Remove workspaces older than {older_than} days?"
if not click.confirm(message):
click.echo(json.dumps({"message": "Cancelled"}))
return
try:
result = clean_workspaces(older_than_days=older_than, remove_all=all_workspaces)
click.echo(json.dumps(result, indent=2))
except Exception as e:
click.echo(json.dumps({"error": str(e)}), err=True)
sys.exit(1)remove function · python · L130-L149 (20 LOC)packages/pitlane-agent/src/pitlane_agent/cli.py
def remove(workspace_id: str, yes: bool):
"""Remove a specific workspace."""
if not workspace_exists(workspace_id):
click.echo(
json.dumps({"error": f"Workspace does not exist for workspace ID: {workspace_id}"}),
err=True,
)
sys.exit(1)
# Confirmation prompt
if not yes and not click.confirm(f"Remove workspace {workspace_id}?"):
click.echo(json.dumps({"message": "Cancelled"}))
return
try:
remove_workspace(workspace_id)
click.echo(json.dumps({"message": f"Workspace {workspace_id} removed successfully"}))
except Exception as e:
click.echo(json.dumps({"error": str(e)}), err=True)
sys.exit(1)Source: Repobility analyzer · https://repobility.com
temporal_context function · python · L166-L191 (26 LOC)packages/pitlane-agent/src/pitlane_agent/cli.py
def temporal_context(format: str, refresh: bool, verbosity: str):
"""Show current F1 temporal context.
This command displays the current state of the F1 season including:
- Current season year and phase (pre/in/post/off-season)
- Active race weekend (if any)
- Current or recent sessions
- Next upcoming race
- Last completed race
"""
try:
context = get_temporal_context(force_refresh=refresh)
if format == "json":
click.echo(json.dumps(context.to_dict(), indent=2, default=str))
elif format == "prompt":
prompt_text = format_for_system_prompt(context, verbosity=verbosity)
click.echo(prompt_text)
else:
# Human-readable text format
text_output = format_as_text(context)
click.echo(text_output)
except Exception as e:
click.echo(json.dumps({"error": str(e)}), err=True)
sys.exit(1)_count_remaining_races function · python · L33-L63 (31 LOC)packages/pitlane-agent/src/pitlane_agent/commands/analyze/championship_possibilities.py
def _count_remaining_races(year: int, current_round: int) -> tuple[int, int]:
"""Count remaining races and sprint races in the season.
Args:
year: Championship year
current_round: Current round number
Returns:
Tuple of (remaining_races, remaining_sprints)
"""
schedule_data = get_event_schedule(year, include_testing=False)
events = schedule_data["events"]
remaining_races = 0
remaining_sprints = 0
for event in events:
round_num = event["round"]
# Only count races after the current round
if round_num > current_round:
# Check if it's a race weekend (has Race session)
has_race = any(session["name"] == "Race" for session in event.get("sessions", []))
if has_race:
remaining_races += 1
# Check if it's a sprint weekend (has Sprint session)
has_sprint = any(session["name"] == "Sprint" for session in event.get("sessions", []))
_calculate_max_points_available function · python · L66-L85 (20 LOC)packages/pitlane-agent/src/pitlane_agent/commands/analyze/championship_possibilities.py
def _calculate_max_points_available(remaining_races: int, remaining_sprints: int, year: int) -> int:
"""Calculate maximum points available for remaining races.
Args:
remaining_races: Number of remaining races
remaining_sprints: Number of remaining sprint races
year: Championship year (affects whether fastest lap point is included)
Returns:
Maximum points available
"""
# Fastest lap point was removed starting in 2025
if year >= FASTEST_LAP_POINT_REMOVED_YEAR:
max_race_points = MAX_RACE_POINTS_PER_WEEKEND_NO_FASTEST_LAP * remaining_races
else:
max_race_points = MAX_RACE_POINTS_PER_WEEKEND_WITH_FASTEST_LAP * remaining_races
max_sprint_points = MAX_SPRINT_POINTS * remaining_sprints
return max_race_points + max_sprint_points_calculate_championship_scenarios function · python · L88-L156 (69 LOC)packages/pitlane-agent/src/pitlane_agent/commands/analyze/championship_possibilities.py
def _calculate_championship_scenarios(
standings: list[dict],
max_points_available: int,
championship_type: str,
) -> tuple[list[dict], dict]:
"""Calculate championship scenarios for each competitor.
Args:
standings: List of standings dictionaries
max_points_available: Maximum points available in remaining races
championship_type: "drivers" or "constructors"
Returns:
Tuple of (competitor_stats, leader_info)
"""
if not standings:
return [], {}
# Ensure standings are sorted by points descending (API should provide sorted data,
# but we verify to ensure correct leader identification and points calculations)
standings = sorted(standings, key=lambda x: x["points"], reverse=True)
leader = standings[0]
leader_points = leader["points"]
# Get name field based on championship type
name_field = "full_name" if championship_type == "drivers" else "constructor_name"
leader_info = {
"_generate_championship_chart function · python · L159-L238 (80 LOC)packages/pitlane-agent/src/pitlane_agent/commands/analyze/championship_possibilities.py
def _generate_championship_chart(
competitor_stats: list[dict],
year: int,
championship_type: str,
ax: plt.Axes,
after_round: int | None = None,
) -> None:
"""Generate horizontal bar chart for championship possibilities.
Args:
competitor_stats: List of competitor statistics
year: Championship year
championship_type: "drivers" or "constructors"
ax: Matplotlib axes to plot on
after_round: Optional round number for historical analysis
"""
# Sort by current points for display
competitor_stats = sorted(competitor_stats, key=lambda x: x["current_points"], reverse=False)
names = [c["name"] for c in competitor_stats]
current_points = [c["current_points"] for c in competitor_stats]
max_points = [c["max_possible_points"] for c in competitor_stats]
can_win = [c["can_win"] for c in competitor_stats]
y_positions = np.arange(len(names))
# Plot current points (filled bars)
for i, (y_pos, cugenerate_championship_possibilities_chart function · python · L241-L328 (88 LOC)packages/pitlane-agent/src/pitlane_agent/commands/analyze/championship_possibilities.py
def generate_championship_possibilities_chart(
year: int,
championship: str = "drivers",
workspace_dir: Path | None = None,
after_round: int | None = None,
) -> dict:
"""Generate championship possibilities visualization.
Args:
year: Season year
championship: Championship type - "drivers" or "constructors"
workspace_dir: Workspace directory for outputs
after_round: Optional round number to analyze historical "what if" scenarios
Returns:
Dictionary with chart metadata and championship statistics
"""
championship = championship.lower()
if championship not in ["drivers", "constructors"]:
raise ValueError(f"Invalid championship type: {championship}. Must be 'drivers' or 'constructors'.")
# Validate after_round parameter
if after_round is not None and after_round <= 0:
raise ValueError(f"after_round must be a positive integer, got: {after_round}")
# Get standings (current or histor_prepare_lap_entry function · python · L41-L88 (48 LOC)packages/pitlane-agent/src/pitlane_agent/commands/analyze/driver_lap_compare.py
def _prepare_lap_entry(lap, label: str, key: str, color: str) -> tuple[dict, dict]:
"""Build rendering entry and stats dict for a single lap.
Returns:
(entry, stats) where entry is consumed by _render_telemetry_chart and
stats is returned to the caller for downstream use.
Raises:
ValueError: If car data is unavailable for the lap.
"""
tel = lap.get_car_data().add_distance()
if tel.empty:
raise ValueError(f"No car telemetry data available for lap labelled '{label}'")
tel["Brake"] = tel["Brake"].astype(int)
analysis = analyze_telemetry(tel)
tel["SuperClip"] = 0
for zone in analysis["super_clipping_zones"]:
mask = (tel["Distance"] >= zone["start_distance"]) & (tel["Distance"] <= zone["end_distance"])
tel.loc[mask, "SuperClip"] = 1
entry = {
"key": key,
"label": label,
"telemetry": tel,
"color": color,
"style": _SOLID_STYLE,
}
stats = {
generate_multi_lap_chart function · python · L91-L184 (94 LOC)packages/pitlane-agent/src/pitlane_agent/commands/analyze/driver_lap_compare.py
def generate_multi_lap_chart(
year: int,
gp: str | None,
session_type: str | None,
driver: str,
lap_specs: list[str | int],
workspace_dir: Path,
annotate_corners: bool = False,
test_number: int | None = None,
session_number: int | None = None,
) -> dict:
"""Compare multiple laps for a single driver within a session.
Args:
year: Season year
gp: Grand Prix name (None when using testing session)
session_type: Session identifier (Q, R, FP1, FP2, FP3, S, SQ; None when using testing session)
driver: Driver abbreviation (e.g. "VER")
lap_specs: List of lap specifiers — "best" for fastest lap or an integer lap number.
Must have between 2 and 6 entries.
workspace_dir: Workspace directory for chart output
annotate_corners: Whether to add corner markers
test_number: Testing event number (mutually exclusive with gp/session_type)
session_number: Day/session within tRepobility's GitHub App fixes findings like these · https://github.com/apps/repobility-bot
generate_year_compare_chart function · python · L187-L288 (102 LOC)packages/pitlane-agent/src/pitlane_agent/commands/analyze/driver_lap_compare.py
def generate_year_compare_chart(
gp: str | None,
session_type: str | None,
driver: str,
years: list[int],
workspace_dir: Path,
annotate_corners: bool = False,
test_number: int | None = None,
session_number: int | None = None,
) -> dict:
"""Compare a driver's best lap at the same track across multiple seasons.
Loads each session independently and picks the fastest lap for the driver.
Circuit info is taken from the first session (same track layout assumed).
Useful for analysing how regulation changes affect lap times, braking points,
speed profiles, and driving technique over multiple seasons.
Args:
gp: Grand Prix name (same track must exist in all specified years; None for testing sessions)
session_type: Session identifier (Q, R, FP1, FP2, FP3, S, SQ; None for testing sessions)
driver: Driver abbreviation (e.g. "HAM")
years: List of season years to compare. Must have between 2 and 6 entries.
_safe_int function · python · L17-L24 (8 LOC)packages/pitlane-agent/src/pitlane_agent/commands/analyze/driver_lap_list.py
def _safe_int(value) -> int | None:
"""Convert to int, returning None for NaN/NaT."""
try:
if pd.isna(value):
return None
return int(value)
except (TypeError, ValueError):
return None_safe_float function · python · L27-L34 (8 LOC)packages/pitlane-agent/src/pitlane_agent/commands/analyze/driver_lap_list.py
def _safe_float(value) -> float | None:
"""Convert to float, returning None for NaN/NaT."""
try:
if pd.isna(value):
return None
return float(value)
except (TypeError, ValueError):
return None_compute_stint_numbers function · python · L37-L63 (27 LOC)packages/pitlane-agent/src/pitlane_agent/commands/analyze/driver_lap_list.py
def _compute_stint_numbers(driver_laps: pd.DataFrame) -> list[int | None]:
"""Compute stint numbers from compound changes when FastF1 Stint column is absent.
A new stint begins whenever the compound changes or a pit-out lap is detected.
"""
stints: list[int | None] = []
current_stint = 1
prev_compound = None
for _, lap in driver_laps.iterrows():
compound = lap.get("Compound")
pit_out = lap.get("PitOutTime")
is_pit_out = not pd.isna(pit_out) if pit_out is not None else False
compound_val = compound if (compound is not None and not pd.isna(compound)) else None
if prev_compound is not None and compound_val != prev_compound:
current_stint += 1
elif is_pit_out and stints:
# Pit-out on same compound (e.g. minor repair) counts as new stint
current_stint += 1
stints.append(current_stint)
if compound_val is not None:
prev_compound = compound_val
rgenerate_driver_lap_list function · python · L66-L195 (130 LOC)packages/pitlane-agent/src/pitlane_agent/commands/analyze/driver_lap_list.py
def generate_driver_lap_list(
year: int,
gp: str | None,
session_type: str | None,
driver: str,
test_number: int | None = None,
session_number: int | None = None,
) -> dict:
"""Return structured per-lap data for a single driver.
Does not load telemetry — uses session.laps only, making this fast.
Args:
year: Season year
gp: Grand Prix name (None when using testing session)
session_type: Session identifier (Q, R, FP1, FP2, FP3, S, SQ; None for testing)
driver: Driver abbreviation (e.g. "VER")
test_number: Testing event number (mutually exclusive with gp/session_type)
session_number: Day/session within testing event
Returns:
Dictionary with per-lap data, pit stop summary, and session metadata.
Raises:
ValueError: If the driver has no laps in the session.
"""
session = load_session_or_testing(
year, gp, session_type, telemetry=False, test_number=test_number, sessi_rotate function · python · L31-L42 (12 LOC)packages/pitlane-agent/src/pitlane_agent/commands/analyze/gear_shifts_map.py
def _rotate(xy: np.ndarray, *, angle: float) -> np.ndarray:
"""Rotate 2D coordinates by the given angle in radians.
Args:
xy: Array-like of shape (2,) or (N, 2) with X/Y coordinates.
angle: Rotation angle in radians.
Returns:
Rotated coordinates with the same shape as input.
"""
rot_mat = np.array([[np.cos(angle), np.sin(angle)], [-np.sin(angle), np.cos(angle)]])
return np.matmul(xy, rot_mat)_format_lap_time function · python · L45-L57 (13 LOC)packages/pitlane-agent/src/pitlane_agent/commands/analyze/gear_shifts_map.py
def _format_lap_time(lap_time: pd.Timedelta) -> str:
"""Format lap time as MM:SS.mmm.
Args:
lap_time: Pandas Timedelta object representing lap time.
Returns:
Formatted lap time string (e.g., "1:23.456").
"""
total_seconds = lap_time.total_seconds()
minutes = int(total_seconds // 60)
seconds = total_seconds % 60
return f"{minutes}:{seconds:06.3f}"_calculate_gear_statistics function · python · L60-L80 (21 LOC)packages/pitlane-agent/src/pitlane_agent/commands/analyze/gear_shifts_map.py
def _calculate_gear_statistics(telemetry: pd.DataFrame) -> dict:
"""Calculate gear usage statistics from telemetry.
Args:
telemetry: DataFrame with nGear column containing gear values.
Returns:
Dictionary with gear distribution, most used gear, highest gear, and total gear changes.
"""
gear_counts = telemetry["nGear"].value_counts()
total_points = len(telemetry)
return {
"gear_distribution": {
int(gear): {"count": int(count), "percentage": round(float(count / total_points * 100), 1)}
for gear, count in gear_counts.items()
},
"most_used_gear": int(gear_counts.idxmax()),
"highest_gear": int(telemetry["nGear"].max()),
"total_gear_changes": int((telemetry["nGear"].diff() != 0).sum()),
}If a scraper extracted this row, it came from Repobility (https://repobility.com)
generate_gear_shifts_map_chart function · python · L83-L274 (192 LOC)packages/pitlane-agent/src/pitlane_agent/commands/analyze/gear_shifts_map.py
def generate_gear_shifts_map_chart(
year: int,
gp: str,
session_type: str,
drivers: list[str],
workspace_dir: Path,
test_number: int | None = None,
session_number: int | None = None,
) -> dict:
"""Generate gear shift visualization on track map for a single driver.
Args:
year: Season year
gp: Grand Prix name (ignored for testing sessions)
session_type: Session identifier (R, Q, FP1, etc., ignored for testing)
drivers: List containing exactly 1 driver abbreviation
workspace_dir: Workspace directory for outputs and cache
test_number: Testing event number (e.g., 1 or 2)
session_number: Session within testing event (e.g., 1, 2, or 3)
Returns:
Dictionary with chart metadata and gear statistics
Raises:
ValueError: If drivers list does not contain exactly 1 driver
ValueError: If telemetry data is unavailable
"""
# Validate driver count (exactly 1 driver requiregenerate_lap_times_distribution_chart function · python · L17-L185 (169 LOC)packages/pitlane-agent/src/pitlane_agent/commands/analyze/lap_times_distribution.py
def generate_lap_times_distribution_chart(
year: int,
gp: str,
session_type: str,
drivers: list[str] | None,
workspace_dir: Path,
test_number: int | None = None,
session_number: int | None = None,
) -> dict:
"""Generate a lap times distribution plot using violin and swarm plots.
Args:
year: Season year
gp: Grand Prix name (ignored for testing sessions)
session_type: Session identifier (ignored for testing sessions)
drivers: List of driver abbreviations to include, or None for top 10 finishers
workspace_dir: Workspace directory for outputs and cache
test_number: Testing event number (e.g., 1 or 2)
session_number: Session within testing event (e.g., 1, 2, or 3)
Returns:
Dictionary with chart metadata and statistics
"""
# Build output path (handle None drivers case specially)
if drivers is None:
output_path = build_chart_path(
workspace_dir,
generate_lap_times_chart function · python · L16-L121 (106 LOC)packages/pitlane-agent/src/pitlane_agent/commands/analyze/lap_times.py
def generate_lap_times_chart(
year: int,
gp: str,
session_type: str,
drivers: list[str],
workspace_dir: Path,
test_number: int | None = None,
session_number: int | None = None,
) -> dict:
"""Generate a lap times scatter plot.
Args:
year: Season year
gp: Grand Prix name (ignored for testing sessions)
session_type: Session identifier (ignored for testing sessions)
drivers: List of driver abbreviations to include
workspace_dir: Workspace directory for outputs and cache
test_number: Testing event number (e.g., 1 or 2)
session_number: Session within testing event (e.g., 1, 2, or 3)
Returns:
Dictionary with chart metadata and statistics
"""
# Build output path
output_path = build_chart_path(
workspace_dir,
"lap_times",
year,
gp,
session_type,
drivers,
test_number=test_number,
session_number=session_number,
)
page 1 / 5next ›