Skip to content

PR1: data-driven voice-action registry (Telegram as first built-in) - #58

Merged
initcore0 merged 1 commit into
mainfrom
feat/voice-action-registry
Jun 24, 2026
Merged

PR1: data-driven voice-action registry (Telegram as first built-in)#58
initcore0 merged 1 commit into
mainfrom
feat/voice-action-registry

Conversation

@initcore0

Copy link
Copy Markdown
Owner

First step of generalizing named voice actions. Replaces the hardcoded enum Action { case telegramPost } + actionPhrases table + single editable telegramPostPrompt with a data-driven registry, so built-in and pack/user actions share one mechanism — and packs can later add new actions (tweet, commit message…), not only retune the Telegram prompt.

This is behavior-preserving; it only adds the extensibility seam PR2 (packs) will use.

Changes

  • VoiceAction {id, displayName, triggerPhrases, prompt} + VoiceActionRegistry (allPhrases, action(id:), merging(_:) = override-by-id / append-new) in OpenWhispCore, Codable so actions can travel in a pack later. The built-in Telegram action carries the exact phrases + default prompt that used to live in AppState.
  • VoiceCommandParser: Result.action: Action?actionID: String?; matches an injected registry (default .builtins), phrases tried longest-first so a specific phrase beats a substring. Wake / imperative / generic paths unchanged.
  • AppState: applyVoiceCommand looks up the action by id and uses its prompt; new computed voiceActionRegistry overlays the user's editable telegramPostPrompt onto the builtins. defaultTelegramPostPrompt becomes an alias.
  • Adversarial review confirmed the Telegram + generic paths are behavior-identical (all 12 EN/RU phrases preserved, default prompt byte-identical, LLM directive identical in empty/default/custom cases). The only difference is a cosmetic status string ("Making Telegram post…" → "Running Telegram post…").
  • Tests: +10 (registry merge/override/codable, custom action triggers by id, longest-phrase-wins); parser tests migrated to actionID. 181 → 191.

swift test 191/191 · ./build.sh clean.

🤖 Generated with Claude Code

First step of generalizing named voice actions: replace the hardcoded
enum Action/actionPhrases + the single editable telegramPostPrompt with a
data-driven registry, so built-in and pack/user actions share one mechanism and
packs can later add NEW actions (not only retune Telegram).

- VoiceAction {id, displayName, triggerPhrases, prompt} + VoiceActionRegistry
  (allPhrases, action(id:), merging(_:) — override-by-id / append-new) in
  OpenWhispCore (Codable, so packs can carry actions later). Built-in Telegram
  action holds the exact phrases + default prompt that used to live in AppState.
- VoiceCommandParser: Result.action: Action? -> actionID: String?; matches
  against an injected registry (default .builtins), phrases tried longest-first
  so a specific phrase beats a substring. Wake/imperative/generic paths unchanged.
- AppState: applyVoiceCommand looks up the action by id and uses its prompt; new
  computed voiceActionRegistry overlays the user's editable telegramPostPrompt
  onto the builtins (empty or == default -> builtins). defaultTelegramPostPrompt
  is now an alias to VoiceAction.defaultTelegramPostPrompt.
- Adversarial review: Telegram path + generic path behavior-identical (all 12
  EN/RU phrases preserved, default prompt byte-identical, directive identical in
  empty/default/custom cases). Only change is a cosmetic status string.
- Tests: +10 (VoiceAction registry merge/override/codable, custom-action triggers
  by id, longest-phrase-wins); parser tests migrated to actionID. 181 -> 191.

No behavior change for users; this only adds the extensibility seam packs use next.

swift test 191/191; ./build.sh clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@initcore0
initcore0 merged commit a8f7f76 into main Jun 24, 2026
3 checks passed
@initcore0
initcore0 deleted the feat/voice-action-registry branch June 24, 2026 02:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant