@mohak34/opencode-notifier 0.1.22-beta.2 → 0.1.22-beta.3

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.
Files changed (2) hide show
  1. package/dist/index.js +48 -17
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -3894,6 +3894,9 @@ function getMessage(config, event) {
3894
3894
  function getSoundPath(config, event) {
3895
3895
  return config.sounds[event];
3896
3896
  }
3897
+ function getSoundVolume(config, event) {
3898
+ return config.volumes[event];
3899
+ }
3897
3900
  function getIconPath(config) {
3898
3901
  if (!config.showIcon) {
3899
3902
  return;
@@ -3908,6 +3911,16 @@ function getIconPath(config) {
3908
3911
  } catch {}
3909
3912
  return;
3910
3913
  }
3914
+ function interpolateMessage(message, context) {
3915
+ let result = message;
3916
+ const sessionTitle = context.sessionTitle || "";
3917
+ result = result.replaceAll("{sessionTitle}", sessionTitle);
3918
+ const projectName = context.projectName || "";
3919
+ result = result.replaceAll("{projectName}", projectName);
3920
+ result = result.replace(/\s*[:\-|]\s*$/, "").trim();
3921
+ result = result.replace(/\s{2,}/g, " ");
3922
+ return result;
3923
+ }
3911
3924
 
3912
3925
  // src/notify.ts
3913
3926
  var import_node_notifier = __toESM(require_node_notifier(), 1);
@@ -4143,9 +4156,13 @@ function getNotificationTitle(config, projectName) {
4143
4156
  }
4144
4157
  return "OpenCode";
4145
4158
  }
4146
- async function handleEvent(config, eventType, projectName, elapsedSeconds) {
4159
+ async function handleEvent(config, eventType, projectName, elapsedSeconds, sessionTitle) {
4147
4160
  const promises = [];
4148
- const message = getMessage(config, eventType);
4161
+ const rawMessage = getMessage(config, eventType);
4162
+ const message = interpolateMessage(rawMessage, {
4163
+ sessionTitle: config.showSessionTitle ? sessionTitle : null,
4164
+ projectName
4165
+ });
4149
4166
  if (isEventNotificationEnabled(config, eventType)) {
4150
4167
  const title = getNotificationTitle(config, projectName);
4151
4168
  const iconPath = getIconPath(config);
@@ -4153,12 +4170,13 @@ async function handleEvent(config, eventType, projectName, elapsedSeconds) {
4153
4170
  }
4154
4171
  if (isEventSoundEnabled(config, eventType)) {
4155
4172
  const customSoundPath = getSoundPath(config, eventType);
4156
- promises.push(playSound(eventType, customSoundPath, 1));
4173
+ const soundVolume = getSoundVolume(config, eventType);
4174
+ promises.push(playSound(eventType, customSoundPath, soundVolume));
4157
4175
  }
4158
4176
  const minDuration = config.command?.minDuration;
4159
4177
  const shouldSkipCommand = typeof minDuration === "number" && Number.isFinite(minDuration) && minDuration > 0 && typeof elapsedSeconds === "number" && Number.isFinite(elapsedSeconds) && elapsedSeconds < minDuration;
4160
4178
  if (!shouldSkipCommand) {
4161
- runCommand2(config, eventType, message);
4179
+ runCommand2(config, eventType, message, sessionTitle, projectName);
4162
4180
  }
4163
4181
  await Promise.allSettled(promises);
4164
4182
  }
@@ -4232,13 +4250,15 @@ async function getElapsedSinceLastPrompt(client, sessionID, nowMs = Date.now())
4232
4250
  } catch {}
4233
4251
  return null;
4234
4252
  }
4235
- async function isChildSession(client, sessionID) {
4253
+ async function getSessionInfo(client, sessionID) {
4236
4254
  try {
4237
4255
  const response = await client.session.get({ path: { id: sessionID } });
4238
- const parentID = response.data?.parentID;
4239
- return !!parentID;
4256
+ return {
4257
+ isChild: !!response.data?.parentID,
4258
+ title: response.data?.title ?? null
4259
+ };
4240
4260
  } catch {
4241
- return false;
4261
+ return { isChild: false, title: null };
4242
4262
  }
4243
4263
  }
4244
4264
  async function processSessionIdle(client, config, projectName, event, sessionID, sequence, idleReceivedAtMs) {
@@ -4248,15 +4268,15 @@ async function processSessionIdle(client, config, projectName, event, sessionID,
4248
4268
  if (shouldSuppressSessionIdle(sessionID)) {
4249
4269
  return;
4250
4270
  }
4251
- const isChild = await isChildSession(client, sessionID);
4271
+ const sessionInfo = await getSessionInfo(client, sessionID);
4252
4272
  if (!hasCurrentSessionIdleSequence(sessionID, sequence)) {
4253
4273
  return;
4254
4274
  }
4255
- if (!isChild) {
4256
- await handleEventWithElapsedTime(client, config, "complete", projectName, event, idleReceivedAtMs);
4275
+ if (!sessionInfo.isChild) {
4276
+ await handleEventWithElapsedTime(client, config, "complete", projectName, event, idleReceivedAtMs, sessionInfo.title);
4257
4277
  return;
4258
4278
  }
4259
- await handleEventWithElapsedTime(client, config, "subagent_complete", projectName, event, idleReceivedAtMs);
4279
+ await handleEventWithElapsedTime(client, config, "subagent_complete", projectName, event, idleReceivedAtMs, sessionInfo.title);
4260
4280
  }
4261
4281
  function scheduleSessionIdle(client, config, projectName, event, sessionID) {
4262
4282
  clearPendingIdleTimer(sessionID);
@@ -4270,17 +4290,22 @@ function scheduleSessionIdle(client, config, projectName, event, sessionID) {
4270
4290
  }, IDLE_COMPLETE_DELAY_MS);
4271
4291
  pendingIdleTimers.set(sessionID, timer);
4272
4292
  }
4273
- async function handleEventWithElapsedTime(client, config, eventType, projectName, event, elapsedReferenceNowMs) {
4293
+ async function handleEventWithElapsedTime(client, config, eventType, projectName, event, elapsedReferenceNowMs, preloadedSessionTitle) {
4294
+ const sessionID = getSessionIDFromEvent(event);
4274
4295
  const minDuration = config.command?.minDuration;
4275
4296
  const shouldLookupElapsed = !!config.command?.enabled && typeof config.command?.path === "string" && config.command.path.length > 0 && typeof minDuration === "number" && Number.isFinite(minDuration) && minDuration > 0;
4276
4297
  let elapsedSeconds = null;
4277
4298
  if (shouldLookupElapsed) {
4278
- const sessionID = getSessionIDFromEvent(event);
4279
4299
  if (sessionID) {
4280
4300
  elapsedSeconds = await getElapsedSinceLastPrompt(client, sessionID, elapsedReferenceNowMs);
4281
4301
  }
4282
4302
  }
4283
- await handleEvent(config, eventType, projectName, elapsedSeconds);
4303
+ let sessionTitle = preloadedSessionTitle ?? null;
4304
+ if (sessionID && !sessionTitle && config.showSessionTitle) {
4305
+ const info = await getSessionInfo(client, sessionID);
4306
+ sessionTitle = info.title;
4307
+ }
4308
+ await handleEvent(config, eventType, projectName, elapsedSeconds, sessionTitle);
4284
4309
  }
4285
4310
  var NotifierPlugin = async ({ client, directory }) => {
4286
4311
  const config = loadConfig();
@@ -4305,8 +4330,14 @@ var NotifierPlugin = async ({ client, directory }) => {
4305
4330
  markSessionBusy(event.properties.sessionID);
4306
4331
  }
4307
4332
  if (event.type === "session.error") {
4308
- markSessionError(getSessionIDFromEvent(event));
4309
- await handleEventWithElapsedTime(client, config, "error", projectName, event);
4333
+ const sessionID = getSessionIDFromEvent(event);
4334
+ markSessionError(sessionID);
4335
+ let sessionTitle = null;
4336
+ if (sessionID && config.showSessionTitle) {
4337
+ const info = await getSessionInfo(client, sessionID);
4338
+ sessionTitle = info.title;
4339
+ }
4340
+ await handleEventWithElapsedTime(client, config, "error", projectName, event, undefined, sessionTitle);
4310
4341
  }
4311
4342
  },
4312
4343
  "permission.ask": async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mohak34/opencode-notifier",
3
- "version": "0.1.22-beta.2",
3
+ "version": "0.1.22-beta.3",
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",