Repository navigation
feat(ai): add a say command that speaks any text - #236
Merged
Merged
Conversation
added 5 commits
October 16, 2026 14:58
`./stack ai say "<text>"` speaks the text on this Mac through the ai stacklet's speech server, in the default voice for `[ai] language` (the same rule as `./stack ai hello`). `--voice <name>` picks one of the voices in the speech server's voice map. An unknown voice is refused with the list of voices, and a speech server that does not answer is reported with `./stack up ai` as the fix. With `--json` the result names the voice that spoke. The shared TTS helper is split into synthesize and play so the command can tell those failures apart; `speak()` keeps its behaviour for `./stack ai intro`. `STACK_SPEECH_URL` points the helper at another speech server, which the tests use for a stand-in.
The driver tests put `tests/driver` on `sys.path` and kept its modules in `sys.modules` for the rest of the run. Their bare names clash with stacklet helpers: a later `stack ai say` test imported the driver's `speech` instead of the ai stacklet's. The test file now removes the path and forgets the driver modules once it has imported them.
The help line is also what the agent reads for an allowed command, so it now says how to write the text: plain sentences, no markdown, lists, links or emoji. The speech server reads markdown marks aloud.
The say command printed "Speaking as <voice>" before the request, so an unreachable speech server showed that line followed by the error.
Speaking is one of the agent's own abilities, like a memory lookup, so `ai say` joins the core API's built-in commands instead of needing an `[agent] allow` entry. The rest of the ai stacklet (`ai switch`, `ai download`) stays out of the agent's reach. An always-loaded skill tells the agent when to speak and how to write for the ear: plain sentences, no markdown, private content only when its owner asks, and a note in chat of what was said.
5 tasks
This was referenced Oct 16, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
./stack ai say "<text>"speaks any text on this Mac through the ai stacklet's speech server, in the default voice for[ai] language;--voice <name>picks one of the voices in the speech server's voice map. An unknown voice, no text, or a speech server that does not answer is refused with what to do, and nothing plays.ai sayjoins the core API's built-in commands, like the memory lookups, so it needs no[agent] allowentry.ai switchandai downloadstay out of its reach. An always-loaded skill tells it to write plain spoken sentences (the speech server reads markdown marks aloud), to read private content aloud only when its owner asks, and to say in chat what it said../stack ai helloand./stack ai introare unchanged.