@s_s/agent-kit 1.0.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 (50) hide show
  1. package/README.md +317 -0
  2. package/build/create-kit.d.ts +16 -0
  3. package/build/create-kit.js +54 -0
  4. package/build/create-kit.js.map +1 -0
  5. package/build/detect.d.ts +13 -0
  6. package/build/detect.js +34 -0
  7. package/build/detect.js.map +1 -0
  8. package/build/hook-capabilities.d.ts +87 -0
  9. package/build/hook-capabilities.js +191 -0
  10. package/build/hook-capabilities.js.map +1 -0
  11. package/build/hook-registry.d.ts +158 -0
  12. package/build/hook-registry.js +223 -0
  13. package/build/hook-registry.js.map +1 -0
  14. package/build/hook-translators/claude-code.d.ts +26 -0
  15. package/build/hook-translators/claude-code.js +351 -0
  16. package/build/hook-translators/claude-code.js.map +1 -0
  17. package/build/hook-translators/index.d.ts +4 -0
  18. package/build/hook-translators/index.js +4 -0
  19. package/build/hook-translators/index.js.map +1 -0
  20. package/build/hook-translators/openclaw.d.ts +25 -0
  21. package/build/hook-translators/openclaw.js +272 -0
  22. package/build/hook-translators/openclaw.js.map +1 -0
  23. package/build/hook-translators/opencode.d.ts +23 -0
  24. package/build/hook-translators/opencode.js +254 -0
  25. package/build/hook-translators/opencode.js.map +1 -0
  26. package/build/hook-translators/types.d.ts +59 -0
  27. package/build/hook-translators/types.js +2 -0
  28. package/build/hook-translators/types.js.map +1 -0
  29. package/build/hook-types.d.ts +155 -0
  30. package/build/hook-types.js +2 -0
  31. package/build/hook-types.js.map +1 -0
  32. package/build/hooks.d.ts +30 -0
  33. package/build/hooks.js +333 -0
  34. package/build/hooks.js.map +1 -0
  35. package/build/index.d.ts +9 -0
  36. package/build/index.js +11 -0
  37. package/build/index.js.map +1 -0
  38. package/build/platform.d.ts +17 -0
  39. package/build/platform.js +79 -0
  40. package/build/platform.js.map +1 -0
  41. package/build/prompt.d.ts +21 -0
  42. package/build/prompt.js +87 -0
  43. package/build/prompt.js.map +1 -0
  44. package/build/register.d.ts +18 -0
  45. package/build/register.js +34 -0
  46. package/build/register.js.map +1 -0
  47. package/build/types.d.ts +111 -0
  48. package/build/types.js +53 -0
  49. package/build/types.js.map +1 -0
  50. package/package.json +42 -0
@@ -0,0 +1,272 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Helpers
3
+ // ---------------------------------------------------------------------------
4
+ function capitalize(str) {
5
+ return str.charAt(0).toUpperCase() + str.slice(1);
6
+ }
7
+ function matcherToRegex(match) {
8
+ if (match === undefined || match === '*')
9
+ return '/.*/';
10
+ if (match instanceof RegExp)
11
+ return match.toString();
12
+ return `/${match}/`;
13
+ }
14
+ // ---------------------------------------------------------------------------
15
+ // OpenClaw Translator
16
+ // ---------------------------------------------------------------------------
17
+ /**
18
+ * Translates intent-based hooks into OpenClaw native format.
19
+ *
20
+ * OpenClaw dual-layer system:
21
+ * - Internal hooks: type:action string keys, event objects, errors never propagate
22
+ * - Plugin hooks: typed, validated, modifying hooks run sequentially by priority
23
+ *
24
+ * File format:
25
+ * - HOOK.md with YAML frontmatter (name, description, metadata.openclaw.events)
26
+ * - handler.ts exporting default async function
27
+ */
28
+ export class OpenClawTranslator {
29
+ translate(intents, rawHooks, extendHooks, toolName) {
30
+ const files = {};
31
+ const warnings = [];
32
+ const skipped = [];
33
+ // OpenClaw hook files live in subdirectories per hook type.
34
+ // We collect all events that the main handler needs to respond to,
35
+ // and internal hooks that need separate registration.
36
+ const pluginEvents = new Set();
37
+ const internalEvents = new Set();
38
+ const handlerSections = [];
39
+ // Track intent-generated hooks for conflict detection
40
+ const intentGeneratedPluginHooks = new Set();
41
+ const intentGeneratedInternalHooks = new Set();
42
+ // --- inject intents ---
43
+ const injectIntents = intents.filter((i) => i.type === 'inject');
44
+ if (injectIntents.length > 0) {
45
+ const internalHook = 'agent:bootstrap';
46
+ if (rawHooks.has(`openclaw::${internalHook}`)) {
47
+ warnings.push(`[openclaw] raw hook for ${internalHook} overrides inject intent.`);
48
+ }
49
+ else {
50
+ internalEvents.add(internalHook);
51
+ intentGeneratedInternalHooks.add(internalHook);
52
+ const reminderParts = injectIntents
53
+ .flatMap((i) => [i.sessionStart, i.perTurn].filter(Boolean))
54
+ .join('\\n\\n');
55
+ handlerSections.push(this.buildInjectSection(toolName, reminderParts));
56
+ }
57
+ // session_start / session_end via plugin hooks
58
+ const sessionStarts = injectIntents.filter((i) => i.sessionStart);
59
+ if (sessionStarts.length > 0 && !rawHooks.has('openclaw::session_start')) {
60
+ pluginEvents.add('session_start');
61
+ intentGeneratedPluginHooks.add('session_start');
62
+ }
63
+ const sessionEnds = injectIntents.filter((i) => i.sessionEnd);
64
+ if (sessionEnds.length > 0 && !rawHooks.has('openclaw::session_end')) {
65
+ pluginEvents.add('session_end');
66
+ intentGeneratedPluginHooks.add('session_end');
67
+ const combined = sessionEnds.map((i) => i.sessionEnd).join('\\n\\n');
68
+ handlerSections.push(this.buildSessionEndInjectSection(combined));
69
+ }
70
+ // compaction → session:compact:before (internal) or before_compaction (plugin)
71
+ const compactions = injectIntents.filter((i) => i.compaction);
72
+ if (compactions.length > 0) {
73
+ if (!rawHooks.has('openclaw::before_compaction')) {
74
+ pluginEvents.add('before_compaction');
75
+ intentGeneratedPluginHooks.add('before_compaction');
76
+ const combined = compactions.map((i) => i.compaction).join('\\n\\n');
77
+ handlerSections.push(this.buildCompactionSection(combined));
78
+ }
79
+ }
80
+ }
81
+ // --- beforeToolCall intents ---
82
+ const beforeIntents = intents.filter((i) => i.type === 'beforeToolCall');
83
+ if (beforeIntents.length > 0) {
84
+ const hookName = 'before_tool_call';
85
+ if (rawHooks.has(`openclaw::${hookName}`)) {
86
+ warnings.push(`[openclaw] raw hook for ${hookName} overrides beforeToolCall intent.`);
87
+ }
88
+ else {
89
+ pluginEvents.add(hookName);
90
+ intentGeneratedPluginHooks.add(hookName);
91
+ handlerSections.push(this.buildBeforeToolCallSection(beforeIntents));
92
+ }
93
+ }
94
+ // --- afterToolCall intents ---
95
+ const afterIntents = intents.filter((i) => i.type === 'afterToolCall');
96
+ if (afterIntents.length > 0) {
97
+ const hookName = 'after_tool_call';
98
+ if (rawHooks.has(`openclaw::${hookName}`)) {
99
+ warnings.push(`[openclaw] raw hook for ${hookName} overrides afterToolCall intent.`);
100
+ }
101
+ else {
102
+ pluginEvents.add(hookName);
103
+ intentGeneratedPluginHooks.add(hookName);
104
+ handlerSections.push(this.buildAfterToolCallSection(afterIntents));
105
+ }
106
+ }
107
+ // --- onSession intents ---
108
+ const sessionIntents = intents.filter((i) => i.type === 'onSession');
109
+ if (sessionIntents.length > 0) {
110
+ const hasStart = sessionIntents.some((i) => i.start);
111
+ const hasEnd = sessionIntents.some((i) => i.end);
112
+ if (hasStart && !intentGeneratedPluginHooks.has('session_start')) {
113
+ if (rawHooks.has('openclaw::session_start')) {
114
+ warnings.push(`[openclaw] raw hook for session_start overrides onSession.start intent.`);
115
+ }
116
+ else {
117
+ pluginEvents.add('session_start');
118
+ intentGeneratedPluginHooks.add('session_start');
119
+ handlerSections.push(this.buildOnSessionSection('start'));
120
+ }
121
+ }
122
+ if (hasEnd && !intentGeneratedPluginHooks.has('session_end')) {
123
+ if (rawHooks.has('openclaw::session_end')) {
124
+ warnings.push(`[openclaw] raw hook for session_end overrides onSession.end intent.`);
125
+ }
126
+ else {
127
+ pluginEvents.add('session_end');
128
+ intentGeneratedPluginHooks.add('session_end');
129
+ handlerSections.push(this.buildOnSessionSection('end'));
130
+ }
131
+ }
132
+ }
133
+ // --- onPermission intents ---
134
+ const permIntents = intents.filter((i) => i.type === 'onPermission');
135
+ if (permIntents.length > 0) {
136
+ // OpenClaw has no dedicated permission hook.
137
+ // Best effort: degrade to before_tool_call with block capability.
138
+ skipped.push({
139
+ intent: 'onPermission',
140
+ agent: 'openclaw',
141
+ reason: 'OpenClaw has no dedicated permission request hook. ' +
142
+ 'Consider using hooks.raw() with before_tool_call for similar behavior.',
143
+ });
144
+ warnings.push(`[openclaw] onPermission: not supported. OpenClaw has no PermissionRequest equivalent. ` +
145
+ `Use hooks.raw("openclaw", "before_tool_call", ...) as a workaround.`);
146
+ }
147
+ // --- Apply extend hooks to handler sections ---
148
+ for (const hookName of [...intentGeneratedPluginHooks, ...intentGeneratedInternalHooks]) {
149
+ const key = `openclaw::${hookName}`;
150
+ const extends_ = extendHooks.get(key);
151
+ if (extends_ && extends_.length > 0) {
152
+ for (const ext of extends_) {
153
+ handlerSections.push(` // --- extend for ${hookName} ---\n ${ext.handler}`);
154
+ }
155
+ }
156
+ }
157
+ // --- Build HOOK.md and handler.ts ---
158
+ if (handlerSections.length > 0 || internalEvents.size > 0 || pluginEvents.size > 0) {
159
+ const allEvents = [...internalEvents, ...pluginEvents];
160
+ files['HOOK.md'] = this.buildHookMd(toolName, allEvents);
161
+ files['handler.ts'] = this.buildHandlerTs(toolName, handlerSections, internalEvents, pluginEvents);
162
+ }
163
+ // --- Raw hooks: write as additional files ---
164
+ for (const [key, reg] of rawHooks) {
165
+ if (!key.startsWith('openclaw::'))
166
+ continue;
167
+ const hookName = key.split('::')[1];
168
+ if (intentGeneratedPluginHooks.has(hookName) || intentGeneratedInternalHooks.has(hookName)) {
169
+ warnings.push(`[openclaw] raw hook for ${hookName} replaces intent-generated hook.`);
170
+ }
171
+ // Raw hooks get their own subdirectory-style files
172
+ const safeName = hookName.replace(/[:.]/g, '-');
173
+ files[`raw-${safeName}.ts`] = reg.handler;
174
+ }
175
+ return { files, warnings, skipped };
176
+ }
177
+ getSettingsEntries() {
178
+ // OpenClaw doesn't use settings.json for hooks
179
+ return [];
180
+ }
181
+ // -----------------------------------------------------------------------
182
+ // Section builders
183
+ // -----------------------------------------------------------------------
184
+ buildInjectSection(toolName, reminderContent) {
185
+ const constName = toolName.toUpperCase().replace(/-/g, '_') + '_REMINDER';
186
+ return ` // --- inject (agent:bootstrap) ---
187
+ if (event.type === 'agent' && event.action === 'bootstrap') {
188
+ if (event.sessionKey && event.sessionKey.includes(':subagent:')) {
189
+ return;
190
+ }
191
+ if (Array.isArray(event.context?.bootstrapFiles)) {
192
+ event.context.bootstrapFiles.push({
193
+ path: '${constName}.md',
194
+ content: \`${reminderContent}\`,
195
+ virtual: true,
196
+ });
197
+ }
198
+ }`;
199
+ }
200
+ buildSessionEndInjectSection(content) {
201
+ return ` // --- inject.sessionEnd (session_end) ---
202
+ if (event.hookName === 'session_end') {
203
+ // Session end content: ${content.substring(0, 50)}...
204
+ }`;
205
+ }
206
+ buildCompactionSection(content) {
207
+ return ` // --- inject.compaction (before_compaction) ---
208
+ if (event.hookName === 'before_compaction') {
209
+ if (event.context) {
210
+ event.context.additionalContext = (event.context.additionalContext || '') +
211
+ '\\n' + \`${content}\`;
212
+ }
213
+ }`;
214
+ }
215
+ buildBeforeToolCallSection(intents) {
216
+ const cases = intents.map((intent, i) => {
217
+ const regex = matcherToRegex(intent.match);
218
+ return ` // beforeToolCall handler #${i + 1}
219
+ if (${regex}.test(event.toolName || "")) {
220
+ // Handler evaluated at runtime via agent-kit
221
+ }`;
222
+ });
223
+ return ` // --- beforeToolCall (before_tool_call) ---
224
+ if (event.hookName === 'before_tool_call') {
225
+ ${cases.join('\n\n')}
226
+ }`;
227
+ }
228
+ buildAfterToolCallSection(intents) {
229
+ const cases = intents.map((intent, i) => {
230
+ const regex = matcherToRegex(intent.match);
231
+ return ` // afterToolCall observer #${i + 1}
232
+ if (${regex}.test(event.toolName || "")) {
233
+ // Observer evaluated at runtime via agent-kit
234
+ }`;
235
+ });
236
+ return ` // --- afterToolCall (after_tool_call) ---
237
+ if (event.hookName === 'after_tool_call') {
238
+ ${cases.join('\n\n')}
239
+ }`;
240
+ }
241
+ buildOnSessionSection(phase) {
242
+ return ` // --- onSession.${phase} (session_${phase}) ---
243
+ if (event.hookName === 'session_${phase}') {
244
+ // Session ${phase} handler — extend with hooks.extend() for custom logic.
245
+ }`;
246
+ }
247
+ // -----------------------------------------------------------------------
248
+ // File builders
249
+ // -----------------------------------------------------------------------
250
+ buildHookMd(toolName, events) {
251
+ return `---
252
+ name: ${toolName}
253
+ description: "${capitalize(toolName)} hook - generated by @s_s/agent-kit"
254
+ metadata: {"openclaw":{"events":${JSON.stringify(events)}}}
255
+ ---
256
+ `;
257
+ }
258
+ buildHandlerTs(toolName, sections, _internalEvents, _pluginEvents) {
259
+ return `/**
260
+ * ${capitalize(toolName)} Hook Handler for OpenClaw
261
+ * Generated by @s_s/agent-kit
262
+ */
263
+
264
+ const handler = async (event: any) => {
265
+ ${sections.join('\n\n')}
266
+ };
267
+
268
+ export default handler;
269
+ `;
270
+ }
271
+ }
272
+ //# sourceMappingURL=openclaw.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openclaw.js","sourceRoot":"","sources":["../../src/hook-translators/openclaw.ts"],"names":[],"mappings":"AAYA,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,SAAS,UAAU,CAAC,GAAW;IAC3B,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACtD,CAAC;AAED,SAAS,cAAc,CAAC,KAAkC;IACtD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,GAAG;QAAE,OAAO,MAAM,CAAC;IACxD,IAAI,KAAK,YAAY,MAAM;QAAE,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC;IACrD,OAAO,IAAI,KAAK,GAAG,CAAC;AACxB,CAAC;AAED,8EAA8E;AAC9E,sBAAsB;AACtB,8EAA8E;AAE9E;;;;;;;;;;GAUG;AACH,MAAM,OAAO,kBAAkB;IAC3B,SAAS,CACL,OAA8B,EAC9B,QAAkD,EAClD,WAAmE,EACnE,QAAgB;QAEhB,MAAM,KAAK,GAA2B,EAAE,CAAC;QACzC,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAiC,EAAE,CAAC;QAEjD,4DAA4D;QAC5D,mEAAmE;QACnE,sDAAsD;QACtD,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;QACvC,MAAM,cAAc,GAAG,IAAI,GAAG,EAAU,CAAC;QACzC,MAAM,eAAe,GAAa,EAAE,CAAC;QAErC,sDAAsD;QACtD,MAAM,0BAA0B,GAAG,IAAI,GAAG,EAAU,CAAC;QACrD,MAAM,4BAA4B,GAAG,IAAI,GAAG,EAAU,CAAC;QAEvD,yBAAyB;QACzB,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAqB,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;QACpF,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,MAAM,YAAY,GAAG,iBAAiB,CAAC;YAEvC,IAAI,QAAQ,CAAC,GAAG,CAAC,aAAa,YAAY,EAAE,CAAC,EAAE,CAAC;gBAC5C,QAAQ,CAAC,IAAI,CAAC,2BAA2B,YAAY,2BAA2B,CAAC,CAAC;YACtF,CAAC;iBAAM,CAAC;gBACJ,cAAc,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;gBACjC,4BAA4B,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;gBAE/C,MAAM,aAAa,GAAG,aAAa;qBAC9B,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;qBAC3D,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAEpB,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC;YAC3E,CAAC;YAED,+CAA+C;YAC/C,MAAM,aAAa,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;YAClE,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,yBAAyB,CAAC,EAAE,CAAC;gBACvE,YAAY,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;gBAClC,0BAA0B,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;YACpD,CAAC;YAED,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;YAC9D,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,uBAAuB,CAAC,EAAE,CAAC;gBACnE,YAAY,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;gBAChC,0BAA0B,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;gBAC9C,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAW,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACtE,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,4BAA4B,CAAC,QAAQ,CAAC,CAAC,CAAC;YACtE,CAAC;YAED,+EAA+E;YAC/E,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;YAC9D,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACzB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,6BAA6B,CAAC,EAAE,CAAC;oBAC/C,YAAY,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;oBACtC,0BAA0B,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;oBACpD,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAW,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;oBACtE,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,sBAAsB,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAChE,CAAC;YACL,CAAC;QACL,CAAC;QAED,iCAAiC;QACjC,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAA6B,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC;QACpG,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,MAAM,QAAQ,GAAG,kBAAkB,CAAC;YACpC,IAAI,QAAQ,CAAC,GAAG,CAAC,aAAa,QAAQ,EAAE,CAAC,EAAE,CAAC;gBACxC,QAAQ,CAAC,IAAI,CAAC,2BAA2B,QAAQ,mCAAmC,CAAC,CAAC;YAC1F,CAAC;iBAAM,CAAC;gBACJ,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBAC3B,0BAA0B,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBACzC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,0BAA0B,CAAC,aAAa,CAAC,CAAC,CAAC;YACzE,CAAC;QACL,CAAC;QAED,gCAAgC;QAChC,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAA4B,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC;QACjG,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,MAAM,QAAQ,GAAG,iBAAiB,CAAC;YACnC,IAAI,QAAQ,CAAC,GAAG,CAAC,aAAa,QAAQ,EAAE,CAAC,EAAE,CAAC;gBACxC,QAAQ,CAAC,IAAI,CAAC,2BAA2B,QAAQ,kCAAkC,CAAC,CAAC;YACzF,CAAC;iBAAM,CAAC;gBACJ,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBAC3B,0BAA0B,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBACzC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAyB,CAAC,YAAY,CAAC,CAAC,CAAC;YACvE,CAAC;QACL,CAAC;QAED,4BAA4B;QAC5B,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAwB,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;QAC3F,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YACrD,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAEjD,IAAI,QAAQ,IAAI,CAAC,0BAA0B,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE,CAAC;gBAC/D,IAAI,QAAQ,CAAC,GAAG,CAAC,yBAAyB,CAAC,EAAE,CAAC;oBAC1C,QAAQ,CAAC,IAAI,CAAC,yEAAyE,CAAC,CAAC;gBAC7F,CAAC;qBAAM,CAAC;oBACJ,YAAY,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;oBAClC,0BAA0B,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;oBAChD,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC,CAAC;gBAC9D,CAAC;YACL,CAAC;YAED,IAAI,MAAM,IAAI,CAAC,0BAA0B,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC;gBAC3D,IAAI,QAAQ,CAAC,GAAG,CAAC,uBAAuB,CAAC,EAAE,CAAC;oBACxC,QAAQ,CAAC,IAAI,CAAC,qEAAqE,CAAC,CAAC;gBACzF,CAAC;qBAAM,CAAC;oBACJ,YAAY,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;oBAChC,0BAA0B,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;oBAC9C,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC;gBAC5D,CAAC;YACL,CAAC;QACL,CAAC;QAED,+BAA+B;QAC/B,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAA2B,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC;QAC9F,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzB,6CAA6C;YAC7C,kEAAkE;YAClE,OAAO,CAAC,IAAI,CAAC;gBACT,MAAM,EAAE,cAAc;gBACtB,KAAK,EAAE,UAAU;gBACjB,MAAM,EACF,qDAAqD;oBACrD,wEAAwE;aAC/E,CAAC,CAAC;YACH,QAAQ,CAAC,IAAI,CACT,wFAAwF;gBACpF,qEAAqE,CAC5E,CAAC;QACN,CAAC;QAED,iDAAiD;QACjD,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAG,0BAA0B,EAAE,GAAG,4BAA4B,CAAC,EAAE,CAAC;YACtF,MAAM,GAAG,GAAG,aAAa,QAAQ,EAAE,CAAC;YACpC,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACtC,IAAI,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAClC,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;oBACzB,eAAe,CAAC,IAAI,CAAC,yBAAyB,QAAQ,aAAa,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;gBACtF,CAAC;YACL,CAAC;QACL,CAAC;QAED,uCAAuC;QACvC,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,IAAI,cAAc,CAAC,IAAI,GAAG,CAAC,IAAI,YAAY,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YACjF,MAAM,SAAS,GAAG,CAAC,GAAG,cAAc,EAAE,GAAG,YAAY,CAAC,CAAC;YACvD,KAAK,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;YACzD,KAAK,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,eAAe,EAAE,cAAc,EAAE,YAAY,CAAC,CAAC;QACvG,CAAC;QAED,+CAA+C;QAC/C,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,QAAQ,EAAE,CAAC;YAChC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,YAAY,CAAC;gBAAE,SAAS;YAC5C,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YAEpC,IAAI,0BAA0B,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,4BAA4B,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACzF,QAAQ,CAAC,IAAI,CAAC,2BAA2B,QAAQ,kCAAkC,CAAC,CAAC;YACzF,CAAC;YAED,mDAAmD;YACnD,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YAChD,KAAK,CAAC,OAAO,QAAQ,KAAK,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC;QAC9C,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;IACxC,CAAC;IAED,kBAAkB;QACd,+CAA+C;QAC/C,OAAO,EAAE,CAAC;IACd,CAAC;IAED,0EAA0E;IAC1E,mBAAmB;IACnB,0EAA0E;IAElE,kBAAkB,CAAC,QAAgB,EAAE,eAAuB;QAChE,MAAM,SAAS,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,GAAG,WAAW,CAAC;QAC1E,OAAO;;;;;;;yBAOU,SAAS;6BACL,eAAe;;;;MAItC,CAAC;IACH,CAAC;IAEO,4BAA4B,CAAC,OAAe;QAChD,OAAO;;kCAEmB,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC;MACpD,CAAC;IACH,CAAC;IAEO,sBAAsB,CAAC,OAAe;QAC1C,OAAO;;;;4BAIa,OAAO;;MAE7B,CAAC;IACH,CAAC;IAEO,0BAA0B,CAAC,OAA+B;QAC9D,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YACpC,MAAM,KAAK,GAAG,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC3C,OAAO,sCAAsC,CAAC,GAAG,CAAC;cAChD,KAAK;;UAET,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,OAAO;;EAEb,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;MACd,CAAC;IACH,CAAC;IAEO,yBAAyB,CAAC,OAA8B;QAC5D,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YACpC,MAAM,KAAK,GAAG,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC3C,OAAO,sCAAsC,CAAC,GAAG,CAAC;cAChD,KAAK;;UAET,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,OAAO;;EAEb,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;MACd,CAAC;IACH,CAAC;IAEO,qBAAqB,CAAC,KAAsB;QAChD,OAAO,wBAAwB,KAAK,aAAa,KAAK;sCACxB,KAAK;qBACtB,KAAK;MACpB,CAAC;IACH,CAAC;IAED,0EAA0E;IAC1E,gBAAgB;IAChB,0EAA0E;IAElE,WAAW,CAAC,QAAgB,EAAE,MAAgB;QAClD,OAAO;QACP,QAAQ;gBACA,UAAU,CAAC,QAAQ,CAAC;kCACF,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;;CAEvD,CAAC;IACE,CAAC;IAEO,cAAc,CAClB,QAAgB,EAChB,QAAkB,EAClB,eAA4B,EAC5B,aAA0B;QAE1B,OAAO;KACV,UAAU,CAAC,QAAQ,CAAC;;;;;EAKvB,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;;;;CAItB,CAAC;IACE,CAAC;CACJ"}
@@ -0,0 +1,23 @@
1
+ import type { AgentHookTranslator, TranslationResult, SettingsHookEntry } from './types.js';
2
+ import type { HookIntent, RawHookRegistration, ExtendHookRegistration } from '../hook-types.js';
3
+ /**
4
+ * Translates intent-based hooks into an OpenCode plugin file.
5
+ *
6
+ * OpenCode constraints:
7
+ * - All hooks must merge into a single .ts plugin file
8
+ * - Plugin exports an async factory function that returns a hook object
9
+ * - Hooks are keys in the returned object (e.g. "tool.execute.before")
10
+ * - Each hook is an async function(input, output) that modifies output in-place
11
+ * - No explicit block mechanism for tool.execute.before (partial support)
12
+ */
13
+ export declare class OpenCodeTranslator implements AgentHookTranslator {
14
+ translate(intents: readonly HookIntent[], rawHooks: ReadonlyMap<string, RawHookRegistration>, extendHooks: ReadonlyMap<string, readonly ExtendHookRegistration[]>, toolName: string): TranslationResult;
15
+ getSettingsEntries(): SettingsHookEntry[];
16
+ private addHookBody;
17
+ private buildInjectHookBody;
18
+ private buildBeforeToolCallBody;
19
+ private buildAfterToolCallBody;
20
+ private buildSessionBody;
21
+ private buildPermissionBody;
22
+ private buildPluginFile;
23
+ }
@@ -0,0 +1,254 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Helpers
3
+ // ---------------------------------------------------------------------------
4
+ function toPascalCase(str) {
5
+ return str
6
+ .split(/[-_]/)
7
+ .map((s) => s.charAt(0).toUpperCase() + s.slice(1).toLowerCase())
8
+ .join('');
9
+ }
10
+ function capitalize(str) {
11
+ return str.charAt(0).toUpperCase() + str.slice(1);
12
+ }
13
+ function matcherToRegex(match) {
14
+ if (match === undefined || match === '*')
15
+ return '/.*/';
16
+ if (match instanceof RegExp)
17
+ return match.toString();
18
+ return `/${match}/`;
19
+ }
20
+ // ---------------------------------------------------------------------------
21
+ // OpenCode Translator
22
+ // ---------------------------------------------------------------------------
23
+ /**
24
+ * Translates intent-based hooks into an OpenCode plugin file.
25
+ *
26
+ * OpenCode constraints:
27
+ * - All hooks must merge into a single .ts plugin file
28
+ * - Plugin exports an async factory function that returns a hook object
29
+ * - Hooks are keys in the returned object (e.g. "tool.execute.before")
30
+ * - Each hook is an async function(input, output) that modifies output in-place
31
+ * - No explicit block mechanism for tool.execute.before (partial support)
32
+ */
33
+ export class OpenCodeTranslator {
34
+ translate(intents, rawHooks, extendHooks, toolName) {
35
+ const warnings = [];
36
+ const skipped = [];
37
+ // Collect all hook bodies keyed by OpenCode hook name
38
+ const hookBodies = new Map();
39
+ // Track intent-generated hooks for conflict detection
40
+ const intentGeneratedHooks = new Set();
41
+ // --- inject intents ---
42
+ const injectIntents = intents.filter((i) => i.type === 'inject');
43
+ if (injectIntents.length > 0) {
44
+ const hookName = 'experimental.chat.messages.transform';
45
+ if (rawHooks.has(`opencode::${hookName}`)) {
46
+ warnings.push(`[opencode] raw hook for ${hookName} overrides inject intent.`);
47
+ }
48
+ else {
49
+ const body = this.buildInjectHookBody(injectIntents);
50
+ this.addHookBody(hookBodies, hookName, body);
51
+ intentGeneratedHooks.add(hookName);
52
+ }
53
+ // compaction → experimental.session.compacting
54
+ const compactions = injectIntents.filter((i) => i.compaction);
55
+ if (compactions.length > 0) {
56
+ const compactHook = 'experimental.session.compacting';
57
+ if (rawHooks.has(`opencode::${compactHook}`)) {
58
+ warnings.push(`[opencode] raw hook for ${compactHook} overrides inject.compaction intent.`);
59
+ }
60
+ else {
61
+ const combined = compactions.map((i) => i.compaction).join('\\n\\n');
62
+ const body = ` output.context.push(\`${combined}\`);`;
63
+ this.addHookBody(hookBodies, compactHook, body);
64
+ intentGeneratedHooks.add(compactHook);
65
+ }
66
+ }
67
+ warnings.push(`[opencode] inject relies on experimental.chat.messages.transform which is marked experimental and may change.`);
68
+ }
69
+ // --- beforeToolCall intents ---
70
+ const beforeIntents = intents.filter((i) => i.type === 'beforeToolCall');
71
+ if (beforeIntents.length > 0) {
72
+ const hookName = 'tool.execute.before';
73
+ if (rawHooks.has(`opencode::${hookName}`)) {
74
+ warnings.push(`[opencode] raw hook for ${hookName} overrides beforeToolCall intent.`);
75
+ }
76
+ else {
77
+ const body = this.buildBeforeToolCallBody(beforeIntents);
78
+ this.addHookBody(hookBodies, hookName, body);
79
+ intentGeneratedHooks.add(hookName);
80
+ if (beforeIntents.some((i) => true)) {
81
+ warnings.push(`[opencode] beforeToolCall.block: OpenCode's tool.execute.before has no explicit block mechanism. ` +
82
+ `Blocking is simulated by clearing tool arguments, which may produce inconsistent behavior.`);
83
+ }
84
+ }
85
+ }
86
+ // --- afterToolCall intents ---
87
+ const afterIntents = intents.filter((i) => i.type === 'afterToolCall');
88
+ if (afterIntents.length > 0) {
89
+ const hookName = 'tool.execute.after';
90
+ if (rawHooks.has(`opencode::${hookName}`)) {
91
+ warnings.push(`[opencode] raw hook for ${hookName} overrides afterToolCall intent.`);
92
+ }
93
+ else {
94
+ const body = this.buildAfterToolCallBody(afterIntents);
95
+ this.addHookBody(hookBodies, hookName, body);
96
+ intentGeneratedHooks.add(hookName);
97
+ }
98
+ }
99
+ // --- onSession intents ---
100
+ const sessionIntents = intents.filter((i) => i.type === 'onSession');
101
+ if (sessionIntents.length > 0) {
102
+ const hookName = 'event';
103
+ if (rawHooks.has(`opencode::${hookName}`)) {
104
+ warnings.push(`[opencode] raw hook for ${hookName} overrides onSession intent.`);
105
+ }
106
+ else {
107
+ const body = this.buildSessionBody(sessionIntents);
108
+ this.addHookBody(hookBodies, hookName, body);
109
+ intentGeneratedHooks.add(hookName);
110
+ }
111
+ }
112
+ // --- onPermission intents ---
113
+ const permIntents = intents.filter((i) => i.type === 'onPermission');
114
+ if (permIntents.length > 0) {
115
+ const hookName = 'permission.ask';
116
+ if (rawHooks.has(`opencode::${hookName}`)) {
117
+ warnings.push(`[opencode] raw hook for ${hookName} overrides onPermission intent.`);
118
+ }
119
+ else {
120
+ const body = this.buildPermissionBody(permIntents);
121
+ this.addHookBody(hookBodies, hookName, body);
122
+ intentGeneratedHooks.add(hookName);
123
+ }
124
+ }
125
+ // --- Apply extend hooks ---
126
+ for (const hookName of hookBodies.keys()) {
127
+ const key = `opencode::${hookName}`;
128
+ const extends_ = extendHooks.get(key);
129
+ if (extends_ && extends_.length > 0) {
130
+ for (const ext of extends_) {
131
+ this.addHookBody(hookBodies, hookName, ` // --- extend ---\n${ext.handler}`);
132
+ }
133
+ }
134
+ }
135
+ // --- Raw hooks: merge directly ---
136
+ for (const [key, reg] of rawHooks) {
137
+ if (!key.startsWith('opencode::'))
138
+ continue;
139
+ const hookName = key.split('::')[1];
140
+ if (intentGeneratedHooks.has(hookName)) {
141
+ warnings.push(`[opencode] raw hook for ${hookName} replaces intent-generated hook.`);
142
+ hookBodies.delete(hookName);
143
+ }
144
+ this.addHookBody(hookBodies, hookName, reg.handler);
145
+ }
146
+ // --- Generate the single plugin file ---
147
+ const files = {};
148
+ if (hookBodies.size > 0) {
149
+ files[`${toolName}-plugin.ts`] = this.buildPluginFile(toolName, hookBodies);
150
+ }
151
+ return { files, warnings, skipped };
152
+ }
153
+ getSettingsEntries() {
154
+ // OpenCode doesn't use settings.json for hooks
155
+ return [];
156
+ }
157
+ // -----------------------------------------------------------------------
158
+ // Private helpers
159
+ // -----------------------------------------------------------------------
160
+ addHookBody(map, hookName, body) {
161
+ const existing = map.get(hookName) ?? [];
162
+ existing.push(body);
163
+ map.set(hookName, existing);
164
+ }
165
+ buildInjectHookBody(intents) {
166
+ const perTurnParts = intents.map((i) => i.perTurn);
167
+ const sessionStartParts = intents.filter((i) => i.sessionStart).map((i) => i.sessionStart);
168
+ const hasSessionStart = sessionStartParts.length > 0;
169
+ const perTurnCombined = perTurnParts.join('\\n\\n');
170
+ const sessionStartCombined = hasSessionStart
171
+ ? [...sessionStartParts, ...perTurnParts].join('\\n\\n')
172
+ : perTurnCombined;
173
+ return ` const messages = output.messages;
174
+ if (!messages || messages.length === 0) return;
175
+
176
+ const sessionID = messages[0]?.info?.sessionID;
177
+ const isNewSession = sessionID && !_seenSessions.has(sessionID);
178
+ if (sessionID) _seenSessions.add(sessionID);
179
+
180
+ const reminder = isNewSession
181
+ ? \`${sessionStartCombined}\`
182
+ : \`${perTurnCombined}\`;
183
+
184
+ for (let i = messages.length - 1; i >= 0; i--) {
185
+ if (messages[i].info?.role === "user") {
186
+ messages[i].parts.push({ type: "text", text: reminder });
187
+ break;
188
+ }
189
+ }`;
190
+ }
191
+ buildBeforeToolCallBody(intents) {
192
+ const cases = intents.map((intent, i) => {
193
+ const regex = matcherToRegex(intent.match);
194
+ return ` // beforeToolCall intent #${i + 1}
195
+ if (${regex}.test(output.toolName || "")) {
196
+ // Handler evaluated at runtime via agent-kit
197
+ }`;
198
+ });
199
+ return cases.join('\n\n');
200
+ }
201
+ buildAfterToolCallBody(intents) {
202
+ const cases = intents.map((intent, i) => {
203
+ const regex = matcherToRegex(intent.match);
204
+ return ` // afterToolCall observer #${i + 1}
205
+ if (${regex}.test(output.toolName || "")) {
206
+ // Observer evaluated at runtime via agent-kit
207
+ }`;
208
+ });
209
+ return cases.join('\n\n');
210
+ }
211
+ buildSessionBody(intents) {
212
+ return ` const eventType = output.type || "";
213
+ if (eventType === "session.start") {
214
+ // onSession.start handlers
215
+ } else if (eventType === "session.end") {
216
+ // onSession.end handlers
217
+ }`;
218
+ }
219
+ buildPermissionBody(intents) {
220
+ const cases = intents.map((intent, i) => {
221
+ const regex = matcherToRegex(intent.match);
222
+ return ` // onPermission handler #${i + 1}
223
+ if (${regex}.test(output.toolName || "")) {
224
+ // Permission decision evaluated at runtime via agent-kit
225
+ }`;
226
+ });
227
+ return cases.join('\n\n');
228
+ }
229
+ buildPluginFile(toolName, hookBodies) {
230
+ const exportName = toPascalCase(toolName) + 'Plugin';
231
+ const hookEntries = Array.from(hookBodies.entries())
232
+ .map(([hookName, bodies]) => {
233
+ const combinedBody = bodies.join('\n\n');
234
+ return ` "${hookName}": async (_input: unknown, output: any) => {
235
+ ${combinedBody}
236
+ }`;
237
+ })
238
+ .join(',\n\n');
239
+ return `/**
240
+ * ${capitalize(toolName)} Plugin for OpenCode
241
+ * Generated by @s_s/agent-kit
242
+ */
243
+
244
+ const _seenSessions = new Set<string>();
245
+
246
+ export const ${exportName} = async () => {
247
+ return {
248
+ ${hookEntries}
249
+ };
250
+ };
251
+ `;
252
+ }
253
+ }
254
+ //# sourceMappingURL=opencode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../src/hook-translators/opencode.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ import type { HookIntent, RawHookRegistration, ExtendHookRegistration } from '../hook-types.js';
2
+ import type { SkippedIntent } from '../types.js';
3
+ /**
4
+ * Result of translating intents into native hook files for a specific agent.
5
+ */
6
+ export interface TranslationResult {
7
+ /** Map of filename → file content to write to the hook directory. */
8
+ files: Record<string, string>;
9
+ /** Warnings about degradation, conflicts, or partial support. */
10
+ warnings: string[];
11
+ /** Intents that were completely skipped (unsupported by this agent). */
12
+ skipped: SkippedIntent[];
13
+ }
14
+ /**
15
+ * Describes a settings.json hook entry to merge.
16
+ * Used by agents that need hook config in a central settings file (Claude Code, Codex).
17
+ */
18
+ export interface SettingsHookEntry {
19
+ /** Native hook event name (e.g. 'UserPromptSubmit', 'PreToolUse'). */
20
+ event: string;
21
+ /** Regex matcher string. Empty string matches all. */
22
+ matcher: string;
23
+ /** Handler type and command/URL. */
24
+ hook: {
25
+ type: 'command';
26
+ command: string;
27
+ };
28
+ }
29
+ /**
30
+ * Translates intent-based hook declarations into native hook files for a specific agent.
31
+ *
32
+ * Each agent has its own translator implementation that understands:
33
+ * - How to map intents to native hook event names
34
+ * - How to generate handler code (shell scripts, TypeScript plugins, etc.)
35
+ * - How to merge multiple intents targeting the same native hook
36
+ * - How to apply raw overrides and extend augmentations
37
+ * - What capabilities are partially or fully unsupported
38
+ */
39
+ export interface AgentHookTranslator {
40
+ /**
41
+ * Translate all registered hook declarations into native files.
42
+ *
43
+ * @param intents - All registered intents from the hook registry.
44
+ * @param rawHooks - Raw hook registrations for this agent.
45
+ * @param extendHooks - Extend hook registrations for this agent.
46
+ * @param toolName - The registered tool name (used for file naming, markers, etc.)
47
+ * @returns Translation result with files, warnings, and skipped intents.
48
+ */
49
+ translate(intents: readonly HookIntent[], rawHooks: ReadonlyMap<string, RawHookRegistration>, extendHooks: ReadonlyMap<string, readonly ExtendHookRegistration[]>, toolName: string): TranslationResult;
50
+ /**
51
+ * Get settings entries that need to be merged into the agent's settings file.
52
+ * Only applicable for agents that use a central settings file (Claude Code, Codex).
53
+ * Returns empty array for agents that don't need settings.json updates.
54
+ *
55
+ * @param hookDir - The directory where hook files are written.
56
+ * @param toolName - The registered tool name.
57
+ */
58
+ getSettingsEntries(hookDir: string, toolName: string): SettingsHookEntry[];
59
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/hook-translators/types.ts"],"names":[],"mappings":""}