Skip to content

vitorqf/luna

Repository files navigation

Luna

Luna is a self-hosted virtual assistant for homelabs. It routes natural-language commands to registered devices (agents), executes local actions on them, and returns structured success/failure feedback to a web UI. Current status: MVP through Slice 52 (resilient agent reconnect runtime).

Tech Stack

  • Language: TypeScript, Node.js 20+ (npm workspaces monorepo)
  • Server: Node.js, WebSocket (ws), REST, UDP discovery
  • Web: Next.js
  • Agent runtime: Node.js device executor, publishable as a standalone CLI (@vitorqf/luna-agent)
  • Validation: Zod
  • Testing: Vitest
  • Packaging: Docker (embedded server + web artifact)

Features

  • Natural-language command parsing (rule-based, targets Portuguese phrasing) for open_app, notify, set_volume, and play_media
  • Command dispatch to registered devices over WebSocket, with local execution and structured success/failure responses (invalid_params, unsupported_intent, execution_error)
  • Device presence tracking (online/offline) with heartbeat timeout and safe reconnect handling for the same device id
  • Agent discovery via UDP announce, plus a REST-based approval flow before a discovered agent becomes a known device
  • Capability-based dispatch validation before sending a command to a device
  • In-memory command history exposed via REST
  • Publishable agent CLI package and a Docker image bundling server + embedded web

Architecture

flowchart LR
  UI["Luna Web (Next.js)"] -->|REST| S["Luna Server (Node.js + WS + HTTP)"]
  S -->|WebSocket command.dispatch| A["Luna Agent (Node.js)"]
  A -->|WebSocket command.ack| S
  A -->|UDP announce| S
  S -->|REST data| UI
Loading

Monorepo layout:

apps/
  server/          # REST + WebSocket + discovery runtime
  web/             # Next.js chat/dashboard UI
  agent/           # Device runtime and local command executors
packages/
  shared-types/    # Cross-app domain types
  protocol/        # WebSocket and UDP message contracts
  command-parser/  # Rule-based natural-language parser

Getting Started

Requirements

  • Node.js 20+
  • npm

Setup

npm install
cp .env.example .env

Key environment variables (see .env.example for the full list):

Variable Description
LUNA_SERVER_HOST / LUNA_SERVER_PORT Server bind address (default 127.0.0.1:4000)
LUNA_AGENT_SERVER_URL WebSocket URL the agent connects to
LUNA_AGENT_DEVICE_ID / _NAME / _HOSTNAME Device identity used by the agent
NEXT_PUBLIC_LUNA_SERVER_URL Base URL used by the web app (empty for same-origin embedded builds)

Run in development

# Terminal 1
npm run start:server

# Terminal 2
npm run start:agent

# Terminal 3
npm run start:web

Open the web UI at http://127.0.0.1:3000.

Run with Docker (embedded server + web)

npm run docker:build:server
npm run docker:run:server

Serves both from http://127.0.0.1:4000.

Testing

npm run test
npm run typecheck

HTTP API

Method Path Purpose
GET /devices List registered devices
GET /commands List command history
GET /discovery/agents List discovered (not yet approved) agents
POST /commands Submit a natural-language command ({ "rawText": "..." })
PATCH /devices/:id Rename a device alias
POST /discovery/agents/:id/approve Approve a discovered agent as a known device

Contributing

Follow AGENTS.md (TDD-first, one slice at a time). Use Conventional Commits, e.g. feat(agent): add executable packaging bootstrap.

About

Self-hosted virtual assistant for homelabs: routes natural-language commands to registered device agents over WebSocket and returns structured success/failure feedback.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages