From 43cee4c0f0cbbaf9673b67ca300ff5b05117819c Mon Sep 17 00:00:00 2001 From: Erik Kotsiuba Date: Mon, 4 May 2026 12:45:54 +0200 Subject: [PATCH] feat: add ask notifications --- README.md | 12 ++-- docs/architecture.md | 4 +- docs/configuration.md | 68 ++++++++++++++++++- docs/contract.md | 10 ++- src/config/defaults.ts | 53 +++++++++++++-- src/config/migrate.ts | 8 +-- src/config/migrations/index.ts | 14 +++- src/config/schema.ts | 42 ++++++++++-- src/config/store.ts | 4 +- src/notifications.ts | 119 +++++++++++++++++++++++++++++++++ src/ui/controller.ts | 20 ++++++ src/ui/settings-list.ts | 67 ++++++++++++------- tests/config-store.test.ts | 66 ++++++++++-------- tests/notifications.test.ts | 68 +++++++++++++++++++ tests/settings-list.test.ts | 4 ++ 15 files changed, 480 insertions(+), 79 deletions(-) create mode 100644 src/notifications.ts create mode 100644 tests/notifications.test.ts diff --git a/README.md b/README.md index 1287763..77f4760 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ Once installed, this package gives the agent a native way to ask for clarificati - 👀 Review tab with `Submit`, `Elaborate`, and `Cancel` - 💬 Elaboration flow to capture note-based clarification before final submission - ⌨️ Fast keyboard-first interaction with customizable ask keymaps (also mobile-friendly in remote sessions) -- ⚙️ Ask settings with persisted behaviour, keymap customization, and `/answer` extraction config +- ⚙️ Ask settings with persisted behaviour, notification toggle, keymap customization, and `/answer` extraction config - 🔁 Slash commands for fallback/replay: - `/answer` extracts questions from the latest assistant message into an ask flow - `/answer:again` reopens the latest `/answer` form on the current branch @@ -122,11 +122,11 @@ Review-tab shortcuts can optionally require the same number key twice via `behav Config file: `~/.pi/agent/extensions/eko24ive-pi-ask.json` -You can edit this file yourself, ask pi to edit it for you, or use `/ask-settings` to find the exact config path and toggle behaviour settings. +You can edit this file yourself, ask pi to edit it for you, or use `/ask-settings` to find the exact config path and toggle behaviour/notification settings. ```json { - "schemaVersion": 2, + "schemaVersion": 3, "answer": { "extractionModels": [ { "provider": "openai-codex", "id": "gpt-5.4-mini" }, @@ -149,6 +149,10 @@ You can edit this file yourself, ask pi to edit it for you, or use `/ask-setting "confirm": "enter", "optionNote": "n", "questionNote": "shift+n" + }, + "notifications": { + "enabled": true, + "channels": ["bell"] } } ``` @@ -159,7 +163,7 @@ Accepted notation follows pi-tui key ids. Common aliases are normalized, for exa After installation, the extension registers the `ask_user` tool plus `/ask-settings`, `/answer`, `/answer:again`, and `/ask:replay` commands. -Agents can auto-discover and call `ask_user` when they need clarification instead of guessing. In interactive sessions, it opens a terminal UI flow for structured answers, supports native pi-style `@` file references while typing answers or notes, and returns normalized answers back to the agent. Ask settings are available both from `?` in the ask flow and from the `/ask-settings` command. Behaviour settings are binary `on`/`off` toggles that save immediately; customizable ask keymaps are changed by editing the shown config file path. +Agents can auto-discover and call `ask_user` when they need clarification instead of guessing. In interactive sessions, it opens a terminal UI flow for structured answers, supports native pi-style `@` file references while typing answers or notes, and returns normalized answers back to the agent. Ask settings are available both from `?` in the ask flow and from the `/ask-settings` command. Behaviour and notification settings are binary `on`/`off` toggles that save immediately; customizable ask keymaps and notification channels are changed by editing the shown config file path. ### Answer and replay commands diff --git a/docs/architecture.md b/docs/architecture.md index 3cc1633..baab2a2 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -18,6 +18,7 @@ The codebase is split so the implementation reads through file boundaries and na - `src/answer-commands.ts` — `/answer`, `/answer:again`, and `/ask:replay` command wiring - `src/answer-extraction.ts` — configured extraction model selection and raw-JSON extraction retries - `src/ask-payload-store.ts` — branch-aware persisted ask payload lookup +- `src/notifications.ts` — best-effort ask notification payload rendering and channel execution - `src/schema.ts` — TypeBox schema - `src/types.ts` — shared types @@ -76,7 +77,8 @@ The codebase is split so the implementation reads through file boundaries and na - config schema migrations preserve user-provided values and add new defaults only when fields are absent - replay payload lookup scans only the current session branch and revalidates payloads before use - invalid persisted keymaps fall back to default keymaps for the current session without discarding valid behaviour settings -- ask settings behaviour changes persist immediately from the settings list +- invalid notification channels are skipped and fall back to the default bell channel if none are valid +- ask settings behaviour and notification enabled changes persist immediately from the settings list - when the ask config file is missing, the first ask use writes a default persisted config snapshot under `~/.pi/agent/extensions/` - legacy root config files move into `~/.pi/agent/extensions/` only when the current config file is absent - live config updates can affect an in-progress ask flow immediately diff --git a/docs/configuration.md b/docs/configuration.md index a6e1895..3f4700a 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -28,7 +28,7 @@ Unsupported future versions or invalid files are backed up and defaults are load ```json { - "schemaVersion": 2, + "schemaVersion": 3, "answer": { "extractionModels": [ { "provider": "openai-codex", "id": "gpt-5.4-mini" }, @@ -51,6 +51,10 @@ Unsupported future versions or invalid files are backed up and defaults are load "confirm": "enter", "optionNote": "n", "questionNote": "shift+n" + }, + "notifications": { + "enabled": true, + "channels": ["bell"] } } ``` @@ -107,6 +111,52 @@ These settings affect only the `/answer` command. Normal `ask_user` tool calls d - default: `true` - effect: when disabled, the ask flow hides the footer keymap hints +## Notifications + +Notifications are best-effort external alerts emitted once per ask session, when the ask UI opens and is waiting for input. + +### `notifications.enabled` + +- type: boolean +- default: `true` +- effect: enables or disables external ask notifications +- settings UI: this is the only notification field toggled by `/ask-settings` or `?` in the ask flow + +### `notifications.channels` + +- type: array +- default: `["bell"]` +- supported channels: + - `"bell"` writes BEL (`\u0007`) + - `"osc9"` writes an OSC 9 terminal notification + - `"osc777"` writes an OSC 777 title/body notification + - `{ "type": "command", "command": string }` runs a shell command +- effect: channels run in order; failures are ignored and never fail the ask flow +- invalid channels are skipped; if none are valid, pi-ask falls back to `["bell"]` + +Notification text: + +```txt +Question waiting: