70 lines
2.8 KiB
JavaScript
70 lines
2.8 KiB
JavaScript
// OSC 99 Desktop Notifications for OpenCode
|
|
//
|
|
// Sends desktop notifications via the OSC 99 escape sequence protocol
|
|
// when OpenCode needs your attention. Notifications are only shown when
|
|
// the terminal window is unfocused (o=unfocused).
|
|
//
|
|
// Tested with: Kitty terminal
|
|
// May also work with other terminals that support the OSC 99 protocol.
|
|
//
|
|
// Features:
|
|
// - Notifies when a session goes idle (waiting for your input)
|
|
// - Notifies when a question is asked (e.g. multiple choice)
|
|
// - Notifies when a permission prompt is raised
|
|
// - Notifies when a session error occurs
|
|
// - Includes the project directory name in the notification title
|
|
// - Suppresses notifications from subagent sessions (e.g. Explore Task)
|
|
// - Suppresses notifications when the terminal window is focused
|
|
// - Uses distinct sounds per notification type (system, question, error)
|
|
//
|
|
// Installation:
|
|
// Copy this file to ~/.config/opencode/plugins/osc99-notify.js
|
|
//
|
|
// Notification types:
|
|
// Idle: title -> OpenCode (project-name)
|
|
// body -> Waiting for your input
|
|
// sound -> system
|
|
//
|
|
// Question: title -> OpenCode (project-name)
|
|
// body -> Has a question for you
|
|
// sound -> question
|
|
//
|
|
// Permission: title -> OpenCode (project-name)
|
|
// body -> Needs your permission
|
|
// sound -> question
|
|
//
|
|
// Error: title -> OpenCode (project-name)
|
|
// body -> Encountered an error
|
|
// sound -> error
|
|
|
|
export const OSC99Notify = async ({ client }) => {
|
|
const path = require('path')
|
|
const project = path.basename(process.cwd())
|
|
let id = 0
|
|
|
|
const notify = (icon, message, sound = 'system') => {
|
|
id++
|
|
process.stderr.write(`\x1b]99;i=${id}:d=0:s=${sound}:o=unfocused;${icon} OpenCode (${project})\x1b\\`)
|
|
process.stderr.write(`\x1b]99;i=${id}:p=body;${message}\x1b\\`)
|
|
}
|
|
|
|
return {
|
|
event: async ({ event }) => {
|
|
if (event.type === "message.part.updated" && event.properties.part.type === "tool" && event.properties.part.tool === "question" && event.properties.part.state?.status === "pending")
|
|
notify('❓', 'Has a question for you', 'question')
|
|
|
|
if (event.type === "session.idle") {
|
|
const session = await client.session.get({ path: { id: event.properties.sessionID } })
|
|
if (!session.data?.parentID)
|
|
notify('🤖', 'Waiting for your input')
|
|
}
|
|
if (event.type === "session.error") {
|
|
const session = await client.session.get({ path: { id: event.properties.sessionID } })
|
|
if (!session.data?.parentID)
|
|
notify('🚨', 'Encountered an error', 'error')
|
|
}
|
|
if (event.type === "permission.updated")
|
|
notify('🔐', 'Needs your permission', 'question')
|
|
},
|
|
}
|
|
}
|