Add counts endpoint

This commit is contained in:
Krzysztof Czerwinski
2025-05-29 16:17:33 +02:00
parent ea2cd3e7bf
commit 09dba93a4a
5 changed files with 112 additions and 1 deletions

View File

@@ -1,6 +1,8 @@
import functools
import logging
import prisma
import backend.server.model as server_model
from backend.blocks import load_all_blocks
from backend.data.block import Block, BlockCategory, BlockSchema
@@ -10,12 +12,14 @@ from backend.server.v2.builder.model import (
BlockCategoryResponse,
BlockResponse,
BlockType,
CountResponse,
Provider,
ProviderResponse,
SearchBlocksResponse,
)
logger = logging.getLogger(__name__)
_static_counts_cache: dict | None = None
def get_block_categories(category_blocks: int = 3) -> list[BlockCategoryResponse]:
@@ -99,6 +103,8 @@ def get_blocks(
take -= 1
blocks.append(block)
# todo kcze costs
return BlockResponse(
blocks=[b.to_dict() for b in blocks],
pagination=server_model.Pagination(
@@ -214,6 +220,69 @@ def get_providers(
)
async def get_counts(user_id: str) -> CountResponse:
my_agents = await prisma.models.LibraryAgent.prisma().count(
where={
"userId": user_id,
"isDeleted": False,
"isArchived": False,
}
)
counts = await _get_static_counts()
return CountResponse(
my_agents=my_agents,
**counts,
)
async def _get_static_counts():
"""
Get counts of blocks, integrations, and marketplace agents.
This is cached to avoid unnecessary database queries and calculations.
Can't use functools.cache here because the function is async.
"""
global _static_counts_cache
if _static_counts_cache is not None:
return _static_counts_cache
all_blocks = 0
input_blocks = 0
action_blocks = 0
output_blocks = 0
integrations = 0
for block_type in load_all_blocks().values():
block: Block[BlockSchema, BlockSchema] = block_type()
if block.disabled:
continue
all_blocks += 1
if block.block_type.value == "Input":
input_blocks += 1
elif block.block_type.value == "Output":
output_blocks += 1
else:
action_blocks += 1
credentials = list(block.input_schema.get_credentials_fields().values())
if len(credentials) > 0:
integrations += 1
marketplace_agents = await prisma.models.StoreAgent.prisma().count()
_static_counts_cache = {
"all_blocks": all_blocks,
"input_blocks": input_blocks,
"action_blocks": action_blocks,
"output_blocks": output_blocks,
"integrations": integrations,
"marketplace_agents": marketplace_agents,
}
return _static_counts_cache
@functools.cache
def _get_all_providers() -> dict[ProviderName, Provider]:
providers: dict[ProviderName, Provider] = {}

View File

@@ -78,3 +78,13 @@ class SearchResponse(BaseModel):
total_items: dict[FilterType, int]
page: int
more_pages: bool
class CountResponse(BaseModel):
all_blocks: int
input_blocks: int
action_blocks: int
output_blocks: int
integrations: int
marketplace_agents: int
my_agents: int

View File

@@ -217,3 +217,13 @@ async def search(
page=options.page,
more_pages=more_pages,
)
@router.get(
"/counts",
dependencies=[fastapi.Depends(auth_middleware)],
)
async def get_counts(
user_id: Annotated[str, fastapi.Depends(get_user_id)],
) -> builder_model.CountResponse:
return await builder_db.get_counts(user_id)

View File

@@ -13,6 +13,7 @@ import type {
BlockRequest,
BlockResponse,
BlockSearchResponse,
CountResponse,
CreateAPIKeyResponse,
CreateLibraryAgentPresetRequest,
CreatorDetails,
@@ -234,7 +235,13 @@ export default class BackendAPI {
searchBlocks(options: {
search_query?: string;
filter?: ("blocks" | "integrations" | "marketplace_agents" | "my_agents")[];
filter?: (
| "blocks"
| "integrations"
| "providers"
| "marketplace_agents"
| "my_agents"
)[];
by_creator?: string[];
search_id?: string;
page?: number;
@@ -243,6 +250,10 @@ export default class BackendAPI {
return this._request("POST", "/builder/search", options);
}
getBlockCounts(): Promise<CountResponse> {
return this._get("/builder/counts");
}
////////////////////////////////////////
//////////////// GRAPHS ////////////////
////////////////////////////////////////

View File

@@ -85,6 +85,17 @@ export type BlockSearchResponse = {
more_pages: boolean;
};
/* Mirror of backend/server/v2/builder/model.py:CountResponse */
export type CountResponse = {
all_blocks: number;
input_blocks: number;
action_blocks: number;
output_blocks: number;
integrations: number;
marketplace_agents: number;
my_agents: number;
};
/* Mirror of backend/data/block.py:Block */
export type Block = {
id: string;