opencode-plugin-apprise 1.1.0 → 1.2.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 +2 -15
- package/dist/hooks/idle.d.ts +1 -1
- package/dist/opencode-plugin-apprise.js +17 -26
- package/dist/types.d.ts +1 -2
- package/package.json +1 -1
- package/dist/hooks/background.d.ts +0 -4
package/README.md
CHANGED
|
@@ -5,9 +5,8 @@ OpenCode plugin for multi-service notifications via Apprise.
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
- Multi-service support for 128+ notification services via Apprise.
|
|
8
|
-
- Automatic notifications when sessions go idle.
|
|
8
|
+
- Automatic notifications when foreground sessions go idle (background tasks are excluded).
|
|
9
9
|
- Delayed notifications for Question tool prompts (30-second grace period).
|
|
10
|
-
- Alerts when sessions transition to idle after activity.
|
|
11
10
|
- Notifications for permission requests with dual-mechanism reliability.
|
|
12
11
|
|
|
13
12
|
## Prerequisites
|
|
@@ -74,7 +73,7 @@ For complete configuration options, see: https://github.com/caronc/apprise#confi
|
|
|
74
73
|
|
|
75
74
|
### Idle
|
|
76
75
|
|
|
77
|
-
Fires
|
|
76
|
+
Fires when a foreground session goes idle. Only sessions where the user has sent at least one message are tracked — background agent sessions are excluded. Includes the last user request, agent response, and todo status.
|
|
78
77
|
|
|
79
78
|
**Severity**: info
|
|
80
79
|
|
|
@@ -100,17 +99,6 @@ Options:
|
|
|
100
99
|
3. cancel
|
|
101
100
|
```
|
|
102
101
|
|
|
103
|
-
### Background
|
|
104
|
-
|
|
105
|
-
Fires when a session's status transitions to `idle` after being active. This indicates the agent has finished working and the session is waiting.
|
|
106
|
-
|
|
107
|
-
**Severity**: success
|
|
108
|
-
|
|
109
|
-
```
|
|
110
|
-
✅ Background Task Complete
|
|
111
|
-
Task: Session ses_abc123
|
|
112
|
-
```
|
|
113
|
-
|
|
114
102
|
### Permission
|
|
115
103
|
|
|
116
104
|
Fires when a tool requires explicit user permission. Uses two mechanisms for reliability: the primary `permission.ask` hook and a fallback `permission.updated` event listener. Permissions are deduplicated by ID to prevent double notifications.
|
|
@@ -150,7 +138,6 @@ Identical notifications are suppressed for 5 minutes. Duplicates are identified
|
|
|
150
138
|
|-------|:-------------|
|
|
151
139
|
| Idle | info |
|
|
152
140
|
| Question | warning |
|
|
153
|
-
| Background | success |
|
|
154
141
|
| Permission | warning |
|
|
155
142
|
|
|
156
143
|
## Troubleshooting
|
package/dist/hooks/idle.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { Hooks, PluginInput } from "@opencode-ai/plugin";
|
|
2
2
|
import type { DedupChecker } from "../dedup.js";
|
|
3
3
|
import type { PluginConfig } from "../types.js";
|
|
4
|
-
export declare function createIdleHook(ctx: PluginInput, config: PluginConfig, dedup: DedupChecker): NonNullable<Hooks["event"]>;
|
|
4
|
+
export declare function createIdleHook(ctx: PluginInput, config: PluginConfig, dedup: DedupChecker, interactiveSessions: Set<string>): NonNullable<Hooks["event"]>;
|
|
@@ -54,7 +54,6 @@ function createDedupChecker() {
|
|
|
54
54
|
var TYPE_MAP = {
|
|
55
55
|
idle: "info",
|
|
56
56
|
question: "warning",
|
|
57
|
-
background: "success",
|
|
58
57
|
permission: "warning"
|
|
59
58
|
};
|
|
60
59
|
var DEFAULT_TRUNCATE_LENGTH = 1500;
|
|
@@ -127,17 +126,6 @@ ${context.options.map((option, index) => ` ${index + 1}. ${option}`).join(`
|
|
|
127
126
|
}
|
|
128
127
|
body = parts.join(`
|
|
129
128
|
|
|
130
|
-
`);
|
|
131
|
-
break;
|
|
132
|
-
}
|
|
133
|
-
case "background": {
|
|
134
|
-
const parts = [];
|
|
135
|
-
if (context.taskName)
|
|
136
|
-
parts.push(`Task: ${context.taskName}`);
|
|
137
|
-
if (context.agentResponse)
|
|
138
|
-
parts.push(`Result: ${context.agentResponse}`);
|
|
139
|
-
body = parts.join(`
|
|
140
|
-
|
|
141
129
|
`);
|
|
142
130
|
break;
|
|
143
131
|
}
|
|
@@ -220,7 +208,6 @@ var EMPTY_CONTEXT = {
|
|
|
220
208
|
question: undefined,
|
|
221
209
|
options: undefined,
|
|
222
210
|
todoStatus: undefined,
|
|
223
|
-
taskName: undefined,
|
|
224
211
|
toolName: undefined,
|
|
225
212
|
action: undefined
|
|
226
213
|
};
|
|
@@ -243,15 +230,12 @@ async function sendHookNotification(hookName, config, dedup, payload) {
|
|
|
243
230
|
}
|
|
244
231
|
|
|
245
232
|
// src/hooks/idle.ts
|
|
246
|
-
function extractText(
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
}
|
|
250
|
-
const parts = Array.isArray(message) ? message.map((p) => typeof p === "string" ? p : p.text || "") : [];
|
|
251
|
-
return parts.join(`
|
|
233
|
+
function extractText(parts) {
|
|
234
|
+
const texts = parts.filter((p) => p.type === "text" && p.text).map((p) => p.text);
|
|
235
|
+
return texts.join(`
|
|
252
236
|
`).trim() || undefined;
|
|
253
237
|
}
|
|
254
|
-
function createIdleHook(ctx, config, dedup) {
|
|
238
|
+
function createIdleHook(ctx, config, dedup, interactiveSessions) {
|
|
255
239
|
return async ({ event }) => {
|
|
256
240
|
if (event.type !== "session.status")
|
|
257
241
|
return;
|
|
@@ -260,6 +244,8 @@ function createIdleHook(ctx, config, dedup) {
|
|
|
260
244
|
return;
|
|
261
245
|
if (!props.sessionID)
|
|
262
246
|
return;
|
|
247
|
+
if (!interactiveSessions.has(props.sessionID))
|
|
248
|
+
return;
|
|
263
249
|
let userRequest = undefined;
|
|
264
250
|
let agentResponse = undefined;
|
|
265
251
|
let todoStatus = undefined;
|
|
@@ -270,16 +256,16 @@ function createIdleHook(ctx, config, dedup) {
|
|
|
270
256
|
const messages = messagesResponse.data ?? [];
|
|
271
257
|
for (let i = messages.length - 1;i >= 0; i--) {
|
|
272
258
|
const msg = messages[i];
|
|
273
|
-
if (msg?.role === "user") {
|
|
274
|
-
userRequest = extractText(msg.
|
|
259
|
+
if (msg?.info?.role === "user") {
|
|
260
|
+
userRequest = extractText(msg.parts);
|
|
275
261
|
break;
|
|
276
262
|
}
|
|
277
263
|
}
|
|
278
264
|
if (userRequest) {
|
|
279
265
|
for (let i = messages.length - 1;i >= 0; i--) {
|
|
280
266
|
const msg = messages[i];
|
|
281
|
-
if (msg?.role === "assistant") {
|
|
282
|
-
agentResponse = extractText(msg.
|
|
267
|
+
if (msg?.info?.role === "assistant") {
|
|
268
|
+
agentResponse = extractText(msg.parts);
|
|
283
269
|
break;
|
|
284
270
|
}
|
|
285
271
|
}
|
|
@@ -392,7 +378,8 @@ var plugin = async (input) => {
|
|
|
392
378
|
return {};
|
|
393
379
|
}
|
|
394
380
|
const dedup = createDedupChecker();
|
|
395
|
-
const
|
|
381
|
+
const interactiveSessions = new Set;
|
|
382
|
+
const idleHook = createIdleHook(input, config, dedup, interactiveSessions);
|
|
396
383
|
const questionHook = createQuestionHook(config, dedup);
|
|
397
384
|
const permissionHooks = createPermissionHooks(config, dedup);
|
|
398
385
|
const combinedEventHook = async ({ event }) => {
|
|
@@ -400,9 +387,13 @@ var plugin = async (input) => {
|
|
|
400
387
|
await permissionHooks.eventFallback({ event });
|
|
401
388
|
await idleHook({ event });
|
|
402
389
|
};
|
|
390
|
+
const chatMessageHook = async (input2) => {
|
|
391
|
+
interactiveSessions.add(input2.sessionID);
|
|
392
|
+
};
|
|
403
393
|
return {
|
|
404
394
|
event: combinedEventHook,
|
|
405
|
-
"permission.ask": permissionHooks.permissionAsk
|
|
395
|
+
"permission.ask": permissionHooks.permissionAsk,
|
|
396
|
+
"chat.message": chatMessageHook
|
|
406
397
|
};
|
|
407
398
|
};
|
|
408
399
|
var src_default = plugin;
|
package/dist/types.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export interface PluginConfig {
|
|
2
2
|
tag?: string;
|
|
3
3
|
}
|
|
4
|
-
export type HookEventType = "idle" | "question" | "
|
|
4
|
+
export type HookEventType = "idle" | "question" | "permission";
|
|
5
5
|
export type AppriseNotificationType = "info" | "warning" | "success" | "failure";
|
|
6
6
|
export interface NotificationContext {
|
|
7
7
|
userRequest: string | undefined;
|
|
@@ -9,7 +9,6 @@ export interface NotificationContext {
|
|
|
9
9
|
question: string | undefined;
|
|
10
10
|
options: string[] | undefined;
|
|
11
11
|
todoStatus: string | undefined;
|
|
12
|
-
taskName: string | undefined;
|
|
13
12
|
toolName: string | undefined;
|
|
14
13
|
action: string | undefined;
|
|
15
14
|
}
|
package/package.json
CHANGED