@ev-ai/agent-hook 1.1.3 → 1.1.5

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.
@@ -1,9 +1,10 @@
1
1
  // src/plugin-hooks.ts
2
- import { mkdirSync, writeFileSync } from "node:fs";
2
+ import { chmodSync, copyFileSync, existsSync, mkdirSync, writeFileSync } from "node:fs";
3
3
  import { dirname, join } from "node:path";
4
4
 
5
5
  // src/constants.ts
6
6
  var HOOK_BINARY_NAME = "ev-ai-agent-hook";
7
+ var HOOK_CHECKSUMS_FILE = "SHA256SUMS";
7
8
  var GLOBAL_HOOK_BINARY_RELATIVE = `current/${HOOK_BINARY_NAME}`;
8
9
  var PROJECT_HOOK_BINARY_RELATIVE = `.ev-ai/agent-hook/${HOOK_BINARY_NAME}`;
9
10
  var HOOK_INPUT_ALLOWLIST_MAX_BYTES = 4 * 1024;
@@ -11,21 +12,17 @@ var HOOK_INPUT_FULL_MAX_BYTES = 32 * 1024;
11
12
  var HOOK_INPUT_MCP_MAX_BYTES = 4 * 1024;
12
13
  var GZIP_MIN_BYTES = 32 * 1024;
13
14
  var USER_SPEC_COOLDOWN_MS = 14 * 60 * 60 * 1e3;
14
- var PACKAGE_VERSION = "1.1.3";
15
+ var PACKAGE_VERSION = "1.1.5";
15
16
  var NPX_PACKAGE_SPEC = `@ev-ai/agent-hook@${PACKAGE_VERSION}`;
16
17
  var HOOK_STATUS_MESSAGE = "ev-ai runtime report";
17
18
 
18
19
  // src/install.ts
19
- function npxHookCommand(packageSpec = NPX_PACKAGE_SPEC) {
20
- return `npx -y --prefer-offline ${packageSpec}`;
21
- }
22
- function withRunnerFlag(command, runner) {
23
- const stripped = command.replace(/\s+--runner(?:=|\s+)\S+/g, "").trimEnd();
24
- return `${stripped} --runner ${runner}`;
20
+ function toCommandList(command) {
21
+ return typeof command === "string" ? [command] : command;
25
22
  }
26
23
  function desiredClaudeHookGroups(command) {
27
24
  const commandHook = () => ({
28
- hooks: [{ type: "command", command }]
25
+ hooks: toCommandList(command).map((entry) => ({ type: "command", command: entry }))
29
26
  });
30
27
  return {
31
28
  SessionStart: [commandHook()],
@@ -46,9 +43,11 @@ function desiredClaudeHookGroups(command) {
46
43
  };
47
44
  }
48
45
  function desiredCodexHookGroups(command) {
46
+ const spec = typeof command === "string" ? { command } : command;
49
47
  const entry = {
50
48
  type: "command",
51
- command,
49
+ command: spec.command,
50
+ ...spec.commandWindows === void 0 ? {} : { commandWindows: spec.commandWindows },
52
51
  statusMessage: HOOK_STATUS_MESSAGE
53
52
  };
54
53
  const commandHook = () => ({ hooks: [entry] });
@@ -76,52 +75,146 @@ var CURSOR_WIRED_HOOK_EVENTS = [
76
75
  ];
77
76
 
78
77
  // src/plugin-hooks.ts
78
+ var PLUGIN_LAUNCHER_SH = "launcher.sh";
79
+ var PLUGIN_LAUNCHER_PS1 = "launcher.ps1";
80
+ var PLUGIN_HOOK_PAYLOAD = "hook.mjs";
81
+ var PLUGIN_VERSION_FILE = "version";
82
+ var PLUGIN_CHECKSUMS_FILE = HOOK_CHECKSUMS_FILE;
83
+ var PLUGIN_ROOT_VARIABLE = {
84
+ claude: "CLAUDE_PLUGIN_ROOT",
85
+ cursor: "CURSOR_PLUGIN_ROOT",
86
+ codex: "PLUGIN_ROOT"
87
+ };
88
+ function pluginLauncherPosixCommand(runner) {
89
+ return `"\${${PLUGIN_ROOT_VARIABLE[runner]}}/${PLUGIN_LAUNCHER_SH}" --runner ${runner} ; exit 0`;
90
+ }
91
+ function pluginLauncherPowerShellCommand(runner) {
92
+ const variable = PLUGIN_ROOT_VARIABLE[runner];
93
+ return `powershell -NoProfile -NonInteractive -Command "& ([scriptblock]::Create((Get-Content -Raw -LiteralPath (Join-Path (Get-Item Env:${variable}).Value '${PLUGIN_LAUNCHER_PS1}')))) --runner ${runner}" ; exit 0`;
94
+ }
95
+ function pluginLauncherCommands(runner) {
96
+ return [pluginLauncherPosixCommand(runner), pluginLauncherPowerShellCommand(runner)];
97
+ }
98
+ function pluginLauncherCodexCommand() {
99
+ return {
100
+ command: `sh -c '"\${PLUGIN_ROOT}/${PLUGIN_LAUNCHER_SH}" --runner codex; exit 0'`,
101
+ commandWindows: pluginLauncherPowerShellCommand("codex")
102
+ };
103
+ }
79
104
  function buildClaudePluginHooks(command) {
80
105
  return { hooks: desiredClaudeHookGroups(command) };
81
106
  }
82
107
  function buildCursorPluginHooks(command) {
108
+ const commands = typeof command === "string" ? [command] : command;
83
109
  const hooks = {};
84
110
  for (const eventName of CURSOR_WIRED_HOOK_EVENTS) {
85
- hooks[eventName] = [{ command }];
111
+ hooks[eventName] = commands.map((entry) => ({ command: entry }));
86
112
  }
87
113
  return { hooks };
88
114
  }
89
115
  function buildCodexPluginHooks(command) {
90
116
  return { hooks: desiredCodexHookGroups(command) };
91
117
  }
118
+ var MARKETPLACE_PLUGIN_NAME = "ev-ai-agent-hooks";
119
+ var MARKETPLACE_NAME = "ev-ai-marketplace";
120
+ var MARKETPLACE_PLUGIN_DIRS = {
121
+ claude: "plugins/claude",
122
+ cursor: "plugins/cursor",
123
+ codex: "plugins/codex"
124
+ };
92
125
  function marketplacePluginHookPaths(marketplaceRoot) {
93
126
  return {
94
- claude: join(marketplaceRoot, "plugins/claude-runtime-hooks/hooks/hooks.json"),
95
- cursor: join(marketplaceRoot, "plugins/cursor-runtime-hooks/hooks/hooks.json"),
96
- codex: join(marketplaceRoot, "plugins/codex-runtime-hooks/hooks/hooks.json")
127
+ claude: join(marketplaceRoot, MARKETPLACE_PLUGIN_DIRS.claude, "hooks/hooks.json"),
128
+ cursor: join(marketplaceRoot, MARKETPLACE_PLUGIN_DIRS.cursor, "hooks/hooks.json"),
129
+ codex: join(marketplaceRoot, MARKETPLACE_PLUGIN_DIRS.codex, "hooks/hooks.json")
97
130
  };
98
131
  }
132
+ var PLUGIN_PAYLOAD_FILES = [
133
+ { source: "dist/hook.mjs", target: PLUGIN_HOOK_PAYLOAD, executable: false },
134
+ { source: `scripts/${PLUGIN_LAUNCHER_SH}`, target: PLUGIN_LAUNCHER_SH, executable: true },
135
+ { source: `scripts/${PLUGIN_LAUNCHER_PS1}`, target: PLUGIN_LAUNCHER_PS1, executable: false },
136
+ {
137
+ source: `compile-out/bin/${PLUGIN_CHECKSUMS_FILE}`,
138
+ target: PLUGIN_CHECKSUMS_FILE,
139
+ executable: false,
140
+ optional: true
141
+ }
142
+ ];
143
+ var PLUGIN_REQUIRED_PAYLOAD_TARGETS = [
144
+ PLUGIN_HOOK_PAYLOAD,
145
+ PLUGIN_LAUNCHER_SH,
146
+ PLUGIN_LAUNCHER_PS1,
147
+ PLUGIN_VERSION_FILE
148
+ ];
99
149
  function writeJson(path, value) {
100
150
  mkdirSync(dirname(path), { recursive: true });
101
151
  writeFileSync(path, `${JSON.stringify(value, null, 2)}
102
152
  `, "utf8");
103
153
  }
104
- function writeMarketplacePluginHooks(marketplaceRoot, packageSpec = NPX_PACKAGE_SPEC) {
105
- const base = npxHookCommand(packageSpec);
154
+ function writeMarketplacePluginHooks(marketplaceRoot) {
106
155
  const paths = marketplacePluginHookPaths(marketplaceRoot);
107
- writeJson(paths.claude, buildClaudePluginHooks(withRunnerFlag(base, "claude")));
108
- writeJson(paths.cursor, buildCursorPluginHooks(withRunnerFlag(base, "cursor")));
109
- writeJson(paths.codex, buildCodexPluginHooks(withRunnerFlag(base, "codex")));
156
+ writeJson(paths.claude, buildClaudePluginHooks(pluginLauncherCommands("claude")));
157
+ writeJson(paths.cursor, buildCursorPluginHooks(pluginLauncherCommands("cursor")));
158
+ writeJson(paths.codex, buildCodexPluginHooks(pluginLauncherCodexCommand()));
110
159
  return paths;
111
160
  }
112
- function expectedMarketplacePluginHooks(packageSpec = NPX_PACKAGE_SPEC) {
113
- const base = npxHookCommand(packageSpec);
161
+ function copyMarketplacePluginPayload(marketplaceRoot, packageRoot) {
162
+ for (const file of PLUGIN_PAYLOAD_FILES) {
163
+ const source = join(packageRoot, file.source);
164
+ if (!file.optional && !existsSync(source)) {
165
+ throw new Error(`Missing plugin payload source: ${source} (run \`yarn build\` first)`);
166
+ }
167
+ }
168
+ const written = [];
169
+ for (const pluginDir of Object.values(MARKETPLACE_PLUGIN_DIRS)) {
170
+ const pluginRoot = join(marketplaceRoot, pluginDir);
171
+ mkdirSync(pluginRoot, { recursive: true });
172
+ for (const file of PLUGIN_PAYLOAD_FILES) {
173
+ const source = join(packageRoot, file.source);
174
+ if (file.optional && !existsSync(source)) {
175
+ continue;
176
+ }
177
+ const target = join(pluginRoot, file.target);
178
+ copyFileSync(source, target);
179
+ chmodSync(target, file.executable ? 493 : 420);
180
+ written.push(target);
181
+ }
182
+ const versionTarget = join(pluginRoot, PLUGIN_VERSION_FILE);
183
+ writeFileSync(versionTarget, `${PACKAGE_VERSION}
184
+ `, "utf8");
185
+ chmodSync(versionTarget, 420);
186
+ written.push(versionTarget);
187
+ }
188
+ return written;
189
+ }
190
+ function expectedMarketplacePluginHooks() {
114
191
  return {
115
- claude: buildClaudePluginHooks(withRunnerFlag(base, "claude")),
116
- cursor: buildCursorPluginHooks(withRunnerFlag(base, "cursor")),
117
- codex: buildCodexPluginHooks(withRunnerFlag(base, "codex"))
192
+ claude: buildClaudePluginHooks(pluginLauncherCommands("claude")),
193
+ cursor: buildCursorPluginHooks(pluginLauncherCommands("cursor")),
194
+ codex: buildCodexPluginHooks(pluginLauncherCodexCommand())
118
195
  };
119
196
  }
120
197
  export {
198
+ MARKETPLACE_NAME,
199
+ MARKETPLACE_PLUGIN_DIRS,
200
+ MARKETPLACE_PLUGIN_NAME,
201
+ PLUGIN_CHECKSUMS_FILE,
202
+ PLUGIN_HOOK_PAYLOAD,
203
+ PLUGIN_LAUNCHER_PS1,
204
+ PLUGIN_LAUNCHER_SH,
205
+ PLUGIN_PAYLOAD_FILES,
206
+ PLUGIN_REQUIRED_PAYLOAD_TARGETS,
207
+ PLUGIN_ROOT_VARIABLE,
208
+ PLUGIN_VERSION_FILE,
121
209
  buildClaudePluginHooks,
122
210
  buildCodexPluginHooks,
123
211
  buildCursorPluginHooks,
212
+ copyMarketplacePluginPayload,
124
213
  expectedMarketplacePluginHooks,
125
214
  marketplacePluginHookPaths,
215
+ pluginLauncherCodexCommand,
216
+ pluginLauncherCommands,
217
+ pluginLauncherPosixCommand,
218
+ pluginLauncherPowerShellCommand,
126
219
  writeMarketplacePluginHooks
127
220
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ev-ai/agent-hook",
3
- "version": "1.1.3",
3
+ "version": "1.1.5",
4
4
  "description": "Cross-runner runtime telemetry hook for Claude Code, Cursor, and Codex",
5
5
  "type": "module",
6
6
  "bin": {