feat: auto_target toggle, print_heard debug, more wake spellings
add behavior.auto_target (default false): with no sticky target and exactly one
session running, false requires an explicit set/target rather than guessing; true
auto-uses it. target.resolve() takes the flag. add behavior.print_heard (default
false, debug): opt-in console echo of non-wake transcripts to see how Whisper
renders the wake word. add behavior.filler_words. expand the wake list with the
spellings Whisper actually emits for the coined word ('claude do', 'claude due',
'ok claude', 'okay claude').
Signed-off-by: disqualifier <dev@disqualifier.me>
This commit is contained in:
parent
b05f6256c1
commit
d734161c97
13
config.toml
13
config.toml
@ -5,7 +5,7 @@
|
|||||||
# wake phrases for listen mode. fuzzy-matched: case/space-insensitive, lenient on
|
# wake phrases for listen mode. fuzzy-matched: case/space-insensitive, lenient on
|
||||||
# the coined word "claudedo" (whisper renders it inconsistently). number words are
|
# the coined word "claudedo" (whisper renders it inconsistently). number words are
|
||||||
# normalized to digits before command matching.
|
# normalized to digits before command matching.
|
||||||
phrases = ["claudedo", "hey claude"]
|
phrases = ["claudedo", "claude do", "claude due", "hey claude", "ok claude", "okay claude"]
|
||||||
|
|
||||||
[input]
|
[input]
|
||||||
# "listen" (default): continuous capture; only acts on utterances that start with a
|
# "listen" (default): continuous capture; only acts on utterances that start with a
|
||||||
@ -55,3 +55,14 @@ match_threshold = 0.8
|
|||||||
# "select yes" / "use yes" behave like "yes". (a filler word followed by a digit is
|
# "select yes" / "use yes" behave like "yes". (a filler word followed by a digit is
|
||||||
# the select command, e.g. "select 1", and is not dropped.)
|
# the select command, e.g. "select 1", and is not dropped.)
|
||||||
filler_words = ["select", "use", "choose"]
|
filler_words = ["select", "use", "choose"]
|
||||||
|
# when no sticky target is set and exactly ONE claude-* session is running:
|
||||||
|
# false (default) -> require an explicit `set <name>` or one-shot `target <name>`;
|
||||||
|
# a bare command does nothing and tells you to set one.
|
||||||
|
# true -> auto-target that single session (convenience).
|
||||||
|
auto_target = false
|
||||||
|
# DEBUG ONLY — relaxes the privacy invariant. when true, the daemon console prints
|
||||||
|
# the raw transcript of EVERY utterance, including non-wake speech it would otherwise
|
||||||
|
# drop silently (shown as `heard (dropped): "<transcript>"`). use it to see exactly
|
||||||
|
# how Whisper renders your wake word, then turn it OFF. default false: non-wake speech
|
||||||
|
# is discarded without ever printing the transcript.
|
||||||
|
print_heard = false
|
||||||
|
|||||||
@ -50,6 +50,8 @@ class Config:
|
|||||||
type_autosend: bool
|
type_autosend: bool
|
||||||
match_threshold: float
|
match_threshold: float
|
||||||
filler_words: tuple[str, ...]
|
filler_words: tuple[str, ...]
|
||||||
|
auto_target: bool
|
||||||
|
print_heard: bool
|
||||||
source_path: Path | None = field(default=None)
|
source_path: Path | None = field(default=None)
|
||||||
|
|
||||||
|
|
||||||
@ -118,6 +120,8 @@ def load_config(explicit: str | os.PathLike | None = None) -> Config:
|
|||||||
match_threshold=float(_require(raw, "behavior", "match_threshold", (int, float), 0.8)),
|
match_threshold=float(_require(raw, "behavior", "match_threshold", (int, float), 0.8)),
|
||||||
filler_words=tuple(_require(raw, "behavior", "filler_words", (list,),
|
filler_words=tuple(_require(raw, "behavior", "filler_words", (list,),
|
||||||
["select", "use", "choose"])),
|
["select", "use", "choose"])),
|
||||||
|
auto_target=bool(_require(raw, "behavior", "auto_target", (bool,), False)),
|
||||||
|
print_heard=bool(_require(raw, "behavior", "print_heard", (bool,), False)),
|
||||||
source_path=path,
|
source_path=path,
|
||||||
)
|
)
|
||||||
if not 0.0 < cfg.match_threshold <= 1.0:
|
if not 0.0 < cfg.match_threshold <= 1.0:
|
||||||
|
|||||||
@ -85,7 +85,7 @@ def list_sessions() -> list[str]:
|
|||||||
return sorted(n for n in names if n.startswith(SESSION_PREFIX))
|
return sorted(n for n in names if n.startswith(SESSION_PREFIX))
|
||||||
|
|
||||||
|
|
||||||
def resolve(one_shot: str | None = None) -> tuple[str | None, str]:
|
def resolve(one_shot: str | None = None, auto_target: bool = False) -> tuple[str | None, str]:
|
||||||
"""resolve the destination session and a short reason describing the choice.
|
"""resolve the destination session and a short reason describing the choice.
|
||||||
|
|
||||||
single source of truth for targeting, used by both the voice and CLI paths.
|
single source of truth for targeting, used by both the voice and CLI paths.
|
||||||
@ -95,7 +95,9 @@ def resolve(one_shot: str | None = None) -> tuple[str | None, str]:
|
|||||||
1. one-shot present -> claude-<name> for THIS command only; never falls through
|
1. one-shot present -> claude-<name> for THIS command only; never falls through
|
||||||
to a different session if it doesn't exist (explicit beats convenience).
|
to a different session if it doesn't exist (explicit beats convenience).
|
||||||
2. sticky set + exists -> use it.
|
2. sticky set + exists -> use it.
|
||||||
3. nothing sticky, exactly one claude-* session -> auto-use it.
|
3. nothing sticky, exactly one claude-* session:
|
||||||
|
auto_target=True -> auto-use it;
|
||||||
|
auto_target=False -> require an explicit set/target, do nothing.
|
||||||
4. nothing sticky, multiple sessions -> ambiguous, do nothing.
|
4. nothing sticky, multiple sessions -> ambiguous, do nothing.
|
||||||
5. nothing sticky, zero sessions -> do nothing.
|
5. nothing sticky, zero sessions -> do nothing.
|
||||||
"""
|
"""
|
||||||
@ -113,7 +115,9 @@ def resolve(one_shot: str | None = None) -> tuple[str | None, str]:
|
|||||||
|
|
||||||
sessions = list_sessions()
|
sessions = list_sessions()
|
||||||
if len(sessions) == 1:
|
if len(sessions) == 1:
|
||||||
|
if auto_target:
|
||||||
return sessions[0], f"auto-target {sessions[0]} (only session)"
|
return sessions[0], f"auto-target {sessions[0]} (only session)"
|
||||||
|
return None, f"no target set ({sessions[0]} running — set one)"
|
||||||
if len(sessions) > 1:
|
if len(sessions) > 1:
|
||||||
return None, f"no target set, {len(sessions)} sessions (set one)"
|
return None, f"no target set, {len(sessions)} sessions (set one)"
|
||||||
return None, "no claude sessions"
|
return None, "no claude sessions"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user