Skip to content
Merged
11 changes: 9 additions & 2 deletions eval_protocol/adapters/fireworks_tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import os

from eval_protocol.models import EvaluationRow, InputMetadata, ExecutionMetadata, Message
from eval_protocol.common_utils import get_user_agent
from .base import BaseAdapter
from .utils import extract_messages_from_data

Expand Down Expand Up @@ -273,7 +274,10 @@ def search_logs(self, tags: List[str], limit: int = 100, hours_back: int = 24) -
if not tags:
raise ValueError("At least one tag is required to fetch logs")

headers = {"Authorization": f"Bearer {os.environ.get('FIREWORKS_API_KEY')}"}
headers = {
"Authorization": f"Bearer {os.environ.get('FIREWORKS_API_KEY')}",
"User-Agent": get_user_agent(),
}
params: Dict[str, Any] = {"tags": tags, "limit": limit, "hours_back": hours_back, "program": "eval_protocol"}

# Try /logs first, fall back to /v1/logs if not found
Expand Down Expand Up @@ -398,7 +402,10 @@ def get_evaluation_rows(
else:
url = f"{self.base_url}/v1/traces/pointwise"

headers = {"Authorization": f"Bearer {os.environ.get('FIREWORKS_API_KEY')}"}
headers = {
"Authorization": f"Bearer {os.environ.get('FIREWORKS_API_KEY')}",
"User-Agent": get_user_agent(),
}

result = None
try:
Expand Down
4 changes: 3 additions & 1 deletion eval_protocol/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

import requests

from .common_utils import get_user_agent

logger = logging.getLogger(__name__)

# Default locations (used for tests and as fallback). Actual resolution is dynamic via _get_auth_ini_file().
Expand Down Expand Up @@ -243,7 +245,7 @@ def verify_api_key_and_get_account_id(
return None
resolved_base = api_base or get_fireworks_api_base()
url = f"{resolved_base.rstrip('/')}/verifyApiKey"
headers = {"Authorization": f"Bearer {resolved_key}"}
headers = {"Authorization": f"Bearer {resolved_key}", "User-Agent": get_user_agent()}
resp = requests.get(url, headers=headers, timeout=10)
if resp.status_code != 200:
logger.debug("verifyApiKey returned status %s", resp.status_code)
Expand Down
16 changes: 16 additions & 0 deletions eval_protocol/common_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,22 @@
import requests


def get_user_agent() -> str:
"""
Returns the user-agent string for eval-protocol CLI requests.

Format: eval-protocol-cli/{version}

Returns:
User-agent string identifying the eval-protocol CLI and version.
"""
try:
from . import __version__
return f"eval-protocol-cli/{__version__}"
except Exception:
return "eval-protocol-cli/unknown"


def load_jsonl(file_path: str) -> List[Dict[str, Any]]:
"""
Reads a JSONL file where each line is a valid JSON object and returns a list of these objects.
Expand Down
3 changes: 3 additions & 0 deletions eval_protocol/evaluation.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
get_fireworks_api_key,
verify_api_key_and_get_account_id,
)
from eval_protocol.common_utils import get_user_agent
from eval_protocol.typed_interface import EvaluationMode

from eval_protocol.get_pep440_version import get_pep440_version
Expand Down Expand Up @@ -405,6 +406,7 @@ def preview(self, sample_file, max_samples=5):
headers = {
"Authorization": f"Bearer {auth_token}",
"Content-Type": "application/json",
"User-Agent": get_user_agent(),
}
logger.info(f"Previewing evaluator using API endpoint: {url} with account: {account_id}")
logger.debug(f"Preview API Request URL: {url}")
Expand Down Expand Up @@ -748,6 +750,7 @@ def create(self, evaluator_id, display_name=None, description=None, force=False)
headers = {
"Authorization": f"Bearer {auth_token}",
"Content-Type": "application/json",
"User-Agent": get_user_agent(),
}

self._ensure_requirements_present(os.getcwd())
Expand Down
16 changes: 13 additions & 3 deletions eval_protocol/fireworks_rft.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import requests

from .auth import get_fireworks_account_id, get_fireworks_api_base, get_fireworks_api_key
from .common_utils import get_user_agent


def _map_api_host_to_app_host(api_base: str) -> str:
Expand Down Expand Up @@ -157,7 +158,11 @@ def create_dataset_from_jsonl(
display_name: Optional[str],
jsonl_path: str,
) -> Tuple[str, Dict[str, Any]]:
headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
"User-Agent": get_user_agent(),
}
# Count examples quickly
example_count = 0
with open(jsonl_path, "r", encoding="utf-8") as f:
Expand All @@ -181,7 +186,7 @@ def create_dataset_from_jsonl(
upload_url = f"{api_base.rstrip('/')}/v1/accounts/{account_id}/datasets/{dataset_id}:upload"
with open(jsonl_path, "rb") as f:
files = {"file": f}
up_headers = {"Authorization": f"Bearer {api_key}"}
up_headers = {"Authorization": f"Bearer {api_key}", "User-Agent": get_user_agent()}
up_resp = requests.post(upload_url, files=files, headers=up_headers, timeout=600)
if up_resp.status_code not in (200, 201):
raise RuntimeError(f"Dataset upload failed: {up_resp.status_code} {up_resp.text}")
Expand All @@ -195,7 +200,12 @@ def create_reinforcement_fine_tuning_job(
body: Dict[str, Any],
) -> Dict[str, Any]:
url = f"{api_base.rstrip('/')}/v1/accounts/{account_id}/reinforcementFineTuningJobs"
headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json", "Accept": "application/json"}
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
"Accept": "application/json",
"User-Agent": get_user_agent(),
}
resp = requests.post(url, json=body, headers=headers, timeout=60)
if resp.status_code not in (200, 201):
raise RuntimeError(f"RFT job creation failed: {resp.status_code} {resp.text}")
Expand Down
3 changes: 3 additions & 0 deletions eval_protocol/generation/clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
from omegaconf import DictConfig
from pydantic import BaseModel # Added for new models

from ..common_utils import get_user_agent

logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -101,6 +103,7 @@ async def generate(
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json",
"Accept": "application/json",
"User-Agent": get_user_agent(),
}

debug_payload_log = json.loads(json.dumps(payload))
Expand Down
7 changes: 6 additions & 1 deletion eval_protocol/log_utils/fireworks_tracing_http_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

import requests

from ..common_utils import get_user_agent


class FireworksTracingHttpHandler(logging.Handler):
"""Logging handler that posts structured logs to tracing.fireworks gateway /logs endpoint."""
Expand All @@ -22,7 +24,10 @@ def __init__(self, gateway_base_url: Optional[str] = None, rollout_id_env: str =
api_key = os.environ.get("FIREWORKS_API_KEY")
if api_key:
try:
self._session.headers.update({"Authorization": f"Bearer {api_key}"})
self._session.headers.update({
"Authorization": f"Bearer {api_key}",
"User-Agent": get_user_agent(),
})

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cursor no need for tracing.fireworks.ai calls

@cursor cursor Bot Nov 3, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! I've removed the user-agent header from reward_function.py. The user-agent will now only be added to direct Fireworks API requests from the CLI, not to reward function endpoint calls.


Open in Cursor Open in Web

Learn more about Cursor Agents

except Exception:
pass

Expand Down
6 changes: 4 additions & 2 deletions eval_protocol/platform_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
get_fireworks_api_base,
get_fireworks_api_key,
)
from eval_protocol.common_utils import get_user_agent

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -95,6 +96,7 @@ def create_or_update_fireworks_secret(
headers = {
"Authorization": f"Bearer {resolved_api_key}",
"Content-Type": "application/json",
"User-Agent": get_user_agent(),
}

# The secret_id for GET/PATCH/DELETE operations is the key_name.
Expand Down Expand Up @@ -217,7 +219,7 @@ def get_fireworks_secret(
logger.error("Missing Fireworks API key, base URL, or account ID for getting secret.")
return None

headers = {"Authorization": f"Bearer {resolved_api_key}"}
headers = {"Authorization": f"Bearer {resolved_api_key}", "User-Agent": get_user_agent()}
resource_id = _normalize_secret_resource_id(key_name)
url = f"{resolved_api_base.rstrip('/')}/v1/accounts/{resolved_account_id}/secrets/{resource_id}"

Expand Down Expand Up @@ -254,7 +256,7 @@ def delete_fireworks_secret(
logger.error("Missing Fireworks API key, base URL, or account ID for deleting secret.")
return False

headers = {"Authorization": f"Bearer {resolved_api_key}"}
headers = {"Authorization": f"Bearer {resolved_api_key}", "User-Agent": get_user_agent()}
resource_id = _normalize_secret_resource_id(key_name)
url = f"{resolved_api_base.rstrip('/')}/v1/accounts/{resolved_account_id}/secrets/{resource_id}"

Expand Down
9 changes: 7 additions & 2 deletions eval_protocol/pytest/handle_persist_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import re
from typing import Any

from eval_protocol.common_utils import get_user_agent
from eval_protocol.directory_utils import find_eval_protocol_dir
from eval_protocol.models import EvaluationRow
from eval_protocol.pytest.store_experiment_link import store_experiment_link
Expand Down Expand Up @@ -127,7 +128,11 @@ def get_auth_value(key: str) -> str | None:
)
continue

headers = {"Authorization": f"Bearer {fireworks_api_key}", "Content-Type": "application/json"}
headers = {
"Authorization": f"Bearer {fireworks_api_key}",
"Content-Type": "application/json",
"User-Agent": get_user_agent(),
}

# Make dataset first
dataset_url = f"https://api.fireworks.ai/v1/accounts/{fireworks_account_id}/datasets"
Expand Down Expand Up @@ -160,7 +165,7 @@ def get_auth_value(key: str) -> str | None:
upload_url = (
f"https://api.fireworks.ai/v1/accounts/{fireworks_account_id}/datasets/{dataset_id}:upload"
)
upload_headers = {"Authorization": f"Bearer {fireworks_api_key}"}
upload_headers = {"Authorization": f"Bearer {fireworks_api_key}", "User-Agent": get_user_agent()}

with open(exp_file, "rb") as f:
files = {"file": f}
Expand Down
2 changes: 2 additions & 0 deletions eval_protocol/reward_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import requests

from .common_utils import get_user_agent
from .models import EvaluateResult, MetricResult
from .typed_interface import reward_function

Expand Down Expand Up @@ -211,6 +212,7 @@ def __call__(
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {api_key}" if api_key else "",
"User-Agent": get_user_agent(),

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cursor no need here

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Taking a look!

Open in Cursor Open in Web

}

try:
Expand Down
Loading