Package-level declarations
Types
Broad grouping for a system action, for future filtering/retrieval (§12).
One supported deterministic system action. id is the stable settings key the executor (settingAction in CommandRouter) maps to a public Android Intent.
Cycle-2 of the LLM pipeline: the model breaks an ACTION input into action→value pairs ("message mom hello on whatsapp" → open→whatsapp, message→mom "hello"); the launcher then maps the pairs onto intents deterministically here — the model names the pairs, the code decides what they execute as. Anything unmappable returns an empty plan so the caller falls back to the full decide prompt (cycle 3).
The central deterministic registry of supported system/settings actions (§12). Tier-0 routing resolves these from natural language with zero model calls and no app-list search; the LLM never produces them. Free of Android imports so it stays unit-testable in isolation.
Answers questions about the installed apps deterministically from the local index (SRS §6) — "how many music apps", "list my games" — so the LLM never has to guess a count or invent an inventory. Matching is by Android's declared app category (ApplicationInfo.CATEGORY_*), with a label-keyword fallback.
An installed app named inside the command claims the whole command ("message mummy hello on whatsapp" is a WhatsApp message, start to finish). Detection is deterministic — the code knows the installed-app list, the model doesn't: a marker phrase ("on/in/via/using
The capability catalog — the single source of truth for what the on-device model is allowed to do. Every entry is a typed template: the model only picks an action id and fills the declared slots; it never authors a raw Android Intent. Construction, validation and safety all live in Kotlin (CommandRouter), so a hallucinated or malformed reply can at worst fail to build — never fire something arbitrary.
A resolved thing the user can run — produced by the AI, rendered by the UI. The launcher does no intent parsing; the model decides, this executes.
Cheap deterministic text cleanup applied before any routing (§5.2). Keeps the original text for display; this is only for matching. It collapses whitespace and removes a repeated leading command verb ("open open developer options" → "open developer options") without stripping the primary verb that Tier-0 routing keys off, and without changing meaning.
Centralized, tunable confidence policy for app resolution (SoT §15). These are starting values, not permanent constants — keep them here (not scattered through the code) so they can be tuned from real device tests.
Functions
The allowed-actions block for the prompt, generated from the catalog.
Tier-0 deterministic router. The obvious ~70% of launcher commands — "open X", "call
The few-shot block, generated from the catalog. Uses a flat "input" -> json form (not a User:/Assistant: transcript) so a small model demonstrates the mapping without being taught to role-play extra conversation turns.
Single-intent parse kept for callers that only want the first action.
Salvages {"action":…,"value":…} objects from a noisy model reply.
Parses the model's reply into a Plan. Robust by design: it accepts a single object or a JSON array, salvages objects with a regex if the surrounding text is noisy, drops anything that doesn't map to a real capability, and coalesces redundant steps (e.g. "open whatsapp and message mom" → just the message).
Maps pairs to a Plan. An "open" pair names the app the whole command is scoped to; when a message/email pair exists it absorbs that open (messaging opens the app itself). Conservative: one unmappable pair empties the plan.