All demosIntent Launcher

Intent Launcher

A Spotlight-style command palette that re-ranks a fixed candidate list by asking the model which row you mean, whether Enter is safe, and whether you want one item or all of them.

/classify/yes-no

How it works

The macOS original fired one fan-out request per keystroke and asked Jev five typed questions about the same state: which candidate is the target, which action kind the query means, whether the query is ready to run on Enter, whether its scope is one item or all of them, and one match_cN noul per candidate. Everything else — the index, the fuzzy prefilter, the arithmetic, the time windows, the ranking — was plain Swift, and is plain TypeScript here.

Here the index is a fixture: 30 apps, the nine system toggles, the seven files and nine browser-history rows from the original's TESTING.md with their ages, and three shortcuts. Typing filters it with the ported fuzzy matcher, adds a calculator row when the text parses and a web-search row at the bottom, and keeps at most 13 rows (30 when the query names a time window). That list is on screen before any request: the model only re-ranks it.

What each judgment sends

  • target → /classify. Text is the bare query, for example "the pdf I just downloaded". Labels are one per local row, keyed c0…cN, each describing what the query would have to mean: "The query describes the file Q3-Roadmap-Review.pdf (PDF in ~/Downloads, modified 6 min ago).", "The query names the system setting \"Turn Wi-Fi Off\" (disable the wi-fi radio).", "The query is arithmetic whose answer is 36." The whole scores map becomes the percentage on every row, not just the winner. The web-search row gets no label — a label mentioning the web fallback pulls every query onto it — and none: "The query names something that is not in this list." is added only when a single local row would leave classify with one option.
  • ready → /yes-no. One statement, "The query is specific enough to run the best-matching item straight away.", with when_true: "One listed item is the obvious meaning, so running it would not surprise the user." and when_false: "Several listed items fit, so the user still has to pick one from the list." The text lists every row so the model sees the complete option set. The top row gets the green ↵ at ready ≥ 0.7, or as a rescue at P(target) ≥ 0.75 with ready ≥ 0.45, at least 0.5 of clear air to the next row's target, and a query the user has finished typing: on the pdf I just downloaded readiness hedges at 0.49 while the target distribution is 78% on the newest PDF against 11%, and a target that lonely is by construction unambiguous. Each guard is there for a measured case that must not get the badge: wifi (61% vs 37%) fails the margin, da (ready 0.35) fails the floor, and sle — which the model scores 91% on Sleep at readiness 0.57 — fails because its last word is still only a prefix of the row it matched. A launcher may not promise Enter while the user is mid-word.
  • scope → /classify, two labels: one: "The user wants exactly one specific item: a singular noun, a name, or 'the X I just ...'." and all: "The user wants every item that fits: plural nouns, all, every, the links, the files, or a period of activity like 'pages I visited today'." scores.all is P(all).
  • match_cN → /yes-no with many statements. One call replaces the original's one noul per candidate. The text is the query with the time window removed, because the window already ran in code: The user's words: "open devin ambassador links I visited". Each statement names one row by title and URL and asks what the user meant: statements: ["The page \"Introducing the Devin Ambassador Program\" (https://cognition.ai/blog/devin-ambassador-program) is what the user meant.", …] (up to 32), with when_true: "The page is what the user meant." and when_false: "The page is not what the user meant." Statement i maps back to row i. Every word of that was measured: asking whether a row "matches the query" reads as a relevance essay and scored the literal announcement page 0.18, and naming only the host made the model grade pages by whether the domain said devin, so cognition.ai lost and Hacker News crept up to 0.53. On the shipped wording the three Ambassador pages come back 0.94 / 0.83 / 0.96 and the GitHub repo, Hacker News and the milliseconds docs stay at 0.39 / 0.30 / 0.18.

Batching and cadence

The original's action question is dropped, because one fan-out request became several calls: its 0.20 ranking weight goes to fuzzy, so a row scores 0.65·P(target) + 0.35·fuzzy, plus 0.25·P(all)·P(match) for rows in the set. A plain query costs 2 calls (target, ready); a query with a plural word or a time window costs 4 (plus scope and the one batched match call). Rows with match ≥ 0.5 form the set; at P(all) ≥ 0.25 a synthetic Open all N row leads the list with its members checkmarked and P(all) beside it. A query that is only a window — everything from the past hour — costs 3: the match call is skipped, because the window filter already ran in code and every surviving dated row is a member. While a judgment is in flight the previous one stays on screen, dimmed.

Nothing fires on load. Judge this query runs one judgment; Live typing runs one per keystroke and stops itself after 60 seconds or 20 judgments, because every visitor shares one key at about 2 requests per second. If a call fails the list falls back to fuzzy order and the error shows under the palette. Execution is simulated: Dark Mode repaints the palette, the calculator row copies its result, and links or files open a list of what would have opened.

Ported from the jev-launcher Jev experiment. Every request here is live; the shared demo key allows about 2 requests per second across all visitors.