Command Parser
Extracts and executes embedded bracket actions from Luna's responses, plus intent parsing helpers for launch, map, Spotify, and research requests.
Overview
When Luna produces a response it may embed action commands inside square brackets — [LAUNCH:chrome], [BROWSE:https://...],[TASK:Buy milk|2025-06-01|low], etc. The command parser extracts these, and the executor carries them out.
| Module | Contents |
|---|---|
command_parser/commands.py | parse_commands(), execute_commands(). |
command_parser/away.py | user_is_leaving(), response_is_farewell(). |
command_parser/intents.py | parse_user_launch_request(), parse_user_map_request(), parse_user_spotify_request(). |
command_parser/research.py | extract_direct_research_query(), extract_direct_dataset_query(). |
command_parser/coding.py | is_coding_request(). |
parse_commands()
Scans Luna's response text for embedded bracket commands and returns a list of parsed command dicts. Does not execute them.
def parse_commands(
response: str,
user_message: str = "",
) -> list[dict]from backend.services.command_parser import parse_commands
response = "Sure! [LAUNCH:spotify] [TASK:Buy milk|2025-06-01|low]"
cmds = parse_commands(response)
# [
# {"type": "launch", "app": "spotify"},
# {"type": "task", "title": "Buy milk", "due": "2025-06-01", "priority": "low"},
# ]execute_commands()
Takes the list returned by parse_commands() and executes each command. Side effects: launching apps, opening URLs, writing to the database, calling Spotify, setting away state.
def execute_commands(
commands: list[dict],
db: Session,
conversation_id: int,
) -> Nonefrom backend.services.command_parser import parse_commands, execute_commands
from backend.models.database import SessionLocal
db = SessionLocal()
cmds = parse_commands(luna_response, user_message)
execute_commands(cmds, db, conversation_id=42)
db.close()execute_commands() are silently swallowed per command — one failing command doesn't block the others. Check logs if an action doesn't seem to execute.Bracket syntax reference
Luna's system prompt teaches it to embed these brackets. Each is parsed by parse_commands():
| Bracket | Command type | Fields |
|---|---|---|
[AWAY] | away | action: "on", label: "away"|"bedtime" |
[BROWSE:https://...] | browse | url — blocked for weather/finance/crypto sites |
[MAP:search:query] | map | action: "search", query |
[MAP:route:destination] | map | action: "route", query |
[MAP:close] | map | action: "close" |
[SPOTIFY:query] | spotify | query |
[SPOTIFY:queue query] | spotify_queue | query |
[LAUNCH:app name] | launch | app |
[WIDGET:kind|title|body] | widget | kind, title, body |
[TASK:title|due?|priority?] | task | title, due (ISO date, optional), priority (default: medium) |
[EVENT:title|datetime|duration?] | event | title, datetime (ISO), duration (minutes, default: 60) |
Browse blocklist
URLs matching weather, finance, or crypto domains are blocked from the[BROWSE] command (Luna is not supposed to open live data pages automatically). Affected domains include weather.com,finance.yahoo.com, coinmarketcap.com, and others.
Away detection
The away.py module provides two helper predicates used byparse_commands() and the chat pipeline:
def user_is_leaving(message: str) -> bool
def response_is_farewell(response: str) -> boolIf the user's message contains farewell phrases ("going to bed","see you later", "taking a break", …) or Luna's response is itself a farewell, an [AWAY] command is emitted with label"bedtime" when bed-related words are present, otherwise "away".
personal variant (LUNA_VARIANT=personal).Intent parsing
These helpers are used by the chat router before sending messages to the LLM, to decide whether to route to a specialised handler:
def parse_user_launch_request(message: str) -> str | None
# Returns the app name to launch, or None
def parse_user_map_request(message: str) -> dict | None
# Returns {"action": "search"|"route", "query": str} or None
def parse_user_spotify_request(message: str) -> dict | None
# Returns {"action": "play"|"pause"|"next"|"prev", "query": str | None} or Nonefrom backend.services.command_parser import (
parse_user_launch_request,
parse_user_map_request,
parse_user_spotify_request,
)
parse_user_launch_request("open notepad") # "notepad"
parse_user_map_request("directions to the gym") # {"action": "route", "query": "the gym"}
parse_user_spotify_request("play some jazz") # {"action": "play", "query": "jazz"}Research query extraction
def extract_direct_research_query(message: str) -> str | None
# Detects explicit research requests ("research X", "look up X", "find info on X")
def extract_direct_dataset_query(message: str) -> str | None
# Detects dataset requests ("find a dataset of X", "get CSV data about X")These are used by the chat router to bypass the main LLM and call the research skill directly when the user's intent is unambiguous.
Coding request detection
def is_coding_request(message: str) -> boolReturns True when the message is clearly a code-writing, debugging, or technical explanation request. Used by the chat router to redirect to the coding agent rather than the general chat pipeline.
from backend.services.command_parser import is_coding_request
is_coding_request("write a Python function to parse JSON") # True
is_coding_request("what should I have for lunch?") # False