Skip to content
13 changes: 13 additions & 0 deletions .changeset/wet-aliens-bet.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
"@inkeep/agents-core": patch
"@inkeep/agents-manage-ui": patch
"@inkeep/agents-cli": patch
"@inkeep/agents-manage-api": patch
"@inkeep/agents-run-api": patch
"@inkeep/agents-sdk": patch
"@inkeep/ai-sdk-provider": patch
"@inkeep/create-agents": patch
"test-agents": patch
---

optimize queries
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ interface ConversationStatsCardProps {
};
searchQuery?: string;
onSearchChange?: (query: string) => void;
totalConversations?: number;
}

export function ConversationStatsCard({
Expand All @@ -41,6 +42,7 @@ export function ConversationStatsCard({
pagination,
searchQuery = '',
onSearchChange,
totalConversations,
}: ConversationStatsCardProps) {
const [localQuery, setLocalQuery] = React.useState<string>(searchQuery);
const [searchError, setSearchError] = React.useState<string | null>(null);
Expand Down Expand Up @@ -109,7 +111,7 @@ export function ConversationStatsCard({
</div>

<Badge variant="code" className="text-xs">
{pagination?.total || stats.length}
{totalConversations ?? 0}
</Badge>
</CardTitle>

Expand Down
37 changes: 3 additions & 34 deletions agents-manage-ui/src/components/traces/traces-overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,6 @@ export function TracesOverview({ refreshKey }: TracesOverviewProps) {
const [debouncedSearchQuery, setDebouncedSearchQuery] = useState<string>('');
const [availableSpanNames, setAvailableSpanNames] = useState<string[]>([]);
const [spanNamesLoading, setSpanNamesLoading] = useState(false);
// Aggregate stats now come from useAggregateStats hook
const [aiCallsByAgent, setAiCallsByAgent] = useState<
Array<{ agentId: string; totalCalls: number }>
>([]);
const [_aiCallsLoading, setAiCallsLoading] = useState(true);
const [activityData, setActivityData] = useState<Array<{ date: string; count: number }>>([]);
const [activityLoading, setActivityLoading] = useState(true);

Expand Down Expand Up @@ -140,7 +135,7 @@ export function TracesOverview({ refreshKey }: TracesOverviewProps) {
filters: spanFilters,
projectId: projectId as string,
searchQuery: debouncedSearchQuery,
pagination: { enabled: true, pageSize: 10 },
pagination: { pageSize: 10 },
agentId: selectedAgent,
});

Expand All @@ -156,24 +151,6 @@ export function TracesOverview({ refreshKey }: TracesOverviewProps) {

// Aggregate stats now come directly from server-side aggregation

// Fetch AI calls by agent
useEffect(() => {
const fetchAICallsByAgent = async () => {
try {
setAiCallsLoading(true);
const client = getSigNozStatsClient();
const aiCallsData = await client.getAICallsByAgent(startTime, endTime, projectId as string);
setAiCallsByAgent(aiCallsData);
} catch (err) {
console.error('Error fetching AI calls by agent:', err);
} finally {
setAiCallsLoading(false);
}
};

fetchAICallsByAgent();
}, [startTime, endTime, projectId]);

// Fetch conversations per day activity
useEffect(() => {
const fetchActivity = async () => {
Expand Down Expand Up @@ -239,15 +216,6 @@ export function TracesOverview({ refreshKey }: TracesOverviewProps) {
// Filter stats based on selected agent (for aggregate calculations)
// Server-side pagination and filtering is now handled by the hooks

// Get AI calls for selected agent
const selectedAgentAICalls = useMemo(() => {
if (!selectedAgent) {
return aggregateStats.totalAICalls;
}
const agentAICalls = aiCallsByAgent.find((ac) => ac.agentId === selectedAgent);
return agentAICalls?.totalCalls || 0;
}, [selectedAgent, aiCallsByAgent, aggregateStats.totalAICalls]);

if (error) {
return (
<div className="space-y-4">
Expand Down Expand Up @@ -424,7 +392,7 @@ export function TracesOverview({ refreshKey }: TracesOverviewProps) {
{/* AI Usage */}
<StatCard
title="AI calls"
stat={selectedAgentAICalls}
stat={aggregateStats.totalAICalls}
statDescription={`Over ${aggregateStats.totalConversations} conversations`}
isLoading={aggregateLoading}
Icon={SparklesIcon}
Expand All @@ -448,6 +416,7 @@ export function TracesOverview({ refreshKey }: TracesOverviewProps) {
pagination={pagination}
searchQuery={searchQuery}
onSearchChange={setSearchQuery}
totalConversations={aggregateStats.totalConversations}
/>
</div>
);
Expand Down
44 changes: 18 additions & 26 deletions agents-manage-ui/src/hooks/use-traces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export interface UseConversationStatsResult {
loading: boolean;
error: string | null;
refresh: () => void;
pagination?: {
pagination: {
page: number;
limit: number;
total: number;
Expand All @@ -34,7 +34,6 @@ export interface UseConversationStatsOptions {
filters?: SpanFilterOptions;
projectId?: string;
pagination?: {
enabled: boolean;
pageSize?: number;
};
searchQuery?: string;
Expand All @@ -53,7 +52,6 @@ export function useConversationStats(
>(null);

// Extract stable values to avoid object recreation issues
const paginationEnabled = options?.pagination?.enabled;
const pageSize = options?.pagination?.pageSize || 50;

const fetchData = useCallback(
Expand All @@ -68,28 +66,18 @@ export function useConversationStats(
const currentEndTime = Math.min(options?.endTime || Date.now() - 1);
const currentStartTime = options?.startTime || new Date('2020-01-01T00:00:00Z').getTime();

const paginationParams = paginationEnabled ? { page, limit: pageSize } : undefined;

const result = await client.getConversationStats(
currentStartTime,
currentEndTime,
options?.filters,
options?.projectId,
paginationParams,
{ page, limit: pageSize },
options?.searchQuery,
options?.agentId
);

if (paginationEnabled && typeof result === 'object' && 'data' in result) {
// Paginated result
setStats(result.data);
setPaginationInfo(result.pagination);
// Don't set currentPage here to avoid infinite loops - it should be managed by navigation functions
} else {
// Non-paginated result (backward compatibility)
setStats(result as ConversationStats[]);
setPaginationInfo(null);
}
setStats(result.data);
setPaginationInfo(result.pagination);
} catch (err) {
console.error('Error fetching conversation stats:', err);
const errorMessage =
Expand All @@ -106,7 +94,6 @@ export function useConversationStats(
options?.projectId,
options?.searchQuery,
options?.agentId,
paginationEnabled,
pageSize,
currentPage,
]
Expand Down Expand Up @@ -149,16 +136,11 @@ export function useConversationStats(
);

// Fetch when component mounts or time range changes
useEffect(() => {
fetchData();
}, [fetchData]);

// Reset to page 1 when filters or time range change
useEffect(() => {
if (paginationEnabled) {
setCurrentPage(1);
}
}, [paginationEnabled]);
setCurrentPage(1);
fetchData(1);
}, [fetchData]);

return {
stats,
Expand All @@ -177,7 +159,17 @@ export function useConversationStats(
previousPage,
goToPage,
}
: undefined,
: {
page: 1,
limit: pageSize,
total: 0,
totalPages: 0,
hasNextPage: false,
hasPreviousPage: false,
nextPage,
previousPage,
goToPage,
},
};
}

Expand Down
Loading