pi-windows-notifier0.4.0
Built for Windows. Zero dependencies. Customizable, security-first notifications and alert sounds for Pi.
Untested on omp
This is a pi package. No one has reported whether it works on omp yet. If you try it, add your result below.
Reports 0
No reports yet.
Readme
pi-windows-notifier
專為 Windows 上的 Pi 設計。0 依賴套件。可自定義,以安全為優先的提示音與通知插件。
需要你確認權限、回答問題,或模型回應結束時,會自動跳出 Windows 通知,並播放系統提示音或你自訂的 WAV 音效。就算你正在看別的視窗也會提醒,讓你不用一直盯著 Pi。
不需要WSL。
通知不會從 session 帶出問題、命令、檔案路徑或模型回答,但你可以設定自己的固定提醒文字。它也不會替你批准權限或回答問題,所有提醒都在本機處理。
使用 Pi 提供的 API、Node.js built-ins 與 Windows 內建通知和音效 API,不必另裝通知函式庫或外部播放器。設計上避開了許多其他同類套件的高風險做法;具體防護與限制見隱私與程序安全。
預覽

安裝
pi install npm:pi-windows-notifier
安裝後開一個新的 Pi session 就能使用,不用先寫設定檔。五種通知和提示音預設都會開啟。
需要的環境:
- Windows 10 或 11。
- 64 位元 Node.js 22.19 以上,支援 x64 和 arm64。
- Pi 1.1.0 以上。
- Windows 內建的 Windows PowerShell 5.1。
只在 Pi 的互動式終端介面啟用。RPC、print、JSON 模式、其他作業系統和 32 位元 Node.js 都不會發通知。缺少必要 UI 事件的舊版 Pi 不支援。
移除套件:
pi remove npm:pi-windows-notifier
什麼時候會提醒?
| 事件 | 通知內容 | Windows 提示音 |
|---|---|---|
permission |
Permission approval needed | Exclamation |
question |
Waiting for your answer | Exclamation |
completed |
Response complete | Hand |
aborted |
Response interrupted | Exclamation |
failed |
Response failed | Exclamation |
彈窗標題預設是 Pi,預設訊息是英文。每個事件都能設定自己的標題與訊息;狀態輸出是英文,其他指令提示仍是繁體中文,沒有整體語言切換設定。
權限提醒搭配 @gotgenes/pi-permission-system 使用,也支援從 subagent 轉送到父 session 的權限請求。自動允許、自動拒絕,或已經有 session approval 的請求不會提醒。
問題提醒支援 @juicesharp/rpiv-ask-user-question(包含 @ssk_dev/rpiv-ask-user-question-lean)和 @narumitw/pi-plan-mode。一份問卷只提醒一次,不會每一題都響。模型在一般文字回答裡寫的問句,以及你手動打開的設定介面,不算這裡的提問。
回應結束提醒會等 Pi 真正結束這次回應才發送,不會在自動重試或續跑途中提早報完成。單一工具出錯,也不等於整次模型回應失敗。
權限和提問套件都是可選的;沒有安裝它們,仍然可以收到回應結束提醒。
提問辨識的限制
Pi 的 UI 事件沒有說明是哪個工具開了視窗。因此,只有恰好一個支援的提問工具正在執行,而且沒有權限提示或已知的其他 UI 佔用時,才會把等待畫面的訊號當成提問。資訊不明確就略過,並記錄 UI_AMBIGUOUS,不硬猜來源。
這個做法無法精確辨識所有重疊視窗的情況。RPIV 的 rpiv:ask-user:blocked 會提供額外訊號,並和共通 UI 事件一起去重。
有些提問套件本身也會發出 terminal bell。如果聽到額外的聲音,請檢查該套件或終端的提示音設定。
設定
想改預設行為時,請自行建立 ~/.pi/agent/extensions/pi-windows-notifier/config.json。在 Windows 上,就是使用者家目錄裡的 .pi\agent\extensions\pi-windows-notifier\config.json。套件不會替你建立或修改這個檔案,也不讀專案內的設定。
新路徑優先;只有新檔案不存在時,才讀舊的 ~/.pi/agent/pi-windows-notifier/config.json,兩份設定不會合併。新檔案若無效或無法讀取,會停用通知,不會改讀舊檔。想搬移設定時,請自行將原本的設定檔放到新路徑後 reload;套件不會搬動或改寫任何一份檔案。
完整設定範例
下面列出系統音效的欄位和五種事件,可以直接複製作為起點;檔案音效範例另列於下方。不過,實際只要保留想修改的欄位,加上 schemaVersion: 2 就好。每個事件都覆寫了共用訊息,因此這份範例的效果等同內建預設。
{
"schemaVersion": 2,
"enabled": true,
"defaults": {
"toast": {
"enabled": true,
"title": "Pi",
"message": "Pi needs your attention."
},
"sound": {
"enabled": true,
"source": {
"type": "system",
"name": "Exclamation"
}
}
},
"events": {
"permission": {
"enabled": true,
"toast": { "enabled": true, "title": "Pi", "message": "Permission approval needed" },
"sound": { "enabled": true, "source": { "type": "system", "name": "Exclamation" } }
},
"question": {
"enabled": true,
"toast": { "enabled": true, "title": "Pi", "message": "Waiting for your answer" },
"sound": { "enabled": true, "source": { "type": "system", "name": "Exclamation" } }
},
"completed": {
"enabled": true,
"toast": { "enabled": true, "title": "Pi", "message": "Response complete" },
"sound": { "enabled": true, "source": { "type": "system", "name": "Hand" } }
},
"aborted": {
"enabled": true,
"toast": { "enabled": true, "title": "Pi", "message": "Response interrupted" },
"sound": { "enabled": true, "source": { "type": "system", "name": "Exclamation" } }
},
"failed": {
"enabled": true,
"toast": { "enabled": true, "title": "Pi", "message": "Response failed" },
"sound": { "enabled": true, "source": { "type": "system", "name": "Exclamation" } }
}
}
}
欄位與覆寫規則
設定依序套用:內建事件預設 → 共用的 defaults → 個別 events.<事件> 設定。沒寫的欄位沿用前一層。例如,defaults.toast.message 會讓所有事件共用同一則訊息,除非事件另外設定自己的訊息;省略它就能保留內建的各事件文字。
| 欄位 | 用途 |
|---|---|
schemaVersion |
使用這個格式時設為 2 |
enabled |
總開關,false 關閉所有通知 |
defaults |
共用的 toast 和 sound 設定,沒有 defaults.enabled |
events.<事件> |
可設定 permission、question、completed、aborted、failed |
events.<事件>.enabled |
開啟或關閉整個事件 |
toast.enabled |
彈窗開關 |
toast.title |
固定的通知標題 |
toast.message |
固定的通知訊息 |
sound.enabled |
音效開關 |
sound.source.type |
"system" 使用 Windows 系統音效,"file" 使用本機 WAV |
sound.source.name |
"system" 必填:Asterisk、Beep、Exclamation、Hand、Question,大小寫要一致 |
sound.source.path |
"file" 必填:本機 WAV 的絕對路徑,最多 1024 個 UTF-16 code units |
toast 和 sound 欄位都能放在 defaults 或個別事件底下。完整範例已寫出每個事件的所有欄位,只改 defaults 不會改到已被事件覆寫的值。 想讓事件沿用共用設定,請刪除該事件底下對應的欄位。設定 sound.source 時必須提供 type,以及系統音效的 name 或檔案音效的 path,不能同時提供兩者;它會整組取代原本的來源。
- 只要彈窗:將
sound.enabled設為false、toast.enabled設為true。 - 只要音效:將
toast.enabled設為false、sound.enabled設為true。 - 兩個通道都關閉時,不啟動 helper。事件可以覆寫共用通道開關,但不能繞過已關閉的總開關或事件開關。
沒有設定檔時,所有事件與通道都開啟,標題是 Pi,訊息是英文。完成通知使用 Hand,其他事件使用 Exclamation。
文字與音效限制
文字會照你寫的內容顯示,不會從 session 帶入變數,也沒有模板替換。標題最多 128 個 UTF-16 code units,訊息最多 512 個;emoji 可能算兩個。兩者都必須是非空白的單行字串,不能包含控制字元或不合法的 XML 字元。自訂文字會出現在 Windows 通知裡,請不要放敏感資訊;它不會顯示在 status 或錯誤提示中。
音效名稱選的是 Windows 系統音效事件,不是套件內附的不同音效檔。實際聲音取決於 Windows 音效配置;不同事件可能共用同一個聲音,也可能沒有對應音效。你可以在 Windows「音效」設定中查看或修改對應,但修改也會影響使用相同事件的其他程式。改用檔案來源只影響這個 extension,不會修改 Windows 音效配置。
自訂 WAV 音效
例如,讓回應完成時播放你自己的音效:
{
"schemaVersion": 2,
"events": {
"completed": {
"sound": {
"source": { "type": "file", "path": "C:/Users/you/Sounds/done.wav" }
}
}
}
}
同樣的 sound.source 也可以放在 defaults,讓多個事件共用檔案,或為每個事件選擇不同音效。想沿用 defaults 時,請移除原本事件底下的來源覆寫。
格式、路徑、大小與長度限制是刻意的安全取捨:讓檔案存取與播放保持有界,不引入外部 codec/播放器選擇或網路音訊來源。這個 extension 著重短提示音,不是通用媒體播放器。
- 使用本機固定磁碟上的絕對路徑,例如
C:/Sounds/done.wav。正斜線可以直接使用,避免 JSON 跳脫;使用反斜線時,C:\Sounds\done.wav在 JSON 要寫成"C:\\Sounds\\done.wav"。 - 不支援相對路徑、
~、環境變數展開、URL、UNC 路徑、網路磁碟、裝置路徑、alternate data streams 或 reparse points(包含上層目錄的 junction/symlink)。 - 檔案必須是 RIFF PCM WAV:mono 或 stereo、8 或 16 bit、8–48 kHz,最多 5 秒、5 MiB。不支援 MP3、壓縮 WAV 或 WAV extensible;把 MP3 改名成
.wav也不能播放。 - 不提供個別音量、循環播放、外部播放器或內附音效。請使用可信任且有權使用的音訊。
- reload 時驗證路徑;只有啟用的音效實際提交時,才讀取並檢查檔案。檔案不存在、無法讀取、格式不支援或超過限制時回報
SOUND_FAILED,彈窗仍會嘗試送出,不會改播系統音效。 - 檔案路徑透過 stdin 送入固定 helper,不放在命令參數,也不顯示在
status或錯誤提示中。
套用修改與舊格式相容
修改後執行 /reload 或 /windows-notifier reload。如果有未知欄位、不支援的版本或音效來源、值不合法、檔案無法讀取或超過 16 KiB,通知會先停用;修正後再 reload 即可。錯誤提示不會印出設定檔內容。
原本沒有版本欄位、音效使用 boolean 的格式(例如 events.completed.sound: false)仍能使用,只在記憶體裡轉換,不會修改你的檔案。要使用新的通道物件,請加上 schemaVersion: 2;不要把舊的音效 boolean 和 v2 物件混在一起。
指令
在 Pi 裡執行。輸入 /windows-notifier 後按 Tab,會列出 status、reload 或 test;用 ↑/↓ 選擇,再按 Tab 接受。補完 status 或 test 會自動加上空白,接著連按 Tab 即可列出並接受明細選項或事件名稱,不必手動輸入空白;也支援 status a、test co 這類前綴。
/windows-notifier status
/windows-notifier status all
/windows-notifier reload
/windows-notifier test
/windows-notifier test permission
status:以分行摘要查看總開關、backend、事件開啟數、佇列計數、helper 狀態和診斷碼。不帶參數也會顯示相同摘要。status all:在摘要下方列出設定版本、五種事件的開關、彈窗開關與音效開關/來源。事件明細是設定值,實際通知仍受總開關、事件開關、通道開關及 backend 限制。- 摘要與明細都不會顯示自訂文字、檔案路徑或 session 內容;檔案音效只標示為
WAV file。 reload:重新讀取設定,取消舊的通知工作。test:預設測試完成通知,也能指定permission、question、completed、aborted或failed。
status 摘要範例:
Windows notifier status
Global: On
Backend: OK
Configured events: 5 / 5 enabled
Queue: Queued 0 · Dropped 0
Helper: Idle
Diagnostics: None
Details: /windows-notifier status all
status all 會再加上每個事件的明細,例如:
completed Event: On Toast: On Sound: On (Hand)
測試會真的跳通知、播放音效。 和自動通知一樣,它會遵守開關、佇列與限流,不會強行送出已停用的事件。
常見問題
為什麼沒看到通知?
Windows 仍然有最終決定權。勿擾模式、通知設定、系統音效方案和靜音,都可能讓已提交的通知沒有彈出或沒有聲音。
因為使用 Microsoft.Windows.PowerShell AppID,通知來源可能顯示 PowerShell,但彈窗標題預設是 Pi,也可以改成你設定的標題。Toast 自帶的音效關閉,提示音另外播放,避免這個 backend 自己重複響兩次。彈窗和音效分開處理,一個失敗仍會嘗試另一個;沒有備用通知方式或播放器。
可以用 /windows-notifier status 查看診斷碼:
| 診斷碼 | 意義或處理方式 |
|---|---|
CONFIG_INVALID/CONFIG_TOO_LARGE/CONFIG_READ_FAILED |
修正全域設定檔後 reload |
ENV_UNSUPPORTED |
請使用支援的 Windows 64 位元 Pi 互動式介面 |
BACKEND_UNAVAILABLE |
檢查 Windows 路徑、PowerShell 和 helper 是否可用 |
UI_AMBIGUOUS/TOOLS_LIMIT |
無法安全辨識 UI 來源,或追蹤已達上限 |
QUEUE_DROPPED |
佇列已滿,有通知被丟棄 |
HELPER_TIMEOUT/OUTPUT_LIMIT/LAUNCH_FAILED |
helper 超時、輸出過多或啟動失敗 |
TOAST_FAILED/SOUND_FAILED/BOTH_FAILED |
Windows 彈窗、音效或兩者提交失敗 |
INPUT_INVALID/INTERNAL_ERROR/HELPER_PROTOCOL |
檢查套件安裝與 helper 協定 |
自動通知錯誤最多每分鐘顯示一次終端警告。診斷只使用固定代碼,不會帶出 PowerShell 原始錯誤內容。
隱私與程序安全
套件透過固定的 PowerShell 腳本呼叫 Windows 內建通知和音效 API,不用另外裝通知服務或播放器。沒有網路通知、遙測、下載或內附音效檔。
部分功能限制是刻意的安全設計,不只是平台限制。以下防護針對命令注入、執行檔搜尋劫持、憑證意外外洩、網路路徑存取、無界程序建立,以及誤傷其他程式等風險;不代表套件保證沒有漏洞。
- 為降低執行檔搜尋劫持風險,PowerShell 使用啟動環境的
SystemRoot/windir下的絕對路徑,不從專案目錄或PATH搜尋。 - 為避免設定值造成命令/XML 注入,helper 不透過 shell 執行,只從 stdin 接收事件類型、已驗證的通道設定(含自訂音效的本機 WAV 路徑)與固定設定文字。文字用 DOM text node 加進通知,不拼進 PowerShell 命令或 XML,也不傳入 session 內容。
- 為降低憑證意外外洩風險,子程序只拿到必要的 Windows 環境變數,不繼承 Pi 的完整環境或 API tokens。
-ExecutionPolicy Bypass只作用於該子程序,不會取得管理員權限或改動永久設定,也不把 Execution Policy 當成安全邊界。 - WAV 播放前會檢查本機磁碟路徑與 reparse points,讀入有大小限制的記憶體並驗證格式,再交給
System.Media.SoundPlayer。播放留在同一個 helper,沿用逾時與取消機制;檔案檢查不是防止攻擊者同時修改路徑的 sandbox。 - 為限制大量程序啟動與資源消耗,同時最多一個 helper,佇列最多 16 筆,啟動至少間隔一秒。工作等待超過 30 秒會過期,helper 的 timeout 是 10 秒,stdout 和 stderr 各限制 8 KiB。權限和提問比回應結束通知優先。
- 為避免誤關其他程式,只嘗試終止自己建立的子程序,不會按名稱關閉其他程序。如果 Windows 不允許終止,就等它結束,不會繼續堆出新的 helper。
- 權限決策、問題結束、新回應、reload、session 切換和 shutdown 都會取消相關舊工作。已經顯示的 Toast 無法收回,取消和提交給 Windows 之間仍可能發生競態。
這些防護假設 Windows 系統目錄、Pi 啟動環境和已安裝套件可信。它們無法防禦同程序裡的惡意 extension,或已遭入侵的使用者帳號。Pi permission system 並不是 extension 的 OS 沙盒。
開發
專案記憶(保存在 repository,不隨 npm 套件發布):目前狀態 · 程式碼架構。開始維護時先讀狀態與架構,再核對本次任務相關的程式碼;功能、架構或驗證結果改變時同步更新對應文件。
npm ci --ignore-scripts
npm run verify
npm pack --dry-run
測試使用假時鐘、event bus 和 launcher。Windows 上也會檢查 PowerShell 語法、無效輸入、PCM WAV 驗證、有界檔案讀取與 junction 拒絕。一般 npm test 不會跳彈窗或播放音效;測試範圍與仍需確認的項目統一見目前狀態與驗證紀錄。
授權
MIT。上游來源和授權聲明見 THIRD_PARTY_NOTICES.md。