Repository navigation
Update tagline: Summon your AI superpower - #44
Merged
Merged
Conversation
GitHub description + README: "Summon your AI superpower — voice, vision, and autonomous action" Web UI: "Summon your AI superpower" Removed "on your Mac" (sounds platform-limited) and added "Summon" (the signature command). Per owner direction. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This was referenced Apr 20, 2026
sonichi
added a commit
that referenced
this pull request
Apr 20, 2026
…, #44) (#486) Two clear-text-logging alerts both involved slice()-ing a sensitive env var and printing the substring. CodeQL's taint model treats any substring as clear-text-logging of the secret, even when the exposed bytes are trivial (public prefix, last 2 digits). - `src/voice-agent.ts:66` — GEMINI_API_KEY / GEMINI_VOICE_API_KEY startup assertion printed the first 4 chars ("AIza" for valid keys). Replaced with a boolean "prefix matches AIza? yes/no" — same diagnostic signal (detects truncated paste + wrong-var), no taint flow. - `skills/phone-conversation/scripts/conversation-server.ts:1625` — Phone-server banner printed a masked TWILIO_PHONE_NUMBER (first 2 + last 2). Replaced with presence-only signal "configured" / "MISSING". Inspect via `env | grep TWILIO_PHONE_NUMBER` if needed. Both are startup-banner context; no runtime or debugging impact. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3 of 4 tasks
liususan091219
added a commit
that referenced
this pull request
Apr 21, 2026
…-logging) (#493) ## #43 js/resource-exhaustion (src/web-client.ts:2549) #489's `Math.min(ttl, MAX_TTL_MS)` is an `isNumericFlowStep` (numeric passthrough) in `codeql/javascript-all@2.6.27` — it narrows the value but doesn't register as a sanitizer. The `js/resource-exhaustion` config only blocks taint via `UpperBoundsCheckSanitizerGuard`, which matches `RelationalComparison` AST nodes (`<`, `<=`, `>`, `>=`). Rewrote the clamp as `ttl <= MAX_TTL_MS ? ttl : MAX_TTL_MS` — semantically identical, but CodeQL now sees `ttl` as the lesser operand in a `<=` comparison and blocks taint in the true branch. ## #44 js/clear-text-logging (src/voice-agent.ts:71) The `${value.length}` and `${prefixOk}` interpolations in `console.error` both read properties of `value`. The env var `GEMINI_API_KEY` triggers `HeuristicNames` → tainted source; `allowImplicitRead` in the cleartext config pulls any property of a tainted value into the logger sink. #486 stopped echoing substrings but the length + ternary-prefix diagnostic still flow the taint. Dropped those two interpolations from the log; kept the name, expected format ("AIza..." 35-60 chars), and remediation URL. Diagnostic loss is minor — a malformed key always needs to be regenerated anyway. ## Verification Local CodeQL CLI 2.25.2 + codeql/javascript-queries@2.3.7: - main (dc7bfbe): 2 alerts (resource-exhaustion @ web-client.ts:2549, clear-text-logging @ voice-agent.ts:71) - this branch: 0 alerts `npx tsc --noEmit` clean. Closes #43, #44. Together with #492 (merged earlier this session), this zeroes the CodeQL security-code-scanning queue. Co-authored-by: Xueqing Liu <xueqingliu@Xueqings-Mac-Studio.local> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3 tasks
sonichi
pushed a commit
that referenced
this pull request
May 15, 2026
Layers the original PR #44 CTA verb back into README hero + web-client tagline without removing the PR #666 "My AI Stand" brand line. Why now: Robin Li keynoted Baidu Create 2026 on 2026-05-14 framing the personal-AI category as "the rise of super individuals" — restores the verb-pair (summon + superpower) at the moment that discourse window opened, ahead of Observe Summit (June 4). Diff is surgical: - README hero gains one bolded CTA line under the brand line - web-client.ts:649 tagline becomes "My AI Stand · Summon your AI superpower" (the dynamic stand-identity branch at :590-591 still overrides this with the named-Stand origin once the user names their Stand) Per owner pick A (layer, not replace) from 2026-05-15 16:06. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
sonichi
added a commit
that referenced
this pull request
May 15, 2026
…tagline (#718) * feat(framing): add "Summon your AI superpower" CTA layer Layers the original PR #44 CTA verb back into README hero + web-client tagline without removing the PR #666 "My AI Stand" brand line. Why now: Robin Li keynoted Baidu Create 2026 on 2026-05-14 framing the personal-AI category as "the rise of super individuals" — restores the verb-pair (summon + superpower) at the moment that discourse window opened, ahead of Observe Summit (June 4). Diff is surgical: - README hero gains one bolded CTA line under the brand line - web-client.ts:649 tagline becomes "My AI Stand · Summon your AI superpower" (the dynamic stand-identity branch at :590-591 still overrides this with the named-Stand origin once the user names their Stand) Per owner pick A (layer, not replace) from 2026-05-15 16:06. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(framing): align CTA pronoun to first-person ("my", not "your") Hero is otherwise first-person — "when I'm engaged", "Learns my patterns", "Runs across my Macs" — so the JoJo Stand voice is the user claiming their Stand. "Summon your AI superpower" broke that voice; "Summon my AI superpower" restores it. Per owner direction in PR #718 review thread. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Chi <wangchi@Chis-Mac-mini.local> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
liususan091219
pushed a commit
to liususan091219/sutando-fork
that referenced
this pull request
May 28, 2026
GitHub description + README: "Summon your AI superpower — voice, vision, and autonomous action" Web UI: "Summon your AI superpower" Removed "on your Mac" (sounds platform-limited) and added "Summon" (the signature command). Per owner direction. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
liususan091219
pushed a commit
to liususan091219/sutando-fork
that referenced
this pull request
May 28, 2026
…onichi#24, sonichi#44) (sonichi#486) Two clear-text-logging alerts both involved slice()-ing a sensitive env var and printing the substring. CodeQL's taint model treats any substring as clear-text-logging of the secret, even when the exposed bytes are trivial (public prefix, last 2 digits). - `src/voice-agent.ts:66` — GEMINI_API_KEY / GEMINI_VOICE_API_KEY startup assertion printed the first 4 chars ("AIza" for valid keys). Replaced with a boolean "prefix matches AIza? yes/no" — same diagnostic signal (detects truncated paste + wrong-var), no taint flow. - `skills/phone-conversation/scripts/conversation-server.ts:1625` — Phone-server banner printed a masked TWILIO_PHONE_NUMBER (first 2 + last 2). Replaced with presence-only signal "configured" / "MISSING". Inspect via `env | grep TWILIO_PHONE_NUMBER` if needed. Both are startup-banner context; no runtime or debugging impact. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
liususan091219
added a commit
to liususan091219/sutando-fork
that referenced
this pull request
May 28, 2026
… (clear-text-logging) (sonichi#493) ## sonichi#43 js/resource-exhaustion (src/web-client.ts:2549) sonichi#489's `Math.min(ttl, MAX_TTL_MS)` is an `isNumericFlowStep` (numeric passthrough) in `codeql/javascript-all@2.6.27` — it narrows the value but doesn't register as a sanitizer. The `js/resource-exhaustion` config only blocks taint via `UpperBoundsCheckSanitizerGuard`, which matches `RelationalComparison` AST nodes (`<`, `<=`, `>`, `>=`). Rewrote the clamp as `ttl <= MAX_TTL_MS ? ttl : MAX_TTL_MS` — semantically identical, but CodeQL now sees `ttl` as the lesser operand in a `<=` comparison and blocks taint in the true branch. ## sonichi#44 js/clear-text-logging (src/voice-agent.ts:71) The `${value.length}` and `${prefixOk}` interpolations in `console.error` both read properties of `value`. The env var `GEMINI_API_KEY` triggers `HeuristicNames` → tainted source; `allowImplicitRead` in the cleartext config pulls any property of a tainted value into the logger sink. sonichi#486 stopped echoing substrings but the length + ternary-prefix diagnostic still flow the taint. Dropped those two interpolations from the log; kept the name, expected format ("AIza..." 35-60 chars), and remediation URL. Diagnostic loss is minor — a malformed key always needs to be regenerated anyway. ## Verification Local CodeQL CLI 2.25.2 + codeql/javascript-queries@2.3.7: - main (dc7bfbe): 2 alerts (resource-exhaustion @ web-client.ts:2549, clear-text-logging @ voice-agent.ts:71) - this branch: 0 alerts `npx tsc --noEmit` clean. Closes sonichi#43, sonichi#44. Together with sonichi#492 (merged earlier this session), this zeroes the CodeQL security-code-scanning queue. Co-authored-by: Xueqing Liu <xueqingliu@Xueqings-Mac-Studio.local> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
liususan091219
pushed a commit
to liususan091219/sutando-fork
that referenced
this pull request
May 28, 2026
…tagline (sonichi#718) * feat(framing): add "Summon your AI superpower" CTA layer Layers the original PR sonichi#44 CTA verb back into README hero + web-client tagline without removing the PR sonichi#666 "My AI Stand" brand line. Why now: Robin Li keynoted Baidu Create 2026 on 2026-05-14 framing the personal-AI category as "the rise of super individuals" — restores the verb-pair (summon + superpower) at the moment that discourse window opened, ahead of Observe Summit (June 4). Diff is surgical: - README hero gains one bolded CTA line under the brand line - web-client.ts:649 tagline becomes "My AI Stand · Summon your AI superpower" (the dynamic stand-identity branch at :590-591 still overrides this with the named-Stand origin once the user names their Stand) Per owner pick A (layer, not replace) from 2026-05-15 16:06. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(framing): align CTA pronoun to first-person ("my", not "your") Hero is otherwise first-person — "when I'm engaged", "Learns my patterns", "Runs across my Macs" — so the JoJo Stand voice is the user claiming their Stand. "Summon your AI superpower" broke that voice; "Summon my AI superpower" restores it. Per owner direction in PR sonichi#718 review thread. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Chi <wangchi@Chis-Mac-mini.local> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
liususan091219
added a commit
that referenced
this pull request
Oct 7, 2026
…p the local copy Review: the Transcribe Live provider is a common component, not a Sutando one. It moves to bodhi in randombet/bodhi_realtime_agent#44. voice-agent now imports it from bodhi-realtime-agent. Its tests moved with it. This does not compile against bodhi 0.4.0. It needs the bodhi release that contains #44, and the dependency bump to that version lands here once it is published. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
liususan091219
added a commit
that referenced
this pull request
Oct 8, 2026
…ve (replaces the prompt-only mode) (#5184) * feat(voice): meeting mode transcribes via Gemini Transcribe Live on bodhi dictation mode switch_mode("meeting") now puts the bodhi session into transcription mode: the voice model is quiesced, gemini-3.5-transcribe-live transcribes the mic, and each final line is appended to notes/meeting-<date>.md. An exit phrase ("Sutando, come back", "meeting is over", "end meeting", ...) or the menu-bar toggle returns to agent mode. GeminiLiveTranscribeSTTProvider implements bodhi's STTProvider over the Live API WebSocket and rotates sessions before the 10-minute cap, handing over at a speech pause so no word is split across sessions. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * docs(src-map): index the meeting dictation modules Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(voice): hint Transcribe Live with the name Sutando so the exit phrase is heard Live test on xueqing: "Sutando, come back" was transcribed as "Siddhartha comeback", "Siddhant will come back", "Sutanu", so meeting mode never exited. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat(voice): meeting mode is dictation only; remove the prompt-only meeting mode Owner: two meeting modes is confusing; "switch to meeting mode" means dictation. - switch_mode("meeting") always enters bodhi dictation; the old instruction (stay silent, call save_meeting_note every 5-10 min) is gone. - save_meeting_note is removed. - The meeting prompts (tool list, critical rules, greeting, reconnect hint, base-mode marker) now describe dictation: the model does not hear the meeting. - Zoom detection at startup and summon/join_zoom/join_gmeet no longer turn on meeting mode by themselves: under dictation the agent could not hear the user in a summoned call. Meeting mode starts only when asked. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(voice): enter meeting dictation after the spoken confirmation, not 1.5 s after switch_mode Live on xueqing the confirmation "I have switched to meeting mode." completed about 1 s after dictation had already quiesced audio output, so it was never heard and the owner could not tell whether transcription had started. Entry now waits for the turn after the one carrying switch_mode, with an 8 s fallback. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(voice): carry the meeting transcript back into the agent when meeting mode ends Dictation keeps the meeting out of the voice model's context, so after "Sutando, come back" the agent knew only the note's path and line count, and could not answer questions about what was said. Exiting now injects this meeting's lines (from entering meeting mode to leaving it), framed as data, not as user speech or an instruction. A meeting longer than 30k characters carries its end, and the agent is told the full text is in the note. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * refactor(voice): take GeminiLiveTranscribeSTTProvider from bodhi, drop the local copy Review: the Transcribe Live provider is a common component, not a Sutando one. It moves to bodhi in randombet/bodhi_realtime_agent#44. voice-agent now imports it from bodhi-realtime-agent. Its tests moved with it. This does not compile against bodhi 0.4.0. It needs the bodhi release that contains #44, and the dependency bump to that version lands here once it is published. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * test(voice): type the meeting-dictation stub provider instead of any The meeting-dictation tests used `const provider: any`. ESLint's no-explicit-any is an error in this file, which failed the lint job. They now use a StubProvider that implements STTProvider, plus a say() helper that delivers a final line. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(voice): leave meeting mode only on a deliberate exit command Review: an exit phrase anywhere in a segment ended the meeting. For example, "Do not stop dictation until we finish the budget review." recorded "Do not" and switched to agent mode, and discussing how to "end the meeting" did the same. A segment now exits only when its last exit phrase ends the segment (trailing please/now/thanks aside) and the segment either - is only that command, apart from fillers like "okay" and "hi", or - addresses it to Sutando ("..., Sutando, end the meeting"). Meeting speech before an addressed command is still recorded. A segment of only fillers before it is no longer written to the note (the stray "Hi" line). "Switch back to active mode" counts as one command. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * build(deps): bodhi-realtime-agent 0.4.1, which exports GeminiLiveTranscribeSTTProvider 0.4.1 includes randombet/bodhi_realtime_agent#44, the Transcribe Live provider that voice-agent now imports, and #42 (function-call behavior). This clears the TS2305 import error and the bundle-smoke failure. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * refactor(voice): meeting notes subscribe to bodhi's dictation transcripts Review: attachMeetingDictation captured provider.onTranscript and replaced it after VoiceSession was built, taking over a callback that bodhi's DictationController owns. bodhi 0.4.2 adds VoiceSession.onDictationTranscript (randombet/bodhi_realtime_agent#46). Meeting dictation now subscribes there instead: - bodhi buffers each final before telling listeners, so the bufferSink hand-off is gone; - partials are ignored; - the provider is no longer passed in. Bumps bodhi-realtime-agent to 0.4.2. That release also takes over the provider's onPartialTranscript, so nothing in sutando may set it any more. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(voice): serialize meeting enter/exit; carry the exit request; report unsaved lines Review (Blue, reproduced against the real VoiceSession): enter() and exit() changed notePath and lines outside bodhi's mode queue, so mode switches that raced lost state. - Exiting while entry was still starting the transcriber left the session in transcription. - Entering during an unfinished exit kept transcription on with notePath=null. Enter and exit now run one at a time, each after the previous one's mode switch has settled. A failed entry clears its note state and rethrows, so the caller rolls back and can retry. The other review notes: - An exit command addressed to Sutando may carry a request ("Sutando, come back and summarize"). It exits, and the request is passed to the agent. - Lines that could not be appended still reach the agent. The exit message then says the notes are incomplete, not that they are saved. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix(voice): keep CJK and numbers as meeting speech; address Sutando only at a sentence start - isFiller tokenizes on Unicode letters/numbers, so CJK text and numbers are never filler: they stay in the note and cannot make a mention an exit. - An addressed command counts only at the start of a sentence; a request is carried only when joined with "and"/"then". A further sentence after the command is recorded as meeting speech, not passed as a request. A mid-sentence mention ("We said Sutando come back online and ...") stays in the meeting. - The note and transcript heading are written once transcription is on (or with the first line), so a failed entry leaves no orphan heading. - Only the latest entry's failure turns meeting mode off. - Log when the transcript cannot be injected into the session. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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
Per owner direction — removed "on your Mac" (sounds platform-limited), added "Summon" (signature command).
Test plan
🤖 Generated with Claude Code