From 7557481e837f9411169936dd9c6a6af0b7274d0a Mon Sep 17 00:00:00 2001 From: Sanju Sivalingam Date: Tue, 17 Feb 2026 14:45:47 +0530 Subject: [PATCH] feat: add devices page with goal input and step log Co-Authored-By: Claude Opus 4.6 --- web/.env.example | 5 ++ web/src/lib/api/devices.remote.ts | 17 +++++ web/src/routes/dashboard/devices/+page.svelte | 36 ++++++++++ .../dashboard/devices/[deviceId]/+page.svelte | 72 +++++++++++++++++++ 4 files changed, 130 insertions(+) create mode 100644 web/.env.example create mode 100644 web/src/lib/api/devices.remote.ts create mode 100644 web/src/routes/dashboard/devices/+page.svelte create mode 100644 web/src/routes/dashboard/devices/[deviceId]/+page.svelte diff --git a/web/.env.example b/web/.env.example new file mode 100644 index 0000000..6697b77 --- /dev/null +++ b/web/.env.example @@ -0,0 +1,5 @@ +# Replace with your DB credentials! +DATABASE_URL="postgres://user:password@host:port/db-name" + +SERVER_URL="http://localhost:8080" +PUBLIC_SERVER_WS_URL="ws://localhost:8080" diff --git a/web/src/lib/api/devices.remote.ts b/web/src/lib/api/devices.remote.ts new file mode 100644 index 0000000..dd412c9 --- /dev/null +++ b/web/src/lib/api/devices.remote.ts @@ -0,0 +1,17 @@ +import { query, getRequestEvent } from '$app/server'; +import { env } from '$env/dynamic/private'; + +const SERVER_URL = env.SERVER_URL || 'http://localhost:8080'; + +export const listDevices = query(async () => { + const { request } = getRequestEvent(); + + const res = await fetch(`${SERVER_URL}/devices`, { + headers: { + cookie: request.headers.get('cookie') ?? '' + } + }); + + if (!res.ok) return []; + return res.json(); +}); diff --git a/web/src/routes/dashboard/devices/+page.svelte b/web/src/routes/dashboard/devices/+page.svelte new file mode 100644 index 0000000..572e841 --- /dev/null +++ b/web/src/routes/dashboard/devices/+page.svelte @@ -0,0 +1,36 @@ + + +

Devices

+ +{#if devices.length === 0} +
+

No devices connected.

+

+ Install the Android app, paste your API key, and your device will appear here. +

+ + Create an API key + +
+{:else} +
+ {#each devices as device (device.deviceId)} + +
+

{device.name}

+

+ Connected {new Date(device.connectedAt).toLocaleString()} +

+
+ +
+ {/each} +
+{/if} diff --git a/web/src/routes/dashboard/devices/[deviceId]/+page.svelte b/web/src/routes/dashboard/devices/[deviceId]/+page.svelte new file mode 100644 index 0000000..72a0aec --- /dev/null +++ b/web/src/routes/dashboard/devices/[deviceId]/+page.svelte @@ -0,0 +1,72 @@ + + +

Device: {deviceId.slice(0, 8)}...

+ +
+
+

Send a Goal

+
+ + +
+
+ + {#if steps.length > 0} +
+
+

Steps

+
+
+ {#each steps as step (step.step)} +
+

Step {step.step}: {step.action}

+

{step.reasoning}

+
+ {/each} +
+
+ {/if} + + {#if status === 'completed'} +

Goal completed successfully.

+ {:else if status === 'failed'} +

Goal failed. Please try again.

+ {/if} +