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,373 @@
1
+ /**
2
+ * Markdown configuration parser for loading hooks from agent and slash-command markdown files
3
+ *
4
+ * Parses YAML frontmatter from markdown files and extracts command_hooks configuration.
5
+ * Supports both agent markdown files (typically in .opencode/agents/) and slash-command
6
+ * markdown files (typically in .opencode/commands/).
7
+ */
8
+ import { load as parseYaml } from "js-yaml";
9
+ import { logger } from "../logging.js";
10
+ /**
11
+ * In-memory cache for markdown configurations
12
+ * Maps file paths to their parsed CommandHooksConfig to avoid repeated file reads.
13
+ * Entries are cached indefinitely; clear manually if config files change.
14
+ */
15
+ const markdownConfigCache = new Map();
16
+ /**
17
+ * Extract YAML frontmatter from markdown content
18
+ *
19
+ * Frontmatter is defined as content between the first `---` and second `---`
20
+ * at the start of the file. Returns the raw YAML string (without delimiters).
21
+ *
22
+ * @param content - Full markdown file content
23
+ * @returns Raw YAML string, or null if no frontmatter found
24
+ *
25
+ * @example
26
+ * ```
27
+ * ---
28
+ * name: my-agent
29
+ * command_hooks:
30
+ * tool: [...]
31
+ * ---
32
+ *
33
+ * # Agent content
34
+ * ```
35
+ * Returns the YAML between the delimiters
36
+ */
37
+ export function extractYamlFrontmatter(content) {
38
+ // Check if content starts with ---
39
+ if (!content.startsWith("---")) {
40
+ return null;
41
+ }
42
+ // Find the second --- delimiter
43
+ // Start searching from position 3 (after the first ---)
44
+ const secondDelimiterIndex = content.indexOf("---", 3);
45
+ if (secondDelimiterIndex === -1) {
46
+ // No closing delimiter found
47
+ return null;
48
+ }
49
+ // Extract YAML between the delimiters
50
+ const yamlContent = content.substring(3, secondDelimiterIndex).trim();
51
+ return yamlContent;
52
+ }
53
+ /**
54
+ * Parse YAML content and return the parsed object
55
+ *
56
+ * Handles YAML parsing errors gracefully by returning null.
57
+ * Does not throw errors - callers should check for null return value.
58
+ *
59
+ * @param yamlContent - Raw YAML string to parse
60
+ * @returns Parsed YAML object, or null if parsing failed
61
+ */
62
+ export function parseYamlFrontmatter(content) {
63
+ try {
64
+ const parsed = parseYaml(content);
65
+ return parsed === undefined ? null : parsed;
66
+ }
67
+ catch (error) {
68
+ const message = error instanceof Error ? error.message : String(error);
69
+ logger.debug(`Failed to parse YAML: ${message}`);
70
+ return null;
71
+ }
72
+ }
73
+ /**
74
+ * Parse simplified agent hooks from YAML frontmatter content
75
+ *
76
+ * Extracts and validates the new simplified `hooks` format from agent markdown
77
+ * frontmatter. Returns null if no hooks are present or if parsing fails.
78
+ *
79
+ * @param yamlContent - Raw YAML string from frontmatter
80
+ * @param agentName - Name of the agent (used for auto-generating hook IDs)
81
+ * @returns Parsed AgentHooks object, or null if no valid hooks found
82
+ *
83
+ * @example
84
+ * ```yaml
85
+ * hooks:
86
+ * before:
87
+ * - run: "echo starting"
88
+ * after:
89
+ * - run: ["npm run test"]
90
+ * inject: "Results:\n{stdout}"
91
+ * ```
92
+ */
93
+ export function parseAgentHooks(yamlContent) {
94
+ const parsed = parseYamlFrontmatter(yamlContent);
95
+ if (parsed === null || typeof parsed !== "object" || parsed === null) {
96
+ return null;
97
+ }
98
+ const config = parsed;
99
+ const hooks = config.hooks;
100
+ if (hooks === undefined) {
101
+ return null;
102
+ }
103
+ if (typeof hooks !== "object" || hooks === null) {
104
+ logger.debug("hooks field is not an object");
105
+ return null;
106
+ }
107
+ const agentHooks = hooks;
108
+ const result = {};
109
+ // Parse before array
110
+ if (agentHooks.before !== undefined) {
111
+ if (!Array.isArray(agentHooks.before)) {
112
+ logger.debug("hooks.before is not an array");
113
+ return null;
114
+ }
115
+ result.before = agentHooks.before;
116
+ }
117
+ // Parse after array
118
+ if (agentHooks.after !== undefined) {
119
+ if (!Array.isArray(agentHooks.after)) {
120
+ logger.debug("hooks.after is not an array");
121
+ return null;
122
+ }
123
+ result.after = agentHooks.after;
124
+ }
125
+ // Return null if both are empty/undefined
126
+ if (!result.before?.length && !result.after?.length) {
127
+ return null;
128
+ }
129
+ return result;
130
+ }
131
+ /**
132
+ * Convert simplified agent hooks to internal CommandHooksConfig format
133
+ *
134
+ * Takes the simplified AgentHooks format and converts it to the internal
135
+ * ToolHook[] format with auto-generated IDs and proper when clauses.
136
+ *
137
+ * @param agentHooks - Simplified agent hooks configuration
138
+ * @param agentName - Name of the agent (used for hook ID generation)
139
+ * @returns CommandHooksConfig with tool hooks converted to internal format
140
+ *
141
+ * @example
142
+ * ```typescript
143
+ * const simpleHooks: AgentHooks = {
144
+ * after: [{ run: "npm run test", inject: "Results: {stdout}" }]
145
+ * };
146
+ * const config = convertToCommandHooksConfig(simpleHooks, "engineer");
147
+ * // Results in: { tool: [{ id: "engineer-after-0", when: {...}, run: ..., inject: ... }] }
148
+ * ```
149
+ */
150
+ export function convertToCommandHooksConfig(agentHooks, agentName) {
151
+ const toolHooks = [];
152
+ // Convert before hooks
153
+ if (agentHooks.before) {
154
+ agentHooks.before.forEach((hook, index) => {
155
+ const toolHook = convertAgentHookEntryToToolHook(hook, agentName, "before", index);
156
+ if (toolHook) {
157
+ toolHooks.push(toolHook);
158
+ }
159
+ });
160
+ }
161
+ // Convert after hooks
162
+ if (agentHooks.after) {
163
+ agentHooks.after.forEach((hook, index) => {
164
+ const toolHook = convertAgentHookEntryToToolHook(hook, agentName, "after", index);
165
+ if (toolHook) {
166
+ toolHooks.push(toolHook);
167
+ }
168
+ });
169
+ }
170
+ return {
171
+ tool: toolHooks,
172
+ session: [],
173
+ };
174
+ }
175
+ /**
176
+ * Convert a single AgentHookEntry to ToolHook format
177
+ */
178
+ function convertAgentHookEntryToToolHook(entry, agentName, phase, index) {
179
+ if (!entry.run) {
180
+ logger.debug("Hook entry missing required 'run' field");
181
+ return null;
182
+ }
183
+ const hookId = `${agentName}-${phase}-${index}`;
184
+ return {
185
+ id: hookId,
186
+ when: {
187
+ phase: phase,
188
+ tool: ["task"],
189
+ callingAgent: [agentName], // Implicit scoping to this agent
190
+ },
191
+ run: entry.run,
192
+ inject: entry.inject,
193
+ toast: entry.toast,
194
+ };
195
+ }
196
+ /**
197
+ * Check if a value is a valid CommandHooksConfig object
198
+ */
199
+ function isValidCommandHooksConfig(value) {
200
+ if (typeof value !== "object" || value === null) {
201
+ return false;
202
+ }
203
+ const obj = value;
204
+ // Both tool and session are optional
205
+ if (obj.tool !== undefined && !Array.isArray(obj.tool)) {
206
+ return false;
207
+ }
208
+ if (obj.session !== undefined && !Array.isArray(obj.session)) {
209
+ return false;
210
+ }
211
+ return true;
212
+ }
213
+ /**
214
+ * Extract agent name from file path
215
+ *
216
+ * Takes an absolute path to an agent markdown file and extracts the agent name
217
+ * (filename without .md extension).
218
+ *
219
+ * @param filePath - Absolute path to agent markdown file
220
+ * @returns Agent name (filename without extension)
221
+ *
222
+ * @example
223
+ * ```typescript
224
+ * const name = extractAgentNameFromPath("/project/.opencode/agent/engineer.md");
225
+ * // Returns: "engineer"
226
+ * ```
227
+ */
228
+ function extractAgentNameFromPath(filePath) {
229
+ const fileName = filePath.split("/").pop() || "";
230
+ return fileName.replace(/\.md$/, "");
231
+ }
232
+ /**
233
+ * Load and parse command hooks configuration from a markdown file
234
+ *
235
+ * Reads a markdown file, extracts YAML frontmatter, parses it, and extracts
236
+ * either the new simplified `hooks` format or the legacy `command_hooks` format.
237
+ *
238
+ * **Caching:** This function implements in-memory caching per file path to avoid
239
+ * repeated file reads. The cache is checked first; if not found, the file is read
240
+ * from disk and cached for subsequent calls.
241
+ *
242
+ * Error handling:
243
+ * - If file doesn't exist: returns empty config (not an error)
244
+ * - If no frontmatter found: returns empty config
245
+ * - If YAML is malformed: logs warning, returns empty config
246
+ * - If hooks format is invalid: logs warning, returns empty config
247
+ * - Never throws errors - always returns a valid config
248
+ *
249
+ * @param filePath - Absolute path to the markdown file
250
+ * @returns Promise resolving to CommandHooksConfig (may be empty)
251
+ *
252
+ * @example
253
+ * ```typescript
254
+ * const config = await loadMarkdownConfig("/path/to/agent.md");
255
+ * // Returns { tool: [...], session: [...] } or { tool: [], session: [] }
256
+ * ```
257
+ */
258
+ export async function loadMarkdownConfig(filePath) {
259
+ // Check cache first
260
+ if (markdownConfigCache.has(filePath)) {
261
+ const cached = markdownConfigCache.get(filePath);
262
+ logger.debug(`Returning cached markdown config from ${filePath}: ${cached.tool?.length ?? 0} tool hooks, ${cached.session?.length ?? 0} session hooks`);
263
+ return cached;
264
+ }
265
+ try {
266
+ // Try to read the file
267
+ let content;
268
+ try {
269
+ const file = Bun.file(filePath);
270
+ if (!(await file.exists())) {
271
+ logger.debug(`Markdown file not found: ${filePath}`);
272
+ const emptyConfig = { tool: [], session: [] };
273
+ markdownConfigCache.set(filePath, emptyConfig);
274
+ return emptyConfig;
275
+ }
276
+ content = await file.text();
277
+ }
278
+ catch (error) {
279
+ const message = error instanceof Error ? error.message : String(error);
280
+ logger.debug(`Failed to read markdown file ${filePath}: ${message}`);
281
+ const emptyConfig = { tool: [], session: [] };
282
+ markdownConfigCache.set(filePath, emptyConfig);
283
+ return emptyConfig;
284
+ }
285
+ // Extract YAML frontmatter
286
+ const yamlContent = extractYamlFrontmatter(content);
287
+ if (!yamlContent) {
288
+ logger.debug(`No YAML frontmatter found in ${filePath}`);
289
+ const emptyConfig = { tool: [], session: [] };
290
+ markdownConfigCache.set(filePath, emptyConfig);
291
+ return emptyConfig;
292
+ }
293
+ // Parse YAML
294
+ const parsed = parseYamlFrontmatter(yamlContent);
295
+ if (parsed === null) {
296
+ logger.info(`Failed to parse YAML frontmatter in ${filePath}`);
297
+ const emptyConfig = { tool: [], session: [] };
298
+ markdownConfigCache.set(filePath, emptyConfig);
299
+ return emptyConfig;
300
+ }
301
+ // Extract command_hooks field
302
+ if (typeof parsed !== "object" || parsed === null) {
303
+ logger.debug(`Parsed YAML is not an object in ${filePath}`);
304
+ const emptyConfig = { tool: [], session: [] };
305
+ markdownConfigCache.set(filePath, emptyConfig);
306
+ return emptyConfig;
307
+ }
308
+ const config = parsed;
309
+ // First, try to parse the new simplified hooks format
310
+ const agentName = extractAgentNameFromPath(filePath);
311
+ const agentHooks = parseAgentHooks(yamlContent);
312
+ if (agentHooks) {
313
+ // Convert simplified format to internal format
314
+ const result = convertToCommandHooksConfig(agentHooks, agentName);
315
+ logger.debug(`Loaded simplified hooks from ${filePath}: ${result.tool?.length ?? 0} tool hooks`);
316
+ // Cache the result
317
+ markdownConfigCache.set(filePath, result);
318
+ return result;
319
+ }
320
+ // Fall back to old command_hooks format
321
+ const commandHooks = config.command_hooks;
322
+ if (commandHooks === undefined) {
323
+ logger.debug(`No hooks or command_hooks field in ${filePath}`);
324
+ const emptyConfig = { tool: [], session: [] };
325
+ markdownConfigCache.set(filePath, emptyConfig);
326
+ return emptyConfig;
327
+ }
328
+ // Validate command_hooks structure
329
+ if (!isValidCommandHooksConfig(commandHooks)) {
330
+ logger.info(`command_hooks field is not a valid object in ${filePath} (expected { tool?: [], session?: [] })`);
331
+ const emptyConfig = { tool: [], session: [] };
332
+ markdownConfigCache.set(filePath, emptyConfig);
333
+ return emptyConfig;
334
+ }
335
+ // Return with defaults for missing arrays
336
+ const result = {
337
+ tool: commandHooks.tool ?? [],
338
+ session: commandHooks.session ?? [],
339
+ };
340
+ logger.debug(`Loaded command_hooks from ${filePath}: ${result.tool?.length ?? 0} tool hooks, ${result.session?.length ?? 0} session hooks`);
341
+ // Cache the result
342
+ markdownConfigCache.set(filePath, result);
343
+ return result;
344
+ }
345
+ catch (error) {
346
+ // Catch-all for unexpected errors
347
+ const message = error instanceof Error ? error.message : String(error);
348
+ logger.info(`Unexpected error loading markdown config from ${filePath}: ${message}`);
349
+ const emptyConfig = { tool: [], session: [] };
350
+ markdownConfigCache.set(filePath, emptyConfig);
351
+ return emptyConfig;
352
+ }
353
+ }
354
+ /**
355
+ * Clear the markdown config cache for a specific file
356
+ *
357
+ * Forces the next call to loadMarkdownConfig() for this file to reload from disk.
358
+ * Useful for testing or when config files may have changed.
359
+ *
360
+ * @param filePath - Path to clear from cache, or undefined to clear all
361
+ * @internal For testing purposes
362
+ */
363
+ export function clearMarkdownConfigCache(filePath) {
364
+ if (filePath) {
365
+ logger.debug(`Clearing markdown config cache for ${filePath}`);
366
+ markdownConfigCache.delete(filePath);
367
+ }
368
+ else {
369
+ logger.debug("Clearing all markdown config cache");
370
+ markdownConfigCache.clear();
371
+ }
372
+ }
373
+ //# sourceMappingURL=markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/config/markdown.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Configuration merging and precedence logic for combining global and markdown configs
3
+ *
4
+ * Implements the precedence rules from PRD section 5.3:
5
+ * 1. Start with global hooks
6
+ * 2. Markdown hooks with same `id` replace global hooks (no error)
7
+ * 3. Markdown hooks with unique `id` are added
8
+ * 4. Duplicate IDs within same source are errors
9
+ */
10
+ import type { CommandHooksConfig, ToolHook, SessionHook, HookValidationError } from "../types/hooks.js";
11
+ /**
12
+ * Find duplicate IDs within a hook array
13
+ *
14
+ * Scans through an array of hooks and returns a list of IDs that appear
15
+ * more than once. Useful for validation of both tool and session hooks.
16
+ *
17
+ * @param hooks - Array of hooks to check (ToolHook[] or SessionHook[])
18
+ * @returns Array of duplicate IDs (empty if no duplicates found)
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * const hooks = [
23
+ * { id: "hook-1", ... },
24
+ * { id: "hook-2", ... },
25
+ * { id: "hook-1", ... } // duplicate
26
+ * ]
27
+ * findDuplicateIds(hooks) // Returns ["hook-1"]
28
+ * ```
29
+ */
30
+ export declare function findDuplicateIds(hooks: (ToolHook | SessionHook)[]): string[];
31
+ /**
32
+ * Merge global and markdown configs with proper precedence
33
+ *
34
+ * Implements the precedence rules from PRD section 5.3:
35
+ * 1. Start with global hooks
36
+ * 2. Markdown hooks with same `id` replace global hooks (no error)
37
+ * 3. Markdown hooks with unique `id` are added
38
+ * 4. Duplicate IDs within same source are errors
39
+ *
40
+ * Returns both the merged config and any validation errors found.
41
+ * Errors are returned but don't prevent merging - the caller can decide
42
+ * how to handle them.
43
+ *
44
+ * @param global - Global configuration from opencode.json
45
+ * @param markdown - Markdown configuration from agent/command .md file
46
+ * @returns Object with merged config and validation errors
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * const global = {
51
+ * tool: [{ id: "hook-1", when: { phase: "after" }, run: "echo global" }],
52
+ * session: []
53
+ * }
54
+ * const markdown = {
55
+ * tool: [{ id: "hook-1", when: { phase: "after" }, run: "echo markdown" }],
56
+ * session: []
57
+ * }
58
+ * const result = mergeConfigs(global, markdown)
59
+ * // result.config.tool[0].run === "echo markdown" (markdown replaced global)
60
+ * // result.errors === [] (no duplicates)
61
+ * ```
62
+ */
63
+ export declare function mergeConfigs(global: CommandHooksConfig, markdown: CommandHooksConfig): {
64
+ config: CommandHooksConfig;
65
+ errors: HookValidationError[];
66
+ };
67
+ //# sourceMappingURL=merge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../src/config/merge.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACR,kBAAkB,EAClB,QAAQ,EACR,WAAW,EACX,mBAAmB,EACtB,MAAM,mBAAmB,CAAA;AAG1B;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,CAAC,QAAQ,GAAG,WAAW,CAAC,EAAE,GAAG,MAAM,EAAE,CAa5E;AA+GD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,YAAY,CACzB,MAAM,EAAE,kBAAkB,EAC1B,QAAQ,EAAE,kBAAkB,GAC5B;IAAE,MAAM,EAAE,kBAAkB,CAAC;IAAC,MAAM,EAAE,mBAAmB,EAAE,CAAA;CAAE,CAmC/D"}
@@ -0,0 +1,192 @@
1
+ /**
2
+ * Configuration merging and precedence logic for combining global and markdown configs
3
+ *
4
+ * Implements the precedence rules from PRD section 5.3:
5
+ * 1. Start with global hooks
6
+ * 2. Markdown hooks with same `id` replace global hooks (no error)
7
+ * 3. Markdown hooks with unique `id` are added
8
+ * 4. Duplicate IDs within same source are errors
9
+ */
10
+ import { logger } from "../logging.js";
11
+ /**
12
+ * Find duplicate IDs within a hook array
13
+ *
14
+ * Scans through an array of hooks and returns a list of IDs that appear
15
+ * more than once. Useful for validation of both tool and session hooks.
16
+ *
17
+ * @param hooks - Array of hooks to check (ToolHook[] or SessionHook[])
18
+ * @returns Array of duplicate IDs (empty if no duplicates found)
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * const hooks = [
23
+ * { id: "hook-1", ... },
24
+ * { id: "hook-2", ... },
25
+ * { id: "hook-1", ... } // duplicate
26
+ * ]
27
+ * findDuplicateIds(hooks) // Returns ["hook-1"]
28
+ * ```
29
+ */
30
+ export function findDuplicateIds(hooks) {
31
+ const idCounts = new Map();
32
+ // Count occurrences of each ID
33
+ for (const hook of hooks) {
34
+ const count = idCounts.get(hook.id) ?? 0;
35
+ idCounts.set(hook.id, count + 1);
36
+ }
37
+ // Return IDs that appear more than once
38
+ return Array.from(idCounts.entries())
39
+ .filter(([, count]) => count > 1)
40
+ .map(([id]) => id);
41
+ }
42
+ /**
43
+ * Validate a single config source for duplicate IDs
44
+ *
45
+ * Checks both tool and session hooks for duplicates and returns
46
+ * validation errors for any found.
47
+ *
48
+ * @param config - Configuration to validate
49
+ * @param source - Source identifier for error reporting (e.g., "global", "markdown")
50
+ * @returns Array of validation errors (empty if no duplicates)
51
+ */
52
+ function validateConfigForDuplicates(config, source) {
53
+ const errors = [];
54
+ // Check tool hooks for duplicates
55
+ if (config.tool && config.tool.length > 0) {
56
+ const toolDuplicates = findDuplicateIds(config.tool);
57
+ for (const id of toolDuplicates) {
58
+ errors.push({
59
+ hookId: id,
60
+ type: "duplicate_id",
61
+ message: `Duplicate hook ID "${id}" found in ${source} tool hooks`,
62
+ severity: "error",
63
+ });
64
+ }
65
+ }
66
+ // Check session hooks for duplicates
67
+ if (config.session && config.session.length > 0) {
68
+ const sessionDuplicates = findDuplicateIds(config.session);
69
+ for (const id of sessionDuplicates) {
70
+ errors.push({
71
+ hookId: id,
72
+ type: "duplicate_id",
73
+ message: `Duplicate hook ID "${id}" found in ${source} session hooks`,
74
+ severity: "error",
75
+ });
76
+ }
77
+ }
78
+ return errors;
79
+ }
80
+ /**
81
+ * Merge two hook arrays with markdown taking precedence
82
+ *
83
+ * Combines global and markdown hooks, where markdown hooks with the same ID
84
+ * replace global hooks. Markdown hooks with unique IDs are appended.
85
+ *
86
+ * Order is preserved: global hooks first (except those replaced), then new markdown hooks.
87
+ *
88
+ * @param globalHooks - Hooks from global config
89
+ * @param markdownHooks - Hooks from markdown config
90
+ * @returns Merged hook array
91
+ *
92
+ * @example
93
+ * ```typescript
94
+ * const global = [
95
+ * { id: "hook-1", ... },
96
+ * { id: "hook-2", ... }
97
+ * ]
98
+ * const markdown = [
99
+ * { id: "hook-1", ... }, // replaces global hook-1
100
+ * { id: "hook-3", ... } // new hook
101
+ * ]
102
+ * mergeHookArrays(global, markdown)
103
+ * // Returns: [{ id: "hook-1", ... (markdown version) }, { id: "hook-2", ... }, { id: "hook-3", ... }]
104
+ * ```
105
+ */
106
+ function mergeHookArrays(globalHooks, markdownHooks) {
107
+ // Create a map of markdown hooks by ID for quick lookup
108
+ const markdownMap = new Map();
109
+ const markdownIds = new Set();
110
+ for (const hook of markdownHooks) {
111
+ markdownMap.set(hook.id, hook);
112
+ markdownIds.add(hook.id);
113
+ }
114
+ // Start with global hooks, replacing those that appear in markdown
115
+ const result = [];
116
+ const processedIds = new Set();
117
+ for (const hook of globalHooks) {
118
+ if (markdownMap.has(hook.id)) {
119
+ // Replace with markdown version
120
+ result.push(markdownMap.get(hook.id));
121
+ }
122
+ else {
123
+ // Keep global hook
124
+ result.push(hook);
125
+ }
126
+ processedIds.add(hook.id);
127
+ }
128
+ // Add markdown hooks that weren't replacements
129
+ for (const hook of markdownHooks) {
130
+ if (!processedIds.has(hook.id)) {
131
+ result.push(hook);
132
+ }
133
+ }
134
+ return result;
135
+ }
136
+ /**
137
+ * Merge global and markdown configs with proper precedence
138
+ *
139
+ * Implements the precedence rules from PRD section 5.3:
140
+ * 1. Start with global hooks
141
+ * 2. Markdown hooks with same `id` replace global hooks (no error)
142
+ * 3. Markdown hooks with unique `id` are added
143
+ * 4. Duplicate IDs within same source are errors
144
+ *
145
+ * Returns both the merged config and any validation errors found.
146
+ * Errors are returned but don't prevent merging - the caller can decide
147
+ * how to handle them.
148
+ *
149
+ * @param global - Global configuration from opencode.json
150
+ * @param markdown - Markdown configuration from agent/command .md file
151
+ * @returns Object with merged config and validation errors
152
+ *
153
+ * @example
154
+ * ```typescript
155
+ * const global = {
156
+ * tool: [{ id: "hook-1", when: { phase: "after" }, run: "echo global" }],
157
+ * session: []
158
+ * }
159
+ * const markdown = {
160
+ * tool: [{ id: "hook-1", when: { phase: "after" }, run: "echo markdown" }],
161
+ * session: []
162
+ * }
163
+ * const result = mergeConfigs(global, markdown)
164
+ * // result.config.tool[0].run === "echo markdown" (markdown replaced global)
165
+ * // result.errors === [] (no duplicates)
166
+ * ```
167
+ */
168
+ export function mergeConfigs(global, markdown) {
169
+ const errors = [];
170
+ // Validate global config for duplicates
171
+ const globalErrors = validateConfigForDuplicates(global, "global");
172
+ errors.push(...globalErrors);
173
+ // Validate markdown config for duplicates
174
+ const markdownErrors = validateConfigForDuplicates(markdown, "markdown");
175
+ errors.push(...markdownErrors);
176
+ // Merge tool hooks
177
+ const globalToolHooks = global.tool ?? [];
178
+ const markdownToolHooks = markdown.tool ?? [];
179
+ const mergedToolHooks = mergeHookArrays(globalToolHooks, markdownToolHooks);
180
+ // Merge session hooks
181
+ const globalSessionHooks = global.session ?? [];
182
+ const markdownSessionHooks = markdown.session ?? [];
183
+ const mergedSessionHooks = mergeHookArrays(globalSessionHooks, markdownSessionHooks);
184
+ // Build merged config
185
+ const mergedConfig = {
186
+ tool: mergedToolHooks.length > 0 ? mergedToolHooks : [],
187
+ session: mergedSessionHooks.length > 0 ? mergedSessionHooks : [],
188
+ };
189
+ logger.debug(`Merged configs: ${mergedToolHooks.length} tool hooks, ${mergedSessionHooks.length} session hooks, ${errors.length} errors`);
190
+ return { config: mergedConfig, errors };
191
+ }
192
+ //# sourceMappingURL=merge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge.js","sourceRoot":"","sources":["../../src/config/merge.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAQH,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAEtC;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAiC;IAC/D,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAA;IAE1C,+BAA+B;IAC/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAA;QACxC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,GAAG,CAAC,CAAC,CAAA;IAClC,CAAC;IAED,wCAAwC;IACxC,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;SAClC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC;SAChC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAA;AACvB,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,2BAA2B,CACjC,MAA0B,EAC1B,MAAc;IAEd,MAAM,MAAM,GAA0B,EAAE,CAAA;IAExC,kCAAkC;IAClC,IAAI,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1C,MAAM,cAAc,GAAG,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QACpD,KAAK,MAAM,EAAE,IAAI,cAAc,EAAE,CAAC;YAChC,MAAM,CAAC,IAAI,CAAC;gBACV,MAAM,EAAE,EAAE;gBACV,IAAI,EAAE,cAAc;gBACpB,OAAO,EAAE,sBAAsB,EAAE,cAAc,MAAM,aAAa;gBAClE,QAAQ,EAAE,OAAO;aAClB,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,qCAAqC;IACrC,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChD,MAAM,iBAAiB,GAAG,gBAAgB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QAC1D,KAAK,MAAM,EAAE,IAAI,iBAAiB,EAAE,CAAC;YACnC,MAAM,CAAC,IAAI,CAAC;gBACV,MAAM,EAAE,EAAE;gBACV,IAAI,EAAE,cAAc;gBACpB,OAAO,EAAE,sBAAsB,EAAE,cAAc,MAAM,gBAAgB;gBACrE,QAAQ,EAAE,OAAO;aAClB,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAA;AAChB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,SAAS,eAAe,CACrB,WAAgB,EAChB,aAAkB;IAElB,wDAAwD;IACxD,MAAM,WAAW,GAAG,IAAI,GAAG,EAAa,CAAA;IACxC,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAA;IAErC,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;QACjC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAA;QAC9B,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAC1B,CAAC;IAED,mEAAmE;IACnE,MAAM,MAAM,GAAQ,EAAE,CAAA;IACtB,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAA;IAEtC,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,IAAI,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YAC7B,gCAAgC;YAChC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAE,CAAC,CAAA;QACxC,CAAC;aAAM,CAAC;YACN,mBAAmB;YACnB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACnB,CAAC;QACD,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAC3B,CAAC;IAED,+CAA+C;IAC/C,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;QACjC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YAC/B,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACnB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAA;AAChB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,UAAU,YAAY,CACzB,MAA0B,EAC1B,QAA4B;IAE5B,MAAM,MAAM,GAA0B,EAAE,CAAA;IAExC,wCAAwC;IACxC,MAAM,YAAY,GAAG,2BAA2B,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;IAClE,MAAM,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,CAAA;IAE5B,0CAA0C;IAC1C,MAAM,cAAc,GAAG,2BAA2B,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAA;IACxE,MAAM,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,CAAA;IAE9B,mBAAmB;IACnB,MAAM,eAAe,GAAG,MAAM,CAAC,IAAI,IAAI,EAAE,CAAA;IACzC,MAAM,iBAAiB,GAAG,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAA;IAC7C,MAAM,eAAe,GAAG,eAAe,CAAC,eAAe,EAAE,iBAAiB,CAAC,CAAA;IAE1E,sBAAsB;IACtB,MAAM,kBAAkB,GAAG,MAAM,CAAC,OAAO,IAAI,EAAE,CAAA;IAC/C,MAAM,oBAAoB,GAAG,QAAQ,CAAC,OAAO,IAAI,EAAE,CAAA;IACnD,MAAM,kBAAkB,GAAG,eAAe,CACxC,kBAAkB,EAClB,oBAAoB,CACrB,CAAA;IAED,sBAAsB;IACtB,MAAM,YAAY,GAAuB;QACvC,IAAI,EAAE,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE;QACvD,OAAO,EAAE,kBAAkB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE;KACjE,CAAA;IAEA,MAAM,CAAC,KAAK,CACV,mBAAmB,eAAe,CAAC,MAAM,gBAAgB,kBAAkB,CAAC,MAAM,mBAAmB,MAAM,CAAC,MAAM,SAAS,CAC5H,CAAA;IAEF,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,CAAA;AAC3C,CAAC"}