@ulthon/ul-opencode-event 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Ulthon
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,154 @@
1
+ # @ulthon/ul-opencode-event
2
+
3
+ OpenCode notification plugin that sends email notifications when session events occur.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @ulthon/ul-opencode-event
9
+ ```
10
+
11
+ Then add to your OpenCode configuration:
12
+
13
+ ```json
14
+ {
15
+ "plugin": ["@ulthon/ul-opencode-event"]
16
+ }
17
+ ```
18
+
19
+ ## Configuration
20
+
21
+ ### Configuration File Locations
22
+
23
+ The plugin looks for configuration in these locations (in order of priority):
24
+
25
+ 1. **Project-level**: `.opencode/ul-opencode-event.json` or `./ul-opencode-event.json`
26
+ 2. **Global**: `~/.config/opencode/ul-opencode-event.json`
27
+
28
+ Project-level configuration overrides global configuration (channels are merged by name).
29
+
30
+ ### Configuration Format
31
+
32
+ ```json
33
+ {
34
+ "channels": [
35
+ {
36
+ "type": "smtp",
37
+ "enabled": true,
38
+ "name": "My Email",
39
+ "config": {
40
+ "host": "smtp.example.com",
41
+ "port": 465,
42
+ "secure": true,
43
+ "auth": {
44
+ "user": "your-email@example.com",
45
+ "pass": "your-app-password"
46
+ }
47
+ },
48
+ "recipients": ["receiver@example.com"],
49
+ "events": {
50
+ "created": true,
51
+ "idle": true,
52
+ "error": true
53
+ },
54
+ "templates": {
55
+ "created": {
56
+ "subject": "[OpenCode] Task Started - {{projectName}}",
57
+ "body": "Task started at {{timestamp}}"
58
+ }
59
+ }
60
+ }
61
+ ]
62
+ }
63
+ ```
64
+
65
+ See `examples/ul-opencode-event.json` for a complete example.
66
+
67
+ ### Channel Configuration
68
+
69
+ | Field | Type | Required | Description |
70
+ |-------|------|----------|-------------|
71
+ | `type` | string | Yes | Channel type: `smtp` (more coming soon) |
72
+ | `enabled` | boolean | No | Whether this channel is active (default: true) |
73
+ | `name` | string | No | Channel name for identification |
74
+ | `config` | object | Yes | Channel-specific configuration |
75
+ | `recipients` | string[] | Yes* | Email recipients (*required for smtp*) |
76
+ | `events` | object | No | Which events to notify |
77
+ | `templates` | object | No | Custom templates for each event |
78
+
79
+ ### SMTP Configuration
80
+
81
+ | Field | Type | Required | Description |
82
+ |-------|------|----------|-------------|
83
+ | `host` | string | Yes | SMTP server hostname |
84
+ | `port` | number | Yes | SMTP port (465 for SSL, 587 for STARTTLS) |
85
+ | `secure` | boolean | No | Use SSL (default: true for port 465) |
86
+ | `auth.user` | string | Yes | SMTP username |
87
+ | `auth.pass` | string | Yes | SMTP password or app password |
88
+
89
+ ## Template Variables
90
+
91
+ Use these variables in your subject and body templates:
92
+
93
+ | Variable | Description | Available Events |
94
+ |----------|-------------|------------------|
95
+ | `{{eventType}}` | Event type (created, idle, error) | All |
96
+ | `{{timestamp}}` | ISO 8601 timestamp | All |
97
+ | `{{projectName}}` | Project name | All |
98
+ | `{{sessionId}}` | Session ID | All |
99
+ | `{{message}}` | Completion message | idle |
100
+ | `{{duration}}` | Task duration | idle |
101
+ | `{{error}}` | Error message | error |
102
+
103
+ ## Events
104
+
105
+ | Event | When it triggers |
106
+ |-------|------------------|
107
+ | `created` | When a new session starts |
108
+ | `idle` | When a session completes (AI finishes responding) |
109
+ | `error` | When a session encounters an error |
110
+
111
+ ## Multiple Channels
112
+
113
+ You can configure multiple channels, and all enabled channels will receive notifications:
114
+
115
+ ```json
116
+ {
117
+ "channels": [
118
+ {
119
+ "type": "smtp",
120
+ "enabled": true,
121
+ "name": "Primary Email",
122
+ "config": { "host": "smtp.primary.com", ... },
123
+ "recipients": ["primary@example.com"],
124
+ "events": { "created": true, "idle": true, "error": true }
125
+ },
126
+ {
127
+ "type": "smtp",
128
+ "enabled": true,
129
+ "name": "Secondary Email",
130
+ "config": { "host": "smtp.secondary.com", ... },
131
+ "recipients": ["secondary@example.com"],
132
+ "events": { "idle": true, "error": true }
133
+ }
134
+ ]
135
+ }
136
+ ```
137
+
138
+ ## Troubleshooting
139
+
140
+ ### No notifications sent
141
+
142
+ 1. Check if `enabled: true` is set
143
+ 2. Check if the event type is enabled in `events`
144
+ 3. Check SMTP credentials are correct
145
+
146
+ ### SMTP authentication failed
147
+
148
+ - For Gmail, use an App Password instead of your regular password
149
+ - For QQ Mail, use the authorization code
150
+ - Ensure `secure` matches your port (465 = true, 587 = false)
151
+
152
+ ## License
153
+
154
+ MIT
@@ -0,0 +1,25 @@
1
+ import type { NotificationConfig } from './types';
2
+ /**
3
+ * Load and merge notification configuration
4
+ *
5
+ * Config locations (in order of priority):
6
+ * 1. Project-level: .opencode/ul-opencode-event.json or ./ul-opencode-event.json
7
+ * 2. Global: ~/.config/opencode/ul-opencode-event.json
8
+ *
9
+ * Merge strategy:
10
+ * - Channels are merged by `name` field
11
+ * - If names match, project channel overrides global channel
12
+ * - If no name match, project channels are appended to global channels
13
+ *
14
+ * Filtering:
15
+ * - Only returns channels where enabled is true (or undefined, which defaults to true)
16
+ * - Channels with enabled: false are excluded
17
+ *
18
+ * Validation:
19
+ * - Channel type must be 'smtp' (only supported type in phase 1)
20
+ * - Throws clear error for unsupported channel types
21
+ *
22
+ * @returns Merged and filtered configuration, or default config if no files exist
23
+ * @throws Error if any channel has an unsupported type
24
+ */
25
+ export declare function loadConfig(): NotificationConfig;
@@ -0,0 +1,10 @@
1
+ import type { Channel } from './types';
2
+ export interface EmailSender {
3
+ send: (subject: string, body: string) => Promise<void>;
4
+ }
5
+ /**
6
+ * Creates an email sender for the given SMTP channel
7
+ * @param channel - The channel configuration (must be SMTP type)
8
+ * @returns EmailSender instance or null if channel is invalid/disabled
9
+ */
10
+ export declare function createEmailSender(channel: Channel): EmailSender | null;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Multi-channel event handler for notifications
3
+ */
4
+ import type { NotificationConfig, EventPayload, EventType } from './types';
5
+ export interface EventHandler {
6
+ handle: (eventType: EventType, payload: EventPayload) => Promise<void>;
7
+ }
8
+ /**
9
+ * Creates an event handler that dispatches notifications to all enabled channels
10
+ */
11
+ export declare function createEventHandler(config: NotificationConfig): EventHandler;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Notification Plugin Entry Point
3
+ * Sends email notifications when session events occur
4
+ */
5
+ import type { Plugin } from '@opencode-ai/plugin';
6
+ /**
7
+ * Notification Plugin for OpenCode
8
+ * Listens for session events and sends notifications via configured channels
9
+ */
10
+ export declare const NotificationPlugin: Plugin;
11
+ export default NotificationPlugin;