Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ References:
Migration should preserve compatibility while moving to new APIs.

- Keep old and new routes running in parallel until migration is complete.
- New stack commonly ships under `/preview/*` while old endpoints remain mounted.
- New stack commonly ships under `/*` while old endpoints remain mounted.
- Prefer data compatibility adapters over breaking payload changes.
- Preserve old IDs/shape when continuity is required.
- If old storage temporarily carries new payload shape, mark it explicitly.
Expand Down
12 changes: 5 additions & 7 deletions api/ee/src/apis/fastapi/organizations/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from datetime import datetime
from uuid import UUID

from pydantic import BaseModel, Field
from pydantic import BaseModel, ConfigDict, Field


# Domain Verification Models
Expand All @@ -26,6 +26,8 @@ class OrganizationDomainVerify(BaseModel):
class OrganizationDomainResponse(BaseModel):
"""Response model for a domain."""

model_config = ConfigDict(from_attributes=True)

id: UUID
slug: str

Expand All @@ -41,9 +43,6 @@ class OrganizationDomainResponse(BaseModel):

organization_id: UUID

class Config:
from_attributes = True


# SSO Provider Models

Expand Down Expand Up @@ -77,6 +76,8 @@ class OrganizationProviderUpdate(BaseModel):
class OrganizationProviderResponse(BaseModel):
"""Response model for an SSO provider."""

model_config = ConfigDict(from_attributes=True)

id: UUID
slug: str

Expand All @@ -91,6 +92,3 @@ class OrganizationProviderResponse(BaseModel):
updated_at: Optional[datetime]

organization_id: UUID

class Config:
from_attributes = True
10 changes: 4 additions & 6 deletions api/ee/src/core/organizations/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ class OrganizationUpdate(BaseModel):


class OrganizationDomain(BaseModel):
model_config = ConfigDict(from_attributes=True)

id: UUID
slug: str

Expand All @@ -73,9 +75,6 @@ class OrganizationDomain(BaseModel):

organization_id: UUID

class Config:
from_attributes = True


class OrganizationDomainCreate(BaseModel):
slug: str
Expand All @@ -98,6 +97,8 @@ class OrganizationDomainCreate(BaseModel):


class OrganizationProvider(BaseModel):
model_config = ConfigDict(from_attributes=True)

id: UUID
slug: str

Expand All @@ -115,9 +116,6 @@ class OrganizationProvider(BaseModel):

organization_id: UUID

class Config:
from_attributes = True


class OrganizationProviderCreate(BaseModel):
slug: str
Expand Down
8 changes: 4 additions & 4 deletions api/ee/src/services/admin_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,19 @@
log = get_module_logger(__name__)


REFERENCE_JSON_ENCODERS = {UUID: str}


class Reference(BaseModel):
id: Optional[UUID] = None
slug: Optional[str] = None

class Config:
json_encoders = {UUID: str}

def encode(self, data: Any) -> Any:
if isinstance(data, dict):
return {k: self.encode(v) for k, v in data.items()}
elif isinstance(data, list):
return [self.encode(item) for item in data]
for type_, encoder in self.Config.json_encoders.items():
for type_, encoder in REFERENCE_JSON_ENCODERS.items():
if isinstance(data, type_):
return encoder(data)
return data
Expand Down
52 changes: 48 additions & 4 deletions api/entrypoints/routers.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,10 +278,6 @@ async def lifespan(*args, **kwargs):
tracing_dao=tracing_dao,
)

simple_traces_service = SimpleTracesService(
tracing_service=tracing_service,
)

events_service = EventsService(
events_dao=events_dao,
)
Expand Down Expand Up @@ -351,6 +347,12 @@ async def lifespan(*args, **kwargs):
evaluators_service=evaluators_service,
)

simple_traces_service = SimpleTracesService(
tracing_service=tracing_service,
evaluators_service=evaluators_service,
simple_evaluators_service=simple_evaluators_service,
)

simple_workflows_service = SimpleWorkflowsService(
workflows_service=workflows_service,
)
Expand Down Expand Up @@ -575,16 +577,30 @@ async def lifespan(*args, **kwargs):
tags=["Observability"],
)

app.include_router(
router=traces.router,
prefix="/traces",
tags=["Observability"],
)

app.include_router(
router=traces.router,
prefix="/preview/traces",
tags=["Observability"],
include_in_schema=False,
)

app.include_router(
router=spans.router,
prefix="/spans",
tags=["Observability"],
)

app.include_router(
router=spans.router,
prefix="/preview/spans",
tags=["Observability"],
include_in_schema=False,
)

app.include_router(
Expand Down Expand Up @@ -761,16 +777,30 @@ async def lifespan(*args, **kwargs):
include_in_schema=False,
)

app.include_router(
router=environments.router,
prefix="/environments",
tags=["Environments"],
)

app.include_router(
router=environments.router,
prefix="/preview/environments",
tags=["Environments"],
include_in_schema=False,
)

app.include_router(
router=simple_environments.router,
prefix="/simple/environments",
tags=["Environments"],
)

app.include_router(
router=simple_environments.router,
prefix="/preview/simple/environments",
tags=["Environments"],
include_in_schema=False,
)

app.include_router(
Expand All @@ -779,10 +809,17 @@ async def lifespan(*args, **kwargs):
tags=["Variants"],
)

app.include_router(
router=tools.router,
prefix="/tools",
tags=["Tools"],
)

app.include_router(
router=tools.router,
prefix="/preview/tools",
tags=["Tools"],
include_in_schema=False,
)

app.include_router(
Expand Down Expand Up @@ -817,10 +854,17 @@ async def lifespan(*args, **kwargs):
include_in_schema=False,
)

app.include_router(
router=simple_queues.router,
prefix="/simple/queues",
tags=["Evaluations"],
)

app.include_router(
router=simple_queues.router,
prefix="/preview/simple/queues",
tags=["Evaluations"],
include_in_schema=False,
)

app.include_router(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from typing import Any, Dict, List, Optional
from datetime import datetime

from pydantic import BaseModel, Field
from pydantic import BaseModel, ConfigDict, Field

from oss.src.core.otel.dtos import (
OTelStatusCode,
Expand Down Expand Up @@ -41,6 +41,8 @@ class LinkData(BaseModel):
class CanonicalAttributes(BaseModel):
"""A normalized and structured container for all attributes and metadata from an OpenTelemetry span."""

model_config = ConfigDict(arbitrary_types_allowed=True)

# Core span identifiers and metadata
span_name: str
trace_id: str
Expand All @@ -67,9 +69,6 @@ class CanonicalAttributes(BaseModel):
# For example, a method to get all 'ag.*' prefixed attributes from span_attributes
# or resource_attributes. For now, adapters will access these dicts directly.

class Config:
arbitrary_types_allowed = True # For OTelSpanKind and OTelStatusCode enums

def get_attributes_in_namespace(
self, prefix: str, source: str = "span"
) -> Dict[str, Any]:
Expand Down
2 changes: 2 additions & 0 deletions api/oss/src/apis/fastapi/testcases/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ class TestcasesRouter:
FastAPI router for testcase endpoints.
"""

__test__ = False

def __init__(
self,
*,
Expand Down
22 changes: 11 additions & 11 deletions api/oss/src/apis/fastapi/testsets/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ def __init__(self, *, testsets_service: TestsetsService):
response_model_exclude=TESTSET_REVISION_RESPONSE_EXCLUDE,
)

# POST /api/preview/testsets/revisions/{testset_revision_id}/download
# POST /api/testsets/revisions/{testset_revision_id}/download
self.router.add_api_route(
"/revisions/{testset_revision_id}/download",
self.fetch_testset_revision_to_file,
Expand All @@ -452,7 +452,7 @@ def __init__(self, *, testsets_service: TestsetsService):
status_code=status.HTTP_200_OK,
)

# POST /api/preview/testsets/revisions/{testset_revision_id}/upload
# POST /api/testsets/revisions/{testset_revision_id}/upload
self.router.add_api_route(
"/revisions/{testset_revision_id}/upload",
self.create_testset_revision_from_file,
Expand Down Expand Up @@ -1466,7 +1466,7 @@ def __init__(

# SIMPLE TESTSETS ------------------------------------------------------

# POST /api/preview/simple/testsets/
# POST /api/simple/testsets/
self.router.add_api_route(
"/",
self.create_simple_testset,
Expand All @@ -1477,7 +1477,7 @@ def __init__(
response_model_exclude_none=True,
)

# GET /api/preview/simple/testsets/{testset_id}
# GET /api/simple/testsets/{testset_id}
self.router.add_api_route(
"/{testset_id}",
self.fetch_simple_testset,
Expand All @@ -1488,7 +1488,7 @@ def __init__(
response_model_exclude_none=True,
)

# PUT /api/preview/simple/testsets/{testset_id}
# PUT /api/simple/testsets/{testset_id}
self.router.add_api_route(
"/{testset_id}",
self.edit_simple_testset,
Expand All @@ -1499,7 +1499,7 @@ def __init__(
response_model_exclude_none=True,
)

# POST /api/preview/simple/testsets/{testset_id}/archive
# POST /api/simple/testsets/{testset_id}/archive
self.router.add_api_route(
"/{testset_id}/archive",
self.archive_simple_testset,
Expand All @@ -1510,7 +1510,7 @@ def __init__(
response_model_exclude_none=True,
)

# POST /api/preview/simple/testsets/{testset_id}/unarchive
# POST /api/simple/testsets/{testset_id}/unarchive
self.router.add_api_route(
"/{testset_id}/unarchive",
self.unarchive_simple_testset,
Expand All @@ -1521,7 +1521,7 @@ def __init__(
response_model_exclude_none=True,
)

# POST /api/preview/simple/testsets/{testset_id}/upload
# POST /api/simple/testsets/{testset_id}/upload
self.router.add_api_route(
"/{testset_id}/upload",
self.edit_simple_testset_from_file,
Expand All @@ -1532,7 +1532,7 @@ def __init__(
response_model_exclude_none=True,
)

# POST /api/preview/simple/testsets/{testset_id}/download
# POST /api/simple/testsets/{testset_id}/download
self.router.add_api_route(
"/{testset_id}/download",
self.fetch_simple_testset_to_file,
Expand All @@ -1541,7 +1541,7 @@ def __init__(
status_code=status.HTTP_200_OK,
)

# POST /api/preview/simple/testsets/query
# POST /api/simple/testsets/query
self.router.add_api_route(
"/query",
self.query_simple_testsets,
Expand All @@ -1552,7 +1552,7 @@ def __init__(
response_model_exclude_none=True,
)

# POST /api/preview/simple/testsets/upload
# POST /api/simple/testsets/upload
self.router.add_api_route(
"/upload",
self.create_simple_testset_from_file,
Expand Down
6 changes: 3 additions & 3 deletions api/oss/src/apis/fastapi/tracing/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -815,7 +815,7 @@ async def query_spans(
conflict_focus=Focus.TRACE,
conflict_detail=(
"Query revision formatting.focus=trace. "
"Use /preview/traces/query for this query revision."
"Use /traces/query for this query revision."
),
)
except QueryFocusConflictError as e:
Expand Down Expand Up @@ -1061,7 +1061,7 @@ async def query_traces( # QUERY
conflict_focus=Focus.SPAN,
conflict_detail=(
"Query revision formatting.focus=span. "
"Use /preview/spans/query for this query revision."
"Use /spans/query for this query revision."
),
)
except QueryFocusConflictError as e:
Expand Down Expand Up @@ -1318,7 +1318,7 @@ async def fetch_trace(
if trace_id.lower() in {"query", "ingest"}:
raise HTTPException(
status_code=status.HTTP_405_METHOD_NOT_ALLOWED,
detail=f"GET /preview/traces/{trace_id} is not supported.",
detail=f"GET /traces/{trace_id} is not supported.",
)

if is_ee():
Expand Down
Loading
Loading