Skip to content

Context drop image/file support + voice agent context fix + watcher Stop hook - #74

Merged
sonichi merged 9 commits into
mainfrom
fix/context-drop-voice-agent-watcher
Apr 2, 2026
Merged

sonichi merged 9 commits into
mainfrom
fix/context-drop-voice-agent-watcher

Conversation

@sonichi

@sonichi sonichi commented Apr 2, 2026

Copy link
Copy Markdown
Owner

Summary

  • context-drop.sh: Extended to support image (clipboard PNG) and file (Finder selection) drops, in addition to text. Finder selection is checked first to avoid clipboard image false matches.
  • voice-agent.ts: Added MISSING CONTEXT rule — voice agent now delegates to core when user references unknown context instead of guessing or asking user to repeat.
  • check-pending-tasks.sh: New Stop hook script that blocks Claude from finishing responses when unprocessed tasks exist in tasks/, preventing the watcher dismiss problem after context compaction.

Test plan

  • Verify text context drop still works via keyboard shortcut
  • Test image drop (copy image to clipboard, trigger shortcut)
  • Test file drop (select file in Finder, trigger shortcut)
  • Verify voice agent delegates "what we discussed" type requests to core
  • Confirm Stop hook fires when tasks exist in tasks/

🤖 Generated with Claude Code

sonichi and others added 9 commits April 1, 2026 22:30
…her Stop hook

- context-drop.sh: Support image (clipboard PNG) and file (Finder selection)
  drops in addition to text. Finder checked first, then clipboard image, then
  text selection fallback.
- voice-agent.ts: Add MISSING CONTEXT rule — delegate to core agent when user
  references context the voice agent doesn't have.
- check-pending-tasks.sh: New Stop hook script that blocks Claude from finishing
  responses when unprocessed tasks exist in tasks/, preventing the watcher
  dismiss problem after context compaction.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Use `shopt -s nullglob` instead of `2>/dev/null` on for-glob (syntax error)
- Skip tasks that already have a matching result file in results/

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… binary

- SutandoDrop: Swift menu bar app replacing Automator Quick Action for context
  drops. Global hotkey (⌃C), clipboard image/text/file detection, writes
  directly to tasks/, NSAppleScript notifications. No sandbox issues.
- context-drop-inline.txt: Copy-paste version of context-drop.sh for Automator
  users who prefer the Quick Action approach.
- Gitignore the compiled SutandoDrop binary.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…dup fix

- Notifications: spawn /usr/bin/osascript subprocess (in-process NSAppleScript
  doesn't show banners). Added NSSound.beep() for audio confirmation.
- Dedup: removed context-drop.txt writes, only writes to tasks/ directly.
- startup.sh: auto-launch SutandoDrop on startup with compile check.
- check-pending-tasks.sh: updated with nullglob + result-skip fix.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- SutandoDrop: ⌃V hotkey sends POST to /voice/toggle on agent-api (port 7843).
  Beeps for confirmation, shows notification with new state.
- agent-api: /voice/toggle (POST) and /voice/state (GET) endpoints to manage
  desired voice connection state.
- web-client: polls /voice/state every 1s, auto-connects/disconnects when
  desired state changes from remote toggle.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Python requires `global` declarations at method scope, not inside
nested try blocks. Moved to top of do_POST().

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Template literal `${}` was inside the HTML template string, causing
esbuild parse error. Use string concatenation instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- SutandoDrop: ⌃V now uses AppleScript to find the localhost:8080 Chrome
  tab and click the voice button directly. Bypasses AudioContext user-gesture
  requirement. Opens the page if no tab exists.
- web-client: Removed polling code (no longer needed). Added window.toggle
  export. AudioContext reuse instead of recreate.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Binary, directory, startup.sh references, and .gitignore all updated.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@sonichi
sonichi merged commit 55daebe into main Apr 2, 2026
@sonichi
sonichi deleted the fix/context-drop-voice-agent-watcher branch April 2, 2026 13:42
liususan091219 pushed a commit to liususan091219/sutando-fork that referenced this pull request May 28, 2026
…top hook (sonichi#74)

* Context drop image/file support, voice agent context delegation, watcher Stop hook

- context-drop.sh: Support image (clipboard PNG) and file (Finder selection)
  drops in addition to text. Finder checked first, then clipboard image, then
  text selection fallback.
- voice-agent.ts: Add MISSING CONTEXT rule — delegate to core agent when user
  references context the voice agent doesn't have.
- check-pending-tasks.sh: New Stop hook script that blocks Claude from finishing
  responses when unprocessed tasks exist in tasks/, preventing the watcher
  dismiss problem after context compaction.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix Stop hook: nullglob instead of stderr redirect, skip processed tasks

- Use `shopt -s nullglob` instead of `2>/dev/null` on for-glob (syntax error)
- Skip tasks that already have a matching result file in results/

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Add SutandoDrop native menu bar app + context-drop-inline + gitignore binary

- SutandoDrop: Swift menu bar app replacing Automator Quick Action for context
  drops. Global hotkey (⌃C), clipboard image/text/file detection, writes
  directly to tasks/, NSAppleScript notifications. No sandbox issues.
- context-drop-inline.txt: Copy-paste version of context-drop.sh for Automator
  users who prefer the Quick Action approach.
- Gitignore the compiled SutandoDrop binary.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* SutandoDrop: osascript subprocess notifications, beep, startup.sh, dedup fix

- Notifications: spawn /usr/bin/osascript subprocess (in-process NSAppleScript
  doesn't show banners). Added NSSound.beep() for audio confirmation.
- Dedup: removed context-drop.txt writes, only writes to tasks/ directly.
- startup.sh: auto-launch SutandoDrop on startup with compile check.
- check-pending-tasks.sh: updated with nullglob + result-skip fix.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Add voice toggle (⌃V) via SutandoDrop + agent-api + web client polling

- SutandoDrop: ⌃V hotkey sends POST to /voice/toggle on agent-api (port 7843).
  Beeps for confirmation, shows notification with new state.
- agent-api: /voice/toggle (POST) and /voice/state (GET) endpoints to manage
  desired voice connection state.
- web-client: polls /voice/state every 1s, auto-connects/disconnects when
  desired state changes from remote toggle.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix agent-api: move global voice_desired_state to method level

Python requires `global` declarations at method scope, not inside
nested try blocks. Moved to top of do_POST().

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix web-client voice polling: escape template literal in outer template

Template literal `${}` was inside the HTML template string, causing
esbuild parse error. Use string concatenation instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Voice toggle: click button via AppleScript instead of API polling

- SutandoDrop: ⌃V now uses AppleScript to find the localhost:8080 Chrome
  tab and click the voice button directly. Bypasses AudioContext user-gesture
  requirement. Opens the page if no tab exists.
- web-client: Removed polling code (no longer needed). Added window.toggle
  export. AudioContext reuse instead of recreate.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Rename SutandoDrop → Sutando

Binary, directory, startup.sh references, and .gitignore all updated.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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