@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,155 @@
1
+ import type { AgentType } from './types.js';
2
+ /**
3
+ * Content injection intent.
4
+ * Injects text into agent context at various lifecycle points.
5
+ */
6
+ export interface InjectIntent {
7
+ type: 'inject';
8
+ /** Reminder injected on every user message turn. */
9
+ perTurn: string;
10
+ /** Reminder injected at session start. */
11
+ sessionStart?: string;
12
+ /** Reminder injected before context compaction. */
13
+ compaction?: string;
14
+ /** Reminder injected at session end. */
15
+ sessionEnd?: string;
16
+ }
17
+ /**
18
+ * Tool call interception result.
19
+ */
20
+ export interface ToolCallInterceptResult {
21
+ /** Block the tool call entirely. */
22
+ block?: boolean;
23
+ /** Reason for blocking (shown to agent). */
24
+ reason?: string;
25
+ /** Modified arguments to pass to the tool (if not blocking). */
26
+ args?: Record<string, unknown>;
27
+ }
28
+ /**
29
+ * Tool call context passed to handler.
30
+ */
31
+ export interface ToolCallContext {
32
+ toolName: string;
33
+ args: Record<string, unknown>;
34
+ }
35
+ /**
36
+ * Pre-tool-call interception intent.
37
+ * Intercept tool calls before execution — can block or modify arguments.
38
+ */
39
+ export interface BeforeToolCallIntent {
40
+ type: 'beforeToolCall';
41
+ /** Regex pattern to match tool names. Omit or '*' to match all. */
42
+ match?: RegExp | string;
43
+ /** Handler that decides whether to block or modify the tool call. */
44
+ handler: (ctx: ToolCallContext) => ToolCallInterceptResult | void;
45
+ }
46
+ /**
47
+ * Tool call observation context.
48
+ */
49
+ export interface ToolCallObserveContext {
50
+ toolName: string;
51
+ args: Record<string, unknown>;
52
+ result: string;
53
+ error?: string;
54
+ }
55
+ /**
56
+ * Post-tool-call observation intent.
57
+ * Observe tool call results — cannot modify, only react.
58
+ */
59
+ export interface AfterToolCallIntent {
60
+ type: 'afterToolCall';
61
+ /** Regex pattern to match tool names. Omit or '*' to match all. */
62
+ match?: RegExp | string;
63
+ /** Handler that reacts to tool call completion. */
64
+ handler: (ctx: ToolCallObserveContext) => void;
65
+ }
66
+ /**
67
+ * Session lifecycle context.
68
+ */
69
+ export interface SessionContext {
70
+ sessionId?: string;
71
+ }
72
+ /**
73
+ * Session lifecycle intent.
74
+ * React to session start and/or end.
75
+ */
76
+ export interface OnSessionIntent {
77
+ type: 'onSession';
78
+ /** Handler called when session starts. */
79
+ start?: (ctx: SessionContext) => void;
80
+ /** Handler called when session ends. */
81
+ end?: (ctx: SessionContext) => void;
82
+ }
83
+ /**
84
+ * Permission decision.
85
+ */
86
+ export type PermissionDecision = 'allow' | 'deny' | 'ask';
87
+ /**
88
+ * Permission request context.
89
+ */
90
+ export interface PermissionContext {
91
+ toolName: string;
92
+ args: Record<string, unknown>;
93
+ }
94
+ /**
95
+ * Permission decision intent.
96
+ * Intercept permission requests and decide allow/deny/ask.
97
+ */
98
+ export interface OnPermissionIntent {
99
+ type: 'onPermission';
100
+ /** Regex pattern to match tool names. Omit or '*' to match all. */
101
+ match?: RegExp | string;
102
+ /** Handler that decides the permission outcome. */
103
+ handler: (ctx: PermissionContext) => PermissionDecision;
104
+ }
105
+ /**
106
+ * Union of all intent types.
107
+ */
108
+ export type HookIntent = InjectIntent | BeforeToolCallIntent | AfterToolCallIntent | OnSessionIntent | OnPermissionIntent;
109
+ /**
110
+ * Discriminant values for intent types.
111
+ */
112
+ export type IntentType = HookIntent['type'];
113
+ /** Claude Code / Codex native hook event names. */
114
+ export type ClaudeCodeHookName = 'SessionStart' | 'InstructionsLoaded' | 'UserPromptSubmit' | 'PreToolUse' | 'PermissionRequest' | 'PostToolUse' | 'PostToolUseFailure' | 'Notification' | 'SubagentStart' | 'SubagentStop' | 'Stop' | 'TeammateIdle' | 'TaskCompleted' | 'ConfigChange' | 'WorktreeCreate' | 'WorktreeRemove' | 'PreCompact' | 'PostCompact' | 'Elicitation' | 'ElicitationResult' | 'SessionEnd';
115
+ /** OpenCode native hook names. */
116
+ export type OpenCodeHookName = 'event' | 'config' | 'tool' | 'auth' | 'chat.message' | 'chat.params' | 'chat.headers' | 'permission.ask' | 'command.execute.before' | 'tool.execute.before' | 'shell.env' | 'tool.execute.after' | 'experimental.chat.messages.transform' | 'experimental.chat.system.transform' | 'experimental.session.compacting' | 'experimental.text.complete' | 'tool.definition';
117
+ /** OpenClaw plugin hook names (24). */
118
+ export type OpenClawPluginHookName = 'before_model_resolve' | 'before_prompt_build' | 'before_agent_start' | 'llm_input' | 'llm_output' | 'agent_end' | 'before_compaction' | 'after_compaction' | 'before_reset' | 'message_received' | 'message_sending' | 'message_sent' | 'before_tool_call' | 'after_tool_call' | 'tool_result_persist' | 'before_message_write' | 'session_start' | 'session_end' | 'subagent_spawning' | 'subagent_delivery_target' | 'subagent_spawned' | 'subagent_ended' | 'gateway_start' | 'gateway_stop';
119
+ /** OpenClaw internal hook names (type:action). */
120
+ export type OpenClawInternalHookName = 'command:new' | 'command:reset' | 'command:stop' | 'session:compact:before' | 'session:compact:after' | 'agent:bootstrap' | 'gateway:startup' | 'message:received' | 'message:sent' | 'message:transcribed' | 'message:preprocessed';
121
+ /** All OpenClaw hook names (plugin + internal). */
122
+ export type OpenClawHookName = OpenClawPluginHookName | OpenClawInternalHookName;
123
+ /** Map from agent type to its native hook name union. */
124
+ export type NativeHookNameMap = {
125
+ 'claude-code': ClaudeCodeHookName;
126
+ codex: ClaudeCodeHookName;
127
+ opencode: OpenCodeHookName;
128
+ openclaw: OpenClawHookName;
129
+ };
130
+ /**
131
+ * Raw hook registration.
132
+ * Provides the handler code (as string) for a specific agent's native hook.
133
+ * When a raw hook targets the same native hook as an intent, raw wins.
134
+ */
135
+ export interface RawHookRegistration<A extends AgentType = AgentType> {
136
+ agent: A;
137
+ hookName: A extends keyof NativeHookNameMap ? NativeHookNameMap[A] : string;
138
+ /** Handler code as string — will be written directly into the generated file. */
139
+ handler: string;
140
+ /** Optional matcher (regex string). Only used by agents that support it. */
141
+ matcher?: string;
142
+ }
143
+ /**
144
+ * Extend hook registration.
145
+ * Runs after the intent-generated handler for the same native hook.
146
+ * Cannot replace, only augment.
147
+ */
148
+ export interface ExtendHookRegistration<A extends AgentType = AgentType> {
149
+ agent: A;
150
+ hookName: A extends keyof NativeHookNameMap ? NativeHookNameMap[A] : string;
151
+ /** Extension code as string — appended to the intent-generated handler. */
152
+ handler: string;
153
+ /** Optional matcher (regex string). Only used by agents that support it. */
154
+ matcher?: string;
155
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=hook-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hook-types.js","sourceRoot":"","sources":["../src/hook-types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,30 @@
1
+ import type { AgentType, HookInstallResult } from './types.js';
2
+ /**
3
+ * Install hooks for the given agent type.
4
+ *
5
+ * Reads all registered intents, raw hooks, and extend hooks from the hook
6
+ * registry. Translates them into native hook files using the agent-specific
7
+ * translator. Runs degradation checks and conflict detection.
8
+ *
9
+ * @internal — called by the Kit object returned from createKit().
10
+ */
11
+ export declare function installHooks(name: string, agent: AgentType): Promise<HookInstallResult>;
12
+ /**
13
+ * Uninstall hooks for the given agent type.
14
+ *
15
+ * Removes hook files from the hook directory and cleans up settings.json
16
+ * entries for agents that use them (Claude Code, Codex).
17
+ *
18
+ * @internal — called by the Kit object returned from createKit().
19
+ */
20
+ export declare function uninstallHooks(name: string, agent: AgentType): Promise<{
21
+ success: boolean;
22
+ removed: string[];
23
+ error?: string;
24
+ }>;
25
+ /**
26
+ * Check if hooks are already installed for the given agent type.
27
+ *
28
+ * @internal — called by the Kit object returned from createKit().
29
+ */
30
+ export declare function hasHooksInstalled(name: string, agent: AgentType): Promise<boolean>;
package/build/hooks.js ADDED
@@ -0,0 +1,333 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import os from 'node:os';
4
+ import { execFile } from 'node:child_process';
5
+ import { promisify } from 'node:util';
6
+ import { AGENT_REGISTRY } from './types.js';
7
+ import { getIntents, getRawHooks, getExtendHooks } from './hook-registry.js';
8
+ import { checkAllDegradation } from './hook-capabilities.js';
9
+ import { ClaudeCodeTranslator } from './hook-translators/claude-code.js';
10
+ import { OpenCodeTranslator } from './hook-translators/opencode.js';
11
+ import { OpenClawTranslator } from './hook-translators/openclaw.js';
12
+ const execFileAsync = promisify(execFile);
13
+ // ---------------------------------------------------------------------------
14
+ // Translator factory
15
+ // ---------------------------------------------------------------------------
16
+ function getTranslator(agent) {
17
+ switch (agent) {
18
+ case 'claude-code':
19
+ return new ClaudeCodeTranslator('claude-code');
20
+ case 'codex':
21
+ return new ClaudeCodeTranslator('codex');
22
+ case 'opencode':
23
+ return new OpenCodeTranslator();
24
+ case 'openclaw':
25
+ return new OpenClawTranslator();
26
+ }
27
+ }
28
+ // ---------------------------------------------------------------------------
29
+ // installHooks — main entry point
30
+ // ---------------------------------------------------------------------------
31
+ /**
32
+ * Install hooks for the given agent type.
33
+ *
34
+ * Reads all registered intents, raw hooks, and extend hooks from the hook
35
+ * registry. Translates them into native hook files using the agent-specific
36
+ * translator. Runs degradation checks and conflict detection.
37
+ *
38
+ * @internal — called by the Kit object returned from createKit().
39
+ */
40
+ export async function installHooks(name, agent) {
41
+ const home = os.homedir();
42
+ const entry = AGENT_REGISTRY[agent];
43
+ const hookDir = entry.getHookDir(home, name);
44
+ const result = {
45
+ success: false,
46
+ hookDir,
47
+ filesWritten: [],
48
+ settingsUpdated: false,
49
+ notes: [],
50
+ warnings: [],
51
+ skipped: [],
52
+ };
53
+ const intents = getIntents();
54
+ const rawHooks = getRawHooks();
55
+ const extendHooks = getExtendHooks();
56
+ // Check if there's anything to install
57
+ if (intents.length === 0 && rawHooks.size === 0 && extendHooks.size === 0) {
58
+ result.error =
59
+ 'No hooks registered. Use hooks.inject(), hooks.beforeToolCall(), etc. to declare hook behavior.';
60
+ return result;
61
+ }
62
+ try {
63
+ // Step 1: Run degradation checks
64
+ const intentTypes = [...new Set(intents.map((i) => i.type))];
65
+ const degradations = checkAllDegradation(agent, intentTypes);
66
+ for (const d of degradations) {
67
+ if (d.level === 'unsupported') {
68
+ result.warnings.push(d.message);
69
+ }
70
+ else if (d.level === 'partial') {
71
+ result.warnings.push(d.message);
72
+ }
73
+ }
74
+ // Step 2: Filter raw/extend hooks for this agent
75
+ const agentRawHooks = new Map();
76
+ for (const [key, reg] of rawHooks) {
77
+ if (key.startsWith(`${agent}::`)) {
78
+ agentRawHooks.set(key, reg);
79
+ }
80
+ }
81
+ const agentExtendHooks = new Map();
82
+ for (const [key, regs] of extendHooks) {
83
+ if (key.startsWith(`${agent}::`)) {
84
+ agentExtendHooks.set(key, regs);
85
+ }
86
+ }
87
+ // Step 3: Translate intents → native files
88
+ const translator = getTranslator(agent);
89
+ const translation = translator.translate(intents, agentRawHooks, agentExtendHooks, name);
90
+ // Merge translation warnings and skipped
91
+ result.warnings.push(...translation.warnings);
92
+ result.skipped.push(...translation.skipped);
93
+ // Step 4: Write hook files
94
+ if (Object.keys(translation.files).length === 0) {
95
+ result.notes.push('No hook files generated for this agent.');
96
+ result.success = true;
97
+ return result;
98
+ }
99
+ await fs.mkdir(hookDir, { recursive: true });
100
+ for (const [fileName, content] of Object.entries(translation.files)) {
101
+ const filePath = path.join(hookDir, fileName);
102
+ await fs.writeFile(filePath, content, 'utf-8');
103
+ if (fileName.endsWith('.sh')) {
104
+ await fs.chmod(filePath, 0o755);
105
+ }
106
+ result.filesWritten.push(filePath);
107
+ }
108
+ // Step 5: Merge settings.json for agents that need it (Claude Code / Codex)
109
+ if (entry.getSettingsPath) {
110
+ const settingsPath = entry.getSettingsPath(home);
111
+ const shellFiles = Object.keys(translation.files).filter((f) => f.endsWith('.sh'));
112
+ if (shellFiles.length > 0) {
113
+ await mergeHookSettings(settingsPath, hookDir, shellFiles, name);
114
+ result.settingsUpdated = true;
115
+ }
116
+ }
117
+ // Step 6: Agent-specific post-install
118
+ if (agent === 'openclaw') {
119
+ try {
120
+ await execFileAsync('openclaw', ['hooks', 'enable', name]);
121
+ result.notes.push(`Hook activated via \`openclaw hooks enable ${name}\`.`);
122
+ }
123
+ catch {
124
+ result.notes.push(`Run \`openclaw hooks enable ${name}\` to activate the hook.`);
125
+ }
126
+ }
127
+ result.success = true;
128
+ }
129
+ catch (err) {
130
+ result.error = err instanceof Error ? err.message : String(err);
131
+ }
132
+ return result;
133
+ }
134
+ // ---------------------------------------------------------------------------
135
+ // uninstallHooks
136
+ // ---------------------------------------------------------------------------
137
+ /**
138
+ * Uninstall hooks for the given agent type.
139
+ *
140
+ * Removes hook files from the hook directory and cleans up settings.json
141
+ * entries for agents that use them (Claude Code, Codex).
142
+ *
143
+ * @internal — called by the Kit object returned from createKit().
144
+ */
145
+ export async function uninstallHooks(name, agent) {
146
+ const home = os.homedir();
147
+ const entry = AGENT_REGISTRY[agent];
148
+ const hookDir = entry.getHookDir(home, name);
149
+ const removed = [];
150
+ try {
151
+ // Remove hook directory
152
+ try {
153
+ const files = await fs.readdir(hookDir);
154
+ for (const file of files) {
155
+ const filePath = path.join(hookDir, file);
156
+ await fs.unlink(filePath);
157
+ removed.push(filePath);
158
+ }
159
+ await fs.rmdir(hookDir);
160
+ }
161
+ catch {
162
+ // Directory may not exist — that's fine
163
+ }
164
+ // Clean settings.json for Claude Code / Codex
165
+ if (entry.getSettingsPath) {
166
+ const settingsPath = entry.getSettingsPath(home);
167
+ await cleanHookSettings(settingsPath, name);
168
+ }
169
+ // Deactivate for OpenClaw
170
+ if (agent === 'openclaw') {
171
+ try {
172
+ await execFileAsync('openclaw', ['hooks', 'disable', name]);
173
+ }
174
+ catch {
175
+ // Best effort
176
+ }
177
+ }
178
+ return { success: true, removed };
179
+ }
180
+ catch (err) {
181
+ return { success: false, removed, error: err instanceof Error ? err.message : String(err) };
182
+ }
183
+ }
184
+ // ---------------------------------------------------------------------------
185
+ // hasHooksInstalled
186
+ // ---------------------------------------------------------------------------
187
+ /**
188
+ * Check if hooks are already installed for the given agent type.
189
+ *
190
+ * @internal — called by the Kit object returned from createKit().
191
+ */
192
+ export async function hasHooksInstalled(name, agent) {
193
+ const home = os.homedir();
194
+ const entry = AGENT_REGISTRY[agent];
195
+ const hookDir = entry.getHookDir(home, name);
196
+ try {
197
+ const files = await fs.readdir(hookDir);
198
+ return files.length > 0;
199
+ }
200
+ catch {
201
+ return false;
202
+ }
203
+ }
204
+ // ---------------------------------------------------------------------------
205
+ // Settings merge (Claude Code / Codex)
206
+ // ---------------------------------------------------------------------------
207
+ /**
208
+ * Merge hook entries into settings.json for Claude Code / Codex.
209
+ * Maps each shell script to its corresponding native hook event based on filename conventions.
210
+ */
211
+ async function mergeHookSettings(settingsPath, hookDir, shellFiles, toolName) {
212
+ let settings = {};
213
+ try {
214
+ const raw = await fs.readFile(settingsPath, 'utf-8');
215
+ settings = JSON.parse(raw);
216
+ }
217
+ catch {
218
+ // Start fresh
219
+ }
220
+ if (!settings.hooks || typeof settings.hooks !== 'object') {
221
+ settings.hooks = {};
222
+ }
223
+ const hooks = settings.hooks;
224
+ // Map filename patterns to native hook events
225
+ const fileToEvent = {
226
+ inject: 'UserPromptSubmit',
227
+ 'session-start': 'SessionStart',
228
+ 'session-end': 'SessionEnd',
229
+ compaction: 'PreCompact',
230
+ 'before-tool': 'PreToolUse',
231
+ 'after-tool': 'PostToolUse',
232
+ 'on-session-start': 'SessionStart',
233
+ 'on-session-end': 'SessionEnd',
234
+ permission: 'PermissionRequest',
235
+ };
236
+ for (const fileName of shellFiles) {
237
+ const activatorPath = path.join(hookDir, fileName);
238
+ // Determine the event from filename
239
+ let event;
240
+ // Check raw hooks first (pattern: toolName-raw-hookname.sh)
241
+ const rawMatch = fileName.match(/^.+-raw-(.+)\.sh$/);
242
+ if (rawMatch) {
243
+ // Raw hooks use the hook name directly (case-insensitive lookup)
244
+ event = rawMatch[1].charAt(0).toUpperCase() + rawMatch[1].slice(1);
245
+ }
246
+ else {
247
+ // Intent-generated hooks use filename conventions
248
+ for (const [pattern, hookEvent] of Object.entries(fileToEvent)) {
249
+ if (fileName.includes(pattern)) {
250
+ event = hookEvent;
251
+ break;
252
+ }
253
+ }
254
+ }
255
+ if (!event)
256
+ continue;
257
+ const hookEntry = {
258
+ matcher: '',
259
+ hooks: [{ type: 'command', command: activatorPath }],
260
+ };
261
+ if (!Array.isArray(hooks[event])) {
262
+ hooks[event] = [];
263
+ }
264
+ // Remove existing entries for this tool
265
+ hooks[event] = hooks[event].filter((entry) => {
266
+ if (!entry || typeof entry !== 'object')
267
+ return true;
268
+ const e = entry;
269
+ if (!Array.isArray(e.hooks))
270
+ return true;
271
+ return !e.hooks.some((h) => {
272
+ if (!h || typeof h !== 'object')
273
+ return false;
274
+ const hook = h;
275
+ return typeof hook.command === 'string' && hook.command.includes(toolName);
276
+ });
277
+ });
278
+ hooks[event].push(hookEntry);
279
+ }
280
+ await fs.mkdir(path.dirname(settingsPath), { recursive: true });
281
+ await fs.writeFile(settingsPath, JSON.stringify(settings, null, 2) + '\n', 'utf-8');
282
+ }
283
+ /**
284
+ * Remove all hook entries for a tool from settings.json.
285
+ */
286
+ async function cleanHookSettings(settingsPath, toolName) {
287
+ let settings;
288
+ try {
289
+ const raw = await fs.readFile(settingsPath, 'utf-8');
290
+ settings = JSON.parse(raw);
291
+ }
292
+ catch {
293
+ return; // No settings file to clean
294
+ }
295
+ if (!settings.hooks || typeof settings.hooks !== 'object')
296
+ return;
297
+ const hooks = settings.hooks;
298
+ let changed = false;
299
+ for (const [event, entries] of Object.entries(hooks)) {
300
+ if (!Array.isArray(entries))
301
+ continue;
302
+ const filtered = entries.filter((entry) => {
303
+ if (!entry || typeof entry !== 'object')
304
+ return true;
305
+ const e = entry;
306
+ if (!Array.isArray(e.hooks))
307
+ return true;
308
+ const hasToolHook = e.hooks.some((h) => {
309
+ if (!h || typeof h !== 'object')
310
+ return false;
311
+ const hook = h;
312
+ return typeof hook.command === 'string' && hook.command.includes(toolName);
313
+ });
314
+ return !hasToolHook;
315
+ });
316
+ if (filtered.length !== entries.length) {
317
+ hooks[event] = filtered;
318
+ changed = true;
319
+ }
320
+ // Remove empty event arrays
321
+ if (filtered.length === 0) {
322
+ delete hooks[event];
323
+ }
324
+ }
325
+ // Remove empty hooks object
326
+ if (Object.keys(hooks).length === 0) {
327
+ delete settings.hooks;
328
+ }
329
+ if (changed) {
330
+ await fs.writeFile(settingsPath, JSON.stringify(settings, null, 2) + '\n', 'utf-8');
331
+ }
332
+ }
333
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export { createKit } from './create-kit.js';
2
+ export type { AgentType, StorageScope, ScopeOptions, KitOptions, Kit, HookInstallResult, SkippedIntent, } from './types.js';
3
+ export { AGENT_TYPES, CLIENT_NAME_MAP } from './types.js';
4
+ export type { InjectIntent, BeforeToolCallIntent, AfterToolCallIntent, OnSessionIntent, OnPermissionIntent, HookIntent, IntentType, ToolCallContext, ToolCallInterceptResult, ToolCallObserveContext, SessionContext, PermissionDecision, PermissionContext, RawHookRegistration, ExtendHookRegistration, } from './hook-types.js';
5
+ export type { SupportLevel, CapabilityEntry, DegradationWarning } from './hook-capabilities.js';
6
+ export { CAPABILITY_MATRIX, checkDegradation, checkAllDegradation, isIntentFullyUnsupported, } from './hook-capabilities.js';
7
+ export { detectProjectRoot } from './platform.js';
8
+ export { detectAgent, detectAgentFromClient } from './detect.js';
9
+ export { hooks } from './hook-registry.js';
package/build/index.js ADDED
@@ -0,0 +1,11 @@
1
+ // Core factory
2
+ export { createKit } from './create-kit.js';
3
+ export { AGENT_TYPES, CLIENT_NAME_MAP } from './types.js';
4
+ export { CAPABILITY_MATRIX, checkDegradation, checkAllDegradation, isIntentFullyUnsupported, } from './hook-capabilities.js';
5
+ // Platform (only detectProjectRoot is standalone; getDataDir is on Kit)
6
+ export { detectProjectRoot } from './platform.js';
7
+ // Detection
8
+ export { detectAgent, detectAgentFromClient } from './detect.js';
9
+ // Hooks — declaration API (global, not bound to kit instance)
10
+ export { hooks } from './hook-registry.js';
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,eAAe;AACf,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAY5C,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAuB1D,OAAO,EACH,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,EACnB,wBAAwB,GAC3B,MAAM,wBAAwB,CAAC;AAEhC,wEAAwE;AACxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAElD,YAAY;AACZ,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEjE,8DAA8D;AAC9D,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { ResolvedKitConfig, ScopeOptions } from './types.js';
2
+ /**
3
+ * Get platform-appropriate data directory path.
4
+ *
5
+ * - global: follows platform conventions (macOS ~/Library/Application Support, Linux XDG, Windows APPDATA)
6
+ * - project: `<projectRoot>/.<name>` (or custom dir name)
7
+ *
8
+ * @internal — called by the Kit object returned from createKit().
9
+ */
10
+ export declare function getDataDir(config: ResolvedKitConfig, options?: ScopeOptions): string;
11
+ /**
12
+ * Detect project root directory.
13
+ *
14
+ * Resolution order: git root > project marker files (.git, package.json, etc.) > cwd fallback.
15
+ * This is an independent function — does not require createKit().
16
+ */
17
+ export declare function detectProjectRoot(cwd?: string): Promise<string>;
@@ -0,0 +1,79 @@
1
+ import path from 'node:path';
2
+ import os from 'node:os';
3
+ import fs from 'node:fs/promises';
4
+ import { execFile } from 'node:child_process';
5
+ import { promisify } from 'node:util';
6
+ const execFileAsync = promisify(execFile);
7
+ const PROJECT_ROOT_MARKERS = ['.git', 'package.json', 'pyproject.toml', 'Cargo.toml', 'go.mod'];
8
+ /**
9
+ * Get platform-appropriate data directory path.
10
+ *
11
+ * - global: follows platform conventions (macOS ~/Library/Application Support, Linux XDG, Windows APPDATA)
12
+ * - project: `<projectRoot>/.<name>` (or custom dir name)
13
+ *
14
+ * @internal — called by the Kit object returned from createKit().
15
+ */
16
+ export function getDataDir(config, options) {
17
+ const scope = options?.scope ?? 'global';
18
+ if (scope === 'project') {
19
+ if (!options?.projectRoot) {
20
+ throw new Error('getDataDir: projectRoot is required when scope is "project".');
21
+ }
22
+ const dirName = config.dirs?.project ?? `.${config.name}`;
23
+ return path.join(options.projectRoot, dirName);
24
+ }
25
+ // Global scope
26
+ const envVar = config.envOverride ?? `${config.name.toUpperCase().replace(/-/g, '_')}_DATA_DIR`;
27
+ const envDir = process.env[envVar];
28
+ if (envDir)
29
+ return envDir;
30
+ const dirName = config.dirs?.global ?? config.name;
31
+ const home = os.homedir();
32
+ const platform = process.platform;
33
+ switch (platform) {
34
+ case 'darwin':
35
+ return path.join(home, 'Library', 'Application Support', dirName);
36
+ case 'win32':
37
+ return path.join(process.env.APPDATA || path.join(home, 'AppData', 'Roaming'), dirName);
38
+ default:
39
+ return path.join(process.env.XDG_DATA_HOME || path.join(home, '.local', 'share'), dirName);
40
+ }
41
+ }
42
+ /**
43
+ * Detect project root directory.
44
+ *
45
+ * Resolution order: git root > project marker files (.git, package.json, etc.) > cwd fallback.
46
+ * This is an independent function — does not require createKit().
47
+ */
48
+ export async function detectProjectRoot(cwd) {
49
+ const startDir = cwd ?? process.cwd();
50
+ // Try git root first
51
+ try {
52
+ const { stdout } = await execFileAsync('git', ['rev-parse', '--show-toplevel'], { cwd: startDir });
53
+ const gitRoot = stdout.trim();
54
+ if (gitRoot)
55
+ return gitRoot;
56
+ }
57
+ catch {
58
+ // Not a git repo or git not available
59
+ }
60
+ // Walk up looking for project markers
61
+ let current = path.resolve(startDir);
62
+ while (true) {
63
+ for (const marker of PROJECT_ROOT_MARKERS) {
64
+ try {
65
+ await fs.access(path.join(current, marker));
66
+ return current;
67
+ }
68
+ catch {
69
+ continue;
70
+ }
71
+ }
72
+ const parent = path.dirname(current);
73
+ if (parent === current)
74
+ break;
75
+ current = parent;
76
+ }
77
+ return path.resolve(startDir);
78
+ }
79
+ //# sourceMappingURL=platform.js.map