Free-text and dictation¶
Most commands match a fixed set of phrases. A free capture is different: it records whatever you say as open text, so a command can take a search query, a message, or a spoken frequency that Amri could not know in advance.
Free capture {name...}¶
A capture ending in ... is a free capture. It does not match a word list.
The trailing text of the utterance is transcribed by the dictation engine and
stored under the capture name.
[[command]]
name = "Search"
description = "Speak a web search."
[command.trigger]
pattern = "search [for;] {query...}"
[command.response]
default = "amri.input.text('{query}')"
Say "search for nearest coffee shop". The words "search for" match the fixed
grammar prefix; "nearest coffee shop" is transcribed and stored as query. The
value is raw text with no synonym lookup and no remapping.
This is not a set capture. A set capture {name:a;b;c} matches one
of a list you write and is handled entirely by the fast command recognizer. A free
capture hands its tail to the dictation engine, which is a separate model. See
recognition and dictation for how the two engines divide the
work, and note one consequence: dictation runs slower than real time, so a
free-text command fires a few seconds after you stop speaking.
Telling Amri where the free text ends¶
The recognizer knows where the free tail begins, from the grammar prefix. It also needs to know where the tail ends. There are two ways.
A terminator word. Put a fixed word after the capture. Amri cuts the free text the moment that word is spoken.
[[command]]
name = "Set Frequency"
description = "Tune the radio to a spoken frequency."
[command.trigger]
pattern = "tune to {freq...} over"
[command.response]
default = "amri.log.info('tuning to {freq}')"
Say "tune to one two one point five over". The word over closes the capture and
is consumed, so freq holds the spoken frequency and not the closer. This suits
radio and brevity-code phrasing, where a spoken closer already ends a
transmission. Choose a terminator that is not itself a command phrase, or a stray
utterance of it will fire that command.
The grammar that follows. A terminator word is the simplest case of a more general rule: whatever grammar comes after the free capture marks where the tail closes. If nothing follows and no terminator is set, the tail closes on a short run of trailing silence instead.
A deliberate pause ends dictation early
The early cut on a terminator word applies to continuous speech only. If you pause before saying the terminator, the utterance ends at the pause. The capture is still correct, and the lone terminator word spoken afterward matches no command and is dropped.
A pattern that starts with a free capture needs push-to-talk¶
If a pattern begins with a free capture, there is no grammar prefix in front of it to mark where the free text starts.
In always-listening mode Amri cannot open this capture on its own, because nothing
tells it when you have begun. A command like this must be held behind
push-to-talk (PTT): the press opens the capture, and the release closes it. If
a leading free capture has no PTT resolved, the profile fails to load. This is
by design. The capture could never open otherwise. A capture with a grammar prefix
in front of it, like tune to {freq...} over, opens on that prefix and does not
need PTT.
The ptt field is not the push_to_talk gate¶
Two different fields are spelled similarly. They do different things, and they do not share a value.
| Field | What it does | Inheritance |
|---|---|---|
push_to_talk |
A gate. The command fires only if the named key was held during the recognized phrase. | Inherits: profile, then category, then command. |
ptt |
A free-capture bracket. Names the one binding whose press opens and whose release closes this command's dictated tail. | Per-command ptt, else the profile-level [ptt] default. No category level. |
The ptt field is a single binding name, never a list. It is what satisfies the
leading-capture rule above. The two fields are independent and may both appear on
one command: gate the phrase on one key, bracket the dictation on another, or name
the same key for both.
# Profile-level default: brackets any free capture whose command sets no ptt.
[ptt]
default = "voice_ptt"
[[command]]
name = "Send Message"
description = "Dictate a chat message."
ptt = "voice_ptt" # press opens, release closes the tail
[command.trigger]
pattern = "{message...}" # leading capture, so ptt is required
[command.response]
default = "amri.input.text('{message}')"
Both ptt and [ptt] default must name a binding defined in engine.toml. For
how the gate itself is defined and inherited, see
push-to-talk.