tool-approval-notifications #1

Merged
jacensekai merged 2 commits from tool-approval-notifications into master 2026-10-13 13:39:23 -04:00
Owner
No description provided.
Every tool now has an approval policy, set per tool or per tool source
in config.approval.rules. A rule for the tool wins over one for its
source, which wins over the default. MCP tools, and integration tools
marked with the new SDK flag `dangerous`, ask first by default;
everything else is allowed, as before. Home Assistant's call_service is
marked dangerous.

Blocked tools are left out of what the model is offered. For "ask",
the loop emits approval_required and waits for
POST /api/conversations/:id/approvals/:toolCallId (or Stop), then
emits approval_resolved. Because these are run events, a client that
reconnects or opens the conversation on another device sees the
pending call through replay. The policy is read at call time, so
"Always allow" (which saves a rule) applies to later calls in the same
run. The outcome is stored in the tool message's meta.approval.

The chat shows the pending call's full arguments with Allow, Always
allow and Deny, and marks denied or blocked calls. A new Settings →
Tools tab lists every tool by source with a policy picker, saved
through PUT /api/tools/policy, which replaces the rules so that
clearing one works.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add notifications (Web Push, ntfy) and flag conversations awaiting approval
Some checks failed
CI / Typecheck, build and test (pull_request) Successful in 17s
CI / End-to-end (Playwright) (pull_request) Successful in 50s
CI / Docker images and sandbox (pull_request) Failing after 11s
CI / Compose stack smoke test (pull_request) Failing after 6s
810600dcdf
The sidebar marks a conversation waiting for a tool approval with an
alert icon and a bold title, the tab title counts them, and the phone
menu button gets a dot when another conversation needs the user. The
global /api/events stream now carries per-conversation status
(running, awaitingApproval), and the conversation list reloads when a
status arrives for one started on another device.

Notifications go out when a run finishes or fails (not when stopped)
and when a run waits for approval, if those events are enabled in
config.notifications. They're skipped while a visible tab shows the
conversation. Each tab reports its presence (open conversation, page
visibility) on the global stream, updates it with POST /api/presence,
and identifies itself with X-Lumina-Client. Starting a run marks the
sending tab as watching, because a new chat navigates only after its
first message is accepted.

Delivery fans out to:
- Web Push, implemented on node:crypto (VAPID ES256 and aes128gcm, no
  new runtime dependency). Keys live in the kv table and subscriptions
  in push_subscriptions. Endpoints must be https with a valid P-256
  key and are never returned by the API. Expired subscriptions are
  dropped. The UI is now an installable PWA with a service worker that
  shows notifications (one per conversation tag) and opens the
  conversation on click.
- Integrations with the new SDK `notify` hook, including a bundled ntfy
  integration.

Settings → Notifications turns push on or off per device, lists
devices, sends a test and picks events. The tests decrypt payloads with
Mozilla's http_ece (dev dependency) and verify VAPID tokens. A
Playwright `pwa` project on full Chromium delivers pushes to the
service worker over CDP, since the headless shell always denies
notifications. Real push services are not exercised.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
jacensekai/lumina!1
No description provided.