feat: installed apps, stop goal, auth fixes, remote commands

- Android: fetch installed apps via PackageManager, send to server on connect
- Android: add QUERY_ALL_PACKAGES permission for full app visibility
- Android: fix duplicate Intent import, increase accessibility retry window
- Android: default server URL to ws:// instead of wss://
- Server: store installed apps in device metadata JSONB
- Server: inject installed apps context into LLM prompt
- Server: preprocessor resolves app names from device's actual installed apps
- Server: add POST /goals/stop endpoint with AbortController cancellation
- Server: rewrite session middleware to direct DB token lookup
- Server: goals route fetches user's saved LLM config from DB
- Web: show installed apps in device detail Overview tab with search
- Web: add Stop button for running goals
- Web: replace API routes with remote commands (submitGoal, stopGoal)
- Web: add error display for goal submission failures
- Shared: add InstalledApp type and apps message to protocol
This commit is contained in:
Sanju Sivalingam
2026-02-17 22:50:18 +05:30
parent fae5fd3534
commit e300f04e13
17 changed files with 410 additions and 88 deletions

View File

@@ -1,4 +1,4 @@
import type { UIElement, DeviceInfo } from "./types.js";
import type { UIElement, DeviceInfo, InstalledApp } from "./types.js";
export type DeviceMessage =
| { type: "auth"; apiKey: string; deviceInfo?: DeviceInfo }
@@ -6,7 +6,8 @@ export type DeviceMessage =
| { type: "result"; requestId: string; success: boolean; error?: string; data?: string }
| { type: "goal"; text: string }
| { type: "pong" }
| { type: "heartbeat"; batteryLevel: number; isCharging: boolean };
| { type: "heartbeat"; batteryLevel: number; isCharging: boolean }
| { type: "apps"; apps: InstalledApp[] };
export type ServerToDeviceMessage =
| { type: "auth_ok"; deviceId: string }

View File

@@ -61,6 +61,11 @@ export interface DeviceInfo {
isCharging: boolean;
}
export interface InstalledApp {
packageName: string;
label: string;
}
export interface ScreenState {
elements: UIElement[];
screenshot?: string;