fix: add getDevice query, fix IN clause, add error handling to getDeviceStats

This commit is contained in:
Sanju Sivalingam
2026-02-17 21:13:50 +05:30
parent b240887b0e
commit 423cd7af01
2 changed files with 66 additions and 34 deletions

View File

@@ -1,7 +1,7 @@
import { query, getRequestEvent } from '$app/server'; import { query, getRequestEvent } from '$app/server';
import { db } from '$lib/server/db'; import { db } from '$lib/server/db';
import { device, agentSession, agentStep } from '$lib/server/db/schema'; import { device, agentSession, agentStep } from '$lib/server/db/schema';
import { eq, desc, and, count, avg, sql } from 'drizzle-orm'; import { eq, desc, and, count, avg, sql, inArray } from 'drizzle-orm';
export const listDevices = query(async () => { export const listDevices = query(async () => {
const { locals } = getRequestEvent(); const { locals } = getRequestEvent();
@@ -25,7 +25,7 @@ export const listDevices = query(async () => {
startedAt: agentSession.startedAt startedAt: agentSession.startedAt
}) })
.from(agentSession) .from(agentSession)
.where(sql`${agentSession.deviceId} IN ${deviceIds}`) .where(inArray(agentSession.deviceId, deviceIds))
.orderBy(desc(agentSession.startedAt)) .orderBy(desc(agentSession.startedAt))
: []; : [];
@@ -59,39 +59,61 @@ export const listDevices = query(async () => {
}); });
}); });
export const getDevice = query(async (deviceId: string) => {
const { locals } = getRequestEvent();
if (!locals.user) return null;
const rows = await db
.select()
.from(device)
.where(and(eq(device.id, deviceId), eq(device.userId, locals.user.id)))
.limit(1);
if (rows.length === 0) return null;
const d = rows[0];
const info = d.deviceInfo as Record<string, unknown> | null;
return {
deviceId: d.id,
name: d.name,
status: d.status,
model: (info?.model as string) ?? null,
manufacturer: (info?.manufacturer as string) ?? null,
androidVersion: (info?.androidVersion as string) ?? null,
screenWidth: (info?.screenWidth as number) ?? null,
screenHeight: (info?.screenHeight as number) ?? null,
batteryLevel: (info?.batteryLevel as number) ?? null,
isCharging: (info?.isCharging as boolean) ?? false,
lastSeen: d.lastSeen?.toISOString() ?? d.createdAt.toISOString()
};
});
export const getDeviceStats = query(async (deviceId: string) => { export const getDeviceStats = query(async (deviceId: string) => {
const { locals } = getRequestEvent(); const { locals } = getRequestEvent();
if (!locals.user) return null; if (!locals.user) return null;
const stats = await db try {
.select({ const stats = await db
totalSessions: count(agentSession.id), .select({
successCount: count(sql`CASE WHEN ${agentSession.status} = 'completed' THEN 1 END`), totalSessions: count(agentSession.id),
avgSteps: avg(agentSession.stepsUsed) successCount: count(sql`CASE WHEN ${agentSession.status} = 'completed' THEN 1 END`),
}) avgSteps: avg(agentSession.stepsUsed)
.from(agentSession) })
.where(and(eq(agentSession.deviceId, deviceId), eq(agentSession.userId, locals.user.id))); .from(agentSession)
.where(and(eq(agentSession.deviceId, deviceId), eq(agentSession.userId, locals.user.id)));
const lastSession = await db const s = stats[0];
.select({ return {
goal: agentSession.goal, totalSessions: Number(s?.totalSessions ?? 0),
status: agentSession.status, successRate: s?.totalSessions
startedAt: agentSession.startedAt ? Math.round((Number(s.successCount) / Number(s.totalSessions)) * 100)
}) : 0,
.from(agentSession) avgSteps: Math.round(Number(s?.avgSteps ?? 0))
.where(and(eq(agentSession.deviceId, deviceId), eq(agentSession.userId, locals.user.id))) };
.orderBy(desc(agentSession.startedAt)) } catch (err) {
.limit(1); console.error('[getDeviceStats] Query failed:', err);
return { totalSessions: 0, successRate: 0, avgSteps: 0 };
const s = stats[0]; }
return {
totalSessions: Number(s?.totalSessions ?? 0),
successRate: s?.totalSessions
? Math.round((Number(s.successCount) / Number(s.totalSessions)) * 100)
: 0,
avgSteps: Math.round(Number(s?.avgSteps ?? 0)),
lastGoal: lastSession[0] ?? null
};
}); });
export const listDeviceSessions = query(async (deviceId: string) => { export const listDeviceSessions = query(async (deviceId: string) => {

View File

@@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import { page } from '$app/state'; import { page } from '$app/state';
import { import {
listDevices, getDevice,
listDeviceSessions, listDeviceSessions,
listSessionSteps, listSessionSteps,
getDeviceStats getDeviceStats
@@ -15,15 +15,25 @@
let activeTab = $state<'overview' | 'sessions' | 'run'>('overview'); let activeTab = $state<'overview' | 'sessions' | 'run'>('overview');
// Device data from DB // Device data from DB
const allDevices = await listDevices(); const deviceData = (await getDevice(deviceId)) as {
const deviceData = allDevices.find((d) => d.deviceId === deviceId); deviceId: string;
name: string;
status: string;
model: string | null;
manufacturer: string | null;
androidVersion: string | null;
screenWidth: number | null;
screenHeight: number | null;
batteryLevel: number | null;
isCharging: boolean;
lastSeen: string;
} | null;
// Device stats // Device stats
const stats = (await getDeviceStats(deviceId)) as { const stats = (await getDeviceStats(deviceId)) as {
totalSessions: number; totalSessions: number;
successRate: number; successRate: number;
avgSteps: number; avgSteps: number;
lastGoal: { goal: string; status: string; startedAt: Date } | null;
} | null; } | null;
// Session history // Session history