Repository navigation
Fix duplicate Discord DMs + phone transcript dedup - #43
Merged
Merged
Conversation
On Gemini reconnect, conversationContext.items could reset or re-populate history, causing turn.end to re-process already-transcribed items. Now tracks a lastProcessedIdx that resets on context shrink, plus deduplicates against the last recorded transcript entry. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
If the caller repeats a request (e.g. Gemini reconnected and they ask again), return the cached result instantly instead of creating a new task and making them wait. Cache is per-call session. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Discord gateway can replay events on reconnect, creating duplicate task files and duplicate DM replies. Now tracks seen message IDs to skip already-processed messages. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
sonichi
approved these changes
Mar 30, 2026
sonichi
left a comment
Owner
There was a problem hiding this comment.
LGTM — task dedup via cache for phone calls, message ID dedup for Discord DMs, transcript dedup on reconnect. All needed fixes.
liususan091219
added a commit
that referenced
this pull request
Apr 1, 2026
The same PR #43 commit also dropped {attachment_note} from the task text, so Discord messages with file attachments lost the attachment reference. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2 of 3 tasks
liususan091219
added a commit
that referenced
this pull request
Apr 1, 2026
* Fix watcher reliability: replace fswatch with persistent polling fswatch -1 exits after one event and dies silently, causing tasks to pile up for hours. Replace with a 2s polling loop that never exits — catches tasks within 2 seconds regardless of fswatch state. Fixes 8-minute phone task delays and missed Discord messages. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Fix Discord bridge NameError: msg_text → text The bridge received DMs but silently crashed when writing task files because line 273 referenced `msg_text` (undefined) instead of `text`. Every Discord DM task was lost with no error logged. Also improved health check to detect stale bridge logs (>5min). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Restore attachment_note in Discord task file The same PR #43 commit also dropped {attachment_note} from the task text, so Discord messages with file attachments lost the attachment reference. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Revert watcher to fswatch + add mkdir -p safety The polling watcher broke task-notifications (never exits = never notifies). Restore main's fswatch version which exits on detection. Add mkdir -p for tasks/ and results/calls/ at startup. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Add tests/ to .gitignore for local test creation Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Remove health check change — covered by PR #71 PR #71 has a more comprehensive health check fix (heartbeat files, multi-process detection, stale log check). Remove overlap from this PR. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- 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
…ion) (#489) CodeQL alert #43 (js/resource-exhaustion, warning): the `ttl_ms` query parameter on /mute-state?state=seeing flowed directly into setTimeout's duration. Existing guard only checked `isFinite && > 0`, not an upper bound — an unbounded ttl_ms would schedule a long-lived timer per request (cheap-to-allocate DoS). Fix: clamp with Math.min(ttl, 60000). The "seeing" overlay is UI flash feedback (1.5-3s typical from `screen-capture-server.py`); nothing legitimate needs a minute-plus timer. Default still 3000ms. Closes the CodeQL queue: 15 alerts across 4 PRs (#485, #486, #487, #488, this PR #489). 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>
liususan091219
added a commit
to liususan091219/sutando-fork
that referenced
this pull request
May 28, 2026
* Phone server: fix duplicate transcript messages across reconnects On Gemini reconnect, conversationContext.items could reset or re-populate history, causing turn.end to re-process already-transcribed items. Now tracks a lastProcessedIdx that resets on context shrink, plus deduplicates against the last recorded transcript entry. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Phone server: cache task results to avoid duplicate work If the caller repeats a request (e.g. Gemini reconnected and they ask again), return the cached result instantly instead of creating a new task and making them wait. Cache is per-call session. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Discord bridge: deduplicate messages using message.id Discord gateway can replay events on reconnect, creating duplicate task files and duplicate DM replies. Now tracks seen message IDs to skip already-processed messages. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
liususan091219
added a commit
to liususan091219/sutando-fork
that referenced
this pull request
May 28, 2026
…ichi#72) * Fix watcher reliability: replace fswatch with persistent polling fswatch -1 exits after one event and dies silently, causing tasks to pile up for hours. Replace with a 2s polling loop that never exits — catches tasks within 2 seconds regardless of fswatch state. Fixes 8-minute phone task delays and missed Discord messages. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Fix Discord bridge NameError: msg_text → text The bridge received DMs but silently crashed when writing task files because line 273 referenced `msg_text` (undefined) instead of `text`. Every Discord DM task was lost with no error logged. Also improved health check to detect stale bridge logs (>5min). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Restore attachment_note in Discord task file The same PR sonichi#43 commit also dropped {attachment_note} from the task text, so Discord messages with file attachments lost the attachment reference. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Revert watcher to fswatch + add mkdir -p safety The polling watcher broke task-notifications (never exits = never notifies). Restore main's fswatch version which exits on detection. Add mkdir -p for tasks/ and results/calls/ at startup. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Add tests/ to .gitignore for local test creation Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Remove health check change — covered by PR sonichi#71 PR sonichi#71 has a more comprehensive health check fix (heartbeat files, multi-process detection, stale log check). Remove overlap from this PR. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- 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
…exhaustion) (sonichi#489) CodeQL alert sonichi#43 (js/resource-exhaustion, warning): the `ttl_ms` query parameter on /mute-state?state=seeing flowed directly into setTimeout's duration. Existing guard only checked `isFinite && > 0`, not an upper bound — an unbounded ttl_ms would schedule a long-lived timer per request (cheap-to-allocate DoS). Fix: clamp with Math.min(ttl, 60000). The "seeing" overlay is UI flash feedback (1.5-3s typical from `screen-capture-server.py`); nothing legitimate needs a minute-plus timer. Default still 3000ms. Closes the CodeQL queue: 15 alerts across 4 PRs (sonichi#485, sonichi#486, sonichi#487, sonichi#488, this PR sonichi#489). 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>
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
message.id— gateway replays on reconnect were creating duplicate task files and sending duplicate DM repliesTest plan
🤖 Generated with Claude Code