@pi-unipi/notify 2.4.0 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -47,6 +47,8 @@ notify_user({
47
47
  })
48
48
  ```
49
49
 
50
+ An explicit semantic priority overrides configured urgency for that dispatch on platforms that support it: `low`/`normal`/`high` map to Gotify `2`/`5`/`8` and ntfy `2`/`3`/`5`. Native and Telegram have no priority input and ignore it. When omitted, Gotify and ntfy retain their configured numeric priorities.
51
+
50
52
  ## Platforms
51
53
 
52
54
  ### Native OS
package/events.ts CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
9
9
  import { UNIPI_EVENTS, emitEvent } from "@pi-unipi/core";
10
- import type { NotifyConfig, NotifyPlatform, NotifyDispatchResult } from "./types.js";
10
+ import type { NotifyConfig, NotifyPlatform, NotifyDispatchResult, NotifyPriority } from "./types.js";
11
11
  import { loadNtfyConfig } from "./ntfy-config.js";
12
12
  import { sendNativeNotification, SuppressedError } from "./platforms/native.js";
13
13
  import { sendGotifyNotification } from "./platforms/gotify.js";
@@ -170,7 +170,8 @@ export async function dispatchNotification(
170
170
  eventPlatforms: NotifyPlatform[],
171
171
  eventType: string,
172
172
  config: NotifyConfig,
173
- cwd: string
173
+ cwd: string,
174
+ priority?: NotifyPriority,
174
175
  ): Promise<NotifyDispatchResult> {
175
176
  // Resolve ntfy config from project/global ntfy.json
176
177
  const ntfyConfig = loadNtfyConfig(cwd);
@@ -194,8 +195,8 @@ export async function dispatchNotification(
194
195
  const results = await Promise.all(
195
196
  enabledPlatforms.map(async (platform) => {
196
197
  try {
197
- await sendToPlatform(platform, title, message, config, cwd);
198
- return { platform, success: true };
198
+ const effectivePriority = await sendToPlatform(platform, title, message, config, cwd, priority);
199
+ return { platform, success: true, ...(effectivePriority === undefined ? {} : { priority: effectivePriority }) };
199
200
  } catch (err) {
200
201
  // SuppressedError is intentional, not a failure
201
202
  if (err instanceof SuppressedError) {
@@ -230,20 +231,29 @@ export async function dispatchNotification(
230
231
  }
231
232
 
232
233
  /** Send to a single platform */
234
+ export function mapNotifyPriority(platform: "gotify" | "ntfy", priority: NotifyPriority): number {
235
+ const mappings = {
236
+ gotify: { low: 2, normal: 5, high: 8 },
237
+ ntfy: { low: 2, normal: 3, high: 5 },
238
+ } as const;
239
+ return mappings[platform][priority];
240
+ }
241
+
233
242
  async function sendToPlatform(
234
243
  platform: NotifyPlatform,
235
244
  title: string,
236
245
  message: string,
237
246
  config: NotifyConfig,
238
- cwd: string
239
- ): Promise<void> {
247
+ cwd: string,
248
+ priority?: NotifyPriority,
249
+ ): Promise<number | undefined> {
240
250
  switch (platform) {
241
251
  case "native":
242
252
  await sendNativeNotification(title, message, {
243
253
  windowsAppId: config.native.windowsAppId,
244
254
  suppressWhenFocused: config.native.suppressWhenFocused,
245
255
  });
246
- break;
256
+ return undefined;
247
257
  case "gotify":
248
258
  if (!config.gotify.serverUrl || !config.gotify.appToken) {
249
259
  throw new Error("Gotify: serverUrl and appToken are required");
@@ -253,9 +263,9 @@ async function sendToPlatform(
253
263
  config.gotify.appToken,
254
264
  title,
255
265
  message,
256
- config.gotify.priority
266
+ priority ? mapNotifyPriority("gotify", priority) : config.gotify.priority
257
267
  );
258
- break;
268
+ return priority ? mapNotifyPriority("gotify", priority) : config.gotify.priority;
259
269
  case "telegram":
260
270
  if (!config.telegram.botToken || !config.telegram.chatId) {
261
271
  throw new Error("Telegram: botToken and chatId are required");
@@ -266,10 +276,10 @@ async function sendToPlatform(
266
276
  title,
267
277
  message
268
278
  );
269
- break;
279
+ return undefined;
270
280
  case "ntfy": {
271
281
  const ntfyConfig = loadNtfyConfig(cwd);
272
- if (!ntfyConfig.enabled) return;
282
+ if (!ntfyConfig.enabled) return undefined;
273
283
  if (!ntfyConfig.serverUrl || !ntfyConfig.topic) {
274
284
  throw new Error("ntfy: serverUrl and topic are required");
275
285
  }
@@ -278,10 +288,10 @@ async function sendToPlatform(
278
288
  ntfyConfig.topic,
279
289
  title,
280
290
  message,
281
- ntfyConfig.priority,
291
+ priority ? mapNotifyPriority("ntfy", priority) : ntfyConfig.priority,
282
292
  ntfyConfig.token
283
293
  );
284
- break;
294
+ return priority ? mapNotifyPriority("ntfy", priority) : ntfyConfig.priority;
285
295
  }
286
296
  }
287
297
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/notify",
3
- "version": "2.4.0",
3
+ "version": "2.4.1",
4
4
  "description": "Cross-platform notification extension for Pi — native OS, Gotify, and Telegram notifications for agent lifecycle events",
5
5
  "type": "module",
6
6
  "main": "index.ts",
@@ -34,7 +34,7 @@
34
34
  "access": "public"
35
35
  },
36
36
  "dependencies": {
37
- "@pi-unipi/core": "2.4.0",
37
+ "@pi-unipi/core": "2.4.1",
38
38
  "node-notifier": "^10.0.1"
39
39
  },
40
40
  "peerDependencies": {
package/tools.ts CHANGED
@@ -8,7 +8,8 @@ import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-a
8
8
  import { Type } from "typebox";
9
9
  import { NOTIFY_TOOLS } from "@pi-unipi/core";
10
10
  import { loadConfig } from "./settings.js";
11
- import { dispatchNotification } from "./events.js";
11
+ import { dispatchNotification, mapNotifyPriority } from "./events.js";
12
+ import type { NotifyPriority } from "./types.js";
12
13
 
13
14
  /** Schema for notify_user tool parameters */
14
15
  const NotifyUserSchema = Type.Object({
@@ -19,7 +20,6 @@ const NotifyUserSchema = Type.Object({
19
20
  priority: Type.Optional(
20
21
  Type.String({
21
22
  enum: ["low", "normal", "high"],
22
- default: "normal",
23
23
  description: "Priority level",
24
24
  })
25
25
  ),
@@ -46,12 +46,12 @@ export function registerNotifyTools(pi: ExtensionAPI): void {
46
46
  const {
47
47
  message,
48
48
  title,
49
- priority: _priority,
49
+ priority,
50
50
  platforms,
51
51
  } = params as {
52
52
  message: string;
53
53
  title?: string;
54
- priority?: "low" | "normal" | "high";
54
+ priority?: NotifyPriority;
55
55
  platforms?: Array<"native" | "gotify" | "telegram" | "ntfy">;
56
56
  };
57
57
 
@@ -65,18 +65,27 @@ export function registerNotifyTools(pi: ExtensionAPI): void {
65
65
 
66
66
  // Fire-and-forget: dispatch in background so the tool doesn't block the agent
67
67
  const cwd = process.cwd();
68
- dispatchNotification(
68
+ const dispatchPromise = dispatchNotification(
69
69
  pi,
70
70
  notifTitle,
71
71
  message,
72
72
  notifPlatforms,
73
73
  "agent_tool",
74
74
  config,
75
- cwd
76
- ).catch(() => {
75
+ cwd,
76
+ priority,
77
+ );
78
+ void dispatchPromise.catch(() => {
77
79
  // Silently ignore — background dispatch failure is non-blocking.
78
80
  });
79
81
 
82
+ const priorityByPlatform = priority ? Object.fromEntries(
83
+ notifPlatforms.flatMap((platform) => {
84
+ if (platform === "gotify" || platform === "ntfy") return [[platform, mapNotifyPriority(platform, priority)]];
85
+ return [];
86
+ }),
87
+ ) : undefined;
88
+
80
89
  return {
81
90
  content: [
82
91
  {
@@ -84,7 +93,7 @@ export function registerNotifyTools(pi: ExtensionAPI): void {
84
93
  text: `Notification sending to ${notifPlatforms.length} platform(s): ${notifPlatforms.join(", ")}`,
85
94
  },
86
95
  ],
87
- details: { platforms: notifPlatforms },
96
+ details: { platforms: notifPlatforms, priority, priorityByPlatform },
88
97
  };
89
98
  },
90
99
  });
package/types.ts CHANGED
@@ -90,13 +90,15 @@ export interface NotifyConfig {
90
90
  }
91
91
 
92
92
  /** Parameters for the notify_user agent tool */
93
+ export type NotifyPriority = "low" | "normal" | "high";
94
+
93
95
  export interface NotifyUserParams {
94
96
  /** Notification message body */
95
97
  message: string;
96
98
  /** Notification title (default: "Pi Notification") */
97
99
  title?: string;
98
100
  /** Priority level */
99
- priority?: "low" | "normal" | "high";
101
+ priority?: NotifyPriority;
100
102
  /** Override platforms for this notification */
101
103
  platforms?: NotifyPlatform[];
102
104
  }
@@ -109,6 +111,8 @@ export interface NotifyResult {
109
111
  success: boolean;
110
112
  /** True when the notification was intentionally suppressed (e.g. window focused) */
111
113
  suppressed?: boolean;
114
+ /** Effective numeric priority for platforms that support it. */
115
+ priority?: number;
112
116
  /** Error message if failed */
113
117
  error?: string;
114
118
  }