diff --git a/autogpt_platform/backend/backend/api/features/admin/platform_cost_routes.py b/autogpt_platform/backend/backend/api/features/admin/platform_cost_routes.py index 70e7772790..048c4ae07e 100644 --- a/autogpt_platform/backend/backend/api/features/admin/platform_cost_routes.py +++ b/autogpt_platform/backend/backend/api/features/admin/platform_cost_routes.py @@ -43,6 +43,7 @@ async def get_cost_dashboard( model: str | None = Query(None), block_name: str | None = Query(None), tracking_type: str | None = Query(None), + graph_exec_id: str | None = Query(None), ): logger.info("Admin %s fetching platform cost dashboard", admin_user_id) return await get_platform_cost_dashboard( @@ -53,6 +54,7 @@ async def get_cost_dashboard( model=model, block_name=block_name, tracking_type=tracking_type, + graph_exec_id=graph_exec_id, ) @@ -72,6 +74,7 @@ async def get_cost_logs( model: str | None = Query(None), block_name: str | None = Query(None), tracking_type: str | None = Query(None), + graph_exec_id: str | None = Query(None), ): logger.info("Admin %s fetching platform cost logs", admin_user_id) logs, total = await get_platform_cost_logs( @@ -84,6 +87,7 @@ async def get_cost_logs( model=model, block_name=block_name, tracking_type=tracking_type, + graph_exec_id=graph_exec_id, ) total_pages = (total + page_size - 1) // page_size return PlatformCostLogsResponse( @@ -117,6 +121,7 @@ async def export_cost_logs( model: str | None = Query(None), block_name: str | None = Query(None), tracking_type: str | None = Query(None), + graph_exec_id: str | None = Query(None), ): logger.info("Admin %s exporting platform cost logs", admin_user_id) logs, truncated = await get_platform_cost_logs_for_export( @@ -127,6 +132,7 @@ async def export_cost_logs( model=model, block_name=block_name, tracking_type=tracking_type, + graph_exec_id=graph_exec_id, ) return PlatformCostExportResponse( logs=logs, diff --git a/autogpt_platform/backend/backend/data/platform_cost.py b/autogpt_platform/backend/backend/data/platform_cost.py index aa539bc66b..25e1d4d77c 100644 --- a/autogpt_platform/backend/backend/data/platform_cost.py +++ b/autogpt_platform/backend/backend/data/platform_cost.py @@ -215,6 +215,7 @@ def _build_prisma_where( model: str | None = None, block_name: str | None = None, tracking_type: str | None = None, + graph_exec_id: str | None = None, ) -> PlatformCostLogWhereInput: """Build a Prisma WhereInput for PlatformCostLog filters.""" where: PlatformCostLogWhereInput = {} @@ -242,6 +243,9 @@ def _build_prisma_where( if tracking_type: where["trackingType"] = tracking_type + if graph_exec_id: + where["graphExecId"] = graph_exec_id + return where @@ -314,6 +318,7 @@ async def get_platform_cost_dashboard( model: str | None = None, block_name: str | None = None, tracking_type: str | None = None, + graph_exec_id: str | None = None, ) -> PlatformCostDashboard: """Aggregate platform cost logs for the admin dashboard. @@ -330,7 +335,7 @@ async def get_platform_cost_dashboard( start = datetime.now(timezone.utc) - timedelta(days=DEFAULT_DASHBOARD_DAYS) where = _build_prisma_where( - start, end, provider, user_id, model, block_name, tracking_type + start, end, provider, user_id, model, block_name, tracking_type, graph_exec_id ) # For per-user tracking-type breakdown we intentionally omit the @@ -338,7 +343,14 @@ async def get_platform_cost_dashboard( # This ensures cost_bearing_request_count is correct even when the caller # is filtering the main view by a different tracking_type. where_no_tracking_type = _build_prisma_where( - start, end, provider, user_id, model, block_name, tracking_type=None + start, + end, + provider, + user_id, + model, + block_name, + tracking_type=None, + graph_exec_id=graph_exec_id, ) sum_fields = { @@ -647,12 +659,13 @@ async def get_platform_cost_logs( model: str | None = None, block_name: str | None = None, tracking_type: str | None = None, + graph_exec_id: str | None = None, ) -> tuple[list[CostLogRow], int]: if start is None: start = datetime.now(tz=timezone.utc) - timedelta(days=DEFAULT_DASHBOARD_DAYS) where = _build_prisma_where( - start, end, provider, user_id, model, block_name, tracking_type + start, end, provider, user_id, model, block_name, tracking_type, graph_exec_id ) offset = (page - 1) * page_size @@ -702,6 +715,7 @@ async def get_platform_cost_logs_for_export( model: str | None = None, block_name: str | None = None, tracking_type: str | None = None, + graph_exec_id: str | None = None, ) -> tuple[list[CostLogRow], bool]: """Return all matching rows up to EXPORT_MAX_ROWS. @@ -712,7 +726,7 @@ async def get_platform_cost_logs_for_export( start = datetime.now(tz=timezone.utc) - timedelta(days=DEFAULT_DASHBOARD_DAYS) where = _build_prisma_where( - start, end, provider, user_id, model, block_name, tracking_type + start, end, provider, user_id, model, block_name, tracking_type, graph_exec_id ) rows = await PrismaLog.prisma().find_many( diff --git a/autogpt_platform/frontend/src/app/(platform)/admin/platform-costs/components/PlatformCostContent.tsx b/autogpt_platform/frontend/src/app/(platform)/admin/platform-costs/components/PlatformCostContent.tsx index ce0329af19..622b963e3e 100644 --- a/autogpt_platform/frontend/src/app/(platform)/admin/platform-costs/components/PlatformCostContent.tsx +++ b/autogpt_platform/frontend/src/app/(platform)/admin/platform-costs/components/PlatformCostContent.tsx @@ -19,6 +19,7 @@ interface Props { model?: string; block_name?: string; tracking_type?: string; + graph_exec_id?: string; page?: string; tab?: string; }; @@ -47,6 +48,8 @@ export function PlatformCostContent({ searchParams }: Props) { setBlockInput, typeInput, setTypeInput, + executionIdInput, + setExecutionIdInput, rateOverrides, handleRateOverride, updateUrl, @@ -235,6 +238,22 @@ export function PlatformCostContent({ searchParams }: Props) { onChange={(e) => setTypeInput(e.target.value)} /> +