opencode-command-hooks 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.
Files changed (46) hide show
  1. package/README.md +796 -0
  2. package/dist/config/agent.d.ts +82 -0
  3. package/dist/config/agent.d.ts.map +1 -0
  4. package/dist/config/agent.js +145 -0
  5. package/dist/config/agent.js.map +1 -0
  6. package/dist/config/global.d.ts +36 -0
  7. package/dist/config/global.d.ts.map +1 -0
  8. package/dist/config/global.js +219 -0
  9. package/dist/config/global.js.map +1 -0
  10. package/dist/config/markdown.d.ts +119 -0
  11. package/dist/config/markdown.d.ts.map +1 -0
  12. package/dist/config/markdown.js +373 -0
  13. package/dist/config/markdown.js.map +1 -0
  14. package/dist/config/merge.d.ts +67 -0
  15. package/dist/config/merge.d.ts.map +1 -0
  16. package/dist/config/merge.js +192 -0
  17. package/dist/config/merge.js.map +1 -0
  18. package/dist/execution/shell.d.ts +55 -0
  19. package/dist/execution/shell.d.ts.map +1 -0
  20. package/dist/execution/shell.js +187 -0
  21. package/dist/execution/shell.js.map +1 -0
  22. package/dist/execution/template.d.ts +55 -0
  23. package/dist/execution/template.d.ts.map +1 -0
  24. package/dist/execution/template.js +106 -0
  25. package/dist/execution/template.js.map +1 -0
  26. package/dist/executor.d.ts +54 -0
  27. package/dist/executor.d.ts.map +1 -0
  28. package/dist/executor.js +314 -0
  29. package/dist/executor.js.map +1 -0
  30. package/dist/index.d.ts +22 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +359 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/logging.d.ts +24 -0
  35. package/dist/logging.d.ts.map +1 -0
  36. package/dist/logging.js +57 -0
  37. package/dist/logging.js.map +1 -0
  38. package/dist/schemas.d.ts +425 -0
  39. package/dist/schemas.d.ts.map +1 -0
  40. package/dist/schemas.js +150 -0
  41. package/dist/schemas.js.map +1 -0
  42. package/dist/types/hooks.d.ts +635 -0
  43. package/dist/types/hooks.d.ts.map +1 -0
  44. package/dist/types/hooks.js +12 -0
  45. package/dist/types/hooks.js.map +1 -0
  46. package/package.json +66 -0
@@ -0,0 +1,314 @@
1
+ /**
2
+ * Unified hook executor for opencode-command-hooks
3
+ *
4
+ * Consolidates the logic for executing hooks across all event types (tool.execute.before,
5
+ * tool.execute.after, session.start, session.idle, etc.). This module provides a single
6
+ * entry point for hook execution that handles:
7
+ *
8
+ * 1. Filtering hooks based on execution context (event type, tool name, agent, etc.)
9
+ * 2. Executing hook commands via shell
10
+ * 3. Capturing and formatting command output
11
+ * 4. Injecting results into sessions via OpenCode SDK
12
+ * 5. Graceful error handling with non-blocking semantics
13
+ *
14
+ * Non-blocking error semantics: Hook failures never prevent tool/session execution.
15
+ * Errors are logged and optionally injected into the session, but never thrown.
16
+ */
17
+ import { executeCommands } from "./execution/shell.js";
18
+ import { interpolateTemplate } from "./execution/template.js";
19
+ import { logger } from "./logging.js";
20
+ /**
21
+ * Format an error message for injection into the session
22
+ *
23
+ * Creates a user-friendly error message that explains what went wrong
24
+ * with the hook execution.
25
+ *
26
+ * @param hookId - Hook ID that failed
27
+ * @param error - Error message or object
28
+ * @returns Formatted error message
29
+ */
30
+ function formatErrorMessage(hookId, error) {
31
+ const errorText = error instanceof Error ? error.message : String(error || "Unknown error");
32
+ return `[opencode-command-hooks] Hook "${hookId}" failed: ${errorText}`;
33
+ }
34
+ /**
35
+ * Show a toast notification to the user
36
+ *
37
+ * Uses client.tui.showToast() to display a toast notification with the
38
+ * provided title, message, variant, and duration.
39
+ *
40
+ * @param client - OpenCode SDK client
41
+ * @param title - Optional title for the toast (defaults to "OpenCode Command Hook")
42
+ * @param message - Message text for the toast
43
+ * @param variant - Visual variant (info, success, warning, error)
44
+ * @param duration - Optional duration in milliseconds
45
+ * @returns Promise that resolves when toast is shown
46
+ */
47
+ async function showToast(client, title, message, variant = "info", duration) {
48
+ try {
49
+ const finalTitle = title || "OpenCode Command Hook";
50
+ logger.debug(`Showing toast: title="${finalTitle}", message="${message.substring(0, 50)}...", variant="${variant}", duration=${duration}`);
51
+ await client.tui.showToast({
52
+ body: {
53
+ title: finalTitle,
54
+ message,
55
+ variant,
56
+ duration,
57
+ },
58
+ });
59
+ logger.info(`[toast] ${finalTitle}: ${message}`);
60
+ }
61
+ catch (error) {
62
+ const errorMessage = error instanceof Error ? error.message : String(error);
63
+ logger.error(`Failed to show toast: ${errorMessage}`);
64
+ // Don't throw - this is non-blocking
65
+ }
66
+ }
67
+ /**
68
+ * Inject a message into a session using the OpenCode SDK
69
+ *
70
+ * Uses client.session.promptAsync() with noReply: true to inject context
71
+ * without triggering an AI response.
72
+ *
73
+ * @param client - OpenCode SDK client
74
+ * @param sessionId - Session ID to inject into
75
+ * @param message - Message text to inject
76
+ * @returns Promise that resolves when message is injected
77
+ */
78
+ async function injectMessage(client, sessionId, message) {
79
+ try {
80
+ logger.debug(`Injecting message into session ${sessionId}`);
81
+ await client.session.promptAsync({
82
+ path: { id: sessionId },
83
+ body: {
84
+ noReply: true,
85
+ parts: [{ type: "text", text: message }],
86
+ },
87
+ });
88
+ logger.info(`[inject] Message injected into session ${sessionId}: ${message.substring(0, 100)}${message.length > 100 ? '...' : ''}`);
89
+ }
90
+ catch (error) {
91
+ const errorMessage = error instanceof Error ? error.message : String(error);
92
+ logger.error(`Failed to inject message into session: ${errorMessage}`);
93
+ throw error;
94
+ }
95
+ }
96
+ /**
97
+ * Execute a single tool hook
98
+ *
99
+ * Runs the hook's commands, interpolates the template if configured,
100
+ * and injects the result into the session if configured.
101
+ *
102
+ * @param hook - The tool hook to execute
103
+ * @param context - Execution context (tool name, session ID, agent, etc.)
104
+ * @param client - OpenCode SDK client for message injection
105
+ * @returns Promise that resolves when hook execution is complete
106
+ */
107
+ async function executeToolHook(hook, context, client) {
108
+ logger.debug(`Executing tool hook "${hook.id}" for tool "${context.tool}"`);
109
+ try {
110
+ // Execute the hook's commands
111
+ const results = await executeCommands(hook.run, hook.id);
112
+ logger.debug(`Hook "${hook.id}" executed ${results.length} command(s)`);
113
+ // If inject is configured, prepare and inject the message
114
+ if (hook.inject) {
115
+ // Use the last command's result for template interpolation
116
+ const lastResult = results[results.length - 1];
117
+ // Build template context
118
+ const templateContext = {
119
+ id: hook.id,
120
+ agent: context.agent,
121
+ tool: context.tool,
122
+ cmd: Array.isArray(hook.run) ? hook.run[0] : hook.run,
123
+ stdout: lastResult?.stdout,
124
+ stderr: lastResult?.stderr,
125
+ exitCode: lastResult?.exitCode,
126
+ };
127
+ // Interpolate template
128
+ const message = interpolateTemplate(hook.inject, templateContext);
129
+ // Inject into session
130
+ await injectMessage(client, context.sessionId, message);
131
+ }
132
+ // If toast is configured, interpolate and show toast notification
133
+ if (hook.toast) {
134
+ // Use the last command's result for template interpolation
135
+ const lastResult = results[results.length - 1];
136
+ // Build template context
137
+ const templateContext = {
138
+ id: hook.id,
139
+ agent: context.agent,
140
+ tool: context.tool,
141
+ cmd: Array.isArray(hook.run) ? hook.run[0] : hook.run,
142
+ stdout: lastResult?.stdout,
143
+ stderr: lastResult?.stderr,
144
+ exitCode: lastResult?.exitCode,
145
+ };
146
+ // Interpolate toast title and message templates
147
+ const toastTitle = hook.toast.title ? interpolateTemplate(hook.toast.title, templateContext) : undefined;
148
+ const toastMessage = interpolateTemplate(hook.toast.message, templateContext);
149
+ // Show toast notification
150
+ await showToast(client, toastTitle, toastMessage, hook.toast.variant || "info", hook.toast.duration);
151
+ }
152
+ }
153
+ catch (error) {
154
+ // Log the error but don't throw - this is non-blocking
155
+ const errorMessage = formatErrorMessage(hook.id, error);
156
+ logger.error(errorMessage);
157
+ // Optionally inject error message into session
158
+ try {
159
+ await injectMessage(client, context.sessionId, errorMessage);
160
+ }
161
+ catch (injectionError) {
162
+ // If error injection fails, just log it
163
+ const injectionErrorMsg = injectionError instanceof Error
164
+ ? injectionError.message
165
+ : String(injectionError);
166
+ logger.error(`Failed to inject error message for hook "${hook.id}": ${injectionErrorMsg}`);
167
+ }
168
+ }
169
+ }
170
+ /**
171
+ * Execute a single session hook
172
+ *
173
+ * Runs the hook's commands, interpolates the template if configured,
174
+ * and injects the result into the session if configured.
175
+ *
176
+ * @param hook - The session hook to execute
177
+ * @param context - Execution context (session ID, agent, etc.)
178
+ * @param client - OpenCode SDK client for message injection
179
+ * @returns Promise that resolves when hook execution is complete
180
+ */
181
+ async function executeSessionHook(hook, context, client) {
182
+ logger.debug(`Executing session hook "${hook.id}"`);
183
+ try {
184
+ // Execute the hook's commands
185
+ const results = await executeCommands(hook.run, hook.id);
186
+ logger.debug(`Hook "${hook.id}" executed ${results.length} command(s)`);
187
+ // If inject is configured, prepare and inject the message
188
+ if (hook.inject) {
189
+ // Use the last command's result for template interpolation
190
+ const lastResult = results[results.length - 1];
191
+ // Build template context
192
+ const templateContext = {
193
+ id: hook.id,
194
+ agent: context.agent,
195
+ cmd: Array.isArray(hook.run) ? hook.run[0] : hook.run,
196
+ stdout: lastResult?.stdout,
197
+ stderr: lastResult?.stderr,
198
+ exitCode: lastResult?.exitCode,
199
+ };
200
+ // Interpolate template
201
+ const message = interpolateTemplate(hook.inject, templateContext);
202
+ // Inject into session
203
+ await injectMessage(client, context.sessionId, message);
204
+ }
205
+ // If toast is configured, interpolate and show toast notification
206
+ if (hook.toast) {
207
+ // Use the last command's result for template interpolation
208
+ const lastResult = results[results.length - 1];
209
+ // Build template context
210
+ const templateContext = {
211
+ id: hook.id,
212
+ agent: context.agent,
213
+ cmd: Array.isArray(hook.run) ? hook.run[0] : hook.run,
214
+ stdout: lastResult?.stdout,
215
+ stderr: lastResult?.stderr,
216
+ exitCode: lastResult?.exitCode,
217
+ };
218
+ // Interpolate toast title and message templates
219
+ const toastTitle = hook.toast.title ? interpolateTemplate(hook.toast.title, templateContext) : undefined;
220
+ const toastMessage = interpolateTemplate(hook.toast.message, templateContext);
221
+ // Show toast notification
222
+ await showToast(client, toastTitle, toastMessage, hook.toast.variant || "info", hook.toast.duration);
223
+ }
224
+ }
225
+ catch (error) {
226
+ // Log the error but don't throw - this is non-blocking
227
+ const errorMessage = formatErrorMessage(hook.id, error);
228
+ logger.error(errorMessage);
229
+ // Optionally inject error message into session
230
+ try {
231
+ await injectMessage(client, context.sessionId, errorMessage);
232
+ }
233
+ catch (injectionError) {
234
+ // If error injection fails, just log it
235
+ const injectionErrorMsg = injectionError instanceof Error
236
+ ? injectionError.message
237
+ : String(injectionError);
238
+ logger.error(`Failed to inject error message for hook "${hook.id}": ${injectionErrorMsg}`);
239
+ }
240
+ }
241
+ }
242
+ /**
243
+ * Check if a hook is a tool hook
244
+ *
245
+ * @param hook - Hook to check
246
+ * @returns true if the hook is a ToolHook
247
+ */
248
+ function isToolHook(hook) {
249
+ return "when" in hook && "phase" in hook.when;
250
+ }
251
+ /**
252
+ * Execute a collection of hooks
253
+ *
254
+ * Main entry point for hook execution. Handles both tool and session hooks,
255
+ * executing each matched hook in sequence. Implements non-blocking error semantics:
256
+ * any errors during hook execution are logged and optionally injected into the
257
+ * session, but never prevent the tool/session from executing.
258
+ *
259
+ * This function consolidates the logic that was previously duplicated across
260
+ * individual event handlers (tool-before, tool-after, session-start, session-idle).
261
+ *
262
+ * @param hooks - Array of hooks to execute (can be tool or session hooks)
263
+ * @param context - Execution context with session ID, agent, tool name, etc.
264
+ * @param client - OpenCode SDK client for message injection
265
+ * @returns Promise that resolves when all hooks are processed
266
+ *
267
+ * @example
268
+ * ```typescript
269
+ * // Execute tool hooks for a tool.execute.before event
270
+ * await executeHooks(matchedToolHooks, {
271
+ * sessionId: "session-123",
272
+ * agent: "build",
273
+ * tool: "task",
274
+ * slashCommand: undefined,
275
+ * callId: "call-456"
276
+ * }, client)
277
+ *
278
+ * // Execute session hooks for a session.start event
279
+ * await executeHooks(matchedSessionHooks, {
280
+ * sessionId: "session-123",
281
+ * agent: "build"
282
+ * }, client)
283
+ * ```
284
+ */
285
+ export async function executeHooks(hooks, context, client) {
286
+ try {
287
+ logger.debug(`executeHooks called with ${hooks.length} hook(s) for session "${context.sessionId}"`);
288
+ // Execute each hook
289
+ for (const hook of hooks) {
290
+ try {
291
+ if (isToolHook(hook)) {
292
+ await executeToolHook(hook, context, client);
293
+ }
294
+ else {
295
+ await executeSessionHook(hook, context, client);
296
+ }
297
+ }
298
+ catch (error) {
299
+ // Catch errors from individual hook execution and continue
300
+ // (errors are already logged and injected by the hook execution functions)
301
+ const errorMessage = error instanceof Error ? error.message : String(error);
302
+ logger.error(`Unexpected error executing hook "${hook.id}": ${errorMessage}`);
303
+ }
304
+ }
305
+ logger.debug(`executeHooks completed for ${hooks.length} hook(s)`);
306
+ }
307
+ catch (error) {
308
+ // Catch-all for unexpected errors
309
+ const errorMessage = error instanceof Error ? error.message : String(error);
310
+ logger.error(`Unexpected error in executeHooks: ${errorMessage}`);
311
+ // Don't throw - this is non-blocking
312
+ }
313
+ }
314
+ //# sourceMappingURL=executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"executor.js","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { Plugin } from "@opencode-ai/plugin";
2
+ export { executeHooks } from "./executor.js";
3
+ /**
4
+ * OpenCode Command Hooks Plugin
5
+ *
6
+ * Allows users to declaratively attach shell commands to agent/tool/slash-command
7
+ * lifecycle events via configuration in opencode.json or markdown frontmatter.
8
+ *
9
+ * Features:
10
+ * - Tool hooks (before/after tool execution)
11
+ * - Session hooks (on session lifecycle events)
12
+ * - Configuration via global config or per-agent/command markdown
13
+ * - Non-blocking error semantics
14
+ *
15
+ * Architecture:
16
+ * - Simplified event handlers that extract context and call executeHooks
17
+ * - No state tracking (pendingAfterEvents, completedAfterEvents removed)
18
+ * - Unified executor handles all hook matching and execution
19
+ */
20
+ declare const plugin: Plugin;
21
+ export default plugin;
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAUjD,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAiG5C;;;;;;;;;;;;;;;;GAgBG;AACH,QAAA,MAAM,MAAM,EAAE,MAoWb,CAAA;AAED,eAAe,MAAM,CAAA"}