@mohak34/opencode-notifier 0.1.12 → 0.1.14
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 +71 -16
- package/dist/index.js +133 -20
- package/package.json +1 -1
- package/sounds/subagent_complete.wav +0 -0
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ To pin a specific version:
|
|
|
18
18
|
|
|
19
19
|
```json
|
|
20
20
|
{
|
|
21
|
-
"plugin": ["@mohak34/opencode-notifier@0.1.
|
|
21
|
+
"plugin": ["@mohak34/opencode-notifier@0.1.14"]
|
|
22
22
|
}
|
|
23
23
|
```
|
|
24
24
|
|
|
@@ -46,13 +46,13 @@ Remove-Item -Recurse -Force "$env:USERPROFILE\.cache\opencode\node_modules\@moha
|
|
|
46
46
|
|
|
47
47
|
Then restart OpenCode - it will download the latest version automatically.
|
|
48
48
|
|
|
49
|
-
### If you use a pinned version (e.g., `@0.1.
|
|
49
|
+
### If you use a pinned version (e.g., `@0.1.14`)
|
|
50
50
|
|
|
51
51
|
1. Update the version in your `opencode.json`:
|
|
52
52
|
|
|
53
53
|
```json
|
|
54
54
|
{
|
|
55
|
-
"plugin": ["@mohak34/opencode-notifier@0.1.
|
|
55
|
+
"plugin": ["@mohak34/opencode-notifier@0.1.14"]
|
|
56
56
|
}
|
|
57
57
|
```
|
|
58
58
|
|
|
@@ -91,21 +91,31 @@ To customize the plugin, create `~/.config/opencode/opencode-notifier.json`:
|
|
|
91
91
|
"sound": true,
|
|
92
92
|
"notification": true,
|
|
93
93
|
"timeout": 5,
|
|
94
|
+
"showProjectName": true,
|
|
95
|
+
"command": {
|
|
96
|
+
"enabled": false,
|
|
97
|
+
"path": "/path/to/command",
|
|
98
|
+
"args": ["--event", "{event}", "--message", "{message}"],
|
|
99
|
+
"minDuration": 0
|
|
100
|
+
},
|
|
94
101
|
"events": {
|
|
95
102
|
"permission": { "sound": true, "notification": true },
|
|
96
103
|
"complete": { "sound": true, "notification": true },
|
|
104
|
+
"subagent_complete": { "sound": false, "notification": false },
|
|
97
105
|
"error": { "sound": true, "notification": true },
|
|
98
106
|
"question": { "sound": true, "notification": true }
|
|
99
107
|
},
|
|
100
108
|
"messages": {
|
|
101
|
-
"permission": "
|
|
102
|
-
"complete": "
|
|
103
|
-
"
|
|
104
|
-
"
|
|
109
|
+
"permission": "Session needs permission",
|
|
110
|
+
"complete": "Session has finished",
|
|
111
|
+
"subagent_complete": "Subagent has finished",
|
|
112
|
+
"error": "Session encountered an error",
|
|
113
|
+
"question": "Session has a question"
|
|
105
114
|
},
|
|
106
115
|
"sounds": {
|
|
107
116
|
"permission": "/path/to/custom/sound.wav",
|
|
108
117
|
"complete": "/path/to/custom/sound.wav",
|
|
118
|
+
"subagent_complete": "/path/to/custom/sound.wav",
|
|
109
119
|
"error": "/path/to/custom/sound.wav",
|
|
110
120
|
"question": "/path/to/custom/sound.wav"
|
|
111
121
|
}
|
|
@@ -119,6 +129,8 @@ To customize the plugin, create `~/.config/opencode/opencode-notifier.json`:
|
|
|
119
129
|
| `sound` | boolean | `true` | Global toggle for all sounds |
|
|
120
130
|
| `notification` | boolean | `true` | Global toggle for all notifications |
|
|
121
131
|
| `timeout` | number | `5` | Notification duration in seconds (Linux only) |
|
|
132
|
+
| `showProjectName` | boolean | `true` | Show project folder name in notification title |
|
|
133
|
+
| `command` | object | — | Command execution settings (enabled/path/args/minDuration) |
|
|
122
134
|
|
|
123
135
|
### Events
|
|
124
136
|
|
|
@@ -129,6 +141,7 @@ Control sound and notification separately for each event:
|
|
|
129
141
|
"events": {
|
|
130
142
|
"permission": { "sound": true, "notification": true },
|
|
131
143
|
"complete": { "sound": false, "notification": true },
|
|
144
|
+
"subagent_complete": { "sound": true, "notification": false },
|
|
132
145
|
"error": { "sound": true, "notification": false },
|
|
133
146
|
"question": { "sound": true, "notification": true }
|
|
134
147
|
}
|
|
@@ -142,12 +155,15 @@ Or use a boolean to toggle both:
|
|
|
142
155
|
"events": {
|
|
143
156
|
"permission": true,
|
|
144
157
|
"complete": false,
|
|
158
|
+
"subagent_complete": true,
|
|
145
159
|
"error": true,
|
|
146
160
|
"question": true
|
|
147
161
|
}
|
|
148
162
|
}
|
|
149
163
|
```
|
|
150
164
|
|
|
165
|
+
Note: `complete` fires for primary (main) session completion, while `subagent_complete` fires for subagent completion. `subagent_complete` defaults to disabled (both sound and notification are false).
|
|
166
|
+
|
|
151
167
|
### Messages
|
|
152
168
|
|
|
153
169
|
Customize notification text:
|
|
@@ -157,12 +173,33 @@ Customize notification text:
|
|
|
157
173
|
"messages": {
|
|
158
174
|
"permission": "Action required",
|
|
159
175
|
"complete": "Done!",
|
|
176
|
+
"subagent_complete": "Subagent finished",
|
|
160
177
|
"error": "Something went wrong",
|
|
161
178
|
"question": "Input needed"
|
|
162
179
|
}
|
|
163
180
|
}
|
|
164
181
|
```
|
|
165
182
|
|
|
183
|
+
### Command
|
|
184
|
+
|
|
185
|
+
Run a custom command when events fire. Use `{event}` and `{message}` tokens in `path` or `args` to inject the event name and message.
|
|
186
|
+
|
|
187
|
+
`command.minDuration` (optional, seconds) gates command execution based on the time elapsed since the last user prompt.
|
|
188
|
+
- Applies to all events for the custom command.
|
|
189
|
+
- If elapsed time is known and is below `minDuration`, the command is skipped.
|
|
190
|
+
- If elapsed time cannot be determined for an event, the command still runs.
|
|
191
|
+
|
|
192
|
+
```json
|
|
193
|
+
{
|
|
194
|
+
"command": {
|
|
195
|
+
"enabled": true,
|
|
196
|
+
"path": "/path/to/command",
|
|
197
|
+
"args": ["--event", "{event}", "--message", "{message}"],
|
|
198
|
+
"minDuration": 10
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
166
203
|
### Custom Sounds
|
|
167
204
|
|
|
168
205
|
Use your own sound files:
|
|
@@ -172,6 +209,7 @@ Use your own sound files:
|
|
|
172
209
|
"sounds": {
|
|
173
210
|
"permission": "/home/user/sounds/alert.wav",
|
|
174
211
|
"complete": "/home/user/sounds/done.wav",
|
|
212
|
+
"subagent_complete": "/home/user/sounds/subagent-done.wav",
|
|
175
213
|
"error": "/home/user/sounds/error.wav",
|
|
176
214
|
"question": "/home/user/sounds/question.wav"
|
|
177
215
|
}
|
|
@@ -180,6 +218,30 @@ Use your own sound files:
|
|
|
180
218
|
|
|
181
219
|
If a custom sound file path is provided but the file doesn't exist, the plugin will fall back to the bundled sound.
|
|
182
220
|
|
|
221
|
+
### Example: Different behaviors for main and subagent completion
|
|
222
|
+
|
|
223
|
+
You may want different notification behaviors for primary sessions versus subagent sessions. For example:
|
|
224
|
+
|
|
225
|
+
- **Main session completion**: Play a sound and show a system notification
|
|
226
|
+
- **Subagent completion**: Play a different sound, but no system notification
|
|
227
|
+
|
|
228
|
+
```json
|
|
229
|
+
{
|
|
230
|
+
"events": {
|
|
231
|
+
"complete": { "sound": true, "notification": true },
|
|
232
|
+
"subagent_complete": { "sound": true, "notification": false }
|
|
233
|
+
},
|
|
234
|
+
"messages": {
|
|
235
|
+
"complete": "Session has finished",
|
|
236
|
+
"subagent_complete": "Subagent task completed"
|
|
237
|
+
},
|
|
238
|
+
"sounds": {
|
|
239
|
+
"complete": "/home/user/sounds/main-done.wav",
|
|
240
|
+
"subagent_complete": "/home/user/sounds/subagent-chime.wav"
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
183
245
|
## Troubleshooting
|
|
184
246
|
|
|
185
247
|
### macOS: Notifications not showing (only sound works)
|
|
@@ -188,17 +250,10 @@ If a custom sound file path is provided but the file doesn't exist, the plugin w
|
|
|
188
250
|
|
|
189
251
|
If notifications still don't work after updating:
|
|
190
252
|
|
|
191
|
-
1. **
|
|
192
|
-
|
|
193
|
-
```bash
|
|
194
|
-
brew install terminal-notifier
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
2. **Check notification permissions:**
|
|
253
|
+
1. **Check notification permissions:**
|
|
198
254
|
- Open **System Settings > Notifications**
|
|
199
|
-
- Find
|
|
255
|
+
- Find **Script Editor** in the list
|
|
200
256
|
- Make sure notifications are set to **Banners** or **Alerts**
|
|
201
|
-
- Also enable notifications for **terminal-notifier** if it appears in the list
|
|
202
257
|
|
|
203
258
|
### Linux: Notifications not showing
|
|
204
259
|
|
package/dist/index.js
CHANGED
|
@@ -3726,6 +3726,9 @@ var require_node_notifier = __commonJS((exports, module) => {
|
|
|
3726
3726
|
module.exports.Growl = Growl;
|
|
3727
3727
|
});
|
|
3728
3728
|
|
|
3729
|
+
// src/index.ts
|
|
3730
|
+
import { basename } from "path";
|
|
3731
|
+
|
|
3729
3732
|
// src/config.ts
|
|
3730
3733
|
import { readFileSync, existsSync } from "fs";
|
|
3731
3734
|
import { join } from "path";
|
|
@@ -3738,21 +3741,30 @@ var DEFAULT_CONFIG = {
|
|
|
3738
3741
|
sound: true,
|
|
3739
3742
|
notification: true,
|
|
3740
3743
|
timeout: 5,
|
|
3744
|
+
showProjectName: true,
|
|
3745
|
+
command: {
|
|
3746
|
+
enabled: false,
|
|
3747
|
+
path: "",
|
|
3748
|
+
minDuration: 0
|
|
3749
|
+
},
|
|
3741
3750
|
events: {
|
|
3742
3751
|
permission: { ...DEFAULT_EVENT_CONFIG },
|
|
3743
3752
|
complete: { ...DEFAULT_EVENT_CONFIG },
|
|
3753
|
+
subagent_complete: { sound: false, notification: false },
|
|
3744
3754
|
error: { ...DEFAULT_EVENT_CONFIG },
|
|
3745
3755
|
question: { ...DEFAULT_EVENT_CONFIG }
|
|
3746
3756
|
},
|
|
3747
3757
|
messages: {
|
|
3748
|
-
permission: "
|
|
3749
|
-
complete: "
|
|
3750
|
-
|
|
3751
|
-
|
|
3758
|
+
permission: "Session needs permission",
|
|
3759
|
+
complete: "Session has finished",
|
|
3760
|
+
subagent_complete: "Subagent task completed",
|
|
3761
|
+
error: "Session encountered an error",
|
|
3762
|
+
question: "Session has a question"
|
|
3752
3763
|
},
|
|
3753
3764
|
sounds: {
|
|
3754
3765
|
permission: null,
|
|
3755
3766
|
complete: null,
|
|
3767
|
+
subagent_complete: null,
|
|
3756
3768
|
error: null,
|
|
3757
3769
|
question: null
|
|
3758
3770
|
}
|
|
@@ -3789,25 +3801,38 @@ function loadConfig() {
|
|
|
3789
3801
|
sound: globalSound,
|
|
3790
3802
|
notification: globalNotification
|
|
3791
3803
|
};
|
|
3804
|
+
const userCommand = userConfig.command ?? {};
|
|
3805
|
+
const commandArgs = Array.isArray(userCommand.args) ? userCommand.args.filter((arg) => typeof arg === "string") : undefined;
|
|
3806
|
+
const commandMinDuration = typeof userCommand.minDuration === "number" && Number.isFinite(userCommand.minDuration) && userCommand.minDuration > 0 ? userCommand.minDuration : 0;
|
|
3792
3807
|
return {
|
|
3793
3808
|
sound: globalSound,
|
|
3794
3809
|
notification: globalNotification,
|
|
3795
3810
|
timeout: typeof userConfig.timeout === "number" && userConfig.timeout > 0 ? userConfig.timeout : DEFAULT_CONFIG.timeout,
|
|
3811
|
+
showProjectName: userConfig.showProjectName ?? DEFAULT_CONFIG.showProjectName,
|
|
3812
|
+
command: {
|
|
3813
|
+
enabled: typeof userCommand.enabled === "boolean" ? userCommand.enabled : DEFAULT_CONFIG.command.enabled,
|
|
3814
|
+
path: typeof userCommand.path === "string" ? userCommand.path : DEFAULT_CONFIG.command.path,
|
|
3815
|
+
args: commandArgs,
|
|
3816
|
+
minDuration: commandMinDuration
|
|
3817
|
+
},
|
|
3796
3818
|
events: {
|
|
3797
3819
|
permission: parseEventConfig(userConfig.events?.permission ?? userConfig.permission, defaultWithGlobal),
|
|
3798
3820
|
complete: parseEventConfig(userConfig.events?.complete ?? userConfig.complete, defaultWithGlobal),
|
|
3821
|
+
subagent_complete: parseEventConfig(userConfig.events?.subagent_complete ?? userConfig.subagent_complete, { sound: false, notification: false }),
|
|
3799
3822
|
error: parseEventConfig(userConfig.events?.error ?? userConfig.error, defaultWithGlobal),
|
|
3800
|
-
question: parseEventConfig(userConfig.events?.question, defaultWithGlobal)
|
|
3823
|
+
question: parseEventConfig(userConfig.events?.question ?? userConfig.question, defaultWithGlobal)
|
|
3801
3824
|
},
|
|
3802
3825
|
messages: {
|
|
3803
3826
|
permission: userConfig.messages?.permission ?? DEFAULT_CONFIG.messages.permission,
|
|
3804
3827
|
complete: userConfig.messages?.complete ?? DEFAULT_CONFIG.messages.complete,
|
|
3828
|
+
subagent_complete: userConfig.messages?.subagent_complete ?? DEFAULT_CONFIG.messages.subagent_complete,
|
|
3805
3829
|
error: userConfig.messages?.error ?? DEFAULT_CONFIG.messages.error,
|
|
3806
3830
|
question: userConfig.messages?.question ?? DEFAULT_CONFIG.messages.question
|
|
3807
3831
|
},
|
|
3808
3832
|
sounds: {
|
|
3809
3833
|
permission: userConfig.sounds?.permission ?? DEFAULT_CONFIG.sounds.permission,
|
|
3810
3834
|
complete: userConfig.sounds?.complete ?? DEFAULT_CONFIG.sounds.complete,
|
|
3835
|
+
subagent_complete: userConfig.sounds?.subagent_complete ?? DEFAULT_CONFIG.sounds.subagent_complete,
|
|
3811
3836
|
error: userConfig.sounds?.error ?? DEFAULT_CONFIG.sounds.error,
|
|
3812
3837
|
question: userConfig.sounds?.question ?? DEFAULT_CONFIG.sounds.question
|
|
3813
3838
|
}
|
|
@@ -3833,7 +3858,6 @@ function getSoundPath(config, event) {
|
|
|
3833
3858
|
var import_node_notifier = __toESM(require_node_notifier(), 1);
|
|
3834
3859
|
import os from "os";
|
|
3835
3860
|
import { exec } from "child_process";
|
|
3836
|
-
var NOTIFICATION_TITLE = "OpenCode";
|
|
3837
3861
|
var DEBOUNCE_MS = 1000;
|
|
3838
3862
|
var platform = os.type();
|
|
3839
3863
|
var platformNotifier;
|
|
@@ -3847,7 +3871,7 @@ if (platform === "Linux" || platform.match(/BSD$/)) {
|
|
|
3847
3871
|
platformNotifier = import_node_notifier.default;
|
|
3848
3872
|
}
|
|
3849
3873
|
var lastNotificationTime = {};
|
|
3850
|
-
async function sendNotification(message, timeout) {
|
|
3874
|
+
async function sendNotification(title, message, timeout) {
|
|
3851
3875
|
const now = Date.now();
|
|
3852
3876
|
if (lastNotificationTime[message] && now - lastNotificationTime[message] < DEBOUNCE_MS) {
|
|
3853
3877
|
return;
|
|
@@ -3856,7 +3880,7 @@ async function sendNotification(message, timeout) {
|
|
|
3856
3880
|
if (platform === "Darwin") {
|
|
3857
3881
|
return new Promise((resolve) => {
|
|
3858
3882
|
const escapedMessage = message.replace(/"/g, "\\\"");
|
|
3859
|
-
const escapedTitle =
|
|
3883
|
+
const escapedTitle = title.replace(/"/g, "\\\"");
|
|
3860
3884
|
exec(`osascript -e 'display notification "${escapedMessage}" with title "${escapedTitle}"'`, () => {
|
|
3861
3885
|
resolve();
|
|
3862
3886
|
});
|
|
@@ -3864,7 +3888,7 @@ async function sendNotification(message, timeout) {
|
|
|
3864
3888
|
}
|
|
3865
3889
|
return new Promise((resolve) => {
|
|
3866
3890
|
const notificationOptions = {
|
|
3867
|
-
title
|
|
3891
|
+
title,
|
|
3868
3892
|
message,
|
|
3869
3893
|
timeout,
|
|
3870
3894
|
icon: undefined
|
|
@@ -3976,42 +4000,131 @@ async function playSound(event, customPath) {
|
|
|
3976
4000
|
} catch {}
|
|
3977
4001
|
}
|
|
3978
4002
|
|
|
4003
|
+
// src/command.ts
|
|
4004
|
+
import { spawn as spawn2 } from "child_process";
|
|
4005
|
+
function substituteTokens(value, event, message) {
|
|
4006
|
+
return value.replaceAll("{event}", event).replaceAll("{message}", message);
|
|
4007
|
+
}
|
|
4008
|
+
function runCommand2(config, event, message) {
|
|
4009
|
+
if (!config.command.enabled || !config.command.path) {
|
|
4010
|
+
return;
|
|
4011
|
+
}
|
|
4012
|
+
const args = (config.command.args ?? []).map((arg) => substituteTokens(arg, event, message));
|
|
4013
|
+
const command = substituteTokens(config.command.path, event, message);
|
|
4014
|
+
const proc = spawn2(command, args, {
|
|
4015
|
+
stdio: "ignore",
|
|
4016
|
+
detached: true
|
|
4017
|
+
});
|
|
4018
|
+
proc.on("error", () => {});
|
|
4019
|
+
proc.unref();
|
|
4020
|
+
}
|
|
4021
|
+
|
|
3979
4022
|
// src/index.ts
|
|
3980
|
-
|
|
4023
|
+
function getNotificationTitle(config, projectName) {
|
|
4024
|
+
if (config.showProjectName && projectName) {
|
|
4025
|
+
return `OpenCode (${projectName})`;
|
|
4026
|
+
}
|
|
4027
|
+
return "OpenCode";
|
|
4028
|
+
}
|
|
4029
|
+
async function handleEvent(config, eventType, projectName, elapsedSeconds) {
|
|
3981
4030
|
const promises = [];
|
|
4031
|
+
const message = getMessage(config, eventType);
|
|
3982
4032
|
if (isEventNotificationEnabled(config, eventType)) {
|
|
3983
|
-
const
|
|
3984
|
-
promises.push(sendNotification(message, config.timeout));
|
|
4033
|
+
const title = getNotificationTitle(config, projectName);
|
|
4034
|
+
promises.push(sendNotification(title, message, config.timeout));
|
|
3985
4035
|
}
|
|
3986
4036
|
if (isEventSoundEnabled(config, eventType)) {
|
|
3987
4037
|
const customSoundPath = getSoundPath(config, eventType);
|
|
3988
4038
|
promises.push(playSound(eventType, customSoundPath));
|
|
3989
4039
|
}
|
|
4040
|
+
const minDuration = config.command?.minDuration;
|
|
4041
|
+
const shouldSkipCommand = typeof minDuration === "number" && Number.isFinite(minDuration) && minDuration > 0 && typeof elapsedSeconds === "number" && Number.isFinite(elapsedSeconds) && elapsedSeconds < minDuration;
|
|
4042
|
+
if (!shouldSkipCommand) {
|
|
4043
|
+
runCommand2(config, eventType, message);
|
|
4044
|
+
}
|
|
3990
4045
|
await Promise.allSettled(promises);
|
|
3991
4046
|
}
|
|
3992
|
-
|
|
4047
|
+
function getSessionIDFromEvent(event) {
|
|
4048
|
+
const sessionID = event?.properties?.sessionID;
|
|
4049
|
+
if (typeof sessionID === "string" && sessionID.length > 0) {
|
|
4050
|
+
return sessionID;
|
|
4051
|
+
}
|
|
4052
|
+
return null;
|
|
4053
|
+
}
|
|
4054
|
+
async function getElapsedSinceLastPrompt(client, sessionID) {
|
|
4055
|
+
try {
|
|
4056
|
+
const response = await client.session.messages({ path: { id: sessionID } });
|
|
4057
|
+
const messages = response.data ?? [];
|
|
4058
|
+
let lastUserMessageTime = null;
|
|
4059
|
+
for (const msg of messages) {
|
|
4060
|
+
const info = msg.info;
|
|
4061
|
+
if (info.role === "user" && typeof info.time?.created === "number") {
|
|
4062
|
+
if (lastUserMessageTime === null || info.time.created > lastUserMessageTime) {
|
|
4063
|
+
lastUserMessageTime = info.time.created;
|
|
4064
|
+
}
|
|
4065
|
+
}
|
|
4066
|
+
}
|
|
4067
|
+
if (lastUserMessageTime !== null) {
|
|
4068
|
+
return (Date.now() - lastUserMessageTime) / 1000;
|
|
4069
|
+
}
|
|
4070
|
+
} catch {}
|
|
4071
|
+
return null;
|
|
4072
|
+
}
|
|
4073
|
+
async function isChildSession(client, sessionID) {
|
|
4074
|
+
try {
|
|
4075
|
+
const response = await client.session.get({ path: { id: sessionID } });
|
|
4076
|
+
const parentID = response.data?.parentID;
|
|
4077
|
+
return !!parentID;
|
|
4078
|
+
} catch {
|
|
4079
|
+
return false;
|
|
4080
|
+
}
|
|
4081
|
+
}
|
|
4082
|
+
async function handleEventWithElapsedTime(client, config, eventType, projectName, event) {
|
|
4083
|
+
const minDuration = config.command?.minDuration;
|
|
4084
|
+
const shouldLookupElapsed = !!config.command?.enabled && typeof config.command?.path === "string" && config.command.path.length > 0 && typeof minDuration === "number" && Number.isFinite(minDuration) && minDuration > 0;
|
|
4085
|
+
let elapsedSeconds = null;
|
|
4086
|
+
if (shouldLookupElapsed) {
|
|
4087
|
+
const sessionID = getSessionIDFromEvent(event);
|
|
4088
|
+
if (sessionID) {
|
|
4089
|
+
elapsedSeconds = await getElapsedSinceLastPrompt(client, sessionID);
|
|
4090
|
+
}
|
|
4091
|
+
}
|
|
4092
|
+
await handleEvent(config, eventType, projectName, elapsedSeconds);
|
|
4093
|
+
}
|
|
4094
|
+
var NotifierPlugin = async ({ client, directory }) => {
|
|
3993
4095
|
const config = loadConfig();
|
|
4096
|
+
const projectName = directory ? basename(directory) : null;
|
|
3994
4097
|
return {
|
|
3995
4098
|
event: async ({ event }) => {
|
|
3996
4099
|
if (event.type === "permission.updated") {
|
|
3997
|
-
await
|
|
4100
|
+
await handleEventWithElapsedTime(client, config, "permission", projectName, event);
|
|
3998
4101
|
}
|
|
3999
4102
|
if (event.type === "permission.asked") {
|
|
4000
|
-
await
|
|
4103
|
+
await handleEventWithElapsedTime(client, config, "permission", projectName, event);
|
|
4001
4104
|
}
|
|
4002
4105
|
if (event.type === "session.idle") {
|
|
4003
|
-
|
|
4106
|
+
const sessionID = getSessionIDFromEvent(event);
|
|
4107
|
+
if (sessionID) {
|
|
4108
|
+
const isChild = await isChildSession(client, sessionID);
|
|
4109
|
+
if (!isChild) {
|
|
4110
|
+
await handleEventWithElapsedTime(client, config, "complete", projectName, event);
|
|
4111
|
+
} else {
|
|
4112
|
+
await handleEventWithElapsedTime(client, config, "subagent_complete", projectName, event);
|
|
4113
|
+
}
|
|
4114
|
+
} else {
|
|
4115
|
+
await handleEventWithElapsedTime(client, config, "complete", projectName, event);
|
|
4116
|
+
}
|
|
4004
4117
|
}
|
|
4005
4118
|
if (event.type === "session.error") {
|
|
4006
|
-
await
|
|
4119
|
+
await handleEventWithElapsedTime(client, config, "error", projectName, event);
|
|
4007
4120
|
}
|
|
4008
4121
|
},
|
|
4009
4122
|
"permission.ask": async () => {
|
|
4010
|
-
await handleEvent(config, "permission");
|
|
4123
|
+
await handleEvent(config, "permission", projectName, null);
|
|
4011
4124
|
},
|
|
4012
|
-
"tool.execute.before": async (input
|
|
4125
|
+
"tool.execute.before": async (input) => {
|
|
4013
4126
|
if (input.tool === "question") {
|
|
4014
|
-
await handleEvent(config, "question");
|
|
4127
|
+
await handleEvent(config, "question", projectName, null);
|
|
4015
4128
|
}
|
|
4016
4129
|
}
|
|
4017
4130
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mohak34/opencode-notifier",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.14",
|
|
4
4
|
"description": "OpenCode plugin that sends system notifications and plays sounds when permission is needed, generation completes, or errors occur",
|
|
5
5
|
"author": "mohak34",
|
|
6
6
|
"license": "MIT",
|
|
Binary file
|