Add public A2A Agent Card endpoint that exposes registered agents as skills
for cross-platform agent discovery. Includes admin CLI for updating agent
capabilities, which populate skill tags and descriptions in the card.
- internal/a2a: new package with AgentCard generator, HTTP handler, and tests
- agents store/service: add ListAllActiveAgents (excludes human accounts)
- admin socket: add agent.update_capabilities command
- admin CLI: add `agent update-capabilities --name --capabilities` subcommand
- main.go: register /.well-known/agent-card.json route (public, no auth)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Background worker that detects stale messages and takes corrective action:
- Auto-fails DMs stuck in "processing" after configurable timeout (default 24h)
- Sends system DM reminders for pending messages after ReminderAfter (default 4h)
- Escalates unprocessed messages to #approvals channel after EscalateAfter (default 48h)
- Deduplicates reminders and escalations to avoid spam
- Configurable via SYNAPBUS_STALEMATE_* environment variables
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The BroadcastMessage function now accepts a replyTo parameter, allowing
channel messages to reference a parent message ID and create threads.
Updated all callers (MCP bridge, hybrid tools, tests) and added a test
verifying reply_to is correctly stored and returned.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Decouple fosite token introspection from the HTTP request context using
context.WithoutCancel + 10s timeout. When claude.ai opens multiple
concurrent MCP connections and one disconnects, the token validation
for subsequent connections no longer fails with "context canceled".
Fixes Bug #6 from #bugs-synapbus.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When SYNAPBUS_BASE_URL is empty or set to "auto", the OAuth metadata
handler now reads X-Forwarded-Proto and X-Forwarded-Host headers to
construct correct OAuth URLs. This allows SynapBus to serve correct
OAuth metadata for both LAN and Cloudflare Tunnel access simultaneously.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The regex matched against HTML-escaped text where & entity chars
broke URL patterns. Now URLs are extracted and replaced with placeholders
before escapeHtml runs, then restored after all other inline processing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the Conversations page with a dedicated search page featuring:
- Large, prominent search input with autofocus
- Collapsible filter panel with time range presets (24h, week, month,
3 months, custom date range), channel filter (comma-separated,
- prefix to exclude), and agent filter (same syntax)
- Search-results-only display with helpful empty state when no search
has been performed
- Remove duplicate "Conversations" heading, rename to "Search"
- Update sidebar nav label and icon to match
Backend changes:
- Add channel, agent, after, before query parameters to
GET /api/messages/search endpoint
- Add Channels, ExcludeChannels, Agents, ExcludeAgents fields to
SearchOptions with SQL filter generation in store.go
- Support include/exclude semantics via - prefix for both channel
and agent filters
API client updated to pass new filter parameters.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace plain-text message rendering with a rich MessageBody component
that supports bold, italic, inline code, fenced code blocks, lists,
headers, auto-linked URLs, @mention pills (linking to /dm/{name}), and
#channel pills (linking to /channels/{name}). Input is HTML-sanitized
before processing to prevent XSS. Updated all 5 rendering locations:
channels, DMs, conversations, MessageList, and ThreadPanel.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
API keys are managed via admin CLI, not the web UI. Remove the
Management section from Settings, delete the api-keys route, and
clean up the Header page-title mapping.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove the duplicate "Search messages" button from the sidebar and make
the header search input bigger (w-80, text-sm, larger padding/icon) with
"Search messages..." placeholder matching the removed sidebar text.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace generic cube favicon and OAuth layered-planes logo with the
same constellation icon used in the sidebar and login page.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Auto-join public channels on first send (bug #1)
- Channel broadcasts no longer create duplicate DM copies; inbox DMs
only sent for @mentions (bug #2)
- Embedding pipeline auto-enqueues new messages via MessageListener
callback instead of requiring pod restart (bug #3)
- Admin socket defaults to /tmp in containers to avoid PVC filesystem
incompatibility with Unix sockets (bug #5)
- SSE events now fire for MCP-sent messages (not just REST API),
enabling live notification badges without page reload
- Fixed frontend SSE field name mismatch (channel_name → channel)
- Fixed SSE client not connecting after login redirect
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Switch Docker runtime from scratch to alpine:3.19 so kubectl exec works
for admin CLI operations. Add `synapbus channels create` and
`synapbus channels join` CLI commands with corresponding admin socket
handlers. Change default socket path to /data/synapbus.sock (absolute).
Also add Helm envFrom support and NodePort configuration.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Use human agent's perspective only for unread counts (avoids system agent inflation)
- Replace onDestroy + get() with $effect cleanup in channel/DM pages (Svelte 5 compat)
- Fix notification store to parse array-of-objects API response format
- Add last_read_message_id to DM messages endpoint
- Fix test agent type seeding for GetHumanAgentForUser
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Backend:
- GET /api/notifications/unread returns channel + DM unread counts
- POST /api/notifications/mark-read updates inbox_state for channels/DMs
- SSE broadcaster wired into message send for real-time push
- last_read_message_id added to channel/DM message responses
Frontend:
- Notification store tracks unread counts per channel/DM
- SSE listener for new_message and unread_update events
- Red circular badges in sidebar (Slack-style)
- "New messages" separator line in channel/DM views
- Auto mark-as-read after 2 seconds of viewing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
sql.NullTime cannot scan SQLite's text-format timestamps from
modernc.org/sqlite. Switch to sql.NullString with manual time.Parse.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- JS/TS execution engine (goja + esbuild) with sandboxed runtime and call() bridge
- BM25 action discovery index over 23 registered actions
- ServiceBridge mapping call() invocations to existing service methods
- Admin CLI subcommands for webhook/k8s/gc operations
- Pagination support (offset/limit) in read_inbox, search_messages, get_channel_messages
- Fixed test assertions for call() envelope structure {ok, result}
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace 5 separate tool registrars (messaging, channels, swarm,
attachments, webhooks) with a single HybridToolRegistrar exposing
4 tools: my_status, send_message, search, and execute.
New foundation packages:
- internal/actions: action registry (22 actions) + BM25 search index
- internal/jsruntime: lightweight call() expression parser with
concurrency-limited execution pool
The `execute` tool dispatches call() expressions through a
ServiceBridge that maps action names to existing service methods,
preserving all original handler logic. The `search` tool enables
agents to discover available actions by keyword. The `send_message`
tool merges DM and channel sending with mutual exclusion.
All unit tests, integration tests, build, and vet pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add Offset, After, Before date filters to ReadOptions and SearchOptions.
Add Channel name filter to SearchOptions. Introduce PaginatedMessages,
PaginatedChannels, and PaginatedTasks types with total counts. Update
ReadInbox, SearchMessages, and GetChannelMessages to return paginated
results. Add CountInboxMessages, CountSearchMessages, CountChannelMessages,
and CountTasks store methods. Update all callers in MCP tools, REST API
handlers, and search service. Add comprehensive tests for offset
pagination, date filtering, channel name filtering, and combined
filters with pagination.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Register all 23 agent-callable operations (messaging, channels, swarm,
attachments) with full parameter metadata and usage examples. Provide
in-memory BM25 text search over action documentation for tool discovery,
with simple stemming and compound-token matching so exact action names
rank highest.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pure Go JavaScript/TypeScript execution engine using goja + esbuild.
Provides sandboxed code execution with a call() bridge for agent
actions, automatic TypeScript detection and transpilation, timeout
enforcement, max-calls limits, and a concurrent execution pool.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add `my_status` MCP tool: single call returns agent identity, pending
DMs, channel mentions, system notifications, channel summaries, and
stats with truncation for large inboxes
- Add embeddings CLI: `synapbus embeddings status|reindex|clear` for
managing vectors when switching embedding providers
- Add automatic message retention worker with configurable period
(--message-retention, default 12m), warning notifications 1 month
before deletion, cascade cleanup, and incremental vacuum
- Add manual purge: `synapbus messages purge --older-than --agent --channel`
and `synapbus db vacuum` for on-demand cleanup
- Add `synapbus retention status` CLI for admin visibility
- Create system agent at startup for sending retention warnings
- Filter system agent from discover_agents results
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
11 Go integration tests that start an in-process server with in-memory
SQLite, register agents with API keys, and make real JSON-RPC 2.0 calls
to /mcp. Tests cover: direct messages, channels, search, threads,
agent discovery, inbox filters, claim/mark-done, tool listing, auth
enforcement, private channels, and read-state tracking.
Run with: make test-e2e
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Parse @agentname patterns in channel message body. Mentioned agents
(who are channel members, excluding sender) get mention=true flag in
their inbox notification metadata. Channel message metadata includes
mentioned_agents list for all recipients.
- mentions.go: regex parser with email exclusion, dedup, 22 test cases
- BroadcastMessage: metadata now uses json.Marshal, includes mentions
- Tests verify mention flag, self-mention exclusion, non-member skip
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Updated tool descriptions to teach agents the right workflow:
- read_inbox: "Call this first when connecting"
- list_channels: "Call this when connecting to see available channels"
- send_message: guides to discover_agents first, points to send_channel_message
- search_messages: clarifies it searches inbox + channels
- send_channel_message: documents @agentname mentions
- discover_agents: explains it lists all agents when no query given
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Agents could send channel messages but had no MCP tool to read them.
Also, search_messages only searched DMs (to/from agent), missing channel
messages entirely. Now SearchMessages includes channel messages where
the agent is a member.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>