Skip to content

feat(messaging): Phase 3.5 — multi-channel notification dispatch (macOS / iMessage / Telegram)#31

Merged
AVADSA25 merged 1 commit intomainfrom
feat/phase35-multichannel-notifications
May 3, 2026
Merged

feat(messaging): Phase 3.5 — multi-channel notification dispatch (macOS / iMessage / Telegram)#31
AVADSA25 merged 1 commit intomainfrom
feat/phase35-multichannel-notifications

Conversation

@AVADSA25
Copy link
Copy Markdown
Owner

@AVADSA25 AVADSA25 commented May 3, 2026

Summary

Last Phase 3.5 backlog item. manifest.notification_channels already existed (set at agent spawn since Step 8) — this PR makes it actually do something beyond the default pwa.

When you spawn an agent with notification_channels: ["pwa", "macos", "telegram"], every agent_update / agent_blocked / agent_done now dispatches to all 3 channels.

What ships

Channel How Configuration
pwa ~/.codec/notifications.json (existing) None — default
macos osascript display notification None — works out of the box on macOS
imessage skills/imessage_send._send(recipient, text) ~/.codec/config.json:notifications.imessage_recipient
telegram direct Bot API sendMessage ~/.codec/config.json:notifications.{telegram_token,telegram_chat_id}

If iMessage / Telegram config is missing, channel silently skips. macOS works without any setup. PWA is always-on.

Configuration example

// ~/.codec/config.json
{
  "notifications": {
    "imessage_recipient": "+33612345678",
    "telegram_token": "1234567890:AAEhBOweik6ad9r_QXz...",
    "telegram_chat_id": "987654321"
  }
}

If absent, channels gracefully skip. Never breaks post_message.

To use

curl -X POST http://localhost:8090/api/agents \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Property bot",
    "description": "...",
    "notification_channels": ["pwa", "macos", "telegram"]
  }'

The PWA's Project mode currently sends notification_channels is unset → defaults to ["pwa"]. Future UI enhancement (small): checkbox set in the Project mode submit.

Tests

5 new tests in tests/test_agent_messaging.py:

  • pwa-only default → no extra dispatch
  • 'macos' in manifest → _dispatch_to_channel called for macos
  • macos dispatch builds osascript command with title + body
  • imessage skipped when recipient unset (no exception)
  • telegram skipped when unconfigured (no exception)

Full suite: 943 passed / 20 failed / 73 skipped — same 20/73 baseline, +5 from this PR.

Phase 3.5 status

All backlog items shipped:

Item Status
Step 11: Project mode UI ✅ PR #25
Project folder creation ✅ PR #28
Step 13: Proactive intelligence overlay ✅ PR #29
Step 9 review C2 (blocked_on_qwen) ✅ PR #30
Step 9 review M4 (read_paths enforcement) ✅ PR #30
Multi-channel notifications ✅ This PR

Remaining: anchor example run (your test of the property bot) + Phase 3 release tag.

🤖 Generated with Claude Code

…OS / iMessage / Telegram)

Closes the last item from Phase 3.5 backlog. `manifest.notification_channels`
already existed (set at agent spawn); this PR makes it actually do something
beyond the default `pwa`.

## What changes

`codec_agent_messaging.py`:
- New helper `_agent_notification_channels(agent_id)` reads
  manifest.notification_channels (defaults to ["pwa"])
- New helper `_dispatch_to_channel(channel, ...)` with handlers for:
  - "macos" — `osascript display notification` (works out of the box)
  - "imessage" — calls `skills/imessage_send._send(recipient, text)` if
    `~/.codec/config.json:notifications.imessage_recipient` is set
  - "telegram" — direct Bot API call to `api.telegram.org/sendMessage`
    if `~/.codec/config.json:notifications.{telegram_token,telegram_chat_id}`
    are set
- New helper `_channel_config(key)` reads `~/.codec/config.json:notifications.<key>`
- `post_message` iterates manifest channels after writing notifications.json
  and dispatches to each non-pwa channel. Best-effort — failures logged
  at debug level, don't block the post

`tests/test_agent_messaging.py`:
- 5 new tests:
  - pwa-only default → no extra dispatch
  - 'macos' in manifest → _dispatch_to_channel called for macos
  - macos dispatch invokes osascript with title + body
  - imessage skipped when recipient unset (no exception)
  - telegram skipped when unconfigured (no exception)

## Configuration model

For iMessage and Telegram, the user adds to `~/.codec/config.json`:

  {
    "notifications": {
      "imessage_recipient": "+33612345678",
      "telegram_token": "...",
      "telegram_chat_id": "..."
    }
  }

If absent, channel is silently skipped. No env vars required.

For macOS notifications, no config needed — osascript is built into macOS.

## To use

At agent spawn time, set `notification_channels`:

  POST /api/agents
  {
    "title": "...",
    "description": "...",
    "notification_channels": ["pwa", "macos", "telegram"]
  }

Each `agent_update` / `agent_blocked` / `agent_done` now dispatches to all
listed channels.

## Test plan

- [x] tests/test_agent_messaging.py → 21 passed (was 16, +5)
- [x] Full suite — 943 passed / 20 failed / 73 skipped (same baseline)
- [x] macOS dispatch verified via subprocess monkeypatch
- [x] iMessage / Telegram gracefully skip when unconfigured

## Compat

- Existing agents with `notification_channels: ["pwa"]` (the default)
  see no behavior change
- Manifest field unchanged (was already there since Step 8)
- Failure modes are conservative — bad config = silent skip, never
  crashes post_message

## Phase 3.5 status after this PR

All Phase 3.5 backlog items shipped:
- Step 11: Project mode UI ✅
- Project folder creation ✅
- Step 13: Proactive intelligence overlay ✅ (PR #29)
- Step 9 review C2 (blocked_on_qwen) ✅ (PR #30)
- Step 9 review M4 (read_paths enforcement) ✅ (PR #30)
- Multi-channel notifications ✅ (this PR)

Pending: anchor example run (user-driven test) + Phase 3 release tag.
@AVADSA25 AVADSA25 merged commit d8a302b into main May 3, 2026
1 check passed
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.

2 participants