@pi-unipi/notify 0.1.7 → 0.1.8
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/events.ts +29 -25
- package/package.json +1 -1
- package/tools.ts +7 -14
package/events.ts
CHANGED
|
@@ -56,10 +56,13 @@ export function registerEventListeners(
|
|
|
56
56
|
const eventConfig = config.events[eventKey];
|
|
57
57
|
if (!eventConfig?.enabled) continue;
|
|
58
58
|
|
|
59
|
-
const handler =
|
|
59
|
+
const handler = (payload: unknown) => {
|
|
60
60
|
const title = `Pi — ${def.label}`;
|
|
61
61
|
const message = buildEventMessage(eventKey, payload);
|
|
62
|
-
|
|
62
|
+
// Fire-and-forget: don't block the event emitter
|
|
63
|
+
dispatchNotification(pi, title, message, eventConfig.platforms, eventKey, config).catch(
|
|
64
|
+
(err) => console.error(`[notify] Background notification failed for ${eventKey}:`, err)
|
|
65
|
+
);
|
|
63
66
|
};
|
|
64
67
|
|
|
65
68
|
(pi as any).on(def.hook, handler);
|
|
@@ -68,43 +71,44 @@ export function registerEventListeners(
|
|
|
68
71
|
// agent_end — custom handler with session name and recap support
|
|
69
72
|
const agentEndConfig = config.events["agent_end"];
|
|
70
73
|
if (agentEndConfig?.enabled) {
|
|
71
|
-
const handler =
|
|
74
|
+
const handler = (payload: unknown) => {
|
|
75
|
+
// Fire-and-forget: build message and dispatch in background,
|
|
76
|
+
// don't block agent_end from completing
|
|
72
77
|
const sessionName = pi.getSessionName?.();
|
|
73
78
|
const title = `Pi — ${BUILTIN_EVENTS.agent_end.label}`;
|
|
74
|
-
let message: string;
|
|
75
79
|
|
|
76
80
|
if (config.recap.enabled) {
|
|
77
|
-
// Recap mode: summarize
|
|
81
|
+
// Recap mode: summarize asynchronously, then dispatch
|
|
78
82
|
const lastText = extractLastAssistantText(payload);
|
|
79
83
|
if (lastText && sessionCtx?.modelRegistry) {
|
|
80
84
|
const provider = extractProvider(config.recap.model);
|
|
81
85
|
const modelId = extractModelId(config.recap.model);
|
|
82
86
|
const model = sessionCtx.modelRegistry.find(provider, modelId);
|
|
83
87
|
if (model) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
message
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
88
|
+
sessionCtx.modelRegistry.getApiKeyAndHeaders(model)
|
|
89
|
+
.then((apiKeyResult) => {
|
|
90
|
+
const apiKey = apiKeyResult.ok ? (apiKeyResult as { apiKey?: string }).apiKey : undefined;
|
|
91
|
+
if (apiKey) {
|
|
92
|
+
return summarizeLastMessage(lastText, apiKey, model.baseUrl, model.api, modelId)
|
|
93
|
+
.then((recap) => sessionName ? `${sessionName}: ${recap}` : recap);
|
|
94
|
+
}
|
|
95
|
+
return buildAgentEndMessage(sessionName);
|
|
96
|
+
})
|
|
97
|
+
.catch(() => buildAgentEndMessage(sessionName))
|
|
98
|
+
.then((message) =>
|
|
99
|
+
dispatchNotification(pi, title, message, agentEndConfig.platforms, "agent_end", config)
|
|
100
|
+
)
|
|
101
|
+
.catch((err) => console.error("[notify] Background agent_end notification failed:", err));
|
|
102
|
+
return;
|
|
98
103
|
}
|
|
99
|
-
} else {
|
|
100
|
-
message = buildAgentEndMessage(sessionName);
|
|
101
104
|
}
|
|
102
|
-
} else {
|
|
103
|
-
// No recap: use session name based message
|
|
104
|
-
message = buildAgentEndMessage(sessionName);
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
|
|
107
|
+
// No recap or recap unavailable: dispatch immediately in background
|
|
108
|
+
const message = buildAgentEndMessage(sessionName);
|
|
109
|
+
dispatchNotification(pi, title, message, agentEndConfig.platforms, "agent_end", config).catch(
|
|
110
|
+
(err) => console.error("[notify] Background agent_end notification failed:", err)
|
|
111
|
+
);
|
|
108
112
|
};
|
|
109
113
|
|
|
110
114
|
(pi as any).on("agent_end", handler);
|
package/package.json
CHANGED
package/tools.ts
CHANGED
|
@@ -9,7 +9,6 @@ import { Type } from "@sinclair/typebox";
|
|
|
9
9
|
import { NOTIFY_TOOLS } from "@pi-unipi/core";
|
|
10
10
|
import { loadConfig } from "./settings.js";
|
|
11
11
|
import { dispatchNotification } from "./events.js";
|
|
12
|
-
import type { NotifyDispatchResult } from "./types.js";
|
|
13
12
|
|
|
14
13
|
/** Schema for notify_user tool parameters */
|
|
15
14
|
const NotifyUserSchema = Type.Object({
|
|
@@ -43,7 +42,7 @@ export function registerNotifyTools(pi: ExtensionAPI): void {
|
|
|
43
42
|
"Send a notification to the user's configured platforms (native OS, Gotify, Telegram, ntfy). " +
|
|
44
43
|
"Use for critical errors, completion of long-running tasks, or when the user explicitly asked to be notified.",
|
|
45
44
|
parameters: NotifyUserSchema,
|
|
46
|
-
async execute(_toolCallId, params, _signal, _onUpdate,
|
|
45
|
+
async execute(_toolCallId, params, _signal, _onUpdate, _ctx: ExtensionContext) {
|
|
47
46
|
const {
|
|
48
47
|
message,
|
|
49
48
|
title,
|
|
@@ -64,32 +63,26 @@ export function registerNotifyTools(pi: ExtensionAPI): void {
|
|
|
64
63
|
// Resolve platforms — use params.platforms or global defaults
|
|
65
64
|
const notifPlatforms = platforms || config.defaultPlatforms;
|
|
66
65
|
|
|
67
|
-
//
|
|
68
|
-
|
|
66
|
+
// Fire-and-forget: dispatch in background so the tool doesn't block the agent
|
|
67
|
+
dispatchNotification(
|
|
69
68
|
pi,
|
|
70
69
|
notifTitle,
|
|
71
70
|
message,
|
|
72
71
|
notifPlatforms,
|
|
73
72
|
"agent_tool",
|
|
74
73
|
config
|
|
75
|
-
)
|
|
76
|
-
|
|
77
|
-
// Format result
|
|
78
|
-
const platformResults = result.results.map(
|
|
79
|
-
(r) => `${r.platform}: ${r.success ? "✓ sent" : `✗ ${r.error || "failed"}`}`
|
|
74
|
+
).catch((err) =>
|
|
75
|
+
console.error("[notify] Background notify_user dispatch failed:", err)
|
|
80
76
|
);
|
|
81
77
|
|
|
82
78
|
return {
|
|
83
79
|
content: [
|
|
84
80
|
{
|
|
85
81
|
type: "text" as const,
|
|
86
|
-
text: `Notification
|
|
82
|
+
text: `Notification sending to ${notifPlatforms.length} platform(s): ${notifPlatforms.join(", ")}`,
|
|
87
83
|
},
|
|
88
84
|
],
|
|
89
|
-
details: {
|
|
90
|
-
platforms: result.results.map((r) => r.platform),
|
|
91
|
-
allSuccess: result.allSuccess,
|
|
92
|
-
},
|
|
85
|
+
details: { platforms: notifPlatforms },
|
|
93
86
|
};
|
|
94
87
|
},
|
|
95
88
|
});
|