omp packages

pi-windows-notifier0.4.0

Built for Windows. Zero dependencies. Customizable, security-first notifications and alert sounds for Pi.

cwz-dev Published 9 days ago MIT ~1.1K downloads/mo

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.

Did it work for you?

Result

One report per person. A new report replaces your old one.

Reports 0

No reports yet.

Readme

pi-windows-notifier

Pi 套件頁 · GitHub · npm

English | 繁體中文

專為 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。