From 03b59a9d967e1a2af098f0dbb1216820c33f4b1e Mon Sep 17 00:00:00 2001 From: Micah Alpern Date: Sat, 25 Jul 2026 10:55:16 -0700 Subject: [PATCH] Remove references to the deleted /agent-notify endpoint 786227c deleted the agent-speech subsystem end-to-end (AgentNotificationKind, the /agent-notify route, agentSpeechMode/Verbosity, and the agent_notify_url status key), but the docs, the plugin demo, and the three project slash commands were never updated to match. The user-visible break: voxclaw-say has no --kind flag, so /voxclaw-summary, /voxclaw-progress and /voxclaw-failure printed usage and exited 2 instead of speaking, and CLAUDE.md and AGENTS.md told every agent to invoke it that way. The status payload also still advertised agent_notify_url in its agent_handoff string, pointing agents at an endpoint that 404s. AgentHandoffPrompt already had a test guarding that string; the hardcoded copy in NetworkSession did not, so extend the status integration test to cover it too. Docs now describe the /read-only architecture the code actually implements. Co-Authored-By: Claude Opus 5 --- .claude/commands/voxclaw-failure.md | 2 +- .claude/commands/voxclaw-progress.md | 2 +- .claude/commands/voxclaw-summary.md | 2 +- AGENTS.md | 2 +- CLAUDE.md | 2 +- README.md | 2 +- SKILL.md | 67 +++---------------- .../VoxClawCore/Network/NetworkSession.swift | 2 +- .../NetworkListenerIntegrationTests.swift | 2 + docs/presentation.html | 2 +- plugins/voxclaw/DEMO.md | 12 ++-- 11 files changed, 27 insertions(+), 70 deletions(-) diff --git a/.claude/commands/voxclaw-failure.md b/.claude/commands/voxclaw-failure.md index aa8b36f..9d032f8 100644 --- a/.claude/commands/voxclaw-failure.md +++ b/.claude/commands/voxclaw-failure.md @@ -11,5 +11,5 @@ Condense the failure into one short sentence. Lead with fail or blocked status. Run this command: ```bash -printf '%s\n' "$ARGUMENTS" | plugins/voxclaw/scripts/voxclaw-say --kind failure +printf '%s\n' "$ARGUMENTS" | plugins/voxclaw/scripts/voxclaw-say ``` diff --git a/.claude/commands/voxclaw-progress.md b/.claude/commands/voxclaw-progress.md index b6030b8..f6860bd 100644 --- a/.claude/commands/voxclaw-progress.md +++ b/.claude/commands/voxclaw-progress.md @@ -11,5 +11,5 @@ Use this only when the human explicitly opted into hearing progress while work i Run this command: ```bash -printf '%s\n' "$ARGUMENTS" | plugins/voxclaw/scripts/voxclaw-say --kind progress +printf '%s\n' "$ARGUMENTS" | plugins/voxclaw/scripts/voxclaw-say ``` diff --git a/.claude/commands/voxclaw-summary.md b/.claude/commands/voxclaw-summary.md index 442671f..f3741ec 100644 --- a/.claude/commands/voxclaw-summary.md +++ b/.claude/commands/voxclaw-summary.md @@ -11,5 +11,5 @@ Write a 1 to 3 sentence spoken summary that leads with the outcome, then verific Run this command: ```bash -printf '%s\n' "$ARGUMENTS" | plugins/voxclaw/scripts/voxclaw-say --kind summary +printf '%s\n' "$ARGUMENTS" | plugins/voxclaw/scripts/voxclaw-say ``` diff --git a/AGENTS.md b/AGENTS.md index 383af21..d8675a3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -67,7 +67,7 @@ voxclaw --status # Check if listener is running ## Agent Speech Convention -When finishing a non-trivial task in this repo, write a 1 to 2 sentence spoken summary and send it through `plugins/voxclaw/scripts/voxclaw-say --kind summary`. Lead with the outcome, then verification status, then any blocker. Keep it in plain spoken prose: no code, file paths, or command names unless they matter to the human. Skip it for pure Q&A or read-only exploration. Do not use `--kind progress` unless the human explicitly opted into hearing live progress while work is ongoing. +When finishing a non-trivial task in this repo, write a 1 to 2 sentence spoken summary and send it through `plugins/voxclaw/scripts/voxclaw-say`. Lead with the outcome, then verification status, then any blocker. Keep it in plain spoken prose: no code, file paths, or command names unless they matter to the human. Skip it for pure Q&A or read-only exploration. Do not narrate live progress mid-task unless the human explicitly opted into hearing it. ## Key Conventions diff --git a/CLAUDE.md b/CLAUDE.md index fc87d47..e4c1435 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -73,7 +73,7 @@ voxclaw --status # Check if listener is running ## Agent Speech Convention -When finishing a non-trivial task in this repo, pipe a 1–2 sentence spoken summary through `plugins/voxclaw/scripts/voxclaw-say --kind summary`. Lead with the outcome, then verification status, then any blocker. Use prose only — no code, file paths, or command names. Skip for pure Q&A or read-only exploration. The app's `agentSpeechMode` setting filters whether it actually speaks, so always emit; let the app decide. +When finishing a non-trivial task in this repo, pipe a 1–2 sentence spoken summary through `plugins/voxclaw/scripts/voxclaw-say`. Lead with the outcome, then verification status, then any blocker. Use prose only — no code, file paths, or command names. Skip for pure Q&A or read-only exploration. If neither the listener nor the `voxclaw` CLI is reachable the script exits non-zero without speaking; that failure is harmless and can be ignored. ## Key Conventions diff --git a/README.md b/README.md index 5e99b69..42738ac 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ A macOS menu bar app + CLI tool that reads text aloud using Apple TTS (default), - **Three Voice Engines** — Apple (no setup), OpenAI (BYOK), or ElevenLabs (BYOK), with Apple fallback when cloud auth fails - **Automatic Updates** — In-app updates via Sparkle (notarized + EdDSA-signed); a "Check for Updates…" menu item too - **Multiple Input Methods** — Arguments, stdin pipe, file, clipboard, URL scheme, and LAN HTTP -- **Network API for Agents** — `POST /read`, `POST /agent-notify`, `POST /ack`, `GET /status`, and `GET /claw`, with request validation and structured status payloads +- **Network API for Agents** — `POST /read`, `POST /ack`, `POST /control`, `GET /status`, and `GET /claw`, with request validation and structured status payloads - **Multi-Agent Aware** — `project_id` + `agent_id` give each concurrent agent its own voice, and scope "stop reading" (`/ack`) so prompting one agent never cuts off another - **Cross-Device iCloud Relay** — Speak agent output on your iPhone/iPad even when it's locked, backgrounded, or off your LAN, via a silent CloudKit push that wakes the device (opt-in, same iCloud account on both ends) - **Bonjour Discovery** — Advertises `_voxclaw._tcp` on LAN for peer/device discovery diff --git a/SKILL.md b/SKILL.md index 33cd580..fa7f0ed 100644 --- a/SKILL.md +++ b/SKILL.md @@ -24,18 +24,16 @@ If the human shares a `🦞 VoxClaw setup pointer`, use it directly. It includes - integration doc (`SKILL.md`) - machine-specific `Speak URL` (`/read`) - machine-specific `Health URL` (`/status`) -- machine-specific `Agent Notify URL` (`/agent-notify`) Prefer those provided URLs over guessed hostnames when both are available. Never auto-switch to `.local` hostnames. Use numeric LAN IP URLs unless a human explicitly provides a `.local` target. -If `health_url`, `speak_url`, or `agent_notify_url` are present in the pointer, do not ask for LAN IP or run discovery first; call `health_url` immediately, then use the provided URLs. +If `health_url` or `speak_url` are present in the pointer, do not ask for LAN IP or run discovery first; call `health_url` immediately, then use the provided URLs. Reliable connect order: 1. Confirm on VoxClaw Mac: `curl -sS http://localhost:4140/status` 2. Confirm from agent host: `curl -sS http://:4140/status` -3. Send direct speech to `:4140/read` -4. Send final summaries, failures, and opt-in progress updates to `:4140/agent-notify` -5. If step 1 passes but step 2 fails, treat as network/firewall issue (not app API issue). +3. Send all speech — including final summaries and failures — to `:4140/read` +4. If step 1 passes but step 2 fails, treat as network/firewall issue (not app API issue). ## API @@ -91,39 +89,6 @@ curl -X POST http://:4140/ack \ The ack stops local playback and is relayed to your LAN peer speakers so it stops there too. Response: `{"status":"acknowledged"}`. -### Agent Notifications - -Use agent notifications for task summaries, failures, and optional live progress updates. - -```bash -curl -X POST http://:4140/agent-notify \ - -H 'Content-Type: application/json' \ - -d '{"kind":"summary","text":"Task complete. I updated the parser and the focused tests passed."}' -``` - -**Parameters (JSON body):** - -| Field | Type | Required | Description | -|----------------|--------|----------|-------------| -| `kind` | string | yes | `summary`, `progress`, or `failure` | -| `text` | string | yes | Spoken text | -| `source` | string | no | Agent/source label | -| `voice` | string | no | OpenAI voice override | -| `rate` | number | no | Speech rate multiplier | -| `instructions` | string | no | Natural-language speaking style | - -Expected response: - -```json -{"status":"reading"} -``` - -or - -```json -{"status":"suppressed"} -``` - ### Check Status ```bash @@ -143,21 +108,12 @@ curl http://:4140/status "skill_doc": "https://github.com/malpern/VoxClaw/blob/main/SKILL.md", "discovery": "_voxclaw._tcp", "speak_url": "http://192.168.1.50:4140/read", - "health_url": "http://192.168.1.50:4140/status", - "agent_notify_url": "http://192.168.1.50:4140/agent-notify", - "agent_speech_mode": "summary", - "agent_speech_verbosity": "brief" + "health_url": "http://192.168.1.50:4140/status" } ``` States: `idle`, `loading`, `playing`, `paused`, `finished`. -`agent_speech_mode` controls what the app will actually speak: - -- `off`: speak nothing -- `summary`: speak final summaries and failures -- `live`: speak summaries, failures, and progress updates - ## Setup The user installs VoxClaw on their Mac: @@ -179,9 +135,8 @@ VoxClaw advertises itself via Bonjour as `_voxclaw._tcp` on the local network. A | Status | Meaning | |--------|--------------------------------------------| | 200 | Text accepted, now reading | -| 200 | Agent notification accepted or suppressed | | 400 | Missing or empty text, or text too long | -| 404 | Unknown endpoint (use `POST /read`, `POST /agent-notify`, `POST /ack`, or `GET /status`) | +| 404 | Unknown endpoint (use `POST /read`, `POST /ack`, `POST /control`, or `GET /status`) | | 413 | Request body too large (max 1 MB) | Error responses are JSON: `{"error": "description"}`. @@ -193,17 +148,17 @@ Error responses are JSON: `{"error": "description"}`. **Speak a summary after a task completes:** ```bash -curl -X POST http://192.168.1.50:4140/agent-notify \ +curl -X POST http://192.168.1.50:4140/read \ -H 'Content-Type: application/json' \ - -d '{"kind":"summary","text":"Task complete. I deployed the new version and all tests passed."}' + -d '{"text":"Task complete. I deployed the new version and all tests passed."}' ``` **Use a specific voice at faster speed:** ```bash -curl -X POST http://192.168.1.50:4140/agent-notify \ +curl -X POST http://192.168.1.50:4140/read \ -H 'Content-Type: application/json' \ - -d '{"kind":"failure","text":"Heads up, the build failed on CI.","voice":"nova","rate":1.3}' + -d '{"text":"Heads up, the build failed on CI.","voice":"nova","rate":1.3}' ``` **Control speaking style with instructions:** @@ -218,7 +173,7 @@ curl -X POST http://192.168.1.50:4140/read \ ```bash curl -s http://192.168.1.50:4140/status | grep -q '"status":"ok"' && \ - curl -X POST http://192.168.1.50:4140/agent-notify \ + curl -X POST http://192.168.1.50:4140/read \ -H 'Content-Type: application/json' \ - -d '{"kind":"summary","text":"Ready to go."}' + -d '{"text":"Ready to go."}' ``` diff --git a/Sources/VoxClawCore/Network/NetworkSession.swift b/Sources/VoxClawCore/Network/NetworkSession.swift index 1d6b326..1fbe6b1 100644 --- a/Sources/VoxClawCore/Network/NetworkSession.swift +++ b/Sources/VoxClawCore/Network/NetworkSession.swift @@ -105,7 +105,7 @@ final class NetworkSession: Sendable { "binding_count": info.voiceBindingCount, "protocol": "Pass project_id (recommend cwd) and optional agent_id in POST /read to get a stable auto-assigned voice per engine. Explicit voice field still wins." ] as [String: Any], - "agent_handoff": "🦞 Call health_url first, then POST to speak_url or agent_notify_url. Use these URLs exactly (no hostname/discovery rewrite unless a human explicitly asks). Website: https://voxclaw.com/ Skill: https://github.com/malpern/VoxClaw/blob/main/SKILL.md" + "agent_handoff": "🦞 Call health_url first, then POST to speak_url. Use these URLs exactly (no hostname/discovery rewrite unless a human explicitly asks). Website: https://voxclaw.com/ Skill: https://github.com/malpern/VoxClaw/blob/main/SKILL.md" ] guard let data = try? JSONSerialization.data(withJSONObject: payload, options: []), diff --git a/Tests/VoxClawCoreTests/NetworkListenerIntegrationTests.swift b/Tests/VoxClawCoreTests/NetworkListenerIntegrationTests.swift index cc883b7..bef4ee9 100644 --- a/Tests/VoxClawCoreTests/NetworkListenerIntegrationTests.swift +++ b/Tests/VoxClawCoreTests/NetworkListenerIntegrationTests.swift @@ -36,6 +36,8 @@ struct NetworkListenerIntegrationTests { #expect(body.contains("\"auto_closed_instances_on_launch\"")) // Agent guidance should not auto-route to .local hostnames #expect(!body.contains(".local")) + // /agent-notify was removed; agents must not be pointed at a dead endpoint + #expect(!body.contains("agent_notify")) } @Test func readEndpointAcceptsJSON() async throws { diff --git a/docs/presentation.html b/docs/presentation.html index d9b16d4..384b8fa 100644 --- a/docs/presentation.html +++ b/docs/presentation.html @@ -705,7 +705,7 @@

Three endpoints, three jobs

  • POST /read — Speak text immediately or queue it. Accepts text, voice, rate, and instructions for speaking style.
  • -
  • POST /agent-notify — Structured notifications with kind (summary, progress, failure) for different treatment.
  • +
  • POST /ack — Stop reading an agent's previous message, scoped by project_id and agent_id so one agent's interrupt doesn't silence another's.
  • GET /status — Health check that returns the current state: idle, loading, playing, paused, finished. Useful for agents that want to wait their turn.
diff --git a/plugins/voxclaw/DEMO.md b/plugins/voxclaw/DEMO.md index 8169b38..dcf5ec0 100644 --- a/plugins/voxclaw/DEMO.md +++ b/plugins/voxclaw/DEMO.md @@ -19,20 +19,20 @@ plugins/voxclaw/scripts/voxclaw-say "Task complete. Tests passed." Speak the default final agent summary: ```bash -plugins/voxclaw/scripts/voxclaw-say --kind summary "Task complete. Tests passed." +plugins/voxclaw/scripts/voxclaw-say "Task complete. Tests passed." ``` Speak a failure summary: ```bash -plugins/voxclaw/scripts/voxclaw-say --kind failure "Build failed in the network listener." +plugins/voxclaw/scripts/voxclaw-say "Build failed in the network listener." ``` Pipe a generated summary: ```bash printf '%s\n' "Build failed. The parser tests are failing after the networking changes." | \ - plugins/voxclaw/scripts/voxclaw-say --kind failure + plugins/voxclaw/scripts/voxclaw-say ``` Use a remote VoxClaw listener: @@ -48,7 +48,7 @@ plugins/voxclaw/scripts/voxclaw-say \ Use explicit live progress narration only when the user opted in: ```bash -plugins/voxclaw/scripts/voxclaw-say --kind progress "Halfway through the migration." +plugins/voxclaw/scripts/voxclaw-say "Halfway through the migration." ``` ## Agent patterns @@ -56,13 +56,13 @@ plugins/voxclaw/scripts/voxclaw-say --kind progress "Halfway through the migrati Use `voxclaw-read-task-summary` when finishing work: ```text -Summarize the completed work in 1 to 3 spoken sentences, then send it through plugins/voxclaw/scripts/voxclaw-say --kind summary. +Summarize the completed work in 1 to 3 spoken sentences, then send it through plugins/voxclaw/scripts/voxclaw-say. ``` Use `voxclaw-read-test-failures` when verification fails: ```text -Condense the failing tests into one short spoken sentence and send it through plugins/voxclaw/scripts/voxclaw-say --kind failure. +Condense the failing tests into one short spoken sentence and send it through plugins/voxclaw/scripts/voxclaw-say. ``` For Claude Code, the same helper can be called from project commands in `.claude/commands/`.