feat(platform): Log Marketplace Search Terms (#11092)

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Reinier van der Leer <Pwuts@users.noreply.github.com>
This commit is contained in:
Swifty
2025-10-10 11:33:28 +02:00
committed by GitHub
parent c5b90f7b09
commit 18e169aa51
3 changed files with 55 additions and 18 deletions

View File

@@ -70,8 +70,7 @@ async def get_store_agents(
logger.debug(
f"Getting store agents. featured={featured}, creators={creators}, sorted_by={sorted_by}, search={search_query}, category={category}, page={page}"
)
sanitized_query = sanitize_query(search_query)
search_term = sanitize_query(search_query)
where_clause: prisma.types.StoreAgentWhereInput = {"is_available": True}
if featured:
where_clause["featured"] = featured
@@ -80,10 +79,10 @@ async def get_store_agents(
if category:
where_clause["categories"] = {"has": category}
if sanitized_query:
if search_term:
where_clause["OR"] = [
{"agent_name": {"contains": sanitized_query, "mode": "insensitive"}},
{"description": {"contains": sanitized_query, "mode": "insensitive"}},
{"agent_name": {"contains": search_term, "mode": "insensitive"}},
{"description": {"contains": search_term, "mode": "insensitive"}},
]
order_by = []
@@ -145,6 +144,23 @@ async def get_store_agents(
raise backend.server.v2.store.exceptions.DatabaseError(
"Failed to fetch store agents"
) from e
finally:
if search_term:
await log_search_term(search_query=search_term)
async def log_search_term(search_query: str):
"""Log a search term to the database"""
# Anonymize the data by preventing correlation with other logs
date = datetime.now(timezone.utc).replace(hour=0, minute=0, second=0, microsecond=0)
try:
await prisma.models.SearchTerms.prisma().create(
data={"searchTerm": search_query, "createdDate": date}
)
except Exception as e:
# Fail silently here so that logging search terms doesn't break the app
logger.error(f"Error logging search term: {e}")
async def get_store_agent_details(

View File

@@ -0,0 +1,11 @@
-- CreateTable
CREATE TABLE "SearchTerms" (
"id" BIGSERIAL NOT NULL,
"createdDate" TIMESTAMP(3) NOT NULL,
"searchTerm" TEXT NOT NULL,
CONSTRAINT "SearchTerms_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE INDEX "SearchTerms_createdDate_idx" ON "SearchTerms"("createdDate");

View File

@@ -118,9 +118,9 @@ model AgentGraph {
createdAt DateTime @default(now())
updatedAt DateTime? @updatedAt
name String?
description String?
instructions String?
name String?
description String?
instructions String?
recommendedScheduleCron String?
isActive Boolean @default(true)
@@ -382,9 +382,9 @@ model AgentGraphExecution {
stats Json?
// Sharing fields
isShared Boolean @default(false)
shareToken String? @unique
sharedAt DateTime?
isShared Boolean @default(false)
shareToken String? @unique
sharedAt DateTime?
@@index([agentGraphId, agentGraphVersion])
@@index([userId, isDeleted, createdAt])
@@ -545,7 +545,7 @@ model CreditTransaction {
createdAt DateTime @default(now())
userId String
User User? @relation(fields: [userId], references: [id], onDelete: NoAction)
User User? @relation(fields: [userId], references: [id], onDelete: NoAction)
amount Int
type CreditTransactionType
@@ -587,6 +587,16 @@ model CreditRefundRequest {
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
model SearchTerms {
// User ID not being logged as this is anonymous analytics data
// Not using uuid as we want to minimise table size
id BigInt @id @default(autoincrement())
createdDate DateTime
searchTerm String
@@index([createdDate])
}
model Profile {
id String @id @default(uuid())
createdAt DateTime @default(now())
@@ -769,13 +779,13 @@ model StoreListingVersion {
AgentGraph AgentGraph @relation(fields: [agentGraphId, agentGraphVersion], references: [id, version])
// Content fields
name String
subHeading String
videoUrl String?
imageUrls String[]
description String
name String
subHeading String
videoUrl String?
imageUrls String[]
description String
instructions String?
categories String[]
categories String[]
isFeatured Boolean @default(false)